Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v11 10/22] drm/rockchip: Add YUV422 output mode constants for VOP2
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Andy Yan
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

The Rockchip display controller has a general YUV422 output mode, and
some SoC-specific connector-specific output modes for RK3576.

Add them, based on the values in downstream and the TRM (dsp_out_mode in
RK3576 TRM Part 2, register POST*_CTRL_POST_DSP_CTRL).

Reviewed-by: Andy Yan <andyshrk@163.com>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 2e86ad00979c..4705dc6b8bd7 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -30,10 +30,14 @@
 #define ROCKCHIP_OUT_MODE_P565		2
 #define ROCKCHIP_OUT_MODE_BT656		5
 #define ROCKCHIP_OUT_MODE_S888		8
+#define ROCKCHIP_OUT_MODE_YUV422	9
 #define ROCKCHIP_OUT_MODE_S888_DUMMY	12
 #define ROCKCHIP_OUT_MODE_YUV420	14
 /* for use special outface */
 #define ROCKCHIP_OUT_MODE_AAAA		15
+/* SoC specific output modes */
+#define ROCKCHIP_OUT_MODE_YUV422_RK3576_DP	12
+#define ROCKCHIP_OUT_MODE_YUV422_RK3576_HDMI	13
 
 /* output flags */
 #define ROCKCHIP_OUTPUT_DSI_DUAL	BIT(0)

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 09/22] drm/amdgpu: Implement "color format" DRM property
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Werner Sembach, Andri Yngvason, Marius Vlad
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

The "color format" DRM property allows userspace to explicitly pick a
color format to use. If an unsupported color format is requested,
userspace will be given an error instead of silently having its request
disobeyed.

The default case, which is AUTO, picks YCbCr 4:2:0 if it's a 4:2:0-only
mode, and RGB in all other cases.

Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Co-developed-by: Andri Yngvason <andri@yngvason.is>
Signed-off-by: Andri Yngvason <andri@yngvason.is>
Co-developed-by: Marius Vlad <marius.vlad@collabora.com>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  | 90 +++++++++++++++++++---
 .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c    |  9 +++
 2 files changed, 88 insertions(+), 11 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 86a64e98e8a1..5d3c6f3984ab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6695,11 +6695,14 @@ static void fill_stream_properties_from_drm_display_mode(
 	const struct dc_stream_state *old_stream,
 	int requested_bpc)
 {
+	bool is_dp_or_hdmi = dc_is_hdmi_signal(stream->signal) || dc_is_dp_signal(stream->signal);
 	struct dc_crtc_timing *timing_out = &stream->timing;
 	const struct drm_display_info *info = &connector->display_info;
 	struct amdgpu_dm_connector *aconnector = NULL;
 	struct hdmi_vendor_infoframe hv_frame;
 	struct hdmi_avi_infoframe avi_frame;
+	bool want_420;
+	bool want_422;
 	ssize_t err;
 
 	if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
@@ -6712,20 +6715,41 @@ 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) ||
-	    (aconnector && aconnector->force_yuv420_output &&
-	     drm_mode_is_420_also(info, mode_in)))
+
+	want_420 = (aconnector && aconnector->force_yuv420_output) ||
+		   (connector_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_YCBCR420);
+	want_422 = (aconnector && aconnector->force_yuv422_output) ||
+		   (connector_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_YCBCR422);
+
+	if (drm_mode_is_420_only(info, mode_in) &&
+	    (want_420 || connector_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_AUTO)) {
 		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
-	else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
-			&& aconnector
-			&& aconnector->force_yuv422_output)
+	} else if (drm_mode_is_420_also(info, mode_in) && want_420) {
+		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+	} else if ((info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422)) &&
+		   want_422 && is_dp_or_hdmi) {
 		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422;
-	else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
-			&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+	} else if (connector_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_YCBCR444 &&
+		   (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) &&
+		   is_dp_or_hdmi) {
 		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
-	else
+	} else if (connector_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_RGB444 ||
+		   connector_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_AUTO) {
 		timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
+	} else {
+		/*
+		 * If a format was explicitly requested but the requested format
+		 * can't be satisfied, set it to an invalid value so that an
+		 * error bubbles up to userspace. This way, userspace knows it
+		 * needs to make a better choice.
+		 */
+		if (connector_state->color_format != DRM_CONNECTOR_COLOR_FORMAT_AUTO)
+			timing_out->pixel_encoding = PIXEL_ENCODING_UNDEFINED;
+		else if (drm_mode_is_420_only(info, mode_in))
+			timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+		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(
@@ -8075,6 +8099,38 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc,
 	return dc_result;
 }
 
+static enum dc_status
+dm_validate_stream_color_format(const struct drm_connector_state *drm_state,
+				const struct dc_stream_state *stream)
+{
+	enum dc_pixel_encoding encoding;
+
+	if (!drm_state->color_format)
+		return DC_OK;
+
+	switch (drm_state->color_format) {
+	case DRM_CONNECTOR_COLOR_FORMAT_AUTO:
+	case DRM_CONNECTOR_COLOR_FORMAT_RGB444:
+		encoding = PIXEL_ENCODING_RGB;
+		break;
+	case DRM_CONNECTOR_COLOR_FORMAT_YCBCR444:
+		encoding = PIXEL_ENCODING_YCBCR444;
+		break;
+	case DRM_CONNECTOR_COLOR_FORMAT_YCBCR422:
+		encoding = PIXEL_ENCODING_YCBCR422;
+		break;
+	case DRM_CONNECTOR_COLOR_FORMAT_YCBCR420:
+		encoding = PIXEL_ENCODING_YCBCR420;
+		break;
+	default:
+		encoding = PIXEL_ENCODING_UNDEFINED;
+		break;
+	}
+
+	return encoding == stream->timing.pixel_encoding ?
+		DC_OK : DC_UNSUPPORTED_VALUE;
+}
+
 struct dc_stream_state *
 create_validate_stream_for_sink(struct drm_connector *connector,
 				const struct drm_display_mode *drm_mode,
@@ -8121,6 +8177,9 @@ create_validate_stream_for_sink(struct drm_connector *connector,
 		if (dc_result == DC_OK)
 			dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);
 
+		if (dc_result == DC_OK)
+			dc_result = dm_validate_stream_color_format(drm_state, stream);
+
 		if (dc_result != DC_OK) {
 			drm_dbg_kms(connector->dev, "Pruned mode %d x %d (clk %d) %s %s -- %s\n",
 				      drm_mode->hdisplay,
@@ -8950,6 +9009,12 @@ static const u32 supported_colorspaces =
 	BIT(DRM_MODE_COLORIMETRY_BT2020_RGB) |
 	BIT(DRM_MODE_COLORIMETRY_BT2020_YCC);
 
+static const u32 supported_colorformats =
+	BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
+
 void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
 				     struct amdgpu_dm_connector *aconnector,
 				     int connector_type,
@@ -9066,8 +9131,11 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
 	    connector_type == DRM_MODE_CONNECTOR_eDP) {
 		drm_connector_attach_hdr_output_metadata_property(&aconnector->base);
 
-		if (!aconnector->mst_root)
+		if (!aconnector->mst_root) {
 			drm_connector_attach_vrr_capable_property(&aconnector->base);
+			drm_connector_attach_color_format_property(&aconnector->base,
+								   supported_colorformats);
+		}
 
 		if (adev->dm.hdcp_workqueue)
 			drm_connector_attach_content_protection_property(&aconnector->base, true);
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 7be50e8c0636..9bced7257f8b 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
@@ -52,6 +52,12 @@
 
 #define PEAK_FACTOR_X1000 1006
 
+static const u32 supported_colorformats =
+	BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
+
 /*
  * This function handles both native AUX and I2C-Over-AUX transactions.
  */
@@ -679,6 +685,9 @@ 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);
 
+	drm_connector_attach_color_format_property(&aconnector->base,
+						   supported_colorformats);
+
 	connector->vrr_capable_property = master->base.vrr_capable_property;
 	if (connector->vrr_capable_property)
 		drm_connector_attach_vrr_capable_property(connector);

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 08/22] drm/i915: Implement the "color format" DRM property
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Werner Sembach, Andri Yngvason, Marius Vlad
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

This includes RGB, YUV420, YUV444 and Auto. Auto will pick RGB, unless
the mode being asked for is YUV420-only, in which case it picks YUV420.

Should the explicitly requested color format not be supported by the
sink, then an error is returned to userspace, so that it can make a
better choice.

Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Co-developed-by: Andri Yngvason <andri@yngvason.is>
Signed-off-by: Andri Yngvason <andri@yngvason.is>
Co-developed-by: Marius Vlad <marius.vlad@collabora.com>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/i915/display/intel_connector.c | 10 ++++
 drivers/gpu/drm/i915/display/intel_connector.h |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c        | 71 ++++++++++++++++++++-----
 drivers/gpu/drm/i915/display/intel_dp.h        |  4 ++
 drivers/gpu/drm/i915/display/intel_dp_mst.c    | 52 ++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_hdmi.c      | 72 ++++++++++++++++++++------
 6 files changed, 181 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index 7ef9338d67ab..d54ae1522b6f 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -38,6 +38,10 @@
 #include "intel_hdcp.h"
 #include "intel_panel.h"
 
+static const u32 supported_colorformats = BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+					  BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
+					  BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
+
 static void intel_connector_modeset_retry_work_fn(struct work_struct *work)
 {
 	struct intel_connector *connector = container_of(work, typeof(*connector),
@@ -321,6 +325,12 @@ intel_attach_dp_colorspace_property(struct drm_connector *connector)
 		drm_connector_attach_colorspace_property(connector);
 }
 
+void
+intel_attach_colorformat_property(struct drm_connector *connector)
+{
+	drm_connector_attach_color_format_property(connector, supported_colorformats);
+}
+
 void
 intel_attach_scaling_mode_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 0aa86626e646..fe6149d1d559 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -31,6 +31,7 @@ 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);
+void intel_attach_colorformat_property(struct drm_connector *connector);
 void intel_attach_scaling_mode_property(struct drm_connector *connector);
 void intel_connector_queue_modeset_retry_work(struct intel_connector *connector);
 void intel_connector_cancel_modeset_retry_work(struct intel_connector *connector);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 4955bd8b11d7..31f2bb92bba6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1178,7 +1178,7 @@ dfp_can_convert(struct intel_dp *intel_dp,
 	return false;
 }
 
-static enum intel_output_format
+enum intel_output_format
 intel_dp_output_format(struct intel_connector *connector,
 		       enum intel_output_format sink_format)
 {
@@ -3337,17 +3337,24 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
 	struct intel_connector *connector = intel_dp->attached_connector;
 	const struct drm_display_info *info = &connector->base.display_info;
 	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
-	bool ycbcr_420_only;
+	enum drm_connector_color_format actual_format;
 	int ret;
 
-	ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
+	if ((conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_YCBCR420 &&
+	     drm_mode_is_420(info, adjusted_mode)) ||
+	    (conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_AUTO &&
+	     drm_mode_is_420_only(info, adjusted_mode)))
+		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+	else if (conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_YCBCR444)
+		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR444;
+	else
+		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
 
-	if (ycbcr_420_only && !connector->base.ycbcr_420_allowed) {
+	if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
+	    !connector->base.ycbcr_420_allowed) {
 		drm_dbg_kms(display->drm,
-			    "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
-		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
-	} else {
-		crtc_state->sink_format = intel_dp_sink_format(connector, adjusted_mode);
+			"YCbCr 4:2:0 mode requested but unsupported by connector.\n");
+		return -EINVAL;
 	}
 
 	crtc_state->output_format = intel_dp_output_format(connector, crtc_state->sink_format);
@@ -3355,9 +3362,20 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
 	ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
 					   respect_downstream_limits);
 	if (ret) {
-		if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
-		    !connector->base.ycbcr_420_allowed ||
-		    !drm_mode_is_420_also(info, adjusted_mode))
+		/*
+		 * If no valid link config can be found due to bandwidth constraints,
+		 * degrade from RGB/YCbCr 4:4:4 to YCbCr 4:2:0 if permitted by
+		 * the source and sink.
+		 */
+		if (!connector->base.ycbcr_420_allowed)
+			return ret;
+		/* No point in trying YCbCr420 a second time. */
+		if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+			return ret;
+		if (!drm_mode_is_420(info, adjusted_mode))
+			return ret;
+		/* If a non-AUTO color format is chosen, don't fall back. */
+		if (conn_state->color_format)
 			return ret;
 
 		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
@@ -3365,9 +3383,36 @@ intel_dp_compute_output_format(struct intel_encoder *encoder,
 								   crtc_state->sink_format);
 		ret = intel_dp_compute_link_config(encoder, crtc_state, conn_state,
 						   respect_downstream_limits);
+		if (ret)
+			return ret;
 	}
 
-	return ret;
+	if (conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_AUTO)
+		return 0;
+
+	switch (crtc_state->sink_format) {
+	case INTEL_OUTPUT_FORMAT_RGB:
+		actual_format = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
+		break;
+	case INTEL_OUTPUT_FORMAT_YCBCR444:
+		actual_format = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
+		break;
+	case INTEL_OUTPUT_FORMAT_YCBCR420:
+		actual_format = DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
+		break;
+	default:
+		drm_dbg_kms(display->drm, "Intel format %d has no connector equivalent\n",
+			    crtc_state->sink_format);
+		return -EINVAL;
+	}
+
+	if (actual_format != conn_state->color_format) {
+		drm_dbg_kms(display->drm, "Requested connector color format %d, got %d\n",
+			    conn_state->color_format, actual_format);
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 void
@@ -6956,6 +7001,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *_connec
 		intel_attach_dp_colorspace_property(&connector->base);
 	}
 
+	intel_attach_colorformat_property(&connector->base);
+
 	if (intel_dp_has_gamut_metadata_dip(&dp_to_dig_port(intel_dp)->base))
 		drm_connector_attach_hdr_output_metadata_property(&connector->base);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 2849b9ecdc71..c42badf752e2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -204,6 +204,10 @@ bool intel_dp_compute_config_limits(struct intel_dp *intel_dp,
 void intel_dp_get_dsc_sink_cap(u8 dpcd_rev,
 			       const struct drm_dp_desc *desc, bool is_branch,
 			       struct intel_connector *connector);
+enum intel_output_format
+intel_dp_output_format(struct intel_connector *connector,
+		       enum intel_output_format sink_format);
+
 bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder);
 
 bool intel_dp_link_params_valid(struct intel_dp *intel_dp, int link_rate,
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 887b6de14e46..1b939c7adf9d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -705,10 +705,13 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 	struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state);
 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
 	struct intel_dp *intel_dp = to_primary_dp(encoder);
+	enum drm_connector_color_format actual_format;
 	struct intel_connector *connector =
 		to_intel_connector(conn_state->connector);
 	const struct drm_display_mode *adjusted_mode =
 		&pipe_config->hw.adjusted_mode;
+	const struct drm_display_info *info =
+		&connector->base.display_info;
 	int num_joined_pipes;
 	int ret = -EINVAL;
 
@@ -719,10 +722,53 @@ static int mst_stream_compute_config(struct intel_encoder *encoder,
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return -EINVAL;
 
-	pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
-	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
+	if ((conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_YCBCR420 &&
+	     drm_mode_is_420(info, adjusted_mode)) ||
+	    (conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_AUTO &&
+	     drm_mode_is_420_only(info, adjusted_mode))) {
+		pipe_config->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
+	} else if (conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_YCBCR444) {
+		pipe_config->sink_format = INTEL_OUTPUT_FORMAT_YCBCR444;
+	} else if (conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_AUTO ||
+		   conn_state->color_format == DRM_CONNECTOR_COLOR_FORMAT_RGB444) {
+		pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB;
+	} else {
+		drm_dbg_kms(display->drm, "Requested format %d unsupported.\n",
+			    conn_state->color_format);
+		return -EINVAL;
+	}
+
+	if (pipe_config->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
+	    !connector->base.ycbcr_420_allowed) {
+		drm_dbg_kms(display->drm,
+			    "YCbCr 4:2:0 mode requested but unsupported by connector.\n");
+		return -EINVAL;
+	}
+
+	pipe_config->output_format = intel_dp_output_format(connector, pipe_config->sink_format);
 	pipe_config->has_pch_encoder = false;
 
+	/* Validate that the right format was picked if explicitly requested */
+	if (conn_state->color_format != DRM_CONNECTOR_COLOR_FORMAT_AUTO) {
+		switch (pipe_config->output_format) {
+		case INTEL_OUTPUT_FORMAT_RGB:
+			actual_format = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
+			break;
+		case INTEL_OUTPUT_FORMAT_YCBCR444:
+			actual_format = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
+			break;
+		case INTEL_OUTPUT_FORMAT_YCBCR420:
+			actual_format = DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
+			break;
+		}
+
+		if (actual_format != conn_state->color_format) {
+			drm_dbg_kms(display->drm, "Requested connector color format %d, got %d\n",
+				    conn_state->color_format, actual_format);
+			return -EINVAL;
+		}
+	}
+
 	for_each_joiner_candidate(connector, adjusted_mode, num_joined_pipes) {
 		if (num_joined_pipes > 1)
 			pipe_config->joiner_pipes = GENMASK(crtc->pipe + num_joined_pipes - 1,
@@ -1693,6 +1739,8 @@ static int mst_topology_add_connector_properties(struct intel_dp *intel_dp,
 	if (connector->base.max_bpc_property)
 		drm_connector_attach_max_bpc_property(&connector->base, 6, 12);
 
+	intel_attach_colorformat_property(&connector->base);
+
 	return drm_connector_set_path_property(&connector->base, pathprop);
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 05e898d10a2b..6b685d9a458e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2270,33 +2270,73 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
 	struct intel_connector *connector = to_intel_connector(conn_state->connector);
 	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
 	const struct drm_display_info *info = &connector->base.display_info;
-	bool ycbcr_420_only = drm_mode_is_420_only(info, adjusted_mode);
+	enum drm_connector_color_format req_fmt = conn_state->color_format;
+	enum drm_connector_color_format actual_fmt;
 	int ret;
 
-	crtc_state->sink_format =
-		intel_hdmi_sink_format(crtc_state, connector, ycbcr_420_only);
-
-	if (ycbcr_420_only && crtc_state->sink_format != INTEL_OUTPUT_FORMAT_YCBCR420) {
-		drm_dbg_kms(display->drm,
-			    "YCbCr 4:2:0 mode but YCbCr 4:2:0 output not possible. Falling back to RGB.\n");
-		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;
-	}
+	if (!req_fmt)
+		crtc_state->sink_format =
+			intel_hdmi_sink_format(crtc_state, connector,
+					       drm_mode_is_420_only(info, adjusted_mode));
+	else if (req_fmt == DRM_CONNECTOR_COLOR_FORMAT_YCBCR444)
+		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR444;
+	else
+		crtc_state->sink_format =
+			intel_hdmi_sink_format(crtc_state, connector,
+					       req_fmt == DRM_CONNECTOR_COLOR_FORMAT_YCBCR420);
 
 	crtc_state->output_format = intel_hdmi_output_format(crtc_state);
 	ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
 	if (ret) {
-		if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
-		    !crtc_state->has_hdmi_sink ||
-		    !connector->base.ycbcr_420_allowed ||
-		    !drm_mode_is_420_also(info, adjusted_mode))
+		/*
+		 * If no valid link config can be found due to bandwidth constraints,
+		 * degrade from RGB/YCbCr 4:4:4 to YCbCr 4:2:0 if permitted by
+		 * the source and sink.
+		 */
+		if (!connector->base.ycbcr_420_allowed)
+			return ret;
+		/* No point in trying YCbCr420 a second time. */
+		if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+			return ret;
+		if (!drm_mode_is_420(info, adjusted_mode))
+			return ret;
+		/* If a non-AUTO color format is chosen, don't fall back. */
+		if (req_fmt)
 			return ret;
 
 		crtc_state->sink_format = INTEL_OUTPUT_FORMAT_YCBCR420;
 		crtc_state->output_format = intel_hdmi_output_format(crtc_state);
 		ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
+		if (ret)
+			return ret;
 	}
 
-	return ret;
+	if (req_fmt == DRM_CONNECTOR_COLOR_FORMAT_AUTO)
+		return 0;
+
+	switch (crtc_state->sink_format) {
+	case INTEL_OUTPUT_FORMAT_RGB:
+		actual_fmt = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
+		break;
+	case INTEL_OUTPUT_FORMAT_YCBCR444:
+		actual_fmt = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
+		break;
+	case INTEL_OUTPUT_FORMAT_YCBCR420:
+		actual_fmt = DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
+		break;
+	default:
+		drm_dbg_kms(display->drm, "Intel format %d has no connector equivalent\n",
+			    crtc_state->sink_format);
+		return -EINVAL;
+	}
+
+	if (req_fmt != actual_fmt) {
+		drm_dbg_kms(display->drm, "Requested connector color format %d, got %d\n",
+			    req_fmt, actual_fmt);
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static bool intel_hdmi_is_cloned(const struct intel_crtc_state *crtc_state)
@@ -2689,8 +2729,10 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *_
 	if (DISPLAY_VER(display) >= 10)
 		drm_connector_attach_hdr_output_metadata_property(&connector->base);
 
-	if (!HAS_GMCH(display))
+	if (!HAS_GMCH(display)) {
 		drm_connector_attach_max_bpc_property(&connector->base, 8, 12);
+		intel_attach_colorformat_property(&connector->base);
+	}
 }
 
 /*

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 06/22] drm/display: hdmi-state-helper: Act on color format DRM property
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Dmitry Baryshkov
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

With the introduction of the "color format" DRM property, which allows
userspace to request a specific color format, the HDMI state helper
should implement this.

Implement it by translating the requested drm_connector_color_format to
a drm_output_color_format enum value as per the logic HDMI should use
for this: Auto is translated to RGB, and a fallback to YUV420 is only
performed if the original color format was auto.

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c | 31 +++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index a0d88701d236..954f8b2973fc 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -670,8 +670,39 @@ hdmi_compute_config(const struct drm_connector *connector,
 	unsigned int max_bpc = clamp_t(unsigned int,
 				       conn_state->max_bpc,
 				       8, connector->max_bpc);
+	enum drm_output_color_format fmt;
 	int ret;
 
+	if (conn_state->color_format != DRM_CONNECTOR_COLOR_FORMAT_AUTO) {
+		switch (conn_state->color_format) {
+		case DRM_CONNECTOR_COLOR_FORMAT_AUTO:
+			drm_warn(connector->dev, "AUTO format in non-AUTO path.\n");
+			fallthrough;
+		case DRM_CONNECTOR_COLOR_FORMAT_RGB444:
+			fmt = DRM_OUTPUT_COLOR_FORMAT_RGB444;
+			break;
+		case DRM_CONNECTOR_COLOR_FORMAT_YCBCR444:
+			fmt = DRM_OUTPUT_COLOR_FORMAT_YCBCR444;
+			break;
+		case DRM_CONNECTOR_COLOR_FORMAT_YCBCR422:
+			fmt = DRM_OUTPUT_COLOR_FORMAT_YCBCR422;
+			break;
+		case DRM_CONNECTOR_COLOR_FORMAT_YCBCR420:
+			fmt = DRM_OUTPUT_COLOR_FORMAT_YCBCR420;
+			break;
+		default:
+			drm_dbg_kms(connector->dev, "HDMI does not support color format '%d'.\n",
+				conn_state->color_format);
+			return -EINVAL;
+		}
+
+		return hdmi_compute_format_bpc(connector, conn_state, mode, max_bpc, fmt);
+	}
+
+	/*
+	 * For %DRM_CONNECTOR_COLOR_FORMAT_AUTO, try RGB first, and fall back
+	 * to the less bandwidth-intensive YCBCR420 if RGB fails.
+	 */
 	ret = hdmi_compute_format_bpc(connector, conn_state, mode, max_bpc,
 				      DRM_OUTPUT_COLOR_FORMAT_RGB444);
 	if (ret) {

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 07/22] drm/display: hdmi-state-helper: Try subsampling in mode_valid
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Dmitry Baryshkov
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

drm_hdmi_connector_mode_valid assumes modes are only valid if they work
with RGB. The reality is more complex however: YCbCr 4:2:0
chroma-subsampled modes only require half the pixel clock that the same
mode would require in RGB.

This leads to drm_hdmi_connector_mode_valid rejecting perfectly valid
420-only or 420-also modes.

Fix this by checking whether the mode is 420-capable first. If so, then
proceed by checking it with DRM_OUTPUT_COLOR_FORMAT_YCBCR420 so long as
the connector has legalized 420, otherwise error out. If the mode is not
420-capable, check with RGB as was previously always the case.

Fixes: 47368ab437fd ("drm/display: hdmi: add generic mode_valid helper")
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 954f8b2973fc..5cc30da30989 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -942,8 +942,21 @@ drm_hdmi_connector_mode_valid(struct drm_connector *connector,
 			      const struct drm_display_mode *mode)
 {
 	unsigned long long clock;
+	enum drm_output_color_format fmt;
+
+	if (drm_mode_is_420_only(&connector->display_info, mode)) {
+		if (connector->ycbcr_420_allowed)
+			fmt = DRM_OUTPUT_COLOR_FORMAT_YCBCR420;
+		else
+			return MODE_NO_420;
+	} else if (drm_mode_is_420_also(&connector->display_info, mode) &&
+		   connector->ycbcr_420_allowed) {
+		fmt = DRM_OUTPUT_COLOR_FORMAT_YCBCR420;
+	} else {
+		fmt = DRM_OUTPUT_COLOR_FORMAT_RGB444;
+	}
 
-	clock = drm_hdmi_compute_mode_clock(mode, 8, DRM_OUTPUT_COLOR_FORMAT_RGB444);
+	clock = drm_hdmi_compute_mode_clock(mode, 8, fmt);
 	if (!clock)
 		return MODE_ERROR;
 

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 05/22] drm/atomic-helper: Add HDMI bridge output bus formats helper
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

The drm_bridge_funcs atomic_get_output_bus_fmts operation should be the
same for likely every HDMI connector bridge, unless such an HDMI
connector bridge has some special hardware restrictions that I cannot
envision yet.

To avoid code duplication and standardize on a set of media bus formats
that the HDMI output color formats translate to, add a common helper
function that implements this operation to the drm bridge helpers.

The function returns a list of output bus formats based on the HDMI
bridge's current output bits-per-component, and its bitmask of supported
color formats.

To guard against future expansion of DRM_OUTPUT_COLOR_FORMAT outgrowing
the hweight8 call, add a BUILD_BUG_ON statement where it's used that
checks for DRM_OUTPUT_COLOR_FORMAT_COUNT. The justification for not
using hweight32 in all cases is that not all ISAs have a popcount
instruction, and will benefit from a smaller/faster software
implementation that doesn't have to operate across all bits.

The justification for not defining an hweight_color depending on the
value of DRM_OUTPUT_COLOR_FORMAT_COUNT is that this count enum value is
only known at compile time, not at preprocessor time.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 81 +++++++++++++++++++++++++++++++++++++
 include/drm/drm_atomic_helper.h     |  7 ++++
 2 files changed, 88 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index b7753454b777..e8613e6df1f4 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -28,6 +28,7 @@
 #include <linux/export.h>
 #include <linux/dma-fence.h>
 #include <linux/ktime.h>
+#include <linux/media-bus-format.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -4095,3 +4096,83 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
 	return input_fmts;
 }
 EXPORT_SYMBOL(drm_atomic_helper_bridge_propagate_bus_fmt);
+
+/**
+ * drm_atomic_helper_bridge_get_hdmi_output_bus_fmts - helper implementing
+ *                                           atomic_get_output_bus_fmts for HDMI
+ * @bridge: pointer to &struct drm_bridge
+ * @bridge_state: pointer to the current bridge state
+ * @crtc_state: pointer to the current CRTC state
+ * @conn_state: pointer to the current connector state
+ * @num_output_fmts: pointer to where the number of entries in the returned array
+ *                   will be stored. Set to 0 if unsuccessful.
+ *
+ * Common implementation for the &drm_bridge_funcs.atomic_get_output_bus_fmts
+ * operation that's applicable to HDMI connectors.
+ *
+ * Returns: a newly allocated array of u32 values of length \*@num_output_fmts,
+ * representing all the MEDIA_BUS_FMTS\_ for the current connector state's
+ * chosen HDMI output bits per compoennt, or %NULL if it fails to allocate one.
+ */
+u32 *
+drm_atomic_helper_bridge_get_hdmi_output_bus_fmts(struct drm_bridge *bridge,
+					struct drm_bridge_state *bridge_state,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state,
+					unsigned int *num_output_fmts)
+{
+	unsigned int num_fmts = 0;
+	u32 *out_fmts;
+
+	/*
+	 * bridge->supported_formats is a bit field of BIT(enum drm_output_color_format)
+	 * values. The smallest hweight that is smaller than or equal to
+	 * %DRM_OUTPUT_COLOR_FORMAT_COUNT will do for counting set bits here.
+	 */
+	BUILD_BUG_ON(const_true(DRM_OUTPUT_COLOR_FORMAT_COUNT > 8));
+	out_fmts = kmalloc_array(hweight8(bridge->supported_formats),
+				 sizeof(u32), GFP_KERNEL);
+	if (!out_fmts) {
+		*num_output_fmts = 0;
+		return NULL;
+	}
+
+	switch (conn_state->hdmi.output_bpc) {
+	case 12:
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_RGB121212_1X36;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_YUV12_1X36;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYVY12_1X24;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYYVYY12_0_5X36;
+		break;
+	case 10:
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_RGB101010_1X30;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_YUV10_1X30;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYVY10_1X20;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYYVYY10_0_5X30;
+		break;
+	default:
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_RGB888_1X24;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_YUV8_1X24;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYVY8_1X16;
+		if (bridge->supported_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420))
+			out_fmts[num_fmts++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
+		break;
+	}
+
+	*num_output_fmts = num_fmts;
+
+	return out_fmts;
+}
+EXPORT_SYMBOL(drm_atomic_helper_bridge_get_hdmi_output_bus_fmts);
+
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index e154ee4f0696..7256eaca109b 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -295,4 +295,11 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
 					u32 output_fmt,
 					unsigned int *num_input_fmts);
 
+u32 *
+drm_atomic_helper_bridge_get_hdmi_output_bus_fmts(struct drm_bridge *bridge,
+					struct drm_bridge_state *bridge_state,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state,
+					unsigned int *num_output_fmts);
+
 #endif /* DRM_ATOMIC_HELPER_H_ */

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 03/22] drm: Add new general DRM property "color format"
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Werner Sembach, Andri Yngvason, Marius Vlad
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

Add a new general DRM property named "color format" which can be used by
userspace to request the display driver to output a particular color
format.

Possible options are:
    - auto (setup by default, driver internally picks the color format)
    - rgb
    - ycbcr444
    - ycbcr422
    - ycbcr420

Drivers should advertise from this list which formats they support.
Together with this list and EDID data from the sink we should be able
to relay a list of usable color formats to users to pick from.

Co-developed-by: Werner Sembach <wse@tuxedocomputers.com>
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Co-developed-by: Andri Yngvason <andri@yngvason.is>
Signed-off-by: Andri Yngvason <andri@yngvason.is>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/drm_atomic_helper.c |   5 ++
 drivers/gpu/drm/drm_atomic_uapi.c   |  11 ++++
 drivers/gpu/drm/drm_connector.c     | 108 ++++++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h         | 104 ++++++++++++++++++++++++++++++++++
 4 files changed, 228 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 26953ed6b53e..b7753454b777 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -737,6 +737,11 @@ 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->color_format !=
+			    new_connector_state->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 5bd5bf6661df..dee510c85e59 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -935,6 +935,15 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		state->privacy_screen_sw_state = val;
 	} else if (property == connector->broadcast_rgb_property) {
 		state->hdmi.broadcast_rgb = val;
+	} else if (property == connector->color_format_property) {
+		if (val > INT_MAX || !drm_connector_color_format_valid(val)) {
+			drm_dbg_atomic(connector->dev,
+				       "[CONNECTOR:%d:%s] unknown color format %llu\n",
+				       connector->base.id, connector->name, val);
+			return -EINVAL;
+		}
+
+		state->color_format = val;
 	} else if (connector->funcs->atomic_set_property) {
 		return connector->funcs->atomic_set_property(connector,
 				state, property, val);
@@ -1020,6 +1029,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->privacy_screen_sw_state;
 	} else if (property == connector->broadcast_rgb_property) {
 		*val = state->hdmi.broadcast_rgb;
+	} else if (property == connector->color_format_property) {
+		*val = state->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 47dc53c4a738..e848374dee0b 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1388,6 +1388,18 @@ static const u32 hdmi_colorspaces =
 	BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65) |
 	BIT(DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER);
 
