AMDgpu Display Manager

The AMDgpu display manager,amdgpu_dm (or even simpler,dm) sits between DRM and DC. It acts as a liaison, converting DRMrequests into DC requests, and DC responses into DRM responses.

The root control structure isstructamdgpu_display_manager.

structdm_compressor_info

Buffer info used by frame buffer compression

Definition:

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

Members

cpu_addr

MMIO cpu addr

bo_ptr

Pointer to the buffer object

gpu_addr

MMIO gpu addr

structdmub_hpd_work

Handle time consuming work in low priority outbox IRQ

Definition:

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

Members

handle_hpd_work

Work to be executed in a separate thread to handle hpd_low_irq

dmub_notify

notification for callback function

adev

amdgpu_device pointer

structvblank_control_work

Work data for vblank control

Definition:

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

Members

work

Kernel work data for the work event

dm

amdgpu display manager device

acrtc

amdgpu CRTC instance for which the event has occurred

stream

DC stream for which the event has occurred

enable

true if enabling vblank

structidle_workqueue

Work data for periodic action in idle

Definition:

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

Members

work

Kernel work data for the work event

dm

amdgpu display manager device

enable

true if idle worker is enabled

running

true if idle worker is running

structvupdate_offload_work

Work data for offloading task from vupdate handler

Definition:

struct vupdate_offload_work {    struct work_struct work;    struct amdgpu_device *adev;    struct dc_stream_state *stream;    struct dc_crtc_timing_adjust *adjust;};

Members

work

Kernel work data for the work event

adev

amdgpu_device back pointer

stream

DC stream associated with the crtc

adjust

DC CRTC timing adjust to be applied to the crtc

structamdgpu_dm_luminance_data

Custom luminance data

Definition:

struct amdgpu_dm_luminance_data {    u8 luminance;    u8 input_signal;};

Members

luminance

Luminance in percent

input_signal

Input signal in range 0-255

structamdgpu_dm_backlight_caps

Information about backlight

Definition:

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;    u32 brightness_mask;    u8 ac_level;    u8 dc_level;    u8 data_points;    struct amdgpu_dm_luminance_data luminance_data[MAX_LUMINANCE_DATA_POINTS];};

Members

ext_caps

Keep the datastructwith all the information about thedisplay support for HDR.

aux_min_input_signal

Min brightness value supported by the display

aux_max_input_signal

Max brightness value supported by the displayin nits.

min_input_signal

minimum possible input in range 0-255.

max_input_signal

maximum possible input in range 0-255.

caps_valid

true if these values are from the ACPI interface.

aux_support

Describes if the display supports AUX backlight.

brightness_mask

After deriving brightness, OR it with this mask.Workaround for panels with issues with certain brightness values.

ac_level

the default brightness if booted on AC

dc_level

the default brightness if booted on DC

data_points

the number of custom luminance data points

luminance_data

custom luminance data

Description

Describe the backlight support for ACPI or eDP AUX.

structdal_allocation

Tracks mapped FB memory for SMU communication

Definition:

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

Members

list

list of dal allocations

bo

GPU buffer object

cpu_ptr

CPU virtual address of the GPU buffer object

gpu_addr

GPU virtual address of the GPU buffer object

structhpd_rx_irq_offload_work_queue

Work queue to handle hpd_rx_irq offload work

Definition:

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;};

Members

wq

workqueue structure to queue offload work.

offload_lock

To protect fields of offload work queue.

is_handling_link_loss

Used to prevent inserting link loss event whenwe’re handling link loss

is_handling_mst_msg_rdy_event

Used to prevent inserting mst messageready event when we’re already handling mst message ready event

aconnector

The aconnector that this work queue is attached to

structhpd_rx_irq_offload_work

hpd_rx_irq offload work structure

Definition:

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

Members

work

offload work

data

reference irq data which is used while handling offload work

offload_wq

offload work queue that this work is queued to

adev

amdgpu_device pointer

structamdgpu_display_manager

Central amdgpu display manager device

Definition:

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;    uint32_t fw_inst_size;    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_ctx;#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;    bool edp0_on_dp1_quirk;    struct mutex dpia_aux_lock;    void *bb_from_dmub;    struct amdgpu_i2c_adapter *oem_i2c;    struct fused_io_sync {        struct completion replied;        char reply_data[0x40];    } fused_io[8];};

Members

dc

Display Core control structure

dmub_srv

DMUB service, used for controlling the DMUB on hardwarethat supports it. The pointer to the dmub_srv will beNULL on hardware that does not support it.

dmub_notify

Notification from DMUB.

dmub_callback

Callback functions to handle notification from DMUB.

dmub_thread_offload

Flag to indicate if callback is offload.

dmub_fb_info

Framebuffer regions for the DMUB.

dmub_fw

DMUB firmware, required on hardware that has DMUB support.

dmub_bo

Buffer object for the DMUB.

dmub_bo_gpu_addr

GPU virtual address for the DMUB buffer object.

dmub_bo_cpu_addr

CPU address for the DMUB buffer object.

dmcub_fw_version

DMCUB firmware version.

fw_inst_size

Size of the firmware instruction buffer.

cgs_device

The Common Graphics Services device. It provides an interface foraccessing registers.

adev

AMDGPU base driver structure

ddev

DRM base driver structure

display_indexes_num

Max number of display streams supported

atomic_obj

