2021-06-30 15:11:53

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 00/17] New uAPI drm properties for color management

Implementation of https://lkml.org/lkml/2021/5/12/764 now feature complete
albeit not fully tested.

I have now corrected the DSC behavior, but still no wait to test it.

Exact dithering behavior remains a mistery so in case dithering is active it's
not 100% clear what "active bpc" means, or where the "max bpc" limit is applied.

I have no DP MST splitter at hand. I tried my best to not break anything,
but if one who has one could test it would be very helpful.

Things on my TODO list:
- add "min bpc" property
- rewrite "preferred color format" to "force color format"
- make "Broadcast RGB" only affect RGB on AMD too
- remove unreachable enums of "active/preferred/force color format"



2021-06-30 15:11:54

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 04/17] drm/amd/display: Add handling for new "active bpc" property

This commit implements the "active bpc" drm property for the AMD GPU
driver.

Signed-off-by: Werner Sembach <[email protected]>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 ++++++++++++++++++-
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ++++
2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f4abb5f215d1..d984de82ae63 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -7708,8 +7708,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
adev->mode_info.underscan_vborder_property,
0);

- if (!aconnector->mst_port)
+ if (!aconnector->mst_port) {
drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
+ drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);
+ }

/* This defaults to the max in the range, but we want 8bpc for non-edp. */
aconnector->base.state->max_bpc = (connector_type == DRM_MODE_CONNECTOR_eDP) ? 16 : 8;
@@ -9078,6 +9080,26 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
mutex_unlock(&dm->dc_lock);
}

+ /* Extract information from crtc to communicate it to userspace as connector properties */
+ for_each_new_connector_in_state(state, connector, new_con_state, i) {
+ struct drm_crtc *crtc = new_con_state->crtc;
+ struct dc_stream_state *stream;
+
+ if (crtc) {
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+ stream = dm_new_crtc_state->stream;
+
+ if (stream)
+ drm_connector_set_active_bpc_property(connector,
+ stream->timing.flags.DSC ?
+ stream->timing.dsc_cfg.bits_per_pixel / 16 / 3 :
+ convert_dc_color_depth_into_bpc(
+ stream->timing.display_color_depth));
+ } else
+ drm_connector_set_active_bpc_property(connector, 0);
+ }
+
/* Count number of newly disabled CRTCs for dropping PM refs later. */
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 5568d4e518e6..0cf38743ec47 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -409,6 +409,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
if (connector->max_bpc_property)
drm_connector_attach_max_bpc_property(connector, 8, 16);

+ connector->active_bpc_property = master->base.active_bpc_property;
+ if (connector->active_bpc_property)
+ drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);
+
connector->vrr_capable_property = master->base.vrr_capable_property;
if (connector->vrr_capable_property)
drm_connector_attach_vrr_capable_property(connector);
--
2.25.1

2021-06-30 15:11:58

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 01/17] drm/amd/display: Remove unnecessary SIGNAL_TYPE_HDMI_TYPE_A check

Remove unnecessary SIGNAL_TYPE_HDMI_TYPE_A check that was performed in the
drm_mode_is_420_only() case, but not in the drm_mode_is_420_also() &&
force_yuv420_output case.

Without further knowledge if YCbCr 4:2:0 is supported outside of HDMI,
there is no reason to use RGB when the display
reports drm_mode_is_420_only() even on a non HDMI connection.

This patch also moves both checks in the same if-case. This eliminates an
extra else-if-case.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 10f878910e55..e081dd3ffb5f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5348,10 +5348,7 @@ static void fill_stream_properties_from_drm_display_mode(
timing_out->v_border_bottom = 0;
/* TODO: un-hardcode */
if (drm_mode_is_420_only(info, mode_in)
- && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
- timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- else if (drm_mode_is_420_also(info, mode_in)
- && aconnector->force_yuv420_output)
+ || (drm_mode_is_420_also(info, mode_in) && aconnector->force_yuv420_output))
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
--
2.25.1

2021-06-30 15:12:03

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 08/17] drm/i915/display: Add handling for new "active color format" property

This commit implements the "active color format" drm property for the Intel
GPU driver.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/i915/display/intel_display.c | 22 +++++++++++++++++++-
drivers/gpu/drm/i915/display/intel_dp.c | 2 ++
drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++++
drivers/gpu/drm/i915/display/intel_hdmi.c | 1 +
4 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 1b63d1404d06..be38f7148285 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -10609,6 +10609,21 @@ static void intel_atomic_prepare_plane_clear_colors(struct intel_atomic_state *s
}
}

+static int convert_intel_output_format_into_drm_color_format(enum intel_output_format output_format)
+{
+ switch (output_format) {
+ case INTEL_OUTPUT_FORMAT_RGB:
+ return DRM_COLOR_FORMAT_RGB444;
+ case INTEL_OUTPUT_FORMAT_YCBCR420:
+ return DRM_COLOR_FORMAT_YCRCB420;
+ case INTEL_OUTPUT_FORMAT_YCBCR444:
+ return DRM_COLOR_FORMAT_YCRCB444;
+ default:
+ break;
+ }
+ return 0;
+}
+
static void intel_atomic_commit_tail(struct intel_atomic_state *state)
{
struct drm_device *dev = state->base.dev;
@@ -10922,8 +10937,13 @@ static int intel_atomic_commit(struct drm_device *dev,
new_crtc_state->dsc.compression_enable ?
new_crtc_state->dsc.compressed_bpp / 3 :
new_crtc_state->pipe_bpp / 3);
- } else
+ drm_connector_set_active_color_format_property(connector,
+ convert_intel_output_format_into_drm_color_format(
+ new_crtc_state->output_format));
+ } else {
drm_connector_set_active_bpc_property(connector, 0);
+ drm_connector_set_active_color_format_property(connector, 0);
+ }
}

drm_atomic_state_get(&state->base);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 815bc313b954..6b85bcdeb238 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4691,9 +4691,11 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
if (HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 6, 10);
drm_connector_attach_active_bpc_property(connector, 6, 10);
+ drm_connector_attach_active_color_format_property(connector);
} else if (DISPLAY_VER(dev_priv) >= 5) {
drm_connector_attach_max_bpc_property(connector, 6, 12);
drm_connector_attach_active_bpc_property(connector, 6, 12);
+ drm_connector_attach_active_color_format_property(connector);
}

/* Register HDMI colorspace for case of lspcon */
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 16bfc59570a5..3e4237df3360 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -856,6 +856,11 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
if (connector->active_bpc_property)
drm_connector_attach_active_bpc_property(connector, 6, 12);

+ connector->active_color_format_property =
+ intel_dp->attached_connector->base.active_color_format_property;
+ if (connector->active_color_format_property)
+ drm_connector_attach_active_color_format_property(connector);
+
return connector;

err:
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 9160e21ac9d6..367aba57b55f 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2516,6 +2516,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
if (!HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 8, 12);
drm_connector_attach_active_bpc_property(connector, 8, 12);
+ drm_connector_attach_active_color_format_property(connector);
}
}

--
2.25.1

2021-06-30 15:12:05

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 07/17] drm/amd/display: Add handling for new "active color format" property

This commit implements the "active color format" drm property for the AMD
GPU driver.

Signed-off-by: Werner Sembach <[email protected]>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 +++++++++++++++++--
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +++
2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d984de82ae63..098f3d53e681 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6710,6 +6710,24 @@ static int convert_dc_color_depth_into_bpc (enum dc_color_depth display_color_de
return 0;
}

+static int convert_dc_pixel_encoding_into_drm_color_format(
+ enum dc_pixel_encoding display_pixel_encoding)
+{
+ switch (display_pixel_encoding) {
+ case PIXEL_ENCODING_RGB:
+ return DRM_COLOR_FORMAT_RGB444;
+ case PIXEL_ENCODING_YCBCR422:
+ return DRM_COLOR_FORMAT_YCRCB422;
+ case PIXEL_ENCODING_YCBCR444:
+ return DRM_COLOR_FORMAT_YCRCB444;
+ case PIXEL_ENCODING_YCBCR420:
+ return DRM_COLOR_FORMAT_YCRCB420;
+ default:
+ break;
+ }
+ return 0;
+}
+
static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
@@ -7711,6 +7729,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
if (!aconnector->mst_port) {
drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);
+ drm_connector_attach_active_color_format_property(&aconnector->base);
}

