| From foo@baz Sun Jun 17 12:07:34 CEST 2018 |
| From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de> |
| Date: Fri, 2 Feb 2018 16:11:23 +0100 |
| Subject: drm/exynos: mixer: avoid Oops in vp_video_buffer() |
| |
| From: Tobias Jakobi <tjakobi@math.uni-bielefeld.de> |
| |
| [ Upstream commit 0ccc1c8f0282e237a0bd6dca7cdac4ed5e318ee7 ] |
| |
| If an interlaced video mode is selected, a IOMMU pagefault is |
| triggered by vp_video_buffer(). |
| |
| Fix the most apparent bugs: |
| - pitch value for chroma plane |
| - divide by two of height and vpos of source and destination |
| |
| Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de> |
| [ a.hajda: Halved also destination height and vpos, updated commit message ] |
| Signed-off-by: Andrzej Hajda <a.hajda@samsung.com> |
| Signed-off-by: Inki Dae <inki.dae@samsung.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/gpu/drm/exynos/exynos_mixer.c | 12 +++++++----- |
| 1 file changed, 7 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/gpu/drm/exynos/exynos_mixer.c |
| +++ b/drivers/gpu/drm/exynos/exynos_mixer.c |
| @@ -485,7 +485,7 @@ static void vp_video_buffer(struct mixer |
| chroma_addr[1] = chroma_addr[0] + 0x40; |
| } else { |
| luma_addr[1] = luma_addr[0] + fb->pitches[0]; |
| - chroma_addr[1] = chroma_addr[0] + fb->pitches[0]; |
| + chroma_addr[1] = chroma_addr[0] + fb->pitches[1]; |
| } |
| } else { |
| luma_addr[1] = 0; |
| @@ -508,21 +508,23 @@ static void vp_video_buffer(struct mixer |
| vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | |
| VP_IMG_VSIZE(fb->height)); |
| /* chroma plane for NV12/NV21 is half the height of the luma plane */ |
| - vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | |
| + vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[1]) | |
| VP_IMG_VSIZE(fb->height / 2)); |
| |
| vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w); |
| - vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h); |
| vp_reg_write(ctx, VP_SRC_H_POSITION, |
| VP_SRC_H_POSITION_VAL(state->src.x)); |
| - vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y); |
| - |
| vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w); |
| vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x); |
| + |
| if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { |
| + vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h / 2); |
| + vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y / 2); |
| vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2); |
| vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2); |
| } else { |
| + vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h); |
| + vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y); |
| vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h); |
| vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y); |
| } |