2 #include <linux/kernel.h>
4 #include <linux/string.h>
8 // ---------------------------------------------------------------------------
10 // ---------------------------------------------------------------------------
12 #define FRAME_WIDTH (480)
13 #define FRAME_HEIGHT (800)
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 static LCM_UTIL_FUNCS lcm_util
= {0};
21 #define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))
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
29 // ---------------------------------------------------------------------------
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)
39 #define LCM_DSI_CMD_MODE
41 struct LCM_setting_table
{
44 unsigned char para_list
[64];
48 static struct LCM_setting_table lcm_initialization_setting
[] = {
53 Data ID will depends on the following rule.
55 count of parameters > 1 => Data ID = 0x39
56 count of parameters = 1 => Data ID = 0x15
57 count of parameters = 0 => Data ID = 0x05
61 {DCS command, count of parameters, {parameter list}}
62 {REGFLAG_DELAY, milliseconds of time, {}},
66 Setting ending by predefined flag
68 {REGFLAG_END_OF_TABLE, 0x00, {}}
72 {0xB9,3,{0xff,0x83,0x69}},
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}},
80 {0x44, 2, {((FRAME_HEIGHT
/2)>>8), ((FRAME_HEIGHT
/2)&0xFF)}},
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, {}},
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}},
94 {REGFLAG_DELAY
, 10, {}},
95 {0xBA,13,{0x00,0xA0,0xC6,0x00,0x0A,0x00,0x10,0x30,0x6F,0x02,0x11,0x18,0x40}},
96 {REGFLAG_DELAY
, 10, {}},
98 {0x2A,4,{0x00,0x00,0x01,0xDF}},
99 {0x2B,4,{0x00,0x00,0x03,0x1F}},
101 {REGFLAG_DELAY
, 120, {}},
104 {REGFLAG_END_OF_TABLE
, 0x00, {}}
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, {}}
115 static struct LCM_setting_table lcm_sleep_out_setting
[] = {
118 {REGFLAG_DELAY
, 100, {}},
122 {REGFLAG_DELAY
, 10, {}},
123 {REGFLAG_END_OF_TABLE
, 0x00, {}}
127 static struct LCM_setting_table lcm_deep_sleep_mode_in_setting
[] = {
128 // Display off sequence
130 {REGFLAG_DELAY
, 10, {}},
133 {REGFLAG_DELAY
, 100, {}},
134 {REGFLAG_END_OF_TABLE
, 0x00, {}}
138 static struct LCM_setting_table lcm_backlight_level_setting
[] = {
140 {REGFLAG_END_OF_TABLE
, 0x00, {}}
144 static struct LCM_setting_table lcm_compare_id_setting
[] = {
145 // Display off sequence
146 {0xB9, 3, {0xFF, 0x83, 0x69}},
147 {REGFLAG_DELAY
, 10, {}},
150 // {0xC3, 1, {0xFF}},
152 {REGFLAG_END_OF_TABLE
, 0x00, {}}
157 void push_table(struct LCM_setting_table
*table
, unsigned int count
, unsigned char force_update
)
161 for(i
= 0; i
< count
; i
++) {
169 MDELAY(table
[i
].count
);
172 case REGFLAG_END_OF_TABLE
:
176 dsi_set_cmdq_V2(cmd
, table
[i
].count
, table
[i
].para_list
, force_update
);
184 static void lcm_set_util_funcs(const LCM_UTIL_FUNCS
*util
)
186 memcpy(&lcm_util
, util
, sizeof(LCM_UTIL_FUNCS
));
190 static void lcm_get_params(LCM_PARAMS
*params
)
192 memset(params
, 0, sizeof(LCM_PARAMS
));
194 params
->type
= LCM_TYPE_DSI
;
196 params
->width
= FRAME_WIDTH
;
197 params
->height
= FRAME_HEIGHT
;
199 // enable tearing-free
200 params
->dbi
.te_mode
= LCM_DBI_TE_MODE_VSYNC_ONLY
;
201 params
->dbi
.te_edge_polarity
= LCM_POLARITY_RISING
;
203 #if defined(LCM_DSI_CMD_MODE)
204 params
->dsi
.mode
= CMD_MODE
;
206 params
->dsi
.mode
= SYNC_PULSE_VDO_MODE
;
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
;
218 // Highly depends on LCD driver capability.
219 // Not support in MT6573
220 params
->dsi
.packet_size
=256;
222 // Video mode setting
223 params
->dsi
.intermediat_buffer_num
= 2;
225 params
->dsi
.PS
=LCM_PACKED_PS_24BIT_RGB888
;
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
;
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
;
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)
244 static void lcm_init(void)
246 /*unsigned int id = 0;
247 unsigned char buffer[2];
248 unsigned int array[16];*/
254 push_table(lcm_initialization_setting
, sizeof(lcm_initialization_setting
) / sizeof(struct LCM_setting_table
), 1);
256 /*SET_RESET_PIN(1); //NOTE:should reset LCM firstly
262 push_table(lcm_compare_id_setting, sizeof(lcm_compare_id_setting) / sizeof(struct LCM_setting_table), 1);
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
271 printf("%s, id1 = 0x%08x\n", __func__, id);
273 printk("%s, id1 = 0x%08x\n", __func__, id);
278 static void lcm_suspend(void)
280 push_table(lcm_deep_sleep_mode_in_setting
, sizeof(lcm_deep_sleep_mode_in_setting
) / sizeof(struct LCM_setting_table
), 1);
287 static void lcm_resume(void)
291 push_table(lcm_sleep_out_setting
, sizeof(lcm_sleep_out_setting
) / sizeof(struct LCM_setting_table
), 1);
295 static void lcm_update(unsigned int x
, unsigned int y
,
296 unsigned int width
, unsigned int height
)
300 unsigned int x1
= x0
+ width
- 1;
301 unsigned int y1
= y0
+ height
- 1;
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);
312 unsigned int data_array
[16];
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;
322 dsi_set_cmdq(&data_array
, 7, 0);
326 static void lcm_setbacklight(unsigned int level
)
328 // Refresh value of backlight level.
329 lcm_backlight_level_setting
[0].para_list
[0] = level
;
331 push_table(lcm_backlight_level_setting
, sizeof(lcm_backlight_level_setting
) / sizeof(struct LCM_setting_table
), 1);
335 static void lcm_setpwm(unsigned int divider
)
341 static unsigned int lcm_getpwm(unsigned int divider
)
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
);
350 // ---------------------------------------------------------------------------
351 // Get LCM ID Information
352 // ---------------------------------------------------------------------------
353 static unsigned int lcm_compare_id()
356 unsigned char buffer
[2];
357 unsigned int array
[16];
359 SET_RESET_PIN(1); //NOTE:should reset LCM firstly
365 push_table(lcm_compare_id_setting
, sizeof(lcm_compare_id_setting
) / sizeof(struct LCM_setting_table
), 1);
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
374 printf("%s, id1 = 0x%08x\n", __func__
, id
);
376 printk("%s, id1 = 0x%08x\n", __func__
, id
);
379 return (0x69 == id
)?1:0;
383 LCM_DRIVER hx8369b_wvga_dsi_vdo_drv
=
385 .name
= "hx8369_dsi",
386 .set_util_funcs
= lcm_set_util_funcs
,
387 .get_params
= lcm_get_params
,
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
,