[PATCH 6/7] drm/omap: fix YUV422 rotation with TILER
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Wed May 24 06:44:39 UTC 2017
Hi Tomi,
Thank you for the patch.
On Wednesday 17 May 2017 10:56:43 Tomi Valkeinen wrote:
> TILER rotation with YUV422 pixelformats does not work at the moment. All
> other pixel formats work, because the pixelformat's pixel size is equal
> to tiler unit size (e.g. XR24's pixel size is 32 bits, and the TILER
> unit size that has to be used is 32 bits).
>
> For YUV422 formats this is not the case, as the TILER unit size has to
> be 32 bits, but the pixel size is 16 bits. The end result is OCP errors
> and sync losts.
>
> This patch adds the code to adjust the variables for YUV422 formats.
>
> We could make the code more generic by passing around the pixel format,
> rotation type, angle and the tiler unit size, which would allow us to do
> calculations without special case for YUV422. However, this would make
> the code more complex, and at least for now this is much more easier to
> handle with these two special cases for YUV422.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ti.com>
> ---
> drivers/gpu/drm/omapdrm/dss/dispc.c | 20 ++++++++++++++++++--
> drivers/gpu/drm/omapdrm/omap_fb.c | 14 ++++++++++++++
> 2 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c
> b/drivers/gpu/drm/omapdrm/dss/dispc.c index a25db6e25165..80c75e5913cb
> 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dispc.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
> @@ -1917,7 +1917,8 @@ static s32 pixinc(int pixels, u8 ps)
> static void calc_offset(u16 screen_width, u16 width,
> u32 fourcc, bool fieldmode,
> unsigned int field_offset, unsigned *offset0, unsigned
*offset1,
> - s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
> + s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim,
> + enum omap_dss_rotation_type rotation_type, u8 rotation)
> {
> u8 ps;
>
> @@ -1925,6 +1926,20 @@ static void calc_offset(u16 screen_width, u16 width,
>
> DSSDBG("scrw %d, width %d\n", screen_width, width);
>
> + if (rotation_type == OMAP_DSS_ROT_TILER &&
> + (fourcc == DRM_FORMAT_UYVY || fourcc == DRM_FORMAT_YUYV) &&
> + drm_rotation_90_or_270(rotation)) {
> + /*
> + * HACK: ROW_INC needs to be calculated with TILER units.
> + * We get such 'screen_width' that multiplying it with the
> + * YUV422 pixel size gives the correct TILER container width.
> + * However, 'width' is in pixels and multiplying it with
YUV422
> + * pixel size gives incorrect result. We thus multiply it here
> + * with 2 to match the 32 bit TILER unit size.
> + */
> + width *= 2;
> + }
> +
> /*
> * field 0 = even field = bottom field
> * field 1 = odd field = top field
> @@ -2473,7 +2488,8 @@ static int dispc_ovl_setup_common(enum omap_plane_id
> plane, calc_offset(screen_width, frame_width,
> fourcc, fieldmode, field_offset,
> &offset0, &offset1, &row_inc, &pix_inc,
> - x_predecim, y_predecim);
> + x_predecim, y_predecim,
> + rotation_type, rotation);
>
> DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
> offset0, offset1, row_inc, pix_inc);
> diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c
> b/drivers/gpu/drm/omapdrm/omap_fb.c index bd05976fc20b..e5cc13799e73 100644
> --- a/drivers/gpu/drm/omapdrm/omap_fb.c
> +++ b/drivers/gpu/drm/omapdrm/omap_fb.c
> @@ -184,16 +184,30 @@ void omap_framebuffer_update_scanout(struct
> drm_framebuffer *fb,
>
> orient = drm_rotation_to_tiler(state->rotation);
>
> + /*
> + * omap_gem_rotated_paddr() wants the x & y in tiler units.
> + * Usually tiler unit size is the same as the pixel size,
except
> + * for YUV422 formats, for which the tiler unit size is 32
bits
> + * and pixel size is 16 bits.
> + */
> + if (fb->format->format == DRM_FORMAT_UYVY ||
> + fb->format->format == DRM_FORMAT_YUYV) {
That's a very peculiar indentation.
> + x /= 2;
> + w /= 2;
> + }
> +
> /* adjust x,y offset for flip/invert: */
> if (orient & MASK_Y_INVERT)
> y += h - 1;
> if (orient & MASK_X_INVERT)
> x += w - 1;
>
> + /* Note: x and y are in TILER units, not pixels */
> omap_gem_rotated_dma_addr(plane->bo, orient, x, y,
> &info->paddr);
> info->rotation_type = OMAP_DSS_ROT_TILER;
> info->rotation = state->rotation ?: DRM_ROTATE_0;
> + /* Note: stride in TILER units, not pixels */
Nitpicking, I would have combined the two comments.
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> info->screen_width = omap_gem_tiled_stride(plane->bo,
orient);
> } else {
> switch (state->rotation & DRM_ROTATE_MASK) {
--
Regards,
Laurent Pinchart
More information about the dri-devel
mailing list