tizen 2.4 release
[kernel/u-boot-tm1.git] / drivers / video / sprdfb / lcd / lcd_otm_8018b_mipi.c
1 /* drivers/video/sc8825/lcd_otm8018b_mipi.c\r
2  *\r
3  * Support for otm8018b mipi LCD device\r
4  *\r
5  * Copyright (C) 2010 Spreadtrum\r
6  *\r
7  * This software is licensed under the terms of the GNU General Public\r
8  * License version 2, as published by the Free Software Foundation, and\r
9  * may be copied, distributed, and modified under those terms.\r
10  *\r
11  * This program is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  */\r
16 \r
17 #include <asm/arch/sprd_lcd.h>\r
18 #include "../sprdfb.h"\r
19 \r
20 #define printk printf\r
21 \r
22 //#define  LCD_DEBUG\r
23 #ifdef LCD_DEBUG\r
24 #define LCD_PRINT printk\r
25 #else\r
26 #define LCD_PRINT(...)\r
27 #endif\r
28 \r
29 #define MAX_DATA   48\r
30 \r
31 typedef struct LCM_Init_Code_tag {\r
32         unsigned int tag;\r
33         unsigned char data[MAX_DATA];\r
34 }LCM_Init_Code;\r
35 \r
36 typedef struct LCM_force_cmd_code_tag{\r
37         unsigned int datatype;\r
38         LCM_Init_Code real_cmd_code;\r
39 }LCM_Force_Cmd_Code;\r
40 \r
41 #define LCM_TAG_SHIFT 24\r
42 #define LCM_TAG_MASK  ((1 << 24) -1)\r
43 #define LCM_SEND(len) ((1 << LCM_TAG_SHIFT)| len)\r
44 #define LCM_SLEEP(ms) ((2 << LCM_TAG_SHIFT)| ms)\r
45 //#define ARRAY_SIZE(array) ( sizeof(array) / sizeof(array[0]))\r
46 \r
47 #define LCM_TAG_SEND  (1<< 0)\r
48 #define LCM_TAG_SLEEP (1 << 1)\r
49 \r
50 static LCM_Init_Code init_data[] = {\r
51 #if 1 \r
52 {LCM_SEND(6), {4, 0, 0xff,0x80,0x09,0x01}}, \r
53 \r
54 {LCM_SEND(2), {0x00,0x80}}, \r
55 {LCM_SEND(5), {3, 0, 0xff,0x80,0x09}},\r
56 \r
57 {LCM_SEND(2), {0x00,0x03}}, \r
58 {LCM_SEND(2), {0xFF,0x01}}, \r
59 \r
60 {LCM_SEND(2), {0x00,0xB4}}, \r
61 {LCM_SEND(2), {0xC0,0x10}}, \r
62 \r
63 {LCM_SEND(2), {0x00,0x82}}, \r
64 {LCM_SEND(2), {0xC5,0xA3}}, \r
65 \r
66 {LCM_SEND(2), {0x00,0x90}}, \r
67 {LCM_SEND(5), {3, 0, 0xC5,0xC6,0x76}},\r
68 \r
69 {LCM_SEND(2), {0x00,0x00}}, \r
70 {LCM_SEND(5), {3, 0, 0xD8,0x75,0x73}},\r
71 \r
72 {LCM_SEND(2), {0x00,0x00}}, \r
73 {LCM_SEND(2), {0xD9,0x4E}}, \r
74 \r
75 /*-------------Gamma+ ------*/\r
76 {LCM_SEND(2), {0x00,0x00}},\r
77 {LCM_SEND(19), {17, 0, 0xE1,0x0C,0x0D,0x11,0x10,0x0A,0x1B,0x0B,0x0B,0x00,0x03,0x03,0x05,0x0D,0x24,0x21,0x05}}, \r
78 \r
79 {LCM_SEND(2), {0x00,0x00}},\r
80 {LCM_SEND(19), {17, 0, 0xE2,0x0C,0x0D,0x11,0x12,0x0E,0x1D,0x0B,0x0B,0x00,0x03,0x03,0x05,0x0D,0x25,0x21,0x05}}, \r
81 \r
82 {LCM_SEND(2), {0x00,0x81}}, \r
83 {LCM_SEND(2), {0xC1,0x66}}, \r
84 {LCM_SEND(2), {0x00,0xA1}}, \r
85 {LCM_SEND(2), {0xC1,0x08}}, \r
86 \r
87 {LCM_SEND(2), {0x00,0x89}}, \r
88 {LCM_SEND(2), {0xC4,0x08}}, \r
89 \r
90 {LCM_SEND(2), {0x00,0xA2}}, \r
91 {LCM_SEND(6), {4, 0, 0xC0,0x1B,0x00,0x02}},\r
92 \r
93 {LCM_SEND(2), {0x00,0x81}}, \r
94 {LCM_SEND(2), {0xC4,0x83}}, \r
95 \r
96 {LCM_SEND(2), {0x00,0x92}}, \r
97 {LCM_SEND(2), {0xC5,0x01}}, \r
98 \r
99 {LCM_SEND(2), {0x00,0xB1}}, \r
100 {LCM_SEND(2), {0xC5,0xA9}}, \r
101 \r
102 /*C09x : mck_shift1/mck_shift2/mck_shift3*/\r
103 {LCM_SEND(2), {0x00,0x90}}, \r
104 {LCM_SEND(9), {7, 0, 0xC0,0x00,0x44,0x00,0x00,0x00,0x03}},\r
105 \r
106 /*C1Ax : hs_shift/vs_shift*/\r
107 {LCM_SEND(2), {0x00,0xA6}}, \r
108 {LCM_SEND(6), {4, 0, 0xC1,0x00,0x00,0x00}},\r
109 \r
110 //CE8x : vst1, vst2, vst3, vst4\r
111 {LCM_SEND(2), {0x00,0x80}}, \r
112 {LCM_SEND(15), {13, 0, 0xCE,0x87,0x03,0x00,0x85,0x03,0x00,0x86,0x03,0x00,0x84,0x03,0x00}},\r
113 \r
114 //CEAx : clka1, clka2\r
115 {LCM_SEND(2), {0x00,0xA0}},\r
116 {LCM_SEND(17), {15, 0, 0xCE,0x38,0x03,0x03,0x58,0x00,0x00,0x00,0x38,0x02,0x03,0x59,0x00,0x00,0x00}},\r
117 \r
118 //CEBx : clka3, clka4\r
119 {LCM_SEND(2), {0x00,0xB0}},\r
120 {LCM_SEND(17), {15, 0, 0xCE,0x38,0x01,0x03,0x5A,0x00,0x00,0x00,0x38,0x00,0x03,0x5B,0x00,0x00,0x00}},\r
121 \r
122 //CECx : clkb1, clkb2\r
123 {LCM_SEND(2), {0x00,0xC0}},\r
124 {LCM_SEND(17), {15, 0, 0xCE,0x30,0x00,0x03,0x5C,0x00,0x00,0x00,0x30,0x01,0x03,0x5D,0x00,0x00,0x00}},\r
125 \r
126 //CEDx : clkb3, clkb4\r
127 {LCM_SEND(2), {0x00,0xD0}},\r
128 {LCM_SEND(17), {15, 0, 0xCE,0x30,0x02,0x03,0x5E,0x00,0x00,0x00,0x30,0x03,0x03,0x5F,0x00,0x00,0x00}},\r
129 \r
130 {LCM_SEND(2), {0x00, 0xC7}}, \r
131 {LCM_SEND(2), {0xCF, 0x00}}, \r
132 \r
133 {LCM_SEND(2), {0x00, 0xC9}}, \r
134 {LCM_SEND(2), {0xCF, 0x00}}, \r
135 \r
136 {LCM_SEND(2), {0x00, 0xC4}}, \r
137 {LCM_SEND(9), {7, 0, 0xCB,0x04,0x04,0x04,0x04,0x04,0x04}},\r
138 \r
139 {LCM_SEND(2), {0x00, 0xD9}}, \r
140 {LCM_SEND(9), {7, 0, 0xCB,0x04,0x04,0x04,0x04,0x04,0x04}},\r
141 \r
142 {LCM_SEND(2), {0x00, 0x84}}, \r
143 {LCM_SEND(9), {7, 0, 0xCC,0x0C,0x0A,0x10,0x0E,0x03,0x04}},\r
144 \r
145 {LCM_SEND(2), {0x00,0x9E}}, \r
146 {LCM_SEND(2), {0xCC,0x0B}}, \r
147 \r
148 {LCM_SEND(2), {0x00,0xA0}}, \r
149 {LCM_SEND(8), {6, 0, 0xCC,0x09,0x0F,0x0D,0x01,0x02}},\r
150 \r
151 {LCM_SEND(2), {0x00,0xB4}}, \r
152 {LCM_SEND(9), {7, 0, 0xCC,0x0D,0x0F,0x09,0x0B,0x02,0x01}},\r
153 \r
154 {LCM_SEND(2), {0x00,0xCE}}, \r
155 {LCM_SEND(2), {0xCC,0x0E}}, \r
156 \r
157 {LCM_SEND(2), {0x00,0xD0}}, \r
158 {LCM_SEND(8), {6, 0, 0xCC,0x10,0x0A,0x0C,0x04,0x03}},\r
159 \r
160 {LCM_SEND(2), {0x00,0x00}}, \r
161 {LCM_SEND(2), {0x3A,0x77}}, \r
162 \r
163 {LCM_SEND(2), {0x11, 0x00}}, // sleep out \r
164 {LCM_SLEEP(200),},\r
165 {LCM_SEND(2), {0x29, 0x00}}, // display on \r
166 \r
167 {LCM_SEND(1), {0x2C}}, // normal on \r
168 \r
169 #endif\r
170 \r
171 };\r
172 \r
173 static LCM_Force_Cmd_Code rd_prep_code[]={\r
174         {0x37, {LCM_SEND(2), {0x5, 0}}},\r
175 };\r
176 \r
177 static LCM_Init_Code disp_on =  {LCM_SEND(1), {0x29}};\r
178 \r
179 static LCM_Init_Code sleep_in =  {LCM_SEND(1), {0x10}};\r
180 \r
181 static LCM_Init_Code sleep_out =  {LCM_SEND(1), {0x11}};\r
182 \r
183 static int32_t otm8018b_mipi_init(struct panel_spec *self)\r
184 {\r
185         int32_t i;\r
186         LCM_Init_Code *init = init_data;\r
187         unsigned int tag;\r
188 \r
189         mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;\r
190         mipi_gen_write_t mipi_gen_write = self->info.mipi->ops->mipi_gen_write;\r
191 \r
192         LCD_PRINT("otm8018b_mipi_init\n");\r
193 \r
194         mipi_set_cmd_mode();\r
195 \r
196         for(i = 0; i < ARRAY_SIZE(init_data); i++){\r
197                 tag = (init->tag >>24);\r
198                 if(tag & LCM_TAG_SEND){\r
199                         mipi_gen_write(init->data, (init->tag & LCM_TAG_MASK));\r
200                         udelay(20);\r
201                 }else if(tag & LCM_TAG_SLEEP){\r
202                         mdelay((init->tag & LCM_TAG_MASK));\r
203                 }\r
204                 init++;\r
205         }\r
206         return 0;\r
207 }\r
208 \r
209 static uint32_t otm8018b_readid(struct panel_spec *self)\r
210 {\r
211         /*Jessica TODO: need read id*/\r
212         int32_t i = 0;\r
213         uint32 j =0;\r
214         LCM_Force_Cmd_Code * rd_prepare = rd_prep_code;\r
215         uint8_t read_data[5] = {0};\r
216         int32_t read_rtn = 0;\r
217         unsigned int tag = 0;\r
218 \r
219         mipi_set_cmd_mode_t mipi_set_cmd_mode = self->info.mipi->ops->mipi_set_cmd_mode;\r
220         mipi_force_write_t mipi_force_write = self->info.mipi->ops->mipi_force_write;\r
221         mipi_force_read_t mipi_force_read = self->info.mipi->ops->mipi_force_read;\r
222 \r
223         LCD_PRINT("lcd_otm8018b_mipi read id!\n");\r
224         mipi_set_cmd_mode();\r
225         for(j = 0; j < 4; j++){\r
226                 rd_prepare = rd_prep_code;\r
227                 for(i = 0; i < ARRAY_SIZE(rd_prep_code); i++){\r
228                         tag = (rd_prepare->real_cmd_code.tag >> 24);\r
229                         if(tag & LCM_TAG_SEND){\r
230                                 mipi_force_write(rd_prepare->datatype, rd_prepare->real_cmd_code.data, (rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));\r
231                         }else if(tag & LCM_TAG_SLEEP){\r
232                                 mdelay((rd_prepare->real_cmd_code.tag & LCM_TAG_MASK));\r
233                         }\r
234                         rd_prepare++;\r
235                 }\r
236 \r
237                 read_rtn = mipi_force_read(0xa1, 3,(uint8_t *)read_data);\r
238                 LCD_PRINT("lcd_otm8018b_mipi read id 0xa1 value is 0x%x, 0x%x, 0x%x, 0x%x, 0x%x!\n",\r
239                         read_data[0], read_data[1], read_data[2], read_data[3], read_data[4]);\r
240 \r
241                 if((0x01 == read_data[0])&&(0x8b == read_data[1])&&(0x80 == read_data[2])&&(0x09 == read_data[3])&&(0xff == read_data[4])){\r
242                         LCD_PRINT("lcd_otm8018b_mipi read id success!\n");\r
243                         return 0x18;\r
244                 }\r
245         }\r
246 \r
247         printk("lcd_otm8018b_mipi identify fail!\n");\r
248         return 0x0;\r
249 }\r
250 \r
251 static struct panel_operations lcd_otm8018b_mipi_operations = {\r
252         .panel_init = otm8018b_mipi_init,\r
253         .panel_readid = otm8018b_readid,\r
254 };\r
255 \r
256 static struct timing_rgb lcd_otm8018b_mipi_timing = {\r
257         .hfp = 80,  /* unit: pixel */\r
258         .hbp = 80,\r
259         .hsync = 6,\r
260         .vfp = 10, /*unit: line*/\r
261         .vbp = 10,\r
262         .vsync = 6,\r
263 };\r
264 \r
265 static struct info_mipi lcd_otm8018b_mipi_info = {\r
266         .work_mode  = SPRDFB_MIPI_MODE_VIDEO,\r
267         .video_bus_width = 24, /*18,16*/\r
268         .lan_number = 2,\r
269         .phy_feq = 500*1000,\r
270         .h_sync_pol = SPRDFB_POLARITY_POS,\r
271         .v_sync_pol = SPRDFB_POLARITY_POS,\r
272         .de_pol = SPRDFB_POLARITY_POS,\r
273         .te_pol = SPRDFB_POLARITY_POS,\r
274         .color_mode_pol = SPRDFB_POLARITY_POS,\r
275         .shut_down_pol = SPRDFB_POLARITY_POS,\r
276         .timing = &lcd_otm8018b_mipi_timing,\r
277         .ops = NULL,\r
278 };\r
279 \r
280 struct panel_spec lcd_otm8018b_mipi_spec = {\r
281         .width = 480,\r
282         .height = 800,\r
283         .type = LCD_MODE_DSI,\r
284         .direction = LCD_DIRECT_NORMAL,\r
285         .info = {\r
286                 .mipi = &lcd_otm8018b_mipi_info\r
287         },\r
288         .ops = &lcd_otm8018b_mipi_operations,\r
289 };\r
290 \r
291 \r