@@ -6237,6 +6237,72 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
skl_detach_scaler(crtc, i);
}
+/**
+ * Theory behind setting nearest-neighbor integer scaling:
+ *
+ * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set.
+ * The letter represents the filter tap (D is the center tap) and the number
+ * represents the coefficient set for a phase (0-16).
+ *
+ * +------------+------------------------+------------------------+
+ * |Index value | Data value coeffient 1 | Data value coeffient 2 |
+ * +------------+------------------------+------------------------+
+ * | 00h | B0 | A0 |
+ * +------------+------------------------+------------------------+
+ * | 01h | D0 | C0 |
+ * +------------+------------------------+------------------------+
+ * | 02h | F0 | E0 |
+ * +------------+------------------------+------------------------+
+ * | 03h | A1 | G0 |
+ * +------------+------------------------+------------------------+
+ * | 04h | C1 | B1 |
+ * +------------+------------------------+------------------------+
+ * | ... | ... | ... |
+ * +------------+------------------------+------------------------+
+ * | 38h | B16 | A16 |
+ * +------------+------------------------+------------------------+
+ * | 39h | D16 | C16 |
+ * +------------+------------------------+------------------------+
+ * | 3Ah | F16 | C16 |
+ * +------------+------------------------+------------------------+
+ * | 3Bh | Reserved | G16 |
+ * +------------+------------------------+------------------------+
+ *
+ * To enable nearest-neighbor scaling: program scaler coefficents with
+ * the center tap (Dxx) values set to 1 and all other values set to 0 as per
+ * SCALER_COEFFICIENT_FORMAT
+ *
+ */
+void skl_scaler_setup_nearest_neighbor_filter(struct drm_i915_private *dev_priv,
+ enum pipe pipe, int id, int set)
+{
+
+ int phase;
+ int coeff = 0;
+ int val = 0;
+
+ /*enable the index auto increment.*/
+ intel_de_write_fw(dev_priv,
+ SKL_PS_COEF_INDEX_SET(pipe, id, set),
+ PS_COEE_INDEX_AUTO_INC);
+
+ for (phase = 0; phase < 17; phase++) {
+ int tap;
+
+ for (tap = 0; tap < 7; tap++) {
+ if (tap == 3)
+ val = phase % 2 ? 0x800 : 0x800 << 16;
+
+ if (++coeff % 2 == 0) {
+ intel_de_write_fw(dev_priv, SKL_PS_COEF_DATA_SET(pipe, id, set), val);
+ val = 0;
+ }
+ }
+ }
+
+ intel_de_write_fw(dev_priv, SKL_PS_COEF_DATA_SET(pipe, id, set), 0);
+}
+
static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -587,6 +587,8 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state);
+void skl_scaler_setup_nearest_neighbor_filter(struct drm_i915_private *dev_priv,
+ enum pipe pipe, int id, int set);
void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state);
u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);