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

Commit 78117d4f 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 HPD notification to userspace"

parents c5190e5b 7bf08e98
Loading
Loading
Loading
Loading
+10 −64
Original line number Diff line number Diff line
@@ -66,12 +66,7 @@ struct dp_ctrl_private {
	struct completion video_comp;
	struct completion irq_comp;

	bool hpd_irq_on;
	bool power_on;
	bool sink_info_read;
	bool cont_splash;
	bool psm_enabled;
	bool initialized;
	bool orientation;

	u32 pixel_rate;
@@ -712,9 +707,6 @@ static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)
{
	int ret = 0;

	if (ctrl->cont_splash)
		return ret;

	ret = wait_for_completion_timeout(&ctrl->video_comp, HZ / 2);
	if (ret <= 0) {
		pr_err("Link Train timedout\n");
@@ -1072,11 +1064,6 @@ static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip)

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (ctrl->initialized) {
		pr_debug("host init done already\n");
		return 0;
	}

	ctrl->orientation = flip;
	catalog = ctrl->catalog;

@@ -1084,8 +1071,6 @@ static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip)
	catalog->phy_reset(ctrl->catalog);
	catalog->enable_irq(ctrl->catalog, true);

	ctrl->initialized = true;

	return 0;
}

@@ -1107,11 +1092,6 @@ static void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (!ctrl->initialized) {
		pr_debug("host deinit done already\n");
		return;
	}

	ctrl->catalog->enable_irq(ctrl->catalog, false);
	ctrl->catalog->reset(ctrl->catalog);

@@ -1120,7 +1100,6 @@ static void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)

	dp_ctrl_disable_mainlink_clocks(ctrl);

	ctrl->initialized = false;
	pr_debug("Host deinitialized successfully\n");
}

@@ -1154,8 +1133,6 @@ static int dp_ctrl_on_irq(struct dp_ctrl_private *ctrl, bool lt_needed)

		reinit_completion(&ctrl->idle_comp);

		ctrl->power_on = true;

		if (ctrl->psm_enabled) {
			ret = ctrl->link->send_psm_request(ctrl->link, false);
			if (ret) {
@@ -1175,9 +1152,6 @@ static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl)
{
	int ret = 0;

	if (ctrl->cont_splash)
		goto link_training;

	ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true);
	ctrl->catalog->hpd_config(ctrl->catalog, true);

@@ -1202,28 +1176,18 @@ static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl)

	if (ctrl->psm_enabled)
		ret = ctrl->link->send_psm_request(ctrl->link, false);
link_training:
	ctrl->power_on = true;

	while (-EAGAIN == dp_ctrl_setup_main_link(ctrl, true))
		pr_debug("MAIN LINK TRAINING RETRY\n");

	ctrl->cont_splash = 0;

	ctrl->power_on = true;
	pr_debug("End-\n");

exit:
	return ret;
}

static int dp_ctrl_off_irq(struct dp_ctrl_private *ctrl)
static void dp_ctrl_off_irq(struct dp_ctrl_private *ctrl)
{
	if (!ctrl->power_on) {
		pr_debug("ctrl already powered off\n");
		return 0;
	}

	ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);

	/* Make sure DP mainlink and audio engines are disabled */
@@ -1231,28 +1195,15 @@ static int dp_ctrl_off_irq(struct dp_ctrl_private *ctrl)

	complete_all(&ctrl->irq_comp);
	pr_debug("end\n");

	return 0;
}

static int dp_ctrl_off_hpd(struct dp_ctrl_private *ctrl)
static void dp_ctrl_off_hpd(struct dp_ctrl_private *ctrl)
{
	if (!ctrl->power_on) {
		pr_debug("panel already powered off\n");
		return 0;
	}

	ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);

	ctrl->power_on = false;
	ctrl->sink_info_read = false;

	pr_debug("DP off done\n");

	return 0;
}