+static const u32 hdmi_colorformats =
+	BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
+
+static const u32 dp_colorformats =
+	BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
+	BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420);
+
 /*
  * As per DP 1.4a spec, 2.2.5.7.5 VSC SDP Payload for Pixel Encoding/Colorimetry
  * Format Table 2-120
@@ -2940,6 +2952,102 @@ int drm_connector_attach_colorspace_property(struct drm_connector *connector)
 }
 EXPORT_SYMBOL(drm_connector_attach_colorspace_property);
 
+/**
+ * drm_connector_attach_color_format_property - create and attach color format property
+ * @connector: connector to create the color format property on
+ * @supported_color_formats: bitmask of bit-shifted &enum drm_output_color_format
+ *                           values the connector supports
+ *
+ * Called by a driver to create a color format property. The property is
+ * attached to the connector automatically on success.
+ *
+ * @supported_color_formats should only include color formats the connector
+ * type can actually support.
+ *
+ * Returns:
+ * 0 on success, negative errno on error
+ */
+int drm_connector_attach_color_format_property(struct drm_connector *connector,
+					       unsigned long supported_color_formats)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_prop_enum_list enum_list[DRM_CONNECTOR_COLOR_FORMAT_COUNT];
+	unsigned int i = 0;
+	unsigned long fmt;
+
+	if (connector->color_format_property)
+		return 0;
+
+	if (!supported_color_formats) {
+		drm_err(dev, "No supported color formats provided on [CONNECTOR:%d:%s]\n",
+			connector->base.id, connector->name);
+		return -EINVAL;
+	}
+
+	if (supported_color_formats & ~GENMASK(DRM_OUTPUT_COLOR_FORMAT_COUNT - 1, 0)) {
+		drm_err(dev, "Unknown color formats provided on [CONNECTOR:%d:%s]\n",
+			connector->base.id, connector->name);
+		return -EINVAL;
+	}
+
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_HDMIA:
+	case DRM_MODE_CONNECTOR_HDMIB:
+		if (supported_color_formats & ~hdmi_colorformats) {
+			drm_err(dev, "Color formats not allowed for HDMI on [CONNECTOR:%d:%s]\n",
+				connector->base.id, connector->name);
+			return -EINVAL;
+		}
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+	case DRM_MODE_CONNECTOR_eDP:
+		if (supported_color_formats & ~dp_colorformats) {
+			drm_err(dev, "Color formats not allowed for DP on [CONNECTOR:%d:%s]\n",
+				connector->base.id, connector->name);
+			return -EINVAL;
+		}
+		break;
+	}
+
+	enum_list[0].name = "AUTO";
+	enum_list[0].type = DRM_CONNECTOR_COLOR_FORMAT_AUTO;
+
+	for_each_set_bit(fmt, &supported_color_formats, DRM_OUTPUT_COLOR_FORMAT_COUNT) {
+		switch (fmt) {
+		case DRM_OUTPUT_COLOR_FORMAT_RGB444:
+			enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
+			break;
+		case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
+			enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
+			break;
+		case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
+			enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR422;
+			break;
+		case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
+			enum_list[++i].type = DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
+			break;
+		default:
+			drm_warn(dev, "Unknown supported format %ld on [CONNECTOR:%d:%s]\n",
+				 fmt, connector->base.id, connector->name);
+			continue;
+		}
+		enum_list[i].name = drm_hdmi_connector_get_output_format_name(fmt);
+	}
+
+	connector->color_format_property =
+		drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, "color format",
+					 enum_list, i + 1);
+
+	if (!connector->color_format_property)
+		return -ENOMEM;
+
+	drm_object_attach_property(&connector->base, connector->color_format_property,
+				   DRM_CONNECTOR_COLOR_FORMAT_AUTO);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_color_format_property);
+
 /**
  * drm_connector_atomic_hdr_metadata_equal - checks if the hdr metadata changed
  * @old_state: old connector state to compare
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index af8b92d2d5b7..bd549f912b76 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -571,14 +571,102 @@ enum drm_colorspace {
  *   YCbCr 4:2:2 output format (ie. with horizontal subsampling)
  * @DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
  *   YCbCr 4:2:0 output format (ie. with horizontal and vertical subsampling)
+ * @DRM_OUTPUT_COLOR_FORMAT_COUNT:
+ *   Number of valid output color format values in this enum
  */
 enum drm_output_color_format {
 	DRM_OUTPUT_COLOR_FORMAT_RGB444 = 0,
 	DRM_OUTPUT_COLOR_FORMAT_YCBCR444,
 	DRM_OUTPUT_COLOR_FORMAT_YCBCR422,
 	DRM_OUTPUT_COLOR_FORMAT_YCBCR420,
+	DRM_OUTPUT_COLOR_FORMAT_COUNT,
 };
 
+/**
+ * enum drm_connector_color_format - Connector Color Format Request
+ *
+ * This enum, unlike &enum drm_output_color_format, is used to specify requests
+ * for a specific color format on a connector through the DRM "color format"
+ * property. The difference is that it has an "AUTO" value to specify that
+ * no specific choice has been made.
+ */
+enum drm_connector_color_format {
+	/**
+	 * @DRM_CONNECTOR_COLOR_FORMAT_AUTO: The driver or display protocol
+	 * helpers should pick a suitable color format. All implementations of a
+	 * specific display protocol must behave the same way with "AUTO", but
+	 * different display protocols do not necessarily have the same "AUTO"
+	 * semantics.
+	 *
+	 * For HDMI, "AUTO" picks RGB, but falls back to YCbCr 4:2:0 if the
+	 * bandwidth required for full-scale RGB is not available, or the mode
+	 * is YCbCr 4:2:0-only, as long as the mode and output both support
+	 * YCbCr 4:2:0.
+	 *
+	 * For display protocols other than HDMI, the recursive bridge chain
+	 * format selection picks the first chain of bridge formats that works,
+	 * as has already been the case before the introduction of the "color
+	 * format" property. Non-HDMI bridges should therefore either sort their
+	 * bus output formats by preference, or agree on a unified auto format
+	 * selection logic that's implemented in a common state helper (like
+	 * how HDMI does it).
+	 */
+	DRM_CONNECTOR_COLOR_FORMAT_AUTO = 0,
+
+	/**
+	 * @DRM_CONNECTOR_COLOR_FORMAT_RGB444: RGB output format
+	 */
+	DRM_CONNECTOR_COLOR_FORMAT_RGB444,
+
+	/**
+	 * @DRM_CONNECTOR_COLOR_FORMAT_YCBCR444: YCbCr 4:4:4 output format (ie.
+	 * not subsampled)
+	 */
+	DRM_CONNECTOR_COLOR_FORMAT_YCBCR444,
+
+	/**
+	 * @DRM_CONNECTOR_COLOR_FORMAT_YCBCR422: YCbCr 4:2:2 output format (ie.
+	 * with horizontal subsampling)
+	 */
+	DRM_CONNECTOR_COLOR_FORMAT_YCBCR422,
+
+	/**
+	 * @DRM_CONNECTOR_COLOR_FORMAT_YCBCR420: YCbCr 4:2:0 output format (ie.
+	 * with horizontal and vertical subsampling)
+	 */
+	DRM_CONNECTOR_COLOR_FORMAT_YCBCR420,
+
+	/**
+	 * @DRM_CONNECTOR_COLOR_FORMAT_COUNT: Number of valid connector color
+	 * format values in this enum
+	 */
+	DRM_CONNECTOR_COLOR_FORMAT_COUNT,
+};
+
+/**
+ * drm_connector_color_format_valid - Validate drm_connector_color_format value
+ * @fmt: value to check against all values of &enum drm_connector_color_format
+ *
+ * Checks whether the passed in value of @fmt is one of the allowable values in
+ * &enum drm_connector_color_format.
+ *
+ * Returns: %true if it's a valid value for the enum, %false otherwise.
+ */
+static inline bool __pure
+drm_connector_color_format_valid(enum drm_connector_color_format fmt)
+{
+	switch (fmt) {
+	case DRM_CONNECTOR_COLOR_FORMAT_AUTO:
+	case DRM_CONNECTOR_COLOR_FORMAT_RGB444:
+	case DRM_CONNECTOR_COLOR_FORMAT_YCBCR444:
+	case DRM_CONNECTOR_COLOR_FORMAT_YCBCR422:
+	case DRM_CONNECTOR_COLOR_FORMAT_YCBCR420:
+		return true;
+	default:
+		return false;
+	}
+}
+
 const char *
 drm_hdmi_connector_get_output_format_name(enum drm_output_color_format fmt);
 
