AMDgpu 显示管理器

AMDgpu 显示管理器 amdgpu_dm (或更简单的 dm)位于 DRM 和 DC 之间。它充当联络人,将 DRM 请求转换为 DC 请求,并将 DC 响应转换为 DRM 响应。

根控制结构是 struct amdgpu_display_manager

struct dm_compressor_info

帧缓冲区压缩使用的缓冲区信息

定义:

struct dm_compressor_info {
    void *cpu_addr;
    struct amdgpu_bo *bo_ptr;
    uint64_t gpu_addr;
};

成员

cpu_addr

MMIO CPU 地址

bo_ptr

指向缓冲区对象的指针

gpu_addr

MMIO GPU 地址

struct dmub_hpd_work

处理低优先级邮箱 IRQ 中的耗时工作

定义:

struct dmub_hpd_work {
    struct work_struct handle_hpd_work;
    struct dmub_notification *dmub_notify;
    struct amdgpu_device *adev;
};

成员

handle_hpd_work

要在单独的线程中执行以处理 hpd_low_irq 的工作

dmub_notify

回调函数的通知

adev

amdgpu_device 指针

struct vblank_control_work

垂直消隐控制的工作数据

定义:

struct vblank_control_work {
    struct work_struct work;
    struct amdgpu_display_manager *dm;
    struct amdgpu_crtc *acrtc;
    struct dc_stream_state *stream;
    bool enable;
};

成员

work

工作事件的内核工作数据

dm

amdgpu 显示管理器设备

acrtc

发生事件的 amdgpu CRTC 实例

stream

发生事件的 DC 流

enable

如果启用垂直消隐则为 true

struct idle_workqueue

空闲时定期操作的工作数据

定义:

struct idle_workqueue {
    struct work_struct work;
    struct amdgpu_display_manager *dm;
    bool enable;
    bool running;
};

成员

work

工作事件的内核工作数据

dm

amdgpu 显示管理器设备

enable

如果启用空闲工作线程则为 true

running

如果空闲工作线程正在运行则为 true

struct amdgpu_dm_backlight_caps

有关背光的信息

定义:

struct amdgpu_dm_backlight_caps {
    union dpcd_sink_ext_caps *ext_caps;
    u32 aux_min_input_signal;
    u32 aux_max_input_signal;
    int min_input_signal;
    int max_input_signal;
    bool caps_valid;
    bool aux_support;
    u8 ac_level;
    u8 dc_level;
};

成员

ext_caps

使用有关 HDR 显示支持的所有信息保存数据结构。

aux_min_input_signal

显示器支持的最小亮度值

aux_max_input_signal

显示器支持的最大亮度值,单位为尼特。

min_input_signal

范围 0-255 中的最小可能输入。

max_input_signal

范围 0-255 中的最大可能输入。

caps_valid

如果这些值来自 ACPI 接口则为 true。

aux_support

描述显示器是否支持 AUX 背光。

ac_level

如果使用 AC 启动的默认亮度

dc_level

如果使用 DC 启动的默认亮度

描述

描述 ACPI 或 eDP AUX 的背光支持。

struct dal_allocation

跟踪用于 SMU 通信的已映射 FB 内存

定义:

struct dal_allocation {
    struct list_head list;
    struct amdgpu_bo *bo;
    void *cpu_ptr;
    u64 gpu_addr;
};

成员

list

dal 分配列表

bo

GPU 缓冲区对象

cpu_ptr

GPU 缓冲区对象的 CPU 虚拟地址

gpu_addr

GPU 缓冲区对象的 GPU 虚拟地址

struct hpd_rx_irq_offload_work_queue

处理 hpd_rx_irq 卸载工作的工作队列

定义:

struct hpd_rx_irq_offload_work_queue {
    struct workqueue_struct *wq;
    spinlock_t offload_lock;
    bool is_handling_link_loss;
    bool is_handling_mst_msg_rdy_event;
    struct amdgpu_dm_connector *aconnector;
};

成员

wq

用于排队卸载工作的工作队列结构。

offload_lock

保护卸载工作队列的字段。

is_handling_link_loss

用于防止在我们处理链路丢失时插入链路丢失事件

is_handling_mst_msg_rdy_event

用于防止在我们已在处理 mst 消息就绪事件时插入 mst 消息就绪事件

aconnector

此工作队列所附加到的 aconnector

struct hpd_rx_irq_offload_work

hpd_rx_irq 卸载工作结构

定义:

struct hpd_rx_irq_offload_work {
    struct work_struct work;
    union hpd_irq_data data;
    struct hpd_rx_irq_offload_work_queue *offload_wq;
};

成员

work

卸载工作

data

在处理卸载工作时使用的参考 irq 数据

offload_wq

此工作排队到的卸载工作队列

struct amdgpu_display_manager

中央 amdgpu 显示管理器设备

定义:

