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