[PATCH 11/23] drm/omap: Query timing information from analog TV encoder

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Jun 8 16:29:14 UTC 2018


Timings for the TV output are currently reported by the analog TV
connector. This has the disadvantage of having to handle timing-related
operations in a connector omap_dss_device that has, at the hardware
level, no knowledge of any timing information.

Implement the .get_timings() operation in the venc driver, and get
timings from the first component in the pipeline that implements the
operatation. This switches the duty of reporting analog TV timings from
the connector to the encoder.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 drivers/gpu/drm/omapdrm/dss/venc.c       | 12 +++++++++++
 drivers/gpu/drm/omapdrm/omap_connector.c | 34 +++++++++++++++++++++++---------
 2 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index f071d2a82f8f..310cf4251788 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -568,6 +568,16 @@ static void venc_display_disable(struct omap_dss_device *dssdev)
 	mutex_unlock(&venc->venc_lock);
 }
 
+static void venc_get_timings(struct omap_dss_device *dssdev,
+			     struct videomode *vm)
+{
+	struct venc_device *venc = dssdev_to_venc(dssdev);
+
+	mutex_lock(&venc->venc_lock);
+	*vm = venc->vm;
+	mutex_unlock(&venc->venc_lock);
+}
+
 static void venc_set_timings(struct omap_dss_device *dssdev,
 			     const struct videomode *vm)
 {
@@ -720,6 +730,7 @@ static const struct omap_dss_device_ops venc_ops = {
 	.disable = venc_display_disable,
 
 	.check_timings = venc_check_timings,
+	.get_timings = venc_get_timings,
 	.set_timings = venc_set_timings,
 };
 
@@ -877,6 +888,7 @@ static int venc_probe(struct platform_device *pdev)
 	mutex_init(&venc->venc_lock);
 
 	venc->wss_data = 0;
+	venc->vm = omap_dss_pal_vm;
 
 	venc_mem = platform_get_resource(venc->pdev, IORESOURCE_MEM, 0);
 	venc->base = devm_ioremap_resource(&pdev->dev, venc_mem);
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index f4e75a546393..c8101bb37d05 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -218,20 +218,41 @@ static int omap_connector_get_modes(struct drm_connector *connector)
 
 	/*
 	 * If display exposes EDID, then we parse that in the normal way to
-	 * build table of supported modes. Otherwise (ie. fixed resolution
-	 * LCD panels) we just return a single mode corresponding to the
-	 * currently configured timings.
+	 * build table of supported modes.
 	 */
 	dssdev = omap_connector_find_device(connector,
 					    OMAP_DSS_DEVICE_OP_EDID);
 	if (dssdev)
 		return omap_connector_get_modes_edid(connector, dssdev);
 
+	/*
+	 * Otherwise we have either a fixed resolution panel or an output that
+	 * doesn't support modes discovery (e.g. DVI or VGA with the DDC bus
+	 * unconnected, or analog TV). Start by querying the size.
+	 */
+	dssdev = omap_connector->display;
+	if (dssdev->driver && dssdev->driver->get_size)
+		dssdev->driver->get_size(dssdev,
+					 &connector->display_info.width_mm,
+					 &connector->display_info.height_mm);
+
+	/*
+	 * Iterate over the pipeline to find the first device that can provide
+	 * timing information. If we can't find any, we just let the KMS core
+	 * add the default modes.
+	 */
+	for (dssdev = omap_connector->display; dssdev; dssdev = dssdev->src) {
+		if (dssdev->ops->get_timings)
+			break;
+	}
+	if (!dssdev)
+		return 0;
+
+	/* Add a single mode corresponding to the fixed panel timings. */
 	mode = drm_mode_create(connector->dev);
 	if (!mode)
 		return 0;
 
-	dssdev = omap_connector->display;
 	dssdev->ops->get_timings(dssdev, &vm);
 
 	drm_display_mode_from_videomode(&vm, mode);
@@ -240,11 +261,6 @@ static int omap_connector_get_modes(struct drm_connector *connector)
 	drm_mode_set_name(mode);
 	drm_mode_probed_add(connector, mode);
 
-	if (dssdev->driver && dssdev->driver->get_size)
-		dssdev->driver->get_size(dssdev,
-					 &connector->display_info.width_mm,
-					 &connector->display_info.height_mm);
-
 	return 1;
 }
 
-- 
Regards,

Laurent Pinchart



More information about the dri-devel mailing list