[PATCH v2] drm/msm: default separate_gpu_kms to auto selection

Mahadevan P posted 1 patch 2 weeks, 6 days ago
There is a newer version of this series
drivers/gpu/drm/msm/adreno/adreno_device.c |  2 +-
drivers/gpu/drm/msm/msm_drv.c              | 52 ++++++++++++++++++++++++++----
drivers/gpu/drm/msm/msm_drv.h              |  4 ++-
drivers/gpu/drm/msm/msm_mdss.c             | 15 +++++++++
4 files changed, 64 insertions(+), 9 deletions(-)
[PATCH v2] drm/msm: default separate_gpu_kms to auto selection
Posted by Mahadevan P 2 weeks, 6 days ago
On platforms with multiple display subsystems, such as SA8775P, the GPU
binds to the first display subsystem that probes. This implicit binding
prevents subsequent display subsystems from probing successfully,
breaking multi-display support.

Use the tristate separate_gpu_kms module parameter with the default
value set to auto (-1). In auto mode, the driver selects the binding
behavior based on the number of GPUs and display subsystems. This allows
display subsystems to probe independently when required, while
preserving the existing single-card behavior on simpler systems.

The separate_gpu_kms module parameter has the following semantics:

  -1 (auto, default):
     Select the binding mode based on hardware topology. If exactly one
     GPU and one display subsystem are present, bind them together to
     form a single DRM device. Otherwise, expose the GPU and display
     subsystems as separate DRM devices.

   0:
     Always bind the GPU and display together to form a single DRM
     device.

   1:
     Always expose the GPU and display subsystems as separate DRM
     devices.

This ensures correct probing on multi-display platforms without
affecting single-display, single-GPU systems.

Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>
---
Changes in v2:
- EDITME: describe what is new in this series revision.
- EDITME: use bulletpoints and terse descriptions.
- Link to v1: https://lore.kernel.org/r/20260223-seperate_gpu_kms-v1-1-e8231e7f1685@oss.qualcomm.com
---
Depends on:
  https://lore.kernel.org/lkml/20260124-adreno-module-table-v1-1-9c2dbb2638b4@oss.qualcomm.com/

  When separate_gpu_kms is enabled, the GPU and display drivers are
  probed independently. In this configuration, the Adreno GPU driver
  may no longer be loaded implicitly via the display subsystem.

  The referenced patch adds a MODULE_DEVICE_TABLE() entry for the
  Adreno GPU device, ensuring proper module autoloading based on
  device tree matching. This is required to guarantee that the GPU
  driver is loaded correctly when GPU and display probing are
  decoupled.

Changes in v2:

    - Drop dependency on Lemans dual-DPU device tree changes as this patch
      works independently (Dmitry)
    - Switch separate_gpu_kms to tristate and default to auto mode (Rob)
    - Rename msm_gpu_no_components() to msm_separate_gpu_kms_components() for clarity
    - Link to v1: https://lore.kernel.org/r/20260223-seperate_gpu_kms-v1-1-e8231e7f1685@oss.qualcomm.com
---
 drivers/gpu/drm/msm/adreno/adreno_device.c |  2 +-
 drivers/gpu/drm/msm/msm_drv.c              | 52 ++++++++++++++++++++++++++----
 drivers/gpu/drm/msm/msm_drv.h              |  4 ++-
 drivers/gpu/drm/msm/msm_mdss.c             | 15 +++++++++
 4 files changed, 64 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 4edfe80c5be7..e40648c05797 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -272,7 +272,7 @@ static const struct component_ops a3xx_ops = {
 static int adreno_probe(struct platform_device *pdev)
 {
 	if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon") ||
-	    msm_gpu_no_components())
+	    msm_separate_gpu_kms_components())
 		return msm_gpu_probe(pdev, &a3xx_ops);
 
 	return component_add(&pdev->dev, &a3xx_ops);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index e5ab1e28851d..575d1aea7927 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -54,16 +54,54 @@ static bool modeset = true;
 MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)");
 module_param(modeset, bool, 0600);
 
