VGA 切换

vga_switcheroo 是 Linux 子系统,用于笔记本电脑的混合图形。它们有两种类型

  • 复用型:双 GPU,带有一个多路复用器芯片,用于在 GPU 之间切换输出。

  • 无复用型:双 GPU,但只有一个连接到输出。另一个仅用于卸载渲染,其结果通过 PCIe 复制到帧缓冲。在 Linux 上,这通过 DRI PRIME 支持。

混合图形在 2000 年代后期开始出现,最初都是复用型的。较新的笔记本电脑出于成本原因转向了无复用架构。一个值得注意的例外是 MacBook Pro,它继续使用多路复用器。多路复用器具有不同的功能:一些仅切换面板,另一些还可以切换外部显示器。一些同时切换所有显示引脚,而另一些则只能切换 DDC 线。(允许探测非活动 GPU 的 EDID。)此外,多路复用器通常用于在未使用独立 GPU 时切断其电源。

DRM 驱动程序使用 vga_switcheroo 注册 GPU,这些 GPU 此后被称为客户端。多路复用器称为处理程序。无复用机器还会注册一个处理程序来控制独立 GPU 的电源状态,出于显而易见的原因,其 ->switchto 回调是一个空操作。独立 GPU 通常配备用于 HDMI/DP 音频信号的 HDA 控制器,它也会注册为客户端,以便 vga_switcheroo 可以在更改独立 GPU 的电源状态时处理正确的挂起/恢复顺序。因此,总共最多可以有三个客户端:两个 VGA 客户端(GPU)和一个音频客户端(在独立 GPU 上)。代码主要准备好支持具有两个以上 GPU 的机器,如果它们可用的话。

当前切换到输出的 GPU 在 vga_switcheroo 术语中称为活动客户端。未使用的 GPU 是非活动客户端。当加载非活动客户端的 DRM 驱动程序时,它将无法探测面板的 EDID,因此依赖于 VBIOS 来提供其显示模式。如果 VBIOS 模式是虚假的,或者根本没有 VBIOS(这在 MacBook Pro 上很常见),则客户端可以选择请求将 DDC 线临时切换到它,前提是处理程序支持此功能。仅切换 DDC 线而不切换整个输出可以避免不必要的闪烁。

使用模式

手动切换和手动电源控制

在这种使用模式下,可以读取文件 /sys/kernel/debug/vgaswitcheroo/switch 来检索当前的 vga_switcheroo 状态,并且可以向其中写入命令来更改状态。一旦两个 GPU 驱动程序和一个处理程序在 vga_switcheroo 中注册,该文件就会出现。以下命令被理解

  • OFF:关闭未使用的设备的电源。

  • ON:打开未使用的设备的电源。

  • IGD:切换到集成图形设备。如果需要,打开集成 GPU 的电源,关闭独立 GPU 的电源。前提是用户空间进程(例如 Xorg、alsactl)没有打开 GPU 或音频客户端的设备文件。如果切换失败,用户可以在 /dev/dri/ 和 /dev/snd/controlC1 上调用 lsof(8) 或 fuser(1) 来识别阻止切换的进程。

  • DIS:切换到独立图形设备。

  • DIGD:延迟切换到集成图形设备。一旦最后一个用户空间进程关闭了 GPU 和音频客户端的设备文件,就会执行此切换。

  • DDIS:延迟切换到独立图形设备。

  • MIGD:仅多路复用切换到集成图形设备。不重新映射控制台或更改任何一个 GPU 的电源状态。如果集成 GPU 当前处于关闭状态,屏幕将变为黑色。如果它处于打开状态,屏幕将显示 VRAM 中碰巧存在的内容。无论哪种方式,用户都必须盲目地输入命令才能切换回来。

  • MDIS:仅多路复用切换到独立图形设备。

对于电源状态由驱动程序的运行时 pm 控制的 GPU,ON 和 OFF 命令是空操作(请参阅下一节)。

对于无复用机器,不应使用 IGD/DIS、DIGD/DDIS 和 MIGD/MDIS 命令。

驱动程序电源控制

在这种使用模式下,独立 GPU 会自动根据驱动程序的运行时 pm 的决定来打开和关闭电源。在复用机器上,用户仍然可以通过 debugfs 接口影响多路复用器状态,但是 ON 和 OFF 命令对于独立 GPU 来说是空操作。

