|
11 | 11 | */
|
12 | 12 |
|
13 | 13 | #include <drm/drmP.h>
|
| 14 | +#include <drm/drm_atomic.h> |
14 | 15 | #include <drm/drm_atomic_helper.h>
|
15 | 16 | #include <drm/drm_crtc.h>
|
16 | 17 | #include <drm/drm_crtc_helper.h>
|
@@ -270,6 +271,69 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
|
270 | 271 | return 0;
|
271 | 272 | }
|
272 | 273 |
|
| 274 | +static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) |
| 275 | +{ |
| 276 | + u16 src_h = state->src_h >> 16; |
| 277 | + u16 src_w = state->src_w >> 16; |
| 278 | + |
| 279 | + DRM_DEBUG_DRIVER("Input size %dx%d, output size %dx%d\n", |
| 280 | + src_w, src_h, state->crtc_w, state->crtc_h); |
| 281 | + |
| 282 | + if ((state->crtc_h != src_h) || (state->crtc_w != src_w)) |
| 283 | + return true; |
| 284 | + |
| 285 | + return false; |
| 286 | +} |
| 287 | + |
| 288 | +static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) |
| 289 | +{ |
| 290 | + struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); |
| 291 | + struct sun4i_backend *backend = layer->backend; |
| 292 | + |
| 293 | + if (IS_ERR(backend->frontend)) |
| 294 | + return false; |
| 295 | + |
| 296 | + return sun4i_backend_plane_uses_scaler(state); |
| 297 | +} |
| 298 | + |
| 299 | +static int sun4i_backend_atomic_check(struct sunxi_engine *engine, |
| 300 | + struct drm_crtc_state *crtc_state) |
| 301 | +{ |
| 302 | + struct drm_atomic_state *state = crtc_state->state; |
| 303 | + struct drm_device *drm = state->dev; |
| 304 | + struct drm_plane *plane; |
| 305 | + unsigned int num_frontend_planes = 0; |
| 306 | + |
| 307 | + DRM_DEBUG_DRIVER("Starting checking our planes\n"); |
| 308 | + |
| 309 | + if (!crtc_state->planes_changed) |
| 310 | + return 0; |
| 311 | + |
| 312 | + drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) { |
| 313 | + struct drm_plane_state *plane_state = |
| 314 | + drm_atomic_get_plane_state(state, plane); |
| 315 | + struct sun4i_layer_state *layer_state = |
| 316 | + state_to_sun4i_layer_state(plane_state); |
| 317 | + |
| 318 | + if (sun4i_backend_plane_uses_frontend(plane_state)) { |
| 319 | + DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", |
| 320 | + plane->index); |
| 321 | + |
| 322 | + layer_state->uses_frontend = true; |
| 323 | + num_frontend_planes++; |
| 324 | + } else { |
| 325 | + layer_state->uses_frontend = false; |
| 326 | + } |
| 327 | + } |
| 328 | + |
| 329 | + if (num_frontend_planes > SUN4I_BACKEND_NUM_FRONTEND_LAYERS) { |
| 330 | + DRM_DEBUG_DRIVER("Too many planes going through the frontend, rejecting\n"); |
| 331 | + return -EINVAL; |
| 332 | + } |
| 333 | + |
| 334 | + return 0; |
| 335 | +} |
| 336 | + |
273 | 337 | static void sun4i_backend_vblank_quirk(struct sunxi_engine *engine)
|
274 | 338 | {
|
275 | 339 | struct sun4i_backend *backend = engine_to_sun4i_backend(engine);
|
@@ -414,6 +478,7 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
|
414 | 478 | }
|
415 | 479 |
|
416 | 480 | static const struct sunxi_engine_ops sun4i_backend_engine_ops = {
|
| 481 | + .atomic_check = sun4i_backend_atomic_check, |
417 | 482 | .commit = sun4i_backend_commit,
|
418 | 483 | .layers_init = sun4i_layers_init,
|
419 | 484 | .apply_color_correction = sun4i_backend_apply_color_correction,
|
|
0 commit comments