import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / lcm / hx8369b_wvga_dsi_vdo / hx8369b_wvga_dsi_vdo.c
1 #ifndef BUILD_UBOOT
2 #include <linux/kernel.h>
3 #endif
4 #include <linux/string.h>
5
6 #include "lcm_drv.h"
7
8 // ---------------------------------------------------------------------------
9 // Local Constants
10 // ---------------------------------------------------------------------------
11
12 #define FRAME_WIDTH (480)
13 #define FRAME_HEIGHT (800)
14
15 // ---------------------------------------------------------------------------
16 // Local Variables
17 // ---------------------------------------------------------------------------
18
19 static LCM_UTIL_FUNCS lcm_util = {0};
20
21 #define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))
22
23 #define UDELAY(n) (lcm_util.udelay(n))
24 #define MDELAY(n) (lcm_util.mdelay(n))
25 #define REGFLAG_DELAY 0XFE
26 #define REGFLAG_END_OF_TABLE 0x00 // END OF REGISTERS MARKER
27
28
29 // ---------------------------------------------------------------------------
30 // Local Functions
31 // ---------------------------------------------------------------------------
32 #define dsi_set_cmdq_V2(cmd, count, ppara, force_update) lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update)
33 #define dsi_set_cmdq(pdata, queue_size, force_update) lcm_util.dsi_set_cmdq(pdata, queue_size, force_update)
34 #define wrtie_cmd(cmd) lcm_util.dsi_write_cmd(cmd)
35 #define write_regs(addr, pdata, byte_nums) lcm_util.dsi_write_regs(addr, pdata, byte_nums)
36 #define read_reg lcm_util.dsi_read_reg()
37 #define read_reg_v2(cmd, buffer, buffer_size) lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size)
38
39 #define LCM_DSI_CMD_MODE
40
41 struct LCM_setting_table {
42 unsigned cmd;
43 unsigned char count;
44 unsigned char para_list[64];
45 };
46
47
48 static struct LCM_setting_table lcm_initialization_setting[] = {
49
50 /*
51 Note :
52
53 Data ID will depends on the following rule.
54
55 count of parameters > 1 => Data ID = 0x39
56 count of parameters = 1 => Data ID = 0x15
57 count of parameters = 0 => Data ID = 0x05
58
59 Structure Format :
60
61 {DCS command, count of parameters, {parameter list}}
62 {REGFLAG_DELAY, milliseconds of time, {}},
63
64 ...
65
66 Setting ending by predefined flag
67
68 {REGFLAG_END_OF_TABLE, 0x00, {}}
69 */
70
71
72 {0xB9,3,{0xff,0x83,0x69}},
73 {0xB0,2,{0x01,0x0B}},
74 {0xB1,19,{0x01,0x00,0x34,0x07,0x00,0x11,0x11,0x34,0x3A,0x3F,0x3F,0x07,0x23,0x01,0xE6,0xE6,0xE6,0xE6,0xE6}},
75 {0xB2,15,{0x00,0x20,0x03,0x03,0x70,0x00,0xFF,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x01}},
76 {0xB4,5,{0x00,0x0C,0xA0,0x0E,0x06}},
77 {0xB6,2,{0x35,0x35}},
78
79 /*ENABLE FMARK*/
80 {0x44, 2, {((FRAME_HEIGHT/2)>>8), ((FRAME_HEIGHT/2)&0xFF)}},
81 {0x35, 1, {0x00}},
82
83 /*ENABLE CABC*/
84 {0x51, 1, {0xFF}},
85 {0x53, 1, {0x24}},
86 {0x55, 1, {0x01}},
87
88 {0xD5,26,{0x00,0x05,0x03,0x00,0x01,0x09,0x10,0x80,0x37,0x37,0x20,0x31,0x46,0x8A,0x57,0x9B,0x20,0x31,0x46,0x8A,0x57,0x9B,0x07,0x0F,0x02,0x00}},
89 {0xE0,34,{0x00,0x0D,0x11,0x31,0x33,0x37,0x1E,0x3A,0x07,0x0F,0x0E,0x12,0x15,0x14,0x16,0x10,0x15,0x00,0x0D,0x11,0x31,0x33,0x37,0x1E,0x3A,0x07,0x0F,0x0E,0x12,0x15,0x14,0x16,0x10,0x15}},
90 {REGFLAG_DELAY, 10, {}},
91 /*
92 {0xC1,127,{0x01,0x00,0x07,0x0F,0x18,0x1F,0x28,0x30,0x37,0x3F,0x48,0x51,0x59,0x61,0x68,0x71,0x79,0x81,0x88,0x8F,0x97,0x9E,0xA7,0xAF,0xB8,0xC0,0xC8,0xCF,0xD7,0xE0,0xE7,0xEF,0xF8,0xFF,0xFF,0xBC,0xF5,0x72,0xAD,0xCD,0xAD,0x3D,0xC0,0x00,0x07,0x0F,0x18,0x1F,0x28,0x30,0x37,0x3F,0x48,0x51,0x59,0x61,0x68,0x71,0x79,0x81,0x88,0x8F,0x97,0x9E,0xA7,0xAF,0xB8,0xC0,0xC8,0xCF,0xD7,0xE0,0xE7,0xEF,0xF8,0xFF,0xFF,0xBC,0xF5,0x72,0xAD,0xCD,0xAD,0x3D,0xC0,0x00,0x07,0x0F,0x18,0x1F,0x28,0x30,0x37,0x3F,0x48,0x51,0x59,0x61,0x68,0x71,0x79,0x81,0x88,0x8F,0x97,0x9E,0xA7,0xAF,0xB8,0xC0,0xC8,0xCF,0xD7,0xE0,0xE7,0xEF,0xF8,0xFF,0xFF,0xBC,0xF5,0x72,0xAD,0xCD,0xAD,0x3D,0xC0}},
93 */
94 {REGFLAG_DELAY, 10, {}},
95 {0xBA,13,{0x00,0xA0,0xC6,0x00,0x0A,0x00,0x10,0x30,0x6F,0x02,0x11,0x18,0x40}},
96 {REGFLAG_DELAY, 10, {}},
97 {0x3A,1,{0x77}},
98 {0x2A,4,{0x00,0x00,0x01,0xDF}},
99 {0x2B,4,{0x00,0x00,0x03,0x1F}},
100 {0x11,0,{}},
101 {REGFLAG_DELAY, 120, {}},
102 {0x29,0,{}},
103 {0x2C,0,{}},
104 {REGFLAG_END_OF_TABLE, 0x00, {}}
105 };
106
107
108 static struct LCM_setting_table lcm_set_window[] = {
109 {0x2A, 4, {0x00, 0x00, (FRAME_WIDTH>>8), (FRAME_WIDTH&0xFF)}},
110 {0x2B, 4, {0x00, 0x00, (FRAME_HEIGHT>>8), (FRAME_HEIGHT&0xFF)}},
111 {REGFLAG_END_OF_TABLE, 0x00, {}}
112 };
113
114
115 static struct LCM_setting_table lcm_sleep_out_setting[] = {
116 // Sleep Out
117 {0x11, 1, {0x00}},
118 {REGFLAG_DELAY, 100, {}},
119
120 // Display ON
121 {0x29, 1, {0x00}},
122 {REGFLAG_DELAY, 10, {}},
123 {REGFLAG_END_OF_TABLE, 0x00, {}}
124 };
125
126
127 static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = {
128 // Display off sequence
129 {0x28, 1, {0x00}},
130 {REGFLAG_DELAY, 10, {}},
131 // Sleep Mode On
132 {0x10, 1, {0x00}},
133 {REGFLAG_DELAY, 100, {}},
134 {REGFLAG_END_OF_TABLE, 0x00, {}}
135 };
136
137
138 static struct LCM_setting_table lcm_backlight_level_setting[] = {
139 {0x51, 1, {0xFF}},
140 {REGFLAG_END_OF_TABLE, 0x00, {}}
141 };
142
143
144 static struct LCM_setting_table lcm_compare_id_setting[] = {
145 // Display off sequence
146 {0xB9, 3, {0xFF, 0x83, 0x69}},
147 {REGFLAG_DELAY, 10, {}},
148
149 // Sleep Mode On
150 // {0xC3, 1, {0xFF}},
151
152 {REGFLAG_END_OF_TABLE, 0x00, {}}
153 };
154
155
156
157 void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update)
158 {
159 unsigned int i;
160
161 for(i = 0; i < count; i++) {
162
163 unsigned cmd;
164 cmd = table[i].cmd;
165
166 switch (cmd) {
167
168 case REGFLAG_DELAY :
169 MDELAY(table[i].count);
170 break;
171
172 case REGFLAG_END_OF_TABLE :
173 break;
174
175 default:
176 dsi_set_cmdq_V2(cmd, table[i].count, table[i].para_list, force_update);
177 MDELAY(10);
178 }
179 }
180
181 }
182
183
184 static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
185 {
186 memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
187 }
188
189
190 static void lcm_get_params(LCM_PARAMS *params)
191 {
192 memset(params, 0, sizeof(LCM_PARAMS));
193
194 params->type = LCM_TYPE_DSI;
195
196 params->width = FRAME_WIDTH;
197 params->height = FRAME_HEIGHT;
198
199 // enable tearing-free
200 params->dbi.te_mode = LCM_DBI_TE_MODE_VSYNC_ONLY;
201 params->dbi.te_edge_polarity = LCM_POLARITY_RISING;
202
203 #if defined(LCM_DSI_CMD_MODE)
204 params->dsi.mode = CMD_MODE;
205 #else
206 params->dsi.mode = SYNC_PULSE_VDO_MODE;
207 #endif
208
209 // DSI
210 /* Command mode setting */
211 params->dsi.LANE_NUM = LCM_TWO_LANE;
212 //The following defined the fomat for data coming from LCD engine.
213 params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;
214 params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST;
215 params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB;
216 params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888;
217
218 // Highly depends on LCD driver capability.
219 // Not support in MT6573
220 params->dsi.packet_size=256;
221
222 // Video mode setting
223 params->dsi.intermediat_buffer_num = 2;
224
225 params->dsi.PS=LCM_PACKED_PS_24BIT_RGB888;
226
227 params->dsi.vertical_sync_active = 3;
228 params->dsi.vertical_backporch = 12;
229 params->dsi.vertical_frontporch = 2;
230 params->dsi.vertical_active_line = FRAME_HEIGHT;
231
232 params->dsi.horizontal_sync_active = 10;
233 params->dsi.horizontal_backporch = 50;
234 params->dsi.horizontal_frontporch = 50;
235 params->dsi.horizontal_active_pixel = FRAME_WIDTH;
236
237 // Bit rate calculation
238 params->dsi.pll_div1=26; // fref=26MHz, fvco=fref*(div1+1) (div1=0~63, fvco=500MHZ~1GHz)
239 params->dsi.pll_div2=1; // div2=0~15: fout=fvo/(2*div2)
240
241 }
242
243
244 static void lcm_init(void)
245 {
246 /*unsigned int id = 0;
247 unsigned char buffer[2];
248 unsigned int array[16];*/
249
250 SET_RESET_PIN(0);
251 MDELAY(25);
252 SET_RESET_PIN(1);
253 MDELAY(100);
254 push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
255
256 /*SET_RESET_PIN(1); //NOTE:should reset LCM firstly
257 SET_RESET_PIN(0);
258 MDELAY(10);
259 SET_RESET_PIN(1);
260 MDELAY(10);
261
262 push_table(lcm_compare_id_setting, sizeof(lcm_compare_id_setting) / sizeof(struct LCM_setting_table), 1);
263
264 array[0] = 0x00023700;// read id return two byte,version and id
265 dsi_set_cmdq(array, 1, 1);
266 //id = read_reg(0xF4);
267 read_reg_v2(0xF4, buffer, 2);
268 id = buffer[0]; //we only need ID
269
270 #ifdef BUILD_UBOOT
271 printf("%s, id1 = 0x%08x\n", __func__, id);
272 #else
273 printk("%s, id1 = 0x%08x\n", __func__, id);
274 #endif */
275 }
276
277
278 static void lcm_suspend(void)
279 {
280 push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);
281 //SET_RESET_PIN(0);
282 //MDELAY(1);
283 //SET_RESET_PIN(1);
284 }
285
286
287 static void lcm_resume(void)
288 {
289 //lcm_init();
290
291 push_table(lcm_sleep_out_setting, sizeof(lcm_sleep_out_setting) / sizeof(struct LCM_setting_table), 1);
292 }
293
294
295 static void lcm_update(unsigned int x, unsigned int y,
296 unsigned int width, unsigned int height)
297 {
298 unsigned int x0 = x;
299 unsigned int y0 = y;
300 unsigned int x1 = x0 + width - 1;
301 unsigned int y1 = y0 + height - 1;
302
303 unsigned char x0_MSB = ((x0>>8)&0xFF);
304 unsigned char x0_LSB = (x0&0xFF);
305 unsigned char x1_MSB = ((x1>>8)&0xFF);
306 unsigned char x1_LSB = (x1&0xFF);
307 unsigned char y0_MSB = ((y0>>8)&0xFF);
308 unsigned char y0_LSB = (y0&0xFF);
309 unsigned char y1_MSB = ((y1>>8)&0xFF);
310 unsigned char y1_LSB = (y1&0xFF);
311
312 unsigned int data_array[16];
313
314 data_array[0]= 0x00053902;
315 data_array[1]= (x1_MSB<<24)|(x0_LSB<<16)|(x0_MSB<<8)|0x2a;
316 data_array[2]= (x1_LSB);
317 data_array[3]= 0x00053902;
318 data_array[4]= (y1_MSB<<24)|(y0_LSB<<16)|(y0_MSB<<8)|0x2b;
319 data_array[5]= (y1_LSB);
320 data_array[6]= 0x002c3909;
321
322 dsi_set_cmdq(&data_array, 7, 0);
323
324 }
325
326 static void lcm_setbacklight(unsigned int level)
327 {
328 // Refresh value of backlight level.
329 lcm_backlight_level_setting[0].para_list[0] = level;
330
331 push_table(lcm_backlight_level_setting, sizeof(lcm_backlight_level_setting) / sizeof(struct LCM_setting_table), 1);
332 }
333
334
335 static void lcm_setpwm(unsigned int divider)
336 {
337 // TBD
338 }
339
340
341 static unsigned int lcm_getpwm(unsigned int divider)
342 {
343 // ref freq = 15MHz, B0h setting 0x80, so 80.6% * freq is pwm_clk;
344 // pwm_clk / 255 / 2(lcm_setpwm() 6th params) = pwm_duration = 23706
345 unsigned int pwm_clk = 23706 / (1<<divider);
346 return pwm_clk;
347 }
348
349
350 // ---------------------------------------------------------------------------
351 // Get LCM ID Information
352 // ---------------------------------------------------------------------------
353 static unsigned int lcm_compare_id()
354 {
355 unsigned int id = 0;
356 unsigned char buffer[2];
357 unsigned int array[16];
358
359 SET_RESET_PIN(1); //NOTE:should reset LCM firstly
360 SET_RESET_PIN(0);
361 MDELAY(10);
362 SET_RESET_PIN(1);
363 MDELAY(10);
364
365 push_table(lcm_compare_id_setting, sizeof(lcm_compare_id_setting) / sizeof(struct LCM_setting_table), 1);
366
367 array[0] = 0x00023700;// read id return two byte,version and id
368 dsi_set_cmdq(array, 1, 1);
369 //id = read_reg(0xF4);
370 read_reg_v2(0xF4, buffer, 2);
371 id = buffer[0]; //we only need ID
372
373 #ifdef BUILD_UBOOT
374 printf("%s, id1 = 0x%08x\n", __func__, id);
375 #else
376 printk("%s, id1 = 0x%08x\n", __func__, id);
377 #endif
378
379 return (0x69 == id)?1:0;
380 }
381
382
383 LCM_DRIVER hx8369b_wvga_dsi_vdo_drv =
384 {
385 .name = "hx8369_dsi",
386 .set_util_funcs = lcm_set_util_funcs,
387 .get_params = lcm_get_params,
388 .init = lcm_init,
389 .suspend = lcm_suspend,
390 .resume = lcm_resume,
391 .set_backlight = lcm_setbacklight,
392 .set_pwm = lcm_setpwm,
393 .get_pwm = lcm_getpwm,
394 .compare_id = lcm_compare_id,
395 #if defined(LCM_DSI_CMD_MODE)
396 .update = lcm_update,
397 #endif
398 };
399