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>
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 <jernej.skrabec@gmail.com>
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,