From c9aaa8b28f715c32f6ce90fe415ee0869d6e9196 Mon Sep 17 00:00:00 2001 From: yxj Date: Mon, 2 Apr 2012 14:47:59 +0800 Subject: [PATCH] rk30 fb:add suspend andr resume support --- drivers/video/rockchip/chips/rk30_lcdc.c | 146 +++++++++++++++-------- drivers/video/rockchip/chips/rk30_lcdc.h | 78 ++++++------ drivers/video/rockchip/rk_fb.c | 49 ++++---- include/linux/rk_fb.h | 3 + 4 files changed, 161 insertions(+), 115 deletions(-) diff --git a/drivers/video/rockchip/chips/rk30_lcdc.c b/drivers/video/rockchip/chips/rk30_lcdc.c index f96bc6685ae0..241377b28c3c 100644 --- a/drivers/video/rockchip/chips/rk30_lcdc.c +++ b/drivers/video/rockchip/chips/rk30_lcdc.c @@ -22,7 +22,7 @@ #include #include #include - +#include #include #include #include @@ -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); diff --git a/drivers/video/rockchip/chips/rk30_lcdc.h b/drivers/video/rockchip/chips/rk30_lcdc.h index 286f9e40e14d..6a181d574811 100644 --- a/drivers/video/rockchip/chips/rk30_lcdc.h +++ b/drivers/video/rockchip/chips/rk30_lcdc.h @@ -17,57 +17,57 @@ 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; diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index ce83abb3c8a1..1fea5dc5b3a1 100644 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -37,10 +37,10 @@ #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); + } } diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index cef5d416738c..a33dfd7ac448 100644 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -17,6 +17,7 @@ #define __ARCH_ARM_MACH_RK30_FB_H #include +#include #include #include @@ -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); -- 2.34.1