高通LCD bring up流程
时间:2023-01-03 10:00:00
高通LCD bring up流程
前言
kernel
添加LCD的dtsi
将屏的dtsi放到平台的dtsi中
电压配置
lk
添加屏的.h文件
Panel configuration
Panel resolution
Panel color information
Panel on/off command information
Panel timing
oem_panel.c
前言
??高通平台LCD的bring up可分为两部分:kernel、lk。点屏前仔细看LCD电路原理图和IC spec,搞清楚LCD亮屏需要满足上电条件和时序要求。同时,寻找FAE获取初始代码。
kernel
??
添加LCD的dtsi
??参考FAE填写分辨率、hfp\hbp\hpw、vfp\vbp\vpw,一般来讲FAE提供初始化代码,hfp\hbp\hpw、vfp\vbp\vpw、spec等信息
??arch/arm64/boot/dts/qcom/dsi-panel-XXX-xxxp-video.dtsi
&mdss_mdp {
dsi_hx8394f_720p_video: qcom,mdss_dsi_hx8394f_720p_video { 保持一致就好
qcom,mdss-dsi-panel-name = "hx8394f 720p video mode dsi panel";//panel name
qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;///保持不变;指定此;panel将映射到的DSI控制器模型
qcom,mdss-dsi-panel-type = "dsi_video_mode";//指定面板操作模式。
//“dsi_video_mode” = 使用视频模式
//“dsi_cmd_mode” = 使用命令模式
qcom,mdss-dsi-panel-destination = "display_1";///指定面板的目标显示,保持不变
qcom,mdss-dsi-panel-framerate = <60>;//指每秒显示60帧,一帧是一个完整的图像(通常是60帧)
qcom,mdss-dsi-virtual-channel-id = <0>; ///指定虚拟频道标识符,默认为0;保持不变
qcom,mdss-dsi-stream = <0>;//指定要数据包流:0 = 流 (默认值);1. = 流 1。保持不变
qcom,mdss-dsi-panel-width = <720>;//分辨率-w
qcom,mdss-dsi-panel-height = <1440>;//分辨率-h
qcom,mdss-dsi-h-front-porch = <60>;//hfp-一行的有效数据结束到下一级同步信号开始之间VCLK对应驱动中的个数right_margin;
qcom,mdss-dsi-h-back-porch = <60>;//hbp-从水平同步信号到一行有效数据之间的表示VCLK对应驱动中的个数left_margin;
qcom,mdss-dsi-h-pulse-width = <18>;//hpw-用于表示水平同步信号的宽度VCLK计算,对应驱动hsync_len;(一行设置几个像素)
qcom,mdss-dsi-h-sync-skew = <0>;///水平同步倾斜值:0 = 默认值。保持不变
qcom,mdss-dsi-v-back-porch = <12>;//vbp-在一帧图像开始时,垂直同步信号后的无效行数对应于驱动upper_margin;
qcom,mdss-dsi-v-front-porch = <15>;//vfp-表示垂直同步信号之前的无效行数在一帧图像结束后对应于驱动lower_margin;
qcom,mdss-dsi-v-pulse-width = <2>;//vpw-用行数计算表示垂直同步脉冲的宽度,并在相应的驱动中vsync_len;(有多少行显示)
qcom,mdss-dsi-h-left-border = <0>;//水平左边框(单位:像素):0 = 默认值。保持不变
qcom,mdss-dsi-h-right-border = <0>;//水平右边框(单位:像素):0 = 默认值。保持不变
qcom,mdss-dsi-v-top-border = <0>;///垂直上框(单位:像素):0 = 默认值。保持不变
qcom,mdss-dsi-v-bottom-border = <0>;///垂直下框(单位:像素):0 = 默认值。保持不变
qcom,mdss-dsi-bpp = <24>; // 指定面板的每像素位数。
// 3 = 适用于 rgb111
// 8 = 适用于 rgb332
// 12 = 适用于 rgb444
// 16 = 适用于 rgb565
&nbp;// 18 = 适用于 rgb666
// 24 = 适用于 rgb888
qcom,mdss-dsi-color-order = "rgb_swap_rgb"; // 指定 R、G 和 B 通道排序"rgb_swap_rgb" =DSI_RGB_SWAP_RGB默认值)
qcom,mdss-dsi-underflow-color = <0xff>;// 指定面板下溢颜色的控制器设置:0xff = 默认值。保持不变
qcom,mdss-dsi-border-color = <0>;//如有边框,定义边框颜色值。0 = 默认值。
qcom,mdss-dsi-on-command = [39 01 00 00 00 00 04 B9 FF 83 94//根据FAE提供的初始化代码填写
39 01 00 00 00 00 03 C0 1F 31
...
05 01 00 00 78 00 02 11 00
05 01 00 00 14 00 02 29 00];
qcom,mdss-dsi-off-command = [//根据FAE提供的初始化代码填写
05 01 00 00 14 00 02 28 00
05 01 00 00 78 00 02 10 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";//指定用于发送 ON /OFF命令的控制状态的字符串。
//"dsi_lp_mode" = DSI 低功率模式(默认值)
//"dsi_hs_mode" = DSI 高速模式
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <0>; //指定面板的脉冲模式选项。
//0 = 不在 vs/ve 数据包之后发送hsa/he(默认值)
//1 = 在 vs/ve 数据包之后发送 hsa/he
qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";//指定面板流量模式
//"non_burst_sync_pulse" = 使用同步脉冲的非突发流量(默认值)
//"non_burst_sync_event" = 使用同步 启动事件的非突发流量
//"burst_mode" = 突发模式
qcom,mdss-dsi-lane-map = "lane_map_0123";// 指定数据通道交换配置; 保持不变
//"lane_map_0123" = <0 1 2 3>(默认值)
qcom,mdss-dsi-bllp-eof-power-mode;//用于确定低功率空白期(BLLP)EOF 模式期间的 DSI 通道状态
qcom,mdss-dsi-bllp-power-mode;//用于确定低功率空白期(BLLP)模式 期间的 DSI 通道状态
qcom,mdss-dsi-tx-eot-append;
qcom,mdss-dsi-lane-0-state;//指定是否启用数据通道 0
qcom,mdss-dsi-lane-1-state;
qcom,mdss-dsi-lane-2-state;
qcom,mdss-dsi-lane-3-state;
qcom,mdss-dsi-panel-timings// 高通表格计算出来的
= [87 1C 12 00 42 42 18 21 17 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x04>;//指定模式切换后的字节时钟周期
qcom,mdss-dsi-t-clk-pre = <0x1B>;// 指定模式切换前的字节时钟周期
qcom,mdss-dsi-dma-trigger = "trigger_sw";//指定用于 DMA 路径的触发机制
//"none" = 无触发
//"trigger_te" = 断开用于触发的检查信 号线
//"trigger_sw" = 由软件触发(默认设置) "trigger_sw_seof" = 软件触发和帧触 发的开始/结束。
//"trigger_sw_te" = 软件触发和 TE
qcom,mdss-dsi-mdp-trigger = "none";//指定用于 MDP 路径的触发机制;"none" = 无触发
qcom,mdss-dsi-lp11-init;//确保在reset前,保证DSI clock和data都要及时被拉高
qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; //列出重置 GPIO 值和睡眠序列的数组
//每个命令具有下面定义的格式:
//--> 重置 GPIO 值:高电平低电平
//--> 睡眠值:多少毫秒
};
};
将屏的dtsi放到平台的dtsi中
指定要用哪个屏幕
#include "dsi-panel-hx8394f-720p-video.dtsi"
&mdss_dsi0 {//对应 .dtsi中“panel-controller”
qcom,dsi-pref-prim-pan = <&dsi_hx8394f_720p_video>;//与屏的dtsi中保持一致
pinctrl-names = "mdss_default", "mdss_sleep";
pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
qcom,regulator-ldo-mode;//低压差线性稳压器(一种电压转换芯片)
qcom,platform-te-gpio = <&tlmm 24 0>;
qcom,platform-reset-gpio = <&tlmm 60 0>;
//qcom,platform-bklight-en-gpio = <&tlmm 93 0>;
//qcom,platform-enable-gpio = <&tlmm 94 0>;
};
&dsi_hx8394f_720p_video {
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;//一个节点,列出用于为DSI面板供电的电源元件
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";//用于指定此面板的背光控制的实现
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;//PWM周期(以微秒为单位)
qcom,mdss-dsi-bl-pmic-bank-select = <0>; //PG背光通道
qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>;// PMIC gpio绑定到背光
// esd检查
qcom,esd-check-enabled;//启用ESD恢复功能
qcom,mdss-dsi-panel-status-check-mode = "reg_read"; //指定用于ESD恢复的面板状态检查方法;“ reg_read” =读取面板状态寄存器以检查面板状态
qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 09];//基于qcom dsi控制器协议的多个dcs数据包形成的字节流,以读取面板状态
qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
qcom,mdss-dsi-panel-status-value = <0x80 0x73 0x06>;//多个整数数组,每个整数数组指定用于检查面板状态的面板状态寄存器的值。 每个数组的大小是qcom,mdss-dsi-panel-status-read-length中指定的长度总和,并且必须相等。
qcom,mdss-dsi-panel-on-check-value = <0x80 0x73 0x06>;
qcom,mdss-dsi-panel-status-read-length = <3>;//数组长度
};
电压配置
除lab、ibb外,还有vdd、vddio自己在平台代码找一下
drivers/video/fbdev/msm/mdss_dsi.c
&mdss_dsi0 {
lab-supply = <&lab_regulator>;
ibb-supply = <&ibb_regulator>;
};
&labibb {
status = "ok";
qpnp,qpnp-labibb-mode = "lcd";
};
&ibb_regulator {
qcom,qpnp-ibb-discharge-resistor = <32>;
};
&dsi_panel_pwr_supply {
qcom,panel-supply-entry@2 {
reg = <2>;
qcom,supply-name = "lab";
qcom,supply-min-voltage = <4600000>;
qcom,supply-max-voltage = <6000000>;
qcom,supply-enable-load = <100000>;
qcom,supply-disable-load = <100>;
};
qcom,panel-supply-entry@3 {
reg = <3>;
qcom,supply-name = "ibb";
qcom,supply-min-voltage = <4600000>;
qcom,supply-max-voltage = <6000000>;
qcom,supply-enable-load = <100000>;
qcom,supply-disable-load = <100>;
qcom,supply-post-on-sleep = <20>;
};
};
修改设备树显示电压"regulator-l17",“regulator-l6”
lk
/android/bootable/bootloader/lk
添加屏的.h文件
.h中很多参数都是根据dtsi填写的
/dev/gcdb/display/include/panel_xxxx_xxxp_video.h
.h中用到的结构体定义在
/android/bootable/bootloader/lk/dev/gcdb/display/include/panel.h
Panel configuration
static struct panel_config hx8394f_720p_video_panel_data = {
"qcom,mdss_dsi_hx8394f_720p_video", "dsi:0:", "qcom,mdss-dsi-panel",
10, 0, "DISPLAY_1", 0, 0, 60, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, NULL
};
对应结构体定义与解析
struct panel_config{
char *panel_node_id;//"qcom,mdss_dsi_st7703p_720p_video" 与dtsi保持一致
char *panel_controller; //"dsi:0:"对应dtsi中“panel-controller”
char *panel_compatible;// "qcom,mdss-dsi-panel" 保持不变
uint16_t panel_interface;//看电路图上有几个mipi接口就填几
uint16_t panel_type; //video是MIPI_VIDEO_PANEL(0), cmd是MIPI_CMD_PANEL(1)
char *panel_destination;// "DISPLAY_1" 对应dtsi中panel-destination
uint32_t panel_orientation;//屏幕旋转方向,默认为0
/* panel_clockrate is deprecated in favor of panel_bitclock_freq */
uint32_t panel_clockrate;//默认为0,不建议修改
uint16_t panel_framerate;// 刷新率,一般为60
uint16_t panel_channelid;//保持不变
uint16_t dsi_virtualchannel_id;//对应DTS中虚拟频道ID(保持不变)
uint16_t panel_broadcast_mode;//保持不变
uint16_t panel_lp11_init;//确保在reset前,保证DSI clock和data都要及时被拉高
uint16_t panel_init_delay;// 初始化延迟
uint16_t dsi_stream;//保持不变
uint8_t interleave_mode;//交错模式(保持不变)
uint32_t panel_bitclock_freq;//保持不变
uint32_t panel_operating_mode;//操作模式,默认为0
uint32_t panel_with_enable_gpio;//保持不变
uint8_t mode_gpio_state;//保持不变
char *slave_panel_node_id;//NULL
};
Panel resolution
根据dtsi写,从左到右依次为分辨率(width*high)、hfp、hbp、hpw、hss、vfp、vbp、vpw…
static struct panel_resolution hx8394f_720p_video_panel_res = {
720, 1440, 58, 58, 16, 0, 15, 12, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0
// w, h, hfp, hbp, hpw, hss, vfp, vpw ...
};
以下参数在上面dtsi中有详细介绍,这里就不再重复了
struct panel_resolution{
uint16_t panel_width;
uint16_t panel_height;
uint16_t hfront_porch;//hfp
uint16_t hback_porch;//hbp
uint16_t hpulse_width;//hpw
uint16_t hsync_skew;//hss - 水平同步倾斜值
uint16_t vfront_porch;//vfp
uint16_t vback_porch;//vbp
uint16_t vpulse_width;//vpw
uint16_t hleft_border;//水平左边框
uint16_t hright_border;//水平右边框
uint16_t vtop_border;//垂直上边框
uint16_t vbottom_border;//垂直下边框
uint16_t hactive_res;//0
uint16_t vactive_res;//0
uint16_t invert_data_polarity;//0
uint16_t invert_vsync_polarity;//垂直脉冲模式
uint16_t invert_hsync_polarity;//水平脉冲模式
};
Panel color information
static struct color_info hx8394f_720p_video_color = {
24, 0, 0xff, 0, 0, 0
};
struct color_info{
uint8_t color_format;
uint8_t color_order;
uint8_t underflow_color;
uint8_t border_color;
uint8_t pixel_packing;
uint8_t pixel_alignment;
};
对应dtsi中
"rgb_swap_rgb"对应0
在安卓R上,pixel_alignment在代码中并没有去解析
Panel on/off command information
初始化代码
eg:
static char st7703p_720p_video_on_cmd1[] = {
0x06, 0x00, 0x39, 0xC0,
0xB1, 0x85, 0x00, 0x24,
0xDA, 0x01, 0xFF, 0xFF,
};
dtsi 的qcom,mdss-dsi-on-command中,每一行为一个cmd,cmd=0开始
第一行第一个数和第二个数之和是数值的个数(第2个一般是0x00),后面两个是datatype;(23,15,05对应80,29和39对应c0).
第二行开始写数值,结尾一行不足4个的填写0xff.
注意:始化代码最后两行只写一行
static char st7703p_720p_video_on_cmd22[] = {
0x11, 0x00, 0x05, 0x80,
};
static char st7703p_720p_video_on_cmd23[] = {
0x29, 0x00, 0x05, 0x80
};
mipi_dsi_cmd结构体中,第一个参数是相应数组的总数,包括第一行和0xff在内
static struct mipi_dsi_cmd st7703p_720p_video_on_command[] = {
{0x08, st7703p_720p_video_on_cmd0, 0x00},
{0x0C, st7703p_720p_video_on_cmd1, 0x00},
{0x08, st7703p_720p_video_on_cmd2, 0x00},
{0x10, st7703p_720p_video_on_cmd3, 0x00},
...
ST7703P_720P_VIDEO_ON_COMMAND 是初始化命令的个数,也就是刚刚填的cmd的个数
#define ST7703P_720P_VIDEO_ON_COMMAND 24
Panel timing
根据dtsi的timings来算
oem_panel.c
android/bootable/bootloader/lk/target/msmxxxx/oem_panel.c
#include "include/panel_xxxxxx_xxxp_video.h"
将panel加入枚举
/*---------------------------------------------------------------------------*/
/* static panel selection variable */
/*---------------------------------------------------------------------------*/
enum {
TRULY_1080P_VIDEO_PANEL,
TRULY_1080P_CMD_PANEL,
...
ST7703P_720P_VIDEO_PANEL,
ILI9881C_720P_VIDEO_PANEL,
UNKNOWN_PANEL
};
加入panel_list
/*
* The list of panels that are supported on this target.
* Any panel in this list can be selected using fastboot oem command.
*/
static struct panel_list supp_panels[] = {
{"truly_1080p_video", TRULY_1080P_VIDEO_PANEL},
{"truly_1080p_cmd", TRULY_1080P_CMD_PANEL},
...
{"st7703p_720p_video", ST7703P_720P_VIDEO_PANEL},
{"ili9881c_720p_video", ILI9881C_720P_VIDEO_PANEL},
};
将 panel_st7703p_720p_video.h中的数据依次赋值
case ST7703P_720P_VIDEO_PANEL:
panelstruct->paneldata = &st7703p_720p_video_panel_data;
panelstruct->panelres = &st7703p_720p_video_panel_res;
panelstruct->color = &st7703p_720p_video_color;
panelstruct->videopanel = &st7703p_720p_video_video_panel;
panelstruct->commandpanel = &st7703p_720p_video_command_panel;
panelstruct->state = &st7703p_720p_video_state;
panelstruct->laneconfig = &st7703p_720p_video_lane_config;
panelstruct->paneltiminginfo
= &st7703p_720p_video_timing_info;
panelstruct->panelresetseq
= &st7703p_720p_video_panel_reset_seq;
panelstruct->backlightinfo = &st7703p_720p_video_backlight;
pinfo->mipi.panel_on_cmds
= st7703p_720p_video_on_command;
pinfo->mipi.num_of_panel_on_cmds
= ST7703P_720P_VIDEO_ON_COMMAND;
pinfo->mipi.panel_off_cmds
= st7703p_720p_video_off_command;
pinfo->mipi.num_of_panel_off_cmds
= ST7703P_720P_VIDEO_OFF_COMMAND;
memcpy(phy_db->timing,
st7703p_720p_video_timings, TIMING_SIZE);
pinfo->mipi.signature = ST7703P_720P_VIDEO_SIGNATURE;
phy_db->regulator_mode = DSI_PHY_REGULATOR_LDO_MODE;
break;
注意:不要忘记配置供电模式