From: yxj Date: Tue, 24 Apr 2012 09:15:06 +0000 (+0800) Subject: rk30 fb; add spinlock for lcdc register config,cancel the delay before and after... X-Git-Tag: firefly_0821_release~9327 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4e08d3f03db74524dc852db98364263d778c9663;p=firefly-linux-kernel-4.4.55.git rk30 fb; add spinlock for lcdc register config,cancel the delay before and after register copy in rk30_lcdc_resume one time only one process allowed to access the register, when the lcdc aclk and hclk were disabled,access to lcdc register were not allowed --- diff --git a/drivers/video/rockchip/chips/rk30_lcdc.c b/drivers/video/rockchip/chips/rk30_lcdc.c index 0d56ac346bed..8e1cd6ba6c97 100644 --- a/drivers/video/rockchip/chips/rk30_lcdc.c +++ b/drivers/video/rockchip/chips/rk30_lcdc.c @@ -66,7 +66,9 @@ static int init_rk30_lcdc(struct rk_lcdc_device_driver *dev_drv) { printk(KERN_ERR "failed to get lcdc%d clk source\n",lcdc_dev->id); } - clk_enable(lcdc_dev->hclk); //enable aclk for register config + clk_enable(lcdc_dev->hclk); //enable aclk and hclk for register config + clk_enable(lcdc_dev->aclk); + lcdc_dev->clk_on = 1; 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) | @@ -107,94 +109,93 @@ static int rk30_load_screen(struct rk_lcdc_device_driver *dev_drv, bool initscre // set the rgb or mcu spin_lock(&lcdc_dev->reg_lock); - if(screen->type==SCREEN_MCU) - { - LcdMskReg(lcdc_dev, MCU_CTRL, m_MCU_OUTPUT_SELECT,v_MCU_OUTPUT_SELECT(1)); - // set out format and mcu timing - mcu_total = (screen->mcu_wrperiod*150*1000)/1000000; - if(mcu_total>31) - mcu_total = 31; - if(mcu_total<3) - mcu_total = 3; - mcu_rwstart = (mcu_total+1)/4 - 1; - mcu_rwend = ((mcu_total+1)*3)/4 - 1; - mcu_csstart = (mcu_rwstart>2) ? (mcu_rwstart-3) : (0); - mcu_csend = (mcu_rwend>15) ? (mcu_rwend-1) : (mcu_rwend); - - DBG(1,">> mcu_total=%d, mcu_rwstart=%d, mcu_csstart=%d, mcu_rwend=%d, mcu_csend=%d \n", - mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend); - - // set horizontal & vertical out timing - - right_margin = x_res/6; - screen->pixclock = 150000000; //mcu fix to 150 MHz - LcdMskReg(lcdc_dev, MCU_CTRL,m_MCU_CS_ST | m_MCU_CS_END| m_MCU_RW_ST | m_MCU_RW_END | - m_MCU_WRITE_PERIOD | m_MCU_HOLDMODE_SELECT | m_MCU_HOLDMODE_FRAME_ST, - v_MCU_CS_ST(mcu_csstart) | v_MCU_CS_END(mcu_csend) | v_MCU_RW_ST(mcu_rwstart) | - v_MCU_RW_END(mcu_rwend) | v_MCU_WRITE_PERIOD(mcu_total) | - v_MCU_HOLDMODE_SELECT((SCREEN_MCU==screen->type)?(1):(0)) | v_MCU_HOLDMODE_FRAME_ST(0)); - - } - + if(likely(lcdc_dev->clk_on)) + { + if(screen->type==SCREEN_MCU) + { + LcdMskReg(lcdc_dev, MCU_CTRL, m_MCU_OUTPUT_SELECT,v_MCU_OUTPUT_SELECT(1)); + // set out format and mcu timing + mcu_total = (screen->mcu_wrperiod*150*1000)/1000000; + if(mcu_total>31) + mcu_total = 31; + if(mcu_total<3) + mcu_total = 3; + mcu_rwstart = (mcu_total+1)/4 - 1; + mcu_rwend = ((mcu_total+1)*3)/4 - 1; + mcu_csstart = (mcu_rwstart>2) ? (mcu_rwstart-3) : (0); + mcu_csend = (mcu_rwend>15) ? (mcu_rwend-1) : (mcu_rwend); + + //DBG(1,">> mcu_total=%d, mcu_rwstart=%d, mcu_csstart=%d, mcu_rwend=%d, mcu_csend=%d \n", + // mcu_total, mcu_rwstart, mcu_csstart, mcu_rwend, mcu_csend); + + // set horizontal & vertical out timing + + right_margin = x_res/6; + screen->pixclock = 150000000; //mcu fix to 150 MHz + LcdMskReg(lcdc_dev, MCU_CTRL,m_MCU_CS_ST | m_MCU_CS_END| m_MCU_RW_ST | m_MCU_RW_END | + m_MCU_WRITE_PERIOD | m_MCU_HOLDMODE_SELECT | m_MCU_HOLDMODE_FRAME_ST, + v_MCU_CS_ST(mcu_csstart) | v_MCU_CS_END(mcu_csend) | v_MCU_RW_ST(mcu_rwstart) | + v_MCU_RW_END(mcu_rwend) | v_MCU_WRITE_PERIOD(mcu_total) | + v_MCU_HOLDMODE_SELECT((SCREEN_MCU==screen->type)?(1):(0)) | v_MCU_HOLDMODE_FRAME_ST(0)); + } - // 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; - } - - //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_DEN_POLARITY(screen->pin_den) | v_DCLK_POLARITY(screen->pin_dclk)); - - //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 | 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) | - v_HORPRD(screen->hsync_len + screen->left_margin + x_res + right_margin)); - LcdWrReg(lcdc_dev, DSP_HACT_ST_END, v_HAEP(screen->hsync_len + screen->left_margin + x_res) | - v_HASP(screen->hsync_len + screen->left_margin)); - - LcdWrReg(lcdc_dev, DSP_VTOTAL_VS_END, v_VSYNC(screen->vsync_len) | - v_VERPRD(screen->vsync_len + screen->upper_margin + y_res + lower_margin)); - LcdWrReg(lcdc_dev, DSP_VACT_ST_END, v_VAEP(screen->vsync_len + screen->upper_margin+y_res)| - v_VASP(screen->vsync_len + screen->upper_margin)); - // let above to take effect - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); - - + 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; + } + + //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_DEN_POLARITY(screen->pin_den) | v_DCLK_POLARITY(screen->pin_dclk)); + + //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 | 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) | + v_HORPRD(screen->hsync_len + screen->left_margin + x_res + right_margin)); + LcdWrReg(lcdc_dev, DSP_HACT_ST_END, v_HAEP(screen->hsync_len + screen->left_margin + x_res) | + v_HASP(screen->hsync_len + screen->left_margin)); + + LcdWrReg(lcdc_dev, DSP_VTOTAL_VS_END, v_VSYNC(screen->vsync_len) | + v_VERPRD(screen->vsync_len + screen->upper_margin + y_res + lower_margin)); + LcdWrReg(lcdc_dev, DSP_VACT_ST_END, v_VAEP(screen->vsync_len + screen->upper_margin+y_res)| + v_VASP(screen->vsync_len + screen->upper_margin)); + // let above to take effect + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + } + spin_unlock(&lcdc_dev->reg_lock); ret = clk_set_rate(lcdc_dev->dclk, screen->pixclock); if(ret) @@ -220,7 +221,6 @@ static int rk30_load_screen(struct rk_lcdc_device_driver *dev_drv, bool initscre } - spin_unlock(&lcdc_dev->reg_lock); if(screen->init) { screen->init(); @@ -243,20 +243,25 @@ static int win0_open(struct rk30_lcdc_device *lcdc_dev,bool open) { spin_lock(&lcdc_dev->reg_lock); - LcdMskReg(lcdc_dev, SYS_CTRL1, m_W0_EN, v_W0_EN(open)); - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); - lcdc_dev->driver.layer_par[0]->state = open; + if(likely(lcdc_dev->clk_on)) + { + LcdMskReg(lcdc_dev, SYS_CTRL1, m_W0_EN, v_W0_EN(open)); + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + lcdc_dev->driver.layer_par[0]->state = open; + } spin_unlock(&lcdc_dev->reg_lock); printk(KERN_INFO "lcdc%d win0 %s\n",lcdc_dev->id,open?"open":"closed"); return 0; } static int win1_open(struct rk30_lcdc_device *lcdc_dev,bool open) { - spin_lock(&lcdc_dev->reg_lock); - LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN, v_W1_EN(open)); - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); - lcdc_dev->driver.layer_par[1]->state = open; + if(likely(lcdc_dev->clk_on)) + { + LcdMskReg(lcdc_dev, SYS_CTRL1, m_W1_EN, v_W1_EN(open)); + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + lcdc_dev->driver.layer_par[1]->state = open; + } spin_unlock(&lcdc_dev->reg_lock); printk(KERN_INFO "lcdc%d win1 %s\n",lcdc_dev->id,open?"open":"closed"); return 0; @@ -268,19 +273,26 @@ static int rk30_lcdc_blank(struct rk_lcdc_device_driver*lcdc_drv,int layer_id,in struct rk30_lcdc_device * lcdc_dev = container_of(lcdc_drv,struct rk30_lcdc_device ,driver); printk(KERN_INFO "%s>>>>>%d\n",__func__, blank_mode); - switch(blank_mode) - { - case FB_BLANK_UNBLANK: - LcdMskReg(lcdc_dev,DSP_CTRL1,m_BLANK_MODE ,v_BLANK_MODE(0)); - break; - case FB_BLANK_NORMAL: - LcdMskReg(lcdc_dev,DSP_CTRL1,m_BLANK_MODE ,v_BLANK_MODE(1)); - break; - default: - LcdMskReg(lcdc_dev,DSP_CTRL1,m_BLANK_MODE ,v_BLANK_MODE(1)); - break; + + spin_lock(&lcdc_dev->reg_lock); + if(likely(lcdc_dev->clk_on)) + { + switch(blank_mode) + { + case FB_BLANK_UNBLANK: + LcdMskReg(lcdc_dev,DSP_CTRL1,m_BLANK_MODE ,v_BLANK_MODE(0)); + break; + case FB_BLANK_NORMAL: + LcdMskReg(lcdc_dev,DSP_CTRL1,m_BLANK_MODE ,v_BLANK_MODE(1)); + break; + default: + LcdMskReg(lcdc_dev,DSP_CTRL1,m_BLANK_MODE ,v_BLANK_MODE(1)); + break; + } + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); } - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + spin_unlock(&lcdc_dev->reg_lock); + return 0; } @@ -291,9 +303,16 @@ static int win0_display(struct rk30_lcdc_device *lcdc_dev,struct layer_par *par y_addr = par->smem_start + par->y_offset; uv_addr = par->cbr_start + par->c_offset; DBG(2,KERN_INFO "lcdc%d>>%s:y_addr:0x%x>>uv_addr:0x%x\n",lcdc_dev->id,__func__,y_addr,uv_addr); - LcdWrReg(lcdc_dev, WIN0_YRGB_MST0, y_addr); - LcdWrReg(lcdc_dev, WIN0_CBR_MST0, uv_addr); - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + + spin_lock(&lcdc_dev->reg_lock); + if(likely(lcdc_dev->clk_on)) + { + LcdWrReg(lcdc_dev, WIN0_YRGB_MST0, y_addr); + LcdWrReg(lcdc_dev, WIN0_CBR_MST0, uv_addr); + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + } + spin_unlock(&lcdc_dev->reg_lock); + return 0; } @@ -305,9 +324,16 @@ static int win1_display(struct rk30_lcdc_device *lcdc_dev,struct layer_par *par y_addr = par->smem_start + par->y_offset; uv_addr = par->cbr_start + par->c_offset; DBG(2,KERN_INFO "lcdc%d>>%s>>y_addr:0x%x>>uv_addr:0x%x\n",lcdc_dev->id,__func__,y_addr,uv_addr); - LcdWrReg(lcdc_dev, WIN1_YRGB_MST, y_addr); - LcdWrReg(lcdc_dev, WIN1_CBR_MST, uv_addr); - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + + spin_lock(&lcdc_dev->reg_lock); + if(likely(lcdc_dev->clk_on)) + { + LcdWrReg(lcdc_dev, WIN1_YRGB_MST, y_addr); + LcdWrReg(lcdc_dev, WIN1_CBR_MST, uv_addr); + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + } + spin_unlock(&lcdc_dev->reg_lock); + return 0; } @@ -350,38 +376,42 @@ static int win0_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen, DBG(1,"%s for lcdc%d>>format:%d>>>xact:%d>>yact:%d>>xsize:%d>>ysize:%d>>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", __func__,lcdc_dev->id,par->format,xact,yact,par->xsize,par->ysize,xvir,yvir,xpos,ypos); + spin_lock(&lcdc_dev->reg_lock); - 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)); - 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)); - LcdMskReg(lcdc_dev, WIN0_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, - v_COLORKEY_EN(1) | v_KEYCOLOR(0)); - switch(par->format) - { - case ARGB888: - LcdWrReg(lcdc_dev, WIN0_VIR,v_ARGB888_VIRWIDTH(xvir)); - //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W0_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1)); - break; - case RGB888: //rgb888 - LcdWrReg(lcdc_dev, WIN0_VIR,v_RGB888_VIRWIDTH(xvir)); - //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W0_RGB_RB_SWAP,v_W0_RGB_RB_SWAP(1)); - break; - case RGB565: //rgb565 - LcdWrReg(lcdc_dev, WIN0_VIR,v_RGB565_VIRWIDTH(xvir)); - break; - case YUV422: - case YUV420: - LcdWrReg(lcdc_dev, WIN0_VIR,v_YUV_VIRWIDTH(xvir)); - break; - default: - LcdWrReg(lcdc_dev, WIN0_VIR,v_RGB888_VIRWIDTH(xvir)); - break; + if(likely(lcdc_dev->clk_on)) + { + 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)); + 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)); + LcdMskReg(lcdc_dev, WIN0_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, + v_COLORKEY_EN(1) | v_KEYCOLOR(0)); + switch(par->format) + { + case ARGB888: + LcdWrReg(lcdc_dev, WIN0_VIR,v_ARGB888_VIRWIDTH(xvir)); + //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W0_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1)); + break; + case RGB888: //rgb888 + LcdWrReg(lcdc_dev, WIN0_VIR,v_RGB888_VIRWIDTH(xvir)); + //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W0_RGB_RB_SWAP,v_W0_RGB_RB_SWAP(1)); + break; + case RGB565: //rgb565 + LcdWrReg(lcdc_dev, WIN0_VIR,v_RGB565_VIRWIDTH(xvir)); + break; + case YUV422: + case YUV420: + LcdWrReg(lcdc_dev, WIN0_VIR,v_YUV_VIRWIDTH(xvir)); + break; + default: + LcdWrReg(lcdc_dev, WIN0_VIR,v_RGB888_VIRWIDTH(xvir)); + break; + } + + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); } - - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); spin_unlock(&lcdc_dev->reg_lock); return 0; @@ -411,56 +441,58 @@ static int win1_set_par(struct rk30_lcdc_device *lcdc_dev,rk_screen *screen, spin_lock(&lcdc_dev->reg_lock); - switch (par->format) - { - case YUV422:// yuv422 - 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); - break; - case YUV444:// yuv444 - ScaleCbrX = CalScale(xact, par->xsize); - ScaleCbrY = CalScale(yact, par->ysize); - break; - default: - break; + if(likely(lcdc_dev->clk_on)) + { + switch (par->format) + { + case YUV422:// yuv422 + 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); + break; + case YUV444:// yuv444 + ScaleCbrX = CalScale(xact, par->xsize); + ScaleCbrY = CalScale(yact, par->ysize); + break; + default: + break; + } + + 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_FORMAT, 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)); + // enable win1 color key and set the color to black(rgb=0) + LcdMskReg(lcdc_dev, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR,v_COLORKEY_EN(1) | v_KEYCOLOR(0)); + switch(par->format) + { + case ARGB888: + LcdWrReg(lcdc_dev, WIN1_VIR,v_ARGB888_VIRWIDTH(xvir)); + //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W1_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1)); + break; + case RGB888: //rgb888 + LcdWrReg(lcdc_dev, WIN1_VIR,v_RGB888_VIRWIDTH(xvir)); + // LcdMskReg(lcdc_dev,SYS_CTRL1,m_W1_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1)); + break; + case RGB565: //rgb565 + LcdWrReg(lcdc_dev, WIN1_VIR,v_RGB565_VIRWIDTH(xvir)); + break; + case YUV422: + case YUV420: + LcdWrReg(lcdc_dev, WIN1_VIR,v_YUV_VIRWIDTH(xvir)); + break; + default: + LcdWrReg(lcdc_dev, WIN1_VIR,v_RGB888_VIRWIDTH(xvir)); + break; + } + + LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); } - - 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_FORMAT, 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)); - // enable win1 color key and set the color to black(rgb=0) - LcdMskReg(lcdc_dev, WIN1_COLOR_KEY_CTRL, m_COLORKEY_EN | m_KEYCOLOR, - v_COLORKEY_EN(1) | v_KEYCOLOR(0)); - switch(par->format) - { - case ARGB888: - LcdWrReg(lcdc_dev, WIN1_VIR,v_ARGB888_VIRWIDTH(xvir)); - //LcdMskReg(lcdc_dev,SYS_CTRL1,m_W1_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1)); - break; - case RGB888: //rgb888 - LcdWrReg(lcdc_dev, WIN1_VIR,v_RGB888_VIRWIDTH(xvir)); - // LcdMskReg(lcdc_dev,SYS_CTRL1,m_W1_RGB_RB_SWAP,v_W1_RGB_RB_SWAP(1)); - break; - case RGB565: //rgb565 - LcdWrReg(lcdc_dev, WIN1_VIR,v_RGB565_VIRWIDTH(xvir)); - break; - case YUV422: - case YUV420: - LcdWrReg(lcdc_dev, WIN1_VIR,v_YUV_VIRWIDTH(xvir)); - break; - default: - LcdWrReg(lcdc_dev, WIN1_VIR,v_RGB888_VIRWIDTH(xvir)); - break; - } - - LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); spin_unlock(&lcdc_dev->reg_lock); return 0; } @@ -597,8 +629,13 @@ static int rk30_get_disp_info(struct rk_lcdc_device_driver *dev_drv,int layer_id 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); + + spin_lock(&lcdc_dev->reg_lock); + lcdc_dev->clk_on = 0; LcdMskReg(lcdc_dev, SYS_CTRL0,m_LCDC_STANDBY,v_LCDC_STANDBY(1)); LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + spin_unlock(&lcdc_dev->reg_lock); + return 0; } @@ -606,8 +643,13 @@ int rk30_lcdc_early_suspend(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); + + spin_lock(&lcdc_dev->reg_lock); LcdMskReg(lcdc_dev, SYS_CTRL0,m_LCDC_STANDBY,v_LCDC_STANDBY(0)); LcdWrReg(lcdc_dev, REG_CFG_DONE, 0x01); + lcdc_dev->clk_on = 1; + spin_unlock(&lcdc_dev->reg_lock); + return 0; } static irqreturn_t rk30_lcdc_isr(int irq, void *dev_id) @@ -659,6 +701,7 @@ static int rk30_lcdc_suspend(struct platform_device *pdev, pm_message_t state) clk_disable(lcdc_dev->dclk); clk_disable(lcdc_dev->hclk); clk_disable(lcdc_dev->aclk); + return 0; } @@ -669,9 +712,8 @@ static int rk30_lcdc_resume(struct platform_device *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); + return 0; } diff --git a/drivers/video/rockchip/chips/rk30_lcdc.h b/drivers/video/rockchip/chips/rk30_lcdc.h index 5fbd95602dde..813fc10a7649 100644 --- a/drivers/video/rockchip/chips/rk30_lcdc.h +++ b/drivers/video/rockchip/chips/rk30_lcdc.h @@ -482,6 +482,7 @@ struct rk30_lcdc_device{ u32 reg_phy_base; // physical basic address of lcdc register u32 len; // physical map length of lcdc register spinlock_t reg_lock; //one time only one process allowed to config the register + bool clk_on; //if aclk or hclk is closed ,acess to register is not allowed unsigned int irq; diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index 478acee2fb38..0a3473d01168 100644 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -33,21 +33,6 @@ #include "hdmi/rk_hdmi.h" -#if 0 - #define fbprintk(msg...) printk(msg); -#else - #define fbprintk(msg...) -#endif - -#if 1 -#define CHK_SUSPEND(drv) \ - if(atomic_read(&drv->in_suspend)) { \ - printk(">>>>>> fb is in suspend! return! \n"); \ - return -EPERM; \ - } -#else -#define CHK_SUSPEND(inf) -#endif static struct platform_device *g_fb_pdev; @@ -110,7 +95,7 @@ static int rk_fb_open(struct fb_info *info,int user) { struct rk_lcdc_device_driver * dev_drv = (struct rk_lcdc_device_driver * )info->par; int layer_id; - CHK_SUSPEND(dev_drv); + layer_id = get_fb_layer_id(&info->fix); if(dev_drv->layer_par[layer_id]->state) { @@ -145,7 +130,7 @@ static int rk_fb_close(struct fb_info *info,int user) static void fb_copy_by_ipp(struct fb_info *dst_info, struct fb_info *src_info,int offset) { struct rk29_ipp_req ipp_req; - u32 dstoffset = 0; + memset(&ipp_req, 0, sizeof(struct rk29_ipp_req)); ipp_req.src0.YrgbMst = src_info->fix.smem_start + offset; ipp_req.src0.w = src_info->var.xres; @@ -185,7 +170,7 @@ static int rk_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) u32 yoffset = var->yoffset; u32 xvir = var->xres_virtual; u8 data_format = var->nonstd&0xff; - CHK_SUSPEND(dev_drv); + layer_id = get_fb_layer_id(fix); if(layer_id < 0) { @@ -252,9 +237,7 @@ static int rk_fb_ioctl(struct fb_info *info, unsigned int cmd,unsigned long arg) struct rk_lcdc_device_driver *dev_drv = (struct rk_lcdc_device_driver * )info->par; u32 yuv_phy[2]; void __user *argp = (void __user *)arg; - fbprintk(">>>>>> %s : cmd:0x%x \n",__FUNCTION__,cmd); - CHK_SUSPEND(dev_drv); switch(cmd) { case FBIOPUT_FBPHYADD: @@ -295,7 +278,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) { @@ -310,7 +293,7 @@ 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) { 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 || ((16!=var->bits_per_pixel)&&(32!=var->bits_per_pixel)) ) @@ -408,7 +391,7 @@ static int rk_fb_set_par(struct fb_info *info) u32 yvir = var->yres_virtual; u8 data_format = var->nonstd&0xff; var->pixclock = dev_drv->pixclock; - CHK_SUSPEND(dev_drv); + #if defined(CONFIG_HDMI_RK30) #if defined(CONFIG_DUAL_DISP_IN_KERNEL) if(hdmi_get_hotplug()) @@ -630,7 +613,7 @@ void rk_direct_fb_show(struct fb_info * fbi) EXPORT_SYMBOL(rk_direct_fb_show); -void rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id) +int rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id) { struct rk_fb_inf *inf = platform_get_drvdata(g_fb_pdev); struct fb_info *info = NULL; @@ -702,6 +685,8 @@ void rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id) } #endif + return 0; + } static int rk_request_fb_buffer(struct fb_info *fbi,int fb_id) { @@ -989,7 +974,6 @@ static void rkfb_early_suspend(struct early_suspend *h) int i; for(i = 0; i < inf->num_lcdc; i++) { - atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,1); if(inf->lcdc_dev_drv[i]->screen_ctr_info->io_disable) inf->lcdc_dev_drv[i]->screen_ctr_info->io_disable(); if(inf->lcdc_dev_drv[i]->screen->standby) @@ -1012,7 +996,6 @@ static void rkfb_early_resume(struct early_suspend *h) inf->lcdc_dev_drv[i]->screen->standby(0); inf->lcdc_dev_drv[i]->resume(inf->lcdc_dev_drv[i]); - atomic_set(&inf->lcdc_dev_drv[i]->in_suspend,0); } } @@ -1029,7 +1012,6 @@ static struct suspend_info suspend_info = { static int __devinit rk_fb_probe (struct platform_device *pdev) { struct rk_fb_inf *fb_inf = NULL; - struct rk29fb_info * mach_info = NULL; int ret = 0; g_fb_pdev=pdev; /* Malloc rk_fb_inf and set it to pdev for drvdata */ diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index 982951707bed..673365dbfce6 100644 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -197,8 +197,6 @@ struct rk_lcdc_device_driver{ 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 - struct rk29fb_info *screen_ctr_info; int (*open)(struct rk_lcdc_device_driver *dev_drv,int layer_id,bool open); int (*init_lcdc)(struct rk_lcdc_device_driver *dev_drv); @@ -231,6 +229,6 @@ extern int rk_fb_register(struct rk_lcdc_device_driver *dev_drv, extern int rk_fb_unregister(struct rk_lcdc_device_driver *dev_drv); extern int get_fb_layer_id(struct fb_fix_screeninfo *fix); extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name); -extern void rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id); +extern int rk_fb_switch_screen(rk_screen *screen ,int enable ,int lcdc_id); extern int rkfb_create_sysfs(struct fb_info *fbi); #endif