mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 15:02:32 +00:00
177 lines
6.0 KiB
Diff
177 lines
6.0 KiB
Diff
|
From 8bac9bb3f865b262e009faffb31d0d0b844faa5f Mon Sep 17 00:00:00 2001
|
||
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||
|
Date: Mon, 14 Nov 2022 19:32:10 +0000
|
||
|
Subject: [PATCH] drm/vc4: hdmi: Add property to allow manual config of
|
||
|
RGB or YCbCr
|
||
|
|
||
|
Add a custom property "Output format" that allows the overriding
|
||
|
of the default colourspace choice in the way that the old
|
||
|
firmware hdmi_pixel_encoding property did. If the chosen format is not
|
||
|
supported, then it will still drop back to the older behaviour.
|
||
|
|
||
|
This won't be acceptable to upstream, but it adds back the missing
|
||
|
functionality of hdmi_pixel_encoding.
|
||
|
|
||
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
||
|
---
|
||
|
drivers/gpu/drm/vc4/vc4_hdmi.c | 60 ++++++++++++++++++++++++++++++++++
|
||
|
drivers/gpu/drm/vc4/vc4_hdmi.h | 8 +++++
|
||
|
2 files changed, 68 insertions(+)
|
||
|
|
||
|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||
|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
||
|
@@ -556,6 +556,7 @@ static int vc4_hdmi_connector_atomic_che
|
||
|
|
||
|
if (old_state->colorspace != new_state->colorspace ||
|
||
|
old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb ||
|
||
|
+ old_vc4_state->requested_output_format != new_vc4_state->requested_output_format ||
|
||
|
!drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
|
||
|
struct drm_crtc_state *crtc_state;
|
||
|
|
||
|
@@ -590,6 +591,8 @@ int vc4_hdmi_connector_get_property(stru
|
||
|
|
||
|
if (property == vc4_hdmi->broadcast_rgb_property) {
|
||
|
*val = vc4_conn_state->broadcast_rgb;
|
||
|
+ } else if (property == vc4_hdmi->output_format_property) {
|
||
|
+ *val = vc4_conn_state->requested_output_format;
|
||
|
} else {
|
||
|
DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
|
||
|
property->base.id, property->name);
|
||
|
@@ -621,6 +624,9 @@ int vc4_hdmi_connector_set_property(stru
|
||
|
if (property == vc4_hdmi->broadcast_rgb_property) {
|
||
|
vc4_conn_state->broadcast_rgb = val;
|
||
|
return 0;
|
||
|
+ } else if (property == vc4_hdmi->output_format_property) {
|
||
|
+ vc4_conn_state->requested_output_format = val;
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
|
||
|
@@ -664,6 +670,7 @@ vc4_hdmi_connector_duplicate_state(struc
|
||
|
new_state->tmds_char_rate = vc4_state->tmds_char_rate;
|
||
|
new_state->output_bpc = vc4_state->output_bpc;
|
||
|
new_state->output_format = vc4_state->output_format;
|
||
|
+ new_state->requested_output_format = vc4_state->requested_output_format;
|
||
|
new_state->broadcast_rgb = vc4_state->broadcast_rgb;
|
||
|
__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
|
||
|
|
||
|
@@ -711,6 +718,33 @@ vc4_hdmi_attach_broadcast_rgb_property(s
|
||
|
drm_object_attach_property(&vc4_hdmi->connector.base, prop, 0);
|
||
|
}
|
||
|
|
||
|
+static const struct drm_prop_enum_list output_format_names[] = {
|
||
|
+ { VC4_HDMI_OUTPUT_AUTO, "Automatic" },
|
||
|
+ { VC4_HDMI_OUTPUT_RGB, "RGB" },
|
||
|
+ { VC4_HDMI_OUTPUT_YUV422, "YCbCr 4:2:2" },
|
||
|
+ { VC4_HDMI_OUTPUT_YUV444, "YCbCr 4:4:4" },
|
||
|
+};
|
||
|
+
|
||
|
+static void
|
||
|
+vc4_hdmi_attach_output_format_property(struct drm_device *dev,
|
||
|
+ struct vc4_hdmi *vc4_hdmi)
|
||
|
+{
|
||
|
+ struct drm_property *prop = vc4_hdmi->output_format_property;
|
||
|
+
|
||
|
+ if (!prop) {
|
||
|
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
|
||
|
+ "Output format",
|
||
|
+ output_format_names,
|
||
|
+ ARRAY_SIZE(output_format_names));
|
||
|
+ if (!prop)
|
||
|
+ return;
|
||
|
+
|
||
|
+ vc4_hdmi->output_format_property = prop;
|
||
|
+ }
|
||
|
+
|
||
|
+ drm_object_attach_property(&vc4_hdmi->connector.base, prop, 0);
|
||
|
+}
|
||
|
+
|
||
|
static int vc4_hdmi_connector_init(struct drm_device *dev,
|
||
|
struct vc4_hdmi *vc4_hdmi)
|
||
|
{
|
||
|
@@ -758,6 +792,7 @@ static int vc4_hdmi_connector_init(struc
|
||
|
drm_connector_attach_hdr_output_metadata_property(connector);
|
||
|
|
||
|
vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi);
|
||
|
+ vc4_hdmi_attach_output_format_property(dev, vc4_hdmi);
|
||
|
|
||
|
drm_connector_attach_encoder(connector, encoder);
|
||
|
|
||
|
@@ -1895,6 +1930,11 @@ static void vc4_hdmi_encoder_atomic_mode
|
||
|
vc4_hdmi->broadcast_rgb = vc4_state->broadcast_rgb;
|
||
|
vc4_hdmi->output_bpc = vc4_state->output_bpc;
|
||
|
vc4_hdmi->output_format = vc4_state->output_format;
|
||
|
+ vc4_hdmi->requested_output_format = vc4_state->requested_output_format;
|
||
|
+ vc4_hdmi->broadcast_rgb = vc4_state->broadcast_rgb;
|
||
|
+ memcpy(&vc4_hdmi->saved_adjusted_mode,
|
||
|
+ &crtc_state->adjusted_mode,
|
||
|
+ sizeof(vc4_hdmi->saved_adjusted_mode));
|
||
|
mutex_unlock(&vc4_hdmi->mutex);
|
||
|
}
|
||
|
|
||
|
@@ -2056,6 +2096,26 @@ vc4_hdmi_encoder_compute_format(const st
|
||
|
const struct drm_display_info *info = &connector->display_info;
|
||
|
unsigned int format;
|
||
|
|
||
|
+ if (vc4_state->requested_output_format != VC4_HDMI_OUTPUT_AUTO) {
|
||
|
+ drm_dbg(dev, "Trying with user requested output %u\n",
|
||
|
+ vc4_state->requested_output_format);
|
||
|
+
|
||
|
+ format = vc4_state->requested_output_format;
|
||
|
+ if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode,
|
||
|
+ format, bpc)) {
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
|
||
|
+ mode, bpc, format);
|
||
|
+ if (!ret) {
|
||
|
+ vc4_state->output_format = format;
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
drm_dbg(dev, "Trying with an RGB output\n");
|
||
|
|
||
|
format = VC4_HDMI_OUTPUT_RGB;
|
||
|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
|
||
|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
|
||
|
@@ -111,6 +111,7 @@ struct vc4_hdmi_audio {
|
||
|
};
|
||
|
|
||
|
enum vc4_hdmi_output_format {
|
||
|
+ VC4_HDMI_OUTPUT_AUTO,
|
||
|
VC4_HDMI_OUTPUT_RGB,
|
||
|
VC4_HDMI_OUTPUT_YUV422,
|
||
|
VC4_HDMI_OUTPUT_YUV444,
|
||
|
@@ -130,6 +131,7 @@ struct vc4_hdmi {
|
||
|
struct delayed_work scrambling_work;
|
||
|
|
||
|
struct drm_property *broadcast_rgb_property;
|
||
|
+ struct drm_property *output_format_property;
|
||
|
|
||
|
struct i2c_adapter *ddc;
|
||
|
void __iomem *hdmicore_regs;
|
||
|
@@ -223,6 +225,11 @@ struct vc4_hdmi {
|
||
|
* for use outside of KMS hooks. Protected by @mutex.
|
||
|
*/
|
||
|
enum vc4_hdmi_output_format output_format;
|
||
|
+ /**
|
||
|
+ * @requested_output_format: Copy of @vc4_connector_state.requested_output_format
|
||
|
+ * for use outside of KMS hooks. Protected by @mutex.
|
||
|
+ */
|
||
|
+ enum vc4_hdmi_output_format requested_output_format;
|
||
|
|
||
|
/**
|
||
|
* @broadcast_rgb: Copy of @vc4_connector_state.broadcast_rgb
|
||
|
@@ -249,6 +256,7 @@ struct vc4_hdmi_connector_state {
|
||
|
unsigned long long tmds_char_rate;
|
||
|
unsigned int output_bpc;
|
||
|
enum vc4_hdmi_output_format output_format;
|
||
|
+ enum vc4_hdmi_output_format requested_output_format;
|
||
|
int broadcast_rgb;
|
||
|
};
|
||
|
|