struct amdgpu_display_manager {
    struct dc *dc;
    struct dmub_srv *dmub_srv;
    struct dmub_notification *dmub_notify;
    dmub_notify_interrupt_callback_t dmub_callback[AMDGPU_DMUB_NOTIFICATION_MAX];
    bool dmub_thread_offload[AMDGPU_DMUB_NOTIFICATION_MAX];
    struct dmub_srv_fb_info *dmub_fb_info;
    const struct firmware *dmub_fw;
    struct amdgpu_bo *dmub_bo;
    u64 dmub_bo_gpu_addr;
    void *dmub_bo_cpu_addr;
    uint32_t dmcub_fw_version;
    struct cgs_device *cgs_device;
    struct amdgpu_device *adev;
    struct drm_device *ddev;
    u16 display_indexes_num;
    struct drm_private_obj atomic_obj;
    struct mutex dc_lock;
    struct mutex audio_lock;
    struct drm_audio_component *audio_component;
    bool audio_registered;
    struct list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER];
    struct list_head irq_handler_list_high_tab[DAL_IRQ_SOURCES_NUMBER];
    struct common_irq_params pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1];
    struct common_irq_params vblank_params[DC_IRQ_SOURCE_VBLANK6 - DC_IRQ_SOURCE_VBLANK1 + 1];
    struct common_irq_params vline0_params[DC_IRQ_SOURCE_DC6_VLINE0 - DC_IRQ_SOURCE_DC1_VLINE0 + 1];
    struct common_irq_params vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1];
    struct common_irq_params dmub_trace_params[1];
    struct common_irq_params dmub_outbox_params[1];
    spinlock_t irq_handler_list_table_lock;
    struct backlight_device *backlight_dev[AMDGPU_DM_MAX_NUM_EDP];
    const struct dc_link *backlight_link[AMDGPU_DM_MAX_NUM_EDP];
    uint8_t num_of_edps;
    struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP];
    struct mod_freesync *freesync_module;
    struct hdcp_workqueue *hdcp_workqueue;
    struct workqueue_struct *vblank_control_workqueue;
    struct idle_workqueue *idle_workqueue;
    struct drm_atomic_state *cached_state;
    struct dc_state *cached_dc_state;
    struct dm_compressor_info compressor;
    const struct firmware *fw_dmcu;
    uint32_t dmcu_fw_version;
    const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
    uint32_t active_vblank_irq_count;
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY);
    struct secure_display_context *secure_display_ctxs;
#endif;
    struct hpd_rx_irq_offload_work_queue *hpd_rx_offload_wq;
    struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC];
    bool force_timing_sync;
    bool disable_hpd_irq;
    bool dmcub_trace_event_en;
    struct list_head da_list;
    struct completion dmub_aux_transfer_done;
    struct workqueue_struct *delayed_hpd_wq;
    u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
    u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];
    bool aux_hpd_discon_quirk;
    struct mutex dpia_aux_lock;
    struct dml2_soc_bb *bb_from_dmub;
};

成员

dc

显示核心控制结构

dmub_srv

DMUB 服务,用于控制支持它的硬件上的 DMUB。在不支持它的硬件上,指向 dmub_srv 的指针将为 NULL。

dmub_notify

来自 DMUB 的通知。

dmub_callback

用于处理来自 DMUB 的通知的回调函数。

dmub_thread_offload

指示回调是否卸载的标志。

dmub_fb_info

DMUB 的帧缓冲区区域。

dmub_fw

具有 DMUB 支持的硬件上需要的 DMUB 固件。

dmub_bo

DMUB 的缓冲区对象。

dmub_bo_gpu_addr

DMUB 缓冲区对象的 GPU 虚拟地址。

dmub_bo_cpu_addr

DMUB 缓冲区对象的 CPU 地址。

dmcub_fw_version

DMCUB 固件版本。

cgs_device

通用图形服务设备。它提供了一个用于访问寄存器的接口。

adev

AMDGPU 基本驱动程序结构

ddev

DRM 基本驱动程序结构

display_indexes_num

支持的最大显示流数

atomic_obj

dm_atomic_state 结合使用,它有助于管理不能干净地映射到现有 drm 资源的全局原子状态,例如 dc_context

dc_lock

保护对可以发出寄存器写入序列的 DC 函数的访问。

audio_lock

保护对音频实例更改的访问。

audio_component

用于通知声音驱动程序 ELD 更改。

audio_registered

如果音频组件已成功注册,则为 True,否则为 false。

irq_handler_list_low_tab

低优先级 IRQ 处理程序表。

它是一个 n*m 表,由 n 个 IRQ 源和每个 IRQ 源 m 个处理程序组成。低优先级 IRQ 处理程序会延迟到工作队列进行处理。因此,它们可以休眠。

请注意,处理程序的调用顺序与它们注册的顺序相同 (FIFO)。

irq_handler_list_high_tab

高优先级 IRQ 处理程序表。

它是一个 n*m 表,与 irq_handler_list_low_tab 相同。但是,此表中的处理程序不会延迟,并会立即调用。

pflip_params

页面翻转 IRQ 参数,在触发时传递给已注册的处理程序。

vblank_params

垂直消隐 IRQ 参数,在触发时传递给已注册的处理程序。

vline0_params

OTG 垂直中断 0 IRQ 参数,在触发时传递给已注册的处理程序。

vupdate_params

垂直更新 IRQ 参数,在触发时传递给已注册的处理程序。

dmub_trace_params

DMUB 跟踪事件 IRQ 参数,在触发时传递给已注册的处理程序。

dmub_outbox_params

DMUB 邮箱参数

irq_handler_list_table_lock

