Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24ee98b6 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge changes...

Merge changes I8cecb007,Ib59d47c4,I028fb3e8,Icd27765a,I4d056b04,Iaea88fd8,I6f8fbe18,I7f39c8d5 into dev/msm-4.14-display

* changes:
  drm/msm/dsi-staging: fix backlight update and dsi off race condition
  drm/msm/sde: Restarting ESD status check after Doze mode
  drm/msm/dsi-staging: validate TE GPIO prior to registering IRQ
  drm/msm/dsi-staging: initialize esd completion early
  drm/msm: add debugfs support to change ESD check interval
  drm/msm/dsi-staging: enable panel te irq only during esd check
  drm/msm/dsi-staging: add debugfs support to switch panel esd check mode
  drm/msm/dsi-staging: add support for te based esd check
parents d1c8fb11 50186726
Loading
Loading
Loading
Loading
+316 −32
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include <linux/list.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/err.h>

#include "msm_drv.h"
@@ -36,6 +37,7 @@
#define NO_OVERRIDE -1

#define MISR_BUFF_SIZE	256
#define ESD_MODE_STRING_MAX_LEN 256

#define MAX_NAME_SIZE	64

@@ -123,8 +125,11 @@ int dsi_display_set_backlight(struct drm_connector *connector,

	panel = dsi_display->panel;

	if (!dsi_panel_initialized(panel))
		return -EINVAL;
	mutex_lock(&panel->panel_lock);
	if (!dsi_panel_initialized(panel)) {
		rc = -EINVAL;
		goto error;
	}

	panel->bl_config.bl_level = bl_lvl;

@@ -159,6 +164,7 @@ int dsi_display_set_backlight(struct drm_connector *connector,
	}

error:
	mutex_unlock(&panel->panel_lock);
	return rc;
}

@@ -305,6 +311,102 @@ static void dsi_display_aspace_cb_locked(void *cb_data, bool is_detach)
	dsi_panel_release_panel_lock(display->panel);
}

static irqreturn_t dsi_display_panel_te_irq_handler(int irq, void *data)
{
	struct dsi_display *display = (struct dsi_display *)data;

	/*
	 * This irq handler is used for sole purpose of identifying
	 * ESD attacks on panel and we can safely assume IRQ_HANDLED
	 * in case of display not being initialized yet
	 */
	if (!display)
		return IRQ_HANDLED;

	complete_all(&display->esd_te_gate);
	return IRQ_HANDLED;
}

static void dsi_display_change_te_irq_status(struct dsi_display *display,
					bool enable)
{
	if (!display) {
		pr_err("Invalid params\n");
		return;
	}

	/* Handle unbalanced irq enable/disbale calls */
	if (enable && !display->is_te_irq_enabled) {
		enable_irq(gpio_to_irq(display->disp_te_gpio));
		display->is_te_irq_enabled = true;
	} else if (!enable && display->is_te_irq_enabled) {
		disable_irq(gpio_to_irq(display->disp_te_gpio));
		display->is_te_irq_enabled = false;
	}
}

static void dsi_display_register_te_irq(struct dsi_display *display)
{
	int rc = 0;
	struct platform_device *pdev;
	struct device *dev;

	pdev = display->pdev;
	if (!pdev) {
		pr_err("invalid platform device\n");
		return;
	}

	dev = &pdev->dev;
	if (!dev) {
		pr_err("invalid device\n");
		return;
	}

	if (!gpio_is_valid(display->disp_te_gpio)) {
		rc = -EINVAL;
		goto error;
	}

	init_completion(&display->esd_te_gate);

	rc = devm_request_irq(dev, gpio_to_irq(display->disp_te_gpio),
			dsi_display_panel_te_irq_handler, IRQF_TRIGGER_FALLING,
			"TE_GPIO", display);
	if (rc) {
		pr_err("TE request_irq failed for ESD rc:%d\n", rc);
		goto error;
	}

	disable_irq(gpio_to_irq(display->disp_te_gpio));
	display->is_te_irq_enabled = false;

	return;

error:
	/* disable the TE based ESD check */
	pr_warn("Unable to register for TE IRQ\n");
	if (display->panel->esd_config.status_mode == ESD_MODE_PANEL_TE)
		display->panel->esd_config.esd_enabled = false;
}

