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 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}},
69 {LCM_SEND(1), {0x29}},
72 static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
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
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
88 static LCM_Init_Code test_key_on[] = {
89 {LCM_SEND(5), {3, 0x00, 0xF0, 0x5A, 0x5A} },
92 static LCM_Init_Code test_key_off[] = {
93 {LCM_SEND(5), {3, 0x00, 0xF0, 0xA5, 0xA5} },
96 static LCM_Init_Code global_para[] = {
97 {LCM_SEND(2), {0xB0, 0x00} },
100 static int32_t s6e8aa5x01_mipi_init(struct panel_spec *self)
103 LCM_Init_Code *init = init_data;
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;
110 printk("kernel s6e8aa5x01_mipi_init\n");
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));
120 }else if(tag & LCM_TAG_SLEEP){
121 mdelay(init->tag & LCM_TAG_MASK);
130 static uint32_t s6e8aa5x01_readid(struct panel_spec *self)
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;
141 LCD_PRINT("lcd_s6e8aa5x01_mipi read id!\n");
146 for(j = 0; j < 4; j++){
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");
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");
166 LCD_PRINT("lcd_s6e8aa5x01_mipi read id failed!\n");
172 static int32_t s6e8aa5x01_enter_sleep(struct panel_spec *self, uint8_t is_sleep)
175 LCM_Init_Code *sleep_in_out = NULL;
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;
183 printk("kernel s6e8aa5x01_enter_sleep, is_sleep = %d\n", is_sleep);
186 sleep_in_out = sleep_in;
187 size = ARRAY_SIZE(sleep_in);
189 sleep_in_out = sleep_out;
190 size = ARRAY_SIZE(sleep_out);
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);
210 static int32_t mipi_dcs_send(struct panel_spec *self,
211 LCM_Init_Code *cmd , int32_t len)
216 mipi_dcs_write_t mipi_dcs_write =
217 self->info.mipi->ops->mipi_dcs_write;
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));
224 } else if (tag & LCM_TAG_SLEEP) {
225 mdelay(cmd->tag & LCM_TAG_MASK);
233 static void s6e8aa5x01_test_key(struct panel_spec *self, uint8_t enable)
235 LCM_Init_Code *test_key = NULL;
239 test_key = test_key_on;
240 size = ARRAY_SIZE(test_key_on);
242 test_key = test_key_off;
243 size = ARRAY_SIZE(test_key_off);
246 mipi_dcs_send(self, test_key, size);
249 static int32_t s6e8aa5x01_check_mtp(struct panel_spec *self)
251 LCM_Init_Code *g_para = NULL;
253 uint8_t mtp_offset[MTP_LEN + 6] = {0};
254 int32_t read_rtn = 0;
255 uint8_t param[2] = {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;
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;
274 s6e8aa5x01_test_key(self, 0x1);
277 param[0] = MTP_LEN + 6;
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);
284 if (mtp_offset[30] != 2 || mtp_offset[31] != 3 ||
286 printk("%s: fail to read mtp offset[%d]\n",
292 s6e8aa5x01_test_key(self, 0x0);
294 mipi_set_video_mode();
296 save_mtp_offset_to_kernel(mtp_offset);
301 static int32_t s6e8aa5x01_check_elvss(struct panel_spec *self)
303 LCM_Init_Code *g_para = NULL;
304 LCM_Init_Code *hbm = NULL;
306 uint8_t elvss_offset = 0;
307 int32_t read_rtn = 0;
308 uint8_t param[2] = {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;
326 s6e8aa5x01_test_key(self, 0x1);
329 for (i = 0; i < 3; i++) {
330 g_para = global_para;
331 size = ARRAY_SIZE(global_para);
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);
343 s6e8aa5x01_test_key(self, 0x0);
345 mipi_set_video_mode();
347 save_elvss_offset_to_kernel(elvss_offset);
352 static int32_t s6e8aa5x01_check_hbm(struct panel_spec *self)
354 LCM_Init_Code *g_para = NULL;
355 LCM_Init_Code *hbm = NULL;
357 uint8_t hbm_g[15] = {0};
358 int32_t read_rtn = 0;
359 uint8_t param[2] = {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;
377 s6e8aa5x01_test_key(self, 0x1);
380 for (i = 0; i < 3; i++) {
381 g_para = global_para;
382 size = ARRAY_SIZE(global_para);
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);
394 s6e8aa5x01_test_key(self, 0x0);
396 mipi_set_video_mode();
398 save_hbm_offset_to_kernel(hbm_g);
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,
412 static struct timing_rgb lcd_s6e8aa5x01_mipi_timing = {
413 .hfp = 84, /* unit: pixel */
416 .vfp = 14, /* unit: line */
421 static struct info_mipi lcd_s6e8aa5x01_mipi_info = {
422 .work_mode = SPRDFB_MIPI_MODE_VIDEO,
423 .video_bus_width = 24, /*18,16*/
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,
436 struct panel_spec lcd_s6e8aa5x01_mipi_spec = {
442 .type = LCD_MODE_DSI,
443 .direction = LCD_DIRECT_NORMAL,
445 .mipi = &lcd_s6e8aa5x01_mipi_info
447 .ops = &lcd_s6e8aa5x01_mipi_operations,