高通LCD bring up流程 前言 添加LCD的dtsi 将屏的dtsi放到平台的dtsi中 电压配置 添加屏的.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获取初始代码。
??
添加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 值:高电平低电平 //--> 睡眠值:多少毫秒 }; }; 指定要用哪个屏幕
#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”
/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 }; 根据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 };
/* * 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; 注意:不要忘记配置供电模式