static bool dsi_display_is_te_based_esd(struct dsi_display *display)
{
	u32 status_mode = 0;

	if (!display->panel) {
		pr_err("Invalid panel data\n");
		return false;
	}

	status_mode = display->panel->esd_config.status_mode;

	if (status_mode == ESD_MODE_PANEL_TE &&
			gpio_is_valid(display->disp_te_gpio))
		return true;
	return false;
}

/* Allocate memory for cmd dma tx buffer */
static int dsi_host_alloc_cmd_tx_buffer(struct dsi_display *display)
{
@@ -415,6 +517,27 @@ static bool dsi_display_validate_reg_read(struct dsi_panel *panel)
	return false;
}

static void dsi_display_parse_te_gpio(struct dsi_display *display)
{
	struct platform_device *pdev;
	struct device *dev;

	pdev = display->pdev;
	if (!pdev) {
		pr_err("Inavlid platform device\n");
		return;
	}

	dev = &pdev->dev;
	if (!dev) {
		pr_err("Inavlid platform device\n");
		return;
	}

	display->disp_te_gpio = of_get_named_gpio(dev->of_node,
					"qcom,platform-te-gpio", 0);
}

static int dsi_display_read_status(struct dsi_display_ctrl *ctrl,
		struct dsi_panel *panel)
{
@@ -559,10 +682,19 @@ static int dsi_display_status_bta_request(struct dsi_display *display)

static int dsi_display_status_check_te(struct dsi_display *display)
{
	int rc = 0;
	int rc = 1;
	int const esd_te_timeout = msecs_to_jiffies(3*20);

	pr_debug(" ++\n");
	/* TODO: wait for TE interrupt from panel */
	dsi_display_change_te_irq_status(display, true);

	reinit_completion(&display->esd_te_gate);
	if (!wait_for_completion_timeout(&display->esd_te_gate,
				esd_te_timeout)) {
		pr_err("ESD check failed\n");
		rc = -EINVAL;
	}

	dsi_display_change_te_irq_status(display, false);

	return rc;
}
@@ -913,6 +1045,71 @@ static ssize_t debugfs_misr_setup(struct file *file,
	return rc;
}

static ssize_t debugfs_misr_read(struct file *file,
				 char __user *user_buf,
				 size_t user_len,
				 loff_t *ppos)
{
	struct dsi_display *display = file->private_data;
	char *buf;
	u32 len = 0;
	int rc = 0;
	struct dsi_ctrl *dsi_ctrl;
	int i;
	u32 misr;
	size_t max_len = min_t(size_t, user_len, MISR_BUFF_SIZE);

	if (!display)
		return -ENODEV;

	if (*ppos)
		return 0;

	buf = kzalloc(max_len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	mutex_lock(&display->display_lock);
	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
			DSI_CORE_CLK, DSI_CLK_ON);
	if (rc) {
		pr_err("[%s] failed to enable DSI core clocks, rc=%d\n",
		       display->name, rc);
		goto error;
	}

	for (i = 0; i < display->ctrl_count; i++) {
		dsi_ctrl = display->ctrl[i].ctrl;
		misr = dsi_ctrl_collect_misr(display->ctrl[i].ctrl);

		len += snprintf((buf + len), max_len - len,
			"DSI_%d MISR: 0x%x\n", dsi_ctrl->cell_index, misr);

		if (len >= max_len)
			break;
	}

	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
			DSI_CORE_CLK, DSI_CLK_OFF);
	if (rc) {
		pr_err("[%s] failed to disable DSI core clocks, rc=%d\n",
		       display->name, rc);
		goto error;
	}

	if (copy_to_user(user_buf, buf, len)) {
		rc = -EFAULT;
		goto error;
	}

	*ppos += len;

error:
	mutex_unlock(&display->display_lock);
	kfree(buf);
	return len;
}

