Merge pull request #8221 from jernejsk/fix-de2

[LE12] Allwinner: linux: fix drm plane rendering for older SoCs
This commit is contained in:
CvH 2023-10-16 21:18:09 +02:00 committed by GitHub
commit b512ce4b0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 227 deletions

View File

@ -1,211 +0,0 @@
From e9a6924289b7ba7ca604272cbe52756f385d26df Mon Sep 17 00:00:00 2001
From: Jonas Karlman <jonas@kwiboo.se>
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

View File

@ -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 <jernej.skrabec@gmail.com> From: Jernej Skrabec <jernej.skrabec@gmail.com>
Date: Sun, 8 Oct 2023 13:01:01 +0200 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 Buffers, compressed with AFBC, are generally more efficient for memory
transfers. Add support for them. transfers. Add support for them.
@ -15,8 +15,8 @@ Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
drivers/gpu/drm/sun4i/Makefile | 2 +- drivers/gpu/drm/sun4i/Makefile | 2 +-
drivers/gpu/drm/sun4i/sun50i_afbc.c | 240 +++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun50i_afbc.c | 240 +++++++++++++++++++++++++
drivers/gpu/drm/sun4i/sun50i_afbc.h | 87 +++++++++ drivers/gpu/drm/sun4i/sun50i_afbc.h | 87 +++++++++
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 81 +++++++-- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 84 +++++++--
4 files changed, 397 insertions(+), 13 deletions(-) 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.c
create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.h create mode 100644 drivers/gpu/drm/sun4i/sun50i_afbc.h
@ -373,7 +373,7 @@ index 000000000000..cea685c86855
+ +
+#endif +#endif
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c 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 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -11,8 +11,10 @@ @@ -11,8 +11,10 @@
@ -430,15 +430,16 @@ index 329e8bf8cd20..28a2c44843e6 100644
static int sun8i_vi_layer_atomic_check(struct drm_plane *plane, static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state) 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, sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
old_zpos); 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, 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); struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
unsigned int zpos = new_state->normalized_zpos; unsigned int zpos = new_state->normalized_zpos;
unsigned int old_zpos = old_state->normalized_zpos; unsigned int old_zpos = old_state->normalized_zpos;
@ -449,7 +450,8 @@ index 329e8bf8cd20..28a2c44843e6 100644
if (!new_state->visible) { if (!new_state->visible) {
sun8i_vi_layer_enable(mixer, layer->channel, sun8i_vi_layer_enable(mixer, layer->channel,
layer->overlay, false, 0, old_zpos); layer->overlay, false, 0, old_zpos);
+ sun50i_afbc_disable(mixer, layer->channel); + if (mixer->cfg->is_de3)
+ sun50i_afbc_disable(mixer, layer->channel);
return; return;
} }
@ -465,7 +467,8 @@ index 329e8bf8cd20..28a2c44843e6 100644
+ plane->state->color_encoding, + plane->state->color_encoding,
+ plane->state->color_range); + plane->state->color_range);
+ } else { + } 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, + sun8i_vi_layer_update_alpha(mixer, layer->channel,
+ layer->overlay, plane); + layer->overlay, plane);
+ sun8i_vi_layer_update_formats(mixer, layer->channel, + 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 = { static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
.atomic_check = sun8i_vi_layer_atomic_check, .atomic_check = sun8i_vi_layer_atomic_check,
.atomic_disable = sun8i_vi_layer_atomic_disable, .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, .disable_plane = drm_atomic_helper_disable_plane,
.reset = drm_atomic_helper_plane_reset, .reset = drm_atomic_helper_plane_reset,
.update_plane = drm_atomic_helper_update_plane, .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_YVU411,
DRM_FORMAT_YVU420, DRM_FORMAT_YVU420,
DRM_FORMAT_YVU422, DRM_FORMAT_YVU422,
@ -517,7 +520,7 @@ index 329e8bf8cd20..28a2c44843e6 100644
}; };
static const uint64_t sun8i_layer_modifiers[] = { 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 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_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
struct sun8i_mixer *mixer, struct sun8i_mixer *mixer,
int index) 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; u32 supported_encodings, supported_ranges;
unsigned int plane_cnt, format_count; unsigned int plane_cnt, format_count;
struct sun8i_vi_layer *layer; struct sun8i_vi_layer *layer;
@ -544,7 +547,7 @@ index 329e8bf8cd20..28a2c44843e6 100644
const u32 *formats; const u32 *formats;
int ret; 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) { if (mixer->cfg->is_de3) {
formats = sun8i_vi_layer_de3_formats; formats = sun8i_vi_layer_de3_formats;
format_count = ARRAY_SIZE(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) 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, ret = drm_universal_plane_init(drm, &layer->plane, 0,
&sun8i_vi_layer_funcs, &sun8i_vi_layer_funcs,
formats, format_count, formats, format_count,