mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-24 11:16:51 +00:00
Allwinner: linux: fix drm plane rendering for older SoCs
This commit is contained in:
parent
b2d1c9fd43
commit
590d15b643
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user