rk30 fb:add suspend andr resume support
authoryxj <yxj@rock-chips.com>
Mon, 2 Apr 2012 06:47:59 +0000 (14:47 +0800)
committeryxj <yxj@rock-chips.com>
Mon, 2 Apr 2012 06:47:59 +0000 (14:47 +0800)
drivers/video/rockchip/chips/rk30_lcdc.c
drivers/video/rockchip/chips/rk30_lcdc.h
drivers/video/rockchip/rk_fb.c
include/linux/rk_fb.h

index f96bc6685ae0d3157e65b9632783424503f8c455..241377b28c3c94d5936e9afa25b1e91fe6160a8e 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/device.h>
-
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -55,7 +55,7 @@ static int init_rk30_lcdc(struct rk30_lcdc_device *lcdc_dev)
        }
        else if(lcdc_dev->id == 1)
        {
-               lcdc_dev->hclk = clk_get(NULL,"hclk_lcdc1"); 
+               lcdc_dev->hclk = clk_get(NULL,"hclk_lcdc1");  
                lcdc_dev->aclk = clk_get(NULL,"aclk_lcdc1");
                lcdc_dev->dclk = clk_get(NULL,"dclk_lcdc1");
        }
@@ -69,6 +69,12 @@ static int init_rk30_lcdc(struct rk30_lcdc_device *lcdc_dev)
                        printk(KERN_ERR "failed to get lcdc%d clk source\n",lcdc_dev->id);
        }
        clk_enable(lcdc_dev->hclk);  //enable aclk for register config
+       LcdMskReg(lcdc_dev,SYS_CTRL0,m_HWC_CHANNEL_ID | m_WIN2_CHANNEL_ID | m_WIN1_CBR_CHANNEL_ID |
+               m_WIN1_YRGB_CHANNEL_ID | m_WIN0_CBR_CHANNEL1_ID | m_WIN0_YRGB_CHANNEL1_ID | 
+               m_WIN0_CBR_CHANNEL0_ID | m_WIN0_YRGB_CHANNEL0_ID,v_HWC_CHANNEL_ID(7) | 
+               v_WIN2_CHANNEL_ID(6) | v_WIN1_CBR_CHANNEL_ID(5) | v_WIN1_YRGB_CHANNEL_ID(4) | 
+               v_WIN0_CBR_CHANNEL1_ID(3) | v_WIN0_YRGB_CHANNEL1_ID(2) | v_WIN0_CBR_CHANNEL0_ID(1) |
+               v_WIN0_YRGB_CHANNEL0_ID(0));                    //channel id ,just use default value
        LcdSetBit(lcdc_dev,DSP_CTRL0, m_LCDC_AXICLK_AUTO_ENABLE);//eanble axi-clk auto gating for low power
        LcdMskReg(lcdc_dev,INT_STATUS,m_FRM_START_INT_CLEAR | m_BUS_ERR_INT_CLEAR | m_LINE_FLAG_INT_EN |
               m_FRM_START_INT_EN | m_HOR_START_INT_EN,v_FRM_START_INT_CLEAR(1) | v_BUS_ERR_INT_CLEAR(0) |
@@ -136,44 +142,45 @@ static int rk30_load_screen(struct rk_lcdc_device_driver *dev_drv, bool initscre
        // set synchronous pin polarity and data pin swap rule
        switch (screen->face)
        {
-        case OUT_P565:
-            face = OUT_P565;
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
-            break;
-        case OUT_P666:
-            face = OUT_P666;
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
-            break;
-        case OUT_D888_P565:
-            face = OUT_P888;
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
-            break;
-        case OUT_D888_P666:
-            face = OUT_P888;
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
-            break;
-        case OUT_P888:
-            face = OUT_P888;
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(1));
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
-            break;
-        default:
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(0));
-            LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
-            face = screen->face;
-            break;
-    }
+               case OUT_P565:
+                       face = OUT_P565;
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
+                       break;
+               case OUT_P666:
+                       face = OUT_P666;
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
+                       break;
+               case OUT_D888_P565:
+                       face = OUT_P888;
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(0));
+                       break;
+               case OUT_D888_P666:
+                       face = OUT_P888;
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(1) | v_DITHER_DOWN_MODE(1));
+                       break;
+               case OUT_P888:
+                       face = OUT_P888;
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(1));
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
+                       break;
+               default:
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_UP_EN, v_DITHER_UP_EN(0));
+                       LcdMskReg(lcdc_dev, DSP_CTRL0, m_DITHER_DOWN_EN | m_DITHER_DOWN_MODE, v_DITHER_DOWN_EN(0) | v_DITHER_DOWN_MODE(0));
+                       face = screen->face;
+                       break;
+       }
 
        //use default overlay,set vsyn hsync den dclk polarity
        LcdMskReg(lcdc_dev, DSP_CTRL0,m_DISPLAY_FORMAT | m_HSYNC_POLARITY | m_VSYNC_POLARITY |
                m_DEN_POLARITY |m_DCLK_POLARITY,v_DISPLAY_FORMAT(face) | 
-               v_HSYNC_POLARITY(screen->pin_hsync) | v_VSYNC_POLARITY(screen->pin_vsync) |
+               v_HSYNC_POLARITY(screen->pin_hsync) | v_VSYNC_POLARITY(screen->pin_vsync) |
                v_DEN_POLARITY(screen->pin_den) | v_DCLK_POLARITY(screen->pin_dclk));
 
