msm: mdss: force display panel status dead
Display panels can be in a bad state which is most likely caused by ESD shocks. Display s/w has the ability to detect panel state and if it is bad, s/w reset and recover the panel from that bad state. For the testability purpose, this change simulates a panel dead state, for example: adb shell 'echo 5 > /sys/devices/virtual/graphics/fb0/msm_fb_panel_status' will simulate a display dead state after 5 detections, which is about 25 seconds if the esd detection feature is enabled with periodic detections every 5 seconds. Change-Id: Ia28e80ffcbfe45a59ae65e0e26b558a467b50863 Signed-off-by: Huaibin Yang <huaibiny@codeaurora.org>
This commit is contained in:
parent
729e8d3d5b
commit
7aa48794fc
3 changed files with 45 additions and 9 deletions
|
@ -55,9 +55,11 @@ static void mdss_report_panel_dead(struct dsi_status_data *pstatus_data)
|
||||||
* after 'interval' milliseconds. If the TE IRQ is not ready, the workqueue
|
* after 'interval' milliseconds. If the TE IRQ is not ready, the workqueue
|
||||||
* gets re-scheduled. Otherwise, report the panel to be dead due to ESD attack.
|
* gets re-scheduled. Otherwise, report the panel to be dead due to ESD attack.
|
||||||
*/
|
*/
|
||||||
static void mdss_check_te_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
|
static bool mdss_check_te_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
|
||||||
struct dsi_status_data *pstatus_data, uint32_t interval)
|
struct dsi_status_data *pstatus_data, uint32_t interval)
|
||||||
{
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* During resume, the panel status will be ON but due to race condition
|
* During resume, the panel status will be ON but due to race condition
|
||||||
* between ESD thread and display UNBLANK (or rather can be put as
|
* between ESD thread and display UNBLANK (or rather can be put as
|
||||||
|
@ -66,14 +68,14 @@ static void mdss_check_te_status(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
|
||||||
* first TE interrupt arrives after the TE IRQ line is enabled. For such
|
* first TE interrupt arrives after the TE IRQ line is enabled. For such
|
||||||
* cases, re-schedule the ESD thread.
|
* cases, re-schedule the ESD thread.
|
||||||
*/
|
*/
|
||||||
if (!atomic_read(&ctrl_pdata->te_irq_ready)) {
|
ret = !atomic_read(&ctrl_pdata->te_irq_ready);
|
||||||
|
if (ret) {
|
||||||
schedule_delayed_work(&pstatus_data->check_status,
|
schedule_delayed_work(&pstatus_data->check_status,
|
||||||
msecs_to_jiffies(interval));
|
msecs_to_jiffies(interval));
|
||||||
pr_debug("%s: TE IRQ line not enabled yet\n", __func__);
|
pr_debug("%s: TE IRQ line not enabled yet\n", __func__);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mdss_report_panel_dead(pstatus_data);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -135,8 +137,10 @@ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctrl_pdata->status_mode == ESD_TE) {
|
if (ctrl_pdata->status_mode == ESD_TE) {
|
||||||
mdss_check_te_status(ctrl_pdata, pstatus_data, interval);
|
if (mdss_check_te_status(ctrl_pdata, pstatus_data, interval))
|
||||||
return;
|
return;
|
||||||
|
else
|
||||||
|
goto status_dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -193,6 +197,18 @@ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval)
|
||||||
schedule_delayed_work(&pstatus_data->check_status,
|
schedule_delayed_work(&pstatus_data->check_status,
|
||||||
msecs_to_jiffies(interval));
|
msecs_to_jiffies(interval));
|
||||||
else
|
else
|
||||||
|
goto status_dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata->panel_info.panel_force_dead) {
|
||||||
|
pr_debug("force_dead=%d\n", pdata->panel_info.panel_force_dead);
|
||||||
|
pdata->panel_info.panel_force_dead--;
|
||||||
|
if (!pdata->panel_info.panel_force_dead)
|
||||||
|
goto status_dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
status_dead:
|
||||||
mdss_report_panel_dead(pstatus_data);
|
mdss_report_panel_dead(pstatus_data);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -573,6 +573,25 @@ static ssize_t mdss_fb_get_panel_status(struct device *dev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t mdss_fb_force_panel_dead(struct device *dev,
|
||||||
|
struct device_attribute *attr, const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||||
|
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
|
||||||
|
struct mdss_panel_data *pdata;
|
||||||
|
|
||||||
|
pdata = dev_get_platdata(&mfd->pdev->dev);
|
||||||
|
if (!pdata) {
|
||||||
|
pr_err("no panel connected!\n");
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sscanf(buf, "%d", &pdata->panel_info.panel_force_dead) != 1)
|
||||||
|
pr_err("sccanf buf error!\n");
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mdss_fb_blanking_mode_switch() - Function triggers dynamic mode switch
|
* mdss_fb_blanking_mode_switch() - Function triggers dynamic mode switch
|
||||||
* @mfd: Framebuffer data structure for display
|
* @mfd: Framebuffer data structure for display
|
||||||
|
@ -725,8 +744,8 @@ static DEVICE_ATTR(msm_fb_src_split_info, S_IRUGO, mdss_fb_get_src_split_info,
|
||||||
NULL);
|
NULL);
|
||||||
static DEVICE_ATTR(msm_fb_thermal_level, S_IRUGO | S_IWUSR,
|
static DEVICE_ATTR(msm_fb_thermal_level, S_IRUGO | S_IWUSR,
|
||||||
mdss_fb_get_thermal_level, mdss_fb_set_thermal_level);
|
mdss_fb_get_thermal_level, mdss_fb_set_thermal_level);
|
||||||
static DEVICE_ATTR(msm_fb_panel_status, S_IRUGO,
|
static DEVICE_ATTR(msm_fb_panel_status, S_IRUGO | S_IWUSR,
|
||||||
mdss_fb_get_panel_status, NULL);
|
mdss_fb_get_panel_status, mdss_fb_force_panel_dead);
|
||||||
static DEVICE_ATTR(msm_fb_dfps_mode, S_IRUGO | S_IWUSR,
|
static DEVICE_ATTR(msm_fb_dfps_mode, S_IRUGO | S_IWUSR,
|
||||||
mdss_fb_get_dfps_mode, mdss_fb_change_dfps_mode);
|
mdss_fb_get_dfps_mode, mdss_fb_change_dfps_mode);
|
||||||
static struct attribute *mdss_fb_attrs[] = {
|
static struct attribute *mdss_fb_attrs[] = {
|
||||||
|
|
|
@ -436,6 +436,7 @@ struct mdss_panel_info {
|
||||||
int blank_state;
|
int blank_state;
|
||||||
|
|
||||||
uint32_t panel_dead;
|
uint32_t panel_dead;
|
||||||
|
u32 panel_force_dead;
|
||||||
u32 panel_orientation;
|
u32 panel_orientation;
|
||||||
bool dynamic_switch_pending;
|
bool dynamic_switch_pending;
|
||||||
bool is_lpm_mode;
|
bool is_lpm_mode;
|
||||||
|
|
Loading…
Add table
Reference in a new issue