同步对 IRQ 表的访问

backlight_dev

背光控制设备

backlight_link

用于控制背光的链路

num_of_edps

背光 eDP 的数量

backlight_caps

背光设备的功能

freesync_module

处理 freesync 计算的模块

hdcp_workqueue

AMDGPU 内容保护队列

vblank_control_workqueue

用于垂直消隐控制事件的延迟工作。

idle_workqueue

用于空闲事件的定期工作。

cached_state

缓存用于挂起/恢复的设备原子状态

cached_dc_state

内容流的缓存状态

compressor

帧缓冲区压缩缓冲区。请参阅 struct dm_compressor_info

fw_dmcu

对 DMCU 固件的引用

dmcu_fw_version

DMCU 固件的版本

soc_bounding_box

gpu_info FW 提供的 soc 边界框结构,如果 FW 中不可用,则为 0

active_vblank_irq_count

当前活动垂直消隐 irq 的数量

secure_display_ctxs

存储所有 crtc 的 ROI 信息和用于命令 dmub 和 psp 的 work_struct。

hpd_rx_offload_wq

用于卸载 hpd_rx_irq 工作的工作队列

mst_encoders

用于 DP MST 的伪编码器。

force_timing_sync

通过 debugfs 设置。设置后,指示所有连接的显示器将被强制同步。

disable_hpd_irq

如果为 true,则禁用驱动程序中的所有 HPD 和 HPD RX 中断处理

dmcub_trace_event_en

启用 dmcub 跟踪事件

da_list

DAL fb 内存分配列表,用于与 SMU 通信。

dmub_aux_transfer_done

用于指示 DMUB 传输何时完成的 struct 完成

delayed_hpd_wq

用于延迟 DMUB HPD 工作的工作队列

brightness

缓存的背光值。

actual_brightness

上次成功应用的背光值。

aux_hpd_discon_quirk

当 aux 正在进行时发生 hpd 断开连接的怪异现象。发生在某些 Intel 平台上

dpia_aux_lock

保护对 DPIA AUX 的访问

bb_from_dmub

在 DCN4+ 的早期初始化期间从 dmub 读取的边界框数据

struct amdgpu_hdmi_vsdb_info

跟踪 VSDB 信息

定义:

struct amdgpu_hdmi_vsdb_info {
    unsigned int amd_vsdb_version;
    bool freesync_supported;
    unsigned int min_refresh_rate_hz;
    unsigned int max_refresh_rate_hz;
    bool replay_mode;
};

成员

amd_vsdb_version

厂商特定数据块版本,应用于确定要发送哪个厂商特定信息帧 (VSIF)。

freesync_supported

支持 FreeSync。

min_refresh_rate_hz

FreeSync 的最低刷新率,单位为 Hz。

max_refresh_rate_hz

FreeSync 的最高刷新率,单位为 Hz。

replay_mode

支持重放

描述

AMDGPU 通过使用 VSDB 部分来支持 HDMI 上的 FreeSync,此结构体用于跟踪有关 FreeSync 的显示特定信息。

生命周期

DM(以及随后的 DC)在 amdgpu 基本驱动程序中注册为 IP 块。当启用 CONFIG_DRM_AMD_DC 时,DM 设备 IP 块将添加到基本驱动程序的设备列表中,以便进行相应的初始化和拆卸。

执行此操作的函数在 struct amd_ip_funcs 中作为钩子提供。

int dm_hw_init(struct amdgpu_ip_block *ip_block)

初始化 DC 设备

参数

struct amdgpu_ip_block *ip_block

指向此硬件实例的 amdgpu_ip_block 的指针。

描述

初始化 struct amdgpu_display_manager 设备。这包括调用每个 DM 组件的初始化器,然后使用它们填充结构体。

尽管该函数暗示硬件初始化,但此处初始化的是硬件和软件。将它们拆分到它们相关的初始化钩子是未来的 TODO 项。

此处初始化的一些值得注意的事项

  • 显示核心,包括软件和硬件

  • 我们需要的 DC 模块(FreeSync 和颜色管理)

  • DRM 软件状态

  • 中断源和处理程序

  • 垂直消隐支持

  • 调试 FS 条目(如果启用)

int dm_hw_fini(struct amdgpu_ip_block *ip_block)

拆卸 DC 设备

参数

struct amdgpu_ip_block *ip_block

指向此硬件实例的 amdgpu_ip_block 的指针。

描述

拆卸 struct amdgpu_display_manager 中需要清理的组件。这包括清理 DRM 设备、DC 和任何已加载的模块。此外,刷新 IRQ 工作队列并禁用它们。

中断

DM 在基本驱动程序已提供的基础上提供了另一层 IRQ 管理。这是可以清理的事情,并且是未来的 TODO 项。

基本驱动程序提供带有 DRM 的 IRQ 源注册、注册到基本驱动程序 IRQ 表中的处理程序以及一个处理程序回调 amdgpu_irq_handler(),DRM 在发生中断时调用该回调。此通用处理程序查找 IRQ 表,并调用相应的 amdgpu_irq_src_funcs.process 钩子。

DM 在此基础上提供的两个 IRQ 表专门用于上半部分和下半部分 IRQ 处理,其中下半部分实现工作队列

