struct LCM_setting_table {
unsigned char cmd; // 命令地址
unsigned char count; // 寄存器值的个数
unsigned char para_list[128]; //寄存器的值
};
static struct LCM_setting_table lcm_initialization_setting[] = {
{0xFF, 4, {0xAA,0x55,0xA5,0x80}}, //就是LCM_setting_table结构体的三个成员。
}
mipi屏的话,MTK平台的是不同的屏只要换这个初始化设置的代码就可以跑起来的,当然有些屏ic已经有程序,不需要再从初始化里下载这段代码。只要上电时序和配置对了就可以跑起来。
效果调试最多的是调试水波纹,可以调试vcom对应的寄存器。竖的波纹好像和pll_clk有关,可以调试试一下。
初始化里的这部分延时不能少。0x11和0x29是用来下载这段代码到lcd ic的,还有其它下载模式。比如:0x10和0x28.
{0x11, 1, {0x00}},
{REGFLAG_DELAY, 120, {}},
{0x29, 1, {0x00}},
{REGFLAG_DELAY, 20, {}},
{REGFLAG_END_OF_TABLE, 0x00, {}},
static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = { }
这个是睡眠设置的寄存器
static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = {}
这个是深度睡眠设置的寄存器
static void push_table(struct LCM_setting_table *table, unsigned int count, unsigned char force_update){}
这个是讲上面这些设置寄存器的数组push到ic里面去的函数。参数:结构体数组,个数,强制更新吧1次(我理解的)
重点内容
驱动实现部分
static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
{
memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
}
lcm 驱动框架提供给驱动开发者的接口函数,将util复制到lcm_util。
static void lcm_get_params(LCM_PARAMS *params)
{
memset(params, 0, sizeof(LCM_PARAMS));
params->type = LCM_TYPE_DSI;
params->width = FRAME_WIDTH; //宽
params->height = FRAME_HEIGHT; //高
params->dsi.mode = CMD_MODE;
params->dsi.mode = SYNC_PULSE_VDO_MODE;
// DSI
/* Command mode setting */
params->dsi.LANE_NUM = LCM_FOUR_LANE;
params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888;
//video mode timing
params->dsi.PS=LCM_PACKED_PS_24BIT_RGB888;
params->dsi.vertical_sync_active = 4;
params->dsi.vertical_backporch = 40;
params->dsi.vertical_frontporch = 40;
params->dsi.vertical_active_line = FRAME_HEIGHT;
params->dsi.horizontal_sync_active = 4;
params->dsi.horizontal_backporch = 82;
params->dsi.horizontal_frontporch = 82;
params->dsi.horizontal_active_pixel = FRAME_WIDTH;
//improve clk quality
params->dsi.PLL_CLOCK = 240; //this value must be in MTK suggested table
params->dsi.compatibility_for_nvk = 1;
params->dsi.ssc_disable = 1;
}
这个是lcm的配置部分,调试驱动必然要改的地方。
MIPI接口:一共有三种接口:DBI(也做CPU或MCU接口)、DPI(也叫RGB接口)、DSI.
在使用DSI接口时,目前6735支持到4条data lane,加上一条clock lane.我们采用的是DSI的
params->dsi.vertical_sync_active = 4;
params->dsi.vertical_backporch = 40;
params->dsi.vertical_frontporch = 40;
params->dsi.horizontal_sync_active = 4;
params->dsi.horizontal_backporch = 82;
params->dsi.horizontal_frontporch = 82;
这几个数据要看datasheet,才可以,调试的关键地方。
params->dsi.PLL_CLOCK = 240; lcm的频率,更据实际情况改动,这个一般mtk的都会影响gps的信号强弱。
static void lcm_id_pin_handle(void)
{
mt_set_gpio_pull_select(GPIO_DISP_ID0_PIN,GPIO_PULL_UP);
mt_set_gpio_pull_select(GPIO_DISP_ID1_PIN,GPIO_PULL_DOWN);
}
这个防止漏电的
static void lcm_init(void)
{
//enable VSP & VSN
lcm_util.set_gpio_out(GPIO_LCD_BIAS_ENP_PIN, GPIO_OUT_ONE);
lcm_util.set_gpio_out(GPIO_LCD_BIAS_ENN_PIN, GPIO_OUT_ONE);
msleep(50);
//reset high to low to high
lcm_util.set_gpio_out(GPIO_DISP_LRSTB_PIN, GPIO_OUT_ONE);
mdelay(5);
lcm_util.set_gpio_out(GPIO_DISP_LRSTB_PIN, GPIO_OUT_ZERO);
mdelay(5);
lcm_util.set_gpio_out(GPIO_DISP_LRSTB_PIN, GPIO_OUT_ONE);
msleep(10);
lcm_id_pin_handle();
push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
// when phone initial , config output high, enable backlight drv chip
lcm_util.set_gpio_out(GPIO_LCD_DRV_EN_PIN, GPIO_OUT_ONE);
LCD_DEBUG("uboot:boe_nt35521_lcm_init\n");
}
//只要是初始化的上电时序,reset脚1 0 1(高低高),vsp和vsn,背光使能。mipi的屏都是一样的。
static void lcm_suspend(void)
{
//Back to MP.P7 baseline , solve LCD display abnormal On the right
// when phone sleep , config output low, disable backlight drv chip
lcm_util.set_gpio_out(GPIO_LCD_DRV_EN_PIN, GPIO_OUT_ZERO);
push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);
//reset low
lcm_util.set_gpio_out(GPIO_DISP_LRSTB_PIN, GPIO_OUT_ZERO);
mdelay(5);
//disable VSP & VSN
lcm_util.set_gpio_out(GPIO_LCD_BIAS_ENP_PIN, GPIO_OUT_ZERO);
lcm_util.set_gpio_out(GPIO_LCD_BIAS_ENN_PIN, GPIO_OUT_ZERO);
mdelay(5);
LCD_DEBUG("kernel:boe_nt35521_lcm_suspend\n");
}
static void lcm_resume(void)
{
//enable VSP & VSN
lcm_util.set_gpio_out(GPIO_LCD_BIAS_ENP_PIN, GPIO_OUT_ONE);
lcm_util.set_gpio_out(GPIO_LCD_BIAS_ENN_PIN, GPIO_OUT_ONE);
msleep(50);
//reset low to high
lcm_util.set_gpio_out(GPIO_DISP_LRSTB_PIN, GPIO_OUT_ONE);
mdelay(5);
lcm_util.set_gpio_out(GPIO_DISP_LRSTB_PIN, GPIO_OUT_ZERO);
mdelay(5);
lcm_util.set_gpio_out(GPIO_DISP_LRSTB_PIN, GPIO_OUT_ONE);
msleep(10);
push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
//Back to MP.P7 baseline , solve LCD display abnormal On the right
//when sleep out, config output high ,enable backlight drv chip
lcm_util.set_gpio_out(GPIO_LCD_DRV_EN_PIN, GPIO_OUT_ONE);
LCD_DEBUG("kernel:boe_nt35521_lcm_resume\n");
}
唤醒和休眠刚好,时序相反,唤醒和初始化的程序是一样的。
static unsigned int lcm_compare_id(void)
{
unsigned int id = 0;
unsigned char buffer[3];
unsigned int array[16];
SET_RESET_PIN(1); //NOTE:should reset LCM firstly
SET_RESET_PIN(0);
MDELAY(10);
SET_RESET_PIN(1);
MDELAY(120);
array[0] = 0x00033700;// read id return two byte,version and id
dsi_set_cmdq(array, 1, 1);
read_reg_v2(0x04, buffer, 3);
id = buffer[1]; //we only need ID
/*The Default Value should be 0x00,0x80,0x00*/
printf("\n\n\n\n[soso]%s, id0 = 0x%08x,id1 = 0x%08x,id2 = 0x%08x\n", __func__, buffer[0],buffer[1],buffer[2]);
return (id == 0x80)?1:0;
}
看数据手册,获取lcm id。
LCM_DRIVER nt35521_hd720_dsi_vdo_boe_lcm_drv =
{
.name = “nt35521_hd720_dsi_vdo_boe”,
.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,
};
给lcm驱动上层提供的接口。