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 static void __raw_bits_and(unsigned int v, unsigned int a)
33 __raw_writel((__raw_readl(a) & v), a);
36 /* dispc soft reset */
37 static void dispc_reset(void)
39 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
40 __raw_writel(__raw_readl(DISPC_AHB_SOFT_RST) | (BIT_DISPC_SOFT_RST), DISPC_AHB_SOFT_RST);
42 __raw_writel(__raw_readl(DISPC_AHB_SOFT_RST) & (~(BIT_DISPC_SOFT_RST)), DISPC_AHB_SOFT_RST);
45 static inline void dispc_set_bg_color(uint32_t bg_color)
47 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
49 dispc_write(bg_color, DISPC_BG_COLOR);
52 static inline void dispc_set_osd_ck(uint32_t ck_color)
54 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
56 dispc_write(ck_color, DISPC_OSD_CK);
59 static void dispc_dithering_enable(uint16_t enable)
61 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
64 dispc_set_bits((1<<6), DISPC_CTRL);
66 dispc_clear_bits((1<<6), DISPC_CTRL);
70 static void dispc_set_exp_mode(uint16_t exp_mode)
72 uint32_t reg_val = dispc_read(DISPC_CTRL);
74 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
76 reg_val &= ~(0x3 << 16);
77 reg_val |= (exp_mode << 16);
78 dispc_write(reg_val, DISPC_CTRL);
81 static void dispc_module_enable(void)
83 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
85 /*dispc module enable */
86 dispc_write((1<<0), DISPC_CTRL);
89 dispc_write(0x0, DISPC_INT_EN);
92 dispc_write(0x1F, DISPC_INT_CLR);
95 static inline int32_t dispc_set_disp_size(struct sprdfb_device *dev)
99 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
101 reg_val = (dev->panel->width& 0xfff) | ((dev->panel->height & 0xfff ) << 16);
102 dispc_write(reg_val, DISPC_SIZE_XY);
107 static void dispc_layer_init(struct sprdfb_device *dev)
109 uint32_t reg_val = 0;
111 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
113 dispc_clear_bits((1<<0),DISPC_IMG_CTRL);
114 dispc_clear_bits((1<<0),DISPC_OSD_CTRL);
116 /******************* OSD layer setting **********************/
121 /*disable color key */
123 /* alpha mode select - block alpha*/
132 dispc_write(reg_val, DISPC_OSD_CTRL);
134 /* OSD layer alpha value */
135 dispc_write(0xff, DISPC_OSD_ALPHA);
138 #ifdef CONFIG_FB_LOW_RES_SIMU
139 if((0 != dev->display_width) && (0 != dev->display_height)){
140 reg_val = ( dev->display_width& 0xfff) | ((dev->display_height & 0xfff ) << 16);
143 reg_val = ( dev->panel->width& 0xfff) | ((dev->panel->height & 0xfff ) << 16);
144 dispc_write(reg_val, DISPC_OSD_SIZE_XY);
146 /* OSD layer start position */
147 dispc_write(0, DISPC_OSD_DISP_XY);
149 /* OSD layer pitch */
150 #ifdef CONFIG_FB_LOW_RES_SIMU
151 if((0 != dev->display_width) && (0 != dev->display_height)){
152 reg_val = ( dev->display_width & 0xfff) ;
155 reg_val = ( dev->panel->width & 0xfff) ;
156 dispc_write(reg_val, DISPC_OSD_PITCH);
159 dispc_write(dev->smem_start, DISPC_OSD_BASE_ADDR);
161 /* OSD color_key value */
162 dispc_set_osd_ck(0x0);
164 /* DISPC workplane size */
165 dispc_set_disp_size(dev);
167 FB_PRINT("DISPC_OSD_CTRL: 0x%x\n", dispc_read(DISPC_OSD_CTRL));
168 FB_PRINT("DISPC_OSD_ALPHA: 0x%x\n", dispc_read(DISPC_OSD_ALPHA));
169 FB_PRINT("DISPC_OSD_SIZE_XY: 0x%x\n", dispc_read(DISPC_OSD_SIZE_XY));
170 FB_PRINT("DISPC_OSD_DISP_XY: 0x%x\n", dispc_read(DISPC_OSD_DISP_XY));
171 FB_PRINT("DISPC_OSD_PITCH: 0x%x\n", dispc_read(DISPC_OSD_PITCH));
172 FB_PRINT("DISPC_OSD_BASE_ADDR: 0x%x\n", dispc_read(DISPC_OSD_BASE_ADDR));
175 static void dispc_update_clock(struct sprdfb_device *dev)
177 uint32_t hpixels, vlines, need_clock, dividor;
179 struct panel_spec* panel = dev->panel;
180 struct info_mipi * mipi = panel->info.mipi;
181 struct info_rgb* rgb = panel->info.rgb;
183 FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);
186 printf("sprdfb: No panel->fps specified!\n");
190 if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
191 if(LCD_MODE_DSI == dev->panel->type ){
192 hpixels = panel->width + mipi->timing->hsync + mipi->timing->hbp + mipi->timing->hfp;
193 vlines = panel->height + mipi->timing->vsync + mipi->timing->vbp + mipi->timing->vfp;
194 }else if(LCD_MODE_RGB == dev->panel->type || dev->panel->type == LCD_MODE_LVDS){
195 hpixels = panel->width + rgb->timing->hsync + rgb->timing->hbp + rgb->timing->hfp;
196 vlines = panel->height + rgb->timing->vsync + rgb->timing->vbp + rgb->timing->vfp;
198 printf("sprdfb:[%s] unexpected panel type!(%d)\n", __FUNCTION__, dev->panel->type);
202 need_clock = hpixels * vlines * panel->fps;
203 dividor = SPRDFB_DPI_CLOCK_SRC/need_clock;
204 if(SPRDFB_DPI_CLOCK_SRC - dividor*need_clock > (need_clock/2) ) {
207 if((dividor<1) || (dividor > 0x100)){
208 printf("sprdfb:[%s]: Invliad dividor(%d)!Not update dpi clock!\n", __FUNCTION__, dividor);
212 dev->dpi_clock = SPRDFB_DPI_CLOCK_SRC / dividor;
213 dispc_dpi_clk_set(DISPC_DPI_SEL_DEFAULT, (dividor-1));
215 printf("sprdfb:[%s] need_clock = %d, dividor = %d, dpi_clock = %d\n", __FUNCTION__, need_clock, dividor, dev->dpi_clock);
222 #if defined(CONFIG_SPX15) || defined(CONFIG_SPX30G)
223 //#define GSP_IOMMU_WORKAROUND1
226 #ifdef GSP_IOMMU_WORKAROUND1
228 static void cycle_delay(uint32_t delay)
234 func:gsp_iommu_workaround
235 desc:dolphin IOMMU workaround, configure GSP-IOMMU CTL REG before dispc_emc enable,
236 including config IO base addr and enable gsp-iommu
237 warn:when dispc_emc disabled, reading ctl or entry register will hung up AHB bus .
238 only 4-writting operations are allowed to exeute, over 4 ops will also hung uo AHB bus
239 GSP module soft reset is not allowed , beacause it will clear gsp-iommu-ctrl register
241 static void gsp_iommu_workaround(void)
243 uint32_t emc_en_cfg = 0;
244 uint32_t gsp_en_cfg = 0;
245 #define REG_WRITE(reg,value) (*(volatile uint32_t*)reg = value)
246 #ifdef CONFIG_SPX30G //tshark
247 #define GSP_MMU_CTRL_BASE (0x21408000)
248 #else//defined(CONFIG_SPX15) //dolphin
249 #define GSP_MMU_CTRL_BASE (0x21404000)
252 emc_en_cfg = __raw_readl(DISPC_EMC_EN);
253 gsp_en_cfg = __raw_readl(DISPC_AHB_EN);
254 printf("ytc:gsp_iommu_workaround: emc_eb_cfg:%x; gsp_eb_cfg:%x;\n", emc_en_cfg, gsp_en_cfg);
255 REG_WRITE(DISPC_EMC_EN,emc_en_cfg & (~0x800)); // disable emc clk
256 REG_WRITE(DISPC_AHB_EN,gsp_en_cfg | 0x8); // enable gsp
257 cycle_delay(5); // delay for a while
258 REG_WRITE(GSP_MMU_CTRL_BASE,0x10000001);//set iova base as 0x10000000, and enable gsp_iommu
259 cycle_delay(5); // delay for a while
260 printf("ytc:gsp_iommu_workaround: %x, gsp_eb_cfg: %x\n", __raw_readl(DISPC_EMC_EN), __raw_readl(DISPC_AHB_EN));
261 REG_WRITE(DISPC_AHB_EN,gsp_en_cfg); // restore gsp
262 REG_WRITE(DISPC_EMC_EN,emc_en_cfg); // restore emc clk
266 static int32_t sprdfb_dispc_early_init(struct sprdfb_device *dev)
268 FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);
270 dispc_pll_clk_set(DISPC_PLL_SEL_DEFAULT, 0);
271 dispc_dbi_clk_set(DISPC_DBI_SEL_DEFAULT, 0);
272 dispc_dpi_clk_set(DISPC_DPI_SEL_DEFAULT, DISPC_DPI_DIV_DEFAULT);
274 dev->dpi_clock = SPRDFB_DPI_CLOCK_SRC /(DISPC_DPI_DIV_DEFAULT + 1);
277 __raw_bits_or(BIT_DISPC_CORE_EN, DISPC_CORE_EN); //core_clock_en
278 #ifdef GSP_IOMMU_WORKAROUND1
279 gsp_iommu_workaround();
281 __raw_bits_or(BIT_DISPC_EMC_EN, DISPC_EMC_EN); //matrix clock en
283 __raw_bits_or(BIT_DISPC_AHB_EN, DISPC_AHB_EN);//enable DISPC clock
285 FB_PRINT("sprdfb:DISPC_CORE_EN:%x \n",__raw_readl(DISPC_CORE_EN));
286 FB_PRINT("sprdfb:DISPC_EMC_EN:%x \n",__raw_readl(DISPC_EMC_EN));
287 FB_PRINT("sprdfb:DISPC_AHB_EN:%x \n",__raw_readl(DISPC_AHB_EN));
293 dispc_module_enable();
300 static int32_t sprdfb_dispc_init(struct sprdfb_device *dev)
302 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
305 // dispc_set_bg_color(0xFFFFFFFF);
306 dispc_set_bg_color(0x0);
308 dispc_dithering_enable(1);
309 /*use MSBs as img exp mode*/
310 dispc_set_exp_mode(0x0);
312 dispc_layer_init(dev);
314 // dispc_update_clock(dev);
316 if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
318 /*set dpi register update only with SW*/
319 dispc_set_bits((1<<4), DISPC_DPI_CTRL);
321 /*set dpi register update with SW & VSYNC*/
322 dispc_clear_bits((1<<4), DISPC_DPI_CTRL);
324 /*enable dispc update done INT*/
325 // dispc_write((1<<4), DISPC_INT_EN);
327 /* enable dispc DONE INT*/
328 // dispc_write((1<<0), DISPC_INT_EN);
330 #if defined CONFIG_SC8830 || (defined CONFIG_SC9630)
333 for(i=0x20800000;i<0x208000c0;i+=16){
334 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));
336 FB_PRINT("**************************************\n");
342 static int32_t sprdfb_dispc_uninit(struct sprdfb_device *dev)
344 FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
346 __raw_bits_and(~(BIT_DISPC_AHB_EN), DISPC_AHB_EN);
351 static int32_t sprdfb_dispc_refresh (struct sprdfb_device *dev)
355 printf("sprdfb:[%s]\n",__FUNCTION__);
357 if(SPRDFB_PANEL_IF_DPI != dev->panel_if_type){
358 sprdfb_panel_invalidate(dev->panel);
361 sprdfb_panel_before_refresh(dev);
363 if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
364 /*dpi register update*/
365 dispc_set_bits((1<<5), DISPC_DPI_CTRL);
368 /*dpi register update with SW and VSync*/
369 dispc_clear_bits((1<<4), DISPC_DPI_CTRL);
371 dispc_set_bits((1 << 4), DISPC_CTRL);
375 if(!(dispc_read(DISPC_INT_RAW) & (0x10))){
382 printf("sprdfb:[%s] wait dispc update int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
384 FB_PRINT("sprdfb:[%s] got dispc update int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
386 dispc_set_bits((1<<5), DISPC_INT_CLR);
390 dispc_set_bits((1 << 4), DISPC_CTRL);
392 if(0x1 != (dispc_read(DISPC_INT_RAW) & (1<<0))){
399 printf("sprdfb:[%s] wait dispc done int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
401 FB_PRINT("sprdfb:[%s] got dispc done int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
403 dispc_set_bits((1<<0), DISPC_INT_CLR);
406 sprdfb_panel_after_refresh(dev);
411 struct display_ctrl sprdfb_dispc_ctrl = {
413 .early_init = sprdfb_dispc_early_init,
414 .init = sprdfb_dispc_init,
415 .uninit = sprdfb_dispc_uninit,
416 .refresh = sprdfb_dispc_refresh,
417 .update_clk = dispc_update_clock,