static ssize_t debugfs_esd_trigger_check(struct file *file,
				  const char __user *user_buf,
				  size_t user_len,
@@ -969,19 +1166,16 @@ static ssize_t debugfs_esd_trigger_check(struct file *file,
	return rc;
}

static ssize_t debugfs_misr_read(struct file *file,
				 char __user *user_buf,
static ssize_t debugfs_alter_esd_check_mode(struct file *file,
				  const char __user *user_buf,
				  size_t user_len,
				  loff_t *ppos)
{
	struct dsi_display *display = file->private_data;
	struct drm_panel_esd_config *esd_config;
	char *buf;
	u32 len = 0;
	int rc = 0;
	struct dsi_ctrl *dsi_ctrl;
	int i;
	u32 misr;
	size_t max_len = min_t(size_t, user_len, MISR_BUFF_SIZE);
	size_t len = min_t(size_t, user_len, ESD_MODE_STRING_MAX_LEN);

	if (!display)
		return -ENODEV;
@@ -989,35 +1183,102 @@ static ssize_t debugfs_misr_read(struct file *file,
	if (*ppos)
		return 0;

	buf = kzalloc(max_len, GFP_KERNEL);
	buf = kzalloc(len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	mutex_lock(&display->display_lock);
	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
			DSI_CORE_CLK, DSI_CLK_ON);
	if (rc) {
		pr_err("[%s] failed to enable DSI core clocks, rc=%d\n",
		       display->name, rc);
	if (copy_from_user(buf, user_buf, user_len)) {
		rc = -EINVAL;
		goto error;
	}

	for (i = 0; i < display->ctrl_count; i++) {
		dsi_ctrl = display->ctrl[i].ctrl;
		misr = dsi_ctrl_collect_misr(display->ctrl[i].ctrl);
	buf[len] = '\0'; /* terminate the string */
	if (!display->panel) {
		rc = -EINVAL;
		goto error;
	}

		len += snprintf((buf + len), max_len - len,
			"DSI_%d MISR: 0x%x\n", dsi_ctrl->cell_index, misr);
	esd_config = &display->panel->esd_config;
	if (!esd_config) {
		pr_err("Invalid panel esd config\n");
		rc = -EINVAL;
		goto error;
	}

		if (len >= max_len)
			break;
	if (!esd_config->esd_enabled)
		goto error;

	if (!strcmp(buf, "te_signal_check\n")) {
		esd_config->status_mode = ESD_MODE_PANEL_TE;
		dsi_display_change_te_irq_status(display, true);
	}

	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
			DSI_CORE_CLK, DSI_CLK_OFF);
	if (!strcmp(buf, "reg_read\n")) {
		rc = dsi_panel_parse_esd_reg_read_configs(display->panel);
		if (rc) {
		pr_err("[%s] failed to disable DSI core clocks, rc=%d\n",
		       display->name, rc);
			pr_err("failed to alter esd check mode,rc=%d\n",
						rc);
			rc = user_len;
			goto error;
		}
		esd_config->status_mode = ESD_MODE_REG_READ;
		if (dsi_display_is_te_based_esd(display))
			dsi_display_change_te_irq_status(display, false);
	}

	rc = len;
error:
	kfree(buf);
	return rc;
}

static ssize_t debugfs_read_esd_check_mode(struct file *file,
				 char __user *user_buf,
				 size_t user_len,
				 loff_t *ppos)
{
	struct dsi_display *display = file->private_data;
	struct drm_panel_esd_config *esd_config;
	char *buf;
	int rc = 0;
	size_t len = min_t(size_t, user_len, ESD_MODE_STRING_MAX_LEN);

	if (!display)
		return -ENODEV;

	if (*ppos)
		return 0;

	if (!display->panel) {
		pr_err("invalid panel data\n");
		return -EINVAL;
	}

	buf = kzalloc(len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	esd_config = &display->panel->esd_config;
	if (!esd_config) {
		pr_err("Invalid panel esd config\n");
		rc = -EINVAL;
		goto error;
	}

	if (!esd_config->esd_enabled) {
		rc = snprintf(buf, len, "ESD feature not enabled");
		goto output_mode;
	}

	if (esd_config->status_mode == ESD_MODE_REG_READ)
		rc = snprintf(buf, len, "reg_read");

	if (esd_config->status_mode == ESD_MODE_PANEL_TE)
		rc = snprintf(buf, len, "te_signal_check");

output_mode:
	if (!rc) {
		rc = -EINVAL;
		goto error;
	}

@@ -1029,7 +1290,6 @@ static ssize_t debugfs_misr_read(struct file *file,
	*ppos += len;

error:
	mutex_unlock(&display->display_lock);
	kfree(buf);
	return len;
}
@@ -1050,6 +1310,12 @@ static const struct file_operations esd_trigger_fops = {
	.write = debugfs_esd_trigger_check,
};

static const struct file_operations esd_check_mode_fops = {
	.open = simple_open,
	.write = debugfs_alter_esd_check_mode,
	.read = debugfs_read_esd_check_mode,
};

static int dsi_display_debugfs_init(struct dsi_display *display)
{
	int rc = 0;
@@ -1089,6 +1355,18 @@ static int dsi_display_debugfs_init(struct dsi_display *display)
		goto error_remove_dir;
	}

	dump_file = debugfs_create_file("esd_check_mode",
					0644,
					dir,
					display,
					&esd_check_mode_fops);
	if (IS_ERR_OR_NULL(dump_file)) {
		rc = PTR_ERR(dump_file);
		pr_err("[%s] debugfs for esd check mode failed, rc=%d\n",
		       display->name, rc);
		goto error_remove_dir;
	}

	misr_data = debugfs_create_file("misr_data",
					0600,
					dir,
@@ -3020,6 +3298,9 @@ static int dsi_display_parse_dt(struct dsi_display *display)
		goto error;
	}

	/* Parse TE gpio */
	dsi_display_parse_te_gpio(display);

	pr_debug("success\n");
error:
	return rc;
@@ -4120,6 +4401,9 @@ static int dsi_display_bind(struct device *dev,
		}
	}

	/* register te irq handler */
	dsi_display_register_te_irq(display);

	goto error;

error_host_deinit:
+6 −0
Original line number Diff line number Diff line
@@ -135,6 +135,9 @@ struct dsi_display_clk_info {
 * @is_cont_splash_enabled:  Is continuous splash enabled
 * @sw_te_using_wd:   Is software te enabled
 * @display_lock:     Mutex for dsi_display interface.
 * @disp_te_gpio:     GPIO for panel TE interrupt.
 * @is_te_irq_enabled:bool to specify whether TE interrupt is enabled.
 * @esd_te_gate:      completion gate to signal TE interrupt.
 * @ctrl_count:       Number of DSI interfaces required by panel.
 * @ctrl:             Controller information for DSI display.
 * @panel:            Handle to DSI panel.
@@ -178,6 +181,9 @@ struct dsi_display {
	bool is_cont_splash_enabled;
	bool sw_te_using_wd;
	struct mutex display_lock;
	int disp_te_gpio;
	bool is_te_irq_enabled;
	struct completion esd_te_gate;

	u32 ctrl_count;
	struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY];
+76 −53
Original line number Diff line number Diff line
@@ -610,13 +610,10 @@ static int dsi_panel_update_backlight(struct dsi_panel *panel,

	dsi = &panel->mipi_device;

	mutex_lock(&panel->panel_lock);

	rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl);
	if (rc < 0)
		pr_err("failed to update dcs backlight:%d\n", bl_lvl);

	mutex_unlock(&panel->panel_lock);
	return rc;
}

@@ -631,7 +628,7 @@ int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl)
		rc = backlight_device_set_brightness(bl->raw_bd, bl_lvl);
		break;
	case DSI_BACKLIGHT_DCS:
		dsi_panel_update_backlight(panel, bl_lvl);
		rc = dsi_panel_update_backlight(panel, bl_lvl);
		break;
	default:
		pr_err("Backlight type(%d) not supported\n", bl->type);
@@ -2586,54 +2583,23 @@ static void dsi_panel_esd_config_deinit(struct drm_panel_esd_config *esd_config)
	kfree(esd_config->status_cmd.cmds);
}

static int dsi_panel_parse_esd_config(struct dsi_panel *panel)
int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel)
{
	struct drm_panel_esd_config *esd_config;
	int rc = 0;
	u32 tmp;
	u32 i, status_len, *lenp;
	struct property *data;
	const char *string;
	struct drm_panel_esd_config *esd_config;
	struct dsi_parser_utils *utils = &panel->utils;
	u8 *esd_mode = NULL;

	esd_config = &panel->esd_config;
	esd_config->status_mode = ESD_MODE_MAX;
	esd_config->esd_enabled = utils->read_bool(utils->data,
					"qcom,esd-check-enabled");

	if (!esd_config->esd_enabled)
		return 0;

	rc = utils->read_string(utils->data,
			"qcom,mdss-dsi-panel-status-check-mode", &string);
	if (!rc) {
		if (!strcmp(string, "bta_check")) {
			esd_config->status_mode = ESD_MODE_SW_BTA;
		} else if (!strcmp(string, "reg_read")) {
			esd_config->status_mode = ESD_MODE_REG_READ;
		} else if (!strcmp(string, "te_signal_check")) {
			if (panel->panel_mode == DSI_OP_CMD_MODE) {
				esd_config->status_mode = ESD_MODE_PANEL_TE;
			} else {
				pr_err("TE-ESD not valid for video mode\n");
				rc = -EINVAL;
				goto error;
			}
		} else {
			pr_err("No valid panel-status-check-mode string\n");
			rc = -EINVAL;
			goto error;
		}
	} else {
		pr_debug("status check method not defined!\n");
		rc = -EINVAL;
		goto error;
	if (!panel) {
		pr_err("Invalid Params\n");
		return -EINVAL;
	}

	if ((esd_config->status_mode == ESD_MODE_SW_BTA) ||
		(esd_config->status_mode == ESD_MODE_PANEL_TE))
		return 0;
	esd_config = &panel->esd_config;
	if (!esd_config)
		return -EINVAL;

	dsi_panel_parse_cmd_sets_sub(&esd_config->status_cmd,
				DSI_CMD_SET_PANEL_STATUS, utils);
@@ -2708,8 +2674,10 @@ static int dsi_panel_parse_esd_config(struct dsi_panel *panel)
	}

	esd_config->status_buf = kzalloc(SZ_4K, GFP_KERNEL);
	if (!esd_config->status_buf)
	if (!esd_config->status_buf) {
		rc = -ENOMEM;
		goto error4;
	}

	rc = utils->read_u32_array(utils->data,
		"qcom,mdss-dsi-panel-status-value",
@@ -2720,15 +2688,6 @@ static int dsi_panel_parse_esd_config(struct dsi_panel *panel)
				esd_config->groups * status_len);
	}

	if (panel->esd_config.status_mode == ESD_MODE_REG_READ)
		esd_mode = "register_read";
	else if (panel->esd_config.status_mode == ESD_MODE_SW_BTA)
		esd_mode = "bta_trigger";
	else if (panel->esd_config.status_mode ==  ESD_MODE_PANEL_TE)
		esd_mode = "te_check";

	pr_info("ESD enabled with mode: %s\n", esd_mode);

	return 0;

error4:
@@ -2740,6 +2699,70 @@ static int dsi_panel_parse_esd_config(struct dsi_panel *panel)
	kfree(esd_config->status_cmds_rlen);
error1:
	kfree(esd_config->status_cmd.cmds);
error:
	return rc;
}

static int dsi_panel_parse_esd_config(struct dsi_panel *panel)
{
	int rc = 0;
	const char *string;
	struct drm_panel_esd_config *esd_config;
	struct dsi_parser_utils *utils = &panel->utils;
	u8 *esd_mode = NULL;

	esd_config = &panel->esd_config;
	esd_config->status_mode = ESD_MODE_MAX;
	esd_config->esd_enabled = utils->read_bool(utils->data,
		"qcom,esd-check-enabled");

	if (!esd_config->esd_enabled)
		return 0;

	rc = utils->read_string(utils->data,
			"qcom,mdss-dsi-panel-status-check-mode", &string);
	if (!rc) {
		if (!strcmp(string, "bta_check")) {
			esd_config->status_mode = ESD_MODE_SW_BTA;
		} else if (!strcmp(string, "reg_read")) {
			esd_config->status_mode = ESD_MODE_REG_READ;
		} else if (!strcmp(string, "te_signal_check")) {
			if (panel->panel_mode == DSI_OP_CMD_MODE) {
				esd_config->status_mode = ESD_MODE_PANEL_TE;
			} else {
				pr_err("TE-ESD not valid for video mode\n");
				rc = -EINVAL;
				goto error;
			}
		} else {
			pr_err("No valid panel-status-check-mode string\n");
			rc = -EINVAL;
			goto error;
		}
	} else {
		pr_debug("status check method not defined!\n");
		rc = -EINVAL;
		goto error;
	}

	if (panel->esd_config.status_mode == ESD_MODE_REG_READ) {
		rc = dsi_panel_parse_esd_reg_read_configs(panel);
		if (rc) {
			pr_err("failed to parse esd reg read mode params, rc=%d\n",
						rc);
			goto error;
		}
		esd_mode = "register_read";
	} else if (panel->esd_config.status_mode == ESD_MODE_SW_BTA) {
		esd_mode = "bta_trigger";
	} else if (panel->esd_config.status_mode ==  ESD_MODE_PANEL_TE) {
		esd_mode = "te_check";
	}

	pr_info("ESD enabled with mode: %s\n", esd_mode);

	return 0;

error:
	panel->esd_config.esd_enabled = false;
	return rc;
+8 −0
Original line number Diff line number Diff line
@@ -282,4 +282,12 @@ int dsi_panel_post_switch(struct dsi_panel *panel);

void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width);

struct dsi_panel *dsi_panel_ext_bridge_get(struct device *parent,
				struct device_node *of_node,
				int topology_override);

int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel);