它们会覆盖基本驱动程序的 IRQ 表,并且可以在 DM 为 amdgpu_irq_src_funcs.process 提供的钩子中看到效果。它们全部设置为 DM 通用处理程序 amdgpu_dm_irq_handler(),该处理程序会查找 DM 的 IRQ 表。但是,为了使基本驱动程序识别此钩子,DM 仍需要向基本驱动程序注册 IRQ。请参见 dce110_register_irq_handlers() 和 dcn10_register_irq_handlers()。

为了将 DC 的硬件中断切换公开给基本驱动程序,DM 实现了 amdgpu_irq_src_funcs.set 钩子。基本驱动程序通过 amdgpu_irq_update() 调用它来启用或禁用中断。

struct amdgpu_dm_irq_handler_data

DM 中断处理程序的数据。

定义:

struct amdgpu_dm_irq_handler_data {
    struct list_head list;
    interrupt_handler handler;
    void *handler_arg;
    struct amdgpu_display_manager *dm;
    enum dc_irq_source irq_source;
    struct work_struct work;
};

成员

list

引用下一个/上一个处理程序的链表条目

handler

处理程序函数

handler_arg

触发时传递给处理程序的参数

dm

此处理程序所属的 DM

irq_source

为此处理程序注册的 DC 中断源

work

work struct

void dm_irq_work_func(struct work_struct *work)

在中断处理程序之外处理 IRQ。

参数

struct work_struct *work

work struct

void unregister_all_irq_handlers(struct amdgpu_device *adev)

从 DM IRQ 表中清除处理程序

参数

struct amdgpu_device *adev

包含 DM 设备的基本驱动程序设备

描述

遍历低上下文和高上下文 IRQ 表,并取消分配处理程序。

void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, struct dc_interrupt_params *int_params, void (*ih)(void*), void *handler_args)

在 DM 中注册处理程序。

参数

struct amdgpu_device *adev

包含 DM 设备的基本驱动程序设备。

struct dc_interrupt_params *int_params

包含源和处理程序上下文的中断参数

void (*ih)(void *)

指向要注册的中断处理程序的函数指针

void *handler_args

发生中断时传递给处理程序的参数

描述

在给定上下文中为给定 IRQ 源注册中断处理程序。上下文可以是高上下文或低上下文。高上下文处理程序直接在 ISR 上下文中执行,而低上下文处理程序在工作队列中执行,从而允许休眠操作。

注册的处理程序按 FIFO 方式调用,即最近注册的处理程序将首先调用。

返回

包含 IRQ 的处理程序数据 struct amdgpu_dm_irq_handler_data

源、处理程序函数和参数

void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, enum dc_irq_source irq_source, void *ih)

从 DM IRQ 表中删除处理程序

参数

struct amdgpu_device *adev

包含 DM 设备的基本驱动程序设备

enum dc_irq_source irq_source

从中删除给定处理程序的 IRQ 源

void *ih

指向要取消注册的中断处理程序的函数指针

描述

遍历低上下文和高上下文 IRQ 表,并查找给定 IRQ 源的给定处理程序。如果找到,则将其删除。否则,不执行任何操作。

int amdgpu_dm_irq_init(struct amdgpu_device *adev)

初始化 DM IRQ 管理

参数

struct amdgpu_device *adev

包含 DM 设备的基本驱动程序设备

描述

初始化 DM 的高上下文和低上下文 IRQ 表。

N x M 表包含 N 个 IRQ 源,其中 M 个 struct amdgpu_dm_irq_handler_data 在一个链表中连接在一起。此处初始化 list_heads。当触发中断 n 时,所有 m 个处理程序都将按注册顺序以 FIFO 顺序调用。

低上下文表需要特殊的初始化步骤,因为处理程序将推迟到工作队列。请参见 struct irq_list_head

void amdgpu_dm_irq_fini(struct amdgpu_device *adev)

拆除 DM IRQ 管理。

参数

struct amdgpu_device *adev

包含 DM 设备的基本驱动程序设备

描述

刷新低上下文 IRQ 表中的所有工作。

int amdgpu_dm_irq_handler(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry)

通用 DM IRQ 处理程序

参数

struct amdgpu_device *adev

包含 DM 设备的 amdgpu 基础驱动程序设备

struct amdgpu_irq_src *source

未使用

struct amdgpu_iv_entry *entry

有关触发中断的数据

描述

立即调用所有注册的高 IRQ 工作,并为低 IRQ 安排工作。 DM IRQ 表用于查找相应的处理程序。

void amdgpu_dm_hpd_init(struct amdgpu_device *adev)

hpd 设置回调。

参数

struct amdgpu_device *adev

amdgpu_device 指针

描述

设置卡使用的 hpd 引脚(evergreen+)。启用引脚,设置极性,并启用 hpd 中断。

void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)

hpd 拆除回调。

参数

struct amdgpu_device *adev

amdgpu_device 指针

描述

拆除卡使用的 hpd 引脚(evergreen+)。禁用 hpd 中断。

void dm_pflip_high_irq(void *interrupt_params)

处理页面翻转中断

参数

void *interrupt_params

已忽略

描述

通过通知所有相关方页面翻转已完成来处理页面翻转中断。

void dm_crtc_high_irq(void *interrupt_params)