这种模式是 Nvidia HybridPower/Optimus 和 ATI PowerXpress 上的默认模式。在内核命令行上指定 nouveau.runpm=0、radeon.runpm=0 或 amdgpu.runpm=0 会禁用它。

在 GPU 挂起后,需要调用处理程序以切断 GPU 的电源。同样,在 GPU 恢复之前,需要恢复电源。这是通过 vga_switcheroo_init_domain_pm_ops() 实现的,它通过对处理程序的必要调用来增强 GPU 的挂起/恢复功能。

当音频设备恢复时,需要唤醒 GPU。这是通过一个 PCI 怪癖实现的,该怪癖调用 device_link_add() 来声明对 GPU 的依赖关系。这样,只要音频设备正在使用,GPU 就会保持唤醒状态。

在复用机器上,如果多路复用器最初切换到独立 GPU,则当 GPU 在启动后关闭电源时,用户最终会看到黑屏。作为一种解决方法,在运行时挂起时,强制将多路复用器切换到集成 GPU,请参阅 https://bugs.freedesktop.org/show_bug.cgi?id=75917

API

公共函数

int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, enum vga_switcheroo_handler_flags_t handler_flags)

注册处理程序

参数

const struct vga_switcheroo_handler *handler

处理程序回调

enum vga_switcheroo_handler_flags_t handler_flags

处理程序标志

描述

注册处理程序。如果已注册两个 VGA 客户端,则启用 vga_switcheroo。

返回值

成功时返回 0,如果已注册处理程序,则返回 -EINVAL。

void vga_switcheroo_unregister_handler(void)

注销处理程序

参数

void

无参数

描述

注销处理程序。禁用 vga_switcheroo。

enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void)

获取处理程序标志

参数

void

无参数

描述

用于客户端获取处理程序标志位掩码的助手。

返回值

处理程序标志。值为 0 表示未注册处理程序或该处理程序没有特殊功能。

int vga_switcheroo_register_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control)

注册 VGA 客户端

参数

struct pci_dev *pdev

客户端 PCI 设备

const struct vga_switcheroo_client_ops *ops

客户端回调

bool driver_power_control

电源状态是否由驱动程序的运行时 pm 控制

描述

注册 VGA 客户端 (GPU)。如果已注册另一个 GPU 和一个处理程序,则启用 vga_switcheroo。客户端的电源状态假定为 ON。在此之前,应调用 vga_switcheroo_client_probe_defer() 以确保满足所有先决条件。

返回值

成功时返回 0,内存分配错误时返回 -ENOMEM。

int vga_switcheroo_register_audio_client(struct pci_dev *pdev, const struct vga_switcheroo_client_ops *ops, struct pci_dev *vga_dev)

注册音频客户端

参数

struct pci_dev *pdev

客户端 PCI 设备

const struct vga_switcheroo_client_ops *ops

客户端回调

struct pci_dev *vga_dev

绑定到当前音频客户端的 PCI 设备

描述

注册音频客户端(GPU 上的音频设备)。 假定客户端使用运行时 PM。 事先应调用 vga_switcheroo_client_probe_defer() 以确保满足所有先决条件。

返回值

成功时返回 0,内存分配错误时返回 -ENOMEM,获取客户端 ID 错误时返回 -EINVAL。

bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev)

是否延迟探测给定客户端

参数

struct pci_dev *pdev

客户端 PCI 设备

描述

确定是否未满足任何探测给定客户端的先决条件。驱动程序应在其 ->probe 回调中尽早调用此函数,如果其计算结果为 true,则返回 -EPROBE_DEFER。 在调用此函数之前,不应注册客户端。

返回值

如果应延迟探测,则返回 true,否则返回 false

enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *pdev)

获取给定客户端的电源状态

参数

struct pci_dev *pdev

客户端 PCI 设备

描述

从 vga_switcheroo 中获取给定客户端的电源状态。 该函数仅从 hda_intel.c 中调用。

返回值

电源状态。

void vga_switcheroo_unregister_client(struct pci_dev *pdev)

注销客户端

参数

struct pci_dev *pdev

客户端 PCI 设备

描述

注销客户端。 如果这是 VGA 客户端 (GPU),则禁用 vga_switcheroo。

void vga_switcheroo_client_fb_set(struct pci_dev *pdev, struct fb_info *info)

设置给定客户端的帧缓冲

参数

struct pci_dev *pdev

客户端 PCI 设备

struct fb_info *info