-static bool separate_gpu_kms;
-MODULE_PARM_DESC(separate_gpu_drm, "Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)");
-module_param(separate_gpu_kms, bool, 0400);
+/*
+ * separate_gpu_kms (tristate):
+ *   -1 (default): decide automatically based on hardware topology. Split devices
+ *                 if there is more than one GPU or more than one display master.
+ *    0: force single DRM device (bind display + GPU)
+ *    1: force separate DRM devices
+ */
+static int separate_gpu_kms = -1;
+MODULE_PARM_DESC(separate_gpu_kms,
+		 "Use separate DRM device for the GPU (-1=auto (default), 0=single DRM device, 1=separate DRM devices)");
+module_param(separate_gpu_kms, int, 0400);
 
 DECLARE_FAULT_ATTR(fail_gem_alloc);
 DECLARE_FAULT_ATTR(fail_gem_iova);
 
-bool msm_gpu_no_components(void)
+static const struct of_device_id msm_gpu_match[];
+static int msm_count_gpus(void)
+{
+	struct device_node *np;
+	int count = 0;
+
+	for_each_matching_node(np, msm_gpu_match) {
+		if (of_device_is_available(np) && adreno_has_gpu(np))
+			count++;
+	}
+
+	return count;
+}
+
+static bool msm_separate_gpu_kms_auto(void)
+{
+	int gpus = msm_count_gpus();
+	int mdss = msm_mdss_count_masters();
+
+	if (gpus <= 0 || mdss <= 0)
+		return false;
+
+	/* If exactly one GPU and one display subsystem single card */
+	return (gpus > 1) || (mdss > 1);
+}
+
+bool msm_separate_gpu_kms_components(void)
 {
-	return separate_gpu_kms;
+	if (separate_gpu_kms == 1)
+		return true;
+	if (separate_gpu_kms == 0)
+		return false;
+	return msm_separate_gpu_kms_auto();
 }
 
 static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops)
