平台:mt65852 + Android 4.4 屏:HX8389B
那么首先来看的是如何配置lcd屏(在mtk中叫做lcm)。
1. ProjectConfig.mk中配置
CUSTOM_LK_LCM = hx8389b_qhd_dsi_vdo CUSTOM_KERNEL_LCM = hx8389b_qhd_dsi_vdo LCM_HEIGHT = 960 LCM_WIDTH = 540那么相应的开机logo也要做相应的修改:
BOOT_LOGO = cu_qhd
然后修改mt65xx_lcm_list.c,依照已有的格式在lcm_driver_list这个数组里面添加下面的内容:
#if defined(HX8389B_QHD_DSI_VDO) &hx8389b_qhd_dsi_vdo_drv, #endif那么在这个数组的上面肯定还需要声明一下hx8389b_qhd_dsi_vdo_drv。
extern LCM_DRIVER hx8389b_qhd_dsi_vdo_drv;
LCM_DRIVER hx8389b_qhd_dsi_vdo_drv = { .name = "hx8389b_qhd_dsi_vdo", .set_util_funcs = lcm_set_util_funcs, .get_params = lcm_get_params, .init = lcm_init, .suspend = lcm_suspend, .resume = lcm_resume, .compare_id = lcm_compare_id, };
static LCM_UTIL_FUNCS lcm_util; static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util) { memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS)); }在lcm_set_util_funcs这个函数中将util的内容复制给了lcm_util。那么在LCM_UTIL_FUNCS这个类型中,主要定义了一些接口函数,这些接口函数是mtk提供给lcm驱动开发者使用的,所以说不管是哪一款lcm驱动,都需要这么一个接口,而且需要实现set_util_funcs接口,然后在mtk lcm核心部分自然会调用这个接口函数,这样我们就可以使用其中的接口函数了。
再来看lcm_get_params。
lcm_get_params函数中主要是一些参数定义,例如屏的分辨率,屏的接口类型等等:
#define FRAME_WIDTH 540 #define FRAME_HEIGHT 960 static void lcm_get_params(LCM_PARAMS *params) { memset(params, 0, sizeof(LCM_PARAMS)); params->type = LCM_TYPE_DSI; /* lcm的接口类型 */ params->width = FRAME_WIDTH; /* lcm分辨率 */ params->height = FRAME_HEIGHT; params->dsi.mode = SYNC_PULSE_VDO_MODE; /* video mode */ params->dsi.LANE_NUM = LCM_THREE_LANE; /* lanes */ params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888; /* 数据格式 */ params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888; params->dsi.vertical_sync_active = 0x02; /* video mode需要配置的一些参数 */ params->dsi.vertical_backporch = 0x0e; params->dsi.vertical_frontporch = 0x09; params->dsi.vertical_active_line = FRAME_HEIGHT; params->dsi.horizontal_sync_active = 0x21; params->dsi.horizontal_backporch = 0x21; params->dsi.horizontal_frontporch = 0x15; params->dsi.horizontal_active_pixel = FRAME_WIDTH; params->dsi.PLL_CLOCK = 180; /* clock(MHz) */ }
#define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v))) #define UDELAY(n) (lcm_util.udelay(n)) #define MDELAY(n) (lcm_util.mdelay(n)) #define dsi_set_cmdq_V3(para_tbl, size, force_update) lcm_util.dsi_set_cmdq_V3(para_tbl, size, force_update) #define dsi_set_cmdq_V2(cmd, count ppara, force_update) lcm_util.dsi_set_cmdq_V2(cmd, count, ppare, force_update) #define dsi_set_cmdq(pdata, queue_size, force_update) lcm_util.dsi_set_cmdq(pdata, queue_size, force_update) #define write_cmd(cmd) lcm_util.dsi_write_cmd(cmd) #define write_regs(addr, pdata, byte_nums) lcm_util.dsi_write_regs(addr, pdata, bytes_nums) #define read_reg(cmd) lcm_util.dsi_dcs_read_lcm_reg(cmd) #define read_reg_v2(cmd, buffer, buffer_size) lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size) static LCM_setting_table_V3 lcm_initialization_setting[] = { {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x03}}, {0x39, 0x90, 9, {0x05, 0x14, 0x05, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00}}, {0x39, 0x91, 9, {0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00}}, {0x39, 0x92, 11, {0x40, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x54, 0x00, 0x00, 0x05, 0x08}}, {0x39, 0x94, 8, {0x00, 0x08, 0x05, 0x03, 0xCE, 0x03, 0xD0, 0x0C}}, {0x39, 0x95, 16, {0x40, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x10, 0x00, 0x54, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08}}, {0x39, 0x99, 2, {0x00, 0x00}}, {0x39, 0x9A, 11, {0x80, 0x0D, 0x03, 0xD2, 0x03, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x50}}, {0x39, 0x9B, 6, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {0x39, 0x9C, 2, {0x00, 0x00}}, {0x39, 0x9D, 8, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00}}, {0x39, 0x9E, 2, {0x00, 0x00}}, {0x39, 0xA0, 10, {0x95, 0x14, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0B, 0x1F}}, {0x39, 0xA1, 10, {0x1F, 0x1F, 0x09, 0x1F, 0x1F, 0x1F, 0x0F, 0x1F, 0x1F, 0x1F}}, {0x39, 0xA2, 10, {0x0D, 0x1F, 0x01, 0x1F, 0x03, 0x1F, 0x1F, 0x1F, 0x05, 0x1F}}, {0x39, 0xA3, 10, {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}}, {0x39, 0xA4, 10, {0x1F, 0x04, 0x1F, 0x1F, 0x1F, 0x02, 0x1F, 0x00, 0x1F, 0x0C}}, {0x39, 0xA5, 10, {0x1F, 0x1F, 0x1F, 0x0E, 0x1F, 0x1F, 0x1F, 0x08, 0x1F, 0x1F}}, {0x39, 0xA6, 10, {0x1F, 0x0A, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x14, 0x15}}, {0x39, 0xA7, 10, {0x14, 0x15, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0C, 0x1F}}, {0x39, 0xA8, 10, {0x1F, 0x1F, 0x0E, 0x1F, 0x1F, 0x1F, 0x08, 0x1F, 0x1F, 0x1F}}, {0x39, 0xA9, 10, {0x0A, 0x1F, 0x02, 0x1F, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x04}}, {0x39, 0xAA, 10, {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}}, {0x39, 0xAB, 10, {0x1F, 0x05, 0x1F, 0x1F, 0x1F, 0x01, 0x1F, 0x03, 0x1F, 0x0B}}, {0x39, 0xAC, 10, {0x1F, 0x1F, 0x1F, 0x09, 0x1F, 0x1F, 0x1F, 0x0F, 0x1F, 0x1F}}, {0x39, 0xAD, 10, {0x1F, 0x0D, 0x1F, 0x1F, 0x1F, 0x02, 0x1F, 0x1F, 0x15, 0x14}}, {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x00}}, {0x15, 0xFC, 1, {0x00}}, {0x39, 0xBC, 3, {0x00, 0x00, 0x00}}, {0x39, 0xB8, 4, {0x01, 0x8F, 0xBF, 0x80}}, {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x01}}, {0x39, 0xD1, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}}, {0x39, 0xD2, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}}, {0x39, 0xD3, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}}, {0x39, 0xD4, 4, {0x03, 0xEE, 0x03, 0xFF}}, {0x39, 0xD5, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}}, {0x39, 0xD6, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}}, {0x39, 0xD7, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}}, {0x39, 0xD8, 4, {0x03, 0xEE, 0x03, 0xFF}}, {0x39, 0xD9, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}}, {0x39, 0xDD, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}}, {0x39, 0xDE, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}}, {0x39, 0xDF, 4, {0x03, 0xEE, 0x03, 0xFF}}, {0x39, 0xE0, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}}, {0x39, 0xE1, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}}, {0x39, 0xE2, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}}, {0x39, 0xE3, 4, {0x03, 0xEE, 0x03, 0xFF}}, {0x39, 0xE4, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}}, {0x39, 0xE5, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}}, {0x39, 0xE6, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}}, {0x39, 0xE7, 4, {0x03, 0xEE, 0x03, 0xFF}}, {0x39, 0xE8, 16, {0x00, 0x17, 0x00, 0x58, 0x00, 0x8D, 0x00, 0xB0, 0x00, 0xCA, 0x00, 0xF2, 0x01, 0x12, 0x01, 0x45}}, {0x39, 0xE9, 16, {0x01, 0x6D, 0x01, 0xAC, 0x01, 0xDD, 0x02, 0x29, 0x02, 0x67, 0x02, 0x69, 0x02, 0xA3, 0x02, 0xE0}}, {0x39, 0xEA, 16, {0x03, 0x05, 0x03, 0x34, 0x03, 0x53, 0x03, 0x7C, 0x03, 0x94, 0x03, 0xB7, 0x03, 0xC9, 0x03, 0xD9}}, {0x39, 0xEB, 4, {0x03, 0xEE, 0x03, 0xFF}}, {0x39, 0xB0, 3, {0x05, 0x05, 0x05}}, {0x39, 0xB1, 3, {0x05, 0x05, 0x05}}, {0x39, 0xB6, 3, {0x44, 0x44, 0x44}}, {0x39, 0xB7, 3, {0x34, 0x34, 0x34}}, {0x39, 0xB3, 3, {0x12, 0x12, 0x12}}, {0x39, 0xB9, 3, {0x34, 0x34, 0x34}}, {0x39, 0xB4, 3, {0x06, 0x06, 0x06}}, {0x39, 0xBA, 3, {0x14, 0x14, 0x14}}, {0x39, 0xBC, 3, {0x00, 0x98, 0x00}}, {0x39, 0xBD, 3, {0x00, 0x98, 0x00}}, {0x15, 0xBE, 1, {0x5A}},//60 {0x39, 0xF0, 5, {0x55, 0xAA, 0x52, 0x08, 0x02}}, {0x39, 0xF6, 2, {0xCA, 0x69}}, {0x39, 0xFB, 3, {0x09, 0x03, 0x08}}, {0x39, 0xF1, 3, {0x22, 0x22, 0x32}}, {0x15, 0x35, 1, {0x00}}, {0x05, 0x11,0,{0x00}}, {REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 200, {}}, {0x05, 0x29,0,{0x00}}, {REGFLAG_ESCAPE_ID, REGFLAG_DELAY_MS_V3, 10, {}}, }; static void lcm_init(void) { SET_RESET_PIN(0); MDELAY(20); SET_RESET_PIN(1); MDELAY(120); dsi_set_cmdq_V3(lcm_initialization_setting, sizeof(lcm_initialization_setting)/sizeof(lcm_initialization_setting[0]), 1); }要理解这部分代码,需要稍微了解一下mipi dsi协议。
long packet格式如下:
不管是long packet还是short packet,都有个DATA ID字段,高两位我们先忽略,而低六位为Data Type,mipi dsi协议中有专门定义,这里暂时用到的有:
0x05 Short WRITE,无参数 0x15 Short WRITE,带一个参数 0x39 Long WRITE
详细的Data Type可以参见mipi dsi手册。
我们看在lcm_initialization_setting数组中,第一个值就是这里的Data Type,而第二个值则是hx8389b寄存器的地址,而第三个参数则是参数的个数,而最后才是参数值。
hx8389b的datasheet也给出了两个例子,例如:
05h CMD 0 ECC 05h 29h 00 1Ch (display on(29h)) 15h CMD Par ECC 15h 36h 08h 11h (MADCTL(36h)-BGR bit=1)我们可以看出lcm_init同它的名字一样,主要是对屏做初始化操作。
static void lcm_suspend(void) { unsigned int data_array[16]; data_array[0] = 0x00100500; dsi_set_cmdq(data_array, 1, 1); MDELAY(120); SET_RESET_PIN(1); SET_RESET_PIN(0); MDELAY(20); SET_RESET_PIN(1); MDELAY(120); } static void lcm_resume(void) { lcm_init(); }在lcm_suspend函数中,我们主要来看dsi_set_cmdq这部分。
bits 8~15 16~23 24~31 DATA_ID DATA_0 DATA_1
所以,前面data_array[0] = 0x00100500对应的是一个不带参数的short packet,寄存器地址是0x10,下发的指令意思是进入sleep模式(可以参见hx8389b的数据手册)。
如果是long packet,那么数组的第一个元素定义如下:
bits 8~15 16~23 DATA_ID DATA_0
注意,在long packet中,DATA_0表示的是Word Count的低8位。
最后来看那个lcm_compare_id函数。
compare_id函数对于lcm驱动来说不是必须的,但最好加上。这个函数主要是用于兼容lcm时,lcm核心会调用该函数来匹配lcm驱动和屏。
#define LCM_ID_HX8389B 0x89 static unsigned int lcm_compare_id(void) { unsigned int id = 0; unsigned char buffer[2]; unsigned int array[16]; SET_RESET_PIN(1); SET_RESET_PIN(0); MDELAY(1); SET_RESET_PIN(1); MDELAY(10); array[0] = 0x00023700; dsi_set_cmdq(array, 1, 1); MDELAY(10); read_reg_v2(0x04, buffer, 2); id = buffer[1]; return (id == LCM_ID_HX8389B) ? 1 : 0; }这里也涉及到了mipi dsi协议:
0x37 Set Maximum Return Packet Size 0x06 DCS READ, no parameters
read_reg_v2第一个参数为读寄存器的地址。
参考文档:
1. MIPI_DSI_Specification_V1.02.00.pdf
2. HX8389-B_DS_Temporary_General_v00_20120109.pdf
3. MT6582_LCM_Porting_Guide_DSI_V1.0.pptx.pdf
附:HX8389B Datasheet下载地址:http://download.csdn.net/detail/mcgrady_tracy/8327585