/* This defaults to the max in the range, but we want 8bpc for non-edp. */
@@ -9090,14 +9109,20 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
stream = dm_new_crtc_state->stream;

- if (stream)
+ if (stream) {
drm_connector_set_active_bpc_property(connector,
stream->timing.flags.DSC ?
stream->timing.dsc_cfg.bits_per_pixel / 16 / 3 :
convert_dc_color_depth_into_bpc(
stream->timing.display_color_depth));
- } else
+ drm_connector_set_active_color_format_property(connector,
+ convert_dc_pixel_encoding_into_drm_color_format(
+ dm_new_crtc_state->stream->timing.pixel_encoding));
+ }
+ } else {
drm_connector_set_active_bpc_property(connector, 0);
+ drm_connector_set_active_color_format_property(connector, 0);
+ }
}

/* Count number of newly disabled CRTCs for dropping PM refs later. */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 0cf38743ec47..13151d13aa73 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -413,6 +413,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
if (connector->active_bpc_property)
drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);

+ connector->active_color_format_property = master->base.active_color_format_property;
+ if (connector->active_color_format_property)
+ drm_connector_attach_active_color_format_property(&aconnector->base);
+
connector->vrr_capable_property = master->base.vrr_capable_property;
if (connector->vrr_capable_property)
drm_connector_attach_vrr_capable_property(connector);
--
2.25.1

2021-06-30 15:12:06

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 09/17] drm/uAPI: Add "active color range" drm property as feedback for userspace

Add a new general drm property "active color range" which can be used by
graphic drivers to report the used color range back to userspace.

There was no way to check which color range got actually used on a given
monitor. To surely predict this, one must know the exact capabilities of
the monitor and what the default behaviour of the used driver is. This
property helps eliminating the guessing at this point.

In the future, automatic color calibration for screens might also depend on
this information being available.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/drm_connector.c | 61 +++++++++++++++++++++++++++++++++
include/drm/drm_connector.h | 27 +++++++++++++++
2 files changed, 88 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 075bdc08d5c3..ebfdd17a7f59 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -897,6 +897,12 @@ static const struct drm_prop_enum_list drm_active_color_format_enum_list[] = {
{ DRM_COLOR_FORMAT_YCRCB420, "ycbcr420" },
};

+static const struct drm_prop_enum_list drm_active_color_range_enum_list[] = {
+ { DRM_MODE_COLOR_RANGE_UNSET, "Not Applicable" },
+ { DRM_MODE_COLOR_RANGE_FULL, "Full" },
+ { DRM_MODE_COLOR_RANGE_LIMITED_16_235, "Limited 16:235" },
+};
+
DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name,
drm_dp_subconnector_enum_list)

@@ -1223,6 +1229,15 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
* property. Possible values are "not applicable", "rgb", "ycbcr444",
* "ycbcr422", and "ycbcr420".
*
+ * active color range:
+ * This read-only property tells userspace the color range actually used by
+ * the hardware display engine "on the cable" on a connector. The chosen
+ * value depends on hardware capabilities of the monitor and the used color
+ * format. Drivers shall use
+ * drm_connector_attach_active_color_range_property() to install this
+ * property. Possible values are "Not Applicable", "Full", and "Limited
+ * 16:235".
+ *
* Connectors also have one standardized atomic property:
*
* CRTC_ID:
@@ -2268,6 +2283,52 @@ void drm_connector_set_active_color_format_property(struct drm_connector *connec
}
EXPORT_SYMBOL(drm_connector_set_active_color_format_property);

+/**
+ * drm_connector_attach_active_color_range_property - attach "active color range" property
+ * @connector: connector to attach active color range property on.
+ *
+ * This is used to check the applied color range on a connector.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_active_color_range_property(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+
+ if (!connector->active_color_range_property) {
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "active color range",
+ drm_active_color_range_enum_list,
+ ARRAY_SIZE(drm_active_color_range_enum_list));
+ if (!prop)
+ return -ENOMEM;
+
+ connector->active_color_range_property = prop;
+ }
+
+ drm_object_attach_property(&connector->base, prop, DRM_MODE_COLOR_RANGE_UNSET);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_active_color_range_property);
+
+/**
+ * drm_connector_set_active_color_range_property - sets the active color range property for a
+ * connector
+ * @connector: drm connector
+ * @active_color_range: color range for the connector currently active "on the cable"
+ *
+ * Should be used by atomic drivers to update the active color range over a connector.
+ */
+void drm_connector_set_active_color_range_property(struct drm_connector *connector,
+ enum drm_mode_color_range active_color_range)
+{
+ drm_object_property_set_value(&connector->base, connector->active_color_range_property,
+ active_color_range);
+}
+EXPORT_SYMBOL(drm_connector_set_active_color_range_property);
+
/**
* drm_connector_attach_hdr_output_metadata_property - attach "HDR_OUTPUT_METADA" property
* @connector: connector to attach the property on.
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 8a5197f14e87..5ef4bb270f71 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -648,6 +648,24 @@ struct drm_tv_connector_state {
unsigned int hue;
};

+/**
+ * enum drm_mode_color_range - color_range info for &drm_connector
+ *
+ * This enum is used to represent full or limited color range on the display
+ * connector signal.
+ *
+ * @DRM_MODE_COLOR_RANGE_UNSET: Color range is unspecified/default.
+ * @DRM_MODE_COLOR_RANGE_FULL: Color range is full range, 0-255 for
+ * 8-Bit color depth.
+ * @DRM_MODE_COLOR_RANGE_LIMITED_16_235: Color range is limited range, 16-235
+ * for 8-Bit color depth.
+ */
+enum drm_mode_color_range {
+ DRM_MODE_COLOR_RANGE_UNSET,
+ DRM_MODE_COLOR_RANGE_FULL,
+ DRM_MODE_COLOR_RANGE_LIMITED_16_235,
+};
+
/**
* struct drm_connector_state - mutable connector state
*/
@@ -1392,6 +1410,12 @@ struct drm_connector {
*/
struct drm_property *active_color_format_property;

+ /**
+ * @active_color_range_property: Default connector property for the
+ * active color range to be driven out of the connector.
+ */
+ struct drm_property *active_color_range_property;
+
#define DRM_CONNECTOR_POLL_HPD (1 << 0)
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
@@ -1719,6 +1743,9 @@ void drm_connector_set_active_bpc_property(struct drm_connector *connector, int
int drm_connector_attach_active_color_format_property(struct drm_connector *connector);
void drm_connector_set_active_color_format_property(struct drm_connector *connector,
u32 active_color_format);
+int drm_connector_attach_active_color_range_property(struct drm_connector *connector);
+void drm_connector_set_active_color_range_property(struct drm_connector *connector,
+ enum drm_mode_color_range active_color_range);

/**
* struct drm_tile_group - Tile group metadata
--
2.25.1

2021-06-30 15:12:07

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 05/17] drm/i915/display: Add handling for new "active bpc" property

This commit implements the "active bpc" drm property for the Intel GPU
driver.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/i915/display/intel_display.c | 19 +++++++++++++++++++
drivers/gpu/drm/i915/display/intel_dp.c | 7 +++++--
drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++++
drivers/gpu/drm/i915/display/intel_hdmi.c | 4 +++-
4 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 6be1b31af07b..1b63d1404d06 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -10839,6 +10839,9 @@ static int intel_atomic_commit(struct drm_device *dev,
{
struct intel_atomic_state *state = to_intel_atomic_state(_state);
struct drm_i915_private *dev_priv = to_i915(dev);
+ struct drm_connector *connector;
+ struct drm_connector_state *new_conn_state;
+ int i;
int ret = 0;

state->wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
@@ -10907,6 +10910,22 @@ static int intel_atomic_commit(struct drm_device *dev,
intel_shared_dpll_swap_state(state);
intel_atomic_track_fbs(state);

+ /* Extract information from crtc to communicate it to userspace as connector properties */
+ for_each_new_connector_in_state(&state->base, connector, new_conn_state, i) {
+ struct intel_crtc *crtc = to_intel_crtc(new_conn_state->crtc);
+
+ if (crtc) {
+ struct intel_crtc_state *new_crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+
+ drm_connector_set_active_bpc_property(connector,
+ new_crtc_state->dsc.compression_enable ?
+ new_crtc_state->dsc.compressed_bpp / 3 :
+ new_crtc_state->pipe_bpp / 3);
+ } else
+ drm_connector_set_active_bpc_property(connector, 0);
+ }
+
drm_atomic_state_get(&state->base);
INIT_WORK(&state->base.commit_work, intel_atomic_commit_work);

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 6cc03b9e4321..815bc313b954 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4688,10 +4688,13 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
intel_attach_force_audio_property(connector);

intel_attach_broadcast_rgb_property(connector);
- if (HAS_GMCH(dev_priv))
+ if (HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 6, 10);
- else if (DISPLAY_VER(dev_priv) >= 5)
+ drm_connector_attach_active_bpc_property(connector, 6, 10);
+ } else if (DISPLAY_VER(dev_priv) >= 5) {
drm_connector_attach_max_bpc_property(connector, 6, 12);
+ drm_connector_attach_active_bpc_property(connector, 6, 12);
+ }

/* Register HDMI colorspace for case of lspcon */
if (intel_bios_is_lspcon_present(dev_priv, port)) {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index b170e272bdee..16bfc59570a5 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -851,6 +851,11 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
if (connector->max_bpc_property)
drm_connector_attach_max_bpc_property(connector, 6, 12);

+ connector->active_bpc_property =
+ intel_dp->attached_connector->base.active_bpc_property;
+ if (connector->active_bpc_property)
+ drm_connector_attach_active_bpc_property(connector, 6, 12);
+
return connector;

err:
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 7e51c98c475e..9160e21ac9d6 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2513,8 +2513,10 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
if (DISPLAY_VER(dev_priv) >= 10)
drm_connector_attach_hdr_output_metadata_property(connector);

- if (!HAS_GMCH(dev_priv))
+ if (!HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 8, 12);
+ drm_connector_attach_active_bpc_property(connector, 8, 12);
+ }
}

