参考
- st7703_hd720_dsi_vdo驱动
- MTK驱动-----添加lcm液晶驱动
- 在mt6735平台下驱动LCD显示屏步骤
- 各种屏幕分辨率
- 基于MTK平台LCM的移植
- mtk-lk display代码分析
Kernel驱动加载流程
- mtkfb驱动
mtkfb驱动通过数据结构platform_driver挂接的到platform总线上。
2890 static struct platform_driver mtkfb_driver = {
2891 .probe = mtkfb_probe,
2892 .remove = mtkfb_remove,
2893 .suspend = mtkfb_suspend,
2894 .resume = mtkfb_resume,
2895 .shutdown = mtkfb_shutdown,
2896
2897 .driver = {
2898 .name = MTKFB_DRIVER,
2899 #ifdef CONFIG_PM
2900 .pm = &mtkfb_pm_ops,
2901 #endif
2902 .bus = &platform_bus_type,
2903 .of_match_table = mtkfb_of_ids,
2904 },
2905 };
-
mtkfb_probe(xxx) drivers/misc/mediatek/video/mt6765/videox/mtkfb.c
- primary_display_init(xxx) drivers/misc/mediatek/video/mt6765/videox/primary_display.c
- disp_lcm_probe(xxx) drivers/misc/mediatek/video/mt6765/videox/disp_lcm.c
- lcm_drv = lcm_driver_list[i];加载st7703_hd720_dsi_vdo_lcm_drv模组 drivers/misc/mediatek/lcm/mt65xx_lcm_list.c
- disp_lcm_probe(xxx) drivers/misc/mediatek/video/mt6765/videox/disp_lcm.c
- primary_display_init(xxx) drivers/misc/mediatek/video/mt6765/videox/primary_display.c
-
lcm驱动模组
struct LCM_DRIVER st7703_hd720_dsi_vdo_lcm_drv ={
.name = "st7703_hd720_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,
};
primary_display_init其实和lk是一样的,但是如果lk初始化过LCD,kernel就不会重复再初始化,根据flag is_lcm_inited判定。
primary_display_init:
3965 if (is_lcm_inited) {
3966 /* ??? why need */
3967 /* no need lcm power on,because lk power on lcm */
3968 /* ret = disp_lcm_init(pgc->plcm, 0); */
3969 } else {
3970 /* lcm not inited:
3971 * 1. fpga no lk(verify done);
3972 * 2. evb no lk(need verify)
3973 */
3974 if (use_cmdq) {
3975 /* make sure dsi configuration done before lcm init */
3976 _cmdq_flush_config_handle(1, NULL, 0);
3977 _cmdq_reset_config_handle();
3978 }
3979
3980 ret = disp_lcm_init(pgc->plcm, 1);
3981 }
- kernel阶段打印
[ 27.615827] <1>.(0)[271:kworker/0:2][name:ddp_drv&]disp driver(1) disp_probe end
[ 27.615836] <1>.(0)[271:kworker/0:2][name:ddp_drv&]disp driver(1) disp_probe_1 begin
[ 27.627919] <1>.(0)[271:kworker/0:2][name:ddp_drv&]disp driver(1) disp_probe_1 end
[ 27.627949] <1>.(0)[271:kworker/0:2][name:bootprof&][name:bootprof&]BOOTPROF: 27627.944603:probe: probe=platform_drv_probe drv=DISPSYS(dispsys_of_driver) 21.845615ms
[ 27.629197] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb]isvideofb_parse_done = 0
[ 27.629229] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb] islcmfound = 1
[ 27.629243] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb] is_lcm_inited = 1
[ 27.629258] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb] fps = 5750
[ 27.629273] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb] fb_base = 0x7f0e0000
[ 27.629288] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb] vram = 0xe20000 (14811136)
[ 27.629303] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb] lcmname = st7703_hd720_dsi_vdo_drv
[ 27.629753] <1>.(0)[271:kworker/0:2][name:ddp_m4u&]disphal_allocate_fb, pa_start=0x0x000000007f0e0000, pa_end=0x0x000000007fefffff, va=0xffffff800e000000
[ 27.632537] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb]isvideofb_parse_done = 1
[ 27.632571] <1>.(0)[271:kworker/0:2][DISP]primary_display_init begin lcm=st7703_hd720_dsi_vdo_drv, inited=1
[ 27.632589] <1>.(0)[271:kworker/0:2][name:mmprofile&][name:mmprofile&]MMP: mmprofile_enable(): enable: 1
[ 27.636614] <1>.(0)[271:kworker/0:2][name:mmprofile&][name:mmprofile&]MMP: mmprofile_force_start(): start: 1
[ 27.639191] <1>.(0)[271:kworker/0:2][DISP]plcm_name=st7703_hd720_dsi_vdo_drv is_lcm_inited 1
[ 27.639200] <1>.(0)[271:kworker/0:2][wugn]enter disp_lcm_probe plcm_name = 1907365624
[ 27.639258] <1>.(0)[271:kworker/0:2][name:st7703_hd720_dsi_vdo&][KERNEL/LCM][wugn]enter lcm_get_params
[ 27.639286] <1>.(0)[271:kworker/0:2][DISP][LCM] name: st7703_hd720_dsi_vdo_drv
[ 27.639302] <1>.(0)[271:kworker/0:2][DISP][LCM] resolution: 720 x 1440
[ 27.639318] <1>.(0)[271:kworker/0:2][DISP][LCM] physical size: 74 x 132
[ 27.639333] <1>.(0)[271:kworker/0:2][DISP][LCM] physical size: 74 x 132
[ 27.639348] <1>.(0)[271:kworker/0:2][DISP][LCM] interface: unknown
[ 27.639363] <1>.(0)[271:kworker/0:2][DISP][LCM] Type: DSI
[ 27.639379] <1>.(0)[271:kworker/0:2][DISP][LCM] DSI Mode: SYNC_PULSE_VDO_MODE
[ 27.639394] <1>.(0)[271:kworker/0:2][DISP][LCM] LANE_NUM: 4
[ 27.639414] <1>.(0)[271:kworker/0:2][DISP][LCM] vact: 4, vbp: 19, vfp: 18, vact_line: 1440, hact: 20, hbp: 20, hfp: 20, hblank: 0
[ 27.639432] <1>.(0)[271:kworker/0:2][DISP][LCM] pll_select: 0, pll_div1: 0, pll_div2: 0, fbk_div: 0,fbk_sel: 0, rg_bir: 0
[ 27.639467] <1>.(0)[271:kworker/0:2][DISP][LCM] rg_bic: 0, rg_bp: 0,PLL_CLOCK: 208, dsi_clock: 0, ssc_range: 0,ssc_disable: 1
[ 27.639466] <1>.(0)[271:kworker/0:2][DISP][LCM]compatibility_for_nvk: 0, cont_clock: 0
[ 27.639484] <1>.(0)[271:kworker/0:2][DISP][LCM] lcm_ext_te_enable: 0, noncont_clock: 0, noncont_clock_period: 0
[ 27.639499] <1>.(0)[271:kworker/0:2][DISP]disp_lcm_probe SUCCESS
[ 27.639507] <1>.(0)[271:kworker/0:2]111111
[ 27.639515] <1>.(0)[271:kworker/0:2][wugn]enter disp_lcm_get_params
[ 27.639526] <1>.(0)[271:kworker/0:2]222222
[ 27.640887] <1>.(0)[271:kworker/0:2][DISP][DT][videolfb]isvideofb_parse_done = 1
[ 27.645103] <1>.(0)[271:kworker/0:2][DISP]dsi0 initializing _dsi_context
[ 27.647424] <1>.(0)[271:kworker/0:2]33333333
[ 27.647446] <1>.(0)[271:kworker/0:2]44444444444444
[ 27.648729] <1>.(0)[271:kworker/0:2]555555555555555555
[ 27.648746] <1>.(0)[271:kworker/0:2][DISP]primary_display_init->dpmgr_path_start
[ 27.649070] <1>.(0)[271:kworker/0:2][name:ddp_gamma&][GAMMA] disp_gamma_write_lut_reg: table [0] not initialized
[ 27.649070] <1>
[ 27.652293] <1>.(0)[271:kworker/0:2]6666666666666
[ 27.652682] <1>.(4)[292:init_decouple_b][name:primary_display&]init_decouple_buffers done
[ 27.662993] <1>.(0)[271:kworker/0:2][name:mtk_sodi&]Power/swap - mtk_idle_disp_is_ready not support anymore!
[ 27.664990] <1>.(0)[271:kworker/0:2][name:cmdq_mdp_common&][CMDQ][Res]resource clock engine:0x400 enable:true
[ 27.665784] <1>.(0)[271:kworker/0:2][DISP]primary_display_init done
[ 27.666049] <1>.(0)[271:kworker/0:2][DISP]MTK_FB_XRES=720, MTKFB_YRES=1440, MTKFB_BPP=32, MTK_FB_PAGES=3, MTKFB_LINE=2944, MTKFB_SIZEV=12718080
[ 27.666067] <1>.(0)[271:kworker/0:2][DISP][FB Driver] fbdev->fb_pa_base = 0x000000000597696f, fbdev->fb_va_base = 0x000000005866925e
[ 27.666154] <1>.(0)[271:kworker/0:2][DISP]mtkfb_check_var,xres=720,yres=1440,x_virt=736,y_virt=4320,xoffset=0,yoffset=0,bits_per_pixel=32)
[ 27.666213] <1>.(0)[271:kworker/0:2][DISP]AEE is not enabled, will disable layer 3
[ 27.998818] <1>.(7)[0:swapper/7][name:rtnetlink&][name:rtnetlink&][mtk_net][rtnl_lock]There is no process hold rtnl lock
[ 28.536888] <0>.(0)[271:kworker/0:2][DISP][DT][videolfb]isvideofb_parse_done = 1
[ 28.544324] <0>.(0)[271:kworker/0:2][DISP][DT][videolfb]isvideofb_parse_done = 1
[ 28.553798] <0>.(0)[271:kworker/0:2][name:ion_drv&][ION]ion_drv_create_heap: create heap: ion_fb_heap
[ 28.563053] <0>.(0)[271:kworker/0:2][DISP][DT][videolfb]isvideofb_parse_done = 1
[ 28.570466] <0>.(0)[271:kworker/0:2][name:mtkfb&]disp driver(2) mtkfb_probe end
LK驱动加载流程
- platform.c流程分析
platform/mt6765/platform.c
void platform_init(void) {
//framebuffer的大小
g_fb_size = mt_disp_get_vram_size();
//framebuffer的起始地址
g_fb_base = mblock_reserve(&g_boot_arg->mblock_info, g_fb_size, 0x10000, 0xa0000000, RANKMAX);
//mtk display系统初始化
mt_disp_init((void *)g_fb_base);
//fb预先填充black
mt_disp_fill_rect(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT, 0x0);
//将fb内容更新到lcm上
mt_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT);
//初始化charge
mtk_charger_init();
//初始化电池
mt65xx_bat_init();
//如果没接电池且是低电量模式,将显示低电量logo,否则正常显示logo
if (kernel_charging_boot() == 1) {
if ((g_boot_mode != LOW_POWER_OFF_CHARGING_BOOT) {
mt_disp_show_low_battery();
}
} else if (g_boot_mode != KERNEL_POWER_OFF_CHARGING_BOOT && g_boot_mode != LOW_POWER_OFF_CHARGING_BOOT) {
//加载logo
mboot_common_load_logo((unsigned long)mt_get_logo_db_addr_pa(), "logo");
//根据启动方式选择加载的logo,填充到fb中
mt_disp_show_boot_logo();
}
//打开背光
mt65xx_backlight_on();
mt_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT);
}
流程如下:
-
thread_create(“bootstrap2”…) kernel/main.c
- bootstrap2(void *arg)
- platform_init();
- mt_disp_init(void *lcdbase) “platform/mt6765/mt_disp_drv.c”
- primary_display_init(char *lcm_name)
- pgc->plcm = disp_lcm_probe(…);“platform/mt6765/primary_display.c初始化pgc->plcm,很重要”
- struct LCM_DRIVER *lcm_drv = NULL;
- lcm_drv = lcm_driver_list[i];
- &st7703_hd720_dsi_vdo_lcm_drv在mk文件中定义了CUSTOM_LK_LCM=“st7703_hd720_dsi_vdo”,选择此驱动
- lcm_drv->get_params(&hlcm_param);
- plcm->lcm_if_id = plcm->params->lcm_if;lcm的接口id,分为DSI0、DSI1
- lcm_drv->init_power()
- lcm_drv->compare_id()
- _dump_lcm_info(plcm);打印LCM信息
- lcm_param = disp_lcm_get_params(pgc->plcm);
- plcm->params; 调用st7703中的lcm_get_params
- disp_lcm_init(pgc->plcm);
- lcm_drv->init调用st7703中的lcm_init
- pgc->plcm = disp_lcm_probe(…);“platform/mt6765/primary_display.c初始化pgc->plcm,很重要”
- primary_display_config_input(&input);
- primary_display_init(char *lcm_name)
- mt_disp_init(void *lcdbase) “platform/mt6765/mt_disp_drv.c”
- platform_init();
- bootstrap2(void *arg)
-
disp_lcm_probe
部分代码详解:
lcm_drv= lcm_driver_list[i]; //驱动选择st7703
lcm_drv->get_params(&hlcm_param); //调用lcm_get_params获取参数
plcm->drv = lcm_drv;
plcm->params = &hlcm_param; //赋值
plcm->lcm_if_id = plcm->params->lcm_if; //lcm的接口id,分为DSI0、DSI1、dual port DSI、DBI0、DPI0、DPI1
if (lcm_drv->init_power) { //实现上电复位初始化的动作,并通过回读0x0A寄存器判断跟lcm之前是否连接OK
lcm_drv->init_power();
}
if (lcm_drv->compare_id != NULL) { //读取display ID
if (lcm_drv->compare_id() != 0) {
isLCMFound = true;
_display_interface_path_deinit(handle);
dprintf(0,"we will use lcm: %s\n", lcm_drv->name);
break;
}
}
- pgc->plcm详解
结构体如下:
24 struct disp_lcm_handle {
25 struct LCM_PARAMS *params;
26 struct LCM_DRIVER *drv;
27 enum LCM_INTERFACE_ID lcm_if_id;
28 int module;
29 int is_inited;
30 unsigned int lcm_original_width;
31 unsigned int lcm_original_height;
32 int index;
33 };
params和drv两个参数很重要,一个是从st7703中获取的显示参数,用lcm_get_params结构获取,同lcm_param,一个是驱动程序。
//LCM_DRIVER,lcm相关的一系列的操作函数
typedef struct {
const char *name; --用于匹配lcm
void (*set_util_funcs) (const LCM_UTIL_FUNCS *util); --设置lcm操作函数,gpio、reset、delay、write/read cmd
void (*get_params) (LCM_PARAMS *params); --获取lcm的参数,接口、分辨率、porch、PLL clock、data format等
void (*init) (void); --lcm初始化,一般为上电复位初始化
void (*suspend) (void); --pm相关
void (*resume) (void);
/* for power-on sequence refinement */
void (*init_power) (void); --上电初始化
void (*suspend_power) (void);
void (*resume_power) (void);
void (*update) (unsigned int x, unsigned int y, unsigned int width, unsigned int height); --设置ram的显示区域(x,y)->(x+width,y+height),只在command mode下使用
unsigned int (*compare_id) (void);
void (*parse_dts)(const LCM_DTS *DTS, unsigned char force_update); --解析设备树
/* /CABC backlight related function */
void (*set_backlight) (unsigned int level); --背光相关函数
void (*set_backlight_cmdq) (void *handle, unsigned int level);
void (*set_pwm) (unsigned int divider);
unsigned int (*get_pwm) (unsigned int divider);
void (*set_backlight_mode) (unsigned int mode);
/* / */
int (*adjust_fps) (void *cmdq, int fps); --调节刷新率,一般刷新率为60Hz
/* ///ESD_RECOVERY// */
unsigned int (*esd_check) (void); --ESD检测相关,开启该功能,系统会周期性检测lcm寄存器状态,状态NG则会reset lcm
unsigned int (*esd_recover) (void);
unsigned int (*check_status) (void);
unsigned int (*ata_check) (unsigned char *buffer);
void (*read_fb) (unsigned char *buffer);
int (*ioctl) (LCM_DRV_IOCTL_CMD cmd, unsigned int data);
/* /// */
void (*enter_idle)(void);
void (*exit_idle)(void);
void (*change_fps)(unsigned int mode);
/* //switch mode */
void *(*switch_mode) (int mode); --用于切换mode,command mode 和video mode切换
void (*set_cmd) (void *handle, int *mode, unsigned int cmd_num);
void (*set_lcm_cmd) (void *handle, unsigned int *lcm_cmd, unsigned int *lcm_count,
unsigned int *lcm_value);
/* /PWM/ */
void (*set_pwm_for_mix) (int enable);
} LCM_DRIVER;
//LCM_PARAMS,lcm参数设置
typedef struct {
LCM_TYPE type; --lcm的接口类型,分为DSI、DBI、DPI
LCM_CTRL ctrl; --lcm寄存器的访问方式,普遍通过MIPI LP下指令,也有的支持spi/i2c等接口访问
LCM_INTERFACE_ID lcm_if; --lcm的接口id,分为DSI0、DSI1、dual port DSI、DBI0、DPI0、DPI1
LCM_INTERFACE_ID lcm_cmd_if; --cmd模式接口,和lcm_if一致
/* common parameters */
unsigned int lcm_x; --(lcm_x,lcm_y)定义显示的起始pixel,(virtual_width,virtual_height)or(width,height)定义显示区域的宽和高
unsigned int lcm_y;
unsigned int width;
unsigned int height;
unsigned int virtual_width;
unsigned int virtual_height;
unsigned int io_select_mode; /* DBI or DPI should select IO mode according to chip spec */
/* particular parameters */
LCM_DBI_PARAMS dbi; --DBI参数
LCM_DPI_PARAMS dpi; --DPI参数
LCM_DSI_PARAMS dsi; --DSI参数
unsigned int physical_width;
unsigned int physical_height;
unsigned int od_table_size;
void *od_table; --光学相关表格,gamma节点
} LCM_PARAMS;
调试准备
- 用dct工具配置dws
工具位置:vendor\mediatek\proprietary\scripts\dct
dws位置:vendor\mediatek\proprietary\bootable\bootloader\preloader\custom\k62v1_64\dct\dct\codegen.dws
配置完相应GPIO后进行驱动代码的移植。
- 添加lcm到lcm_driver_list[]数组中供遍历(kernel和lk阶段)。
(略···)
- MK文件的配置(kernel和lk阶段)。
(略···)
调试lcm
- LCM_setting_table调试
调试指令:
struct LCM_setting_table {
unsigned char cmd; // 命令地址
unsigned char count; // 寄存器值的个数
unsigned char para_list[128]; //寄存器的值
};
- lcm_initialization_setting 设置
供应商提供资料:
SSD_SEND(0x11,0xB9,0xF1,0x12,0x83);
SSD_SEND(0x11,0xBA,0x33,0x81,0x05,0xF9,0x0e,0x0e,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x25,0x00,0x91,0x0a,0x00,0x00,0x02,0x4F,0x11,0x00,0x00,0x37);
SSD_SEND(0x11,0xB8,0x75,0x22,0x20,0x03);
SSD_SEND(0x11,0xB3,0x10,0x10,0x05,0x05,0x03,0xFF,0x00,0x00,0x00,0x00);
SSD_SEND(0x11,0xC0,0x70,0x73,0x50,0x50,0x00,0x00,0x08,0x70,0x00);
SSD_SEND(0x10,0xBC,0x4E);
SSD_SEND(0x10,0xCC,0x0B);
SSD_SEND(0x10,0xB4,0x80);
SSD_SEND(0x11,0xB2,0xF0,0x12,0x30);
SSD_SEND(0x11,0xE3,0x07,0x07,0x0B,0x0B,0x03,0x0B,0x00,0x00,0x00,0x00,0xFF,0x00,0xC0,0x10);
SSD_SEND(0x11,0xC1,0x54,0x00,0x1E,0x1E,0x77,0xF1,0xFF,0xFF,0xCC,0xCC,0x77,0x77);
SSD_SEND(0x11,0xB5,0x07,0x07);
SSD_SEND(0x11,0xB6,0x30,0x30);
SSD_SEND(0x11,0xBF,0x02,0x11,0x00);
SSD_SEND(0x11,0xE9,0X02,0x00,0x10,0x05,0xB6,0x0A,0xA0,0x12,0x31,0x23,0x37,0x13,0x40,0xA0,0x27,0x38,0x0C,0x00,0x03,0x00,0x00,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x75,0x75,0x31,0x88,0x88,0x88,0x88,0x88,0x88,0x13,0x88,0x64,0x64,0x20,0x88,0x88,0x88,0x88,0x88,0x88,0x02,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
SSD_SEND(0x11,0xEA,0x02,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x46,0x02,0x88,0x88,0x88,0x88,0x88,0x88,0x64,0x88,0x13,0x57,0x13,0x88,0x88,0x88,0x88,0x88,0x88,0x75,0x88,0x23,0x10,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0A,0xA0,0x00,0x00,0x00,0x00);
SSD_SEND(0x11,0xE0,0x00,0x07,0x0F,0x30,0x35,0x3C,0x43,0x37,0x06,0x0D,0x0D,0x10,0x11,0x0F,0x12,0x0F,0x14,0x00,0x07,0x0F,0x30,0x35,0x3C,0x43,0x37,0x06,0x0D,0x0D,0x10,0x11,0x0F,0x12,0x0F,0x14);
DCS_Short_Write_NP(0x11);
Delay(600);
DCS_Short_Write_NP(0x29);
Delay(250);
代码修改如下:
static struct LCM_setting_table init_setting[] = {
{REGFLAG_DELAY, 50, {0}},
{0xb9,3,{0xF1,0x12,0x83}},
{0xba,27,{0x33,0x81,0x05,0xF9,0x0E,0x0E,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x25,0x00,0x91,0x0A,0x00,0x00,0x02,0x4F,0x11,0x00,0x00,0x37}},
{0xb8,4,{0x26,0x22,0x20,0x03}},
{0xb3,10,{0x10,0x10,0x05,0x05,0x03,0xFF,0x00,0x00,0x00,0x00}},
{0xc0,9,{0x70,0x73,0x50,0x50,0x00,0x00,0x08,0x70,0x00}},
{0xbc,1,{0x4E}},
{0xcc,2,{0x0B}},
{0xb4,1,{0x80}},
{0xb2,3,{0xF0,0x12,0x30}},
{0xe3,14,{0x07,0x07,0x0B,0x0B,0x03,0x0B,0x00,0x00,0x00,0x00,0xFF,0x80,0xC0,0x10}},
{0xc1,12,{0x54,0x00,0x1E,0x1E,0x77,0xF1,0xFF,0xFF,0xCC,0xCC,0x77,0x77}},
{0xb5,2,{0x07,0x07}},
{0xb6,2,{0x30,0x30}},
{0xbf,3,{0x02,0x11,0x00}},
{0xe9,63,{0x02,0x00,0x10,0x05,0xB6,0x0A,0xA0,0x12,0x31,0x23,0x37,0x13,0x40,0xA0,0x27,0x38,0x0C,0x00,0x03,0x00,0x00,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x75,0x75,0x31,0x88,0x88,0x88,0x88,0x88,0x88,0x13,0x88,0x64,0x64,0x20,0x88,0x88,0x88,0x88,0x88,0x88,0x02,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
{0xea,61,{0x02,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x46,0x02,0x88,0x88,0x88,0x88,0x88,0x88,0x64,0x88,0x13,0x57,0x13,0x88,0x88,0x88,0x88,0x88,0x88,0x75,0x88,0x23,0x10,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0A,0xA0,0x00,0x00,0x00,0x00}},
{0xe0,34,{0x00,0x07,0x0F,0x30,0x35,0x3C,0x43,0x37,0x06,0x0D,0x0D,0x10,0x11,0x0F,0x12,0x0F,0x14,0x00,0x07,0x0F,0x30,0x35,0x3C,0x43,0x37,0x06,0x0D,0x0D,0x10,0x11,0x0F,0x12,0x0F,0x14}},
{0x11,1,{0x00}},
{REGFLAG_DELAY, 600, {0}},
{0x29,1,{0x00}}, // Display On
{REGFLAG_DELAY, 250, {0}},
{REGFLAG_END_OF_TABLE, 0x00, {}}
};
mipi屏的话,MTK平台的是不同的屏只要换这个lcm_initialization_setting初始化设置的代码就可以跑起来的,当然有些屏ic已经有程序,不需要再从初始化里下载这段代码。只要上电时序和配置对了就可以跑起来。
- lcm_sleep_out_setting和lcm_deep_sleep_mode_in_setting设置
开屏和关屏设置。
#if 0
static struct LCM_setting_table lcm_sleep_out_setting和[] = { // Display On
{0x11, 0, {0x00}},
{REGFLAG_DELAY, 120, {}},
{0x29, 0, {0x00}},
{REGFLAG_END_OF_TABLE, 0x00, {}}
};
#endif
static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = { // Display Off
{0x28, 0, {0x00}},
{REGFLAG_DELAY, 50, {}},
/* Sleep Mode On */
{0x10, 0, {0x00}},
{ REGFLAG_DELAY, 120, {} },
{ REGFLAG_END_OF_TABLE, 0x00, {} }
};
- 分辨率设置
#define FRAME_WIDTH (720)
#define FRAME_HEIGHT (1440)
- display ID
LCM_ID_ST7703 (0x3821)
查阅datasheet找到ID信息如下:
只需要读0x04寄存器的两个字节就能确定是st7703这个屏了,读取ID的驱动程序如下:
static unsigned int lcm_compare_id(void)
{
unsigned int id=0;
unsigned char buffer[3];
unsigned int array[16];
...
read_reg_v2(0x04, buffer, 3);
id = buffer[1]|(buffer[0]<<8); //we only need ID
...
if(id == LCM_ID_ST7703)
return 1;
}
LCM_DRIVER st7703_hd720_dsi_vdo_lcm_drv ={
.compare_id = lcm_compare_id,
};
- DSI PLL_CLOCK设置
MIPI DSI接口PLL计算:
总数据量=(VS+VBP+VACT+VFP)(HS+HBP+HACT+HFP) fps * format_bit(format_bit根据一个pixel的数据位来定,大多为24位,RGB888)
每lane的数据量=总数据量/lane数
DSI为差分信号,一个clock内双沿采样,传输2bit数据
则最终PLL速率为每lane数据量/2
params->dsi.PLL_CLOCK = 208;
公式如下:
(VS+VBP+VACT+VFP)*(HS+HBP+HACT+HFP)* fps * format_bit
pll=(4+19+1440+18)*(20+20+720+20)*60*24/(4*2)=1481*780*60*24/8=207,932,400
- 屏幕圆缺角设置
此功能主要是设定4个边角是圆弧形的。
static void lcm_get_params(LCM_PARAMS *params) {
...
#ifdef MTK_ROUND_CORNER_SUPPORT
params->round_corner_params.round_corner_en = 1;
params->round_corner_params.full_content = 0;
params->round_corner_params.w = ROUND_CORNER_W;
params->round_corner_params.h = ROUND_CORNER_H;
params->round_corner_params.lt_addr = left_top;
params->round_corner_params.lb_addr = left_bottom;
params->round_corner_params.rt_addr = right_top;
params->round_corner_params.rb_addr = right_bottom;
#endif
...
}
- display-timming && DSI设置
DSI为4 lane,display-timming供应商提供如下:
/* DSI */
/* Command mode setting */
params->dsi.LANE_NUM = LCM_FOUR_LANE;
/* The following defined the fomat for data coming from LCD engine. */
params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;
params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST;
params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB;
params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888;
/* Highly depends on LCD driver capability. */
/* Not support in MT6573 */
params->dsi.packet_size = 256;
params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888;
params->dsi.vertical_sync_active = 4;
params->dsi.vertical_backporch = 19;
params->dsi.vertical_frontporch = 18;
params->dsi.vertical_active_line = FRAME_HEIGHT;
params->dsi.horizontal_sync_active = 20;
params->dsi.horizontal_backporch = 20;
params->dsi.horizontal_frontporch = 20;
params->dsi.horizontal_active_pixel = FRAME_WIDTH;
params->dsi.PLL_CLOCK = 230; /* this value must be in MTK suggested table */
Lk调试打印
_dump_lcm_info(plcm)
打印如下:
[1865] [DISP]func|disp_lcm_probe
[1869] [DISPCHECK]******** dump lcm driver information ********
[1874] [DISPCHECK][LCM], name: st7703_hd720_dsi_vdo
[1879] [DISPCHECK][LCM] resolution: 720 x 1440
[1883] [DISPCHECK][LCM] physical size: 0 x 0
[1887] [DISPCHECK][LCM] physical size: 0 x 0
[1891] [DISPCHECK][LCM] lcm_if:0, cmd_if:0
[1895] [DISPCHECK][LCM] interface: unknown
[1899] [DISPCHECK][LCM] Type: DSI
[1902] [DISPCHECK][LCM] DSI Mode: SYNC_PULSE_VDO_MODE
[1907] [DISPCHECK][LCM] LANE_NUM: 4,data_format:(0,2,0,0)
[1913] [DISPCHECK][LCM] vact: 4, vbp: 19, vfp: 18, vact_line: 1440, hact: 20, hbp: 20, hfp: 20, hblank: 0, hactive: 720
[1923] [DISPCHECK][LCM] pll_select: 0, pll_div1: 0, pll_div2: 0, fbk_div: 0,fbk_sel: 0, rg_bir: 0
[1932] [DISPCHECK][LCM] rg_bic: 0, rg_bp: 0, PLL_CLOCK: 230, dsi_clock: 0, ssc_range: 0, ssc_disable: 0, compatibility_for_nvk: 0, cont_clock: 0
[1945] [DISPCHECK][LCM] lcm_ext_te_enable: 0, noncont_clock: 0, noncont_clock_period: 0
primary_display_init
打印如下:
[2470] [DISP]func|primary_display_init
[2474] [LK_DDP/ddp_manager]ddp manager init
[2478] [DISPCHECK]disp_lcm_probe SUCCESS
[2481] [DISP]func|disp_lcm_get_params
[2485] [DISP]func|_build_path_direct_link
[2489] [LK_DDP/ddp_manager]scenario primary_disp acquire mutex 0 , left mutex 0xe!
[2496] [LK_DDP/ddp_manager]create handle 0x480b8710 on scenario primary_disp
[2503] [DISPCHECK]dpmgr create path SUCCESS(0x480b8710)
[2508] [LK_DDP/ddp_manager]set dst module on scenario primary_disp, module dsi0
[2515] [LK_DDP/ddp_path]ddp_set_dst_module, scenario=primary_disp, dst_module=dsi0
[2523] [LK_DDP/ddp_path]dsi0 is already on path
[2527] [DISPCHECK]dpmgr set dst module FINISHED(dsi0)
[2532] [LK_DDP/ddp_manager]path set lcm drv handle 0x480b8710
[2538] [LK_DDP/ddp_manager]dsi0 set lcm utils
[2542] [DISPCHECK]primary display is DIRECT LINK MODE
[2547] [DISPCHECK]primary display BUILD cmdq trigger loop finished
[2553] [DISPCHECK]primary display START cmdq trigger loop finished
[2559] [DISP]func|disp_lcm_is_video_mode
[2562] [LK_DDP/ddp_manager]set scenario primary_disp mode Video Mode
[2569] [LK_DDP/ddp_manager]path init on scenario primary_disp
[2574] [LK_DDP/ddp_path]ddp path top clock on
[2578] [LK_DDP/ddp_path]ddp CG0:df87ffff CG1:3ffff
[2583] [LK_DDP/ddp_path]ddp path m4u off
[2587] [LK_DDP/ddp_path]module ovl0 added to mutex 0
[2592] [LK_DDP/ddp_path]module ovl0_2l added to mutex 0
[2597] [LK_DDP/ddp_path]module rdma0 added to mutex 0
[2602] [LK_DDP/ddp_path]module disp_rsz0_virtual0 not added to mutex 0
[2608] [LK_DDP/ddp_path]module disp_rsz0_virtual1 not added to mutex 0
[2614] [LK_DDP/ddp_path]module pwm0 added to mutex 0
[2619] [LK_DDP/ddp_path]module dsi0 added to mutex 0
[2624] [LK_DDP/ddp_path]mutex 0 value=0x90380, sof=dsi0, eof=dsi0
[2630] [LK_DDP/ddp_path]path connect on scenario primary_disp
[2635] [LK_DDP/ddp_path]connect_path: ovl0 to dsi0
[2640] [LK_DDP/ddp_path]connect mout ovl0 to ovl0_2l bits 0x2
[2646] [LK_DDP/ddp_path]connect mout ovl0_2l to rdma0 bits 0x1
[2651] [LK_DDP/ddp_path]connect out_s rdma0 to disp_rsz0_virtual0, value=0
[2658] [LK_DDP/ddp_path]connect out_s disp_rsz0_virtual1 to dsi0, value=0
[2665] [LK_DDP/ddp_path]connect in_s ovl0_2l to rdma0, value=1
[2670] [LK_DDP/ddp_path]connect in_s disp_rsz0_virtual0 to disp_rsz0_virtual1, value=0
[2678] [LK_DDP/ddp_path]connect in_s disp_rsz0_virtual1 to dsi0, value=0
[2685] [DISP]func|ddp_dsi_init
[2688] [DISPCHECK]dsi0 init finished
[2691] [LK_DDP/ddp_manager]path config ovl 0, rdma 0, wdma 0, dst 1 on handle 0x480b8710 scenario primary_disp
[2701] [DISP]func|ddp_dsi_config
[2704] [DISPCHECK][DDPDSI] DSI Mode: SYNC_PULSE_VDO_MODE
[2709] [DISPCHECK][DDPDSI] LANE_NUM: 4,data_format:(0,2,0,0)
[2715] [DISPCHECK][DDPDSI] vact: 4, vbp: 19, vfp: 18, vact_line: 1440, hact: 20, hbp: 20, hfp: 20, hblank: 0
[2724] [DISPCHECK][DDPDSI] pll_select: 0, pll_div1: 0, pll_div2: 0, fbk_div: 0,fbk_sel: 0, rg_bir: 0
[2733] [DISPCHECK][DDPDSI] rg_bic: 0, rg_bp: 0, PLL_CLOCK: 208, dsi_clock: 0, ssc_range: 0, ssc_disable: 1, compatibility_for_nvk: 0, cont_clock: 0
[2746] [DISPCHECK][DDPDSI] lcm_ext_te_enable: 0, noncont_clock: 0, noncont_clock_period: 0
[2755] [DISP]func|DSI_PHY_clk_setting
[2762] [DISP]func|DSI_PS_Control
[2765] [DISPCHECK][DISP] - LK - DSI_PHY_TIMCONFIG, pll=208, Cycle Time = 20(ns), Unit Interval = 3(ns). , lane# = 4
[2776] DISP/[DISP] - LK - DSI_PHY_TIMCONFIG, HS_TRAIL = 4, HS_ZERO = 8, HS_PRPR = 3, LPX = 4, TA_GET = 20, TA_SURE = 6, TA_GO = 16, CLK_TRAIL = 5, CLK_ZERO = 20, CLK_HS_PRPR = 3
[2791] DISP/CLK_HS_POST=36,CLK_HS_EXIT=8,CLK_TRAIL=5
[2796] DSI_PHY_TIMCONFIG, 0x04080304,0x08140610,0x05140100,0x00082403
[2802] [DISP]func|DSI_Config_VDO_Timing
[2806] [DISP]func|disp_lcm_init
[2809] [DISPCHECK]lcm init_power
[2812] [DISPCHECK]lcm init
[2819] [LK/LCM]st7703----tps6132----cmd=b3--i2c write success----
[2827] [LK/LCM]st7703----tps6132----cmd=b4--i2c write success----
[2834] [LK/LCM]st7703----tps6132----cmd=b1--i2c write success----
[3265] [DISP]func|DSI_dcs_read_lcm_reg_v2
[3269] [DISPCHECK]Last DSI Read Why not clear irq???
[3274] [DISPCHECK]DSI_CMDQ_SIZE : 1
[3277] [DISPCHECK]DSI_CMDQ_DATA0 : 0x00291500
[3281] [DISPCHECK]DSI_RX_DATA0 : 0x00000000
[3285] [DISPCHECK]DSI_RX_DATA1 : 0x00000000
[3290] [DISPCHECK]DSI_RX_DATA2 : 0x00000000
[3294] [DISPCHECK]DSI_RX_DATA3 : 0x00000000
[3298] DISP/ Start polling DSI read ready!!!
[3302] DISP/ End polling DSI read ready!!!
[3306] [DISPCHECK]DSI read begin i = 1 --------------------
[3311] [DISPCHECK]DSI_RX_STA : 0x00000740
[3316] [DISPCHECK]DSI_CMDQ_SIZE : 2
[3319] [DISPCHECK]DSI_CMDQ_DATA0 : 0x00013700
[3323] [DISPCHECK]DSI_CMDQ_DATA1 : 0x000a0604
[3327] [DISPCHECK]DSI_RX_DATA0 : 0x0c00011a
[3332] [DISPCHECK]DSI_RX_DATA1 : 0x0051629c
[3336] [DISPCHECK]DSI_RX_DATA2 : 0x00000000
[3340] [DISPCHECK]DSI_RX_DATA3 : 0x00000000
[3344] [DISPCHECK]DSI read end ----------------------------
[3350] [DISPCHECK]DSI read packet_type is 0x1a
[3354] [DISPCHECK]DSI read long packet size: 1
[3358] [DISP]read from lcm 0x0A: 156
[3362] [DISP]lcm is connected
[3364] [DISP]func|disp_lcm_is_video_mode
[3368] [LK_DDP/ddp_manager]map event 7 to irq 0x60004 on scenario primary_disp
[3375] [LK_DDP/ddp_manager]enable event on scenario primary_disp, event 7, irtbit 0x60004
[3383] [LK_DDP/ddp_manager]enable event on scenario primary_disp, event 1, irtbit 0x60004
[3394] [DISP]func|primary_display_config_input
[3398] [LK_DDP/ddp_manager]path check busy on scenario primary_disp
[3404] [DISP]func|ddp_dsi_is_busy
[3407] [LK_DDP/ddp_manager]path config ovl 1, rdma 0, wdma 0, dst 0 on handle 0x480b8710 scenario primary_disp
[3417] [LK_DDP/OVL]module 0, layer=1, en=1, src=0, fmt=16785410, addr=0x7f4eb000, x=0, y=0, pitch=2880, dst(0, 0, 720, 1440),keyEn=0, key=0, aen=1, alpha=255
[3431] [LK_DDP/OVL]ovl0, layer=1, source=memory, off(x=0, y=0), dst(0, 0, 720, 1440),pitch=2880,fmt=eBGRA8888, addr=7f4eb000, keyEn=0, key=0, aen=1, alpha=255
[3445] [DISP]func|ddp_dsi_config
[3448] [DISP]func|primary_display_config_input
[3453] [LK_DDP/ddp_manager]path check busy on scenario primary_disp
[3459] [DISP]func|ddp_dsi_is_busy
[3462] [LK_DDP/ddp_manager]path config ovl 1, rdma 0, wdma 0, dst 0 on handle 0x480b8710 scenario primary_disp
[3472] [LK_DDP/OVL]module 0, layer=0, en=1, src=0, fmt=16785410, addr=0x7f0e0000, x=0, y=0, pitch=2944, dst(0, 0, 720, 1440),keyEn=0, key=0, aen=1, alpha=255
[3486] [LK_DDP/OVL]ovl0, layer=0, source=memory, off(x=0, y=0), dst(0, 0, 720, 1440),pitch=2944,fmt=eBGRA8888, addr=7f0e0000, keyEn=0, key=0, aen=1, alpha=255
[3500] [LK_DDP/OVL]module 0, layer=1, en=1, src=0, fmt=16785410, addr=0x7f4eb000, x=0, y=0, pitch=2880, dst(0, 0, 720, 1440),keyEn=0, key=0, aen=1, alpha=255
[3514] [LK_DDP/OVL]ovl0, layer=1, source=memory, off(x=0, y=0), dst(0, 0, 720, 1440),pitch=2880,fmt=eBGRA8888, addr=7f4eb000, keyEn=0, key=0, aen=1, alpha=255
[3528] [DISP]func|ddp_dsi_config
[3531] [DISP]mt_disp_init() done