bring up LCD

一、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

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

产品人卫朋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值