/*
--
2.25.1

2021-06-30 15:12:13

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 03/17] drm/uAPI: Add "active bpc" as feedback channel for "max bpc" drm property

Add a new general drm property "active bpc" which can be used by graphic
drivers to report the applied bit depth per pixel color back to userspace.

While "max bpc" can be used to change the color depth, there was no way to
check which one actually got used. While in theory the driver chooses the
best/highest color depth within the max bpc setting a user might not be
fully aware what his hardware is or isn't capable off. This is meant as a
quick way to double check the setup.

In the future, automatic color calibration for screens might also depend on
this information being available.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/drm_connector.c | 53 +++++++++++++++++++++++++++++++++
include/drm/drm_connector.h | 8 +++++
2 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index da39e7ff6965..6461d00e8e49 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1197,6 +1197,15 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
* drm_connector_attach_max_bpc_property() to create and attach the
* property to the connector during initialization.
*
+ * active bpc:
+ * This read-only range property tells userspace the pixel color bit depth
+ * actually used by the hardware display engine "on the cable" on a
+ * connector. This means after display stream compression and dithering
+ * done by the GPU. The chosen value depends on hardware capabilities, both
+ * display engine and connected monitor, and the "max bpc" property.
+ * Drivers shall use drm_connector_attach_active_bpc_property() to install
+ * this property. A value of 0 means "not applicable".
+ *
* Connectors also have one standardized atomic property:
*
* CRTC_ID:
@@ -2152,6 +2161,50 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_connector_attach_max_bpc_property);

+/**
+ * drm_connector_attach_active_bpc_property - attach "active bpc" property
+ * @connector: connector to attach active bpc property on.
+ * @min: The minimum bit depth supported by the connector.
+ * @max: The maximum bit depth supported by the connector.
+ *
+ * This is used to check the applied bit depth on a connector.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_active_bpc_property(struct drm_connector *connector, int min, int max)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+
+ if (!connector->active_bpc_property) {
+ prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "active bpc",
+ min, max);
+ if (!prop)
+ return -ENOMEM;
+
+ connector->active_bpc_property = prop;
+ }
+
+ drm_object_attach_property(&connector->base, prop, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_active_bpc_property);
+
+/**
+ * drm_connector_set_active_bpc_property - sets the active bits per color property for a connector
+ * @connector: drm connector
+ * @active_bpc: bits per color for the connector currently active "on the cable"
+ *
+ * Should be used by atomic drivers to update the active bits per color over a connector.
+ */
+void drm_connector_set_active_bpc_property(struct drm_connector *connector, int active_bpc)
+{
+ drm_object_property_set_value(&connector->base, connector->active_bpc_property, active_bpc);
+}
+EXPORT_SYMBOL(drm_connector_set_active_bpc_property);
+
/**
* drm_connector_attach_hdr_output_metadata_property - attach "HDR_OUTPUT_METADA" property
* @connector: connector to attach the property on.
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 714d1a01c065..eee86de62a5f 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1380,6 +1380,12 @@ struct drm_connector {
*/
struct drm_property *max_bpc_property;

+ /**
+ * @active_bpc_property: Default connector property for the active bpc
+ * to be driven out of the connector.
+ */
+ struct drm_property *active_bpc_property;
+
#define DRM_CONNECTOR_POLL_HPD (1 << 0)
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
@@ -1702,6 +1708,8 @@ int drm_connector_set_panel_orientation_with_quirk(
int width, int height);
int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
int min, int max);
+int drm_connector_attach_active_bpc_property(struct drm_connector *connector, int min, int max);
+void drm_connector_set_active_bpc_property(struct drm_connector *connector, int active_bpc);

/**
* struct drm_tile_group - Tile group metadata
--
2.25.1

2021-06-30 15:12:22

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 06/17] drm/uAPI: Add "active color format" drm property as feedback for userspace

Add a new general drm property "active color format" which can be used by
graphic drivers to report the used color format back to userspace.

There was no way to check which color format got actually used on a given
monitor. To surely predict this, one must know the exact capabilities of
the monitor, the GPU, and the connection used and what the default
behaviour of the used driver is (e.g. amdgpu prefers YCbCr 4:4:4 while i915
prefers RGB). This property helps eliminating the guessing on this point.

In the future, automatic color calibration for screens might also depend on
this information being available.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/drm_connector.c | 63 +++++++++++++++++++++++++++++++++
include/drm/drm_connector.h | 9 +++++
2 files changed, 72 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 6461d00e8e49..075bdc08d5c3 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -889,6 +889,14 @@ static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = {
{ DRM_MODE_SUBCONNECTOR_Native, "Native" }, /* DP */
};

+static const struct drm_prop_enum_list drm_active_color_format_enum_list[] = {
+ { 0, "not applicable" },
+ { DRM_COLOR_FORMAT_RGB444, "rgb" },
+ { DRM_COLOR_FORMAT_YCRCB444, "ycbcr444" },
+ { DRM_COLOR_FORMAT_YCRCB422, "ycbcr422" },
+ { DRM_COLOR_FORMAT_YCRCB420, "ycbcr420" },
+};
+
DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name,
drm_dp_subconnector_enum_list)

@@ -1206,6 +1214,15 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
* Drivers shall use drm_connector_attach_active_bpc_property() to install
* this property. A value of 0 means "not applicable".
*
+ * active color format:
+ * This read-only property tells userspace the color format actually used
+ * by the hardware display engine "on the cable" on a connector. The chosen
+ * value depends on hardware capabilities, both display engine and
+ * connected monitor. Drivers shall use
+ * drm_connector_attach_active_color_format_property() to install this
+ * property. Possible values are "not applicable", "rgb", "ycbcr444",
+ * "ycbcr422", and "ycbcr420".
+ *
* Connectors also have one standardized atomic property:
*
* CRTC_ID:
@@ -2205,6 +2222,52 @@ void drm_connector_set_active_bpc_property(struct drm_connector *connector, int
}
EXPORT_SYMBOL(drm_connector_set_active_bpc_property);