处理 CRTC 中断

参数

void *interrupt_params

用于确定 CRTC 实例

描述

通过通知 DRM 的 VBLANK 事件处理程序来处理 CRTC/VSYNC 中断。

原子实现

WIP

void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)

AMDgpu DM 的提交尾部实现。

参数

struct drm_atomic_state *state

要提交的原子状态

描述

这将告诉 DC 提交从 atomic_check 构建的 DC 状态,从而对硬件进行编程。此处的任何失败都意味着硬件故障,因为原子检查应该已经过滤掉了任何不合规的内容。

int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)

AMDgpu DM 的原子检查实现。

参数

struct drm_device *dev

DRM 设备

struct drm_atomic_state *state

要提交的原子状态

描述

验证给定的原子状态是否可以通过 DC 编程到硬件中。这涉及到构造一个 struct dc_state,反映我们希望提交的新硬件状态,然后查询 DC 以查看它是否可编程。重要的是不要修改现有的 DC 状态。否则,atomic_check 可能会意外提交硬件更改。

在验证 DC 状态时,重要的是获取正确的锁。对于在翻转另一个 CRTC 时删除/添加/更新一个 CRTC 上的流的完全更新情况,获取全局锁将保证任何此类完全更新提交都将等待使用 DRM 同步事件的任何未完成翻转完成。

请注意,DM 为状态中的所有 CRTC 添加了受影响的连接器,即使这似乎不是必需的。这是因为 DC 流创建需要 DC sink,而 DC sink 与 DRM 连接器状态相关联。清理此问题应该是可行的,但并非微不足道 - 这是一个可能的 TODO 项。

返回

- 如果验证失败,则返回错误代码。

颜色管理属性

到硬件的 DC 接口为我们提供了每个管道(表面)的以下颜色管理块

  • 输入伽马 LUT(非归一化)

  • 输入 CSC(归一化)

  • 表面去伽马 LUT(归一化)

  • 表面 CSC(归一化)

  • 表面再伽马 LUT(归一化)

  • 输出 CSC(归一化)

但是,这些与 DRM 颜色属性没有直接映射。当前的 DRM 接口公开了 CRTC 去伽马、CRTC CTM 和 CRTC 再伽马,而我们的硬件本质上提供

平面 CTM -> 平面去伽马 -> 平面 CTM -> 平面再伽马 -> 平面 CTM

输入伽马 LUT 块在这里不是真正适用的,因为它作用于实际的输入数据本身,而不是 HW fp 表示。输入和输出 CSC 块在技术上可作为 DC 接口的一部分使用,但通常由 DC 内部用于颜色空间之间的转换。将来可以将这些与用户调整混合在一起,但现在这些应保持不变。

管道混合也发生在这些块之后,因此我们实际上不支持任何具有多个平面正确混合的 CRTC 属性 - 但我们仍然可以通过在 DM 中巧妙管理 DC 接口,在大多数单平面情况下正确支持 DM 中的 CRTC 颜色管理属性。

根据 DRM 文档,当各自的属性设置为 NULL 时,块应处于硬件旁路中。线性 DGM/RGM LUT 也应被视为将各自的块置于旁路模式。

这意味着以下配置被假定为默认配置

平面 DGM 旁路 -> 平面 CTM 旁路 -> 平面 RGM 旁路 -> ... CRTC DGM 旁路 -> CRTC CTM 旁路 -> CRTC RGM 旁路

void amdgpu_dm_init_color_mod(void)

初始化颜色模块。

参数

void

无参数

描述

我们不使用完整的颜色模块,仅使用某些组件。仅对我们需要使用的组件调用设置函数。

const struct drm_color_lut *__extract_blob_lut(const struct drm_property_blob *blob, uint32_t *size)

从 blob 中提取 DRM lut 和 lut 大小。

参数

const struct drm_property_blob *blob

DRM 颜色管理属性 blob

uint32_t *size

lut 大小

返回

DRM LUT 或 NULL

bool __is_lut_linear(const struct drm_color_lut *lut, uint32_t size)

检查给定的 lut 是否是值的线性映射

参数

const struct drm_color_lut *lut

要检查值的给定 lut

uint32_t size

lut 大小

描述

如果 lut 表示:f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a;对于 [0, MAX_COLOR_LUT_ENTRIES) 中的整数 a,则认为它是线性的

返回

如果给定 lut 是值的线性映射,即它的作用类似于旁路 LUT,则返回 true。否则,返回 false。

void __drm_lut_to_dc_gamma(const struct drm_color_lut *lut, struct dc_gamma *gamma, bool is_legacy)

将 drm_color_lut 转换为 dc_gamma。

参数

const struct drm_color_lut *lut

用于颜色转换的 DRM 查找表

struct dc_gamma *gamma

要设置条目的 DC 伽马

bool is_legacy

传统伽马或原子伽马

描述

转换取决于 lut 的大小 - 无论它是否是传统的。

void __drm_ctm_to_dc_matrix(const struct drm_color_ctm *ctm, struct fixed31_32 *matrix)

将 DRM CTM 转换为 DC CSC 浮点矩阵

参数

const struct drm_color_ctm *ctm

DRM 颜色转换矩阵

struct fixed31_32 *matrix

