1 /* drivers/video/sprdfb/lcd_otm8019a_mipi.c
\r
3 * Support for otm8019a mipi LCD device
\r
5 * Copyright (C) 2010 Spreadtrum
\r
9 #include <asm/arch/sprd_lcd.h>
\r
10 #include "../sprdfb.h"
\r
12 #define printk printf
\r
15 //#define THREE_LANE_SUPPORT
\r
18 #define LCD_PRINT printk
\r
20 #define LCD_PRINT(...)
\r
24 typedef struct LCM_Init_Code_tag {
\r
26 unsigned char data[MAX_DATA];
\r
29 typedef struct LCM_force_cmd_code_tag{
\r
30 unsigned int datatype;
\r
31 LCM_Init_Code real_cmd_code;
\r
32 }LCM_Force_Cmd_Code;
\r
34 #define LCM_TAG_SHIFT 24
\r
35 #define LCM_TAG_MASK ((1 << 24) -1)
\r
36 #define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)
\r
37 #define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)
\r
38 //#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))
\r
40 #define LCM_TAG_SEND (1<< 0)
\r
41 #define LCM_TAG_SLEEP (1 << 1)
\r
44 static LCM_Force_Cmd_Code rd_prep_code[]={
\r
45 {0x37, {LCM_SEND(2), {0x5, 0}}},
\r
48 static LCM_Init_Code init_data[] = {
\r
49 {LCM_SEND(2),{0x00,0x00}},
\r
50 {LCM_SEND(6),{4,0,0xFF,0x80,0x19,0x01}},
\r
52 {LCM_SEND(2),{0x00,0x80}},
\r
53 {LCM_SEND(5),{3,0,0xFF,0x80,0x19}},
\r
55 {LCM_SEND(2),{0x00,0x03}},
\r
56 {LCM_SEND(2),{0xFF,0x01}},
\r
58 {LCM_SEND(2),{0x00,0x00}},
\r
59 {LCM_SEND(5),{3,0,0xD8,0x7F,0X7F}},//6f
\r
61 {LCM_SEND(2),{0x00,0x082}},
\r
62 {LCM_SEND(2),{0xC5,0xB0}},
\r
64 {LCM_SEND(2),{0x00,0xA1}},
\r
65 {LCM_SEND(2),{0xC1,0x08}},
\r
67 {LCM_SEND(2),{0x00,0xA3}},
\r
68 {LCM_SEND(2),{0xC0,0x1B}},
\r
70 {LCM_SEND(2),{0x00,0xB4}},
\r
71 {LCM_SEND(2),{0xC0,0x77}},
\r
73 {LCM_SEND(2),{0x00,0x81}},
\r
74 {LCM_SEND(2),{0xC4,0x83}},
\r
76 {LCM_SEND(2),{0x00,0x90}},
\r
77 {LCM_SEND(6),{4,0,0xC5,0x4E,0xA7,0x01}},
\r
79 {LCM_SEND(2),{0x00,0xB1}},
\r
80 {LCM_SEND(2),{0xC5,0xA9}},
\r
82 {LCM_SEND(2),{0x00,0x00}},
\r
83 {LCM_SEND(2),{0xD9,0x17}},
\r
85 {LCM_SEND(2),{0x00,0x80}},
\r
86 {LCM_SEND(2),{0xD8,0x58}},//kai ce
\r
88 //***************Gamma 2.2********************
\r
89 {LCM_SEND(2),{0x00,0x00}},
\r
90 {LCM_SEND(23),{21,0,0xE1,0x00,0x06,0x14,0x25,0x3d,0x4e,0x5a,0x8d,0x7c,0x91,0x75,0x64,0x7d,
\r
91 0x69,0x6e,0x67,0x5f,0x55,0x5c,0x02}},
\r
93 {LCM_SEND(2),{0x00,0x00}},
\r
94 {LCM_SEND(23),{21,0,0xE2,0x00,0x06,0x14,0x25,0x3d,0x4e,0x5a,0x8d,0x7b,0x91,0x75,0x64,0x7d,
\r
95 0x69,0x6e,0x67,0x5f,0x55,0x5c,0x02}},
\r
96 //********************************************
\r
97 //***************Gamma 2.5********************
\r
98 {LCM_SEND(2),{0x00,0x00}},
\r
99 {LCM_SEND(23),{21,0,0xE1,0x00,0x02,0x07,0x12,0x22,0x37,0x41,0x78,0x6b,0x85,0x7f,0x6b,0x82,
\r
100 0x6b,0x71,0x69,0x61,0x58,0x4c,0x00}},
\r
102 {LCM_SEND(2),{0x00,0x00}},
\r
103 {LCM_SEND(23),{21,0,0xE2,0x00,0x02,0x07,0x12,0x22,0x37,0x41,0x78,0x6b,0x85,0x7f,0x6b,0x82,
\r
104 0x6b,0x71,0x69,0x61,0x58,0x4c,0x00}},
\r
105 //********************************************
\r
107 {LCM_SEND(2),{0x00,0xA7}},
\r
108 {LCM_SEND(2),{0xB3,0x00}},
\r
110 {LCM_SEND(2),{0x00,0x92}},
\r
111 {LCM_SEND(2),{0xB3,0x45}},
\r
113 {LCM_SEND(2),{0x00,0x90}},
\r
114 {LCM_SEND(2),{0xB3,0x02}},
\r
116 {LCM_SEND(2),{0x00,0x00}},
\r
117 {LCM_SEND(2),{0x36,0x00}},
\r
119 {LCM_SEND(2),{0x00,0x90}},
\r
120 {LCM_SEND(9),{7,0,0xC0,0x00,0x15,0x00,0x00,0x00,0x03}},
\r
122 {LCM_SEND(2),{0x00,0xA0}},
\r
123 {LCM_SEND(2),{0xC1,0xE8}},
\r
125 {LCM_SEND(2),{0x00,0xA6}},
\r
126 {LCM_SEND(6),{4,0,0xC1,0x01,0x00,0x00}},
\r
128 {LCM_SEND(2),{0x00,0x80}},
\r
129 {LCM_SEND(9),{7,0,0xCE,0x87,0x03,0x00,0x86,0x03,0x00}},
\r
132 {LCM_SEND(2),{0x00,0x90}},
\r
133 {LCM_SEND(9),{7,0,0xCE,0x33,0x54,0x00,0x33,0x55,0x00}},
\r
136 {LCM_SEND(2),{0x00,0xA0}},
\r
137 {LCM_SEND(17),{15,0,0xCE,0x38,0x03,0x03,0x58,0x00,0x00,0x00,0x38,0x02,0x03,0x59,0x00,0x00,0x00}},
\r
140 {LCM_SEND(2),{0x00,0xB0}},
\r
141 {LCM_SEND(17),{15,0,0xCE,0x38,0x01,0x03,0x5A,0x00,0x00,0x00,0x38,0x00,0x03,0x5B,0x00,0x00,0x00}},
\r
144 {LCM_SEND(2),{0x00,0xC0}},
\r
145 {LCM_SEND(17),{15,0,0xCE,0x30,0x00,0x03,0x5C,0x00,0x00,0x00,0x30,0x01,0x03,0x5D,0x00,0x00,0x00}},
\r
148 {LCM_SEND(2),{0x00,0xD0}},
\r
149 {LCM_SEND(17),{15,0,0xCE,0x38,0x05,0x03,0x5E,0x00,0x00,0x00,0x38,0x04,0x03,0x5F,0x00,0x00,0x00}},
\r
152 {LCM_SEND(2),{0x00,0xC0}},
\r
153 {LCM_SEND(13),{11,0,0xCF,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x09}},
\r
155 {LCM_SEND(2),{0x00,0xC0}},
\r
156 {LCM_SEND(18),{16,0,0xCB,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00}},
\r
158 {LCM_SEND(2),{0x00,0xD0}},
\r
159 {LCM_SEND(18),{16,0,0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x00}},
\r
161 {LCM_SEND(2),{0x00,0xE0}},
\r
162 {LCM_SEND(13),{11,0,0xCB,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00}},
\r
164 {LCM_SEND(2),{0x00,0x80}},
\r
165 {LCM_SEND(13),{11,0,0xCC,0x00,0x26,0x25,0x02,0x06,0x00,0x00,0x0A,0x0E,0x0C}},
\r
167 {LCM_SEND(2),{0x00,0x90}},
\r
168 {LCM_SEND(18),{16,0,0xCC,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
\r
170 {LCM_SEND(2),{0x00,0xA0}},
\r
171 {LCM_SEND(18),{16,0,0xCC,0x0f,0x0b,0x0d,0x09,0x00,0x00,0x05,0x01,0x25,0x26,0x00,0x00,0x00,0x00,0x00}},
\r
173 {LCM_SEND(2),{0x00,0xB0}},
\r
174 {LCM_SEND(13),{11,0,0xCC,0x00,0x25,0x26,0x05,0x01,0x00,0x00,0x0D,0x09,0x0B}},
\r
176 {LCM_SEND(2),{0x00,0xC0}},
\r
177 {LCM_SEND(18),{16,0,0xCC,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
\r
179 {LCM_SEND(2),{0x00,0xD0}},
\r
180 {LCM_SEND(18),{16,0,0xCC,0x10,0x0c,0x0a,0x0e,0x00,0x00,0x02,0x06,0x26,0x25,0x00,0x00,0x00,0x00,0x00}},
\r
182 //-----------------AUTO SHIFT-------------------
\r
183 {LCM_SEND(2),{0x00,0x98}},
\r
184 {LCM_SEND(2),{0xC0,0x00}},
\r
185 {LCM_SEND(2),{0x00,0xA9}},
\r
186 {LCM_SEND(2),{0xC0,0x06}},
\r
187 {LCM_SEND(2),{0x00,0xB0}},
\r
188 {LCM_SEND(6),{4,0,0xC1,0x20,0x00,0x00}},
\r
189 {LCM_SEND(2),{0x00,0xE1}},
\r
190 {LCM_SEND(5),{3,0,0xC0,0x40,0x18}},
\r
191 //----------------------------------------------
\r
192 {LCM_SEND(2),{0x00,0x80}},
\r
193 {LCM_SEND(2),{0xC4,0x30}}, //source blanking area=GND
\r
195 {LCM_SEND(2),{0x00,0x80}},
\r
196 {LCM_SEND(5),{3,0,0xC1,0x03,0x33}},
\r
198 {LCM_SEND(2),{0x00,0x90}},
\r
199 {LCM_SEND(2),{0xB6,0xB4}},//command fial
\r
202 {LCM_SEND(2),{0x00,0x00}},
\r
203 {LCM_SEND(2),{0xfb,0x01}},
\r
205 {LCM_SEND(2),{0x00,0x00}},
\r
206 {LCM_SEND(2),{4,0,0xFF,0xFF,0xFF,0xFF}},
\r
208 {LCM_SEND(1), {0x11}}, // sleep out
\r
210 {LCM_SEND(1), {0x29}}, // display on
\r
211 {LCM_SLEEP(5),}, //30,100
\r
212 {LCM_SEND(1), {0x2C}}, // normal on
\r
216 static LCM_Init_Code disp_on = {LCM_SEND(1), {0x29}};
\r
217 static LCM_Init_Code sleep_in = {LCM_SEND(1), {0x10}};
\r
218 static LCM_Init_Code sleep_out = {LCM_SEND(1), {0x11}};
\r
220 static int32_t otm8019a_mipi_init(struct panel_spec *self)
\r
223 LCM_Init_Code *init = init_data;
\r
226 mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
\r
227 mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;
\r
228 mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
\r
230 LCD_PRINT("otm8019a_mipi_init\n");
\r
232 mipi_set_cmd_mode();
\r
233 mipi_eotp_set(1,0);
\r
235 for(i = 0; i < ARRAY_SIZE(init_data); i++){
\r
236 tag = (init->tag >>24);
\r
237 if(tag & LCM_TAG_SEND){
\r
238 mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));
\r
240 }else if(tag & LCM_TAG_SLEEP){
\r
241 mdelay((init->tag & LCM_TAG_MASK));
\r
245 mipi_eotp_set(1,1);
\r
249 static uint32_t otm8019a_readid(struct panel_spec *self)
\r
251 /*Jessica TODO: need read id*/
\r
254 LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;
\r
255 uint8_t read_data[5] = {0};
\r
256 int32_t read_rtn = 0;
\r
257 unsigned int tag = 0;
\r
259 mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;
\r
260 mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;
\r
261 mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;
\r
262 mipi_eotp_set_t mipi_eotp_set = self->info.mipi->ops->mipi_eotp_set;
\r
264 LCD_PRINT("lcd_otm8019a_mipi read id!\n");
\r
267 mipi_set_cmd_mode();
\r
268 mipi_eotp_set(1,0);
\r
270 for(j = 0; j < 4; j++){
\r
271 rd_prepare = rd_prep_code;
\r
272 for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){
\r
273 tag = (rd_prepare->real_cmd_code.tag >> 24);
\r
274 if(tag & LCM_TAG_SEND){
\r
275 mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
\r
276 }else if(tag & LCM_TAG_SLEEP){
\r
277 mdelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));
\r
282 read_rtn = mipi_force_read(0xa1, 5,(uint8_t *)read_data);
\r
283 LCD_PRINT("lcd_otm8019a_mipi read id 0xa1 value is 0x%x, 0x%x, 0x%x, 0x%x, 0x%x!\n",
\r
284 read_data[0], read_data[1], read_data[2], read_data[3], read_data[4]);
\r
286 mipi_eotp_set(1,1);
\r
288 if((0x01 == read_data[0])&&(0x8b == read_data[1])&&(0x80 == read_data[2])&&(0x19 == read_data[3])&&(0xff == read_data[4])){
\r
289 LCD_PRINT("lcd_otm8019a_mipi read id success!\n");
\r
294 printk("lcd_otm8019a_mipi identify fail!\n");
\r
298 static struct panel_operations lcd_otm8019a_mipi_operations = {
\r
299 .panel_init = otm8019a_mipi_init,
\r
300 .panel_readid = otm8019a_readid,
\r
303 static struct timing_rgb lcd_otm8019a_mipi_timing = {
\r
312 static struct info_mipi lcd_otm8019a_mipi_info = {
\r
313 .work_mode = SPRDFB_MIPI_MODE_VIDEO,
\r
314 .video_bus_width = 24, /*18,16*/
\r
316 .phy_feq = 500*1000,
\r
317 .h_sync_pol = SPRDFB_POLARITY_POS,
\r
318 .v_sync_pol = SPRDFB_POLARITY_POS,
\r
319 .de_pol = SPRDFB_POLARITY_POS,
\r
320 .te_pol = SPRDFB_POLARITY_POS,
\r
321 .color_mode_pol = SPRDFB_POLARITY_NEG,
\r
322 .shut_down_pol = SPRDFB_POLARITY_NEG,
\r
323 .timing = &lcd_otm8019a_mipi_timing,
\r
327 struct panel_spec lcd_otm8019a_mipi_spec = {
\r
331 .type = LCD_MODE_DSI,
\r
332 .direction = LCD_DIRECT_NORMAL,
\r
334 .mipi = &lcd_otm8019a_mipi_info
\r
336 .ops = &lcd_otm8019a_mipi_operations,
\r