linux display子系统流程分析

本文详细分析了Linux Display软件框架,从/dev/fb、/dev/dri/card等设备生成,DTS中的ARM HDLCD与HDMI配置,到ARM HDLCD控制器与HDMI芯片TD998X的连接,以及I2C初始化过程。探讨了帧数据如何通过FB、CRTC、Encoder、Connector,经HDMI到达显示器,并讨论了DRM框架取代传统Framebuffer的原因及其优势。涉及的关键结构包括struct drm_device、struct drm_framebuffer等,并介绍了关键函数如hdlcd_drm_bind、tda998x探测和初始化流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

linux display软件总体框图

对于linux diplay软件框架的分析,我认为,应该带着如下几个疑问去阅读代码:

  1. /dev/fb, /dev/dri/card, dev/dri/controlD, dev/dri/renderD这些设备是如何生成的?
  2. DTS中定义的有关ARM HDLCD与HDMI的信息,在内核代码中是如何被使用到的?
  3. /dev/fb设备与ARM HDLCD控制器硬件是如何关联的?
  4. ARM HDLCD控制器是如何与HDMI芯片TD998X关联起来?
  5. HDMI芯片是如何通过I2C初始化的?
  6. 一帧YUV转换后得到的RGB数据,是如何通过fb到达crtc,再到encoder, connector,最后,通过HDMI线到达显示器,并且在显示器上面显示出来的?
  7. 为什么DRM框架会取代以往内核中非常普遍使用的Frame Buffer这种框架的?DRM到底有什么好处?
  8. DRM框架中用到了component机制,这个机制是干什么用的?
  9. DRM框架中KMS、GEM这些概念又是干什么用的?
  10. DRM框架是如何对GPU硬件进行支持的?

需要重点理解的核心数据结构

struct drm_device

struct drm_driver

struct drm_master

struct drm_framebuffer

struct drm_plane

struct drm_crtc

​​​​​​​struct drm_encoder

const struct drm_encoder_funcs *funcs;

const struct drm_encoder_helper_funcs *helper_private;

 xxx_helper_funcs里面通常是一些比较common的函数,而xxx_funs通常是一些与特定硬件相关的函数,因此,xxx_heler_funcs可能会调用xxx_funcs中的函数

​​​​​​​struct drm_connector

static const struct drm_connector_helper_funcs  tda998x_connector_helper_funcs = {

               .get_modes = tda998x_connector_get_modes,

               .best_encoder = tda998x_connector_best_encoder,

};

static const struct drm_connector_funcs tda998x_connector_funcs = {

               .reset = drm_atomic_helper_connector_reset,

               .fill_modes = drm_helper_probe_single_connector_modes,

               .detect = tda998x_connector_detect//检测是否HDMI插入,读取寄存器cec_read(priv, REG_CEC_RXSHPDLEV) bit1是否为1

               .destroy = tda998x_connector_destroy,

               .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,

               .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,

};

​​​​​​​struct drm_client_funcs

static const struct drm_client_funcs drm_fbdev_client_funcs = {

               .owner                 = THIS_MODULE,

               .unregister          = drm_fbdev_client_unregister,

               .restore = drm_fbdev_client_restore,

               .hotplug               = drm_fbdev_client_hotplug,

};

hdlcd_drm_bind

               -> drm_fbdev_generic_setup(drm, 32)

                              -> drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs)

                              -> drm_fbdev_client_hotplug(&fb_helper->client)

                                             -> drm_fb_helper_init(dev, fb_helper, 0)

                                                            -> dev->fb_helper = helper

                                             -> drm_fb_helper_initial_config(fb_helper, fb_helper->preferred_bpp)

                                                            -> __drm_fb_helper_initial_config_and_unlock(fb_helper, bpp_sel)  //启动时,第一次初始化

                                                                           ->drm_client_modeset_probe(&fb_helper->client, width, height)  //这里读取EDID

                                                                           -> drm_fb_helper_single_fb_probe(fb_helper, bpp_sel)

​​​​​​​​​​​​​​struct drm_fb_helper_funcs

static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {

               .fb_probe = drm_fbdev_cma_create,

};

display相关的dts定义

hdlcd_0

hdlcd@7ff50000 {

                              compatible = "arm,hdlcd";

                              reg = <0 0x7ff50000 0 0x1000>;

                              interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;

                              clocks = <&scmi_clk 3>;

                              clock-names = "pxlclk";

                              port {

                                             hdlcd1_output: hdlcd1-endpoint {

                                                            remote-endpoint = <&tda998x_1_input>;

                                             };

                              };

               };