@@ -1030,7 +1068,7 @@ static int add_gpu_components(struct device *dev,
 static int msm_drm_bind(struct device *dev)
 {
 	return msm_drm_init(dev,
-			    msm_gpu_no_components() ?
+			    msm_separate_gpu_kms_components() ?
 				    &msm_kms_driver :
 				    &msm_driver,
 			    NULL);
@@ -1069,7 +1107,7 @@ int msm_drv_probe(struct device *master_dev,
 			return ret;
 	}
 
-	if (!msm_gpu_no_components()) {
+	if (!msm_separate_gpu_kms_components()) {
 		ret = add_gpu_components(master_dev, &match);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 6d847d593f1a..64a5ad35f7a2 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -555,6 +555,8 @@ void msm_kms_shutdown(struct platform_device *pdev);
 
 bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver);
 
-bool msm_gpu_no_components(void);
+bool msm_separate_gpu_kms_components(void);
+
+int msm_mdss_count_masters(void);
 
 #endif /* __MSM_DRV_H__ */
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index 9047e8d9ee89..00e3ac7dab3a 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -73,6 +73,21 @@ static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
 	return 0;
 }
 
+static const struct of_device_id mdss_dt_match[];
+
+int msm_mdss_count_masters(void)
+{
+	struct device_node *np;
+	int count = 0;
+
+	for_each_matching_node(np, mdss_dt_match) {
+		if (of_device_is_available(np))
+			count++;
+	}
+
+	return count;
+}
+
 static void msm_mdss_irq(struct irq_desc *desc)
 {
 	struct msm_mdss *msm_mdss = irq_desc_get_handler_data(desc);

---
base-commit: b84a0ebe421ca56995ff78b66307667b62b3a900
change-id: 20260316-separate_gpu_kms-04d2cf4d91e2

Best regards,
-- 
Mahadevan P <mahadevan.p@oss.qualcomm.com>
Re: [PATCH v2] drm/msm: default separate_gpu_kms to auto selection
Posted by kernel test robot 2 weeks, 2 days ago
Hi Mahadevan,

kernel test robot noticed the following build errors:

[auto build test ERROR on b84a0ebe421ca56995ff78b66307667b62b3a900]

url:    https://github.com/intel-lab-lkp/linux/commits/Mahadevan-P/drm-msm-default-separate_gpu_kms-to-auto-selection/20260318-063854
base:   b84a0ebe421ca56995ff78b66307667b62b3a900
patch link:    https://lore.kernel.org/r/20260317-separate_gpu_kms-v2-1-b027ca97b9fe%40oss.qualcomm.com
patch subject: [PATCH v2] drm/msm: default separate_gpu_kms to auto selection
config: loongarch-randconfig-002-20260321 (https://download.01.org/0day-ci/archive/20260321/202603211049.NkgQVReV-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260321/202603211049.NkgQVReV-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603211049.NkgQVReV-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "msm_mdss_count_masters" [drivers/gpu/drm/msm/msm.ko] undefined!

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v2] drm/msm: default separate_gpu_kms to auto selection
Posted by Mahadevan P 2 weeks, 6 days ago

On 3/17/2026 3:57 PM, Mahadevan P wrote:
> On platforms with multiple display subsystems, such as SA8775P, the GPU
> binds to the first display subsystem that probes. This implicit binding
> prevents subsequent display subsystems from probing successfully,
> breaking multi-display support.
> 
> Use the tristate separate_gpu_kms module parameter with the default
> value set to auto (-1). In auto mode, the driver selects the binding
> behavior based on the number of GPUs and display subsystems. This allows
> display subsystems to probe independently when required, while
> preserving the existing single-card behavior on simpler systems.
> 
> The separate_gpu_kms module parameter has the following semantics:
> 
>    -1 (auto, default):
>       Select the binding mode based on hardware topology. If exactly one
>       GPU and one display subsystem are present, bind them together to
>       form a single DRM device. Otherwise, expose the GPU and display
>       subsystems as separate DRM devices.
> 
>     0:
>       Always bind the GPU and display together to form a single DRM
>       device.
> 
>     1:
>       Always expose the GPU and display subsystems as separate DRM
>       devices.
> 
> This ensures correct probing on multi-display platforms without
> affecting single-display, single-GPU systems.
> 
> Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>
> ---
> Changes in v2:
> - EDITME: describe what is new in this series revision.
> - EDITME: use bulletpoints and terse descriptions.
> - Link to v1: https://lore.kernel.org/r/20260223-seperate_gpu_kms-v1-1-e8231e7f1685@oss.qualcomm.com

 From coverletter this got added from b4 will make sure will be posted 
properly with subsequent patches.

> ---
> Depends on:
>    https://lore.kernel.org/lkml/20260124-adreno-module-table-v1-1-9c2dbb2638b4@oss.qualcomm.com/
> 
>    When separate_gpu_kms is enabled, the GPU and display drivers are
>    probed independently. In this configuration, the Adreno GPU driver
>    may no longer be loaded implicitly via the display subsystem.
> 
>    The referenced patch adds a MODULE_DEVICE_TABLE() entry for the
>    Adreno GPU device, ensuring proper module autoloading based on
>    device tree matching. This is required to guarantee that the GPU
>    driver is loaded correctly when GPU and display probing are
>    decoupled.
> 
> Changes in v2:
> 
>      - Drop dependency on Lemans dual-DPU device tree changes as this patch
>        works independently (Dmitry)
>      - Switch separate_gpu_kms to tristate and default to auto mode (Rob)
>      - Rename msm_gpu_no_components() to msm_separate_gpu_kms_components() for clarity
>      - Link to v1: https://lore.kernel.org/r/20260223-seperate_gpu_kms-v1-1-e8231e7f1685@oss.qualcomm.com
> ---
>   drivers/gpu/drm/msm/adreno/adreno_device.c |  2 +-
>   drivers/gpu/drm/msm/msm_drv.c              | 52 ++++++++++++++++++++++++++----
>   drivers/gpu/drm/msm/msm_drv.h              |  4 ++-
>   drivers/gpu/drm/msm/msm_mdss.c             | 15 +++++++++
>   4 files changed, 64 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index 4edfe80c5be7..e40648c05797 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -272,7 +272,7 @@ static const struct component_ops a3xx_ops = {
>   static int adreno_probe(struct platform_device *pdev)
>   {
>   	if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon") ||
> -	    msm_gpu_no_components())
> +	    msm_separate_gpu_kms_components())
>   		return msm_gpu_probe(pdev, &a3xx_ops);
>   
>   	return component_add(&pdev->dev, &a3xx_ops);
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index e5ab1e28851d..575d1aea7927 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -54,16 +54,54 @@ static bool modeset = true;
>   MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)");
>   module_param(modeset, bool, 0600);
>   
> -static bool separate_gpu_kms;
> -MODULE_PARM_DESC(separate_gpu_drm, "Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)");
> -module_param(separate_gpu_kms, bool, 0400);
> +/*
> + * separate_gpu_kms (tristate):
> + *   -1 (default): decide automatically based on hardware topology. Split devices
> + *                 if there is more than one GPU or more than one display master.
> + *    0: force single DRM device (bind display + GPU)
> + *    1: force separate DRM devices
> + */
> +static int separate_gpu_kms = -1;
> +MODULE_PARM_DESC(separate_gpu_kms,
> +		 "Use separate DRM device for the GPU (-1=auto (default), 0=single DRM device, 1=separate DRM devices)");
> +module_param(separate_gpu_kms, int, 0400);
>   
>   DECLARE_FAULT_ATTR(fail_gem_alloc);
>   DECLARE_FAULT_ATTR(fail_gem_iova);
>   
> -bool msm_gpu_no_components(void)
> +static const struct of_device_id msm_gpu_match[];
> +static int msm_count_gpus(void)
> +{
> +	struct device_node *np;
> +	int count = 0;
> +
> +	for_each_matching_node(np, msm_gpu_match) {
> +		if (of_device_is_available(np) && adreno_has_gpu(np))
> +			count++;
> +	}
> +
> +	return count;
> +}
> +
> +static bool msm_separate_gpu_kms_auto(void)
> +{
> +	int gpus = msm_count_gpus();
> +	int mdss = msm_mdss_count_masters();
> +
> +	if (gpus <= 0 || mdss <= 0)
> +		return false;
> +
> +	/* If exactly one GPU and one display subsystem single card */
> +	return (gpus > 1) || (mdss > 1);
> +}
> +
> +bool msm_separate_gpu_kms_components(void)
>   {
> -	return separate_gpu_kms;
> +	if (separate_gpu_kms == 1)
> +		return true;
> +	if (separate_gpu_kms == 0)
> +		return false;
> +	return msm_separate_gpu_kms_auto();
>   }
>   
>   static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops)
> @@ -1030,7 +1068,7 @@ static int add_gpu_components(struct device *dev,
>   static int msm_drm_bind(struct device *dev)
>   {
>   	return msm_drm_init(dev,
> -			    msm_gpu_no_components() ?
> +			    msm_separate_gpu_kms_components() ?
>   				    &msm_kms_driver :
>   				    &msm_driver,
>   			    NULL);
> @@ -1069,7 +1107,7 @@ int msm_drv_probe(struct device *master_dev,
>   			return ret;
>   	}
>   
> -	if (!msm_gpu_no_components()) {
> +	if (!msm_separate_gpu_kms_components()) {
>   		ret = add_gpu_components(master_dev, &match);
>   		if (ret)
>   			return ret;
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index 6d847d593f1a..64a5ad35f7a2 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -555,6 +555,8 @@ void msm_kms_shutdown(struct platform_device *pdev);
>   
>   bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver);
>   
> -bool msm_gpu_no_components(void);
> +bool msm_separate_gpu_kms_components(void);
> +
> +int msm_mdss_count_masters(void);
>   
>   #endif /* __MSM_DRV_H__ */
> diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
> index 9047e8d9ee89..00e3ac7dab3a 100644
> --- a/drivers/gpu/drm/msm/msm_mdss.c
> +++ b/drivers/gpu/drm/msm/msm_mdss.c
> @@ -73,6 +73,21 @@ static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
>   	return 0;
>   }
>   
> +static const struct of_device_id mdss_dt_match[];
> +
> +int msm_mdss_count_masters(void)
> +{
> +	struct device_node *np;
> +	int count = 0;
> +
> +	for_each_matching_node(np, mdss_dt_match) {
> +		if (of_device_is_available(np))
> +			count++;
> +	}
> +
> +	return count;
> +}
> +
>   static void msm_mdss_irq(struct irq_desc *desc)
>   {
>   	struct msm_mdss *msm_mdss = irq_desc_get_handler_data(desc);
> 
> ---
> base-commit: b84a0ebe421ca56995ff78b66307667b62b3a900
> change-id: 20260316-separate_gpu_kms-04d2cf4d91e2
> 
> Best regards,
Re: [PATCH v2] drm/msm: default separate_gpu_kms to auto selection
Posted by Dmitry Baryshkov 2 weeks, 6 days ago
On Tue, Mar 17, 2026 at 04:06:30PM +0530, Mahadevan P wrote:
> 
> 
> On 3/17/2026 3:57 PM, Mahadevan P wrote:
> > On platforms with multiple display subsystems, such as SA8775P, the GPU
> > binds to the first display subsystem that probes. This implicit binding
> > prevents subsequent display subsystems from probing successfully,
> > breaking multi-display support.
> > 
> > Use the tristate separate_gpu_kms module parameter with the default
> > value set to auto (-1). In auto mode, the driver selects the binding
> > behavior based on the number of GPUs and display subsystems. This allows
> > display subsystems to probe independently when required, while
> > preserving the existing single-card behavior on simpler systems.
> > 
> > The separate_gpu_kms module parameter has the following semantics:
> > 
> >    -1 (auto, default):
> >       Select the binding mode based on hardware topology. If exactly one
> >       GPU and one display subsystem are present, bind them together to
> >       form a single DRM device. Otherwise, expose the GPU and display
> >       subsystems as separate DRM devices.
> > 
> >     0:
> >       Always bind the GPU and display together to form a single DRM
> >       device.
> > 
> >     1:
> >       Always expose the GPU and display subsystems as separate DRM
> >       devices.
> > 
> > This ensures correct probing on multi-display platforms without
> > affecting single-display, single-GPU systems.
> > 
> > Signed-off-by: Mahadevan P <mahadevan.p@oss.qualcomm.com>
> > ---
> > Changes in v2:
> > - EDITME: describe what is new in this series revision.
> > - EDITME: use bulletpoints and terse descriptions.
> > - Link to v1: https://lore.kernel.org/r/20260223-seperate_gpu_kms-v1-1-e8231e7f1685@oss.qualcomm.com
> 
> From coverletter this got added from b4 will make sure will be posted
> properly with subsequent patches.

You know, you can just edit it in the b4's coverletter and drop your
manual changelog...

> 
> > ---
> > Depends on:
> >    https://lore.kernel.org/lkml/20260124-adreno-module-table-v1-1-9c2dbb2638b4@oss.qualcomm.com/
> > 
> >    When separate_gpu_kms is enabled, the GPU and display drivers are
> >    probed independently. In this configuration, the Adreno GPU driver
> >    may no longer be loaded implicitly via the display subsystem.
> > 
> >    The referenced patch adds a MODULE_DEVICE_TABLE() entry for the
> >    Adreno GPU device, ensuring proper module autoloading based on
> >    device tree matching. This is required to guarantee that the GPU
> >    driver is loaded correctly when GPU and display probing are
> >    decoupled.
> > 
> > Changes in v2:
> > 
> >      - Drop dependency on Lemans dual-DPU device tree changes as this patch
> >        works independently (Dmitry)
> >      - Switch separate_gpu_kms to tristate and default to auto mode (Rob)
> >      - Rename msm_gpu_no_components() to msm_separate_gpu_kms_components() for clarity
> >      - Link to v1: https://lore.kernel.org/r/20260223-seperate_gpu_kms-v1-1-e8231e7f1685@oss.qualcomm.com
> > ---
> >   drivers/gpu/drm/msm/adreno/adreno_device.c |  2 +-
> >   drivers/gpu/drm/msm/msm_drv.c              | 52 ++++++++++++++++++++++++++----
> >   drivers/gpu/drm/msm/msm_drv.h              |  4 ++-
> >   drivers/gpu/drm/msm/msm_mdss.c             | 15 +++++++++
> >   4 files changed, 64 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
> > index 4edfe80c5be7..e40648c05797 100644
> > --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> > +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> > @@ -272,7 +272,7 @@ static const struct component_ops a3xx_ops = {
> >   static int adreno_probe(struct platform_device *pdev)
> >   {
> >   	if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon") ||
> > -	    msm_gpu_no_components())
> > +	    msm_separate_gpu_kms_components())
> >   		return msm_gpu_probe(pdev, &a3xx_ops);
> >   	return component_add(&pdev->dev, &a3xx_ops);
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> > index e5ab1e28851d..575d1aea7927 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -54,16 +54,54 @@ static bool modeset = true;
> >   MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disable)");
> >   module_param(modeset, bool, 0600);
> > -static bool separate_gpu_kms;
> > -MODULE_PARM_DESC(separate_gpu_drm, "Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)");
> > -module_param(separate_gpu_kms, bool, 0400);
> > +/*
> > + * separate_gpu_kms (tristate):
> > + *   -1 (default): decide automatically based on hardware topology. Split devices
> > + *                 if there is more than one GPU or more than one display master.
> > + *    0: force single DRM device (bind display + GPU)
> > + *    1: force separate DRM devices
> > + */
> > +static int separate_gpu_kms = -1;
> > +MODULE_PARM_DESC(separate_gpu_kms,
> > +		 "Use separate DRM device for the GPU (-1=auto (default), 0=single DRM device, 1=separate DRM devices)");
> > +module_param(separate_gpu_kms, int, 0400);
> >   DECLARE_FAULT_ATTR(fail_gem_alloc);
> >   DECLARE_FAULT_ATTR(fail_gem_iova);
> > -bool msm_gpu_no_components(void)
> > +static const struct of_device_id msm_gpu_match[];
> > +static int msm_count_gpus(void)
> > +{
> > +	struct device_node *np;
> > +	int count = 0;
> > +
> > +	for_each_matching_node(np, msm_gpu_match) {
> > +		if (of_device_is_available(np) && adreno_has_gpu(np))
> > +			count++;

If !adreno_has_gpu() we definitely should be using separate binding.

> > +	}
> > +
> > +	return count;
> > +}
> > +
> > +static bool msm_separate_gpu_kms_auto(void)
> > +{
> > +	int gpus = msm_count_gpus();
> > +	int mdss = msm_mdss_count_masters();

This breaks MDP4 case.

> > +
> > +	if (gpus <= 0 || mdss <= 0)
> > +		return false;
> > +
> > +	/* If exactly one GPU and one display subsystem single card */
> > +	return (gpus > 1) || (mdss > 1);
> > +}
> > +
> > +bool msm_separate_gpu_kms_components(void)
> >   {
> > -	return separate_gpu_kms;
> > +	if (separate_gpu_kms == 1)
> > +		return true;
> > +	if (separate_gpu_kms == 0)
> > +		return false;
> > +	return msm_separate_gpu_kms_auto();
> >   }
> >   static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops)
> > @@ -1030,7 +1068,7 @@ static int add_gpu_components(struct device *dev,
> >   static int msm_drm_bind(struct device *dev)
> >   {
> >   	return msm_drm_init(dev,
> > -			    msm_gpu_no_components() ?
> > +			    msm_separate_gpu_kms_components() ?
> >   				    &msm_kms_driver :
> >   				    &msm_driver,
> >   			    NULL);
> > @@ -1069,7 +1107,7 @@ int msm_drv_probe(struct device *master_dev,
> >   			return ret;
> >   	}
> > -	if (!msm_gpu_no_components()) {
> > +	if (!msm_separate_gpu_kms_components()) {
> >   		ret = add_gpu_components(master_dev, &match);
> >   		if (ret)
> >   			return ret;
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> > index 6d847d593f1a..64a5ad35f7a2 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -555,6 +555,8 @@ void msm_kms_shutdown(struct platform_device *pdev);
> >   bool msm_disp_drv_should_bind(struct device *dev, bool dpu_driver);
> > -bool msm_gpu_no_components(void);
> > +bool msm_separate_gpu_kms_components(void);
> > +
> > +int msm_mdss_count_masters(void);
> >   #endif /* __MSM_DRV_H__ */
> > diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
> > index 9047e8d9ee89..00e3ac7dab3a 100644
> > --- a/drivers/gpu/drm/msm/msm_mdss.c
> > +++ b/drivers/gpu/drm/msm/msm_mdss.c
> > @@ -73,6 +73,21 @@ static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
> >   	return 0;
> >   }
> > +static const struct of_device_id mdss_dt_match[];
> > +
> > +int msm_mdss_count_masters(void)

No masters please.

> > +{
> > +	struct device_node *np;
> > +	int count = 0;
> > +
> > +	for_each_matching_node(np, mdss_dt_match) {
> > +		if (of_device_is_available(np))
> > +			count++;
> > +	}
> > +
> > +	return count;
> > +}
> > +
> >   static void msm_mdss_irq(struct irq_desc *desc)
> >   {
> >   	struct msm_mdss *msm_mdss = irq_desc_get_handler_data(desc);
> > 
> > ---
> > base-commit: b84a0ebe421ca56995ff78b66307667b62b3a900
> > change-id: 20260316-separate_gpu_kms-04d2cf4d91e2
> > 
> > Best regards,

-- 
With best wishes
Dmitry