void dsi_panel_ext_bridge_put(struct dsi_panel *panel);

#endif /* _DSI_PANEL_H_ */
+38 −7
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ static int sde_backlight_device_update_status(struct backlight_device *bd)
	struct sde_connector *c_conn;
	int bl_lvl;
	struct drm_event event;
	int rc = 0;

	brightness = bd->props.brightness;

@@ -97,11 +98,11 @@ static int sde_backlight_device_update_status(struct backlight_device *bd)
		event.length = sizeof(u32);
		msm_mode_object_event_notify(&c_conn->base.base,
				c_conn->base.dev, &event, (u8 *)&brightness);
		c_conn->ops.set_backlight(&c_conn->base,
		rc = c_conn->ops.set_backlight(&c_conn->base,
				c_conn->display, bl_lvl);
	}

	return 0;
	return rc;
}

static int sde_backlight_device_get_brightness(struct backlight_device *bd)
@@ -419,16 +420,32 @@ void sde_connector_schedule_status_work(struct drm_connector *connector,
	if (!c_conn)
		return;

	/* Return if there is no change in ESD status check condition */
	if (en == c_conn->esd_status_check)
		return;

	sde_connector_get_info(connector, &info);
	if (c_conn->ops.check_status &&
		(info.capabilities & MSM_DISPLAY_ESD_ENABLED)) {
		if (en)
		if (en) {
			u32 interval;

			/*
			 * If debugfs property is not set then take
			 * default value
			 */
			interval = c_conn->esd_status_interval ?
				c_conn->esd_status_interval :
					STATUS_CHECK_INTERVAL_MS;
			/* Schedule ESD status check */
			schedule_delayed_work(&c_conn->status_work,
				msecs_to_jiffies(STATUS_CHECK_INTERVAL_MS));
		else
				msecs_to_jiffies(interval));
			c_conn->esd_status_check = true;
		} else {
			/* Cancel any pending ESD status check */
			cancel_delayed_work_sync(&c_conn->status_work);
			c_conn->esd_status_check = false;
		}
	}
}

