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

Commit c0cf3e0d 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/dp: add support for custom edid"

parents f7570fd7 4c92d396
Loading
Loading
Loading
Loading
+110 −20
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@

struct dp_debug_private {
	struct dentry *root;
	u8 *edid;
	u32 edid_size;

	struct dp_usbpd *usbpd;
	struct dp_link *link;
@@ -39,6 +41,71 @@ struct dp_debug_private {
	struct dp_debug dp_debug;
};

static ssize_t dp_debug_write_edid(struct file *file,
		const char __user *user_buff, size_t count, loff_t *ppos)
{
	struct dp_debug_private *debug = file->private_data;
	u8 *buf = NULL, *buf_t = NULL, *edid = NULL;
	const int char_to_nib = 2;
	size_t edid_size = 0;
	size_t size = 0, edid_buf_index = 0;
	ssize_t rc = count;

	if (!debug)
		return -ENODEV;

	if (*ppos)
		goto bail;

	size = min_t(size_t, count, SZ_1K);

	buf = kzalloc(size, GFP_KERNEL);
	if (!buf) {
		rc = -ENOMEM;
		goto bail;
	}

	if (copy_from_user(buf, user_buff, size))
		goto bail;

	edid_size = size / char_to_nib;
	buf_t = buf;

	memset(debug->edid, 0, debug->edid_size);

	if (edid_size != debug->edid_size) {
		pr_debug("clearing debug edid\n");
		goto bail;
	}

	while (edid_size--) {
		char t[3];
		int d;

		memcpy(t, buf_t, sizeof(char) * char_to_nib);
		t[char_to_nib] = '\0';

		if (kstrtoint(t, 16, &d)) {
			pr_err("kstrtoint error\n");
			goto bail;
		}

		if (edid_buf_index < debug->edid_size)
			debug->edid[edid_buf_index++] = d;

		buf_t += char_to_nib;
	}

	print_hex_dump(KERN_DEBUG, "DEBUG EDID: ", DUMP_PREFIX_NONE,
		16, 1, debug->edid, debug->edid_size, false);

	edid = debug->edid;
bail:
	kfree(buf);
	debug->panel->set_edid(debug->panel, edid);
	return rc;
}

static ssize_t dp_debug_write_hpd(struct file *file,
		const char __user *user_buff, size_t count, loff_t *ppos)
{
@@ -431,6 +498,11 @@ static const struct file_operations hpd_fops = {
	.write = dp_debug_write_hpd,
};

static const struct file_operations edid_fops = {
	.open = simple_open,
	.write = dp_debug_write_edid,
};

static const struct file_operations connected_fops = {
	.open = simple_open,
	.read = dp_debug_read_connected,
@@ -447,10 +519,7 @@ static int dp_debug_init(struct dp_debug *dp_debug)
	int rc = 0;
	struct dp_debug_private *debug = container_of(dp_debug,
		struct dp_debug_private, dp_debug);
	struct dentry *dir, *file, *edid_modes;
	struct dentry *hpd, *connected;
	struct dentry *max_bw_code;
	struct dentry *root = debug->root;
	struct dentry *dir, *file;

	dir = debugfs_create_dir(DEBUG_NAME, NULL);
	if (IS_ERR_OR_NULL(dir)) {
@@ -460,6 +529,8 @@ static int dp_debug_init(struct dp_debug *dp_debug)
		goto error;
	}

	debug->root = dir;

	file = debugfs_create_file("dp_debug", 0444, dir,
				debug, &dp_debug_fops);
	if (IS_ERR_OR_NULL(file)) {
@@ -469,46 +540,55 @@ static int dp_debug_init(struct dp_debug *dp_debug)
		goto error_remove_dir;
	}

	edid_modes = debugfs_create_file("edid_modes", 0644, dir,
	file = debugfs_create_file("edid_modes", 0644, dir,
					debug, &edid_modes_fops);
	if (IS_ERR_OR_NULL(edid_modes)) {
		rc = PTR_ERR(edid_modes);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		pr_err("[%s] debugfs create edid_modes failed, rc=%d\n",
		       DEBUG_NAME, rc);
		goto error_remove_dir;
	}

	hpd = debugfs_create_file("hpd", 0644, dir,
	file = debugfs_create_file("hpd", 0644, dir,
					debug, &hpd_fops);
	if (IS_ERR_OR_NULL(hpd)) {
		rc = PTR_ERR(hpd);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		pr_err("[%s] debugfs hpd failed, rc=%d\n",
			DEBUG_NAME, rc);
		goto error_remove_dir;
	}

	connected = debugfs_create_file("connected", 0444, dir,
	file = debugfs_create_file("connected", 0444, dir,
					debug, &connected_fops);
	if (IS_ERR_OR_NULL(connected)) {
		rc = PTR_ERR(connected);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		pr_err("[%s] debugfs connected failed, rc=%d\n",
			DEBUG_NAME, rc);
		goto error_remove_dir;
	}

	max_bw_code = debugfs_create_file("max_bw_code", 0644, dir,
	file = debugfs_create_file("max_bw_code", 0644, dir,
			debug, &bw_code_fops);
	if (IS_ERR_OR_NULL(max_bw_code)) {
		rc = PTR_ERR(max_bw_code);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		pr_err("[%s] debugfs max_bw_code failed, rc=%d\n",
		       DEBUG_NAME, rc);
		goto error_remove_dir;
	}

	root = dir;
	return rc;
	file = debugfs_create_file("edid", 0644, dir,
					debug, &edid_fops);
	if (IS_ERR_OR_NULL(file)) {
		rc = PTR_ERR(file);
		pr_err("[%s] debugfs edid failed, rc=%d\n",
			DEBUG_NAME, rc);
		goto error_remove_dir;
	}

	return 0;

error_remove_dir:
	debugfs_remove(dir);
	debugfs_remove_recursive(dir);
error:
	return rc;
}
@@ -533,6 +613,15 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
		goto error;
	}

	debug->edid = devm_kzalloc(dev, SZ_256, GFP_KERNEL);
	if (!debug->edid) {
		rc = -ENOMEM;
		kfree(debug);
		goto error;
	}

	debug->edid_size = SZ_256;

	debug->dp_debug.debug_en = false;
	debug->usbpd = usbpd;
	debug->link = link;
@@ -565,7 +654,7 @@ static int dp_debug_deinit(struct dp_debug *dp_debug)

	debug = container_of(dp_debug, struct dp_debug_private, dp_debug);

	debugfs_remove(debug->root);
	debugfs_remove_recursive(debug->root);

	return 0;
}
@@ -581,5 +670,6 @@ void dp_debug_put(struct dp_debug *dp_debug)

	dp_debug_deinit(dp_debug);

	devm_kfree(debug->dev, debug->edid);
	devm_kfree(debug->dev, debug);
}
+29 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ struct dp_panel_private {
	struct dp_link *link;
	struct dp_catalog_panel *catalog;
	bool aux_cfg_update_done;
	bool custom_edid;
};

static const struct dp_panel_info fail_safe = {
@@ -133,6 +134,28 @@ static int dp_panel_set_default_link_params(struct dp_panel *dp_panel)
	link_info->num_lanes = default_num_lanes;
	pr_debug("link_rate=%d num_lanes=%d\n",
		link_info->rate, link_info->num_lanes);

	return 0;
}

static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid)
{
	struct dp_panel_private *panel;

	if (!dp_panel) {
		pr_err("invalid input\n");
		return -EINVAL;
	}

	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);

	if (edid) {
		dp_panel->edid_ctrl->edid = (struct edid *)edid;
		panel->custom_edid = true;
	} else {
		panel->custom_edid = false;
	}

	return 0;
}

@@ -150,6 +173,11 @@ static int dp_panel_read_edid(struct dp_panel *dp_panel,

	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);

	if (panel->custom_edid) {
		pr_debug("skip edid read in debug mode\n");
		return 0;
	}

	do {
		sde_get_edid(connector, &panel->aux->drm_aux->ddc,
			(void **)&dp_panel->edid_ctrl);
@@ -527,6 +555,7 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in)
	dp_panel->get_mode_bpp = dp_panel_get_mode_bpp;
	dp_panel->get_modes = dp_panel_get_modes;
	dp_panel->handle_sink_request = dp_panel_handle_sink_request;
	dp_panel->set_edid = dp_panel_set_edid;

	return dp_panel;
error:
+1 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ struct dp_panel {
	int (*get_modes)(struct dp_panel *dp_panel,
		struct drm_connector *connector, struct dp_display_mode *mode);
	void (*handle_sink_request)(struct dp_panel *dp_panel);
	int (*set_edid)(struct dp_panel *dp_panel, u8 *edid);
};

/**