1、使用PMIC输出的背光,即bl_ctrl_wled背光驱动的方式
使用原理
即可使用PMI8952上的WLED_link模块驱动两组LED灯的。如下:
而PMI8952上的PMI_MPP3输出的WLED模式PWM输出管脚链接到LCD的背光控制光脚上。如下:
电路使用方式如下:
2、背光驱动IC的方式
实现原理:
背光驱动方式:
驱动IC使能管脚使用GPIO33和MCU使能与控制。在初期调试的时候,先断开MCU的链接。PWM使用PMI8953上的MPP4输出,如下:
3、代码中的实现方式
3.1、kernel代码实现方式
其中:
qcom,mdss-dsi-bl-pmic-control-type
“bl_ctrl_pwm”:Backlight controlled by PWM gpio.
“bl_ctrl_wled” :Backlight controlled by WLED.
“bl_ctrl_dcs” :Backlight controlled by DCS commands.
WLED方式:
kernel\msm-4.9\arch\arm64\boot\dts\GM620S\dsi-panel-ek79030-1080p-video.dtsi
qcom,mdss-dsi-bl-pmic-control-type = “bl_ctrl_wled”;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
背光驱动IC驱动方式:
qcom,mdss-dsi-bl-pmic-control-type = “bl_ctrl_pwm”;
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
qcom,mdss-dsi-bl-pmic-bank-select = <0>;
qcom,mdss-dsi-pwm-gpio = <&pm8953_mpps 4 0>;
背光设备树解析:
mdss_dsi_ctrl_probe() ///// kernel/msm-3.18/drivers/video/msm/mdss/mdss_dsi.c
|___mdss_panel_parse_bl_setting() ///// kernel/msm-3.18/drivers/video/msm/mdss/mdss_dsi_panel.c
设置背光亮度代码:
mdss_fb_probe() //// kernel/msm-3.18/drivers/video/msm/mdss/mdss_fb.c
|___mdss_fb_set_bl_brightness()
|___mdss_fb_set_brightness()
|___pdata->set_backlight()
|___ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl()
mdss_dsi_panel_bl_ctrl() ///// kernel/msm-3.18/drivers/video/msm/mdss/mdss_dsi_panel.c
背光控制节点:
3.2 lk中实现:
bootable\bootloader\lk\dev\gcdb\display\include\panel_ek79030_1080p_video.h
/---------------------------------------------------------------------------/
/* Backlight setting /
/---------------------------------------------------------------------------/
/
uint16_t bl_interface_type;
uint16_t bl_min_level;
uint16_t bl_max_level;
uint16_t bl_step;
uint16_t bl_pmic_controltype;
char *bl_pmic_model;
*/
static struct backlight ek79030_1080p_video_backlight = {
1, 1, 4095, 100, 1, “PMIC_8941”
};
bootable\bootloader\lk\target\msm8953\target_display.c
bootable\bootloader\lk\dev\gcdb\display\gcdb_display.c
bootable\bootloader\lk\dev\qpnp_wled\qpnp_wled.c
bootable\bootloader\lk\dev\pmic\pm8x41\pm_pwm.c
4、代码移植
本文中只针对背光驱动IC实现的方式,因为我们发现使用PMI8952的MPP3实现方式时,PWM调整到最大背光的驱动电流还是不够,亮度满足不了需求,而背光驱动IC可以既调节PWM的占空比,要可以调节驱动IC上的电阻来达到调节最大背光亮度。
4.1 lk部分的移植
配置PWM:
bootable\bootloader\lk\dev\gcdb\display\include\panel_ek79030_1080p_video.h
/*---------------------------------------------------------------------------*/
/* Backlight setting */
/*---------------------------------------------------------------------------*/
/*
uint16_t bl_interface_type;
uint16_t bl_min_level;
uint16_t bl_max_level;
uint16_t bl_step;
uint16_t bl_pmic_controltype;
char *bl_pmic_model;
*/
static struct backlight ek79030_1080p_video_backlight = {
1, 1, 4095, 100, 1, "PMIC_8941"
};
配置背光使能GPIO33:
bootable\bootloader\lk\target\msm8953\target_display.c
//blk enable GPIO33
static struct gpio_pin bkl_gpio = {
//"msmgpio", 59, 3, 1, 0, 1
"msmgpio", 33, 3, 1, 0, 1
};
将wled驱动模式修改成mpp4的PWM背光IC驱动模式:
bootable\bootloader\lk\target\msm8953\target_display.c
static int pwm_backlight_ctrl(uint8_t enable)
{
if(enable) {
pm_pwm_enable(false);
pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
pm_pwm_enable(true);
} else {
pm_pwm_enable(false);
}
return NO_ERROR;
}
//add lizhongyu modify for niou PWM backlight start
static int pwm_backlight_ctrl_niou(uint8_t enable)
{
struct pm8x41_mpp mpp;
int rc;
mpp.base = PM8x41_MMP4_BASE;
mpp.vin = MPP_VIN3;//MPP_VIN0;
if (enable) {
dprintf(INFO, "%s: enable\n", __func__);
pm_pwm_enable(false);
rc = pm_pwm_config(PWM_DUTY_US, PWM_PERIOD_US);
if (rc < 0)
mpp.mode = MPP_HIGH;
else {
mpp.mode = MPP_DTEST2;//MPP_DTEST1;
pm_pwm_enable(true);
}
pm8x41_config_output_mpp(&mpp);
pm8x41_enable_mpp(&mpp, MPP_ENABLE);
} else {
dprintf(INFO, "%s: disable\n", __func__);
pm_pwm_enable(false);
pm8x41_enable_mpp(&mpp, MPP_DISABLE);
}
mdelay(20);
return 0;
}
//dd lizhongyu modify for niou PWM backlight end
int target_backlight_ctrl(struct backlight *bl, uint8_t enable)
{
uint32_t ret = NO_ERROR;
if (bl->bl_interface_type == BL_DCS)
return ret;
if(target_get_pmic() == PMIC_IS_PMI632) {
ret = pwm_backlight_ctrl(enable);
} else {
dprintf(CRITICAL, "wled_backlight_ctrl(enable)\n");
//add lizhongyu modify for niou PWM backlight
//ret = wled_backlight_ctrl(enable);
dprintf(CRITICAL, "target_backlight_ctrl() PWM\n");
ret = pwm_backlight_ctrl_niou(enable);
//end
}
return ret;
}
ap\bootable\bootloader\lk\dev\pmic\pm8x41\pm_pwm.c
配合lcd头文件中的ek79030_1080p_video_backlight来使用
void pm_pwm_enable(bool enable)
{
uint8_t reg;
reg = enable << PM_PWM_ENABLE_CTL_SHIFT
& PM_PWM_ENABLE_CTL_MASK;
pm_pwm_reg_write(PM_PWM_ENABLE_CTL_REG_OFFSET, reg);
//add mpp4 pwm
if (enable){
pm_pwm_reg_write(0xd0, 0xa5);
pm_pwm_reg_write(0xe3, 0x02);
} else {
pm_pwm_reg_write(0xd0, 0x00);
pm_pwm_reg_write(0xe3, 0x00);
}
//end add
}
4.2 内核部分移植
kernel\msm-4.9\arch\arm64\boot\dts\GM620S\dsi-panel-ek79030-1080p-video.dtsi
//qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
qcom,mdss-dsi-bl-pmic-bank-select = <0>;
qcom,mdss-dsi-pwm-gpio = <&pm8953_mpps 4 0>;
ap\kernel\msm-4.9\arch\arm64\boot\dts\GM620S\pm8953.dtsi
pm8953_mpps: mpps {
compatible = "qcom,spmi-mpp";
reg = <0xa000 0x400>;
interrupts = <0x0 0xa0 0 IRQ_TYPE_NONE>,
<0x0 0xa1 0 IRQ_TYPE_NONE>,
<0x0 0xa2 0 IRQ_TYPE_NONE>,
<0x0 0xa3 0 IRQ_TYPE_NONE>;
interrupt-names = "pm8953_mpp1", "pm8953_mpp2",
"pm8953_mpp3", "pm8953_mpp4";
gpio-controller;
#gpio-cells = <2>;
// add lizhongyu modify for niou PWM backlight --- start
pinctrl-names = "default";
pinctrl-0 = <&pm8953_default>;
pm8953_default: pm8953_mpp4 {
gpio {
pins = "mpp4";
function = "digital";
output-high;
bias-disable = <0>; //no pull
qcom,dtest = <2>; //DTEST2
power-source = <3>; //VPH_PWR
};
};
/*case_therm {
cas_therm_default: cas_therm_default {
pins = "mpp4";
function = "analog";
input-enable;
qcom,amux-route = <3>;
};
};*/
//add lizhongyu modify for niou PWM backlight --- end
pm8953_vadc: vadc@3100 {
compatible = "qcom,qpnp-vadc";
reg = <0x3100 0x100>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set";
qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1800>;
qcom,vadc-poll-eoc;
#thermal-sensor-cells = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pa_therm1_default /*&cas_therm_default*/>; //chanage lizhongyu modify for niou PWM backlight
chan@5 {
label = "vcoin";
reg = <5>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <1>;
qcom,calibration-type = "absolute";
qcom,scale-function = <0>;
qcom,hw-settle-time = <0>;
qcom,fast-avg-setup = <0>;
};
//add lizhongyu modify for niou PWM backlight --- start
/* pm8953_1: qcom,pm8953@1 {
compatible = "qcom,spmi-pmic";
reg = <0x1 SPMI_USID>;
#address-cells = <1>;
#size-cells = <1>;
pm8953_pwm: qcom,pwms@bc00 {
status = "disabled";
compatible = "qcom,pwm-lpg";
reg = <0xbc00 0x100>;
reg-names = "lpg-base";
#pwm-cells = <2>;
};
};*/
pm8953_1: qcom,pm8953@1 {
status = "ok";
compatible = "qcom,spmi-pmic";
reg = <0x1 SPMI_USID>;
#address-cells = <1>;
#size-cells = <1>;
pm8953_pwm: pwms@bc00 {
compatible = "qcom,qpnp-pwm";
reg = <0xbc00 0x100>;
reg-names = "qpnp-lpg-channel-base";
qcom,channel-id = <0>;
qcom,supported-sizes = <6>, <9>;
#pwm-cells = <2>;
qcom,dtest-line = <2>;
qcom,dtest-output = <2>;
};
};
//end lizhongyu modify for niou PWM backlight --- end
};
内核中优化PWM输出的占空比:
kernel\msm-4.9\drivers\video\fbdev\msm\mdss_dsi_panel.c
static void mdss_dsi_panel_bklt_pwm(struct mdss_dsi_ctrl_pdata *ctrl, int level)
{
int ret;
u32 duty;
u32 period_ns;
if (ctrl->pwm_bl == NULL) {
pr_err("%s: no PWM\n", __func__);
return;
}
if (level == 0) {
if (ctrl->pwm_enabled) {
ret = pwm_config(ctrl->pwm_bl, 0,
ctrl->pwm_period * NSEC_PER_USEC);
if (ret)
pr_err("%s: pwm_config() failed err=%d.\n",
__func__, ret);
pwm_disable(ctrl->pwm_bl);
}
ctrl->pwm_enabled = 0;
return;
}
duty = level * ctrl->pwm_period; //pwm_period=100 pwm_gpio=1271
duty /= ctrl->bklt_max; //ctrl->bklt_max=4095
pr_debug("%s: bklt_ctrl=%d pwm_period=%d pwm_gpio=%d pwm_lpg_chan=%d\n",
__func__, ctrl->bklt_ctrl, ctrl->pwm_period,
ctrl->pwm_pmic_gpio, ctrl->pwm_lpg_chan);
pr_debug("%s: ndx=%d level=%d duty=%d\n", __func__,
ctrl->ndx, level, duty);
//添加优化代码
//duty=40<--->100 //duty=40 level=1638 pwm_period=100 //duty=3 level=161
if((duty>=40)&&(duty<=60)){ //duty=40 <==>255 //duty=100 <==>10
duty= duty-20;
}
//end add
if (ctrl->pwm_period >= USEC_PER_SEC) {
ret = pwm_config_us(ctrl->pwm_bl, duty, ctrl->pwm_period);
if (ret) {
pr_err("%s: pwm_config_us() failed err=%d.\n",
__func__, ret);
return;
}
} else {
period_ns = ctrl->pwm_period * NSEC_PER_USEC;
ret = pwm_config(ctrl->pwm_bl,
level * period_ns / ctrl->bklt_max,
period_ns);
if (ret) {
pr_err("%s: pwm_config() failed err=%d.\n",
__func__, ret);
return;
}
}
................................................................
4.3 修改BP测,将PMIC的MPP4这个管脚配置成PWM模式
修改BP测,将PMIC的MPP4这个管脚配置成PWM模式,否则系统启动时会报以下错误:
[ 32.370588] qpnp_pwm_config: Failed to configure PWM mode
[ 32.377116] mdss_dsi_panel_bklt_pwm: pwm_config() failed err=-19.
........................................................................
[ 74.704024] qpnp_pwm_config: Failed to configure PWM mode
[ 74.704035] mdss_dsi_panel_bklt_pwm: pwm_config() failed err=-19.
[ 74.713036] spmi spmi-0: error: impermissible write to peripheral sid:1 addr:0xbc44
[ 74.713049] qpnp_pwm_config: Failed to configure PWM mode
[ 74.713056] mdss_dsi_panel_bklt_pwm: pwm_config() failed err=-19.
[ 74.717835] spmi spmi-0: error: impermissible write to peripheral sid:1 addr:0xbc44
[ 74.717848] qpnp_pwm_config: Failed to configure PWM mode
[ 74.717855] mdss_dsi_panel_bklt_pwm: pwm_config() failed err=-19.
具体修改路径如下:
mdm/Tz.BF.4.0.5\trustzone_images\core\systemdrivers\pmic\config\msm8953_pm8950\src\pm_spmi_config.c
修改之后编译将devcfg.mbn和之前编译的内核和lk编译的img文件烧录系统即可。
参考:android7.1+msm8937背光控制