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(const struct intel_crtc_state *crtc_state) 65 { 66 struct intel_display *display = to_intel_display(crtc_state); 67 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 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 static void intel_casf_compute_win_size(struct intel_crtc_state *crtc_state) 79 { 80 const struct drm_display_mode *mode = &crtc_state->hw.adjusted_mode; 81 u32 total_pixels = mode->hdisplay * mode->vdisplay; 82 83 if (total_pixels <= MAX_PIXELS_FOR_3_TAP_FILTER) 84 crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_3X3; 85 else if (total_pixels <= MAX_PIXELS_FOR_5_TAP_FILTER) 86 crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_5X5; 87 else 88 crtc_state->pch_pfit.casf.win_size = SHARPNESS_FILTER_SIZE_7X7; 89 } 90 91 static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state); 92 93 int intel_casf_compute_config(struct intel_crtc_state *crtc_state) 94 { 95 struct intel_display *display = to_intel_display(crtc_state); 96 97 if (crtc_state->hw.sharpness_strength == 0) 98 return 0; 99 100 /* CASF with joiner not supported in hardware */ 101 if (crtc_state->joiner_pipes) { 102 drm_dbg_kms(display->drm, "CASF not supported with joiner\n"); 103 return -EINVAL; 104 } 105 106 crtc_state->pch_pfit.casf.enable = true; 107 108 /* 109 * HW takes a value in form (1.0 + strength) in 4.4 fixed format. 110 * Strength is from 0.0-14.9375 ie from 0-239. 111 * User can give value from 0-255 but is clamped to 239. 112 * Ex. User gives 85 which is 5.3125 and adding 1.0 gives 6.3125. 113 * 6.3125 in 4.4 format is b01100101 which is equal to 101. 114 * Also 85 + 16 = 101. 115 */ 116 crtc_state->pch_pfit.casf.strength = 117 min(crtc_state->hw.sharpness_strength, 0xEF) + 0x10; 118 119 intel_casf_compute_win_size(crtc_state); 120 121 intel_casf_scaler_compute_coef(crtc_state); 122 123 return 0; 124 } 125 126 void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state) 127 { 128 struct intel_display *display = to_intel_display(crtc_state); 129 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 130 u32 sharp; 131 132 sharp = intel_de_read(display, SHARPNESS_CTL(crtc->pipe)); 133 if (sharp & FILTER_EN) { 134 if (drm_WARN_ON(display->drm, 135 REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp) < 16)) 136 crtc_state->pch_pfit.casf.strength = 0; 137 else 138 crtc_state->pch_pfit.casf.strength = 139 REG_FIELD_GET(FILTER_STRENGTH_MASK, sharp); 140 crtc_state->pch_pfit.casf.enable = true; 141 crtc_state->pch_pfit.casf.win_size = 142 REG_FIELD_GET(FILTER_SIZE_MASK, sharp); 143 } 144 } 145 146 static int casf_coeff_tap(int i) 147 { 148 return i % SCALER_FILTER_NUM_TAPS; 149 } 150 151 static u32 casf_coeff(const struct intel_crtc_state *crtc_state, int t) 152 { 153 struct scaler_filter_coeff value; 154 u32 coeff; 155 156 value = crtc_state->pch_pfit.casf.coeff[t]; 157 value.sign = 0; 158 159 coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3; 160 return coeff; 161 } 162 163 /* 164 * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set. 165 * To enable casf: program scaler coefficients with the coeffients 166 * that are calculated and stored in pch_pfit.casf.coeff as per 167 * SCALER_COEFFICIENT_FORMAT 168 */ 169 static void intel_casf_write_coeff(const struct intel_crtc_state *crtc_state) 170 { 171 struct intel_display *display = to_intel_display(crtc_state); 172 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 173 int id = crtc_state->scaler_state.scaler_id; 174 int i; 175 176 if (id != 1) { 177 drm_WARN(display->drm, 0, "Second scaler not enabled\n"); 178 return; 179 } 180 181 intel_de_write_fw(display, GLK_PS_COEF_INDEX_SET(crtc->pipe, id, 0), 182 PS_COEF_INDEX_AUTO_INC); 183 184 for (i = 0; i < 17 * SCALER_FILTER_NUM_TAPS; i += 2) { 185 u32 tmp; 186 int t; 187 188 t = casf_coeff_tap(i); 189 tmp = casf_coeff(crtc_state, t); 190 191 t = casf_coeff_tap(i + 1); 192 tmp |= casf_coeff(crtc_state, t) << 16; 193 194 intel_de_write_fw(display, GLK_PS_COEF_DATA_SET(crtc->pipe, id, 0), 195 tmp); 196 } 197 } 198 199 static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff, 200 u16 coefficient) 201 { 202 if (coefficient < 25) { 203 coeff->mantissa = (coefficient * 2048) / 100; 204 coeff->exp = 3; 205 } else if (coefficient < 50) { 206 coeff->mantissa = (coefficient * 1024) / 100; 207 coeff->exp = 2; 208 } else if (coefficient < 100) { 209 coeff->mantissa = (coefficient * 512) / 100; 210 coeff->exp = 1; 211 } else { 212 coeff->mantissa = (coefficient * 256) / 100; 213 coeff->exp = 0; 214 } 215 } 216 217 static void intel_casf_scaler_compute_coef(struct intel_crtc_state *crtc_state) 218 { 219 const u16 *filtercoeff; 220 u16 filter_coeff[SCALER_FILTER_NUM_TAPS]; 221 u16 sumcoeff = 0; 222 int i; 223 224 if (crtc_state->pch_pfit.casf.win_size == 0) 225 filtercoeff = filtercoeff_1; 226 else if (crtc_state->pch_pfit.casf.win_size == 1) 227 filtercoeff = filtercoeff_2; 228 else 229 filtercoeff = filtercoeff_3; 230 231 for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) 232 sumcoeff += *(filtercoeff + i); 233 234 for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) { 235 filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff); 236 convert_sharpness_coef_binary(&crtc_state->pch_pfit.casf.coeff[i], 237 filter_coeff[i]); 238 } 239 } 240 241 void intel_casf_setup(const struct intel_crtc_state *crtc_state) 242 { 243 intel_casf_filter_lut_load(crtc_state); 244 intel_casf_write_coeff(crtc_state); 245 } 246