​​​​​​​hdlcd_1

hdlcd@7ff60000 {

                              compatible = "arm,hdlcd";

                              reg = <0 0x7ff60000 0 0x1000>;

                              interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;

                              clocks = <&scmi_clk 3>;

                              clock-names = "pxlclk";

                              port {

                                             hdlcd0_output: hdlcd0-endpoint {

                                                            remote-endpoint = <&tda998x_0_input>;

                                             };

                              };

               };

​​​​​​​tda998(hdmi0和hdmi1)

i2c@7ffa0000 {

                              compatible = "snps,designware-i2c";

                              reg = <0x0 0x7ffa0000 0x0 0x1000>;  //I2C控制器基地址

                              #address-cells = <1>;

                              #size-cells = <0>;

                              interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;

                              clock-frequency = <400000>;  //i2c速率400K

                              i2c-sda-hold-time-ns = <500>;

                              clocks = <&soc_smc50mhz>;

hdmi_transmitter0: hdmi-transmitter@70 {

                                             compatible = "nxp,tda998x";

                                             reg = <0x70>;  //I2C从设备地址

                                             #sound-dai-cells = <1>;

                                             audio-ports = <TDA998x_I2S 0x03

                                                                           TDA998x_SPDIF 0x04>;

                                             port {

                                                            tda998x_0_input: tda998x-0-endpoint {

                                                                           remote-endpoint = <&hdlcd0_output>; 

                                                            };

                                             };

                              };

hdmi_transmitter1: hdmi-transmitter@71 {

                                             compatible = "nxp,tda998x";

                                             reg = <0x71>;  //I2C从设备地址

                                             port {

                                                            tda998x_1_input: tda998x-1-endpoint {

                                                                           remote-endpoint = <&hdlcd1_output>;

                                                            };

                                             };

                              };

               };

arm hdlcd驱动分析

ARM HDLCD是在多个ARM开发平台上用到的显示控制器,由 ARM Ltd 提供。

HDLCD从帧缓冲区读取RGB数据并将其发送到数字编码器(DVI HDMI)。

​​​​​​​hdlcd控制器硬件说明

如下是juno文档中对HDLCD控制器的描述:

​​​​​​​hdlcd控制器寄存器定义

//drivers/gpu/drm/arm/hdlcd_regs.h

/* register offsets */

#define HDLCD_REG_VERSION                  0x0000  /* ro */

#define HDLCD_REG_INT_RAWSTAT                       0x0010  /* rw */

#define HDLCD_REG_INT_CLEAR                              0x0014  /* wo */

#define HDLCD_REG_INT_MASK                0x0018  /* rw */

#define HDLCD_REG_INT_STATUS                           0x001c  /* ro */

#define HDLCD_REG_FB_BASE                  0x0100  /* rw */

#define HDLCD_REG_FB_LINE_LENGTH   0x0104  /* rw */

#define HDLCD_REG_FB_LINE_COUNT                   0x0108  /* rw */

#define HDLCD_REG_FB_LINE_PITCH                      0x010c  /* rw */

#define HDLCD_REG_BUS_OPTIONS                        0x0110  /* rw */

#define HDLCD_REG_V_SYNC                     0x0200  /* rw */

#define HDLCD_REG_V_BACK_PORCH                    0x0204  /* rw */

#define HDLCD_REG_V_DATA                    0x0208  /* rw */

#define HDLCD_REG_V_FRONT_PORCH                 0x020c  /* rw */

#define HDLCD_REG_H_SYNC                    0x0210  /* rw */

#define HDLCD_REG_H_BACK_PORCH                    0x0214  /* rw */

#define HDLCD_REG_H_DATA                    0x0218  /* rw */

#define HDLCD_REG_H_FRONT_PORCH                 0x021c  /* rw */

#define HDLCD_REG_POLARITIES                             0x0220  /* rw */

#define HDLCD_REG_COMMAND                             0x0230  /* rw */

#define HDLCD_REG_PIXEL_FORMAT                      0x0240  /* rw */

#define HDLCD_REG_RED_SELECT                           0x0244  /* rw */

#define HDLCD_REG_GREEN_SELECT                      0x0248  /* rw */

#define HDLCD_REG_BLUE_SELECT                         0x024c  /* rw */

/* version */

#define HDLCD_PRODUCT_ID                    0x1CDC0000

#define HDLCD_PRODUCT_MASK                             0xFFFF0000

