come from : https://blog.csdn.net/u012719256/article/details/54290565
0. fb0以及背光注册流程
// mdss_fb.c
mdss_fb_probe
// fbi 结构赋值
mdss_fb_register(struct msm_fb_data_type *mfd)
struct fb_info *fbi = mfd->fbi;
.....
fix = &fbi->fix;
var = &fbi->var;
fbi->fbops = &mdss_fb_ops; //ops
static struct fb_ops mdss_fb_ops = {
...
.fb_blank = mdss_fb_blank, /* blank display */
...
};
mdss_fb_blank
mdss_fb_blank_sub
case FB_BLANK_UNBLANK:
mdss_fb_blank_unblank(mfd); //light up
break;
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
mdss_fb_blank_blank(mfd, req_power_state); // light off
break;
// 注册 backlight sys节点及set函数实现
led_classdev_register(&pdev->dev, &backlight_led)
static struct led_classdev backlight_led = {
.name = "lcd-backlight",
.brightness = MDSS_MAX_BL_BRIGHTNESS / 2,
.brightness_set = mdss_fb_set_bl_brightness, // 背光set函数
.max_brightness = MDSS_MAX_BL_BRIGHTNESS,
};
// register fbx
register_framebuffer(struct fb_info *fb_info) // fbmem.c
1.mdss_fb_blank_blank & unblank
// (drivers\video\msm\mdss\mdss_fb.c)
/* 亮灭lcm代码追踪 */
mdss_fb_blank_blank
mdss_fb_set_backlight // <1> 背光
mfd->mdp.off_fnc(mfd); // <2> 显示
mdss_fb_blank_unblank
ret = mfd->mdp.on_fnc(mfd);
mdss_fb_set_backlight
<1> 背光
// mdss_fb_set_backlight 函数追踪
mdss_fb_set_backlight // mdss_fb.c
mdss_panel_data->set_backlight
----------
// (drivers\video\msm\mdss\mdss_dsi_panel.c)
ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
case BL_WLED:
printk("zch===============set blk type = BL_WLED\n");
led_trigger_event(bl_led_trigger, bl_level);
break;
case BL_PWM:
printk("zch===============set blk type = BL_PWM\n");
mdss_dsi_panel_bklt_pwm(ctrl_pdata, bl_level);
break;
note: 背光的控制方式由 dsi中的 qcom,mdss-dsi-bl-pmic-control-type 属性值控制 !
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled" , “bl_ctrl_pwm”;
1
<2> 显示
// (drivers\video\msm\mdss\mdp3_ctrl.c) mdp3_interface->on_fnc mdp3_interface->off_fnc event_handler
mdp3_interface->on_fnc =mdp3_ctrl_on
mdp3_clk_enable(1, 0);
rc = panel->event_handler(panel,
MDSS_EVENT_LINK_READY, NULL); // 开电 ①
rc |= panel->event_handler(panel,
MDSS_EVENT_UNBLANK, NULL); // 执行亮屏指令 ②
rc |= panel->event_handler(panel,
MDSS_EVENT_PANEL_ON, NULL);
mdp3_clk_enable(0, 0);
mdp3_interface->off_fnc = mdp3_ctrl_off;
rc = panel->event_handler(panel, MDSS_EVENT_BLANK, // 执行灭屏指令 ②
(void *) (long int)mfd->panel_power_state);
rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, // 关电 ①
(void *) (long int)mfd->panel_power_state);
① 开关panel电源
// mdss_dsi.c event_handler MDSS_EVENT_LINK_READY|MDSS_EVENT_PANEL_OFF
dsi_panel_device_register
ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
mdss_dsi_event_handler
MDSS_EVENT_LINK_READY|MDSS_EVENT_PANEL_OFF
mdss_dsi_on | mdss_dsi_off
mdss_dsi_panel_power_ctrl(struct mdss_panel_data * pdata, int power_state)(struct mdss_panel_data *pdata,int power_state)
case MDSS_PANEL_POWER_OFF:
mdss_dsi_panel_power_off(pdata); // ☆
case MDSS_PANEL_POWER_ON:
mdss_dsi_panel_power_on(pdata); // ☆
② 开关panel
/* MDSS_EVENT_UNBLANK | MDSS_EVENT_BLANK (drivers\video\msm\mdss\mdss_dsi.c)*/
mdss_dsi_event_handler
case MDSS_EVENT_UNBLANK:
if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE)
rc = mdss_dsi_unblank(pdata); // ☆
break;
case MDSS_EVENT_PANEL_ON:
ctrl_pdata->ctrl_state |= CTRL_STATE_MDP_ACTIVE;
if (ctrl_pdata->on_cmds.link_state == DSI_HS_MODE)
rc = mdss_dsi_unblank(pdata);
pdata->panel_info.esd_rdy = true;
break;
case MDSS_EVENT_BLANK:
if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE)
rc = mdss_dsi_blank(pdata, power_state); // ☆
break;
case MDSS_EVENT_PANEL_OFF:
ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
rc = mdss_dsi_blank(pdata, power_state);
rc = mdss_dsi_off(pdata, power_state);
break;
----------
// mdss_dsi_unblank |mdss_dsi_blank 函数追踪
mdss_dsi_unblank
ATRACE_BEGIN("dsi_panel_on");
mdss_dsi_ctrl_pdata ctrl_pdata->on(pdata);
ATRACE_END("dsi_panel_on");
mdss_dsi_blank
ATRACE_BEGIN("dsi_panel_off");
mdss_dsi_ctrl_pdata ctrl_pdata->off(pdata);
ATRACE_END("dsi_panel_off");
----------
// 解析lcm dts ,开关panel 回调函数赋值 (drivers\video\msm\mdss\Mdss_dsi_panel.c)
/* 0.解析lcm的dtsi,开关屏函数赋值 */
mdss_dsi_panel_init
mdss_dsi_ctrl_pdata ctrl_pdata->on = mdss_dsi_panel_on;
mdss_dsi_ctrl_pdata ctrl_pdata->off = mdss_dsi_panel_off;
/* 1. 解析 on/off cmd data */
mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds,
"qcom,mdss-dsi-on-command","qcom,mdss-dsi-on-command-state");
mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds,
"qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state");
/* 2. 执行开关屏命令参数函数 */
mdss_dsi_panel_on
mdss_dsi_panel_cmds_send(ctrl, on_cmds, CMD_REQ_COMMIT);
mdss_dsi_panel_off
mdss_dsi_panel_cmds_send(ctrl, &ctrl->off_cmds, CMD_REQ_COMMIT);
2.打印背光亮灭
diff --git a/kernel/msm-3.18/drivers/leds/leds-qpnp-wled.c b/kernel/msm-3.18/drivers/leds/leds-qpnp-wled.c
index 06b80c8..fbf3403 100644
--- a/kernel/msm-3.18/drivers/leds/leds-qpnp-wled.c
+++ b/kernel/msm-3.18/drivers/leds/leds-qpnp-wled.c
@@ -199,7 +199,7 @@
#define QPNP_WLED_AVDD_MIN_TRIM_VALUE 0x0
#define QPNP_WLED_AVDD_MAX_TRIM_VALUE 0xF
#define QPNP_WLED_AVDD_SET_BIT BIT(4)
-
+ int myflag;
@@ -841,16 +843,29 @@ static void qpnp_wled_set(struct led_classdev *led_cdev,
enum led_brightness level)
{
struct qpnp_wled *wled;
-
+
wled = container_of(led_cdev, struct qpnp_wled, cdev);
if (level < LED_OFF)
level = LED_OFF;
else if (level > wled->cdev.max_brightness)
level = wled->cdev.max_brightness;
-
wled->cdev.brightness = level;
- schedule_work(&wled->work);
+if(level ==0)
+{
+ printk("zch--- set backlight brightness= %d\n",level);
+
+ myflag =1;
+}
+else
+{
+if(myflag)
+{
+ myflag =0;
+ printk("zch--- set backlight brightness= %d\n",level);
+}
+
+} schedule_work(&wled->work);
}
static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)