帧缓冲

描述

设置给定客户端的帧缓冲。 控制台将在切换时重新映射到此。

int vga_switcheroo_lock_ddc(struct pci_dev *pdev)

暂时将 DDC 线切换到给定客户端

参数

struct pci_dev *pdev

客户端 PCI 设备

描述

暂时将 DDC 线切换到由 **pdev** 标识的客户端(但将输出保持切换到它们所在的任何位置)。 这允许非活动客户端探测 EDID。 DDC 线必须在之后通过调用 vga_switcheroo_unlock_ddc() 切换回来,即使此函数返回错误也是如此。

返回值

成功时返回先前的 DDC 所有者,或在出错时返回负整数。 具体而言,如果未注册处理程序或处理程序不支持切换 DDC 线,则返回 -ENODEV。 此外,处理程序返回的负值会传播回调用方。 返回值仅对任何可能对其感兴趣的调用方具有信息性目的。 可以忽略返回值,而仅依赖于后续 EDID 探测的结果,如果 DDC 切换失败,则该结果将为 NULL

int vga_switcheroo_unlock_ddc(struct pci_dev *pdev)

将 DDC 线切换回先前的所有者

参数

struct pci_dev *pdev

客户端 PCI 设备

描述

在调用 vga_switcheroo_lock_ddc() 后,将 DDC 线切换回先前的所有者。 即使 vga_switcheroo_lock_ddc() 返回错误,也必须调用此函数。

返回值

成功时返回先前的 DDC 所有者(即 **pdev** 的客户端标识符),或在出错时返回负整数。 具体而言,如果未注册处理程序或处理程序不支持切换 DDC 线,则返回 -ENODEV。 此外,处理程序返回的负值会传播回调用方。 最后,不允许在未首先调用 vga_switcheroo_lock_ddc() 的情况下调用此函数,这将导致 -EINVAL

int vga_switcheroo_process_delayed_switch(void)

延迟切换的帮助程序

参数

void

无参数

描述

如果存在挂起的延迟切换,则进行处理。

返回值

成功时返回 0。如果没有挂起的延迟切换、客户端在此期间已注销或有其他客户端阻止切换,则返回 -EINVAL。 如果实际切换失败,则报告错误并返回 0。

int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain *domain)

驱动程序电源控制的帮助程序

参数

struct device *dev

VGA 客户端设备

struct dev_pm_domain *domain

电源域

描述

对于其电源状态由驱动程序的运行时 pm 控制的 GPU 的帮助程序。 在 GPU 挂起后,需要调用处理程序以切断 GPU 的电源。 同样,在 GPU 恢复之前,它需要恢复电源。 为此,此帮助程序通过对处理程序的必要调用来扩充挂起/恢复函数。 它只需要在电源开关与正在断电的设备分离的平台上调用。

公共结构

struct vga_switcheroo_handler

处理程序回调

定义:

struct vga_switcheroo_handler {
    int (*init)(void);
    int (*switchto)(enum vga_switcheroo_client_id id);
    int (*switch_ddc)(enum vga_switcheroo_client_id id);
    int (*power_state)(enum vga_switcheroo_client_id id, enum vga_switcheroo_state state);
    enum vga_switcheroo_client_id (*get_client_id)(struct pci_dev *pdev);
};

成员

init

初始化处理程序。 可选。当启用 vga_switcheroo 时(即当两个 VGA 客户端注册时)会调用此函数。它允许处理程序执行一些依赖于 VGA 客户端存在的延迟初始化。当前只有 radeon 和 amdgpu 驱动程序使用此函数。返回值将被忽略

switchto

将输出切换到指定客户端。 必须项。 对于无多路复用器的机器,这应为空操作。 返回 0 表示成功,任何其他值表示失败(在这种情况下,切换将中止)

switch_ddc

将 DDC 线切换到指定客户端。 可选项。 成功时应返回之前的 DDC 所有者,失败时返回负整数

power_state

断开或恢复指定客户端的电源。 可选项。 返回值将被忽略

get_client_id

确定给定的 PCI 设备是集成 GPU 还是独立 GPU。 必须项

描述

处理程序回调。 多路复用器本身。switchtoget_client_id 方法是必须的,所有其他方法都可以设置为 NULL。

struct vga_switcheroo_client_ops

客户端回调

定义:

struct vga_switcheroo_client_ops {
    void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
    void (*reprobe)(struct pci_dev *dev);
    bool (*can_switch)(struct pci_dev *dev);
    void (*gpu_bound)(struct pci_dev *dev, enum vga_switcheroo_client_id);
};

成员

set_gpu_state

对卡执行等效的挂起/恢复操作。 必须项。 这不应切断独立 GPU 的电源,这是处理程序的工作

reprobe

轮询输出。 可选项。 这会在唤醒 GPU 并将其输出切换到它之后调用

can_switch

检查设备是否处于现在可以切换的位置。 必须项。 如果用户空间进程打开了它的一个设备文件,则客户端应返回 false

gpu_bound

当 GPU 被绑定时通知音频客户端客户端 ID。

描述

客户端回调。 客户端可以是 GPU 或 GPU 上的音频设备。set_gpu_statecan_switch 方法是必须的,reprobe 可以设置为 NULL。 对于音频客户端,reprobe 成员是无效的。 另一方面,gpu_bound 仅用于音频客户端,而不用于 GPU 客户端。

公共常量

enum vga_switcheroo_handler_flags_t

处理程序标志位掩码

常量

VGA_SWITCHEROO_CAN_SWITCH_DDC

处理程序是否能够单独切换 DDC 线。 这向客户端发出信号,指示它们应该调用 drm_get_edid_switcheroo() 来探测 EDID

VGA_SWITCHEROO_NEEDS_EDP_CONFIG

处理程序是否无法单独切换 AUX 通道。 这向客户端发出信号,指示活动的 GPU 需要训练链路并将链路参数传递给不活动的 GPU(由 vga_switcheroo 调解)。 然后,不活动的 GPU 可以跳过 AUX 握手,并使用这些预校准值设置其输出(DisplayPort 规范 v1.1a,第 2.5.3.3 节)

描述

处理程序标志位掩码。 由处理程序用于声明它们在向 vga_switcheroo 注册时的功能。

enum vga_switcheroo_client_id

客户端标识符

常量

VGA_SWITCHEROO_UNKNOWN_ID

分配给 vga 客户端的初始标识符。 确定 ID 需要处理程序,因此 GPU 在 vga_switcheroo_enable() 中以延迟方式获得其真实 ID

VGA_SWITCHEROO_IGD

集成图形设备

VGA_SWITCHEROO_DIS

独立图形设备

VGA_SWITCHEROO_MAX_CLIENTS

目前仅支持最多两个 GPU

描述

客户端标识符。 音频客户端使用相同的标识符 & 0x100。

enum vga_switcheroo_state

客户端电源状态

常量

VGA_SWITCHEROO_OFF

关闭

VGA_SWITCHEROO_ON

开启

VGA_SWITCHEROO_NOT_FOUND

客户端未在 vga_switcheroo 中注册。 仅在 vga_switcheroo_get_client_state() 中使用,而 vga_switcheroo_get_client_state() 又仅从 hda_intel.c 中调用

描述

客户端电源状态。

私有结构

struct vgasr_priv

vga_switcheroo 私有数据

定义:

struct vgasr_priv {
    bool active;
    bool delayed_switch_active;
    enum vga_switcheroo_client_id delayed_client_id;
    struct dentry *debugfs_root;
    int registered_clients;
    struct list_head clients;
    const struct vga_switcheroo_handler *handler;
    enum vga_switcheroo_handler_flags_t handler_flags;
    struct mutex mux_hw_lock;
    int old_ddc_owner;
};

成员

active

是否启用 vga_switcheroo。 先决条件是注册两个 GPU 和一个处理程序

delayed_switch_active

是否正在等待延迟切换

delayed_client_id

正在等待延迟切换的客户端

debugfs_root

vga_switcheroo debugfs 接口的目录

registered_clients

注册的 GPU 数量(仅计算 vga 客户端,不计算音频客户端)

clients

注册的客户端列表

handler

注册的处理程序

handler_flags

注册的处理程序的标志

mux_hw_lock

保护多路复用器状态(尤其是在临时切换 DDC 线时)

old_ddc_owner

DDC 线在解锁时将切换回的客户端

描述

vga_switcheroo 私有数据。 目前,每个系统仅支持一个 vga_switcheroo 实例。

struct vga_switcheroo_client

注册的客户端

定义:

struct vga_switcheroo_client {
    struct pci_dev *pdev;
    struct fb_info *fb_info;
    enum vga_switcheroo_state pwr_state;
    const struct vga_switcheroo_client_ops *ops;
    enum vga_switcheroo_client_id id;
    bool active;
    bool driver_power_control;
    struct list_head list;
    struct pci_dev *vga_dev;
};

成员

pdev

客户端 PCI 设备

fb_info

在切换时将控制台重新映射到的帧缓冲器

pwr_state

如果使用手动电源控制,则为当前电源状态。 对于驱动程序电源控制,请调用 vga_switcheroo_pwr_state()。

ops

客户端回调

id

客户端标识符。 确定 ID 需要处理程序,因此 GPU 最初被分配 VGA_SWITCHEROO_UNKNOWN_ID,然后在 vga_switcheroo_enable() 中获得其真实 ID

active

输出当前是否已切换到此客户端

driver_power_control

电源状态是否由驱动程序的运行时 pm 控制。 如果为 true,则向 vga_switcheroo debugfs 接口写入 ON 和 OFF 将不起作用,以免干扰运行时 pm

list

客户端列表

vga_dev

pci 设备,指示哪个 GPU 绑定到当前音频客户端

描述

注册的客户端。 客户端可以是 GPU 或 GPU 上的音频设备。 对于音频客户端,fb_infoactive 成员是无效的。 对于 GPU 客户端,vga_dev 是无效的。

处理程序

apple-gmux 处理程序

gmux 是内置在 MacBook Pro 中的微控制器,用于支持双 GPU:pre-retina 上的 Lattice XP2,pre-T2 retina 上的 Renesas R4F2113

在 T2 Macbooks 上,gmux 是 T2 协处理器 SMC 的一部分。 SMC 与一个 NXP PCAL6524 GPIO 扩展器具有 I2C 连接,该扩展器启用/禁用独立 GPU 的稳压器,驱动显示面板电源,并具有一个 GPIO 来切换 eDP 多路复用器。 Intel CPU 可以通过 MMIO 与 gmux 交互,类似于控制主 SMC 接口的方式。

(MacPro6,1 2013 也有一个 gmux,但不清楚为什么,因为它有双 GPU 但没有内置显示器。)

gmux 连接到南桥的 LPC 总线。 根据微控制器的不同,其 I/O 端口的访问方式也不同:访问 pre-retina gmux 的驱动程序函数以 _pio_ 作为后缀,访问 pre-T2 retina gmux 的驱动程序函数以 _index_ 作为后缀,而 T2 Mac 上的驱动程序函数以 _mmio_ 作为后缀。

gmux 还连接到南桥的 GPIO 引脚,从而能够触发 ACPI GPE。 ACPI 名称 GMGP 保存着此 GPIO 引脚的编号。 在 MBP5 2008/09 上,它是 Nvidia MCP79 的 GPIO 引脚 22,在后续几代中,它是 Intel PCH 的 GPIO 引脚 6,在 MMIO gmux 上,它是引脚 21。

GPE 仅表示发生了中断,实际的事件类型通过读取 gmux 寄存器来识别。

除了 GMGP 名称之外,gmux 的 ACPI 设备还具有两个方法 GMSP 和 GMLV。 GMLV 可能表示“GMUX Level”,并读取 GPIO 的值,而 GMSP 可能表示“GMUX Set Polarity”,并且似乎写入 GPIO 的值。 在较新的 Macbooks 上(这是在 MacBookPro14,3 或之前引入的),ACPI GPE 方法区分 OS 类型:在 Darwin 上,仅发出通知信号,而在其他 OS 上,读取 GPIO 的值,然后反转。

由于 Linux 伪装成 Darwin,因此最终进入了仅通知代码路径。 在 MMIO gmux 上,这似乎导致我们无法清除中断,除非我们调用 GMSP(0)。 如果没有此操作,则会发生大量无法清除的 status=0 中断。 此问题似乎是 MMIO gmux 独有的。

图形多路复用器

在 pre-retina 上,两个 GPU 的 LVDS 输出都馈入 gmux,gmux 将其中一个多路复用到面板。 gmux 的一个诀窍是在切换期间延长其输出的消隐间隔,以使其与切换到的 GPU 同步。 这可以实现用户无法察觉的无闪烁切换 (US 8,687,007 B2)。

在Retina显示屏上,多路复用不再由gmux本身完成,而是由一个单独的芯片控制,该芯片由gmux控制。该芯片有三个供应商,分别是恩智浦 CBTL06142德州仪器 HD3SS212Pericom PI3VDP12412。面板采用eDP驱动而不是LVDS,因为Retina分辨率所需的像素时钟超过了LVDS的限制。

Retina之前的型号能够单独切换面板的DDC引脚。这由一个德州仪器 SN74LV4066A 处理,该芯片由gmux控制。因此,不活动的GPU可以在不切换整个面板的情况下探测面板的EDID。Retina型号缺少此功能,因为用于eDP多路复用的芯片无法单独切换AUX通道(请参阅相关的数据表,Pericom可以实现,但未使用)。但是,Retina面板的DPCD中设置了NO_AUX_HANDSHAKE_LINK_TRAINING位,允许不活动的GPU跳过AUX握手,并使用活动GPU预校准的链路参数设置输出。

外部DP端口仅在前两个一体式MacBook Pro型号上完全可切换,即MBP5 2008/09和MBP6 2010。这是由一个恩智浦 CBTL06141 完成的,该芯片由gmux控制。它是Retina上eDP多路复用的前身,区别在于支持2.7与5.4 Gbit/s的速度。

后续的MacBook Pro型号用组合的DP/Thunderbolt端口取代了外部DP端口,并失去了在GPU之间切换该端口的能力,将其连接到独立GPU或Thunderbolt控制器。奇怪的是,虽然整个端口不再可切换,但AUX和HPD仍然可以通过恩智浦 CBTL03062(在Retina之前的MBP8 2011和MBP9 2012上)或两个德州仪器 TS3DS10224(在Retina之前的型号上)在gmux的控制下进行切换。由于集成GPU缺少主链路,外部显示器对它来说表现为无法链路训练的幻影。

gmux接收所有显示连接器的HPD信号,并在热插拔时发送中断。在无法切换外部端口的型号上,可以唤醒独立GPU来驱动新连接的显示器。在这些型号上,切换AUX的能力可以用于提高热插拔检测的可靠性,让集成GPU在独立GPU处于休眠状态时轮询端口,但目前我们没有使用此功能。

我们的外部端口切换策略是,在能够完全切换的型号上,当向vga_switcheroo发出IGD / DIS命令时,端口与面板一起切换。因此,可以使用集成GPU在电池供电的情况下驱动例如投影仪。如果需要更高的性能,用户可以手动切换到独立GPU。

在所有较新的型号上,外部端口只能由独立GPU驱动。如果在面板切换到集成GPU时插入显示器,两个GPU都将用于最大性能。为了降低功耗,用户可以手动切换到独立GPU,从而暂停集成GPU。

gmux在启动时的初始切换状态通过EFI变量gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9(第5个字节,1 = IGD,0 = DIS)进行用户配置。基于此设置,EFI固件会告诉gmux切换面板和外部DP连接器,并为选定的GPU分配帧缓冲区。

电源控制

gmux能够切断独立GPU的电源。它会自动处理用于核心电压、VRAM和PCIe的电源轨的正确拆除和启动顺序。

背光控制

在单GPU MacBook上,背光的PWM信号由GPU生成。相比之下,在双GPU MacBook Pro上,可以暂停任一GPU以节省能量。因此,PWM信号需要由一个单独的背光驱动器生成,该驱动器由gmux控制。最早的MBP5 2008/09型号使用德州仪器 LP8543背光驱动器。较新的型号使用德州仪器 LP8545或德州仪器 LP8548。

公共函数

bool apple_gmux_detect(struct pnp_dev *pnp_dev, enum apple_gmux_type *type_ret)

检测机器中是否内置了gmux

参数

struct pnp_dev *pnp_dev

要探测的设备,如果为NULL,则使用第一个匹配的设备

enum apple_gmux_type *type_ret

返回(通过引用)设备的apple_gmux_type

描述

通过实际探测来检测是否存在支持的gmux设备。这避免了apple_gmux_present()在某些型号上返回的误报。

返回值

如果检测到受支持的gmux ACPI设备并且内核已使用CONFIG_APPLE_GMUX配置,则返回true,否则返回false

bool apple_gmux_present(void)

检查是否存在gmux ACPI设备

参数

void

无参数

描述

驱动程序可以使用它来激活特定于双GPU MacBook Pro和Mac Pro的怪癖,例如延迟探测、运行时pm和背光。

返回值

如果存在gmux ACPI设备并且内核已使用CONFIG_APPLE_GMUX配置,则返回true,否则返回false