LCD移植

基于msm8909移植lcd流程

  • 模块功能描述
  • LCD移植
  • lk部分
  • kernel部分

模块功能描述

LCD模块功能主要是LCD液晶显示

LCD移植

以helitech ili9881d为例,首先需要准备东西如下:
1、屏IC Data Sheet
2、初始化代码 —>获得初始化屏幕ic的命令,用于编写屏的.h文件(lk)和.dtsi文件(kernel)
首先从Data Sheet或者初始化代码中可以获得以下一些信息:
1、水平脉冲宽度(qcom,mdss-dsi-h-pulse-width,Hsync)为68
2、水平后沿值(qcom,mdss-dsi-h-back-porch,HBP)为120
3、水平前沿值(qcom,mdss-dsi-h-front-porch,HFP)为88
4、垂直脉冲宽度(qcom,mdss-dsi-v-pulse-width,Vsync)为8
5、垂直后沿值(qcom,mdss-dsi-v-back-porch,VBP)为24
6、垂直前沿值(qcom,mdss-dsi-v-front-porch,VFP)为16
7、面板高度(qcom,mdss-dsi-panel-height,VAdr)为1280
8、面板宽度(qcom,mdss-dsi-panel-width,HAdr)为720

lk部分

首先准备好LCD的.h(命名规则panel_ic_vendor_platform_res_mod)
因为ILI9881D型号的LCD在高通的推荐供应商列表中,所以可以在高通官网中找到类似的patch,里面有相关的.h代码,仿照来合成需要的.h文件。
在这个.h文件中,需要修改的地方有如下:

static struct panel_resolution ili9881d_hlt_a8_720p_video_panel_res = {
  720, 1280, 88, 120, 68, 0, 16, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

这个结构体包含了显示屏的许多参数,在panel.h中可以找到其结构体如下:

typedef struct panel_resolution{
    uint16_t panel_width;
    uint16_t panel_height;
    uint16_t hfront_porch;
    uint16_t hback_porch;
    uint16_t hpulse_width;
    uint16_t hsync_skew;
    uint16_t vfront_porch;
    uint16_t vback_porch;
    uint16_t vpulse_width;
    uint16_t hleft_border;
    uint16_t hright_border;
    uint16_t vtop_border;
    uint16_t vbottom_border;
    uint16_t hactive_res;
    uint16_t vactive_res;
    uint16_t invert_data_polarity;
    uint16_t invert_vsync_polarity;
    uint16_t invert_hsync_polarity;
};

根据屏的信息,把数据填入相应的位置。

const uint32_t ili9881d_hlt_a8_720p_video_timings[] = {
0x86, 0x1E, 0x14, 0x00, 0x42, 0x46, 0x18, 0x20, 0x16, 0x03, 0x04, 0x00
};

指定面板 PHY 定时设置的长度为 12 的数组。这组数据一般是根据计算得到.

static struct panel_timing ili9881d_hlt_a8_720p_video_timing_info = {
  0, 4, 0x04, 0x1B
};

0x04是指qcom,mdss-dsi-t-clk-post,指定模式切换后的字节时钟周期。
0x1B是指 qcom,mdss-dsi-t-clk-pre,指定模式切换前的字节时钟周期。
上面两组数据通过DSI_Timing_Parameters.xlsm计算得来,方法如下:
LCD移植_第1张图片将从规格书中获得信息依次填入上表,然后ctrl+j;ctrl+k;得到
DSI PHY registers和DSI Registers,如下图
`LCD移植_第2张图片

Static struct panel_reset_sequence ili9881d_hlt_a8_720p_video_panel_reset_seq  =  {
{ 1, 0, 1, }, { 20, 20, 20, }, 2
};

对应的结构体如下:

typedef struct panel_reset_sequence {
    //引脚的状态,数据对应的含义分别为,拉低,拉高,拉低
    uint8_t pin_state[TOTAL_RESET_GPIO_CTRL]; 
    //拉高、拉低的状态持续的时间,分别为20、20和20毫秒
    uint32_t sleep[TOTAL_RESET_GPIO_CTRL];
    //pin脚的两个方向
    uint8_t pin_direction;
};
static struct backlight ili9881d_hlt_a8_720p_video_backlight = {
  2, 1, 4095, 100, 1, "PMIC_8909"
};
对应的结构体如下:
typedef struct backlight {
    uint16_t bl_interface_type;
    uint16_t bl_min_level;
    uint16_t bl_max_level;  //背光的最大值为4096
    uint16_t bl_step;
    uint16_t bl_pmic_controltype;
char     *bl_pmic_model; //背光的模式
};

看一下厂家给的初始化代码:

REGISTER,FF,03,98,81,03
REGISTER,02,01,00
REGISTER,03,01,56
REGISTER,04,01,13
REGISTER,05,01,00
………
REGISTER,FF,03,98,91,00
REGISTER,35
REGISTER,11
Delayms(120);
REGISTER,29
Delayms(10);

参考已有的LCD屏幕,可以模仿有:
LCD移植_第3张图片
厂家提供的初始化代码中没有点亮背光的代码,自己Data Sheet中找到ILI9881d的背光控制为0x51和0x53;
LCD移植_第4张图片
LCD移植_第5张图片
mipi_dsi_cmd对应的结构体如下:

struct mipi_dsi_cmd {
    int size;    //大小
    char *payload; //命令
    int wait;  //等待时间
    uint8_t cmds_post_tg;
};

从中可以看出,每一条命令写入一个ili9881d_hlt_a8_720p_video_on_command[]中,最后在汇总到
static struct mipi_dsi_cmd结构体中。
至此,.h文件完成了。

接下来的步骤是使得lk代码可以调用这个.h文件
1、在msm_panel.h中,添加这个屏的LCM_ID

2、在bootloader/lk/platform/msm_shared/mipi_dsi.c 中的mdss_dsi_panel_initialize函数中可以通get_panel_rdid来获取屏幕的LCMID,给panel_ic_id赋值;

3、在bootable/bootloader/lk/target/msm8909/oem_panel.c中
首先,添加lcd头文件#include “include/xxx.h” —>上一步的头文件
接着在init_panel_data函数中,利用switch (panel_ic_id),找到相应的地方,给panelstruct结构体赋值
LCD移植_第6张图片
//panelstruct结构体

typedef struct panel_struct{
    struct panel_config         *paneldata;
    struct panel_resolution     *panelres;
    struct color_info           *color;
    struct videopanel_info      *videopanel;
    struct commandpanel_info    *commandpanel;
    struct command_state        *state;
    struct lane_configuration   *laneconfig;
    struct panel_timing         *paneltiminginfo;
    struct panel_reset_sequence *panelresetseq;
    struct backlight            *backlightinfo;
    struct fb_compression       fbcinfo;
};

至此lk中的移植就完成了.

kernel部分

在Kernel中移植lcd ,流程大致和在lk中移植lcd差不多
首先要写好.dts文件
创建arch/arm/boot/dts/qcom/dsi-panel-xxx-video.dtsi文件
文件就一个节点,&mdss_mdp,这其中有显示屏的节点dsi_xxx,其中很多节点的数值都在LK中有提及

&mdss_mdp {
dsi_ili9881d_hlt_a8_hd_vid: qcom,mdss_dsi_ili9881d_hlt_a8_hd_video 
(LK添加的显示屏的节点名称(panel_config->panel_node_id)一样)
{
		//qcom,mdss-dsi-panel-name = " ic vendor platform res mod dsi panel ";
		qcom,mdss-dsi-panel-name = "ili9881d hlt a8 hd video mode dsi panel";
		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
		qcom,mdss-dsi-panel-type = "dsi_video_mode";
		qcom,mdss-dsi-panel-destination = "display_1";
		qcom,mdss-dsi-panel-framerate = <60>;
		qcom,mdss-dsi-virtual-channel-id = <0>;
		qcom,mdss-dsi-stream = <0>;
		qcom,mdss-dsi-panel-width = <720>;//面板宽度
		qcom,mdss-dsi-panel-height = <1280>;//面板高度
		qcom,mdss-dsi-h-front-porch = <88>;//水平前沿值
		qcom,mdss-dsi-h-back-porch = <120>;//水平后沿值
		qcom,mdss-dsi-h-pulse-width = <68>;//水平脉冲宽度
		qcom,mdss-dsi-h-sync-skew = <0>;
		qcom,mdss-dsi-v-back-porch = <24>;//垂直后沿值
		qcom,mdss-dsi-v-front-porch = <16>;//垂直前沿值
		qcom,mdss-dsi-v-pulse-width = <8>;//垂直脉冲宽度
		qcom,mdss-dsi-h-left-border = <0>;
		qcom,mdss-dsi-h-right-border = <0>;
		qcom,mdss-dsi-v-top-border = <0>;
		qcom,mdss-dsi-v-bottom-border = <0>;
		qcom,mdss-dsi-bpp = <24>;
		qcom,mdss-dsi-color-order = <0>;
		qcom,mdss-dsi-underflow-color = <0xff>;
		qcom,mdss-dsi-border-color = <0>;
		qcom,ulps-enabled;
  		//厂商初始化改为以下属性,每一行一条命令
		//39--写,格式,04--写的字节,命令
		qcom,mdss-dsi-on-command = 
			[
			39 01 00 00 00 00 04 FF 98 81 03
			39 01 00 00 00 00 02 02 00
			39 01 00 00 00 00 02 03 56
			39 01 00 00 00 00 02 04 13
			.....	
			39 01 00 00 00 00 03 51 0F FF 
			39 01 00 00 00 00 02 53 24 
			39 01 00 00 00 00 02 35 00
			05 01 00 00 80 00 02 11 00      
			05 01 00 00 20 00 02 29 00
		];
		qcom,mdss-dsi-off-command = [			
					05 01 00 00 32 00 02 28 00
					05 01 00 00 78 00 02 10 00
					];
		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
		qcom,mdss-dsi-h-sync-pulse = <0>;
		qcom,mdss-dsi-traffic-mode = "burst_mode";
		qcom,mdss-dsi-lane-map ="lane_map_0123";
		qcom,mdss-dsi-bllp-eof-power-mode;
		qcom,mdss-dsi-bllp-power-mode;
		qcom,mdss-dsi-lane-0-state;
		qcom,mdss-dsi-lane-1-state;
		qcom,mdss-dsi-lane-2-state;
		qcom,mdss-dsi-lane-3-state;
 		//指定面板 PHY 定时设置的长度为 12 的数组,跟lk一样
		qcom,mdss-dsi-panel-timings =[86 1E 14 00 42 46 18 20 16 03 04 00]; 
		//指定模式切换后的字节时钟周期,跟lk一样
		qcom,mdss-dsi-t-clk-post = <0x04>;//1f>;
		//指定模式切换前的字节时钟周期,跟lk一样
		qcom,mdss-dsi-t-clk-pre = <0x1b>;//x2d>;		
		qcom,mdss-dsi-bl-min-level = <20>;
		//背光最大电流,4095
		qcom,mdss-dsi-bl-max-level = <4095>;
		qcom,mdss-dsi-dma-trigger = "trigger_sw";
		qcom,mdss-dsi-mdp-trigger = "none";
		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
		//屏幕的上电时序,1代表拉高,0代表拉低,20代表20ms时间
		qcom,mdss-dsi-reset-sequence = <1 20>,<0 2>, <1 20>;
		qcom,mdss-dsi-lp11-init;		
		qcom,cont-splash-enabled;
		qcom,mdss-dsi-hbp-power-mode;
		qcom,mdss-dsi-panel-status-check-mode = "bta_check";
	};
};

在对应的msm89-qrd-skue.dtsi加上dsi-panel-xxx-video.dtsi,以在A8添加ILI9881d为例,则在msm8909-qrd-skue.dtsi中添加
dsi-panel-ili9881d-holitech-a8-hd-video.dtsi;

你可能感兴趣的:(Android)