ditsi 配置
lagvm/LINUX/android/vendor/qcom/proprietary/devicetree/qcom
direwolf-g9ph.dts #include "direwolf-vm-la.dtsi"
direwolf-vm-la.dtsi #include "display/quin-vm-display-la.dtsi"
quin-vm-display-la.dtsi
//对应/sys/class/drm/card0/device/driver的节点
//dtsi节点层级
//soc:
//qcom,sde-cfg:
//qcom,sde-sub-cfg@0:
//qcom,sde_kms_hyp@ae00000
&soc {
sde_cfg: qcom,sde-cfg {
compatible = "qcom,sde-cfg";
qcom,sde-sub-cfg@0 {
reg = <0>;
wfd_kms: qcom,wfd_kms@0 {
compatible = "qcom,wfd-kms";
qcom,client-id = "7815";
};
qcom,sde_kms_hyp@ae00000 {
compatible = "qcom,sde-kms-hyp";
qcom,kms = <&wfd_kms>;
};
};
qcom,sde-sub-cfg@1 {
reg = <1>;
qcom,sde_kms_hyp@ae00000 {
compatible = "qcom,sde-kms-hyp-legacy";
qcom,client-id = "7815";
};
};
};
};
Makfile 配置
# SPDX-License-Identifier: GPL-2.0-only
//单LA
# auto-detect subdirs
ifeq (y, $(findstring y, $(CONFIG_ARCH_SA8155) $(CONFIG_ARCH_SA6155) $(CONFIG_ARCH_SA8195)))
include $(srctree)/techpack/display/config/augen3disp.conf
LINUXINCLUDE += -include $(srctree)/techpack/display/config/augen3dispconf.h
LINUXINCLUDE += -I$(srctree)/techpack/display/include \
-I$(srctree)/techpack/display/include/uapi/display
USERINCLUDE = -I$(srctree)/techpack/display/include/uapi/display
endif
//Q+A 这个CONFIG_QTI_QUIN_GVM宏enable
ifeq (y, $(findstring y, $(CONFIG_QTI_QUIN_GVM)))
include $(srctree)/techpack/display/config/gvmgen3disp.conf
LINUXINCLUDE += -include $(srctree)/techpack/display/config/gvmgen3dispconf.h
endif
//根据config 配置msm-hyp msm-hyp-legacy msm-cfg参与编译
obj-$(CONFIG_DRM_MSM) += msm/
obj-$(CONFIG_DRM_MSM_HYP) += msm-hyp/
obj-$(CONFIG_DRM_MSM_HYP_LEGACY) += msm-hyp-legacy/
obj-$(CONFIG_MSM_SDE_ROTATOR) += rotator/
obj-$(CONFIG_DRM_MSM_CFG) += msm-cfg/
/techpack/display/config/gvmgen3dispconf.h
* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
*/
#define CONFIG_DRM_MSM_HYP 1
#define CONFIG_DRM_MSM_HYP_WFD 1
#define CONFIG_SYNC_FILE 1
#define CONFIG_DRM_MSM_LEASE 1
gvmgen3disp.conf
export CONFIG_DRM_MSM_LEASE=y
export CONFIG_SYNC_FILE=y
export CONFIG_DRM_MSM_HYP_WFD=y
ifeq ($(CONFIG_QGKI), y)
export CONFIG_DRM_MSM_HYP=y
export CONFIG_DRM_MSM_HYP_LEGACY=y
export CONFIG_DRM_MSM_CFG=y
endif
drm设备创建card0 和renderD128
1,前面提到的需要分析的代码中,其实只有红框部分代码有用(msm-cfg&msm-hyp-legacy),绿框中的代码在内核驱动加载的时候只会运行register,而根本不会执行probe函数。
2,绿框中的代码完全不编译也不影响系统运行,这些代码感觉像是历史遗留代码
3,驱动加载时,msm-cfg模块会先加载,然后带起msm-hyp-legacy模块,本质上他们是一个模块,目的是创建android系统需要的drm设备card0 和renderD128,驱动实现中,这两个节点只提供非常有限的文件操作功能,比如open/close,ioctl则几乎不实现。这点在目录下NOTES也说的很明白:
NOTES about msm drm/kms hyp driver:
This driver registers with drm framework for the purpose of creating the
/dev/dri/card0 path, which User Space DRM masters rely on.
Furthermore, per-CRTC VBLANK and PAGE_FLIP events are queued to the device
path to notify User Space components listeners.
No other IOCTL or HW support is provided through this driver.
/*
396 * Platform driver:
397 */
398
399 static int msm_pdev_probe(struct platform_device *pdev)
400 {
401 struct device *dev = &pdev->dev;
402 struct drm_device *ddev;
403 struct msm_drm_private *priv;
404 int ret;
405
406 ddev = drm_dev_alloc(&msm_driver, dev);
407 if (!ddev) {
408 dev_err(dev, "failed to allocate drm_device\n");
409 return -ENOMEM;
410 }
411
412 platform_set_drvdata(pdev, ddev);
413
414 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
415 if (!priv) {
416 ret = -ENOMEM;
417 goto priv_alloc_fail;
418 }
419
420 ddev->dev_private = priv;
421 priv->dev = ddev;
422
423 ret = drm_dev_register(ddev, 0);
424 if (ret) {
425 dev_err(dev, "failed to register drm device\n");
426 goto fail;
427 }
428
429 return 0;
430
431 fail:
432
433 priv_alloc_fail:
434 drm_dev_put(ddev);
435 return ret;
436 }
struct drm_device *drm_dev_alloc(struct drm_driver *driver,
820 struct device *parent)
821 {
822 struct drm_device *dev;
823 int ret;
824
825 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
826 if (!dev)
827 return ERR_PTR(-ENOMEM);
828
829 ret = drm_dev_init(dev, driver, parent);
830 if (ret) {
831 kfree(dev);
832 return ERR_PTR(ret);
833 }
834
835 return dev;
836 }
837 EXPORT_SYMBOL(drm_dev_alloc);
int drm_dev_init(struct drm_device *dev,
632 struct drm_driver *driver,
633 struct device *parent)
634 {
635 int ret;
636
637 if (!drm_core_init_complete) {
638 DRM_ERROR("DRM core is not initialized\n");
639 return -ENODEV;
640 }
641
642 BUG_ON(!parent);
643
644 kref_init(&dev->ref);
645 dev->dev = get_device(parent);
646 dev->driver = driver;
647
648 /* no per-device feature limits by default */
649 dev->driver_features = ~0u;
650
651 drm_legacy_init_members(dev);
652 INIT_LIST_HEAD(&dev->filelist);
653 INIT_LIST_HEAD(&dev->filelist_internal);
654 INIT_LIST_HEAD(&dev->clientlist);
655 INIT_LIST_HEAD(&dev->vblank_event_list);
656
657 spin_lock_init(&dev->event_lock);
658 mutex_init(&dev->struct_mutex);
659 mutex_init(&dev->filelist_mutex);
660 mutex_init(&dev->clientlist_mutex);
661 mutex_init(&dev->master_mutex);
662
663 dev->anon_inode = drm_fs_inode_new();
664 if (IS_ERR(dev->anon_inode)) {
665 ret = PTR_ERR(dev->anon_inode);
666 DRM_ERROR("Cannot allocate anonymous inode: %d\n", ret);
667 goto err_free;
668 }
669
670 if (drm_core_check_feature(dev, DRIVER_RENDER)) {
671 ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
672 if (ret)
673 goto err_minors;
674 }
675 //创建生成card0&render128
676 ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);
677 if (ret)
678 goto err_minors;
679
680 ret = drm_legacy_create_map_hash(dev);
681 if (ret)
682 goto err_minors;
683
684 drm_legacy_ctxbitmap_init(dev);
685
686 if (drm_core_check_feature(dev, DRIVER_GEM)) {
687 ret = drm_gem_init(dev);
688 if (ret) {
689 DRM_ERROR("Cannot initialize graphics execution manager (GEM)\n");
690 goto err_ctxbitmap;
691 }
692 }
693
694 ret = drm_dev_set_unique(dev, dev_name(parent));
695 if (ret)
696 goto err_setunique;
697
698 return 0;
699
700 err_setunique:
701 if (drm_core_check_feature(dev, DRIVER_GEM))
702 drm_gem_destroy(dev);
703 err_ctxbitmap:
704 drm_legacy_ctxbitmap_cleanup(dev);
705 drm_legacy_remove_map_hash(dev);
706 err_minors:
707 drm_minor_free(dev, DRM_MINOR_PRIMARY);
708 drm_minor_free(dev, DRM_MINOR_RENDER);
709 drm_fs_inode_free(dev->anon_inode);
710 err_free:
711 put_device(dev->dev);
712 mutex_destroy(&dev->master_mutex);
713 mutex_destroy(&dev->clientlist_mutex);
714 mutex_destroy(&dev->filelist_mutex);
715 mutex_destroy(&dev->struct_mutex);
716 drm_legacy_destroy_members(dev);
717 return ret;
718 }
719 EXPORT_SYMBOL(drm_dev_init);
112 static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
113 {
114 struct drm_minor *minor;
115 unsigned long flags;
116 int r;
117
118 minor = kzalloc(sizeof(*minor), GFP_KERNEL);
119 if (!minor)
120 return -ENOMEM;
121
122 minor->type = type;
123 minor->dev = dev;
124
125 idr_preload(GFP_KERNEL);
126 spin_lock_irqsave(&drm_minor_lock, flags);
//获取次设备号
127 r = idr_alloc(&drm_minors_idr,
128 NULL,
129 64 * type,
130 64 * (type + 1),
131 GFP_NOWAIT);
132 spin_unlock_irqrestore(&drm_minor_lock, flags);
133 idr_preload_end();
134
135 if (r < 0)
136 goto err_free;
137
138 minor->index = r;
139
140 minor->kdev = drm_sysfs_minor_alloc(minor);
141 if (IS_ERR(minor->kdev)) {
142 r = PTR_ERR(minor->kdev);
143 goto err_index;
144 }
145
146 *drm_minor_get_slot(dev, type) = minor;
147 return 0;
148
149 err_index:
150 spin_lock_irqsave(&drm_minor_lock, flags);
151 idr_remove(&drm_minors_idr, minor->index);
152 spin_unlock_irqrestore(&drm_minor_lock, flags);
153 err_free:
154 kfree(minor);
155 return r;
156 }
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
386 {
387 const char *minor_str;
388 struct device *kdev;
389 int r;
390
391 if (minor->type == DRM_MINOR_RENDER)
392 minor_str = "renderD%d";
393 else
394 minor_str = "card%d";
395
396 kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
397 if (!kdev)
398 return ERR_PTR(-ENOMEM);
399
400 device_initialize(kdev);
401 kdev->devt = MKDEV(DRM_MAJOR, minor->index);
402 kdev->class = drm_class;
403 kdev->type = &drm_sysfs_device_minor;
404 kdev->parent = minor->dev->dev;
405 kdev->release = drm_sysfs_release;
406 dev_set_drvdata(kdev, minor);
407 //根据次设备号set 设备名
408 r = dev_set_name(kdev, minor_str, minor->index);
409 if (r < 0)
410 goto err_free;
411
412 return kdev;
413
414 err_free:
415 put_device(kdev);
416 return ERR_PTR(r);
417 }
创建dbuggfs 节点
根据DRM_MINOR_PRIMARY DRM_MINOR_PRIMARY
使用次设备号创建card0 和renderD128 debug节点
使用命令mount debugfs 后可以看到debug 节点
mount -t debugfs none /sys/kernel/debug/
/**
941 * drm_dev_register - Register DRM device
942 * @dev: Device to register
943 * @flags: Flags passed to the driver's .load() function
944 *
945 * Register the DRM device @dev with the system, advertise device to user-space
946 * and start normal device operation. @dev must be initialized via drm_dev_init()
947 * previously.
948 *
949 * Never call this twice on any device!
950 *
951 * NOTE: To ensure backward compatibility with existing drivers method this
952 * function calls the &drm_driver.load method after registering the device
953 * nodes, creating race conditions. Usage of the &drm_driver.load methods is
954 * therefore deprecated, drivers must perform all initialization before calling
955 * drm_dev_register().
956 *
957 * RETURNS:
958 * 0 on success, negative error code on failure.
959 */
960 int drm_dev_register(struct drm_device *dev, unsigned long flags)
961 {
962 struct drm_driver *driver = dev->driver;
963 int ret;
964
965 mutex_lock(&drm_global_mutex);
966
967 ret = drm_minor_register(dev, DRM_MINOR_RENDER);
968 if (ret)
969 goto err_minors;
970
971 ret = drm_minor_register(dev, DRM_MINOR_PRIMARY);
972 if (ret)
973 goto err_minors;
974
975 ret = create_compat_control_link(dev);
976 if (ret)
977 goto err_minors;
978
979 dev->registered = true;
980
981 if (dev->driver->load) {
982 ret = dev->driver->load(dev, flags);
983 if (ret)
984 goto err_minors;
985 }
986
987 if (drm_core_check_feature(dev, DRIVER_MODESET))
988 drm_modeset_register_all(dev);
989
990 ret = 0;
991
992 DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
993 driver->name, driver->major, driver->minor,
994 driver->patchlevel, driver->date,
995 dev->dev ? dev_name(dev->dev) : "virtual device",
996 dev->primary->index);
997
998 goto out_unlock;
999
1000 err_minors:
1001 remove_compat_control_link(dev);
1002 drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
1003 drm_minor_unregister(dev, DRM_MINOR_RENDER);
1004 out_unlock:
1005 mutex_unlock(&drm_global_mutex);
1006 return ret;
1007 }
1008 EXPORT_SYMBOL(drm_dev_register);
static int drm_minor_register(struct drm_device *dev, unsigned int type)179 {
180 struct drm_minor *minor;
181 unsigned long flags;
182 int ret;
183
184 DRM_DEBUG("\n");
185
186 minor = *drm_minor_get_slot(dev, type);
187 if (!minor)
188 return 0;
189
190 ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
191 if (ret) {
192 DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
193 goto err_debugfs;
194 }
195
196 ret = device_add(minor->kdev);
197 if (ret)
198 goto err_debugfs;
199
200 /* replace NULL with @minor so lookups will succeed from now on */201 spin_lock_irqsave(&drm_minor_lock, flags);
202 idr_replace(&drm_minors_idr, minor, minor->index);
203 spin_unlock_irqrestore(&drm_minor_lock, flags);
204
205 DRM_DEBUG("new minor registered %d\n", minor->index);
206 return 0;
207
208 err_debugfs:
209 drm_debugfs_cleanup(minor);
210 return ret;
211 }
【1】参考连接 https://blog.csdn.net/kill150/article/details/131323757https://blog.csdn.net/kill150/article/details/131323757