home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / linux / amba / clcd.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  6.4 KB  |  281 lines

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