+/**
+ * drm_connector_attach_active_color_format_property - attach "active color format" property
+ * @connector: connector to attach active color format property on.
+ *
+ * This is used to check the applied color format on a connector.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_active_color_format_property(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+
+ if (!connector->active_color_format_property) {
+ prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "active color format",
+ drm_active_color_format_enum_list,
+ ARRAY_SIZE(drm_active_color_format_enum_list));
+ if (!prop)
+ return -ENOMEM;
+
+ connector->active_color_format_property = prop;
+ }
+
+ drm_object_attach_property(&connector->base, prop, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_active_color_format_property);
+
+/**
+ * drm_connector_set_active_color_format_property - sets the active color format property for a
+ * connector
+ * @connector: drm connector
+ * @active_color_format: color format for the connector currently active "on the cable"
+ *
+ * Should be used by atomic drivers to update the active color format over a connector.
+ */
+void drm_connector_set_active_color_format_property(struct drm_connector *connector,
+ u32 active_color_format)
+{
+ drm_object_property_set_value(&connector->base, connector->active_color_format_property,
+ active_color_format);
+}
+EXPORT_SYMBOL(drm_connector_set_active_color_format_property);
+
/**
* drm_connector_attach_hdr_output_metadata_property - attach "HDR_OUTPUT_METADA" property
* @connector: connector to attach the property on.
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index eee86de62a5f..8a5197f14e87 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1386,6 +1386,12 @@ struct drm_connector {
*/
struct drm_property *active_bpc_property;

+ /**
+ * @active_color_format_property: Default connector property for the
+ * active color format to be driven out of the connector.
+ */
+ struct drm_property *active_color_format_property;
+
#define DRM_CONNECTOR_POLL_HPD (1 << 0)
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
@@ -1710,6 +1716,9 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
int min, int max);
int drm_connector_attach_active_bpc_property(struct drm_connector *connector, int min, int max);
void drm_connector_set_active_bpc_property(struct drm_connector *connector, int active_bpc);
+int drm_connector_attach_active_color_format_property(struct drm_connector *connector);
+void drm_connector_set_active_color_format_property(struct drm_connector *connector,
+ u32 active_color_format);

/**
* struct drm_tile_group - Tile group metadata
--
2.25.1

2021-06-30 15:13:52

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 15/17] drm/uAPI: Move "Broadcast RGB" property from driver specific to general context

Add "Broadcast RGB" to general drm context so that more drivers besides
i915 and gma500 can implement it without duplicating code.

Userspace can use this property to tell the graphic driver to use full or
limited color range for a given connector, overwriting the default
behaviour/automatic detection.

Possible options are:
- Automatic (default/current behaviour)
- Full
- Limited 16:235

In theory the driver should be able to automatically detect the monitors
capabilities, but because of flawed standard implementations in Monitors,
this might fail. In this case a manual overwrite is required to not have
washed out colors or lose details in very dark or bright scenes.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/drm_atomic_helper.c | 4 +++
drivers/gpu/drm/drm_atomic_uapi.c | 4 +++
drivers/gpu/drm/drm_connector.c | 46 +++++++++++++++++++++++++++++
include/drm/drm_connector.h | 16 ++++++++++
4 files changed, 70 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 90d62f305257..0c89d32efbd0 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -691,6 +691,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
if (old_connector_state->preferred_color_format !=
new_connector_state->preferred_color_format)
new_crtc_state->connectors_changed = true;
+
+ if (old_connector_state->preferred_color_range !=
+ new_connector_state->preferred_color_range)
+ new_crtc_state->connectors_changed = true;
}

if (funcs->atomic_check)
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index c536f5e22016..c589bb1a8163 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -798,6 +798,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
state->max_requested_bpc = val;
} else if (property == connector->preferred_color_format_property) {
state->preferred_color_format = val;
+ } else if (property == connector->preferred_color_range_property) {
+ state->preferred_color_range = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
@@ -877,6 +879,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
*val = state->max_requested_bpc;
} else if (property == connector->preferred_color_format_property) {
*val = state->preferred_color_format;
+ } else if (property == connector->preferred_color_range_property) {
+ *val = state->preferred_color_range;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 67dd59b12258..20ae2e6d907b 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -905,6 +905,12 @@ static const struct drm_prop_enum_list drm_active_color_format_enum_list[] = {
{ DRM_COLOR_FORMAT_YCRCB420, "ycbcr420" },
};

+static const struct drm_prop_enum_list drm_preferred_color_range_enum_list[] = {
+ { DRM_MODE_COLOR_RANGE_UNSET, "Automatic" },
+ { DRM_MODE_COLOR_RANGE_FULL, "Full" },
+ { DRM_MODE_COLOR_RANGE_LIMITED_16_235, "Limited 16:235" },
+};
+
static const struct drm_prop_enum_list drm_active_color_range_enum_list[] = {
{ DRM_MODE_COLOR_RANGE_UNSET, "Not Applicable" },
{ DRM_MODE_COLOR_RANGE_FULL, "Full" },
@@ -1246,6 +1252,15 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
* property. Possible values are "not applicable", "rgb", "ycbcr444",
* "ycbcr422", and "ycbcr420".
*
+ * Broadcast RGB:
+ * This property is used by userspace to change the used color range. This
+ * property affects the RGB color format as well as the Y'CbCr color
+ * formats, if the driver supports both full and limited Y'CbCr. Drivers to
+ * use the function drm_connector_attach_preferred_color_format_property()
+ * to create and attach the property to the connector during
+ * initialization. Possible values are "Automatic", "Full", and "Limited
+ * 16:235".
+ *
* active color range:
* This read-only property tells userspace the color range actually used by
* the hardware display engine "on the cable" on a connector. The chosen
@@ -2331,6 +2346,37 @@ void drm_connector_set_active_color_format_property(struct drm_connector *connec
}
EXPORT_SYMBOL(drm_connector_set_active_color_format_property);

+/**
+ * drm_connector_attach_preferred_color_range_property - attach "Broadcast RGB" property
+ * @connector: connector to attach preferred color range property on.
+ *
+ * This is used to add support for selecting a color range on a connector.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_preferred_color_range_property(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+
+ if (!connector->preferred_color_range_property) {
+ prop = drm_property_create_enum(dev, 0, "Broadcast RGB",
+ drm_preferred_color_range_enum_list,
+ ARRAY_SIZE(drm_preferred_color_range_enum_list));
+ if (!prop)
+ return -ENOMEM;
+
+ connector->preferred_color_range_property = prop;
+ }
+
+ drm_object_attach_property(&connector->base, prop, DRM_MODE_COLOR_RANGE_UNSET);
+ connector->state->preferred_color_range = DRM_MODE_COLOR_RANGE_UNSET;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_preferred_color_range_property);
+
/**
* drm_connector_attach_active_color_range_property - attach "active color range" property
* @connector: connector to attach active color range property on.
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 0dd7ece375c5..028bfb831abb 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -809,6 +809,15 @@ struct drm_connector_state {
*/
u32 preferred_color_format;

+ /**
+ * preferred_color_range: Property set by userspace via "Broadcast RGB"
+ * property to tell the GPU driver which color range to use. It
+ * overwrites existing automatic detection mechanisms, if set and valid
+ * for the current color format. Userspace can check for (un-)successful
+ * application via the "active color range" property.
+ */
+ enum drm_mode_color_range preferred_color_range;
+
/**
* @hdr_output_metadata:
* DRM blob property for HDR output metadata
@@ -1426,6 +1435,12 @@ struct drm_connector {
*/
struct drm_property *active_color_format_property;