In combination withdm_atomic_state it helps manageglobal atomic state that doesn’t map cleanly into existingdrm resources, likedc_context.

dc_lock

Guards access to DC functions that can issue register writesequences.

audio_lock

Guards access to audio instance changes.

audio_component

Used to notify ELD changes to sound driver.

audio_registered

True if the audio component has been registeredsuccessfully, false otherwise.

irq_handler_list_low_tab

Low priority IRQ handler table.

It is a n*m table consisting of n IRQ sources, and m handlers per IRQsource. Low priority IRQ handlers are deferred to a workqueue to beprocessed. Hence, they can sleep.

Note that handlers are called in the same order as they wereregistered (FIFO).

irq_handler_list_high_tab

High priority IRQ handler table.

It is a n*m table, same asirq_handler_list_low_tab. However,handlers in this table are not deferred and are called immediately.

pflip_params

Page flip IRQ parameters, passed to registered handlers whentriggered.

vblank_params

Vertical blanking IRQ parameters, passed to registered handlers whentriggered.

vline0_params

OTG vertical interrupt0 IRQ parameters, passed to registeredhandlers when triggered.

vupdate_params

Vertical update IRQ parameters, passed to registered handlers whentriggered.

dmub_trace_params

DMUB trace event IRQ parameters, passed to registered handlers whentriggered.

dmub_outbox_params

DMUB Outbox parameters

irq_handler_list_table_lock

Synchronizes access to IRQ tables

backlight_dev

Backlight control device

backlight_link

Link on which to control backlight

num_of_edps

number of backlight eDPs

backlight_caps

Capabilities of the backlight device

freesync_module

Module handling freesync calculations

hdcp_workqueue

AMDGPU content protection queue

vblank_control_workqueue

Deferred work for vblank control events.

idle_workqueue

Periodic work for idle events.

cached_state

Caches device atomic state for suspend/resume

cached_dc_state

Cached state of content streams

compressor

Frame buffer compression buffer. Seestructdm_compressor_info

fw_dmcu

Reference to DMCU firmware

dmcu_fw_version

Version of the DMCU firmware

soc_bounding_box

gpu_info FW provided soc bounding boxstructor 0 if notavailable in FW

active_vblank_irq_count

number of currently active vblank irqs

secure_display_ctx

Store secure display relevant info. e.g. the ROI information, the work_struct to command dmub, etc.

hpd_rx_offload_wq

Work queue to offload works of hpd_rx_irq

mst_encoders

fake encoders used for DP MST.

force_timing_sync

set via debugfs. When set, indicates that all connecteddisplays will be forced to synchronize.

disable_hpd_irq

disables all HPD and HPD RX interrupt handling in thedriver when true

dmcub_trace_event_en

enable dmcub trace events

da_list

DAL fb memory allocation list, for communication with SMU.

dmub_aux_transfer_done

structcompletion used to indicate when DMUBtransfers are done

delayed_hpd_wq

work queue used to delay DMUB HPD work

brightness

cached backlight values.

actual_brightness

last successfully applied backlight values.

aux_hpd_discon_quirk

quirk for hpd discon while aux is on-going.occurred on certain intel platform

edp0_on_dp1_quirk

quirk for platforms that put edp0 on DP1.

dpia_aux_lock

Guards access to DPIA AUX

bb_from_dmub

Bounding box data read from dmub during early initialization for DCN4+Data is stored as a byte array that should be casted to the appropriate bb struct

oem_i2c

OEM i2c bus

fused_io

dmub fused io interface

structamdgpu_hdmi_vsdb_info

Keep track of the VSDB info

Definition:

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;};

Members

amd_vsdb_version

Vendor Specific Data Block Version, should beused to determine which Vendor Specific InfoFrame (VSIF) to send.

freesync_supported

FreeSync Supported.

min_refresh_rate_hz

FreeSync Minimum Refresh Rate in Hz.

max_refresh_rate_hz

FreeSync Maximum Refresh Rate in Hz

replay_mode

Replay supported

Description

AMDGPU supports FreeSync over HDMI by using the VSDB section, and thisstructis useful to keep track of the display-specific information aboutFreeSync.

Lifecycle

DM (and consequently DC) is registered in the amdgpu base driver as a IPblock. When CONFIG_DRM_AMD_DC is enabled, the DM device IP block is added tothe base driver’s device list to be initialized and torn down accordingly.

The functions to do so are provided as hooks instructamd_ip_funcs.

intdm_hw_init(structamdgpu_ip_block*ip_block)

Initialize DC device

Parameters

structamdgpu_ip_block*ip_block

Pointer to the amdgpu_ip_block for this hw instance.

Description

Initialize thestructamdgpu_display_manager device. This involves callingthe initializers of each DM component, then populating thestructwith them.

Although the function implies hardware initialization, both hardware andsoftware are initialized here. Splitting them out to their relevant inithooks is a future TODO item.

Some notable things that are initialized here:

  • Display Core, both software and hardware

  • DC modules that we need (freesync and color management)

  • DRM software states

  • Interrupt sources and handlers

  • Vblank support

  • Debug FS entries, if enabled

intdm_hw_fini(structamdgpu_ip_block*ip_block)

Teardown DC device

Parameters

structamdgpu_ip_block*ip_block

Pointer to the amdgpu_ip_block for this hw instance.

Description

