Welcome 微信登录

首页 / 操作系统 / Linux / Linux S3C2440 LCD 设备驱动

主机:VM - RedHat 9.0开发板:FL2440,linux-2.6.12arm-linux-gcc:3.4.1
  1. /* 
  2.  *  linux/drivers/video/s3c2410fb.c 
  3.  */  
  4.   
  5. #include <linux/config.h>   
  6. #include <linux/module.h>   
  7. #include <linux/moduleparam.h>   
  8. #include <linux/kernel.h>   
  9. #include <linux/sched.h>   
  10. #include <linux/errno.h>   
  11. #include <linux/string.h>   
  12. #include <linux/interrupt.h>   
  13. #include <linux/slab.h>   
  14. #include <linux/fb.h>   
  15. #include <linux/delay.h>   
  16. #include <linux/init.h>   
  17. #include <linux/ioport.h>   
  18. #include <linux/cpufreq.h>   
  19. #include <linux/device.h>   
  20. #include <linux/dma-mapping.h>   
  21.   
  22. #include <asm/hardware.h>   
  23. #include <asm/io.h>   
  24. #include <asm/irq.h>   
  25. #include <asm/mach-types.h>   
  26. #include <asm/uaccess.h>   
  27. #include <asm/arch/regs-gpio.h>   
  28. #include <asm/arch/regs-lcd.h>   
  29. #include <asm/arch/regs-irq.h>   
  30.   
  31. #include "s3c2410fb.h"   
  32.   
  33. /* 
  34.  * Complain if VAR is out of range. 
  35.  */  
  36. #define DEBUG_VAR 1   
  37.   
  38. // 通过写入一个数据到此寄存器来清除SRCPND 寄存器的指定位。其只清除那些数据中被设置为1 的相应   
  39. // 位置的SRCPND 位。那些数据中被设置为0 的相应位置的位保持不变。   
  40. #define ClearPending(x) {      
  41.               __raw_writel((1 << (x)), S3C2410_SRCPND);     
  42.               __raw_writel((1 << (x)), S3C2410_INTPND);     
  43.             }  
  44.   
  45. struct gzliu_fb_mach_info fs2410_info = {  
  46.     .pixclock   = 270000,  
  47.     .xres       = 320,  
  48.     .yres       = 240,  
  49.     .bpp        = 16,  
  50.     .hsync_len  = 8,  
  51.     .left_margin    = 5,  
  52.     .right_margin   = 15,  
  53.     .vsync_len  = 15,  
  54.     .upper_margin   = 3,  
  55.     .lower_margin   = 5,  
  56.     .sync       = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  
  57.     .cmap_greyscale = 0,  
  58.     .cmap_inverse   = 0,  
  59.     .cmap_static    = 0,  
  60.     .reg        = {  
  61.         .lcdcon1 = (6<<8)|(0<<7)|(3<<5)|(12<<1),  
  62.         .lcdcon2 = (3<<24) | (239<<14) | (5<<6) | (15),  
  63.         .lcdcon3 = (58<<19) | (319<<8) | (15),  
  64.         .lcdcon4 = (13<<8) | (8),  
  65.         .lcdcon5 = (1<<11) | (0<<10) | (1<<9) | (1<<8) | (0<<7) | (0<<6) | (1<<3)  |(0<<1) | (1),  
  66.     }  
  67. };  
  68.   
  69. static void (*gzliu_fb_backlight_power)(int);  
  70. static void (*gzliu_fb_lcd_power)(int);  
  71.   
  72. static int gzliu_fb_activate_var(struct fb_var_screeninfo *var, struct gzliu_fb_info *);  
  73. static void set_ctrlr_state(struct gzliu_fb_info *fbi, u_int state);  
  74.   
  75. static inline void gzliu_fb_schedule_work(struct gzliu_fb_info *fbi, u_int state)  
  76. {  
  77. printk("@@@@@@@@@@ gzliu_fb_schedule_work() @@@@@@@@@@@@ ");  
  78.     unsigned long flags;  
  79.   
  80.     local_irq_save(flags);  
  81.     /* 
  82.      * We need to handle two requests being made at the same time. 
  83.      * There are two important cases: 
  84.      *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE) 
  85.      *     We must perform the unblanking, which will do our REENABLE for us. 
  86.      *  2. When we are blanking, but immediately unblank before we have 
  87.      *     blanked.  We do the "REENABLE" thing here as well, just to be sure. 
  88.      */  
  89.     if (fbi->task_state == C_ENABLE && state == C_REENABLE)  
  90.         state = (u_int) -1;  
  91.     if (fbi->task_state == C_DISABLE && state == C_ENABLE)  
  92.         state = C_REENABLE;  
  93.   
  94.     if (state != (u_int)-1) {  
  95.         fbi->task_state = state;  
  96.         schedule_work(&fbi->task);  
  97.     }  
  98.     local_irq_restore(flags);  
  99. }  
  100.   
  101. static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)  
  102. {  
  103. printk("@@@@@@@@@@ chan_to_field() @@@@@@@@@@@@ ");  
  104.     chan &= 0xffff;  
  105.     chan >>= 16 - bf->length;  
  106.     return chan << bf->offset;  
  107. }  
  108.   
  109. static int gzliu_fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,  
  110.                u_int trans, struct fb_info *info)  
  111. {  
  112. printk("@@@@@@@@@@ gzliu_fb_setpalettereg() @@@@@@@@@@@@ ");  
  113.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  114.     u_int val, ret = 1;  
  115.   
  116.     if (regno < fbi->palette_size) {  
  117.         if (fbi->fb.var.grayscale) {  
  118.             val = ((blue >> 8) & 0x00ff);  
  119.         } else {  
  120.             val  = ((red   >>  0) & 0xf800);  
  121.             val |= ((green >>  5) & 0x07e0);  
  122.             val |= ((blue  >> 11) & 0x001f);  
  123.         }  
  124.   
  125.         fbi->palette_cpu[regno] = val;  
  126.         ret = 0;  
  127.     }  
  128.     return ret;  
  129. }  
  130.   
  131. static int gzliu_fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,  
  132.            u_int trans, struct fb_info *info)  
  133. {  
  134. printk("@@@@@@@@@@ gzliu_fb_setcolreg() @@@@@@@@@@@@ ");  
  135.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  136.     unsigned int val;  
  137.     int ret = 1;  
  138.   
  139.     /* 
  140.      * If inverse mode was selected, invert all the colours 
  141.      * rather than the register number.  The register number 
  142.      * is what you poke into the framebuffer to produce the 
  143.      * colour you requested. 
  144.      */  
  145.     if (fbi->cmap_inverse) {  
  146.         red   = 0xffff - red;  
  147.         green = 0xffff - green;  
  148.         blue  = 0xffff - blue;  
  149.     }  
  150.   
  151.     /* 
  152.      * If greyscale is true, then we convert the RGB value 
  153.      * to greyscale no matter what visual we are using. 
  154.      */  
  155.     if (fbi->fb.var.grayscale)  
  156.         red = green = blue = (19595 * red + 38470 * green +  
  157.                     7471 * blue) >> 16;  
  158.   
  159.     switch (fbi->fb.fix.visual) {  
  160.     case FB_VISUAL_TRUECOLOR:  
  161.         /* 
  162.          * 12 or 16-bit True Colour.  We encode the RGB value 
  163.          * according to the RGB bitfield information. 
  164.          */  
  165.         if (regno < 16) {  
  166.             u32 *pal = fbi->fb.pseudo_palette;  
  167.   
  168.             val  = chan_to_field(red, &fbi->fb.var.red);  
  169.             val |= chan_to_field(green, &fbi->fb.var.green);  
  170.             val |= chan_to_field(blue, &fbi->fb.var.blue);  
  171.   
  172.             pal[regno] = val;  
  173.             ret = 0;  
  174.         }  
  175.         break;  
  176.   
  177.     case FB_VISUAL_STATIC_PSEUDOCOLOR:  
  178.     case FB_VISUAL_PSEUDOCOLOR:  
  179.         ret = gzliu_fb_setpalettereg(regno, red, green, blue, trans, info);  
  180.         break;  
  181.     }  
  182.   
  183.     return ret;  
  184. }  
  185.   
  186. /* 
  187.  *  gzliu_fb_check_var(): 
  188.  *    Get the video params out of "var". If a value doesn"t fit, round it up, 
  189.  *    if it"s too big, return -EINVAL. 
  190.  * 
  191.  *    Round up in the following order: bits_per_pixel, xres, 
  192.  *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, 
  193.  *    bitfields, horizontal timing, vertical timing. 
  194.  */  
  195. static int gzliu_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)  
  196. {  
  197. printk("@@@@@@@@@@ gzliu_fb_check_var() @@@@@@@@@@@@ ");  
  198.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  199.   
  200.     if (var->xres < MIN_XRES)  
  201.         var->xres = MIN_XRES;  
  202.     if (var->yres < MIN_YRES)  
  203.         var->yres = MIN_YRES;  
  204.     if (var->xres > fbi->max_xres)  
  205.         var->xres = fbi->max_xres;  
  206.     if (var->yres > fbi->max_yres)  
  207.         var->yres = fbi->max_yres;  
  208.     var->xres_virtual =  
  209.         max(var->xres_virtual, var->xres);  
  210.     var->yres_virtual =  
  211.         max(var->yres_virtual, var->yres);  
  212.   
  213.         /* 
  214.      * Setup the RGB parameters for this display. 
  215.      * 
  216.      * The pixel packing format is described on page 7-11 of the 
  217.      * PXA2XX Developer"s Manual. 
  218.          */  
  219.     if ( var->bits_per_pixel == 16 ) {  
  220.         var->red.offset   = 11; var->red.length   = 5;  
  221.         var->green.offset = 5;  var->green.length = 6;  
  222.         var->blue.offset  = 0;  var->blue.length  = 5;  
  223.         var->transp.offset = var->transp.length = 0;  
  224.     } else {  
  225.         var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0;  
  226.         var->red.length   = 8;  
  227.         var->green.length = 8;  
  228.         var->blue.length  = 8;  
  229.         var->transp.length = 0;  
  230.     }  
  231.   
  232. #ifdef CONFIG_CPU_FREQ   
  233.     DPRINTK("dma period = %d ps, clock = %d kHz ",  
  234.         gzliu_fb_display_dma_period(var),  
  235.         get_clk_frequency_khz(0));  
  236. #endif   
  237.   
  238.     return 0;  
  239. }  
  240.   
  241. static inline void gzliu_fb_set_truecolor(u_int is_true_color)  
  242. {  
  243. printk("@@@@@@@@@@ gzliu_fb_set_truecolor() @@@@@@@@@@@@ ");  
  244.     DPRINTK("true_color = %d ", is_true_color);  
  245. }  
  246.   
  247. /* 
  248.  * gzliu_fb_set_par(): 
  249.  *  Set the user defined part of the display for the specified console 
  250.  */  
  251. static int gzliu_fb_set_par(struct fb_info *info)  
  252. {  
  253. printk("@@@@@@@@@@ gzliu_fb_set_par() @@@@@@@@@@@@ ");  
  254.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  255.     struct fb_var_screeninfo *var = &info->var;  
  256.     unsigned long palette_mem_size;  
  257.   
  258.     DPRINTK("set_par ");  
  259.   
  260.     if (var->bits_per_pixel == 16)  
  261.         fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;  
  262.     else if (!fbi->cmap_static)  
  263.         fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;  
  264.     else {  
  265.         /* 
  266.          * Some people have weird ideas about wanting static 
  267.          * pseudocolor maps.  I suspect their user space 
  268.          * applications are broken. 
  269.          */  
  270.         fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;  
  271.     }  
  272.   
  273.     fbi->fb.fix.line_length = var->xres_virtual *  
  274.                   var->bits_per_pixel / 8;  
  275.     if (var->bits_per_pixel == 16)  
  276.         fbi->palette_size = 0;  
  277.     else  
  278.         fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;  
  279.   
  280.     palette_mem_size = fbi->palette_size * sizeof(u16);  
  281.   
  282. printk("@@@@@@@ palette_mem_size = 0x%08lx ", (u_long) palette_mem_size);  
  283.   
  284.     fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);  
  285.     fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;  
  286.   
  287.     /* 
  288.      * Set (any) board control register to handle new color depth 
  289.      */  
  290.     gzliu_fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);  
  291.       
  292.     if (fbi->fb.var.bits_per_pixel == 16)  
  293.         fb_dealloc_cmap(&fbi->fb.cmap);  
  294.     else  
  295.         fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);  
  296.   
  297.     gzliu_fb_activate_var(var, fbi);  
  298.   
  299.     return 0;  
  300. }  
  301.   
  302. /* 
  303.  * gzliu_fb_blank(): 
  304.  *  Blank the display by setting all palette values to zero.  Note, the 
  305.  *  12 and 16 bpp modes don"t really use the palette, so this will not 
  306.  *      blank the display in all modes. 
  307.  */  
  308. static int gzliu_fb_blank(int blank, struct fb_info *info)  
  309. {  
  310. printk("@@@@@@@@@@ gzliu_fb_blank() @@@@@@@@@@@@ ");  
  311.     struct gzliu_fb_info *fbi = (struct gzliu_fb_info *)info;  
  312.     int i;  
  313.   
  314.     DPRINTK("gzliu_fb_blank: blank=%d ", blank);  
  315.   
  316.     switch (blank) {  
  317.     case VESA_POWERDOWN:  
  318.     case VESA_VSYNC_SUSPEND:  
  319.     case VESA_HSYNC_SUSPEND:  
  320.         if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||  
  321.             fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)  
  322.             for (i = 0; i < fbi->palette_size; i++);  
  323.   
  324.         gzliu_fb_schedule_work(fbi, C_DISABLE);  
  325.         break;  
  326.   
  327.     case VESA_NO_BLANKING:  
  328.         if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||  
  329.             fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)  
  330.             fb_set_cmap(&fbi->fb.cmap, info);  
  331.         gzliu_fb_schedule_work(fbi, C_ENABLE);  
  332.     }  
  333.     return 0;  
  334. }  
  335.   
  336. static int soft_cursor_dummy(struct fb_info *info, struct fb_cursor *cursor)  
  337. {  
  338. printk("@@@@@@@@@@ soft_cursor_dummy() @@@@@@@@@@@@ ");  
  339.     return 0;  
  340. }  
  341.   
  342. static struct fb_ops gzliu_fb_ops = {  
  343.     .owner      = THIS_MODULE,  
  344.     .fb_check_var   = gzliu_fb_check_var,  
  345.     .fb_set_par = gzliu_fb_set_par,  
  346.     .fb_setcolreg   = gzliu_fb_setcolreg,  
  347.     .fb_blank   = gzliu_fb_blank,  
  348.     .fb_cursor  = soft_cursor_dummy,  
  349. };  
  350.   
  351. static inline unsigned int get_pcd(unsigned int pixclock)  
  352. {  
  353. printk("@@@@@@@@@@ get_pcd() @@@@@@@@@@@@ ");  
  354.     unsigned long long pcd;  
  355.   
  356.     pcd = s3c2410_hclk/(((__raw_readl(S3C2410_LCDCON1)>>8)&0x3ff)*2+1);  
  357.     return (unsigned int)pcd;  
  358. }  
  359.   
  360. /* 
  361.  * gzliu_fb_activate_var(): 
  362.  *  Configures LCD Controller based on entries in var parameter.  Settings are 
  363.  *  only written to the controller if changes were made. 
  364.  */  
  365. static int gzliu_fb_activate_var(struct fb_var_screeninfo *var, struct gzliu_fb_info *fbi)  
  366. {  
  367. printk("@@@@@@@@@@ gzliu_fb_activate_var() @@@@@@@@@@@@ ");  
  368.     struct gzliu_fb_lcd_reg new_regs;  
  369.     u_long flags;  
  370.     u_int half_screen_size, yres;  
  371.     unsigned long VideoPhysicalTemp = fbi->screen_dma;  
  372.   
  373.     DPRINTK("Configuring gzliu_ LCD ");  
  374.   
  375.     DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d ",  
  376.         var->xres, var->hsync_len,  
  377.         var->left_margin, var->right_margin);  
  378.     DPRINTK("var: yres=%d vslen=%d um=%d bm=%d ",  
  379.         var->yres, var->vsync_len,  
  380.         var->upper_margin, var->lower_margin);  
  381.     DPRINTK("var: pixclock=%d pcd=%d ", var->pixclock, pcd);  
  382.   
  383. #if DEBUG_VAR   
  384.     if (var->xres < 16 || var->xres > 1024)  
  385.         printk(KERN_ERR "%s: invalid xres %d ",  
  386.             fbi->fb.fix.id, var->xres);  
  387.     switch(var->bits_per_pixel) {  
  388.     case 1:  
  389.     case 2:  
  390.     case 4:  
  391.     case 8:  
  392.     case 16:  
  393.         break;  
  394.     default:  
  395.         printk(KERN_ERR "%s: invalid bit depth %d ",  
  396.                fbi->fb.fix.id, var->bits_per_pixel);  
  397.         break;  
  398.     }  
  399.     if (var->hsync_len < 1    || var->hsync_len > 64)  
  400.         printk(KERN_ERR "%s: invalid hsync_len %d ",  
  401.             fbi->fb.fix.id, var->hsync_len);  
  402.     if (var->left_margin < 1  || var->left_margin > 255)  
  403.         printk(KERN_ERR "%s: invalid left_margin %d ",  
  404.             fbi->fb.fix.id, var->left_margin);  
  405.     if (var->right_margin < 1 || var->right_margin > 255)  
  406.         printk(KERN_ERR "%s: invalid right_margin %d ",  
  407.             fbi->fb.fix.id, var->right_margin);  
  408.     if (var->yres < 1         || var->yres > 1024)  
  409.         printk(KERN_ERR "%s: invalid yres %d ",  
  410.             fbi->fb.fix.id, var->yres);  
  411.     if (var->vsync_len < 1    || var->vsync_len > 64)  
  412.         printk(KERN_ERR "%s: invalid vsync_len %d ",  
  413.             fbi->fb.fix.id, var->vsync_len);  
  414.     if (var->upper_margin < 0 || var->upper_margin > 255)  
  415.         printk(KERN_ERR "%s: invalid upper_margin %d ",  
  416.             fbi->fb.fix.id, var->upper_margin);  
  417.     if (var->lower_margin < 0 || var->lower_margin > 255)  
  418.         printk(KERN_ERR "%s: invalid lower_margin %d ",  
  419.             fbi->fb.fix.id, var->lower_margin);  
  420. #endif   
  421.   
  422.     /* Update shadow copy atomically */  
  423.     local_irq_save(flags);  
  424.   
  425.     new_regs.lcdcon1 = fbi->reg.lcdcon1 & ~S3C2410_LCDCON1_ENVID;  
  426.   
  427.     new_regs.lcdcon2 = (fbi->reg.lcdcon2 & ~LCD2_LINEVAL_MSK)   
  428.                         | LCD2_LINEVAL(var->yres - 1);  
  429.   
  430.     /* TFT LCD only ! */  
  431.     new_regs.lcdcon3 = (fbi->reg.lcdcon3 & ~LCD3_HOZVAL_MSK)  
  432.                         | LCD3_HOZVAL(var->xres - 1);  
  433.   
  434.     new_regs.lcdcon4 = fbi->reg.lcdcon4;  
  435.     new_regs.lcdcon5 = fbi->reg.lcdcon5;  
  436.   
  437.     new_regs.lcdsaddr1 =   
  438.         LCDADDR_BANK(((unsigned long)VideoPhysicalTemp >> 22))  
  439.         | LCDADDR_BASEU(((unsigned long)VideoPhysicalTemp >> 1));  
  440.   
  441.     /* 16bpp */  
  442.     new_regs.lcdsaddr2 = LCDADDR_BASEL(   
  443.         ((unsigned long)VideoPhysicalTemp + (var->xres * 2 * (var->yres/*-1*/)))  
  444.         >> 1);  
  445.   
  446.     new_regs.lcdsaddr3 = LCDADDR_OFFSET(0) | (LCDADDR_PAGE(var->xres) /*>> 1*/);  
  447.   
  448.     yres = var->yres;  
  449.   
  450.     half_screen_size = var->bits_per_pixel;  
  451.     half_screen_size = half_screen_size * var->xres * var->yres / 16;  
  452.   
  453.     fbi->reg.lcdcon1 = new_regs.lcdcon1;  
  454.     fbi->reg.lcdcon2 = new_regs.lcdcon2;  
  455.     fbi->reg.lcdcon3 = new_regs.lcdcon3;  
  456.     fbi->reg.lcdcon4 = new_regs.lcdcon4;  
  457.     fbi->reg.lcdcon5 = new_regs.lcdcon5;  
  458.     fbi->reg.lcdsaddr1 = new_regs.lcdsaddr1;  
  459.     fbi->reg.lcdsaddr2 = new_regs.lcdsaddr2;  
  460.     fbi->reg.lcdsaddr3 = new_regs.lcdsaddr3;  
  461.   
  462.     __raw_writel(fbi->reg.lcdcon1&~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);  
  463.     __raw_writel(fbi->reg.lcdcon2, S3C2410_LCDCON2);  
  464.     __raw_writel(fbi->reg.lcdcon3, S3C2410_LCDCON3);  
  465.     __raw_writel(fbi->reg.lcdcon4, S3C2410_LCDCON4);  
  466.     __raw_writel(fbi->reg.lcdcon5, S3C2410_LCDCON5);  
  467.     __raw_writel(fbi->reg.lcdsaddr1, S3C2410_LCDSADDR1);  
  468.     __raw_writel(fbi->reg.lcdsaddr2, S3C2410_LCDSADDR2);  
  469.     __raw_writel(fbi->reg.lcdsaddr3, S3C2410_LCDSADDR3);  
  470.   
  471.     //next code should not be used in TX06D18 LCD   
  472.     #if !defined (TX06D18_TFT_LCD )     //change by gongjun   
  473.         #if defined(CONFIG_S3C2410_SMDK) && !defined(CONFIG_SMDK_AIJI)   
  474.             LCDLPCSEL = 0x2;  
  475.         #elif defined(CONFIG_S3C2410_SMDK) && defined(CONFIG_SMDK_AIJI)    
  476.             LCDLPCSEL = 0x7;  
  477.         #endif   
  478.     #endif   
  479.       
  480.     __raw_writel(0, S3C2410_TPAL);  
  481.     __raw_writel(fbi->reg.lcdcon1|S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);  
  482.   
  483. #if 1   
  484.     {  
  485.         printk("LCDCON1 0x%08x ", __raw_readl(S3C2410_LCDCON1));  
  486.         printk("LCDCON2 0x%08x ", __raw_readl(S3C2410_LCDCON2));  
  487.         printk("LCDCON3 0x%08x ", __raw_readl(S3C2410_LCDCON3));  
  488.         printk("LCDCON4 0x%08x ", __raw_readl(S3C2410_LCDCON4));  
  489.         printk("LCDCON5 0x%08x ", __raw_readl(S3C2410_LCDCON5));  
  490.         printk("LCDSADDR1 0x%08x ", __raw_readl(S3C2410_LCDSADDR1));  
  491.         printk("LCDSADDR2 0x%08x ", __raw_readl(S3C2410_LCDSADDR2));  
  492.         printk("LCDSADDR3 0x%08x ", __raw_readl(S3C2410_LCDSADDR3));  
  493.     }  
  494. #endif   
  495.     local_irq_restore(flags);  
  496.   
  497.     return 0;  
  498. }  
  499.   
  500. /* 
  501.  * NOTE!  The following functions are purely helpers for set_ctrlr_state. 
  502.  * Do not call them directly; set_ctrlr_state does the correct serialisation 
  503.  * to ensure that things happen in the right way 100% of time time. 
  504.  *  -- rmk 
  505.  */  
  506. static inline void __gzliu_fb_backlight_power(struct gzliu_fb_info *fbi, int on)  
  507. {  
  508. printk("@@@@@@@@@@ __gzliu_fb_backlight_power() @@@@@@@@@@@@ ");  
  509. printk("backlight o%s ", on ? "n" : "ff");  
  510.   
  511.     if (gzliu_fb_backlight_power)  
  512.         gzliu_fb_backlight_power(on);  
  513. }  
  514.   
  515. static inline void __gzliu_fb_lcd_power(struct gzliu_fb_info *fbi, int on)  
  516. {  
  517. printk("@@@@@@@@@@ __gzliu_fb_lcd_power() @@@@@@@@@@@@ ");  
  518. printk("LCD power o%s ", on ? "n" : "ff");  
  519.   
  520.     if (gzliu_fb_lcd_power)  
  521.         gzliu_fb_lcd_power(on);  
  522. }  
  523.   
  524. static void gzliu_fb_setup_gpio(struct gzliu_fb_info *fbi)  
  525. {  
  526. printk("@@@@@@@@@@ gzliu_fb_setup_gpio() @@@@@@@@@@@@ ");  
  527.     DPRINTK("setup gpio ");  
  528.       
  529.     // 将GPD这组GPIO的16个引脚配置为VD   
  530.     __raw_writel(0xaaaaaaaa, S3C2410_GPDCON);  
  531.     __raw_writel(7, S3C2410_LCDINTMSK);         // 3 by gjl MASK LCD Sub Interrupt   
  532.     __raw_writel(0, S3C2410_TPAL);              // Disable Temp Palette   
  533.     __raw_writel(0, S3C2410_LPCSEL);            // 0 by gjl Disable LPC3600   
  534.     __raw_writel(0, S3C2410_PRIORITY);          //0x7f add by gjl   
  535. }  
  536.   
  537. static void gzliu_fb_enable_controller(struct gzliu_fb_info *fbi)  
  538. {  
  539. printk("@@@@@@@@@@ gzliu_fb_enable_controller() @@@@@@@@@@@@ ");  
  540.     __raw_writel(fbi->reg.lcdcon1&~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);  
  541.     __raw_writel(fbi->reg.lcdcon2, S3C2410_LCDCON2);  
  542.     __raw_writel(fbi->reg.lcdcon3, S3C2410_LCDCON3);  
  543.     __raw_writel(fbi->reg.lcdcon4, S3C2410_LCDCON4);  
  544.     __raw_writel(fbi->reg.lcdcon5, S3C2410_LCDCON5);  
  545.     __raw_writel(fbi->reg.lcdsaddr1, S3C2410_LCDSADDR1);  
  546.     __raw_writel(fbi->reg.lcdsaddr2, S3C2410_LCDSAD