1 /******************************************************************************
2 ** File Name: sprdfb_dispc.c *
5 ** Copyright: 2005 Spreatrum, Incoporated. All Rights Reserved. *
7 ******************************************************************************/
8 /******************************************************************************
10 **---------------------------------------------------------------------------*
11 ** DATE NAME DESCRIPTION *
13 ******************************************************************************/
18 #include "sprdfb_chip_common.h"
20 #define SPRDFB_DPI_CLOCK_SRC (384000000)
22 static uint16_t is_first_frame = 1;
24 extern void sprdfb_panel_before_refresh(struct sprdfb_device *dev);
25 extern void sprdfb_panel_after_refresh(struct sprdfb_device *dev);
26 extern void sprdfb_panel_invalidate(struct panel_spec *self);
27 extern void sprdfb_panel_invalidate_rect(struct panel_spec *self,
28 uint16_t left, uint16_t top,
29 uint16_t right, uint16_t bottom);
31 /* dispc soft reset */
32 static void dispc_reset(void)
34 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
35 __raw_writel(__raw_readl(DISPC_AHB_SOFT_RST) | (BIT_DISPC_SOFT_RST), DISPC_AHB_SOFT_RST);
37 __raw_writel(__raw_readl(DISPC_AHB_SOFT_RST) & (~(BIT_DISPC_SOFT_RST)), DISPC_AHB_SOFT_RST);
40 static inline void dispc_set_bg_color(uint32_t bg_color)
42 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
44 dispc_write(bg_color, DISPC_BG_COLOR);
47 static inline void dispc_set_osd_ck(uint32_t ck_color)
49 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
51 dispc_write(ck_color, DISPC_OSD_CK);
54 static void dispc_dithering_enable(uint16_t enable)
56 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
59 dispc_set_bits((1<<6), DISPC_CTRL);
61 dispc_clear_bits((1<<6), DISPC_CTRL);
65 static void dispc_set_exp_mode(uint16_t exp_mode)
67 uint32_t reg_val = dispc_read(DISPC_CTRL);
69 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
71 reg_val &= ~(0x3 << 16);
72 reg_val |= (exp_mode << 16);
73 dispc_write(reg_val, DISPC_CTRL);
76 static void dispc_module_enable(void)
78 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
80 /*dispc module enable */
81 dispc_write((1<<0), DISPC_CTRL);
84 dispc_write(0x0, DISPC_INT_EN);
87 dispc_write(0x1F, DISPC_INT_CLR);
90 static inline int32_t dispc_set_disp_size(struct sprdfb_device *dev)
94 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
96 reg_val = (dev->panel->width& 0xfff) | ((dev->panel->height & 0xfff ) << 16);
97 dispc_write(reg_val, DISPC_SIZE_XY);
102 static void dispc_layer_init(struct sprdfb_device *dev)
104 uint32_t reg_val = 0;
106 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
108 dispc_clear_bits((1<<0),DISPC_IMG_CTRL);
109 dispc_clear_bits((1<<0),DISPC_OSD_CTRL);
111 /******************* OSD layer setting **********************/
116 /*disable color key */
118 /* alpha mode select - block alpha*/
127 dispc_write(reg_val, DISPC_OSD_CTRL);
129 /* OSD layer alpha value */
130 dispc_write(0xff, DISPC_OSD_ALPHA);
133 #ifdef CONFIG_FB_LOW_RES_SIMU
134 if((0 != dev->display_width) && (0 != dev->display_height)){
135 reg_val = ( dev->display_width& 0xfff) | ((dev->display_height & 0xfff ) << 16);
138 reg_val = ( dev->panel->width& 0xfff) | ((dev->panel->height & 0xfff ) << 16);
139 dispc_write(reg_val, DISPC_OSD_SIZE_XY);
141 /* OSD layer start position */
142 dispc_write(0, DISPC_OSD_DISP_XY);
144 /* OSD layer pitch */
145 #ifdef CONFIG_FB_LOW_RES_SIMU
146 if((0 != dev->display_width) && (0 != dev->display_height)){
147 reg_val = ( dev->display_width & 0xfff) ;
150 reg_val = ( dev->panel->width & 0xfff) ;
151 dispc_write(reg_val, DISPC_OSD_PITCH);
154 dispc_write(dev->smem_start, DISPC_OSD_BASE_ADDR);
156 /* OSD color_key value */
157 dispc_set_osd_ck(0x0);
159 /* DISPC workplane size */
160 dispc_set_disp_size(dev);
162 FB_PRINT("DISPC_OSD_CTRL: 0x%x\n", dispc_read(DISPC_OSD_CTRL));
163 FB_PRINT("DISPC_OSD_ALPHA: 0x%x\n", dispc_read(DISPC_OSD_ALPHA));
164 FB_PRINT("DISPC_OSD_SIZE_XY: 0x%x\n", dispc_read(DISPC_OSD_SIZE_XY));
165 FB_PRINT("DISPC_OSD_DISP_XY: 0x%x\n", dispc_read(DISPC_OSD_DISP_XY));
166 FB_PRINT("DISPC_OSD_PITCH: 0x%x\n", dispc_read(DISPC_OSD_PITCH));
167 FB_PRINT("DISPC_OSD_BASE_ADDR: 0x%x\n", dispc_read(DISPC_OSD_BASE_ADDR));
170 static void dispc_update_clock(struct sprdfb_device *dev)
172 uint32_t hpixels, vlines, need_clock, dividor;
174 struct panel_spec* panel = dev->panel;
175 struct info_mipi * mipi = panel->info.mipi;
176 struct info_rgb* rgb = panel->info.rgb;
178 FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);
181 printf("sprdfb: No panel->fps specified!\n");
185 if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
186 if(LCD_MODE_DSI == dev->panel->type ){
187 hpixels = panel->width + mipi->timing->hsync + mipi->timing->hbp + mipi->timing->hfp;
188 vlines = panel->height + mipi->timing->vsync + mipi->timing->vbp + mipi->timing->vfp;
189 }else if(LCD_MODE_RGB == dev->panel->type || dev->panel->type == LCD_MODE_LVDS){
190 hpixels = panel->width + rgb->timing->hsync + rgb->timing->hbp + rgb->timing->hfp;
191 vlines = panel->height + rgb->timing->vsync + rgb->timing->vbp + rgb->timing->vfp;
193 printf("sprdfb:[%s] unexpected panel type!(%d)\n", __FUNCTION__, dev->panel->type);
197 need_clock = hpixels * vlines * panel->fps;
198 dividor = SPRDFB_DPI_CLOCK_SRC/need_clock;
199 if(SPRDFB_DPI_CLOCK_SRC - dividor*need_clock > (need_clock/2) ) {
202 if((dividor<1) || (dividor > 0x100)){
203 printf("sprdfb:[%s]: Invliad dividor(%d)!Not update dpi clock!\n", __FUNCTION__, dividor);
207 dev->dpi_clock = SPRDFB_DPI_CLOCK_SRC / dividor;
208 dispc_dpi_clk_set(DISPC_DPI_SEL_DEFAULT, (dividor-1));
210 printf("sprdfb:[%s] need_clock = %d, dividor = %d, dpi_clock = %d\n", __FUNCTION__, need_clock, dividor, dev->dpi_clock);
217 #if defined(CONFIG_SPX15) || defined(CONFIG_SPX30G)
218 //#define GSP_IOMMU_WORKAROUND1
221 #ifdef GSP_IOMMU_WORKAROUND1
223 static void cycle_delay(uint32_t delay)
229 func:gsp_iommu_workaround
230 desc:dolphin IOMMU workaround, configure GSP-IOMMU CTL REG before dispc_emc enable,
231 including config IO base addr and enable gsp-iommu
232 warn:when dispc_emc disabled, reading ctl or entry register will hung up AHB bus .
233 only 4-writting operations are allowed to exeute, over 4 ops will also hung uo AHB bus
234 GSP module soft reset is not allowed , beacause it will clear gsp-iommu-ctrl register
236 static void gsp_iommu_workaround(void)
238 uint32_t emc_en_cfg = 0;
239 uint32_t gsp_en_cfg = 0;
240 #define REG_WRITE(reg,value) (*(volatile uint32_t*)reg = value)
241 #ifdef CONFIG_SPX30G //tshark
242 #define GSP_MMU_CTRL_BASE (0x21408000)
243 #else//defined(CONFIG_SPX15) //dolphin
244 #define GSP_MMU_CTRL_BASE (0x21404000)
247 emc_en_cfg = __raw_readl(DISPC_EMC_EN);
248 gsp_en_cfg = __raw_readl(DISPC_AHB_EN);
249 printf("ytc:gsp_iommu_workaround: emc_eb_cfg:%x; gsp_eb_cfg:%x;\n", emc_en_cfg, gsp_en_cfg);
250 REG_WRITE(DISPC_EMC_EN,emc_en_cfg & (~0x800)); // disable emc clk
251 REG_WRITE(DISPC_AHB_EN,gsp_en_cfg | 0x8); // enable gsp
252 cycle_delay(5); // delay for a while
253 REG_WRITE(GSP_MMU_CTRL_BASE,0x10000001);//set iova base as 0x10000000, and enable gsp_iommu
254 cycle_delay(5); // delay for a while
255 printf("ytc:gsp_iommu_workaround: %x, gsp_eb_cfg: %x\n", __raw_readl(DISPC_EMC_EN), __raw_readl(DISPC_AHB_EN));
256 REG_WRITE(DISPC_AHB_EN,gsp_en_cfg); // restore gsp
257 REG_WRITE(DISPC_EMC_EN,emc_en_cfg); // restore emc clk
261 static int32_t sprdfb_dispc_early_init(struct sprdfb_device *dev)
263 FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);
265 dispc_pll_clk_set(DISPC_PLL_SEL_DEFAULT, 0);
266 dispc_dbi_clk_set(DISPC_DBI_SEL_DEFAULT, 0);
267 dispc_dpi_clk_set(DISPC_DPI_SEL_DEFAULT, DISPC_DPI_DIV_DEFAULT);
269 dev->dpi_clock = SPRDFB_DPI_CLOCK_SRC /(DISPC_DPI_DIV_DEFAULT + 1);
272 __raw_bits_or(BIT_DISPC_CORE_EN, DISPC_CORE_EN); //core_clock_en
273 #ifdef GSP_IOMMU_WORKAROUND1
274 gsp_iommu_workaround();
276 __raw_bits_or(BIT_DISPC_EMC_EN, DISPC_EMC_EN); //matrix clock en
278 __raw_bits_or(BIT_DISPC_AHB_EN, DISPC_AHB_EN);//enable DISPC clock
280 FB_PRINT("sprdfb:DISPC_CORE_EN:%x \n",__raw_readl(DISPC_CORE_EN));
281 FB_PRINT("sprdfb:DISPC_EMC_EN:%x \n",__raw_readl(DISPC_EMC_EN));
282 FB_PRINT("sprdfb:DISPC_AHB_EN:%x \n",__raw_readl(DISPC_AHB_EN));
288 dispc_module_enable();
295 static int32_t sprdfb_dispc_init(struct sprdfb_device *dev)
297 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
300 // dispc_set_bg_color(0xFFFFFFFF);
301 dispc_set_bg_color(0x0);
303 dispc_dithering_enable(1);
304 /*use MSBs as img exp mode*/
305 dispc_set_exp_mode(0x0);
307 dispc_layer_init(dev);
309 // dispc_update_clock(dev);
311 if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
313 /*set dpi register update only with SW*/
314 dispc_set_bits((1<<4), DISPC_DPI_CTRL);
316 /*set dpi register update with SW & VSYNC*/
317 dispc_clear_bits((1<<4), DISPC_DPI_CTRL);
319 /*enable dispc update done INT*/
320 // dispc_write((1<<4), DISPC_INT_EN);
322 /* enable dispc DONE INT*/
323 // dispc_write((1<<0), DISPC_INT_EN);
325 #if defined CONFIG_SC8830 || (defined CONFIG_SC9630)
328 for(i=0x20800000;i<0x208000c0;i+=16){
329 FB_PRINT("sprdfb: %x: 0x%x, 0x%x, 0x%x, 0x%x\n", i, __raw_readl(i), __raw_readl(i+4), __raw_readl(i+8), __raw_readl(i+12));
331 FB_PRINT("**************************************\n");
337 static int32_t sprdfb_dispc_uninit(struct sprdfb_device *dev)
339 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
341 __raw_bits_and(~(BIT_DISPC_AHB_EN), DISPC_AHB_EN);
346 static int32_t sprdfb_dispc_refresh (struct sprdfb_device *dev)
350 printf("sprdfb:[%s]\n",__FUNCTION__);
352 if(SPRDFB_PANEL_IF_DPI != dev->panel_if_type){
353 sprdfb_panel_invalidate(dev->panel);
356 sprdfb_panel_before_refresh(dev);
358 if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
359 /*dpi register update*/
360 dispc_set_bits((1<<5), DISPC_DPI_CTRL);
363 /*dpi register update with SW and VSync*/
364 dispc_clear_bits((1<<4), DISPC_DPI_CTRL);
366 dispc_set_bits((1 << 4), DISPC_CTRL);
370 if(!(dispc_read(DISPC_INT_RAW) & (0x10))){
377 printf("sprdfb:[%s] wait dispc update int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
379 FB_PRINT("sprdfb:[%s] got dispc update int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
381 dispc_set_bits((1<<5), DISPC_INT_CLR);
385 dispc_set_bits((1 << 4), DISPC_CTRL);
387 if(0x1 != (dispc_read(DISPC_INT_RAW) & (1<<0))){
394 printf("sprdfb:[%s] wait dispc done int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
396 FB_PRINT("sprdfb:[%s] got dispc done int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
398 dispc_set_bits((1<<0), DISPC_INT_CLR);
401 sprdfb_panel_after_refresh(dev);
406 struct display_ctrl sprdfb_dispc_ctrl = {
408 .early_init = sprdfb_dispc_early_init,
409 .init = sprdfb_dispc_init,
410 .uninit = sprdfb_dispc_uninit,
411 .refresh = sprdfb_dispc_refresh,
412 .update_clk = dispc_update_clock,