+ /**
+ * @preferred_color_range_property: Default connector property for the
+ * preferred color range to be driven out of the connector.
+ */
+ struct drm_property *preferred_color_range_property;
+
/**
* @active_color_range_property: Default connector property for the
* active color range to be driven out of the connector.
@@ -1760,6 +1775,7 @@ int drm_connector_attach_preferred_color_format_property(struct drm_connector *c
int drm_connector_attach_active_color_format_property(struct drm_connector *connector);
void drm_connector_set_active_color_format_property(struct drm_connector *connector,
u32 active_color_format);
+int drm_connector_attach_preferred_color_range_property(struct drm_connector *connector);
int drm_connector_attach_active_color_range_property(struct drm_connector *connector);
void drm_connector_set_active_color_range_property(struct drm_connector *connector,
enum drm_mode_color_range active_color_range);
--
2.25.1

2021-06-30 15:13:55

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 11/17] drm/i915/display: Add handling for new "active color range" property

This commit implements the "active color range" drm property for the Intel
GPU driver.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/i915/display/intel_display.c | 7 +++++++
drivers/gpu/drm/i915/display/intel_dp.c | 1 +
drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++++
drivers/gpu/drm/i915/display/intel_hdmi.c | 1 +
4 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index be38f7148285..b0bcb42a97fc 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -10940,9 +10940,16 @@ static int intel_atomic_commit(struct drm_device *dev,
drm_connector_set_active_color_format_property(connector,
convert_intel_output_format_into_drm_color_format(
new_crtc_state->output_format));
+ drm_connector_set_active_color_range_property(connector,
+ new_crtc_state->limited_color_range ||
+ new_crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ?
+ DRM_MODE_COLOR_RANGE_LIMITED_16_235 :
+ DRM_MODE_COLOR_RANGE_FULL);
} else {
drm_connector_set_active_bpc_property(connector, 0);
drm_connector_set_active_color_format_property(connector, 0);
+ drm_connector_set_active_color_range_property(connector,
+ DRM_MODE_COLOR_RANGE_UNSET);
}
}

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 6b85bcdeb238..fd33f753244d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4688,6 +4688,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
intel_attach_force_audio_property(connector);

intel_attach_broadcast_rgb_property(connector);
+ drm_connector_attach_active_color_range_property(connector);
if (HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 6, 10);
drm_connector_attach_active_bpc_property(connector, 6, 10);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 3e4237df3360..cb876175258f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -861,6 +861,11 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
if (connector->active_color_format_property)
drm_connector_attach_active_color_format_property(connector);

+ connector->active_color_range_property =
+ intel_dp->attached_connector->base.active_color_range_property;
+ if (connector->active_color_range_property)
+ drm_connector_attach_active_color_range_property(connector);
+
return connector;

err:
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 367aba57b55f..3ee25e0cc3b9 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2505,6 +2505,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c

intel_attach_force_audio_property(connector);
intel_attach_broadcast_rgb_property(connector);
+ drm_connector_attach_active_color_range_property(connector);
intel_attach_aspect_ratio_property(connector);

intel_attach_hdmi_colorspace_property(connector);
--
2.25.1

2021-06-30 15:14:05

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 12/17] drm/uAPI: Add "preferred color format" drm property as setting for userspace

Add a new general drm property "preferred color format" which can be used
by userspace to tell the graphic drivers to which color format to use.

Possible options are:
- auto (default/current behaviour)
- rgb
- ycbcr444
- ycbcr422 (not supported by both amdgpu and i915)
- ycbcr420

In theory the auto option should choose the best available option for the
current setup, but because of bad internal conversion some monitors look
better with rgb and some with ycbcr444.

Also, because of bad shielded connectors and/or cables, it might be
preferable to use the less bandwidth heavy ycbcr422 and ycbcr420 formats
for a signal that is less deceptible to interference.

In the future, automatic color calibration for screens might also depend on
this option being available.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/drm_atomic_helper.c | 4 +++
drivers/gpu/drm/drm_atomic_uapi.c | 4 +++
drivers/gpu/drm/drm_connector.c | 50 ++++++++++++++++++++++++++++-
include/drm/drm_connector.h | 17 ++++++++++
4 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index bc3487964fb5..90d62f305257 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -687,6 +687,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
if (old_connector_state->max_requested_bpc !=
new_connector_state->max_requested_bpc)
new_crtc_state->connectors_changed = true;
+
+ if (old_connector_state->preferred_color_format !=
+ new_connector_state->preferred_color_format)
+ new_crtc_state->connectors_changed = true;
}

if (funcs->atomic_check)
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 438e9585b225..c536f5e22016 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -796,6 +796,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
fence_ptr);
} else if (property == connector->max_bpc_property) {
state->max_requested_bpc = val;
+ } else if (property == connector->preferred_color_format_property) {
+ state->preferred_color_format = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
@@ -873,6 +875,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
*val = 0;
} else if (property == connector->max_bpc_property) {
*val = state->max_requested_bpc;
+ } else if (property == connector->preferred_color_format_property) {
+ *val = state->preferred_color_format;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index ebfdd17a7f59..67dd59b12258 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -889,6 +889,14 @@ static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = {
{ DRM_MODE_SUBCONNECTOR_Native, "Native" }, /* DP */
};

