diff options
author | Dave Airlie <airlied@redhat.com> | 2023-10-04 13:55:19 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2023-10-04 13:55:19 +1000 |
commit | 389af786f92ecdff35883551d54bf4e507ffcccb (patch) | |
tree | 6c08f598e39f3ccff1680ec5491408554407a284 /drivers/gpu/drm/i915/display/intel_link_bw.c | |
parent | caacbdc28f545744770fb2caf347b3c4be9a6299 (diff) | |
parent | 3570bd989acc66add5726785058cceffa06b1f54 (diff) |
Merge tag 'drm-intel-next-2023-09-29' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
drm/i915 feature pull for v6.7:
Features and functionality:
- Early Xe2 LPD / Lunarlake (LNL) display enabling (Lucas, Matt, Gustavo,
Stanislav, Luca, Clint, Juha-Pekka, Balasubramani, Ravi)
- Plenty of various DSC improvements and fixes (Ankit)
- Add DSC PPS state readout and verification (Suraj)
- Improve fastsets for VRR, LRR and M/N updates (Ville)
- Use connector->ddc to create (non-DP MST) connector sysfs ddc symlinks (Ville)
- Various DSB improvements, load LUTs using DSB (Ville)
- Improve shared link bandwidth management, starting with FDI (Imre)
- Optimize get param ioctl for PXP status (Alan)
- Remove DG2 pre-production hardware workarounds (Matt)
- Add more RPL P/U PCI IDs (Dnyaneshwar)
- Add new DG2-G12 stepping (Swati)
- Add PSR sink error status to debugfs (Jouni)
- Add DP enhanced framing to crtc state checker (Ville)
Refactoring and cleanups:
- Simplify TileY/Tile4 tiling selftest enumeration (Matt)
- Remove some unused power domain code (Gustavo)
- Check stepping of display IP version rather than MTL platform (Matt)
- DP audio compute config cleanups (Vinod)
- SDVO cleanups and refactoring, more robust failure handling (Ville)
- Color register definition and readout cleanups (Jani)
- Reduce header interdependencies for frontbuffer tracking (Jani)
- Continue replacing struct edid with struct drm_edid (Jani)
- Use source physical address instead of EDID for CEC (Jani)
- Clean up Type-C port lane count functions (Luca)
- Clean up DSC PPS register definitions and readout (Jani)
- Stop using GEM_BUG_ON()/GEM_WARN_ON() in display code (Jani)
- Move more of the display probe to display code (Jani)
- Remove redundant runtime suspended state flag (Jouni)
- Move display info printing to display code (Balasubramani)
- Frontbuffer tracking improvements (Jouni)
- Add trailing newlines to debug logging (Jim Cromie)
- Separate display workarounds from clock gating init (Matt)
- Reduce dmesg log spamming for combo PHY, PLL state, FEC, DP MST (Ville, Imre)
Fixes:
- Fix hotplug poll detect loops via suspend/resume (Imre)
- Fix hotplug detect for forced connectors (Imre)
- Fix DSC first_line_bpg_offset calculation (Suraj)
- Fix debug prints for SDP CRC16 (Arun)
- Fix PXP runtime resume (Alan)
- Fix cx0 PHY lane handling (Gustavo)
- Fix frontbuffer tracking locking in debugfs (Juha-Pekka)
- Fix SDVO detect on some models (Ville)
- Fix SDP split configuration for DP MST (Vinod)
- Fix AUX usage and reads for HDCP on DP MST (Suraj)
- Fix PSR workaround (Jouni)
- Fix redundant AUX power get/put in DP force (Imre)
- Fix ICL DSI TCLK POST by letting hardware handle it (William)
- Fix IRQ reset for XE LP+ (Gustavo)
- Fix h/vsync_end instead of h/vtotal in VBT (Ville)
- Fix C20 PHY msgbus timeout issues (Gustavo)
- Fix pre-TGL FEC pipe A vs. DDI A mixup (Ville)
- Fix FEC state readout for DP MST (Ville)
DRM subsystem core changes:
- Assume sink supports 8 bpc when DSC is supported (Ankit)
- Add drm_edid_is_digital() helper (Jani)
- Parse source physical address from EDID (Jani)
- Add function to attach CEC without EDID (Jani)
- Reorder connector sysfs/debugfs remove (Ville)
- Register connector sysfs ddc symlink later (Ville)
Media subsystem changes:
- Add comments about CEC source physical address usage (Jani)
Merges:
- Backmerge drm-next to get v6.6-rc1 (Jani)
Signed-off-by: Dave Airlie <airlied@redhat.com>
# Conflicts:
# drivers/gpu/drm/i915/i915_drv.h
From: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/87r0mhi7a6.fsf@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_link_bw.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_link_bw.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c new file mode 100644 index 000000000000..c5eb5f242536 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include "i915_drv.h" + +#include "intel_atomic.h" +#include "intel_display_types.h" +#include "intel_fdi.h" +#include "intel_link_bw.h" + +/** + * intel_link_bw_init_limits - initialize BW limits + * @i915: device instance + * @limits: link BW limits + * + * Initialize @limits. + */ +void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits) +{ + enum pipe pipe; + + limits->bpp_limit_reached_pipes = 0; + for_each_pipe(i915, pipe) + limits->max_bpp_x16[pipe] = INT_MAX; +} + +/** + * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe + * @state: atomic state + * @limits: link BW limits + * @pipe_mask: mask of pipes to select from + * @reason: explanation of why bpp reduction is needed + * + * Select the pipe from @pipe_mask with the biggest link bpp value and set the + * maximum of link bpp in @limits below this value. Modeset the selected pipe, + * so that its state will get recomputed. + * + * This function can be called to resolve a link's BW overallocation by reducing + * the link bpp of one pipe on the link and hence reducing the total link BW. + * + * Returns + * - 0 in case of success + * - %-ENOSPC if no pipe can further reduce its link bpp + * - Other negative error, if modesetting the selected pipe failed + */ +int intel_link_bw_reduce_bpp(struct intel_atomic_state *state, + struct intel_link_bw_limits *limits, + u8 pipe_mask, + const char *reason) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + enum pipe max_bpp_pipe = INVALID_PIPE; + struct intel_crtc *crtc; + int max_bpp = 0; + + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) { + struct intel_crtc_state *crtc_state; + int link_bpp; + + if (limits->bpp_limit_reached_pipes & BIT(crtc->pipe)) + continue; + + crtc_state = intel_atomic_get_crtc_state(&state->base, + crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + if (crtc_state->dsc.compression_enable) + link_bpp = crtc_state->dsc.compressed_bpp; + else + /* + * TODO: for YUV420 the actual link bpp is only half + * of the pipe bpp value. The MST encoder's BW allocation + * is based on the pipe bpp value, set the actual link bpp + * limit here once the MST BW allocation is fixed. + */ + link_bpp = crtc_state->pipe_bpp; + + if (link_bpp > max_bpp) { + max_bpp = link_bpp; + max_bpp_pipe = crtc->pipe; + } + } + + if (max_bpp_pipe == INVALID_PIPE) + return -ENOSPC; + + limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1; + + return intel_modeset_pipes_in_mask_early(state, reason, + BIT(max_bpp_pipe)); +} + +/** + * intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum + * @state: atomic state + * @old_limits: link BW limits + * @new_limits: link BW limits + * @pipe: pipe + * + * Set the link bpp limit for @pipe in @new_limits to its value in + * @old_limits and mark this limit as the minimum. This function must be + * called after a pipe's compute config function failed, @old_limits + * containing the bpp limit with which compute config previously passed. + * + * The function will fail if setting a minimum is not possible, either + * because the old and new limits match (and so would lead to a pipe compute + * config failure) or the limit is already at the minimum. + * + * Returns %true in case of success. + */ +bool +intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state, + const struct intel_link_bw_limits *old_limits, + struct intel_link_bw_limits *new_limits, + enum pipe pipe) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + + if (pipe == INVALID_PIPE) + return false; + + if (new_limits->max_bpp_x16[pipe] == + old_limits->max_bpp_x16[pipe]) + return false; + + if (drm_WARN_ON(&i915->drm, + new_limits->bpp_limit_reached_pipes & BIT(pipe))) + return false; + + new_limits->max_bpp_x16[pipe] = + old_limits->max_bpp_x16[pipe]; + new_limits->bpp_limit_reached_pipes |= BIT(pipe); + + return true; +} + +static int check_all_link_config(struct intel_atomic_state *state, + struct intel_link_bw_limits *limits) +{ + /* TODO: Check additional shared display link configurations like MST */ + int ret; + + ret = intel_fdi_atomic_check_link(state, limits); + if (ret) + return ret; + + return 0; +} + +static bool +assert_link_limit_change_valid(struct drm_i915_private *i915, + const struct intel_link_bw_limits *old_limits, + const struct intel_link_bw_limits *new_limits) +{ + bool bpps_changed = false; + enum pipe pipe; + + for_each_pipe(i915, pipe) { + /* The bpp limit can only decrease. */ + if (drm_WARN_ON(&i915->drm, + new_limits->max_bpp_x16[pipe] > + old_limits->max_bpp_x16[pipe])) + return false; + + if (new_limits->max_bpp_x16[pipe] < + old_limits->max_bpp_x16[pipe]) + bpps_changed = true; + } + + /* At least one limit must change. */ + if (drm_WARN_ON(&i915->drm, + !bpps_changed)) + return false; + + return true; +} + +/** + * intel_link_bw_atomic_check - check display link states and set a fallback config if needed + * @state: atomic state + * @new_limits: link BW limits + * + * Check the configuration of all shared display links in @state and set new BW + * limits in @new_limits if there is a BW limitation. + * + * Returns: + * - 0 if the confugration is valid + * - %-EAGAIN, if the configuration is invalid and @new_limits got updated + * with fallback values with which the configuration of all CRTCs + * in @state must be recomputed + * - Other negative error, if the configuration is invalid without a + * fallback possibility, or the check failed for another reason + */ +int intel_link_bw_atomic_check(struct intel_atomic_state *state, + struct intel_link_bw_limits *new_limits) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_link_bw_limits old_limits = *new_limits; + int ret; + + ret = check_all_link_config(state, new_limits); + if (ret != -EAGAIN) + return ret; + + if (!assert_link_limit_change_valid(i915, &old_limits, new_limits)) + return -EINVAL; + + return -EAGAIN; +} |