@@ -477,8 +494,12 @@ static int _sde_connector_update_power_locked(struct sde_connector *c_conn)
	}
	c_conn->last_panel_power_mode = mode;

	mutex_unlock(&c_conn->lock);
	if (mode != SDE_MODE_DPMS_ON)
		sde_connector_schedule_status_work(connector, false);
	else
		sde_connector_schedule_status_work(connector, true);
	mutex_lock(&c_conn->lock);

	return rc;
}
@@ -1516,10 +1537,14 @@ static int sde_connector_init_debugfs(struct drm_connector *connector)

	sde_connector_get_info(connector, &info);
	if (sde_connector->ops.check_status &&
		(info.capabilities & MSM_DISPLAY_ESD_ENABLED))
		(info.capabilities & MSM_DISPLAY_ESD_ENABLED)) {
		debugfs_create_u32("force_panel_dead", 0600,
				connector->debugfs_entry,
				&sde_connector->force_panel_dead);
		debugfs_create_u32("esd_status_interval", 0600,
				connector->debugfs_entry,
				&sde_connector->esd_status_interval);
	}

	if (!debugfs_create_bool("fb_kmap", 0600, connector->debugfs_entry,
			&sde_connector->fb_kmap)) {
@@ -1732,10 +1757,16 @@ static void sde_connector_check_status_work(struct work_struct *work)
	}

	if (rc > 0) {
		u32 interval;

		SDE_DEBUG("esd check status success conn_id: %d enc_id: %d\n",
				conn->base.base.id, conn->encoder->base.id);

		/* If debugfs property is not set then take default value */
		interval = conn->esd_status_interval ?
			conn->esd_status_interval : STATUS_CHECK_INTERVAL_MS;
		schedule_delayed_work(&conn->status_work,
			msecs_to_jiffies(STATUS_CHECK_INTERVAL_MS));
			msecs_to_jiffies(interval));
		return;
	}

Loading