Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/i915/wm: Use skl_prefill

Replace the current ad-hoc prefill calculations with skl_prefill.

v2: cdclk_state no longer needed
Rename to skl_prefill

Reviewed-by: Uma Shankar <uma.shankar@intel.com> #v1
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20251014191808.12326-10-ville.syrjala@linux.intel.com

+20 -106
+20 -106
drivers/gpu/drm/i915/display/skl_watermark.c
··· 30 30 #include "intel_plane.h" 31 31 #include "intel_vblank.h" 32 32 #include "intel_wm.h" 33 + #include "skl_prefill.h" 33 34 #include "skl_scaler.h" 34 35 #include "skl_universal_plane_regs.h" 35 36 #include "skl_watermark.h" ··· 2148 2147 return 0; 2149 2148 } 2150 2149 2151 - static int 2152 - cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state) 2153 - { 2154 - struct intel_display *display = to_intel_display(crtc_state); 2155 - struct intel_atomic_state *state = 2156 - to_intel_atomic_state(crtc_state->uapi.state); 2157 - const struct intel_cdclk_state *cdclk_state; 2158 - 2159 - cdclk_state = intel_atomic_get_cdclk_state(state); 2160 - if (IS_ERR(cdclk_state)) { 2161 - drm_WARN_ON(display->drm, PTR_ERR(cdclk_state)); 2162 - return 1; 2163 - } 2164 - 2165 - return min(1, DIV_ROUND_UP(crtc_state->pixel_rate, 2166 - 2 * intel_cdclk_logical(cdclk_state))); 2167 - } 2168 - 2169 - static int 2170 - dsc_prefill_latency(const struct intel_crtc_state *crtc_state) 2171 - { 2172 - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2173 - const struct intel_crtc_scaler_state *scaler_state = 2174 - &crtc_state->scaler_state; 2175 - int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal, 2176 - crtc_state->hw.adjusted_mode.clock); 2177 - int num_scaler_users = hweight32(scaler_state->scaler_users); 2178 - int chroma_downscaling_factor = 2179 - crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1; 2180 - u32 dsc_prefill_latency = 0; 2181 - 2182 - if (!crtc_state->dsc.compression_enable || 2183 - !num_scaler_users || 2184 - num_scaler_users > crtc->num_scalers) 2185 - return dsc_prefill_latency; 2186 - 2187 - dsc_prefill_latency = DIV_ROUND_UP(15 * linetime * chroma_downscaling_factor, 10); 2188 - 2189 - for (int i = 0; i < num_scaler_users; i++) { 2190 - u64 hscale_k, vscale_k; 2191 - 2192 - hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].hscale, 1000) >> 16); 2193 - vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[i].vscale, 1000) >> 16); 2194 - dsc_prefill_latency = DIV_ROUND_UP_ULL(dsc_prefill_latency * hscale_k * vscale_k, 2195 - 1000000); 2196 - } 2197 - 2198 - dsc_prefill_latency *= cdclk_prefill_adjustment(crtc_state); 2199 - 2200 - return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, dsc_prefill_latency); 2201 - } 2202 - 2203 - static int 2204 - scaler_prefill_latency(const struct intel_crtc_state *crtc_state) 2205 - { 2206 - const struct intel_crtc_scaler_state *scaler_state = 2207 - &crtc_state->scaler_state; 2208 - int num_scaler_users = hweight32(scaler_state->scaler_users); 2209 - int scaler_prefill_latency = 0; 2210 - int linetime = DIV_ROUND_UP(1000 * crtc_state->hw.adjusted_mode.htotal, 2211 - crtc_state->hw.adjusted_mode.clock); 2212 - 2213 - if (!num_scaler_users) 2214 - return scaler_prefill_latency; 2215 - 2216 - scaler_prefill_latency = 4 * linetime; 2217 - 2218 - if (num_scaler_users > 1) { 2219 - u64 hscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].hscale, 1000) >> 16); 2220 - u64 vscale_k = max(1000, mul_u32_u32(scaler_state->scalers[0].vscale, 1000) >> 16); 2221 - int chroma_downscaling_factor = 2222 - crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ? 2 : 1; 2223 - int latency; 2224 - 2225 - latency = DIV_ROUND_UP_ULL((4 * linetime * hscale_k * vscale_k * 2226 - chroma_downscaling_factor), 1000000); 2227 - scaler_prefill_latency += latency; 2228 - } 2229 - 2230 - scaler_prefill_latency *= cdclk_prefill_adjustment(crtc_state); 2231 - 2232 - return intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, scaler_prefill_latency); 2233 - } 2234 - 2235 - static bool 2236 - skl_is_vblank_too_short(const struct intel_crtc_state *crtc_state, 2237 - int wm0_lines, int latency) 2238 - { 2239 - const struct drm_display_mode *adjusted_mode = 2240 - &crtc_state->hw.adjusted_mode; 2241 - 2242 - return crtc_state->framestart_delay + 2243 - intel_usecs_to_scanlines(adjusted_mode, latency) + 2244 - scaler_prefill_latency(crtc_state) + 2245 - dsc_prefill_latency(crtc_state) + 2246 - wm0_lines > 2247 - intel_crtc_vblank_length(crtc_state); 2248 - } 2249 - 2250 2150 unsigned int skl_wm0_prefill_lines_worst(const struct intel_crtc_state *crtc_state) 2251 2151 { 2252 2152 struct intel_display *display = to_intel_display(crtc_state); ··· 2226 2324 * the scenario to apply Wa_16025596647. 2227 2325 */ 2228 2326 static int skl_max_wm_level_for_vblank(struct intel_crtc_state *crtc_state, 2229 - int wm0_lines) 2327 + const struct skl_prefill_ctx *ctx) 2230 2328 { 2231 2329 struct intel_display *display = to_intel_display(crtc_state); 2330 + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2232 2331 int level; 2233 2332 2234 2333 for (level = display->wm.num_levels - 1; level >= 0; level--) { ··· 2244 2341 if (level == 0) 2245 2342 latency = 0; 2246 2343 2247 - if (!skl_is_vblank_too_short(crtc_state, wm0_lines, latency)) 2344 + if (!skl_prefill_vblank_too_short(ctx, crtc_state, latency)) 2248 2345 return level; 2249 2346 } 2347 + 2348 + drm_dbg_kms(display->drm, "[CRTC:%d:%s] Not enough time in vblank for prefill\n", 2349 + crtc->base.base.id, crtc->base.name); 2250 2350 2251 2351 return -EINVAL; 2252 2352 } ··· 2258 2352 { 2259 2353 struct intel_display *display = to_intel_display(crtc_state); 2260 2354 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2261 - int wm0_lines, level; 2355 + struct skl_prefill_ctx ctx; 2356 + int level; 2262 2357 2263 2358 if (!crtc_state->hw.active) 2264 2359 return 0; 2265 2360 2266 - wm0_lines = skl_max_wm0_lines(crtc_state); 2361 + skl_prefill_init(&ctx, crtc_state); 2267 2362 2268 - level = skl_max_wm_level_for_vblank(crtc_state, wm0_lines); 2363 + level = skl_max_wm_level_for_vblank(crtc_state, &ctx); 2269 2364 if (level < 0) 2270 2365 return level; 2271 2366 ··· 2275 2368 * based on whether we're limited by the vblank duration. 2276 2369 */ 2277 2370 crtc_state->wm_level_disabled = level < display->wm.num_levels - 1; 2371 + 2372 + /* 2373 + * TODO: assert that we are in fact using the maximum guardband 2374 + * if we end up disabling any WM levels here. Otherwise we clearly 2375 + * failed in using a realistic worst case prefill estimate when 2376 + * determining the guardband size. 2377 + */ 2278 2378 2279 2379 for (level++; level < display->wm.num_levels; level++) { 2280 2380 enum plane_id plane_id; ··· 2301 2387 2302 2388 if (DISPLAY_VER(display) >= 12 && 2303 2389 display->sagv.block_time_us && 2304 - skl_is_vblank_too_short(crtc_state, wm0_lines, 2305 - display->sagv.block_time_us)) { 2390 + skl_prefill_vblank_too_short(&ctx, crtc_state, 2391 + display->sagv.block_time_us)) { 2306 2392 enum plane_id plane_id; 2307 2393 2308 2394 for_each_plane_id_on_crtc(crtc, plane_id) {