Teardown components withinstructamdgpu_display_manager that requirecleanup. This involves cleaning up the DRM device, DC, and any modules thatwere loaded. Also flush IRQ workqueues and disable them.

Interrupts

DM provides another layer of IRQ management on top of what the base driveralready provides. This is something that could be cleaned up, and is afuture TODO item.

The base driver provides IRQ source registration with DRM, handlerregistration into the base driver’s IRQ table, and a handler callbackamdgpu_irq_handler(), with which DRM calls on interrupts. This generichandler looks up the IRQ table, and calls the respectiveamdgpu_irq_src_funcs.process hookups.

What DM provides on top are two IRQ tables specifically for top-half andbottom-half IRQ handling, with the bottom-half implementing workqueues:

They override the base driver’s IRQ table, and the effect can be seenin the hooks that DM provides foramdgpu_irq_src_funcs.process. Theyare all set to the DM generic handleramdgpu_dm_irq_handler(), which looks upDM’s IRQ tables. However, in order for base driver to recognize this hook, DMstill needs to register the IRQ with the base driver. Seedce110_register_irq_handlers() anddcn10_register_irq_handlers().

To expose DC’s hardware interrupt toggle to the base driver, DM implementsamdgpu_irq_src_funcs.set hooks. Base driver calls it throughamdgpu_irq_update() to enable or disable the interrupt.

structamdgpu_dm_irq_handler_data

Data for DM interrupt handlers.

Definition:

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;};

Members

list

Linked list entry referencing the next/previous handler

handler

Handler function

handler_arg

Argument passed to the handler when triggered

dm

DM which this handler belongs to

irq_source

DC interrupt source that this handler is registered for

work

work struct

voiddm_irq_work_func(structwork_struct*work)

Handle an IRQ outside of the interrupt handler proper.

Parameters

structwork_struct*work

work struct

voidunregister_all_irq_handlers(structamdgpu_device*adev)

Cleans up handlers from the DM IRQ table

Parameters

structamdgpu_device*adev

The base driver device containing the DM device

Description

Go through low and high context IRQ tables and deallocate handlers.

void*amdgpu_dm_irq_register_interrupt(structamdgpu_device*adev,structdc_interrupt_params*int_params,void(*ih)(void*),void*handler_args)

Register a handler within DM.

Parameters

structamdgpu_device*adev

The base driver device containing the DM device.

structdc_interrupt_params*int_params

Interrupt parameters containing the source, and handler context

void(*ih)(void*)

Function pointer to the interrupt handler to register

void*handler_args

Arguments passed to the handler when the interrupt occurs

Description

Register an interrupt handler for the given IRQ source, under the givencontext. The context can either be high or low. High context handlers areexecuted directly within ISR context, while low context is executed within aworkqueue, thereby allowing operations that sleep.

Registered handlers are called in a FIFO manner, i.e. the most recentlyregistered handler will be called first.

Return

Handler datastructamdgpu_dm_irq_handler_data containing the IRQsource, handler function, and args

voidamdgpu_dm_irq_unregister_interrupt(structamdgpu_device*adev,enumdc_irq_sourceirq_source,void*ih)

Remove a handler from the DM IRQ table

Parameters

structamdgpu_device*adev

The base driver device containing the DM device

enumdc_irq_sourceirq_source

IRQ source to remove the given handler from

void*ih

Function pointer to the interrupt handler to unregister

Description

Go through both low and high context IRQ tables, and find the given handlerfor the given irq source. If found, remove it. Otherwise, do nothing.

intamdgpu_dm_irq_init(structamdgpu_device*adev)

Initialize DM IRQ management

Parameters

structamdgpu_device*adev

The base driver device containing the DM device

Description

Initialize DM’s high and low context IRQ tables.

The N by M table contains N IRQ sources, with Mstructamdgpu_dm_irq_handler_data hooked together in a linked list. Thelist_heads are initialized here. When an interrupt n is triggered, all mhandlers are called in sequence, FIFO according to registration order.

The low context table requires special steps to initialize, since handlerswill be deferred to a workqueue. Seestructirq_list_head.

voidamdgpu_dm_irq_fini(structamdgpu_device*adev)

Tear down DM IRQ management

Parameters

structamdgpu_device*adev

The base driver device containing the DM device

Description

Flush all work within the low context IRQ table.

intamdgpu_dm_irq_handler(structamdgpu_device*adev,structamdgpu_irq_src*source,structamdgpu_iv_entry*entry)

Generic DM IRQ handler

Parameters

structamdgpu_device*adev

amdgpu base driver device containing the DM device

structamdgpu_irq_src*source

Unused

structamdgpu_iv_entry*entry

Data about the triggered interrupt

Description

Calls all registered high irq work immediately, and schedules work for lowirq. The DM IRQ table is used to find the corresponding handlers.

voidamdgpu_dm_hpd_init(structamdgpu_device*adev)

hpd setup callback.

Parameters

structamdgpu_device*adev

amdgpu_device pointer

Description

Setup the hpd pins used by the card (evergreen+).Enable the pin, set the polarity, and enable the hpd interrupts.

voidamdgpu_dm_hpd_fini(structamdgpu_device*adev)

hpd tear down callback.

Parameters

structamdgpu_device*adev

amdgpu_device pointer

Description

Tear down the hpd pins used by the card (evergreen+).Disable the hpd interrupts.

voiddm_pflip_high_irq(void*interrupt_params)