+static const struct drm_prop_enum_list drm_preferred_color_format_enum_list[] = {
+ { 0, "auto" },
+ { DRM_COLOR_FORMAT_RGB444, "rgb" },
+ { DRM_COLOR_FORMAT_YCRCB444, "ycbcr444" },
+ { DRM_COLOR_FORMAT_YCRCB422, "ycbcr422" },
+ { DRM_COLOR_FORMAT_YCRCB420, "ycbcr420" },
+};
+
static const struct drm_prop_enum_list drm_active_color_format_enum_list[] = {
{ 0, "not applicable" },
{ DRM_COLOR_FORMAT_RGB444, "rgb" },
@@ -1220,11 +1228,20 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
* Drivers shall use drm_connector_attach_active_bpc_property() to install
* this property. A value of 0 means "not applicable".
*
+ * preferred color format:
+ * This property is used by userspace to change the used color format. When
+ * used the driver will use the selected format if valid for the hardware,
+ * sink, and current resolution and refresh rate combination. Drivers to
+ * use the function drm_connector_attach_preferred_color_format_property()
+ * to create and attach the property to the connector during
+ * initialization. Possible values are "auto", "rgb", "ycbcr444",
+ * "ycbcr422", and "ycbcr420".
+ *
* active color format:
* This read-only property tells userspace the color format actually used
* by the hardware display engine "on the cable" on a connector. The chosen
* value depends on hardware capabilities, both display engine and
- * connected monitor. Drivers shall use
+ * connected monitor, and the "preferred color format". Drivers shall use
* drm_connector_attach_active_color_format_property() to install this
* property. Possible values are "not applicable", "rgb", "ycbcr444",
* "ycbcr422", and "ycbcr420".
@@ -2237,6 +2254,37 @@ void drm_connector_set_active_bpc_property(struct drm_connector *connector, int
}
EXPORT_SYMBOL(drm_connector_set_active_bpc_property);

+/**
+ * drm_connector_attach_preferred_color_format_property - attach "preferred color format" property
+ * @connector: connector to attach preferred color format property on.
+ *
+ * This is used to add support for selecting a color format on a connector.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_preferred_color_format_property(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_property *prop;
+
+ if (!connector->preferred_color_format_property) {
+ prop = drm_property_create_enum(dev, 0, "preferred color format",
+ drm_preferred_color_format_enum_list,
+ ARRAY_SIZE(drm_preferred_color_format_enum_list));
+ if (!prop)
+ return -ENOMEM;
+
+ connector->preferred_color_format_property = prop;
+ }
+
+ drm_object_attach_property(&connector->base, prop, 0);
+ connector->state->preferred_color_format = 0;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_preferred_color_format_property);
+
/**
* drm_connector_attach_active_color_format_property - attach "active color format" property
* @connector: connector to attach active color format property on.
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 5ef4bb270f71..0dd7ece375c5 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -799,6 +799,16 @@ struct drm_connector_state {
*/
u8 max_bpc;

+ /**
+ * preferred_color_format: Property set by userspace to tell the GPU
+ * driver which color format to use. It only gets applied if hardware,
+ * meaning both the computer and the monitor, and the driver support the
+ * given format at the current resolution and refresh rate. Userspace
+ * can check for (un-)successful application via the "active color
+ * format" property.
+ */
+ u32 preferred_color_format;
+
/**
* @hdr_output_metadata:
* DRM blob property for HDR output metadata
@@ -1404,6 +1414,12 @@ struct drm_connector {
*/
struct drm_property *active_bpc_property;

+ /**
+ * @preferred_color_format_property: Default connector property for the
+ * preferred color format to be driven out of the connector.
+ */
+ struct drm_property *preferred_color_format_property;
+
/**
* @active_color_format_property: Default connector property for the
* active color format to be driven out of the connector.
@@ -1740,6 +1756,7 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector,
int min, int max);
int drm_connector_attach_active_bpc_property(struct drm_connector *connector, int min, int max);
void drm_connector_set_active_bpc_property(struct drm_connector *connector, int active_bpc);
+int drm_connector_attach_preferred_color_format_property(struct drm_connector *connector);
int drm_connector_attach_active_color_format_property(struct drm_connector *connector);
void drm_connector_set_active_color_format_property(struct drm_connector *connector,
u32 active_color_format);
--
2.25.1

2021-06-30 15:14:25

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 10/17] drm/amd/display: Add handling for new "active color range" property

This commit implements the "active color range" drm property for the AMD
GPU driver.

Signed-off-by: Werner Sembach <[email protected]>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 +++++++++++++++++++
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +++
2 files changed, 37 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 098f3d53e681..b4acedac1ac9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6728,6 +6728,33 @@ static int convert_dc_pixel_encoding_into_drm_color_format(
return 0;
}

+static int convert_dc_color_space_into_drm_mode_color_range(enum dc_color_space color_space)
+{
+ if (color_space == COLOR_SPACE_SRGB ||
+ color_space == COLOR_SPACE_XR_RGB ||
+ color_space == COLOR_SPACE_MSREF_SCRGB ||
+ color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
+ color_space == COLOR_SPACE_ADOBERGB ||
+ color_space == COLOR_SPACE_DCIP3 ||
+ color_space == COLOR_SPACE_DOLBYVISION ||
+ color_space == COLOR_SPACE_YCBCR601 ||
+ color_space == COLOR_SPACE_XV_YCC_601 ||
+ color_space == COLOR_SPACE_YCBCR709 ||
+ color_space == COLOR_SPACE_XV_YCC_709 ||
+ color_space == COLOR_SPACE_2020_YCBCR ||
+ color_space == COLOR_SPACE_YCBCR709_BLACK ||
+ color_space == COLOR_SPACE_DISPLAYNATIVE ||
+ color_space == COLOR_SPACE_APPCTRL ||
+ color_space == COLOR_SPACE_CUSTOMPOINTS)
+ return DRM_MODE_COLOR_RANGE_FULL;
+ if (color_space == COLOR_SPACE_SRGB_LIMITED ||
+ color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
+ color_space == COLOR_SPACE_YCBCR601_LIMITED ||
+ color_space == COLOR_SPACE_YCBCR709_LIMITED)
+ return DRM_MODE_COLOR_RANGE_LIMITED_16_235;
+ return DRM_MODE_COLOR_RANGE_UNSET;
+}
+
static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
@@ -7730,6 +7757,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);
drm_connector_attach_active_color_format_property(&aconnector->base);
+ drm_connector_attach_active_color_range_property(&aconnector->base);
}

/* This defaults to the max in the range, but we want 8bpc for non-edp. */
@@ -9118,10 +9146,15 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
drm_connector_set_active_color_format_property(connector,
convert_dc_pixel_encoding_into_drm_color_format(
dm_new_crtc_state->stream->timing.pixel_encoding));
+ drm_connector_set_active_color_range_property(connector,
+ convert_dc_color_space_into_drm_mode_color_range(
+ dm_new_crtc_state->stream->output_color_space));
}
} else {
drm_connector_set_active_bpc_property(connector, 0);
drm_connector_set_active_color_format_property(connector, 0);
+ drm_connector_set_active_color_range_property(connector,
+ DRM_MODE_COLOR_RANGE_UNSET);
}
}

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 13151d13aa73..b5d57bbbdd20 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -417,6 +417,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
if (connector->active_color_format_property)
drm_connector_attach_active_color_format_property(&aconnector->base);

+ connector->active_color_range_property = master->base.active_color_range_property;
+ if (connector->active_color_range_property)
+ drm_connector_attach_active_color_range_property(&aconnector->base);
+
connector->vrr_capable_property = master->base.vrr_capable_property;
if (connector->vrr_capable_property)
drm_connector_attach_vrr_capable_property(connector);
--
2.25.1

2021-06-30 15:14:40

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 02/17] drm/amd/display: Add missing cases convert_dc_color_depth_into_bpc

convert_dc_color_depth_into_bpc() that converts the enum dc_color_depth to
an integer had the casses for COLOR_DEPTH_999 and COLOR_DEPTH_111111
missing.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index e081dd3ffb5f..f4abb5f215d1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6700,6 +6700,10 @@ static int convert_dc_color_depth_into_bpc (enum dc_color_depth display_color_de
return 14;
case COLOR_DEPTH_161616:
return 16;
+ case COLOR_DEPTH_999:
+ return 9;
+ case COLOR_DEPTH_111111:
+ return 11;
default:
break;
}
--
2.25.1

2021-06-30 15:15:16

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 17/17] drm/amd/display: Add handling for new "Broadcast RGB" property

This commit implements the "Broadcast RGB" drm property for the AMD GPU
driver.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++++---
.../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ++++
2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 02a5809d4993..80d5a11fb0c5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5247,7 +5247,8 @@ get_aspect_ratio(const struct drm_display_mode *mode_in)
}

static enum dc_color_space
-get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
+get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
+ enum drm_mode_color_range preferred_color_range)
{
enum dc_color_space color_space = COLOR_SPACE_SRGB;

@@ -5278,7 +5279,10 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
}
break;
case PIXEL_ENCODING_RGB:
- color_space = COLOR_SPACE_SRGB;
+ if (preferred_color_range == DRM_MODE_COLOR_RANGE_LIMITED_16_235)
+ color_space = COLOR_SPACE_SRGB_LIMITED;
+ else
+ color_space = COLOR_SPACE_SRGB;
break;

default:
@@ -5424,7 +5428,10 @@ static void fill_stream_properties_from_drm_display_mode(

timing_out->aspect_ratio = get_aspect_ratio(mode_in);

- stream->output_color_space = get_output_color_space(timing_out);
+ stream->output_color_space = get_output_color_space(timing_out,
+ connector_state ?
+ connector_state->preferred_color_range :
+ DRM_MODE_COLOR_RANGE_UNSET);

stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
@@ -7775,6 +7782,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);
drm_connector_attach_preferred_color_format_property(&aconnector->base);
drm_connector_attach_active_color_format_property(&aconnector->base);
+ drm_connector_attach_preferred_color_range_property(&aconnector->base);
drm_connector_attach_active_color_range_property(&aconnector->base);
}

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 2563788ba95a..80e1389fd0ec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -421,6 +421,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
if (connector->active_color_format_property)
drm_connector_attach_active_color_format_property(&aconnector->base);

+ connector->preferred_color_range_property = master->base.preferred_color_range_property;
+ if (connector->preferred_color_range_property)
+ drm_connector_attach_preferred_color_range_property(&aconnector->base);
+
connector->active_color_range_property = master->base.active_color_range_property;
if (connector->active_color_range_property)
drm_connector_attach_active_color_range_property(&aconnector->base);
--
2.25.1

2021-06-30 15:15:16

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 14/17] drm/i915/display: Add handling for new "preferred color format" property

