diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-09-21 09:13:00 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2019-03-18 05:42:13 -0400 |
commit | d68164fe29642270ffba64ed64b0178ef7d916bf (patch) | |
tree | c45b50d24194a87669042fcb39b36bb206b42081 /drivers/gpu/drm | |
parent | d60dfaba4225d72e54ec887c5e307dd9fc0aa1db (diff) |
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>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.c | 54 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_encoder.c | 30 |
3 files changed, 44 insertions, 45 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index 99ca5b3eaebb..6fceb020e86c 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c | |||
@@ -241,45 +241,51 @@ static int omap_connector_get_modes(struct drm_connector *connector) | |||
241 | return 0; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | static int omap_connector_mode_valid(struct drm_connector *connector, | 244 | enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev, |
245 | struct drm_display_mode *mode) | 245 | const struct drm_display_mode *mode, |
246 | struct drm_display_mode *adjusted_mode) | ||
246 | { | 247 | { |
247 | struct omap_connector *omap_connector = to_omap_connector(connector); | 248 | struct videomode vm = { 0 }; |
248 | struct omap_dss_device *dssdev; | 249 | int ret; |
249 | struct videomode vm = {0}; | ||
250 | struct drm_device *dev = connector->dev; | ||
251 | struct drm_display_mode *new_mode; | ||
252 | int r, ret = MODE_BAD; | ||
253 | 250 | ||
254 | drm_display_mode_to_videomode(mode, &vm); | 251 | drm_display_mode_to_videomode(mode, &vm); |
255 | mode->vrefresh = drm_mode_vrefresh(mode); | ||
256 | 252 | ||
257 | for (dssdev = omap_connector->output; dssdev; dssdev = dssdev->next) { | 253 | for (; dssdev; dssdev = dssdev->next) { |
258 | if (!dssdev->ops->check_timings) | 254 | if (!dssdev->ops->check_timings) |
259 | continue; | 255 | continue; |
260 | 256 | ||
261 | r = dssdev->ops->check_timings(dssdev, &vm); | 257 | ret = dssdev->ops->check_timings(dssdev, &vm); |
262 | if (r) | 258 | if (ret) |
263 | goto done; | 259 | return MODE_BAD; |
264 | } | 260 | } |
265 | 261 | ||
266 | /* check if vrefresh is still valid */ | 262 | drm_display_mode_from_videomode(&vm, adjusted_mode); |
267 | new_mode = drm_mode_duplicate(dev, mode); | ||
268 | if (!new_mode) | ||
269 | return MODE_BAD; | ||
270 | 263 | ||
271 | new_mode->clock = vm.pixelclock / 1000; | 264 | return MODE_OK; |
272 | new_mode->vrefresh = 0; | 265 | } |
273 | if (mode->vrefresh == drm_mode_vrefresh(new_mode)) | 266 | |
274 | ret = MODE_OK; | 267 | static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector, |
275 | drm_mode_destroy(dev, new_mode); | 268 | struct drm_display_mode *mode) |
269 | { | ||
270 | struct omap_connector *omap_connector = to_omap_connector(connector); | ||
271 | struct drm_display_mode new_mode = { { 0 } }; | ||
272 | enum drm_mode_status status; | ||
273 | |||
274 | status = omap_connector_mode_fixup(omap_connector->output, mode, | ||
275 | &new_mode); | ||
276 | if (status != MODE_OK) | ||
277 | goto done; | ||
278 | |||
279 | /* Check if vrefresh is still valid. */ | ||
280 | if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(&new_mode)) | ||
281 | status = MODE_NOCLOCK; | ||
276 | 282 | ||
277 | done: | 283 | done: |
278 | DBG("connector: mode %s: " DRM_MODE_FMT, | 284 | DBG("connector: mode %s: " DRM_MODE_FMT, |
279 | (ret == MODE_OK) ? "valid" : "invalid", | 285 | (status == MODE_OK) ? "valid" : "invalid", |
280 | DRM_MODE_ARG(mode)); | 286 | DRM_MODE_ARG(mode)); |
281 | 287 | ||
282 | return ret; | 288 | return status; |
283 | } | 289 | } |
284 | 290 | ||
285 | static const struct drm_connector_funcs omap_connector_funcs = { | 291 | static const struct drm_connector_funcs omap_connector_funcs = { |
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.h b/drivers/gpu/drm/omapdrm/omap_connector.h index 4a1dcd0f031b..6b7d4d95e32b 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.h +++ b/drivers/gpu/drm/omapdrm/omap_connector.h | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | 24 | ||
25 | enum drm_mode_status; | ||
26 | |||
25 | struct drm_connector; | 27 | struct drm_connector; |
26 | struct drm_device; | 28 | struct drm_device; |
27 | struct drm_encoder; | 29 | struct drm_encoder; |
@@ -34,5 +36,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, | |||
34 | bool omap_connector_get_hdmi_mode(struct drm_connector *connector); | 36 | bool omap_connector_get_hdmi_mode(struct drm_connector *connector); |
35 | void omap_connector_enable_hpd(struct drm_connector *connector); | 37 | void omap_connector_enable_hpd(struct drm_connector *connector); |
36 | void omap_connector_disable_hpd(struct drm_connector *connector); | 38 | void omap_connector_disable_hpd(struct drm_connector *connector); |
39 | enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev, | ||
40 | const struct drm_display_mode *mode, | ||
41 | struct drm_display_mode *adjusted_mode); | ||
37 | 42 | ||
38 | #endif /* __OMAPDRM_CONNECTOR_H__ */ | 43 | #endif /* __OMAPDRM_CONNECTOR_H__ */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 623154bc44bb..3a7cca01888e 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c | |||
@@ -206,29 +206,17 @@ static int omap_encoder_atomic_check(struct drm_encoder *encoder, | |||
206 | struct drm_connector_state *conn_state) | 206 | struct drm_connector_state *conn_state) |
207 | { | 207 | { |
208 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 208 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
209 | struct drm_device *dev = encoder->dev; | 209 | enum drm_mode_status status; |
210 | struct omap_dss_device *dssdev; | 210 | |
211 | struct videomode vm = { 0 }; | 211 | status = omap_connector_mode_fixup(omap_encoder->output, |
212 | int ret; | 212 | &crtc_state->mode, |
213 | 213 | &crtc_state->adjusted_mode); | |
214 | drm_display_mode_to_videomode(&crtc_state->mode, &vm); | 214 | if (status != MODE_OK) { |
215 | 215 | dev_err(encoder->dev->dev, "invalid timings: %d\n", status); | |
216 | for (dssdev = omap_encoder->output; dssdev; dssdev = dssdev->next) { | 216 | return -EINVAL; |
217 | if (!dssdev->ops->check_timings) | ||
218 | continue; | ||
219 | |||
220 | ret = dssdev->ops->check_timings(dssdev, &vm); | ||
221 | if (ret) | ||
222 | goto done; | ||
223 | } | 217 | } |
224 | 218 | ||
225 | drm_display_mode_from_videomode(&vm, &crtc_state->adjusted_mode); | 219 | return 0; |
226 | |||
227 | done: | ||
228 | if (ret) | ||
229 | dev_err(dev->dev, "invalid timings: %d\n", ret); | ||
230 | |||
231 | return ret; | ||
232 | } | 220 | } |
233 | 221 | ||
234 | static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { | 222 | static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { |