基于msm8916移植lcd流程--LK

come from : https://blog.youkuaiyun.com/m0_37166404/article/details/55510535

本篇先不讲解lcd代码在kernel和lk中的流程,讲解基于msm8916,移植ILI9881C型号的lcd

首先要准备一下东西:屏IC 规格书,初始化代码,硬件原理图 
屏IC 规格书—>获得时序等数据 
初始化代码 —>获得初始化屏幕ic的命令,用于编写屏的.h文件(lk)和.dtsi文件(kernel) 
硬件原理图 —>获得打开背光、reset等有关电源的引脚,在代码中拉高拉低

首先从规格书中可以获得以下一些信息: 
 
得到的信息如下: 
水平脉冲宽度(qcom,mdss-dsi-h-pulse-width,Hsync)为30 
水平后沿值(qcom,mdss-dsi-h-back-porch,HBP)为30 
水平前沿值(qcom,mdss-dsi-h-front-porch,HFP)为38 
面板宽度(qcom,mdss-dsi-panel-width,HAdr)为720 
垂直脉冲宽度(qcom,mdss-dsi-v-pulse-width,Vsync)为6 
垂直后沿值(qcom,mdss-dsi-v-back-porch,VBP)为8 
垂直前沿值(qcom,mdss-dsi-v-front-porch,VFP)为10 
面板高度(qcom,mdss-dsi-panel-height,VAdr)为1280

一、在LK中移植LCD 
1.首先要准备好LCD的.h文件 
因为ILI9881C型号的lcd在高通的推荐供应商列表中,所以可以在高通官网中找到类似的patch,里面有相关的.h代码,仿照来合成需要的.h文件。 
在这个.h文件中,需要修改的地方有如下:

static struct panel_resolution cpt_claa053wd41_3xb_ili9881_720p_video_panel_res = { 
720, 1280, 38, 30, 30, 0, 10, 8, 6, 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;
};

根据屏的信息,把数据填入相应的位置。(上面结构体是改好的)

static const uint32_t cpt_claa053wd41_3xb_ili9881_720p_video_timings[] = { 
0x80, 0x20, 0x11, 0x00, 0x3C, 0x38, 0x1A, 0x20, 0x13, 0x03, 0x04, 0x00 
}; 
指定面板 PHY 定时设置的长度为 12 的数组。这组数据一般是根据计算得到,在这里我使用的是以前项目使用的数据。

static struct panel_timing cpt_claa053wd41_3xb_ili9881_720p_video_timing_info = { 
0, 4, 0x04, 0x1b 
}; 
0x04是指qcom,mdss-dsi-t-clk-post,指定模式切换后的字节时钟周期。 
0x1b是指 qcom,mdss-dsi-t-clk-pre,指定模式切换前的字节时钟周期。 
这两个数据都是沿用上一个项目的数据。

static struct panel_reset_sequence cpt_claa053wd41_3xb_ili9881_720p_video_reset_seq = { 
{1, 0, 1, }, {50, 20, 50, }, 2 
}; 
对应的结构体如下:

typedef struct panel_reset_sequence {
    //引脚的状态,数据对应的含义分别为,拉低,拉高,拉低
    uint8_t pin_state[TOTAL_RESET_GPIO_CTRL]; 
    //拉高、拉低的状态持续的时间,分别为50、20和50毫秒
    uint32_t sleep[TOTAL_RESET_GPIO_CTRL];
    //pin脚的两个方向
    uint8_t pin_direction;
};

看产品规格书可以获得此数据: 
 

只要符合图片的值就可以了

static struct backlight cpt_claa053wd41_3xb_ili9881_720p_video_backlight = { 
1, 1, 255, 100, 2, “BL_PWM” 
}; 
对应的结构体如下:

typedef struct backlight {
    uint16_t bl_interface_type;
    uint16_t bl_min_level;
    uint16_t bl_max_level;  //背光的最大值为255
    uint16_t bl_step;
    uint16_t bl_pmic_controltype;
    char     *bl_pmic_model; //背光的模式为PWM模式
};

最麻烦的是,利用厂家的初始化代码合成.h文件的以下结构体(一般厂商会直接给合成后的,这次没有): 
首先看一下厂家给的初始化代码:

    Generic_Long_Write_3P(0xFF,0x98,0x81,0x03);
    Generic_Short_Write_1P(0x01,0x00);
    Generic_Short_Write_1P(0x02,0x00);
    ...
    Generic_Short_Write_1P(0x35,0x00);
    Generic_Short_Write_NP(0x11);
    Delay(120);
    Generic_Short_Write_NP(0x29);  // Display On
    Delay(20);

根据下载的patch中的例子,可以模仿有:

