mtk lcm驅動流程

lcm驅動流程:
lcm模組驅動,ili9881c_dsi_hd_vdo_dj_sp603_drv

LCM_DRIVER ili9881c_dsi_hd_vdo_dj_sp603_drv =
{
.name = “ili9881c_dsi_hd_vdo_dj_sp603”,
.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,
#if defined(LCM_DSI_CMD_MODE)
.update = lcm_update,
#endif
};

Mt65xx_lcm_list.c 函數中通過lcm_driver_list調用到lcm模組驅動函數。

Disp_lcm.c文件中通過disp_lcm_probe函數來調用lcm_driver_list數組,

Primary_display.c文件中通過primary_display_init函數調用
disp_lcm_probe(lcm_name, LCM_INTERFACE_NOTDEFINED)

在mtkfb.c文件中通過mtkfb_probe函數調用
primary_display_init(mtkfb_find_lcm_driver(), lcd_fps);

通過數據結構platform_driver掛接的到platform總線上

static struct platform_driver mtkfb_driver = {
.driver = {
.name = MTKFB_DRIVER,
#ifdef CONFIG_PM
.pm = &mtkfb_pm_ops,
#endif
.bus = &platform_bus_type,
.probe = mtkfb_probe,
.remove = mtkfb_remove,
.suspend = mtkfb_suspend,
.resume = mtkfb_resume,
.shutdown = mtkfb_shutdown,
.of_match_table = mtkfb_of_ids,
},
};

framebuffer設備驅動程序的核心數據結構是fb_ops;用戶空間就是
通過此結構體,調用其中的函數來對LCD實現控制。

Mtkfb.c中定義並實現了fb_ops類型的mtkfb_ops。

static struct fb_ops mtkfb_ops = {
.owner = THIS_MODULE,
.fb_open = mtkfb_open,
.fb_release = mtkfb_release,
.fb_setcolreg = mtkfb_setcolreg, //批量配置顏色參數
.fb_pan_display = mtkfb_pan_display_proxy, //虛擬屏幕內容顯示
.fb_fillrect = cfb_fillrect, //填充區域顯示
.fb_copyarea = cfb_copyarea, //複製區域顯示
.fb_imageblit = cfb_imageblit, //顯示圖象
.fb_cursor = mtkfb_soft_cursor, //光標顯示
.fb_check_var = mtkfb_check_var, //檢查並配置fb_var_screeninfo參數
.fb_set_par = mtkfb_set_par, //change display mode and set parameter
.fb_ioctl = mtkfb_ioctl, //特定ioctl配置LCD屏幕特性
#ifdef CONFIG_COMPAT
.fb_compat_ioctl = mtkfb_compat_ioctl,
#endif
#if defined(CONFIG_PM_AUTOSLEEP)
.fb_blank = mtkfb_blank,
#endif
};

對結構體的調用關係 在函數中mtkfb_fbinfo_init,info->fbops = &mtkfb_ops;
在mtkfb_probe函數中註冊到系統/* Register to system */r = mtkfb_fbinfo_init(fbi);

probe函數會調用register_framebuffer來向內核註冊一個fb_info結構體。而這個fb_info結構體便是lcd驅動的核心了。它就是應用程序調用open,open函數根據次設備號尋找的fb_info結構體。下面可以總結下probe函數的核心工作了,也是我們寫整個驅動的核心工作:

1、分配fb_info結構體;

2、設置fb_info結構體;

3、register_framebuffer()向內核註冊fb_info結構體;

這樣應用程序在調用open函數時,它會找到我們提交的fb_info結構體。並應用裏邊的設置來完成相應的操作。當然除了open函數,read、write等函數都會調用到我們的fb_info.

驅動具體實現代碼解析

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; //高

if (LCM_DSI_CMD_MODE)

params->dsi.mode = CMD_MODE;

else

params->dsi.mode = SYNC_PULSE_VDO_MODE;

endif

// 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

if defined(BUILD_UBOOT)

/*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]);

endif

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驅動上層提供的接口。

http://blog.csdn.net/good123_2014/article/details/52416358
http://blog.csdn.net/loongembedded/article/details/46929173
http://blog.csdn.net/ojiuyue1234567890/article/details/52964072

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章