[igt-dev] [PATCH i-g-t 4/6] HACK: tools/intel_scaler_coef: Test cnl+ pipe scaler programmable coefficients
Ville Syrjala
ville.syrjala at linux.intel.com
Tue Mar 10 14:18:28 UTC 2020
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
cnl+ (actually glk already has this, but presumably not validated)
have programmable pipe scaler coefficients. Add some code to figure
out how they work.
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
tools/intel_scaler_coef.c | 166 ++++++++++++++++++++++++++++++++++++++
1 file changed, 166 insertions(+)
diff --git a/tools/intel_scaler_coef.c b/tools/intel_scaler_coef.c
index 8565261099d0..de6872a91545 100644
--- a/tools/intel_scaler_coef.c
+++ b/tools/intel_scaler_coef.c
@@ -1204,6 +1204,170 @@ static void ilk_program(struct filter *f, int pipe)
intel_register_access_fini(&mmio_data);
}
+#define _PS_REG(reg_a_1, pipe, scaler) ((reg_a_1) + (pipe) * 0x800 + (scaler) * 0x100)
+#define PS_CTRL(pipe, scaler) _PS_REG(0x68180, (pipe), (scaler))
+#define PS_ENABLE (1 << 31)
+#define PS_CTRL_FILTER_PROG (1 << 23)
+#define PS_CTRL_Y_VERT_FILTER_SET(set) ((set) << 4)
+#define PS_CTRL_Y_HORZ_FILTER_SET(set) ((set) << 3)
+#define PS_CTRL_UV_VERT_FILTER_SET(set) ((set) << 2)
+#define PS_CTRL_UV_HORZ_FILTER_SET(set) ((set) << 1)
+#define PS_WIN_POS(pipe, scaler) _PS_REG(0x68170, (pipe), (scaler))
+#define PS_WIN_SZ(pipe, scaler) _PS_REG(0x68174, (pipe), (scaler))
+#define PS_VSCALE(pipe, scaler) _PS_REG(0x68184, (pipe), (scaler))
+#define PS_VPHASE(pipe, scaler) _PS_REG(0x68188, (pipe), (scaler))
+#define PS_HSCALE(pipe, scaler) _PS_REG(0x68190, (pipe), (scaler))
+#define PS_HPHASE(pipe, scaler) _PS_REG(0x68194, (pipe), (scaler))
+#define PS_Y_PHASE(x) ((x) << 16)
+#define PS_UV_RGB_PHASE(x) ((x) << 0)
+#define PS_PHASE_MASK (0x7fff << 1) /* u2.13 */
+#define PS_PHASE_TRIP (1 << 0)
+
+#define _PS_COEF_REG(reg_a_1, pipe, scaler, set) (_PS_REG((reg_a_1), (pipe), (scaler)) + (set) * 0x8)
+#define PS_COEF_INDEX(pipe, scaler, set) _PS_COEF_REG(0x68198, (pipe), (scaler), (set))
+#define PS_COEF_AUTO_INCREMENT (1 << 10)
+#define PS_COEF_DATA(pipe, scaler, set) _PS_COEF_REG(0x6819c, (pipe), (scaler), (set))
+
+static uint16_t ps_calc_phase(int scale)
+{
+ bool chroma_cosited = false;
+ int sub = 1;
+ int phase = -0x8000;
+ uint16_t trip = 0;
+
+ if (chroma_cosited)
+ phase += (sub - 1) * 0x8000 / sub;
+
+ phase += scale / (2 * sub);
+
+ if (phase < 0)
+ phase = 0x10000 + phase;
+ else
+ trip = PS_PHASE_TRIP;
+
+ return ((phase >> 2) & PS_PHASE_MASK) | trip;
+}
+
+static void cnl_program_coefs(int pipe, int scaler, int set,
+ const uint16_t coef[])
+{
+ I915_WRITE(PS_COEF_INDEX(pipe, scaler, set),
+ PS_COEF_AUTO_INCREMENT);
+
+ for (int i = 0; i < 7 * 17; i += 2) {
+ uint32_t tmp = coef[i+1] << 16 | coef[i];
+
+ I915_WRITE(PS_COEF_DATA(pipe, scaler, set), tmp);
+ }
+
+ I915_WRITE(PS_COEF_INDEX(pipe, scaler, set), 0);
+}
+
+static void cnl_coefs(struct filter *f, uint16_t coef[])
+{
+ f->config = configs[FORMAT_CNL_PS];
+
+ generate_filter(f);
+ print_filter(f);
+ hw_print_filter(f);
+ update_filter(f);
+ print_filter(f);
+ hw_print_filter(f);
+ fixup_filter(f);
+ printf("cnl ps\n");
+ print_filter(f);
+ hw_print_filter(f);
+ print_c_filter(f);
+
+ for (int p = 0; p < f->config.nphases/2+1; p++) {
+ const double *coefs = f->phases[p].coefs;
+
+ for (int t = 0; t < f->config.ntaps; t++) {
+ union gen2_coef_reg r;
+ int i = ilk_coef_index(f, p, t);
+
+ gen2_coef_to_reg(f, t, coefs[t], &r);
+
+ coef[i] = r.reg;
+ }
+ }
+}
+
+static void cnl_program(struct filter *f, int pipe)
+{
+ struct intel_mmio_data mmio_data;
+ struct rect src = {};
+ struct rect dst = {};
+ uint16_t hcoef[7*17+1] = {};
+ uint16_t vcoef[7*17+1] = {};
+ uint32_t devid;
+ int trans = pipe;
+ int scaler = 0;
+
+ devid = intel_get_pci_device()->device_id;
+
+ if (intel_gen(devid) < 10 && !IS_GEMINILAKE(devid))
+ return;
+
+ intel_register_access_init(&mmio_data, intel_get_pci_device(), 0, -1);
+
+ if (!(I915_READ(PIPECONF(trans)) & PIPECONF_ENABLE))
+ trans = 0xf; /* assume we are using transcoder EDP */
+ if (!(I915_READ(PIPECONF(trans)) & PIPECONF_ENABLE))
+ goto out;
+
+ dst.w = (I915_READ(HTOTAL(trans)) & 0xffff) + 1;
+ dst.h = (I915_READ(VTOTAL(trans)) & 0xffff) + 1;
+
+ src.w = ((I915_READ(PIPESRC(pipe)) >> 16) & 0xffff) + 1;
+ src.h = (I915_READ(PIPESRC(pipe)) & 0xffff) + 1;
+
+ dst.x = 8;
+ dst.y = 8;
+ dst.w -= 16;
+ dst.h -= 16;
+
+ cnl_coefs(f, hcoef);
+ cnl_coefs(f, vcoef);
+
+ cnl_program_coefs(pipe, scaler, 0, hcoef);
+ cnl_program_coefs(pipe, scaler, 1, vcoef);
+
+ I915_WRITE(PS_VPHASE(pipe, scaler),
+ ps_calc_phase((src.h << 16) / dst.h));
+ I915_WRITE(PS_HPHASE(pipe, scaler),
+ ps_calc_phase((src.w << 16) / dst.w));
+
+ I915_WRITE(PS_CTRL(pipe, scaler), PS_ENABLE |
+ PS_CTRL_FILTER_PROG |
+ PS_CTRL_Y_VERT_FILTER_SET(0) |
+ PS_CTRL_Y_HORZ_FILTER_SET(0) |
+ PS_CTRL_UV_VERT_FILTER_SET(0) |
+ PS_CTRL_UV_HORZ_FILTER_SET(0));
+
+ I915_WRITE(PS_WIN_POS(pipe, scaler), dst.x << 16 | dst.y);
+ I915_WRITE(PS_WIN_SZ(pipe, scaler), dst.w << 16 | dst.h);
+
+ printf("%dx%d%+d%+d -> %dx%d%+d%+d\n",
+ src.w, src.h, src.x, src.y,
+ dst.w, dst.h, dst.x, dst.y);
+ printf("sw: hscale 0x%x, vscale 0x%x\n",
+ (((src.w << 16) + 1) / dst.w) >> 1,
+ (((src.h << 16) + 1) / dst.h) >> 1);
+ printf("hw: hscale 0x%x, vscale 0x%x\n",
+ I915_READ(PS_HSCALE(pipe, scaler)),
+ I915_READ(PS_VSCALE(pipe, scaler)));
+
+ sleep(2);
+
+ I915_WRITE(PS_CTRL(pipe, scaler), 0);
+ I915_WRITE(PS_WIN_POS(pipe, scaler), 0);
+ I915_WRITE(PS_WIN_SZ(pipe, scaler), 0);
+
+ out:
+ intel_register_access_fini(&mmio_data);
+}
+
int main(int argc, char *argv[])
{
const struct option opts[] = {
@@ -1364,6 +1528,8 @@ int main(int argc, char *argv[])
print_c_filter(&f);
+ if (1)
+ cnl_program(&f, 0);
if (1)
ilk_program(&f, 0);
--
2.24.1
More information about the igt-dev
mailing list