[PATCH 05/10] drm/i915/display: Compute the scaler coefficients
Nemesa Garg
nemesa.garg at intel.com
Thu Jul 24 13:45:39 UTC 2025
The sharpness property requires the use of one of the scaler
so need to set the sharpness scaler coefficient values.
These values are based on experiments and vary for different
tap value/win size. These values are normalized by taking the
sum of all values and then dividing each value with a sum.
v2: Fix ifndef header naming issue reported by kernel test robot
v3: Rename file name[Arun]
Replace array size number with macro[Arun]
v4: Correct the register format[Jani]
Add brief comment and expalin about file[Jani]
Remove coefficient value from crtc_state[Jani]
v5: Fix build issue
v6: Add new function for writing coefficients[Ankit]
v7: Add cooments and add a scaler id check [Ankit]
v8: Remove casf_enable from here[Ankit]
v9: Removed REG and use shift operator[Jani]
Signed-off-by: Nemesa Garg <nemesa.garg at intel.com>
Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
drivers/gpu/drm/i915/display/intel_casf.c | 104 ++++++++++++++++++
drivers/gpu/drm/i915/display/intel_casf.h | 1 +
.../drm/i915/display/intel_display_types.h | 8 ++
3 files changed, 113 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_casf.c b/drivers/gpu/drm/i915/display/intel_casf.c
index 18a8a621016a..607829df06d9 100644
--- a/drivers/gpu/drm/i915/display/intel_casf.c
+++ b/drivers/gpu/drm/i915/display/intel_casf.c
@@ -15,6 +15,13 @@
#define MAX_PIXELS_FOR_3_TAP_FILTER (1920 * 1080)
#define MAX_PIXELS_FOR_5_TAP_FILTER (3840 * 2160)
+#define FILTER_COEFF_0_125 125
+#define FILTER_COEFF_0_25 250
+#define FILTER_COEFF_0_5 500
+#define FILTER_COEFF_1_0 1000
+#define FILTER_COEFF_0_0 0
+#define SET_POSITIVE_SIGN(x) ((x) & (~SIGN))
+
/**
* DOC: Content Adaptive Sharpness Filter (CASF)
*
@@ -125,6 +132,8 @@ int intel_casf_compute_config(struct intel_crtc_state *crtc_state)
intel_casf_compute_win_size(crtc_state);
+ intel_casf_scaler_compute_config(crtc_state);
+
return 0;
}
@@ -147,3 +156,98 @@ void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state)
REG_FIELD_GET(FILTER_SIZE_MASK, sharp);
}
}
+
+static int casf_coeff_tap(int i)
+{
+ return i % SCALER_FILTER_NUM_TAPS;
+}
+
+static u32 casf_coeff(struct intel_crtc_state *crtc_state, int t)
+{
+ struct scaler_filter_coeff value;
+ u32 coeff;
+
+ value = crtc_state->hw.casf_params.coeff[t];
+ value.sign = 0;
+
+ coeff = value.sign << 15 | value.exp << 12 | value.mantissa << 3;
+ return coeff;
+}
+
+/*
+ * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set.
+ * To enable casf: program scaler coefficients with the coeffients
+ * that are calculated and stored in hw.casf_params.coeff as per
+ * SCALER_COEFFICIENT_FORMAT
+ */
+static void intel_casf_write_coeff(struct intel_crtc_state *crtc_state)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ int id = crtc_state->scaler_state.scaler_id;
+ int i;
+
+ if (id != 1) {
+ drm_WARN(display->drm, 0, "Second scaler not enabled\n");
+ return;
+ }
+
+ intel_de_write_fw(display, GLK_PS_COEF_INDEX_SET(crtc->pipe, id, 0),
+ PS_COEF_INDEX_AUTO_INC);
+
+ for (i = 0; i < 17 * SCALER_FILTER_NUM_TAPS; i += 2) {
+ u32 tmp;
+ int t;
+
+ t = casf_coeff_tap(i);
+ tmp = casf_coeff(crtc_state, t);
+
+ t = casf_coeff_tap(i + 1);
+ tmp |= casf_coeff(crtc_state, t) << 16;
+
+ intel_de_write_fw(display, GLK_PS_COEF_DATA_SET(crtc->pipe, id, 0),
+ tmp);
+ }
+}
+
+static void convert_sharpness_coef_binary(struct scaler_filter_coeff *coeff,
+ u16 coefficient)
+{
+ if (coefficient < 25) {
+ coeff->mantissa = (coefficient * 2048) / 100;
+ coeff->exp = 3;
+ } else if (coefficient < 50) {
+ coeff->mantissa = (coefficient * 1024) / 100;
+ coeff->exp = 2;
+ } else if (coefficient < 100) {
+ coeff->mantissa = (coefficient * 512) / 100;
+ coeff->exp = 1;
+ } else {
+ coeff->mantissa = (coefficient * 256) / 100;
+ coeff->exp = 0;
+ }
+}
+
+void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state)
+{
+ const u16 *filtercoeff;
+ u16 filter_coeff[SCALER_FILTER_NUM_TAPS];
+ u16 sumcoeff = 0;
+ int i;
+
+ if (crtc_state->hw.casf_params.win_size == 0)
+ filtercoeff = filtercoeff_1;
+ else if (crtc_state->hw.casf_params.win_size == 1)
+ filtercoeff = filtercoeff_2;
+ else
+ filtercoeff = filtercoeff_3;
+
+ for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++)
+ sumcoeff += *(filtercoeff + i);
+
+ for (i = 0; i < SCALER_FILTER_NUM_TAPS; i++) {
+ filter_coeff[i] = (*(filtercoeff + i) * 100 / sumcoeff);
+ convert_sharpness_coef_binary(&crtc_state->hw.casf_params.coeff[i],
+ filter_coeff[i]);
+ }
+}
diff --git a/drivers/gpu/drm/i915/display/intel_casf.h b/drivers/gpu/drm/i915/display/intel_casf.h
index 3edbc3ad51cf..031d2e41701e 100644
--- a/drivers/gpu/drm/i915/display/intel_casf.h
+++ b/drivers/gpu/drm/i915/display/intel_casf.h
@@ -16,5 +16,6 @@ void intel_casf_update_strength(struct intel_crtc_state *new_crtc_state);
void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state);
void intel_casf_filter_lut_load(struct intel_crtc *crtc,
const struct intel_crtc_state *crtc_state);
+void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state);
#endif /* __INTEL_CASF_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index a4649669f538..9f29456aa34e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -943,7 +943,15 @@ struct intel_csc_matrix {
u16 postoff[3];
};
+struct scaler_filter_coeff {
+ u16 sign;
+ u16 exp;
+ u16 mantissa;
+};
+
struct intel_casf {
+#define SCALER_FILTER_NUM_TAPS 7
+ struct scaler_filter_coeff coeff[SCALER_FILTER_NUM_TAPS];
u8 strength;
u8 win_size;
bool casf_enable;
--
2.25.1
More information about the Intel-xe
mailing list