Handle pageflip interrupt

Parameters

void*interrupt_params

ignored

Description

Handles the pageflip interrupt by notifying all interested partiesthat the pageflip has been completed.

voiddm_crtc_high_irq(void*interrupt_params)

Handles CRTC interrupt

Parameters

void*interrupt_params

used for determining the CRTC instance

Description

Handles the CRTC/VSYNC interrupt by notfying DRM’s VBLANKevent handler.

Atomic Implementation

WIP

voidamdgpu_dm_atomic_commit_tail(structdrm_atomic_state*state)

AMDgpu DM’s commit tail implementation.

Parameters

structdrm_atomic_state*state

The atomic state to commit

Description

This will tell DC to commit the constructed DC state from atomic_check,programming the hardware. Any failures here implies a hardware failure, sinceatomic check should have filtered anything non-kosher.

intamdgpu_dm_atomic_check(structdrm_device*dev,structdrm_atomic_state*state)

Atomic check implementation for AMDgpu DM.

Parameters

structdrm_device*dev

The DRM device

structdrm_atomic_state*state

The atomic state to commit

Description

Validate that the given atomic state is programmable by DC into hardware.This involves constructing astructdc_state reflecting the new hardwarestate we wish to commit, then querying DC to see if it is programmable. It’simportant not to modify the existing DC state. Otherwise, atomic_checkmay unexpectedly commit hardware changes.

When validating the DC state, it’s important that the right locks areacquired. For full updates case which removes/adds/updates streams on oneCRTC while flipping on another CRTC, acquiring global lock will guaranteethat any such full update commit will wait for completion of any outstandingflip using DRMs synchronization events.

Note that DM adds the affected connectors for all CRTCs in state, when thatmight not seem necessary. This is because DC stream creation requires theDC sink, which is tied to the DRM connector state. Cleaning this up shouldbe possible but non-trivial - a possible TODO item.

Return

-Error code if validation failed.

Color Management Properties

We have three types of color management in the AMD display driver.1. the legacydrm_crtc DEGAMMA, CTM, and GAMMA properties2. AMD driver private color management ondrm_plane anddrm_crtc3. AMD plane color pipeline

The CRTC properties are the original color management. When they wereimplemented per-plane color management was not a thing yet. Becauseof that we could get away with plumbing the DEGAMMA and CTMproperties to pre-blending HW functions. This is incompatible withper-plane color management, such as via the AMD private properties orthe new drm_plane color pipeline. The only compatible CRTC propertywith per-plane color management is the GAMMA property as it isapplied post-blending.

The AMD driver private color management properties are only exposedwhen the kernel is built explicitly with -DAMD_PRIVATE_COLOR. Theyare temporary building blocks on the path to full-fledgeddrm_planeanddrm_crtc color pipelines and lay the driver’s groundwork for thecolor pipelines.

The AMD plane color pipeline describes AMD’sdrm_colorops via thedrm_plane’s COLOR_PIPELINE property.

drm_crtc Properties

The DC interface to HW gives us the following color management blocksper pipe (surface):

  • Input gamma LUT (de-normalized)

  • Input CSC (normalized)

  • Surface degamma LUT (normalized)

  • Surface CSC (normalized)

  • Surface regamma LUT (normalized)

  • Output CSC (normalized)

But these aren’t a direct mapping to DRM color properties. Thecurrent DRM interface exposes CRTC degamma, CRTC CTM and CRTC regammawhile our hardware is essentially giving:

Plane CTM -> Plane degamma -> Plane CTM -> Plane regamma -> Plane CTM

The input gamma LUT block isn’t really applicable here since itoperates on the actual input data itself rather than the HW fprepresentation. The input and output CSC blocks are technicallyavailable to use as part of the DC interface but are typically usedinternally by DC for conversions between color spaces. These could beblended together with user adjustments in the future but for nowthese should remain untouched.

The pipe blending also happens after these blocks so we don’tactually support any CRTC props with correct blending with multipleplanes - but we can still support CRTC color management properties inDM in most single plane cases correctly with clever management of theDC interface in DM.

As per DRM documentation, blocks should be in hardware bypass whentheir respective property is set to NULL. A linear DGM/RGM LUT shouldalso considered as putting the respective block into bypass mode.

This means that the following configuration is assumed to be thedefault:

Plane DGM Bypass -> Plane CTM Bypass -> Plane RGM Bypass -> ... CRTCDGM Bypass -> CRTC CTM Bypass -> CRTC RGM Bypass

AMD Private Color Management on drm_plane

The AMD private color management properties on adrm_plane are:

  • AMD_PLANE_DEGAMMA_LUT

  • AMD_PLANE_DEGAMMA_LUT_SIZE

  • AMD_PLANE_DEGAMMA_TF

  • AMD_PLANE_HDR_MULT

  • AMD_PLANE_CTM

  • AMD_PLANE_SHAPER_LUT

  • AMD_PLANE_SHAPER_LUT_SIZE

  • AMD_PLANE_SHAPER_TF

  • AMD_PLANE_LUT3D

  • AMD_PLANE_LUT3D_SIZE

  • AMD_PLANE_BLEND_LUT

  • AMD_PLANE_BLEND_LUT_SIZE

  • AMD_PLANE_BLEND_TF

The AMD private color management property on adrm_crtc is:

  • AMD_CRTC_REGAMMA_TF

