tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / video / sprdfb / lcd / lcd_s6e8aa5x01_mipi.c
1 /* drivers/video/sprdfb/lcd_s6e8aa5x01_mipi.c
2  *
3  * Support for s6e8aa5x01 mipi LCD device
4  *
5  * Copyright (C) 2015 Spreadtrum
6  *
7  * This software is licensed under the terms of the GNU General Public
8  * License version 2, as published by the Free Software Foundation, and
9  * may be copied, distributed, and modified under those terms.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 #include <asm/arch/sprd_lcd.h>
17 #include "../sprdfb.h"
18 #define printk printf
19
20 #define  LCD_DEBUG
21 #ifdef LCD_DEBUG
22 #define LCD_PRINT printk
23 #else
24 #define LCD_PRINT(...)
25 #endif
26
27 #define MAX_DATA   150
28
29 #define PIKEA_J1_NBW_PANEL
30
31
32 typedef struct LCM_Init_Code_tag {
33         unsigned int tag;
34         unsigned char data[MAX_DATA];
35 }LCM_Init_Code;
36
37 typedef struct LCM_force_cmd_code_tag{
38         unsigned int datatype;
39         LCM_Init_Code real_cmd_code;
40 }LCM_Force_Cmd_Code;
41
42 #define LCM_TAG_SHIFT 24
43 #define LCM_TAG_MASK  ((1 << 24) -1)
44 #define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
45 #define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
46 //#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
47
48 #define LCM_TAG_SEND  (1<< 0)
49 #define LCM_TAG_SLEEP (1 << 1)
50
51 #define MTP_ADDR        0xC8
52 #define MTP_LEN         0x21
53 #define ELVSS_ADDR      0xB6
54
55 static LCM_Init_Code init_data[] = {
56         {LCM_SEND(5),           {3, 0x00, 0xF0, 0x5A, 0x5A} },
57         {LCM_SEND(5),           {3, 0x00, 0xF1, 0x5A, 0x5A} },
58         {LCM_SEND(36),          {34, 0x00, 0xCA, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
59                                                         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
60                                                         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, } },
61         {LCM_SEND(7),           {5, 0x00, 0xB2, 0x00, 0x0F, 0x00, 0x0F} },
62         {LCM_SEND(5),           {3, 0x00, 0xB6, 0xB3, 0x0F} },
63         {LCM_SEND(2),           {0xf7, 0x03} },
64         {LCM_SEND(6),           {4, 0x00, 0xC0, 0xD8, 0xD8, 0x40} },
65         {LCM_SEND(2),           {0xB0, 0x06} },
66         {LCM_SEND(2),           {0xB8, 0xA8} },
67         {LCM_SEND(1),           {0x11}},
68         {LCM_SLEEP(120)},
69         {LCM_SEND(1),           {0x29}},
70 };
71
72 static LCM_Init_Code disp_on =  {LCM_SEND(1), {0x29}};
73
74 static LCM_Init_Code sleep_in[] =  {
75         {LCM_SEND(1), {0x28}},
76         {LCM_SLEEP(150)},       //>150ms
77         {LCM_SEND(1), {0x10}},
78         {LCM_SLEEP(150)},       //>150ms
79 };
80
81 static LCM_Init_Code sleep_out[] =  {
82         {LCM_SEND(1), {0x11}},
83         {LCM_SLEEP(120)},//>120ms
84         {LCM_SEND(1), {0x29}},
85         {LCM_SLEEP(20)}, //>20ms
86 };
87
88 static LCM_Init_Code test_key_on[] =  {
89         {LCM_SEND(5),           {3, 0x00, 0xF0, 0x5A, 0x5A} },
90 };
91
92 static LCM_Init_Code test_key_off[] =  {
93         {LCM_SEND(5),           {3, 0x00, 0xF0, 0xA5, 0xA5} },
94 };
95
96 static LCM_Init_Code global_para[] =  {
97         {LCM_SEND(2),           {0xB0, 0x00} },
98 };
99
100 static int32_t s6e8aa5x01_mipi_init(struct panel_spec *self)
101 {
102         int32_t i = 0;
103         LCM_Init_Code *init = init_data;
104         unsigned int tag;
105
106         mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
107         mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
108         mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
109
110         printk("kernel s6e8aa5x01_mipi_init\n");
111
112         mipi_set_cmd_mode();
113         mipi_eotp_set(0,0);
114
115         for(i = 0; i < ARRAY_SIZE(init_data); i++){
116                 tag = (init->tag >>24);
117                 if(tag & LCM_TAG_SEND){
118                         mipi_dcs_write(init->data, (init->tag & LCM_TAG_MASK));
119                         udelay(20);
120                 }else if(tag & LCM_TAG_SLEEP){
121                         mdelay(init->tag & LCM_TAG_MASK);
122                 }
123                 init++;
124         }
125         mipi_eotp_set(0,0);
126
127         return 0;
128 }
129
130 static uint32_t s6e8aa5x01_readid(struct panel_spec *self)
131         {
132         uint8_t j =0;
133         uint8_t read_data[4] = {0};
134         int32_t read_rtn = 0;
135         uint8_t param[2] = {0};
136         mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
137         mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
138         mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
139         mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
140
141         LCD_PRINT("lcd_s6e8aa5x01_mipi read id!\n");
142
143         mipi_set_cmd_mode();
144         mipi_eotp_set(0,0);
145
146         for(j = 0; j < 4; j++){
147                 param[0] = 0x03;
148                 param[1] = 0x00;
149                 mipi_force_write(0x37, param, 2);
150                 read_rtn = mipi_force_read(0x04, 3, read_data);
151                 LCD_PRINT("lcd_s6e8aa5x01_mipi read id 0xda, 0xdb,0xdc is 0x%x,0x%x,0x%x!\n",
152                                 read_data[0], read_data[1], read_data[2]);
153                 if ((0x40 == read_data[0]) && (0x00 == read_data[1])
154                                 && (0x02 == read_data[2])) {
155                         LCD_PRINT("lcd_s6e8aa5x01_mipi read 0x02 id success!\n");
156                         return 0x400002;
157                 } else if ((0x40 == read_data[0]) && (0x00 == read_data[1])
158                                 && (0x03 == read_data[2])) {
159                         LCD_PRINT("lcd_s6e8aa5x01_mipi read 0x03 id success!\n");
160                         return 0x400002;
161                 }
162         }
163
164         mipi_eotp_set(0,0);
165
166         LCD_PRINT("lcd_s6e8aa5x01_mipi read id failed!\n");
167         return 0;
168
169 }
170
171
172 static int32_t s6e8aa5x01_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
173 {
174         int32_t i = 0;
175         LCM_Init_Code *sleep_in_out = NULL;
176         unsigned int tag;
177         int32_t size = 0;
178
179         mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
180         mipi_dcs_write_t mipi_dcs_write = self->info.mipi->ops->mipi_dcs_write;
181         mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
182
183         printk("kernel s6e8aa5x01_enter_sleep, is_sleep = %d\n", is_sleep);
184
185         if(is_sleep){
186                 sleep_in_out = sleep_in;
187                 size = ARRAY_SIZE(sleep_in);
188         }else{
189                 sleep_in_out = sleep_out;
190                 size = ARRAY_SIZE(sleep_out);
191         }
192
193         mipi_set_cmd_mode();
194         mipi_eotp_set(0,0);
195
196         for(i = 0; i <size ; i++){
197                 tag = (sleep_in_out->tag >>24);
198                 if(tag & LCM_TAG_SEND){
199                         mipi_dcs_write(sleep_in_out->data, (sleep_in_out->tag & LCM_TAG_MASK));
200                 }else if(tag & LCM_TAG_SLEEP){
201                         mdelay(sleep_in_out->tag & LCM_TAG_MASK);
202                 }
203                 sleep_in_out++;
204         }
205         mipi_eotp_set(0,0);
206
207         return 0;
208 }
209
210 static int32_t mipi_dcs_send(struct panel_spec *self,
211                                 LCM_Init_Code *cmd , int32_t len)
212 {
213         int32_t i = 0;
214         unsigned int tag;
215
216         mipi_dcs_write_t mipi_dcs_write =
217                         self->info.mipi->ops->mipi_dcs_write;
218
219         for (i = 0; i < len; i++) {
220                 tag = (cmd->tag >> 24);
221                 if (tag & LCM_TAG_SEND) {
222                         mipi_dcs_write(cmd->data, (cmd->tag & LCM_TAG_MASK));
223                         udelay(20);
224                 } else if (tag & LCM_TAG_SLEEP) {
225                         mdelay(cmd->tag & LCM_TAG_MASK);
226                 }
227                 cmd++;
228         }
229
230         return 0;
231 }
232
233 static void s6e8aa5x01_test_key(struct panel_spec *self, uint8_t enable)
234 {
235         LCM_Init_Code *test_key = NULL;
236         int32_t size = 0;
237
238         if (enable) {
239                 test_key = test_key_on;
240                 size = ARRAY_SIZE(test_key_on);
241         } else {
242                 test_key = test_key_off;
243                 size = ARRAY_SIZE(test_key_off);
244         }
245
246         mipi_dcs_send(self, test_key, size);
247 }
248
249 static int32_t s6e8aa5x01_check_mtp(struct panel_spec *self)
250 {
251         LCM_Init_Code *g_para = NULL;
252         uint8_t i = 0;
253         uint8_t mtp_offset[MTP_LEN + 6] = {0};
254         int32_t read_rtn = 0;
255         uint8_t param[2] = {0};
256         int32_t size = 0;
257         mipi_force_write_t mipi_force_write =
258                         self->info.mipi->ops->mipi_force_write;
259         mipi_force_read_t mipi_force_read =
260                         self->info.mipi->ops->mipi_force_read;
261         mipi_dcs_write_t mipi_dcs_write =
262                         self->info.mipi->ops->mipi_dcs_write;
263         mipi_set_cmd_mode_t mipi_set_cmd_mode =
264                         self->info.mipi->ops->mipi_set_cmd_mode;
265
266         mipi_set_cmd_mode_t mipi_set_video_mode =
267                         self->info.mipi->ops->mipi_set_video_mode;
268         mipi_eotp_set_t mipi_eotp_set =
269                         self->info.mipi->ops->mipi_eotp_set;
270
271         mipi_set_cmd_mode();
272         mipi_eotp_set(0, 0);
273
274         s6e8aa5x01_test_key(self, 0x1);
275
276         /* MTP OFFSET READ*/
277         param[0] = MTP_LEN + 6;
278         param[1] = 0x00;
279
280         for (i = 0; i < 3; i++) {
281                 mipi_force_write(0x37, param, 2);
282                 read_rtn = mipi_force_read(MTP_ADDR, MTP_LEN + 6, mtp_offset);
283
284                 if (mtp_offset[30] != 2 || mtp_offset[31] != 3 ||
285                         mtp_offset[32] != 2)
286                         printk("%s: fail to read mtp offset[%d]\n",
287                                         __func__, i);
288                 else
289                         break;
290         }
291
292         s6e8aa5x01_test_key(self, 0x0);
293         mipi_eotp_set(0, 0);
294         mipi_set_video_mode();
295
296         save_mtp_offset_to_kernel(mtp_offset);
297
298         return 0;
299 }
300
301 static int32_t s6e8aa5x01_check_elvss(struct panel_spec *self)
302 {
303         LCM_Init_Code *g_para = NULL;
304         LCM_Init_Code *hbm = NULL;
305         uint8_t i = 0;
306         uint8_t elvss_offset = 0;
307         int32_t read_rtn = 0;
308         uint8_t param[2] = {0};
309         int32_t size = 0;
310         mipi_force_write_t mipi_force_write =
311                         self->info.mipi->ops->mipi_force_write;
312         mipi_force_read_t mipi_force_read =
313                         self->info.mipi->ops->mipi_force_read;
314         mipi_dcs_write_t mipi_dcs_write =
315                         self->info.mipi->ops->mipi_dcs_write;
316         mipi_set_cmd_mode_t mipi_set_cmd_mode =
317                         self->info.mipi->ops->mipi_set_cmd_mode;
318         mipi_set_cmd_mode_t mipi_set_video_mode =
319                         self->info.mipi->ops->mipi_set_video_mode;
320         mipi_eotp_set_t mipi_eotp_set =
321                         self->info.mipi->ops->mipi_eotp_set;
322
323         mipi_set_cmd_mode();
324         mipi_eotp_set(0, 0);
325
326         s6e8aa5x01_test_key(self, 0x1);
327
328         /* ELVSS OFFSET */
329         for (i = 0; i < 3; i++) {
330                 g_para = global_para;
331                 size = ARRAY_SIZE(global_para);
332                 param[0] = 0x1;
333                 param[1] = 0x00;
334                 mipi_force_write(0x37, param, 2);
335                 g_para->data[1] = 0x15; /*B6 22th para*/
336                 mipi_dcs_write(g_para->data, (g_para->tag & LCM_TAG_MASK));
337                 read_rtn = mipi_force_read(ELVSS_ADDR, 0x1, &elvss_offset);
338
339                 if (read_rtn == 1) {
340                         break;
341                 }
342         }
343         s6e8aa5x01_test_key(self, 0x0);
344         mipi_eotp_set(0, 0);
345         mipi_set_video_mode();
346
347         save_elvss_offset_to_kernel(elvss_offset);
348
349         return 0;
350 }
351
352 static int32_t s6e8aa5x01_check_hbm(struct panel_spec *self)
353 {
354         LCM_Init_Code *g_para = NULL;
355         LCM_Init_Code *hbm = NULL;
356         uint8_t i = 0;
357         uint8_t hbm_g[15] = {0};
358         int32_t read_rtn = 0;
359         uint8_t param[2] = {0};
360         int32_t size = 0;
361         mipi_force_write_t mipi_force_write =
362                         self->info.mipi->ops->mipi_force_write;
363         mipi_force_read_t mipi_force_read =
364                         self->info.mipi->ops->mipi_force_read;
365         mipi_dcs_write_t mipi_dcs_write =
366                         self->info.mipi->ops->mipi_dcs_write;
367         mipi_set_cmd_mode_t mipi_set_cmd_mode =
368                         self->info.mipi->ops->mipi_set_cmd_mode;
369         mipi_set_cmd_mode_t mipi_set_video_mode =
370                         self->info.mipi->ops->mipi_set_video_mode;
371         mipi_eotp_set_t mipi_eotp_set =
372                         self->info.mipi->ops->mipi_eotp_set;
373
374         mipi_set_cmd_mode();
375         mipi_eotp_set(0, 0);
376
377         s6e8aa5x01_test_key(self, 0x1);
378
379         /* HBM GAMMA */
380         for (i = 0; i < 3; i++) {
381                 g_para = global_para;
382                 size = ARRAY_SIZE(global_para);
383                 param[0] = 0xf;
384                 param[1] = 0x00;
385                 mipi_force_write(0x37, param, 2);
386                 g_para->data[1] = 0x48; /*C8 34th~39th, 73th ~ 87th*/
387                 mipi_dcs_write(g_para->data, (g_para->tag & LCM_TAG_MASK));
388                 read_rtn = mipi_force_read(MTP_ADDR, 0xf, hbm_g);
389
390                 if (read_rtn > 0)
391                         break;
392         }
393
394         s6e8aa5x01_test_key(self, 0x0);
395         mipi_eotp_set(0, 0);
396         mipi_set_video_mode();
397
398         save_hbm_offset_to_kernel(hbm_g);
399
400         return 0;
401 }
402
403 static struct panel_operations lcd_s6e8aa5x01_mipi_operations = {
404         .panel_init = s6e8aa5x01_mipi_init,
405         .panel_readid = s6e8aa5x01_readid,
406         .panel_enter_sleep = s6e8aa5x01_enter_sleep,
407         .panel_check_mtp = s6e8aa5x01_check_mtp,
408         .panel_check_elvss = s6e8aa5x01_check_elvss,
409         .panel_check_hbm = s6e8aa5x01_check_hbm,
410 };
411
412 static struct timing_rgb lcd_s6e8aa5x01_mipi_timing = {
413         .hfp = 84,  /* unit: pixel */
414         .hbp = 90,
415         .hsync = 40,
416         .vfp = 14, /* unit: line */
417         .vbp = 10,
418         .vsync = 4,
419 };
420
421 static struct info_mipi lcd_s6e8aa5x01_mipi_info = {
422         .work_mode  = SPRDFB_MIPI_MODE_VIDEO,
423         .video_bus_width = 24, /*18,16*/
424         .lan_number =   4,
425         .phy_feq =500*1000,
426         .h_sync_pol = SPRDFB_POLARITY_POS,
427         .v_sync_pol = SPRDFB_POLARITY_POS,
428         .de_pol = SPRDFB_POLARITY_POS,
429         .te_pol = SPRDFB_POLARITY_POS,
430         .color_mode_pol = SPRDFB_POLARITY_NEG,
431         .shut_down_pol = SPRDFB_POLARITY_NEG,
432         .timing = &lcd_s6e8aa5x01_mipi_timing,
433         .ops = NULL,
434 };
435
436 struct panel_spec lcd_s6e8aa5x01_mipi_spec = {
437         .width = 720,
438         .height = 1280,
439 //      .width_mm = 62,
440 //      .height_mm = 110,
441         .fps    = 60,
442         .type = LCD_MODE_DSI,
443         .direction = LCD_DIRECT_NORMAL,
444         .info = {
445                 .mipi = &lcd_s6e8aa5x01_mipi_info
446         },
447         .ops = &lcd_s6e8aa5x01_mipi_operations,
448 };
449