Commit 6c623d6b authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Tomi Valkeinen
Browse files

drm/omap: hdmi5: Register a drm_bridge for EDID read



In order to integrate with a chain of drm_bridge, the internal HDMI5
encoder has to expose the EDID read operation through the drm_bridge
API. Register a bridge at initialisation time to do so.

For the time being make the next bridge in the chain optional as the
HDMI output is still based on omap_dss_device. The create_connector
argument to the bridge attach function is also ignored for the same
reason. This will be changed later when removing the related
omapdrm-specific display drivers.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Tested-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Reviewed-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200226112514.12455-33-laurent.pinchart@ideasonboard.com
parent ee34f23a
Loading
Loading
Loading
Loading
+73 −6
Original line number Diff line number Diff line
@@ -388,8 +388,10 @@ static void hdmi_disconnect(struct omap_dss_device *src,

#define MAX_EDID	512

static struct edid *hdmi_read_edid_data(struct hdmi_core_data *core)
static struct edid *hdmi_read_edid_data(struct omap_hdmi *hdmi,
					struct drm_connector *connector)
{
	struct hdmi_core_data *core = &hdmi->core;
	int max_ext_blocks = 3;
	int r, n, i;
	u8 *edid;
@@ -421,9 +423,12 @@ error:
	return NULL;
}

static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
static struct edid *
hdmi_do_read_edid(struct omap_hdmi *hdmi,
		  struct edid *(*read)(struct omap_hdmi *hdmi,
				       struct drm_connector *connector),
		  struct drm_connector *connector)
{
	struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
	struct edid *edid;
	bool need_enable;
	int idlemode;
@@ -447,7 +452,7 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)

	hdmi5_core_ddc_init(&hdmi->core);

	edid = hdmi_read_edid_data(&hdmi->core);
	edid = read(hdmi, connector);

	hdmi5_core_ddc_uninit(&hdmi->core);

@@ -462,6 +467,12 @@ static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
	return (struct edid *)edid;
}

static struct edid *hdmi_read_edid(struct omap_dss_device *dssdev)
{
	return hdmi_do_read_edid(dssdev_to_hdmi(dssdev), hdmi_read_edid_data,
				 NULL);
}

static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
		const struct hdmi_avi_infoframe *avi)
{
@@ -497,6 +508,56 @@ static const struct omap_dss_device_ops hdmi_ops = {
	},
};

/* -----------------------------------------------------------------------------
 * DRM Bridge Operations
 */

static int hdmi5_bridge_attach(struct drm_bridge *bridge,
			       enum drm_bridge_attach_flags flags)
{
	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);

	if (!hdmi->output.next_bridge)
		return 0;

	return drm_bridge_attach(bridge->encoder, hdmi->output.next_bridge,
				 bridge, flags);
}

static struct edid *hdmi5_bridge_read_edid(struct omap_hdmi *hdmi,
					   struct drm_connector *connector)
{
	return drm_do_get_edid(connector, hdmi5_core_ddc_read, &hdmi->core);
}

static struct edid *hdmi5_bridge_get_edid(struct drm_bridge *bridge,
					  struct drm_connector *connector)
{
	struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);

	return hdmi_do_read_edid(hdmi, hdmi5_bridge_read_edid, connector);
}

static const struct drm_bridge_funcs hdmi5_bridge_funcs = {
	.attach = hdmi5_bridge_attach,
	.get_edid = hdmi5_bridge_get_edid,
};

static void hdmi5_bridge_init(struct omap_hdmi *hdmi)
{
	hdmi->bridge.funcs = &hdmi5_bridge_funcs;
	hdmi->bridge.of_node = hdmi->pdev->dev.of_node;
	hdmi->bridge.ops = DRM_BRIDGE_OP_EDID;
	hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;

	drm_bridge_add(&hdmi->bridge);
}

static void hdmi5_bridge_cleanup(struct omap_hdmi *hdmi)
{
	drm_bridge_remove(&hdmi->bridge);
}

/* -----------------------------------------------------------------------------
 * Audio Callbacks
 */
@@ -679,6 +740,8 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
	struct omap_dss_device *out = &hdmi->output;
	int r;

	hdmi5_bridge_init(hdmi);

	out->dev = &hdmi->pdev->dev;
	out->id = OMAP_DSS_OUTPUT_HDMI;
	out->type = OMAP_DISPLAY_TYPE_HDMI;
@@ -689,9 +752,11 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
	out->of_port = 0;
	out->ops_flags = OMAP_DSS_DEVICE_OP_EDID;

	r = omapdss_device_init_output(out, NULL);
	if (r < 0)
	r = omapdss_device_init_output(out, &hdmi->bridge);
	if (r < 0) {
		hdmi5_bridge_cleanup(hdmi);
		return r;
	}

	omapdss_device_register(out);

@@ -704,6 +769,8 @@ static void hdmi5_uninit_output(struct omap_hdmi *hdmi)

	omapdss_device_unregister(out);
	omapdss_device_cleanup_output(out);

	hdmi5_bridge_cleanup(hdmi);
}

static int hdmi5_probe_of(struct omap_hdmi *hdmi)