Use of these properties is discouraged.

AMD plane color pipeline

The AMDdrm_plane color pipeline is advertised for DCN generations3.0 and newer. It exposes these elements in this order:

  1. 1D curve colorop

  2. Multiplier

  3. 3x4 CTM

  4. 1D curve colorop

  5. 1D LUT

  6. 3D LUT

  7. 1D curve colorop

  8. 1D LUT

The multiplier (#2) is a simple multiplier that is applied to allchannels.

The 3x4 CTM (#3) is a simple 3x4 matrix.

#1, and #7 are non-linear to linear curves. #4 is a linear tonon-linear curve. They support sRGB, PQ, and BT.709/BT.2020 EOTFs ortheir inverse.

The 1D LUTs (#5 and #8) are plain 4096 entry LUTs.

The 3DLUT (#6) is a tetrahedrally interpolated 17 cube LUT.

voidamdgpu_dm_init_color_mod(void)

Initialize the color module.

Parameters

void

no arguments

Description

We’re not using the full color module, only certain components.Only call setup functions for components that we need.

conststructdrm_color_lut*__extract_blob_lut(conststructdrm_property_blob*blob,uint32_t*size)

Extracts the DRM lut and lut size from a blob.

Parameters

conststructdrm_property_blob*blob

DRM color mgmt property blob

uint32_t*size

lut size

Return

DRM LUT or NULL

conststructdrm_color_lut32*__extract_blob_lut32(conststructdrm_property_blob*blob,uint32_t*size)

Extracts the DRM lut and lut size from a blob.

Parameters

conststructdrm_property_blob*blob

DRM color mgmt property blob

uint32_t*size

lut size

Return

DRM LUT or NULL

bool__is_lut_linear(conststructdrm_color_lut*lut,uint32_tsize)

check if the given lut is a linear mapping of values

Parameters

conststructdrm_color_lut*lut

given lut to check values

uint32_tsize

lut size

Description

It is considered linear if the lut represents:f(a) = (0xFF00/MAX_COLOR_LUT_ENTRIES-1)a; for integer a in [0,MAX_COLOR_LUT_ENTRIES)

Return

True if the given lut is a linear mapping of values, i.e. it acts like abypass LUT. Otherwise, false.

void__drm_lut_to_dc_gamma(conststructdrm_color_lut*lut,structdc_gamma*gamma,boolis_legacy)

convert the drm_color_lut to dc_gamma.

Parameters

conststructdrm_color_lut*lut

DRM lookup table for color conversion

structdc_gamma*gamma

DC gamma to set entries

boolis_legacy

legacy or atomic gamma

Description

The conversion depends on the size of the lut - whether or not it’s legacy.

void__drm_lut32_to_dc_gamma(conststructdrm_color_lut32*lut,structdc_gamma*gamma)

convert the drm_color_lut to dc_gamma.

Parameters

conststructdrm_color_lut32*lut

DRM lookup table for color conversion

structdc_gamma*gamma

DC gamma to set entries

Description

The conversion depends on the size of the lut - whether or not it’s legacy.

void__drm_ctm_to_dc_matrix(conststructdrm_color_ctm*ctm,structfixed31_32*matrix)

converts a DRM CTM to a DC CSC float matrix

Parameters

conststructdrm_color_ctm*ctm

DRM color transformation matrix

structfixed31_32*matrix

DC CSC float matrix

Description

The matrix needs to be a 3x4 (12 entry) matrix.

void__drm_ctm_3x4_to_dc_matrix(conststructdrm_color_ctm_3x4*ctm,structfixed31_32*matrix)

converts a DRM CTM 3x4 to a DC CSC float matrix

Parameters

conststructdrm_color_ctm_3x4*ctm

DRM color transformation matrix with 3x4 dimensions

structfixed31_32*matrix

DC CSC float matrix

Description

The matrix needs to be a 3x4 (12 entry) matrix.

int__set_legacy_tf(structdc_transfer_func*func,conststructdrm_color_lut*lut,uint32_tlut_size,boolhas_rom)

Calculates the legacy transfer function

Parameters

structdc_transfer_func*func

transfer function

conststructdrm_color_lut*lut

lookup table that defines the color space

uint32_tlut_size

size of respective lut

boolhas_rom

if ROM can be used for hardcoded curve

Description

Only for sRGB input space

Return

0 in case of success, -ENOMEM if fails

int__set_output_tf(structdc_transfer_func*func,conststructdrm_color_lut*lut,uint32_tlut_size,boolhas_rom)

calculates the output transfer function based on expected input space.

Parameters

structdc_transfer_func*func

transfer function

conststructdrm_color_lut*lut

lookup table that defines the color space

uint32_tlut_size

size of respective lut

boolhas_rom

if ROM can be used for hardcoded curve

Return

0 in case of success. -ENOMEM if fails.

int__set_output_tf_32(structdc_transfer_func*func,conststructdrm_color_lut32*lut,uint32_tlut_size,boolhas_rom)

calculates the output transfer function based on expected input space.

Parameters

structdc_transfer_func*func

transfer function

conststructdrm_color_lut32*lut

lookup table that defines the color space

uint32_tlut_size

size of respective lut

boolhas_rom

if ROM can be used for hardcoded curve

Return

0 in case of success. -ENOMEM if fails.

int__set_input_tf(structdc_color_caps*caps,structdc_transfer_func*func,conststructdrm_color_lut*lut,uint32_tlut_size)

calculates the input transfer function based on expected input space.

Parameters

structdc_color_caps*caps

dc color capabilities

structdc_transfer_func*func

transfer function

conststructdrm_color_lut*lut

lookup table that defines the color space

uint32_tlut_size

size of respective lut.

Return

0 in case of success. -ENOMEM if fails.

int__set_input_tf_32(structdc_color_caps*caps,structdc_transfer_func*func,conststructdrm_color_lut32*lut,uint32_tlut_size)

calculates the input transfer function based on expected input space.

Parameters

structdc_color_caps*caps

dc color capabilities

structdc_transfer_func*func

transfer function

conststructdrm_color_lut32*lut

lookup table that defines the color space

uint32_tlut_size

size of respective lut.

Return

0 in case of success. -ENOMEM if fails.

intamdgpu_dm_verify_lut3d_size(structamdgpu_device*adev,structdrm_plane_state*plane_state)

verifies if 3D LUT is supported and if user shaper and 3D LUTs match the hw supported size

Parameters

structamdgpu_device*adev

amdgpu device

structdrm_plane_state*plane_state

the DRM plane state

Description

Verifies if pre-blending (DPP) 3D LUT is supported by the HW (DCN 2.0 ornewer) and if the user shaper and 3D LUTs match the supported size.

Return

0 on success. -EINVAL if lut size are invalid.

intamdgpu_dm_verify_lut_sizes(conststructdrm_crtc_state*crtc_state)

verifies if DRM luts match the hw supported sizes

Parameters

conststructdrm_crtc_state*crtc_state

the DRM CRTC state

Description

Verifies that the Degamma and Gamma LUTs attached to thecrtc_stateare of the expected size.

Return

0 on success. -EINVAL if any lut sizes are invalid.

intamdgpu_dm_check_crtc_color_mgmt(structdm_crtc_state*crtc,boolcheck_only)

Check if DRM color props are programmable by DC.

Parameters

structdm_crtc_state*crtc

amdgpu_dm crtc state

boolcheck_only

only check color state without update dc stream

Description

This function just verifies CRTC LUT sizes, if there is enough space foroutput transfer function and if its parameters can be calculated by AMDcolor module. It also adjusts some settings for programming CRTC degamma atplane stage, using plane DGM block.

The RGM block is typically more fully featured and accurate acrossall ASICs - DCE can’t support a custom non-linear CRTC DGM.

For supporting both plane level color management and CRTC level colormanagement at once we have to either restrict the usage of some CRTCproperties or blend adjustments together.

Return

0 on success. Error code if validation fails.

intamdgpu_dm_update_crtc_color_mgmt(structdm_crtc_state*crtc)

Maps DRM color management to DC stream.

Parameters

structdm_crtc_state*crtc

amdgpu_dm crtc state

Description

With no plane level color management properties we’re free to use anyof the HW blocks as long as the CRTC CTM always comes before theCRTC RGM and after the CRTC DGM.

  • The CRTC RGM block will be placed in the RGM LUT block if it is non-linear.

  • The CRTC DGM block will be placed in the DGM LUT block if it is non-linear.

  • The CRTC CTM will be placed in the gamut remap block if it is non-linear.

The RGM block is typically more fully featured and accurate acrossall ASICs - DCE can’t support a custom non-linear CRTC DGM.

For supporting both plane level color management and CRTC level colormanagement at once we have to either restrict the usage of CRTC propertiesor blend adjustments together.

Return

0 on success. Error code if setup fails.

intamdgpu_dm_update_plane_color_mgmt(structdm_crtc_state*crtc,structdrm_plane_state*plane_state,structdc_plane_state*dc_plane_state)

Maps DRM color management to DC plane.

Parameters

structdm_crtc_state*crtc

amdgpu_dm crtc state

structdrm_plane_state*plane_state

DRM plane state

structdc_plane_state*dc_plane_state

target DC surface

Description

Update the underlying dc_stream_state’s input transfer function (ITF) inpreparation for hardware commit. The transfer function used depends onthe preparation done on the stream for color management.

Return

0 on success. -ENOMEM if mem allocation fails.

DC Color Capabilities between DCN generations

DRM/KMS framework defines three CRTC color correction properties: degamma,color transformation matrix (CTM) and gamma, and two properties for degamma andgamma LUT sizes. AMD DC programs some of the color correction featurespre-blending but DRM/KMS has not per-plane color correction properties.

In general, the DRM CRTC color properties are programmed to DC, as follows:CRTC gamma after blending, and CRTC degamma pre-blending. Although CTM isprogrammed after blending, it is mapped to DPP hw blocks (pre-blending). Othercolor caps available in the hw is not currently exposed by DRM interface andare bypassed.

Color management caps (DPP and MPC)

Modules/color calculates various color operations which are translated toabstracted HW. DCE 5-12 had almost no important changes, but starting withDCN1, every new generation comes with fairly major differences in colorpipeline. Therefore, we abstract color pipe capabilities so modules/DM candecide mapping to HW block based on logical capabilities.

MAX_SURFACES

MAX_SURFACES

representative of the upper bound of surfaces that can be piped to a single CRTC

MAX_PLANES

MAX_PLANES

representative of the upper bound of planes that are supported by the HW

structrom_curve_caps

predefined transfer function caps for degamma and regamma

Definition:

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;};

Members

srgb

RGB color space transfer func

bt2020

BT.2020 transfer func

gamma2_2

standard gamma

pq

perceptual quantizer transfer function

hlg

hybrid log–gamma transfer function

structdpp_color_caps

color pipeline capabilities for display pipe and plane blocks

Definition:

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;};

Members

dcn_arch

all DCE generations treated the same

input_lut_shared

shared with DGAM. Input LUT is different than most LUTs,just plain 256-entry lookup

icsc

input color space conversion

dgam_ram

programmable degamma LUT

post_csc

post color space conversion, before gamut remap

gamma_corr

degamma correction

hw_3d_lut

3D LUT support. It implies a shaper LUT before. It may be sharedwith MPC by setting mpc:shared_3d_lut flag

ogam_ram

programmable out/blend gamma LUT

ocsc

output color space conversion

dgam_rom_for_yuv

pre-defined degamma LUT for YUV planes

dgam_rom_caps

pre-definied curve caps for degamma 1D LUT

ogam_rom_caps

pre-definied curve caps for regamma 1D LUT

Note

hdr_mult and gamut remap (CTM) are always available in DPP (in that order)

structmpc_color_caps

color pipeline capabilities for multiple pipe and plane combined blocks

Definition:

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 num_rmcm_3dluts : 3;    uint16_t shared_3d_lut:1;    struct rom_curve_caps ogam_rom_caps;    struct lut3d_caps mcm_3d_lut_caps;    struct lut3d_caps rmcm_3d_lut_caps;    bool preblend;};

Members

gamut_remap

color transformation matrix

ogam_ram

programmable out gamma LUT

ocsc

output color space conversion matrix

num_3dluts

MPC 3D LUT; always assumes a preceding shaper LUT

num_rmcm_3dluts

number of RMCM 3D LUTS; always assumes a preceding shaper LUT

shared_3d_lut

shared 3D LUT flag. Can be either DPP or MPC, but singleinstance

ogam_rom_caps

pre-definied curve caps for regamma 1D LUT

mcm_3d_lut_caps

HW support cap for MCM LUT memory

rmcm_3d_lut_caps

HW support cap for RMCM LUT memory

preblend

whether color manager supports preblend with MPC

structdc_color_caps

color pipes capabilities for DPP and MPC hw blocks

Definition:

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

Members

dpp

color pipes caps for DPP

mpc

color pipes caps for MPC

enumpipe_split_policy

Pipe split strategy supported by DCN

Constants

MPC_SPLIT_DYNAMIC

DC will automatically decide how to split thepipe in order to bring the best trade-off between performance andpower consumption. This is the recommended option.

MPC_SPLIT_AVOID

Avoid pipe split, which means that DC will nottry any sort of split optimization.

MPC_SPLIT_AVOID_MULT_DISP

With this option, DC will only try tooptimize the pipe utilization when using a single display; if theuser connects to a second display, DC will avoid pipe split.

Description

Thisenumis used to define the pipe split policy supported by DCN. Bydefault, DC favors MPC_SPLIT_DYNAMIC.

structdc_validation_set

Struct to store surface/stream associations for validation

Definition:

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

Members

stream

Stream state properties

plane_states

Surface state

plane_count

Total of active planes

voiddc_get_underflow_debug_data_for_otg(structdc*dc,intprimary_otg_inst,structdc_underflow_debug_data*out_data)

Retrieve underflow debug data.

Parameters

structdc*dc

Pointer to the display core context.

intprimary_otg_inst

Instance index of the primary OTG that underflowed.

structdc_underflow_debug_data*out_data

Pointer to a dc_underflow_debug_datastructto be filled with debug information.

Description

This function collects and logs underflow-related HW states when underflow happens,including OTG underflow status, current read positions, frame count, and per-HUBP debug data.The results are stored in the provided out_data structure for further analysis or logging.

booldc_capture_register_software_state(structdc*dc,structdc_register_software_state*state)

Capture software state for register programming

Parameters

structdc*dc

DC context containing current display configuration

structdc_register_software_state*state

Pointer to dc_register_software_state structure to populate

Description

Extracts all software state variables that are used to program hardware registerfields across the display driver pipeline. This provides a complete snapshotof the software configuration that drives hardware register programming.

The function traverses the DC context and extracts values from:- Stream configurations (timing, format, DSC settings)- Plane states (surface format, rotation, scaling, cursor)- Pipe contexts (resource allocation, blending, viewport)- Clock manager (display clocks, DPP clocks, pixel clocks)- Resource context (DET buffer allocation, ODM configuration)

This is essential for underflow debugging as it captures the exact softwarestate that determines how registers are programmed, allowing analysis ofwhether underflow is caused by incorrect register programming or timing issues.

Return

true if state was successfully captured, false on error

booldc_get_qos_info(structdc*dc,structdc_qos_info*info)

Retrieve Quality of Service (QoS) information from display core

Parameters

structdc*dc

DC context containing current display configuration

structdc_qos_info*info

Pointer to dc_qos_info structure to populate with QoS metrics

Description

This function retrieves QoS metrics from the display core that can be used bybenchmark tools to analyze display system performance. The function may takeseveral milliseconds to execute due to hardware measurement requirements.

QoS information includes:- Bandwidth bounds (lower limits in Mbps)- Latency bounds (upper limits in nanoseconds)- Hardware-measured bandwidth metrics (peak/average in Mbps)- Hardware-measured latency metrics (maximum/average in nanoseconds)

The function will populate the provided dc_qos_info structure with currentQoS measurements. If hardware measurement functions are not available forthe current DCN version, the function returns false with zero’d info structure.

Return

true if QoS information was successfully retrieved, false if measurementfunctions are unavailable or hardware measurements cannot be performed

The color pipeline has undergone major changes between DCN hardwaregenerations. What’s possible to do before and after blending depends onhardware capabilities, as illustrated below by the DCN 2.0 and DCN 3.0 familiesschemas.

DCN 2.0 family color caps and mapping

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

DCN 3.0 family color caps and mapping

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

Blend Mode Properties

Pixel blend mode is a DRM plane composition property ofdrm_plane used todescribes how pixels from a foreground plane (fg) are composited with thebackground plane (bg). Here, we present main concepts of DRM blend mode to helpto understand how this property is mapped to AMD DC interface. See more aboutthis DRM property and the alpha blending equations inDRM PlaneComposition Properties.

Basically, a blend mode sets the alpha blending equation for planecomposition that fits the mode in which the alpha channel affects the state ofpixel color values and, therefore, the resulted pixel color. Forexample, consider the following elements of the alpha blending equation:

  • fg.rgb: Each of the RGB component values from the foreground’s pixel.

  • fg.alpha: Alpha component value from the foreground’s pixel.

  • bg.rgb: Each of the RGB component values from the background.

  • plane_alpha: Plane alpha value set by theplane “alpha” property, seemore inDRM Plane Composition Properties.

in the basic alpha blending equation:

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

the alpha channel value of each pixel in a plane is ignored and only the planealpha affects the resulted pixel color values.

DRM has three blend mode to define the blend formula in the plane composition:

  • None: Blend formula that ignores the pixel alpha.

  • Pre-multiplied: Blend formula that assumes the pixel color values in aplane was already pre-multiplied by its own alpha channel before storage.

  • Coverage: Blend formula that assumes the pixel color values were notpre-multiplied with the alpha channel values.

and pre-multiplied is the default pixel blend mode, that means, when no blendmode property is created or defined, DRM considers the plane’s pixels haspre-multiplied color values. On IGT GPU tools, the kms_plane_alpha_blend testprovides a set of subtests to verify plane alpha and blend mode properties.

The DRM blend mode and its elements are then mapped by AMDGPU display manager(DM) to program the blending configuration of the Multiple Pipe/Plane Combined(MPC), as follows:

structmpcc_blnd_cfg

MPCC blending configuration

Definition:

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;};

