tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / video / sc8825fb / sprdfb_panel.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <common.h>
15 #include <lcd.h>
16
17 #include <asm/arch/tiger_lcd.h>
18 #include <asm/arch/dispc_reg.h>
19
20 #include "sprdfb.h"
21
22
23 static ushort colormap[256];
24
25
26 #ifdef CONFIG_SC8810_OPENPHONE
27
28 extern struct panel_spec lcd_panel_hx8357;
29 static struct panel_cfg lcd_panel[] = {
30         [0]={
31                 .lcd_id = 0x57,
32                 .panel = &lcd_panel_hx8357,
33                 },
34 };
35 #elif defined CONFIG_SC8825EA_ONTIM
36 extern struct panel_spec lcd_otm8018b_mipi_spec;
37 static struct panel_cfg lcd_panel[] = {
38         [0]={
39                 .lcd_id = 0x18,
40                 .panel = &lcd_otm8018b_mipi_spec ,
41         },
42  };
43
44 #elif defined CONFIG_SC8825EA
45 extern struct panel_spec lcd_nt35516_mipi_spec;
46 extern struct panel_spec lcd_otm8018b_mipi_spec;
47
48 static struct panel_cfg lcd_panel[] = {
49         [0]={
50                 .lcd_id = 0x18,
51                 .panel = &lcd_otm8018b_mipi_spec ,
52         },
53         [1]={
54                 .lcd_id = 0x16,
55                 .panel = &lcd_nt35516_mipi_spec ,
56         },
57  };
58
59 #elif defined CONFIG_SC8825EB
60 #if 1                           //add for debug
61 extern struct panel_spec lcd_nt35516_mcu_spec;
62 static struct panel_cfg lcd_panel[] = {
63     [0]={
64         .lcd_id = 0x16,
65         .panel = &lcd_nt35516_mcu_spec ,
66         },
67 };
68 #else
69 extern struct panel_spec lcd_panel_hx8362_rgb_spi_spec;
70 static struct panel_cfg lcd_panel[] = {
71     [0]={
72         .lcd_id = 0x62,
73         .panel = &lcd_panel_hx8362_rgb_spi_spec ,
74         },
75 };
76 #endif
77
78 #elif defined CONFIG_LCD_788
79 extern struct panel_spec lcd_panel_hx8357;
80 static struct panel_cfg lcd_panel[] = {
81     [0]={
82         .lcd_id = 0x57,
83         .panel = &lcd_panel_hx8357,
84         },
85 };
86
87 #elif defined CONFIG_GARDA
88 extern struct panel_spec lcd_nt35510_mipi_spec;
89 static struct panel_cfg lcd_panel[] = {
90         [0]={
91                 .lcd_id = 0x10,
92                 .panel = &lcd_nt35510_mipi_spec ,
93         },
94  };
95
96
97 #elif defined(CONFIG_SP6825GA) || defined(CONFIG_SP6825GB)
98 /*
99 extern struct panel_spec lcd_nt35516_mcu_spec;
100 static struct panel_cfg lcd_panel[] = {
101     [0]={
102         .lcd_id = 0x16,
103         .panel = &lcd_nt35516_mcu_spec ,
104         },
105 };
106 */
107 extern struct panel_spec lcd_panel_hx8363_rgb_spi_spec;
108 static struct panel_cfg lcd_panel[] = {
109         [0]={
110                 .lcd_id = 0x84,
111                 .panel = &lcd_panel_hx8363_rgb_spi_spec ,
112                 },
113 };
114
115 #elif defined CONFIG_SP8825GA_OPENPHONE
116 extern struct panel_spec lcd_nt35516_mipi_spec;
117 static struct panel_cfg lcd_panel[] = {
118     [0]={
119         .lcd_id = 0x16,
120         .panel = &lcd_nt35516_mipi_spec ,
121         },
122 };
123
124 #elif defined CONFIG_MACH_SP7720G2
125 extern struct panel_spec lcd_hx8363_mcu_spec;
126 static struct panel_cfg lcd_panel[] = {
127     [0]={
128         .lcd_id = 0x18,
129         .panel = &lcd_hx8363_mcu_spec ,
130         },
131 };
132
133 #else
134 #ifdef CONFIG_LCD_QVGA
135 /*
136 extern struct panel_spec lcd_panel_ili9341s;
137 static struct panel_cfg lcd_panel[] = {
138     [0]={
139         .lcd_id = 0x61,
140         .panel = &lcd_panel_ili9341s,
141         },
142 };
143 */
144 extern struct panel_spec lcd_s6d0139_spec;
145 static struct panel_cfg lcd_panel[] = {
146     [0]={
147         .lcd_id = 0x139,
148         .panel = &lcd_s6d0139_spec ,
149         },
150 };
151 #else
152 extern struct panel_spec lcd_panel_hx8369;
153 static struct panel_cfg lcd_panel[] = {
154         [0]={
155                 .lcd_id = 0x69,
156                 .panel = &lcd_panel_hx8369,
157                 },
158 };
159 #endif
160 #endif
161
162 #ifdef CONFIG_LCD_FWVGA
163 vidinfo_t panel_info = {
164         .vl_col = 480,
165         .vl_bpix = 4,
166         .vl_row = 854,
167         .cmap = colormap,
168 };
169 #endif
170
171
172 #ifdef CONFIG_LCD_WVGA
173 vidinfo_t panel_info = {
174         .vl_col = 480,
175         .vl_bpix = 4,
176         .vl_row = 800,
177         .cmap = colormap,
178 };
179 #endif
180
181 #ifdef CONFIG_LCD_HVGA
182 vidinfo_t panel_info = {
183         .vl_col = 320,
184         .vl_bpix = 4,
185         .vl_row = 480,
186         .cmap = colormap,
187 };
188 #endif
189
190 #ifdef CONFIG_LCD_QVGA
191 vidinfo_t panel_info = {
192         .vl_col = 240,
193         .vl_bpix = 4,
194         .vl_row = 320,
195         .cmap = colormap,
196 };
197 #endif
198
199 #ifdef CONFIG_LCD_QHD
200 vidinfo_t panel_info = {
201         .vl_col = 540,
202         .vl_bpix = 4,
203         .vl_row = 960,
204         .cmap = colormap,
205 };
206 #endif
207
208 extern struct panel_if_ctrl sprdfb_mcu_ctrl;
209 extern struct panel_if_ctrl sprdfb_rgb_ctrl;
210 extern struct panel_if_ctrl sprdfb_mipi_ctrl;
211
212 void sprdfb_panel_remove(struct sprdfb_device *dev);
213
214
215 static int32_t panel_reset_dispc(struct panel_spec *self)
216 {
217         dispc_write(1, DISPC_RSTN);
218         mdelay(20);
219         dispc_write(0, DISPC_RSTN);
220         mdelay(20);
221         dispc_write(1, DISPC_RSTN);
222         /* wait 10ms util the lcd is stable */
223         mdelay(120);
224         return 0;
225 }
226
227
228 static void panel_reset(struct panel_spec *panel)
229 {
230         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
231
232         /* panel reset */
233         panel_reset_dispc(panel);
234 }
235
236 static int panel_mount(struct sprdfb_device *dev, struct panel_spec *panel)
237 {
238         uint16_t rval = 1;
239
240         FB_PRINT("sprdfb: [%s], type = %d\n",__FUNCTION__, panel->type);
241
242         switch(panel->type){
243         case SPRDFB_PANEL_TYPE_MCU:
244                 dev->if_ctrl = &sprdfb_mcu_ctrl;
245                 break;
246         case SPRDFB_PANEL_TYPE_RGB:
247                 dev->if_ctrl = &sprdfb_rgb_ctrl;
248                 break;
249 #ifdef CONFIG_SC8825
250         case SPRDFB_PANEL_TYPE_MIPI:
251                 dev->if_ctrl = &sprdfb_mipi_ctrl;
252                 break;
253 #endif
254         default:
255                 FB_PRINT("sprdfb: [%s]: erro panel type.(%d)",__FUNCTION__, panel->type);
256                 dev->if_ctrl = NULL;
257                 rval = 0 ;
258                 break;
259         };
260
261         if(NULL == dev->if_ctrl){
262                 return -1;
263         }
264
265         if(dev->if_ctrl->panel_if_check){
266                 rval = dev->if_ctrl->panel_if_check(panel);
267         }
268
269         if(0 == rval){
270                 FB_PRINT("sprdfb: [%s] check panel fail!\n", __FUNCTION__);
271                 dev->if_ctrl = NULL;
272                 return -1;
273         }
274
275         dev->panel = panel;
276
277         if(NULL == dev->panel->ops->panel_reset){
278                 dev->panel->ops->panel_reset = panel_reset_dispc;
279         }
280
281         dev->if_ctrl->panel_if_mount(dev);
282
283         return 0;
284 }
285
286
287 int panel_init(struct sprdfb_device *dev)
288 {
289         if((NULL == dev) || (NULL == dev->panel)){
290                 FB_PRINT("sprdfb: [%s]: Invalid param\n", __FUNCTION__);
291                 return -1;
292         }
293
294         FB_PRINT("sprdfb: [%s], type = %d\n",__FUNCTION__, dev->panel->type);
295
296         if(NULL != dev->if_ctrl->panel_if_init){
297                 dev->if_ctrl->panel_if_init(dev);
298         }
299         return 0;
300 }
301
302 int panel_ready(struct sprdfb_device *dev)
303 {
304         if((NULL == dev) || (NULL == dev->panel)){
305                 FB_PRINT("sprdfb: [%s]: Invalid param\n", __FUNCTION__);
306                 return -1;
307         }
308
309         FB_PRINT("sprdfb: [%s],  type = %d\n",__FUNCTION__, dev->panel->type);
310
311         if(NULL != dev->if_ctrl->panel_if_ready){
312                 dev->if_ctrl->panel_if_ready(dev);
313         }
314
315         return 0;
316 }
317
318
319 static struct panel_spec *adapt_panel_from_readid(struct sprdfb_device *dev)
320 {
321         int id, i;
322
323         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
324
325         for(i = 0;i<(sizeof(lcd_panel))/(sizeof(lcd_panel[0]));i++) {
326                 FB_PRINT("sprdfb: [%s]: try panel 0x%x\n", __FUNCTION__, lcd_panel[i].lcd_id);
327                 panel_mount(dev, lcd_panel[i].panel);
328                 panel_init(dev);
329                 panel_reset(lcd_panel[i].panel);
330                 id = dev->panel->ops->panel_readid(dev->panel);
331                 if(id == lcd_panel[i].lcd_id) {
332                         FB_PRINT("sprdfb: [%s]: LCD Panel 0x%x is attached!\n", __FUNCTION__, lcd_panel[i].lcd_id);
333
334                         dev->panel->ops->panel_init(dev->panel);                //zxdebug modify for LCD adaptor 
335                         
336                         save_lcd_id_to_kernel(id);
337                         panel_ready(dev);
338                         return lcd_panel[i].panel;
339                 } else {                                                        //zxdbg for LCD adaptor
340                         FB_PRINT("sprdfb: [%s]: LCD Panel 0x%x attached fail!go next ", __FUNCTION__, lcd_panel[i].lcd_id);
341                         sprdfb_panel_remove(dev);                               //zxdebug modify for LCD adaptor 
342                 }
343         }
344         
345         FB_PRINT("sprdfb:  [%s]: final failed to attach LCD Panel!\n", __FUNCTION__);
346         return NULL;
347 }
348
349 uint16_t sprdfb_panel_probe(struct sprdfb_device *dev)
350 {
351         struct panel_spec *panel;
352
353         if(NULL == dev){
354                 FB_PRINT("sprdfb: [%s]: Invalid param\n", __FUNCTION__);
355                 return -1;
356         }
357
358         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
359
360         /* can not be here in normal; we should get correct device id from uboot */
361         panel = adapt_panel_from_readid(dev);
362
363         if (panel) {
364                 FB_PRINT("sprdfb: [%s] got panel\n", __FUNCTION__);
365                 return 0;
366         }
367
368         FB_PRINT("sprdfb: [%s] can not got panel\n", __FUNCTION__);
369
370         return -1;
371 }
372
373 void sprdfb_panel_invalidate_rect(struct panel_spec *self,
374                                 uint16_t left, uint16_t top,
375                                 uint16_t right, uint16_t bottom)
376 {
377         FB_PRINT("sprdfb: [%s]\n, (%d, %d, %d,%d)",__FUNCTION__, left, top, right, bottom);
378
379         if(NULL != self->ops->panel_invalidate_rect){
380                 self->ops->panel_invalidate_rect(self, left, top, right, bottom);
381         }
382 }
383
384 void sprdfb_panel_invalidate(struct panel_spec *self)
385 {
386         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
387
388         if(NULL != self->ops->panel_invalidate){
389                 self->ops->panel_invalidate(self);
390         }
391 }
392
393 void sprdfb_panel_before_refresh(struct sprdfb_device *dev)
394 {
395         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
396
397         if(NULL != dev->if_ctrl->panel_if_before_refresh)
398                 dev->if_ctrl->panel_if_before_refresh(dev);
399 }
400
401 void sprdfb_panel_after_refresh(struct sprdfb_device *dev)
402 {
403         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
404
405         if(NULL != dev->if_ctrl->panel_if_after_refresh)
406                 dev->if_ctrl->panel_if_after_refresh(dev);
407 }
408
409 void sprdfb_panel_remove(struct sprdfb_device *dev)
410 {
411         FB_PRINT("sprdfb: [%s]\n",__FUNCTION__);
412
413         if(NULL != dev->if_ctrl->panel_if_uninit){
414                 dev->if_ctrl->panel_if_uninit(dev);
415         }
416         dev->panel = NULL;
417 }
418