DC CSC 浮点矩阵

描述

该矩阵需要是一个 3x4(12 个条目)的矩阵。

void __drm_ctm_3x4_to_dc_matrix(const struct drm_color_ctm_3x4 *ctm, struct fixed31_32 *matrix)

将 DRM CTM 3x4 转换为 DC CSC 浮点矩阵

参数

const struct drm_color_ctm_3x4 *ctm

具有 3x4 维度的 DRM 颜色转换矩阵

struct fixed31_32 *matrix

DC CSC 浮点矩阵

描述

该矩阵需要是一个 3x4(12 个条目)的矩阵。

int __set_legacy_tf(struct dc_transfer_func *func, const struct drm_color_lut *lut, uint32_t lut_size, bool has_rom)

计算传统传输函数

参数

struct dc_transfer_func *func

传输函数

const struct drm_color_lut *lut

定义颜色空间的查找表

uint32_t lut_size

相应查找表的大小

bool has_rom

如果可以使用 ROM 进行硬编码曲线

描述

仅适用于 sRGB 输入空间

返回

成功时为 0,失败时为 -ENOMEM

int __set_output_tf(struct dc_transfer_func *func, const struct drm_color_lut *lut, uint32_t lut_size, bool has_rom)

根据预期的输入空间计算输出传输函数。

参数

struct dc_transfer_func *func

传输函数

const struct drm_color_lut *lut

定义颜色空间的查找表

uint32_t lut_size

相应查找表的大小

bool has_rom

如果可以使用 ROM 进行硬编码曲线

返回

成功时为 0。失败时为 -ENOMEM。

int __set_input_tf(struct dc_color_caps *caps, struct dc_transfer_func *func, const struct drm_color_lut *lut, uint32_t lut_size)

根据预期的输入空间计算输入传输函数。

参数

struct dc_color_caps *caps

dc 颜色功能

struct dc_transfer_func *func

传输函数

const struct drm_color_lut *lut

定义颜色空间的查找表

uint32_t lut_size

相应查找表的大小。

返回

成功时为 0。失败时为 -ENOMEM。

int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev, struct drm_plane_state *plane_state)

验证是否支持 3D LUT,以及用户整形器和 3D LUT 是否与硬件支持的大小匹配

参数

struct amdgpu_device *adev

amdgpu 设备

struct drm_plane_state *plane_state

DRM 平面状态

描述

验证硬件(DCN 2.0 或更新版本)是否支持预混合 (DPP) 3D LUT,以及用户整形器和 3D LUT 是否与支持的大小匹配。

返回

成功时为 0。如果 LUT 大小无效,则为 -EINVAL。

int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state)

验证 DRM LUT 是否与硬件支持的大小匹配

参数

const struct drm_crtc_state *crtc_state

DRM CRTC 状态

描述

验证附加到 crtc_state 的 Degamma 和 Gamma LUT 是否为预期的大小。

返回

成功时为 0。如果任何 LUT 大小无效,则为 -EINVAL。

int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc)

将 DRM 颜色管理映射到 DC 流。

参数

struct dm_crtc_state *crtc

amdgpu_dm crtc 状态

描述

在没有平面级颜色管理属性的情况下,我们可以自由使用任何硬件块,只要 CRTC CTM 始终在 CRTC RGM 之前,并在 CRTC DGM 之后即可。

  • 如果 CRTC RGM 块是非线性的,则将其放置在 RGM LUT 块中。

  • 如果 CRTC DGM 块是非线性的,则将其放置在 DGM LUT 块中。

  • 如果 CRTC CTM 是非线性的,则将其放置在色域重映射块中。

RGM 块通常在所有 ASIC 中都具有更完整的功能和准确性 - DCE 不能支持自定义的非线性 CRTC DGM。

为了同时支持平面级颜色管理和 CRTC 级颜色管理,我们必须限制 CRTC 属性的使用或将调整混合在一起。

返回

成功时为 0。如果设置失败,则为错误代码。

int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, struct drm_plane_state *plane_state, struct dc_plane_state *dc_plane_state)

将 DRM 颜色管理映射到 DC 平面。

参数

struct dm_crtc_state *crtc

amdgpu_dm crtc 状态

struct drm_plane_state *plane_state

DRM 平面状态

struct dc_plane_state *dc_plane_state

目标 DC 表面

描述

更新底层 dc_stream_state 的输入传输函数 (ITF),以准备硬件提交。所使用的传输函数取决于为颜色管理在流上完成的准备工作。

返回

成功时为 0。如果内存分配失败,则为 -ENOMEM。

DCN 各代之间的 DC 颜色功能

DRM/KMS 框架定义了三个 CRTC 颜色校正属性:去伽马、颜色转换矩阵 (CTM) 和伽马,以及两个用于去伽马和伽马 LUT 大小的属性。AMD DC 在混合前编程一些颜色校正功能,但 DRM/KMS 没有每个平面的颜色校正属性。

一般来说,DRM CRTC 颜色属性按以下方式编程到 DC:混合后的 CRTC 伽马和混合前的 CRTC 去伽马。虽然 CTM 是在混合后编程的,但它被映射到 DPP 硬件块(混合前)。DRM 接口目前没有公开硬件中可用的其他颜色功能,因此会被绕过。

