diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index d53435b68ae6..cf131c2aa23e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -91,6 +91,7 @@ struct exynos_drm_plane { #define EXYNOS_DRM_PLANE_CAP_DOUBLE (1 << 0) #define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1) #define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2) +#define EXYNOS_DRM_PLANE_CAP_TILE (1 << 3) /* * Exynos DRM plane configuration structure. diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 6592f50d460a..8208df56a88f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -225,4 +225,6 @@ void exynos_drm_mode_config_init(struct drm_device *dev) dev->mode_config.funcs = &exynos_drm_mode_config_funcs; dev->mode_config.helper_private = &exynos_drm_mode_config_helpers; + + dev->mode_config.allow_fb_modifiers = true; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index 8de74009dee4..d2a90dae5c71 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -178,6 +178,29 @@ static struct drm_plane_funcs exynos_plane_funcs = { .atomic_destroy_state = exynos_drm_plane_destroy_state, }; +static int +exynos_drm_plane_check_format(const struct exynos_drm_plane_config *config, + struct exynos_drm_plane_state *state) +{ + struct drm_framebuffer *fb = state->base.fb; + + switch (fb->modifier) { + case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: + if (!(config->capabilities & EXYNOS_DRM_PLANE_CAP_TILE)) + return -ENOTSUPP; + break; + + case DRM_FORMAT_MOD_LINEAR: + break; + + default: + DRM_ERROR("unsupported pixel format modifier"); + return -ENOTSUPP; + } + + return 0; +} + static int exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config, struct exynos_drm_plane_state *state) @@ -222,6 +245,10 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, /* translate state into exynos_state */ exynos_plane_mode_set(exynos_state); + ret = exynos_drm_plane_check_format(exynos_plane->config, exynos_state); + if (ret) + return ret; + ret = exynos_drm_plane_check_size(exynos_plane->config, exynos_state); return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index cbd949a989f9..f9a06b8007c5 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -148,7 +148,8 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = { .pixel_formats = vp_formats, .num_pixel_formats = ARRAY_SIZE(vp_formats), .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE | - EXYNOS_DRM_PLANE_CAP_ZPOS, + EXYNOS_DRM_PLANE_CAP_ZPOS | + EXYNOS_DRM_PLANE_CAP_TILE, }, }; @@ -500,6 +501,9 @@ static void vp_video_buffer(struct mixer_context *ctx, return; } + if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE) + tiled_mode = true; + luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0); chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1);