static char cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd0[] = {
    0x04, 0x00, 0x39, 0xC0, //0x04, 0x00--有效字节为四个,0x39--表示写,0xC0--ECC校验
    0xFF, 0x98, 0x81, 0x03, //0xFF, 0x98,0x81, 0x03--有效数据
};
static char cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd1[] = {
    0x02, 0x00, 0x39, 0xC0,//0x02, 0x00--两个有效字节
    0x01, 0x00, 0xFF, 0xFF,//0x01, 0x00--有效数据 0xFF, 0xFF--crc校验
};
...
    static char cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd192[] = {
    0x11, 0x00, 0x05, 0x80 //最后两个命令有点不一样,0x11--有效数据
};
    static char cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd193[] = {
    0x29, 0x00, 0x05, 0x80 //0x29
};
    static struct mipi_dsi_cmd cpt_claa053wd41_3xb_ili9881_720p_video_on_command[] = {
    {0x8, cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd0, 0x00},
    {0x8, cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd1, 0x00},
    ...
    {0x4, cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd192, 0x78},//0x78为延迟时间,十进制为120
    {0x4, cpt_claa053wd41_3xb_ili9881_720p_video_on_cmd193, 0x00}
};
    #define CPT_CLAA053WD41_3XB_ILI9881_720P_VIDEO_ON_COMMAND 194

mipi_dsi_cmd对应的结构体如下:

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

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

2.接下来的步骤是使得lk代码可以调用这个.h文件 
在display.h中的枚举类型中,添加这个屏

enum {
    JDI_1080P_VIDEO_PANEL,
    ...
    XXX_PANEL,
    UNKNOWN_PANEL
};

在bootable/bootloader/lk/target/msm8916/oem_panel.c中 
首先,添加头文件#include “include/xxx.h” —>上一步的头文件 
接着在屏列表信息中添加新屏:

static struct panel_list supp_panels[] = {
    {"jdi_1080p_video", JDI_1080P_VIDEO_PANEL},
    ...
    {"xxx_video", XXX_PANEL},
};
//屏列表结构体
struct panel_list {
    char name[MAX_PANEL_ID_LEN];
    uint32_t id;
};
1
2
3
4
5
6
7
8
9
10
在进入oem_panel_select函数中,事先要知道hw_id是什么,switch后进入相应的分支,进行如下赋值: 
panel_id = XXX_PANEL;

在init_panel_data函数中,利用switch (panel_id),找到相应的地方,给panelstruct结构体赋值

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

//赋值的代码,
    case XXX_PANEL:
        panelstruct->paneldata    = &XXX_video_panel_data;
        panelstruct->panelres     = &XXX_video_panel_res;
        panelstruct->color        = &XXX_video_color;
        panelstruct->videopanel   = &XXX_video_video_panel;
        panelstruct->commandpanel = &XXX_video_command_panel;
        panelstruct->state        = &XXX_video_state;
        panelstruct->laneconfig   = &XXX_video_lane_config;
        panelstruct->paneltiminginfo
            = &XXX_video_timing_info;
        panelstruct->panelresetseq
                     = &XXX_video_reset_seq;
        panelstruct->backlightinfo = &XXX_video_backlight;
        pinfo->mipi.panel_cmds
            = XXX_video_on_command;
        pinfo->mipi.num_of_panel_cmds
            = XXX_VIDEO_ON_COMMAND;
        memcpy(phy_db->timing,
            XXX_video_timings, TIMING_SIZE);
        break;

至此.h文件的信息就可以被代码使用了

3.根据原理图,在代码某处拉高引脚 


从中可以看出,要拉高的引脚为GPIO_24和GPIO_25,分别为点亮背光和reset引脚 
在bootable\bootloader\lk\target\msm8916\target_display.c中,

int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,
                        struct msm_panel_info *pinfo)
{   
        ...
        //在Display.h中定义为24号引脚
        gpio_tlmm_config(vdd_enable_gpio.pin_id, 0,
            vdd_enable_gpio.pin_direction, vdd_enable_gpio.pin_pull,
            vdd_enable_gpio.pin_strength,
            vdd_enable_gpio.pin_state);
        gpio_set_dir(vdd_enable_gpio.pin_id, 2); //拉高
        //在Display.h中定义为25号引脚
        gpio_tlmm_config(reset_gpio.pin_id, 0,
                reset_gpio.pin_direction, reset_gpio.pin_pull,
                reset_gpio.pin_strength, reset_gpio.pin_state);
        gpio_set_dir(reset_gpio.pin_id, 2);     //拉高
        ...
}

display.h中定义了显示屏相关的引脚,和一些相关的宏以及配置信息 
panel.h中定义了显示屏代码中相关的结构体

4.注意 
有些屏的稳压器tps系列的,需要手动拉高引脚,例如97号引脚 
在新的代码中添加显示屏,一般要在bootable/bootloader/lk/platform/msm8916/中添加和初始化相关i2c的接口,需要改变的文件为(一般可以仿照前后代码写):gpio.c、iomap.h、msm8916-clock.c

5.完成,下篇讲解在kernel中添加显示屏
 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值