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 <[email protected]> > > --- > > 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/[email protected] > > 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/[email protected]/ > > > > 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/[email protected] > > --- > > 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