static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)
static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool hpd_irq)
{
	int rc = 0;
	struct dp_ctrl_private *ctrl;
@@ -1264,7 +1215,7 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (ctrl->hpd_irq_on)
	if (hpd_irq)
		rc = dp_ctrl_on_irq(ctrl, false);
	else
		rc = dp_ctrl_on_hpd(ctrl);
@@ -1272,24 +1223,19 @@ static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)
	return rc;
}

static int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
static void dp_ctrl_off(struct dp_ctrl *dp_ctrl, bool hpd_irq)
{
	int rc = 0;
	struct dp_ctrl_private *ctrl;

	if (!dp_ctrl) {
		rc = -EINVAL;
		goto end;
	}
	if (!dp_ctrl)
		return;

	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);

	if (ctrl->hpd_irq_on)
		rc = dp_ctrl_off_irq(ctrl);
	if (hpd_irq)
		dp_ctrl_off_irq(ctrl);
	else
		rc = dp_ctrl_off_hpd(ctrl);
end:
	return rc;
		dp_ctrl_off_hpd(ctrl);
}

static void dp_ctrl_isr(struct dp_ctrl *dp_ctrl)
+2 −2
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@
struct dp_ctrl {
	int (*init)(struct dp_ctrl *dp_ctrl, bool flip);
	void (*deinit)(struct dp_ctrl *dp_ctrl);
	int (*on)(struct dp_ctrl *dp_ctrl);
	int (*off)(struct dp_ctrl *dp_ctrl);
	int (*on)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
	void (*off)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
	void (*push_idle)(struct dp_ctrl *dp_ctrl);
	void (*isr)(struct dp_ctrl *dp_ctrl);
};
+82 −38
Original line number Diff line number Diff line
@@ -38,6 +38,11 @@ struct dp_display_private {
	char *name;
	int irq;

	/* state variables */
	bool core_initialized;
	bool power_on;
	bool hpd_irq_on;

	struct platform_device *pdev;
	struct dentry *root;
	struct mutex lock;
@@ -255,30 +260,63 @@ static const struct component_ops dp_display_comp_ops = {

static int dp_display_process_hpd_high(struct dp_display_private *dp)
{
	int rc;
	int rc = 0;

	rc = dp->panel->read_dpcd(dp->panel);
	if (rc)
		goto end;
		return rc;

	sde_get_edid(dp->dp_display.connector, &dp->aux->drm_aux->ddc,
		(void **)&dp->panel->edid_ctrl);

	return 0;
end:
	dp->dp_display.is_connected = true;
	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);

	return rc;
}

static int dp_display_process_hpd_low(struct dp_display_private *dp)
static void dp_display_host_init(struct dp_display_private *dp)
{
	bool flip = false;

	if (dp->core_initialized) {
		pr_debug("DP core already initialized\n");
		return;
	}

	if (dp->usbpd->orientation == ORIENTATION_CC2)
		flip = true;

	dp->power->init(dp->power, flip);
	dp->ctrl->init(dp->ctrl, flip);
	dp->aux->init(dp->aux, dp->parser->aux_cfg);
	enable_irq(dp->irq);
	dp->core_initialized = true;
}

static void dp_display_host_deinit(struct dp_display_private *dp)
{
	if (!dp->core_initialized) {
		pr_debug("DP core already off\n");
		return;
	}

	dp->aux->deinit(dp->aux);
	dp->ctrl->deinit(dp->ctrl);
	dp->power->deinit(dp->power);
	disable_irq(dp->irq);
	dp->core_initialized = false;
}

static void dp_display_process_hpd_low(struct dp_display_private *dp)
{
	dp->dp_display.is_connected = false;
	return 0;
	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
}

static int dp_display_usbpd_configure_cb(struct device *dev)
{
	int rc = 0;
	bool flip = false;
	struct dp_display_private *dp;

	if (!dev) {
@@ -295,19 +333,9 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
	}

	mutex_lock(&dp->lock);

	if (dp->usbpd->orientation == ORIENTATION_CC2)
		flip = true;

	dp->power->init(dp->power, flip);
	dp->ctrl->init(dp->ctrl, flip);
	dp->aux->init(dp->aux, dp->parser->aux_cfg);
	enable_irq(dp->irq);

	dp_display_host_init(dp);
	if (dp->usbpd->hpd_high)
		dp_display_process_hpd_high(dp);
	dp->dp_display.is_connected = true;

	mutex_unlock(&dp->lock);
end:
	return rc;
@@ -332,10 +360,23 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev)
	}

	mutex_lock(&dp->lock);

	dp->dp_display.is_connected = false;
	disable_irq(dp->irq);
	mutex_unlock(&dp->lock);
	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);

	/*
	 * If a cable/dongle is connected to the TX device but
	 * no sink device is connected, we call host
	 * initialization where orientation settings are
	 * configured. When the cable/dongle is disconnect,
	 * call host de-initialization to make sure
	 * we re-configure the orientation settings during
	 * the next connect event.
	 */
	if (!dp->power_on && dp->core_initialized)
		dp_display_host_deinit(dp);

	mutex_unlock(&dp->lock);