颜色管理功能(DPP 和 MPC)

Modules/color 计算各种颜色操作,这些操作被转换为抽象的硬件。DCE 5-12 几乎没有重要的更改,但从 DCN1 开始,每一代新产品的颜色管道都有相当大的差异。因此,我们抽象了颜色管道功能,以便 modules/DM 可以根据逻辑功能决定映射到硬件块。

struct rom_curve_caps

用于去伽马和重新伽马的预定义传输函数功能

定义:

struct rom_curve_caps {
    uint16_t srgb : 1;
    uint16_t bt2020 : 1;
    uint16_t gamma2_2 : 1;
    uint16_t pq : 1;
    uint16_t hlg : 1;
};

成员

srgb

RGB 颜色空间传输函数

bt2020

BT.2020 传输函数

gamma2_2

标准伽马

pq

感知量化器传输函数

hlg

混合对数伽马传输函数

struct dpp_color_caps

显示管道和平面块的颜色管道功能

定义:

struct dpp_color_caps {
    uint16_t dcn_arch : 1;
    uint16_t input_lut_shared : 1;
    uint16_t icsc : 1;
    uint16_t dgam_ram : 1;
    uint16_t post_csc : 1;
    uint16_t gamma_corr : 1;
    uint16_t hw_3d_lut : 1;
    uint16_t ogam_ram : 1;
    uint16_t ocsc : 1;
    uint16_t dgam_rom_for_yuv : 1;
    struct rom_curve_caps dgam_rom_caps;
    struct rom_curve_caps ogam_rom_caps;
};

成员

dcn_arch

所有 DCE 代的处理方式相同

input_lut_shared

与 DGAM 共享。输入 LUT 与大多数 LUT 不同,只是普通的 256 条目查找

icsc

输入颜色空间转换

dgam_ram

可编程的去伽马 LUT

post_csc

颜色空间转换后,在色域重映射之前

gamma_corr

去伽马校正

hw_3d_lut

3D LUT 支持。它意味着之前有一个整形器 LUT。可以通过设置 mpc:shared_3d_lut 标志与 MPC 共享

ogam_ram

可编程的输出/混合伽马 LUT

ocsc

输出颜色空间转换

dgam_rom_for_yuv

YUV 平面的预定义反伽马 LUT

dgam_rom_caps

用于反伽马 1D LUT 的预定义曲线上限

ogam_rom_caps

用于重伽马 1D LUT 的预定义曲线上限

注意

hdr_mult 和色域重映射 (CTM) 在 DPP 中始终可用(按此顺序)

struct mpc_color_caps

用于多个管道和平面组合块的颜色管道能力

定义:

struct mpc_color_caps {
    uint16_t gamut_remap : 1;
    uint16_t ogam_ram : 1;
    uint16_t ocsc : 1;
    uint16_t num_3dluts : 3;
    uint16_t shared_3d_lut:1;
    struct rom_curve_caps ogam_rom_caps;
};

成员

gamut_remap

颜色变换矩阵

ogam_ram

可编程输出伽马 LUT

ocsc

输出颜色空间转换矩阵

num_3dluts

MPC 3D LUT;始终假定前面有一个整形器 LUT

shared_3d_lut

共享 3D LUT 标志。可以是 DPP 或 MPC,但只能有一个实例

ogam_rom_caps

用于重伽马 1D LUT 的预定义曲线上限

struct dc_color_caps

DPP 和 MPC 硬件块的颜色管道能力

定义:

struct dc_color_caps {
    struct dpp_color_caps dpp;
    struct mpc_color_caps mpc;
};

成员

dpp

DPP 的颜色管道上限

mpc

MPC 的颜色管道上限

enum pipe_split_policy

DCN 支持的管道拆分策略

常量

MPC_SPLIT_DYNAMIC

DC 将自动决定如何拆分管道,以在性能和功耗之间取得最佳平衡。这是建议的选项。

MPC_SPLIT_AVOID

避免管道拆分,这意味着 DC 不会尝试任何类型的拆分优化。

MPC_SPLIT_AVOID_MULT_DISP

使用此选项,DC 仅在使用单个显示器时尝试优化管道利用率;如果用户连接到第二个显示器,DC 将避免管道拆分。

描述

此枚举用于定义 DCN 支持的管道拆分策略。默认情况下,DC 倾向于 MPC_SPLIT_DYNAMIC。

struct dc_validation_set

用于存储用于验证的表面/流关联的结构

定义:

struct dc_validation_set {
    struct dc_stream_state *stream;
    struct dc_plane_state *plane_states[MAX_SURFACES];
    uint8_t plane_count;
};

成员

stream

流状态属性

plane_states

表面状态

plane_count

活动平面的总数

颜色管道在 DCN 硬件世代之间经历了重大变化。在混合之前和之后可以执行哪些操作取决于硬件功能,如下面的 DCN 2.0 和 DCN 3.0 系列示意图所示。

DCN 2.0 系列颜色上限和映射

../../../_images/dcn2_cm_drm_current.svg

DCN 3.0 系列颜色上限和映射

../../../_images/dcn3_cm_drm_current.svg

混合模式属性

