[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