end:
	return rc;
}
@@ -347,31 +388,36 @@ static int dp_display_usbpd_attention_cb(struct device *dev)

	if (!dev) {
		pr_err("invalid dev\n");
		rc = -EINVAL;
		goto end;
		return -EINVAL;
	}

	dp = dev_get_drvdata(dev);
	if (!dp) {
		pr_err("no driver data found\n");
		rc = -ENODEV;
		goto end;
		return -ENODEV;
	}

	mutex_lock(&dp->lock);

	if (dp->usbpd->hpd_irq) {
		if (!dp->link->process_request(dp->link))
		dp->hpd_irq_on = true;
		rc = dp->link->process_request(dp->link);
		dp->hpd_irq_on = false;
		if (!rc)
			goto end;
	}

	if (dp->usbpd->hpd_high)
		dp_display_process_hpd_high(dp);
	else
	if (!dp->usbpd->hpd_high) {
		dp_display_process_hpd_low(dp);
		goto end;
	}

	mutex_unlock(&dp->lock);
	if (dp->usbpd->alt_mode_cfg_done) {
		dp_display_host_init(dp);
		dp_display_process_hpd_high(dp);
	}
end:
	mutex_unlock(&dp->lock);
	return rc;
}

@@ -492,7 +538,9 @@ static int dp_display_enable(struct dp_display *dp_display)
	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->lock);
	dp->ctrl->on(dp->ctrl);
	rc = dp->ctrl->on(dp->ctrl, dp->hpd_irq_on);
	if (!rc)
		dp->power_on = true;
	mutex_unlock(&dp->lock);
error:
	return rc;
@@ -517,9 +565,7 @@ static int dp_display_pre_disable(struct dp_display *dp_display)
	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->lock);

	dp->ctrl->off(dp->ctrl);

	dp->ctrl->push_idle(dp->ctrl);
	mutex_unlock(&dp->lock);
error:
	return rc;
@@ -539,11 +585,9 @@ static int dp_display_disable(struct dp_display *dp_display)
	dp = container_of(dp_display, struct dp_display_private, dp_display);

	mutex_lock(&dp->lock);

	dp->aux->deinit(dp->aux);
	dp->ctrl->deinit(dp->ctrl);
	dp->power->deinit(dp->power);

	dp->ctrl->off(dp->ctrl, dp->hpd_irq_on);
	dp_display_host_deinit(dp);
	dp->power_on = false;
	mutex_unlock(&dp->lock);
error:
	return rc;
+5 −1
Original line number Diff line number Diff line
@@ -345,8 +345,12 @@ static void dp_usbpd_response_cb(struct usbpd_svid_handler *hdlr, u8 cmd,
		pd->vdo = *vdos;
		dp_usbpd_get_status(pd);

		if (pd->dp_cb && pd->dp_cb->attention)
		if (pd->dp_cb && pd->dp_cb->attention) {
			pd->dp_cb->attention(pd->dev);

			if (!pd->dp_usbpd.alt_mode_cfg_done)
				dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE);
		}
		break;
	case DP_USBPD_VDM_STATUS:
		pd->vdo = *vdos;