linux/include/linux/amba/clcd.h
<<
>>
Prefs
   1/*
   2 * linux/include/asm-arm/hardware/amba_clcd.h -- Integrator LCD panel.
   3 *
   4 * David A Rusling
   5 *
   6 * Copyright (C) 2001 ARM Limited
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file COPYING in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/fb.h>
  13
  14/*
  15 * CLCD Controller Internal Register addresses
  16 */
  17#define CLCD_TIM0               0x00000000
  18#define CLCD_TIM1               0x00000004
  19#define CLCD_TIM2               0x00000008
  20#define CLCD_TIM3               0x0000000c
  21#define CLCD_UBAS               0x00000010
  22#define CLCD_LBAS               0x00000014
  23
  24#define CLCD_PL110_IENB         0x00000018
  25#define CLCD_PL110_CNTL         0x0000001c
  26#define CLCD_PL110_STAT         0x00000020
  27#define CLCD_PL110_INTR         0x00000024
  28#define CLCD_PL110_UCUR         0x00000028
  29#define CLCD_PL110_LCUR         0x0000002C
  30
  31#define CLCD_PL111_CNTL         0x00000018
  32#define CLCD_PL111_IENB         0x0000001c
  33#define CLCD_PL111_RIS          0x00000020
  34#define CLCD_PL111_MIS          0x00000024
  35#define CLCD_PL111_ICR          0x00000028
  36#define CLCD_PL111_UCUR         0x0000002c
  37#define CLCD_PL111_LCUR         0x00000030
  38
  39#define CLCD_PALL               0x00000200
  40#define CLCD_PALETTE            0x00000200
  41
  42#define TIM2_CLKSEL             (1 << 5)
  43#define TIM2_IVS                (1 << 11)
  44#define TIM2_IHS                (1 << 12)
  45#define TIM2_IPC                (1 << 13)
  46#define TIM2_IOE                (1 << 14)
  47#define TIM2_BCD                (1 << 26)
  48
  49#define CNTL_LCDEN              (1 << 0)
  50#define CNTL_LCDBPP1            (0 << 1)
  51#define CNTL_LCDBPP2            (1 << 1)
  52#define CNTL_LCDBPP4            (2 << 1)
  53#define CNTL_LCDBPP8            (3 << 1)
  54#define CNTL_LCDBPP16           (4 << 1)
  55#define CNTL_LCDBPP16_565       (6 << 1)
  56#define CNTL_LCDBPP24           (5 << 1)
  57#define CNTL_LCDBW              (1 << 4)
  58#define CNTL_LCDTFT             (1 << 5)
  59#define CNTL_LCDMONO8           (1 << 6)
  60#define CNTL_LCDDUAL            (1 << 7)
  61#define CNTL_BGR                (1 << 8)
  62#define CNTL_BEBO               (1 << 9)
  63#define CNTL_BEPO               (1 << 10)
  64#define CNTL_LCDPWR             (1 << 11)
  65#define CNTL_LCDVCOMP(x)        ((x) << 12)
  66#define CNTL_LDMAFIFOTIME       (1 << 15)
  67#define CNTL_WATERMARK          (1 << 16)
  68
  69struct clcd_panel {
  70        struct fb_videomode     mode;
  71        signed short            width;  /* width in mm */
  72        signed short            height; /* height in mm */
  73        u32                     tim2;
  74        u32                     tim3;
  75        u32                     cntl;
  76        unsigned int            bpp:8,
  77                                fixedtimings:1,
  78                                grayscale:1;
  79        unsigned int            connector;
  80};
  81
  82struct clcd_regs {
  83        u32                     tim0;
  84        u32                     tim1;
  85        u32                     tim2;
  86        u32                     tim3;
  87        u32                     cntl;
  88        unsigned long           pixclock;
  89};
  90
  91struct clcd_fb;
  92
  93/*
  94 * the board-type specific routines
  95 */
  96struct clcd_board {
  97        const char *name;
  98
  99        /*
 100         * Optional.  Check whether the var structure is acceptable
 101         * for this display.
 102         */
 103        int     (*check)(struct clcd_fb *fb, struct fb_var_screeninfo *var);
 104
 105        /*
 106         * Compulsary.  Decode fb->fb.var into regs->*.  In the case of
 107         * fixed timing, set regs->* to the register values required.
 108         */
 109        void    (*decode)(struct clcd_fb *fb, struct clcd_regs *regs);
 110
 111        /*
 112         * Optional.  Disable any extra display hardware.
 113         */
 114        void    (*disable)(struct clcd_fb *);
 115
 116        /*
 117         * Optional.  Enable any extra display hardware.
 118         */
 119        void    (*enable)(struct clcd_fb *);
 120
 121        /*
 122         * Setup platform specific parts of CLCD driver
 123         */
 124        int     (*setup)(struct clcd_fb *);
 125
 126        /*
 127         * mmap the framebuffer memory
 128         */
 129        int     (*mmap)(struct clcd_fb *, struct vm_area_struct *);
 130
 131        /*
 132         * Remove platform specific parts of CLCD driver
 133         */
 134        void    (*remove)(struct clcd_fb *);
 135};
 136
 137struct amba_device;
 138struct clk;
 139
 140/* this data structure describes each frame buffer device we find */
 141struct clcd_fb {
 142        struct fb_info          fb;
 143        struct amba_device      *dev;
 144        struct clk              *clk;
 145        struct clcd_panel       *panel;
 146        struct clcd_board       *board;
 147        void                    *board_data;
 148        void __iomem            *regs;
 149        u16                     off_ienb;
 150        u16                     off_cntl;
 151        u32                     clcd_cntl;
 152        u32                     cmap[16];
 153};
 154
 155static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
 156{
 157        u32 val, cpl;
 158
 159        /*
 160         * Program the CLCD controller registers and start the CLCD
 161         */
 162        val = ((fb->fb.var.xres / 16) - 1) << 2;
 163        val |= (fb->fb.var.hsync_len - 1) << 8;
 164        val |= (fb->fb.var.right_margin - 1) << 16;
 165        val |= (fb->fb.var.left_margin - 1) << 24;
 166        regs->tim0 = val;
 167
 168        val = fb->fb.var.yres;
 169        if (fb->panel->cntl & CNTL_LCDDUAL)
 170                val /= 2;
 171        val -= 1;
 172        val |= (fb->fb.var.vsync_len - 1) << 10;
 173        val |= fb->fb.var.lower_margin << 16;
 174        val |= fb->fb.var.upper_margin << 24;
 175        regs->tim1 = val;
 176
 177        val = fb->panel->tim2;
 178        val |= fb->fb.var.sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
 179        val |= fb->fb.var.sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
 180
 181        cpl = fb->fb.var.xres_virtual;
 182        if (fb->panel->cntl & CNTL_LCDTFT)        /* TFT */
 183                /* / 1 */;
 184        else if (!fb->fb.var.grayscale)           /* STN color */
 185                cpl = cpl * 8 / 3;
 186        else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */
 187                cpl /= 8;
 188        else                                      /* STN monochrome, 4bit */
 189                cpl /= 4;
 190
 191        regs->tim2 = val | ((cpl - 1) << 16);
 192
 193        regs->tim3 = fb->panel->tim3;
 194
 195        val = fb->panel->cntl;
 196        if (fb->fb.var.grayscale)
 197                val |= CNTL_LCDBW;
 198
 199        switch (fb->fb.var.bits_per_pixel) {
 200        case 1:
 201                val |= CNTL_LCDBPP1;
 202                break;
 203        case 2:
 204                val |= CNTL_LCDBPP2;
 205                break;
 206        case 4:
 207                val |= CNTL_LCDBPP4;
 208                break;
 209        case 8:
 210                val |= CNTL_LCDBPP8;
 211                break;
 212        case 16:
 213                /*
 214                 * PL110 cannot choose between 5551 and 565 modes in
 215                 * its control register
 216                 */
 217                if ((fb->dev->periphid & 0x000fffff) == 0x00041110)
 218                        val |= CNTL_LCDBPP16;
 219                else if (fb->fb.var.green.length == 5)
 220                        val |= CNTL_LCDBPP16;
 221                else
 222                        val |= CNTL_LCDBPP16_565;
 223                break;
 224        case 32:
 225                val |= CNTL_LCDBPP24;
 226                break;
 227        }
 228
 229        regs->cntl = val;
 230        regs->pixclock = fb->fb.var.pixclock;
 231}
 232
 233static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
 234{
 235        var->xres_virtual = var->xres = (var->xres + 15) & ~15;
 236        var->yres_virtual = var->yres = (var->yres + 1) & ~1;
 237
 238#define CHECK(e,l,h) (var->e < l || var->e > h)
 239        if (CHECK(right_margin, (5+1), 256) ||  /* back porch */
 240            CHECK(left_margin, (5+1), 256) ||   /* front porch */
 241            CHECK(hsync_len, (5+1), 256) ||
 242            var->xres > 4096 ||
 243            var->lower_margin > 255 ||          /* back porch */
 244            var->upper_margin > 255 ||          /* front porch */
 245            var->vsync_len > 32 ||
 246            var->yres > 1024)
 247                return -EINVAL;
 248#undef CHECK
 249
 250        /* single panel mode: PCD = max(PCD, 1) */
 251        /* dual panel mode: PCD = max(PCD, 5) */
 252
 253        /*
 254         * You can't change the grayscale setting, and
 255         * we can only do non-interlaced video.
 256         */
 257        if (var->grayscale != fb->fb.var.grayscale ||
 258            (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
 259                return -EINVAL;
 260
 261#define CHECK(e) (var->e != fb->fb.var.e)
 262        if (fb->panel->fixedtimings &&
 263            (CHECK(xres)                ||
 264             CHECK(yres)                ||
 265             CHECK(bits_per_pixel)      ||
 266             CHECK(pixclock)            ||
 267             CHECK(left_margin)         ||
 268             CHECK(right_margin)        ||
 269             CHECK(upper_margin)        ||
 270             CHECK(lower_margin)        ||
 271             CHECK(hsync_len)           ||
 272             CHECK(vsync_len)           ||
 273             CHECK(sync)))
 274                return -EINVAL;
 275#undef CHECK
 276
 277        var->nonstd = 0;
 278        var->accel_flags = 0;
 279
 280        return 0;
 281}
 282
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.