Members

black_color

background color.

alpha_mode

alpha blend mode (MPCC_ALPHA_BLND_MODE).

pre_multiplied_alpha

Whether pixel color values were pre-multiplied by the alpha channel(MPCC_ALPHA_MULTIPLIED_MODE).

global_gain

Used when blend mode considers both pixel alpha and plane.

global_alpha

Plane alpha value.

overlap_only

Whether overlapping of different planes is allowed.

bottom_gain_mode

Blend mode for bottom gain setting.

background_color_bpc

Background color for bpc.

top_gain

Top gain setting.

bottom_inside_gain

Blend mode for bottom inside.

bottom_outside_gain

Blend mode for bottom outside.

Therefore, the blending configuration for a single MPCC instance on the MPCtree is defined bympcc_blnd_cfg, wherepre_multiplied_alpha is the alpha pre-multiplied mode flag used tosetMPCC_ALPHA_MULTIPLIED_MODE. It controls whether alpha ismultiplied (true/false), being only true for DRM pre-multiplied blend mode.mpcc_alpha_blend_mode defines the alpha blend mode regarding pixelalpha and plane alpha values. It sets one of the three modes forMPCC_ALPHA_BLND_MODE, as described below.

enummpcc_alpha_blend_mode

define the alpha blend mode regarding pixel alpha and plane alpha values

