import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / lcm / hx8369_6575_dsi_hvga / hx8369_6575_dsi_hvga.c
CommitLineData
6fa3eb70
S
1#include <linux/string.h>
2
3#include "lcm_drv.h"
4#ifndef BUILD_UBOOT
5#include <linux/kernel.h> ///for printk
6#endif
7
8// ---------------------------------------------------------------------------
9// Local Constants
10// ---------------------------------------------------------------------------
11
12#define FRAME_WIDTH (320)
13#define FRAME_HEIGHT (480)
14#define LCM_ID (0x69)
15#define REGFLAG_DELAY 0XFE
16#define REGFLAG_END_OF_TABLE 0xFF // END OF REGISTERS MARKER
17
18// ---------------------------------------------------------------------------
19// Local Variables
20// ---------------------------------------------------------------------------
21
22static LCM_UTIL_FUNCS lcm_util = {0};
23
24#define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))
25
26#define UDELAY(n) (lcm_util.udelay(n))
27#define MDELAY(n) (lcm_util.mdelay(n))
28
29
30// ---------------------------------------------------------------------------
31// Local Functions
32// ---------------------------------------------------------------------------
33
34#define dsi_set_cmdq_V2(cmd, count, ppara, force_update) lcm_util.dsi_set_cmdq_V2(cmd, count, ppara, force_update)
35#define dsi_set_cmdq(pdata, queue_size, force_update) lcm_util.dsi_set_cmdq(pdata, queue_size, force_update)
36#define wrtie_cmd(cmd) lcm_util.dsi_write_cmd(cmd)
37#define write_regs(addr, pdata, byte_nums) lcm_util.dsi_write_regs(addr, pdata, byte_nums)
38#define read_reg(cmd) lcm_util.dsi_dcs_read_lcm_reg(cmd)
39#define read_reg_v2(cmd, buffer, buffer_size) lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size)
40
41static struct LCM_setting_table {
42 unsigned cmd;
43 unsigned char count;
44 unsigned char para_list[64];
45};
46
47
48static 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 {REGFLAG_DELAY, 10, {}},
74
75 {0xB0, 2, {0x01, 0x0B}},
76 {REGFLAG_DELAY, 10, {}},
77
78 {0xB2, 15, {0x00, 0x20, 0x05, 0x05,
79 0x70, 0x00, 0xFF, 0x00,
80 0x00, 0x00, 0x00, 0x03,
81 0x03, 0x00, 0x01}},
82 {REGFLAG_DELAY, 10, {}},
83
84 {0xB4, 5, {0x00, 0x18, 0x80, 0x06,
85 0x02}},
86 {REGFLAG_DELAY, 10, {}},
87
88 {0xD5, 26, {0x00, 0x04, 0x03, 0x00,
89 0x01, 0x05, 0x28, 0x70,
90 0x01, 0x03, 0x00, 0x00,
91 0x40, 0x06, 0x51, 0x07,
92 0x00, 0x00, 0x41, 0x06,
93 0x50, 0x07, 0x07, 0x0F,
94 0x04, 0x00}},
95 {REGFLAG_DELAY, 10, {}},
96
97 {0xB1, 19, {0x85, 0x00, 0x34, 0x07,
98 0x00, 0x0f, 0x0f, 0x2A,
99 0x32, 0x3F, 0x3F, 0x01,
100 0x3A, 0x01, 0xE6, 0xE6,
101 0xE6, 0xE6, 0xE6}},
102 {REGFLAG_DELAY, 10, {}},
103
104
105 {0x3A, 1, {0x07}},
106 {0xCC, 1, {0x02}},
107
108 {0xB6, 2, {0x42, 0x42}},
109 {REGFLAG_DELAY, 10, {}},
110
111 // ENABLE FMARK
112 {0x44, 2, {((FRAME_HEIGHT/2)>>8), ((FRAME_HEIGHT/2)&0xFF)}},
113 {0x35, 1, {0x00}},
114
115 // SET GAMMA
116 {0xE0, 34, {0x00, 0x31, 0x19, 0x38,
117 0x3D, 0x3F, 0x28, 0x46,
118 0x07, 0x0D, 0x0E, 0x12,
119 0x15, 0x12, 0x14, 0x0F,
120 0x17, 0x00, 0x13, 0x19,
121 0x38, 0x3D, 0x3F, 0x28,
122 0x46, 0x07, 0x0D, 0x0E,
123 0x12, 0x15, 0x12, 0x14,
124 0x0F, 0x17}},
125 {REGFLAG_DELAY, 10, {}},
126
127 {0xBA, 13, {0x00, 0xA0, 0xC6, 0x00,
128 0x0A, 0x02, 0x10, 0x30,
129 0x6F, 0x02, 0x11, 0x18,
130 0x40}},
131
132 // Note
133 // Strongly recommend not to set Sleep out / Display On here. That will cause messed frame to be shown as later the backlight is on.
134
135
136 // Setting ending by predefined flag
137 {REGFLAG_END_OF_TABLE, 0x00, {}}
138};
139
140
141static struct LCM_setting_table lcm_set_window[] = {
142 {0x2A, 4, {0x00, 0x00, (FRAME_WIDTH>>8), (FRAME_WIDTH&0xFF)}},
143 {0x2B, 4, {0x00, 0x00, (FRAME_HEIGHT>>8), (FRAME_HEIGHT&0xFF)}},
144 {REGFLAG_END_OF_TABLE, 0x00, {}}
145};
146
147
148static struct LCM_setting_table lcm_sleep_out_setting[] = {
149 // Sleep Out
150 {0x11, 1, {0x00}},
151 {REGFLAG_DELAY, 120, {}},
152
153 // Display ON
154 {0x29, 1, {0x00}},
155 {REGFLAG_END_OF_TABLE, 0x00, {}}
156};
157
158
159static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = {
160 // Display off sequence
161 {0x28, 1, {0x00}},
162
163 // Sleep Mode On
164 {0x10, 1, {0x00}},
165
166 {REGFLAG_END_OF_TABLE, 0x00, {}}
167};
168
169static struct LCM_setting_table lcm_compare_id_setting[] = {
170 // Display off sequence
171 {0xB9, 3, {0xFF, 0x83, 0x69}},
172 {REGFLAG_DELAY, 10, {}},
173
174 // Sleep Mode On
175// {0xC3, 1, {0xFF}},
176
177 {REGFLAG_END_OF_TABLE, 0x00, {}}
178};
179
180static struct LCM_setting_table lcm_backlight_level_setting[] = {
181 {0x51, 1, {0xFF}},
182 {REGFLAG_END_OF_TABLE, 0x00, {}}
183};
184
185
186static void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update)
187{
188 unsigned int i;
189
190 for(i = 0; i < count; i++) {
191
192 unsigned cmd;
193 cmd = table[i].cmd;
194
195 switch (cmd) {
196
197 case REGFLAG_DELAY :
198 MDELAY(table[i].count);
199 break;
200
201 case REGFLAG_END_OF_TABLE :
202 break;
203
204 default:
205 dsi_set_cmdq_V2(cmd, table[i].count, table[i].para_list, force_update);
206 }
207 }
208
209}
210
211
212// ---------------------------------------------------------------------------
213// LCM Driver Implementations
214// ---------------------------------------------------------------------------
215
216static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
217{
218 memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
219}
220
221
222static void lcm_get_params(LCM_PARAMS *params)
223{
224 memset(params, 0, sizeof(LCM_PARAMS));
225
226 params->type = LCM_TYPE_DSI;
227
228 params->width = FRAME_WIDTH;
229 params->height = FRAME_HEIGHT;
230
231 // enable tearing-free
232 params->dbi.te_mode = LCM_DBI_TE_MODE_VSYNC_ONLY;
233 params->dbi.te_edge_polarity = LCM_POLARITY_RISING;
234
235 params->dsi.mode = CMD_MODE;
236
237 // DSI
238 /* Command mode setting */
239 params->dsi.LANE_NUM = LCM_TWO_LANE;
240 //The following defined the fomat for data coming from LCD engine.
241 params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;
242 params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST;
243 params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB;
244 params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888;
245
246 // Highly depends on LCD driver capability.
247 params->dsi.packet_size=256;
248
249 // Video mode setting
250 params->dsi.PS=LCM_PACKED_PS_24BIT_RGB888;
251
252 params->dsi.word_count=480*3;
253 params->dsi.vertical_sync_active=2;
254 params->dsi.vertical_backporch=2;
255 params->dsi.vertical_frontporch=2;
256 params->dsi.vertical_active_line=800;
257
258 params->dsi.line_byte=2180; // 2256 = 752*3
259 params->dsi.horizontal_sync_active_byte=26;
260 params->dsi.horizontal_backporch_byte=206;
261 params->dsi.horizontal_frontporch_byte=206;
262 params->dsi.rgb_byte=(480*3+6);
263
264 params->dsi.horizontal_sync_active_word_count=20;
265 params->dsi.horizontal_backporch_word_count=200;
266 params->dsi.horizontal_frontporch_word_count=200;
267
268 // Bit rate calculation
269 params->dsi.pll_div1=38; // fref=26MHz, fvco=fref*(div1+1) (div1=0~63, fvco=500MHZ~1GHz)
270 params->dsi.pll_div2=1; // div2=0~15: fout=fvo/(2*div2)
271
272}
273
274
275static void lcm_init(void)
276{
277 SET_RESET_PIN(1);
278 SET_RESET_PIN(0);
279 MDELAY(1);
280 SET_RESET_PIN(1);
281 MDELAY(10);
282
283 push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
284}
285
286
287static void lcm_suspend(void)
288{
289 push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);
290}
291
292
293static void lcm_resume(void)
294{
295 push_table(lcm_sleep_out_setting, sizeof(lcm_sleep_out_setting) / sizeof(struct LCM_setting_table), 1);
296}
297
298
299static void lcm_update(unsigned int x, unsigned int y,
300 unsigned int width, unsigned int height)
301{
302 unsigned int x0 = x;
303 unsigned int y0 = y;
304 unsigned int x1 = x0 + width - 1;
305 unsigned int y1 = y0 + height - 1;
306
307 unsigned char x0_MSB = ((x0>>8)&0xFF);
308 unsigned char x0_LSB = (x0&0xFF);
309 unsigned char x1_MSB = ((x1>>8)&0xFF);
310 unsigned char x1_LSB = (x1&0xFF);
311 unsigned char y0_MSB = ((y0>>8)&0xFF);
312 unsigned char y0_LSB = (y0&0xFF);
313 unsigned char y1_MSB = ((y1>>8)&0xFF);
314 unsigned char y1_LSB = (y1&0xFF);
315
316 unsigned int data_array[16];
317
318 data_array[0]= 0x00053902;
319 data_array[1]= (x1_MSB<<24)|(x0_LSB<<16)|(x0_MSB<<8)|0x2a;
320 data_array[2]= (x1_LSB);
321 data_array[3]= 0x00053902;
322 data_array[4]= (y1_MSB<<24)|(y0_LSB<<16)|(y0_MSB<<8)|0x2b;
323 data_array[5]= (y1_LSB);
324 data_array[6]= 0x002c3909;
325
326 dsi_set_cmdq(&data_array, 7, 0);
327
328}
329
330
331static void lcm_setbacklight(unsigned int level)
332{
333 // Refresh value of backlight level.
334 lcm_backlight_level_setting[0].para_list[0] = level;
335
336 push_table(lcm_backlight_level_setting, sizeof(lcm_backlight_level_setting) / sizeof(struct LCM_setting_table), 1);
337}
338
339
340static void lcm_setpwm(unsigned int divider)
341{
342 // TBD
343}
344
345
346static unsigned int lcm_getpwm(unsigned int divider)
347{
348 // ref freq = 15MHz, B0h setting 0x80, so 80.6% * freq is pwm_clk;
349 // pwm_clk / 255 / 2(lcm_setpwm() 6th params) = pwm_duration = 23706
350 unsigned int pwm_clk = 23706 / (1<<divider);
351 return pwm_clk;
352}
353
354static unsigned int lcm_compare_id()
355{
356 unsigned int id = 0;
357 unsigned char buffer[2];
358 unsigned int array[16];
359 SET_RESET_PIN(1); //NOTE:should reset LCM firstly
360 SET_RESET_PIN(0);
361 MDELAY(1);
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 return (LCM_ID == id)?1:0;
374}
375
376// ---------------------------------------------------------------------------
377// Get LCM Driver Hooks
378// ---------------------------------------------------------------------------
379LCM_DRIVER hx8369_dsi_6575_hvga_lcm_drv =
380{
381 .name = "hx8369_dsi_6575_hvga",
382 .set_util_funcs = lcm_set_util_funcs,
383 .get_params = lcm_get_params,
384 .init = lcm_init,
385 .suspend = lcm_suspend,
386 .resume = lcm_resume,
387 .update = lcm_update,
388 .set_backlight = lcm_setbacklight,
389 .set_pwm = lcm_setpwm,
390 .get_pwm = lcm_getpwm,
391 .compare_id = lcm_compare_id,
392};