This commit implements the "preferred color format" drm property for the
Intel GPU driver.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/i915/display/intel_dp.c | 7 ++++++-
drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +++++
drivers/gpu/drm/i915/display/intel_hdmi.c | 6 ++++++
3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index fd33f753244d..29bb181ec4be 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -616,9 +616,12 @@ intel_dp_output_format(struct drm_connector *connector,
{
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
const struct drm_display_info *info = &connector->display_info;
+ const struct drm_connector_state *connector_state = connector->state;

if (!connector->ycbcr_420_allowed ||
- !drm_mode_is_420_only(info, mode))
+ !(drm_mode_is_420_only(info, mode) ||
+ (drm_mode_is_420_also(info, mode) && connector_state &&
+ connector_state->preferred_color_format == DRM_COLOR_FORMAT_YCRCB420)))
return INTEL_OUTPUT_FORMAT_RGB;

if (intel_dp->dfp.rgb_to_ycbcr &&
@@ -4692,10 +4695,12 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
if (HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 6, 10);
drm_connector_attach_active_bpc_property(connector, 6, 10);
+ drm_connector_attach_preferred_color_format_property(connector);
drm_connector_attach_active_color_format_property(connector);
} else if (DISPLAY_VER(dev_priv) >= 5) {
drm_connector_attach_max_bpc_property(connector, 6, 12);
drm_connector_attach_active_bpc_property(connector, 6, 12);
+ drm_connector_attach_preferred_color_format_property(connector);
drm_connector_attach_active_color_format_property(connector);
}

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index cb876175258f..67f0fb649876 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -856,6 +856,11 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
if (connector->active_bpc_property)
drm_connector_attach_active_bpc_property(connector, 6, 12);

+ connector->preferred_color_format_property =
+ intel_dp->attached_connector->base.preferred_color_format_property;
+ if (connector->preferred_color_format_property)
+ drm_connector_attach_preferred_color_format_property(connector);
+
connector->active_color_format_property =
intel_dp->attached_connector->base.active_color_format_property;
if (connector->active_color_format_property)
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 3ee25e0cc3b9..a7b85cd13227 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2153,6 +2153,11 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;
}

+ if (connector->ycbcr_420_allowed &&
+ conn_state->preferred_color_format == DRM_COLOR_FORMAT_YCRCB420 &&
+ drm_mode_is_420_also(&connector->display_info, adjusted_mode))
+ crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+
ret = intel_hdmi_compute_clock(encoder, crtc_state);
if (ret) {
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420 &&
@@ -2517,6 +2522,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
if (!HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 8, 12);
drm_connector_attach_active_bpc_property(connector, 8, 12);
+ drm_connector_attach_preferred_color_format_property(connector);
drm_connector_attach_active_color_format_property(connector);
}
}
--
2.25.1

2021-06-30 15:16:09

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 16/17] drm/i915/display: Use the general "Broadcast RGB" implementation

Change from the i915 specific "Broadcast RGB" drm property implementation
to the general one.

This commit delete all traces of the former "Broadcast RGB" implementation
and add a new one using the new driver agnoistic functions an variables.