Constants

MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA

per pixel alpha using DPPalpha value

MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN

perpixel alpha using DPP alpha value multiplied by a global gain (planealpha)

MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA

global alpha value, ignorespixel alpha and consider only plane alpha

DM then maps the elements ofenummpcc_alpha_blend_mode to those in the DRMblend formula, as follows:

  • MPC pixel alpha matchesDRM fg.alpha as the alpha component valuefrom the plane’s pixel

  • MPC global alpha matchesDRM plane_alpha when the pixel alpha shouldbe ignored and, therefore, pixel values are not pre-multiplied

  • MPC global gain assumesMPC global alpha value when bothDRMfg.alpha andDRM plane_alpha participate in the blend equation

In short,fg.alpha is ignored by selectingMPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA. On the other hand, (plane_alpha *fg.alpha) component becomes available by selectingMPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN. And theMPCC_ALPHA_MULTIPLIED_MODE defines if the pixel color values arepre-multiplied by alpha or not.

Blend configuration flow

The alpha blending equation is configured from DRM to DC interface by thefollowing path:

  1. When updating adrm_plane_state, DM callsamdgpu_dm_plane_fill_blending_from_plane_state() that mapsdrm_plane_state attributes todc_plane_infostructto be handled in theOS-agnostic component (DC).

  2. On DC interface,structmpcc_blnd_cfg programs theMPCC blend configuration considering thedc_plane_info input from DPP.