video: sprd: remove build warnings
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / video / sprdfb / sprdfb_dispc.c
1 /******************************************************************************
2  ** File Name:    sprdfb_dispc.c                                            *
3  ** Author:                                                           *
4  ** DATE:                                                           *
5  ** Copyright:    2005 Spreatrum, Incoporated. All Rights Reserved.           *
6  ** Description:                                                            *
7  ******************************************************************************/
8 /******************************************************************************
9  **                   Edit    History                                         *
10  **---------------------------------------------------------------------------*
11  ** DATE          NAME            DESCRIPTION                                 *
12  **
13  ******************************************************************************/
14
15 #include <common.h>
16
17 #include "sprdfb.h"
18 #include "sprdfb_chip_common.h"
19
20 #define SPRDFB_DPI_CLOCK_SRC (384000000)
21
22 static uint16_t         is_first_frame = 1;
23
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);
30
31 /* dispc soft reset */
32 static void dispc_reset(void)
33 {
34         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
35         __raw_writel(__raw_readl(DISPC_AHB_SOFT_RST) | (BIT_DISPC_SOFT_RST), DISPC_AHB_SOFT_RST);
36         udelay(10);
37         __raw_writel(__raw_readl(DISPC_AHB_SOFT_RST) & (~(BIT_DISPC_SOFT_RST)), DISPC_AHB_SOFT_RST);
38 }
39
40 static inline void dispc_set_bg_color(uint32_t bg_color)
41 {
42         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
43
44         dispc_write(bg_color, DISPC_BG_COLOR);
45 }
46
47 static inline void dispc_set_osd_ck(uint32_t ck_color)
48 {
49         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
50
51         dispc_write(ck_color, DISPC_OSD_CK);
52 }
53
54 static void dispc_dithering_enable(uint16_t enable)
55 {
56         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
57
58         if(enable){
59                 dispc_set_bits((1<<6), DISPC_CTRL);
60         }else{
61                 dispc_clear_bits((1<<6), DISPC_CTRL);
62         }
63 }
64
65 static void dispc_set_exp_mode(uint16_t exp_mode)
66 {
67         uint32_t reg_val = dispc_read(DISPC_CTRL);
68
69         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
70
71         reg_val &= ~(0x3 << 16);
72         reg_val |= (exp_mode << 16);
73         dispc_write(reg_val, DISPC_CTRL);
74 }
75
76 static void dispc_module_enable(void)
77 {
78         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
79
80         /*dispc module enable */
81         dispc_write((1<<0), DISPC_CTRL);
82
83         /*disable dispc INT*/
84         dispc_write(0x0, DISPC_INT_EN);
85
86         /* clear dispc INT */
87         dispc_write(0x1F, DISPC_INT_CLR);
88 }
89
90 static inline int32_t  dispc_set_disp_size(struct sprdfb_device *dev)
91 {
92         uint32_t reg_val;
93
94         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
95
96         reg_val = (dev->panel->width& 0xfff) | ((dev->panel->height & 0xfff ) << 16);
97         dispc_write(reg_val, DISPC_SIZE_XY);
98
99         return 0;
100 }
101
102 static void dispc_layer_init(struct sprdfb_device *dev)
103 {
104         uint32_t reg_val = 0;
105
106         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
107
108         dispc_clear_bits((1<<0),DISPC_IMG_CTRL);
109         dispc_clear_bits((1<<0),DISPC_OSD_CTRL);
110
111         /******************* OSD layer setting **********************/
112
113         /*enable OSD layer*/
114         reg_val |= (1 << 0);
115
116         /*disable  color key */
117
118         /* alpha mode select  - block alpha*/
119         reg_val |= (1 << 2);
120
121         /* data format */
122         /* RGB565 */
123         reg_val |= (5 << 4);
124         /* B2B3B0B1 */
125         reg_val |= (2 << 8);
126
127         dispc_write(reg_val, DISPC_OSD_CTRL);
128
129         /* OSD layer alpha value */
130         dispc_write(0xff, DISPC_OSD_ALPHA);
131
132         /* OSD layer size */
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);
136         }else
137  #endif 
138         reg_val = ( dev->panel->width& 0xfff) | ((dev->panel->height & 0xfff ) << 16);
139         dispc_write(reg_val, DISPC_OSD_SIZE_XY);
140
141         /* OSD layer start position */
142         dispc_write(0, DISPC_OSD_DISP_XY);
143
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) ;
148         }else
149  #endif 
150         reg_val = ( dev->panel->width & 0xfff) ;        
151         dispc_write(reg_val, DISPC_OSD_PITCH);
152
153         /*OSD base address*/
154         dispc_write(dev->smem_start, DISPC_OSD_BASE_ADDR);
155
156         /* OSD color_key value */
157         dispc_set_osd_ck(0x0);
158
159         /* DISPC workplane size */
160         dispc_set_disp_size(dev);
161
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));
168 }
169
170 static void dispc_update_clock(struct sprdfb_device *dev)
171 {
172         uint32_t hpixels, vlines, need_clock, dividor;
173
174         struct panel_spec* panel = dev->panel;
175         struct info_mipi * mipi = panel->info.mipi;
176         struct info_rgb* rgb = panel->info.rgb;
177
178         FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);
179
180         if(0 == panel->fps){
181                 printf("sprdfb: No panel->fps specified!\n");
182                 return;
183         }
184
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;
192                 }else{
193                         printf("sprdfb:[%s] unexpected panel type!(%d)\n", __FUNCTION__, dev->panel->type);
194                         return;
195                 }
196
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) ) {
200                         dividor += 1;
201                 }
202                 if((dividor<1) || (dividor > 0x100)){
203                         printf("sprdfb:[%s]: Invliad dividor(%d)!Not update dpi clock!\n", __FUNCTION__, dividor);
204                         return;
205                 }
206
207                 dev->dpi_clock = SPRDFB_DPI_CLOCK_SRC / dividor;
208                 dispc_dpi_clk_set(DISPC_DPI_SEL_DEFAULT, (dividor-1));
209
210                 printf("sprdfb:[%s] need_clock = %d, dividor = %d, dpi_clock = %d\n", __FUNCTION__, need_clock, dividor, dev->dpi_clock);
211         }
212         dispc_print_clk();
213
214 }
215
216
217 #if defined(CONFIG_SPX15) || defined(CONFIG_SPX30G)
218 //#define GSP_IOMMU_WORKAROUND1
219 #endif
220
221 #ifdef GSP_IOMMU_WORKAROUND1
222
223 static void cycle_delay(uint32_t delay)
224 {
225         while(delay--);
226 }
227
228 /*
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
235 */
236 static void gsp_iommu_workaround(void)
237 {
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)
245 #endif
246
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
258 }
259
260 #endif
261 static int32_t sprdfb_dispc_early_init(struct sprdfb_device *dev)
262 {
263         FB_PRINT("sprdfb:[%s]\n", __FUNCTION__);
264
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);
268         
269         dev->dpi_clock = SPRDFB_DPI_CLOCK_SRC /(DISPC_DPI_DIV_DEFAULT + 1);
270
271
272         __raw_bits_or(BIT_DISPC_CORE_EN, DISPC_CORE_EN);  //core_clock_en
273 #ifdef GSP_IOMMU_WORKAROUND1
274         gsp_iommu_workaround();
275 #endif
276         __raw_bits_or(BIT_DISPC_EMC_EN, DISPC_EMC_EN);  //matrix clock en
277
278         __raw_bits_or(BIT_DISPC_AHB_EN, DISPC_AHB_EN);//enable DISPC clock
279
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));
283
284
285
286
287         dispc_reset();
288         dispc_module_enable();
289         is_first_frame = 1;
290
291         return 0;
292 }
293
294
295 static int32_t sprdfb_dispc_init(struct sprdfb_device *dev)
296 {
297         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
298
299         /*set bg color*/
300 //      dispc_set_bg_color(0xFFFFFFFF);
301         dispc_set_bg_color(0x0);
302         /*enable dithering*/
303         dispc_dithering_enable(1);
304         /*use MSBs as img exp mode*/
305         dispc_set_exp_mode(0x0);
306
307         dispc_layer_init(dev);
308
309 //      dispc_update_clock(dev);
310
311         if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
312                 if(is_first_frame){
313                         /*set dpi register update only with SW*/
314                         dispc_set_bits((1<<4), DISPC_DPI_CTRL);
315                 }else{
316                         /*set dpi register update with SW & VSYNC*/
317                         dispc_clear_bits((1<<4), DISPC_DPI_CTRL);
318                 }
319                 /*enable dispc update done INT*/
320 //              dispc_write((1<<4), DISPC_INT_EN);
321         }else{
322                 /* enable dispc DONE  INT*/
323 //              dispc_write((1<<0), DISPC_INT_EN);
324         }
325 #if defined CONFIG_SC8830 || (defined CONFIG_SC9630)
326                 {/*for debug*/
327                         int32_t i;
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));
330                         }
331                         FB_PRINT("**************************************\n");
332                 }
333 #endif
334         return 0;
335 }
336
337 static int32_t sprdfb_dispc_uninit(struct sprdfb_device *dev)
338 {
339         FB_PRINT("sprdfb:[%s]\n",__FUNCTION__);
340
341         __raw_bits_and(~(BIT_DISPC_AHB_EN), DISPC_AHB_EN);
342
343         return 0;
344 }
345
346 static int32_t sprdfb_dispc_refresh (struct sprdfb_device *dev)
347 {
348         uint32_t i;
349
350         printf("sprdfb:[%s]\n",__FUNCTION__);
351
352         if(SPRDFB_PANEL_IF_DPI != dev->panel_if_type){
353                 sprdfb_panel_invalidate(dev->panel);
354         }
355
356         sprdfb_panel_before_refresh(dev);
357
358         if(SPRDFB_PANEL_IF_DPI == dev->panel_if_type){
359                 /*dpi register update*/
360                 dispc_set_bits((1<<5), DISPC_DPI_CTRL);
361                 if(is_first_frame){
362                         udelay(30);
363                         /*dpi register update with SW and VSync*/
364                         dispc_clear_bits((1<<4), DISPC_DPI_CTRL);
365                         /* start refresh */
366                         dispc_set_bits((1 << 4), DISPC_CTRL);
367                         is_first_frame = 0;
368                 }else{
369                         for(i=0;i<1000;i++){
370                                 if(!(dispc_read(DISPC_INT_RAW) & (0x10))){
371                                         udelay(100);
372                                 }else{
373                                         break;
374                                 }
375                         }
376                         if(i >= 1000){
377                                 printf("sprdfb:[%s] wait dispc update  int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
378                         }else{
379                                 FB_PRINT("sprdfb:[%s] got dispc update int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
380                         }
381                         dispc_set_bits((1<<5), DISPC_INT_CLR);
382                    }
383         }else{
384                 /* start refresh */
385                 dispc_set_bits((1 << 4), DISPC_CTRL);
386                 for(i=0;i<500;i++){
387                         if(0x1 != (dispc_read(DISPC_INT_RAW) & (1<<0))){
388                                 udelay(1000);
389                         }else{
390                                 break;
391                         }
392                 }
393                 if(i >= 1000){
394                         printf("sprdfb:[%s] wait dispc done int time out!! (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
395                 }else{
396                         FB_PRINT("sprdfb:[%s] got dispc done int (0x%x)\n", __FUNCTION__, dispc_read(DISPC_INT_RAW));
397                 }
398                 dispc_set_bits((1<<0), DISPC_INT_CLR);
399         }
400
401         sprdfb_panel_after_refresh(dev);
402
403         return 0;
404 }
405
406 struct display_ctrl sprdfb_dispc_ctrl = {
407         .name           = "dispc",
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,
413 };
414