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

Commit 71aec2d3 authored by Padmanabhan Komanduru's avatar Padmanabhan Komanduru Committed by Ajay Singh Parmar
Browse files

drm/msm/dp: add support for custom hotplug event in DP driver



Add support to send custom hotplug notifications from display
port driver. This would avoid duplication of code between DRM
upstream driver/MSM DRM driver and also enables to add more
information as part of the uevent string like bpp/video test
pattern information.

CRs-Fixed: 2093830
Change-Id: I186410221c7f642fbea7bd47a838769cfeaee8a1
Signed-off-by: default avatarPadmanabhan Komanduru <pkomandu@codeaurora.org>
parent 6ce8ab38
Loading
Loading
Loading
Loading
+49 −2
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "dp_debug.h"

static struct dp_display *g_dp_display;
#define HPD_STRING_SIZE 30

struct dp_hdcp {
	void *data;
@@ -434,10 +435,55 @@ 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)
{
	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;
	}

	dp = container_of(dp_display, struct dp_display_private, dp_display);
	if (!dp) {
		pr_err("invalid params\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));
	snprintf(name, HPD_STRING_SIZE, "name=%s", connector->name);
	snprintf(status, HPD_STRING_SIZE, "status=%s",
		drm_get_connector_status_name(connector->status));
	snprintf(bpp, HPD_STRING_SIZE, "bpp=%d",
		dp_link_bit_depth_to_bpp(
		dp->link->test_video.test_bit_depth));
	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);
	envp[0] = name;
	envp[1] = status;
	envp[2] = bpp;
	envp[3] = pattern;
	envp[4] = NULL;
	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE,
			envp);
}

static int dp_display_send_hpd_notification(struct dp_display_private *dp,
		bool hpd)
{

	if ((hpd && dp->dp_display.is_connected) ||
			(!hpd && !dp->dp_display.is_connected)) {
		pr_info("HPD already %s\n", (hpd ? "on" : "off"));
@@ -446,7 +492,7 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp,

	dp->dp_display.is_connected = hpd;
	reinit_completion(&dp->notification_comp);
	drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
	dp_display_send_hpd_event(&dp->dp_display);

	if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2)) {
		pr_warn("%s timeout\n", hpd ? "connect" : "disconnect");
@@ -1024,6 +1070,7 @@ 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;

	rc = component_add(&pdev->dev, &dp_display_comp_ops);
	if (rc)
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ 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);
};

int dp_display_get_num_of_displays(void);
+15 −0
Original line number Diff line number Diff line
@@ -375,6 +375,21 @@ enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
	return status;
}

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

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

	dp = display;

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

int dp_connector_get_modes(struct drm_connector *connector,
		void *display)
{
+2 −0
Original line number Diff line number Diff line
@@ -86,6 +86,8 @@ 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);

int dp_drm_bridge_init(void *display,
	struct drm_encoder *encoder);

+0 −36
Original line number Diff line number Diff line
@@ -60,42 +60,6 @@ struct dp_link_private {
	u8 link_status[DP_LINK_STATUS_SIZE];
};

/**
 * mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp
 * @tbd: test bit depth
 *
 * Returns the bits per pixel (bpp) to be used corresponding to the
 * git bit depth value. This function assumes that bit depth has
 * already been validated.
 */
static inline u32 dp_link_bit_depth_to_bpp(u32 tbd)
{
	u32 bpp;

	/*
	 * Few simplistic rules and assumptions made here:
	 *    1. Bit depth is per color component
	 *    2. If bit depth is unknown return 0
	 *    3. Assume 3 color components
	 */
	switch (tbd) {
	case DP_TEST_BIT_DEPTH_6:
		bpp = 18;
		break;
	case DP_TEST_BIT_DEPTH_8:
		bpp = 24;
		break;
	case DP_TEST_BIT_DEPTH_10:
		bpp = 30;
		break;
	case DP_TEST_BIT_DEPTH_UNKNOWN:
	default:
		bpp = 0;
	}

	return bpp;
}

static char *dp_link_get_audio_test_pattern(u32 pattern)
{
	switch (pattern) {
Loading