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