drm/amd/display - Display Core (DC)

placeholder - general description of supported platforms, what dc is, etc.

Because it is partially shared with other operating systems, the Display CoreDriver is divided in two pieces.

  1. Display Core (DC) contains the OS-agnostic components. Things likehardware programming and resource management are handled here.
  2. Display Manager (DM) contains the OS-dependent components. Hooks to theamdgpu base driver and DRM are implemented here.

It doesn’t help that the entire package is frequently referred to as DC. Butwith the context in mind, it should be clear.

When CONFIG_DRM_AMD_DC is enabled, DC will be initialized by default forsupported ASICs. To force disable, setamdgpu.dc=0 on kernel command line.Likewise, to force enable on unsupported ASICs, setamdgpu.dc=1.

To determine if DC is loaded, search dmesg for the following entry:

DisplayCoreinitializedwith<versionnumberhere>

AMDgpu Display Manager

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

The root control structure isstructamdgpu_display_manager.

structirq_list_head

Linked-list for low context IRQ handlers.

Definition

struct irq_list_head {  struct list_head head;  struct work_struct work;};

Members

head
The list_head withinstructhandler_data
work
A work_struct containing the deferred handler work
structdm_comressor_info

Buffer info used by frame buffer compression

Definition

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

Members

ext_caps
Keep the data struct with 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.

Description

Describe the backlight support for ACPI or eDP AUX.

structamdgpu_display_manager

Central amdgpu display manager device

Definition

struct amdgpu_display_manager {  struct dc *dc;  struct dmub_srv *dmub_srv;  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 irq_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 vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1];  spinlock_t irq_handler_list_table_lock;  struct backlight_device *backlight_dev;  const struct dc_link *backlight_link;  struct amdgpu_dm_backlight_caps backlight_caps;  struct mod_freesync *freesync_module;#ifdef CONFIG_DRM_AMD_DC_HDCP;  struct hdcp_workqueue *hdcp_workqueue;#endif;  struct drm_atomic_state *cached_state;  struct dc_state *cached_dc_state;  struct dm_comressor_info compressor;  const struct firmware *fw_dmcu;  uint32_t dmcu_fw_version;  const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;  struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC];};

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_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.
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.
vupdate_params
Vertical update IRQ parameters, passed to registered handlers whentriggered.
irq_handler_list_table_lock
Synchronizes access to IRQ tables
backlight_dev
Backlight control device
backlight_link
Link on which to control backlight
backlight_caps
Capabilities of the backlight device
freesync_module
Module handling freesync calculations
hdcp_workqueue
AMDGPU content protection queue
cached_state
Caches device atomic state for suspend/resume
cached_dc_state
Cached state of content streams
compressor
Frame buffer compression buffer. Seestructdm_comressor_info
fw_dmcu
Reference to DMCU firmware
dmcu_fw_version
Version of the DMCU firmware
soc_bounding_box
gpu_info FW provided soc bounding box struct or 0 if notavailable in FW
mst_encoders
fake encoders used for DP MST.

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(void * handle)

Initialize DC device

Parameters

void*handle
The base driver device containing the amdgpu_dm device.

Description

Initialize thestructamdgpu_display_manager device. This involves callingthe initializers of each DM component, then populating the struct with 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(void * handle)

Teardown DC device

Parameters

void*handle
The base driver device containing the amdgpu_dm device.

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() and dcn10_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;};

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
voiddm_irq_work_func(struct work_struct * work)

Handle an IRQ outside of the interrupt handler proper.

Parameters

structwork_struct*work
work struct
void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device * adev, struct dc_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(*)(void*)ih
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 IRQ
source, handler function, and args
voidamdgpu_dm_irq_unregister_interrupt(struct amdgpu_device * adev, enum dc_irq_source irq_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(struct amdgpu_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(struct amdgpu_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(struct amdgpu_device * adev, struct amdgpu_irq_src * source, struct amdgpu_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(struct amdgpu_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(struct amdgpu_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. Seedm_determine_update_type_for_commit()

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.

Display Core

WIP