@@ -1129,6 +1217,13 @@ struct drm_connector_state {
 	 */
 	enum drm_colorspace colorspace;
 
+	/**
+	 * @color_format: State variable for Connector property to request
+	 * color format change on Sink. This is most commonly used to switch
+	 * between RGB to YUV and vice-versa.
+	 */
+	enum drm_connector_color_format color_format;
+
 	/**
 	 * @writeback_job: Writeback job for writeback connectors
 	 *
@@ -2127,6 +2222,12 @@ struct drm_connector {
 	 */
 	struct drm_property *colorspace_property;
 
+	/**
+	 * @color_format_property: Connector property to set the suitable
+	 * color format supported by the sink.
+	 */
+	struct drm_property *color_format_property;
+
 	/**
 	 * @path_blob_ptr:
 	 *
@@ -2610,6 +2711,9 @@ bool drm_connector_has_possible_encoder(struct drm_connector *connector,
 					struct drm_encoder *encoder);
 const char *drm_get_colorspace_name(enum drm_colorspace colorspace);
 
+int drm_connector_attach_color_format_property(struct drm_connector *connector,
+					       unsigned long supported_color_formats);
+
 /**
  * drm_for_each_connector_iter - connector_list iterator macro
  * @connector: &struct drm_connector pointer used as cursor

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 04/22] drm/bridge: Act on the DRM color format property
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

The new DRM color format property allows userspace to request a specific
color format on a connector. In turn, this fills the connector state's
color_format member to switch color formats.

Make drm_bridges consider the color_format set in the connector state
during the atomic bridge check. For bridges that represent HDMI bridges,
rely on whatever format the HDMI logic set. Reject any output bus
formats that do not correspond to the requested color format.

Non-HDMI last bridges with DRM_CONNECTOR_COLOR_FORMAT_AUTO set will end
up choosing the first output format that functions to make a whole
recursive bridge chain format selection succeed.

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/drm_bridge.c | 89 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 1c2903c6e44b..9ee3a8c25510 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -1150,6 +1150,47 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge,
 	return ret;
 }
 
+static bool __pure bus_format_is_color_fmt(u32 bus_fmt, enum drm_connector_color_format fmt)
+{
+	if (fmt == DRM_CONNECTOR_COLOR_FORMAT_AUTO)
+		return true;
+
+	switch (bus_fmt) {
+	case MEDIA_BUS_FMT_FIXED:
+		return true;
+	case MEDIA_BUS_FMT_RGB888_1X24:
+	case MEDIA_BUS_FMT_RGB101010_1X30:
+	case MEDIA_BUS_FMT_RGB121212_1X36:
+	case MEDIA_BUS_FMT_RGB161616_1X48:
+		return fmt == DRM_CONNECTOR_COLOR_FORMAT_RGB444;
+	case MEDIA_BUS_FMT_YUV8_1X24:
+	case MEDIA_BUS_FMT_YUV10_1X30:
+	case MEDIA_BUS_FMT_YUV12_1X36:
+	case MEDIA_BUS_FMT_YUV16_1X48:
+		return fmt == DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_VYUY8_1X16:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
+	case MEDIA_BUS_FMT_YVYU8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+	case MEDIA_BUS_FMT_YUYV10_1X20:
+	case MEDIA_BUS_FMT_VYUY10_1X20:
+	case MEDIA_BUS_FMT_YVYU10_1X20:
+	case MEDIA_BUS_FMT_UYVY12_1X24:
+	case MEDIA_BUS_FMT_VYUY12_1X24:
+	case MEDIA_BUS_FMT_YUYV12_1X24:
+	case MEDIA_BUS_FMT_YVYU12_1X24:
+		return fmt == DRM_CONNECTOR_COLOR_FORMAT_YCBCR422;
+	case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
+	case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
+	case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
+	case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
+		return fmt == DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
+	default:
+		return false;
+	}
+}
+
 /*
  * This function is called by &drm_atomic_bridge_chain_check() just before
  * calling &drm_bridge_funcs.atomic_check() on all elements of the chain.
@@ -1193,6 +1234,7 @@ drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
 	struct drm_encoder *encoder = bridge->encoder;
 	struct drm_bridge_state *last_bridge_state;
 	unsigned int i, num_out_bus_fmts = 0;
+	enum drm_connector_color_format fmt;
 	u32 *out_bus_fmts;
 	int ret = 0;
 
@@ -1234,13 +1276,58 @@ drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
 			out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
 	}
 
+	/*
+	 * On HDMI connectors, use the output format chosen by whatever does the
+	 * HDMI logic. For everyone else, just trust that the bridge out_bus_fmts
+	 * are sorted by preference for %DRM_CONNECTOR_COLOR_FORMAT_AUTO, as
+	 * bus_format_is_color_fmt() always returns true for AUTO.
+	 */
+	if (last_bridge->type == DRM_MODE_CONNECTOR_HDMIA) {
+		drm_dbg_kms(last_bridge->dev,
+			    "HDMI bridge requests format %s\n",
+			    drm_hdmi_connector_get_output_format_name(
+				    conn_state->hdmi.output_format));
+		switch (conn_state->hdmi.output_format) {
+		case DRM_OUTPUT_COLOR_FORMAT_RGB444:
+			fmt = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
+			break;
+		case DRM_OUTPUT_COLOR_FORMAT_YCBCR444:
+			fmt = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
+			break;
+		case DRM_OUTPUT_COLOR_FORMAT_YCBCR422:
+			fmt = DRM_CONNECTOR_COLOR_FORMAT_YCBCR422;
+			break;
+		case DRM_OUTPUT_COLOR_FORMAT_YCBCR420:
+			fmt = DRM_CONNECTOR_COLOR_FORMAT_YCBCR420;
+			break;
+		default:
+			ret = -EINVAL;
+			goto out_free_bus_fmts;
+		}
+	} else {
+		fmt = conn_state->color_format;
+		drm_dbg_kms(last_bridge->dev, "Non-HDMI bridge requests format %d\n", fmt);
+	}
+
 	for (i = 0; i < num_out_bus_fmts; i++) {
+		if (!bus_format_is_color_fmt(out_bus_fmts[i], fmt)) {
+			drm_dbg_kms(last_bridge->dev,
+				    "Skipping bus format 0x%04x as it doesn't match format %d\n",
+				    out_bus_fmts[i], fmt);
+			ret = -ENOTSUPP;
+			continue;
+		}
 		ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state,
 					       conn_state, out_bus_fmts[i]);
-		if (ret != -ENOTSUPP)
+		if (ret != -ENOTSUPP) {
+			drm_dbg_kms(last_bridge->dev,
+				    "Found bridge chain ending with bus format 0x%04x\n",
+				    out_bus_fmts[i]);
 			break;
+		}
 	}
 
+out_free_bus_fmts:
 	kfree(out_bus_fmts);
 
 	return ret;

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 00/22] Add new general DRM property "color format"
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Werner Sembach, Andri Yngvason,
	Cristian Ciocaltea, Marius Vlad, Dmitry Baryshkov, Andy Yan

Hello,

this is a follow-up to
https://lore.kernel.org/all/20250911130739.4936-1-marius.vlad@collabora.com/
which in of itself is a follow-up to
https://lore.kernel.org/dri-devel/20240115160554.720247-1-andri@yngvason.is/ where
a new DRM connector property has been added allowing users to
force a particular color format.

That in turn was actually also a follow-up from Werner Sembach's posted at
https://lore.kernel.org/dri-devel/20210630151018.330354-1-wse@tuxedocomputers.com/

As the number of cooks have reached critical mass, I'm hoping I'll be
the last person to touch this particular series.

We have an implementation in Weston at
https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/1825 that
adds support for this property. This patch series has been tested
against that MR on i915 (HDMI, DP), amdgpu (HDMI, DP) and on rockchip
(HDMI).

You can also manually test this with modetest like so, but beware that
this is a non-atomic invocation, so testing YUV420 like this will result
in weird outcomes if only some of the modes support YUV420:

  $ modetest -s 115:1920x1080-60@NV12 -w 115:'color format':4

where 115 is the connector ID and '4' is the enum value for a particular
color format.

General notes on the approach taken by me: instead of silently switching
to a different format than was explicitly requested, or even worse,
outputting something to the sink the sink doesn't support, bubble up an
error to userspace instead. "color format" is a "I want this" type
property, not a "force this" type property, i.e. the kernel will respect
the limits imposed by the hardware.

Things I've tested:
- HDMI (YCbCr 4:4:4 + YCbCr 4:2:2 (8-bit) + RGB + Auto) on RK3588
- HDMI (YCbCr 4:4:4 + YCbCr 4:2:2 (8-bit) + RGB + Auto) on RK3576
- HDMI + DP (YCbCr 4:4:4, YCbCr 4:2:0, RGB, Auto) on Intel N97 (i915)
  including DP-MST.
- HDMI (YCbCr 4:4:4, YCbCr 4:2:2, YCbCr 4:2:0, RGB, Auto) + DP (YCbCr
  4:4:4, RGB, Auto) as well as DP-MST on an AMD Radeon RX 550 (amdgpu).

Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
Changes in v11:
- amdgpu: fix property registration on DP-MST
- i915: fix property registration on DP-MST
- rebase on drm-tip, which includes Maxime's refactor series that was
  previously declared a dependency of this series
- Link to v10: https://lore.kernel.org/r/20260305-color-format-v10-0-a58c68a11868@collabora.com

Changes in v10:
- Make DRM_OUTPUT_COLOR_FORMAT_COUNT and
  DRM_CONNECTOR_COLOR_FORMAT_COUNT part of the enum definition (thanks
  to Maxime)
- Preemptively avoid the warning that would be generated by the
  enumification of DRM_OUTPUT_COLOR_FORMAT_COUNT by modifying the
  problematic switch statement in drm_hdmi_state_helper's
  sink_supports_format_bpc.
- drm/bridge: Change HDMI check from checking for the last bridge having
  a DRM_BRIDGE_OP_HDMI in ops to checking if last_bridge->type is HDMIA.
  This is not quite the suggestion Dmitry had, but according to the
  documentation of the drm_bridge.type member, and the
  display-connector.c code, it should be correct.
- Combine drm_mode_create_color_format_property and
  drm_connector_attach_color_format_property into one function named the
  latter. (thanks to Dmitry Baryshkov)
- Change author of 'drm: Add new general DRM property "color format"'
  to myself as it has by now changed quite a bit, and add Andri and
  Werner as Co-developed-by, as per Andri's suggestion.
- hdmi-state-helper: Rework hdmi_compute_config to make code flow more
  obvious, and drop Dmitry's R-b as a consequence (thanks to Maxime)
- Move dw-hdmi-qp's atomic_get_output_bus_fmts into
  drm_bridge_helper.c, along with kernel doc string (thanks to Dmitry)
- Future-proof the aforementioned get_output_bus_fmts use of hweight8 on
  the supported_formats bitmask with a BUILD_BUG_ON.
- Add a KUnit test for the HDMI output bus formats helper
- Link to v9: https://lore.kernel.org/r/20260227-color-format-v9-0-658c3b9db7ef@collabora.com

Changes in v9:
- Document what the "AUTO" behaviour is in the color format enum (thanks
  to Maxime)
- drm/bridge: dw-hdmi-qp: Fix a rebase oopsie that reintroduced some
  functions that were dropped. (thanks to Cristian)
- drm/bridge: Shuffle "1:1" in the bridge fmt selection docs to earlier
  in the sentence. (thanks to Randy Dunlap)
- i915: Check chosen output format against requested format for dp-mst
- All color format driver implementations: rebase and rework on top of
  Maxime's series
- As part of this rework, rename drm_color_format_enum to
  drm_connector_color_format
- drm kunit tests: rework for the new enums. Changes were trivial, so
  trailers were kept
- Link to v8: https://lore.kernel.org/r/20260216-color-format-v8-0-5722ce175dd5@collabora.com

Changes in v8:
- Drop "drm/rockchip: vop2: Fix YUV444 output", as the original problem
  could not be reproduced anymore, and the justification did not make
  sense.
- Remove the 12-bit format from "drm/rockchip: vop2: Recognise 10/12-bit
  YUV422 as YUV formats".
- Refactor to keep the original DRM_COLOR_FORMAT bitshifted defines
  as-is, but introduce a new drm_color_format_enum enum.
- Adjust conversion functions for the newly refactored enum, ensuring
  they only return valid enum values, and only convert in directions
  that open up no error value cans of worms.
- Rework the property uapi code for the newly refactored enum, since
  it no longer needs to do any bitshifting or ffs().
- Rework all the device drivers for the new enum.
- Rework all the tests for the refactored enum.
- Rework the hdmi state helper for the new enum, and also make it more
  explicit about the auto behaviour by not relying on a conversion
  function to map AUTO to RGB, but do this in the framework itself.
- rockchip dw_hdmi_qp: Fix the GRF value to check for color >= 0 instead
  of color > 0, as the latter broke switching back to RGB.
- Rebase onto a recent drm-tip. This necessitated blindly reworking some
  of the i915 dp-mst code.
- Drop the __maybe_unused edid test patch, as I could no longer
  reproduce the build warnings I added it for. I blame ghosts.
- drm_bridge tests: remove "destroyed" member from struct
  drm_bridge_chain_priv and all associated code, as it was not used in
  any test.
- Link to v7: https://lore.kernel.org/r/20260121-color-format-v7-0-ef790dae780c@collabora.com

Changes in v7:
- Fix drm_bridge kunit test build failure caused by rebasing across an
  API change.
- Make compilers shut up about unused EDID definitions in the test
  suites.
- Empty line checkpatch fixes that b4 prep --check didn't catch.
- Link to v6: https://lore.kernel.org/r/20260121-color-format-v6-0-7b81a771cd0b@collabora.com

Changes in v6:
- Checkpatch fixes
- Add drm_bridge.c kerneldoc fix patch to b4 deps so the kernel docs
  required for every contribution to the subsystem can be built
- dw-hdmi-qp core has gained the atomic_get_output_bus_fmts bridge func,
  which allows it to participate in the drm_bridge chain recursive format
  selection code properly.
- The Rockchip dw-hdmi-qp integration now no longer reimplements the
  color format logic (improperly), but reads the bus format of the first
  bridge as set by the recursive bridge format selection. If the input
  format is FIXED, it'll use the output format. Otherwise, the input
  format is used.
- In the synopsys drivers, YUV422 uses the same bus format as the non-qp
  hdmi encoder driver. Probably correcter this way. The Rockchip vop2
  is_yuv function has been extended to recognise this format as well.
- KUnit tests for drm_bridge chains are now included, which exercise the
  chain's recursive bus format selection.
- On HDMI connectors, the drm_bridge bus format selection will try to target
  the color format that the HDMI layer came up with. This means the AUTO
  logic is not duplicated for HDMI connectors.
- The enum conversion function commit gained a function for converting
  from hdmi_colorspace to drm_color_format, and its author changed as no
  original code remains anyway. Marius is still included as a
  Co-developer.
- Some tests for the HDMI state helper's mode_valid have been written.
  They are incomplete as we lack a test EDID for a 420-also mode that
  would violate the clock constraints on RGB. I hacked one together with
  a hex editor, but it reports a too high of a clock rate, and there's
  no EDID editor I could find which supports these extension blocks.
- The color_format KUnit tests have been more heavily parameterised, the
  auto case absorbed into other tests, and the comments around them
  rewritten.
- Add a few paragraphs of documentation that explain the bridge format
  selection, and how to make use of it in a display driver.
- Link to v5: https://lore.kernel.org/r/20251128-color-format-v5-0-63e82f1db1e1@collabora.com

Changes in v5:
- Rebase onto drm-tip
- Drop DRM_MODE_COLOR_FORMAT_* as an enum
- Unify DRM_COLOR_FORMAT_NONE and DRM_COLOR_FORMAT_AUTO, with AUTO being
  0. This makes conversion and general logic much easier.
- Adjust the drm_color_format enum to not needlessly renumber the
  existing defines, as it doesn't need to correspond to how HDMI numbers
  them.
- Make the DRM-to-HDMI conversion function static inline __pure, because
  the assembly it generates is tiny, and the function is pure.
- Don't accept nothing as the list of supported color formats for
  registration of the property.
- Drop the per-connector variants of the color format registration
  function, as it's not needed.
- drm_hdmi_state_helper: Fix mode_valid rejecting 420-only modes.
- drm_hdmi_state_helper: Only fall back to YUV420 with
  DRM_COLOR_FORMAT_AUTO.
- drm_hdmi_state_helper: Remove redundant AUTO->RGB condition, as the
  conversion already does this.
- Add KUnit tests for hdmi_compute_config.
- drm/bridge: Refactor bus_format_is_color_fmt and add a few more YUV422
  formats.
- Register the color format property in drmm_connector_hdmi_init based
  on the supported HDMI formats passed to it. This means rockchip
  dw_hdmi_qp no longer needs to register it.
- amdgpu: Simplify YUV420 logic
- amdgpu: Don't try to pick YUV444 on YUV420-only modes
- i915: Try to make behaviour more or less the same as that of the drm
  hdmi state helper.
- rockchip dw_hdmi_qp: Set supported HDMI formats
- rockchip dw_hdmi_qp: Set the right VO GRF values depending on color
  format.
- rockchip dw_hdmi_qp: Act on the color format property in this driver,
  rather than in VOP2, by setting the bus_format appropriately.
- rockchip VOP2: Can the BCSH-based implementation. BCSH isn't available
  on all video ports of the hardware, and the code was extremely
  suspect. Instead, plug into the existing YUV-to-RGB/RGB-to-YUV code,
  which can be done now that the HDMI driver sets the bus format.
- A whole bunch of Rockchip VOP2 fixes.
- Link to v4: https://lore.kernel.org/r/20251117-color-format-v4-0-0ded72bd1b00@collabora.com

Changes in v4:
- Rebase onto next-20251117
- Get rid of HDMI_COLORSPACE_AUTO
- Split hdmi_compute_config change into separate patch
- Add missing symbol export for color_format_to_hdmi_colorspace to fix
  builds in certain configurations
- Drop "drm: Pass supported color formats straight onto drm_bridge"
- Make dw-hdmi-qp set the platform data's supported color formats as
  the bridge's supported HDMI color formats
- drm_hdmi_state_helper: pass requested color format to
  hdmi_compute_format_bpc if set.
- drm_bridge: limit the bus formats to those explicitly requested with
  the color format property during the atomic bridge check call,
  specifically in drm_atomic_bridge_chain_select_bus_fmts.
- i915: Remove INTEL_OUTPUT_FORMAT_AUTO, as automatic format selection
  does not need to involve the hardware state
- i915: Deduplicate ntel_output_format_to_drm_color_format code by
  moving it as a static inline __pure function into a shared header
- i915: rework logic in HDMI, DP and DP-MST output config functions to
  remove redundant locals, simplify execution flow, and return an error
  to userspace if an explicit color_format request can't be satisfied.
- i915: assign myself as the author and make the others Co-developers,
  so that they don't get the blame for any of my bugs.
- amdgpu: refactor fill_stream_properties_from_drm_display_mode to
  improve readability and ensure that impossible color format requests
  get bubbled up to userspace as errors
- amdgpu: don't pick YUV444 over RGB.
- amdgpu: assign authorship to myself, with others as Co-developers, as
  logic was modified and the blame should fall on me
- dw_hdmi_qp-rockchip: set the supported color formats platform data
  member
- rockchip: remove drm property registration for rk3066_hdmi and
  inno_hdmi. None of the platforms that use these use vop2 as the
  video output processor.
- Link to v3: https://lore.kernel.org/all/20250911130739.4936-1-marius.vlad@collabora.com/

Changes in v3 by mvlad compared to Andri's v2 series:
- renamed the property to just 'color format'
- the property is added dynamically similar to the Colorspace property
- a key point from previous comments was that drivers should advertise
  the color formats they support and userspace would query EDID and
  perform an intersection from those color formats which users can
  further use. With this patch set each driver that adds this property
  has such list of hard-coded color formats, but fundamentally the idea
  is that driver can query the HW and do that on its own. The
  infrastructure is now in place to allow to do that
- by default the 'AUTO' color format is set. With this patch series that
  has been introduced as a fallback to RGB. Drivers could further
  customize this behavour and could perform additional checks on the sink
  to pick another suitable color format they'd like for AUTO
- drm_bridge bridge code has been improved to allow initialization with
  the same color formats list as the DRM connector property. Similarly, bpc
  pick-up now takes the color format into consideration when deciding
  which bpc to choose from
- The new DRM color format re-uses HDMI_COLORPSACE enum and provides an
  enum translations between the two to avoid touching all other drivers that
  use HDMI_COLORPSACE enum. I believe at this point that this allows the
  least amount of disruption and avoids a massive bike shedding around
  that part
- a rockchip implementation has been by my colleague Derek Foreman
- YUV444 color format has been added in i915
- address comment about "Remove unnecessary SIGNAL_TYPE_HDMI_TYPE_A
  check" where aconnector might be invalid
- Link to v2: https://lore.kernel.org/dri-devel/20240115160554.720247-1-andri@yngvason.is/

---
Nicolas Frattaroli (21):
      drm/display: hdmi-state-helper: Use default case for unsupported formats
      drm: Add new general DRM property "color format"
      drm/bridge: Act on the DRM color format property
      drm/atomic-helper: Add HDMI bridge output bus formats helper
      drm/display: hdmi-state-helper: Act on color format DRM property
      drm/display: hdmi-state-helper: Try subsampling in mode_valid
      drm/i915: Implement the "color format" DRM property
      drm/amdgpu: Implement "color format" DRM property
      drm/rockchip: Add YUV422 output mode constants for VOP2
      drm/rockchip: vop2: Add RK3576 to the RG swap special case
      drm/rockchip: vop2: Recognise 10-bit YUV422 as YUV format
      drm/rockchip: vop2: Set correct output format for RK3576 YUV422
      drm/bridge: dw-hdmi-qp: Use common HDMI output bus fmts helper
      drm/rockchip: dw_hdmi_qp: Implement "color format" DRM property
      drm/rockchip: dw_hdmi_qp: Set supported_formats platdata
      drm/connector: Register color format property on HDMI connectors
      drm/tests: hdmi: Add tests for the color_format property
      drm/tests: hdmi: Add tests for HDMI helper's mode_valid
      drm/tests: bridge: Add KUnit tests for bridge chain format selection
      drm/tests: bridge: Add test for HDMI output bus formats helper
      drm/bridge: Document bridge chain format selection

Werner Sembach (1):
      drm/amd/display: Remove unnecessary SIGNAL_TYPE_HDMI_TYPE_A check

 Documentation/gpu/drm-kms-helpers.rst              |   6 +
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |  91 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c    |   9 +
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c       |   1 +
 drivers/gpu/drm/display/drm_hdmi_state_helper.c    |  53 +-
 drivers/gpu/drm/drm_atomic_helper.c                |  86 ++
 drivers/gpu/drm/drm_atomic_uapi.c                  |  11 +
 drivers/gpu/drm/drm_bridge.c                       | 129 ++-
 drivers/gpu/drm/drm_connector.c                    | 112 +++
 drivers/gpu/drm/i915/display/intel_connector.c     |  10 +
 drivers/gpu/drm/i915/display/intel_connector.h     |   1 +
 drivers/gpu/drm/i915/display/intel_dp.c            |  71 +-
 drivers/gpu/drm/i915/display/intel_dp.h            |   4 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c        |  52 +-
 drivers/gpu/drm/i915/display/intel_hdmi.c          |  72 +-
 drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c     | 111 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h        |   4 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop2.c       |  21 +-
 drivers/gpu/drm/tests/drm_bridge_test.c            | 971 +++++++++++++++++++++
 drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 345 ++++++++
 include/drm/drm_atomic_helper.h                    |   7 +
 include/drm/drm_connector.h                        | 104 +++
 22 files changed, 2214 insertions(+), 57 deletions(-)
---
base-commit: 84e58d2aeaa1e5871d5f58a75283589b05415f7e
change-id: 20251028-color-format-49fd202b7183

Best regards,
--  
Nicolas Frattaroli <nicolas.frattaroli@collabora.com>



^ permalink raw reply

* [PATCH v11 02/22] drm/display: hdmi-state-helper: Use default case for unsupported formats
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Cristian Ciocaltea
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

Switch statements that do not handle all possible values of an
enumeration will generate a warning during compilation. In preparation
for adding a COUNT value to the end of the enum, this needs to be dealt
with.

Add a default case to sink_supports_format_bpc's DRM_OUTPUT_COLOR_FORMAT
switch statement, and move the log-and-return unknown pixel format
handling into it.

No functional change.

Reviewed-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/display/drm_hdmi_state_helper.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
index 9f3b696aceeb..a0d88701d236 100644
--- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c
+++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c
@@ -541,10 +541,11 @@ sink_supports_format_bpc(const struct drm_connector *connector,
 		drm_dbg_kms(dev, "YUV444 format supported in that configuration.\n");
 
 		return true;
-	}
 
-	drm_dbg_kms(dev, "Unsupported pixel format.\n");
-	return false;
+	default:
+		drm_dbg_kms(dev, "Unsupported pixel format.\n");
+		return false;
+	}
 }
 
 static enum drm_mode_status

-- 
2.53.0



^ permalink raw reply related

* [PATCH v11 01/22] drm/amd/display: Remove unnecessary SIGNAL_TYPE_HDMI_TYPE_A check
From: Nicolas Frattaroli @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
	Christian König, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
	Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
	Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
	Jonathan Corbet, Shuah Khan
  Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
	linux-rockchip, intel-gfx, intel-xe, linux-doc,
	Nicolas Frattaroli, Werner Sembach, Andri Yngvason
In-Reply-To: <20260324-color-format-v11-0-605559af4fb4@collabora.com>

From: Werner Sembach <wse@tuxedocomputers.com>

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 <wse@tuxedocomputers.com>
Signed-off-by: Andri Yngvason <andri@yngvason.is>
Tested-by: Andri Yngvason <andri@yngvason.is>
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++------
 1 file changed, 3 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 646fbdd5688b..86a64e98e8a1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -6713,12 +6713,9 @@ static void fill_stream_properties_from_drm_display_mode(
 	timing_out->v_border_top = 0;
 	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
-			&& aconnector->force_yuv420_output)
+	if (drm_mode_is_420_only(info, mode_in) ||
+	    (aconnector && aconnector->force_yuv420_output &&
+	     drm_mode_is_420_also(info, mode_in)))
 		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
 	else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
 			&& aconnector

-- 
2.53.0



^ permalink raw reply related

* Re: [PATCH] arm64: dts: imx8mp: Add DT overlays for DH i.MX8M Plus DHCOM SoM and boards
From: Frank Li @ 2026-03-24 16:01 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-arm-kernel, Christoph Niedermaier, Conor Dooley,
	Fabio Estevam, Krzysztof Kozlowski, Pengutronix Kernel Team,
	Rob Herring, Sascha Hauer, devicetree, imx, kernel, linux-kernel
In-Reply-To: <20260312232500.197096-1-marex@nabladev.com>

On Fri, Mar 13, 2026 at 12:24:04AM +0100, Marek Vasut wrote:
...

> diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-overlay-panel-ch101olhlwh.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-overlay-panel-ch101olhlwh.dtsi
> new file mode 100644
> index 0000000000000..534737363c9f0
> --- /dev/null
> +++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-overlay-panel-ch101olhlwh.dtsi
> @@ -0,0 +1,42 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (C) 2022 Marek Vasut

2026?

> + */
> +
> +&display_bl {
> +	pwms = <&pwm1 0 5000000 0>;
> +};
> +
> +&DH_OVERLAY_PANEL_I2C_BUS {

why upcase for label, generally it should be lower case

> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +
> +	touchscreen@41 {
> +		compatible = "ilitek,ili251x";
> +		pinctrl-0 = <DH_OVERLAY_PANEL_I2C_TOUCHSCREEN_PINCTRL>;
> +		pinctrl-names = "default";
> +		reg = <0x41>;

reg should second property,  please dt-format for new dts files.
check others

> +		interrupt-parent = <&DH_OVERLAY_PANEL_I2C_TOUCHSCREEN_IRQ_PARENT>;
...
> +
> +	ports {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		port@1 {
> +			reg = <1>;

need empty line between child node and property.

> +	#size-cells = <0>;
> +
> +	eeprom@56 {
> +		compatible = "atmel,24c04";
> +		reg = <0x56>;
> +		pagesize = <16>;
> +	};
> +};
> +
> +&ecspi2 {
> +	status = "okay";

status should be last property. I stop here because these
should be identify by tools/script

Frank



^ permalink raw reply

* Re: [PATCH v2] net: stmmac: skip VLAN restore when VLAN hash ops are missing
From: Russell King (Oracle) @ 2026-03-24 15:59 UTC (permalink / raw)
  To: Ovidiu Panait
  Cc: Paolo Abeni, Michal Piekos, Andrew Lunn, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Maxime Coquelin, Alexandre Torgue,
	netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <TY7P301MB1984855F48CACF4FE1B502A4D348A@TY7P301MB1984.JPNP301.PROD.OUTLOOK.COM>

On Tue, Mar 24, 2026 at 03:37:24PM +0000, Ovidiu Panait wrote:
> Hi,
> 
> My understanding is that the code in stmmac_vlan_update() that checks for
> !priv->dma_cap.vlhash is dead code, this condition cannot be true inside
> the ndo_vlan_rx_add_vid and ndo_vlan_rx_kill_vid callbacks because the
> callbacks are only called when priv->dma_cap.vlhash is true.
> 
> This seems to be a long-standing issue in the VLAN code.

If you're certain that there's dead code here, please consider
submitting patches to clean it up thereby making the code easier
to understand.

> I only have access to a board that uses the DWMAC4 IP, but I'll have
> a look in the documentation I have to check how to improve VLAN
> features handling. 

Definitely please do! Having more effort to clean up parts of stmmac
would be very welcome (but please bear in mind that I have had quite
a large patch set, but that's reducing now.)

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


^ permalink raw reply

* Re: [PATCH v3 01/27] media: dt-bindings: media: rockchip-rga: add rockchip,rk3588-rga3
From: Sven Püschel @ 2026-03-24 15:55 UTC (permalink / raw)
  To: Nicolas Dufresne, Jacob Chen, Ezequiel Garcia,
	Mauro Carvalho Chehab, Heiko Stuebner, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-media, linux-rockchip, linux-arm-kernel, linux-kernel,
	devicetree, kernel
In-Reply-To: <f5028eecdecedd9ea5e2a94d4fbf08b675e0842f.camel@ndufresne.ca>

Hi Nicolas,

On 3/24/26 1:55 PM, Nicolas Dufresne wrote:
> Le mardi 24 mars 2026 à 11:22 +0100, Sven Püschel a écrit :
>> Hi Nicolas,
>>
>> On 3/19/26 7:44 PM, Nicolas Dufresne wrote:
>>> Le mardi 27 janvier 2026 à 15:39 +0100, Sven Püschel a écrit :
>>>> Add a new compatible for the RGA3 (Raster Graphic Acceleration 3)
>>>> peripheral found on the RK3588 SoC. Also specify an iommu property,
>>>> as the RGA3 contains the generic rockchip iommu. The RGA2 also has
>>>> an iommu, but it's specific to the RGA2.
>>>>
>>>> The existing binding refers to the RGA2 peripheral. The RK3588
>>>> contains one RGA2 core and two RGA3 cores. Both feature a similar
>>>> functionality of scaling, cropping and rotating of up to two input
>>>> images into one output image. Key differences of the RGA3 are:
>>>>
>>>> - supports 10bit YUV output formats
>>>> - supports 8x8 tiles and FBCD as inputs and outputs
>>>> - supports BT2020 color space conversion
>>>> - max output resolution of (8192-64)x(8192-64)
>>>> - MMU can map up to 32G DDR RAM
>>>> - fully planar formats (3 planes) are not supported
>>>> - max scale up/down factor of 8 (RGA2 allows up to 16)
>>> Nothing import, but some more details on the differences can be found here.
>>>
>>> https://github.com/sravansenthiln1/rga-demos/tree/main
>>>
>>> They also removed from RGA3 the neural network quantization support
>>> (CLIP((source + offset) * scale). I suppose that integer tensors are fading
>>> away, and the accelerator does not do floats.
>> I've found a more complete list in the librga docs [1]. There are a
>> bunch of different RGA2 versions out there, the RGA2 from the rk3288
>> isn't the same as the RGA2-Enhanced contained in the rk3588/rk3399. Only
>> the latter one includes the NN features.
>>
>> [1]
>> https://github.com/airockchip/librga/blob/main/docs/Rockchip_Developer_Guide_RGA_EN.md#design-index
> That is a way better list, thanks.
>
>>> One things that isn't clear, even in the upstream RGA2 implementation is if the
>>> accelerator is cache coherent. When I study the BSP usage of RGA2, they
>>> integrate the RGA2 directly into GStreamer software video converter. They don't
>>> do anything to flush the cache, indicating that RGA2 is most probably cache
>>> coherent.
>>>
>>> Do you know if RGA3 has the same feature or if this is one of the difference ?
>>> Typically, RKIOMMU users are not, in RGA2, a completely custom mmu was used (and
>>> implemented inside the driver, as standalone).
>> I don't know. Looking at the vendor driver for the RGA3 it sets a cache
>> flush flag when the source is virtual memory (vs. dma-bufs and physical
>> memory). So I'd assume the RGA3 is not cache coherent. From a chat with
>> my colleagues, they found it a bit odd that the RGA2 should be cache
>> coherent, as it looks like a strange exception for a minor peripheral.
>>
>> Does this imply anything for my driver or is the whole cache coherency
>> handled by the underlying buffer handling or is this just for the
>> difference documentation?
>>
>> Btw. to which BSP do you refer?
> No implication, pretty much everything I looked in in rockchip-linux/kernel on
> github. Checking again, with a bit more knowledge then last time (but still very
> little), indeed, it seems that virtual address handling is similar to what VB2
> USERPTR code is doing. Basically, locks pages, and sync them in some ways.
>
> I was just trying to help gather what this driver is leaving behind.
>
>>>> Signed-off-by: Sven Püschel <s.pueschel@pengutronix.de>
>>>> ---
>>>>    .../devicetree/bindings/media/rockchip-rga.yaml       | 19 ++++++++++++++++++-
>>>>    1 file changed, 18 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/media/rockchip-rga.yaml b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
>>>> index ac17cda65191b..7735d8794c719 100644
>>>> --- a/Documentation/devicetree/bindings/media/rockchip-rga.yaml
>>>> +++ b/Documentation/devicetree/bindings/media/rockchip-rga.yaml
>>>> @@ -9,7 +9,9 @@ title: Rockchip 2D raster graphic acceleration controller (RGA)
>>>>    description:
>>>>      RGA is a standalone 2D raster graphic acceleration unit. It accelerates 2D
>>>>      graphics operations, such as point/line drawing, image scaling, rotation,
>>>> -  BitBLT, alpha blending and image blur/sharpness.
>>>> +  BitBLT, alpha blending and image blur/sharpness. There exist two variants
>>>> +  named RGA2 and RGA3 that differ in the supported inputs/output formats,
>>>> +  the attached IOMMU and the supported operations on the input.
> We should say, "this driver supports two variants", rather then there exist. Can
> we clarify that we don't support BitBLT, I think it is miss-leading. In general,
> I found most 2D m2m fooling people into thinking, great, that chip is supported
> until they find that v4l2 m2m can only handle a tiny subset.

Isn't talking about drivers/implementation at this point incorrect? In 
my understanding the dt docs just describe the Hardware (which can do 
more than the m2m API supports).

Btw.: given the multitude of different RGA versions (as I've only found 
out recently through the librga docs) I'll adjust the docs to avoid 
implying that there only exists a RGA2 and RGA3. Instead more like 
"there exist various RGA versions" and that some SoCs (aka. the rk3588) 
contain RGA cores with different version (making the rga3 distiction 
necessary, as rk3588-rga doesn't imply if it's the RGA2-Enhanced or the 
RGA3 core).

Sincerely
     Sven

>
> Nicolas
>
>>>>    
>>>>    maintainers:
>>>>      - Jacob Chen <jacob-chen@iotwrt.com>
>>>> @@ -20,6 +22,7 @@ properties:
>>>>        oneOf:
>>>>          - const: rockchip,rk3288-rga
>>>>          - const: rockchip,rk3399-rga
>>>> +      - const: rockchip,rk3588-rga3
>>>>          - items:
>>>>              - enum:
>>>>                  - rockchip,rk3228-rga
>>>> @@ -45,6 +48,9 @@ properties:
>>>>      power-domains:
>>>>        maxItems: 1
>>>>    
>>>> +  iommus:
>>>> +    maxItems: 1
>>>> +
>>>>      resets:
>>>>        maxItems: 3
>>>>    
>>>> @@ -54,6 +60,17 @@ properties:
>>>>          - const: axi
>>>>          - const: ahb
>>>>    
>>>> +allOf:
>>>> +- if:
>>>> +    properties:
>>>> +      compatible:
>>>> +        contains:
>>>> +          enum:
>>>> +            - rockchip,rk3588-rga3
>>>> +  then:
>>>> +    required:
>>>> +      - iommus
>>>> +
>>> You really can't use this chip with CMA ?
>> Ah, no. I'd rather thought that this just describes that there is a
>> dedicated iommu (which also has a appropriate dt node) for this
>> peripheral. I'll just drop this block (which also fixes the indentation
>> issue).
>>
>> Sincerely
>>       Sven
>>
>>> Nicolas
>>>
>>>>    required:
>>>>      - compatible
>>>>      - reg


^ permalink raw reply

* Re: [RFC PATCH] arm64: dts: imx8mp-edm-g-wb: Use 0 for reserved bit
From: Frank Li @ 2026-03-24 15:47 UTC (permalink / raw)
  To: Eduard Bostina
  Cc: daniel.baluta, simona.toaca, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, devicetree, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <20260310091054.2029912-1-egbostina@gmail.com>

On Tue, Mar 10, 2026 at 09:10:53AM +0000, Eduard Bostina wrote:

Remove RFC.

> The i.MX8MP Reference Manual documents bit 0 of the
> IOMUXC_SW_PAD_CTL_PAD registers as reserved. The hd3ss3220
> IRQ pin (SAI1_RXD6/GPIO4_IO08) currently uses pad config
> value 0x41 which sets this reserved bit.
>
> Change 0x41 to 0x40 to leave the reserved bit cleared, as
> recommended by the reference manual.

Any impact if set bit 0 to 1?

> This also allows for
> easier conversion to symbolic macros.

Can you send this patch also?

Frank
>
> Signed-off-by: Eduard Bostina <egbostina@gmail.com>
> ---
>  arch/arm64/boot/dts/freescale/imx8mp-edm-g-wb.dts | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8mp-edm-g-wb.dts b/arch/arm64/boot/dts/freescale/imx8mp-edm-g-wb.dts
> index 242fa930b..a78401d11 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mp-edm-g-wb.dts
> +++ b/arch/arm64/boot/dts/freescale/imx8mp-edm-g-wb.dts
> @@ -345,7 +345,7 @@ MX8MP_IOMUXC_SAI1_TXD5__GPIO4_IO17		0x16 /* DSI_VDDEN */
>
>  	pinctrl_hd3ss3220_irq: hd3ss3220-irqgrp {
>  		fsl,pins = <
> -			MX8MP_IOMUXC_SAI1_RXD6__GPIO4_IO08		0x41 /* GPIO_P253 */
> +			MX8MP_IOMUXC_SAI1_RXD6__GPIO4_IO08		0x40 /* GPIO_P253 */
>  		>;
>  	};
>
> --
> 2.43.0
>


^ permalink raw reply

* Re: [PATCH v13 3/6] iommu: Add verisilicon IOMMU driver
From: Will Deacon @ 2026-03-24 15:46 UTC (permalink / raw)
  To: Benjamin Gaignard
  Cc: joro, robin.murphy, robh, krzk+dt, conor+dt, heiko,
	nicolas.dufresne, p.zabel, mchehab, iommu, devicetree,
	linux-kernel, linux-arm-kernel, linux-rockchip, linux-media
In-Reply-To: <20260216095144.107356-4-benjamin.gaignard@collabora.com>

On Mon, Feb 16, 2026 at 10:51:35AM +0100, Benjamin Gaignard wrote:
> The Verisilicon IOMMU hardware block can be found in combination
> with Verisilicon hardware video codecs (encoders or decoders) on
> different SoCs.
> Enable it will allow us to use non contiguous memory allocators
> for Verisilicon video codecs.
> If both decoder and this iommu driver are compiled has modules
> there is undefined symboles issues so this iommu driver could
> only be compiled has built-in.
> 
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> ---
>  MAINTAINERS               |   8 +
>  drivers/iommu/Kconfig     |  11 +
>  drivers/iommu/Makefile    |   1 +
>  drivers/iommu/vsi-iommu.c | 794 ++++++++++++++++++++++++++++++++++++++
>  include/linux/vsi-iommu.h |  21 +
>  5 files changed, 835 insertions(+)
>  create mode 100644 drivers/iommu/vsi-iommu.c
>  create mode 100644 include/linux/vsi-iommu.h

[...]

> +static size_t vsi_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
> +			      size_t size, size_t count, struct iommu_iotlb_gather *gather)
> +{
> +	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
> +	dma_addr_t pte_dma, iova = (dma_addr_t)_iova;
> +	unsigned long flags;
> +	phys_addr_t pt_phys;
> +	u32 dte;
> +	u32 *pte_addr;
> +	size_t unmap_size = 0;
> +
> +	spin_lock_irqsave(&vsi_domain->lock, flags);
> +
> +	dte = vsi_domain->dt[vsi_iova_dte_index(iova)];
> +	/* Just return 0 if iova is unmapped */
> +	if (!vsi_dte_is_pt_valid(dte))
> +		goto unlock;
> +
> +	pt_phys = vsi_dte_pt_address(dte);
> +	pte_addr = (u32 *)phys_to_virt(pt_phys) + vsi_iova_pte_index(iova);
> +	pte_dma = pt_phys + vsi_iova_pte_index(iova) * sizeof(u32);
> +	unmap_size = vsi_iommu_unmap_iova(vsi_domain, pte_addr, pte_dma, size);
> +
> +unlock:
> +	spin_unlock_irqrestore(&vsi_domain->lock, flags);
> +
> +	return unmap_size;
> +}

I still think you need TLB invalidation here.

I looked at the downstream code that you linked to and it litters the
invalidation in the callers via mpp_iommu_flush_tlb(), which tend to
invalidate _before_ starting an operation. That's very likely buggy and
certainly not something we want upstream.

The unmap routine should do the invalidation so that, when it returns,
the pages really are unmapped from the device (assuming strict mode).

I know you said that you tried to add invalidation here and it "didn't
work", but that's not something I can really help you with.

Will


^ permalink raw reply

* [PATCH v3] tpm: i2c: atmel: fix block comment formatting
From: Ethan Luna @ 2026-03-24 15:39 UTC (permalink / raw)
  To: peterhuewe, jarkko
  Cc: jgg, nicolas.ferre, claudiu.beznea, linux-integrity,
	linux-arm-kernel, linux-kernel

Multiple block comments in tpm_i2c_atmel.c placed the closing '*/' on the
same line as the comment text. This violates the kernel's preferred
comment style, which requires the closing delimiter to appear on its
line.

Fix the formatting to improve readability and resolve checkpatch
warnings.

Signed-off-by: Ethan Luna <trunixcodes@zohomail.com>
---

V1 -> V2: Fixed block comment formatting consistently across all multi-line comments
V2 -> V3: Fixed trailing whitespaces consistently across all multi-line comments

v1: https://lore.kernel.org/all/20260322193112.27010-1-trunixcodes@zohomail.com/
v2: https://lore.kernel.org/all/20260323134200.7766-1-trunixcodes@zohomail.com/

 drivers/char/tpm/tpm_i2c_atmel.c | 34 +++++++++++++++++++++-----------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
index 4f229656a8e2..9fd73049821f 100644
--- a/drivers/char/tpm/tpm_i2c_atmel.c
+++ b/drivers/char/tpm/tpm_i2c_atmel.c
@@ -31,9 +31,11 @@
 
 struct priv_data {
 	size_t len;
-	/* This is the amount we read on the first try. 25 was chosen to fit a
+	/*
+	 * This is the amount we read on the first try. 25 was chosen to fit a
 	 * fair number of read responses in the buffer so a 2nd retry can be
-	 * avoided in small message cases. */
+	 * avoided in small message cases.
+	 */
 	u8 buffer[sizeof(struct tpm_header) + 25];
 };
 
@@ -58,7 +60,9 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
 	if (status < 0)
 		return status;
 
-	/* The upper layer does not support incomplete sends. */
+	/*
+	 * The upper layer does not support incomplete sends.
+	 */
 	if (status != len)
 		return -E2BIG;
 
@@ -76,9 +80,11 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 	if (priv->len == 0)
 		return -EIO;
 
-	/* Get the message size from the message header, if we didn't get the
+	/*
+	 * Get the message size from the message header, if we didn't get the
 	 * whole message in read_status then we need to re-read the
-	 * message. */
+	 * message.
+	 */
 	expected_len = be32_to_cpu(hdr->length);
 	if (expected_len > count)
 		return -ENOMEM;
@@ -111,15 +117,19 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip)
 	struct i2c_client *client = to_i2c_client(chip->dev.parent);
 	int rc;
 
-	/* The TPM fails the I2C read until it is ready, so we do the entire
+	/*
+	 * The TPM fails the I2C read until it is ready, so we do the entire
 	 * transfer here and buffer it locally. This way the common code can
-	 * properly handle the timeouts. */
+	 * properly handle the timeouts.
+	 */
 	priv->len = 0;
 	memset(priv->buffer, 0, sizeof(priv->buffer));
 
 
-	/* Once the TPM has completed the command the command remains readable
-	 * until another command is issued. */
+	/*
+	 * Once the TPM has completed the command the command remains readable
+	 * until another command is issued.
+	 */
 	rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer));
 	dev_dbg(&chip->dev,
 		"%s: sts=%d", __func__, rc);
@@ -172,9 +182,11 @@ static int i2c_atmel_probe(struct i2c_client *client)
 
 	dev_set_drvdata(&chip->dev, priv);
 
-	/* There is no known way to probe for this device, and all version
+	/*
+	 * There is no known way to probe for this device, and all version
 	 * information seems to be read via TPM commands. Thus we rely on the
-	 * TPM startup process in the common code to detect the device. */
+	 * TPM startup process in the common code to detect the device.
+	 */
 
 	return tpm_chip_register(chip);
 }