-       //set background color to black,set swap according to the screen panel
+       //set background color to black,set swap according to the screen panel,disable blank mode
        LcdMskReg(lcdc_dev, DSP_CTRL1, m_BG_COLOR | m_OUTPUT_RB_SWAP | m_OUTPUT_RG_SWAP | m_DELTA_SWAP | 
-               m_DUMMY_SWAP,  v_BG_COLOR(0x000000) | v_OUTPUT_RB_SWAP(screen->swap_rb) | 
-               v_OUTPUT_RG_SWAP(screen->swap_rg) | v_DELTA_SWAP(screen->swap_delta) | v_DUMMY_SWAP(screen->swap_dumy) );
+               m_DUMMY_SWAP | m_BLANK_MODE,v_BG_COLOR(0x000000) | v_OUTPUT_RB_SWAP(screen->swap_rb) | 
+               v_OUTPUT_RG_SWAP(screen->swap_rg) | v_DELTA_SWAP(screen->swap_delta) | v_DUMMY_SWAP(screen->swap_dumy) |
+               v_BLACK_MODE(0));
 
        
        LcdWrReg(lcdc_dev, DSP_HTOTAL_HS_END,v_HSYNC(screen->hsync_len) |
@@ -331,30 +338,30 @@ static  int win0_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
     switch (par->format)
     {
        case YUV422:// yuv422
-            ScaleCbrX CalScale((xact/2), par->xsize);
+            ScaleCbrX = CalScale((xact/2), par->xsize);
             ScaleCbrY = CalScale(yact, par->ysize);
                    break;
        case YUV420: // yuv420
-           ScaleCbrX= CalScale(xact/2, par->xsize);
-           ScaleCbrY =  CalScale(yact/2, par->ysize);
+           ScaleCbrX = CalScale(xact/2, par->xsize);
+           ScaleCbrY = CalScale(yact/2, par->ysize);
            break;
        case YUV444:// yuv444
-           ScaleCbrX= CalScale(xact, par->xsize);
+           ScaleCbrX = CalScale(xact, par->xsize);
            ScaleCbrY = CalScale(yact, par->ysize);
            break;
        default:
            break;
     }
 
-       DBG("%s>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>ypos:%d>>\n",
+    DBG("%s>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>ypos:%d>>\n",
                __func__,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,ypos);
-    LcdMskReg(lcdc_dev,SYS_CTRL1,  m_W0_FORMAT , v_W0_FORMAT(par->format));            //(inf->video_mode==0)
+    LcdMskReg(lcdc_dev,SYS_CTRL1, m_W0_FORMAT , v_W0_FORMAT(par->format));             //(inf->video_mode==0)
     LcdWrReg(lcdc_dev, WIN0_ACT_INFO,v_ACT_WIDTH(xact) | v_ACT_HEIGHT(yact));
     LcdWrReg(lcdc_dev, WIN0_DSP_ST, v_DSP_STX(xpos) | v_DSP_STY(ypos));
-    LcdWrReg(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(par->xsize) | v_DSP_HEIGHT(par->ysize));
+    LcdWrReg(lcdc_dev, WIN0_DSP_INFO, v_DSP_WIDTH(par->xsize)| v_DSP_HEIGHT(par->ysize));
     LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_YRGB, v_X_SCL_FACTOR(ScaleYrgbX) | v_Y_SCL_FACTOR(ScaleYrgbY));
-    LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_CBR,  v_X_SCL_FACTOR(ScaleCbrX) | v_Y_SCL_FACTOR(ScaleCbrY));
-    switch(par->format)
+    LcdWrReg(lcdc_dev, WIN0_SCL_FACTOR_CBR,v_X_SCL_FACTOR(ScaleCbrX)| v_Y_SCL_FACTOR(ScaleCbrY));
+    switch(par->format) 
     {
         case ARGB888:
             LcdWrReg(lcdc_dev, WIN0_VIR,v_ARGB888_VIRWIDTH(xvir));
@@ -421,7 +428,7 @@ static int win1_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen,
 
     LcdWrReg(lcdc_dev, WIN1_SCL_FACTOR_YRGB, v_X_SCL_FACTOR(ScaleYrgbX) | v_Y_SCL_FACTOR(ScaleYrgbY));
     LcdWrReg(lcdc_dev, WIN1_SCL_FACTOR_CBR,  v_X_SCL_FACTOR(ScaleCbrX) | v_Y_SCL_FACTOR(ScaleCbrY));
-    LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN|m_W1_FORMAT, v_W1_EN(1)|v_W1_FORMAT(par->format));
+    LcdMskReg(lcdc_dev,SYS_CTRL1, m_W1_EN|m_W1_FORMAT, v_W1_EN(1)|v_W1_FORMAT(par->format));
     LcdWrReg(lcdc_dev, WIN1_ACT_INFO,v_ACT_WIDTH(xact) | v_ACT_HEIGHT(yact));
     LcdWrReg(lcdc_dev, WIN1_DSP_ST,v_DSP_STX(xpos) | v_DSP_STY(ypos));
     LcdWrReg(lcdc_dev, WIN1_DSP_INFO,v_DSP_WIDTH(par->xsize) | v_DSP_HEIGHT(par->ysize));
