drm/omap: Factor out common mode validation code

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>
This commit is contained in:
Laurent Pinchart 2018-09-21 16:13:00 +03:00 committed by Tomi Valkeinen
parent d60dfaba42
commit d68164fe29
3 changed files with 43 additions and 44 deletions

View File

@ -241,45 +241,51 @@ static int omap_connector_get_modes(struct drm_connector *connector)
return 0; return 0;
} }
static int omap_connector_mode_valid(struct drm_connector *connector, enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
struct drm_display_mode *mode) const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{ {
struct omap_connector *omap_connector = to_omap_connector(connector); struct videomode vm = { 0 };
struct omap_dss_device *dssdev; int ret;
struct videomode vm = {0};
struct drm_device *dev = connector->dev;
struct drm_display_mode *new_mode;
int r, ret = MODE_BAD;
drm_display_mode_to_videomode(mode, &vm); 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) if (!dssdev->ops->check_timings)
continue; continue;
r = dssdev->ops->check_timings(dssdev, &vm); ret = dssdev->ops->check_timings(dssdev, &vm);
if (r) if (ret)
goto done; return MODE_BAD;
} }
/* check if vrefresh is still valid */ drm_display_mode_from_videomode(&vm, adjusted_mode);
new_mode = drm_mode_duplicate(dev, mode);
if (!new_mode)
return MODE_BAD;
new_mode->clock = vm.pixelclock / 1000; return MODE_OK;
new_mode->vrefresh = 0; }
if (mode->vrefresh == drm_mode_vrefresh(new_mode))
ret = MODE_OK; static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector,
drm_mode_destroy(dev, new_mode); 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: done:
DBG("connector: mode %s: " DRM_MODE_FMT, DBG("connector: mode %s: " DRM_MODE_FMT,
(ret == MODE_OK) ? "valid" : "invalid", (status == MODE_OK) ? "valid" : "invalid",
DRM_MODE_ARG(mode)); DRM_MODE_ARG(mode));
return ret; return status;
} }
static const struct drm_connector_funcs omap_connector_funcs = { static const struct drm_connector_funcs omap_connector_funcs = {

View File

@ -22,6 +22,8 @@
#include <linux/types.h> #include <linux/types.h>
enum drm_mode_status;
struct drm_connector; struct drm_connector;
struct drm_device; struct drm_device;
struct drm_encoder; 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); bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
void omap_connector_enable_hpd(struct drm_connector *connector); void omap_connector_enable_hpd(struct drm_connector *connector);
void omap_connector_disable_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__ */ #endif /* __OMAPDRM_CONNECTOR_H__ */

View File

@ -206,29 +206,17 @@ static int omap_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state) struct drm_connector_state *conn_state)
{ {
struct omap_encoder *omap_encoder = to_omap_encoder(encoder); struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct drm_device *dev = encoder->dev; enum drm_mode_status status;
struct omap_dss_device *dssdev;
struct videomode vm = { 0 };
int ret;
drm_display_mode_to_videomode(&crtc_state->mode, &vm); status = omap_connector_mode_fixup(omap_encoder->output,
&crtc_state->mode,
for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) { &crtc_state->adjusted_mode);
if (!dssdev->ops->check_timings) if (status != MODE_OK) {
continue; dev_err(encoder->dev->dev, "invalid timings: %d\n", status);
return -EINVAL;
ret = dssdev->ops->check_timings(dssdev, &vm);
if (ret)
goto done;
} }
drm_display_mode_from_videomode(&vm, &crtc_state->adjusted_mode); return 0;
done:
if (ret)
dev_err(dev->dev, "invalid timings: %d\n", ret);
return ret;
} }
static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {