1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include <linux/debugfs.h> 7 8 #include <drm/drm_print.h> 9 10 #include "intel_cdclk.h" 11 #include "intel_display_core.h" 12 #include "intel_display_types.h" 13 #include "intel_vblank.h" 14 #include "intel_vdsc.h" 15 #include "skl_prefill.h" 16 #include "skl_scaler.h" 17 #include "skl_watermark.h" 18 19 static unsigned int prefill_usecs_to_lines(const struct intel_crtc_state *crtc_state, 20 unsigned int usecs) 21 { 22 const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; 23 24 return DIV_ROUND_UP_ULL(mul_u32_u32(pipe_mode->crtc_clock, usecs << 16), 25 pipe_mode->crtc_htotal * 1000); 26 } 27 28 static void prefill_init(struct skl_prefill_ctx *ctx, 29 const struct intel_crtc_state *crtc_state) 30 { 31 memset(ctx, 0, sizeof(*ctx)); 32 33 ctx->prefill.fixed = crtc_state->framestart_delay << 16; 34 35 /* 20 usec for translation walks/etc. */ 36 ctx->prefill.fixed += prefill_usecs_to_lines(crtc_state, 20); 37 38 ctx->prefill.dsc = intel_vdsc_prefill_lines(crtc_state); 39 } 40 41 static void prefill_init_nocdclk_worst(struct skl_prefill_ctx *ctx, 42 const struct intel_crtc_state *crtc_state) 43 { 44 prefill_init(ctx, crtc_state); 45 46 ctx->prefill.wm0 = skl_wm0_prefill_lines_worst(crtc_state); 47 ctx->prefill.scaler_1st = skl_scaler_1st_prefill_lines_worst(crtc_state); 48 ctx->prefill.scaler_2nd = skl_scaler_2nd_prefill_lines_worst(crtc_state); 49 50 ctx->adj.scaler_1st = skl_scaler_1st_prefill_adjustment_worst(crtc_state); 51 ctx->adj.scaler_2nd = skl_scaler_2nd_prefill_adjustment_worst(crtc_state); 52 } 53 54 static void prefill_init_nocdclk(struct skl_prefill_ctx *ctx, 55 const struct intel_crtc_state *crtc_state) 56 { 57 prefill_init(ctx, crtc_state); 58 59 ctx->prefill.wm0 = skl_wm0_prefill_lines(crtc_state); 60 ctx->prefill.scaler_1st = skl_scaler_1st_prefill_lines(crtc_state); 61 ctx->prefill.scaler_2nd = skl_scaler_2nd_prefill_lines(crtc_state); 62 63 ctx->adj.scaler_1st = skl_scaler_1st_prefill_adjustment(crtc_state); 64 ctx->adj.scaler_2nd = skl_scaler_2nd_prefill_adjustment(crtc_state); 65 } 66 67 static unsigned int prefill_adjust(unsigned int value, unsigned int factor) 68 { 69 return DIV_ROUND_UP_ULL(mul_u32_u32(value, factor), 0x10000); 70 } 71 72 static unsigned int prefill_lines_nocdclk(const struct skl_prefill_ctx *ctx) 73 { 74 unsigned int prefill = 0; 75 76 prefill += ctx->prefill.dsc; 77 prefill = prefill_adjust(prefill, ctx->adj.scaler_2nd); 78 79 prefill += ctx->prefill.scaler_2nd; 80 prefill = prefill_adjust(prefill, ctx->adj.scaler_1st); 81 82 prefill += ctx->prefill.scaler_1st; 83 prefill += ctx->prefill.wm0; 84 85 return prefill; 86 } 87 88 static unsigned int prefill_lines_cdclk(const struct skl_prefill_ctx *ctx) 89 { 90 return prefill_adjust(prefill_lines_nocdclk(ctx), ctx->adj.cdclk); 91 } 92 93 static unsigned int prefill_lines_full(const struct skl_prefill_ctx *ctx) 94 { 95 return ctx->prefill.fixed + prefill_lines_cdclk(ctx); 96 } 97 98 void skl_prefill_init_worst(struct skl_prefill_ctx *ctx, 99 const struct intel_crtc_state *crtc_state) 100 { 101 prefill_init_nocdclk_worst(ctx, crtc_state); 102 103 ctx->adj.cdclk = intel_cdclk_prefill_adjustment_worst(crtc_state); 104 105 ctx->prefill.full = prefill_lines_full(ctx); 106 } 107 108 void skl_prefill_init(struct skl_prefill_ctx *ctx, 109 const struct intel_crtc_state *crtc_state) 110 { 111 prefill_init_nocdclk(ctx, crtc_state); 112 113 ctx->adj.cdclk = intel_cdclk_prefill_adjustment(crtc_state); 114 115 ctx->prefill.full = prefill_lines_full(ctx); 116 } 117 118 static unsigned int prefill_lines_with_latency(const struct skl_prefill_ctx *ctx, 119 const struct intel_crtc_state *crtc_state, 120 unsigned int latency_us) 121 { 122 return ctx->prefill.full + prefill_usecs_to_lines(crtc_state, latency_us); 123 } 124 125 int skl_prefill_min_guardband(const struct skl_prefill_ctx *ctx, 126 const struct intel_crtc_state *crtc_state, 127 unsigned int latency_us) 128 { 129 unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, latency_us); 130 131 return DIV_ROUND_UP(prefill, 0x10000); 132 } 133 134 static unsigned int prefill_guardband(const struct intel_crtc_state *crtc_state) 135 { 136 return intel_crtc_vblank_length(crtc_state) << 16; 137 } 138 139 bool skl_prefill_vblank_too_short(const struct skl_prefill_ctx *ctx, 140 const struct intel_crtc_state *crtc_state, 141 unsigned int latency_us) 142 { 143 unsigned int guardband = prefill_guardband(crtc_state); 144 unsigned int prefill = prefill_lines_with_latency(ctx, crtc_state, latency_us); 145 146 return guardband < prefill; 147 } 148 149 int skl_prefill_min_cdclk(const struct skl_prefill_ctx *ctx, 150 const struct intel_crtc_state *crtc_state) 151 { 152 unsigned int prefill_unadjusted = prefill_lines_nocdclk(ctx); 153 unsigned int prefill_available = prefill_guardband(crtc_state) - ctx->prefill.fixed; 154 155 return intel_cdclk_min_cdclk_for_prefill(crtc_state, prefill_unadjusted, 156 prefill_available); 157 } 158