@@ -542,18 +549,20 @@ int rk30_lcdc_ioctl(struct rk_lcdc_device_driver * dev_drv,unsigned int cmd, uns
        return 0;
 }
 
-int rk30_lcdc_suspend(struct rk_lcdc_device_driver *dev_drv)
+int rk30_lcdc_early_suspend(struct rk_lcdc_device_driver *dev_drv)
 {
        struct rk30_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk30_lcdc_device,driver);
        LcdMskReg(lcdc_dev, SYS_CTRL0,m_LCDC_STANDBY,v_LCDC_STANDBY(1));
+       LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
        return 0;
 }
 
 
-int rk30_lcdc_resume(struct rk_lcdc_device_driver *dev_drv)
+int rk30_lcdc_early_resume(struct rk_lcdc_device_driver *dev_drv)
 {  
        struct rk30_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk30_lcdc_device,driver);
        LcdMskReg(lcdc_dev, SYS_CTRL0,m_LCDC_STANDBY,v_LCDC_STANDBY(0));
+       LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01);
        return 0;
 }
 
@@ -570,13 +579,13 @@ static irqreturn_t rk30_lcdc_isr(int irq, void *dev_id)
 
 static struct layer_par lcdc_layer[] = {
        [0] = {
-               .name           = "win0",
-               .id                     = 0,
+               .name           = "win0",
+               .id             = 0,
                .support_3d     = true,
        },
        [1] = {
-        .name                  = "win1",
-               .id                     = 1,
+               .name           = "win1",
+               .id             = 1,
                .support_3d     = false,
        },
 };
@@ -586,13 +595,44 @@ static struct rk_lcdc_device_driver lcdc_driver = {
        .layer_par              = lcdc_layer,
        .num_layer              = ARRAY_SIZE(lcdc_layer),
        .ioctl                  = rk30_lcdc_ioctl,
-       .suspend                = rk30_lcdc_suspend,
-       .resume                 = rk30_lcdc_resume,
+       .suspend                = rk30_lcdc_early_suspend,
+       .resume                 = rk30_lcdc_early_resume,
        .set_par                = rk30_lcdc_set_par,
        .blank                  = rk30_lcdc_blank,
        .pan_display            = rk30_lcdc_pan_display,
        .load_screen            = rk30_load_screen,
 };
