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

Commit fba4f1f3 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: fix usbpd and drm framework sequence"

parents d88f28ae 315e585c
Loading
Loading
Loading
Loading
+123 −72
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ struct dp_display_private {
	struct dp_usbpd_cb usbpd_cb;
	struct dp_display_mode mode;
	struct dp_display dp_display;
	struct msm_drm_private *priv;

	struct workqueue_struct *wq;
	struct delayed_work hdcp_cb_work;
@@ -300,7 +301,12 @@ static int dp_display_initialize_hdcp(struct dp_display_private *dp)
	pr_debug("HDCP 1.3 initialized\n");

	dp->hdcp.hdcp2 = sde_dp_hdcp2p2_init(&hdcp_init_data);
	if (!IS_ERR_OR_NULL(dp->hdcp.hdcp2))
	if (IS_ERR_OR_NULL(dp->hdcp.hdcp2)) {
		pr_err("Error initializing HDCP 2.x\n");
		rc = -EINVAL;
		goto error;
	}

	pr_debug("HDCP 2.2 initialized\n");

	dp->hdcp.feature_enabled = true;
@@ -317,7 +323,6 @@ static int dp_display_bind(struct device *dev, struct device *master,
	int rc = 0;
	struct dp_display_private *dp;
	struct drm_device *drm;
	struct msm_drm_private *priv;
	struct platform_device *pdev = to_platform_device(dev);

	if (!dev || !pdev || !master) {
@@ -337,25 +342,7 @@ static int dp_display_bind(struct device *dev, struct device *master,
	}

	dp->dp_display.drm_dev = drm;
	priv = drm->dev_private;

	rc = dp->aux->drm_aux_register(dp->aux);
	if (rc) {
		pr_err("DRM DP AUX register failed\n");
		goto end;
	}

	rc = dp->power->power_client_init(dp->power, &priv->phandle);
	if (rc) {
		pr_err("Power client create failed\n");
		goto end;
	}

	rc = dp_display_initialize_hdcp(dp);
	if (rc) {
		pr_err("HDCP initialization failed\n");
		goto end;
	}
	dp->priv = drm->dev_private;
end:
	return rc;
}
@@ -399,32 +386,25 @@ static bool dp_display_is_sink_count_zero(struct dp_display_private *dp)
		(dp->link->sink_count.count == 0);
}

static void dp_display_send_hpd_event(struct dp_display *dp_display)
static void dp_display_send_hpd_event(struct dp_display_private *dp)
{
	struct drm_device *dev = NULL;
	struct dp_display_private *dp;
	struct drm_connector *connector;
	char name[HPD_STRING_SIZE], status[HPD_STRING_SIZE],
		bpp[HPD_STRING_SIZE], pattern[HPD_STRING_SIZE];
	char *envp[5];

	if (!dp_display) {
		pr_err("invalid input\n");
		return;
	}
	connector = dp->dp_display.connector;

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	if (!dp) {
		pr_err("invalid params\n");
	if (!connector) {
		pr_err("connector not set\n");
		return;
	}
	connector = dp->dp_display.connector;
	dev = dp_display->connector->dev;

	connector->status = connector->funcs->detect(connector, false);
	pr_debug("[%s] status updated to %s\n",
			      connector->name,
			      drm_get_connector_status_name(connector->status));

	dev = dp->dp_display.connector->dev;

	snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name);
	snprintf(status, HPD_STRING_SIZE, "status=%s",
		drm_get_connector_status_name(connector->status));
@@ -434,8 +414,7 @@ static void dp_display_send_hpd_event(struct dp_display *dp_display)
	snprintf(pattern, HPD_STRING_SIZE, "pattern=%d",
		dp->link->test_video.test_video_pattern);

	pr_debug("generating hotplug event [%s]:[%s] [%s] [%s]\n",
		name, status, bpp, pattern);
	pr_debug("[%s]:[%s] [%s] [%s]\n", name, status, bpp, pattern);
	envp[0] = name;
	envp[1] = status;
	envp[2] = bpp;
@@ -445,12 +424,48 @@ static void dp_display_send_hpd_event(struct dp_display *dp_display)
			envp);
}

