LCD的MIPI命令格式
在litter kernel中和kernel中的MIPI命令格式稍有不同。
1、LK短包格式
寄存器地址 | 寄存器值 | 参数个数 | 结束标志(固定) |
---|---|---|---|
0x11 | 0x00 | 0x05 | 0x80 |
2、LK长包格式
数据个数(2个) | 补位 | 表示可以多个参数 | 标志(固定) |
---|---|---|---|
0x02 | 0x00 | 0x39 | 0xC0 |
寄存器地址 | 寄存器值 | 补齐 | 补齐 |
0x36 | 0x08 | 0xFF | 0xFF |
长包和短包的数据个数都为4的倍数。
3、kernel短包
表示0个参数 | 固定 | 固定 | 固定 | 延时(ms) | 延时(ms) | 数据长度 | 地址 | 无参数补零 |
---|---|---|---|---|---|---|---|---|
0x05 | 0x01 | 0x00 | 0x00 | 0x11 | 0x00 | 0x02 | 0x11 | 0x00 |
4、kernel长包
可多个参数 | 固定 | 固定 | 固定 | 延时(ms) | 延时(ms) | 数据长度 | 地址 | 参数值 |
---|---|---|---|---|---|---|---|---|
0x39 | 0x01 | 0x00 | 0x00 | 0x11 | 0x00 | 0x02 | 0x36 | 0x08 |
代码修改
全志平台的LK和kernel会读取同一份LCD初始化代码,只需要在
/loong/chips/msm8916/devices/c10/config.dtsi b/loong/chips/msm8916/devices/c10/config.dtsi
/loong/chips/msm8916/devices/c10/panel-video.dtsi b/loong/chips/msm8916/devices/c10/panel-video.dtsi中
添加对应的LCD配置参数即可。
LK运行时会有一个选屏过程在文件
/bootable/bootloader/lk/target/msm8916/oem_panel.c b/bootable/bootloader/lk/target/msm8916/oem_panel.c
void oem_panel_adaptive(void *fdt)
{
...
switch(auto_pan_loop)
{
case 0:
//NH2
gpio_val3=0; //4个gpio用于选择屏幕
gpio_val2=0;
gpio_val1=1;
gpio_val0=1;
break;
case 1:
//帝晶
gpio_val3=0;
gpio_val2=0;
gpio_val1=1;
gpio_val0=0;
break;
case 2:
//普耐
gpio_val3=1;
gpio_val2=0;
gpio_val1=1;
gpio_val0=0;
break;
default:
break;
}
sprintf(pars_name, "qcom,dsi-pref-prim-str-%d%d%d%d", gpio_val3, gpio_val2, gpio_val1, gpio_val0);
sprintf(lcd_selet_gpios, "%d%d%d%d\0", gpio_val3, gpio_val2, gpio_val1, gpio_val0);
dprintf(CRITICAL, "jiyh lcd_selet_gpios = %s ==============================\n", lcd_selet_gpios);
auto_pan_loop++;
}
sprintf(PANEL_DEVICE_PATH, "/soc/qcom,mdss_mdp@1a00000/");
/*find the node name*/
ret = parse_panel_node_name(fdt, pars_name, node_name);
if(!ret)
strcat(PANEL_DEVICE_PATH, node_name);
else
strcat(PANEL_DEVICE_PATH, "mdss_dsi_video");
dprintf(INFO,"pars_name = %s, node_name = %s, PANEL_DEVICE_PATH=%s\n",
pars_name, node_name, PANEL_DEVICE_PATH);
}
此段代码会遍历每种屏幕,并根据gpio值设置屏幕ID值pinfo->mipi.signature
int oem_panel_parse_dt(void *fdt, struct panel_struct *panelstruct,
struct msm_panel_info *pinfo,
struct mdss_dsi_phy_ctrl *phy_db)
{
...
if(strcmp(lcd_selet_gpios,"1110")==0)
pinfo->mipi.signature = 0x9367; //国显
else if(strcmp(lcd_selet_gpios,"0010")==0)
pinfo->mipi.signature = 0x018000;//帝晶
else if(strcmp(lcd_selet_gpios,"1010")==0)
pinfo->mipi.signature = 0x6820;//普耐
else if(strcmp(lcd_selet_gpios,"0011")==0)
pinfo->mipi.signature = 0x0011;//NH2
else
pinfo->mipi.signature = 0x0;
...
}
pinfo->mipi.signature会与mipi_dsi.c中通过mipi命令读取的实际屏幕ID比较,匹配则停止遍历进入下一步
/bootable/bootloader/lk/platform/msm_shared/mipi_dsi.c b/bootable/bootloader/lk/platform/msm_shared/mipi_dsi.c
uint32_t mdss_dsi_read_panel_signature(uint32_t panel_signature)
{
int ret = 0;
dprintf(CRITICAL, "%s:jiyh panel_signature %x -----------------------a\n", __func__,panel_signature);
#if (DISPLAY_TYPE_MDSS == 1)
switch(panel_signature)
{
case 0x9367 :
ret = mipi_jd9367_manufacture_ida();//国显
break;
case 0x018000 :
ret = mipi_dj_manufacture_ida();//帝晶
break;
case 0x6820 :
ret = mipi_rm68200_manufacture_ida();//普耐
break;
case 0x0011 :
ret = mipi_nh2_manufacture_ida();//NH2根据实际情况自行添加读取ID函数
break;
default:
break;
}
if (ret != panel_signature)
ret = panel_signature;
else
ret=0;
dprintf(CRITICAL, "%s:jiyh ret = %x-------------------b\n", __func__, ret);
exit_read_signature:
/* Keep the non detectable panel at the end and set panel signature 0xFFFF */
if (panel_signature == 0xFFFF)
ret = 0;
#endif
return ret;
}
屏幕ID匹配成功后,会根据oem_panel.c中选择的gpio组合匹配loong/chips/msm8916/devices/c10/config.dtsi文件中的设置
...
&dsi_video_tv080wxm_nh2 { //显示屏背光设置
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
qcom,mdss-dsi-bl-pmic-bank-select = <0>;
qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>;
qcom,cont-splash-enabled;
};
//注意:这个节点为了兼容多屏适配,必须按照下面的规则配置 否则出错
//0: 多屏的时候一定要加上这一项标示 qcom,dsi-multi-pan-support;
//1: 必须保留 qcom,dsi-pref-prim-pan = <&dsi_video_boe>; 这一项为作为默认项。
//2: qcom,platform-selectlcd-gpio-0 / 1 / 2 /3 这几个io作为选屏io, 他的值对应 qcom,dsi-pref-prim-pan-0000 和 qcom,dsi-pref-prim-str-0000
// gpio-0 对应 -xxxx的 最后一位 , gpio-1 对应倒数第二位 ,其他类推
//3: pan-xxxx 和 str-xxxx 必须是对应的关系的节点名和别名{panel-video.dtsi中定义},整个字符串最长128字符。
//4: qcom,dsi-pref-prim-pan-xxxx 对应的节点 在这个文件中 还有定义,修改的时候 必须一起修改
//GPIO50、GPIO51不做选屏电阻
&mdss_dsi0 {
qcom,dsi-pref-prim-pan = <&dsi_video_nt35521_c8>;
pinctrl-names = "mdss_default", "mdss_sleep";
pinctrl-0 = <&mdss_dsi_active>;
pinctrl-1 = <&mdss_dsi_suspend>;
qcom,regulator-ldo-mode;
qcom,platform-regulator-settings = [00 01 01 00 20 07 00];
qcom,platform-enable-gpio = <&msm_gpio 97 0>;
qcom,platform-reset-gpio = <&msm_gpio 25 0>;
//qcom,platform-bklight-en-gpio = <&msm_gpio 24 0>;
qcom,platform-vmipi-en-gpio = <&msm_gpio 24 0>;
qcom,dsi-multi-pan-support;
//NH2
qcom,dsi-pref-prim-pan-0011 = <&dsi_video_tv080wxm_nh2>; //pan_0011对应oem_panel.c中gpio值,dsi_video_tv080wxm_nh2
//对应panel-video.dtsi添加的LCD配置设备树节点
qcom,dsi-pref-prim-str-0011 = "qcom,mdss_dsi_tv080wxm_nh2_800p_video";
};
有关屏配置位于/loong/chips/msm8916/devices/c10/panel-video.dtsi,添加针对该屏的设备树节点
dsi_video_tv080wxm_nh2: qcom,mdss_dsi_tv080wxm_nh2_800p_video{ //dsi_video_tv080wxm_nh2节点名称,在dts中可通过&节点名引用和修改
qcom,mdss-dsi-panel-name = "qcom,mdss_dsi_tv080wxm_nh2_800p_video"; //节点字段名称,驱动中通过该名获取所需节点
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-with-enable-gpio = <1>;
qcom,mdss-dsi-panel-framerate = <60>; //帧率
qcom,mdss-dsi-virtual-channel-id = <0>;
qcom,mdss-dsi-stream = <0>;
qcom,mdss-dsi-panel-width = <800>; //分辨率
qcom,mdss-dsi-panel-height = <1280>; //分辨率
qcom,mdss-dsi-h-front-porch = <16>;
qcom,mdss-dsi-h-back-porch = <48>;
qcom,mdss-dsi-h-pulse-width = <16>;
qcom,mdss-dsi-h-sync-skew = <0>;
qcom,mdss-dsi-v-front-porch = <8>;
qcom,mdss-dsi-v-back-porch = <4>;
qcom,mdss-dsi-v-pulse-width = <4>;
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-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
qcom,mdss-dsi-pixel-packing = "tight";
qcom,mdss-dsi-on-command = [ //初始化屏幕的mipi指令
15 01 00 00 64 00 02 E0 00
15 01 00 00 00 00 02 E1 93
15 01 00 00 00 00 02 E2 65
...
];
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"; //启动屏幕时mipi工作模式low power,参考规格书
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <1>;
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; //4数据通道的mipi
qcom,mdss-dsi-panel-timings = [D5 32 22 00 60 64 26 34 29 03 04 00]; //设置时钟频率
qcom,mdss-dsi-t-clk-post = <0x04>;
qcom,mdss-dsi-t-clk-pre = <0x1A>;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <255>;
qcom,mdss-dsi-dma-trigger = "trigger_sw";
qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-reset-sequence = <1 10>, <0 20>, <1 30>; //上电复位时序(ms)
qcom,mdss-pan-physical-width-dimension = <136>;
qcom,mdss-pan-physical-height-dimension = <217>;
};
修改平台的lcd_vdd电压
画板的时候lcd_vdd是由电源管理的ldo17供电,所以需要修改ldo17供电电压,全志平台的dts文件在loogn目录下
/loong/chips/msm8916/devices/default/dts/msm/msm8916-mdss.dtsi
mdss_dsi0: qcom,mdss_dsi@1a98000 {
...
qcom,panel-supply-entries {
#address-cells = <1>;
#size-cells = <0>;
qcom,panel-supply-entry@0 {
reg = <0>;
qcom,supply-name = "vdd"; //修改vdd对应的电压为3.3V
qcom,supply-min-voltage = <3300000>;
qcom,supply-max-voltage = <3300000>;
qcom,supply-enable-load = <100000>;
qcom,supply-disable-load = <100>;
};
qcom,panel-supply-entry@1 {
reg = <1>;
qcom,supply-name = "vddio";
qcom,supply-min-voltage = <1800000>;
qcom,supply-max-voltage = <1800000>;
qcom,supply-enable-load = <100000>;
qcom,supply-disable-load = <100>;
};
};
};
由于vdd的电压是由ldo17引出的,所以还需要修改/loong/chips/msm8916/devices/default/dts/msm/msm8916-regulator.dtsi
/* RPM controlled regulators */
&rpm_bus {
...
rpm-regulator-ldoa17 {
status = "okay";
pm8916_l17: regulator-l17 {
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
qcom,init-voltage = <3300000>;
status = "okay";
};
};
};