From 590d15b643fff2052cbd411f8aa8b1f5e8ca9dc6 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 16 Oct 2023 21:08:41 +0200 Subject: [PATCH] Allwinner: linux: fix drm plane rendering for older SoCs --- ...w-hdmi-limit-mode-and-bus-format-to-.patch | 211 ------------------ ...drm-sun4i-de3-Implement-AFBC-support.patch | 35 +-- 2 files changed, 19 insertions(+), 227 deletions(-) delete mode 100644 projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch diff --git a/projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch b/projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch deleted file mode 100644 index 3a100d143f..0000000000 --- a/projects/Allwinner/patches/linux/0058-WIP-drm-bridge-dw-hdmi-limit-mode-and-bus-format-to-.patch +++ /dev/null @@ -1,211 +0,0 @@ -From e9a6924289b7ba7ca604272cbe52756f385d26df Mon Sep 17 00:00:00 2001 -From: Jonas Karlman -Date: Fri, 20 Dec 2019 08:12:43 +0000 -Subject: [PATCH 12/23] WIP: drm/bridge: dw-hdmi: limit mode and bus format to - max_tmds_clock - ---- - drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 113 ++++++++++++++-------- - 1 file changed, 73 insertions(+), 40 deletions(-) - -diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -index da2641a65e75..9c8c17827956 100644 ---- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c -@@ -1989,6 +1989,21 @@ static void hdmi_config_drm_infoframe(struct dw_hdmi *hdmi, - HDMI_FC_PACKET_TX_EN_DRM_MASK, HDMI_FC_PACKET_TX_EN); - } - -+static unsigned int -+hdmi_get_tmdsclock(unsigned int bus_format, unsigned int pixelclock) -+{ -+ int color_depth = hdmi_bus_fmt_color_depth(bus_format); -+ unsigned int tmdsclock = pixelclock; -+ -+ if (!hdmi_bus_fmt_is_yuv422(bus_format) && color_depth > 8) -+ tmdsclock = (u64)pixelclock * color_depth / 8; -+ -+ if (hdmi_bus_fmt_is_yuv420(bus_format)) -+ tmdsclock /= 2; -+ -+ return tmdsclock; -+} -+ - static void hdmi_av_composer(struct dw_hdmi *hdmi, - const struct drm_display_info *display, - const struct drm_display_mode *mode) -@@ -2000,29 +2015,11 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, - unsigned int vdisplay, hdisplay; - - vmode->mpixelclock = mode->clock * 1000; -+ vmode->mtmdsclock = -+ hdmi_get_tmdsclock(hdmi->hdmi_data.enc_out_bus_format, -+ vmode->mpixelclock); - - dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); -- -- vmode->mtmdsclock = vmode->mpixelclock; -- -- if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format)) { -- switch (hdmi_bus_fmt_color_depth( -- hdmi->hdmi_data.enc_out_bus_format)) { -- case 16: -- vmode->mtmdsclock = vmode->mpixelclock * 2; -- break; -- case 12: -- vmode->mtmdsclock = vmode->mpixelclock * 3 / 2; -- break; -- case 10: -- vmode->mtmdsclock = vmode->mpixelclock * 5 / 4; -- break; -- } -- } -- -- if (hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format)) -- vmode->mtmdsclock /= 2; -- - dev_dbg(hdmi->dev, "final tmdsclock = %d\n", vmode->mtmdsclock); - - /* Set up HDMI_FC_INVIDCONF */ -@@ -2646,8 +2643,21 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi) - * - MEDIA_BUS_FMT_RGB888_1X24, - */ - --/* Can return a maximum of 11 possible output formats for a mode/connector */ --#define MAX_OUTPUT_SEL_FORMATS 11 -+/* Can return a maximum of 15 possible output formats for a mode/connector */ -+#define MAX_OUTPUT_SEL_FORMATS 15 -+ -+static bool is_tmds_allowed(struct drm_display_info *info, -+ struct drm_display_mode *mode, -+ u32 bus_format) -+{ -+ unsigned long tmdsclock = hdmi_get_tmdsclock(bus_format, mode->clock); -+ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; -+ -+ if (max_tmds_clock >= tmdsclock) -+ return true; -+ -+ return false; -+} - - static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state, -@@ -2690,19 +2700,23 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - - /* Order bus formats from 16bit to 8bit if supported */ - if (max_bpc >= 16 && info->bpc == 16 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_48) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY16_0_5X48)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY16_0_5X48; - - if (max_bpc >= 12 && info->bpc >= 12 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_36) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY12_0_5X36)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36; - - if (max_bpc >= 10 && info->bpc >= 10 && -- (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30)) -+ (info->hdmi.y420_dc_modes & DRM_EDID_YCBCR420_DC_30) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY10_0_5X30)) - output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30; - - /* Default 8bit fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYYVYY8_0_5X24)) -+ output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24; - - if (drm_mode_is_420_only(info, mode)) { - *num_output_fmts = i; -@@ -2715,42 +2729,52 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, - * if supported. In any case the default RGB888 format is added - */ - -- /* Default 8bit RGB fallback */ -- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -- - if (max_bpc >= 16 && info->bpc == 16) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV16_1X48)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB161616_1X48)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48; - } - - if (max_bpc >= 12 && info->bpc >= 12) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY12_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV12_1X36)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB121212_1X36)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36; - } - - if (max_bpc >= 10 && info->bpc >= 10) { -- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY10_1X20)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV10_1X30)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30; - -- output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; -+ if (is_tmds_allowed(info, mode, MEDIA_BUS_FMT_RGB101010_1X30)) -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30; - } - -- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR422) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_UYVY8_1X16)) - output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16; - -- if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444) -+ if ((info->color_formats & DRM_COLOR_FORMAT_YCBCR444) && -+ is_tmds_allowed(info, mode, MEDIA_BUS_FMT_YUV8_1X24)) - output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24; - -+ /* Default 8bit RGB fallback */ -+ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24; -+ - *num_output_fmts = i; - - return output_fmts; -@@ -2930,11 +2954,20 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge, - struct dw_hdmi *hdmi = bridge->driver_private; - const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; - enum drm_mode_status mode_status = MODE_OK; -+ int max_tmds_clock = info->max_tmds_clock ? info->max_tmds_clock : 340000; -+ int clock = mode->clock; - - /* We don't support double-clocked modes */ - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - return MODE_BAD; - -+ if (pdata->ycbcr_420_allowed && drm_mode_is_420(info, mode) && -+ (info->color_formats & DRM_COLOR_FORMAT_YCBCR420)) -+ clock /= 2; -+ -+ if (clock > max_tmds_clock) -+ return MODE_CLOCK_HIGH; -+ - if (pdata->mode_valid) - mode_status = pdata->mode_valid(hdmi, pdata->priv_data, info, - mode); --- -2.42.0 - diff --git a/projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch b/projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch index d8cc547d85..fab63060da 100644 --- a/projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch +++ b/projects/Allwinner/patches/linux/0065-drm-sun4i-de3-Implement-AFBC-support.patch @@ -1,7 +1,7 @@ -From 75f9a78d91a37c0eadf952e97e93d3f51bfda1b6 Mon Sep 17 00:00:00 2001 +From 98b6e69f14c6c670a4156d92860500f5adfb530f Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sun, 8 Oct 2023 13:01:01 +0200 -Subject: [PATCH 19/23] drm/sun4i: de3: Implement AFBC support +Subject: [PATCH] drm/sun4i: de3: Implement AFBC support Buffers, compressed with AFBC, are generally more efficient for memory transfers. Add support for them. @@ -15,8 +15,8 @@ Signed-off-by: Jernej Skrabec drivers/gpu/drm/sun4i/Makefile | 2 +- drivers/gpu/drm/sun4i/sun50i_afbc.c | 240 +++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun50i_afbc.h | 87 +++++++++ - drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 81 +++++++-- - 4 files changed, 397 insertions(+), 13 deletions(-) + drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 84 +++++++-- + 4 files changed, 400 insertions(+), 13 deletions(-) create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.c create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.h @@ -373,7 +373,7 @@ index 000000000000..cea685c86855 + +#endif diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c -index 329e8bf8cd20..28a2c44843e6 100644 +index 329e8bf8cd20..bda91c3e2bb7 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -11,8 +11,10 @@ @@ -430,15 +430,16 @@ index 329e8bf8cd20..28a2c44843e6 100644 static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) { -@@ -399,6 +410,7 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, +@@ -399,6 +410,8 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, old_zpos); -+ sun50i_afbc_disable(mixer, layer->channel); ++ if (mixer->cfg->is_de3) ++ sun50i_afbc_disable(mixer, layer->channel); } static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, -@@ -411,26 +423,51 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, +@@ -411,26 +424,53 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); unsigned int zpos = new_state->normalized_zpos; unsigned int old_zpos = old_state->normalized_zpos; @@ -449,7 +450,8 @@ index 329e8bf8cd20..28a2c44843e6 100644 if (!new_state->visible) { sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, old_zpos); -+ sun50i_afbc_disable(mixer, layer->channel); ++ if (mixer->cfg->is_de3) ++ sun50i_afbc_disable(mixer, layer->channel); return; } @@ -465,7 +467,8 @@ index 329e8bf8cd20..28a2c44843e6 100644 + plane->state->color_encoding, + plane->state->color_range); + } else { -+ sun50i_afbc_disable(mixer, layer->channel); ++ if (mixer->cfg->is_de3) ++ sun50i_afbc_disable(mixer, layer->channel); + sun8i_vi_layer_update_alpha(mixer, layer->channel, + layer->overlay, plane); + sun8i_vi_layer_update_formats(mixer, layer->channel, @@ -497,7 +500,7 @@ index 329e8bf8cd20..28a2c44843e6 100644 static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { .atomic_check = sun8i_vi_layer_atomic_check, .atomic_disable = sun8i_vi_layer_atomic_disable, -@@ -444,6 +481,7 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = { +@@ -444,6 +484,7 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = { .disable_plane = drm_atomic_helper_disable_plane, .reset = drm_atomic_helper_plane_reset, .update_plane = drm_atomic_helper_update_plane, @@ -505,7 +508,7 @@ index 329e8bf8cd20..28a2c44843e6 100644 }; /* -@@ -527,6 +565,11 @@ static const u32 sun8i_vi_layer_de3_formats[] = { +@@ -527,6 +568,11 @@ static const u32 sun8i_vi_layer_de3_formats[] = { DRM_FORMAT_YVU411, DRM_FORMAT_YVU420, DRM_FORMAT_YVU422, @@ -517,7 +520,7 @@ index 329e8bf8cd20..28a2c44843e6 100644 }; static const uint64_t sun8i_layer_modifiers[] = { -@@ -534,6 +577,18 @@ static const uint64_t sun8i_layer_modifiers[] = { +@@ -534,6 +580,18 @@ static const uint64_t sun8i_layer_modifiers[] = { DRM_FORMAT_MOD_INVALID }; @@ -536,7 +539,7 @@ index 329e8bf8cd20..28a2c44843e6 100644 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, struct sun8i_mixer *mixer, int index) -@@ -542,6 +597,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, +@@ -542,6 +600,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, u32 supported_encodings, supported_ranges; unsigned int plane_cnt, format_count; struct sun8i_vi_layer *layer; @@ -544,7 +547,7 @@ index 329e8bf8cd20..28a2c44843e6 100644 const u32 *formats; int ret; -@@ -556,9 +612,11 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, +@@ -556,9 +615,11 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, if (mixer->cfg->is_de3) { formats = sun8i_vi_layer_de3_formats; format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats); @@ -556,7 +559,7 @@ index 329e8bf8cd20..28a2c44843e6 100644 } if (!mixer->cfg->ui_num && index == 0) -@@ -568,8 +626,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, +@@ -568,8 +629,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, ret = drm_universal_plane_init(drm, &layer->plane, 0, &sun8i_vi_layer_funcs, formats, format_count,