From fc526cbd31a8030cf641023cadd7c41e06875157 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 11 Jan 2012 18:27:14 +0200 Subject: [PATCH] gfx: drv: overlay: More thorough fix for SWIDTHSW issues MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The current code can still misprogram SWIDTHSW if fb->offsets[] is suitably misaligned. Simply limit SWIDTHSW to 2k pixels in such cases. Change the SWIDTHSW alignment code to be more readable, and align the width to 32 bytes (SWORD), instead of 64 bytes. Signed-off-by: Ville Syrjälä Signed-off-by: Kirill A. Shutemov --- drivers/staging/mrst/drv/mdfld_overlay.c | 39 +++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/staging/mrst/drv/mdfld_overlay.c b/drivers/staging/mrst/drv/mdfld_overlay.c index 3d77e40..81e6058 100644 --- a/drivers/staging/mrst/drv/mdfld_overlay.c +++ b/drivers/staging/mrst/drv/mdfld_overlay.c @@ -904,22 +904,39 @@ mfld_overlay_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct } /* - * uv.width *= uv.cpp is missing because NV12 chroma SWIDTHSW seems - * to be based on pixels instead of bytes. Not quite sure how the - * alignment should be handled, but this code at least appears to work. - * For all other formats uv.cpp is one or zero anyway. + * Hardware starts fetching from a 64 byte + * aligned address in 32 byte (SWORD) units. */ - y.width *= y.cpp; - y.width = (((y_off + y.width + 0x3f) >> 6) - (y_off >> 6)) << 3; - uv.width = (((u_off + uv.width + 0x3f) >> 6) - (u_off >> 6)) << 3; + y.width = ALIGN((y_off & 63) + y.width * y.cpp, 32); + uv.width = ALIGN((u_off & 63) + uv.width * uv.cpp, 32); + /* - * Apparently the register likes to be programmed - * with one SWORD less than we want to fetch. + * Hardware doesn't like SWIDTHSW getting too big. + * This can only happen if the source window is already + * close to the maximum width, and fb->offset[] is + * sufficiently misaligned. This limit may cause some + * pixels near the end of the source window to be repeated, + * but at least the hardware will not fail. */ - if (y.width) + y.width = min(y.width, 2048 * y.cpp); + uv.width = min(uv.width, 2048 * uv.cpp / c.hsub); + + if (y.width) { + y.width >>= 3; y.width -= 4; - if (uv.width) + } + if (uv.width) { + /* + * NV12 chroma SWIDTHSW must be halved. The two lsbs + * aren't used, so align to 64 to avoid an underflow. + */ + if (fb->pixel_format == DRM_FORMAT_NV12) + uv.width = ALIGN(uv.width, 64) >> 4; + else + uv.width >>= 3; uv.width -= 4; + } + regs->SWIDTHSW = (uv.width << 16) | (y.width & 0xffff); regs->OSTRIDE = (uv.stride << 16) | (y.stride & 0xffff); -- 2.7.4