硬件:高通8926
软件:高通Android
开发主机:ubuntu
通信接口:MIPI(lane 4)
背光控制:GPIO实现PWM
LCM主要参数:分辨率768(W)X1024(H),像素位深(BPP)24,MIPI通道数(lane)4
前后肩VBPD 6,VFPD 8,VSPW 6,HBPD 60,HFPD 40,HSPW 8
屏工作需要要背光和LCD显示两部分。对于手机来讲又要使屏在bootloader和kernel 两个模式下都可以工作,屏的工作原理是一样的,只是在bootloader和kernel中的实现格式不一样而已,下面将会详细说明。
图1是背光控制电路,LCD_BL_CTL就是背光控制引脚,它连接在图2的PM-8926芯片的GPIO_6上,把这个引脚配置成PWM输出即可点亮背光。
图1
图2
Bootloader的背光是通过target_backlight_ctrl()控制的,找到本项目的这个函数修改
成如下形式:
int target_backlight_ctrl(uint8_t enable)
{
struct pm8x41_gpio gpio;
static uint8_t bl_flag = 0;
static uint8_t init_gpio = 0;
if (enable == bl_flag)
return 0;
if(enable)
mdelay(20);
if(!init_gpio){
gpio.direction = PM_GPIO_DIR_OUT;
gpio.function = 6;
gpio.output_buffer = PM_GPIO_OUT_CMOS;
gpio.vin_sel = 3;
gpio.out_strength = 1;
pm8x41_gpio_config(6, &gpio);
init_gpio = 1;
}
pm8x41_backlight_enable(enable);
bl_flag = enable;
return 0;
}
把pm8x41_backlight_enable()改成如下形式:
int pm8x41_backlight_enable(uint8_t enable)
{
if(enable){
pm8x41_lpg_write(4,LPG_N_PWM_SIZE_CLK,0x33);
pm8x41_lpg_write(4,LPG_N_PWM_FREQ_PREDIV_CLK,0x00);//0x43
pm8x41_lpg_write(4,LPG_N_PWM_TYPE_CONFIG,0x20);
pm8x41_lpg_write(4,LPG_N_ENABLE_CONTROL,0xe4);
pm8x41_lpg_write(4,LPG_N_PWM_VALUE_LSB,0xcc);
pm8x41_lpg_write(4,LPG_N_PWM_VALUE_MSB,0x0);
}
else {
pm8x41_lpg_write(4,LPG_N_ENABLE_CONTROL,0x04);
}
return 0;
}
宏定义如下:
#define LPG_N_PWM_SIZE_CLK 0x41
#define LPG_N_PWM_FREQ_PREDIV_CLK 0x42
#define LPG_N_PWM_TYPE_CONFIG 0x43
#define LPG_N_PWM_VALUE_LSB 0x44
#define LPG_N_PWM_VALUE_MSB 0x45
#define LPG_N_ENABLE_CONTROL 0x46
还有一些配置是在配置屏的位置一起配置的,后面会讲。
找到对应项目的dtsi文件,我这里是d508.dtsi,添加如下代码配置GPIO
&spmi_bus {
/* Config the pmic gpio_6 as pwm out */
qcom,pm8226@0 {
gpios {
gpio@c500 {
qcom,mode = <1>; /* Digital output */ // QPNP_PIN_MODE_DIG_OUT
qcom,output-type = <0>; /* CMOS logic */
qcom,pull = <5>; /* QPNP_PIN_PULL_NO*/
qcom,vin-sel = <3>; /* QPNP_PIN_VIN3 */
qcom,src-sel = <3>; /* QPNP_PIN_SEL_FUNC_2 */ // QPNP_PIN_SEL_FUNC_2//not 6
qcom,master-en = <1>; /* Enable GPIO */
qcom,invert = <0>;
};
};
};
};
还有一些配置是在配置屏的位置一起配置的,后面会讲。
图3是接口电路,就是板子上通过排线连接LCM的那个插槽,主要包括VDD,4路MIPI数据线和背光LED.
图3
供电引脚LCD_3V3是由图4电路的LCD_PWR_EN引脚进行控制的, LCD_PWR_EN是由图5的MSM8926的GPIO_34进行控制的,所以我们在程序中要它配置成输出,并使用它来控制供电。
MIPI只要在程序中配成4路就ok
背光LED前面已经配好,后面程序中直接使用。
图4
图5
找一个类似的LCM作为模板进行移植,查看公司其他人集成LCM提交的分支看需要添加修改哪些文件。
主要包括添加LCM配置文件panel_xxx_video.h和在oem_panel中把屏添加进去两部分。
相关参数代表的意思可以查看结构体的原型,也可以结合后面将要创建的dsi-panel-xxx-video.dtsi查看/kernel/documentation/devicetree/bindings/fb/内文档。
a. Panel_config,panel_resolution,color_info,lane_configuration等结构体就是屏的基本参数配置,按照LCD的datasheet填写就可以了,文章开头已经列出了我的主要参数;
b. mipi_dsi_cmd包括on和off两个结构体,分别表示上电初始化和下电前要做的寄存器操作,按照FAE提供的初始化代码填充;
c. xxx_video_timings[]数组要使用高通提供的算法工具(一个Excel表格)算出;
d. 没提到的一些结构体和参数,如果你能确认就修改,否则就先使用默认值,如果没调通,后面调试的时候修改。
a. 添加头文件包含
#include "include/panel_xxx _video.h
b. 在屏menu中添加
XXX_VIDEO_PANEL,
c. 在屏选择函数oem_panel_select()的本项目中选择新增屏:
case HW_PLATFORM_D508:
panel_id = OTA7155A_XGA_VIDEO_PANEL;
d .在init_panel_data()中参考其它屏添加初始化赋值代码:
case XXX_VIDEO_PANEL:
panelstruct->paneldata = &xxx _video_panel_data;
.
.
.
memcpy(phy_db->timing, xxx_video_timings, TIMING_SIZE);
break;
找一个类似的LCM作为模板进行移植,查看公司其他人集成LCM提交的分支看需要添加修改哪些文件。
主要包括添加LCM配置文件dsi-panel-xxx-video.dtsi和在oem_panel中把屏添加进去两部分。
相关参数代表的意思可以结合前面bootloader中创建的panel_xxx_video.h和查看/kernel/documentation/devicetree/bindings/fb/内文档。
找个类似的文件复制一份,改成自己的名字“dsi-panel-xxx-video.dtsi”,参数按照前面创建的panel_xxx_video.h填写就ok,不知道的就使用默认值,后面调试再进行修改。
我这里是d508.dtsi,修改mdss_dsi0
&mdss_dsi0 {
qcom,dsi-pref-prim-pan = <&dsi_xxx_vid>;
};
a. 添加LCD供电使能GPIO,就是前面提到的GPIO_34
在mdss_dsi0: qcom,mdss_dsi@fd922800中添加:
qcom,platform-sgm2031-en-gpio = <&msmgpio 34 0>;
其中platform-sgm2031-en-gpio是我们自己定义的名字,后面在mdss_dsi.c中会根据它来配置GPIO
b. 修改上电时序
platform-supply-entry1, platform-supply-entry2, platform-supply-entry3为上电顺序,从电路图中看我们这里只用到VDD,所以我把entry2和entry3都删除了。
a.在mdss_dsi.h的mdss_dsi_ctrl_pdata{}结构体中添加:
#ifdef CONFIG_ARCH_MSM8226_D508
int sgm2031_en_gpio;
#endif
因为是公用文件,所以最好用宏控一下。
b. 在mdss_dsi.c的dsi_panel_device_register()函数中添加:
#ifdef CONFIG_ARCH_MSM8226_D508
ctrl_pdata->sgm2031_en_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
"qcom,platform-sgm2031-en-gpio", 0);
printk(KERN_INFO "sgm2031_en_gpio: %d\n", ctrl_pdata->sgm2031_en_gpio);
if (!gpio_is_valid(ctrl_pdata->sgm2031_en_gpio)) {
pr_err("%s:%d, sgm2031_en_gpio gpio not specified\n",
__func__, __LINE__);
} else {
rc = gpio_request(ctrl_pdata->sgm2031_en_gpio, "sgm2031_en_gpio");
if (rc) {
pr_err("request sgm2031_en_gpio gpio failed, rc=%d\n",
rc);
return -ENODEV;
}
rc = gpio_direction_output(ctrl_pdata->sgm2031_en_gpio, 1);
if (rc) {
pr_err("sgm2031_en_gpio gpio set out, rc=%d\n",
rc);
return -ENODEV;
}
}
#endif
c.在mdss_io_util.c中添加:
#define SGM2031_EN_GPIO 34
在msm_dss_enable_vreg()函数中设置GPIO进行上电和下电
//上电:
#ifdef CONFIG_ARCH_MSM8226_D508
gpio_set_value(SGM2031_EN_GPIO, 1);
msleep(75);
#endif
} else {//下电
#ifdef CONFIG_ARCH_MSM8226_D508
gpio_set_value(SGM2031_EN_GPIO, 0);
msleep(20);
#endif
程序写好了,接下来就可以编译下载看一下结果:
fastboot flash aboot emmc_appsboot.mbn
fastboot flash boot boot.img