From f887685ee0eb4ef716391355568181230338f6eb Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 7 Feb 2025 11:25:27 -0500 Subject: [PATCH 01/73] drm: zynqmp_dp: Fix a deadlock in zynqmp_dp_ignore_hpd_set() Instead of attempting the same mutex twice, lock and unlock it. This bug has been detected by the Clang thread-safety analyzer. Cc: Sean Anderson Cc: Tomi Valkeinen Fixes: 28edaacb821c ("drm: zynqmp_dp: Add debugfs interface for compliance testing") Signed-off-by: Bart Van Assche Reviewed-by: Sean Anderson Signed-off-by: Sean Anderson Reviewed-by: Laurent Pinchart Reviewed-by: Sean Anderson Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20250207162528.1651426-2-sean.anderson@linux.dev --- drivers/gpu/drm/xlnx/zynqmp_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index 979f6d3239ba..189a08cdc73c 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -2295,7 +2295,7 @@ static int zynqmp_dp_ignore_hpd_set(void *data, u64 val) mutex_lock(&dp->lock); dp->ignore_hpd = val; - mutex_lock(&dp->lock); + mutex_unlock(&dp->lock); return 0; } From 2f2cd4a0595d894ba53d95e2a230032f8615dcdd Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Fri, 7 Feb 2025 11:25:28 -0500 Subject: [PATCH 02/73] drm: zynqmp_dp: Use scope-based mutex helpers Convert most mutex_(un)lock calls to use (scoped_)guard instead. This generally reduces line count and prevents bugs like forgetting to unlock the mutex. I've left traditional calls in a few places where scoped helpers would be more verbose. This mostly happens where debugfs_file_put needs to be called regardless. I looked into defining a CLASS for debugfs_file, but it seems like more effort than it's worth since debugfs_file_get can fail. Signed-off-by: Sean Anderson Reviewed-by: Laurent Pinchart Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20250207162528.1651426-3-sean.anderson@linux.dev --- drivers/gpu/drm/xlnx/zynqmp_dp.c | 147 +++++++++++-------------------- 1 file changed, 50 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index 189a08cdc73c..63842f657836 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -1534,10 +1534,10 @@ zynqmp_dp_bridge_mode_valid(struct drm_bridge *bridge, } /* Check with link rate and lane count */ - mutex_lock(&dp->lock); - rate = zynqmp_dp_max_rate(dp->link_config.max_rate, - dp->link_config.max_lanes, dp->config.bpp); - mutex_unlock(&dp->lock); + scoped_guard(mutex, &dp->lock) + rate = zynqmp_dp_max_rate(dp->link_config.max_rate, + dp->link_config.max_lanes, + dp->config.bpp); if (mode->clock > rate) { dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n", mode->name); @@ -1722,13 +1722,9 @@ static enum drm_connector_status __zynqmp_dp_bridge_detect(struct zynqmp_dp *dp) static enum drm_connector_status zynqmp_dp_bridge_detect(struct drm_bridge *bridge) { struct zynqmp_dp *dp = bridge_to_dp(bridge); - enum drm_connector_status ret; - mutex_lock(&dp->lock); - ret = __zynqmp_dp_bridge_detect(dp); - mutex_unlock(&dp->lock); - - return ret; + guard(mutex)(&dp->lock); + return __zynqmp_dp_bridge_detect(dp); } static const struct drm_edid *zynqmp_dp_bridge_edid_read(struct drm_bridge *bridge, @@ -1881,10 +1877,9 @@ static ssize_t zynqmp_dp_pattern_read(struct file *file, char __user *user_buf, if (unlikely(ret)) return ret; - mutex_lock(&dp->lock); - ret = snprintf(buf, sizeof(buf), "%s\n", - test_pattern_str[dp->test.pattern]); - mutex_unlock(&dp->lock); + scoped_guard(mutex, &dp->lock) + ret = snprintf(buf, sizeof(buf), "%s\n", + test_pattern_str[dp->test.pattern]); debugfs_file_put(dentry); return simple_read_from_buffer(user_buf, count, ppos, buf, ret); @@ -1939,24 +1934,18 @@ static int zynqmp_dp_enhanced_get(void *data, u64 *val) { struct zynqmp_dp *dp = data; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = dp->test.enhanced; - mutex_unlock(&dp->lock); return 0; } static int zynqmp_dp_enhanced_set(void *data, u64 val) { struct zynqmp_dp *dp = data; - int ret = 0; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); dp->test.enhanced = val; - if (dp->test.active) - ret = zynqmp_dp_test_setup(dp); - mutex_unlock(&dp->lock); - - return ret; + return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; } DEFINE_DEBUGFS_ATTRIBUTE(fops_zynqmp_dp_enhanced, zynqmp_dp_enhanced_get, @@ -1966,24 +1955,19 @@ static int zynqmp_dp_downspread_get(void *data, u64 *val) { struct zynqmp_dp *dp = data; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = dp->test.downspread; - mutex_unlock(&dp->lock); return 0; } static int zynqmp_dp_downspread_set(void *data, u64 val) { struct zynqmp_dp *dp = data; - int ret = 0; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); dp->test.downspread = val; - if (dp->test.active) - ret = zynqmp_dp_test_setup(dp); - mutex_unlock(&dp->lock); - return ret; + return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; } DEFINE_DEBUGFS_ATTRIBUTE(fops_zynqmp_dp_downspread, zynqmp_dp_downspread_get, @@ -1993,33 +1977,32 @@ static int zynqmp_dp_active_get(void *data, u64 *val) { struct zynqmp_dp *dp = data; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = dp->test.active; - mutex_unlock(&dp->lock); return 0; } static int zynqmp_dp_active_set(void *data, u64 val) { struct zynqmp_dp *dp = data; - int ret = 0; + int ret; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); if (val) { if (val < 2) { ret = zynqmp_dp_test_setup(dp); if (ret) - goto out; + return ret; } ret = zynqmp_dp_set_test_pattern(dp, dp->test.pattern, dp->test.custom); if (ret) - goto out; + return ret; ret = zynqmp_dp_update_vs_emph(dp, dp->test.train_set); if (ret) - goto out; + return ret; dp->test.active = true; } else { @@ -2032,10 +2015,8 @@ static int zynqmp_dp_active_set(void *data, u64 val) err); zynqmp_dp_train_loop(dp); } -out: - mutex_unlock(&dp->lock); - return ret; + return 0; } DEFINE_DEBUGFS_ATTRIBUTE(fops_zynqmp_dp_active, zynqmp_dp_active_get, @@ -2102,9 +2083,8 @@ static int zynqmp_dp_swing_get(void *data, u64 *val) struct zynqmp_dp_train_set_priv *priv = data; struct zynqmp_dp *dp = priv->dp; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = dp->test.train_set[priv->lane] & DP_TRAIN_VOLTAGE_SWING_MASK; - mutex_unlock(&dp->lock); return 0; } @@ -2113,12 +2093,11 @@ static int zynqmp_dp_swing_set(void *data, u64 val) struct zynqmp_dp_train_set_priv *priv = data; struct zynqmp_dp *dp = priv->dp; u8 *train_set = &dp->test.train_set[priv->lane]; - int ret = 0; if (val > 3) return -EINVAL; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *train_set &= ~(DP_TRAIN_MAX_SWING_REACHED | DP_TRAIN_VOLTAGE_SWING_MASK); *train_set |= val; @@ -2126,10 +2105,9 @@ static int zynqmp_dp_swing_set(void *data, u64 val) *train_set |= DP_TRAIN_MAX_SWING_REACHED; if (dp->test.active) - ret = zynqmp_dp_update_vs_emph(dp, dp->test.train_set); - mutex_unlock(&dp->lock); + return zynqmp_dp_update_vs_emph(dp, dp->test.train_set); - return ret; + return 0; } DEFINE_DEBUGFS_ATTRIBUTE(fops_zynqmp_dp_swing, zynqmp_dp_swing_get, @@ -2140,10 +2118,9 @@ static int zynqmp_dp_preemphasis_get(void *data, u64 *val) struct zynqmp_dp_train_set_priv *priv = data; struct zynqmp_dp *dp = priv->dp; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = FIELD_GET(DP_TRAIN_PRE_EMPHASIS_MASK, dp->test.train_set[priv->lane]); - mutex_unlock(&dp->lock); return 0; } @@ -2152,12 +2129,11 @@ static int zynqmp_dp_preemphasis_set(void *data, u64 val) struct zynqmp_dp_train_set_priv *priv = data; struct zynqmp_dp *dp = priv->dp; u8 *train_set = &dp->test.train_set[priv->lane]; - int ret = 0; if (val > 2) return -EINVAL; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *train_set &= ~(DP_TRAIN_MAX_PRE_EMPHASIS_REACHED | DP_TRAIN_PRE_EMPHASIS_MASK); *train_set |= val; @@ -2165,10 +2141,9 @@ static int zynqmp_dp_preemphasis_set(void *data, u64 val) *train_set |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; if (dp->test.active) - ret = zynqmp_dp_update_vs_emph(dp, dp->test.train_set); - mutex_unlock(&dp->lock); + return zynqmp_dp_update_vs_emph(dp, dp->test.train_set); - return ret; + return 0; } DEFINE_DEBUGFS_ATTRIBUTE(fops_zynqmp_dp_preemphasis, zynqmp_dp_preemphasis_get, @@ -2178,31 +2153,24 @@ static int zynqmp_dp_lanes_get(void *data, u64 *val) { struct zynqmp_dp *dp = data; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = dp->test.link_cnt; - mutex_unlock(&dp->lock); return 0; } static int zynqmp_dp_lanes_set(void *data, u64 val) { struct zynqmp_dp *dp = data; - int ret = 0; if (val > ZYNQMP_DP_MAX_LANES) return -EINVAL; - mutex_lock(&dp->lock); - if (val > dp->num_lanes) { - ret = -EINVAL; - } else { - dp->test.link_cnt = val; - if (dp->test.active) - ret = zynqmp_dp_test_setup(dp); - } - mutex_unlock(&dp->lock); + guard(mutex)(&dp->lock); + if (val > dp->num_lanes) + return -EINVAL; - return ret; + dp->test.link_cnt = val; + return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; } DEFINE_DEBUGFS_ATTRIBUTE(fops_zynqmp_dp_lanes, zynqmp_dp_lanes_get, @@ -2212,9 +2180,8 @@ static int zynqmp_dp_rate_get(void *data, u64 *val) { struct zynqmp_dp *dp = data; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = drm_dp_bw_code_to_link_rate(dp->test.bw_code) * 10000ULL; - mutex_unlock(&dp->lock); return 0; } @@ -2222,7 +2189,6 @@ static int zynqmp_dp_rate_set(void *data, u64 val) { struct zynqmp_dp *dp = data; int link_rate; - int ret = 0; u8 bw_code; if (do_div(val, 10000)) @@ -2237,13 +2203,9 @@ static int zynqmp_dp_rate_set(void *data, u64 val) bw_code != DP_LINK_BW_5_4) return -EINVAL; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); dp->test.bw_code = bw_code; - if (dp->test.active) - ret = zynqmp_dp_test_setup(dp); - mutex_unlock(&dp->lock); - - return ret; + return dp->test.active ? zynqmp_dp_test_setup(dp) : 0; } DEFINE_DEBUGFS_ATTRIBUTE(fops_zynqmp_dp_rate, zynqmp_dp_rate_get, @@ -2253,9 +2215,8 @@ static int zynqmp_dp_ignore_aux_errors_get(void *data, u64 *val) { struct zynqmp_dp *dp = data; - mutex_lock(&dp->aux.hw_mutex); + guard(mutex)(&dp->lock); *val = dp->ignore_aux_errors; - mutex_unlock(&dp->aux.hw_mutex); return 0; } @@ -2266,9 +2227,8 @@ static int zynqmp_dp_ignore_aux_errors_set(void *data, u64 val) if (val != !!val) return -EINVAL; - mutex_lock(&dp->aux.hw_mutex); + guard(mutex)(&dp->lock); dp->ignore_aux_errors = val; - mutex_unlock(&dp->aux.hw_mutex); return 0; } @@ -2280,9 +2240,8 @@ static int zynqmp_dp_ignore_hpd_get(void *data, u64 *val) { struct zynqmp_dp *dp = data; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); *val = dp->ignore_hpd; - mutex_unlock(&dp->lock); return 0; } @@ -2293,9 +2252,8 @@ static int zynqmp_dp_ignore_hpd_set(void *data, u64 val) if (val != !!val) return -EINVAL; - mutex_lock(&dp->lock); + guard(mutex)(&dp->lock); dp->ignore_hpd = val; - mutex_unlock(&dp->lock); return 0; } @@ -2391,14 +2349,12 @@ static void zynqmp_dp_hpd_work_func(struct work_struct *work) struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp, hpd_work); enum drm_connector_status status; - mutex_lock(&dp->lock); - if (dp->ignore_hpd) { - mutex_unlock(&dp->lock); - return; - } + scoped_guard(mutex, &dp->lock) { + if (dp->ignore_hpd) + return; - status = __zynqmp_dp_bridge_detect(dp); - mutex_unlock(&dp->lock); + status = __zynqmp_dp_bridge_detect(dp); + } drm_bridge_hpd_notify(&dp->bridge, status); } @@ -2410,11 +2366,9 @@ static void zynqmp_dp_hpd_irq_work_func(struct work_struct *work) u8 status[DP_LINK_STATUS_SIZE + 2]; int err; - mutex_lock(&dp->lock); - if (dp->ignore_hpd) { - mutex_unlock(&dp->lock); + guard(mutex)(&dp->lock); + if (dp->ignore_hpd) return; - } err = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, status, DP_LINK_STATUS_SIZE + 2); @@ -2428,7 +2382,6 @@ static void zynqmp_dp_hpd_irq_work_func(struct work_struct *work) zynqmp_dp_train_loop(dp); } } - mutex_unlock(&dp->lock); } static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data) From f7d07bcd0651b90dda8a6962057eb5fb1807a089 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Wed, 28 Aug 2024 16:49:29 +0800 Subject: [PATCH 03/73] drm: zynqmp_dp: Use devm_platform_ioremap_resource_byname() platform_get_resource_byname() and devm_ioremap_resource() can be replaced by devm_platform_ioremap_resource_byname(), which can simplify the code logic a bit, No functional change here. Signed-off-by: Jinjie Ruan Reviewed-by: Laurent Pinchart Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20240828084929.2527228-1-ruanjinjie@huawei.com --- drivers/gpu/drm/xlnx/zynqmp_dp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index 63842f657836..e3bf97a4a3c5 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -2436,7 +2436,6 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) struct platform_device *pdev = to_platform_device(dpsub->dev); struct drm_bridge *bridge; struct zynqmp_dp *dp; - struct resource *res; int ret; dp = kzalloc(sizeof(*dp), GFP_KERNEL); @@ -2453,8 +2452,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub) INIT_WORK(&dp->hpd_irq_work, zynqmp_dp_hpd_irq_work_func); /* Acquire all resources (IOMEM, IRQ and PHYs). */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp"); - dp->iomem = devm_ioremap_resource(dp->dev, res); + dp->iomem = devm_platform_ioremap_resource_byname(pdev, "dp"); if (IS_ERR(dp->iomem)) { ret = PTR_ERR(dp->iomem); goto err_free; From 48ca4a1faafd1dbd5009bad9b32ee75e3b6317cc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 22 Jan 2025 16:41:33 +0200 Subject: [PATCH 04/73] drm/client: include types.h to make drm_client_event.h self-contained drm_client_event.h uses bool without types.h, include it. Fixes: bf17766f1083 ("drm/client: Move suspend/resume into DRM client callbacks") Cc: Thomas Zimmermann Acked-by: Simona Vetter Link: https://patchwork.freedesktop.org/patch/msgid/6c69cb005cc3a2b968b6c9675d0ba03173f6c574.1737556766.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- include/drm/drm_client_event.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_client_event.h b/include/drm/drm_client_event.h index 99863554b055..1d544d3a3228 100644 --- a/include/drm/drm_client_event.h +++ b/include/drm/drm_client_event.h @@ -3,6 +3,8 @@ #ifndef _DRM_CLIENT_EVENT_H_ #define _DRM_CLIENT_EVENT_H_ +#include + struct drm_device; #if defined(CONFIG_DRM_CLIENT) From 62ae45687e43574f6c13158f8b8c5e10d3d22fc4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 22 Jan 2025 16:41:34 +0200 Subject: [PATCH 05/73] drm: ensure drm headers are self-contained and pass kernel-doc Ensure drm headers build, are self-contained, have header guards, and have no kernel-doc warnings, when CONFIG_DRM_HEADER_TEST=y. The mechanism follows similar patters used in i915, xe, and usr/include. To cover include/drm, we need to recurse there using the top level Kbuild and the new include/Kbuild files. v4: check for CONFIG_WERROR in addition to CONFIG_DRM_WERROR v3: adapt to upstream build changes v2: make DRM_HEADER_TEST depend on DRM Suggested-by: Daniel Vetter Cc: David Airlie Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: Masahiro Yamada Acked-by: Thomas Zimmermann Acked-by: Simona Vetter Link: https://patchwork.freedesktop.org/patch/msgid/d8ad1c6d707f38a55987f616cb9650aef30b84e1.1737556766.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- Kbuild | 1 + drivers/gpu/drm/Kconfig | 11 +++++++++++ drivers/gpu/drm/Makefile | 18 ++++++++++++++++++ include/Kbuild | 1 + include/drm/Makefile | 18 ++++++++++++++++++ 5 files changed, 49 insertions(+) create mode 100644 include/Kbuild create mode 100644 include/drm/Makefile diff --git a/Kbuild b/Kbuild index 464b34a08f51..f327ca86990c 100644 --- a/Kbuild +++ b/Kbuild @@ -97,3 +97,4 @@ obj-$(CONFIG_SAMPLES) += samples/ obj-$(CONFIG_NET) += net/ obj-y += virt/ obj-y += $(ARCH_DRIVERS) +obj-$(CONFIG_DRM_HEADER_TEST) += include/ diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index fbef3f471bd0..f9b3ebf63fa9 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -494,6 +494,17 @@ config DRM_WERROR If in doubt, say N. +config DRM_HEADER_TEST + bool "Ensure DRM headers are self-contained and pass kernel-doc" + depends on DRM && EXPERT + default n + help + Ensure the DRM subsystem headers both under drivers/gpu/drm and + include/drm compile, are self-contained, have header guards, and have + no kernel-doc warnings. + + If in doubt, say N. + endif # Separate option because drm_panel_orientation_quirks.c is shared with fbdev diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 85af94bb907d..42901f877bf2 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -222,3 +222,21 @@ obj-y += solomon/ obj-$(CONFIG_DRM_SPRD) += sprd/ obj-$(CONFIG_DRM_LOONGSON) += loongson/ obj-$(CONFIG_DRM_POWERVR) += imagination/ + +# Ensure drm headers are self-contained and pass kernel-doc +hdrtest-files := \ + $(shell cd $(src) && find . -maxdepth 1 -name 'drm_*.h') \ + $(shell cd $(src) && find display lib -name '*.h') + +always-$(CONFIG_DRM_HEADER_TEST) += \ + $(patsubst %.h,%.hdrtest, $(hdrtest-files)) + +# Include the header twice to detect missing include guard. +quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) + cmd_hdrtest = \ + $(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \ + $(srctree)/scripts/kernel-doc -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ + touch $@ + +$(obj)/%.hdrtest: $(src)/%.h FORCE + $(call if_changed_dep,hdrtest) diff --git a/include/Kbuild b/include/Kbuild new file mode 100644 index 000000000000..5e76a599e2dd --- /dev/null +++ b/include/Kbuild @@ -0,0 +1 @@ +obj-$(CONFIG_DRM_HEADER_TEST) += drm/ diff --git a/include/drm/Makefile b/include/drm/Makefile new file mode 100644 index 000000000000..a7bd15d2803e --- /dev/null +++ b/include/drm/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 + +# Ensure drm headers are self-contained and pass kernel-doc +hdrtest-files := \ + $(shell cd $(src) && find * -name '*.h' 2>/dev/null) + +always-$(CONFIG_DRM_HEADER_TEST) += \ + $(patsubst %.h,%.hdrtest, $(hdrtest-files)) + +# Include the header twice to detect missing include guard. +quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) + cmd_hdrtest = \ + $(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \ + $(srctree)/scripts/kernel-doc -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ + touch $@ + +$(obj)/%.hdrtest: $(src)/%.h FORCE + $(call if_changed_dep,hdrtest) From 796a9f55a8d1d85387b973df9a06cbf4bc2d6327 Mon Sep 17 00:00:00 2001 From: Philipp Stanner Date: Tue, 11 Feb 2025 12:14:23 +0100 Subject: [PATCH 06/73] drm/sched: Use struct for drm_sched_init() params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_sched_init() has a great many parameters and upcoming new functionality for the scheduler might add even more. Generally, the great number of parameters reduces readability and has already caused one missnaming, addressed in: commit 6f1cacf4eba7 ("drm/nouveau: Improve variable name in nouveau_sched_init()"). Introduce a new struct for the scheduler init parameters and port all users. Reviewed-by: Liviu Dudau Acked-by: Matthew Brost # for Xe Reviewed-by: Boris Brezillon # for Panfrost and Panthor Reviewed-by: Christian Gmeiner # for Etnaviv Reviewed-by: Frank Binns # for Imagination Reviewed-by: Tvrtko Ursulin # for Sched Reviewed-by: Maíra Canal # for v3d Reviewed-by: Danilo Krummrich Reviewed-by: Lizhi Hou # for amdxdna Signed-off-by: Philipp Stanner Link: https://patchwork.freedesktop.org/patch/msgid/20250211111422.21235-2-phasta@kernel.org --- drivers/accel/amdxdna/aie2_ctx.c | 12 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 18 ++++-- drivers/gpu/drm/etnaviv/etnaviv_sched.c | 20 +++---- drivers/gpu/drm/imagination/pvr_queue.c | 18 ++++-- drivers/gpu/drm/lima/lima_sched.c | 16 ++++-- drivers/gpu/drm/msm/msm_ringbuffer.c | 17 +++--- drivers/gpu/drm/nouveau/nouveau_sched.c | 16 ++++-- drivers/gpu/drm/panfrost/panfrost_job.c | 20 ++++--- drivers/gpu/drm/panthor/panthor_mmu.c | 16 ++++-- drivers/gpu/drm/panthor/panthor_sched.c | 28 ++++++---- drivers/gpu/drm/scheduler/sched_main.c | 50 ++++++----------- drivers/gpu/drm/v3d/v3d_sched.c | 65 +++++++++------------- drivers/gpu/drm/xe/xe_execlist.c | 15 +++-- drivers/gpu/drm/xe/xe_gpu_scheduler.c | 17 +++++- include/drm/gpu_scheduler.h | 36 ++++++++++-- 15 files changed, 210 insertions(+), 154 deletions(-) diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 2799729801f6..8ac01bc2f0db 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -516,6 +516,14 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) { struct amdxdna_client *client = hwctx->client; struct amdxdna_dev *xdna = client->xdna; + const struct drm_sched_init_args args = { + .ops = &sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = HWCTX_MAX_CMDS, + .timeout = msecs_to_jiffies(HWCTX_MAX_TIMEOUT), + .name = hwctx->name, + .dev = xdna->ddev.dev, + }; struct drm_gpu_scheduler *sched; struct amdxdna_hwctx_priv *priv; struct amdxdna_gem_obj *heap; @@ -573,9 +581,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) might_lock(&priv->io_lock); fs_reclaim_release(GFP_KERNEL); - ret = drm_sched_init(sched, &sched_ops, NULL, DRM_SCHED_PRIORITY_COUNT, - HWCTX_MAX_CMDS, 0, msecs_to_jiffies(HWCTX_MAX_TIMEOUT), - NULL, NULL, hwctx->name, xdna->ddev.dev); + ret = drm_sched_init(sched, &args); if (ret) { XDNA_ERR(xdna, "Failed to init DRM scheduler. ret %d", ret); goto free_cmd_bufs; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d100bb7a137c..6800f72fafd2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2823,6 +2823,12 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) static int amdgpu_device_init_schedulers(struct amdgpu_device *adev) { + struct drm_sched_init_args args = { + .ops = &amdgpu_sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .timeout_wq = adev->reset_domain->wq, + .dev = adev->dev, + }; long timeout; int r, i; @@ -2848,12 +2854,12 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev) break; } - r = drm_sched_init(&ring->sched, &amdgpu_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - ring->num_hw_submission, 0, - timeout, adev->reset_domain->wq, - ring->sched_score, ring->name, - adev->dev); + args.timeout = timeout; + args.credit_limit = ring->num_hw_submission; + args.score = ring->sched_score; + args.name = ring->name; + + r = drm_sched_init(&ring->sched, &args); if (r) { DRM_ERROR("Failed to create scheduler on ring %s.\n", ring->name); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 5b67eda122db..76a3a3e517d8 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -144,17 +144,17 @@ int etnaviv_sched_push_job(struct etnaviv_gem_submit *submit) int etnaviv_sched_init(struct etnaviv_gpu *gpu) { - int ret; + const struct drm_sched_init_args args = { + .ops = &etnaviv_sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = etnaviv_hw_jobs_limit, + .hang_limit = etnaviv_job_hang_limit, + .timeout = msecs_to_jiffies(500), + .name = dev_name(gpu->dev), + .dev = gpu->dev, + }; - ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - etnaviv_hw_jobs_limit, etnaviv_job_hang_limit, - msecs_to_jiffies(500), NULL, NULL, - dev_name(gpu->dev), gpu->dev); - if (ret) - return ret; - - return 0; + return drm_sched_init(&gpu->sched, &args); } void etnaviv_sched_fini(struct etnaviv_gpu *gpu) diff --git a/drivers/gpu/drm/imagination/pvr_queue.c b/drivers/gpu/drm/imagination/pvr_queue.c index c4f08432882b..21c185d18bb2 100644 --- a/drivers/gpu/drm/imagination/pvr_queue.c +++ b/drivers/gpu/drm/imagination/pvr_queue.c @@ -1210,6 +1210,17 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx, }, }; struct pvr_device *pvr_dev = ctx->pvr_dev; + const struct drm_sched_init_args sched_args = { + .ops = &pvr_queue_sched_ops, + .submit_wq = pvr_dev->sched_wq, + .num_rqs = 1, + .credit_limit = 64 * 1024, + .hang_limit = 1, + .timeout = msecs_to_jiffies(500), + .timeout_wq = pvr_dev->sched_wq, + .name = "pvr-queue", + .dev = pvr_dev->base.dev, + }; struct drm_gpu_scheduler *sched; struct pvr_queue *queue; int ctx_state_size, err; @@ -1282,12 +1293,7 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx, queue->timeline_ufo.value = cpu_map; - err = drm_sched_init(&queue->scheduler, - &pvr_queue_sched_ops, - pvr_dev->sched_wq, 1, 64 * 1024, 1, - msecs_to_jiffies(500), - pvr_dev->sched_wq, NULL, "pvr-queue", - pvr_dev->base.dev); + err = drm_sched_init(&queue->scheduler, &sched_args); if (err) goto err_release_ufo; diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index b40c90e97d7e..825135a26aa4 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -515,18 +515,22 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name) { unsigned int timeout = lima_sched_timeout_ms > 0 ? lima_sched_timeout_ms : 10000; + const struct drm_sched_init_args args = { + .ops = &lima_sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = 1, + .hang_limit = lima_job_hang_limit, + .timeout = msecs_to_jiffies(timeout), + .name = name, + .dev = pipe->ldev->dev, + }; pipe->fence_context = dma_fence_context_alloc(1); spin_lock_init(&pipe->fence_lock); INIT_WORK(&pipe->recover_work, lima_sched_recover_work); - return drm_sched_init(&pipe->base, &lima_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - 1, - lima_job_hang_limit, - msecs_to_jiffies(timeout), NULL, - NULL, name, pipe->ldev->dev); + return drm_sched_init(&pipe->base, &args); } void lima_sched_pipe_fini(struct lima_sched_pipe *pipe) diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index c803556a8f64..c5651c39ac2a 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -59,8 +59,14 @@ static const struct drm_sched_backend_ops msm_sched_ops = { struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, void *memptrs, uint64_t memptrs_iova) { + struct drm_sched_init_args args = { + .ops = &msm_sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = num_hw_submissions, + .timeout = MAX_SCHEDULE_TIMEOUT, + .dev = gpu->dev->dev, + }; struct msm_ringbuffer *ring; - long sched_timeout; char name[32]; int ret; @@ -87,6 +93,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, } msm_gem_object_set_name(ring->bo, "ring%d", id); + args.name = to_msm_bo(ring->bo)->name, ring->end = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2); ring->next = ring->start; @@ -95,13 +102,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, ring->memptrs = memptrs; ring->memptrs_iova = memptrs_iova; - /* currently managing hangcheck ourselves: */ - sched_timeout = MAX_SCHEDULE_TIMEOUT; - - ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - num_hw_submissions, 0, sched_timeout, - NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev); + ret = drm_sched_init(&ring->sched, &args); if (ret) { goto fail; } diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c index 4412f2711fb5..d326e55d2d24 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sched.c +++ b/drivers/gpu/drm/nouveau/nouveau_sched.c @@ -404,7 +404,14 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, { struct drm_gpu_scheduler *drm_sched = &sched->base; struct drm_sched_entity *entity = &sched->entity; - const long timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); + struct drm_sched_init_args args = { + .ops = &nouveau_sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = credit_limit, + .timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS), + .name = "nouveau_sched", + .dev = drm->dev->dev + }; int ret; if (!wq) { @@ -416,10 +423,9 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, sched->wq = wq; } - ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, - NOUVEAU_SCHED_PRIORITY_COUNT, - credit_limit, 0, timeout, - NULL, NULL, "nouveau_sched", drm->dev->dev); + args.submit_wq = wq, + + ret = drm_sched_init(drm_sched, &args); if (ret) goto fail_wq; diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 9b8e82fb8bc4..5657106c2f7d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -836,8 +836,16 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data) int panfrost_job_init(struct panfrost_device *pfdev) { + struct drm_sched_init_args args = { + .ops = &panfrost_sched_ops, + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = 2, + .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), + .timeout_wq = pfdev->reset.wq, + .name = "pan_js", + .dev = pfdev->dev, + }; struct panfrost_job_slot *js; - unsigned int nentries = 2; int ret, j; /* All GPUs have two entries per queue, but without jobchain @@ -845,7 +853,7 @@ int panfrost_job_init(struct panfrost_device *pfdev) * so let's just advertise one entry in that case. */ if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_JOBCHAIN_DISAMBIGUATION)) - nentries = 1; + args.credit_limit = 1; pfdev->js = js = devm_kzalloc(pfdev->dev, sizeof(*js), GFP_KERNEL); if (!js) @@ -875,13 +883,7 @@ int panfrost_job_init(struct panfrost_device *pfdev) for (j = 0; j < NUM_JOB_SLOTS; j++) { js->queue[j].fence_context = dma_fence_context_alloc(1); - ret = drm_sched_init(&js->queue[j].sched, - &panfrost_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - nentries, 0, - msecs_to_jiffies(JOB_TIMEOUT_MS), - pfdev->reset.wq, - NULL, "pan_js", pfdev->dev); + ret = drm_sched_init(&js->queue[j].sched, &args); if (ret) { dev_err(pfdev->dev, "Failed to create scheduler: %d.", ret); goto err_sched; diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c index 0a4e352b5505..8c6fc587ddc3 100644 --- a/drivers/gpu/drm/panthor/panthor_mmu.c +++ b/drivers/gpu/drm/panthor/panthor_mmu.c @@ -2311,6 +2311,16 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, u64 full_va_range = 1ull << va_bits; struct drm_gem_object *dummy_gem; struct drm_gpu_scheduler *sched; + const struct drm_sched_init_args sched_args = { + .ops = &panthor_vm_bind_ops, + .submit_wq = ptdev->mmu->vm.wq, + .num_rqs = 1, + .credit_limit = 1, + /* Bind operations are synchronous for now, no timeout needed. */ + .timeout = MAX_SCHEDULE_TIMEOUT, + .name = "panthor-vm-bind", + .dev = ptdev->base.dev, + }; struct io_pgtable_cfg pgtbl_cfg; u64 mair, min_va, va_range; struct panthor_vm *vm; @@ -2368,11 +2378,7 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu, goto err_mm_takedown; } - /* Bind operations are synchronous for now, no timeout needed. */ - ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, ptdev->mmu->vm.wq, - 1, 1, 0, - MAX_SCHEDULE_TIMEOUT, NULL, NULL, - "panthor-vm-bind", ptdev->base.dev); + ret = drm_sched_init(&vm->sched, &sched_args); if (ret) goto err_free_io_pgtable; diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c index 0b93bf83a9b2..1a276db095ff 100644 --- a/drivers/gpu/drm/panthor/panthor_sched.c +++ b/drivers/gpu/drm/panthor/panthor_sched.c @@ -3289,6 +3289,22 @@ static struct panthor_queue * group_create_queue(struct panthor_group *group, const struct drm_panthor_queue_create *args) { + const struct drm_sched_init_args sched_args = { + .ops = &panthor_queue_sched_ops, + .submit_wq = group->ptdev->scheduler->wq, + .num_rqs = 1, + /* + * The credit limit argument tells us the total number of + * instructions across all CS slots in the ringbuffer, with + * some jobs requiring twice as many as others, depending on + * their profiling status. + */ + .credit_limit = args->ringbuf_size / sizeof(u64), + .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), + .timeout_wq = group->ptdev->reset.wq, + .name = "panthor-queue", + .dev = group->ptdev->base.dev, + }; struct drm_gpu_scheduler *drm_sched; struct panthor_queue *queue; int ret; @@ -3359,17 +3375,7 @@ group_create_queue(struct panthor_group *group, if (ret) goto err_free_queue; - /* - * Credit limit argument tells us the total number of instructions - * across all CS slots in the ringbuffer, with some jobs requiring - * twice as many as others, depending on their profiling status. - */ - ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops, - group->ptdev->scheduler->wq, 1, - args->ringbuf_size / sizeof(u64), - 0, msecs_to_jiffies(JOB_TIMEOUT_MS), - group->ptdev->reset.wq, - NULL, "panthor-queue", group->ptdev->base.dev); + ret = drm_sched_init(&queue->scheduler, &sched_args); if (ret) goto err_free_queue; diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index a48be16ab84f..8c36a59afb72 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -1244,40 +1244,24 @@ static void drm_sched_run_job_work(struct work_struct *w) * drm_sched_init - Init a gpu scheduler instance * * @sched: scheduler instance - * @ops: backend operations for this scheduler - * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is - * allocated and used - * @num_rqs: number of runqueues, one for each priority, up to DRM_SCHED_PRIORITY_COUNT - * @credit_limit: the number of credits this scheduler can hold from all jobs - * @hang_limit: number of times to allow a job to hang before dropping it - * @timeout: timeout value in jiffies for the scheduler - * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is - * used - * @score: optional score atomic shared with other schedulers - * @name: name used for debugging - * @dev: target &struct device + * @args: scheduler initialization arguments * * Return 0 on success, otherwise error code. */ -int drm_sched_init(struct drm_gpu_scheduler *sched, - const struct drm_sched_backend_ops *ops, - struct workqueue_struct *submit_wq, - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, - long timeout, struct workqueue_struct *timeout_wq, - atomic_t *score, const char *name, struct device *dev) +int drm_sched_init(struct drm_gpu_scheduler *sched, const struct drm_sched_init_args *args) { int i; - sched->ops = ops; - sched->credit_limit = credit_limit; - sched->name = name; - sched->timeout = timeout; - sched->timeout_wq = timeout_wq ? : system_wq; - sched->hang_limit = hang_limit; - sched->score = score ? score : &sched->_score; - sched->dev = dev; + sched->ops = args->ops; + sched->credit_limit = args->credit_limit; + sched->name = args->name; + sched->timeout = args->timeout; + sched->hang_limit = args->hang_limit; + sched->timeout_wq = args->timeout_wq ? args->timeout_wq : system_wq; + sched->score = args->score ? args->score : &sched->_score; + sched->dev = args->dev; - if (num_rqs > DRM_SCHED_PRIORITY_COUNT) { + if (args->num_rqs > DRM_SCHED_PRIORITY_COUNT) { /* This is a gross violation--tell drivers what the problem is. */ drm_err(sched, "%s: num_rqs cannot be greater than DRM_SCHED_PRIORITY_COUNT\n", @@ -1292,16 +1276,16 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, return 0; } - if (submit_wq) { - sched->submit_wq = submit_wq; + if (args->submit_wq) { + sched->submit_wq = args->submit_wq; sched->own_submit_wq = false; } else { #ifdef CONFIG_LOCKDEP - sched->submit_wq = alloc_ordered_workqueue_lockdep_map(name, + sched->submit_wq = alloc_ordered_workqueue_lockdep_map(args->name, WQ_MEM_RECLAIM, &drm_sched_lockdep_map); #else - sched->submit_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM); + sched->submit_wq = alloc_ordered_workqueue(args->name, WQ_MEM_RECLAIM); #endif if (!sched->submit_wq) return -ENOMEM; @@ -1309,11 +1293,11 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, sched->own_submit_wq = true; } - sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq), + sched->sched_rq = kmalloc_array(args->num_rqs, sizeof(*sched->sched_rq), GFP_KERNEL | __GFP_ZERO); if (!sched->sched_rq) goto Out_check_own; - sched->num_rqs = num_rqs; + sched->num_rqs = args->num_rqs; for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) { sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL); if (!sched->sched_rq[i]) diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 961465128d80..80466ce8c7df 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -820,67 +820,54 @@ static const struct drm_sched_backend_ops v3d_cpu_sched_ops = { .free_job = v3d_cpu_job_free }; +static int +v3d_queue_sched_init(struct v3d_dev *v3d, const struct drm_sched_backend_ops *ops, + enum v3d_queue queue, const char *name) +{ + struct drm_sched_init_args args = { + .num_rqs = DRM_SCHED_PRIORITY_COUNT, + .credit_limit = 1, + .timeout = msecs_to_jiffies(500), + .dev = v3d->drm.dev, + }; + + args.ops = ops; + args.name = name; + + return drm_sched_init(&v3d->queue[queue].sched, &args); +} + int v3d_sched_init(struct v3d_dev *v3d) { - int hw_jobs_limit = 1; - int job_hang_limit = 0; - int hang_limit_ms = 500; int ret; - ret = drm_sched_init(&v3d->queue[V3D_BIN].sched, - &v3d_bin_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_bin", v3d->drm.dev); + ret = v3d_queue_sched_init(v3d, &v3d_bin_sched_ops, V3D_BIN, "v3d_bin"); if (ret) return ret; - ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched, - &v3d_render_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_render", v3d->drm.dev); + ret = v3d_queue_sched_init(v3d, &v3d_render_sched_ops, V3D_RENDER, + "v3d_render"); if (ret) goto fail; - ret = drm_sched_init(&v3d->queue[V3D_TFU].sched, - &v3d_tfu_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_tfu", v3d->drm.dev); + ret = v3d_queue_sched_init(v3d, &v3d_tfu_sched_ops, V3D_TFU, "v3d_tfu"); if (ret) goto fail; if (v3d_has_csd(v3d)) { - ret = drm_sched_init(&v3d->queue[V3D_CSD].sched, - &v3d_csd_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_csd", v3d->drm.dev); + ret = v3d_queue_sched_init(v3d, &v3d_csd_sched_ops, V3D_CSD, + "v3d_csd"); if (ret) goto fail; - ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched, - &v3d_cache_clean_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - hw_jobs_limit, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_cache_clean", v3d->drm.dev); + ret = v3d_queue_sched_init(v3d, &v3d_cache_clean_sched_ops, + V3D_CACHE_CLEAN, "v3d_cache_clean"); if (ret) goto fail; } - ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, - &v3d_cpu_sched_ops, NULL, - DRM_SCHED_PRIORITY_COUNT, - 1, job_hang_limit, - msecs_to_jiffies(hang_limit_ms), NULL, - NULL, "v3d_cpu", v3d->drm.dev); + ret = v3d_queue_sched_init(v3d, &v3d_cpu_sched_ops, V3D_CPU, "v3d_cpu"); if (ret) goto fail; diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 5ef96deaa881..66001af5cf55 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -336,6 +336,15 @@ static const struct drm_sched_backend_ops drm_sched_ops = { static int execlist_exec_queue_init(struct xe_exec_queue *q) { struct drm_gpu_scheduler *sched; + const struct drm_sched_init_args args = { + .ops = &drm_sched_ops, + .num_rqs = 1, + .credit_limit = q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, + .hang_limit = XE_SCHED_HANG_LIMIT, + .timeout = XE_SCHED_JOB_TIMEOUT, + .name = q->hwe->name, + .dev = gt_to_xe(q->gt)->drm.dev, + }; struct xe_execlist_exec_queue *exl; struct xe_device *xe = gt_to_xe(q->gt); int err; @@ -350,11 +359,7 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q) exl->q = q; - err = drm_sched_init(&exl->sched, &drm_sched_ops, NULL, 1, - q->lrc[0]->ring.size / MAX_JOB_SIZE_BYTES, - XE_SCHED_HANG_LIMIT, XE_SCHED_JOB_TIMEOUT, - NULL, NULL, q->hwe->name, - gt_to_xe(q->gt)->drm.dev); + err = drm_sched_init(&exl->sched, &args); if (err) goto err_free; diff --git a/drivers/gpu/drm/xe/xe_gpu_scheduler.c b/drivers/gpu/drm/xe/xe_gpu_scheduler.c index 50361b4638f9..869b43a4151d 100644 --- a/drivers/gpu/drm/xe/xe_gpu_scheduler.c +++ b/drivers/gpu/drm/xe/xe_gpu_scheduler.c @@ -63,13 +63,24 @@ int xe_sched_init(struct xe_gpu_scheduler *sched, atomic_t *score, const char *name, struct device *dev) { + const struct drm_sched_init_args args = { + .ops = ops, + .submit_wq = submit_wq, + .num_rqs = 1, + .credit_limit = hw_submission, + .hang_limit = hang_limit, + .timeout = timeout, + .timeout_wq = timeout_wq, + .score = score, + .name = name, + .dev = dev, + }; + sched->ops = xe_ops; INIT_LIST_HEAD(&sched->msgs); INIT_WORK(&sched->work_process_msg, xe_sched_process_msg_work); - return drm_sched_init(&sched->base, ops, submit_wq, 1, hw_submission, - hang_limit, timeout, timeout_wq, score, name, - dev); + return drm_sched_init(&sched->base, &args); } void xe_sched_fini(struct xe_gpu_scheduler *sched) diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index cf88f2bd020f..6bf458dbce84 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -540,12 +540,38 @@ struct drm_gpu_scheduler { struct device *dev; }; +/** + * struct drm_sched_init_args - parameters for initializing a DRM GPU scheduler + * + * @ops: backend operations provided by the driver + * @submit_wq: workqueue to use for submission. If NULL, an ordered wq is + * allocated and used. + * @num_rqs: Number of run-queues. This may be at most DRM_SCHED_PRIORITY_COUNT, + * as there's usually one run-queue per priority, but may be less. + * @credit_limit: the number of credits this scheduler can hold from all jobs + * @hang_limit: number of times to allow a job to hang before dropping it. + * This mechanism is DEPRECATED. Set it to 0. + * @timeout: timeout value in jiffies for submitted jobs. + * @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is used. + * @score: score atomic shared with other schedulers. May be NULL. + * @name: name (typically the driver's name). Used for debugging + * @dev: associated device. Used for debugging + */ +struct drm_sched_init_args { + const struct drm_sched_backend_ops *ops; + struct workqueue_struct *submit_wq; + struct workqueue_struct *timeout_wq; + u32 num_rqs; + u32 credit_limit; + unsigned int hang_limit; + long timeout; + atomic_t *score; + const char *name; + struct device *dev; +}; + int drm_sched_init(struct drm_gpu_scheduler *sched, - const struct drm_sched_backend_ops *ops, - struct workqueue_struct *submit_wq, - u32 num_rqs, u32 credit_limit, unsigned int hang_limit, - long timeout, struct workqueue_struct *timeout_wq, - atomic_t *score, const char *name, struct device *dev); + const struct drm_sched_init_args *args); void drm_sched_fini(struct drm_gpu_scheduler *sched); int drm_sched_job_init(struct drm_sched_job *job, From 4dd40b5f9c3d89b67af0dbe059cf4a51aac6bf06 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Sat, 1 Feb 2025 13:50:46 +0100 Subject: [PATCH 07/73] drm/v3d: Add clock handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the initial commit 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") the struct v3d_dev reserved a pointer for an optional V3D clock. But there wasn't any code, which fetched it. So add the missing clock handling before accessing any V3D registers. Signed-off-by: Stefan Wahren Reviewed-by: Maíra Canal Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20250201125046.33030-1-wahrenst@gmx.net --- drivers/gpu/drm/v3d/v3d_drv.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 930737a9347b..852015214e97 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -295,11 +295,21 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) if (ret) return ret; + v3d->clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(v3d->clk)) + return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n"); + + ret = clk_prepare_enable(v3d->clk); + if (ret) { + dev_err(&pdev->dev, "Couldn't enable the V3D clock\n"); + return ret; + } + mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO); mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)); ret = dma_set_mask_and_coherent(dev, mask); if (ret) - return ret; + goto clk_disable; v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH); @@ -319,28 +329,29 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) ret = PTR_ERR(v3d->reset); if (ret == -EPROBE_DEFER) - return ret; + goto clk_disable; v3d->reset = NULL; ret = map_regs(v3d, &v3d->bridge_regs, "bridge"); if (ret) { dev_err(dev, "Failed to get reset control or bridge regs\n"); - return ret; + goto clk_disable; } } if (v3d->ver < 41) { ret = map_regs(v3d, &v3d->gca_regs, "gca"); if (ret) - return ret; + goto clk_disable; } v3d->mmu_scratch = dma_alloc_wc(dev, 4096, &v3d->mmu_scratch_paddr, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); if (!v3d->mmu_scratch) { dev_err(dev, "Failed to allocate MMU scratch page\n"); - return -ENOMEM; + ret = -ENOMEM; + goto clk_disable; } ret = v3d_gem_init(drm); @@ -369,6 +380,8 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) v3d_gem_destroy(drm); dma_free: dma_free_wc(dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr); +clk_disable: + clk_disable_unprepare(v3d->clk); return ret; } @@ -386,6 +399,8 @@ static void v3d_platform_drm_remove(struct platform_device *pdev) dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr); + + clk_disable_unprepare(v3d->clk); } static struct platform_driver v3d_platform_driver = { From e6a7b473699c6a9e3ec1f74ce3ff96a8f396fe48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Thu, 6 Feb 2025 11:35:44 +0100 Subject: [PATCH 08/73] MAINTAINERS: Add TTM reviewers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Matthew Auld and Matthew Brost as TTM reviewers Cc: Matthew Auld Cc: Matthew Brost Cc: Christian König Cc: Dave Airlie Cc: Simona Vetter Cc: dri-devel@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Thomas Hellström Reviewed-by: Christian König Acked-by: Matthew Auld Acked-by: Nirmoy Das Acked-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250206103544.36971-1-thomas.hellstrom@linux.intel.com --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1c5b22f00434..8aef574769a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8007,6 +8007,8 @@ F: include/drm/drm_privacy_screen* DRM TTM SUBSYSTEM M: Christian Koenig M: Huang Rui +R: Matthew Auld +R: Matthew Brost L: dri-devel@lists.freedesktop.org S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git From f4dd4cb79f9ec3294e5100223ed90d8ae371f168 Mon Sep 17 00:00:00 2001 From: Tejas Vipin Date: Mon, 10 Feb 2025 14:53:42 +0530 Subject: [PATCH 09/73] drm/panel: visionox-r66451: transition to mipi_dsi wrapped functions Change the visionox-r66451 panel to use multi style functions for improved error handling. Additionally, always drop LPM flag after sending init sequence. Signed-off-by: Tejas Vipin Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20250210092342.287324-1-tejasvipin76@gmail.com --- drivers/gpu/drm/panel/panel-visionox-r66451.c | 181 ++++++++---------- 1 file changed, 77 insertions(+), 104 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-visionox-r66451.c b/drivers/gpu/drm/panel/panel-visionox-r66451.c index 493f2a6076f8..3ea0a86f6e69 100644 --- a/drivers/gpu/drm/panel/panel-visionox-r66451.c +++ b/drivers/gpu/drm/panel/panel-visionox-r66451.c @@ -42,85 +42,84 @@ static void visionox_r66451_reset(struct visionox_r66451 *ctx) static int visionox_r66451_on(struct visionox_r66451 *ctx) { struct mipi_dsi_device *dsi = ctx->dsi; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; dsi->mode_flags |= MIPI_DSI_MODE_LPM; - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc2, - 0x09, 0x24, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x09, 0x3c); - mipi_dsi_dcs_write_seq(dsi, 0xd7, - 0x00, 0xb9, 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, - 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xde, - 0x40, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, - 0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xe8, 0x00, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x00, 0x08); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xc4, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32); - mipi_dsi_dcs_write_seq(dsi, 0xcf, - 0x64, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x0b, 0x77, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x03); - mipi_dsi_dcs_write_seq(dsi, 0xd3, - 0x45, 0x00, 0x00, 0x01, 0x13, 0x15, 0x00, 0x15, 0x07, - 0x0f, 0x77, 0x77, 0x77, 0x37, 0xb2, 0x11, 0x00, 0xa0, - 0x3c, 0x9c); - mipi_dsi_dcs_write_seq(dsi, 0xd7, - 0x00, 0xb9, 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, - 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xd8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, - 0x00, 0x32, 0x00, 0x0a, 0x00, 0x22); - mipi_dsi_dcs_write_seq(dsi, 0xdf, - 0x50, 0x42, 0x58, 0x81, 0x2d, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x0f, 0xff, 0xd4, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x53, 0xf1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x80); - mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x34, 0xb4, 0x00, 0x00, 0x00, 0x39, 0x04, 0x09, 0x34); - mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x04); - mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x50, 0x40); - mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x50, 0x00, 0x00, 0x00, 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x11); - mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01); - mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x00, 0x02); - mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x19); - mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x50, 0x42); - mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - mipi_dsi_dcs_set_column_address(dsi, 0, 1080 - 1); - mipi_dsi_dcs_set_page_address(dsi, 0, 2340 - 1); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2, + 0x09, 0x24, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x09, 0x3c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd7, + 0x00, 0xb9, 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, + 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xde, + 0x40, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, + 0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe8, 0x00, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0x00, 0x08); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcf, + 0x64, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x0b, 0x77, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd3, + 0x45, 0x00, 0x00, 0x01, 0x13, 0x15, 0x00, 0x15, 0x07, + 0x0f, 0x77, 0x77, 0x77, 0x37, 0xb2, 0x11, 0x00, 0xa0, + 0x3c, 0x9c); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd7, + 0x00, 0xb9, 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, + 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x32, 0x00, 0x0a, 0x00, 0x22); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, + 0x50, 0x42, 0x58, 0x81, 0x2d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x0f, 0xff, 0xd4, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x53, 0xf1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x80); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0x34, 0xb4, 0x00, 0x00, 0x00, 0x39, + 0x04, 0x09, 0x34); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x50, 0x40); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x50, 0x00, 0x00, 0x00, 0x00); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x11); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, 0x00, 0x02); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x19); + mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x50, 0x42); + mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0, 1080 - 1); + mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0, 2340 - 1); dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - return 0; + return dsi_ctx.accum_err; } -static int visionox_r66451_off(struct visionox_r66451 *ctx) +static void visionox_r66451_off(struct visionox_r66451 *ctx) { ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; - return 0; } static int visionox_r66451_prepare(struct drm_panel *panel) { struct visionox_r66451 *ctx = to_visionox_r66451(panel); - struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; int ret; ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), @@ -132,7 +131,6 @@ static int visionox_r66451_prepare(struct drm_panel *panel) ret = visionox_r66451_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to initialize panel: %d\n", ret); gpiod_set_value_cansleep(ctx->reset_gpio, 1); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); return ret; @@ -146,12 +144,8 @@ static int visionox_r66451_prepare(struct drm_panel *panel) static int visionox_r66451_unprepare(struct drm_panel *panel) { struct visionox_r66451 *ctx = to_visionox_r66451(panel); - struct device *dev = &ctx->dsi->dev; - int ret; - ret = visionox_r66451_off(ctx); - if (ret < 0) - dev_err(dev, "Failed to un-initialize panel: %d\n", ret); + visionox_r66451_off(ctx); gpiod_set_value_cansleep(ctx->reset_gpio, 1); regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -179,7 +173,7 @@ static int visionox_r66451_enable(struct drm_panel *panel) struct visionox_r66451 *ctx = to_visionox_r66451(panel); struct mipi_dsi_device *dsi = ctx->dsi; struct drm_dsc_picture_parameter_set pps; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; if (!dsi->dsc) { dev_err(&dsi->dev, "DSC not attached to DSI\n"); @@ -187,51 +181,30 @@ static int visionox_r66451_enable(struct drm_panel *panel) } drm_dsc_pps_payload_pack(&pps, dsi->dsc); - ret = mipi_dsi_picture_parameter_set(dsi, &pps); - if (ret) { - dev_err(&dsi->dev, "Failed to set PPS\n"); - return ret; - } + mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps); - ret = mipi_dsi_dcs_exit_sleep_mode(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); - ret = mipi_dsi_dcs_set_display_on(dsi); - if (ret < 0) { - dev_err(&dsi->dev, "Failed on set display on: %d\n", ret); - return ret; - } - msleep(20); + mipi_dsi_dcs_set_display_on_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); - return 0; + return dsi_ctx.accum_err; } static int visionox_r66451_disable(struct drm_panel *panel) { struct visionox_r66451 *ctx = to_visionox_r66451(panel); struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; - int ret; + struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi }; - ret = mipi_dsi_dcs_set_display_off(dsi); - if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); - return ret; - } - msleep(20); + mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 20); - ret = mipi_dsi_dcs_enter_sleep_mode(dsi); - if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); - return ret; - } - msleep(120); + mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + mipi_dsi_msleep(&dsi_ctx, 120); - return 0; + return dsi_ctx.accum_err; } static int visionox_r66451_get_modes(struct drm_panel *panel, From b7c5169ab9ddc3432161412bc2de28111306fbb3 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 13 Jan 2025 11:53:44 +0200 Subject: [PATCH 10/73] drm/i2c: tda998x: drop support for platform_data After the commit 0fb2970b4b6b ("drm/armada: remove non-component support") there are no remaining users of the struct tda998x_encoder_params. Drop the header and corresponding API from the TDA998x driver. Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20250113-drm-move-tda998x-v3-1-214e0682a5e4@linaro.org Signed-off-by: Dmitry Baryshkov --- MAINTAINERS | 1 - drivers/gpu/drm/i2c/tda998x_drv.c | 49 +++---------------------------- include/drm/i2c/tda998x.h | 40 ------------------------- 3 files changed, 4 insertions(+), 86 deletions(-) delete mode 100644 include/drm/i2c/tda998x.h diff --git a/MAINTAINERS b/MAINTAINERS index 8aef574769a4..dee6992dcd4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17081,7 +17081,6 @@ S: Maintained T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-devel T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-fixes F: drivers/gpu/drm/i2c/tda998x_drv.c -F: include/drm/i2c/tda998x.h F: include/dt-bindings/display/tda998x.h K: "nxp,tda998x" diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 82d4a4e206a5..ebc758c72891 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -21,10 +21,11 @@ #include #include #include -#include #include +#include + #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) enum { @@ -1717,10 +1718,10 @@ static int tda998x_get_audio_ports(struct tda998x_priv *priv, u8 ena_ap = be32_to_cpup(&port_data[2*i+1]); switch (afmt) { - case AFMT_I2S: + case TDA998x_I2S: route = AUDIO_ROUTE_I2S; break; - case AFMT_SPDIF: + case TDA998x_SPDIF: route = AUDIO_ROUTE_SPDIF; break; default: @@ -1746,44 +1747,6 @@ static int tda998x_get_audio_ports(struct tda998x_priv *priv, return 0; } -static int tda998x_set_config(struct tda998x_priv *priv, - const struct tda998x_encoder_params *p) -{ - priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) | - (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) | - VIP_CNTRL_0_SWAP_B(p->swap_b) | - (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0); - priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) | - (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) | - VIP_CNTRL_1_SWAP_D(p->swap_d) | - (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0); - priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) | - (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) | - VIP_CNTRL_2_SWAP_F(p->swap_f) | - (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0); - - if (p->audio_params.format != AFMT_UNUSED) { - unsigned int ratio, route; - bool spdif = p->audio_params.format == AFMT_SPDIF; - - route = AUDIO_ROUTE_I2S + spdif; - - priv->audio.route = &tda998x_audio_route[route]; - priv->audio.cea = p->audio_params.cea; - priv->audio.sample_rate = p->audio_params.sample_rate; - memcpy(priv->audio.status, p->audio_params.status, - min(sizeof(priv->audio.status), - sizeof(p->audio_params.status))); - priv->audio.ena_ap = p->audio_params.config; - priv->audio.i2s_format = I2S_FORMAT_PHILIPS; - - ratio = spdif ? 64 : p->audio_params.sample_width * 2; - return tda998x_derive_cts_n(priv, &priv->audio, ratio); - } - - return 0; -} - static void tda998x_destroy(struct device *dev) { struct tda998x_priv *priv = dev_get_drvdata(dev); @@ -1982,10 +1945,6 @@ static int tda998x_create(struct device *dev) if (priv->audio_port_enable[AUDIO_ROUTE_I2S] || priv->audio_port_enable[AUDIO_ROUTE_SPDIF]) tda998x_audio_codec_init(priv, &client->dev); - } else if (dev->platform_data) { - ret = tda998x_set_config(priv, dev->platform_data); - if (ret) - goto fail; } priv->bridge.funcs = &tda998x_bridge_funcs; diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h deleted file mode 100644 index 3cb25ccbe5e6..000000000000 --- a/include/drm/i2c/tda998x.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __DRM_I2C_TDA998X_H__ -#define __DRM_I2C_TDA998X_H__ - -#include -#include - -enum { - AFMT_UNUSED = 0, - AFMT_SPDIF = TDA998x_SPDIF, - AFMT_I2S = TDA998x_I2S, -}; - -struct tda998x_audio_params { - u8 config; - u8 format; - unsigned sample_width; - unsigned sample_rate; - struct hdmi_audio_infoframe cea; - u8 status[5]; -}; - -struct tda998x_encoder_params { - u8 swap_b:3; - u8 mirr_b:1; - u8 swap_a:3; - u8 mirr_a:1; - u8 swap_d:3; - u8 mirr_d:1; - u8 swap_c:3; - u8 mirr_c:1; - u8 swap_f:3; - u8 mirr_f:1; - u8 swap_e:3; - u8 mirr_e:1; - - struct tda998x_audio_params audio_params; -}; - -#endif From caa6f4a75e9f8eaebd814a9c2d1602e0926f473d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 13 Jan 2025 11:53:45 +0200 Subject: [PATCH 11/73] media: cec: move driver for TDA9950 from drm/i2c Move the driver for NXP TDA9950 / CEC part of TDA998x together to drivers/media/i2c, close to other CEC drivers. Specify 'default DRM_I2C_NXP_TDA998X' in order to simplify migration from old config files as the Kconfig name has been changed to follow media/cec style. Acked-by: Hans Verkuil Link: https://patchwork.freedesktop.org/patch/msgid/20250113-drm-move-tda998x-v3-2-214e0682a5e4@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/i2c/Kconfig | 5 ----- drivers/gpu/drm/i2c/Makefile | 1 - drivers/media/cec/i2c/Kconfig | 9 +++++++++ drivers/media/cec/i2c/Makefile | 1 + drivers/{gpu/drm => media/cec}/i2c/tda9950.c | 0 5 files changed, 10 insertions(+), 6 deletions(-) rename drivers/{gpu/drm => media/cec}/i2c/tda9950.c (100%) diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig index d5200f67958e..1aa2a0bf5cc1 100644 --- a/drivers/gpu/drm/i2c/Kconfig +++ b/drivers/gpu/drm/i2c/Kconfig @@ -10,9 +10,4 @@ config DRM_I2C_NXP_TDA998X help Support for NXP Semiconductors TDA998X HDMI encoders. -config DRM_I2C_NXP_TDA9950 - tristate "NXP Semiconductors TDA9950/TDA998X HDMI CEC" - select CEC_NOTIFIER - select CEC_CORE - endmenu diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile index 31fd35527d99..45791fbfae98 100644 --- a/drivers/gpu/drm/i2c/Makefile +++ b/drivers/gpu/drm/i2c/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 tda998x-y := tda998x_drv.o obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o -obj-$(CONFIG_DRM_I2C_NXP_TDA9950) += tda9950.o diff --git a/drivers/media/cec/i2c/Kconfig b/drivers/media/cec/i2c/Kconfig index d912d143fb31..b9d21643eef1 100644 --- a/drivers/media/cec/i2c/Kconfig +++ b/drivers/media/cec/i2c/Kconfig @@ -13,3 +13,12 @@ config CEC_CH7322 generic CEC framework interface. CEC bus is present in the HDMI connector and enables communication between compatible devices. + +config CEC_NXP_TDA9950 + tristate "NXP Semiconductors TDA9950/TDA998X HDMI CEC" + select CEC_NOTIFIER + select CEC_CORE + default DRM_I2C_NXP_TDA998X + help + This is a driver for the NXP TDA9950 CEC controller and for the CEC + controller block integrated into several NXP TDA998x HDMI encoders. diff --git a/drivers/media/cec/i2c/Makefile b/drivers/media/cec/i2c/Makefile index d7496dfd0fa4..95c9eda52583 100644 --- a/drivers/media/cec/i2c/Makefile +++ b/drivers/media/cec/i2c/Makefile @@ -3,3 +3,4 @@ # Makefile for the CEC I2C device drivers. # obj-$(CONFIG_CEC_CH7322) += ch7322.o +obj-$(CONFIG_CEC_NXP_TDA9950) += tda9950.o diff --git a/drivers/gpu/drm/i2c/tda9950.c b/drivers/media/cec/i2c/tda9950.c similarity index 100% rename from drivers/gpu/drm/i2c/tda9950.c rename to drivers/media/cec/i2c/tda9950.c From 325ba852d148434c5bcb06d513af1933a7f77b70 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 13 Jan 2025 11:53:46 +0200 Subject: [PATCH 12/73] drm/i2c: move TDA998x driver under drivers/gpu/drm/bridge TDA998x is the HDMI bridge driver, incorporating drm_connector and optional drm_encoder (created via the component bind API by the TICLDC and HDLCD drivers). Thus it should be residing together with the other DRM bridge drivers under drivers/gpu/drm/bridge/. Acked-by: Neil Armstrong Acked-by: Liviu Dudau Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20250113-drm-move-tda998x-v3-3-214e0682a5e4@linaro.org Signed-off-by: Dmitry Baryshkov --- MAINTAINERS | 2 +- drivers/gpu/drm/Kconfig | 2 -- drivers/gpu/drm/arm/Kconfig | 1 + drivers/gpu/drm/bridge/Kconfig | 8 ++++++++ drivers/gpu/drm/bridge/Makefile | 4 ++++ drivers/gpu/drm/{i2c => bridge}/tda998x_drv.c | 0 drivers/gpu/drm/i2c/Kconfig | 13 ------------- drivers/gpu/drm/i2c/Makefile | 3 --- 8 files changed, 14 insertions(+), 19 deletions(-) rename drivers/gpu/drm/{i2c => bridge}/tda998x_drv.c (100%) delete mode 100644 drivers/gpu/drm/i2c/Kconfig delete mode 100644 drivers/gpu/drm/i2c/Makefile diff --git a/MAINTAINERS b/MAINTAINERS index dee6992dcd4c..c20a5d072ea1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17080,7 +17080,7 @@ M: Russell King S: Maintained T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-devel T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-fixes -F: drivers/gpu/drm/i2c/tda998x_drv.c +F: drivers/gpu/drm/bridge/tda998x_drv.c F: include/dt-bindings/display/tda998x.h K: "nxp,tda998x" diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index f9b3ebf63fa9..d9986fd52194 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -326,8 +326,6 @@ config DRM_SCHED tristate depends on DRM -source "drivers/gpu/drm/i2c/Kconfig" - source "drivers/gpu/drm/arm/Kconfig" source "drivers/gpu/drm/radeon/Kconfig" diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig index c901ac00c0c3..ed3ed617c688 100644 --- a/drivers/gpu/drm/arm/Kconfig +++ b/drivers/gpu/drm/arm/Kconfig @@ -9,6 +9,7 @@ config DRM_HDLCD select DRM_CLIENT_SELECTION select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER + select DRM_BRIDGE # for TDA998x help Choose this option if you have an ARM High Definition Colour LCD controller. diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 6b4664d91faa..d20f1646dac2 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -90,6 +90,14 @@ config DRM_FSL_LDB help Support for i.MX8MP DPI-to-LVDS on-SoC encoder. +config DRM_I2C_NXP_TDA998X + tristate "NXP Semiconductors TDA998X HDMI encoder" + default m if DRM_TILCDC + select CEC_CORE if CEC_NOTIFIER + select SND_SOC_HDMI_CODEC if SND_SOC + help + Support for NXP Semiconductors TDA998X HDMI encoders. + config DRM_ITE_IT6263 tristate "ITE IT6263 LVDS/HDMI bridge" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 97304b429a53..245e8a27e3fc 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -6,6 +6,10 @@ obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o obj-$(CONFIG_DRM_FSL_LDB) += fsl-ldb.o + +tda998x-y := tda998x_drv.o +obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o + obj-$(CONFIG_DRM_ITE_IT6263) += ite-it6263.o obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/bridge/tda998x_drv.c similarity index 100% rename from drivers/gpu/drm/i2c/tda998x_drv.c rename to drivers/gpu/drm/bridge/tda998x_drv.c diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig deleted file mode 100644 index 1aa2a0bf5cc1..000000000000 --- a/drivers/gpu/drm/i2c/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menu "I2C encoder or helper chips" - depends on DRM && DRM_KMS_HELPER && I2C - -config DRM_I2C_NXP_TDA998X - tristate "NXP Semiconductors TDA998X HDMI encoder" - default m if DRM_TILCDC - select CEC_CORE if CEC_NOTIFIER - select SND_SOC_HDMI_CODEC if SND_SOC - help - Support for NXP Semiconductors TDA998X HDMI encoders. - -endmenu diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile deleted file mode 100644 index 45791fbfae98..000000000000 --- a/drivers/gpu/drm/i2c/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -tda998x-y := tda998x_drv.o -obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o From efc84f661e0a1b73449d678a89ad86d61bbf6bf4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 13 Feb 2025 02:49:41 +0200 Subject: [PATCH 13/73] drm: drop i2c subdir from Makefile The commit 325ba852d148 ("drm/i2c: move TDA998x driver under drivers/gpu/drm/bridge") deleted the drivers/gpu/drm/i2c/ subdir, but didn't update upper level Makefile. Drop corresponding line to fix build issues. Fixes: 325ba852d148 ("drm/i2c: move TDA998x driver under drivers/gpu/drm/bridge") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/dri-devel/20250213113841.7645b74c@canb.auug.org.au Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20250213-fix-tda-v1-1-d3d34b2dc907@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 42901f877bf2..50604b49d1ac 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -197,7 +197,6 @@ obj-$(CONFIG_DRM_INGENIC) += ingenic/ obj-$(CONFIG_DRM_LOGICVC) += logicvc/ obj-$(CONFIG_DRM_MEDIATEK) += mediatek/ obj-$(CONFIG_DRM_MESON) += meson/ -obj-y += i2c/ obj-y += panel/ obj-y += bridge/ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/ From e5f5f7ccae5fd5807587f8075e06eb8a9fca2b41 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 12 Feb 2025 18:24:09 +0300 Subject: [PATCH 14/73] drm/tests: Fix a test in drm_test_check_valid_clones() The drm_atomic_get_crtc_state() function returns error pointers and not NULL. Update the check to check for error pointers as well as NULL. Fixes: 88849f24e2ab ("drm/tests: Add test for drm_atomic_helper_check_modeset()") Signed-off-by: Dan Carpenter Link: https://patchwork.freedesktop.org/patch/msgid/c50f11c7-932c-47dc-b40f-4ada8b9b6679@stanley.mountain Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_atomic_state_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c index 0ab5d9ec4a75..5945c3298901 100644 --- a/drivers/gpu/drm/tests/drm_atomic_state_test.c +++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c @@ -283,7 +283,7 @@ static void drm_test_check_valid_clones(struct kunit *test) KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); crtc_state = drm_atomic_get_crtc_state(state, priv->crtc); - KUNIT_ASSERT_NOT_NULL(test, crtc_state); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); crtc_state->encoder_mask = param->encoder_mask; From ff3881cc6a588f8cd714c9ffbbcc9ef6b02c8d0f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 12 Feb 2025 18:23:48 +0300 Subject: [PATCH 15/73] drm: writeback: Fix use after free in drm_writeback_connector_cleanup() The drm_writeback_cleanup_job() function frees "pos" so call list_del(&pos->list_entry) first to avoid a use after free. Fixes: 1914ba2b91ea ("drm: writeback: Create drmm variants for drm_writeback_connector initialization") Signed-off-by: Dan Carpenter Reviewed-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/78abd541-71e9-4b3b-a05d-2c7caf8d5b2f@stanley.mountain Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_writeback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index 3628fbef7752..f139b49af4c9 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -360,8 +360,8 @@ static void drm_writeback_connector_cleanup(struct drm_device *dev, spin_lock_irqsave(&wb_connector->job_lock, flags); list_for_each_entry_safe(pos, n, &wb_connector->job_queue, list_entry) { - drm_writeback_cleanup_job(pos); list_del(&pos->list_entry); + drm_writeback_cleanup_job(pos); } spin_unlock_irqrestore(&wb_connector->job_lock, flags); } From ed15511a773df86205bda66c37193569575ae828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Wed, 12 Feb 2025 09:49:12 +0100 Subject: [PATCH 16/73] drm/vkms: Fix use after free and double free on init error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the driver initialization fails, the vkms_exit() function might access an uninitialized or freed default_config pointer and it might double free it. Fix both possible errors by initializing default_config only when the driver initialization succeeded. Reported-by: Louis Chauvet Closes: https://lore.kernel.org/all/Z5uDHcCmAwiTsGte@louis-chauvet-laptop/ Fixes: 2df7af93fdad ("drm/vkms: Add vkms_config type") Signed-off-by: José Expósito Reviewed-by: Thomas Zimmermann Reviewed-by: Louis Chauvet Link: https://patchwork.freedesktop.org/patch/msgid/20250212084912.3196-1-jose.exposito89@gmail.com Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 7c142bfc3bd9..b6de91134a22 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -235,17 +235,19 @@ static int __init vkms_init(void) if (!config) return -ENOMEM; - default_config = config; - config->cursor = enable_cursor; config->writeback = enable_writeback; config->overlay = enable_overlay; ret = vkms_create(config); - if (ret) + if (ret) { kfree(config); + return ret; + } - return ret; + default_config = config; + + return 0; } static void vkms_destroy(struct vkms_config *config) @@ -269,9 +271,10 @@ static void vkms_destroy(struct vkms_config *config) static void __exit vkms_exit(void) { - if (default_config->dev) - vkms_destroy(default_config); + if (!default_config) + return; + vkms_destroy(default_config); kfree(default_config); } From feb7ef6e2b1f3ac1fc98652205f3be91e51c4da2 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 10 Feb 2025 14:26:16 +0100 Subject: [PATCH 17/73] dt-bindings: display: bridge: sn65dsi83: Add interrupt Both the TI SN65DSI83 and SN65DSI84 bridges have an IRQ pin to signal errors using interrupt. This interrupt is not documented in the binding. Add the missing interrupts property. Signed-off-by: Herve Codina Reviewed-by: Laurent Pinchart Acked-by: Conor Dooley Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250210132620.42263-2-herve.codina@bootlin.com Signed-off-by: Maxime Ripard --- .../devicetree/bindings/display/bridge/ti,sn65dsi83.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml index bad6f5c81b06..9b5f3f3eab19 100644 --- a/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml +++ b/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml @@ -35,6 +35,9 @@ properties: vcc-supply: description: A 1.8V power supply (see regulator/regulator.yaml). + interrupts: + maxItems: 1 + ports: $ref: /schemas/graph.yaml#/properties/ports From ab83b7f6a0c10b5e040ae60bc6789ff89dd9488c Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 10 Feb 2025 14:26:17 +0100 Subject: [PATCH 18/73] drm/atomic-helper: Introduce drm_atomic_helper_reset_crtc() drm_atomic_helper_reset_crtc() allows to reset the CRTC active outputs. This resets all active components available between the CRTC and connectors. Signed-off-by: Herve Codina Reviewed-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250210132620.42263-3-herve.codina@bootlin.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 41 +++++++++++++++++++++++++++++ include/drm/drm_atomic_helper.h | 2 ++ 2 files changed, 43 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 26bf2465cee7..d6a206fc9ddd 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3400,6 +3400,47 @@ int drm_atomic_helper_disable_all(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_disable_all); +/** + * drm_atomic_helper_reset_crtc - reset the active outputs of a CRTC + * @crtc: DRM CRTC + * @ctx: lock acquisition context + * + * Reset the active outputs by indicating that connectors have changed. + * This implies a reset of all active components available between the CRTC and + * connectors. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +int drm_atomic_helper_reset_crtc(struct drm_crtc *crtc, + struct drm_modeset_acquire_ctx *ctx) +{ + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + int ret; + + state = drm_atomic_state_alloc(crtc->dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = ctx; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto out; + } + + crtc_state->connectors_changed = true; + + ret = drm_atomic_commit(state); +out: + drm_atomic_state_put(state); + + return ret; +} +EXPORT_SYMBOL(drm_atomic_helper_reset_crtc); + /** * drm_atomic_helper_shutdown - shutdown all CRTC * @dev: DRM device diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 9aa0a05aa072..53382fe93537 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -139,6 +139,8 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set, int drm_atomic_helper_disable_all(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx); +int drm_atomic_helper_reset_crtc(struct drm_crtc *crtc, + struct drm_modeset_acquire_ctx *ctx); void drm_atomic_helper_shutdown(struct drm_device *dev); struct drm_atomic_state * drm_atomic_helper_duplicate_state(struct drm_device *dev, From 9f3f59382a4e83c9fdfbaf1d8eb2ccfcd51cd38c Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 10 Feb 2025 14:26:18 +0100 Subject: [PATCH 19/73] drm/vc4: hdmi: Use drm_atomic_helper_reset_crtc() The current code uses a the reset_pipe() local function to reset the CRTC outputs. drm_atomic_helper_reset_crtc() has been introduced recently and it performs exact same operations. In order to avoid code duplication, use the new helper instead of the local function. Signed-off-by: Herve Codina Acked-by: Dmitry Baryshkov Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250210132620.42263-4-herve.codina@bootlin.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/vc4/vc4_hdmi.c | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 47d9ada98430..e878eddc9c3f 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -270,34 +270,6 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {} #endif -static int reset_pipe(struct drm_crtc *crtc, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_atomic_state *state; - struct drm_crtc_state *crtc_state; - int ret; - - state = drm_atomic_state_alloc(crtc->dev); - if (!state) - return -ENOMEM; - - state->acquire_ctx = ctx; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); - goto out; - } - - crtc_state->connectors_changed = true; - - ret = drm_atomic_commit(state); -out: - drm_atomic_state_put(state); - - return ret; -} - static int vc4_hdmi_reset_link(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx) { @@ -376,7 +348,7 @@ static int vc4_hdmi_reset_link(struct drm_connector *connector, * would be perfectly happy if were to just reconfigure * the SCDC settings on the fly. */ - return reset_pipe(crtc, ctx); + return drm_atomic_helper_reset_crtc(crtc, ctx); } static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi, From ad5c6ecef27e4f54748b7aa0815a722f83df5bce Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Mon, 10 Feb 2025 14:26:19 +0100 Subject: [PATCH 20/73] drm: bridge: ti-sn65dsi83: Add error recovery mechanism In some cases observed during ESD tests, the TI SN65DSI83 cannot recover from errors by itself. A full restart of the bridge is needed in those cases to have the bridge output LVDS signals again. Also, during tests, cases were observed where reading the status of the bridge was not even possible. Indeed, in those cases, the bridge stops to acknowledge I2C transactions. Only a full reset of the bridge (power off/on) brings back the bridge to a functional state. The TI SN65DSI83 has some error detection capabilities. Introduce an error recovery mechanism based on this detection. The errors detected are signaled through an interrupt. On system where this interrupt is not available, the driver uses a polling monitoring fallback to check for errors. When an error is present or when reading the bridge status leads to an I2C failure, the recovery process is launched. Restarting the bridge needs to redo the initialization sequence. This initialization sequence has to be done with the DSI data lanes driven in LP11 state. In order to do that, the recovery process resets the whole output path (i.e the path from the encoder to the connector) where the bridge is located. Signed-off-by: Herve Codina Reviewed-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20250210132620.42263-5-herve.codina@bootlin.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 142 ++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index f6728c491cc5..8da9eb3832dd 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -35,9 +35,12 @@ #include #include #include +#include +#include #include #include +#include /* DRM_MODESET_LOCK_ALL_BEGIN() needs drm_drv_uses_atomic_modeset() */ #include #include #include @@ -158,6 +161,9 @@ struct sn65dsi83 { bool lvds_dual_link_even_odd_swap; int lvds_vod_swing_conf[2]; int lvds_term_conf[2]; + int irq; + struct delayed_work monitor_work; + struct work_struct reset_work; }; static const struct regmap_range sn65dsi83_readable_ranges[] = { @@ -362,6 +368,106 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx) return dsi_div - 1; } +static int sn65dsi83_reset_pipe(struct sn65dsi83 *sn65dsi83) +{ + struct drm_device *dev = sn65dsi83->bridge.dev; + struct drm_modeset_acquire_ctx ctx; + int err; + + /* + * Reset active outputs of the related CRTC. + * + * This way, drm core will reconfigure each components in the CRTC + * outputs path. In our case, this will force the previous component to + * go back in LP11 mode and so allow the reconfiguration of SN65DSI83 + * bridge. + * + * Keep the lock during the whole operation to be atomic. + */ + + DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, err); + + if (!sn65dsi83->bridge.encoder->crtc) { + /* + * No CRTC attached -> No CRTC active outputs to reset + * This can happen when the SN65DSI83 is reset. Simply do + * nothing without returning any errors. + */ + err = 0; + goto end; + } + + dev_warn(sn65dsi83->dev, "reset the pipe\n"); + + err = drm_atomic_helper_reset_crtc(sn65dsi83->bridge.encoder->crtc, &ctx); + +end: + DRM_MODESET_LOCK_ALL_END(dev, ctx, err); + + return err; +} + +static void sn65dsi83_reset_work(struct work_struct *ws) +{ + struct sn65dsi83 *ctx = container_of(ws, struct sn65dsi83, reset_work); + int ret; + + /* Reset the pipe */ + ret = sn65dsi83_reset_pipe(ctx); + if (ret) { + dev_err(ctx->dev, "reset pipe failed %pe\n", ERR_PTR(ret)); + return; + } + if (ctx->irq) + enable_irq(ctx->irq); +} + +static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx) +{ + unsigned int irq_stat; + int ret; + + /* + * Schedule a reset in case of: + * - the bridge doesn't answer + * - the bridge signals an error + */ + + ret = regmap_read(ctx->regmap, REG_IRQ_STAT, &irq_stat); + if (ret || irq_stat) { + /* + * IRQ acknowledged is not always possible (the bridge can be in + * a state where it doesn't answer anymore). To prevent an + * interrupt storm, disable interrupt. The interrupt will be + * after the reset. + */ + if (ctx->irq) + disable_irq_nosync(ctx->irq); + + schedule_work(&ctx->reset_work); + } +} + +static void sn65dsi83_monitor_work(struct work_struct *work) +{ + struct sn65dsi83 *ctx = container_of(to_delayed_work(work), + struct sn65dsi83, monitor_work); + + sn65dsi83_handle_errors(ctx); + + schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000)); +} + +static void sn65dsi83_monitor_start(struct sn65dsi83 *ctx) +{ + schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000)); +} + +static void sn65dsi83_monitor_stop(struct sn65dsi83 *ctx) +{ + cancel_delayed_work_sync(&ctx->monitor_work); +} + static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { @@ -548,6 +654,15 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, regmap_read(ctx->regmap, REG_IRQ_STAT, &pval); if (pval) dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval); + + if (ctx->irq) { + /* Enable irq to detect errors */ + regmap_write(ctx->regmap, REG_IRQ_GLOBAL, REG_IRQ_GLOBAL_IRQ_EN); + regmap_write(ctx->regmap, REG_IRQ_EN, 0xff); + } else { + /* Use the polling task */ + sn65dsi83_monitor_start(ctx); + } } static void sn65dsi83_atomic_disable(struct drm_bridge *bridge, @@ -556,6 +671,15 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge, struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); int ret; + if (ctx->irq) { + /* Disable irq */ + regmap_write(ctx->regmap, REG_IRQ_EN, 0x0); + regmap_write(ctx->regmap, REG_IRQ_GLOBAL, 0x0); + } else { + /* Stop the polling task */ + sn65dsi83_monitor_stop(ctx); + } + /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */ gpiod_set_value_cansleep(ctx->enable_gpio, 0); usleep_range(10000, 11000); @@ -805,6 +929,14 @@ static int sn65dsi83_host_attach(struct sn65dsi83 *ctx) return 0; } +static irqreturn_t sn65dsi83_irq(int irq, void *data) +{ + struct sn65dsi83 *ctx = data; + + sn65dsi83_handle_errors(ctx); + return IRQ_HANDLED; +} + static int sn65dsi83_probe(struct i2c_client *client) { const struct i2c_device_id *id = i2c_client_get_device_id(client); @@ -818,6 +950,8 @@ static int sn65dsi83_probe(struct i2c_client *client) return -ENOMEM; ctx->dev = dev; + INIT_WORK(&ctx->reset_work, sn65dsi83_reset_work); + INIT_DELAYED_WORK(&ctx->monitor_work, sn65dsi83_monitor_work); if (dev->of_node) { model = (enum sn65dsi83_model)(uintptr_t) @@ -842,6 +976,14 @@ static int sn65dsi83_probe(struct i2c_client *client) if (IS_ERR(ctx->regmap)) return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n"); + if (client->irq) { + ctx->irq = client->irq; + ret = devm_request_threaded_irq(ctx->dev, ctx->irq, NULL, sn65dsi83_irq, + IRQF_ONESHOT, dev_name(ctx->dev), ctx); + if (ret) + return dev_err_probe(dev, ret, "failed to request irq\n"); + } + dev_set_drvdata(dev, ctx); i2c_set_clientdata(client, ctx); From b7cf9f4ac1b8ad0fae1c0f011913361c140b49e1 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Tue, 4 Feb 2025 12:35:24 +0530 Subject: [PATCH 21/73] drm: Introduce device wedged event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce device wedged event, which notifies userspace of 'wedged' (hanged/unusable) state of the DRM device through a uevent. This is useful especially in cases where the device is no longer operating as expected and has become unrecoverable from driver context. Purpose of this implementation is to provide drivers a generic way to recover the device with the help of userspace intervention without taking any drastic measures (like resetting or re-enumerating the full bus, on which the underlying physical device is sitting) in the driver. A 'wedged' device is basically a device that is declared dead by the driver after exhausting all possible attempts to recover it from driver context. The uevent is the notification that is sent to userspace along with a hint about what could possibly be attempted to recover the device from userspace and bring it back to usable state. Different drivers may have different ideas of a 'wedged' device depending on hardware implementation of the underlying physical device, and hence the vendor agnostic nature of the event. It is up to the drivers to decide when they see the need for device recovery and how they want to recover from the available methods. Driver prerequisites -------------------- The driver, before opting for recovery, needs to make sure that the 'wedged' device doesn't harm the system as a whole by taking care of the prerequisites. Necessary actions must include disabling DMA to system memory as well as any communication channels with other devices. Further, the driver must ensure that all dma_fences are signalled and any device state that the core kernel might depend on is cleaned up. All existing mmaps should be invalidated and page faults should be redirected to a dummy page. Once the event is sent, the device must be kept in 'wedged' state until the recovery is performed. New accesses to the device (IOCTLs) should be rejected, preferably with an error code that resembles the type of failure the device has encountered. This will signify the reason for wedging, which can be reported to the application if needed. Recovery -------- Current implementation defines three recovery methods, out of which, drivers can use any one, multiple or none. Method(s) of choice will be sent in the uevent environment as ``WEDGED=[,..,]`` in order of less to more side-effects. If driver is unsure about recovery or method is unknown (like soft/hard system reboot, firmware flashing, physical device replacement or any other procedure which can't be attempted on the fly), ``WEDGED=unknown`` will be sent instead. Userspace consumers can parse this event and attempt recovery as per the following expectations. =============== ======================================== Recovery method Consumer expectations =============== ======================================== none optional telemetry collection rebind unbind + bind driver bus-reset unbind + bus reset/re-enumeration + bind unknown consumer policy =============== ======================================== The only exception to this is ``WEDGED=none``, which signifies that the device was temporarily 'wedged' at some point but was recovered from driver context using device specific methods like reset. No explicit recovery is expected from the consumer in this case, but it can still take additional steps like gathering telemetry information (devcoredump, syslog). This is useful because the first hang is usually the most critical one which can result in consequential hangs or complete wedging. Consumer prerequisites ---------------------- It is the responsibility of the consumer to make sure that the device or its resources are not in use by any process before attempting recovery. With IOCTLs erroring out, all device memory should be unmapped and file descriptors should be closed to prevent leaks or undefined behaviour. The idea here is to clear the device of all user context beforehand and set the stage for a clean recovery. Example ------- Udev rule:: SUBSYSTEM=="drm", ENV{WEDGED}=="rebind", DEVPATH=="*/drm/card[0-9]", RUN+="/path/to/rebind.sh $env{DEVPATH}" Recovery script:: #!/bin/sh DEVPATH=$(readlink -f /sys/$1/device) DEVICE=$(basename $DEVPATH) DRIVER=$(readlink -f $DEVPATH/driver) echo -n $DEVICE > $DRIVER/unbind echo -n $DEVICE > $DRIVER/bind Customization ------------- Although basic recovery is possible with a simple script, consumers can define custom policies around recovery. For example, if the driver supports multiple recovery methods, consumers can opt for the suitable one depending on scenarios like repeat offences or vendor specific failures. Consumers can also choose to have the device available for debugging or telemetry collection and base their recovery decision on the findings. This is useful especially when the driver is unsure about recovery or method is unknown. v4: s/drm_dev_wedged/drm_dev_wedged_event Use drm_info() (Jani) Kernel doc adjustment (Aravind) v5: Send recovery method with uevent (Lina) v6: Access wedge_recovery_opts[] using helper function (Jani) Use snprintf() (Jani) v7: Convert recovery helpers into regular functions (Andy, Jani) Aesthetic adjustments (Andy) Handle invalid recovery method v8: Allow sending multiple methods with uevent (Lucas, Michal) static_assert() globally (Andy) v9: Provide 'none' method for device reset (Christian) Provide recovery opts using switch cases v11: Log device reset (André) Signed-off-by: Raag Jadav Reviewed-by: André Almeida Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20250204070528.1919158-2-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/drm_drv.c | 68 +++++++++++++++++++++++++++++++++++++++ include/drm/drm_device.h | 8 +++++ include/drm/drm_drv.h | 1 + 3 files changed, 77 insertions(+) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3cf440eee8a2..17fc5dc708f4 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -26,6 +26,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include @@ -498,6 +500,72 @@ void drm_dev_unplug(struct drm_device *dev) } EXPORT_SYMBOL(drm_dev_unplug); +/* + * Available recovery methods for wedged device. To be sent along with device + * wedged uevent. + */ +static const char *drm_get_wedge_recovery(unsigned int opt) +{ + switch (BIT(opt)) { + case DRM_WEDGE_RECOVERY_NONE: + return "none"; + case DRM_WEDGE_RECOVERY_REBIND: + return "rebind"; + case DRM_WEDGE_RECOVERY_BUS_RESET: + return "bus-reset"; + default: + return NULL; + } +} + +/** + * drm_dev_wedged_event - generate a device wedged uevent + * @dev: DRM device + * @method: method(s) to be used for recovery + * + * This generates a device wedged uevent for the DRM device specified by @dev. + * Recovery @method\(s) of choice will be sent in the uevent environment as + * ``WEDGED=[,..,]`` in order of less to more side-effects. + * If caller is unsure about recovery or @method is unknown (0), + * ``WEDGED=unknown`` will be sent instead. + * + * Refer to "Device Wedging" chapter in Documentation/gpu/drm-uapi.rst for more + * details. + * + * Returns: 0 on success, negative error code otherwise. + */ +int drm_dev_wedged_event(struct drm_device *dev, unsigned long method) +{ + const char *recovery = NULL; + unsigned int len, opt; + /* Event string length up to 28+ characters with available methods */ + char event_string[32]; + char *envp[] = { event_string, NULL }; + + len = scnprintf(event_string, sizeof(event_string), "%s", "WEDGED="); + + for_each_set_bit(opt, &method, BITS_PER_TYPE(method)) { + recovery = drm_get_wedge_recovery(opt); + if (drm_WARN_ONCE(dev, !recovery, "invalid recovery method %u\n", opt)) + break; + + len += scnprintf(event_string + len, sizeof(event_string), "%s,", recovery); + } + + if (recovery) + /* Get rid of trailing comma */ + event_string[len - 1] = '\0'; + else + /* Caller is unsure about recovery, do the best we can at this point. */ + snprintf(event_string, sizeof(event_string), "%s", "WEDGED=unknown"); + + drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ? + "but recovered through reset" : "needs recovery"); + + return kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); +} +EXPORT_SYMBOL(drm_dev_wedged_event); + /* * DRM internal mount * We want to be able to allocate our own "struct address_space" to control diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index c91f87b5242d..6ea54a578cda 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -21,6 +21,14 @@ struct inode; struct pci_dev; struct pci_controller; +/* + * Recovery methods for wedged device in order of less to more side-effects. + * To be used with drm_dev_wedged_event() as recovery @method. Callers can + * use any one, multiple (or'd) or none depending on their needs. + */ +#define DRM_WEDGE_RECOVERY_NONE BIT(0) /* optional telemetry collection */ +#define DRM_WEDGE_RECOVERY_REBIND BIT(1) /* unbind + bind driver */ +#define DRM_WEDGE_RECOVERY_BUS_RESET BIT(2) /* unbind + reset bus device + bind */ /** * enum switch_power_state - power state of drm device diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 9952b846c170..a43d707b5f36 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -482,6 +482,7 @@ void drm_put_dev(struct drm_device *dev); bool drm_dev_enter(struct drm_device *dev, int *idx); void drm_dev_exit(int idx); void drm_dev_unplug(struct drm_device *dev); +int drm_dev_wedged_event(struct drm_device *dev, unsigned long method); /** * drm_dev_is_unplugged - is a DRM device unplugged From a97bc11b20df7083e1a5f9250eacf054f5d2eae0 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Tue, 4 Feb 2025 12:35:25 +0530 Subject: [PATCH 22/73] drm/doc: Document device wedged event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add documentation for device wedged event in a new "Device wedging" chapter. This describes basic definitions, prerequisites and consumer expectations along with an example. v8: Improve introduction (Christian, Rodrigo) v9: Add prerequisites section (Christian) v10: Clarify mmap cleanup and consumer prerequisites (Christian, Aravind) v11: Reference wedged event in device reset chapter (André) v12: Refine consumer expectations and terminologies (Xaver, Pekka) Signed-off-by: Raag Jadav Reviewed-by: Christian König Reviewed-by: André Almeida Link: https://patchwork.freedesktop.org/patch/msgid/20250204070528.1919158-3-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- Documentation/gpu/drm-uapi.rst | 116 ++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 3 deletions(-) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index b75cc9a70d1f..69f72e71a96e 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -371,9 +371,119 @@ Reporting causes of resets Apart from propagating the reset through the stack so apps can recover, it's really useful for driver developers to learn more about what caused the reset in -the first place. DRM devices should make use of devcoredump to store relevant -information about the reset, so this information can be added to user bug -reports. +the first place. For this, drivers can make use of devcoredump to store relevant +information about the reset and send device wedged event with ``none`` recovery +method (as explained in "Device Wedging" chapter) to notify userspace, so this +information can be collected and added to user bug reports. + +Device Wedging +============== + +Drivers can optionally make use of device wedged event (implemented as +drm_dev_wedged_event() in DRM subsystem), which notifies userspace of 'wedged' +(hanged/unusable) state of the DRM device through a uevent. This is useful +especially in cases where the device is no longer operating as expected and has +become unrecoverable from driver context. Purpose of this implementation is to +provide drivers a generic way to recover the device with the help of userspace +intervention, without taking any drastic measures (like resetting or +re-enumerating the full bus, on which the underlying physical device is sitting) +in the driver. + +A 'wedged' device is basically a device that is declared dead by the driver +after exhausting all possible attempts to recover it from driver context. The +uevent is the notification that is sent to userspace along with a hint about +what could possibly be attempted to recover the device from userspace and bring +it back to usable state. Different drivers may have different ideas of a +'wedged' device depending on hardware implementation of the underlying physical +device, and hence the vendor agnostic nature of the event. It is up to the +drivers to decide when they see the need for device recovery and how they want +to recover from the available methods. + +Driver prerequisites +-------------------- + +The driver, before opting for recovery, needs to make sure that the 'wedged' +device doesn't harm the system as a whole by taking care of the prerequisites. +Necessary actions must include disabling DMA to system memory as well as any +communication channels with other devices. Further, the driver must ensure +that all dma_fences are signalled and any device state that the core kernel +might depend on is cleaned up. All existing mmaps should be invalidated and +page faults should be redirected to a dummy page. Once the event is sent, the +device must be kept in 'wedged' state until the recovery is performed. New +accesses to the device (IOCTLs) should be rejected, preferably with an error +code that resembles the type of failure the device has encountered. This will +signify the reason for wedging, which can be reported to the application if +needed. + +Recovery +-------- + +Current implementation defines three recovery methods, out of which, drivers +can use any one, multiple or none. Method(s) of choice will be sent in the +uevent environment as ``WEDGED=[,..,]`` in order of less to +more side-effects. If driver is unsure about recovery or method is unknown +(like soft/hard system reboot, firmware flashing, physical device replacement +or any other procedure which can't be attempted on the fly), ``WEDGED=unknown`` +will be sent instead. + +Userspace consumers can parse this event and attempt recovery as per the +following expectations. + + =============== ======================================== + Recovery method Consumer expectations + =============== ======================================== + none optional telemetry collection + rebind unbind + bind driver + bus-reset unbind + bus reset/re-enumeration + bind + unknown consumer policy + =============== ======================================== + +The only exception to this is ``WEDGED=none``, which signifies that the device +was temporarily 'wedged' at some point but was recovered from driver context +using device specific methods like reset. No explicit recovery is expected from +the consumer in this case, but it can still take additional steps like gathering +telemetry information (devcoredump, syslog). This is useful because the first +hang is usually the most critical one which can result in consequential hangs or +complete wedging. + +Consumer prerequisites +---------------------- + +It is the responsibility of the consumer to make sure that the device or its +resources are not in use by any process before attempting recovery. With IOCTLs +erroring out, all device memory should be unmapped and file descriptors should +be closed to prevent leaks or undefined behaviour. The idea here is to clear the +device of all user context beforehand and set the stage for a clean recovery. + +Example +------- + +Udev rule:: + + SUBSYSTEM=="drm", ENV{WEDGED}=="rebind", DEVPATH=="*/drm/card[0-9]", + RUN+="/path/to/rebind.sh $env{DEVPATH}" + +Recovery script:: + + #!/bin/sh + + DEVPATH=$(readlink -f /sys/$1/device) + DEVICE=$(basename $DEVPATH) + DRIVER=$(readlink -f $DEVPATH/driver) + + echo -n $DEVICE > $DRIVER/unbind + echo -n $DEVICE > $DRIVER/bind + +Customization +------------- + +Although basic recovery is possible with a simple script, consumers can define +custom policies around recovery. For example, if the driver supports multiple +recovery methods, consumers can opt for the suitable one depending on scenarios +like repeat offences or vendor specific failures. Consumers can also choose to +have the device available for debugging or telemetry collection and base their +recovery decision on the findings. This is useful especially when the driver is +unsure about recovery or method is unknown. .. _drm_driver_ioctl: From 7bc00751f877cf9f57117842d62c4728c02cec85 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Tue, 4 Feb 2025 12:35:26 +0530 Subject: [PATCH 23/73] drm/xe: Use device wedged event This was previously attempted as xe specific reset uevent but dropped in commit 77a0d4d1cea2 ("drm/xe/uapi: Remove reset uevent for now") as part of refactoring. Now that we have device wedged event provided by DRM core, make use of it and support both driver rebind and bus-reset based recovery. With this in place userspace will be notified of wedged device, on the basis of which, userspace may take respective action to recover the device. $ udevadm monitor --property --kernel monitor will print the received events for: KERNEL - the kernel uevent KERNEL[265.802982] change /devices/pci0000:00/0000:00:01.0/0000:01:00.0/0000:02:01.0/0000:03:00.0/drm/card0 (drm) ACTION=change DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/0000:02:01.0/0000:03:00.0/drm/card0 SUBSYSTEM=drm WEDGED=rebind,bus-reset DEVNAME=/dev/dri/card0 DEVTYPE=drm_minor SEQNUM=5208 MAJOR=226 MINOR=0 v2: Change authorship to Himal (Aravind) Add uevent for all device wedged cases (Aravind) v3: Generic implementation in DRM subsystem (Lucas) v4: Change authorship to Raag (Aravind) Signed-off-by: Raag Jadav Reviewed-by: Aravind Iddamsetty Acked-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20250204070528.1919158-4-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_device.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 4e1839b483a0..fc4a49f25c09 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -1003,7 +1003,8 @@ static void xe_device_wedged_fini(struct drm_device *drm, void *arg) * re-probe (unbind + bind). * In this state every IOCTL will be blocked so the GT cannot be used. * In general it will be called upon any critical error such as gt reset - * failure or guc loading failure. + * failure or guc loading failure. Userspace will be notified of this state + * through device wedged uevent. * If xe.wedged module parameter is set to 2, this function will be called * on every single execution timeout (a.k.a. GPU hang) right after devcoredump * snapshot capture. In this mode, GT reset won't be attempted so the state of @@ -1033,6 +1034,10 @@ void xe_device_declare_wedged(struct xe_device *xe) "IOCTLs and executions are blocked. Only a rebind may clear the failure\n" "Please file a _new_ bug report at https://gitlab.freedesktop.org/drm/xe/kernel/issues/new\n", dev_name(xe->drm.dev)); + + /* Notify userspace of wedged device */ + drm_dev_wedged_event(&xe->drm, + DRM_WEDGE_RECOVERY_REBIND | DRM_WEDGE_RECOVERY_BUS_RESET); } for_each_gt(gt, xe, id) From 11bb3d1876fc59d2699e8050a361c9bc92464830 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Tue, 4 Feb 2025 12:35:27 +0530 Subject: [PATCH 24/73] drm/i915: Use device wedged event Now that we have device wedged event provided by DRM core, make use of it and support both driver rebind and bus-reset based recovery. With this in place, userspace will be notified of wedged device on gt reset failure. Signed-off-by: Raag Jadav Reviewed-by: Aravind Iddamsetty Acked-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20250204070528.1919158-5-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_reset.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index aae5a081cb53..d6dc12fd87c1 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1422,6 +1422,9 @@ static void intel_gt_reset_global(struct intel_gt *gt, if (!test_bit(I915_WEDGED, >->reset.flags)) kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event); + else + drm_dev_wedged_event(>->i915->drm, + DRM_WEDGE_RECOVERY_REBIND | DRM_WEDGE_RECOVERY_BUS_RESET); } /** From 6fe52b63f569c11a70b737751055afd46c4454b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Tue, 4 Feb 2025 12:35:28 +0530 Subject: [PATCH 25/73] drm/amdgpu: Use device wedged event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use DRM's device wedged event to notify userspace that a reset had happened. For now, only use `none` method meant for telemetry capture. In the future we might want to report a recovery method if the reset didn't succeed. Acked-by: Shashank Sharma Signed-off-by: André Almeida Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20250204070528.1919158-6-raag.jadav@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6800f72fafd2..24ba52d76045 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -6122,6 +6122,10 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, dev_info(adev->dev, "GPU reset end with ret = %d\n", r); atomic_set(&adev->reset_domain->reset_res, r); + + if (!r) + drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE); + return r; } From fd40a63c63a182aeea1089a343e2f729de7e514d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Mon, 27 Jan 2025 16:59:39 -0300 Subject: [PATCH 26/73] drm/atomic: Let drivers decide which planes to async flip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, DRM atomic uAPI allows only primary planes to be flipped asynchronously. However, each driver might be able to perform async flips in other different plane types. To enable drivers to set their own restrictions on which type of plane they can or cannot flip, use the existing atomic_async_check() from struct drm_plane_helper_funcs to enhance this flexibility, thus allowing different plane types to be able to do async flips as well. Create a new parameter for the atomic_async_check(), `bool flip`. This parameter is used to distinguish when this function is being called from a plane update from a full page flip. In order to prevent regressions and such, we keep the current policy: we skip the driver check for the primary plane, because it is always allowed to do async flips on it. Signed-off-by: André Almeida Reviewed-by: Dmitry Baryshkov Reviewed-by: Christopher Snowhill Tested-by: Christopher Snowhill Link: https://patchwork.freedesktop.org/patch/msgid/20250127-tonyk-async_flip-v12-1-0f7f8a8610d3@igalia.com Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/drm_atomic_helper.c | 2 +- drivers/gpu/drm/drm_atomic_uapi.c | 37 +++++++++++++++------ drivers/gpu/drm/loongson/lsdc_plane.c | 3 +- drivers/gpu/drm/mediatek/mtk_plane.c | 2 +- drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 +- drivers/gpu/drm/tegra/dc.c | 3 +- drivers/gpu/drm/vc4/vc4_plane.c | 2 +- include/drm/drm_modeset_helper_vtables.h | 7 +++- 9 files changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index d6a206fc9ddd..fd3d14592663 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1966,7 +1966,7 @@ int drm_atomic_helper_async_check(struct drm_device *dev, return -EBUSY; } - ret = funcs->atomic_async_check(plane, state); + ret = funcs->atomic_async_check(plane, state, false); if (ret != 0) drm_dbg_atomic(dev, "[PLANE:%d:%s] driver async check failed\n", diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 370dc676e3aa..2765ba90ad8f 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -27,8 +27,9 @@ * Daniel Vetter */ -#include #include +#include +#include #include #include #include @@ -1063,6 +1064,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_plane *plane = obj_to_plane(obj); struct drm_plane_state *plane_state; struct drm_mode_config *config = &plane->dev->mode_config; + const struct drm_plane_helper_funcs *plane_funcs = plane->helper_private; plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) { @@ -1070,15 +1072,30 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } - if (async_flip && - (plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY || - (prop != config->prop_fb_id && - prop != config->prop_in_fence_fd && - prop != config->prop_fb_damage_clips))) { - ret = drm_atomic_plane_get_property(plane, plane_state, - prop, &old_val); - ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); - break; + if (async_flip) { + /* check if the prop does a nop change */ + if ((prop != config->prop_fb_id && + prop != config->prop_in_fence_fd && + prop != config->prop_fb_damage_clips)) { + ret = drm_atomic_plane_get_property(plane, plane_state, + prop, &old_val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + } + + /* ask the driver if this non-primary plane is supported */ + if (plane->type != DRM_PLANE_TYPE_PRIMARY) { + ret = -EINVAL; + + if (plane_funcs && plane_funcs->atomic_async_check) + ret = plane_funcs->atomic_async_check(plane, state, true); + + if (ret) { + drm_dbg_atomic(prop->dev, + "[PLANE:%d:%s] does not support async flips\n", + obj->id, plane->name); + break; + } + } } ret = drm_atomic_plane_set_property(plane, diff --git a/drivers/gpu/drm/loongson/lsdc_plane.c b/drivers/gpu/drm/loongson/lsdc_plane.c index d227a2c1dcf1..aa9a97f9c4dc 100644 --- a/drivers/gpu/drm/loongson/lsdc_plane.c +++ b/drivers/gpu/drm/loongson/lsdc_plane.c @@ -171,7 +171,8 @@ static const struct drm_plane_helper_funcs lsdc_primary_helper_funcs = { }; static int lsdc_cursor_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, + bool flip) { struct drm_plane_state *new_state; struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/mediatek/mtk_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c index 8a48b3b0a956..655106bbb76d 100644 --- a/drivers/gpu/drm/mediatek/mtk_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_plane.c @@ -101,7 +101,7 @@ static void mtk_plane_destroy_state(struct drm_plane *plane, } static int mtk_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, bool flip) { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index 62de248ed1b0..bb1601921938 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c @@ -368,7 +368,7 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, } static int mdp5_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, bool flip) { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 57747f1cff26..e3596e2b557d 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1072,7 +1072,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, } static int vop_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, bool flip) { struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 430b2eededb2..798507a8ae56 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1025,7 +1025,8 @@ static void tegra_cursor_atomic_disable(struct drm_plane *plane, tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); } -static int tegra_cursor_atomic_async_check(struct drm_plane *plane, struct drm_atomic_state *state) +static int tegra_cursor_atomic_async_check(struct drm_plane *plane, struct drm_atomic_state *state, + bool flip) { struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index d608860d525f..c5e84d3494d2 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -2338,7 +2338,7 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, } static int vc4_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, bool flip) { struct vc4_dev *vc4 = to_vc4_dev(plane->dev); struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index b62f41f48962..ce7c7aeac887 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -1400,13 +1400,18 @@ struct drm_plane_helper_funcs { * given update can be committed asynchronously, that is, if it can * jump ahead of the state currently queued for update. * + * This function is also used by drm_atomic_set_property() to determine + * if the plane can be flipped in async. The flip flag is used to + * distinguish if the function is used for just the plane state or for a + * flip. + * * RETURNS: * * Return 0 on success and any error returned indicates that the update * can not be applied in asynchronous manner. */ int (*atomic_async_check)(struct drm_plane *plane, - struct drm_atomic_state *state); + struct drm_atomic_state *state, bool flip); /** * @atomic_async_update: From 41129e236f14c6c54145c722da06f6793e9fd13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Mon, 27 Jan 2025 16:59:40 -0300 Subject: [PATCH 27/73] drm/amdgpu: Enable async flip on overlay planes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit amdgpu can handle async flips on overlay planes, so allow it for atomic async checks. Signed-off-by: André Almeida Acked-by: Alex Deucher Reviewed-by: Harry Wentland Link: https://patchwork.freedesktop.org/patch/msgid/20250127-tonyk-async_flip-v12-2-0f7f8a8610d3@igalia.com [DB: fixed checkpatch warning by adding braces] Signed-off-by: Dmitry Baryshkov --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index 774cc3f4f3fd..82cf6ddcaffe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -1258,21 +1258,24 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane, } static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane, - struct drm_atomic_state *state) + struct drm_atomic_state *state, bool flip) { struct drm_crtc_state *new_crtc_state; struct drm_plane_state *new_plane_state; struct dm_crtc_state *dm_new_crtc_state; - /* Only support async updates on cursor planes. */ - if (plane->type != DRM_PLANE_TYPE_CURSOR) + if (flip) { + if (plane->type != DRM_PLANE_TYPE_OVERLAY) + return -EINVAL; + } else if (plane->type != DRM_PLANE_TYPE_CURSOR) { return -EINVAL; + } new_plane_state = drm_atomic_get_new_plane_state(state, plane); new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); /* Reject overlay cursors for now*/ - if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE) + if (!flip && dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE) return -EINVAL; return 0; From 4fd6ca90fc7f509977585d39885f21b2911123f3 Mon Sep 17 00:00:00 2001 From: Lizhi Hou Date: Fri, 24 Jan 2025 09:35:36 -0800 Subject: [PATCH 28/73] accel/amdxdna: Refactor hardware context destroy routine It is required by firmware to wait up to 2 seconds for pending commands before sending the destroy hardware context command. After 2 seconds wait, if there are still pending commands, driver needs to cancel them. So the context destroy steps need to be: 1. Stop drm scheduler. (drm_sched_entity_destroy) 2. Wait up to 2 seconds for pending commands. 3. Destroy hardware context and cancel the rest pending requests. 4. Wait all jobs associated with the hwctx are freed. 5. Free job resources. Signed-off-by: Lizhi Hou Reviewed-by: Jeffrey Hugo Signed-off-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20250124173536.148676-1-lizhi.hou@amd.com --- drivers/accel/amdxdna/aie2_ctx.c | 37 ++++++++++++++++------------- drivers/accel/amdxdna/amdxdna_ctx.c | 2 ++ drivers/accel/amdxdna/amdxdna_ctx.h | 3 +++ 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 8ac01bc2f0db..00d215ac866e 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -34,6 +34,8 @@ static void aie2_job_release(struct kref *ref) job = container_of(ref, struct amdxdna_sched_job, refcnt); amdxdna_sched_job_cleanup(job); + atomic64_inc(&job->hwctx->job_free_cnt); + wake_up(&job->hwctx->priv->job_free_wq); if (job->out_fence) dma_fence_put(job->out_fence); kfree(job); @@ -134,7 +136,8 @@ static void aie2_hwctx_wait_for_idle(struct amdxdna_hwctx *hwctx) if (!fence) return; - dma_fence_wait(fence, false); + /* Wait up to 2 seconds for fw to finish all pending requests */ + dma_fence_wait_timeout(fence, false, msecs_to_jiffies(2000)); dma_fence_put(fence); } @@ -622,6 +625,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) hwctx->status = HWCTX_STAT_INIT; ndev = xdna->dev_handle; ndev->hwctx_num++; + init_waitqueue_head(&priv->job_free_wq); XDNA_DBG(xdna, "hwctx %s init completed", hwctx->name); @@ -658,24 +662,22 @@ void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx) xdna = hwctx->client->xdna; ndev = xdna->dev_handle; ndev->hwctx_num--; - drm_sched_wqueue_stop(&hwctx->priv->sched); - - /* Now, scheduler will not send command to device. */ - aie2_release_resource(hwctx); - - /* - * All submitted commands are aborted. - * Restart scheduler queues to cleanup jobs. The amdxdna_sched_job_run() - * will return NODEV if it is called. - */ - drm_sched_wqueue_start(&hwctx->priv->sched); - - aie2_hwctx_wait_for_idle(hwctx); - drm_sched_entity_destroy(&hwctx->priv->entity); - drm_sched_fini(&hwctx->priv->sched); - aie2_ctx_syncobj_destroy(hwctx); XDNA_DBG(xdna, "%s sequence number %lld", hwctx->name, hwctx->priv->seq); + drm_sched_entity_destroy(&hwctx->priv->entity); + + aie2_hwctx_wait_for_idle(hwctx); + + /* Request fw to destroy hwctx and cancel the rest pending requests */ + aie2_release_resource(hwctx); + + /* Wait for all submitted jobs to be completed or canceled */ + wait_event(hwctx->priv->job_free_wq, + atomic64_read(&hwctx->job_submit_cnt) == + atomic64_read(&hwctx->job_free_cnt)); + + drm_sched_fini(&hwctx->priv->sched); + aie2_ctx_syncobj_destroy(hwctx); for (idx = 0; idx < ARRAY_SIZE(hwctx->priv->cmd_buf); idx++) drm_gem_object_put(to_gobj(hwctx->priv->cmd_buf[idx])); @@ -885,6 +887,7 @@ int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, drm_gem_unlock_reservations(job->bos, job->bo_cnt, &acquire_ctx); aie2_job_put(job); + atomic64_inc(&hwctx->job_submit_cnt); return 0; diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c index d11b1c83d9c3..43442b9e273b 100644 --- a/drivers/accel/amdxdna/amdxdna_ctx.c +++ b/drivers/accel/amdxdna/amdxdna_ctx.c @@ -220,6 +220,8 @@ int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct dr args->syncobj_handle = hwctx->syncobj_hdl; mutex_unlock(&xdna->dev_lock); + atomic64_set(&hwctx->job_submit_cnt, 0); + atomic64_set(&hwctx->job_free_cnt, 0); XDNA_DBG(xdna, "PID %d create HW context %d, ret %d", client->pid, args->handle, ret); drm_dev_exit(idx); return 0; diff --git a/drivers/accel/amdxdna/amdxdna_ctx.h b/drivers/accel/amdxdna/amdxdna_ctx.h index 80b0304193ec..f0a4a8586d85 100644 --- a/drivers/accel/amdxdna/amdxdna_ctx.h +++ b/drivers/accel/amdxdna/amdxdna_ctx.h @@ -87,6 +87,9 @@ struct amdxdna_hwctx { struct amdxdna_qos_info qos; struct amdxdna_hwctx_param_config_cu *cus; u32 syncobj_hdl; + + atomic64_t job_submit_cnt; + atomic64_t job_free_cnt ____cacheline_aligned_in_smp; }; #define drm_job_to_xdna_job(j) \ From eb8f1e3e8ee10cff591d4a47437dfd34d850d454 Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:49 +0000 Subject: [PATCH 29/73] drm: panel-orientation-quirks: Add support for AYANEO 2S AYANEO 2S uses the same panel and orientation as the AYANEO 2. Update the AYANEO 2 DMI match to also match AYANEO 2S. Signed-off-by: Andrew Wyatt Signed-off-by: John Edwards Tested-by: John Edwards Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-2-uejji@uejji.net --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 4a73821b81f6..f9c975338fc9 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -184,10 +184,10 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"), }, .driver_data = (void *)&lcd800x1280_rightside_up, - }, { /* AYA NEO AYANEO 2 */ + }, { /* AYA NEO AYANEO 2/2S */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"), + DMI_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"), }, .driver_data = (void *)&lcd1200x1920_rightside_up, }, { /* AYA NEO 2021 */ From 529741c331da1fbf54f86c6ec3a4558b9b0b16dc Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:50 +0000 Subject: [PATCH 30/73] drm: panel-orientation-quirks: Add quirks for AYA NEO Flip DS and KB The AYA NEO Flip DS and KB both use a 1080x1920 portrait LCD panel. The Flip DS additionally uses a 640x960 portrait LCD panel as a second display. Add DMI matches to correctly rotate these panels. Signed-off-by: Andrew Wyatt Co-developed-by: John Edwards Signed-off-by: John Edwards Tested-by: Paco Avelar Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-3-uejji@uejji.net --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index f9c975338fc9..b5f6ae045945 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -93,6 +93,12 @@ static const struct drm_dmi_panel_orientation_data onegx1_pro = { .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, }; +static const struct drm_dmi_panel_orientation_data lcd640x960_leftside_up = { + .width = 640, + .height = 960, + .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, +}; + static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = { .width = 720, .height = 1280, @@ -202,6 +208,18 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_PRODUCT_NAME, "AIR"), }, .driver_data = (void *)&lcd1080x1920_leftside_up, + }, { /* AYA NEO Flip DS Bottom Screen */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FLIP DS"), + }, + .driver_data = (void *)&lcd640x960_leftside_up, + }, { /* AYA NEO Flip KB/DS Top Screen */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), + DMI_MATCH(DMI_PRODUCT_NAME, "FLIP"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* AYA NEO Founder */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYA NEO"), From 132c89ef8872e602cfb909377815111d121fe8d7 Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:51 +0000 Subject: [PATCH 31/73] drm: panel-orientation-quirks: Add quirk for AYA NEO Slide The AYANEO Slide uses a 1080x1920 portrait LCD panel. This is the same panel used on the AYANEO Air Plus, but the DMI data is too different to match both with one entry. Add a DMI match to correctly rotate the panel on the AYANEO Slide. This also covers the Antec Core HS, which is a rebranded AYANEO Slide with the exact same hardware and DMI strings. Signed-off-by: Andrew Wyatt Signed-off-by: John Edwards Tested-by: John Edwards Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-4-uejji@uejji.net --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index b5f6ae045945..b57078cfdd80 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -244,6 +244,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_BOARD_NAME, "KUN"), }, .driver_data = (void *)&lcd1600x2560_rightside_up, + }, { /* AYA NEO SLIDE */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), + DMI_MATCH(DMI_PRODUCT_NAME, "SLIDE"), + }, + .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* AYN Loki Max */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"), From a860eb9c6ba6cdbf32e3e01a606556e5a90a2931 Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:52 +0000 Subject: [PATCH 32/73] drm: panel-orientation-quirks: Add new quirk for GPD Win 2 Some GPD Win 2 units shipped with the correct DMI strings. Add a DMI match to correctly rotate the panel on these units. Signed-off-by: Andrew Wyatt Signed-off-by: John Edwards Tested-by: Paco Avelar Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-5-uejji@uejji.net --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index b57078cfdd80..384a8dcf454f 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -339,6 +339,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), }, .driver_data = (void *)&gpd_win2, + }, { /* GPD Win 2 (correct DMI strings) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "WIN2") + }, + .driver_data = (void *)&lcd720x1280_rightside_up, }, { /* GPD Win 3 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"), From b24dcc183583fc360ae0f0899e286a68f46abbd0 Mon Sep 17 00:00:00 2001 From: Andrew Wyatt Date: Thu, 13 Feb 2025 22:24:53 +0000 Subject: [PATCH 33/73] drm: panel-orientation-quirks: Add quirk for OneXPlayer Mini (Intel) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Intel model of the OneXPlayer Mini uses a 1200x1920 portrait LCD panel. The DMI strings are the same as the OneXPlayer, which already has a DMI quirk, but the panel is different. Add a DMI match to correctly rotate this panel. Signed-off-by: Andrew Wyatt Co-developed-by: John Edwards Signed-off-by: John Edwards Tested-by: João Pedro Kurtz Reviewed-by: Thomas Zimmermann Reviewed-by: Hans de Goede Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20250213222455.93533-6-uejji@uejji.net --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 384a8dcf454f..c554ad8f246b 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -129,6 +129,12 @@ static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = { .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, }; +static const struct drm_dmi_panel_orientation_data lcd1200x1920_leftside_up = { + .width = 1200, + .height = 1920, + .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, +}; + static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = { .width = 1200, .height = 1920, @@ -473,6 +479,12 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"), }, .driver_data = (void *)&lcd1600x2560_leftside_up, + }, { /* OneXPlayer Mini (Intel) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"), + }, + .driver_data = (void *)&lcd1200x1920_leftside_up, }, { /* OrangePi Neo */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"), From f65727be3fa5f252c8d982d15023aab8255ded19 Mon Sep 17 00:00:00 2001 From: Vitalii Mordan Date: Fri, 14 Feb 2025 18:46:32 +0300 Subject: [PATCH 34/73] gpu: cdns-mhdp8546: fix call balance of mhdp->clk handling routines If the clock mhdp->clk was not enabled in cdns_mhdp_probe(), it should not be disabled in any path. The return value of clk_prepare_enable() is not checked. If mhdp->clk was not enabled, it may be disabled in the error path of cdns_mhdp_probe() (e.g., if cdns_mhdp_load_firmware() fails) or in cdns_mhdp_remove() after a successful cdns_mhdp_probe() call. Use the devm_clk_get_enabled() helper function to ensure proper call balance for mhdp->clk. Found by Linux Verification Center (linuxtesting.org) with Klever. Fixes: fb43aa0acdfd ("drm: bridge: Add support for Cadence MHDP8546 DPI/DP bridge") Signed-off-by: Vitalii Mordan Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250214154632.1907425-1-mordan@ispras.ru --- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 25345c3274e3..01eeae7309e5 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2463,9 +2463,9 @@ static int cdns_mhdp_probe(struct platform_device *pdev) if (!mhdp) return -ENOMEM; - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) { - dev_err(dev, "couldn't get clk: %ld\n", PTR_ERR(clk)); + dev_err(dev, "couldn't get and enable clk: %ld\n", PTR_ERR(clk)); return PTR_ERR(clk); } @@ -2504,14 +2504,12 @@ static int cdns_mhdp_probe(struct platform_device *pdev) mhdp->info = of_device_get_match_data(dev); - clk_prepare_enable(clk); - pm_runtime_enable(dev); ret = pm_runtime_resume_and_get(dev); if (ret < 0) { dev_err(dev, "pm_runtime_resume_and_get failed\n"); pm_runtime_disable(dev); - goto clk_disable; + return ret; } if (mhdp->info && mhdp->info->ops && mhdp->info->ops->init) { @@ -2590,8 +2588,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev) runtime_put: pm_runtime_put_sync(dev); pm_runtime_disable(dev); -clk_disable: - clk_disable_unprepare(mhdp->clk); return ret; } @@ -2632,8 +2628,6 @@ static void cdns_mhdp_remove(struct platform_device *pdev) cancel_work_sync(&mhdp->modeset_retry_work); flush_work(&mhdp->hpd_work); /* Ignoring mhdp->hdcp.check_work and mhdp->hdcp.prop_work here. */ - - clk_disable_unprepare(mhdp->clk); } static const struct of_device_id mhdp_ids[] = { From 72443c730b7a7b5670a921ea928e17b9b99bd934 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 14 Feb 2025 13:57:40 +0100 Subject: [PATCH 35/73] drm/debugfs: fix printk format for bridge index idx is an unsigned int, use %u for printk-style strings. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-1-88ca5827d7af@bootlin.com --- drivers/gpu/drm/drm_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 536409a35df4..6b2178864c7e 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -748,7 +748,7 @@ static int bridges_show(struct seq_file *m, void *data) unsigned int idx = 0; drm_for_each_bridge_in_chain(encoder, bridge) { - drm_printf(&p, "bridge[%d]: %ps\n", idx++, bridge->funcs); + drm_printf(&p, "bridge[%u]: %ps\n", idx++, bridge->funcs); drm_printf(&p, "\ttype: [%d] %s\n", bridge->type, drm_get_connector_type_name(bridge->type)); From 9d60cf4e8cf7c480d2cbd03ebe971faa64c2b166 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 14 Feb 2025 13:57:41 +0100 Subject: [PATCH 36/73] drm: of: drm_of_find_panel_or_bridge: move misplaced comment This comment is misleading as it refers to one of the inner if() branches only, not the whole outer if(). Move it to the branch it refers to. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-2-88ca5827d7af@bootlin.com --- drivers/gpu/drm/drm_of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 5530919e0ba0..d0183dea7703 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -268,9 +268,9 @@ int drm_of_find_panel_or_bridge(const struct device_node *np, *panel = NULL; } - /* No panel found yet, check for a bridge next. */ if (bridge) { if (ret) { + /* No panel found yet, check for a bridge next. */ *bridge = of_drm_find_bridge(remote); if (*bridge) ret = 0; From cc46371e3d32de0e7ccb6077d064036822b8527f Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 14 Feb 2025 13:57:42 +0100 Subject: [PATCH 37/73] drm/bridge: panel: use drm_bridge_is_panel() instead of open code drm_panel_bridge_remove() reads bridge->funcs to find out whether this is a panel bridge or another kind of bridge. drm_bridge_is_panel() is made exactly for that, so use it. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-3-88ca5827d7af@bootlin.com --- drivers/gpu/drm/bridge/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 6e88339dec0f..0c5db13b11dc 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -322,7 +322,7 @@ void drm_panel_bridge_remove(struct drm_bridge *bridge) if (!bridge) return; - if (bridge->funcs != &panel_bridge_bridge_funcs) + if (!drm_bridge_is_panel(bridge)) return; panel_bridge = drm_bridge_to_panel_bridge(bridge); From 77053ef7207a964c3b8e4e38dda2e273da5ccfb3 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 14 Feb 2025 13:57:43 +0100 Subject: [PATCH 38/73] drm/bridge: panel: drm_panel_bridge_remove: warn when called on non-panel bridge This function is for panel_bridge instances only. The silent return when invoked on other bridges might hide actual errors, so avoid them to go unnoticed. Reviewed-by: Maxime Ripard Signed-off-by: Luca Ceresoli Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-4-88ca5827d7af@bootlin.com --- drivers/gpu/drm/bridge/panel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 0c5db13b11dc..c57036b06493 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -322,8 +322,10 @@ void drm_panel_bridge_remove(struct drm_bridge *bridge) if (!bridge) return; - if (!drm_bridge_is_panel(bridge)) + if (!drm_bridge_is_panel(bridge)) { + drm_warn(bridge->dev, "%s: called on non-panel bridge!\n", __func__); return; + } panel_bridge = drm_bridge_to_panel_bridge(bridge); From b296955b3a740ecc8b3b08e34fd64f1ceabb8fb4 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 14 Feb 2025 13:57:44 +0100 Subject: [PATCH 39/73] drm/bridge: panel: forbid initializing a panel with unknown connector type Having an DRM_MODE_CONNECTOR_Unknown connector type is considered bad, and drm_panel_bridge_add_typed() and derivatives are deprecated for this. drm_panel_init() won't prevent initializing a panel with a DRM_MODE_CONNECTOR_Unknown connector type. Luckily there are no in-tree users doing it, so take this as an opportinuty to document a valid connector type must be passed. Returning an error if this rule is violated is not possible because drm_panel_init() is a void function. Add at least a warning to make any violations noticeable, especially to non-upstream drivers. Reviewed-by: Dmitry Baryshkov Signed-off-by: Luca Ceresoli Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250214-drm-assorted-cleanups-v7-5-88ca5827d7af@bootlin.com --- drivers/gpu/drm/drm_panel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 9940e96d35e3..c627e42a7ce7 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -50,7 +50,7 @@ static LIST_HEAD(panel_list); * @dev: parent device of the panel * @funcs: panel operations * @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to - * the panel interface + * the panel interface (must NOT be DRM_MODE_CONNECTOR_Unknown) * * Initialize the panel structure for subsequent registration with * drm_panel_add(). @@ -58,6 +58,9 @@ static LIST_HEAD(panel_list); void drm_panel_init(struct drm_panel *panel, struct device *dev, const struct drm_panel_funcs *funcs, int connector_type) { + if (connector_type == DRM_MODE_CONNECTOR_Unknown) + DRM_WARN("%s: %s: a valid connector type is required!\n", __func__, dev_name(dev)); + INIT_LIST_HEAD(&panel->list); INIT_LIST_HEAD(&panel->followers); mutex_init(&panel->follower_lock); From 43c00fb1a5184ef68b1ae95a23476a85d4a4b0cc Mon Sep 17 00:00:00 2001 From: Shixiong Ou Date: Tue, 28 Jan 2025 14:56:45 +0800 Subject: [PATCH 40/73] drm/bridge: analogix_dp: Use devm_platform_ioremap_resource() Convert platform_get_resource(), devm_ioremap_resource() to a single call to devm_platform_ioremap_resource(). Signed-off-by: Shixiong Ou Reviewed-by: Robert Foss Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250128065645.27140-1-oushixiong1025@163.com --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index bfa88409a7ff..f6e4bdc05ba0 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1553,7 +1553,6 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data) { struct platform_device *pdev = to_platform_device(dev); struct analogix_dp_device *dp; - struct resource *res; unsigned int irq_flags; int ret; @@ -1605,9 +1604,7 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data) return ERR_CAST(dp->clock); } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - dp->reg_base = devm_ioremap_resource(&pdev->dev, res); + dp->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dp->reg_base)) { ret = PTR_ERR(dp->reg_base); goto err_disable_clk; From 272f17229e470af263823013792994fccf430fc7 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Mon, 20 Jan 2025 14:21:34 +0100 Subject: [PATCH 41/73] drm/bridge: ti-sn65dsi83: Set bridge type This is a DSI to LVDS bridge, so set the bridge type accordingly. Signed-off-by: Alexander Stein Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250120132135.554391-1-alexander.stein@ew.tq-group.com --- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index 8da9eb3832dd..a2c723f435ec 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -990,6 +990,7 @@ static int sn65dsi83_probe(struct i2c_client *client) ctx->bridge.funcs = &sn65dsi83_funcs; ctx->bridge.of_node = dev->of_node; ctx->bridge.pre_enable_prev_first = true; + ctx->bridge.type = DRM_MODE_CONNECTOR_LVDS; drm_bridge_add(&ctx->bridge); ret = sn65dsi83_host_attach(ctx); From 9b6c03cb96b9e19bce2c2764d2c6dd4ccbd06c5d Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Mon, 20 Jan 2025 14:21:35 +0100 Subject: [PATCH 42/73] drm/bridge: nwl-dsi: Set bridge type This is a DSI bridge, so set the bridge type accordingly. Signed-off-by: Alexander Stein Reviewed-by: Dmitry Baryshkov Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20250120132135.554391-2-alexander.stein@ew.tq-group.com --- drivers/gpu/drm/bridge/nwl-dsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 1e5b2a37cb8c..6f2581e0034b 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -1184,6 +1184,7 @@ static int nwl_dsi_probe(struct platform_device *pdev) dsi->bridge.funcs = &nwl_dsi_bridge_funcs; dsi->bridge.of_node = dev->of_node; dsi->bridge.timings = &nwl_dsi_timings; + dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; dev_set_drvdata(dev, dsi); pm_runtime_enable(dev); From fdee05235a25bac8495e1261be10a7727ffd0a79 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Feb 2025 10:31:21 +0300 Subject: [PATCH 43/73] drm/nouveau: Fix error pointer dereference in r535_gsp_msgq_recv() If "rpc" is an error pointer then return directly. Otherwise it leads to an error pointer dereference. Fixes: 50f290053d79 ("drm/nouveau: support handling the return of large GSP message") Signed-off-by: Dan Carpenter Acked-by: Zhi Wang Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/b7052ac0-98e4-433b-ad58-f563bf51858c@stanley.mountain --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 2075cad63805..db2602e88006 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -348,6 +348,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries) if (IS_ERR(buf)) { kvfree(info.gsp_rpc_buf); info.gsp_rpc_buf = NULL; + return buf; } if (expected <= max_rpc_size) From 56339ffaeaf87cce070c2437df71dc3340598be0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:20 +0100 Subject: [PATCH 44/73] drm/atomic: Document history of drm_atomic_state After some discussions on the mailing-list for an earlier revision of the series, it was suggested to document the evolution of drm_atomic_state and its use by drivers to explain some of the confusion one might still encounter when reading the framework code. Suggested-by: Simona Vetter Link: https://lore.kernel.org/dri-devel/Z4jtKHY4qN3RNZNG@phenom.ffwll.local/ Reviewed-by: Simona Vetter Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-1-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- include/drm/drm_atomic.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 1ded9a8d4e84..4c673f0698fe 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -357,6 +357,37 @@ struct __drm_private_objs_state { * States are added to an atomic update by calling drm_atomic_get_crtc_state(), * drm_atomic_get_plane_state(), drm_atomic_get_connector_state(), or for * private state structures, drm_atomic_get_private_obj_state(). + * + * NOTE: struct drm_atomic_state first started as a single collection of + * entities state pointers (drm_plane_state, drm_crtc_state, etc.). + * + * At atomic_check time, you could get the state about to be committed + * from drm_atomic_state, and the one currently running from the + * entities state pointer (drm_crtc.state, for example). After the call + * to drm_atomic_helper_swap_state(), the entities state pointer would + * contain the state previously checked, and the drm_atomic_state + * structure the old state. + * + * Over time, and in order to avoid confusion, drm_atomic_state has + * grown to have both the old state (ie, the state we replace) and the + * new state (ie, the state we want to apply). Those names are stable + * during the commit process, which makes it easier to reason about. + * + * You can still find some traces of that evolution through some hooks + * or callbacks taking a drm_atomic_state parameter called names like + * "old_state". This doesn't necessarily mean that the previous + * drm_atomic_state is passed, but rather that this used to be the state + * collection we were replacing after drm_atomic_helper_swap_state(), + * but the variable name was never updated. + * + * Some atomic operations implementations followed a similar process. We + * first started to pass the entity state only. However, it was pretty + * cumbersome for drivers, and especially CRTCs, to retrieve the states + * of other components. Thus, we switched to passing the whole + * drm_atomic_state as a parameter to those operations. Similarly, the + * transition isn't complete yet, and one might still find atomic + * operations taking a drm_atomic_state pointer, or a component state + * pointer. The former is the preferred form. */ struct drm_atomic_state { /** From e9db46e57661553444bf4543621c8d0202616501 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:21 +0100 Subject: [PATCH 45/73] drm/bridge: Pass full state to atomic_pre_enable It's pretty inconvenient to access the full atomic state from drm_bridges, so let's change the atomic_pre_enable hook prototype to pass it directly. Reviewed-by: Dmitry Baryshkov Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-2-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- .../gpu/drm/bridge/analogix/analogix_dp_core.c | 6 ++---- drivers/gpu/drm/bridge/chipone-icn6211.c | 2 +- drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 7 +++---- drivers/gpu/drm/bridge/ite-it6505.c | 2 +- drivers/gpu/drm/bridge/lontium-lt9611.c | 2 +- drivers/gpu/drm/bridge/panel.c | 3 +-- drivers/gpu/drm/bridge/parade-ps8640.c | 2 +- drivers/gpu/drm/bridge/samsung-dsim.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c | 2 +- drivers/gpu/drm/bridge/tc358762.c | 3 ++- drivers/gpu/drm/bridge/ti-dlpc3433.c | 2 +- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 3 +-- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 2 +- drivers/gpu/drm/drm_bridge.c | 15 +++------------ drivers/gpu/drm/mediatek/mtk_dsi.c | 2 +- drivers/gpu/drm/mediatek/mtk_hdmi.c | 2 +- drivers/gpu/drm/vc4/vc4_dsi.c | 3 +-- include/drm/drm_bridge.h | 2 +- 19 files changed, 25 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index f6e4bdc05ba0..e17dbcb0a493 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1197,11 +1197,9 @@ struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp, return conn_state->crtc; } -static void -analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *old_state) { - struct drm_atomic_state *old_state = old_bridge_state->base.state; struct analogix_dp_device *dp = bridge->driver_private; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index d47703559b0d..7a009ab57f9e 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -445,7 +445,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge, } static void chipone_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct chipone *icn = bridge_to_chipone(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c index 7bce2305d676..009c7fcb3d59 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c @@ -203,9 +203,8 @@ imx8qxp_ldb_bridge_mode_set(struct drm_bridge *bridge, companion->funcs->mode_set(companion, mode, adjusted_mode); } -static void -imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct ldb_channel *ldb_ch = bridge->driver_private; struct ldb *ldb = ldb_ch->ldb; @@ -217,7 +216,7 @@ imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge, clk_prepare_enable(imx8qxp_ldb->clk_bypass); if (is_split && companion) - companion->funcs->atomic_pre_enable(companion, old_bridge_state); + companion->funcs->atomic_pre_enable(companion, state); } static void diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 76dabca04d0d..647579342a0a 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3254,7 +3254,7 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge, } static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct it6505 *it6505 = bridge_to_it6505(bridge); struct device *dev = it6505->dev; diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index e650cd83fc8d..5d3bbfeaf229 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -767,7 +767,7 @@ static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge, } static void lt9611_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct lt9611 *lt9611 = bridge_to_lt9611(bridge); static const struct reg_sequence reg_cfg[] = { diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index c57036b06493..5653885412cb 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -109,10 +109,9 @@ static void panel_bridge_detach(struct drm_bridge *bridge) } static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_encoder *encoder = bridge->encoder; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index b0e38177c1ec..7ec674bffa81 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -437,7 +437,7 @@ static const struct dev_pm_ops ps8640_pm_ops = { }; static void ps8640_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL]; diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index f8b4fb835765..415ce14e747d 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1457,7 +1457,7 @@ static int samsung_dsim_init(struct samsung_dsim *dsi) } static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct samsung_dsim *dsi = bridge_to_dsi(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 0fb02e4e7f4e..9731a6b45a52 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -1022,7 +1022,7 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi, } static void dw_mipi_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c index d7569bf2d9c3..194ac6e192f4 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c @@ -821,7 +821,7 @@ static void dw_mipi_dsi2_mode_set(struct dw_mipi_dsi2 *dsi2, } static void dw_mipi_dsi2_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dw_mipi_dsi2 *dsi2 = bridge_to_dsi2(bridge); diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index f92aff3d515a..15daf6d97365 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -171,7 +171,8 @@ static void tc358762_post_disable(struct drm_bridge *bridge, struct drm_bridge_s dev_err(ctx->dev, "error disabling regulators (%d)\n", ret); } -static void tc358762_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *state) +static void tc358762_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tc358762 *ctx = bridge_to_tc358762(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c index eaec70fa42b6..c513cd190204 100644 --- a/drivers/gpu/drm/bridge/ti-dlpc3433.c +++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c @@ -170,7 +170,7 @@ static void dlpc_atomic_enable(struct drm_bridge *bridge, } static void dlpc_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dlpc *dlpc = bridge_to_dlpc(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index a2c723f435ec..d0a4fc7ca11b 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -469,10 +469,9 @@ static void sn65dsi83_monitor_stop(struct sn65dsi83 *ctx) } static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); - struct drm_atomic_state *state = old_bridge_state->base.state; const struct drm_bridge_state *bridge_state; const struct drm_crtc_state *crtc_state; const struct drm_display_mode *mode; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 205bd0fde4f8..86bbfdc37d97 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1164,7 +1164,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge, } static void ti_sn_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 241a384ebce3..e6bf964ddd82 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -698,19 +698,10 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable); static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge, struct drm_atomic_state *old_state) { - if (old_state && bridge->funcs->atomic_pre_enable) { - struct drm_bridge_state *old_bridge_state; - - old_bridge_state = - drm_atomic_get_old_bridge_state(old_state, - bridge); - if (WARN_ON(!old_bridge_state)) - return; - - bridge->funcs->atomic_pre_enable(bridge, old_bridge_state); - } else if (bridge->funcs->pre_enable) { + if (old_state && bridge->funcs->atomic_pre_enable) + bridge->funcs->atomic_pre_enable(bridge, old_state); + else if (bridge->funcs->pre_enable) bridge->funcs->pre_enable(bridge); - } } /** diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 40752f232054..aed9d03bcf01 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -845,7 +845,7 @@ static void mtk_dsi_bridge_atomic_enable(struct drm_bridge *bridge, } static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct mtk_dsi *dsi = bridge_to_dsi(bridge); int ret; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index ca82bc829cb9..928909b4403a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1362,7 +1362,7 @@ static void mtk_hdmi_bridge_mode_set(struct drm_bridge *bridge, } static void mtk_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 5eb293bdb363..eb747ea3325c 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -873,9 +873,8 @@ static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge, } static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *state = old_state->base.state; struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); const struct drm_crtc_state *crtc_state; struct device *dev = &dsi->pdev->dev; diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 496dbbd2ad7e..eef4487f45af 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -305,7 +305,7 @@ struct drm_bridge_funcs { * The @atomic_pre_enable callback is optional. */ void (*atomic_pre_enable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); /** * @atomic_enable: From c2b190bf2a8bd02ac196a5a41a00f2bbb73e8252 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:22 +0100 Subject: [PATCH 46/73] drm/bridge: Pass full state to atomic_enable It's pretty inconvenient to access the full atomic state from drm_bridges, so let's change the atomic_enable hook prototype to pass it directly. Reviewed-by: Dmitry Baryshkov Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-3-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 2 +- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 6 ++---- drivers/gpu/drm/bridge/analogix/anx7625.c | 6 +++--- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 3 +-- drivers/gpu/drm/bridge/chipone-icn6211.c | 3 +-- drivers/gpu/drm/bridge/fsl-ldb.c | 3 +-- drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c | 5 +++-- drivers/gpu/drm/bridge/imx/imx8qm-ldb.c | 5 ++--- drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 7 +++---- drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c | 5 ++--- drivers/gpu/drm/bridge/ite-it6263.c | 6 ++---- drivers/gpu/drm/bridge/ite-it6505.c | 3 +-- drivers/gpu/drm/bridge/ite-it66121.c | 3 +-- drivers/gpu/drm/bridge/lontium-lt9211.c | 3 +-- drivers/gpu/drm/bridge/lontium-lt9611.c | 6 ++---- drivers/gpu/drm/bridge/nwl-dsi.c | 5 ++--- drivers/gpu/drm/bridge/panel.c | 3 +-- drivers/gpu/drm/bridge/samsung-dsim.c | 2 +- drivers/gpu/drm/bridge/sii902x.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 3 +-- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 3 +-- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c | 2 +- drivers/gpu/drm/bridge/tc358762.c | 3 ++- drivers/gpu/drm/bridge/tc358767.c | 10 ++++------ drivers/gpu/drm/bridge/ti-dlpc3433.c | 2 +- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 2 +- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 4 ++-- drivers/gpu/drm/bridge/ti-tdp158.c | 3 ++- drivers/gpu/drm/drm_bridge.c | 10 +--------- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 2 +- drivers/gpu/drm/mediatek/mtk_dp.c | 4 ++-- drivers/gpu/drm/mediatek/mtk_dsi.c | 2 +- drivers/gpu/drm/mediatek/mtk_hdmi.c | 3 +-- drivers/gpu/drm/meson/meson_encoder_cvbs.c | 3 +-- drivers/gpu/drm/meson/meson_encoder_dsi.c | 3 +-- drivers/gpu/drm/meson/meson_encoder_hdmi.c | 3 +-- drivers/gpu/drm/msm/dp/dp_display.c | 12 ++++++------ drivers/gpu/drm/msm/dp/dp_drm.c | 9 ++++----- drivers/gpu/drm/msm/dp/dp_drm.h | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 3 +-- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 3 +-- drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c | 3 +-- drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c | 2 +- drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 3 +-- drivers/gpu/drm/stm/lvds.c | 3 +-- drivers/gpu/drm/vc4/vc4_dsi.c | 2 +- drivers/gpu/drm/xlnx/zynqmp_dp.c | 10 ++++------ include/drm/drm_bridge.h | 2 +- 49 files changed, 79 insertions(+), 117 deletions(-) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 19f4319eb647..3d22685d33b5 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -911,7 +911,7 @@ static struct adv7511 *bridge_to_adv7511(struct drm_bridge *bridge) } static void adv7511_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct adv7511 *adv = bridge_to_adv7511(bridge); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index e17dbcb0a493..7fc0918c086d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1255,11 +1255,9 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp) return ret; } -static void -analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *old_state) { - struct drm_atomic_state *old_state = old_bridge_state->base.state; struct analogix_dp_device *dp = bridge->driver_private; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 4be34d5c7a3b..79f78dbe9635 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2380,7 +2380,7 @@ static int anx7625_bridge_atomic_check(struct drm_bridge *bridge, } static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *state) + struct drm_atomic_state *state) { struct anx7625_data *ctx = bridge_to_anx7625(bridge); struct device *dev = ctx->dev; @@ -2389,7 +2389,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge, dev_dbg(dev, "drm atomic enable\n"); - connector = drm_atomic_get_new_connector_for_encoder(state->base.state, + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); if (!connector) return; @@ -2401,7 +2401,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge, anx7625_dp_start(ctx); - conn_state = drm_atomic_get_new_connector_state(state->base.state, connector); + conn_state = drm_atomic_get_new_connector_state(state, connector); if (WARN_ON(!conn_state)) return; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 01eeae7309e5..edc5347551e5 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -1979,10 +1979,9 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp, } static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); - struct drm_atomic_state *state = bridge_state->base.state; struct cdns_mhdp_bridge_state *mhdp_state; struct drm_crtc_state *crtc_state; struct drm_connector *connector; diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 7a009ab57f9e..2d9e3add135c 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -341,10 +341,9 @@ static void chipone_configure_pll(struct chipone *icn, } static void chipone_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct chipone *icn = bridge_to_chipone(bridge); - struct drm_atomic_state *state = old_bridge_state->base.state; struct drm_display_mode *mode = &icn->mode; const struct drm_bridge_state *bridge_state; u16 hfp, hbp, hsync; diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c index 0fc8a14fd800..0ba8bbc1afae 100644 --- a/drivers/gpu/drm/bridge/fsl-ldb.c +++ b/drivers/gpu/drm/bridge/fsl-ldb.c @@ -122,10 +122,9 @@ static int fsl_ldb_attach(struct drm_bridge *bridge, } static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge); - struct drm_atomic_state *state = old_bridge_state->base.state; const struct drm_bridge_state *bridge_state; const struct drm_crtc_state *crtc_state; const struct drm_display_mode *mode; diff --git a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c index 0d1ac3edcab4..9ee645489ea3 100644 --- a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c +++ b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c @@ -49,16 +49,17 @@ static int imx8mp_hdmi_pvi_bridge_attach(struct drm_bridge *bridge, } static void imx8mp_hdmi_pvi_bridge_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *state = bridge_state->base.state; struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge); struct drm_connector_state *conn_state; + struct drm_bridge_state *bridge_state; const struct drm_display_mode *mode; struct drm_crtc_state *crtc_state; struct drm_connector *connector; u32 bus_flags = 0, val; + bridge_state = drm_atomic_get_new_bridge_state(state, bridge); connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); conn_state = drm_atomic_get_new_connector_state(state, connector); crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); diff --git a/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c index dd5823f04c70..fe2313aa2051 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c +++ b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c @@ -200,9 +200,8 @@ imx8qm_ldb_bridge_mode_set(struct drm_bridge *bridge, CH_HSYNC_M(chno), CH_PHSYNC(chno)); } -static void -imx8qm_ldb_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qm_ldb_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct ldb_channel *ldb_ch = bridge->driver_private; struct ldb *ldb = ldb_ch->ldb; diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c index 009c7fcb3d59..f3f5b7b810f6 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c @@ -219,9 +219,8 @@ static void imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge, companion->funcs->atomic_pre_enable(companion, state); } -static void -imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct ldb_channel *ldb_ch = bridge->driver_private; struct ldb *ldb = ldb_ch->ldb; @@ -251,7 +250,7 @@ imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge, DRM_DEV_ERROR(dev, "failed to power on PHY: %d\n", ret); if (is_split && companion) - companion->funcs->atomic_enable(companion, old_bridge_state); + companion->funcs->atomic_enable(companion, state); } static void diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c index 4b0715ed6f38..9b79e5dbcaca 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c @@ -153,9 +153,8 @@ imx8qxp_pixel_link_bridge_mode_set(struct drm_bridge *bridge, imx8qxp_pixel_link_set_mst_addr(pl); } -static void -imx8qxp_pixel_link_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qxp_pixel_link_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct imx8qxp_pixel_link *pl = bridge->driver_private; diff --git a/drivers/gpu/drm/bridge/ite-it6263.c b/drivers/gpu/drm/bridge/ite-it6263.c index 306b5e374b9e..0cf624a8495c 100644 --- a/drivers/gpu/drm/bridge/ite-it6263.c +++ b/drivers/gpu/drm/bridge/ite-it6263.c @@ -581,11 +581,9 @@ it6263_bridge_atomic_disable(struct drm_bridge *bridge, AFE_DRV_RST | AFE_DRV_PWD); } -static void -it6263_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void it6263_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { - struct drm_atomic_state *state = old_bridge_state->base.state; struct it6263 *it = bridge_to_it6263(bridge); const struct drm_crtc_state *crtc_state; struct regmap *regmap = it->hdmi_regmap; diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 647579342a0a..159fdce35129 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3183,11 +3183,10 @@ it6505_bridge_mode_valid(struct drm_bridge *bridge, } static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct it6505 *it6505 = bridge_to_it6505(bridge); struct device *dev = it6505->dev; - struct drm_atomic_state *state = old_state->base.state; struct hdmi_avi_infoframe frame; struct drm_crtc_state *crtc_state; struct drm_connector_state *conn_state; diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 23edcde6b9a7..4b784ac04b3a 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -721,10 +721,9 @@ static u32 *it66121_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, } static void it66121_bridge_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); - struct drm_atomic_state *state = bridge_state->base.state; ctx->connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c index 999ddebb832d..65d5cdfe0d32 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9211.c +++ b/drivers/gpu/drm/bridge/lontium-lt9211.c @@ -455,10 +455,9 @@ static int lt9211_configure_tx(struct lt9211 *ctx, bool jeida, } static void lt9211_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct lt9211 *ctx = bridge_to_lt9211(bridge); - struct drm_atomic_state *state = old_bridge_state->base.state; const struct drm_bridge_state *bridge_state; const struct drm_crtc_state *crtc_state; const struct drm_display_mode *mode; diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index 5d3bbfeaf229..521cce42d033 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -640,12 +640,10 @@ lt9611_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) } /* bridge funcs */ -static void -lt9611_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void lt9611_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct lt9611 *lt9611 = bridge_to_lt9611(bridge); - struct drm_atomic_state *state = old_bridge_state->base.state; struct drm_connector *connector; struct drm_connector_state *conn_state; struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 6f2581e0034b..516ef0409b5d 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -898,9 +898,8 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge, pm_runtime_put_sync(dev); } -static void -nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 5653885412cb..08b1704b0ab2 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -128,10 +128,9 @@ static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge, } static void panel_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_encoder *encoder = bridge->encoder; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 415ce14e747d..ddf55fad2815 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1485,7 +1485,7 @@ static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge, } static void samsung_dsim_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct samsung_dsim *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index bf2d1632b020..ae53d94a3931 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -339,7 +339,7 @@ static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge, } static void sii902x_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct sii902x *sii902x = bridge_to_sii902x(bridge); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index b281cabfe992..e48084201623 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -362,10 +362,9 @@ static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi, } static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct dw_hdmi_qp *hdmi = bridge->driver_private; - struct drm_atomic_state *state = old_state->base.state; struct drm_connector_state *conn_state; struct drm_connector *connector; unsigned int op_mode; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index d1256c82de96..b92e1fa9f352 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2959,10 +2959,9 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, } static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct dw_hdmi *hdmi = bridge->driver_private; - struct drm_atomic_state *state = old_state->base.state; struct drm_connector *connector; connector = drm_atomic_get_new_connector_for_encoder(state, diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 9731a6b45a52..f9371b19a476 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -1043,7 +1043,7 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge, } static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c index 194ac6e192f4..1d9d16fbcc7f 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c @@ -840,7 +840,7 @@ static void dw_mipi_dsi2_bridge_mode_set(struct drm_bridge *bridge, } static void dw_mipi_dsi2_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dw_mipi_dsi2 *dsi2 = bridge_to_dsi2(bridge); diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index 15daf6d97365..6ed8ae6ffc3d 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -189,7 +189,8 @@ static void tc358762_pre_enable(struct drm_bridge *bridge, ctx->pre_enabled = true; } -static void tc358762_enable(struct drm_bridge *bridge, struct drm_bridge_state *state) +static void tc358762_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tc358762 *ctx = bridge_to_tc358762(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 4637bf6ea7a3..a1f72e61b944 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1548,9 +1548,8 @@ static int tc_edp_stream_disable(struct tc_data *tc) return 0; } -static void -tc_dpi_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void tc_dpi_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tc_data *tc = bridge_to_tc(bridge); @@ -1576,9 +1575,8 @@ tc_dpi_bridge_atomic_disable(struct drm_bridge *bridge, dev_err(tc->dev, "main link stream stop error: %d\n", ret); } -static void -tc_edp_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void tc_edp_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tc_data *tc = bridge_to_tc(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c index c513cd190204..963af4fc28a8 100644 --- a/drivers/gpu/drm/bridge/ti-dlpc3433.c +++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c @@ -105,7 +105,7 @@ static const struct regmap_config dlpc_regmap_config = { }; static void dlpc_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dlpc *dlpc = bridge_to_dlpc(bridge); struct device *dev = dlpc->dev; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index d0a4fc7ca11b..3ea3165b6e05 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -639,7 +639,7 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, } static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); unsigned int pval; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 86bbfdc37d97..c3ad7e326ae8 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1073,7 +1073,7 @@ static int ti_sn_link_training(struct ti_sn65dsi86 *pdata, int dp_rate_idx, } static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); struct drm_connector *connector; @@ -1085,7 +1085,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge, int max_dp_lanes; unsigned int bpp; - connector = drm_atomic_get_new_connector_for_encoder(old_bridge_state->base.state, + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); if (!connector) { dev_err_ratelimited(pdata->dev, "Could not get the connector\n"); diff --git a/drivers/gpu/drm/bridge/ti-tdp158.c b/drivers/gpu/drm/bridge/ti-tdp158.c index 3472ed5924e8..c0308f997445 100644 --- a/drivers/gpu/drm/bridge/ti-tdp158.c +++ b/drivers/gpu/drm/bridge/ti-tdp158.c @@ -18,7 +18,8 @@ struct tdp158 { struct device *dev; }; -static void tdp158_enable(struct drm_bridge *bridge, struct drm_bridge_state *prev) +static void tdp158_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { int err; struct tdp158 *tdp158 = bridge->driver_private; diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index e6bf964ddd82..7d9d176347f3 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -806,15 +806,7 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, encoder = bridge->encoder; list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { if (bridge->funcs->atomic_enable) { - struct drm_bridge_state *old_bridge_state; - - old_bridge_state = - drm_atomic_get_old_bridge_state(old_state, - bridge); - if (WARN_ON(!old_bridge_state)) - return; - - bridge->funcs->atomic_enable(bridge, old_bridge_state); + bridge->funcs->atomic_enable(bridge, old_state); } else if (bridge->funcs->enable) { bridge->funcs->enable(bridge); } diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index c23ee2d214de..e52d8c4f0b7e 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -229,7 +229,7 @@ static int ingenic_drm_update_pixclk(struct notifier_block *nb, } static void ingenic_drm_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ingenic_drm *priv = drm_device_get_priv(bridge->dev); diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index cd385ba4c66a..bd67423556b7 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2350,12 +2350,12 @@ static void mtk_dp_bridge_detach(struct drm_bridge *bridge) } static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); int ret; - mtk_dp->conn = drm_atomic_get_new_connector_for_encoder(old_state->base.state, + mtk_dp->conn = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); if (!mtk_dp->conn) { drm_err(mtk_dp->drm_dev, diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index aed9d03bcf01..be21f8e64317 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -834,7 +834,7 @@ static void mtk_dsi_bridge_atomic_disable(struct drm_bridge *bridge, } static void mtk_dsi_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct mtk_dsi *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 928909b4403a..a1904480fff8 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1383,9 +1383,8 @@ static void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi, } static void mtk_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *state = old_state->base.state; struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); /* Retrieve the connector through the atomic state. */ diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c index d1191de855d9..b535e74345f0 100644 --- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c +++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c @@ -139,10 +139,9 @@ static int meson_encoder_cvbs_atomic_check(struct drm_bridge *bridge, } static void meson_encoder_cvbs_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct meson_encoder_cvbs *encoder_cvbs = bridge_to_meson_encoder_cvbs(bridge); - struct drm_atomic_state *state = bridge_state->base.state; struct meson_drm *priv = encoder_cvbs->priv; const struct meson_cvbs_mode *meson_mode; struct drm_connector_state *conn_state; diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c index 7816902f5907..140b3604dba1 100644 --- a/drivers/gpu/drm/meson/meson_encoder_dsi.c +++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c @@ -42,10 +42,9 @@ static int meson_encoder_dsi_attach(struct drm_bridge *bridge, } static void meson_encoder_dsi_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct meson_encoder_dsi *encoder_dsi = bridge_to_meson_encoder_dsi(bridge); - struct drm_atomic_state *state = bridge_state->base.state; struct meson_drm *priv = encoder_dsi->priv; struct drm_connector_state *conn_state; struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index 0593a1cde906..7544c4e6af63 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -186,10 +186,9 @@ static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bri } static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); - struct drm_atomic_state *state = bridge_state->base.state; unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR; struct meson_drm *priv = encoder_hdmi->priv; struct drm_connector_state *conn_state; diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 24dd37f1682b..ffb9c80543ad 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1491,13 +1491,13 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev, } void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = msm_dp_bridge->msm_dp_display; int rc = 0; struct msm_dp_display_private *msm_dp_display; - u32 state; + u32 hpd_state; bool force_link_train = false; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); @@ -1516,8 +1516,8 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; } - state = msm_dp_display->hpd_state; - if (state != ST_DISPLAY_OFF && state != ST_MAINLINK_READY) { + hpd_state = msm_dp_display->hpd_state; + if (hpd_state != ST_DISPLAY_OFF && hpd_state != ST_MAINLINK_READY) { mutex_unlock(&msm_dp_display->event_mutex); return; } @@ -1529,9 +1529,9 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, return; } - state = msm_dp_display->hpd_state; + hpd_state = msm_dp_display->hpd_state; - if (state == ST_DISPLAY_OFF) { + if (hpd_state == ST_DISPLAY_OFF) { msm_dp_display_host_phy_init(msm_dp_display); force_link_train = true; } diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index d3e241ea6941..eae8e849edc5 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -137,9 +137,8 @@ static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge, } static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); @@ -151,19 +150,19 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, * If the panel is in psr, just exit psr state and skip the full * bridge enable sequence. */ - crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state, + crtc = drm_atomic_get_new_crtc_for_encoder(state, drm_bridge->encoder); if (!crtc) return; - old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc); + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); if (old_crtc_state && old_crtc_state->self_refresh_active) { msm_dp_display_set_psr(dp, false); return; } - msm_dp_bridge_atomic_enable(drm_bridge, old_bridge_state); + msm_dp_bridge_atomic_enable(drm_bridge, state); } static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 8eae2f74839f..d54253ecbbff 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -26,7 +26,7 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, bool yuv_supported); void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, struct drm_bridge_state *old_bridge_state); void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 4435f0027c78..c43f4a5218d1 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -341,10 +341,9 @@ static void hdmi4_bridge_mode_set(struct drm_bridge *bridge, } static void hdmi4_bridge_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); - struct drm_atomic_state *state = bridge_state->base.state; struct drm_connector_state *conn_state; struct drm_connector *connector; struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index a8c740df3146..49a4d31243e7 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -339,10 +339,9 @@ static void hdmi5_bridge_mode_set(struct drm_bridge *bridge, } static void hdmi5_bridge_enable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); - struct drm_atomic_state *state = bridge_state->base.state; struct drm_connector_state *conn_state; struct drm_connector *connector; struct drm_crtc_state *crtc_state; diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c index e8d64583e3bd..86e112fe1fc4 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c @@ -582,9 +582,8 @@ EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable); */ static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *state = old_bridge_state->base.state; struct drm_connector *connector; struct drm_crtc *crtc; diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c index 3c0c18d5249a..4c8f63bd106e 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c @@ -808,7 +808,7 @@ static int rcar_mipi_dsi_attach(struct drm_bridge *bridge, } static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c index fa7a1ae22aa3..1eafb637092b 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c @@ -532,9 +532,8 @@ static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge, } static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *state = old_bridge_state->base.state; struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); const struct drm_display_mode *mode; struct drm_connector *connector; diff --git a/drivers/gpu/drm/stm/lvds.c b/drivers/gpu/drm/stm/lvds.c index 06f2d7a56cc9..7ec44f226403 100644 --- a/drivers/gpu/drm/stm/lvds.c +++ b/drivers/gpu/drm/stm/lvds.c @@ -980,9 +980,8 @@ static int lvds_attach(struct drm_bridge *bridge, } static void lvds_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { - struct drm_atomic_state *state = old_bridge_state->base.state; struct stm_lvds *lvds = bridge_to_stm_lvds(bridge); struct drm_connector_state *conn_state; struct drm_connector *connector; diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index eb747ea3325c..59d881ddf0ee 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -1142,7 +1142,7 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge, } static void vc4_dsi_bridge_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); bool debug_dump_regs = false; diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index e3bf97a4a3c5..576683dfcae0 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -1437,7 +1437,7 @@ zynqmp_dp_disp_connected_live_layer(struct zynqmp_dp *dp) } static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct zynqmp_disp_layer *layer; struct drm_bridge_state *bridge_state; @@ -1447,8 +1447,7 @@ static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp, if (!layer) return; - bridge_state = drm_atomic_get_new_bridge_state(old_bridge_state->base.state, - old_bridge_state->bridge); + bridge_state = drm_atomic_get_new_bridge_state(state, &dp->bridge); if (WARN_ON(!bridge_state)) return; @@ -1549,10 +1548,9 @@ zynqmp_dp_bridge_mode_valid(struct drm_bridge *bridge, } static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct zynqmp_dp *dp = bridge_to_dp(bridge); - struct drm_atomic_state *state = old_bridge_state->base.state; const struct drm_crtc_state *crtc_state; const struct drm_display_mode *adjusted_mode; const struct drm_display_mode *mode; @@ -1565,7 +1563,7 @@ static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge, pm_runtime_get_sync(dp->dev); guard(mutex)(&dp->lock); - zynqmp_dp_disp_enable(dp, old_bridge_state); + zynqmp_dp_disp_enable(dp, state); /* * Retrieve the CRTC mode and adjusted mode. This requires a little diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index eef4487f45af..4c5e23123030 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -325,7 +325,7 @@ struct drm_bridge_funcs { * The @atomic_enable callback is optional. */ void (*atomic_enable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); /** * @atomic_disable: * From f5f6a5bf01096fbb8d33d917de3df681374d2b52 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:23 +0100 Subject: [PATCH 47/73] drm/bridge: Pass full state to atomic_disable It's pretty inconvenient to access the full atomic state from drm_bridges, so let's change the atomic_disable hook prototype to pass it directly. Reviewed-by: Dmitry Baryshkov Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-4-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 2 +- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 6 ++---- drivers/gpu/drm/bridge/analogix/anx7625.c | 2 +- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 2 +- drivers/gpu/drm/bridge/fsl-ldb.c | 2 +- drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c | 2 +- drivers/gpu/drm/bridge/imx/imx8qm-ldb.c | 5 ++--- drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c | 7 +++---- drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c | 5 ++--- drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c | 5 ++--- drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c | 8 +++----- drivers/gpu/drm/bridge/ite-it6263.c | 5 ++--- drivers/gpu/drm/bridge/ite-it6505.c | 2 +- drivers/gpu/drm/bridge/ite-it66121.c | 2 +- drivers/gpu/drm/bridge/lontium-lt9211.c | 2 +- drivers/gpu/drm/bridge/lontium-lt9611.c | 5 ++--- drivers/gpu/drm/bridge/nwl-dsi.c | 5 ++--- drivers/gpu/drm/bridge/panel.c | 3 +-- drivers/gpu/drm/bridge/samsung-dsim.c | 2 +- drivers/gpu/drm/bridge/sii902x.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- drivers/gpu/drm/bridge/tc358767.c | 10 ++++------ drivers/gpu/drm/bridge/ti-sn65dsi83.c | 2 +- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 2 +- drivers/gpu/drm/bridge/ti-tdp158.c | 3 ++- drivers/gpu/drm/drm_bridge.c | 10 +--------- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 2 +- drivers/gpu/drm/mediatek/mtk_dp.c | 2 +- drivers/gpu/drm/mediatek/mtk_dsi.c | 2 +- drivers/gpu/drm/mediatek/mtk_hdmi.c | 2 +- drivers/gpu/drm/meson/meson_encoder_cvbs.c | 2 +- drivers/gpu/drm/meson/meson_encoder_dsi.c | 2 +- drivers/gpu/drm/meson/meson_encoder_hdmi.c | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 2 +- drivers/gpu/drm/msm/dp/dp_drm.c | 5 ++--- drivers/gpu/drm/msm/dp/dp_drm.h | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 2 +- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 2 +- drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c | 2 +- drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c | 2 +- drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 2 +- drivers/gpu/drm/stm/lvds.c | 2 +- drivers/gpu/drm/vc4/vc4_dsi.c | 2 +- drivers/gpu/drm/xlnx/zynqmp_dp.c | 4 +++- include/drm/drm_bridge.h | 2 +- 46 files changed, 64 insertions(+), 84 deletions(-) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 3d22685d33b5..050dae338ffe 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -919,7 +919,7 @@ static void adv7511_bridge_atomic_enable(struct drm_bridge *bridge, } static void adv7511_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct adv7511 *adv = bridge_to_adv7511(bridge); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 7fc0918c086d..78391682cca9 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1323,11 +1323,9 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) dp->dpms_mode = DRM_MODE_DPMS_OFF; } -static void -analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *old_state) { - struct drm_atomic_state *old_state = old_bridge_state->base.state; struct analogix_dp_device *dp = bridge->driver_private; struct drm_crtc *old_crtc, *new_crtc; struct drm_crtc_state *old_crtc_state = NULL; diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 79f78dbe9635..0b97b66de577 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2419,7 +2419,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge, } static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old) + struct drm_atomic_state *state) { struct anx7625_data *ctx = bridge_to_anx7625(bridge); struct device *dev = ctx->dev; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index edc5347551e5..81fad14c2cd5 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2069,7 +2069,7 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge, } static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); u32 resp; diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c index 0ba8bbc1afae..26ae1ab5237f 100644 --- a/drivers/gpu/drm/bridge/fsl-ldb.c +++ b/drivers/gpu/drm/bridge/fsl-ldb.c @@ -223,7 +223,7 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge, } static void fsl_ldb_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge); diff --git a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c index 9ee645489ea3..a17433a7c755 100644 --- a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c +++ b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c @@ -89,7 +89,7 @@ static void imx8mp_hdmi_pvi_bridge_enable(struct drm_bridge *bridge, } static void imx8mp_hdmi_pvi_bridge_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge); diff --git a/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c index fe2313aa2051..524aac751359 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c +++ b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c @@ -246,9 +246,8 @@ static void imx8qm_ldb_bridge_atomic_enable(struct drm_bridge *bridge, ldb_bridge_enable_helper(bridge); } -static void -imx8qm_ldb_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qm_ldb_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct ldb_channel *ldb_ch = bridge->driver_private; struct ldb *ldb = ldb_ch->ldb; diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c index f3f5b7b810f6..3cb484773ddf 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c @@ -253,9 +253,8 @@ static void imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge, companion->funcs->atomic_enable(companion, state); } -static void -imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct ldb_channel *ldb_ch = bridge->driver_private; struct ldb *ldb = ldb_ch->ldb; @@ -281,7 +280,7 @@ imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge, clk_disable_unprepare(imx8qxp_ldb->clk_pixel); if (is_split && companion) - companion->funcs->atomic_disable(companion, old_bridge_state); + companion->funcs->atomic_disable(companion, state); ret = pm_runtime_put(dev); if (ret < 0) diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c index 1812bd106261..1d9529dc7f2a 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c @@ -176,9 +176,8 @@ imx8qxp_pc_bridge_mode_set(struct drm_bridge *bridge, clk_disable_unprepare(pc->clk_apb); } -static void -imx8qxp_pc_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qxp_pc_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct imx8qxp_pc_channel *ch = bridge->driver_private; struct imx8qxp_pc *pc = ch->pc; diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c index 9b79e5dbcaca..cd6818db0fd3 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c @@ -163,9 +163,8 @@ static void imx8qxp_pixel_link_bridge_atomic_enable(struct drm_bridge *bridge, imx8qxp_pixel_link_enable_sync(pl); } -static void -imx8qxp_pixel_link_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qxp_pixel_link_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct imx8qxp_pixel_link *pl = bridge->driver_private; diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c index 65cf3a6c8ec6..49dd4f96d52c 100644 --- a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c +++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c @@ -122,9 +122,8 @@ imx8qxp_pxl2dpi_bridge_mode_set(struct drm_bridge *bridge, } } -static void -imx8qxp_pxl2dpi_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void imx8qxp_pxl2dpi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct imx8qxp_pxl2dpi *p2d = bridge->driver_private; int ret; @@ -134,8 +133,7 @@ imx8qxp_pxl2dpi_bridge_atomic_disable(struct drm_bridge *bridge, DRM_DEV_ERROR(p2d->dev, "failed to put runtime PM: %d\n", ret); if (p2d->companion) - p2d->companion->funcs->atomic_disable(p2d->companion, - old_bridge_state); + p2d->companion->funcs->atomic_disable(p2d->companion, state); } static const u32 imx8qxp_pxl2dpi_bus_output_fmts[] = { diff --git a/drivers/gpu/drm/bridge/ite-it6263.c b/drivers/gpu/drm/bridge/ite-it6263.c index 0cf624a8495c..21152a1c28f7 100644 --- a/drivers/gpu/drm/bridge/ite-it6263.c +++ b/drivers/gpu/drm/bridge/ite-it6263.c @@ -569,9 +569,8 @@ static int it6263_read_edid(void *data, u8 *buf, unsigned int block, size_t len) return 0; } -static void -it6263_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void it6263_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct it6263 *it = bridge_to_it6263(bridge); diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 159fdce35129..d8265a205c0d 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3238,7 +3238,7 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, } static void it6505_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct it6505 *it6505 = bridge_to_it6505(bridge); struct device *dev = it6505->dev; diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 4b784ac04b3a..b9f90f32145d 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -731,7 +731,7 @@ static void it66121_bridge_enable(struct drm_bridge *bridge, } static void it66121_bridge_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c index 65d5cdfe0d32..0fc5ea18fe6a 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9211.c +++ b/drivers/gpu/drm/bridge/lontium-lt9211.c @@ -552,7 +552,7 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge, } static void lt9211_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct lt9211 *ctx = bridge_to_lt9211(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index 521cce42d033..bacc8d373fe7 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -687,9 +687,8 @@ static void lt9611_bridge_atomic_enable(struct drm_bridge *bridge, regmap_write(lt9611->regmap, 0x8130, 0xea); } -static void -lt9611_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void lt9611_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct lt9611 *lt9611 = bridge_to_lt9611(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 516ef0409b5d..d04c62a0cb9f 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -736,9 +736,8 @@ static int nwl_dsi_disable(struct nwl_dsi *dsi) return 0; } -static void -nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct nwl_dsi *dsi = bridge_to_dsi(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 08b1704b0ab2..19b08303ed8b 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -147,10 +147,9 @@ static void panel_bridge_atomic_enable(struct drm_bridge *bridge, } static void panel_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_encoder *encoder = bridge->encoder; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index ddf55fad2815..4a75a49110bc 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1496,7 +1496,7 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge, } static void samsung_dsim_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct samsung_dsim *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index ae53d94a3931..2100a687096e 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -325,7 +325,7 @@ static const struct drm_connector_helper_funcs sii902x_connector_helper_funcs = }; static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct sii902x *sii902x = bridge_to_sii902x(bridge); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index e48084201623..1d39015f1533 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -395,7 +395,7 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, } static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct dw_hdmi_qp *hdmi = bridge->driver_private; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index b92e1fa9f352..0890add5f707 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2945,7 +2945,7 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, } static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct dw_hdmi *hdmi = bridge->driver_private; diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index a1f72e61b944..39e2d3a7a27d 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1563,9 +1563,8 @@ static void tc_dpi_bridge_atomic_enable(struct drm_bridge *bridge, } } -static void -tc_dpi_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void tc_dpi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tc_data *tc = bridge_to_tc(bridge); int ret; @@ -1601,9 +1600,8 @@ static void tc_edp_bridge_atomic_enable(struct drm_bridge *bridge, } } -static void -tc_edp_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void tc_edp_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tc_data *tc = bridge_to_tc(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index 3ea3165b6e05..54ad462d17ef 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -665,7 +665,7 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, } static void sn65dsi83_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index c3ad7e326ae8..38f30aad7d9b 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -813,7 +813,7 @@ ti_sn_bridge_mode_valid(struct drm_bridge *bridge, } static void ti_sn_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); diff --git a/drivers/gpu/drm/bridge/ti-tdp158.c b/drivers/gpu/drm/bridge/ti-tdp158.c index c0308f997445..22316382451f 100644 --- a/drivers/gpu/drm/bridge/ti-tdp158.c +++ b/drivers/gpu/drm/bridge/ti-tdp158.c @@ -35,7 +35,8 @@ static void tdp158_enable(struct drm_bridge *bridge, gpiod_set_value_cansleep(tdp158->enable, 1); } -static void tdp158_disable(struct drm_bridge *bridge, struct drm_bridge_state *prev) +static void tdp158_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tdp158 *tdp158 = bridge->driver_private; diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 7d9d176347f3..198083cacfc0 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -571,15 +571,7 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, encoder = bridge->encoder; list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { if (iter->funcs->atomic_disable) { - struct drm_bridge_state *old_bridge_state; - - old_bridge_state = - drm_atomic_get_old_bridge_state(old_state, - iter); - if (WARN_ON(!old_bridge_state)) - return; - - iter->funcs->atomic_disable(iter, old_bridge_state); + iter->funcs->atomic_disable(iter, old_state); } else if (iter->funcs->disable) { iter->funcs->disable(iter); } diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index e52d8c4f0b7e..20b93fff0239 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -260,7 +260,7 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc, } static void ingenic_drm_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ingenic_drm *priv = drm_device_get_priv(bridge->dev); unsigned int var; diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index bd67423556b7..3d4648d2e15f 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2400,7 +2400,7 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge, } static void mtk_dp_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge); diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index be21f8e64317..661db80b2377 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -826,7 +826,7 @@ static void mtk_dsi_bridge_mode_set(struct drm_bridge *bridge, } static void mtk_dsi_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct mtk_dsi *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index a1904480fff8..602c9d348a7d 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1309,7 +1309,7 @@ static bool mtk_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, } static void mtk_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c index b535e74345f0..e79f7c3ce32e 100644 --- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c +++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c @@ -190,7 +190,7 @@ static void meson_encoder_cvbs_atomic_enable(struct drm_bridge *bridge, } static void meson_encoder_cvbs_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct meson_encoder_cvbs *meson_encoder_cvbs = bridge_to_meson_encoder_cvbs(bridge); diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c index 140b3604dba1..fe204437bd65 100644 --- a/drivers/gpu/drm/meson/meson_encoder_dsi.c +++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c @@ -79,7 +79,7 @@ static void meson_encoder_dsi_atomic_enable(struct drm_bridge *bridge, } static void meson_encoder_dsi_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct meson_encoder_dsi *meson_encoder_dsi = bridge_to_meson_encoder_dsi(bridge); diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index 7544c4e6af63..6d1c9262a2cf 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -249,7 +249,7 @@ static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge, } static void meson_encoder_hdmi_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge); struct meson_drm *priv = encoder_hdmi->priv; diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ffb9c80543ad..77948f0514de 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1552,7 +1552,7 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, } void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = msm_dp_bridge->msm_dp_display; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index eae8e849edc5..84ecec79467d 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -166,9 +166,8 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge, } static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state = NULL, *old_crtc_state = NULL; struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); @@ -207,7 +206,7 @@ static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, } out: - msm_dp_bridge_atomic_disable(drm_bridge, old_bridge_state); + msm_dp_bridge_atomic_disable(drm_bridge, atomic_state); } static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index d54253ecbbff..faf31a9da752 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -28,7 +28,7 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev, void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, struct drm_atomic_state *state); void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, struct drm_bridge_state *old_bridge_state); enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index c43f4a5218d1..e1ac447221ee 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -409,7 +409,7 @@ static void hdmi4_bridge_enable(struct drm_bridge *bridge, } static void hdmi4_bridge_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); unsigned long flags; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 49a4d31243e7..fa9904e4c218 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -407,7 +407,7 @@ static void hdmi5_bridge_enable(struct drm_bridge *bridge, } static void hdmi5_bridge_disable(struct drm_bridge *bridge, - struct drm_bridge_state *bridge_state) + struct drm_atomic_state *state) { struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); unsigned long flags; diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c index 86e112fe1fc4..380a855b832a 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c @@ -595,7 +595,7 @@ static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, } static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c index 4c8f63bd106e..d1e626068065 100644 --- a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c @@ -816,7 +816,7 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge, } static void rcar_mipi_dsi_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge); diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c index 1eafb637092b..4550c6d84796 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c @@ -567,7 +567,7 @@ static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge, } static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); diff --git a/drivers/gpu/drm/stm/lvds.c b/drivers/gpu/drm/stm/lvds.c index 7ec44f226403..4613e8e3b8fd 100644 --- a/drivers/gpu/drm/stm/lvds.c +++ b/drivers/gpu/drm/stm/lvds.c @@ -1016,7 +1016,7 @@ static void lvds_atomic_enable(struct drm_bridge *bridge, } static void lvds_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct stm_lvds *lvds = bridge_to_stm_lvds(bridge); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 59d881ddf0ee..60b300db52d2 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -800,7 +800,7 @@ dsi_esc_timing(u32 ns) } static void vc4_dsi_bridge_disable(struct drm_bridge *bridge, - struct drm_bridge_state *state) + struct drm_atomic_state *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); u32 disp0_ctrl; diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c index 576683dfcae0..a6a4a871f197 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c @@ -1625,8 +1625,10 @@ static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge, } static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { + struct drm_bridge_state *old_bridge_state = drm_atomic_get_old_bridge_state(state, + bridge); struct zynqmp_dp *dp = bridge_to_dp(bridge); mutex_lock(&dp->lock); diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 4c5e23123030..087752226bf9 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -342,7 +342,7 @@ struct drm_bridge_funcs { * The @atomic_disable callback is optional. */ void (*atomic_disable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); /** * @atomic_post_disable: From f82fe0d44913248877450584c27992c5b0f96ce7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:24 +0100 Subject: [PATCH 48/73] drm/bridge: Pass full state to atomic_post_disable It's pretty inconvenient to access the full atomic state from drm_bridges, so let's change the atomic_post_disable hook prototype to pass it directly. Reviewed-by: Dmitry Baryshkov Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-5-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- .../gpu/drm/bridge/analogix/analogix_dp_core.c | 6 ++---- drivers/gpu/drm/bridge/chipone-icn6211.c | 2 +- drivers/gpu/drm/bridge/ite-it6505.c | 2 +- drivers/gpu/drm/bridge/lontium-lt9611.c | 5 ++--- drivers/gpu/drm/bridge/panel.c | 3 +-- drivers/gpu/drm/bridge/parade-ps8640.c | 2 +- drivers/gpu/drm/bridge/samsung-dsim.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c | 2 +- drivers/gpu/drm/bridge/tc358762.c | 3 ++- drivers/gpu/drm/bridge/ti-dlpc3433.c | 2 +- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 2 +- drivers/gpu/drm/drm_bridge.c | 16 +++------------- drivers/gpu/drm/mediatek/mtk_dsi.c | 2 +- drivers/gpu/drm/mediatek/mtk_hdmi.c | 2 +- drivers/gpu/drm/msm/dp/dp_display.c | 14 +++++++------- drivers/gpu/drm/msm/dp/dp_drm.c | 5 ++--- drivers/gpu/drm/msm/dp/dp_drm.h | 2 +- drivers/gpu/drm/vc4/vc4_dsi.c | 2 +- include/drm/drm_bridge.h | 2 +- 20 files changed, 32 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 78391682cca9..071168aa0c3b 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1361,11 +1361,9 @@ static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, analogix_dp_bridge_disable(bridge); } -static void -analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *old_state) { - struct drm_atomic_state *old_state = old_bridge_state->base.state; struct analogix_dp_device *dp = bridge->driver_private; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 2d9e3add135c..81f7c701961f 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -481,7 +481,7 @@ static void chipone_atomic_pre_enable(struct drm_bridge *bridge, } static void chipone_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct chipone *icn = bridge_to_chipone(bridge); diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index d8265a205c0d..8a607558ac89 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3264,7 +3264,7 @@ static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge, } static void it6505_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct it6505 *it6505 = bridge_to_it6505(bridge); struct device *dev = it6505->dev; diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index bacc8d373fe7..026803034231 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -783,9 +783,8 @@ static void lt9611_bridge_atomic_pre_enable(struct drm_bridge *bridge, lt9611->sleep = false; } -static void -lt9611_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) +static void lt9611_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct lt9611 *lt9611 = bridge_to_lt9611(bridge); diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 19b08303ed8b..258c85c83a28 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -166,10 +166,9 @@ static void panel_bridge_atomic_disable(struct drm_bridge *bridge, } static void panel_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_encoder *encoder = bridge->encoder; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 7ec674bffa81..a42138b33258 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -472,7 +472,7 @@ static void ps8640_atomic_pre_enable(struct drm_bridge *bridge, } static void ps8640_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 4a75a49110bc..54de6ed2fae8 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1508,7 +1508,7 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge, } static void samsung_dsim_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct samsung_dsim *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index f9371b19a476..2b6e70a49f43 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -934,7 +934,7 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi) } static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c index 1d9d16fbcc7f..5fd7a459efdd 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c @@ -745,7 +745,7 @@ static int dw_mipi_dsi2_bridge_atomic_check(struct drm_bridge *bridge, } static void dw_mipi_dsi2_bridge_post_atomic_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dw_mipi_dsi2 *dsi2 = bridge_to_dsi2(bridge); const struct dw_mipi_dsi2_phy_ops *phy_ops = dsi2->plat_data->phy_ops; diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index 6ed8ae6ffc3d..49c76027f831 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -149,7 +149,8 @@ static int tc358762_init(struct tc358762 *ctx) return tc358762_clear_error(ctx); } -static void tc358762_post_disable(struct drm_bridge *bridge, struct drm_bridge_state *state) +static void tc358762_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct tc358762 *ctx = bridge_to_tc358762(bridge); int ret; diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c index 963af4fc28a8..85f2a0e74a1c 100644 --- a/drivers/gpu/drm/bridge/ti-dlpc3433.c +++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c @@ -193,7 +193,7 @@ static void dlpc_atomic_pre_enable(struct drm_bridge *bridge, } static void dlpc_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct dlpc *dlpc = bridge_to_dlpc(bridge); diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 38f30aad7d9b..ae34585e05b3 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1178,7 +1178,7 @@ static void ti_sn_bridge_atomic_pre_enable(struct drm_bridge *bridge, } static void ti_sn_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 198083cacfc0..cb71ec57c47a 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -585,20 +585,10 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_disable); static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge, struct drm_atomic_state *old_state) { - if (old_state && bridge->funcs->atomic_post_disable) { - struct drm_bridge_state *old_bridge_state; - - old_bridge_state = - drm_atomic_get_old_bridge_state(old_state, - bridge); - if (WARN_ON(!old_bridge_state)) - return; - - bridge->funcs->atomic_post_disable(bridge, - old_bridge_state); - } else if (bridge->funcs->post_disable) { + if (old_state && bridge->funcs->atomic_post_disable) + bridge->funcs->atomic_post_disable(bridge, old_state); + else if (bridge->funcs->post_disable) bridge->funcs->post_disable(bridge); - } } /** diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 661db80b2377..b50dc9a013ac 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -856,7 +856,7 @@ static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, } static void mtk_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct mtk_dsi *dsi = bridge_to_dsi(bridge); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 602c9d348a7d..ac5e40c27617 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1326,7 +1326,7 @@ static void mtk_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, } static void mtk_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *old_state) + struct drm_atomic_state *state) { struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 77948f0514de..8b1cc8f166b8 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1564,11 +1564,11 @@ void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, } void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *state) { struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge); struct msm_dp *dp = msm_dp_bridge->msm_dp_display; - u32 state; + u32 hpd_state; struct msm_dp_display_private *msm_dp_display; msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display); @@ -1578,15 +1578,15 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, mutex_lock(&msm_dp_display->event_mutex); - state = msm_dp_display->hpd_state; - if (state != ST_DISCONNECT_PENDING && state != ST_CONNECTED) + hpd_state = msm_dp_display->hpd_state; + if (hpd_state != ST_DISCONNECT_PENDING && hpd_state != ST_CONNECTED) drm_dbg_dp(dp->drm_dev, "type=%d wrong hpd_state=%d\n", - dp->connector_type, state); + dp->connector_type, hpd_state); msm_dp_display_disable(msm_dp_display); - state = msm_dp_display->hpd_state; - if (state == ST_DISCONNECT_PENDING) { + hpd_state = msm_dp_display->hpd_state; + if (hpd_state == ST_DISCONNECT_PENDING) { /* completed disconnection */ msm_dp_display->hpd_state = ST_DISCONNECTED; } else { diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 84ecec79467d..dc888f8269d6 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -210,9 +210,8 @@ static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge, } static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state) + struct drm_atomic_state *atomic_state) { - struct drm_atomic_state *atomic_state = old_bridge_state->base.state; struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state = NULL; @@ -231,7 +230,7 @@ static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, if (new_crtc_state->self_refresh_active) return; - msm_dp_bridge_atomic_post_disable(drm_bridge, old_bridge_state); + msm_dp_bridge_atomic_post_disable(drm_bridge, atomic_state); } /** diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index faf31a9da752..d8c9b905f8bf 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -30,7 +30,7 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge, void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge, struct drm_atomic_state *state); void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode); diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 60b300db52d2..779b22efe27b 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -811,7 +811,7 @@ static void vc4_dsi_bridge_disable(struct drm_bridge *bridge, } static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge, - struct drm_bridge_state *state) + struct drm_atomic_state *state) { struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge); struct device *dev = &dsi->pdev->dev; diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 087752226bf9..d4c75d59fa12 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -361,7 +361,7 @@ struct drm_bridge_funcs { * The @atomic_post_disable callback is optional. */ void (*atomic_post_disable)(struct drm_bridge *bridge, - struct drm_bridge_state *old_bridge_state); + struct drm_atomic_state *state); /** * @atomic_duplicate_state: From 6d5815e22981500b189eb6aa2a0f8017d5f7fab7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:25 +0100 Subject: [PATCH 49/73] drm/atomic-helper: Fix commit_tail state variable name Even though the commit_tail () drm_atomic_state parameter is called old_state, it's actually the state being committed which is confusing. It's even more confusing since the atomic_commit_tail hook being called by commit_tail() parameter is called state. Let's rename the variable from old_state to state to make it less confusing. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-6-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index fd3d14592663..f8ab33fec5d0 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1830,9 +1830,9 @@ void drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) } EXPORT_SYMBOL(drm_atomic_helper_commit_tail_rpm); -static void commit_tail(struct drm_atomic_state *old_state) +static void commit_tail(struct drm_atomic_state *state) { - struct drm_device *dev = old_state->dev; + struct drm_device *dev = state->dev; const struct drm_mode_config_helper_funcs *funcs; struct drm_crtc_state *new_crtc_state; struct drm_crtc *crtc; @@ -1854,33 +1854,33 @@ static void commit_tail(struct drm_atomic_state *old_state) */ start = ktime_get(); - drm_atomic_helper_wait_for_fences(dev, old_state, false); + drm_atomic_helper_wait_for_fences(dev, state, false); - drm_atomic_helper_wait_for_dependencies(old_state); + drm_atomic_helper_wait_for_dependencies(state); /* * We cannot safely access new_crtc_state after * drm_atomic_helper_commit_hw_done() so figure out which crtc's have * self-refresh active beforehand: */ - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) if (new_crtc_state->self_refresh_active) new_self_refresh_mask |= BIT(i); if (funcs && funcs->atomic_commit_tail) - funcs->atomic_commit_tail(old_state); + funcs->atomic_commit_tail(state); else - drm_atomic_helper_commit_tail(old_state); + drm_atomic_helper_commit_tail(state); commit_time_ms = ktime_ms_delta(ktime_get(), start); if (commit_time_ms > 0) - drm_self_refresh_helper_update_avg_times(old_state, + drm_self_refresh_helper_update_avg_times(state, (unsigned long)commit_time_ms, new_self_refresh_mask); - drm_atomic_helper_commit_cleanup_done(old_state); + drm_atomic_helper_commit_cleanup_done(state); - drm_atomic_state_put(old_state); + drm_atomic_state_put(state); } static void commit_work(struct work_struct *work) From c0a98824fe5be4b7c7f3323e840928bc6eeb618e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:26 +0100 Subject: [PATCH 50/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_wait_for_dependencies() drm_atomic_helper_wait_for_dependencies() waits for all the dependencies a commit has before going forward with it. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-7-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index f8ab33fec5d0..512f10c4b6aa 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2423,17 +2423,17 @@ EXPORT_SYMBOL(drm_atomic_helper_setup_commit); /** * drm_atomic_helper_wait_for_dependencies - wait for required preceding commits - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This function waits for all preceding commits that touch the same CRTC as - * @old_state to both be committed to the hardware (as signalled by + * @state to both be committed to the hardware (as signalled by * drm_atomic_helper_commit_hw_done()) and executed by the hardware (as signalled * by calling drm_crtc_send_vblank_event() on the &drm_crtc_state.event). * * This is part of the atomic helper support for nonblocking commits, see * drm_atomic_helper_setup_commit() for an overview. */ -void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) +void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; @@ -2444,7 +2444,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) int i; long ret; - for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { ret = drm_crtc_commit_wait(old_crtc_state->commit); if (ret) drm_err(crtc->dev, @@ -2452,7 +2452,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) crtc->base.id, crtc->name); } - for_each_old_connector_in_state(old_state, conn, old_conn_state, i) { + for_each_old_connector_in_state(state, conn, old_conn_state, i) { ret = drm_crtc_commit_wait(old_conn_state->commit); if (ret) drm_err(conn->dev, @@ -2460,7 +2460,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state) conn->base.id, conn->name); } - for_each_old_plane_in_state(old_state, plane, old_plane_state, i) { + for_each_old_plane_in_state(state, plane, old_plane_state, i) { ret = drm_crtc_commit_wait(old_plane_state->commit); if (ret) drm_err(plane->dev, From 63379dbb50618d388f6ed54e62966d0240048964 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:27 +0100 Subject: [PATCH 51/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_commit_tail() drm_atomic_helper_commit_tail() is the final part of an atomic commit, and is given a parameter with the drm_atomic_state being committed. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-8-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 512f10c4b6aa..70354f223daf 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1768,7 +1768,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); /** * drm_atomic_helper_commit_tail - commit atomic update to hardware - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This is the default implementation for the * &drm_mode_config_helper_funcs.atomic_commit_tail hook, for drivers @@ -1779,23 +1779,23 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); * Note that the default ordering of how the various stages are called is to * match the legacy modeset helper library closest. */ -void drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state) +void drm_atomic_helper_commit_tail(struct drm_atomic_state *state) { - struct drm_device *dev = old_state->dev; + struct drm_device *dev = state->dev; - drm_atomic_helper_commit_modeset_disables(dev, old_state); + drm_atomic_helper_commit_modeset_disables(dev, state); - drm_atomic_helper_commit_planes(dev, old_state, 0); + drm_atomic_helper_commit_planes(dev, state, 0); - drm_atomic_helper_commit_modeset_enables(dev, old_state); + drm_atomic_helper_commit_modeset_enables(dev, state); - drm_atomic_helper_fake_vblank(old_state); + drm_atomic_helper_fake_vblank(state); - drm_atomic_helper_commit_hw_done(old_state); + drm_atomic_helper_commit_hw_done(state); - drm_atomic_helper_wait_for_vblanks(dev, old_state); + drm_atomic_helper_wait_for_vblanks(dev, state); - drm_atomic_helper_cleanup_planes(dev, old_state); + drm_atomic_helper_cleanup_planes(dev, state); } EXPORT_SYMBOL(drm_atomic_helper_commit_tail); From af2ea3d32e53d0012fe00ede5666870f65a7035e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:28 +0100 Subject: [PATCH 52/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_commit_tail_rpm() drm_atomic_helper_commit_tail_rpm() is the final part of an atomic commit, and is given the state being committed as a parameter. However, that parameter is named old_state, but documented as the "new modeset state" which is all super confusing. Let's rename that parameter to state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-9-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 70354f223daf..284dab6958c7 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1801,7 +1801,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_tail); /** * drm_atomic_helper_commit_tail_rpm - commit atomic update to hardware - * @old_state: new modeset state to be committed + * @state: new modeset state to be committed * * This is an alternative implementation for the * &drm_mode_config_helper_funcs.atomic_commit_tail hook, for drivers @@ -1809,24 +1809,24 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_tail); * commit. Otherwise, one should use the default implementation * drm_atomic_helper_commit_tail(). */ -void drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) +void drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *state) { - struct drm_device *dev = old_state->dev; + struct drm_device *dev = state->dev; - drm_atomic_helper_commit_modeset_disables(dev, old_state); + drm_atomic_helper_commit_modeset_disables(dev, state); - drm_atomic_helper_commit_modeset_enables(dev, old_state); + drm_atomic_helper_commit_modeset_enables(dev, state); - drm_atomic_helper_commit_planes(dev, old_state, + drm_atomic_helper_commit_planes(dev, state, DRM_PLANE_COMMIT_ACTIVE_ONLY); - drm_atomic_helper_fake_vblank(old_state); + drm_atomic_helper_fake_vblank(state); - drm_atomic_helper_commit_hw_done(old_state); + drm_atomic_helper_commit_hw_done(state); - drm_atomic_helper_wait_for_vblanks(dev, old_state); + drm_atomic_helper_wait_for_vblanks(dev, state); - drm_atomic_helper_cleanup_planes(dev, old_state); + drm_atomic_helper_cleanup_planes(dev, state); } EXPORT_SYMBOL(drm_atomic_helper_commit_tail_rpm); From 65d463807e8dc5b747abcfacb54b9119b8b71850 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:29 +0100 Subject: [PATCH 53/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_modeset_disables() drm_atomic_helper_modeset_disables() disables all the outputs affected by a commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-10-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 284dab6958c7..e45e63240640 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1439,7 +1439,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) /** * drm_atomic_helper_commit_modeset_disables - modeset commit to disable outputs * @dev: DRM device - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This function shuts down all the outputs that need to be shut down and * prepares them (if required) with the new mode. @@ -1451,14 +1451,14 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) * PM since planes updates then only happen when the CRTC is actually enabled. */ void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { - disable_outputs(dev, old_state); + disable_outputs(dev, state); - drm_atomic_helper_update_legacy_modeset_state(dev, old_state); - drm_atomic_helper_calc_timestamping_constants(old_state); + drm_atomic_helper_update_legacy_modeset_state(dev, state); + drm_atomic_helper_calc_timestamping_constants(state); - crtc_set_mode(dev, old_state); + crtc_set_mode(dev, state); } EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables); From 5af3ff97c5789a500c2b9b4a5b63261d19a3eb1e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:30 +0100 Subject: [PATCH 54/73] drm/atomic-helper: Change parameter name of disable_outputs() disable_outputs() disables all connectors and CRTCs affected by a commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-11-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index e45e63240640..4571ddcfd3bf 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1160,7 +1160,7 @@ crtc_needs_disable(struct drm_crtc_state *old_state, } static void -disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) +disable_outputs(struct drm_device *dev, struct drm_atomic_state *state) { struct drm_connector *connector; struct drm_connector_state *old_conn_state, *new_conn_state; @@ -1168,7 +1168,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) struct drm_crtc_state *old_crtc_state, *new_crtc_state; int i; - for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) { const struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; struct drm_bridge *bridge; @@ -1180,11 +1180,11 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) if (!old_conn_state->crtc) continue; - old_crtc_state = drm_atomic_get_old_crtc_state(old_state, old_conn_state->crtc); + old_crtc_state = drm_atomic_get_old_crtc_state(state, old_conn_state->crtc); if (new_conn_state->crtc) new_crtc_state = drm_atomic_get_new_crtc_state( - old_state, + state, new_conn_state->crtc); else new_crtc_state = NULL; @@ -1211,12 +1211,12 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) * it away), so we won't call disable hooks twice. */ bridge = drm_bridge_chain_get_first_bridge(encoder); - drm_atomic_bridge_chain_disable(bridge, old_state); + drm_atomic_bridge_chain_disable(bridge, state); /* Right function depends upon target state. */ if (funcs) { if (funcs->atomic_disable) - funcs->atomic_disable(encoder, old_state); + funcs->atomic_disable(encoder, state); else if (new_conn_state->crtc && funcs->prepare) funcs->prepare(encoder); else if (funcs->disable) @@ -1225,10 +1225,10 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) funcs->dpms(encoder, DRM_MODE_DPMS_OFF); } - drm_atomic_bridge_chain_post_disable(bridge, old_state); + drm_atomic_bridge_chain_post_disable(bridge, state); } - for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { const struct drm_crtc_helper_funcs *funcs; int ret; @@ -1249,7 +1249,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) if (new_crtc_state->enable && funcs->prepare) funcs->prepare(crtc); else if (funcs->atomic_disable) - funcs->atomic_disable(crtc, old_state); + funcs->atomic_disable(crtc, state); else if (funcs->disable) funcs->disable(crtc); else if (funcs->dpms) From be8425c2fda5f635f56f4159a1b9b5640342c279 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:31 +0100 Subject: [PATCH 55/73] drm/bridge: Change parameter name of drm_atomic_bridge_chain_disable() drm_atomic_bridge_chain_disable() disables all bridges affected by a new commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-12-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_bridge.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index cb71ec57c47a..b21b43af3d1d 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -550,7 +550,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set); /** * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain * @bridge: bridge control structure - * @old_state: old atomic state + * @state: atomic state being committed * * Calls &drm_bridge_funcs.atomic_disable (falls back on * &drm_bridge_funcs.disable) op for all the bridges in the encoder chain, @@ -560,7 +560,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set); * Note: the bridge passed should be the one closest to the encoder */ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_encoder *encoder; struct drm_bridge *iter; @@ -571,7 +571,7 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, encoder = bridge->encoder; list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { if (iter->funcs->atomic_disable) { - iter->funcs->atomic_disable(iter, old_state); + iter->funcs->atomic_disable(iter, state); } else if (iter->funcs->disable) { iter->funcs->disable(iter); } From 72d1eda78b77083482bb91515c58a7c0bb84703b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:32 +0100 Subject: [PATCH 56/73] drm/bridge: Change parameter name of drm_atomic_bridge_chain_post_disable() drm_atomic_bridge_chain_post_disable() disables all bridges affected by a new commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-13-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_bridge.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index b21b43af3d1d..b63ec3d0b285 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -583,10 +583,10 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, EXPORT_SYMBOL(drm_atomic_bridge_chain_disable); static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { - if (old_state && bridge->funcs->atomic_post_disable) - bridge->funcs->atomic_post_disable(bridge, old_state); + if (state && bridge->funcs->atomic_post_disable) + bridge->funcs->atomic_post_disable(bridge, state); else if (bridge->funcs->post_disable) bridge->funcs->post_disable(bridge); } @@ -595,7 +595,7 @@ static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge, * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges * in the encoder chain * @bridge: bridge control structure - * @old_state: old atomic state + * @state: atomic state being committed * * Calls &drm_bridge_funcs.atomic_post_disable (falls back on * &drm_bridge_funcs.post_disable) op for all the bridges in the encoder chain, @@ -616,7 +616,7 @@ static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge, * Note: the bridge passed should be the one closest to the encoder */ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_encoder *encoder; struct drm_bridge *next, *limit; @@ -663,12 +663,12 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, break; drm_atomic_bridge_call_post_disable(next, - old_state); + state); } } } - drm_atomic_bridge_call_post_disable(bridge, old_state); + drm_atomic_bridge_call_post_disable(bridge, state); if (limit) /* Jump all bridges that we have already post_disabled */ From 488e10740fbdfbfcfc359e0c69877a78ae9d9bb5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:33 +0100 Subject: [PATCH 57/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_update_legacy_modeset_state() drm_atomic_helper_update_legacy_modeset_state() updates all the legacy modeset pointers a connector, encoder or CRTC might have with the ones being setup by a given commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-14-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4571ddcfd3bf..90c23e9e35a6 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1277,7 +1277,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *state) /** * drm_atomic_helper_update_legacy_modeset_state - update legacy modeset state * @dev: DRM device - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This function updates all the various legacy modeset state pointers in * connectors, encoders and CRTCs. @@ -1293,7 +1293,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *state) */ void drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_connector *connector; struct drm_connector_state *old_conn_state, *new_conn_state; @@ -1302,7 +1302,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, int i; /* clear out existing links and update dpms */ - for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) { + for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) { if (connector->encoder) { WARN_ON(!connector->encoder->crtc); @@ -1323,7 +1323,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, } /* set new links */ - for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { + for_each_new_connector_in_state(state, connector, new_conn_state, i) { if (!new_conn_state->crtc) continue; @@ -1335,7 +1335,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, } /* set legacy state in the crtc structure */ - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { struct drm_plane *primary = crtc->primary; struct drm_plane_state *new_plane_state; @@ -1343,7 +1343,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, crtc->enabled = new_crtc_state->enable; new_plane_state = - drm_atomic_get_new_plane_state(old_state, primary); + drm_atomic_get_new_plane_state(state, primary); if (new_plane_state && new_plane_state->crtc == crtc) { crtc->x = new_plane_state->src_x >> 16; From a9bb617f20eac215fe09e263cf5df1d85e4af8c1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:34 +0100 Subject: [PATCH 58/73] drm/atomic-helper: Change parameter name of crtc_set_mode() crtc_set_mode() deals with calling the modeset related hooks for CRTC, connectors and bridges if and when a new commit changes them. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-15-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 90c23e9e35a6..5d8fba7b5782 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1375,7 +1375,7 @@ void drm_atomic_helper_calc_timestamping_constants(struct drm_atomic_state *stat EXPORT_SYMBOL(drm_atomic_helper_calc_timestamping_constants); static void -crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) +crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_state *new_crtc_state; @@ -1383,7 +1383,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) struct drm_connector_state *new_conn_state; int i; - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { const struct drm_crtc_helper_funcs *funcs; if (!new_crtc_state->mode_changed) @@ -1399,7 +1399,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) } } - for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { + for_each_new_connector_in_state(state, connector, new_conn_state, i) { const struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; struct drm_display_mode *mode, *adjusted_mode; From f302d33096c059eaf97af3c0e098d46dec9dc29f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:35 +0100 Subject: [PATCH 59/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_commit_planes() drm_atomic_helper_commit_planes() updates all planes affected by a new commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-16-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 5d8fba7b5782..08ce7a0a829a 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2731,7 +2731,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state) /** * drm_atomic_helper_commit_planes - commit plane state * @dev: DRM device - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * @flags: flags for committing plane state * * This function commits the new plane state using the plane and atomic helper @@ -2739,7 +2739,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state) * been pushed into the relevant object state pointers, since this step can no * longer fail. * - * It still requires the global state object @old_state to know which planes and + * It still requires the global state object @state to know which planes and * crtcs need to be updated though. * * Note that this function does all plane updates across all CRTCs in one step. @@ -2770,7 +2770,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state) * This should not be copied blindly by drivers. */ void drm_atomic_helper_commit_planes(struct drm_device *dev, - struct drm_atomic_state *old_state, + struct drm_atomic_state *state, uint32_t flags) { struct drm_crtc *crtc; @@ -2781,7 +2781,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, bool active_only = flags & DRM_PLANE_COMMIT_ACTIVE_ONLY; bool no_disable = flags & DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET; - for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { const struct drm_crtc_helper_funcs *funcs; funcs = crtc->helper_private; @@ -2792,10 +2792,10 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (active_only && !new_crtc_state->active) continue; - funcs->atomic_begin(crtc, old_state); + funcs->atomic_begin(crtc, state); } - for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) { + for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { const struct drm_plane_helper_funcs *funcs; bool disabling; @@ -2833,18 +2833,18 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, no_disable) continue; - funcs->atomic_disable(plane, old_state); + funcs->atomic_disable(plane, state); } else if (new_plane_state->crtc || disabling) { - funcs->atomic_update(plane, old_state); + funcs->atomic_update(plane, state); if (!disabling && funcs->atomic_enable) { if (drm_atomic_plane_enabling(old_plane_state, new_plane_state)) - funcs->atomic_enable(plane, old_state); + funcs->atomic_enable(plane, state); } } } - for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { const struct drm_crtc_helper_funcs *funcs; funcs = crtc->helper_private; @@ -2855,14 +2855,14 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, if (active_only && !new_crtc_state->active) continue; - funcs->atomic_flush(crtc, old_state); + funcs->atomic_flush(crtc, state); } /* * Signal end of framebuffer access here before hw_done. After hw_done, * a later commit might have already released the plane state. */ - for_each_old_plane_in_state(old_state, plane, old_plane_state, i) { + for_each_old_plane_in_state(state, plane, old_plane_state, i) { const struct drm_plane_helper_funcs *funcs = plane->helper_private; if (funcs->end_fb_access) From ba94ce115e73e3bf5854a5b356b8e0825adc94cf Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:36 +0100 Subject: [PATCH 60/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_commit_modeset_enables() drm_atomic_helper_commit_modeset_enables() enables all outputs affected by a new commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-17-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 08ce7a0a829a..e41045cc7e39 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1486,7 +1486,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, /** * drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs * @dev: DRM device - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This function enables all the outputs with the new configuration which had to * be turned off for the update. @@ -1498,7 +1498,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, * PM since planes updates then only happen when the CRTC is actually enabled. */ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; @@ -1507,7 +1507,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, struct drm_connector_state *new_conn_state; int i; - for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { const struct drm_crtc_helper_funcs *funcs; /* Need to filter out CRTCs where only planes change. */ @@ -1523,13 +1523,13 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, drm_dbg_atomic(dev, "enabling [CRTC:%d:%s]\n", crtc->base.id, crtc->name); if (funcs->atomic_enable) - funcs->atomic_enable(crtc, old_state); + funcs->atomic_enable(crtc, state); else if (funcs->commit) funcs->commit(crtc); } } - for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { + for_each_new_connector_in_state(state, connector, new_conn_state, i) { const struct drm_encoder_helper_funcs *funcs; struct drm_encoder *encoder; struct drm_bridge *bridge; @@ -1552,21 +1552,21 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, * it away), so we won't call enable hooks twice. */ bridge = drm_bridge_chain_get_first_bridge(encoder); - drm_atomic_bridge_chain_pre_enable(bridge, old_state); + drm_atomic_bridge_chain_pre_enable(bridge, state); if (funcs) { if (funcs->atomic_enable) - funcs->atomic_enable(encoder, old_state); + funcs->atomic_enable(encoder, state); else if (funcs->enable) funcs->enable(encoder); else if (funcs->commit) funcs->commit(encoder); } - drm_atomic_bridge_chain_enable(bridge, old_state); + drm_atomic_bridge_chain_enable(bridge, state); } - drm_atomic_helper_commit_writebacks(dev, old_state); + drm_atomic_helper_commit_writebacks(dev, state); } EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables); From b78fc1c13587ec37ec67de072921a5527cc70ec3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:37 +0100 Subject: [PATCH 61/73] drm/bridge: Change parameter name of drm_atomic_bridge_chain_pre_enable() drm_atomic_bridge_chain_pre_enable() enables all bridges affected by a new commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-18-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_bridge.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index b63ec3d0b285..41bb3700ca7b 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -678,10 +678,10 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable); static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { - if (old_state && bridge->funcs->atomic_pre_enable) - bridge->funcs->atomic_pre_enable(bridge, old_state); + if (state && bridge->funcs->atomic_pre_enable) + bridge->funcs->atomic_pre_enable(bridge, state); else if (bridge->funcs->pre_enable) bridge->funcs->pre_enable(bridge); } @@ -690,7 +690,7 @@ static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge, * drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in * the encoder chain * @bridge: bridge control structure - * @old_state: old atomic state + * @state: atomic state being committed * * Calls &drm_bridge_funcs.atomic_pre_enable (falls back on * &drm_bridge_funcs.pre_enable) op for all the bridges in the encoder chain, @@ -710,7 +710,7 @@ static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge, * Note: the bridge passed should be the one closest to the encoder */ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_encoder *encoder; struct drm_bridge *iter, *next, *limit; @@ -749,11 +749,11 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, */ break; - drm_atomic_bridge_call_pre_enable(next, old_state); + drm_atomic_bridge_call_pre_enable(next, state); } } - drm_atomic_bridge_call_pre_enable(iter, old_state); + drm_atomic_bridge_call_pre_enable(iter, state); if (iter->pre_enable_prev_first) /* Jump all bridges that we have already pre_enabled */ From 742043c8affa8cb96db5bcc85b6dd4f904a804dd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:38 +0100 Subject: [PATCH 62/73] drm/bridge: Change parameter name of drm_atomic_bridge_chain_enable() drm_atomic_bridge_chain_enable() enables all bridges affected by a new commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-19-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_bridge.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 41bb3700ca7b..fa2794217a90 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -768,7 +768,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable); /** * drm_atomic_bridge_chain_enable - enables all bridges in the encoder chain * @bridge: bridge control structure - * @old_state: old atomic state + * @state: atomic state being committed * * Calls &drm_bridge_funcs.atomic_enable (falls back on * &drm_bridge_funcs.enable) op for all the bridges in the encoder chain, @@ -778,7 +778,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable); * Note: the bridge passed should be the one closest to the encoder */ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_encoder *encoder; @@ -788,7 +788,7 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, encoder = bridge->encoder; list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { if (bridge->funcs->atomic_enable) { - bridge->funcs->atomic_enable(bridge, old_state); + bridge->funcs->atomic_enable(bridge, state); } else if (bridge->funcs->enable) { bridge->funcs->enable(bridge); } From f1296603cc56219a6bf786b7ab4ad0cb6c7bbaa3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:39 +0100 Subject: [PATCH 63/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_commit_writebacks() drm_atomic_helper_commit_writebacks() updates all writeback connectors affected by a new commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-20-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index e41045cc7e39..ece056ab07b4 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1463,13 +1463,13 @@ void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables); static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_connector *connector; struct drm_connector_state *new_conn_state; int i; - for_each_new_connector_in_state(old_state, connector, new_conn_state, i) { + for_each_new_connector_in_state(state, connector, new_conn_state, i) { const struct drm_connector_helper_funcs *funcs; funcs = connector->helper_private; @@ -1478,7 +1478,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, if (new_conn_state->writeback_job && new_conn_state->writeback_job->fb) { WARN_ON(connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK); - funcs->atomic_commit(connector, old_state); + funcs->atomic_commit(connector, state); } } } From b756b0cbcb8574fc1b6c8448b63bc5b9b8c38f90 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:40 +0100 Subject: [PATCH 64/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_fake_vblank() drm_atomic_helper_fake_vblank() fake a vblank event if needed when a new commit is being applied. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-21-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ece056ab07b4..2ee7df6aca54 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2472,7 +2472,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies); /** * drm_atomic_helper_fake_vblank - fake VBLANK events if needed - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This function walks all CRTCs and fakes VBLANK events on those with * &drm_crtc_state.no_vblank set to true and &drm_crtc_state.event != NULL. @@ -2488,25 +2488,25 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies); * This is part of the atomic helper support for nonblocking commits, see * drm_atomic_helper_setup_commit() for an overview. */ -void drm_atomic_helper_fake_vblank(struct drm_atomic_state *old_state) +void drm_atomic_helper_fake_vblank(struct drm_atomic_state *state) { struct drm_crtc_state *new_crtc_state; struct drm_crtc *crtc; int i; - for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { unsigned long flags; if (!new_crtc_state->no_vblank) continue; - spin_lock_irqsave(&old_state->dev->event_lock, flags); + spin_lock_irqsave(&state->dev->event_lock, flags); if (new_crtc_state->event) { drm_crtc_send_vblank_event(crtc, new_crtc_state->event); new_crtc_state->event = NULL; } - spin_unlock_irqrestore(&old_state->dev->event_lock, flags); + spin_unlock_irqrestore(&state->dev->event_lock, flags); } } EXPORT_SYMBOL(drm_atomic_helper_fake_vblank); From 3fae6d20e329816e4f0b32b765eaa4e48b02ec66 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:41 +0100 Subject: [PATCH 65/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_commit_hw_done() drm_atomic_helper_commit_hw_done() signals hardware completion of a given commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-22-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2ee7df6aca54..15937860e406 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2513,7 +2513,7 @@ EXPORT_SYMBOL(drm_atomic_helper_fake_vblank); /** * drm_atomic_helper_commit_hw_done - setup possible nonblocking commit - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This function is used to signal completion of the hardware commit step. After * this step the driver is not allowed to read or change any permanent software @@ -2526,14 +2526,14 @@ EXPORT_SYMBOL(drm_atomic_helper_fake_vblank); * This is part of the atomic helper support for nonblocking commits, see * drm_atomic_helper_setup_commit() for an overview. */ -void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state) +void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc_commit *commit; int i; - for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { commit = new_crtc_state->commit; if (!commit) continue; @@ -2553,9 +2553,9 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state) complete_all(&commit->hw_done); } - if (old_state->fake_commit) { - complete_all(&old_state->fake_commit->hw_done); - complete_all(&old_state->fake_commit->flip_done); + if (state->fake_commit) { + complete_all(&state->fake_commit->hw_done); + complete_all(&state->fake_commit->flip_done); } } EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); From e64834b5094ff4ef2cfd960b82f69c2c26345501 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:42 +0100 Subject: [PATCH 66/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_wait_for_vblanks() drm_atomic_helper_wait_for_vblanks() waits for vblank events on all the CRTCs affected by a commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-23-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 15937860e406..8f290535c861 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1668,7 +1668,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); /** * drm_atomic_helper_wait_for_vblanks - wait for vblank on CRTCs * @dev: DRM device - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * Helper to, after atomic commit, wait for vblanks on all affected * CRTCs (ie. before cleaning up old framebuffers using @@ -1682,7 +1682,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); */ void drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; @@ -1693,10 +1693,10 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, * Legacy cursor ioctls are completely unsynced, and userspace * relies on that (by doing tons of cursor updates). */ - if (old_state->legacy_cursor_update) + if (state->legacy_cursor_update) return; - for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!new_crtc_state->active) continue; @@ -1705,17 +1705,17 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, continue; crtc_mask |= drm_crtc_mask(crtc); - old_state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc); + state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc); } - for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { if (!(crtc_mask & drm_crtc_mask(crtc))) continue; ret = wait_event_timeout(dev->vblank[i].queue, - old_state->crtcs[i].last_vblank_count != - drm_crtc_vblank_count(crtc), - msecs_to_jiffies(100)); + state->crtcs[i].last_vblank_count != + drm_crtc_vblank_count(crtc), + msecs_to_jiffies(100)); WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n", crtc->base.id, crtc->name); From 6280e96f8a5dcee3125d8963bc80773c99536429 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:43 +0100 Subject: [PATCH 67/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_cleanup_planes() drm_atomic_helper_cleanup_planes() is one of the final part of a commit, and will free up all plane resources used in the previous commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-24-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8f290535c861..9ec332360d08 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2989,10 +2989,10 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc); /** * drm_atomic_helper_cleanup_planes - cleanup plane resources after commit * @dev: DRM device - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * This function cleans up plane state, specifically framebuffers, from the old - * configuration. Hence the old configuration must be perserved in @old_state to + * configuration. Hence the old configuration must be perserved in @state to * be able to call this function. * * This function may not be called on the new state when the atomic update @@ -3000,13 +3000,13 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc); * drm_atomic_helper_unprepare_planes() in this case. */ void drm_atomic_helper_cleanup_planes(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_plane *plane; struct drm_plane_state *old_plane_state; int i; - for_each_old_plane_in_state(old_state, plane, old_plane_state, i) { + for_each_old_plane_in_state(state, plane, old_plane_state, i) { const struct drm_plane_helper_funcs *funcs = plane->helper_private; if (funcs->cleanup_fb) From bc8ab44023c1a4193ef2c5d2a152955722b33a8e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:44 +0100 Subject: [PATCH 68/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_commit_cleanup_done() drm_atomic_helper_wait_for_dependencies() is the final part of a commit and signals it completion. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-25-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9ec332360d08..c429b0248e81 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2562,23 +2562,23 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done); /** * drm_atomic_helper_commit_cleanup_done - signal completion of commit - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * - * This signals completion of the atomic update @old_state, including any + * This signals completion of the atomic update @state, including any * cleanup work. If used, it must be called right before calling * drm_atomic_state_put(). * * This is part of the atomic helper support for nonblocking commits, see * drm_atomic_helper_setup_commit() for an overview. */ -void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) +void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state) { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; struct drm_crtc_commit *commit; int i; - for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { + for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { commit = old_crtc_state->commit; if (WARN_ON(!commit)) continue; @@ -2591,9 +2591,9 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) spin_unlock(&crtc->commit_lock); } - if (old_state->fake_commit) { - complete_all(&old_state->fake_commit->cleanup_done); - WARN_ON(!try_wait_for_completion(&old_state->fake_commit->hw_done)); + if (state->fake_commit) { + complete_all(&state->fake_commit->cleanup_done); + WARN_ON(!try_wait_for_completion(&state->fake_commit->hw_done)); } } EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done); From f56b6db3e5e432fd0c82ab231572f92a159b5d34 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 13 Feb 2025 15:43:45 +0100 Subject: [PATCH 69/73] drm/atomic-helper: Change parameter name of drm_atomic_helper_wait_for_flip_done() drm_atomic_helper_wait_for_flip_done() will wait for pages flips on all CRTCs affected by a given commit. It takes the drm_atomic_state being committed as a parameter. However, that parameter name is called (and documented) as old_state, which is pretty confusing. Let's rename that variable as state. Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250213-bridge-connector-v3-26-e71598f49c8f@kernel.org Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index c429b0248e81..7a25e70694ba 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1728,7 +1728,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); /** * drm_atomic_helper_wait_for_flip_done - wait for all page flips to be done * @dev: DRM device - * @old_state: atomic state object with old state structures + * @state: atomic state object being committed * * Helper to, after atomic commit, wait for page flips on all affected * crtcs (ie. before cleaning up old framebuffers using @@ -1741,16 +1741,16 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); * initialized using drm_atomic_helper_setup_commit(). */ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, - struct drm_atomic_state *old_state) + struct drm_atomic_state *state) { struct drm_crtc *crtc; int i; for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct drm_crtc_commit *commit = old_state->crtcs[i].commit; + struct drm_crtc_commit *commit = state->crtcs[i].commit; int ret; - crtc = old_state->crtcs[i].ptr; + crtc = state->crtcs[i].ptr; if (!crtc || !commit) continue; @@ -1761,8 +1761,8 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, crtc->base.id, crtc->name); } - if (old_state->fake_commit) - complete_all(&old_state->fake_commit->flip_done); + if (state->fake_commit) + complete_all(&state->fake_commit->flip_done); } EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); From 6ec054a52d92fd172560996e3b2a4234a31f5265 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 17 Feb 2025 13:22:04 +0100 Subject: [PATCH 70/73] drm/ast: cursor: Calculate checksum in helper Setting the cursor image requires a 32-bit checksum of the cursor image data. The current cursor code converts the image to ARGB4444 format and computes the checksum in a single step. Moving the checksum calculation into a separate helper will allow to move the format conversion into a shared helper. v2: - don't loop for checksum'ing final pixel (Jocelyn) - fix typo in commit message (Jocelyn) Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250217122336.230067-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 13 +++++++- drivers/gpu/drm/ast/ast_mode.c | 61 +++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 022a8c070c1b..d3115b31b032 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -142,6 +142,17 @@ static inline struct ast_plane *to_ast_plane(struct drm_plane *plane) return container_of(plane, struct ast_plane, base); } +struct ast_cursor_plane { + struct ast_plane base; + + u8 argb4444[AST_HWC_SIZE]; +}; + +static inline struct ast_cursor_plane *to_ast_cursor_plane(struct drm_plane *plane) +{ + return container_of(to_ast_plane(plane), struct ast_cursor_plane, base); +} + /* * Connector */ @@ -186,7 +197,7 @@ struct ast_device { enum ast_tx_chip tx_chip; struct ast_plane primary_plane; - struct ast_plane cursor_plane; + struct ast_cursor_plane cursor_plane; struct drm_crtc crtc; union { struct { diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index bd781293b6d9..d25852b0ce03 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -632,7 +632,34 @@ static int ast_primary_plane_init(struct ast_device *ast) * Cursor plane */ -static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height) +static u32 ast_cursor_calculate_checksum(const void *src, unsigned int width, unsigned int height) +{ + u32 csum = 0; + unsigned int one_pixel_copy = width & BIT(0); + unsigned int two_pixel_copy = width - one_pixel_copy; + unsigned int trailing_bytes = (AST_MAX_HWC_WIDTH - width) * sizeof(u16); + unsigned int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < two_pixel_copy; x += 2) { + const u32 *src32 = (const u32 *)src; + + csum += *src32; + src += SZ_4; + } + if (one_pixel_copy) { + const u16 *src16 = (const u16 *)src; + + csum += *src16; + src += SZ_2; + } + src += trailing_bytes; + } + + return csum; +} + +static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, u8 *tmp, int width, int height) { union { u32 ul; @@ -642,9 +669,9 @@ static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, i u16 us; u8 b[2]; } data16; - u32 csum = 0; + u32 csum; s32 alpha_dst_delta, last_alpha_dst_delta; - u8 __iomem *dstxor; + u8 *dstxor; const u8 *srcxor; int i, j; u32 per_pixel_copy, two_pixel_copy; @@ -653,7 +680,7 @@ static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, i last_alpha_dst_delta = alpha_dst_delta - (width << 1); srcxor = src; - dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; + dstxor = tmp + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; per_pixel_copy = width & 1; two_pixel_copy = width >> 1; @@ -665,21 +692,17 @@ static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, i data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); - - writel(data32.ul, dstxor); - csum += data32.ul; + memcpy(dstxor, &data32, 4); dstxor += 4; srcxor += 8; - } for (i = 0; i < per_pixel_copy; i++) { srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); - writew(data16.us, dstxor); - csum += (u32)data16.us; + memcpy(dstxor, &data16, 2); dstxor += 2; srcxor += 4; @@ -687,6 +710,11 @@ static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, i dstxor += last_alpha_dst_delta; } + csum = ast_cursor_calculate_checksum(tmp, width, height); + + /* write pixel data */ + memcpy_toio(dst, tmp, AST_HWC_SIZE); + /* write checksum + signature */ dst += AST_HWC_SIZE; writel(csum, dst); @@ -767,6 +795,7 @@ static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state) { + struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane); struct ast_plane *ast_plane = to_ast_plane(plane); struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); @@ -789,7 +818,8 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, */ if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) { - ast_update_cursor_image(dst, src, fb->width, fb->height); + ast_update_cursor_image(dst, src, ast_cursor_plane->argb4444, + fb->width, fb->height); ast_set_cursor_base(ast, dst_off); } @@ -849,8 +879,9 @@ static const struct drm_plane_funcs ast_cursor_plane_funcs = { static int ast_cursor_plane_init(struct ast_device *ast) { struct drm_device *dev = &ast->base; - struct ast_plane *ast_cursor_plane = &ast->cursor_plane; - struct drm_plane *cursor_plane = &ast_cursor_plane->base; + struct ast_cursor_plane *ast_cursor_plane = &ast->cursor_plane; + struct ast_plane *ast_plane = &ast_cursor_plane->base; + struct drm_plane *cursor_plane = &ast_plane->base; size_t size; void __iomem *vaddr; u64 offset; @@ -869,7 +900,7 @@ static int ast_cursor_plane_init(struct ast_device *ast) vaddr = ast->vram + ast->vram_fb_available - size; offset = ast->vram_fb_available - size; - ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size, + ret = ast_plane_init(dev, ast_plane, vaddr, offset, size, 0x01, &ast_cursor_plane_funcs, ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats), NULL, DRM_PLANE_TYPE_CURSOR); @@ -1156,7 +1187,7 @@ static int ast_crtc_init(struct ast_device *ast) int ret; ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base, - &ast->cursor_plane.base, &ast_crtc_funcs, + &ast->cursor_plane.base.base, &ast_crtc_funcs, NULL); if (ret) return ret; From 966a0d49d1cd57165ad3e6232cf9de6fe43ecc63 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 17 Feb 2025 13:22:05 +0100 Subject: [PATCH 71/73] drm/ast: cursor: Move format conversion to shared helper User-space cursor-image data is encoded in ARBG8888, while hardware supports ARGB4444. Implement the format conversion as part of the format-helper framework, so that other drivers can benefit. This allows to respect the damage area of the cursor update. In previous code, all cursor image data had to be converted on each update. Now, only the changed areas require an update. The hardware image is always updated completely, as it is required for the checksum update. The format-conversion helper still contains the old implementation's optimization of writing 2 output pixels at the same time. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250217122336.230067-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 4 +- drivers/gpu/drm/ast/ast_mode.c | 71 +++++++---------------------- drivers/gpu/drm/drm_format_helper.c | 69 ++++++++++++++++++++++++++++ include/drm/drm_format_helper.h | 3 ++ 4 files changed, 92 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index d3115b31b032..973abd0cbd42 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -113,7 +113,9 @@ enum ast_config_mode { #define AST_MAX_HWC_WIDTH 64 #define AST_MAX_HWC_HEIGHT 64 -#define AST_HWC_SIZE (AST_MAX_HWC_WIDTH * AST_MAX_HWC_HEIGHT * 2) +#define AST_HWC_PITCH (AST_MAX_HWC_WIDTH * SZ_2) +#define AST_HWC_SIZE (AST_MAX_HWC_HEIGHT * AST_HWC_PITCH) + #define AST_HWC_SIGNATURE_SIZE 32 /* define for signature structure */ diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index d25852b0ce03..8ab006e6bc32 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -659,61 +659,16 @@ static u32 ast_cursor_calculate_checksum(const void *src, unsigned int width, un return csum; } -static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, u8 *tmp, int width, int height) +static void ast_set_cursor_image(struct ast_device *ast, const u8 *src, + unsigned int width, unsigned int height) { - union { - u32 ul; - u8 b[4]; - } srcdata32[2], data32; - union { - u16 us; - u8 b[2]; - } data16; + u8 __iomem *dst = ast->cursor_plane.base.vaddr; u32 csum; - s32 alpha_dst_delta, last_alpha_dst_delta; - u8 *dstxor; - const u8 *srcxor; - int i, j; - u32 per_pixel_copy, two_pixel_copy; - alpha_dst_delta = AST_MAX_HWC_WIDTH << 1; - last_alpha_dst_delta = alpha_dst_delta - (width << 1); - - srcxor = src; - dstxor = tmp + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta; - per_pixel_copy = width & 1; - two_pixel_copy = width >> 1; - - for (j = 0; j < height; j++) { - for (i = 0; i < two_pixel_copy; i++) { - srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; - srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0; - data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); - data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); - data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4); - data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4); - memcpy(dstxor, &data32, 4); - - dstxor += 4; - srcxor += 8; - } - - for (i = 0; i < per_pixel_copy; i++) { - srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0; - data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4); - data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4); - memcpy(dstxor, &data16, 2); - - dstxor += 2; - srcxor += 4; - } - dstxor += last_alpha_dst_delta; - } - - csum = ast_cursor_calculate_checksum(tmp, width, height); + csum = ast_cursor_calculate_checksum(src, width, height); /* write pixel data */ - memcpy_toio(dst, tmp, AST_HWC_SIZE); + memcpy_toio(dst, src, AST_HWC_SIZE); /* write checksum + signature */ dst += AST_HWC_SIZE; @@ -802,9 +757,7 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, struct drm_framebuffer *fb = plane_state->fb; struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); struct ast_device *ast = to_ast_device(plane->dev); - struct iosys_map src_map = shadow_plane_state->data[0]; struct drm_rect damage; - const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */ u64 dst_off = ast_plane->offset; u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */ u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */ @@ -818,8 +771,18 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, */ if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) { - ast_update_cursor_image(dst, src, ast_cursor_plane->argb4444, - fb->width, fb->height); + u8 *argb4444 = ast_cursor_plane->argb4444; + struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = { + IOSYS_MAP_INIT_VADDR(argb4444), + }; + unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + AST_HWC_PITCH, + }; + + drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch, + shadow_plane_state->data, fb, &damage, + &shadow_plane_state->fmtcnv_state); + ast_set_cursor_image(ast, argb4444, fb->width, fb->height); ast_set_cursor_base(ast, dst_off); } diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index b1be458ed4dd..ecb278b63e8c 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -978,6 +978,75 @@ void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pit } EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8); +static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + unsigned int pixels2 = pixels & ~GENMASK_ULL(0, 0); + __le32 *dbuf32 = dbuf; + __le16 *dbuf16 = dbuf + pixels2 * sizeof(*dbuf16); + const __le32 *sbuf32 = sbuf; + unsigned int x; + u32 val32; + u16 val16; + u32 pix[2]; + + for (x = 0; x < pixels2; x += 2, ++dbuf32) { + pix[0] = le32_to_cpu(sbuf32[x]); + pix[1] = le32_to_cpu(sbuf32[x + 1]); + val32 = ((pix[0] & 0xf0000000) >> 16) | + ((pix[0] & 0x00f00000) >> 12) | + ((pix[0] & 0x0000f000) >> 8) | + ((pix[0] & 0x000000f0) >> 4) | + ((pix[1] & 0xf0000000) >> 0) | + ((pix[1] & 0x00f00000) << 4) | + ((pix[1] & 0x0000f000) << 8) | + ((pix[1] & 0x000000f0) << 12); + *dbuf32 = cpu_to_le32(val32); + } + for (; x < pixels; x++) { + pix[0] = le32_to_cpu(sbuf32[x]); + val16 = ((pix[0] & 0xf0000000) >> 16) | + ((pix[0] & 0x00f00000) >> 12) | + ((pix[0] & 0x0000f000) >> 8) | + ((pix[0] & 0x000000f0) >> 4); + dbuf16[x] = cpu_to_le16(val16); + } +} + +/** + * drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer + * @dst: Array of ARGB4444 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of ARGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts + * the color format during the process. The parameters @dst, @dst_pitch and + * @src refer to arrays. Each array must have at least as many entries as + * there are planes in @fb's format. Each entry stores the value for the + * format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for ARGB4444 devices that don't support + * ARGB8888 natively. + */ +void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 2, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, + drm_fb_argb8888_to_argb4444_line); +} +EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444); + /** * drm_fb_blit - Copy parts of a framebuffer to display memory * @dst: Array of display-memory addresses to copy to diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 428d81afe215..a1347e47e9d5 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -110,6 +110,9 @@ void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *d void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, const struct iosys_map *src, const struct drm_framebuffer *fb, From 19f4da84b695fa84b42de017ebe6018a0195425d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 17 Feb 2025 13:22:06 +0100 Subject: [PATCH 72/73] drm/ast: cursor: Add support for ARGB4444 Add support for cursor image data in ARGB4444 format. This is the hardware's native format and requires no conversion. Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250217122336.230067-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 8ab006e6bc32..91da54a4d8a6 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -720,6 +720,7 @@ static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled) } static const uint32_t ast_cursor_plane_formats[] = { + DRM_FORMAT_ARGB4444, DRM_FORMAT_ARGB8888, }; @@ -771,17 +772,28 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, */ if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) { - u8 *argb4444 = ast_cursor_plane->argb4444; - struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = { - IOSYS_MAP_INIT_VADDR(argb4444), - }; - unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - AST_HWC_PITCH, - }; + u8 *argb4444; - drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch, - shadow_plane_state->data, fb, &damage, - &shadow_plane_state->fmtcnv_state); + switch (fb->format->format) { + case DRM_FORMAT_ARGB4444: + argb4444 = shadow_plane_state->data[0].vaddr; + break; + default: + argb4444 = ast_cursor_plane->argb4444; + { + struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = { + IOSYS_MAP_INIT_VADDR(argb4444), + }; + unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + AST_HWC_PITCH, + }; + + drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch, + shadow_plane_state->data, fb, &damage, + &shadow_plane_state->fmtcnv_state); + } + break; + } ast_set_cursor_image(ast, argb4444, fb->width, fb->height); ast_set_cursor_base(ast, dst_off); } From e82e1a0c22d841f379b1c768469dcdaae650e443 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 17 Feb 2025 13:22:07 +0100 Subject: [PATCH 73/73] drm/ast: cursor: Move implementation to separate source file Move the cursor code into a separate source file for readability. No functional changes. v2: - include Signed-off-by: Thomas Zimmermann Reviewed-by: Jocelyn Falempe Link: https://patchwork.freedesktop.org/patch/msgid/20250217122336.230067-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/Makefile | 1 + drivers/gpu/drm/ast/ast_cursor.c | 309 +++++++++++++++++++++++++++++++ drivers/gpu/drm/ast/ast_drv.h | 24 +-- drivers/gpu/drm/ast/ast_mode.c | 277 +-------------------------- 4 files changed, 330 insertions(+), 281 deletions(-) create mode 100644 drivers/gpu/drm/ast/ast_cursor.c diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile index 3107ea9c7bf5..8d09ba5d5889 100644 --- a/drivers/gpu/drm/ast/Makefile +++ b/drivers/gpu/drm/ast/Makefile @@ -4,6 +4,7 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. ast-y := \ + ast_cursor.o \ ast_ddc.o \ ast_dp501.o \ ast_dp.o \ diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c new file mode 100644 index 000000000000..139ab00dee8f --- /dev/null +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: MIT +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ast_drv.h" + +/* + * Hardware cursor + */ + +/* define for signature structure */ +#define AST_HWC_SIGNATURE_CHECKSUM 0x00 +#define AST_HWC_SIGNATURE_SizeX 0x04 +#define AST_HWC_SIGNATURE_SizeY 0x08 +#define AST_HWC_SIGNATURE_X 0x0C +#define AST_HWC_SIGNATURE_Y 0x10 +#define AST_HWC_SIGNATURE_HOTSPOTX 0x14 +#define AST_HWC_SIGNATURE_HOTSPOTY 0x18 + +static u32 ast_cursor_calculate_checksum(const void *src, unsigned int width, unsigned int height) +{ + u32 csum = 0; + unsigned int one_pixel_copy = width & BIT(0); + unsigned int two_pixel_copy = width - one_pixel_copy; + unsigned int trailing_bytes = (AST_MAX_HWC_WIDTH - width) * sizeof(u16); + unsigned int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < two_pixel_copy; x += 2) { + const u32 *src32 = (const u32 *)src; + + csum += *src32; + src += SZ_4; + } + if (one_pixel_copy) { + const u16 *src16 = (const u16 *)src; + + csum += *src16; + src += SZ_2; + } + src += trailing_bytes; + } + + return csum; +} + +static void ast_set_cursor_image(struct ast_device *ast, const u8 *src, + unsigned int width, unsigned int height) +{ + u8 __iomem *dst = ast->cursor_plane.base.vaddr; + u32 csum; + + csum = ast_cursor_calculate_checksum(src, width, height); + + /* write pixel data */ + memcpy_toio(dst, src, AST_HWC_SIZE); + + /* write checksum + signature */ + dst += AST_HWC_SIZE; + writel(csum, dst); + writel(width, dst + AST_HWC_SIGNATURE_SizeX); + writel(height, dst + AST_HWC_SIGNATURE_SizeY); + writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); + writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); +} + +static void ast_set_cursor_base(struct ast_device *ast, u64 address) +{ + u8 addr0 = (address >> 3) & 0xff; + u8 addr1 = (address >> 11) & 0xff; + u8 addr2 = (address >> 19) & 0xff; + + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc8, addr0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc9, addr1); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xca, addr2); +} + +static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y, + u8 x_offset, u8 y_offset) +{ + u8 x0 = (x & 0x00ff); + u8 x1 = (x & 0x0f00) >> 8; + u8 y0 = (y & 0x00ff); + u8 y1 = (y & 0x0700) >> 8; + + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc2, x_offset); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc3, y_offset); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc4, x0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc5, x1); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc6, y0); + ast_set_index_reg(ast, AST_IO_VGACRI, 0xc7, y1); +} + +static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled) +{ + static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP | + AST_IO_VGACRCB_HWC_ENABLED); + + u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP; + + if (enabled) + vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED; + + ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xcb, mask, vgacrcb); +} + +/* + * Cursor plane + */ + +static const uint32_t ast_cursor_plane_formats[] = { + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ARGB8888, +}; + +static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_framebuffer *new_fb = new_plane_state->fb; + struct drm_crtc_state *new_crtc_state = NULL; + int ret; + + if (new_plane_state->crtc) + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); + + ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, + DRM_PLANE_NO_SCALING, + DRM_PLANE_NO_SCALING, + true, true); + if (ret || !new_plane_state->visible) + return ret; + + if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT) + return -EINVAL; + + return 0; +} + +static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane); + struct ast_plane *ast_plane = to_ast_plane(plane); + struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); + struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); + struct drm_framebuffer *fb = plane_state->fb; + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); + struct ast_device *ast = to_ast_device(plane->dev); + struct drm_rect damage; + u64 dst_off = ast_plane->offset; + u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */ + u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */ + unsigned int offset_x, offset_y; + u16 x, y; + u8 x_offset, y_offset; + + /* + * Do data transfer to hardware buffer and point the scanout + * engine to the offset. + */ + + if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) { + u8 *argb4444; + + switch (fb->format->format) { + case DRM_FORMAT_ARGB4444: + argb4444 = shadow_plane_state->data[0].vaddr; + break; + default: + argb4444 = ast_cursor_plane->argb4444; + { + struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = { + IOSYS_MAP_INIT_VADDR(argb4444), + }; + unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + AST_HWC_PITCH, + }; + + drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch, + shadow_plane_state->data, fb, &damage, + &shadow_plane_state->fmtcnv_state); + } + break; + } + ast_set_cursor_image(ast, argb4444, fb->width, fb->height); + ast_set_cursor_base(ast, dst_off); + } + + /* + * Update location in HWC signature and registers. + */ + + writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X); + writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y); + + offset_x = AST_MAX_HWC_WIDTH - fb->width; + offset_y = AST_MAX_HWC_HEIGHT - fb->height; + + if (plane_state->crtc_x < 0) { + x_offset = (-plane_state->crtc_x) + offset_x; + x = 0; + } else { + x_offset = offset_x; + x = plane_state->crtc_x; + } + if (plane_state->crtc_y < 0) { + y_offset = (-plane_state->crtc_y) + offset_y; + y = 0; + } else { + y_offset = offset_y; + y = plane_state->crtc_y; + } + + ast_set_cursor_location(ast, x, y, x_offset, y_offset); + + /* Dummy write to enable HWC and make the HW pick-up the changes. */ + ast_set_cursor_enabled(ast, true); +} + +static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, + struct drm_atomic_state *state) +{ + struct ast_device *ast = to_ast_device(plane->dev); + + ast_set_cursor_enabled(ast, false); +} + +static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = { + DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, + .atomic_check = ast_cursor_plane_helper_atomic_check, + .atomic_update = ast_cursor_plane_helper_atomic_update, + .atomic_disable = ast_cursor_plane_helper_atomic_disable, +}; + +static const struct drm_plane_funcs ast_cursor_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + DRM_GEM_SHADOW_PLANE_FUNCS, +}; + +int ast_cursor_plane_init(struct ast_device *ast) +{ + struct drm_device *dev = &ast->base; + struct ast_cursor_plane *ast_cursor_plane = &ast->cursor_plane; + struct ast_plane *ast_plane = &ast_cursor_plane->base; + struct drm_plane *cursor_plane = &ast_plane->base; + size_t size; + void __iomem *vaddr; + u64 offset; + int ret; + + /* + * Allocate backing storage for cursors. The BOs are permanently + * pinned to the top end of the VRAM. + */ + + size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); + + if (ast->vram_fb_available < size) + return -ENOMEM; + + vaddr = ast->vram + ast->vram_fb_available - size; + offset = ast->vram_fb_available - size; + + ret = ast_plane_init(dev, ast_plane, vaddr, offset, size, + 0x01, &ast_cursor_plane_funcs, + ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats), + NULL, DRM_PLANE_TYPE_CURSOR); + if (ret) { + drm_err(dev, "ast_plane_init() failed: %d\n", ret); + return ret; + } + drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs); + drm_plane_enable_fb_damage_clips(cursor_plane); + + ast->vram_fb_available -= size; + + return 0; +} diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 973abd0cbd42..d2c2605d2728 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -118,15 +118,6 @@ enum ast_config_mode { #define AST_HWC_SIGNATURE_SIZE 32 -/* define for signature structure */ -#define AST_HWC_SIGNATURE_CHECKSUM 0x00 -#define AST_HWC_SIGNATURE_SizeX 0x04 -#define AST_HWC_SIGNATURE_SizeY 0x08 -#define AST_HWC_SIGNATURE_X 0x0C -#define AST_HWC_SIGNATURE_Y 0x10 -#define AST_HWC_SIGNATURE_HOTSPOTX 0x14 -#define AST_HWC_SIGNATURE_HOTSPOTY 0x18 - /* * Planes */ @@ -383,8 +374,6 @@ struct ast_crtc_state { #define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base) -int ast_mode_config_init(struct ast_device *ast); - #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) @@ -450,6 +439,9 @@ void ast_patch_ahb_2500(void __iomem *regs); int ast_vga_output_init(struct ast_device *ast); int ast_sil164_output_init(struct ast_device *ast); +/* ast_cursor.c */ +int ast_cursor_plane_init(struct ast_device *ast); + /* ast dp501 */ bool ast_backup_fw(struct ast_device *ast, u8 *addr, u32 size); void ast_init_3rdtx(struct ast_device *ast); @@ -459,4 +451,14 @@ int ast_dp501_output_init(struct ast_device *ast); int ast_dp_launch(struct ast_device *ast); int ast_astdp_output_init(struct ast_device *ast); +/* ast_mode.c */ +int ast_mode_config_init(struct ast_device *ast); +int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane, + void __iomem *vaddr, u64 offset, unsigned long size, + uint32_t possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, unsigned int format_count, + const uint64_t *format_modifiers, + enum drm_plane_type type); + #endif diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 91da54a4d8a6..c3b950675485 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -438,13 +438,13 @@ static void ast_wait_for_vretrace(struct ast_device *ast) * Planes */ -static int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane, - void __iomem *vaddr, u64 offset, unsigned long size, - uint32_t possible_crtcs, - const struct drm_plane_funcs *funcs, - const uint32_t *formats, unsigned int format_count, - const uint64_t *format_modifiers, - enum drm_plane_type type) +int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane, + void __iomem *vaddr, u64 offset, unsigned long size, + uint32_t possible_crtcs, + const struct drm_plane_funcs *funcs, + const uint32_t *formats, unsigned int format_count, + const uint64_t *format_modifiers, + enum drm_plane_type type) { struct drm_plane *plane = &ast_plane->base; @@ -628,269 +628,6 @@ static int ast_primary_plane_init(struct ast_device *ast) return 0; } -/* - * Cursor plane - */ - -static u32 ast_cursor_calculate_checksum(const void *src, unsigned int width, unsigned int height) -{ - u32 csum = 0; - unsigned int one_pixel_copy = width & BIT(0); - unsigned int two_pixel_copy = width - one_pixel_copy; - unsigned int trailing_bytes = (AST_MAX_HWC_WIDTH - width) * sizeof(u16); - unsigned int x, y; - - for (y = 0; y < height; y++) { - for (x = 0; x < two_pixel_copy; x += 2) { - const u32 *src32 = (const u32 *)src; - - csum += *src32; - src += SZ_4; - } - if (one_pixel_copy) { - const u16 *src16 = (const u16 *)src; - - csum += *src16; - src += SZ_2; - } - src += trailing_bytes; - } - - return csum; -} - -static void ast_set_cursor_image(struct ast_device *ast, const u8 *src, - unsigned int width, unsigned int height) -{ - u8 __iomem *dst = ast->cursor_plane.base.vaddr; - u32 csum; - - csum = ast_cursor_calculate_checksum(src, width, height); - - /* write pixel data */ - memcpy_toio(dst, src, AST_HWC_SIZE); - - /* write checksum + signature */ - dst += AST_HWC_SIZE; - writel(csum, dst); - writel(width, dst + AST_HWC_SIGNATURE_SizeX); - writel(height, dst + AST_HWC_SIGNATURE_SizeY); - writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX); - writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY); -} - -static void ast_set_cursor_base(struct ast_device *ast, u64 address) -{ - u8 addr0 = (address >> 3) & 0xff; - u8 addr1 = (address >> 11) & 0xff; - u8 addr2 = (address >> 19) & 0xff; - - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc8, addr0); - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc9, addr1); - ast_set_index_reg(ast, AST_IO_VGACRI, 0xca, addr2); -} - -static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y, - u8 x_offset, u8 y_offset) -{ - u8 x0 = (x & 0x00ff); - u8 x1 = (x & 0x0f00) >> 8; - u8 y0 = (y & 0x00ff); - u8 y1 = (y & 0x0700) >> 8; - - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc2, x_offset); - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc3, y_offset); - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc4, x0); - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc5, x1); - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc6, y0); - ast_set_index_reg(ast, AST_IO_VGACRI, 0xc7, y1); -} - -static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled) -{ - static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP | - AST_IO_VGACRCB_HWC_ENABLED); - - u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP; - - if (enabled) - vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED; - - ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xcb, mask, vgacrcb); -} - -static const uint32_t ast_cursor_plane_formats[] = { - DRM_FORMAT_ARGB4444, - DRM_FORMAT_ARGB8888, -}; - -static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); - struct drm_framebuffer *new_fb = new_plane_state->fb; - struct drm_crtc_state *new_crtc_state = NULL; - int ret; - - if (new_plane_state->crtc) - new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc); - - ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, - DRM_PLANE_NO_SCALING, - DRM_PLANE_NO_SCALING, - true, true); - if (ret || !new_plane_state->visible) - return ret; - - if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT) - return -EINVAL; - - return 0; -} - -static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane); - struct ast_plane *ast_plane = to_ast_plane(plane); - struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane); - struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state); - struct drm_framebuffer *fb = plane_state->fb; - struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane); - struct ast_device *ast = to_ast_device(plane->dev); - struct drm_rect damage; - u64 dst_off = ast_plane->offset; - u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */ - u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */ - unsigned int offset_x, offset_y; - u16 x, y; - u8 x_offset, y_offset; - - /* - * Do data transfer to hardware buffer and point the scanout - * engine to the offset. - */ - - if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) { - u8 *argb4444; - - switch (fb->format->format) { - case DRM_FORMAT_ARGB4444: - argb4444 = shadow_plane_state->data[0].vaddr; - break; - default: - argb4444 = ast_cursor_plane->argb4444; - { - struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = { - IOSYS_MAP_INIT_VADDR(argb4444), - }; - unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - AST_HWC_PITCH, - }; - - drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch, - shadow_plane_state->data, fb, &damage, - &shadow_plane_state->fmtcnv_state); - } - break; - } - ast_set_cursor_image(ast, argb4444, fb->width, fb->height); - ast_set_cursor_base(ast, dst_off); - } - - /* - * Update location in HWC signature and registers. - */ - - writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X); - writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y); - - offset_x = AST_MAX_HWC_WIDTH - fb->width; - offset_y = AST_MAX_HWC_HEIGHT - fb->height; - - if (plane_state->crtc_x < 0) { - x_offset = (-plane_state->crtc_x) + offset_x; - x = 0; - } else { - x_offset = offset_x; - x = plane_state->crtc_x; - } - if (plane_state->crtc_y < 0) { - y_offset = (-plane_state->crtc_y) + offset_y; - y = 0; - } else { - y_offset = offset_y; - y = plane_state->crtc_y; - } - - ast_set_cursor_location(ast, x, y, x_offset, y_offset); - - /* Dummy write to enable HWC and make the HW pick-up the changes. */ - ast_set_cursor_enabled(ast, true); -} - -static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct ast_device *ast = to_ast_device(plane->dev); - - ast_set_cursor_enabled(ast, false); -} - -static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = { - DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, - .atomic_check = ast_cursor_plane_helper_atomic_check, - .atomic_update = ast_cursor_plane_helper_atomic_update, - .atomic_disable = ast_cursor_plane_helper_atomic_disable, -}; - -static const struct drm_plane_funcs ast_cursor_plane_funcs = { - .update_plane = drm_atomic_helper_update_plane, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = drm_plane_cleanup, - DRM_GEM_SHADOW_PLANE_FUNCS, -}; - -static int ast_cursor_plane_init(struct ast_device *ast) -{ - struct drm_device *dev = &ast->base; - struct ast_cursor_plane *ast_cursor_plane = &ast->cursor_plane; - struct ast_plane *ast_plane = &ast_cursor_plane->base; - struct drm_plane *cursor_plane = &ast_plane->base; - size_t size; - void __iomem *vaddr; - u64 offset; - int ret; - - /* - * Allocate backing storage for cursors. The BOs are permanently - * pinned to the top end of the VRAM. - */ - - size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE); - - if (ast->vram_fb_available < size) - return -ENOMEM; - - vaddr = ast->vram + ast->vram_fb_available - size; - offset = ast->vram_fb_available - size; - - ret = ast_plane_init(dev, ast_plane, vaddr, offset, size, - 0x01, &ast_cursor_plane_funcs, - ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats), - NULL, DRM_PLANE_TYPE_CURSOR); - if (ret) { - drm_err(dev, "ast_plane_init() failed: %d\n", ret); - return ret; - } - drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs); - drm_plane_enable_fb_damage_clips(cursor_plane); - - ast->vram_fb_available -= size; - - return 0; -} - /* * CRTC */