+#ifdef CONFIG_PM
+static int rk30_lcdc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rk30_lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
+
+       
+       clk_disable(lcdc_dev->dclk);
+       clk_disable(lcdc_dev->hclk);
+       clk_disable(lcdc_dev->aclk);
+       printk("%s>>>>\n",__func__);
+       return 0;
+}
+
+static int rk30_lcdc_resume(struct platform_device *pdev)
+{
+       struct rk30_lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
+       clk_enable(lcdc_dev->hclk);
+       clk_enable(lcdc_dev->dclk);
+       clk_enable(lcdc_dev->aclk);
+       usleep_range(10*1000, 10*1000);
+       memcpy((u8*)lcdc_dev->preg, (u8*)&lcdc_dev->regbak, 0xc4);  //resume reg
+       usleep_range(40*1000, 40*1000);
+       printk("%s>>>>\n",__func__);
+       return 0;
+}
+
+#else
+#define rk30_lcdc_suspend NULL
+#define rk30_lcddc_resume NULL
+#endif
+
 static int __devinit rk30_lcdc_probe (struct platform_device *pdev)
 {
        struct rk30_lcdc_device *lcdc_dev=NULL;
@@ -736,6 +776,8 @@ static struct platform_driver rk30lcdc_driver = {
                .name   = "rk30-lcdc",
                .owner  = THIS_MODULE,
        },
+       .suspend        = rk30_lcdc_suspend,
+       .resume         = rk30_lcdc_resume,
        .shutdown   = rk30_lcdc_shutdown,
 };
 
@@ -751,7 +793,7 @@ static void __exit rk30_lcdc_exit(void)
 
 
 
-fs_initcall(rk30_lcdc_init);
+fs_initcall_sync(rk30_lcdc_init);
 module_exit(rk30_lcdc_exit);
 
 
