drm/omap: Factor out common mode validation code
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 21 Sep 2018 13:13:00 +0000 (16:13 +0300)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Mon, 18 Mar 2019 09:42:13 +0000 (11:42 +0200)
The encoder .atomic_check() and connector .mode_valid() operations both
walk through the dss devices in the pipeline to validate the mode.
Factor out the common code in a new omap_drm_connector_mode_fixup()
function.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/omapdrm/omap_connector.c
drivers/gpu/drm/omapdrm/omap_connector.h
drivers/gpu/drm/omapdrm/omap_encoder.c

index 99ca5b3..6fceb02 100644 (file)
@@ -241,45 +241,51 @@ static int omap_connector_get_modes(struct drm_connector *connector)
        return 0;
 }
 
-static int omap_connector_mode_valid(struct drm_connector *connector,
-                                struct drm_display_mode *mode)
+enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
+                                       const struct drm_display_mode *mode,
+                                       struct drm_display_mode *adjusted_mode)
 {
-       struct omap_connector *omap_connector = to_omap_connector(connector);
-       struct omap_dss_device *dssdev;
-       struct videomode vm = {0};
-       struct drm_device *dev = connector->dev;
-       struct drm_display_mode *new_mode;
-       int r, ret = MODE_BAD;
+       struct videomode vm = { 0 };
+       int ret;
 
        drm_display_mode_to_videomode(mode, &vm);
-       mode->vrefresh = drm_mode_vrefresh(mode);
 
-       for (dssdev = omap_connector->output; dssdev; dssdev = dssdev->next) {
+       for (; dssdev; dssdev = dssdev->next) {
                if (!dssdev->ops->check_timings)
                        continue;
 
-               r = dssdev->ops->check_timings(dssdev, &vm);
-               if (r)
-                       goto done;
+               ret = dssdev->ops->check_timings(dssdev, &vm);
+               if (ret)
+                       return MODE_BAD;
        }
 
-       /* check if vrefresh is still valid */
-       new_mode = drm_mode_duplicate(dev, mode);
-       if (!new_mode)
-               return MODE_BAD;
+       drm_display_mode_from_videomode(&vm, adjusted_mode);
 
-       new_mode->clock = vm.pixelclock / 1000;
-       new_mode->vrefresh = 0;
-       if (mode->vrefresh == drm_mode_vrefresh(new_mode))
-               ret = MODE_OK;
-       drm_mode_destroy(dev, new_mode);
+       return MODE_OK;
+}
+
+static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector,
+                                struct drm_display_mode *mode)
+{
+       struct omap_connector *omap_connector = to_omap_connector(connector);
+       struct drm_display_mode new_mode = { { 0 } };
+       enum drm_mode_status status;
+
+       status = omap_connector_mode_fixup(omap_connector->output, mode,
+                                          &new_mode);
+       if (status != MODE_OK)
+               goto done;
+
+       /* Check if vrefresh is still valid. */
+       if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(&new_mode))
+               status = MODE_NOCLOCK;
 
 done:
        DBG("connector: mode %s: " DRM_MODE_FMT,
-                       (ret == MODE_OK) ? "valid" : "invalid",
+                       (status == MODE_OK) ? "valid" : "invalid",
                        DRM_MODE_ARG(mode));
 
-       return ret;
+       return status;
 }
 
 static const struct drm_connector_funcs omap_connector_funcs = {
index 4a1dcd0..6b7d4d9 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <linux/types.h>
 
+enum drm_mode_status;
+
 struct drm_connector;
 struct drm_device;
 struct drm_encoder;
@@ -34,5 +36,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev,
 bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
 void omap_connector_enable_hpd(struct drm_connector *connector);
 void omap_connector_disable_hpd(struct drm_connector *connector);
+enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
+                                       const struct drm_display_mode *mode,
+                                       struct drm_display_mode *adjusted_mode);
 
 #endif /* __OMAPDRM_CONNECTOR_H__ */
index 623154b..3a7cca0 100644 (file)
@@ -206,29 +206,17 @@ static int omap_encoder_atomic_check(struct drm_encoder *encoder,
                                     struct drm_connector_state *conn_state)
 {
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       struct drm_device *dev = encoder->dev;
-       struct omap_dss_device *dssdev;
-       struct videomode vm = { 0 };
-       int ret;
-
-       drm_display_mode_to_videomode(&crtc_state->mode, &vm);
-
-       for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
-               if (!dssdev->ops->check_timings)
-                       continue;
-
-               ret = dssdev->ops->check_timings(dssdev, &vm);
-               if (ret)
-                       goto done;
+       enum drm_mode_status status;
+
+       status = omap_connector_mode_fixup(omap_encoder->output,
+                                          &crtc_state->mode,
+                                          &crtc_state->adjusted_mode);
+       if (status != MODE_OK) {
+               dev_err(encoder->dev->dev, "invalid timings: %d\n", status);
+               return -EINVAL;
        }
 
-       drm_display_mode_from_videomode(&vm, &crtc_state->adjusted_mode);
-
-done:
-       if (ret)
-               dev_err(dev->dev, "invalid timings: %d\n", ret);
-
-       return ret;
+       return 0;
 }
 
 static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {