From: Thierry Reding Date: Wed, 29 Jan 2014 19:31:17 +0000 (+0100) Subject: drm/tegra: dc - Add YUYV support X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f925390efccb24016a4fafe77721770021ed754a;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git drm/tegra: dc - Add YUYV support YUYV is UYVY with swapped bytes. Luckily the Tegra DC hardware can swap bytes during scan-out, so supporting YUYV is simply a matter of writing the correct value to the byteswap register. This patch modifies tegra_dc_format() to return the byte swap parameter via an output parameter in addition to returning the pixel format. Many other formats can potentially be supported in a similar way. Signed-off-by: Thierry Reding --- diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index edb871d7d395..f9cd2474403b 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -49,7 +49,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, window.dst.y = crtc_y; window.dst.w = crtc_w; window.dst.h = crtc_h; - window.format = tegra_dc_format(fb->pixel_format); + window.format = tegra_dc_format(fb->pixel_format, &window.swap); window.bits_per_pixel = fb->bits_per_pixel; window.bottom_up = tegra_fb_is_bottom_up(fb); window.tiled = tegra_fb_is_tiled(fb); @@ -117,6 +117,7 @@ static const uint32_t plane_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_UYVY, + DRM_FORMAT_YUYV, DRM_FORMAT_YUV420, DRM_FORMAT_YUV422, }; @@ -150,9 +151,9 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc) static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, struct drm_framebuffer *fb) { - unsigned int format = tegra_dc_format(fb->pixel_format); struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); unsigned int h_offset = 0, v_offset = 0; + unsigned int format, swap; unsigned long value; tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); @@ -162,7 +163,10 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR); tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); + + format = tegra_dc_format(fb->pixel_format, &swap); tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); + tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP); if (tegra_fb_is_tiled(fb)) { value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | @@ -490,7 +494,7 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH); - tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP); + tegra_dc_writel(dc, window->swap, DC_WIN_BYTE_SWAP); value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x); tegra_dc_writel(dc, value, DC_WIN_POSITION); @@ -611,8 +615,12 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, return 0; } -unsigned int tegra_dc_format(uint32_t format) +unsigned int tegra_dc_format(uint32_t format, uint32_t *swap) { + /* assume no swapping of fetched data */ + if (swap) + *swap = BYTE_SWAP_NOSWAP; + switch (format) { case DRM_FORMAT_XBGR8888: return WIN_COLOR_DEPTH_R8G8B8A8; @@ -626,6 +634,12 @@ unsigned int tegra_dc_format(uint32_t format) case DRM_FORMAT_UYVY: return WIN_COLOR_DEPTH_YCbCr422; + case DRM_FORMAT_YUYV: + if (swap) + *swap = BYTE_SWAP_SWAP2; + + return WIN_COLOR_DEPTH_YCbCr422; + case DRM_FORMAT_YUV420: return WIN_COLOR_DEPTH_YCbCr420P; @@ -682,7 +696,8 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, window.dst.y = 0; window.dst.w = mode->hdisplay; window.dst.h = mode->vdisplay; - window.format = tegra_dc_format(crtc->primary->fb->pixel_format); + window.format = tegra_dc_format(crtc->primary->fb->pixel_format, + &window.swap); window.bits_per_pixel = crtc->primary->fb->bits_per_pixel; window.stride[0] = crtc->primary->fb->pitches[0]; window.base[0] = bo->paddr; diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 597aa829af1f..302bfee83f0a 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -156,6 +156,7 @@ struct tegra_dc_window { } dst; unsigned int bits_per_pixel; unsigned int format; + unsigned int swap; unsigned int stride[2]; unsigned long base[3]; bool bottom_up; @@ -163,7 +164,7 @@ struct tegra_dc_window { }; /* from dc.c */ -unsigned int tegra_dc_format(uint32_t format); +unsigned int tegra_dc_format(uint32_t format, unsigned int *swap); int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, const struct tegra_dc_window *window); void tegra_dc_enable_vblank(struct tegra_dc *dc);