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 <treding@nvidia.com>
This commit is contained in:
parent
688c59afbf
commit
f925390efc
|
@ -49,7 +49,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||||
window.dst.y = crtc_y;
|
window.dst.y = crtc_y;
|
||||||
window.dst.w = crtc_w;
|
window.dst.w = crtc_w;
|
||||||
window.dst.h = crtc_h;
|
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.bits_per_pixel = fb->bits_per_pixel;
|
||||||
window.bottom_up = tegra_fb_is_bottom_up(fb);
|
window.bottom_up = tegra_fb_is_bottom_up(fb);
|
||||||
window.tiled = tegra_fb_is_tiled(fb);
|
window.tiled = tegra_fb_is_tiled(fb);
|
||||||
|
@ -117,6 +117,7 @@ static const uint32_t plane_formats[] = {
|
||||||
DRM_FORMAT_XRGB8888,
|
DRM_FORMAT_XRGB8888,
|
||||||
DRM_FORMAT_RGB565,
|
DRM_FORMAT_RGB565,
|
||||||
DRM_FORMAT_UYVY,
|
DRM_FORMAT_UYVY,
|
||||||
|
DRM_FORMAT_YUYV,
|
||||||
DRM_FORMAT_YUV420,
|
DRM_FORMAT_YUV420,
|
||||||
DRM_FORMAT_YUV422,
|
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,
|
static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
|
||||||
struct drm_framebuffer *fb)
|
struct drm_framebuffer *fb)
|
||||||
{
|
{
|
||||||
unsigned int format = tegra_dc_format(fb->pixel_format);
|
|
||||||
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
|
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
|
||||||
unsigned int h_offset = 0, v_offset = 0;
|
unsigned int h_offset = 0, v_offset = 0;
|
||||||
|
unsigned int format, swap;
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
|
|
||||||
tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
|
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, bo->paddr + value, DC_WINBUF_START_ADDR);
|
||||||
tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
|
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, format, DC_WIN_COLOR_DEPTH);
|
||||||
|
tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
|
||||||
|
|
||||||
if (tegra_fb_is_tiled(fb)) {
|
if (tegra_fb_is_tiled(fb)) {
|
||||||
value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
|
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, value, DC_CMD_DISPLAY_WINDOW_HEADER);
|
||||||
|
|
||||||
tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH);
|
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);
|
value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
|
||||||
tegra_dc_writel(dc, value, DC_WIN_POSITION);
|
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;
|
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) {
|
switch (format) {
|
||||||
case DRM_FORMAT_XBGR8888:
|
case DRM_FORMAT_XBGR8888:
|
||||||
return WIN_COLOR_DEPTH_R8G8B8A8;
|
return WIN_COLOR_DEPTH_R8G8B8A8;
|
||||||
|
@ -626,6 +634,12 @@ unsigned int tegra_dc_format(uint32_t format)
|
||||||
case DRM_FORMAT_UYVY:
|
case DRM_FORMAT_UYVY:
|
||||||
return WIN_COLOR_DEPTH_YCbCr422;
|
return WIN_COLOR_DEPTH_YCbCr422;
|
||||||
|
|
||||||
|
case DRM_FORMAT_YUYV:
|
||||||
|
if (swap)
|
||||||
|
*swap = BYTE_SWAP_SWAP2;
|
||||||
|
|
||||||
|
return WIN_COLOR_DEPTH_YCbCr422;
|
||||||
|
|
||||||
case DRM_FORMAT_YUV420:
|
case DRM_FORMAT_YUV420:
|
||||||
return WIN_COLOR_DEPTH_YCbCr420P;
|
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.y = 0;
|
||||||
window.dst.w = mode->hdisplay;
|
window.dst.w = mode->hdisplay;
|
||||||
window.dst.h = mode->vdisplay;
|
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.bits_per_pixel = crtc->primary->fb->bits_per_pixel;
|
||||||
window.stride[0] = crtc->primary->fb->pitches[0];
|
window.stride[0] = crtc->primary->fb->pitches[0];
|
||||||
window.base[0] = bo->paddr;
|
window.base[0] = bo->paddr;
|
||||||
|
|
|
@ -156,6 +156,7 @@ struct tegra_dc_window {
|
||||||
} dst;
|
} dst;
|
||||||
unsigned int bits_per_pixel;
|
unsigned int bits_per_pixel;
|
||||||
unsigned int format;
|
unsigned int format;
|
||||||
|
unsigned int swap;
|
||||||
unsigned int stride[2];
|
unsigned int stride[2];
|
||||||
unsigned long base[3];
|
unsigned long base[3];
|
||||||
bool bottom_up;
|
bool bottom_up;
|
||||||
|
@ -163,7 +164,7 @@ struct tegra_dc_window {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* from dc.c */
|
/* 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,
|
int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
|
||||||
const struct tegra_dc_window *window);
|
const struct tegra_dc_window *window);
|
||||||
void tegra_dc_enable_vblank(struct tegra_dc *dc);
|
void tegra_dc_enable_vblank(struct tegra_dc *dc);
|
||||||
|
|
Loading…
Reference in New Issue