-- 
2.53.0



^ permalink raw reply related

* Re: [PATCH v2 11/12] ARM: dts: imx6q: Use undeprecated reset-gpios and drop reset-gpio-active-high
From: Frank Li @ 2026-03-24 15:43 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Christoph Niedermaier,
	Marek Vasut, Russell King, devicetree, imx, linux-arm-kernel,
	linux-kernel, kernel, linux
In-Reply-To: <9caf255d-834f-4407-afd8-7eae9c0f3cb6@oss.qualcomm.com>

On Thu, Mar 12, 2026 at 08:27:37PM +0100, Krzysztof Kozlowski wrote:
> On 12/03/2026 20:17, Krzysztof Kozlowski wrote:
> > Freescale i.MX6 PCIe host controller bindings, through referenced
> > snps,dw-pcie-common.yaml schema, already document "reset-gpios", just
> > like Linux kernel did for a long time.  Use the preferred form over
> > "reset-gpio" which is deprecated since commit 42694f9f6407
> > ("dt-bindings: PCI: add snps,dw-pcie.yaml") in 2021.
> >
> > Linux kernel already properly parses GPIO active level from phandle
> > arguments, thus we can also drop "reset-gpio-active-high".
> >
> > However this change will impact U-Boot, because it only parses
> > "reset-gpio" property for imx6q amd imx6sq.  Intention is to update
> > U-Boot to work with newer DTS, but any other out of tree user of this
> > DTS which did not implement undeprecated "reset-gpios" will be affected
> > as well.  There was plenty of time for these projects to switch to
> > undeprecated "reset-gpios", though.
> >
> > Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> >
> > ---
>
> U-Boot patch:
> lore.kernel.org/r/20260312192605.131132-1-krzysztof.kozlowski@oss.qualcomm.com

Krzysztof Kozlowski:

	Do I need wait for uboot apply patch before I pick up these?

Frank
>
> Best regards,
> Krzysztof


^ permalink raw reply

* Re: [PATCH v3 4/5] arm64: dts: freescale: add initial device tree for TQMa8x
From: Frank Li @ 2026-03-24 15:38 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Michael Turquette, Stephen Boyd, Peter Chen,
	Pawel Laszczak, Roger Quadros, Greg Kroah-Hartman, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Magnus Damm,
	Marek Vasut, devicetree, linux-kernel, linux-renesas-soc,
	linux-clk, linux-usb, imx, linux-arm-kernel, linux
In-Reply-To: <20260226153859.665901-5-alexander.stein@ew.tq-group.com>

On Thu, Feb 26, 2026 at 04:38:53PM +0100, Alexander Stein wrote:
> This adds support for TQMa8QM module on MBa8x board, based on i.MX8 SoC.
>
> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
> ---

I picked other patches in serial, I found missed this one when go through
patchworks.

> +
> +	fan0: pwm-fan {
> +		compatible = "pwm-fan";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_pwmfan>;
> +		fan-supply = <&reg_pwm_fan>;
> +		#cooling-cells = <2>;
> +		/* typical 25 kHz -> 40.000 nsec */
> +		pwms = <&lsio_pwm3 0 40000 PWM_POLARITY_INVERTED>;
> +		cooling-levels = <0 32 64 128 196 240>;
> +		pulses-per-revolution = <2>;
> +		interrupt-parent = <&lsio_gpio2>;
> +		interrupts = <20 IRQ_TYPE_EDGE_FALLING>;
> +		status = "disabled";
> +	};

Please order by node name.

Can you try run my tools dt-format for new dts file, which speed up the
flow.

Frank

> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_gpiokeys>;
> +		autorepeat;
> +
> +		switch-1 {
> +			label = "SWITCH_A";
> +			linux,code = <BTN_0>;
> +			gpios = <&lsio_gpio2 11 GPIO_ACTIVE_LOW>;
> +			wakeup-source;
> +		};
> +
> +		switch-2 {
> +			label = "SWITCH_B";
> +			linux,code = <BTN_1>;
> +			gpios = <&lsio_gpio1 0 GPIO_ACTIVE_LOW>;
> +			wakeup-source;
> +		};
> +	};
> +
> +	gpio-leds {
> +		compatible = "gpio-leds";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_gpioled>;
> +
> +		user-led0 {
> +			color = <LED_COLOR_ID_GREEN>;
> +			function = LED_FUNCTION_HEARTBEAT;
> +			gpios = <&lsio_gpio5 20 GPIO_ACTIVE_HIGH>;
> +			linux,default-trigger = "heartbeat";
> +		};
> +
> +		user-led1 {
> +			color = <LED_COLOR_ID_GREEN>;
> +			function = LED_FUNCTION_STATUS;
> +			gpios = <&lsio_gpio5 19 GPIO_ACTIVE_HIGH>;
> +			default-state = "on";
> +		};
> +	};
> +
> +	reg_mba8x_v3v3: regulator-mba8x-v3v3 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "V_3V3_MB";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		regulator-always-on;
> +	};
> +
> +	reg_mba8x_12v: regulator-mba8x-12v {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_reg_mba8x_12v>;
> +		regulator-name = "MBa8x-V12";
> +		regulator-min-microvolt = <12000000>;
> +		regulator-max-microvolt = <12000000>;
> +		enable-active-high;
> +		gpio = <&lsio_gpio1 2 GPIO_ACTIVE_HIGH>;
> +	};
> +
> +	reg_pwm_fan: regulator-pwm-fan {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_regpwmfan>;
> +		regulator-name = "FAN_PWR";
> +		regulator-min-microvolt = <12000000>;
> +		regulator-max-microvolt = <12000000>;
> +		gpio = <&lsio_gpio2 12 GPIO_ACTIVE_HIGH>;
> +		enable-active-high;
> +		vin-supply = <&reg_mba8x_12v>;
> +	};
> +
> +	reg_usb_phy: regulator-usb-phy {
> +		compatible = "regulator-fixed";
> +		regulator-max-microvolt = <3000000>;
> +		regulator-min-microvolt = <3000000>;
> +		regulator-name = "usb-phy-dummy";
> +	};
> +
> +	reg_v1v5_pcie: regulator-v1v5-pcie {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_reg_pcie_v1v5>;
> +		regulator-name = "V_1V5_MPCIE";
> +		regulator-min-microvolt = <1500000>;
> +		regulator-max-microvolt = <1500000>;
> +		vin-supply = <&reg_mba8x_v3v3>;
> +		enable-active-high;
> +		gpio = <&lsio_gpio0 31 GPIO_ACTIVE_HIGH>;
> +		regulator-always-on;
> +	};
> +
> +	reg_vref_v1v8: regulator-vref-v1v8 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "VREF_V1V8";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <1800000>;
> +		regulator-always-on;
> +	};
> +
> +	reg_v1v8: regulator-v1v8 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "MBa8x-V1V8";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <1800000>;
> +		regulator-always-on;
> +	};
> +
> +	reg_v3v3_pcie: regulator-v3v3-pcie {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_reg_pcie_v3v3>;
> +		regulator-name = "V_3V3_MPCIE";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		vin-supply = <&reg_mba8x_v3v3>;
> +		enable-active-high;
> +		gpio = <&lsio_gpio1 1 GPIO_ACTIVE_HIGH>;
> +		regulator-always-on;
> +	};
> +
> +	reg_v3v3_sd: regulator-v3v3-sd {
> +		compatible = "regulator-fixed";
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_reg_v3v3_sd>;
> +		regulator-name = "V3V3_SD";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		vin-supply = <&reg_mba8x_v3v3>;
> +		gpio = <&lsio_gpio4 7 GPIO_ACTIVE_HIGH>;
> +		enable-active-high;
> +		regulator-boot-on;
> +		off-on-delay-us = <200000>;
> +	};
> +
> +	reserved-memory {
> +		#address-cells = <2>;
> +		#size-cells = <2>;
> +		ranges;
> +
> +		decoder_boot: decoder-boot@84000000 {
> +			reg = <0 0x84000000 0 0x2000000>;
> +			no-map;
> +		};
> +
> +		encoder1_boot: encoder1-boot@86000000 {
> +			reg = <0 0x86000000 0 0x200000>;
> +			no-map;
> +		};
> +
> +		encoder2_boot: encoder2-boot@86200000 {
> +			reg = <0 0x86200000 0 0x200000>;
> +			no-map;
> +		};
> +
> +		decoder_rpc: decoder-rpc@92000000 {
> +			reg = <0 0x92000000 0 0x100000>;
> +			no-map;
> +		};
> +
> +		encoder1_rpc: encoder1-rpc@92100000 {
> +			reg = <0 0x92100000 0 0x700000>;
> +			no-map;
> +		};
> +
> +		encoder2_rpc: encoder1-rpc@92800000 {
> +			reg = <0 0x92800000 0 0x700000>;
> +			no-map;
> +		};
> +
> +		/*
> +		 * global autoconfigured region for contiguous allocations
> +		 * must not exceed memory size and region
> +		 */
> +		linux,cma {
> +			compatible = "shared-dma-pool";
> +			reusable;
> +			size = <0 0x3c000000>;
> +			alloc-ranges = <0 0x96000000 0 0x3c000000>;
> +			linux,cma-default;
> +		};
> +	};
> +
> +	sound {
> +		compatible = "fsl,imx-audio-tlv320aic32x4";
> +		model = "tqm-tlv320aic32";
> +		ssi-controller = <&sai1>;
> +		audio-codec = <&tlv320aic3x04>;
> +		audio-routing =
> +			"IN3_L", "Mic Jack",
> +			"Mic Jack", "Mic Bias",
> +			"IN1_L", "Line In Jack",
> +			"IN1_R", "Line In Jack",
> +			"Line Out Jack", "LOL",
> +			"Line Out Jack", "LOR";
> +	};
> +
> +	sound-hdmi {
> +		compatible = "fsl,imx-audio-hdmi";
> +		model = "imx-audio-dp";
> +		audio-cpu = <&sai5>;
> +		hdmi-out;
> +	};
> +
> +	thermal-zones {
> +		cpu0-thermal {
> +			trips {
> +				soc_active0_0: trip-active0 {
> +					temperature = <40000>;
> +					hysteresis = <5000>;
> +					type = "active";
> +				};
> +
> +				soc_active0_1: trip-active1 {
> +					temperature = <48000>;
> +					hysteresis = <3000>;
> +					type = "active";
> +				};
> +
> +				soc_active0_2: trip-active2 {
> +					temperature = <60000>;
> +					hysteresis = <10000>;
> +					type = "active";
> +				};
> +			};
> +
> +			cooling-maps {
> +				map1 {
> +					trip = <&soc_active0_0>;
> +					cooling-device = <&fan0 1 1>;
> +				};
> +
> +				map2 {
> +					trip = <&soc_active0_1>;
> +					cooling-device = <&fan0 2 2>;
> +				};
> +
> +				map3 {
> +					trip = <&soc_active0_2>;
> +					cooling-device = <&fan0 3 3>;
> +				};
> +			};
> +		};
> +
> +		cpu1-thermal {
> +			trips {
> +				soc_active1_0: trip-active0 {
> +					temperature = <40000>;
> +					hysteresis = <5000>;
> +					type = "active";
> +				};
> +
> +				soc_active1_1: trip-active1 {
> +					temperature = <48000>;
> +					hysteresis = <3000>;
> +					type = "active";
> +				};
> +
> +				soc_active1_2: trip-active2 {
> +					temperature = <60000>;
> +					hysteresis = <10000>;
> +					type = "active";
> +				};
> +			};
> +
> +			cooling-maps {
> +				map1 {
> +					trip = <&soc_active1_0>;
> +					cooling-device = <&fan0 1 1>;
> +				};
> +
> +				map2 {
> +					trip = <&soc_active1_1>;
> +					cooling-device = <&fan0 2 2>;
> +				};
> +
> +				map3 {
> +					trip = <&soc_active1_2>;
> +					cooling-device = <&fan0 3 3>;
> +				};
> +			};
> +		};
> +	};
> +};
> +
> +&fec1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_fec1>;
> +	phy-mode = "rgmii-id";
> +	phy-handle = <&ethphy0>;
> +	nvmem-cells = <&fec_mac0>;
> +	nvmem-cell-names = "mac-address";
> +	status = "okay";
> +
> +	mdio {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		ethphy0: ethernet-phy@0 {
> +			compatible = "ethernet-phy-ieee802.3-c22";
> +			reg = <0>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&pinctrl_ethphy0>;
> +			ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
> +			ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
> +			ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
> +			ti,dp83867-rxctrl-strap-quirk;
> +			ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
> +			reset-gpios = <&lsio_gpio2 6 GPIO_ACTIVE_LOW>;
> +			reset-assert-us = <500000>;
> +			reset-deassert-us = <50000>;
> +			enet-phy-lane-no-swap;
> +			interrupt-parent = <&lsio_gpio2>;
> +			interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
> +		};
> +	};
> +};
> +
> +&fec2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_fec2>;
> +	phy-mode = "rgmii-id";
> +	phy-handle = <&ethphy3>;
> +	nvmem-cells = <&fec_mac1>;
> +	nvmem-cell-names = "mac-address";
> +	status = "okay";
> +
> +	mdio {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		ethphy3: ethernet-phy@3 {
> +			compatible = "ethernet-phy-ieee802.3-c22";
> +			reg = <3>;
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&pinctrl_ethphy3>;
> +			ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
> +			ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
> +			ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
> +			ti,dp83867-rxctrl-strap-quirk;
> +			ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
> +			reset-gpios = <&lsio_gpio2 4 GPIO_ACTIVE_LOW>;
> +			reset-assert-us = <500000>;
> +			reset-deassert-us = <50000>;
> +			enet-phy-lane-no-swap;
> +		};
> +	};
> +};
> +
> +&flexcan1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_flexcan1>;
> +	status = "okay";
> +};
> +
> +&flexcan2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_flexcan2>;
> +	status = "okay";
> +};
> +
> +&hsio_phy {
> +	fsl,hsio-cfg = "pciea-pcieb-sata";
> +	fsl,refclk-pad-mode = "input";
> +	status = "okay";
> +};
> +
> +/* no refclock gating */
> +&hsio_refa_clk {
> +	compatible = "fixed-factor-clock";
> +	clocks = <&pcieclk 0>;
> +	clock-div = <1>;
> +	clock-mult = <1>;
> +	/delete-property/ enable-gpios;
> +};
> +
> +&hsio_refb_clk {
> +	compatible = "fixed-factor-clock";
> +	clocks = <&pcieclk 0>;
> +	clock-div = <1>;
> +	clock-mult = <1>;
> +	/delete-property/ enable-gpios;
> +};
> +
> +&i2c1 {
> +	tlv320aic3x04: audio-codec@18 {
> +		compatible = "ti,tlv320aic32x4";
> +		reg = <0x18>;
> +		clocks = <&mclkout0_lpcg IMX_LPCG_CLK_0>;
> +		clock-names = "mclk";
> +		assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
> +				<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
> +				<&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
> +				<&mclkout0_lpcg IMX_LPCG_CLK_0>;
> +		assigned-clock-rates = <786432000>, <49152000>, <12288000>, <12288000>;
> +		ldoin-supply = <&reg_mba8x_v3v3>;
> +		iov-supply = <&reg_v1v8>;
> +	};
> +
> +	sensor1: temperature-sensor@1c {
> +		compatible = "nxp,se97b", "jedec,jc-42.4-temp";
> +		reg = <0x1c>;
> +	};
> +
> +	eeprom2: eeprom@54 {
> +		compatible = "nxp,se97b", "atmel,24c02";
> +		reg = <0x54>;
> +		pagesize = <16>;
> +		vcc-supply = <&reg_mba8x_v3v3>;
> +	};
> +
> +	pcieclk: clock-generator@68 {
> +		compatible = "renesas,9fgv0441";
> +		reg = <0x68>;
> +		clocks = <&clk_xtal25>;
> +		#clock-cells = <1>;
> +	};
> +};
> +
> +&lpspi0 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_lpspi0 &pinctrl_lpspi0_cs>;
> +	cs-gpios = <&lsio_gpio3 5 GPIO_ACTIVE_LOW>, <&lsio_gpio3 6 GPIO_ACTIVE_LOW>;
> +	status = "okay";
> +};
> +
> +&lpspi1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_lpspi1 &pinctrl_lpspi1_cs>;
> +	cs-gpios = <&lsio_gpio3 24 GPIO_ACTIVE_LOW>, <&lsio_gpio3 25 GPIO_ACTIVE_LOW>;
> +	status = "okay";
> +};
> +
> +&lpspi2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_lpspi2 &pinctrl_lpspi2_cs>;
> +	cs-gpios = <&lsio_gpio3 10 GPIO_ACTIVE_LOW>, <&lsio_gpio3 11 GPIO_ACTIVE_LOW>;
> +	status = "okay";
> +};
> +
> +&lpuart0 { /* console */
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_lpuart0>;
> +	status = "okay";
> +};
> +
> +&lpuart1 { /* X62 pin header */
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_lpuart1>;
> +	status = "okay";
> +};
> +
> +&lpuart2 { /* mikroBUS */
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_lpuart2>;
> +	status = "okay";
> +};
> +
> +&lsio_gpio2 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_gpio2>;
> +	gpio-line-names = "", "", "", "",
> +			  "", "PCIE0_DISABLE#", "", "";
> +
> +	pcie0-wdisable1-hog {
> +		gpio-hog;
> +		gpios = <5 0>;
> +		output-high;
> +		line-name = "PCIE0_DISABLE#";
> +	};
> +
> +	pcie-clk-pd-hog {
> +		gpio-hog;
> +		gpios = <10 0>;
> +		output-high;
> +		line-name = "PCIE_CLK_PD#";
> +	};
> +};
> +
> +&lsio_pwm3 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_lsio_pwm3>;
> +	status = "okay";
> +};
> +
> +&pciea {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_pciea>;
> +	phys = <&hsio_phy 0 PHY_TYPE_PCIE 0>;
> +	phy-names = "pcie-phy";
> +	reset-gpio = <&lsio_gpio4 29 GPIO_ACTIVE_LOW>;
> +	status = "okay";
> +};
> +
> +&pcieb {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_pcieb>;
> +	phys = <&hsio_phy 1 PHY_TYPE_PCIE 1>;
> +	phy-names = "pcie-phy";
> +	reset-gpio = <&lsio_gpio5 0 GPIO_ACTIVE_LOW>;
> +	status = "okay";
> +};
> +
> +&sai1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_sai1>;
> +	assigned-clocks = <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_PLL>,
> +			  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_SLV_BUS>,
> +			  <&clk IMX_SC_R_AUDIO_PLL_0 IMX_SC_PM_CLK_MST_BUS>,
> +			  <&sai1_lpcg IMX_LPCG_CLK_0>;
> +	assigned-clock-rates = <786432000>, <49152000>, <12288000>, <49152000>;
> +	status = "okay";
> +};
> +
> +&sai5 {
> +	status = "okay";
> +};
> +
> +&sai5_lpcg {
> +	status = "okay";
> +};
> +
> +&sata {
> +	status = "okay";
> +};
> +
> +&usbphy1 {
> +	phy-3p0-supply = <&reg_usb_phy>;
> +	status = "okay";
> +};
> +
> +&usbotg1 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usbotg1>;
> +	srp-disable;
> +	hnp-disable;
> +	adp-disable;
> +	power-active-high;
> +	over-current-active-low;
> +	dr_mode = "otg";
> +	status = "okay";
> +};
> +
> +&usb3_phy {
> +	status = "okay";
> +};
> +
> +&usbotg3 {
> +	/* over-current disabled by default */
> +	status = "okay";
> +};
> +
> +&usbotg3_cdns3 {
> +	dr_mode = "host";
> +	#address-cells = <1>;
> +	#size-cells = <0>;
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_usbhub>;
> +	status = "okay";
> +
> +	hub_2_0: hub@1 {
> +		compatible = "usb451,8142";
> +		reg = <1>;
> +		peer-hub = <&hub_3_0>;
> +		reset-gpios = <&lsio_gpio2 7 GPIO_ACTIVE_LOW>;
> +		vdd-supply = <&reg_mba8x_v3v3>;
> +	};
> +
> +	hub_3_0: hub@2 {
> +		compatible = "usb451,8140";
> +		reg = <2>;
> +		peer-hub = <&hub_2_0>;
> +		reset-gpios = <&lsio_gpio2 7 GPIO_ACTIVE_LOW>;
> +		vdd-supply = <&reg_mba8x_v3v3>;
> +	};
> +};
> +
> +&usdhc2 {
> +	pinctrl-names = "default", "state_100mhz", "state_200mhz";
> +	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
> +	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
> +	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
> +	bus-width = <4>;
> +	cd-gpios = <&lsio_gpio5 22 GPIO_ACTIVE_LOW>;
> +	wp-gpios = <&lsio_gpio5 21 GPIO_ACTIVE_HIGH>;
> +	vmmc-supply = <&reg_v3v3_sd>;
> +	no-mmc;
> +	no-sdio;
> +	status = "okay";
> +};
> +
> +&iomuxc {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_gpio>;
> +
> +	pinctrl_adc0: adc0grp {
> +		fsl,pins = <IMX8QM_ADC_IN1_DMA_ADC0_IN1		0x02000060>,
> +			   <IMX8QM_ADC_IN2_DMA_ADC0_IN2		0x02000060>;
> +	};
> +
> +	pinctrl_ethphy0: ethphy0grp {
> +		fsl,pins = <IMX8QM_ESAI1_SCKR_LSIO_GPIO2_IO06	0x00000041>,
> +			   <IMX8QM_ESAI1_TX0_LSIO_GPIO2_IO08	0x00000021>;
> +	};
> +
> +	pinctrl_ethphy3: ethphy3grp {
> +		fsl,pins = <IMX8QM_ESAI1_FSR_LSIO_GPIO2_IO04	0x00000041>;
> +	};
> +
> +	pinctrl_fec1: fec1grp {
> +		fsl,pins = <IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB_PAD		0x000014a0>,
> +			   <IMX8QM_ENET0_MDC_CONN_ENET0_MDC			0x06000041>,
> +			   <IMX8QM_ENET0_MDIO_CONN_ENET0_MDIO			0x06000041>,
> +			   <IMX8QM_ENET0_RGMII_TX_CTL_CONN_ENET0_RGMII_TX_CTL	0x00000041>,
> +			   <IMX8QM_ENET0_RGMII_TXC_CONN_ENET0_RGMII_TXC		0x00000041>,
> +			   <IMX8QM_ENET0_RGMII_TXD0_CONN_ENET0_RGMII_TXD0	0x00000041>,
> +			   <IMX8QM_ENET0_RGMII_TXD1_CONN_ENET0_RGMII_TXD1	0x00000041>,
> +			   <IMX8QM_ENET0_RGMII_TXD2_CONN_ENET0_RGMII_TXD2	0x00000041>,
> +			   <IMX8QM_ENET0_RGMII_TXD3_CONN_ENET0_RGMII_TXD3	0x00000041>,
> +			   <IMX8QM_ENET0_RGMII_RXC_CONN_ENET0_RGMII_RXC		0x00000040>,
> +			   <IMX8QM_ENET0_RGMII_RX_CTL_CONN_ENET0_RGMII_RX_CTL	0x00000040>,
> +			   <IMX8QM_ENET0_RGMII_RXD0_CONN_ENET0_RGMII_RXD0	0x00000040>,
> +			   <IMX8QM_ENET0_RGMII_RXD1_CONN_ENET0_RGMII_RXD1	0x00000040>,
> +			   <IMX8QM_ENET0_RGMII_RXD2_CONN_ENET0_RGMII_RXD2	0x00000040>,
> +			   <IMX8QM_ENET0_RGMII_RXD3_CONN_ENET0_RGMII_RXD3	0x00000040>;
> +	};
> +
> +	pinctrl_fec2: fec2grp {
> +		fsl,pins = <IMX8QM_COMP_CTL_GPIO_1V8_3V3_ENET_ENETA_PAD		0x000014a0>,
> +			   <IMX8QM_ENET1_MDC_CONN_ENET1_MDC			0x06000041>,
> +			   <IMX8QM_ENET1_MDIO_CONN_ENET1_MDIO			0x06000041>,
> +			   <IMX8QM_ENET1_RGMII_TX_CTL_CONN_ENET1_RGMII_TX_CTL	0x00000041>,
> +			   <IMX8QM_ENET1_RGMII_TXC_CONN_ENET1_RGMII_TXC		0x00000041>,
> +			   <IMX8QM_ENET1_RGMII_TXD0_CONN_ENET1_RGMII_TXD0	0x00000041>,
> +			   <IMX8QM_ENET1_RGMII_TXD1_CONN_ENET1_RGMII_TXD1	0x00000041>,
> +			   <IMX8QM_ENET1_RGMII_TXD2_CONN_ENET1_RGMII_TXD2	0x00000041>,
> +			   <IMX8QM_ENET1_RGMII_TXD3_CONN_ENET1_RGMII_TXD3	0x00000041>,
> +			   <IMX8QM_ENET1_RGMII_RXC_CONN_ENET1_RGMII_RXC		0x00000040>,
> +			   <IMX8QM_ENET1_RGMII_RX_CTL_CONN_ENET1_RGMII_RX_CTL	0x00000040>,
> +			   <IMX8QM_ENET1_RGMII_RXD0_CONN_ENET1_RGMII_RXD0	0x00000040>,
> +			   <IMX8QM_ENET1_RGMII_RXD1_CONN_ENET1_RGMII_RXD1	0x00000040>,
> +			   <IMX8QM_ENET1_RGMII_RXD2_CONN_ENET1_RGMII_RXD2	0x00000040>,
> +			   <IMX8QM_ENET1_RGMII_RXD3_CONN_ENET1_RGMII_RXD3	0x00000040>;
> +	};
> +
> +	pinctrl_flexcan1: flexcan0grp {
> +		fsl,pins = <IMX8QM_FLEXCAN0_TX_DMA_FLEXCAN0_TX		0x00000021>,
> +			   <IMX8QM_FLEXCAN0_RX_DMA_FLEXCAN0_RX		0x00000021>;
> +	};
> +
> +	pinctrl_flexcan2: flexcan1grp {
> +		fsl,pins = <IMX8QM_FLEXCAN1_TX_DMA_FLEXCAN1_TX		0x00000021>,
> +			   <IMX8QM_FLEXCAN1_RX_DMA_FLEXCAN1_RX		0x00000021>;
> +	};
> +
> +	pinctrl_gpio: pingpiogrp {
> +		fsl,pins = /* GPIO0_05 on X62:26 */
> +			   <IMX8QM_SIM0_GPIO0_00_LSIO_GPIO0_IO05	0x00000021>,
> +			   /* GPIO1_14 on X64:21 */
> +			   <IMX8QM_LVDS1_I2C1_SCL_LSIO_GPIO1_IO14	0x00000021>,
> +			   /* GPIO1_15 on X64:23 */
> +			   <IMX8QM_LVDS1_I2C1_SDA_LSIO_GPIO1_IO15	0x00000021>,
> +			   /* GPIO2_17 on X63:37 */
> +			   <IMX8QM_SPI3_SCK_LSIO_GPIO2_IO17		0x00000021>,
> +			   /* GPIO2_21 on X63:39 */
> +			   <IMX8QM_SPI3_CS1_LSIO_GPIO2_IO21		0x00000021>,
> +			   /* GPIO4_12 on X61:24 */
> +			   <IMX8QM_USDHC2_CD_B_LSIO_GPIO4_IO12		0x00000021>,
> +			   /* GPIO4_11 on X61:26 */
> +			   <IMX8QM_USDHC2_WP_LSIO_GPIO4_IO11		0x00000021>,
> +			   /* GPIO4_10 on X61:28 */
> +			   <IMX8QM_USDHC2_VSELECT_LSIO_GPIO4_IO10	0x00000021>,
> +			   /* GPIO4_09 on X61:30 */
> +			   <IMX8QM_USDHC2_RESET_B_LSIO_GPIO4_IO09	0x00000021>,
> +			   /* GPIO5_23 on X62:24 */
> +			   <IMX8QM_USDHC1_STROBE_LSIO_GPIO5_IO23	0x00000021>,
> +			   /* GPIO5_24 on X61:15 */
> +			   <IMX8QM_USDHC2_CLK_LSIO_GPIO5_IO24		0x00000021>,
> +			   /* GPIO5_25 on X61:17 */
> +			   <IMX8QM_USDHC2_CMD_LSIO_GPIO5_IO25		0x00000021>,
> +			   /* GPIO5_26 on X61:19 */
> +			   <IMX8QM_USDHC2_DATA0_LSIO_GPIO5_IO26		0x00000021>,
> +			   /* GPIO5_27 on X61:21 */
> +			   <IMX8QM_USDHC2_DATA1_LSIO_GPIO5_IO27		0x00000021>,
> +			   /* GPIO5_28 on X61:23 */
> +			   <IMX8QM_USDHC2_DATA2_LSIO_GPIO5_IO28		0x00000021>,
> +			   /* GPIO5_29 on X61:25 */
> +			   <IMX8QM_USDHC2_DATA3_LSIO_GPIO5_IO29		0x00000021>;
> +	};
> +
> +	pinctrl_gpio2: gpio2grp {
> +		fsl,pins = <IMX8QM_ESAI1_FST_LSIO_GPIO2_IO05		0x00000021>,
> +			   <IMX8QM_ESAI1_TX2_RX3_LSIO_GPIO2_IO10	0x00000021>;
> +	};
> +
> +	pinctrl_gpiokeys: gpiokeysgrp {
> +		fsl,pins = <IMX8QM_ESAI1_TX3_RX2_LSIO_GPIO2_IO11	0x00000021>,
> +			   <IMX8QM_SCU_GPIO0_04_LSIO_GPIO1_IO00		0x00000021>;
> +	};
> +
> +	pinctrl_gpioled: gpioledgrp {
> +		fsl,pins = <IMX8QM_USDHC1_DATA4_LSIO_GPIO5_IO19		0x00000021>,
> +			   <IMX8QM_USDHC1_DATA5_LSIO_GPIO5_IO20		0x00000021>;
> +	};
> +
> +	pinctrl_lpspi0: lpspi0grp {
> +		fsl,pins = <IMX8QM_SPI0_SCK_DMA_SPI0_SCK		0x0600004d>,
> +			   <IMX8QM_SPI0_SDO_DMA_SPI0_SDO		0x0600004d>,
> +			   <IMX8QM_SPI0_SDI_DMA_SPI0_SDI		0x0600004d>;
> +	};
> +
> +	pinctrl_lpspi0_cs: lpspi0csgrp {
> +		fsl,pins = <IMX8QM_SPI0_CS0_LSIO_GPIO3_IO05		0x00000021>,
> +			   <IMX8QM_SPI0_CS1_LSIO_GPIO3_IO06		0x00000021>;
> +	};
> +
> +	pinctrl_lpspi1: lpspi1grp {
> +		fsl,pins = <IMX8QM_ADC_IN3_DMA_SPI1_SCK			0x0600004d>,
> +			   <IMX8QM_ADC_IN4_DMA_SPI1_SDO			0x0600004d>,
> +			   <IMX8QM_ADC_IN5_DMA_SPI1_SDI			0x0600004d>;
> +	};
> +
> +	pinctrl_lpspi1_cs: lpspi1csgrp {
> +		fsl,pins = <IMX8QM_ADC_IN6_LSIO_GPIO3_IO24		0x00000021>,
> +			   <IMX8QM_ADC_IN7_LSIO_GPIO3_IO25		0x00000021>;
> +	};
> +
> +	pinctrl_lpspi2: lpspi2grp {
> +		fsl,pins = <IMX8QM_SPI2_SCK_DMA_SPI2_SCK		0x0600004d>,
> +			   <IMX8QM_SPI2_SDO_DMA_SPI2_SDO		0x0600004d>,
> +			   <IMX8QM_SPI2_SDI_DMA_SPI2_SDI		0x0600004d>;
> +	};
> +
> +	pinctrl_lpspi2_cs: lpspi2sgrp {
> +		fsl,pins = <IMX8QM_SPI2_CS0_LSIO_GPIO3_IO10		0x00000021>,
> +			   <IMX8QM_SPI2_CS1_LSIO_GPIO3_IO11		0x00000021>;
> +	};
> +
> +	pinctrl_lpuart0: lpuart0grp {
> +		fsl,pins = <IMX8QM_UART0_RX_DMA_UART0_RX		0x06000021>,
> +			   <IMX8QM_UART0_TX_DMA_UART0_TX		0x06000021>,
> +			   <IMX8QM_UART0_CTS_B_DMA_UART0_CTS_B		0x00000021>,
> +			   <IMX8QM_UART0_RTS_B_DMA_UART0_RTS_B		0x00000021>;
> +	};
> +
> +	pinctrl_lpuart1: lpuart1grp {
> +		fsl,pins = <IMX8QM_UART1_RX_DMA_UART1_RX		0x06000021>,
> +			   <IMX8QM_UART1_TX_DMA_UART1_TX		0x06000021>,
> +			   <IMX8QM_UART1_CTS_B_DMA_UART1_CTS_B		0x00000021>,
> +			   <IMX8QM_UART1_RTS_B_DMA_UART1_RTS_B		0x00000021>;
> +	};
> +
> +	pinctrl_lpuart2: lpuart2grp {
> +		fsl,pins = <IMX8QM_LVDS0_I2C1_SDA_DMA_UART2_RX		0x06000021>,
> +			   <IMX8QM_LVDS0_I2C1_SCL_DMA_UART2_TX		0x06000021>;
> +	};
> +
> +	pinctrl_lsio_pwm3: lsiopwm3grp {
> +		fsl,pins = <IMX8QM_GPT0_COMPARE_LSIO_PWM3_OUT		0x00000021>;
> +	};
> +
> +	pinctrl_pciea: pcieagrp {
> +		fsl,pins = <IMX8QM_PCIE_CTRL0_PERST_B_LSIO_GPIO4_IO29		0x06000021>,
> +			   <IMX8QM_PCIE_CTRL0_CLKREQ_B_HSIO_PCIE0_CLKREQ_B	0x06000021>,
> +			   <IMX8QM_PCIE_CTRL0_WAKE_B_LSIO_GPIO4_IO28		0x04000021>;
> +	};
> +
> +	pinctrl_pcieb: pciebgrp {
> +		fsl,pins = <IMX8QM_PCIE_CTRL1_PERST_B_LSIO_GPIO5_IO00		0x06000021>,
> +			   <IMX8QM_PCIE_CTRL1_CLKREQ_B_HSIO_PCIE1_CLKREQ_B	0x06000021>,
> +			   <IMX8QM_PCIE_CTRL1_WAKE_B_LSIO_GPIO4_IO31		0x04000021>;
> +	};
> +
> +	pinctrl_pwmfan: pwmfangrp {
> +		fsl,pins = <IMX8QM_SPI3_CS0_LSIO_GPIO2_IO20		0x30>;
> +	};
> +
> +	pinctrl_reg_mba8x_12v: mba12vgrp {
> +		fsl,pins = <IMX8QM_SCU_GPIO0_06_LSIO_GPIO1_IO02		0x00000021>;
> +	};
> +
> +	pinctrl_reg_pcie_v1v5: regpcie1v5grp {
> +		fsl,pins = <IMX8QM_SCU_GPIO0_03_LSIO_GPIO0_IO31		0x00000021>;
> +	};
> +
> +	pinctrl_reg_pcie_v3v3: regpcie3v3grp {
> +		fsl,pins = <IMX8QM_SCU_GPIO0_05_LSIO_GPIO1_IO01		0x00000021>;
> +	};
> +
> +	pinctrl_regpwmfan: regpwmfangrp {
> +		fsl,pins = <IMX8QM_ESAI1_TX4_RX1_LSIO_GPIO2_IO12	0x00000021>;
> +	};
> +
> +	pinctrl_reg_v3v3_sd: reg3v3sdgrp {
> +		fsl,pins = <IMX8QM_USDHC1_RESET_B_LSIO_GPIO4_IO07	0x00000021>;
> +	};
> +
> +	pinctrl_sai1: sai1grp {
> +		fsl,pins = <IMX8QM_SAI1_RXD_AUD_SAI1_RXD		0x06000041>,
> +			   <IMX8QM_SAI1_RXC_AUD_SAI1_RXC		0x06000041>,
> +			   <IMX8QM_SAI1_RXFS_AUD_SAI1_RXFS		0x06000041>,
> +			   <IMX8QM_SAI1_TXD_AUD_SAI1_TXD		0x06000061>,
> +			   <IMX8QM_SAI1_TXC_AUD_SAI1_TXC		0x06000041>,
> +			   <IMX8QM_MCLK_OUT0_AUD_ACM_MCLK_OUT0		0x0600004d>;
> +	};
> +
> +	pinctrl_usbotg1: usbotg1grp {
> +		fsl,pins = <IMX8QM_USB_SS3_TC2_CONN_USB_OTG1_OC		0x00000021>,
> +			   <IMX8QM_USB_SS3_TC0_CONN_USB_OTG1_PWR	0x00000021>;
> +	};
> +
> +	pinctrl_usbhub: usbhubgrp {
> +		fsl,pins = <IMX8QM_ESAI1_SCKT_LSIO_GPIO2_IO07		0x00000021>;
> +	};
> +
> +	pinctrl_usdhc2_gpio: usdhc2-gpiogrp {
> +		fsl,pins = <IMX8QM_USDHC1_DATA6_LSIO_GPIO5_IO21		0x00000021>,
> +			   <IMX8QM_USDHC1_DATA7_LSIO_GPIO5_IO22		0x00000021>;
> +	};
> +
> +	pinctrl_usdhc2: usdhc2grp {
> +		fsl,pins = <IMX8QM_USDHC1_CLK_CONN_USDHC1_CLK		0x06000041>,
> +			   <IMX8QM_USDHC1_CMD_CONN_USDHC1_CMD		0x00000021>,
> +			   <IMX8QM_USDHC1_DATA0_CONN_USDHC1_DATA0	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA1_CONN_USDHC1_DATA1	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA2_CONN_USDHC1_DATA2	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA3_CONN_USDHC1_DATA3	0x00000021>,
> +			   <IMX8QM_USDHC1_VSELECT_CONN_USDHC1_VSELECT	0x00000021>;
> +	};
> +
> +	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
> +		fsl,pins = <IMX8QM_USDHC1_CLK_CONN_USDHC1_CLK		0x06000041>,
> +			   <IMX8QM_USDHC1_CMD_CONN_USDHC1_CMD		0x00000021>,
> +			   <IMX8QM_USDHC1_DATA0_CONN_USDHC1_DATA0	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA1_CONN_USDHC1_DATA1	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA2_CONN_USDHC1_DATA2	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA3_CONN_USDHC1_DATA3	0x00000021>,
> +			   <IMX8QM_USDHC1_VSELECT_CONN_USDHC1_VSELECT	0x00000021>;
> +	};
> +
> +	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
> +		fsl,pins = <IMX8QM_USDHC1_CLK_CONN_USDHC1_CLK		0x06000041>,
> +			   <IMX8QM_USDHC1_CMD_CONN_USDHC1_CMD		0x00000021>,
> +			   <IMX8QM_USDHC1_DATA0_CONN_USDHC1_DATA0	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA1_CONN_USDHC1_DATA1	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA2_CONN_USDHC1_DATA2	0x00000021>,
> +			   <IMX8QM_USDHC1_DATA3_CONN_USDHC1_DATA3	0x00000021>,
> +			   <IMX8QM_USDHC1_VSELECT_CONN_USDHC1_VSELECT	0x00000021>;
> +	};
> +};
> diff --git a/arch/arm64/boot/dts/freescale/imx8qm-tqma8qm.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-tqma8qm.dtsi
> new file mode 100644
> index 0000000000000..d94605c999915
> --- /dev/null
> +++ b/arch/arm64/boot/dts/freescale/imx8qm-tqma8qm.dtsi
> @@ -0,0 +1,318 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
> +/*
> + * Copyright (c) 2019-2026 TQ-Systems GmbH <linux@ew.tq-group.com>,
> + * D-82229 Seefeld, Germany.
> + * Author: Alexander Stein
> + */
> +
> +#include <dt-bindings/firmware/imx/rsrc.h>
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/thermal/thermal.h>
> +
> +#include "imx8qm.dtsi"
> +
> +/ {
> +	model = "TQ-Systems i.MX8QM TQMa8QM";
> +	compatible = "tq,imx8qm-tqma8qm", "fsl,imx8qm";
> +
> +	memory@80000000 {
> +		device_type = "memory";
> +		/*
> +		 * DRAM base addr, size : 1024 MiB DRAM
> +		 * should be corrected by bootloader
> +		 */
> +		reg = <0x00000000 0x80000000 0 0x40000000>;
> +	};
> +
> +	reg_tqma8x_v3v3: regulator-tqma8x-v3v3 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "V_3V3";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		regulator-always-on;
> +	};
> +
> +	/* SW7 controlled by SCU */
> +	reg_1v8_io1: regulator-v1v8-io1 {
> +		compatible = "regulator-fixed";
> +		regulator-name = "V_1V8_IO1";
> +		regulator-min-microvolt = <1800000>;
> +		regulator-max-microvolt = <1800000>;
> +		regulator-always-on;
> +	};
> +
> +	/* LDO4 controlled by SCU */
> +	reg_3v3_emmc: regulator-v3v3-emmc {
> +		compatible = "regulator-fixed";
> +		regulator-name = "V_3V3_EMMC";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		regulator-always-on;
> +	};
> +};
> +
> +&acm {
> +	status = "okay";
> +};
> +
> +&adc0 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_adc0>;
> +	vref-supply = <&reg_vref_v1v8>;
> +	status = "okay";
> +};
> +
> +/* TQMa8QM only uses industrial grade, reduce trip points accordingly */
> +&cpu_alert0 {
> +	temperature = <95000>;
> +};
> +
> +&cpu_crit0 {
> +	temperature = <100000>;
> +};
> +
> +&cpu_alert1 {
> +	temperature = <95000>;
> +};
> +
> +&cpu_crit1 {
> +	temperature = <100000>;
> +};
> +
> +&gpu_alert0 {
> +	temperature = <95000>;
> +};
> +
> +&gpu_crit0 {
> +	temperature = <100000>;
> +};
> +
> +&gpu_alert1 {
> +	temperature = <95000>;
> +};
> +
> +&gpu_crit1 {
> +	temperature = <100000>;
> +};
> +
> +&drc_alert0 {
> +	temperature = <95000>;
> +};
> +
> +&drc_crit0 {
> +	temperature = <100000>;
> +};
> +/* end of temperature grade adjustments */
> +
> +&flexspi0 {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pinctrl_flexspi0>;
> +	status = "okay";
> +
> +	flash0: flash@0 {
> +		compatible = "jedec,spi-nor";
> +		reg = <0>;
> +		spi-max-frequency = <66000000>;
> +		spi-tx-bus-width = <4>;
> +		spi-rx-bus-width = <4>;
> +		vcc-supply = <&reg_1v8_io1>;
> +
> +		partitions {
> +			compatible = "fixed-partitions";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +		};
> +	};
> +};
> +
> +&i2c1 {
> +	clock-frequency = <400000>;
> +	pinctrl-names = "default", "gpio";
> +	pinctrl-0 = <&pinctrl_lpi2c1>;
> +	pinctrl-1 = <&pinctrl_lpi2c1gpio>;
> +	scl-gpios = <&lsio_gpio0 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> +	sda-gpios = <&lsio_gpio0 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> +	status = "okay";
> +
> +	se97: temperature-sensor@1b {
> +		compatible = "nxp,se97b", "jedec,jc-42.4-temp";
> +		reg = <0x1b>;
> +	};
> +
> +	pcf85063: rtc@51 {
> +		compatible = "nxp,pcf85063a";
> +		reg = <0x51>;
> +		quartz-load-femtofarads = <7000>;
> +	};
> +
> +	at24c02: eeprom@53 {
> +		compatible = "nxp,se97b", "atmel,24c02";
> +		reg = <0x53>;
> +		pagesize = <16>;
> +		read-only;
> +		vcc-supply = <&reg_tqma8x_v3v3>;
> +	};
> +
> +	m24c64: eeprom@57 {
> +		compatible = "atmel,24c64";
> +		reg = <0x57>;
> +		pagesize = <32>;
> +		vcc-supply = <&reg_tqma8x_v3v3>;
> +	};
> +};
> +
> +&mu_m0 {
> +	status = "okay";
> +};
> +
> +&mu1_m0 {
> +	status = "okay";
> +};
> +
> +&mu2_m0 {
> +	status = "okay";
> +};
> +
> +&thermal_zones {
> +	pmic0-thermal {
> +		polling-delay-passive = <250>;
> +		polling-delay = <2000>;
> +		thermal-sensors = <&tsens IMX_SC_R_PMIC_0>;
> +
> +		trips {
> +			pmic_alert0: trip0 {
> +				temperature = <110000>;
> +				hysteresis = <2000>;
> +				type = "passive";
> +			};
> +			pmic_crit0: trip1 {
> +				temperature = <125000>;
> +				hysteresis = <2000>;
> +				type = "critical";
> +			};
> +		};
> +
> +		cooling-maps {
> +			map0 {
> +				trip = <&pmic_alert0>;
> +				cooling-device =
> +					<&A53_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +					<&A53_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +					<&A53_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +					<&A53_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +					<&A72_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> +					<&A72_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> +			};
> +		};
> +	};
> +};
> +
> +&usdhc1 {
> +	pinctrl-names = "default", "state_100mhz", "state_200mhz";
> +	pinctrl-0 = <&pinctrl_usdhc1>;
> +	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
> +	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
> +	bus-width = <8>;
> +	vmmc-supply = <&reg_3v3_emmc>;
> +	vqmmc-supply = <&reg_1v8_io1>;
> +	no-sd;
> +	no-sdio;
> +	non-removable;
> +	status = "okay";
> +};
> +
> +&vpu {
> +	compatible = "nxp,imx8qm-vpu";
> +	status = "okay";
> +};
> +
> +&vpu_core0 {
> +	memory-region = <&decoder_boot>, <&decoder_rpc>;
> +	status = "okay";
> +};
> +
> +&vpu_core1 {
> +	memory-region = <&encoder1_boot>, <&encoder1_rpc>;
> +	status = "okay";
> +};
> +
> +&vpu_core2 {
> +	memory-region = <&encoder2_boot>, <&encoder2_rpc>;
> +	status = "okay";
> +};
> +
> +&iomuxc {
> +	pinctrl_lpi2c1: lpi2c1grp {
> +		fsl,pins = <IMX8QM_GPT0_CAPTURE_DMA_I2C1_SDA		0x0600004d>,
> +			   <IMX8QM_GPT0_CLK_DMA_I2C1_SCL		0x0600004d>;
> +	};
> +
> +	pinctrl_lpi2c1gpio: lpi2c1gpiogrp {
> +		fsl,pins = <IMX8QM_GPT0_CAPTURE_LSIO_GPIO0_IO15		0x0600004d>,
> +			   <IMX8QM_GPT0_CLK_LSIO_GPIO0_IO14		0x0600004d>;
> +	};
> +
> +	pinctrl_usdhc1: usdhc1grp {
> +		fsl,pins = <IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK		0x06000041>,
> +			   <IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7		0x00000021>,
> +			   <IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE	0x00000041>,
> +			   <IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B	0x00000021>;
> +	};
> +
> +	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
> +		fsl,pins = <IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK		0x06000040>,
> +			   <IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7		0x00000021>,
> +			   <IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE	0x00000041>,
> +			   <IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B	0x00000021>;
> +	};
> +
> +	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
> +		fsl,pins = <IMX8QM_EMMC0_CLK_CONN_EMMC0_CLK		0x06000040>,
> +			   <IMX8QM_EMMC0_CMD_CONN_EMMC0_CMD		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA0_CONN_EMMC0_DATA0		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA1_CONN_EMMC0_DATA1		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA2_CONN_EMMC0_DATA2		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA3_CONN_EMMC0_DATA3		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA4_CONN_EMMC0_DATA4		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA5_CONN_EMMC0_DATA5		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA6_CONN_EMMC0_DATA6		0x00000021>,
> +			   <IMX8QM_EMMC0_DATA7_CONN_EMMC0_DATA7		0x00000021>,
> +			   <IMX8QM_EMMC0_STROBE_CONN_EMMC0_STROBE	0x00000041>,
> +			   <IMX8QM_EMMC0_RESET_B_CONN_EMMC0_RESET_B	0x00000021>;
> +	};
> +
> +	pinctrl_flexspi0: flexspi0grp {
> +		fsl,pins = <IMX8QM_QSPI0A_DATA0_LSIO_QSPI0A_DATA0	0x0000004d>,
> +			   <IMX8QM_QSPI0A_DATA1_LSIO_QSPI0A_DATA1	0x0000004d>,
> +			   <IMX8QM_QSPI0A_DATA2_LSIO_QSPI0A_DATA2	0x0000004d>,
> +			   <IMX8QM_QSPI0A_DATA3_LSIO_QSPI0A_DATA3	0x0000004d>,
> +			   <IMX8QM_QSPI0A_DQS_LSIO_QSPI0A_DQS		0x0000004d>,
> +			   <IMX8QM_QSPI0A_SS0_B_LSIO_QSPI0A_SS0_B	0x0000004d>,
> +			   <IMX8QM_QSPI0A_SS1_B_LSIO_QSPI0A_SS1_B	0x0000004d>,
> +			   <IMX8QM_QSPI0A_SCLK_LSIO_QSPI0A_SCLK		0x0000004d>,
> +			   <IMX8QM_QSPI0B_SCLK_LSIO_QSPI0B_SCLK		0x0000004d>,
> +			   <IMX8QM_QSPI0B_DATA0_LSIO_QSPI0B_DATA0	0x0000004d>,
> +			   <IMX8QM_QSPI0B_DATA1_LSIO_QSPI0B_DATA1	0x0000004d>,
> +			   <IMX8QM_QSPI0B_DATA2_LSIO_QSPI0B_DATA2	0x0000004d>,
> +			   <IMX8QM_QSPI0B_DATA3_LSIO_QSPI0B_DATA3	0x0000004d>,
> +			   <IMX8QM_QSPI0B_DQS_LSIO_QSPI0B_DQS		0x0000004d>,
> +			   <IMX8QM_QSPI0B_SS0_B_LSIO_QSPI0B_SS0_B	0x0000004d>,
> +			   <IMX8QM_QSPI0B_SS1_B_LSIO_QSPI0B_SS1_B	0x0000004d>;
> +	};
> +};
> --
> 2.43.0
>