#define HDLCD_VERSION_MAJOR_MASK               0x0000FF00

#define HDLCD_VERSION_MINOR_MASK               0x000000FF

​​​​​​​hdlcd_probe

drivers/gpu/drm/arm/hdlcd_drv.c

static struct platform_driver  hdlcd_platform_driver = {

               .probe                  = hdlcd_probe,

               .remove               = hdlcd_remove,

               .driver   = {

                              .name = "hdlcd",

                              .pm = &hdlcd_pm_ops,

                              .of_match_table               = hdlcd_of_match,

               },

};

static const struct of_device_id  hdlcd_of_match[] = {

               { .compatible      = "arm,hdlcd" },

               {},

};

hdlcd_probe

               ->of_graph_get_next_endpoint(pdev->dev.of_node, NULL)

                              ->port = of_get_child_by_name(parent, "port")   //查找port结点

                              ->endpoint = of_get_next_child(port, prev) //查找port中的endpoint结点

               ->port = of_graph_get_remote_port_parent(ep)

                              ->np = of_parse_phandle(node, "remote-endpoint", 0)  //解析得到"remote-endpoint"属性值:tda998x_1_input

               ->component_match_add(&pdev->dev, &match, compare_dev, port)

                              ->component_match_add_release(master, matchptr, NULL, compare, compare_data)

                                             -> match = devres_alloc(devm_component_match_release, sizeof(*match), GFP_KERNEL)

                                             -> match->compare[match->num].compare = compare

               ->component_master_add_with_match(&pdev->dev, &hdlcd_master_ops, match)  //hdlcd_master_ops定义在下面,里面有bind()接口

                              -> try_to_bring_up_master(master, NULL)

compare_dev定义如下:

static int compare_dev(struct device *dev, void *data)

{

               return dev->of_node == data;

}

hdlcd_master_ops定义在下面,里面有bind()接口

static const struct component_master_ops hdlcd_master_ops = {

               .bind                     = hdlcd_drm_bind,

               .unbind                 = hdlcd_drm_unbind,

};

​​​​​​​hdlcd_drm_bind

static const struct  component_master_ops    hdlcd_master_ops = {

               .bind                    = hdlcd_drm_bind,

               .unbind                 = hdlcd_drm_unbind,

};

hdlcd_drm_bind

               ->drm_dev_alloc(&hdlcd_driver, dev)  // hdlcd_driver定义如下

               ->hdlcd_setup_mode_config(drm);

                              ->drm->mode_config.funcs = &hdlcd_mode_config_funcs  //定义在下面

               ->hdlcd_load(drm, 0);

                              ->hdlcd->mmio = devm_ioremap_resource(drm->dev, res)

                              ->version = hdlcd_read(hdlcd, HDLCD_REG_VERSION)  //hdlcd version寄存器

                              ->of_reserved_mem_device_init(drm->dev)

                              ->hdlcd_setup_crtc(drm)

                                             ->hdlcd_plane_init(drm)

                                                            ->drm_plane_helper_add(plane, &hdlcd_plane_helper_funcs) // 里面有一个atomic_update()接口,会配置hdlcdFB BASE寄存器

                                                                           -> hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start)

                                             -> drm_crtc_init_with_planes(drm, &hdlcd->crtc, primary, NULL, &hdlcd_crtc_funcs, NULL)

                                             ->drm_crtc_helper_add(&hdlcd->crtc, &hdlcd_crtc_helper_funcs)

                              ->drm_irq_install(drm, platform_get_irq(pdev, 0))

                                             ->request_irq(irq, dev->driver->irq_handler, sh_flags, dev->driver->name, dev)

->drm_dev_register(drm, 0);  //注册drm字符设备

               ->drm_minor_register(dev, DRM_MINOR_CONTROL);

->drm_minor_register(dev, DRM_MINOR_RENDER);

               ->drm_minor_register(dev, DRM_MINOR_PRIMARY);

               ->dev->driver->load(dev, flags)  // hdlcd_driver中没有定义load()接口,所以这里为空

               ->drm_modeset_register_all(dev)

                               ->drm_plane_register_all(dev); //调用各自的 late_register()接口

                               ->drm_crtc_register_all(dev);

                               ->drm_encoder_register_all(dev);  //遍历dev->mode_config.encoder_list

