diff options
Diffstat (limited to 'drivers/gpu/drm/imx/ipuv3-plane.c')
-rw-r--r-- | drivers/gpu/drm/imx/ipuv3-plane.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index ce22d0a0ddc8..d5864ed4d772 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c | |||
@@ -103,11 +103,11 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) | |||
103 | (state->src_x >> 16) / 2 - eba; | 103 | (state->src_x >> 16) / 2 - eba; |
104 | } | 104 | } |
105 | 105 | ||
106 | static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane, | 106 | static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane) |
107 | struct drm_plane_state *old_state) | ||
108 | { | 107 | { |
109 | struct drm_plane *plane = &ipu_plane->base; | 108 | struct drm_plane *plane = &ipu_plane->base; |
110 | struct drm_plane_state *state = plane->state; | 109 | struct drm_plane_state *state = plane->state; |
110 | struct drm_crtc_state *crtc_state = state->crtc->state; | ||
111 | struct drm_framebuffer *fb = state->fb; | 111 | struct drm_framebuffer *fb = state->fb; |
112 | unsigned long eba, ubo, vbo; | 112 | unsigned long eba, ubo, vbo; |
113 | int active; | 113 | int active; |
@@ -117,7 +117,7 @@ static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane, | |||
117 | switch (fb->pixel_format) { | 117 | switch (fb->pixel_format) { |
118 | case DRM_FORMAT_YUV420: | 118 | case DRM_FORMAT_YUV420: |
119 | case DRM_FORMAT_YVU420: | 119 | case DRM_FORMAT_YVU420: |
120 | if (old_state->fb) | 120 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) |
121 | break; | 121 | break; |
122 | 122 | ||
123 | /* | 123 | /* |
@@ -149,7 +149,7 @@ static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane, | |||
149 | break; | 149 | break; |
150 | } | 150 | } |
151 | 151 | ||
152 | if (old_state->fb) { | 152 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) { |
153 | active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); | 153 | active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch); |
154 | ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); | 154 | ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba); |
155 | ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); | 155 | ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); |
@@ -259,6 +259,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, | |||
259 | struct drm_framebuffer *fb = state->fb; | 259 | struct drm_framebuffer *fb = state->fb; |
260 | struct drm_framebuffer *old_fb = old_state->fb; | 260 | struct drm_framebuffer *old_fb = old_state->fb; |
261 | unsigned long eba, ubo, vbo, old_ubo, old_vbo; | 261 | unsigned long eba, ubo, vbo, old_ubo, old_vbo; |
262 | int hsub, vsub; | ||
262 | 263 | ||
263 | /* Ok to disable */ | 264 | /* Ok to disable */ |
264 | if (!fb) | 265 | if (!fb) |
@@ -355,7 +356,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, | |||
355 | if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) | 356 | if ((ubo > 0xfffff8) || (vbo > 0xfffff8)) |
356 | return -EINVAL; | 357 | return -EINVAL; |
357 | 358 | ||
358 | if (old_fb) { | 359 | if (old_fb && |
360 | (old_fb->pixel_format == DRM_FORMAT_YUV420 || | ||
361 | old_fb->pixel_format == DRM_FORMAT_YVU420)) { | ||
359 | old_ubo = drm_plane_state_to_ubo(old_state); | 362 | old_ubo = drm_plane_state_to_ubo(old_state); |
360 | old_vbo = drm_plane_state_to_vbo(old_state); | 363 | old_vbo = drm_plane_state_to_vbo(old_state); |
361 | if (ubo != old_ubo || vbo != old_vbo) | 364 | if (ubo != old_ubo || vbo != old_vbo) |
@@ -370,6 +373,16 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, | |||
370 | 373 | ||
371 | if (old_fb && old_fb->pitches[1] != fb->pitches[1]) | 374 | if (old_fb && old_fb->pitches[1] != fb->pitches[1]) |
372 | crtc_state->mode_changed = true; | 375 | crtc_state->mode_changed = true; |
376 | |||
377 | /* | ||
378 | * The x/y offsets must be even in case of horizontal/vertical | ||
379 | * chroma subsampling. | ||
380 | */ | ||
381 | hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); | ||
382 | vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); | ||
383 | if (((state->src_x >> 16) & (hsub - 1)) || | ||
384 | ((state->src_y >> 16) & (vsub - 1))) | ||
385 | return -EINVAL; | ||
373 | } | 386 | } |
374 | 387 | ||
375 | return 0; | 388 | return 0; |
@@ -392,7 +405,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
392 | struct drm_crtc_state *crtc_state = state->crtc->state; | 405 | struct drm_crtc_state *crtc_state = state->crtc->state; |
393 | 406 | ||
394 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) { | 407 | if (!drm_atomic_crtc_needs_modeset(crtc_state)) { |
395 | ipu_plane_atomic_set_base(ipu_plane, old_state); | 408 | ipu_plane_atomic_set_base(ipu_plane); |
396 | return; | 409 | return; |
397 | } | 410 | } |
398 | } | 411 | } |
@@ -424,6 +437,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
424 | ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); | 437 | ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false); |
425 | break; | 438 | break; |
426 | default: | 439 | default: |
440 | ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); | ||
427 | break; | 441 | break; |
428 | } | 442 | } |
429 | } | 443 | } |
@@ -437,7 +451,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, | |||
437 | ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); | 451 | ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); |
438 | ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); | 452 | ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); |
439 | ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); | 453 | ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); |
440 | ipu_plane_atomic_set_base(ipu_plane, old_state); | 454 | ipu_plane_atomic_set_base(ipu_plane); |
441 | ipu_plane_enable(ipu_plane); | 455 | ipu_plane_enable(ipu_plane); |
442 | } | 456 | } |
443 | 457 | ||