static void dp_display_post_open(struct dp_display *dp_display)
{
	struct drm_connector *connector;
	struct dp_display_private *dp;

	if (!dp_display) {
		pr_err("invalid input\n");
		return;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	if (IS_ERR_OR_NULL(dp)) {
		pr_err("invalid params\n");
		return;
	}

	connector = dp->dp_display.connector;

	if (!connector) {
		pr_err("connector not set\n");
		return;
	}

	/* if cable is already connected, send notification */
	if (dp_display->is_connected)
		dp_display_send_hpd_event(dp);
	else
		dp_display->post_open = NULL;

}

static int dp_display_send_hpd_notification(struct dp_display_private *dp,
		bool hpd)
{
	dp->dp_display.is_connected = hpd;

	/* in case, framework is not yet up, don't notify hpd */
	if (dp->dp_display.post_open)
		return 0;

	reinit_completion(&dp->notification_comp);
	dp_display_send_hpd_event(&dp->dp_display);
	dp_display_send_hpd_event(dp);

	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 5)) {
		pr_warn("%s timeout\n", hpd ? "connect" : "disconnect");
@@ -476,6 +491,9 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
		dp->debug->psm_enabled = false;
	}

	if (!dp->dp_display.connector)
		return 0;

	rc = dp->panel->read_sink_caps(dp->panel, dp->dp_display.connector);
	if (rc) {
		if (rc == -ETIMEDOUT) {
@@ -793,18 +811,6 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
		.dev = dev,
	};

	cb->configure  = dp_display_usbpd_configure_cb;
	cb->disconnect = dp_display_usbpd_disconnect_cb;
	cb->attention  = dp_display_usbpd_attention_cb;

	dp->usbpd = dp_usbpd_get(dev, cb);
	if (IS_ERR(dp->usbpd)) {
		rc = PTR_ERR(dp->usbpd);
		pr_err("failed to initialize usbpd, rc = %d\n", rc);
		dp->usbpd = NULL;
		goto error;
	}

	mutex_init(&dp->session_lock);

	dp->parser = dp_parser_get(dp->pdev);
@@ -812,7 +818,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
		rc = PTR_ERR(dp->parser);
		pr_err("failed to initialize parser, rc = %d\n", rc);
		dp->parser = NULL;
		goto error_parser;
		goto error;
	}

	rc = dp->parser->parse(dp->parser);
@@ -837,6 +843,12 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
		goto error_power;
	}

	rc = dp->power->power_client_init(dp->power, &dp->priv->phandle);
	if (rc) {
		pr_err("Power client create failed\n");
		goto error_aux;
	}

	dp->aux = dp_aux_get(dev, &dp->catalog->aux, dp->parser->aux_cfg);
	if (IS_ERR(dp->aux)) {
		rc = PTR_ERR(dp->aux);
@@ -845,6 +857,12 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
		goto error_aux;
	}

	rc = dp->aux->drm_aux_register(dp->aux);
	if (rc) {
		pr_err("DRM DP AUX register failed\n");
		goto error_link;
	}

	dp->link = dp_link_get(dev, dp->aux);
	if (IS_ERR(dp->link)) {
		rc = PTR_ERR(dp->link);
@@ -888,6 +906,18 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
		goto error_audio;
	}

	cb->configure  = dp_display_usbpd_configure_cb;
	cb->disconnect = dp_display_usbpd_disconnect_cb;
	cb->attention  = dp_display_usbpd_attention_cb;

	dp->usbpd = dp_usbpd_get(dev, cb);
	if (IS_ERR(dp->usbpd)) {
		rc = PTR_ERR(dp->usbpd);
		pr_err("failed to initialize usbpd, rc = %d\n", rc);
		dp->usbpd = NULL;
		goto error_usbpd;
	}

	dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
				dp->link, &dp->dp_display.connector);
	if (IS_ERR(dp->debug)) {
@@ -899,6 +929,8 @@ static int dp_init_sub_modules(struct dp_display_private *dp)

	return rc;
error_debug:
	dp_usbpd_put(dp->usbpd);
error_usbpd:
	dp_audio_put(dp->audio);
error_audio:
	dp_ctrl_put(dp->ctrl);
@@ -914,13 +946,40 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
	dp_catalog_put(dp->catalog);
error_catalog:
	dp_parser_put(dp->parser);
error_parser:
	dp_usbpd_put(dp->usbpd);
	mutex_destroy(&dp->session_lock);
error:
	mutex_destroy(&dp->session_lock);
	return rc;
}

static void dp_display_post_init(struct dp_display *dp_display)
{
	int rc = 0;
	struct dp_display_private *dp;

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

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	if (IS_ERR_OR_NULL(dp)) {
		pr_err("invalid params\n");
		rc = -EINVAL;
		goto end;
	}

	rc = dp_init_sub_modules(dp);
	if (rc)
		goto end;

	dp_display_initialize_hdcp(dp);

	dp_display->post_init = NULL;
end:
	pr_debug("%s\n", rc ? "failed" : "success");
}

static int dp_display_set_mode(struct dp_display *dp_display,
		struct dp_display_mode *mode)
{
@@ -1023,7 +1082,7 @@ static int dp_display_post_enable(struct dp_display *dp_display)
	}
end:
	/* clear framework event notifier */
	dp_display->send_hpd_event = NULL;
	dp_display->post_open = NULL;

	complete_all(&dp->notification_comp);
	mutex_unlock(&dp->session_lock);
@@ -1148,7 +1207,7 @@ static int dp_display_validate_mode(struct dp_display *dp, u32 mode_pclk_khz)
	struct drm_dp_link *link_info;
	u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;

	if (!dp || !mode_pclk_khz) {
	if (!dp || !mode_pclk_khz || !dp->connector) {
		pr_err("invalid params\n");
		return -EINVAL;
	}
@@ -1178,7 +1237,7 @@ static int dp_display_get_modes(struct dp_display *dp,
	struct dp_display_private *dp_display;
	int ret = 0;

	if (!dp) {
	if (!dp || !dp->connector) {
		pr_err("invalid params\n");
		return 0;
	}
@@ -1206,7 +1265,7 @@ static int dp_display_pre_kickoff(struct dp_display *dp_display,

	dp = container_of(dp_display, struct dp_display_private, dp_display);

	if (hdr->hdr_supported)
	if (hdr->hdr_supported && dp->panel->hdr_supported(dp->panel))
		rc = dp->panel->setup_hdr(dp->panel, hdr);

	return rc;
@@ -1249,16 +1308,10 @@ static int dp_display_probe(struct platform_device *pdev)
	dp->pdev = pdev;
	dp->name = "drm_dp";

	rc = dp_init_sub_modules(dp);
	if (rc) {
		rc = -EPROBE_DEFER;
		goto err_dev;
	}

	rc = dp_display_create_workqueue(dp);
	if (rc) {
		pr_err("Failed to create workqueue\n");
		goto err_sub_mod;
		goto error;
	}

	platform_set_drvdata(pdev, dp);
@@ -1276,20 +1329,18 @@ static int dp_display_probe(struct platform_device *pdev)
	g_dp_display->unprepare     = dp_display_unprepare;
	g_dp_display->request_irq   = dp_request_irq;
	g_dp_display->get_debug     = dp_get_debug;
	g_dp_display->send_hpd_event    = dp_display_send_hpd_event;
	g_dp_display->post_open     = dp_display_post_open;
	g_dp_display->post_init     = dp_display_post_init;
	g_dp_display->pre_kickoff   = dp_display_pre_kickoff;

	rc = component_add(&pdev->dev, &dp_display_comp_ops);
	if (rc) {
		pr_err("component add failed, rc=%d\n", rc);
		goto err_sub_mod;
		goto error;
	}

	return 0;

err_sub_mod:
	dp_display_deinit_sub_modules(dp);
err_dev:
error:
	devm_kfree(&pdev->dev, dp);
bail:
	return rc;
+2 −1
Original line number Diff line number Diff line
@@ -42,9 +42,10 @@ struct dp_display {
	int (*unprepare)(struct dp_display *dp_display);
	int (*request_irq)(struct dp_display *dp_display);
	struct dp_debug *(*get_debug)(struct dp_display *dp_display);
	void (*send_hpd_event)(struct dp_display *dp_display);
	void (*post_open)(struct dp_display *dp_display);
	int (*pre_kickoff)(struct dp_display *dp_display,
				struct drm_msm_ext_hdr_metadata *hdr_meta);
	void (*post_init)(struct dp_display *dp_display);
};

int dp_display_get_num_of_displays(void);
+7 −3
Original line number Diff line number Diff line
@@ -295,6 +295,10 @@ int dp_connector_post_init(struct drm_connector *connector, void *display)
		return -EINVAL;

	dp_display->connector = connector;

	if (dp_display->post_init)
		dp_display->post_init(dp_display);

	return 0;
}

@@ -376,7 +380,7 @@ enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
	return status;
}

void dp_connector_send_hpd_event(void *display)
void dp_connector_post_open(void *display)
{
	struct dp_display *dp;

@@ -387,8 +391,8 @@ void dp_connector_send_hpd_event(void *display)

	dp = display;

	if (dp->send_hpd_event)
		dp->send_hpd_event(dp);
	if (dp->post_open)
		dp->post_open(dp);
}

int dp_connector_get_modes(struct drm_connector *connector,
+5 −1
Original line number Diff line number Diff line
@@ -95,7 +95,11 @@ int dp_connector_get_mode_info(const struct drm_display_mode *drm_mode,

int dp_connector_get_info(struct msm_display_info *info, void *display);

void dp_connector_send_hpd_event(void *display);
/**
 * dp_connector_post_open - handle the post open functionalites
 * @display: Pointer to private display structure
 */
void dp_connector_post_open(void *display);

int dp_drm_bridge_init(void *display,
	struct drm_encoder *encoder);
+56 −5
Original line number Diff line number Diff line
@@ -19,6 +19,11 @@
#define DP_PANEL_DEFAULT_BPP 24
#define DP_MAX_DS_PORT_COUNT 1

#define DPRX_FEATURE_ENUMERATION_LIST 0x2210
#define VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED BIT(3)
#define VSC_EXT_VESA_SDP_SUPPORTED BIT(4)
#define VSC_EXT_VESA_SDP_CHAINING_SUPPORTED BIT(5)

enum dp_panel_hdr_pixel_encoding {
	RGB,
	YCbCr444,
@@ -65,9 +70,14 @@ struct dp_panel_private {
	bool custom_edid;
	bool custom_dpcd;
	bool panel_on;
	bool vsc_supported;
	bool vscext_supported;
	bool vscext_chaining_supported;
	enum dp_panel_hdr_state hdr_state;
	u8 spd_vendor_name[8];
	u8 spd_product_description[16];
	u8 major;
	u8 minor;
};

static const struct dp_panel_info fail_safe = {
@@ -99,7 +109,7 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
	int rlen, rc = 0;
	struct dp_panel_private *panel;
	struct drm_dp_link *link_info;
	u8 *dpcd, major = 0, minor = 0;
	u8 *dpcd, rx_feature;
	u32 dfp_count = 0;
	unsigned long caps = DP_LINK_CAP_ENHANCED_FRAMING;

@@ -131,11 +141,33 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
			DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false);
	}

	rlen = drm_dp_dpcd_read(panel->aux->drm_aux,
		DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
	if (rlen != 1) {
		pr_debug("failed to read DPRX_FEATURE_ENUMERATION_LIST\n");
		panel->vsc_supported = false;
		panel->vscext_supported = false;
		panel->vscext_chaining_supported = false;
	} else {
		panel->vsc_supported = !!(rx_feature &
			VSC_SDP_EXTENSION_FOR_COLORIMETRY_SUPPORTED);

		panel->vscext_supported = !!(rx_feature &
			VSC_EXT_VESA_SDP_SUPPORTED);

		panel->vscext_chaining_supported = !!(rx_feature &
			VSC_EXT_VESA_SDP_CHAINING_SUPPORTED);
	}

	pr_debug("vsc=%d, vscext=%d, vscext_chaining=%d\n",
		panel->vsc_supported, panel->vscext_supported,
		panel->vscext_chaining_supported);

	link_info->revision = dp_panel->dpcd[DP_DPCD_REV];

	major = (link_info->revision >> 4) & 0x0f;
	minor = link_info->revision & 0x0f;
	pr_debug("version: %d.%d\n", major, minor);
	panel->major = (link_info->revision >> 4) & 0x0f;
	panel->minor = link_info->revision & 0x0f;
	pr_debug("version: %d.%d\n", panel->major, panel->minor);

	link_info->rate =
		drm_dp_bw_code_to_link_rate(dp_panel->dpcd[DP_MAX_LINK_RATE]);
@@ -655,6 +687,21 @@ static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel)
	return min_link_rate_khz;
}

static bool dp_panel_hdr_supported(struct dp_panel *dp_panel)
{
	struct dp_panel_private *panel;

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

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

	return panel->major >= 1 && panel->vsc_supported &&
		(panel->minor >= 4 || panel->vscext_supported);
}

static bool dp_panel_is_validate_hdr_state(struct dp_panel_private *panel,
		struct drm_msm_ext_hdr_metadata *hdr_meta)
{
@@ -731,7 +778,10 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
	hdr->version = 0x01;
	hdr->length = 0x1A;

	if (panel->hdr_state)
		memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta));
	else
		memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));

	panel->catalog->config_hdr(panel->catalog, panel->hdr_state);
end:
@@ -806,6 +856,7 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in)
	dp_panel->tpg_config = dp_panel_tpg_config;
	dp_panel->spd_config = dp_panel_spd_config;
	dp_panel->setup_hdr = dp_panel_setup_hdr;
	dp_panel->hdr_supported = dp_panel_hdr_supported;

	dp_panel_edid_register(panel);

Loading