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

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

Merge "drm/msm/dsi-staging: add debugfs support to switch panel esd check mode"

parents ad48d258 b7e79bc4
Loading
Loading
Loading
Loading
+175 −27
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
#define NO_OVERRIDE -1
#define NO_OVERRIDE -1


#define MISR_BUFF_SIZE	256
#define MISR_BUFF_SIZE	256
#define ESD_MODE_STRING_MAX_LEN 256


#define MAX_NAME_SIZE	64
#define MAX_NAME_SIZE	64


@@ -1027,6 +1028,71 @@ static ssize_t debugfs_misr_setup(struct file *file,
	return rc;
	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,
static ssize_t debugfs_esd_trigger_check(struct file *file,
				  const char __user *user_buf,
				  const char __user *user_buf,
				  size_t user_len,
				  size_t user_len,
@@ -1083,19 +1149,16 @@ static ssize_t debugfs_esd_trigger_check(struct file *file,
	return rc;
	return rc;
}
}


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


	if (!display)
	if (!display)
		return -ENODEV;
		return -ENODEV;
@@ -1103,35 +1166,103 @@ static ssize_t debugfs_misr_read(struct file *file,
	if (*ppos)
	if (*ppos)
		return 0;
		return 0;


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


	mutex_lock(&display->display_lock);
	if (copy_from_user(buf, user_buf, user_len)) {
	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
		rc = -EINVAL;
			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;
		goto error;
	}
	}


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


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


		if (len >= max_len)
	if (!esd_config->esd_enabled)
			break;
		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,
	if (!strcmp(buf, "reg_read\n")) {
			DSI_CORE_CLK, DSI_CLK_OFF);
		rc = dsi_panel_parse_esd_reg_read_configs(display->panel,
						display->panel_of);
		if (rc) {
		if (rc) {
		pr_err("[%s] failed to disable DSI core clocks, rc=%d\n",
			pr_err("failed to alter esd check mode,rc=%d\n",
		       display->name, rc);
						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;
		goto error;
	}
	}


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


error:
error:
	mutex_unlock(&display->display_lock);
	kfree(buf);
	kfree(buf);
	return len;
	return len;
}
}
@@ -1164,6 +1294,12 @@ static const struct file_operations esd_trigger_fops = {
	.write = debugfs_esd_trigger_check,
	.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)
static int dsi_display_debugfs_init(struct dsi_display *display)
{
{
	int rc = 0;
	int rc = 0;
@@ -1203,6 +1339,18 @@ static int dsi_display_debugfs_init(struct dsi_display *display)
		goto error_remove_dir;
		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",
	misr_data = debugfs_create_file("misr_data",
					0600,
					0600,
					dir,
					dir,
+76 −50
Original line number Original line Diff line number Diff line
@@ -2627,54 +2627,23 @@ static void dsi_panel_esd_config_deinit(struct drm_panel_esd_config *esd_config)
	kfree(esd_config->status_cmd.cmds);
	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 device_node *of_node)
				struct device_node *of_node)
{
{
	struct drm_panel_esd_config *esd_config;
	int rc = 0;
	int rc = 0;
	u32 tmp;
	u32 tmp;
	u32 i, status_len, *lenp;
	u32 i, status_len, *lenp;
	struct property *data;
	struct property *data;
	const char *string;
	struct drm_panel_esd_config *esd_config;
	u8 *esd_mode = NULL;

	esd_config = &panel->esd_config;
	esd_config->status_mode = ESD_MODE_MAX;
	esd_config->esd_enabled = of_property_read_bool(of_node,
		"qcom,esd-check-enabled");


	if (!esd_config->esd_enabled)
	if (!panel || !of_node) {
		return 0;
		pr_err("Invalid Params\n");

		return -EINVAL;
	rc = of_property_read_string(of_node,
			"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 ((esd_config->status_mode == ESD_MODE_SW_BTA) ||
	esd_config = &panel->esd_config;
		(esd_config->status_mode == ESD_MODE_PANEL_TE))
	if (!esd_config)
		return 0;
		return -EINVAL;


	dsi_panel_parse_cmd_sets_sub(&esd_config->status_cmd,
	dsi_panel_parse_cmd_sets_sub(&esd_config->status_cmd,
				DSI_CMD_SET_PANEL_STATUS, of_node);
				DSI_CMD_SET_PANEL_STATUS, of_node);
@@ -2749,8 +2718,10 @@ static int dsi_panel_parse_esd_config(struct dsi_panel *panel,
	}
	}


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


	rc = of_property_read_u32_array(of_node,
	rc = of_property_read_u32_array(of_node,
		"qcom,mdss-dsi-panel-status-value",
		"qcom,mdss-dsi-panel-status-value",
@@ -2761,15 +2732,6 @@ static int dsi_panel_parse_esd_config(struct dsi_panel *panel,
				esd_config->groups * status_len);
				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;
	return 0;


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

static int dsi_panel_parse_esd_config(struct dsi_panel *panel,
				     struct device_node *of_node)
{
	int rc = 0;
	const char *string;
	struct drm_panel_esd_config *esd_config;
	u8 *esd_mode = NULL;

	esd_config = &panel->esd_config;
	esd_config->status_mode = ESD_MODE_MAX;
	esd_config->esd_enabled = of_property_read_bool(of_node,
		"qcom,esd-check-enabled");

	if (!esd_config->esd_enabled)
		return 0;

	rc = of_property_read_string(of_node,
			"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, of_node);
		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:
error:
	panel->esd_config.esd_enabled = false;
	panel->esd_config.esd_enabled = false;
	return rc;
	return rc;
+3 −0
Original line number Original line Diff line number Diff line
@@ -283,6 +283,9 @@ struct dsi_panel *dsi_panel_ext_bridge_get(struct device *parent,
				struct device_node *of_node,
				struct device_node *of_node,
				int topology_override);
				int topology_override);


int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel,
				struct device_node *of_node);

void dsi_panel_ext_bridge_put(struct dsi_panel *panel);
void dsi_panel_ext_bridge_put(struct dsi_panel *panel);


#endif /* _DSI_PANEL_H_ */
#endif /* _DSI_PANEL_H_ */