1 // SPDX-License-Identifier: MIT 2 /* Copyright © 2025 Intel Corporation */ 3 4 #include <drm/drm_print.h> 5 6 #include "intel_casf.h" 7 #include "intel_casf_regs.h" 8 #include "intel_de.h" 9 #include "intel_display_regs.h" 10 #include "intel_display_types.h" 11 #include "skl_scaler.h" 12 13 #define MAX_PIXELS_FOR_3_TAP_FILTER (1920 * 1080) 14 #define MAX_PIXELS_FOR_5_TAP_FILTER (3840 * 2160) 15 16 #define FILTER_COEFF_0_125 125 17 #define FILTER_COEFF_0_25 250 18 #define FILTER_COEFF_0_5 500 19 #define FILTER_COEFF_1_0 1000 20 #define FILTER_COEFF_0_0 0 21 #define SET_POSITIVE_SIGN(x) ((x) & (~SIGN)) 22 23 /** 24 * DOC: Content Adaptive Sharpness Filter (CASF) 25 * 26 * Starting from LNL the display engine supports an 27 * adaptive sharpening filter, enhancing the image 28 * quality. The display hardware utilizes the second 29 * pipe scaler for implementing CASF. 30 * If sharpness is being enabled then pipe scaling 31 * cannot be used. 32 * This filter operates on a region of pixels based 33 * on the tap size. Coefficients are used to generate 34 * an alpha value which blends the sharpened image to 35 * original image. 36 */ 37 38 /* Default LUT values to be loaded one time. */ 39 static const u16 sharpness_lut[] = { 40 4095, 2047, 1364, 1022, 816, 678, 579, 41 504, 444, 397, 357, 323, 293, 268, 244, 224, 42 204, 187, 170, 154, 139, 125, 111, 98, 85, 43 73, 60, 48, 36, 24, 12, 0 44 }; 45 46 const u16 filtercoeff_1[] = { 47 FILTER_COEFF_0_0, FILTER_COEFF_0_0, FILTER_COEFF_0_5, 48 FILTER_COEFF_1_0, FILTER_COEFF_0_5, FILTER_COEFF_0_0, 49 FILTER_COEFF_0_0, 50 }; 51 52 const u16 filtercoeff_2[] = { 53 FILTER_COEFF_0_0, FILTER_COEFF_0_25, FILTER_COEFF_0_5, 54 FILTER_COEFF_1_0, FILTER_COEFF_0_5, FILTER_COEFF_0_25, 55 FILTER_COEFF_0_0, 56 }; 57 58 const u16 filtercoeff_3[] = { 59 FILTER_COEFF_0_125, FILTER_COEFF_0_25, FILTER_COEFF_0_5, 60 FILTER_COEFF_1_0, FILTER_COEFF_0_5, FILTER_COEFF_0_25, 61 FILTER_COEFF_0_125, 62 }; 63 64 static void intel_casf_filter_lut_load(struct intel_crtc *crtc, 65 const struct intel_crtc_state *crtc_state) 66 { 67 struct intel_display *display = to_intel_display(crtc_state); 68 int i; 69 70 intel_de_write(display, SHRPLUT_INDEX(crtc->pipe), 71 INDEX_AUTO_INCR | INDEX_VALUE(0)); 72 73 for (i = 0; i < ARRAY_SIZE(sharpness_lut); i++) 74 intel_de_write(display, SHRPLUT_DATA(crtc->pipe), 75 sharpness_lut[i]); 76 } 77 78 void intel_casf_update_strength(struct intel_crtc_state *crtc_state) 79 { 80 struct intel_display *display = to_intel_display(crtc_state); 81 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 82 int win_size; 83 84 intel_de_rmw(display, SHARPNESS_CTL(crtc->pipe), FILTER_STRENGTH_MASK, 85 FILTER_STRENGTH(crtc_state->hw.casf_params.strength)); 86 87 win_size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, 1)); 88 89 intel_de_write_fw(display, SKL_PS_WIN_SZ(crtc->pipe, 1), win_size); 90 } 91 92 static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state) 93 { 94 const struct drm_display_mode *mode = &crtc_state->hw.adjusted_mode; 95 u32 total_pixels = mode->hdisplay * mode->vdisplay; 96 97 if (total_pixels <= MAX_PIXELS_FOR_3_TAP_FILTER) 98 crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_3X3; 99 else if (total_pixels <= MAX_PIXELS_FOR_5_TAP_FILTER) 100 crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_5X5; 101 else 102 crtc_state->hw.casf_params.win_size = SHARPNESS_FILTER_SIZE_7X7; 103 } 104 105 int intel_casf_compute_config(struct intel_crtc_state *crtc_state) 106 { 107 struct intel_display *display = to_intel_display(crtc_state); 108 109 if (!HAS_CASF(display)) 110 return 0; 111 112 if (crtc_state->uapi.sharpness_strength == 0) { 113 crtc_state->hw.casf_params.casf_enable = false; 114 crtc_state->hw.casf_params.strength = 0; 115 return 0; 116 } 117 118 /* CASF with joiner not supported in hardware */ 119 if (crtc_state->joiner_pipes) { 120 drm_dbg_kms(display->drm, "CASF not supported with joiner\n"); 121 return -EINVAL; 122 } 123 124 crtc_state->hw.casf_params.casf_enable = true; 125 126 /* 127 * HW takes a value in form (1.0 + strength) in 4.4 fixed format. 128 * Strength is from 0.0-14.9375 ie from 0-239. 129 * User can give value from 0-255 but is clamped to 239. 130 * Ex. User gives 85 which is 5.3125 and adding 1.0 gives 6.3125. 131 * 6.3125 in 4.4 format is b01100101 which is equal to 101. 132 * Also 85 + 16 = 101. 133 */ 134 crtc_state->hw.casf_params.strength = 135 min(crtc_state->uapi.sharpness_strength, 0xEF) + 0x10; 136 137 intel_casf_compute_win_size(crtc_state); 138 139 intel_casf_scaler_compute_config(crtc_state); 140 141 return 0; 142 } 143 144 void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state) 145 { 146 struct intel_display *display = to_intel_display(crtc_state); 147 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 148 u32 sharp; 149 150 sharp = intel_de_read(display, SHARPNESS_CTL(crtc->pipe)); 151 if (sharp & FILTER_EN) { 152 if (drm_WARN_ON(display->drm, 153 REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp) < 16)) 154 crtc_state->hw.casf_params.strength = 0; 155 else 156 crtc_state->hw.casf_params.strength = 157 REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp); 158 crtc_state->hw.casf_params.casf_enable = true; 159 crtc_state->hw.casf_params.win_size = 160 REG_FIELD_GET(FILTER_SIZE_MASK, sharp); 161 } 162 } 163 164 bool intel_casf_needs_scaler(const struct intel_crtc_state *crtc_state) 165 { 166 if (crtc_state->hw.casf_params.casf_enable) 167 return true; 168 169 return false; 170 } 171 172 static int casf_coeff_tap(int i) 173 { 174 return i % SCALER_FILTER_NUM_TAPS; 175 } 176 177 static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t) 178 { 179 struct scaler_filter_coeff value; 180 u32 coeff; 181 182 value = crtc_state->hw.casf_params.coeff[t]; 183 value.sign = 0; 184 185 coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3; 186 return coeff; 187 } 188 189 /* 190 * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set. 191 * To enable casf: program scaler coefficients with the coeffients 192 * that are calculated and stored in hw.casf_params.coeff as per 193 * SCALER_COEFFICIENT_FORMAT 194 */ 195 static void intel_casf_write_coeff(struct intel_crtc_state *crtc_state) 196 { 197 struct intel_display *display = to_intel_display(crtc_state); 198 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 199 int id = crtc_state->scaler_state.scaler_id; 200 int i; 201 202 if (id != 1) { 203 drm_WARN(display->drm, 0, "Second scaler not enabled\n"); 204 return; 205 } 206 207 intel_de_write_fw(display, GLK_PS_COEF_INDEX_SET(crtc->pipe, id, 0), 208 PS_COEF_INDEX_AUTO_INC); 209 210 for (i = 0; i < 17 * SCALER_FILTER_NUM_TAPS; i += 2) { 211 u32 tmp; 212 int t; 213 214 t = casf_coeff_tap(i); 215 tmp = casf_coeff(crtc_state, t); 216 217 t = casf_coeff_tap(i + 1); 218 tmp |= casf_coeff(crtc_state, t) << 16; 219 220 intel_de_write_fw(display, GLK_PS_COEF_DATA_SET(crtc->pipe, id, 0), 221 tmp); 222 } 223 } 224 225 static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff, 226 u16 coefficient) 227 { 228 if (coefficient < 25) { 229 coeff->mantissa = (coefficient * 2048) / 100; 230 coeff->exp = 3; 231 } else if (coefficient < 50) { 232 coeff->mantissa = (coefficient * 1024) / 100; 233 coeff->exp = 2; 234 } else if (coefficient < 100) { 235 coeff->mantissa = (coefficient * 512) / 100; 236 coeff->exp = 1; 237 } else { 238 coeff->mantissa = (coefficient * 256) / 100; 239 coeff->exp = 0; 240 } 241 } 242 243 void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state) 244 { 245 const u16 *filtercoeff; 246 u16 filter_coeff[SCALER_FILTER_NUM_TAPS]; 247 u16 sumcoeff = 0; 248 int i; 249 250 if (crtc_state->hw.casf_params.win_size == 0) 251 filtercoeff = filtercoeff_1; 252 else if (crtc_state->hw.casf_params.win_size == 1) 253 filtercoeff = filtercoeff_2; 254 else 255 filtercoeff = filtercoeff_3; 256 257 for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) 258 sumcoeff += *(filtercoeff + i); 259 260 for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) { 261 filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff); 262 convert_sharpness_coef_binary(&crtc_state->hw.casf_params.coeff[i], 263 filter_coeff[i]); 264 } 265 } 266 267 void intel_casf_enable(struct intel_crtc_state *crtc_state) 268 { 269 struct intel_display *display = to_intel_display(crtc_state); 270 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 271 u32 sharpness_ctl; 272 273 intel_casf_filter_lut_load(crtc, crtc_state); 274 275 intel_casf_write_coeff(crtc_state); 276 277 sharpness_ctl = FILTER_EN | FILTER_STRENGTH(crtc_state->hw.casf_params.strength); 278 279 sharpness_ctl |= crtc_state->hw.casf_params.win_size; 280 281 intel_de_write(display, SHARPNESS_CTL(crtc->pipe), sharpness_ctl); 282 283 skl_scaler_setup_casf(crtc_state); 284 } 285 286 void intel_casf_disable(const struct intel_crtc_state *crtc_state) 287 { 288 struct intel_display *display = to_intel_display(crtc_state); 289 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 290 291 intel_de_write(display, SKL_PS_CTRL(crtc->pipe, 1), 0); 292 intel_de_write(display, SKL_PS_WIN_POS(crtc->pipe, 1), 0); 293 intel_de_write(display, SHARPNESS_CTL(crtc->pipe), 0); 294 intel_de_write(display, SKL_PS_WIN_SZ(crtc->pipe, 1), 0); 295 } 296