From 686d263856a9d5e1b3f66c7795308af9e8e20d96 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:33 +0100 Subject: drm/sun4i: Cleanup video/YUV source before enabling a layer This adds a dedicated function for cleaning the video and YUV source channel layer enable bits. This function is called first on layer atomic update to make sure that there are no leftover bits from previous plane configuration that were not cleaned until now. It fixes issues when alternating between video and YUV planes, where both bits would be set eventually, leading to broken plane display. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-2-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index bf49c55b0f2c..67b4bb4f5365 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -395,6 +395,15 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer, return 0; } +void sun4i_backend_cleanup_layer(struct sun4i_backend *backend, + int layer) +{ + regmap_update_bits(backend->engine.regs, + SUN4I_BACKEND_ATTCTL_REG0(layer), + SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN | + SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0); +} + static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) { u16 src_h = state->src_h >> 16; -- cgit v1.2.3-59-g8ed1b From ad25d0736db00afb2c7bf355bc50437434325387 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:35 +0100 Subject: drm/sun4i: Add TODO comment about supporting scaling with the backend The backend allows integer-only scaling but can handle alpha components, unlike the frontend. It could be useful to add support for this eventually, so add a short TODO comment describing the situation. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-4-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 67b4bb4f5365..c3444246755b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -426,6 +426,11 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) if (IS_ERR(backend->frontend)) return false; + /* + * TODO: The backend alone allows 2x and 4x integer scaling, including + * support for an alpha component (which the frontend doesn't support). + * Use the backend directly instead of the frontend in this case. + */ return sun4i_backend_plane_uses_scaler(state); } -- cgit v1.2.3-59-g8ed1b From 3d4265f89d064df2a6952e3f24a3da4fd687cc65 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:36 +0100 Subject: drm/sun4i: backend: Add a helper and a list for supported formats In order to check whether the backend supports a specific format, an explicit list and a related helper are introduced. The prototype of this helper is added to the header so that it can be called from sun4i_layer later (when introducing tiled mode support). Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-5-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun4i_backend.h | 1 + 2 files changed, 28 insertions(+) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index c3444246755b..7dd24eb03f89 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -155,6 +155,33 @@ static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) return 0; } +static const uint32_t sun4i_backend_formats[] = { + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGBA4444, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, +}; + +bool sun4i_backend_format_is_supported(uint32_t fmt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++) + if (sun4i_backend_formats[i] == fmt) + return true; + + return false; +} + int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, int layer, struct drm_plane *plane) { diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 339dbff1cce4..93db3af675b3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -198,6 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine) void sun4i_backend_layer_enable(struct sun4i_backend *backend, int layer, bool enable); +bool sun4i_backend_format_is_supported(uint32_t fmt); int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, int layer, struct drm_plane *plane); int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, -- cgit v1.2.3-59-g8ed1b From aaf3880b0823113af9ed742a687e7fb1b411a201 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:38 +0100 Subject: drm/sun4i: backend: Refine the logic behind using the frontend Checking that scaling is in use is not sufficient as a condition to decide to use the frontend. Since not all layer formats are supported by the frontend, we need to check for that support first. Then, the frontend must only be enabled if the backend doesn't support the format or that scaling is required. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-7-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 7dd24eb03f89..735fea7ead0b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -449,16 +449,32 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) { struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); struct sun4i_backend *backend = layer->backend; + uint32_t format = state->fb->format->format; if (IS_ERR(backend->frontend)) return false; + if (!sun4i_frontend_format_is_supported(format)) + return false; + + if (!sun4i_backend_format_is_supported(format)) + return true; + /* * TODO: The backend alone allows 2x and 4x integer scaling, including * support for an alpha component (which the frontend doesn't support). - * Use the backend directly instead of the frontend in this case. + * Use the backend directly instead of the frontend in this case, with + * another test to return false. + */ + + if (sun4i_backend_plane_uses_scaler(state)) + return true; + + /* + * Here the format is supported by both the frontend and the backend + * and no frontend scaling is required, so use the backend directly. */ - return sun4i_backend_plane_uses_scaler(state); + return false; } static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, -- cgit v1.2.3-59-g8ed1b From ab6985108a53d531f0abaf06529ba148403d187d Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:39 +0100 Subject: drm/sun4i: backend: Use a specific function to check if a plane is supported Before this patch, it is assumed that a plane is supported either through the frontend or through the backend alone. However, the DRM interface does not allow finely reporting our hardware capabilities and there are cases where neither are support. In particular, some plane formats are supported by the backend and not the frontend, so they can only be supported without scaling. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-8-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 735fea7ead0b..52caf561da0e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -477,6 +477,23 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) return false; } +static bool sun4i_backend_plane_is_supported(struct drm_plane_state *state, + bool *uses_frontend) +{ + if (sun4i_backend_plane_uses_frontend(state)) { + *uses_frontend = true; + return true; + } + + *uses_frontend = false; + + /* Scaling is not supported without the frontend. */ + if (sun4i_backend_plane_uses_scaler(state)) + return false; + + return true; +} + static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, struct drm_crtc_state *old_state) { @@ -517,14 +534,14 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, struct drm_framebuffer *fb = plane_state->fb; struct drm_format_name_buf format_name; - if (sun4i_backend_plane_uses_frontend(plane_state)) { + if (!sun4i_backend_plane_is_supported(plane_state, + &layer_state->uses_frontend)) + return -EINVAL; + + if (layer_state->uses_frontend) { DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", plane->index); - - layer_state->uses_frontend = true; num_frontend_planes++; - } else { - layer_state->uses_frontend = false; } DRM_DEBUG_DRIVER("Plane FB format is %s\n", -- cgit v1.2.3-59-g8ed1b From ae56bfbdad9b1996037a7209321cfb2ef49ea563 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:46 +0100 Subject: drm/sun4i: backend: Avoid counting YUV planes that use the frontend Our hardware has a limited number of YUV planes (usually 1) that can be supported using the backend only. However, YUV planes can also be supported by the frontend and must then not be counted when checking for that limitation. Only count the YUV plane when the frontend is not used. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-15-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 52caf561da0e..2a9569f16c81 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -542,6 +542,11 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", plane->index); num_frontend_planes++; + } else { + if (fb->format->is_yuv) { + DRM_DEBUG_DRIVER("Plane FB format is YUV\n"); + num_yuv_planes++; + } } DRM_DEBUG_DRIVER("Plane FB format is %s\n", @@ -550,11 +555,6 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE)) num_alpha_planes++; - if (fb->format->is_yuv) { - DRM_DEBUG_DRIVER("Plane FB format is YUV\n"); - num_yuv_planes++; - } - DRM_DEBUG_DRIVER("Plane zpos is %d\n", plane_state->normalized_zpos); -- cgit v1.2.3-59-g8ed1b From dc7d4b655a2c4a8db1342600319a7939eafeb9af Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:55 +0100 Subject: drm/sun4i: backend: Detail the YUV to RGB values coding explanation The values in the BT601 YUV to RGB colorspace translation are not simply coded as multiples, but rather as fixed-point signed fractional values on a given number of bits. Add an explanation about that. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-24-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 2a9569f16c81..f43c4b0f1e5d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -48,8 +48,12 @@ static const u32 sunxi_rgb2yuv_coef[12] = { /* * These coefficients are taken from the A33 BSP from Allwinner. * - * The formula is for each component, each coefficient being multiplied by - * 1024 and each constant being multiplied by 16: + * The first three values of each row are coded as 13-bit signed fixed-point + * numbers, with 10 bits for the fractional part. The fourth value is a + * constant coded as a 14-bit signed fixed-point number with 4 bits for the + * fractional part. + * + * The values in table order give the following colorspace translation: * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135 * R = 1.164 * Y + 1.596 * V - 222 * B = 1.164 * Y + 2.018 * U + 276 -- cgit v1.2.3-59-g8ed1b From 02a3ce3c2a67f3c3693029bc650f0c0571d9a3a2 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:25:04 +0100 Subject: drm/sun4i: Pass modifier to backend and frontend format support helpers To prepare the introduction of tiled mode support, pass the framebuffer format modifier to the helpers dealing with format support. Since only linear mode is supported for now, add corresponding checks in each helper. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-33-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 10 +++++++--- drivers/gpu/drm/sun4i/sun4i_backend.h | 2 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 5 ++++- drivers/gpu/drm/sun4i/sun4i_frontend.h | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/sun4i/sun4i_backend.c') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index f43c4b0f1e5d..9e9255ee59cd 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -175,10 +175,13 @@ static const uint32_t sun4i_backend_formats[] = { DRM_FORMAT_YVYU, }; -bool sun4i_backend_format_is_supported(uint32_t fmt) +bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier) { unsigned int i; + if (modifier != DRM_FORMAT_MOD_LINEAR) + return false; + for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++) if (sun4i_backend_formats[i] == fmt) return true; @@ -454,14 +457,15 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); struct sun4i_backend *backend = layer->backend; uint32_t format = state->fb->format->format; + uint64_t modifier = state->fb->modifier; if (IS_ERR(backend->frontend)) return false; - if (!sun4i_frontend_format_is_supported(format)) + if (!sun4i_frontend_format_is_supported(format, modifier)) return false; - if (!sun4i_backend_format_is_supported(format)) + if (!sun4i_backend_format_is_supported(format, modifier)) return true; /* diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 93db3af675b3..01f66463271b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -198,7 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine) void sun4i_backend_layer_enable(struct sun4i_backend *backend, int layer, bool enable); -bool sun4i_backend_format_is_supported(uint32_t fmt); +bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier); int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, int layer, struct drm_plane *plane); int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 5d765764bff9..1a7ebc45747e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -163,10 +163,13 @@ static const uint32_t sun4i_frontend_formats[] = { DRM_FORMAT_XRGB8888, }; -bool sun4i_frontend_format_is_supported(uint32_t fmt) +bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier) { unsigned int i; + if (modifier != DRM_FORMAT_MOD_LINEAR) + return false; + for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++) if (sun4i_frontend_formats[i] == fmt) return true; diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h index 800a193eebc2..ad146e8d8d70 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.h +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h @@ -97,6 +97,6 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, struct drm_plane *plane); int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, struct drm_plane *plane, uint32_t out_fmt); -bool sun4i_frontend_format_is_supported(uint32_t fmt); +bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier); #endif /* _SUN4I_FRONTEND_H_ */ -- cgit v1.2.3-59-g8ed1b