[PATCH v2] drm/exynos: mixer: avoid Oops in vp_video_buffer()
Tobias Jakobi
tjakobi at math.uni-bielefeld.de
Thu Nov 30 15:47:45 UTC 2017
Inki Dae wrote:
> Hi Tobias,
>
> Thanks for touching this code.
>
> But I think below changes chould be explained exactly. Anyway, below are my comments,
>
> 2017년 11월 23일 23:19에 Tobias Jakobi 이(가) 쓴 글:
>> 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
>>
>> This is more like a band-aid at this point. The VP plane is
>> still corrupted, but at least there are no more pagefaults.
>>
>> Signed-off-by: Tobias Jakobi <tjakobi at math.uni-bielefeld.de>
>> ---
>> drivers/gpu/drm/exynos/exynos_mixer.c | 21 +++++++++++----------
>> 1 file changed, 11 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
>> index dc5d79465f9b..a18426379e57 100644
>> --- 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_context *ctx,
>> 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];
>
> chroma_addr[1] is set to VP_BOT_C_PTR register and datasheet says about this register,
> "specifies base address for Chrominance of bottom field"
>
> Before that, we would need to look into NV12 pixel format and its video signal mode - interlaced or progressive.
You're mixing something up here. The buffer is (progressive) NV12, but the video
mode is interlaced.
> NV12 interfaced
> YYYYYYYYYY
> YYYYYYYYYY
> UVUVUVUVUV
> YYYYYYYYYY
> YYYYYYYYYY
> UVUVUVUVUV
>
> NV12 progressive
> YYYYYYYYYY
> YYYYYYYYYY
> YYYYYYYYYY
> YYYYYYYYYY
> UVUVUVUVUV
> UVUVUVUVUV
>
> As you can see above, the offset of the gem buffer should be decided according to video signal mode, and 'base address + the offset' should be set to chroma_addr[1] register properly.
>
> And also there would be one thing more we have to consider,
> User space can make two separated gem buffers - one is for luminance pixel data and other is for chrominance pixel data - and send them to KMS driver, or he can make one contiguous gem buffer which contains two kinds of pixel data and send it to KMS driver.
>
> I guess now vp side of mixer driver didn't manage these buffers properly so page fault happened. So I think a good way for it would be to handle two kinds of buffers properly - one continuous buffer or two separated buffers - through exynos_drm_gem_fb_dma_addr function, and calculate the offset properly according to video signal mode - interfaced or progressive.
>
> Regarding this, we had posted one patch and it had been merged to mainline. This patch added two new pixel formats, DRM_FORMAT_NV12M and DRM_FORMAT_YUV420M to judge how KMS driver should handle these gem buffers.
> However, this patch had been reverted[1] by Ville due to breaking the ABI. So the only way to identify buffer type would be to check how many buffers are set to exynos_drm_fb object.
That's not related. In fact the second part (div by 2) is what actually removes
the pagefaults.
- Tobias
> [1] https://lists.freedesktop.org/archives/dri-devel/2012-April/021812.html
>
> Thanks,
> Inki Dae
>
>> }
>> } else {
>> luma_addr[1] = 0;
>> @@ -507,25 +507,26 @@ static void vp_video_buffer(struct mixer_context *ctx,
>> 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_DST_HEIGHT, state->crtc.h / 2);
>> - vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2);
>> + vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h / 2);
>> + vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y / 2);
>> } else {
>> - vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h);
>> - vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y);
>> + 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_WIDTH, state->crtc.w);
>> + vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x);
>> + vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h);
>> + vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y);
>> +
>> vp_reg_write(ctx, VP_H_RATIO, state->h_ratio);
>> vp_reg_write(ctx, VP_V_RATIO, state->v_ratio);
>>
>>
More information about the dri-devel
mailing list