]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/msm: enable separate binding of GPU and display devices
authorDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Sat, 5 Jul 2025 10:02:35 +0000 (13:02 +0300)
committerRob Clark <robin.clark@oss.qualcomm.com>
Sat, 5 Jul 2025 14:37:21 +0000 (07:37 -0700)
There are cases when we want to have separate DRM devices for GPU and
display pipelines.
One example is development, when it is beneficial to be able to bind the
GPU driver separately, without the display pipeline (and without the
hacks adding "amd,imageon" to the compatible string).
Another example is some of Qualcomm platforms, which have two MDSS
units, but only one GPU. With current approach it is next to impossible
to support this usecase properly, while separate binding allows users to
have three DRM devices: two for MDSS units and a single headless GPU.

Add kernel param msm.separate_gpu_kms, which if set to true forces
creation of separate display and GPU DRM devices. Mesa supports this
setup by using the kmsro wrapper.

The param is disabled by default, in order to be able to test userspace
for the compatibility issues. Simple clients are able to handle this
setup automatically.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Patchwork: https://patchwork.freedesktop.org/patch/662590/
[Rob: renamed the modparam to separate_gpu_kms, and add missing
      DRIVER_GEM_GPUVA]
Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
drivers/gpu/drm/msm/adreno/adreno_device.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h

index 99c8d2f4e4b49fda912fa49429399cf207eccead..50945bfe9b4992118f23db3cd17ac348be9f9c9d 100644 (file)
@@ -262,7 +262,8 @@ 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"))
+       if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon") ||
+           msm_gpu_no_components())
                return msm_gpu_probe(pdev, &a3xx_ops);
 
        return component_add(&pdev->dev, &a3xx_ops);
index 0ab005a7d5e99e46fe47c9e64514434416898d20..b6efc5b9933be4d7caffe70c6779ee11e9d57c82 100644 (file)
@@ -54,9 +54,18 @@ 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);
+
 DECLARE_FAULT_ATTR(fail_gem_alloc);
 DECLARE_FAULT_ATTR(fail_gem_iova);
 
+bool msm_gpu_no_components(void)
+{
+       return separate_gpu_kms;
+}
+
 static int msm_drm_uninit(struct device *dev, const struct component_ops *gpu_ops)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -836,8 +845,33 @@ static const struct drm_driver msm_driver = {
        .patchlevel         = MSM_VERSION_PATCHLEVEL,
 };
 
+static const struct drm_driver msm_kms_driver = {
+       .driver_features    = DRIVER_GEM |
+                               DRIVER_ATOMIC |
+                               DRIVER_MODESET,
+       .open               = msm_open,
+       .postclose          = msm_postclose,
+       .dumb_create        = msm_gem_dumb_create,
+       .dumb_map_offset    = msm_gem_dumb_map_offset,
+       .gem_prime_import_sg_table = msm_gem_prime_import_sg_table,
+#ifdef CONFIG_DEBUG_FS
+       .debugfs_init       = msm_debugfs_init,
+#endif
+       MSM_FBDEV_DRIVER_OPS,
+       .show_fdinfo        = msm_show_fdinfo,
+       .ioctls             = msm_ioctls,
+       .num_ioctls         = ARRAY_SIZE(msm_ioctls),
+       .fops               = &fops,
+       .name               = "msm-kms",
+       .desc               = "MSM Snapdragon DRM",
+       .major              = MSM_VERSION_MAJOR,
+       .minor              = MSM_VERSION_MINOR,
+       .patchlevel         = MSM_VERSION_PATCHLEVEL,
+};
+
 static const struct drm_driver msm_gpu_driver = {
        .driver_features    = DRIVER_GEM |
+                               DRIVER_GEM_GPUVA |
                                DRIVER_RENDER |
                                DRIVER_SYNCOBJ_TIMELINE |
                                DRIVER_SYNCOBJ,
@@ -982,7 +1016,11 @@ static int add_gpu_components(struct device *dev,
 
 static int msm_drm_bind(struct device *dev)
 {
-       return msm_drm_init(dev, &msm_driver, NULL);
+       return msm_drm_init(dev,
+                           msm_gpu_no_components() ?
+                                   &msm_kms_driver :
+                                   &msm_driver,
+                           NULL);
 }
 
 static void msm_drm_unbind(struct device *dev)
@@ -1018,9 +1056,11 @@ int msm_drv_probe(struct device *master_dev,
                        return ret;
        }
 
-       ret = add_gpu_components(master_dev, &match);
-       if (ret)
-               return ret;
+       if (!msm_gpu_no_components()) {
+               ret = add_gpu_components(master_dev, &match);
+               if (ret)
+                       return ret;
+       }
 
        /* on all devices that I am aware of, iommu's which can map
         * any address the cpu can see are used:
index e3dfaa156307dcd8bb675f865985a0888be8fb87..9875ca62e9adb12dca9bcc74e2825b0364372a54 100644 (file)
@@ -554,4 +554,6 @@ 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);
+
 #endif /* __MSM_DRV_H__ */