Signed-off-by: Werner Sembach <[email protected]>
---
drivers/gpu/drm/i915/display/intel_atomic.c | 8 ------
.../gpu/drm/i915/display/intel_connector.c | 28 -------------------
.../gpu/drm/i915/display/intel_connector.h | 1 -
.../drm/i915/display/intel_display_types.h | 8 ------
drivers/gpu/drm/i915/display/intel_dp.c | 9 ++----
drivers/gpu/drm/i915/display/intel_dp_mst.c | 6 +++-
drivers/gpu/drm/i915/display/intel_hdmi.c | 8 ++----
drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +-
drivers/gpu/drm/i915/i915_drv.h | 1 -
9 files changed, 12 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index b4e7ac51aa31..f8d5a0e287b0 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -63,8 +63,6 @@ int intel_digital_connector_atomic_get_property(struct drm_connector *connector,

if (property == dev_priv->force_audio_property)
*val = intel_conn_state->force_audio;
- else if (property == dev_priv->broadcast_rgb_property)
- *val = intel_conn_state->broadcast_rgb;
else {
drm_dbg_atomic(&dev_priv->drm,
"Unknown property [PROP:%d:%s]\n",
@@ -99,11 +97,6 @@ int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
return 0;
}

- if (property == dev_priv->broadcast_rgb_property) {
- intel_conn_state->broadcast_rgb = val;
- return 0;
- }
-
drm_dbg_atomic(&dev_priv->drm, "Unknown property [PROP:%d:%s]\n",
property->base.id, property->name);
return -EINVAL;
@@ -134,7 +127,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn,
* up in a modeset.
*/
if (new_conn_state->force_audio != old_conn_state->force_audio ||
- new_conn_state->broadcast_rgb != old_conn_state->broadcast_rgb ||
new_conn_state->base.colorspace != old_conn_state->base.colorspace ||
new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
new_conn_state->base.content_type != old_conn_state->base.content_type ||
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index 9bed1ccecea0..89f0edf19182 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -241,34 +241,6 @@ intel_attach_force_audio_property(struct drm_connector *connector)
drm_object_attach_property(&connector->base, prop, 0);
}

-static const struct drm_prop_enum_list broadcast_rgb_names[] = {
- { INTEL_BROADCAST_RGB_AUTO, "Automatic" },
- { INTEL_BROADCAST_RGB_FULL, "Full" },
- { INTEL_BROADCAST_RGB_LIMITED, "Limited 16:235" },
-};
-
-void
-intel_attach_broadcast_rgb_property(struct drm_connector *connector)
-{
- struct drm_device *dev = connector->dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct drm_property *prop;
-
- prop = dev_priv->broadcast_rgb_property;
- if (prop == NULL) {
- prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
- "Broadcast RGB",
- broadcast_rgb_names,
- ARRAY_SIZE(broadcast_rgb_names));
- if (prop == NULL)
- return;
-
- dev_priv->broadcast_rgb_property = prop;
- }
-
- drm_object_attach_property(&connector->base, prop, 0);
-}
-
void
intel_attach_aspect_ratio_property(struct drm_connector *connector)
{
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h
index 661a37a3c6d8..f3058a035476 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -28,7 +28,6 @@ int intel_connector_update_modes(struct drm_connector *connector,
struct edid *edid);
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
void intel_attach_force_audio_property(struct drm_connector *connector);
-void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
void intel_attach_aspect_ratio_property(struct drm_connector *connector);
void intel_attach_hdmi_colorspace_property(struct drm_connector *connector);
void intel_attach_dp_colorspace_property(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 15e91a99c8b9..fb091216df78 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -77,13 +77,6 @@ enum hdmi_force_audio {
HDMI_AUDIO_ON, /* force turn on HDMI audio */
};

-/* "Broadcast RGB" property */
-enum intel_broadcast_rgb {
- INTEL_BROADCAST_RGB_AUTO,
- INTEL_BROADCAST_RGB_FULL,
- INTEL_BROADCAST_RGB_LIMITED,
-};
-
struct intel_fb_view {
/*
* The remap information used in the remapped and rotated views to
@@ -552,7 +545,6 @@ struct intel_digital_connector_state {
struct drm_connector_state base;

enum hdmi_force_audio force_audio;
- int broadcast_rgb;
};

#define to_intel_digital_connector_state(x) container_of(x, struct intel_digital_connector_state, base)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 29bb181ec4be..e007f9ac0f40 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1417,8 +1417,6 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- const struct intel_digital_connector_state *intel_conn_state =
- to_intel_digital_connector_state(conn_state);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;

@@ -1432,7 +1430,7 @@ bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
return false;

- if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {
+ if (conn_state->preferred_color_range == DRM_MODE_COLOR_RANGE_UNSET) {
/*
* See:
* CEA-861-E - 5.1 Default Encoding Parameters
@@ -1442,8 +1440,7 @@ bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
drm_default_rgb_quant_range(adjusted_mode) ==
HDMI_QUANTIZATION_RANGE_LIMITED;
} else {
- return intel_conn_state->broadcast_rgb ==
- INTEL_BROADCAST_RGB_LIMITED;
+ return conn_state->preferred_color_range == DRM_MODE_COLOR_RANGE_LIMITED_16_235;
}
}

@@ -4690,7 +4687,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
if (!IS_G4X(dev_priv) && port != PORT_A)
intel_attach_force_audio_property(connector);

- intel_attach_broadcast_rgb_property(connector);
+ drm_connector_attach_preferred_color_range_property(connector);
drm_connector_attach_active_color_range_property(connector);
if (HAS_GMCH(dev_priv)) {
drm_connector_attach_max_bpc_property(connector, 6, 10);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 67f0fb649876..1a0684c0cb5d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -833,7 +833,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
goto err;

intel_attach_force_audio_property(connector);
- intel_attach_broadcast_rgb_property(connector);

if (DISPLAY_VER(dev_priv) <= 12) {
ret = intel_dp_hdcp_init(dig_port, intel_connector);
@@ -866,6 +865,11 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
if (connector->active_color_format_property)
drm_connector_attach_active_color_format_property(connector);

+ connector->preferred_color_range_property =
+ intel_dp->attached_connector->base.preferred_color_range_property;
+ if (connector->preferred_color_range_property)
+ drm_connector_attach_preferred_color_range_property(connector);
+
connector->active_color_range_property =
intel_dp->attached_connector->base.active_color_range_property;
if (connector->active_color_range_property)
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index a7b85cd13227..c05d164b9ca0 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2091,8 +2091,6 @@ static int intel_hdmi_compute_clock(struct intel_encoder *encoder,
bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- const struct intel_digital_connector_state *intel_conn_state =
- to_intel_digital_connector_state(conn_state);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;

@@ -2106,13 +2104,13 @@ bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
return false;

- if (intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {
+ if (conn_state->preferred_color_range == DRM_MODE_COLOR_RANGE_UNSET) {
/* See CEA-861-E - 5.1 Default Encoding Parameters */
return crtc_state->has_hdmi_sink &&
drm_default_rgb_quant_range(adjusted_mode) ==
HDMI_QUANTIZATION_RANGE_LIMITED;
} else {
- return intel_conn_state->broadcast_rgb == INTEL_BROADCAST_RGB_LIMITED;
+ return conn_state->preferred_color_range == DRM_MODE_COLOR_RANGE_LIMITED_16_235;
}
}

@@ -2509,7 +2507,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
struct drm_i915_private *dev_priv = to_i915(connector->dev);

intel_attach_force_audio_property(connector);
- intel_attach_broadcast_rgb_property(connector);
+ drm_connector_attach_preferred_color_range_property(connector);
drm_connector_attach_active_color_range_property(connector);
intel_attach_aspect_ratio_property(connector);

diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index e4f91d7a5c60..bf4ecd029533 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2722,7 +2722,7 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
{
intel_attach_force_audio_property(&connector->base.base);
if (intel_sdvo->colorimetry_cap & SDVO_COLORIMETRY_RGB220)
- intel_attach_broadcast_rgb_property(&connector->base.base);
+ drm_connector_attach_preferred_color_range_property(&connector->base.base);
intel_attach_aspect_ratio_property(&connector->base.base);
}

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 01e11fe38642..f5987e809b78 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -999,7 +999,6 @@ struct drm_i915_private {
struct intel_fbdev *fbdev;
struct work_struct fbdev_suspend_work;

- struct drm_property *broadcast_rgb_property;
struct drm_property *force_audio_property;

/* hda/i915 audio component */
--
2.25.1

2021-06-30 15:16:17

by Werner Sembach

[permalink] [raw]
Subject: [PATCH v5 13/17] drm/amd/display: Add handling for new "preferred color format" property

This commit implements the "preferred color format" drm property for the
AMD GPU driver.

Signed-off-by: Werner Sembach <[email protected]>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 +++++++++++++++----
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +++
2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index b4acedac1ac9..02a5809d4993 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5346,15 +5346,32 @@ static void fill_stream_properties_from_drm_display_mode(
timing_out->h_border_right = 0;
timing_out->v_border_top = 0;
timing_out->v_border_bottom = 0;
- /* TODO: un-hardcode */
- if (drm_mode_is_420_only(info, mode_in)
- || (drm_mode_is_420_also(info, mode_in) && aconnector->force_yuv420_output))
+
+ if (connector_state
+ && (connector_state->preferred_color_format == DRM_COLOR_FORMAT_YCRCB420
+ || aconnector->force_yuv420_output) && drm_mode_is_420(info, mode_in))
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
- && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ else if (connector_state
+ && connector_state->preferred_color_format == DRM_COLOR_FORMAT_YCRCB444
+ && connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
- else
+ else if (connector_state
+ && connector_state->preferred_color_format == DRM_COLOR_FORMAT_RGB444
+ && !drm_mode_is_420_only(info, mode_in))
timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
+ else
+ /*
+ * connector_state->preferred_color_format not possible
+ * || connector_state->preferred_color_format == 0 (auto)
+ * || connector_state->preferred_color_format == DRM_COLOR_FORMAT_YCRCB422
+ */
+ if (drm_mode_is_420_only(info, mode_in))
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+ else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
+ && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
+ else
+ timing_out->pixel_encoding = PIXEL_ENCODING_RGB;

timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
timing_out->display_color_depth = convert_color_depth_from_display_info(
@@ -7756,6 +7773,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
if (!aconnector->mst_port) {
drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);
+ drm_connector_attach_preferred_color_format_property(&aconnector->base);
drm_connector_attach_active_color_format_property(&aconnector->base);
drm_connector_attach_active_color_range_property(&aconnector->base);
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index b5d57bbbdd20..2563788ba95a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -413,6 +413,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
if (connector->active_bpc_property)
drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);

+ connector->preferred_color_format_property = master->base.preferred_color_format_property;
+ if (connector->preferred_color_format_property)
+ drm_connector_attach_preferred_color_format_property(&aconnector->base);
+
connector->active_color_format_property = master->base.active_color_format_property;
if (connector->active_color_format_property)
drm_connector_attach_active_color_format_property(&aconnector->base);
--
2.25.1

2021-07-14 18:22:17

by Werner Sembach

[permalink] [raw]
Subject: Re: [PATCH v5 17/17] drm/amd/display: Add handling for new "Broadcast RGB" property

Am 30.06.21 um 17:10 schrieb Werner Sembach:
> This commit implements the "Broadcast RGB" drm property for the AMD GPU
> driver.
>
> Signed-off-by: Werner Sembach <[email protected]>
> ---
> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++++++---
> .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ++++
> 2 files changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 02a5809d4993..80d5a11fb0c5 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -5247,7 +5247,8 @@ get_aspect_ratio(const struct drm_display_mode *mode_in)
> }
>
> static enum dc_color_space
> -get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
> +get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing,
> + enum drm_mode_color_range preferred_color_range)
> {
> enum dc_color_space color_space = COLOR_SPACE_SRGB;
>
> @@ -5278,7 +5279,10 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
> }
> break;
> case PIXEL_ENCODING_RGB:
> - color_space = COLOR_SPACE_SRGB;
> + if (preferred_color_range == DRM_MODE_COLOR_RANGE_LIMITED_16_235)
> + color_space = COLOR_SPACE_SRGB_LIMITED;
> + else
> + color_space = COLOR_SPACE_SRGB;
> break;

After some testing I found out, that what I did here, was useless.

amdgpu actually never sets the quantization_range range in the
hdmi_avi_infoframe and from that I guess any quantization range, besides
the default one, is not implemented in multiple places

Until limited RGB is properly implemented in amdgpu there kind of is no
purpose of generalizing the Broadcast RGB switch.

>
> default:
> @@ -5424,7 +5428,10 @@ static void fill_stream_properties_from_drm_display_mode(
>
> timing_out->aspect_ratio = get_aspect_ratio(mode_in);
>
> - stream->output_color_space = get_output_color_space(timing_out);
> + stream->output_color_space = get_output_color_space(timing_out,
> + connector_state ?
> + connector_state->preferred_color_range :
> + DRM_MODE_COLOR_RANGE_UNSET);
>
> stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
> stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
> @@ -7775,6 +7782,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
> drm_connector_attach_active_bpc_property(&aconnector->base, 8, 16);
> drm_connector_attach_preferred_color_format_property(&aconnector->base);
> drm_connector_attach_active_color_format_property(&aconnector->base);
> + drm_connector_attach_preferred_color_range_property(&aconnector->base);
> drm_connector_attach_active_color_range_property(&aconnector->base);
> }
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 2563788ba95a..80e1389fd0ec 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -421,6 +421,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
> if (connector->active_color_format_property)
> drm_connector_attach_active_color_format_property(&aconnector->base);
>
> + connector->preferred_color_range_property = master->base.preferred_color_range_property;
> + if (connector->preferred_color_range_property)
> + drm_connector_attach_preferred_color_range_property(&aconnector->base);
> +
> connector->active_color_range_property = master->base.active_color_range_property;
> if (connector->active_color_range_property)
> drm_connector_attach_active_color_range_property(&aconnector->base);