index 286f9e40e14d3dd0225f2ebed072c4faa04d5109..6a181d5748115589bb398a677c4b6137b84ce111 100644 (file)
 typedef volatile struct tagLCDC_REG
 {
     /* offset 0x00~0xc0 */
-    unsigned int SYS_CTRL0;               //0x00 system control register 0
-    unsigned int SYS_CTRL1;                              //0x04 system control register 1
-    unsigned int DSP_CTRL0;                             //0x08 display control register 0
-    unsigned int DSP_CTRL1;                             //0x0c display control register 1
-    unsigned int INT_STATUS;             //0x10 Interrupt status register
-    unsigned int MCU_CTRL ;                             //0x14 MCU mode contol register
-    unsigned int BLEND_CTRL;             //0x18 Blending control register
-    unsigned int WIN0_COLOR_KEY_CTRL;     //0x1c Win0 blending control register
-    unsigned int WIN1_COLOR_KEY_CTRL;     //0x20 Win1 blending control register
-    unsigned int WIN2_COLOR_KEY_CTRL;     //0x24 Win2 blending control register
-    unsigned int WIN0_YRGB_MST0;           //0x28 Win0 active YRGB memory start address0
-    unsigned int WIN0_CBR_MST0;            //0x2c Win0 active Cbr memory start address0
-    unsigned int WIN0_YRGB_MST1;           //0x30 Win0 active YRGB memory start address1
-    unsigned int WIN0_CBR_MST1;            //0x34 Win0 active Cbr memory start address1
-    unsigned int WIN0_VIR;                //0x38 WIN0 virtual display width/height
-    unsigned int WIN0_ACT_INFO;           //0x3C Win0 active window width/height
-    unsigned int WIN0_DSP_INFO;           //0x40 Win0 display width/height on panel
-    unsigned int WIN0_DSP_ST;             //0x44 Win0 display start point on panel
-    unsigned int WIN0_SCL_FACTOR_YRGB;    //0x48Win0 YRGB scaling  factor setting
-    unsigned int WIN0_SCL_FACTOR_CBR;     //0x4c Win0 YRGB scaling factor setting
-    unsigned int WIN0_SCL_OFFSET;         //0x50 Win0 Cbr scaling start point offset
-    unsigned int WIN1_YRGB_MST;           //0x54 Win1 active YRGB memory start address
-    unsigned int WIN1_CBR_MST;            //0x58 Win1 active Cbr memory start address
-    unsigned int WIN1_VIR;                //0x5c WIN1 virtual display width/height
-    unsigned int WIN1_ACT_INFO;           //0x60 Win1 active window width/height
-    unsigned int WIN1_DSP_INFO;           //0x64 Win1 display width/height on panel
-    unsigned int WIN1_DSP_ST;             //0x68 Win1 display start point on panel
-    unsigned int WIN1_SCL_FACTOR_YRGB;    //0x6c Win1 YRGB scaling  factor setting
-    unsigned int WIN1_SCL_FACTOR_CBR;     //0x70 Win1 YRGB scaling factor setting
-    unsigned int WIN1_SCL_OFFSET;         //0x74 Win1 Cbr scaling start point offset
+       unsigned int SYS_CTRL0;               //0x00 system control register 0
+       unsigned int SYS_CTRL1;                           //0x04 system control register 1
+       unsigned int DSP_CTRL0;                          //0x08 display control register 0
+       unsigned int DSP_CTRL1;                          //0x0c display control register 1
+       unsigned int INT_STATUS;             //0x10 Interrupt status register
+       unsigned int MCU_CTRL ;                          //0x14 MCU mode contol register
+       unsigned int BLEND_CTRL;             //0x18 Blending control register
+       unsigned int WIN0_COLOR_KEY_CTRL;     //0x1c Win0 blending control register
+       unsigned int WIN1_COLOR_KEY_CTRL;     //0x20 Win1 blending control register
+       unsigned int WIN2_COLOR_KEY_CTRL;     //0x24 Win2 blending control register
+       unsigned int WIN0_YRGB_MST0;           //0x28 Win0 active YRGB memory start address0
+       unsigned int WIN0_CBR_MST0;            //0x2c Win0 active Cbr memory start address0
+       unsigned int WIN0_YRGB_MST1;           //0x30 Win0 active YRGB memory start address1
+       unsigned int WIN0_CBR_MST1;            //0x34 Win0 active Cbr memory start address1
+       unsigned int WIN0_VIR;                //0x38 WIN0 virtual display width/height
+       unsigned int WIN0_ACT_INFO;           //0x3C Win0 active window width/height
+       unsigned int WIN0_DSP_INFO;           //0x40 Win0 display width/height on panel
+       unsigned int WIN0_DSP_ST;             //0x44 Win0 display start point on panel
+       unsigned int WIN0_SCL_FACTOR_YRGB;    //0x48Win0 YRGB scaling  factor setting
+       unsigned int WIN0_SCL_FACTOR_CBR;     //0x4c Win0 YRGB scaling factor setting
+       unsigned int WIN0_SCL_OFFSET;         //0x50 Win0 Cbr scaling start point offset
+       unsigned int WIN1_YRGB_MST;           //0x54 Win1 active YRGB memory start address
+       unsigned int WIN1_CBR_MST;            //0x58 Win1 active Cbr memory start address
+       unsigned int WIN1_VIR;                //0x5c WIN1 virtual display width/height
+       unsigned int WIN1_ACT_INFO;           //0x60 Win1 active window width/height
+       unsigned int WIN1_DSP_INFO;           //0x64 Win1 display width/height on panel
+       unsigned int WIN1_DSP_ST;             //0x68 Win1 display start point on panel
+       unsigned int WIN1_SCL_FACTOR_YRGB;    //0x6c Win1 YRGB scaling  factor setting
+       unsigned int WIN1_SCL_FACTOR_CBR;     //0x70 Win1 YRGB scaling factor setting
+       unsigned int WIN1_SCL_OFFSET;         //0x74 Win1 Cbr scaling start point offset
        unsigned int WIN2_MST;                            //0x78 win2 memort start address
        unsigned int WIM2_VIR;                            //0x7c win2 virtual stride
        unsigned int WIN2_DSP_INFO;           //0x80 Win2 display width/height on panel
-    unsigned int WIN2_DSP_ST;             //0x84 Win2 display start point on panel
-    unsigned int HWC_MST;                 //0x88 HWC memory start address
-    unsigned int HWC_DSP_ST;              //0x8C HWC display start point on panel
+       unsigned int WIN2_DSP_ST;             //0x84 Win2 display start point on panel
+       unsigned int HWC_MST;                 //0x88 HWC memory start address
+       unsigned int HWC_DSP_ST;              //0x8C HWC display start point on panel
        unsigned int HWC_COLOR_LUT0;          //0x90 Hardware cursor color 2¡¯b01 look up table 0
-    unsigned int HWC_COLOR_LUT1;          //0x94 Hardware cursor color 2¡¯b10 look up table 1
-    unsigned int HWC_COLOR_LUT2;          //0x98 Hardware cursor color 2¡¯b11 look up table 2
+       unsigned int HWC_COLOR_LUT1;          //0x94 Hardware cursor color 2¡¯b10 look up table 1
+       unsigned int HWC_COLOR_LUT2;          //0x98 Hardware cursor color 2¡¯b11 look up table 2
        unsigned int DSP_HTOTAL_HS_END;       //0x9c Panel scanning horizontal width and hsync pulse end point
        unsigned int DSP_HACT_ST_END;         //0xa0 Panel active horizontal scanning start/end point
        unsigned int DSP_VTOTAL_VS_END;       //0xa4 Panel scanning vertical height and vsync pulse end point
-    unsigned int DSP_VACT_ST_END;         //0xa8 Panel active vertical scanning start/end point
+       unsigned int DSP_VACT_ST_END;         //0xa8 Panel active vertical scanning start/end point
        unsigned int DSP_VS_ST_END_F1;        //0xac Vertical scanning start point and vsync pulse end point of even filed in interlace mode
-    unsigned int DSP_VACT_ST_END_F1;      //0xb0 Vertical scanning active start/end point of even filed in interlace mode
-    unsigned int reserved0[(0xc0-0xb4)/4];
+       unsigned int DSP_VACT_ST_END_F1;      //0xb0 Vertical scanning active start/end point of even filed in interlace mode
+       unsigned int reserved0[(0xc0-0xb4)/4];
        unsigned int REG_CFG_DONE;            //0xc0 REGISTER CONFIG FINISH
        unsigned int reserved1[(0x100-0xc4)/4];
        unsigned int MCU_BYPASS_WPORT;         //0x100 MCU BYPASS MODE, DATA Write Only Port
        unsigned int reserved2[(0x200-0x104)/4];
-    unsigned int MCU_BYPASS_RPORT;         //0x200 MCU BYPASS MODE, DATA Read Only Port   
+       unsigned int MCU_BYPASS_RPORT;         //0x200 MCU BYPASS MODE, DATA Read Only Port   
   
 } LCDC_REG, *pLCDC_REG;
 
index ce83abb3c8a1c55384822605813feb456d28f80b..1fea5dc5b3a1f36d1b433d65c7e2c27f792fb764 100644 (file)
        #define fbprintk(msg...)
 #endif
 
-#if 0
-#define CHK_SUSPEND(inf)       \
-       if(inf->in_suspend)     {       \
-               fbprintk(">>>>>> fb is in suspend! return! \n");        \
+#if 1
+#define CHK_SUSPEND(drv)       \
+       if(atomic_dec_and_test(&drv->in_suspend))       {       \
+               printk(">>>>>> fb is in suspend! return! \n");  \
                return -EPERM;  \
        }
 #else
@@ -100,17 +100,8 @@ struct rk_lcdc_device_driver * rk_get_lcdc_drv(int  id)
 }
 static int rk_fb_open(struct fb_info *info,int user)
 {
-    struct rk_fb_inf *inf = dev_get_drvdata(info->device);
-    struct rk_lcdc_device_driver *dev_drv = NULL;
-    struct fb_fix_screeninfo *fix = &info->fix;
-    int layer_id;
-    if(!strcmp(fix->id,"fb1")){
-        dev_drv = inf->lcdc_dev_drv[0];
-        layer_id = 0;
-        dev_drv->blank(dev_drv,1,FB_BLANK_NORMAL);  //when open fb1,defautl close fb0 layer win1
-        dev_drv->blank(dev_drv,layer_id,FB_BLANK_UNBLANK); //open fb1 layer win0
-        inf->video_mode = 1;
-    }
+    struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par;
+    CHK_SUSPEND(dev_drv);
     
 
     return 0;
@@ -139,6 +130,7 @@ static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
        u32 xvir = var->xres_virtual;
        u8 data_format = var->nonstd&0xff;
        layer_id = get_fb_layer_id(fix);
+       CHK_SUSPEND(dev_drv);
        if(layer_id < 0)
        {
                return  -ENODEV;
@@ -187,8 +179,8 @@ static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg)
        u32 yuv_phy[2];
        void __user *argp = (void __user *)arg;
        fbprintk(">>>>>> %s : cmd:0x%x \n",__FUNCTION__,cmd);
-       CHK_SUSPEND(inf);
        
+       CHK_SUSPEND(dev_drv);
        switch(cmd)
        {
                case FBIOPUT_FBPHYADD:
@@ -229,6 +221,7 @@ static int rk_fb_blank(int blank_mode, struct fb_info *info)
        struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
        struct fb_fix_screeninfo *fix = &info->fix;
        int layer_id;
+       CHK_SUSPEND(dev_drv);
        layer_id = get_fb_layer_id(fix);
        if(layer_id < 0)
        {
@@ -242,7 +235,8 @@ static int rk_fb_blank(int blank_mode, struct fb_info *info)
 
 static int rk_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-       CHK_SUSPEND(inf);
+       struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par;
+       CHK_SUSPEND(dev_drv);
  
         if( 0==var->xres_virtual || 0==var->yres_virtual ||
                 0==var->xres || 0==var->yres || var->xres<16 ||
@@ -336,7 +330,7 @@ static int rk_fb_set_par(struct fb_info *info)
     u32 xvir = var->xres_virtual;
     u32 yvir = var->yres_virtual;
     u8 data_format = var->nonstd&0xff;
-
+    CHK_SUSPEND(dev_drv);
     layer_id = get_fb_layer_id(fix);
     if(layer_id < 0)
     {
@@ -356,7 +350,6 @@ static int rk_fb_set_par(struct fb_info *info)
         xsize = (var->grayscale>>8) & 0xfff;  //visiable size in panel ,for vide0
         ysize = (var->grayscale>>20) & 0xfff;
     }
-       CHK_SUSPEND(inf);
        /* calculate y_offset,c_offset,line_length,cblen and crlen  */
 #if 1
     switch (data_format)
@@ -750,18 +743,26 @@ static void rkfb_early_suspend(struct early_suspend *h)
        struct suspend_info *info = container_of(h, struct suspend_info,
                                                early_suspend);
        struct rk_fb_inf *inf = info->inf;
-       inf->lcd_info->io_disable();
-       inf->lcdc_dev_drv[0]->suspend(inf->lcdc_dev_drv[0]);
-       inf->lcdc_dev_drv[1]->suspend(inf->lcdc_dev_drv[1]);
+       int i;
+       inf->lcd_info->io_disable();
+       for(i = 0; i < inf->num_lcdc; i++)
+       {
+               atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,1);
+               inf->lcdc_dev_drv[i]->suspend(inf->lcdc_dev_drv[i]);
+       }
 }
 static void rkfb_early_resume(struct early_suspend *h)
 {
        struct suspend_info *info = container_of(h, struct suspend_info,
                                                early_suspend);
        struct rk_fb_inf *inf = info->inf;
+       int i;
        inf->lcd_info->io_enable();
-       inf->lcdc_dev_drv[0]->resume(inf->lcdc_dev_drv[0]);
-       inf->lcdc_dev_drv[1]->resume(inf->lcdc_dev_drv[1]);
+       for(i = 0; i < inf->num_lcdc; i++)
+       {
+               inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]);
+               atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,0);
+       }
 
 }
 
index cef5d416738cea9a39ea0e399ad9692afc0f534f..a33dfd7ac448bdfd64a6b561f1a4882fa8628a9c 100644 (file)
@@ -17,6 +17,7 @@
 #define __ARCH_ARM_MACH_RK30_FB_H
 
 #include<linux/completion.h>
+#include<asm/atomic.h>
 #include <mach/board.h>
 #include<linux/rk_screen.h>
 
@@ -192,6 +193,8 @@ struct rk_lcdc_device_driver{
        struct completion  frame_done;            //sync for pan_display,whe we set a new frame address to lcdc register,we must make sure the frame begain to display
        spinlock_t  cpl_lock;                    //lock for completion  frame done
        int first_frame ;
+
+       atomic_t in_suspend;                    //when enter suspend write or read lcdc register are forbidden
        
        int (*ioctl)(struct rk_lcdc_device_driver *dev_drv, unsigned int cmd,unsigned long arg,int layer_id);
        int (*suspend)(struct rk_lcdc_device_driver *dev_drv);