]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/display: Compute the scaler coefficients
authorNemesa Garg <nemesa.garg@intel.com>
Tue, 28 Oct 2025 12:07:41 +0000 (17:37 +0530)
committerJani Nikula <jani.nikula@intel.com>
Thu, 30 Oct 2025 13:42:59 +0000 (15:42 +0200)
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.

Add helper to compute and set the scaler coefficients.

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]
v10: Remove filter macros
v11: Add casf_write_coeff function to casf_enable

Signed-off-by: Nemesa Garg <nemesa.garg@intel.com>
Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Link: https://patch.msgid.link/20251028120747.3027332-6-ankit.k.nautiyal@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
drivers/gpu/drm/i915/display/intel_casf.c
drivers/gpu/drm/i915/display/intel_casf.h
drivers/gpu/drm/i915/display/intel_display_types.h

index bd63fdafb898f4c79b4f4f17dd5b1ae116d97921..ee24e5957d3d30dc3dc6a03033da703a4ccf02be 100644 (file)
@@ -130,6 +130,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;
 }
 
@@ -153,6 +155,101 @@ void intel_casf_sharpness_get_config(struct intel_crtc_state *crtc_state)
        }
 }
 
+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]);
+       }
+}
+
 void intel_casf_enable(struct intel_crtc_state *crtc_state)
 {
        struct intel_display *display = to_intel_display(crtc_state);
@@ -161,6 +258,8 @@ void intel_casf_enable(struct intel_crtc_state *crtc_state)
 
        intel_casf_filter_lut_load(crtc, crtc_state);
 
+       intel_casf_write_coeff(crtc_state);
+
        sharpness_ctl = FILTER_EN | FILTER_STRENGTH(crtc_state->hw.casf_params.strength);
 
        sharpness_ctl |= crtc_state->hw.casf_params.win_size;
index 7538718802795bd405f30991bc86ce4024054307..203a5587921c5e28be0f391c2a76ff62e5d6f410 100644 (file)
@@ -15,5 +15,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_enable(struct intel_crtc_state *crtc_state);
 void intel_casf_disable(const struct intel_crtc_state *crtc_state);
+void intel_casf_scaler_compute_config(struct intel_crtc_state *crtc_state);
 
 #endif /* __INTEL_CASF_H__ */
index 2afb346249ef24616077a6663947a972b53b0aa7..00600134bda0aacf3cb7d7cc731d503ebfae3741 100644 (file)
@@ -961,7 +961,15 @@ enum intel_panel_replay_dsc_support {
        INTEL_DP_PANEL_REPLAY_DSC_SELECTIVE_UPDATE,
 };
 
+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;