diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 7d5a483a54de..d5720fab510c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -109,6 +109,7 @@ struct fimd_driver_data { unsigned int has_dp_clk:1; unsigned int has_hw_trigger:1; unsigned int has_trigger_per_te:1; + unsigned int has_bgr_support:1; }; static struct fimd_driver_data s3c64xx_fimd_driver_data = { @@ -138,6 +139,7 @@ static struct fimd_driver_data exynos4_fimd_driver_data = { .lcdblk_bypass_shift = 1, .has_shadowcon = 1, .has_vtsel = 1, + .has_bgr_support = 1, }; static struct fimd_driver_data exynos5_fimd_driver_data = { @@ -149,6 +151,7 @@ static struct fimd_driver_data exynos5_fimd_driver_data = { .has_vidoutcon = 1, .has_vtsel = 1, .has_dp_clk = 1, + .has_bgr_support = 1, }; static struct fimd_driver_data exynos5420_fimd_driver_data = { @@ -162,6 +165,7 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = { .has_vtsel = 1, .has_mic_bypass = 1, .has_dp_clk = 1, + .has_bgr_support = 1, }; struct fimd_context { @@ -226,6 +230,18 @@ static const uint32_t fimd_formats[] = { DRM_FORMAT_ARGB8888, }; +static const uint32_t fimd_extended_formats[] = { + DRM_FORMAT_C8, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_RGB565, + DRM_FORMAT_BGR565, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, +}; + static const unsigned int capabilities[WINDOWS_NR] = { 0, EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, @@ -673,21 +689,25 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, val |= WINCONx_BYTSWP; break; case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: val |= WINCON0_BPPMODE_16BPP_1555; val |= WINCONx_HAWSWP; val |= WINCONx_BURSTLEN_16WORD; break; case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: val |= WINCON0_BPPMODE_16BPP_565; val |= WINCONx_HAWSWP; val |= WINCONx_BURSTLEN_16WORD; break; case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: val |= WINCON0_BPPMODE_24BPP_888; val |= WINCONx_WSWP; val |= WINCONx_BURSTLEN_16WORD; break; case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: default: val |= WINCON1_BPPMODE_25BPP_A1888; val |= WINCONx_WSWP; @@ -695,6 +715,18 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, break; } + switch (pixel_format) { + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_BGR565: + writel(WIN_RGB_ORDER_REVERSE, ctx->regs + WIN_RGB_ORDER(win)); + break; + default: + writel(WIN_RGB_ORDER_FORWARD, ctx->regs + WIN_RGB_ORDER(win)); + break; + } + /* * Setting dma-burst to 16Word causes permanent tearing for very small * buffers, e.g. cursor buffer. Burst Mode switching which based on @@ -1074,8 +1106,14 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) ctx->drm_dev = drm_dev; for (i = 0; i < WINDOWS_NR; i++) { - ctx->configs[i].pixel_formats = fimd_formats; - ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats); + if (ctx->driver_data->has_bgr_support) { + ctx->configs[i].pixel_formats = fimd_extended_formats; + ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_extended_formats); + } else { + ctx->configs[i].pixel_formats = fimd_formats; + ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats); + } + ctx->configs[i].zpos = i; ctx->configs[i].type = fimd_win_types[i]; ctx->configs[i].capabilities = capabilities[i]; diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h index c4a93ce1de48..e6966d187591 100644 --- a/include/video/samsung_fimd.h +++ b/include/video/samsung_fimd.h @@ -476,6 +476,10 @@ * 1111 -none- -none- -none- -none- -none- */ +#define WIN_RGB_ORDER(_win) (0x2020 + ((_win) * 4)) +#define WIN_RGB_ORDER_FORWARD (0 << 11) +#define WIN_RGB_ORDER_REVERSE (1 << 11) + /* FIMD Version 8 register offset definitions */ #define FIMD_V8_VIDTCON0 0x20010 #define FIMD_V8_VIDTCON1 0x20014