^ permalink raw reply

* RE: [PATCH v2] net: stmmac: skip VLAN restore when VLAN hash ops are missing
From: Ovidiu Panait @ 2026-03-24 15:37 UTC (permalink / raw)
  To: Russell King, Paolo Abeni
  Cc: Michal Piekos, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Maxime Coquelin, Alexandre Torgue,
	netdev@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <acKL4RoM-zdwj1Ib@shell.armlinux.org.uk>

Hi,

> 
> On Tue, Mar 24, 2026 at 01:14:29PM +0100, Paolo Abeni wrote:
> > On 3/21/26 6:38 AM, Michal Piekos wrote:
> > > stmmac_vlan_restore() unconditionally calls stmmac_vlan_update() when
> > > NETIF_F_VLAN_FEATURES is set. On platforms where priv->hw->vlan (or
> > > ->update_vlan_hash) is not provided, stmmac_update_vlan_hash() returns
> > > -EINVAL via stmmac_do_void_callback(), resulting in a spurious
> > > "Failed to restore VLANs" error even when no VLAN filtering is in use.
> > >
> > > Check presence of VLAN HW FILTER flags before stmmac_vlan_update().
> > >
> > > Tested on Orange Pi Zero 3.
> > >
> > > Fixes: bd7ad51253a7 ("net: stmmac: Fix VLAN HW state restore")
> > > Signed-off-by: Michal Piekos <michal.piekos@mmpsystems.pl>
> > > ---
> > > This patch fixes a noisy "Failed to restore VLANs" message on
> platforms
> > > where stmmac VLAN hash ops are not implemented.
> > > stmmac_vlan_restore() calls stmmac_vlan_update() without checking for
> > > VLAN hash ops presence which results in -EINVAL.
> > > ---
> > > Changes in v2:
> > > - Replace check for hash ops with check for HW FILTER flags
> > > - Link to v1: https://lore.kernel.org/r/20260314-vlan-restore-error-
> v1-1-4fc6c3e2115f@mmpsystems.pl
> > > ---
> > >  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > index 6827c99bde8c..cfc0ce9cec9c 100644
> > > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > > @@ -6863,7 +6863,8 @@ static int stmmac_vlan_restore(struct
> stmmac_priv *priv)
> > >  {
> > >  	int ret;
> > >
> > > -	if (!(priv->dev->features & NETIF_F_VLAN_FEATURES))
> > > +	if (!(priv->dev->features &
> > > +	      (NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)))
> > >  		return 0;
> > >
> > >  	if (priv->hw->num_vlan)
> > Adding Russell.
> >
> > It's not obvious to me that with this change the
> > restore_hw_vlan_rx_fltr() and vlan_update() callback are still invoked
> > in all the relevant driver/features permutation.
> 
> I think there's a few questions here.
> 
> When CONFIG_VLAN_8021Q is enabled, then we set the filter features
> if the vlhash dma capability is set:
> 
>         if (priv->dma_cap.vlhash) {
>                 ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
>                 ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
>         }
> 

The VLAN core will call into the ndo_vlan_rx_add_vid and ndo_vlan_rx_kill_vid
callbacks in the driver only if NETIF_F_HW_VLAN_CTAG_FILTER or
NETIF_F_HW_VLAN_STAG_FILTER features are advertised. For stmmac, the HW
filtering features are currently advertised only if priv->dma_cap.vlhash is
set.

stmmac_vlan_update() is only called from ndo_vlan_rx_add_vid and
ndo_vlan_rx_kill_vid callbacks to set up hash filtering, so on the
restore path it should also be called only if HW filtering is enabled.
Otherwise there is nothing to restore.

> Only dwmac4 and dwxgmac2 have the ability to set this feature (and
> thus be synthesised with the feature enabled.) From what I understand,
> when present, these features are permanently enabled (as they're not
> set in hw_Features).
> 
> However, in stmmac_vlan_update() there is:
> 
>         if (!priv->dma_cap.vlhash) {
>                 if (count > 2) /* VID = 0 always passes filter */
>                         return -EOPNOTSUPP;
> 
>                 pmatch = vid;
>                 hash = 0;
>         }
> 
> So, it is clear that the intention is that stmmac_vlan_update() will
> be called even when the NETIF_F_HW_VLAN_*TAG_FILTER features are not
> present - consider a core that implements the VLAN ops, but has
> priv->dma_cap.vlhash false.
> 

My understanding is that the code in stmmac_vlan_update() that checks for
!priv->dma_cap.vlhash is dead code, this condition cannot be true inside
the ndo_vlan_rx_add_vid and ndo_vlan_rx_kill_vid callbacks because the
callbacks are only called when priv->dma_cap.vlhash is true.

This seems to be a long-standing issue in the VLAN code.

> It looks like vlan support was added in dwmac v4.0 and later cores
> (from the hwif table.) As the vlan ops are NULL before that, the
> horrid stmmac_do_void_callback() crud will return -EINVAL (yuck). The
> method it calls is a void function, so the only possible return values
> are zero if implemented, or -EINVAL if not.
> 
> stmmac_vlan_update() itself only ever returns zero if the netif
> isn't running, or the above return value. So, an error returned from
> stmmac_vlan_update() just means that the driver has no support for
> programming the vlan configuration.
> 
> Looking at the implementations for the case where vlhash is false,
> (where stmmac_update_vlan_hash() will be called with hash=0 and
> perfect_match with a vid, vlan_update_hash() still write
> to the VLAN_TAG register to configure vlan handling. I haven't
> looked up exactly what it does.
> 
> The other possibility is dwxgmac2_update_vlan_hash(). This looks
> similar.
> 
> So, I don't think that the correct solution is to only call this
> function when one or more of NETIF_F_HW_VLAN_*TAG_FILTER feature flags
> are set - clearly the code is written to handle the case where the
> update_vlan_hash method is populated but vlhash is false and these
> feature flags are clear.
> 

Even though the original intent seems to have been to allow for
stmmac_vlan_update() to work with priv->dma_cap.vlhash = false, in practice
it doesn't work because stmmac_vlan_update() is only called when
priv->dma_cap.vlhash = true.

> Now I'm wondering whether the code in the STMMAC_VLAN_TAG_USED block
> is correct:
> 
>         /* Both mac100 and gmac support receive VLAN tag detection */
>         ndev->features |= NETIF_F_HW_VLAN_CTAG_RX |
> NETIF_F_HW_VLAN_STAG_RX;
>         if (dwmac_is_xmac(priv->plat->core_type)) {
>                 ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
>                 priv->hw->hw_vlan_en = true;
>         }
>         if (priv->dma_cap.vlhash) {
>                 ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
>                 ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
>         }
>         if (priv->dma_cap.vlins)
>                 ndev->features |= NETIF_F_HW_VLAN_CTAG_TX;
> 
> The test for dwmac_is_xmac() matches for dwmac4 and dwxgmac cores. If
> this is true, then we will have the vlan ops populated, and it means
> that NETIF_F_HW_VLAN_CTAG_RX can be configured by the user rather than
> being always-enabled. Is this correct? I'm not sure - I haven't dug
> into enough of the documentation for this yet. However, I suggest
> that we need to always call stmmac_update_vlan_hash() for these cores.
> 
> So, I'm coming to the conclusion that we either need a test for
> dwmac_is_xmac() and not the feature flags, or maybe we just get rid
> of the "Failed to restore VLANs" error print and make
> stmmac_vlan_restore() return void (nothing uses the return value.)
> 
> In summary, I'm not sure what the correct approach is - please reach
> out to Ovidiu Panait <ovidiu.panait.rb@renesas.com> who recently added
> this code, but I'm fairly sure that this solution is incorrect.
> 
> Really, Ovidiu Panait should be reviewing this patch as his recent
> change introduced the problematical error print.
> 

I reviewed the v1 for this patch ([1]), and given the existing VLAN
implementation and for a targeted fix, I think checking HW filtering
features is correct. The restore only takes care of restoring the HW
filters, so it should run only when we have HW filters support.

When the HW filters should be enabled, though, I think is a separate
issue that requires some refactoring of the VLAN implementation, to
make it more precise, as Russell pointed out.

I only have access to a board that uses the DWMAC4 IP, but I'll have
a look in the documentation I have to check how to improve VLAN
features handling. 

[1] https://lore.kernel.org/all/20260314-vlan-restore-error-v1-1-4fc6c3e2115f@mmpsystems.pl/

Ovidiu

> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


^ permalink raw reply

* Re: [PATCH] firmware: arm_scmi: clock: Relax check in scmi_clock_protocol_init
From: Geert Uytterhoeven @ 2026-03-24 15:32 UTC (permalink / raw)
  To: Cristian Marussi
  Cc: Sudeep Holla, Peng Fan (OSS), Jacky Bai, arm-scmi,
	linux-arm-kernel, linux-kernel, Peng Fan
In-Reply-To: <acKhJ8Z9WDvHEnYL@pluto>

Hi Cristian,

On Tue, 24 Mar 2026 at 15:35, Cristian Marussi <cristian.marussi@arm.com> wrote:
> On Tue, Mar 24, 2026 at 02:15:36PM +0100, Geert Uytterhoeven wrote:
> > On Tue, 24 Mar 2026 at 09:41, Cristian Marussi <cristian.marussi@arm.com> wrote:
> > > Looking at the spec 3.6.2.5 CLOCK_ATTRIBUTES
> > >
> > > "This command returns the attributes that are associated with a specific clock. An agent might be allowed access to only
> > > a subset of the clocks available in the system. The platform must thus guarantee that clocks that an agent cannot access
> > > are not visible to it."
> > >
> > > ...not sure if this sheds some light or it is ambiguos anyway...I'd say that
> > > NOT_FOUND does NOT equate to be invisible...
> > >
> > > ...BUT at the same time I think that this practice of exposing a non-contiguos
> > > set of resources IDs (a set with holes in it) is the a well-known spec-loophole
> > > used by many vendors to deploy one single FW image across all of their platforms
> > > without having to reconfigure their reosurces IDs ro expose a common set of
> > > contiguos IDs like the spec would suggest...
> > >
> > > Having said that, since we unfortunately left this door open in the
> > > implementation, now this loophole has become common practice
> > > apparently...
> >
> > When I first read that paragraph, I was also confused.
> > What does "not visible" mean?
> >   - Not present in the clock ID space exposed to that client of
> >     the system?
> >     Yeah, multiple different sequences of contiguous IDs, depending
> >     on client!
>
> Yes that is the most spec-compliant interpretation usually; in general
> across all protocols the SCMI server, through customized enumeration
> results, should provide a per-agent view of the system: this should help
> handling shared or virtualized resources, since the agent always see
> only the 'illusion' provided by the server...
>
> ...under this assumption if you dont even need a resource at all (not
> RW nor RO) you should NOT even be able to see it...this in turn of
> course means that in order to expose a contiguous set of IDs you should
> be able to properly configure at build time the FW resources on a per
> platform basis...
>
> >   - Return failure on CLOCK_ATTRIBUTES?
> >     Which is what implementations seem to do.
>
> Yes this is what is done leveraging the gap in the implementation...I am
> not sure that the non-contiguous set of IDs is supported if not by
> chance as of now :P (especially in other protocols)
>
> > The next step in the fun is when the system actually needs to know the
> > clock rate of such a clock...
>
> Well...that seems a bit of wishful thinking ...

Unfortunately it is real... [cliffhanger, to be continued... :-]

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


^ permalink raw reply

* Re: [PATCH v4 08/21] mm: add vm_ops->mapped hook
From: Vlastimil Babka (SUSE) @ 2026-03-24 15:32 UTC (permalink / raw)
  To: Lorenzo Stoakes (Oracle), Andrew Morton
  Cc: Jonathan Corbet, Clemens Ladisch, Arnd Bergmann,
	Greg Kroah-Hartman, K . Y . Srinivasan, Haiyang Zhang, Wei Liu,
	Dexuan Cui, Long Li, Alexander Shishkin, Maxime Coquelin,
	Alexandre Torgue, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Bodo Stroesser, Martin K . Petersen,
	David Howells, Marc Dionne, Alexander Viro, Christian Brauner,
	Jan Kara, David Hildenbrand, Liam R . Howlett, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Jann Horn, Pedro Falcato,
	linux-kernel, linux-doc, linux-hyperv, linux-stm32,
	linux-arm-kernel, linux-mtd, linux-staging, linux-scsi,
	target-devel, linux-afs, linux-fsdevel, linux-mm, Ryan Roberts
In-Reply-To: <4c5e98297eb0aae9565c564e1c296a112702f144.1774045440.git.ljs@kernel.org>

On 3/20/26 23:39, Lorenzo Stoakes (Oracle) wrote:
> Previously, when a driver needed to do something like establish a
> reference count, it could do so in the mmap hook in the knowledge that the
> mapping would succeed.
> 
> With the introduction of f_op->mmap_prepare this is no longer the case, as
> it is invoked prior to actually establishing the mapping.
> 
> mmap_prepare is not appropriate for this kind of thing as it is called
> before any merge might take place, and after which an error might occur
> meaning resources could be leaked.
> 
> To take this into account, introduce a new vm_ops->mapped callback which
> is invoked when the VMA is first mapped (though notably - not when it is
> merged - which is correct and mirrors existing mmap/open/close behaviour).
> 
> We do better that vm_ops->open() here, as this callback can return an
> error, at which point the VMA will be unmapped.
> 
> Note that vm_ops->mapped() is invoked after any mmap action is complete
> (such as I/O remapping).
> 
> We intentionally do not expose the VMA at this point, exposing only the
> fields that could be used, and an output parameter in case the operation
> needs to update the vma->vm_private_data field.
> 
> In order to deal with stacked filesystems which invoke inner filesystem's
> mmap() invocations, add __compat_vma_mapped() and invoke it on vfs_mmap()
> (via compat_vma_mmap()) to ensure that the mapped callback is handled when
> an mmap() caller invokes a nested filesystem's mmap_prepare() callback.
> 
> Update the mmap_prepare documentation to describe the mapped hook and make
> it clear what its intended use is.
> 
> The vm_ops->mapped() call is handled by the mmap complete logic to ensure
> the same code paths are handled by both the compatibility and VMA layers.
> 
> Additionally, update VMA userland test headers to reflect the change.
> 
> Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>

Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>




^ permalink raw reply

* Re: [PATCH v4 00/11] arm64: dts: freescale: imx8mm-var-som: Align SOM and Symphony DTSs
From: Frank Li @ 2026-03-24 15:31 UTC (permalink / raw)
  To: linux-kernel, devicetree, imx, linux-arm-kernel, Stefano Radaelli
  Cc: Frank Li, pierluigi.p, Stefano Radaelli, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
In-Reply-To: <cover.1773944896.git.stefano.r@variscite.com>


On Thu, 19 Mar 2026 19:40:20 +0100, Stefano Radaelli wrote:
> This series aligns the i.MX8MM VAR-SOM and VAR-SOM Symphony device
> trees with the latest hardware revisions.
>
> The update consolidates the device tree descriptions to better reflect
> the actual hardware partitioning between the SOM and the carrier board.
> Nodes describing peripherals physically present on the SOM are kept in
> the SOM dtsi, while carrier-specific components are described in the
> corresponding carrier dts.
>
> [...]

Applied, thanks!

[01/11] arm64: dts: freescale: imx8mm-var-som: Move UART4 description to Symphony
        commit: f87a5bdec6fb40b913099d71cfcd5ab36db8c9ff
[02/11] arm64: dts: freescale: imx8mm-var-som: Align fsl,pins tables
        commit: 07118b23d92eaaf2eba2c9c17f96a2d5bbe319ed
[03/11] arm64: dts: freescale: imx8mm-var-som: Update FEC support with MaxLinear PHY
        commit: d485f4c5d7c5e8a12fc3c64f1e42622f4195f48e
[04/11] arm64: dts: freescale: imx8mm-var-som: Add support for WM8904 audio codec
        commit: 83bf7b1be4d2f7720541a174d21a7428fabf2946

Adjust commit message by "Add description about I2C recovery GPIO settings"

[05/11] arm64: dts: freescale: imx8mm-var-som: Add MCP251xFD CAN controller
        commit: 684e1a3ed73a85f56dd8eefd98afa842bae30720

Move vendor property microchip,rx-int-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
to last


[06/11] arm64: dts: freescale: imx8mm-var-som: Rework WiFi/BT and add legacy dts
        commit: afee7e5ccd61e07bc50cdd93d963fb5e4a6348f5
[07/11] arm64: dts: imx8mm-var-som-symphony: Move USB configuration from SOM
        commit: 0be9f14dbf5eeef7cb606785b0b3868336891c45
[08/11] arm64: dts: imx8mm-var-som-symphony: Enable uSD on USDHC2
        commit: 32e31d0e98f0c8a769d3ab4a4b120e9daa134717
[09/11] arm64: dts: imx8mm-var-som-symphony: Add TPM2 support
        commit: 1808013e644a4f4b4352c7e5fe24d4156922d427
[10/11] arm64: dts: imx8mm-var-som-symphony: Enable I2C4
        commit: f8ee13d589224021b85621a45f97b78405f355bd
[11/11] arm64: dts: imx8mm-var-som-symphony: Enable PCIe
        commit: 074ae0d55f603eb6d58d78a3ff49b1c69e1f9470

Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* Re: [PATCH v7 12/41] KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE
From: Marc Zyngier @ 2026-03-24 15:25 UTC (permalink / raw)
  To: Mark Brown
  Cc: Sascha Bischoff, linux-arm-kernel@lists.infradead.org,
	kvmarm@lists.linux.dev, kvm@vger.kernel.org, nd,
	oliver.upton@linux.dev, Joey Gouly, Suzuki Poulose,
	yuzenghui@huawei.com, peter.maydell@linaro.org,
	lpieralisi@kernel.org, Timothy Hayes, jonathan.cameron@huawei.com
In-Reply-To: <ebd9ebb4-06ac-41a1-af16-664a4eedf3fd@sirena.org.uk>

On Tue, 24 Mar 2026 14:53:58 +0000,
Mark Brown <broonie@kernel.org> wrote:
> 
> [1  <text/plain; us-ascii (7bit)>]
> On Tue, Mar 24, 2026 at 02:48:04PM +0000, Marc Zyngier wrote:
> > Mark Brown <broonie@kernel.org> wrote:
> 
> > > We're also seeing an issue with this in the aarch32_id_regs test:
> 
> ...
> 
> > > which for some reason only manifests on TX2 of the platforms I've
> > > seen.
> 
> > Is your TX2 the only machine you have that is AArch64 only at all ELs?
> 
> Yes, that should be the case.

The hack below fixes it on my favourite Qualcomm box.

	M.

diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index fd872079f2a24..7212cb3766d3d 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -696,7 +696,8 @@ void kvm_vgic_finalize_idregs(struct kvm *kvm)
 		break;
 	case KVM_DEV_TYPE_ARM_VGIC_V3:
 		aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
-		pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
+		if (kvm_supports_32bit_el0())
+			pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
 		break;
 	case KVM_DEV_TYPE_ARM_VGIC_V5:
 		aa64pfr2 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR2_EL1, GCIE, IMP);

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply related

* Re: [PATCH] KVM: arm64: Inject UNDEF when host is executing an smc with imm16 != 0
From: Fuad Tabba @ 2026-03-24 15:13 UTC (permalink / raw)
  To: Sebastian Ene
  Cc: kvmarm, linux-arm-kernel, linux-kernel, android-kvm,
	catalin.marinas, joey.gouly, mark.rutland, maz, oupton,
	suzuki.poulose, vdonnefort, will, yuzenghui
In-Reply-To: <20260324135728.3532400-1-sebastianene@google.com>

Hi Seb,

On Tue, 24 Mar 2026 at 13:57, Sebastian Ene <sebastianene@google.com> wrote:
>
> The ARM Service Calling Convention (SMCCC) specifies that the function
> identifier and parameters should be passed in registers, leaving the
> 16-bit immediate field of the SMC instruction un-handled.
> Currently, our pKVM handler ignores the immediate value, which could lead
> to non-compliant software relying on implementation-defined behavior.
> Enforce the host kernel running under pKVM to use an immediate value
> of 0 by decoding the ISS from the ESR_EL2 and inject an undefined
> instruction exception back to the caller.
>
> Signed-off-by: Sebastian Ene <sebastianene@google.com>
> ---
>  arch/arm64/kvm/hyp/nvhe/hyp-main.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index e7790097db93..ff6a90a4a4c7 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -756,13 +756,18 @@ static bool handle_host_mte(u64 esr)
>  void handle_trap(struct kvm_cpu_context *host_ctxt)
>  {
>         u64 esr = read_sysreg_el2(SYS_ESR);
> +       u16 imm16;
>
>         switch (ESR_ELx_EC(esr)) {
>         case ESR_ELx_EC_HVC64:
>                 handle_host_hcall(host_ctxt);
>                 break;
>         case ESR_ELx_EC_SMC64:
> -               handle_host_smc(host_ctxt);
> +               imm16 = esr & U16_MAX;
> +               if (!imm16)

Do we need to introduce a new variable for this? This isn't easier to read than:
+               if (!(esr & U16_MAX))

Also, we have a mask for this: ESR_ELx_xVC_IMM_MASK , please use that instead

Cheers,
/fuad



> +                       handle_host_smc(host_ctxt);
> +               else
> +                       inject_undef64();
>                 break;
>         case ESR_ELx_EC_IABT_LOW:
>         case ESR_ELx_EC_DABT_LOW:
> --
> 2.53.0.983.g0bb29b3bc5-goog
>


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox