1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023 Intel Corporation
8 #include "intel_atomic.h"
9 #include "intel_display_types.h"
10 #include "intel_fdi.h"
11 #include "intel_link_bw.h"
14 * intel_link_bw_init_limits - initialize BW limits
15 * @i915: device instance
16 * @limits: link BW limits
20 void intel_link_bw_init_limits(struct drm_i915_private *i915, struct intel_link_bw_limits *limits)
24 limits->bpp_limit_reached_pipes = 0;
25 for_each_pipe(i915, pipe)
26 limits->max_bpp_x16[pipe] = INT_MAX;
30 * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
31 * @state: atomic state
32 * @limits: link BW limits
33 * @pipe_mask: mask of pipes to select from
34 * @reason: explanation of why bpp reduction is needed
36 * Select the pipe from @pipe_mask with the biggest link bpp value and set the
37 * maximum of link bpp in @limits below this value. Modeset the selected pipe,
38 * so that its state will get recomputed.
40 * This function can be called to resolve a link's BW overallocation by reducing
41 * the link bpp of one pipe on the link and hence reducing the total link BW.
44 * - 0 in case of success
45 * - %-ENOSPC if no pipe can further reduce its link bpp
46 * - Other negative error, if modesetting the selected pipe failed
48 int intel_link_bw_reduce_bpp(struct intel_atomic_state *state,
49 struct intel_link_bw_limits *limits,
53 struct drm_i915_private *i915 = to_i915(state->base.dev);
54 enum pipe max_bpp_pipe = INVALID_PIPE;
55 struct intel_crtc *crtc;
58 for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) {
59 struct intel_crtc_state *crtc_state;
62 if (limits->bpp_limit_reached_pipes & BIT(crtc->pipe))
65 crtc_state = intel_atomic_get_crtc_state(&state->base,
67 if (IS_ERR(crtc_state))
68 return PTR_ERR(crtc_state);
70 if (crtc_state->dsc.compression_enable)
71 link_bpp = crtc_state->dsc.compressed_bpp;
74 * TODO: for YUV420 the actual link bpp is only half
75 * of the pipe bpp value. The MST encoder's BW allocation
76 * is based on the pipe bpp value, set the actual link bpp
77 * limit here once the MST BW allocation is fixed.
79 link_bpp = crtc_state->pipe_bpp;
81 if (link_bpp > max_bpp) {
83 max_bpp_pipe = crtc->pipe;
87 if (max_bpp_pipe == INVALID_PIPE)
90 limits->max_bpp_x16[max_bpp_pipe] = to_bpp_x16(max_bpp) - 1;
92 return intel_modeset_pipes_in_mask_early(state, reason,
97 * intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum
98 * @state: atomic state
99 * @old_limits: link BW limits
100 * @new_limits: link BW limits
103 * Set the link bpp limit for @pipe in @new_limits to its value in
104 * @old_limits and mark this limit as the minimum. This function must be
105 * called after a pipe's compute config function failed, @old_limits
106 * containing the bpp limit with which compute config previously passed.
108 * The function will fail if setting a minimum is not possible, either
109 * because the old and new limits match (and so would lead to a pipe compute
110 * config failure) or the limit is already at the minimum.
112 * Returns %true in case of success.
115 intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state *state,
116 const struct intel_link_bw_limits *old_limits,
117 struct intel_link_bw_limits *new_limits,
120 struct drm_i915_private *i915 = to_i915(state->base.dev);
122 if (pipe == INVALID_PIPE)
125 if (new_limits->max_bpp_x16[pipe] ==
126 old_limits->max_bpp_x16[pipe])
129 if (drm_WARN_ON(&i915->drm,
130 new_limits->bpp_limit_reached_pipes & BIT(pipe)))
133 new_limits->max_bpp_x16[pipe] =
134 old_limits->max_bpp_x16[pipe];
135 new_limits->bpp_limit_reached_pipes |= BIT(pipe);
140 static int check_all_link_config(struct intel_atomic_state *state,
141 struct intel_link_bw_limits *limits)
143 /* TODO: Check additional shared display link configurations like MST */
146 ret = intel_fdi_atomic_check_link(state, limits);
154 assert_link_limit_change_valid(struct drm_i915_private *i915,
155 const struct intel_link_bw_limits *old_limits,
156 const struct intel_link_bw_limits *new_limits)
158 bool bpps_changed = false;
161 for_each_pipe(i915, pipe) {
162 /* The bpp limit can only decrease. */
163 if (drm_WARN_ON(&i915->drm,
164 new_limits->max_bpp_x16[pipe] >
165 old_limits->max_bpp_x16[pipe]))
168 if (new_limits->max_bpp_x16[pipe] <
169 old_limits->max_bpp_x16[pipe])
173 /* At least one limit must change. */
174 if (drm_WARN_ON(&i915->drm,
182 * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
183 * @state: atomic state
184 * @new_limits: link BW limits
186 * Check the configuration of all shared display links in @state and set new BW
187 * limits in @new_limits if there is a BW limitation.
190 * - 0 if the confugration is valid
191 * - %-EAGAIN, if the configuration is invalid and @new_limits got updated
192 * with fallback values with which the configuration of all CRTCs
193 * in @state must be recomputed
194 * - Other negative error, if the configuration is invalid without a
195 * fallback possibility, or the check failed for another reason
197 int intel_link_bw_atomic_check(struct intel_atomic_state *state,
198 struct intel_link_bw_limits *new_limits)
200 struct drm_i915_private *i915 = to_i915(state->base.dev);
201 struct intel_link_bw_limits old_limits = *new_limits;
204 ret = check_all_link_config(state, new_limits);
208 if (!assert_link_limit_change_valid(i915, &old_limits, new_limits))