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

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: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Tested-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent d60dfaba
Loading
Loading
Loading
Loading
+30 −24
Original line number Original line Diff line number Diff line
@@ -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 omap_dss_device *dssdev;
	struct videomode vm = { 0 };
	struct videomode vm = { 0 };
	struct drm_device *dev = connector->dev;
	int ret;
	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 = {
+5 −0
Original line number Original line Diff line number Diff line
@@ -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__ */
+9 −21
Original line number Original line Diff line number Diff line
@@ -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);


	for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) {
	status = omap_connector_mode_fixup(omap_encoder->output,
		if (!dssdev->ops->check_timings)
					   &crtc_state->mode,
			continue;
					   &crtc_state->adjusted_mode);

	if (status != MODE_OK) {
		ret = dssdev->ops->check_timings(dssdev, &vm);
		dev_err(encoder->dev->dev, "invalid timings: %d\n", status);
		if (ret)
		return -EINVAL;
			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 = {