<think>好的,我需要帮助用户了解如何在Windows系统中安装Kali Linux子系统。首先,我应该回忆一下相关的步骤,确保信息准确。记得WSL(Windows Subsystem for Linux)是必须的,所以需要先启用这个功能。 接下来,用户可能对如何启用WSL不太清楚,应该分步骤说明。可能有两种方法:使用PowerShell命令或者通过控制面板的图形界面。需要确认当前Windows版本是否支持WSL 2,因为Kali可能推荐使用更新的版本。 然后,安装Kali Linux子系统的时候,用户可能不知道具体在Microsoft Store里搜索什么,需要给出正确的名称,比如“Kali Linux”并提示如何安装。安装完成后,初始化设置包括创建用户账户和密码,这部分需要详细说明。 另外,考虑到用户可能想使用图形界面,可能需要提到安装桌面环境的方法,比如Xfce4,以及如何配置X Server。不过这部分可能属于高级内容,用户如果不需要图形界面可以跳过。 还要注意是否需要更新系统和安装工具,比如运行sudo apt update && sudo apt upgrade -y,以及安装kali-linux-default这样的元数据包来获取常用工具。如果用户只是想基本使用,可能不需要全部工具,但建议至少更新系统。 可能遇到的常见问题包括WSL未正确启用、商店无法访问或者安装后启动失败。这时候需要提供一些排查步骤,比如检查系统版本、重启计算机或者手动下载安装包。 最后,整理步骤时要条理清晰,使用列表形式让用户容易跟随。同时,避免使用专业术语过多,保持语言简洁明了。确保所有命令准确无误,特别是PowerShell命令,可能需要管理员权限。提醒用户注意命令中的空格和大小写,避免出错。 总结一下,安装过程大致分为启用WSL、安装Kali Linux子系统、初始设置、可选图形界面和工具安装。每个步骤需要详细但简洁的说明,确保用户能一步步操作成功。如果有必要,可以补充常见问题解决方法,帮助用户应对可能出现的困难。</think>在Windows系统中安装Kali Linux子系统(WSL)完整步骤如下: --- ### 一、启用WSL功能 1. **以管理员身份打开PowerShell** - 右键开始菜单 → 选择 **Windows PowerShell (管理员)** 2. **执行命令启用WSL**: ```powershell wsl --install ``` > 注:如果提示命令无效,可手动分步执行: > ```powershell > dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart > dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart > ``` 3. **重启电脑** --- ### 二、设置WSL 2为默认版本 1. **下载并安装WSL 2内核更新包**: - 官方下载地址:[https://aka.ms/wsl2kernel](https://aka.ms/wsl2kernel) 2. **设置默认版本**: ```powershell wsl --set-default-version 2 ``` --- ### 三、安装Kali Linux子系统 1. **通过Microsoft Store安装**: - 打开Microsoft Store → 搜索 **Kali Linux** → 点击 **获取** - 安装完成后,从开始菜单启动Kali Linux 2. **命令行安装(备用方法)**: ```powershell wsl --install -d kali-linux ``` --- ### 四、初始化Kali Linux 1. **首次启动时等待解压完成** 2. **创建用户账户**: - 输入新用户名(建议小写字母) - 设置密码(输入时不会显示字符) --- ### 五、更新系统及工具 ```bash sudo apt update && sudo apt upgrade -y sudo apt install kali-linux-default # 安装基础渗透测试工具包 ``` --- ### 六、高级配置(可选) 1. **图形界面支持**: - 安装Xfce4桌面: ```bash sudo apt install kali-desktop-xfce -y ``` - 安装[Xming](https://sourceforge.net/projects/xming/)或[VcXsrv](https://sourceforge.net/projects/vcxsrv/)作为X Server 2. **启动图形界面**: ```bash export DISPLAY=:0 startxfce4 ``` --- ### 常见问题解决 1. **WSL 2未生效**: ```powershell wsl -l -v # 查看子系统版本 wsl --set-version kali-linux 2 # 手动升级到WSL 2 ``` 2. **网络连接问题**: ```bash echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf ``` 3. **文件系统交互**: - 通过`\\wsl$\kali-linux`路径直接访问子系统文件 --- ### 优势对比 | 特性 | WSL Kali | 虚拟机安装 | |-------------------|---------------------------|-------------------------| | 性能 | 接近原生速度 | 有性能损耗 | | 资源占用 | 低内存占用 | 需要分配固定内存 | | 系统集成 | 直接访问Windows文件 | 需配置共享文件夹 | | 硬件支持 | 直接使用主机硬件 | 虚拟化层隔离 | > 提示:WSL适合日常学习和轻度渗透测试,如需完整硬件控制(如无线网卡监控模式),建议使用物理机安装或USB设备直通虚拟机。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值