像素混合模式是 drm_plane 的 DRM 平面合成属性,用于描述如何将前景平面 (fg) 的像素与背景平面 (bg) 合成。在这里,我们介绍了 DRM 混合模式的主要概念,以帮助理解如何将此属性映射到 AMD DC 接口。有关此 DRM 属性和 alpha 混合方程的更多信息,请参阅 DRM 平面合成属性

基本上,混合模式为平面合成设置 alpha 混合方程,该方程符合 alpha 通道影响像素颜色值状态的模式,从而影响生成的像素颜色。例如,考虑 alpha 混合方程的以下元素

  • fg.rgb:来自前景像素的每个 RGB 分量值。

  • fg.alpha:来自前景像素的 alpha 分量值。

  • bg.rgb:来自背景的每个 RGB 分量值。

  • plane_alpha:由平面“alpha”属性设置的平面 alpha 值,有关更多信息,请参阅 DRM 平面合成属性

在基本的 alpha 混合方程中

out.rgb = alpha * fg.rgb + (1 - alpha) * bg.rgb

忽略平面中每个像素的 alpha 通道值,只有平面 alpha 会影响生成的像素颜色值。

DRM 有三种混合模式来定义平面合成中的混合公式

  • None:忽略像素 alpha 的混合公式。

  • 预乘:假设平面中的像素颜色值在存储之前已由其自身的 alpha 通道预乘的混合公式。

  • 覆盖:假设像素颜色值未与 alpha 通道值预乘的混合公式。

预乘是默认的像素混合模式,这意味着,当没有创建或定义混合模式属性时,DRM 认为平面的像素具有预乘的颜色值。在 IGT GPU 工具上,kms_plane_alpha_blend 测试提供了一组子测试来验证平面 alpha 和混合模式属性。

然后,AMDGPU 显示管理器 (DM) 将 DRM 混合模式及其元素映射到多管道/平面组合 (MPC) 的混合配置,如下所示

struct mpcc_blnd_cfg

MPCC 混合配置

定义:

struct mpcc_blnd_cfg {
    struct tg_color black_color;
    enum mpcc_alpha_blend_mode alpha_mode;
    bool pre_multiplied_alpha;
    int global_gain;
    int global_alpha;
    bool overlap_only;
    int bottom_gain_mode;
    int background_color_bpc;
    int top_gain;
    int bottom_inside_gain;
    int bottom_outside_gain;
};

成员

black_color

背景颜色。

alpha_mode

alpha 混合模式 (MPCC_ALPHA_BLND_MODE)。

pre_multiplied_alpha

像素颜色值是否已由 alpha 通道预乘 (MPCC_ALPHA_MULTIPLIED_MODE)。

global_gain

当混合模式同时考虑像素 alpha 和平面时使用。

global_alpha

平面 alpha 值。

overlap_only

是否允许不同平面的重叠。

bottom_gain_mode

底部增益设置的混合模式。

background_color_bpc

bpc 的背景颜色。

top_gain

顶部增益设置。

bottom_inside_gain

底部内部的混合模式。

bottom_outside_gain

底部外部的混合模式。

因此,MPC 树上单个 MPCC 实例的混合配置由 mpcc_blnd_cfg 定义,其中 pre_multiplied_alpha 是用于设置 MPCC_ALPHA_MULTIPLIED_MODE 的 alpha 预乘模式标志。它控制是否乘以 alpha(真/假),仅当 DRM 预乘混合模式为真时。 mpcc_alpha_blend_mode 定义关于像素 alpha 和平面 alpha 值的 alpha 混合模式。它为 MPCC_ALPHA_BLND_MODE 设置以下三种模式之一,如下所述。

enum mpcc_alpha_blend_mode

定义关于像素 alpha 和平面 alpha 值的 alpha 混合模式

常量

MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA

使用 DPP alpha 值的每个像素 alpha

MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN

使用 DPP alpha 值乘以全局增益(平面 alpha)的每个像素 alpha

MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA

全局 alpha 值,忽略像素 alpha,仅考虑平面 alpha

然后,DM 将 enum mpcc_alpha_blend_mode 中的元素映射到 DRM 混合公式中的元素,如下所示

  • MPC 像素 alphaDRM fg.alpha 匹配,作为来自平面的像素的 alpha 分量值

  • 当应忽略像素 alpha 并且因此像素值未预乘时,MPC 全局 alphaDRM plane_alpha 匹配

  • DRM fg.alphaDRM plane_alpha 都参与混合方程时,MPC 全局增益 假定 MPC 全局 alpha

简而言之,通过选择 MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA,将忽略 fg.alpha。另一方面,通过选择 MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN,可以使用 (plane_alpha * fg.alpha) 分量。并且 MPCC_ALPHA_MULTIPLIED_MODE 定义像素颜色值是否乘以 alpha 预乘。

混合配置流程

通过以下路径从 DRM 配置到 DC 接口的 alpha 混合方程

  1. 更新 drm_plane_state 时,DM 调用 amdgpu_dm_plane_fill_blending_from_plane_state(),该函数将 drm_plane_state 属性映射到 dc_plane_info 结构,以便在操作系统无关组件 (DC) 中进行处理。

  2. 在 DC 接口上,struct mpcc_blnd_cfg 考虑到来自 DPP 的 dc_plane_info 输入来编程 MPCC 混合配置。