STRUCT DPU_ENCODER_VIRT(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct dpu_encoder_virt(9) β€” the kernel API manual, but make it make sense

okay so bestie, welcome to the struct dpu_encoder_virt(9) page from the Kernel API Manual πŸ’– this one lives in ./drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c and honestly? it's giving "main character of the display pipeline" energy, no cap.

✨ NAME ✨

struct dpu_encoder_virt β€” the virtual encoder, aka the container of one or more physical encoders. 🫢

The virtual encoder manages exactly one "logical" display. The physical encoders each manage one intf block, and each one is tied to a specific panel/sub-panel. The virtual encoder defers as much as possible to the physical encoders (she delegates, she's a manager πŸ’…), and she registers herself with the DRM Framework as the encoder. Periodt.

🌈 SYNOPSIS 🌈

struct dpu_encoder_virt {
    struct drm_encoder base;
    spinlock_t enc_spinlock;
    bool enabled;
    bool commit_done_timedout;
    unsigned int num_phys_encs;
    struct dpu_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL];
    struct dpu_encoder_phys *cur_master;
    struct dpu_encoder_phys *cur_slave;
    struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
    struct dpu_hw_cwb *hw_cwb[MAX_CWB_PER_ENC];
    struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
    unsigned int dsc_mask;
    unsigned int cwb_mask;
    bool intfs_swapped;
    struct drm_crtc *crtc;
    struct drm_connector *connector;
    struct mutex enc_lock;
    unsigned long frame_busy_mask[BITS_TO_LONGS(MAX_PHYS_ENCODERS_PER_VIRTUAL)];
    atomic_t frame_done_timeout_ms;
    atomic_t frame_done_timeout_cnt;
    struct timer_list frame_done_timer;
    struct msm_display_info disp_info;
    bool idle_pc_supported;
    struct mutex rc_lock;
    enum dpu_enc_rc_states rc_state;
    struct delayed_work delayed_off_work;
    struct msm_display_topology topology;
    u32 idle_timeout;
    bool wide_bus_en;
    struct drm_dsc_config *dsc;
};

πŸŽ€ Members πŸŽ€

okay here's the whole cast, one by one, and yes I'm gonna introduce every single one because they all ate πŸ’–

  • base β€” the drm_encoder base class, for registration with DRM. literally her legal name for the framework.
  • enc_spinlock β€” Virtual-Encoder-Wide Spin Lock for IRQ purposes. one lock to rule the interrupts ✨
  • enabled β€” True if the encoder is active, protected by enc_lock. (emphasis on protected, bestie πŸ”’)
  • commit_done_timedout β€” True if there has been a timeout on commit after enabling the encoder. 😭 she timed out, it happens.
  • num_phys_encs β€” the actual number of physical encoders contained. the real count, not the vibe count.
  • phys_encs β€” the container of physical encoders managed. her whole friend group 🫢
  • cur_master β€” pointer to the current master in this mode. Optimization. Only valid after enable, and cleared as disable. so like, only valid while she's on πŸ‘‘
  • cur_slave β€” as above but for the slave encoder. matching set, iconic.
  • hw_pp β€” handle to the pingpong blocks used for the display. Ngl, the number of pingpong blocks can be different than num_phys_encs. don't assume, k?
  • hw_cwb β€” handle to the CWB muxes used for concurrent writeback display. The number of CWB muxes can be different than num_phys_encs too. same energy as above fr fr.
  • hw_dsc β€” handle to the DSC blocks used for the display.
  • dsc_mask β€” bitmask of used DSC blocks. 🎯
  • cwb_mask β€” bitmask of used CWB muxes.
  • intfs_swapped β€” whether or not the phys_enc interfaces have been swapped for partial update right-only cases, such as pingpong split where virtual pingpong does not generate IRQs. (iykyk πŸ’€)
  • crtc β€” pointer to the currently assigned crtc. Normally you would use crtc->state->encoder_mask to determine the link between encoder/crtc β€” BUT in this case we need to track crtc in the disable hook, which is called _after_ encoder_mask is cleared. so yeah, she has to remember things herself. lowkey relatable.
  • connector β€” if a mode is set, a cached pointer to the active connector. caching queen 🧚
  • enc_lock β€” lock around physical encoder create/destroy/enable/disable. the bouncer at the door.
  • frame_busy_mask β€” bitmask tracking which phys_enc we are still busy processing current command. Bit0 = phys_encs[0] etc.
  • frame_done_timeout_ms β€” frame done timeout in ms. ⏱️
  • frame_done_timeout_cnt β€” atomic counter tracking the number of frame done timeouts. yes we're counting them. πŸ’€
  • frame_done_timer β€” watchdog timer for frame done event. she's watching πŸ‘€
  • disp_info β€” local copy of msm_display_info struct.
  • idle_pc_supported β€” indicate if idle power collaps is supported.
  • rc_lock β€” resource control mutex lock to protect virt encoder over various state changes. very demure, very mindful locking.
  • rc_state β€” resource controller state.
  • delayed_off_work β€” delayed worker to schedule disabling of clks and resources after IDLE_TIMEOUT time. procrastination but make it a feature ✨
  • topology β€” topology of the display. the whole layout, the whole aesthetic 🌸
  • idle_timeout β€” idle timeout duration in milliseconds.
  • wide_bus_en β€” wide bus is enabled on this interface. wide bus wide vibes 🚌
  • dsc β€” drm_dsc_config pointer, for DSC-enabled encoders.

πŸ¦‹ SEE ALSO πŸ¦‹

the whole squad, in no particular order (okay it's the original order, don't come for me):


ngl bestie, this page is from the ./drivers/gpu/drm/msm/disp/dpu1 directory, dated October 2026, and it's filed under struct dpu_encoder_virt(9). slay πŸ’…πŸ’– go read the source, it's right there, ily, bye 🫢✨
πŸ“¦ where this page comes from