1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023 Intel Corporation
8 #include "intel_atomic.h"
9 #include "intel_display_types.h"
10 #include "intel_dp_mst.h"
11 #include "intel_fdi.h"
12 #include "intel_link_bw.h"
15 * intel_link_bw_init_limits - initialize BW limits
16 * @i915: device instance
17 * @limits: link BW limits
21 void intel_link_bw_init_limits(struct drm_i915_private
*i915
, struct intel_link_bw_limits
*limits
)
25 limits
->force_fec_pipes
= 0;
26 limits
->bpp_limit_reached_pipes
= 0;
27 for_each_pipe(i915
, pipe
)
28 limits
->max_bpp_x16
[pipe
] = INT_MAX
;
32 * intel_link_bw_reduce_bpp - reduce maximum link bpp for a selected pipe
33 * @state: atomic state
34 * @limits: link BW limits
35 * @pipe_mask: mask of pipes to select from
36 * @reason: explanation of why bpp reduction is needed
38 * Select the pipe from @pipe_mask with the biggest link bpp value and set the
39 * maximum of link bpp in @limits below this value. Modeset the selected pipe,
40 * so that its state will get recomputed.
42 * This function can be called to resolve a link's BW overallocation by reducing
43 * the link bpp of one pipe on the link and hence reducing the total link BW.
46 * - 0 in case of success
47 * - %-ENOSPC if no pipe can further reduce its link bpp
48 * - Other negative error, if modesetting the selected pipe failed
50 int intel_link_bw_reduce_bpp(struct intel_atomic_state
*state
,
51 struct intel_link_bw_limits
*limits
,
55 struct drm_i915_private
*i915
= to_i915(state
->base
.dev
);
56 enum pipe max_bpp_pipe
= INVALID_PIPE
;
57 struct intel_crtc
*crtc
;
60 for_each_intel_crtc_in_pipe_mask(&i915
->drm
, crtc
, pipe_mask
) {
61 struct intel_crtc_state
*crtc_state
;
64 if (limits
->bpp_limit_reached_pipes
& BIT(crtc
->pipe
))
67 crtc_state
= intel_atomic_get_crtc_state(&state
->base
,
69 if (IS_ERR(crtc_state
))
70 return PTR_ERR(crtc_state
);
72 if (crtc_state
->dsc
.compression_enable
)
73 link_bpp_x16
= crtc_state
->dsc
.compressed_bpp_x16
;
76 * TODO: for YUV420 the actual link bpp is only half
77 * of the pipe bpp value. The MST encoder's BW allocation
78 * is based on the pipe bpp value, set the actual link bpp
79 * limit here once the MST BW allocation is fixed.
81 link_bpp_x16
= to_bpp_x16(crtc_state
->pipe_bpp
);
83 if (link_bpp_x16
> max_bpp_x16
) {
84 max_bpp_x16
= link_bpp_x16
;
85 max_bpp_pipe
= crtc
->pipe
;
89 if (max_bpp_pipe
== INVALID_PIPE
)
92 limits
->max_bpp_x16
[max_bpp_pipe
] = max_bpp_x16
- 1;
94 return intel_modeset_pipes_in_mask_early(state
, reason
,
99 * intel_link_bw_set_bpp_limit_for_pipe - set link bpp limit for a pipe to its minimum
100 * @state: atomic state
101 * @old_limits: link BW limits
102 * @new_limits: link BW limits
105 * Set the link bpp limit for @pipe in @new_limits to its value in
106 * @old_limits and mark this limit as the minimum. This function must be
107 * called after a pipe's compute config function failed, @old_limits
108 * containing the bpp limit with which compute config previously passed.
110 * The function will fail if setting a minimum is not possible, either
111 * because the old and new limits match (and so would lead to a pipe compute
112 * config failure) or the limit is already at the minimum.
114 * Returns %true in case of success.
117 intel_link_bw_set_bpp_limit_for_pipe(struct intel_atomic_state
*state
,
118 const struct intel_link_bw_limits
*old_limits
,
119 struct intel_link_bw_limits
*new_limits
,
122 struct drm_i915_private
*i915
= to_i915(state
->base
.dev
);
124 if (pipe
== INVALID_PIPE
)
127 if (new_limits
->max_bpp_x16
[pipe
] ==
128 old_limits
->max_bpp_x16
[pipe
])
131 if (drm_WARN_ON(&i915
->drm
,
132 new_limits
->bpp_limit_reached_pipes
& BIT(pipe
)))
135 new_limits
->max_bpp_x16
[pipe
] =
136 old_limits
->max_bpp_x16
[pipe
];
137 new_limits
->bpp_limit_reached_pipes
|= BIT(pipe
);
142 static int check_all_link_config(struct intel_atomic_state
*state
,
143 struct intel_link_bw_limits
*limits
)
145 /* TODO: Check additional shared display link configurations like MST */
148 ret
= intel_dp_mst_atomic_check_link(state
, limits
);
152 ret
= intel_fdi_atomic_check_link(state
, limits
);
160 assert_link_limit_change_valid(struct drm_i915_private
*i915
,
161 const struct intel_link_bw_limits
*old_limits
,
162 const struct intel_link_bw_limits
*new_limits
)
164 bool bpps_changed
= false;
167 /* FEC can't be forced off after it was forced on. */
168 if (drm_WARN_ON(&i915
->drm
,
169 (old_limits
->force_fec_pipes
& new_limits
->force_fec_pipes
) !=
170 old_limits
->force_fec_pipes
))
173 for_each_pipe(i915
, pipe
) {
174 /* The bpp limit can only decrease. */
175 if (drm_WARN_ON(&i915
->drm
,
176 new_limits
->max_bpp_x16
[pipe
] >
177 old_limits
->max_bpp_x16
[pipe
]))
180 if (new_limits
->max_bpp_x16
[pipe
] <
181 old_limits
->max_bpp_x16
[pipe
])
185 /* At least one limit must change. */
186 if (drm_WARN_ON(&i915
->drm
,
188 new_limits
->force_fec_pipes
==
189 old_limits
->force_fec_pipes
))
196 * intel_link_bw_atomic_check - check display link states and set a fallback config if needed
197 * @state: atomic state
198 * @new_limits: link BW limits
200 * Check the configuration of all shared display links in @state and set new BW
201 * limits in @new_limits if there is a BW limitation.
204 * - 0 if the confugration is valid
205 * - %-EAGAIN, if the configuration is invalid and @new_limits got updated
206 * with fallback values with which the configuration of all CRTCs
207 * in @state must be recomputed
208 * - Other negative error, if the configuration is invalid without a
209 * fallback possibility, or the check failed for another reason
211 int intel_link_bw_atomic_check(struct intel_atomic_state
*state
,
212 struct intel_link_bw_limits
*new_limits
)
214 struct drm_i915_private
*i915
= to_i915(state
->base
.dev
);
215 struct intel_link_bw_limits old_limits
= *new_limits
;
218 ret
= check_all_link_config(state
, new_limits
);
222 if (!assert_link_limit_change_valid(i915
, &old_limits
, new_limits
))