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

Commit d3cc31fd 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 basic mst simulator support" into msm-4.14

parents c96d875e 56517e76
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -497,7 +497,8 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
				msg->size);
			aux->aux_error_num = DP_AUX_ERR_NONE;
		} else {
			memset(msg->buffer, 0, msg->size);
			memcpy(aux->dpcd + msg->address, msg->buffer,
				msg->size);
		}
	} else {
		if (aux->read && msg->address == 0x50) {
@@ -510,6 +511,9 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
	if (aux->aux_error_num == DP_AUX_ERR_NONE) {
		dp_aux_hex_dump(drm_aux, msg);

		if (!aux->read)
			memset(msg->buffer, 0, msg->size);

		msg->reply = aux->native ?
			DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
	} else {
+105 −3
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct dp_debug_private {
	struct device *dev;
	struct work_struct sim_work;
	struct dp_debug dp_debug;
	struct dp_parser *parser;
};

static int dp_debug_get_edid_buf(struct dp_debug_private *debug)
@@ -73,13 +74,13 @@ static int dp_debug_get_dpcd_buf(struct dp_debug_private *debug)
	int rc = 0;

	if (!debug->dpcd) {
		debug->dpcd = devm_kzalloc(debug->dev, SZ_1K, GFP_KERNEL);
		debug->dpcd = devm_kzalloc(debug->dev, SZ_16K, GFP_KERNEL);
		if (!debug->dpcd) {
			rc = -ENOMEM;
			goto end;
		}

		debug->dpcd_size = SZ_1K;
		debug->dpcd_size = SZ_16K;
	}
end:
	return rc;
@@ -363,6 +364,65 @@ static ssize_t dp_debug_bw_code_write(struct file *file,
	return len;
}

static ssize_t dp_debug_mst_mode_write(struct file *file,
		const char __user *user_buff, size_t count, loff_t *ppos)
{
	struct dp_debug_private *debug = file->private_data;
	char buf[SZ_8];
	size_t len = 0;
	u32 mst_mode = 0;

	if (!debug)
		return -ENODEV;

	if (*ppos)
		return 0;

	len = min_t(size_t, count, SZ_8 - 1);
	if (copy_from_user(buf, user_buff, len))
		return 0;

	buf[len] = '\0';

	if (kstrtoint(buf, 10, &mst_mode) != 0)
		return 0;

	debug->parser->has_mst = mst_mode ? true : false;
	pr_debug("mst_enable: %d\n", mst_mode);

	return len;
}

static ssize_t dp_debug_mst_sideband_mode_write(struct file *file,
		const char __user *user_buff, size_t count, loff_t *ppos)
{
	struct dp_debug_private *debug = file->private_data;
	char buf[SZ_8];
	size_t len = 0;
	u32 mst_sideband_mode = 0;

	if (!debug)
		return -ENODEV;

	if (*ppos)
		return 0;

	/* Leave room for termination char */
	len = min_t(size_t, count, SZ_8 - 1);
	if (copy_from_user(buf, user_buff, len))
		return 0;

	buf[len] = '\0';

	if (kstrtoint(buf, 10, &mst_sideband_mode) != 0)
		return 0;

	debug->parser->has_mst_sideband = mst_sideband_mode ? true : false;
	pr_debug("mst_enable: %d\n", mst_sideband_mode);

	return len;
}

static ssize_t dp_debug_tpg_write(struct file *file,
		const char __user *user_buff, size_t count, loff_t *ppos)
{
@@ -1078,6 +1138,16 @@ static const struct file_operations dump_fops = {
	.read = dp_debug_read_dump,
};

static const struct file_operations mst_mode_fops = {
	.open = simple_open,
	.write = dp_debug_mst_mode_write,
};

static const struct file_operations mst_sideband_mode_fops = {
	.open = simple_open,
	.write = dp_debug_mst_sideband_mode_write,
};

static int dp_debug_init(struct dp_debug *dp_debug)
{
	int rc = 0;
@@ -1217,6 +1287,22 @@ static int dp_debug_init(struct dp_debug *dp_debug)
		goto error_remove_dir;
	}

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

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

	return 0;

error_remove_dir:
@@ -1235,10 +1321,23 @@ static void dp_debug_sim_work(struct work_struct *work)
	debug->usbpd->simulate_attention(debug->usbpd, debug->vdo);
}

u8 *dp_debug_get_edid(struct dp_debug *dp_debug)
{
	struct dp_debug_private *debug;

	if (!dp_debug)
		return NULL;

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

	return debug->edid;
}

struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
			struct dp_usbpd *usbpd, struct dp_link *link,
			struct dp_aux *aux, struct drm_connector **connector,
			struct dp_catalog *catalog)
			struct dp_catalog *catalog,
			struct dp_parser *parser)
{
	int rc = 0;
	struct dp_debug_private *debug;
@@ -1266,6 +1365,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
	debug->dev = dev;
	debug->connector = connector;
	debug->catalog = catalog;
	debug->parser = parser;

	dp_debug = &debug->dp_debug;
	dp_debug->vdisplay = 0;
@@ -1278,6 +1378,8 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
		goto error;
	}

	dp_debug->get_edid = dp_debug_get_edid;

	return dp_debug;
error:
	return ERR_PTR(rc);
+5 −1
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ struct dp_debug {
	int hdisplay;
	int vrefresh;
	bool tpg_state;

	u8 *(*get_edid)(struct dp_debug *dp_debug);
};

/**
@@ -48,6 +50,7 @@ struct dp_debug {
 * @link: instance of link module
 * @connector: double pointer to display connector
 * @catalog: instance of catalog module
 * @parser: instance of parser module
 * return: pointer to allocated debug module data
 *
 * This function sets up the debug module and provides a way
@@ -56,7 +59,8 @@ struct dp_debug {
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
			struct dp_usbpd *usbpd, struct dp_link *link,
			struct dp_aux *aux, struct drm_connector **connector,
			struct dp_catalog *catalog);
			struct dp_catalog *catalog,
			struct dp_parser *parser);
/**
 * dp_debug_put()
 *
+17 −5
Original line number Diff line number Diff line
@@ -513,6 +513,7 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp,
static void dp_display_process_mst_hpd_high(struct dp_display_private *dp)
{
	bool is_mst_receiver;
	struct dp_mst_hdp_info info;

	if (dp->parser->has_mst && dp->mst.drm_registered) {
		DP_MST_DEBUG("mst_hpd_high work\n");
@@ -522,8 +523,11 @@ static void dp_display_process_mst_hpd_high(struct dp_display_private *dp)
		if (is_mst_receiver && !dp->mst.mst_active) {
			dp->mst.mst_active = true;

			info.mst_protocol = dp->parser->has_mst_sideband;
			info.edid = dp->debug->get_edid(dp->debug);

			if (dp->mst.cbs.hpd)
				dp->mst.cbs.hpd(&dp->dp_display, true);
				dp->mst.cbs.hpd(&dp->dp_display, true, &info);
		}
	}

@@ -613,11 +617,15 @@ static void dp_display_host_deinit(struct dp_display_private *dp)

static void dp_display_process_mst_hpd_low(struct dp_display_private *dp)
{
	struct dp_mst_hdp_info info = {0};

	if (dp->mst.mst_active) {
		DP_MST_DEBUG("mst_hpd_low work\n");

		if (dp->mst.cbs.hpd)
			dp->mst.cbs.hpd(&dp->dp_display, false);
		if (dp->mst.cbs.hpd) {
			info.mst_protocol = dp->parser->has_mst_sideband;
			dp->mst.cbs.hpd(&dp->dp_display, false, &info);
		}

		dp->mst.mst_active = false;
	}
@@ -1085,7 +1093,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
	dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
				dp->link, dp->aux,
				&dp->dp_display.base_connector,
				dp->catalog);
				dp->catalog, dp->parser);

	if (IS_ERR(dp->debug)) {
		rc = PTR_ERR(dp->debug);
@@ -1516,8 +1524,12 @@ static int dp_display_validate_mode(struct dp_display *dp, void *panel,
	mode_rate_khz = mode_pclk_khz * mode_bpp;
	supported_rate_khz = link_info->num_lanes * link_info->rate * 8;

	if (mode_rate_khz > supported_rate_khz)
	if (mode_rate_khz > supported_rate_khz) {
		DP_MST_DEBUG("pclk:%d, supported_rate:%d\n",
				mode_pclk_khz, supported_rate_khz);

		return MODE_BAD;
	}

	return MODE_OK;
}
+7 −1
Original line number Diff line number Diff line
@@ -20,8 +20,14 @@

#include "dp_panel.h"

struct dp_mst_hdp_info {
	bool mst_protocol;
	u8 *edid;
};

struct dp_mst_drm_cbs {
	void (*hpd)(void *display, bool hpd_status);
	void (*hpd)(void *display, bool hpd_status,
			struct dp_mst_hdp_info *info);
	void (*hpd_irq)(void *display);
};

Loading