bring up LCD

    xiaoxiao2021-03-25  121

    一、kernel相关: 移植kernel之前需要准备好该panel的dtsi文件,因为这直接关系到屏能否快速被点亮,需要timing和上电命令序列。

    kernel/arch/arm/boot/dts-b50/dsi-panel-jdi-1080p-cmd.dtsi

    command和video模式不太一样

    &mdss_mdp {     dsi_jdi_1080_cmd: qcom,mdss_dsi_jdi_1080p_cmd {          qcom,mdss-dsi-panel-name = "jdi 1080p cmd mode dsi panel";         qcom,mdss-dsi-vendor-name = "Truly";         qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;          qcom,mdss-dsi-panel-type = "dsi_cmd_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 = <1080>;         qcom,mdss-dsi-panel-height = <1920>;         qcom,mdss-dsi-h-front-porch = <100>;         qcom,mdss-dsi-h-back-porch = <10>;         qcom,mdss-dsi-h-pulse-width = <60>;         qcom,mdss-dsi-h-sync-skew = <0>;          qcom,mdss-dsi-v-back-porch = <7>;         qcom,mdss-dsi-v-front-porch = <25>;         qcom,mdss-dsi-v-pulse-width = <2>;         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-on-command = [         23 01 00 00 01 00 02 b0 04] qcom,mdss-dsi-off-command = [05 01 00 00 02 00 02 28 00                  05 01 00 00 79 00 02 10 00];   //mipi数据格式         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 = "non_burst_sync_event";         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;         qcom,mdss-dsi-te-pin-select = <1>;// Specifies TE operating mode.          qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;         qcom,mdss-dsi-te-v-sync-continues-lines = <0x3c>;         qcom,mdss-dsi-te-dcs-command = <1>;         qcom,mdss-dsi-te-check-enable;         qcom,mdss-dsi-te-using-te-pin;         qcom,mdss-dsi-panel-timings = [f9 3d 34 00 58 4d 36 3f 53 03 04 00];         qcom,mdss-dsi-t-clk-post = <0x04>;         qcom,mdss-dsi-t-clk-pre = <0x1f>;         qcom,mdss-dsi-bl-min-level = <1>;         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_wled";         qcom,mdss-dsi-reset-sequence = <1 20>;     };

    };

    dsi命令格式如下: qcom,mdss-dsi-on-command:                     byte 0: dcs data type                     byte 1: set to indicate this is an individual packet                     byte 2: virtual channel number                     byte 3: expect ack from client (dcs read command)                     byte 4: wait number of specified ms after dcs command                          transmitted                     byte 5, 6: 16 bits length in network byte order                     byte 7 and beyond: number byte of payload 1、设备树 kernel/arch/arm/boot/dts-b50/msm8974-cdp.dtsi a. 添加一个panel支持 添加默认panel     qcom,mdss_dsi@fd922800 {         qcom,dsi-pref-prim-pan = <&dsi_ jdi_1080_cmd >;     }; 使能连续显示 &dsi_jdi_1080_cmd {        qcom,cont-splash-enabled; }; 将panel的dtsi文件包含进来 kernel/arch/arm/boot/dts-b50/msm8974-mdss-panels.dtsi /include/ "dsi-panel-jdi-1080p-cmd.dtsi" b. 添加电源支持     i2c@f9923000 {         ktd2510@3e {             compatible = "ktd2150,dc_dc";             reg = <0x3e>;             vcc_i2c-supply = <&pm8941_lvs2>;             bias-en-gpio = <&pm8941_gpios 13 0x00>;             en-p-gpio = <&msmgpio 58 0x00>;             en-n-gpio = <&msmgpio 56 0x00>;             ktd2150,regulator {                 regulator-name = "vcc_i2c";                 regulator-min-microvolt = <1800000>;                 regulator-max-microvolt = <1800000>;                 regulator-max-microamp = <9360>;             };         };                                                                                                                                                                     }; c. GPIO configuration GPIO配置主要是针对电源使能脚的配置,用到的GPIO如下: LCD_BIAS_EN   --- 供电电源使能脚 DISPLAY_ENP/ DISPLAY_ENN  --- +/- 5.75V 使能 LCD_1P8_EN  --- IOVCC使能 DISP_RESET_N  ---- display enable LCD_I2C_SCL/ LCD_I2C_SDA  ----  I2C总线 由于msm8974上的GPIO驱动能力不够,对于一些特殊的GPIO,需要使用pm8941上的GPIO替代。配置pmic的GPIO稍有不同。通常的做法是参考现有的配置做修改。 LCD_BIAS_EN使用的是pmic上的GPIO 13,配置如下: kernel/arch/arm/boot/dts-b50/msm8974-cdp.dtsi     gpio@cc00 { /* GPIO 13 */             qcom,mode = <1>;        /* QPNP_PIN_MODE_DIG_OUT */         qcom,output-type = <0>;     /* QPNP_PIN_OUT_BUF_CMOS */         qcom,pull = <5>;        /* QPNP_PIN_PULL_NO */         qcom,vin-sel = <2>;     /* QPNP_PIN_VIN2 */         qcom,out-strength = <2>;    /* QPNP_PIN_OUT_STRENGTH_MED */         qcom,src-sel = <0>;     /* QPNP_PIN_SEL_FUNC_CONSTANT */         qcom,master-en = <1>;     }; msm8974上的GPIO配置如下: kernel/arch/arm/mach-msm/board-8974-gpiomux.c static struct msm_gpiomux_config msm_hdmi_configs[] __initdata = { #ifdef CONFIG_NTD_I2C_GPIO     {             .gpio = 31,         .settings = {             [GPIOMUX_ACTIVE]    = &gpio_simulate_i2c_act_config,             [GPIOMUX_SUSPENDED] = &gpio_simulate_i2c_suspend_config,         },        },        {             .gpio = 32,         .settings = {             [GPIOMUX_ACTIVE]    = &gpio_simulate_i2c_act_config,             [GPIOMUX_SUSPENDED] = &gpio_simulate_i2c_suspend_config,         },        },    }; 其中,GPIOMUX_ACTIVE配置是当GPIO有效时被使用,在休眠时使用GPIOMUX_SUSPENDED配置 static struct gpiomux_setting gpio_simulate_i2c_act_config = {                                                                                                                 .func = GPIOMUX_FUNC_GPIO,     .drv = GPIOMUX_DRV_2MA,     .pull = GPIOMUX_PULL_UP, }; static struct gpiomux_setting gpio_simulate_i2c_suspend_config = {     .func = GPIOMUX_FUNC_GPIO,     .drv = GPIOMUX_DRV_2MA,     .pull = GPIOMUX_PULL_NONE, }; d. 接口配置 从原理图中可知,DCDC控制IC由I2C总线驱动,因此需要确保I2C总线是否使能。如果没有使能还需要添加I2C使能。 kernel/arch/arm/boot/dts-b50/msm8974.dtsi     i2c_1: i2c@f9923000 {         cell-index = <1>;          compatible = "qcom,i2c-qup";         reg = <0xf9923000 0x1000>;         #address-cells = <1>;          #size-cells = <0>;          reg-names = "qup_phys_addr";         interrupts = <0 95 0>;         interrupt-names = "qup_err_intr";         qcom,i2c-bus-freq = <100000>;         qcom,i2c-src-freq = <19200000>;         qcom,scl-gpio = <&msmgpio 3 0>;         qcom,sda-gpio = <&msmgpio 2 0>;         qcom,master-id = <86>;         status = "okay";     }; 另外,msm8974共有两个dsi接口,而b50需要的是DSI0,因此也需要保证正确使能,对于dsi1则禁止。DSI电源使能脚也需要在此配置。     mdss_dsi0: qcom,mdss_dsi@fd922800 {         compatible = "qcom,mdss-dsi-ctrl";         status = “okay”;         label = "MDSS DSI CTRL->0";         cell-index = <0>;         reg =   <0xfd922800 0x1f8>,             <0xfd922b00 0x2b0>,             <0xfdf30000 0x108>;         reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";         vdd-supply = <&pm8941_l22>;  //not used         vddio-supply = <&pm8941_l12>; //1.8v         vdda-supply = <&pm8941_l2>;  //vdd_dsi         qcom,mdss-fb-map = <&mdss_fb0>;         qcom,mdss-mdp = <&mdss_mdp>;          qcom,platform-reset-gpio = <&pm8941_gpios 19 0>;         qcom,platform-enable-gpio = <&msmgpio 131 0>;         qcom,platform-te-gpio = <&msmgpio 12 0>;         qcom,platform-strength-ctrl = [ff 06];         qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];         qcom,platform-regulator-settings = [07 09 03 00 20 00 01]; } e. 驱动修改 驱动部分代码需电源的控制逻辑,硬件电路中添加了一个的DCDC用来控制LCD模拟电源输出。电源上电顺序也是根据前面spec中的指导实现;kernel中LCD显示驱动主要由三部分组成MDP,DSI以及framebuffer驱动,与panel相关的是DSI驱动,目录如下: kernel/drivers/video/msm/mdss/mdss_dsi.c static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata, int enable) { ……     if (enable) {         ret = msm_dss_enable_vreg(             ctrl_pdata->power_data.vreg_config,             ctrl_pdata->power_data.num_vreg, 1);         if (ret) {             pr_err("%s:Failed to enable vregs.rc=%d\n",                 __func__, ret);             goto error;         } #ifdef CONFIG_xxx_KTD2150_5V_DCDC          ktd2150_set_power(enable); #endif         if (!pdata->panel_info.mipi.lp11_init) {             ret = mdss_dsi_panel_reset(pdata, 1);             if (ret) {                 pr_err("%s: Panel reset failed. rc=%d\n",                         __func__, ret);                 if (msm_dss_enable_vreg(                 ctrl_pdata->power_data.vreg_config,                 ctrl_pdata->power_data.num_vreg, 0))                     pr_err("Disable vregs failed\n");                 goto error;             }         }     } else {         ret = mdss_dsi_panel_reset(pdata, 0); #ifdef CONFIG_xxx_KTD2150_5V_DCDC          ktd2150_set_power(enable); #endif         ret = msm_dss_enable_vreg(             ctrl_pdata->power_data.vreg_config,             ctrl_pdata->power_data.num_vreg, 0);         if (ret) {             pr_err("%s: Failed to disable vregs.rc=%d\n",                 __func__, ret);         }

    }

    Touch Panel

    1、Device Tree 高通平台对一些常用的TP,在代码中已经有支持,但是还需要根据实际的应用进行修改。 file:kernel/arch/arm/boot/dts-b50/msm8974-cdp.dtsi i2c@f9924000 { /* CONFIG_xxx_SYNAPTICS_I2C_PANEL */         synaptics@20 {             compatible = "synaptics,rmi4";             reg = <0x20>;                                                                                                                                                              interrupt-parent = <&msmgpio>;             interrupts = <61 0x2008>;             vdd-supply = <&pm8941_l18>;              vdd-io-supply = <&pm8941_l12>;             vcc_i2c-supply = <&pm8941_lvs1>;             synaptics,reset-gpio = <&msmgpio 60 0x00>;             synaptics,irq-gpio = <&msmgpio 61 0x2008>;              synaptics,en-1p8-gpio = <&msmgpio 55 0x2008>;             synaptics,en-gpio = <&pm8941_gpios 12 0x2008>;             synaptics,display-coords = <0 0 1079 1919>;              synaptics,button-map = <139 102 158>;             synaptics,i2c-pull-up;              synaptics,support-vdd-io;             synaptics,power-down;  //suspend时,完全断电             synaptics,disable-gpios;             synaptics,do-lockdown; synaptics,fw-image-name = "PR1597452.img";         };   /* CONFIG_NTD_SYNAPTICS_I2C_PANEL */     };   在该设备树节点指定电源和GPIO配置。synaptics,fw-image-name表示TP使用的固件。在B50项目中使用了两个LCD模组,各厂家模组有差异,所以需要在代码中区分。TP电源使能脚由PM8941驱动,该引脚配置如下:     gpio@cb00 { /* GPIO 12 */ /* CONFIG_xxx_SYNAPTICS_I2C_PANEL */         qcom,mode = <1>;        /* QPNP_PIN_MODE_DIG_OUT */         qcom,output-type = <0>;     /* QPNP_PIN_OUT_BUF_CMOS */         qcom,pull = <5>;        /* QPNP_PIN_PULL_NO */         qcom,vin-sel = <0>;     /* QPNP_PIN_VIN2 */         qcom,out-strength = <2>;    /* QPNP_PIN_OUT_STRENGTH_MED */         qcom,src-sel = <0>;     /* QPNP_PIN_SEL_FUNC_CONSTANT */         qcom,master-en = <1>; /* CONFIG_xxx_SYNAPTICS_I2C_PANEL */     }; 1.8V电源是能脚配置如下: kernel/arch/arm/mach-msm/board-8974-gpiomux.c static struct msm_gpiomux_config msm_touch_configs[] __initdata = { #ifdef CONFIG_xxx_SYNAPTICS_I2C_PANEL     {         .gpio      = 55,        /* TOUCH 1.8V ENABLE */         .settings = {             [GPIOMUX_ACTIVE] = &atmel_resout_act_cfg,             [GPIOMUX_SUSPENDED] = &atmel_resout_sus_cfg,         },     }, #endif }; 2、 驱动修改 从bootarg参数中获得当前使用的panel,根据panel决定使用不同的TP firmware。 kernel/ drivers/input/touchscreen/synaptics_i2c_rmi4.c static int synaptics_rmi4_parse_bootarg(         struct synaptics_rmi4_platform_data *rmi4_pdata) { /*获取bootargs参数*/     cmd_line = of_get_property(chosen_node, "bootargs", &len);     if (!cmd_line || len <= 0) {         pr_err("%s: get bootargs failed\n", __func__);         rc = -ENODEV;         goto get_dt_pan;     } /*找到panel name偏移*/     disp_idx = strnstr(cmd_line, "qcom,", strlen(cmd_line));     if (!disp_idx) {         pr_err("%s:%d:cmdline panel not set disp_idx=[%p]\n",                 __func__, __LINE__, disp_idx);         rc = -1;         goto get_dt_pan;     }      if (strcmp(disp_idx, "qcom,mdss_dsi_jdi_1080p_cmd") == 0)         rmi4_pdata->fw_image_name = "PR1597452.img";     else if (strcmp(disp_idx, "qcom,mdss_dsi_ntd_nt35596_1080p_video") == 0)         rmi4_pdata->fw_image_name = "PR1650926.img";                                                                                                                       } 在移植时,需要在probe函数中添加代码获取属性的值。probe函数执行到synaptics_rmi4_parse_dt函数 static int synaptics_rmi4_parse_dt(struct device *dev,                 struct synaptics_rmi4_platform_data *rmi4_pdata) { #ifdef CONFIG_xxx_SYNAPTICS_I2C_PANEL     if (rmi4_pdata->fw_image_name == NULL) {         synaptics_rmi4_parse_bootarg(rmi4_pdata);     } #endif 。。。 /*取出属性赋值*/ rmi4_pdata->is_vdd_io = of_property_read_bool(np,             "synaptics,support-vdd-io");     rmi4_pdata->en_gpio = of_get_named_gpio_flags(np,             "synaptics,en-gpio", 0, &rmi4_pdata->en_flags);     rmi4_pdata->en_1p8_gpio = of_get_named_gpio_flags(np,             "synaptics,en-1p8-gpio", 0, &rmi4_pdata->en_1p8_flags);     printk("en_1p8_gpio: %d\n", rmi4_pdata->en_1p8_gpio); ...... } 此外,初始化配置工作还有三步,配置regulator以及相应的 gpio使能信号,上电,复位IC。 a. 配置regulator static int synaptics_rmi4_regulator_configure(struct synaptics_rmi4_data                         *rmi4_data, bool on) { #ifdef CONFIG_xxx_SYNAPTICS_I2C_PANEL /*判断该GPIO号是否有效*/     if (gpio_is_valid(rmi4_data->board->en_gpio)) { /*申请使用该GPIO*/         retval = gpio_request(rmi4_data->board->en_gpio,                 "rmi4_enable_gpio");    。。。 /*设置GPIO输出,在power on打开GPIO*/         retval = gpio_direction_output(rmi4_data->board->en_gpio, VDD_OFF); 。。。     } if (rmi4_data->board->is_vdd_io) { /*根据ID,从dt中找到regulator*/         rmi4_data->vdd_io = regulator_get(&rmi4_data->i2c_client->dev,                         "vdd-io"); /*函数返回值是该reg支持设置的电压个数*/         if (regulator_count_voltages(rmi4_data->vdd_io) > 0) {             retval = regulator_set_voltage(rmi4_data->vdd_io,                 RMI4_IO_VTG_MIN_UV, RMI4_IO_VTG_MAX_UV);         …         }         if (gpio_is_valid(rmi4_data->board->en_1p8_gpio)) {             retval = gpio_request(rmi4_data->board->en_1p8_gpio, "rmi4_en_1p8_gpio");             if (retval) {                 dev_err(&rmi4_data->i2c_client->dev,                     "unable to request gpio [%d]\n",                     rmi4_data->board->en_1p8_gpio);                 goto err_req_vtg_vdd_io_en;             }             retval = gpio_direction_output(rmi4_data->board->en_1p8_gpio, 0);             if (retval) {                 dev_err(&rmi4_data->i2c_client->dev,                     "unable to set direction for gpio " \                     "[%d]\n", rmi4_data->board->en_1p8_gpio);                 goto err_set_vtg_vdd_io_en;             }         } else {                                                                                                                                                                       dev_err(&rmi4_data->i2c_client->dev,                 "1.8v enable gpio is invalid\n");         }     } } b. Power ON 使能TP vdd-io和gpio输出 static int synaptics_rmi4_power_on(struct synaptics_rmi4_data *rmi4_data,                     bool on) { 。。。 /*enable GPIO*/ if (gpio_is_valid(rmi4_data->board->en_gpio)) {         gpio_set_value(rmi4_data->board->en_gpio, VDD_ON);     }     /* Enable TP IO vcc */     if (rmi4_data->board->is_vdd_io) {         retval = reg_set_optimum_mode_check(rmi4_data->vdd_io,             RMI4_IO_ACTIVE_LOAD_UA);         if (retval < 0) {             dev_err(&rmi4_data->i2c_client->dev,                 "Regulator vdd set_opt failed rc=%d\n",                 retval);             return retval;         }         retval = regulator_enable(rmi4_data->vdd_io);         if (retval) {             dev_err(&rmi4_data->i2c_client->dev,                 "Regulator vdd enable failed rc=%d\n",                 retval);             goto error_reg_en_vdd_io;         }         if (gpio_is_valid(rmi4_data->board->en_1p8_gpio)) {             gpio_set_value(rmi4_data->board->en_1p8_gpio, 1);         }     } 。。。 } c. Suspend 在屏幕灭屏操作后,为了降低功耗考虑考虑,将TP进入低功耗模式。如果在设备数中使能了synaptics,power-down属性,则完全关断TP电源。否则进入低功耗模式 static int synaptics_rmi4_regulator_lpm(struct synaptics_rmi4_data *rmi4_data, bool on) { if (on == false)         goto regulator_hpm; #ifdef CONFIG_NTD_SYNAPTICS_I2C_PANEL     if (rmi4_data->board->is_vdd_io) {         load_ua = rmi4_data->board->power_down_enable ? 0 : RMI4_IO_LPM_LOAD_UA;         retval = reg_set_optimum_mode_check(rmi4_data->vdd_io, load_ua); 。。。         if (rmi4_data->board->power_down_enable) {             retval = regulator_disable(rmi4_data->vdd_io); 。。。             if (gpio_is_valid(rmi4_data->board->en_1p8_gpio))                 gpio_set_value(rmi4_data->board->en_1p8_gpio, 0);         }     } #endif 。。。 #ifdef CONFIG_NTD_SYNAPTICS_I2C_PANEL         if (gpio_is_valid(rmi4_data->board->en_gpio))             gpio_set_value(rmi4_data->board->en_gpio, VDD_OFF); #endif return 0; regulator_hpm: 。。。 #ifdef CONFIG_NTD_SYNAPTICS_I2C_PANEL                                                                                                                                              if (gpio_is_valid(rmi4_data->board->en_gpio))             gpio_set_value(rmi4_data->board->en_gpio, VDD_ON); #endif     } #ifdef CONFIG_NTD_SYNAPTICS_I2C_PANEL     if (rmi4_data->board->is_vdd_io) {         retval = reg_set_optimum_mode_check(rmi4_data->vdd_io,                     RMI4_IO_ACTIVE_LOAD_UA);         if (retval < 0) {             dev_err(&rmi4_data->i2c_client->dev,                 "Regulator vcc_dig set_opt failed rc=%d\n",                 retval);             goto fail_regulator_hpm;         }         if (rmi4_data->board->power_down_enable) {             retval = regulator_enable(rmi4_data->vdd_io);             if (retval) {                 dev_err(&rmi4_data->i2c_client->dev,                     "Regulator vdd_io enable failed rc=%d\n",                     retval);                 goto fail_regulator_hpm;             }             if (gpio_is_valid(rmi4_data->board->en_1p8_gpio))                 gpio_set_value(rmi4_data->board->en_1p8_gpio, 1);         }     } #endif ...... } 二、LK相关: 1、代码添加支持 bootable/bootloader/lk/ target/msm8974/oem_panel.c enum { JDI_1080P_VIDEO_PANEL, #ifdef xxx_JDI_PANEL JDI_1080P_CMD_PANEL,  //cmd panel #endif #ifdef xxx_NT35596_VID_PANEL NT35596_1080P_VIDEO_PANEL, //video panel #endif ...... }; 在枚举中添加panel_id,为了标识不同的panel。并为添加panel配置,也就是从对应屏幕的头文件中获取配置 static uint32_t panel_id; static void init_panel_data(struct panel_struct *panelstruct,             struct msm_panel_info *pinfo,             struct mdss_dsi_phy_ctrl *phy_db) { switch(panel_id) {  … #ifdef xxx_JDI_PANEL     case JDI_1080P_CMD_PANEL:         panelstruct->paneldata    = &jdi_1080p_cmd_panel_data;         panelstruct->panelres     = &jdi_1080p_cmd_panel_res;         panelstruct->color        = &jdi_1080p_cmd_color;         panelstruct->videopanel   = &jdi_1080p_cmd_video_panel;         panelstruct->commandpanel = &jdi_1080p_cmd_command_panel;         panelstruct->state        = &jdi_1080p_cmd_state;         panelstruct->laneconfig   = &jdi_1080p_cmd_lane_config;         panelstruct->paneltiminginfo             = &jdi_1080p_cmd_timing_info;         panelstruct->panelresetseq                      = &jdi_1080p_cmd_panel_reset_seq;         panelstruct->backlightinfo = &jdi_1080p_cmd_backlight;         pinfo->mipi.panel_cmds             = jdi_1080p_cmd_on_command;         pinfo->mipi.num_of_panel_cmds             = JDI_1080P_CMD_ON_COMMAND;         memcpy(phy_db->timing,             jdi_1080p_cmd_timings, TIMING_SIZE);         pinfo->mipi.signature = JDI_1080P_CMD_SIGNATURE;         break; #endif       … } } 那么这个panel_id怎么来的呢,平台可能支持多个屏幕,所以需要循环扫描屏幕,每次扫描获取一个panel_id  bool oem_panel_select(const char *panel_name, struct panel_struct *panelstruct,             struct msm_panel_info *pinfo,             struct mdss_dsi_phy_ctrl *phy_db) { ......    switch (hw_id) {     case HW_PLATFORM_MTP:     case HW_PLATFORM_FLUID:     case HW_PLATFORM_SURF:         switch (auto_pan_loop) {         case 0: #ifdef xxx_JDI_PANEL             panel_id = JDI_1080P_CMD_PANEL; #else             panel_id = JDI_1080P_VIDEO_PANEL; #endif             break;         case 1: #ifdef xxx_NT35596_VID_PANEL             panel_id = NT35596_1080P_VIDEO_PANEL; #else             panel_id = TOSHIBA_720P_VIDEO_PANEL;                                                                                                                           #endif             break;         case 2:             panel_id = GENERIC_720P_CMD_PANEL;             break;         default:             panel_id = UNKNOWN_PANEL;             ret = false;             break;         }         auto_pan_loop++;         break;     } panel_init:     init_panel_data(panelstruct, pinfo, phy_db);     return ret; } 2、上电配置 a. gpio 配置 上电配置主要是配置相关的gpio引脚,包括reset,enable,te等引脚。根据硬件电路,在如下头文件中配置GPIO: bootable/ bootloader/lk/target/msm8974/include/target/display.h typedef struct gpio_pin{                                                                                                                                                       char    *pin_source;   // pm8941_gpios/ msmgpio     uint32_t pin_id;       //引脚号     uint32_t pin_strength;     uint32_t pin_direction;  //输入输出     uint32_t pin_pull;     uint32_t pin_state; }; pin_source表示GPIO源,如果是pmic上的引脚则pm8941_gpios,cpu上的引脚是msmgpio。 static struct gpio_pin reset_gpio = {    "pm8941_gpios", 19, 2, 1, 0, 1 };                                                                                                                                                                         static struct gpio_pin enable_gpio = {  #if defined(NTD_2K_SHARP_PANEL) || defined(NTD_B50_JDI_PANEL)   "msmgpio", 131, 3, 1, 0, 1    //1.8V enable #else   "msmgpio", 58, 3, 1, 0, 1 #endif }; #if defined(NTD_2K_SHARP_PANEL) || defined(NTD_B50_JDI_PANEL) static struct gpio_pin enable_p_gpio = {    "msmgpio", 56, 3, 1, 0, 1 }; static struct gpio_pin enable_n_gpio = {    "msmgpio", 58, 3, 1, 0, 1 }; #endif b. LDO 配置如下: typedef struct ldo_entry{                                                                                                                                                      char    *ldo_name;     uint32_t ldo_id;     uint32_t ldo_type;     uint32_t ldo_voltage;     uint32_t ldo_enable_load;     uint32_t ldo_disable_load;     uint32_t ldo_preon_sleep;     uint32_t ldo_poston_sleep;     uint32_t ldo_preoff_sleep;     uint32_t ldo_postoff_sleep; }; 设置pm8941供给LCD的各路电源,包括寄存器偏移,输出电压等 static struct ldo_entry ldo_entry_array[] = { #ifdef xxx_2K_SHARP_PANEL { "vddio", 12, 0, 1800000, 100000, 100, 0, 20, 0, 0}, { "vdda", 2, 1, 1200000, 100000, 100, 0, 0, 0, 0}, { "lvs2", 66, 2, 1800000, 100000, 100, 0, 0, 0, 0}, #else { "vdd", 22, 0, 3000000, 100000, 100, 0, 20, 0, 0}, { "vddio", 12, 0, 1800000, 100000, 100, 0, 20, 0, 0}, { "vdda", 2, 1, 1200000, 100000, 100, 0, 0, 0, 0}, #endif }; C. 上电函数 负责执行上电时序,复位panel,使能电源。 bootable/bootloader/lk/target/msm8974/target_display.c int target_panel_reset(uint8_t enable, struct panel_reset_sequence *resetseq,                     struct msm_panel_info *pinfo) {     uint32_t rst_gpio = reset_gpio.pin_id; ......     struct pm8x41_gpio resetgpio_param = {         .direction = PM_GPIO_DIR_OUT,         .output_buffer = PM_GPIO_OUT_CMOS,         .out_strength = PM_GPIO_OUT_DRIVE_MED, #if defined(xxx_2K_SHARP_PANEL) || defined(xxx_B50_JDI_PANEL)         .pull = 5,         .function = 0,         .vin_sel = 2, #endif     }; 。。。     pm8x41_gpio_config(rst_gpio, &resetgpio_param);     /* enable LCD_BIAS_EN*/ #if defined(xxx_2K_SHARP_PANEL) || defined(xxx_B50_JDI_PANEL)     pm8x41_gpio_config(13, &resetgpio_param);     pm8x41_gpio_set(13, 1);     mdelay(2); #endif     if (enable) {             /*config  LCD_1P8_EN*/ gpio_tlmm_config(enable_gpio.pin_id, 0,             enable_gpio.pin_direction, enable_gpio.pin_pull,             enable_gpio.pin_strength, enable_gpio.pin_state); #if defined(xxx_2K_SHARP_PANEL) || defined(xxx_B50_JDI_PANEL)                /*config  LCD_ENP */                                                                                                                       gpio_tlmm_config(enable_p_gpio.pin_id, 0,              enable_p_gpio.pin_direction, enable_p_gpio.pin_pull,              enable_p_gpio.pin_strength, enable_p_gpio.pin_state);             /*config  LCD_ENN */             gpio_tlmm_config(enable_n_gpio.pin_id, 0,              enable_n_gpio.pin_direction, enable_n_gpio.pin_pull, enable_n_gpio.pin_strength, enable_n_gpio.pin_state);             /*enable lcd_enp lcd_enn*/             gpio_set(enable_p_gpio.pin_id, resetseq->pin_direction);             gpio_set(enable_n_gpio.pin_id, resetseq->pin_direction); #endif         /*enable 1p8_en*/         gpio_set(enable_gpio.pin_id, resetseq->pin_direction);         /*reset panel*/ pm8x41_gpio_set(rst_gpio, resetseq->pin_state[0]);                                                                                                                         mdelay(resetseq->sleep[0]);         pm8x41_gpio_set(rst_gpio, resetseq->pin_state[1]);         mdelay(resetseq->sleep[1]);         pm8x41_gpio_set(rst_gpio, resetseq->pin_state[2]);         mdelay(resetseq->sleep[2]);     } else {         resetgpio_param.out_strength = PM_GPIO_OUT_DRIVE_LOW;         pm8x41_gpio_config(rst_gpio, &resetgpio_param);         pm8x41_gpio_set(rst_gpio, PM_GPIO_FUNC_LOW);         gpio_set(enable_gpio.pin_id, resetseq->pin_direction); #if defined(xxx_2K_SHARP_PANEL) || defined(xxx_B50_JDI_PANEL)         gpio_set(enable_p_gpio.pin_id, resetseq->pin_direction);         gpio_set(enable_n_gpio.pin_id, resetseq->pin_direction); #endif     }     return NO_ERROR; } 3、显示开机logo 在panel初始化完毕之后,开始图片显示,图片显示原理简单的说就是先向内存申请一段内存空间,根据图像格式向及地址拷贝。我们目前所使用的屏bpp是24位,也就是RGB888格式,R/G/B三通道分别占一个字节,一个像素用三个字节表示。bpp即bits per pixel。 void display_image_on_screen() {     struct fbimage default_fbimg, *fbimg;     bool flag = true;     fbimg = fetch_image_from_partition();     if(!fbimg) {         flag = false;         fbimg = &default_fbimg;         fbimg->header.width = SPLASH_IMAGE_HEIGHT;         fbimg->header.height = SPLASH_IMAGE_WIDTH;         fbimg->image = (unsigned char *)imageBuffer_rgb888;     }        fbcon_putImage(fbimg, flag); } 而imageBuffer_rgb888就是存放图片的头文件。在如下文件中bootable/bootloader/lk/platform/msm_shared/include/splash.h
    转载请注明原文地址: https://ju.6miu.com/read-12952.html

    最新回复(0)