1 /* drivers/video/sprdfb/lcd_s6e8aa5x01_mipi.c
3 * Support for s6e8aa5x01 mipi LCD device
5 * Copyright (C) 2015 Spreadtrum
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.
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.
16 #include <asm/arch/sprd_lcd.h>
17 #include "../sprdfb.h"
22 #define LCD_PRINT printk
24 #define LCD_PRINT(...)
29 #define PIKEA_J1_NBW_PANEL
32 typedef struct LCM_Init_Code_tag {
34 unsigned char data[MAX_DATA];
37 typedef struct LCM_force_cmd_code_tag{
38 unsigned int datatype;
39 LCM_Init_Code real_cmd_code;
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]))
48 #define LCM_TAG_SEND (1<< 0)
49 #define LCM_TAG_SLEEP (1 << 1)
53 #define ELVSS_ADDR 0xB6
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);
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}},
73 {LCM_SEND(1), {0x29}},
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
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
90 static LCM_Init_Code test_key_on[] = {
91 {LCM_SEND(5), {3, 0x00, 0xF0, 0x5A, 0x5A} },
94 static LCM_Init_Code test_key_off[] = {
95 {LCM_SEND(5), {3, 0x00, 0xF0, 0xA5, 0xA5} },
98 static LCM_Init_Code global_para[] = {
99 {LCM_SEND(2), {0xB0, 0x00} },
102 static int32_t s6e8aa5x01_mipi_init(struct panel_spec *self)
105 LCM_Init_Code *init = init_data;
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;
112 printk("kernel s6e8aa5x01_mipi_init\n");
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));
122 }else if(tag & LCM_TAG_SLEEP){
123 mdelay(init->tag & LCM_TAG_MASK);
132 static uint32_t s6e8aa5x01_readid(struct panel_spec *self)
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;
142 LCD_PRINT("lcd_s6e8aa5x01_mipi read id!\n");
147 for(j = 0; j < 4; j++){
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");
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");
167 LCD_PRINT("lcd_s6e8aa5x01_mipi read id failed!\n");
173 static int32_t s6e8aa5x01_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
176 LCM_Init_Code *sleep_in_out = NULL;
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;
184 printk("kernel s6e8aa5x01_enter_sleep, is_sleep = %d\n", is_sleep);
187 sleep_in_out = sleep_in;
188 size = ARRAY_SIZE(sleep_in);
190 sleep_in_out = sleep_out;
191 size = ARRAY_SIZE(sleep_out);
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);
211 static int32_t mipi_dcs_send(struct panel_spec *self,
212 LCM_Init_Code *cmd , int32_t len)
217 mipi_dcs_write_t mipi_dcs_write =
218 self->info.mipi->ops->mipi_dcs_write;
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));
225 } else if (tag & LCM_TAG_SLEEP) {
226 mdelay(cmd->tag & LCM_TAG_MASK);
234 static void s6e8aa5x01_test_key(struct panel_spec *self, uint8_t enable)
236 LCM_Init_Code *test_key = NULL;
240 test_key = test_key_on;
241 size = ARRAY_SIZE(test_key_on);
243 test_key = test_key_off;
244 size = ARRAY_SIZE(test_key_off);
247 mipi_dcs_send(self, test_key, size);
250 static int32_t s6e8aa5x01_check_mtp(struct panel_spec *self)
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;
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;
270 s6e8aa5x01_test_key(self, 0x1);
273 param[0] = MTP_LEN + 6;
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);
280 if (mtp_offset[30] != 2 || mtp_offset[31] != 3 ||
282 printk("%s: fail to read mtp offset[%d]\n",
288 s6e8aa5x01_test_key(self, 0x0);
290 mipi_set_video_mode();
292 save_mtp_offset_to_kernel(mtp_offset);
297 static int32_t s6e8aa5x01_check_elvss(struct panel_spec *self)
299 LCM_Init_Code *g_para = NULL;
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;
320 s6e8aa5x01_test_key(self, 0x1);
323 for (i = 0; i < 3; i++) {
324 g_para = global_para;
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);
336 s6e8aa5x01_test_key(self, 0x0);
338 mipi_set_video_mode();
340 save_elvss_offset_to_kernel(elvss_offset);
345 static int32_t s6e8aa5x01_check_hbm(struct panel_spec *self)
347 LCM_Init_Code *g_para = NULL;
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;
368 s6e8aa5x01_test_key(self, 0x1);
371 for (i = 0; i < 3; i++) {
372 g_para = global_para;
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);
384 s6e8aa5x01_test_key(self, 0x0);
386 mipi_set_video_mode();
388 save_hbm_offset_to_kernel(hbm_g);
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,
402 static struct timing_rgb lcd_s6e8aa5x01_mipi_timing = {
403 .hfp = 84, /* unit: pixel */
406 .vfp = 14, /* unit: line */
411 static struct info_mipi lcd_s6e8aa5x01_mipi_info = {
412 .work_mode = SPRDFB_MIPI_MODE_VIDEO,
413 .video_bus_width = 24, /*18,16*/
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,
426 struct panel_spec lcd_s6e8aa5x01_mipi_spec = {
432 .type = LCD_MODE_DSI,
433 .direction = LCD_DIRECT_NORMAL,
435 .mipi = &lcd_s6e8aa5x01_mipi_info
437 .ops = &lcd_s6e8aa5x01_mipi_operations,