hypervisor display显卡节点card0生成过程

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/displayUSERINCLUDE = -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/131323757icon-default.png?t=N7T8https://blog.csdn.net/kill150/article/details/131323757

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/231066.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐几款值得收藏的3DMAX插件

推荐几款值得收藏的3DMAX插件 StairGenerator StairGenerator一键楼梯插件&#xff0c;不需要花费太多的时间&#xff0c;轻松从2D平面图生成3D楼梯模型&#xff0c;生成的楼梯模型细节丰富真实。 【主要功能】 1.简单&#xff1a;轻松实现2D到3D建模。 2.具有最详细三维结…

高级桌面编程(一)

前言 学习心得&#xff1a;C# 入门经典第8版书中的第15章《高级桌面编程》 创建控件并设置样式 1 样式 Style WPF 当中我们可以对每一个控件进行完全的自定义。我们可以随意更改控件外观和功能。提供我们能完成这样的效果与控件的样式&#xff08;Style&#xff09;有着不可分…

人工智能革命:共同探索AIGC时代的未来

一、引言 随着大数据和强大的计算能力的兴起&#xff0c;人工智能技术&#xff08;AI&#xff09;正在快速发展&#xff0c;并为各个领域带来革命性的变化。人工智能与智能计算技术&#xff08;AIGC&#xff09;的融合不仅为企业、科研机构和普通用户提供了巨大的机遇&#xff…

60.Sentinel源码分析

Sentinel源码分析 1.Sentinel的基本概念 Sentinel实现限流、隔离、降级、熔断等功能&#xff0c;本质要做的就是两件事情&#xff1a; 统计数据&#xff1a;统计某个资源的访问数据&#xff08;QPS、RT等信息&#xff09; 规则判断&#xff1a;判断限流规则、隔离规则、降级规…

数字孪生Web3D智慧机房可视化运维云平台建设方案

前言 进入信息化时代&#xff0c;数字经济发展如火如荼&#xff0c;数据中心作为全行业数智化转型的智慧基座&#xff0c;重要性日益凸显。与此同时&#xff0c;随着东数西算工程落地和新型算力网络体系构建&#xff0c;数据中心建设规模和业务总量不断增长&#xff0c;机房管理…

Xcode 15 Assertion failed: (false “compact unwind compressed function offset doesn‘t fit in 24

xcode 真机运行报错&#xff1a;Assertion failed: (false && "compact unwind compressed function offset doesnt fit in 24 bits"), function operator(), file Layout.cpp, line 5758 如下图&#xff1a; 解决办法&#xff1a; 在 targets-->Build …

力扣---最长回文子串(动态规划)

目录 ​编辑 题目 思路步骤&#xff1a; 代码 我的其他博客 题目 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&…

【C++】标准库中的string类

目录 一、介绍 二、常用接口 1.构造函数和赋值操作 2.string类对象的容量操作 3.string类对象的访问及遍历操作 4.string类对象的修改操作 5.string类非成员函数 放在最后 一、介绍 在C中&#xff0c;std::string 是标准库提供的字符串类。它属于 <string> 头文件…

ROS机器人入门

http://www.autolabor.com.cn/book/ROSTutorials/ 1、ROS简介 ROS 是一个适用于机器人的开源的元操作系统。其实它并不是一个真正的操作系统&#xff0c;其 底层的任务调度、编译、寻址等任务还是由 Linux 操作系统完成&#xff0c;也就是说 ROS 实际上是运 行在 Linux 上的次级…

MySQL主从复制详解

目录 1. 主从复制的工作原理 1.1. 主从复制的角色 1.2. 主从复制的流程 2. 配置MySQL主从复制 2.1. 确保主服务器开启二进制日志 2.2. 设置从服务器 2.3. 连接主从服务器 2.4. 启动复制 3. 主从复制的优化与注意事项 3.1. 优化复制性能 3.2. 注意复制延迟 3.3. 处理…

买显卡别再只看N、A两家了,这些高性价比I卡也很香

谈起独立显卡&#xff0c;相信不少朋友都会第一时间想起NVIDIA与AMD这两家巨头。然而&#xff0c;除了这两家巨头以外&#xff0c;凭借集显占据全球最高显卡市场份额的英特尔在2021年正式入局了独显市场&#xff0c;并在去年9月的时候公布了Arc A系列显卡阵容&#xff0c;型号从…

算法——动态规划(DP,Dynamic Programming)

一、基础概念 DP的思想&#xff1a; 把问题分成子问题&#xff0c;前面子问题的解决结果被后面的子问题使用DP与分治法的区别&#xff1a; 分治法把问题分成独立的子问题&#xff0c;各个子问题能独立解决 自顶向下DP前面子问题的解决结果被后面的子问题使用&#xff0c;子问题…

【基于APB总线的DES实现】

基于APB总线的DES实现 本文内容摘要APB介绍仿真结果整体仿真写入数据DES加密部分DES加密读出密文 整体代码 本文内容摘要 本文是设计一个可兼容APB总线的DES加密协处理器&#xff0c;用来将DES加密模块与APB总线进行对接&#xff0c;使总线发送来的数据可以正常写入并进行加密后…

Autosar DEM DTC的Debounce策略

文章目录 简介Debounce策略1、基于计数器的 Debounce 策略2、基于时间的Debounce策略 简介 故障事件防抖&#xff0c;与按键防抖&#xff08;软件需要延时确认按键不是误触发&#xff09;的作用类似&#xff0c;目的是为了防止事件误触发采取的策略。 因为DTC并不是一达到触发…

产品调研——AI平台

本文主要记录了对腾讯云-TIONE平台、华为云-ModelArt等主流AI平台的产品调研。 交互式建模 简单点说就是提供了带训练资源的云IDE&#xff0c;使用形态包括Notebook、VsCode等。 腾讯云-TI平台 TI平台将tensorflow、pytorch、spark环境等均集成到一个Notebook容器中&#xf…

Android 一分钟使用RecyclerView完美实现瀑布

【免费】安卓RecyclerView瀑布流效果实现资源-CSDN文库 1.WaterfallFlowActivity 主函数代码&#xff1a; package com.example.mytestapplication;import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.widget.Toast;im…

Git总结 | Git面试都问些啥?

什么是Git为什么要用Git等等这些相信看到该标题点进来的同学也不希望浪费时间再看一遍&#xff0c;那么直接进入主题&#xff0c;对于日常工作中常用的Git相关操作进行整理&#xff0c;一起看看吧 面试官&#xff1a;你常用的Git操作是什么? 候选人&#xff1a;git clone 面试…

59. 螺旋矩阵 II(java实现,史上最详细教程,想学会的进!!!)

今天来分享一下螺旋矩阵的解题思路及代码的实现。 题目描述如下&#xff1a; 首先拿到这道题&#xff0c;首先不要慌张&#xff0c;我们来仔细分析一下会发现并没有那么难。 首先看下边界的元素是1、2、3递增的&#xff0c;那么我们也许可以根据这一点先把边界的元素一个一个给…

【Proteus仿真】【51单片机】视力保护仪

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使LCD1602液晶&#xff0c;按键、HC-SR04超声波、PCF8591 ADC、光敏传感器、蜂鸣器、LED等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示…

【vtkWidgetRepresentation】第十四期 二维标注

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享vtk中的二维标注,主要用于医学领域,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 目录 前言 1. vtkBiDimension…