[Intel-gfx] tools/intel_display_poller: Poll DSPARB across mixed pipe vblank

Submitted by Ville Syrjälä on Aug. 10, 2016, 1:35 p.m.

Details

Message ID 1470836144-2423-1-git-send-email-ville.syrjala@linux.intel.com
State New
Headers show
Series "tools/intel_display_poller: Poll DSPARB across mixed pipe vblank" ( rev: 1 ) in IGT (deprecated)

Not browsing as part of any series.

Commit Message

Ville Syrjälä Aug. 10, 2016, 1:35 p.m.
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add another mode which changes the DSPARB registers at specific
scanlines, to determine if the individual bits get latches only
on the vblank of the relevant pipe, of if other pipes would cause
premature latching to happen when their vblank happens first.

The results I got on my CHV were that there is no premature latching.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 lib/intel_reg.h              |   2 +
 tools/intel_display_poller.c | 180 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 167 insertions(+), 15 deletions(-)

Patch hide | download patch | download mbox

diff --git a/lib/intel_reg.h b/lib/intel_reg.h
index 3a28c08c3595..f2e6d1d60216 100644
--- a/lib/intel_reg.h
+++ b/lib/intel_reg.h
@@ -2223,6 +2223,8 @@  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define   DSPARB_BSTART_SHIFT	0
 #define   DSPARB_BEND_SHIFT	9 /* on 855 */
 #define   DSPARB_AEND_SHIFT	0
+#define DSPARB2			0x70060
+#define DSPARB3			0x7006c
 #define DSPFW1			0x70034
 #define DSPFW2			0x70038
 #define DSPFW3			0x7003c
diff --git a/tools/intel_display_poller.c b/tools/intel_display_poller.c
index eab17c52428e..9a6ec3d2af36 100644
--- a/tools/intel_display_poller.c
+++ b/tools/intel_display_poller.c
@@ -54,6 +54,7 @@  enum test {
 	TEST_SURFLIVE,
 	TEST_WRAP,
 	TEST_FIELD,
+	TEST_DSPARB,
 };
 
 static uint32_t vlv_offset;
@@ -899,6 +900,111 @@  static void poll_dsl_field(int pipe, uint32_t *min, uint32_t *max, const int cou
 	}
 }
 
+static void poll_frm_dsparb(uint32_t devid, int pipe, int pipe_2,
+			    int target_scanline_a, int target_scanline_b,
+			    uint32_t *min, uint32_t *max, const int count)
+{
+	uint32_t dsl[2], frm[2];
+
+	if ((read_reg(PIPE_REG(pipe, PIPEACONF)) & (1 << 31)) == 0 ||
+	    (read_reg(PIPE_REG(pipe_2, PIPEACONF)) & (1 << 31)) == 0) {
+		fprintf(stderr, "pipe %c & %c should be enabled for the test\n",
+		       pipe_name(pipe), pipe_name(pipe_2));
+		return;
+	}
+	if (IS_CHERRYVIEW(devid)) {
+		int pipe_3 = 3 - pipe - pipe_2;
+
+		if ((read_reg(PIPE_REG(pipe_3, PIPEACONF)) & (1 << 31)) != 0) {
+			fprintf(stderr, "pipe %c enabled, which might interfere with the test\n",
+				pipe_name(pipe_3));
+			return;
+		}
+	}
+
+	dsl[0] = PIPE_REG(pipe, PIPEA_DSL);
+	dsl[1] = PIPE_REG(pipe_2, PIPEA_DSL);
+	frm[0] = PIPE_REG(pipe, PIPEAFRMCOUNT_G4X);
+	frm[1] = PIPE_REG(pipe_2, PIPEAFRMCOUNT_G4X);
+
+	for (int n = 0; n < 20; n++)
+		printf("pipe %c %d pipe %c %d\n",
+		       pipe_name(pipe), read_reg(dsl[0]),
+		       pipe_name(pipe_2), read_reg(dsl[1]));
+
+	while (!quit) {
+		uint32_t saved, saved2;
+		uint32_t wr, wr2;
+		uint32_t dsl_pre[2];
+		uint32_t dsl_post[2];
+		uint32_t frm_pre[2];
+		uint32_t frm_post[2];
+
+		while (!quit) {
+			uint32_t d = read_reg(dsl[0]);
+			d &= ~0x80000000;
+			if (d == target_scanline_a)
+				break;
+		}
+
+		dsl_pre[0] = read_reg(dsl[0]);
+		frm_pre[0] = read_reg(frm[0]);
+		dsl_pre[1] = read_reg(dsl[1]);
+		frm_pre[1] = read_reg(frm[1]);
+
+		saved = read_reg(DSPARB);
+		saved2 = read_reg(DSPARB2);
+		switch (pipe) {
+		case 0:
+			//write_reg(DSPARB, (saved & ~0xff) | 0x1);
+			write_reg(DSPARB2, (saved2 & ~0x1) | 0x0);
+			break;
+		case 1:
+			//write_reg(DSPARB, (saved & ~0xff0000) | 0x10000);
+			write_reg(DSPARB2, (saved2 & ~0x100) | 0x000);
+			break;
+		case 2:
+			//write_reg(DSPARB3, (saved & ~0xff) | 0x1);
+			write_reg(DSPARB2, (saved2 & ~0x10000) | 0x00000);
+			break;
+		}
+		wr = read_reg(DSPARB);
+		wr2 = read_reg(DSPARB2);
+
+		while (!quit) {
+			uint32_t d = read_reg(dsl[1]);
+			d &= ~0x80000000;
+			if (d == target_scanline_b)
+				break;
+		}
+
+		write_reg(DSPARB, saved);
+		write_reg(DSPARB2, saved2);
+
+		dsl_post[0] = read_reg(dsl[0]);
+		frm_post[0] = read_reg(frm[0]);
+		dsl_post[1] = read_reg(dsl[1]);
+		frm_post[1] = read_reg(frm[1]);
+
+		if (frm_pre[0] == frm_post[0] &&
+		    frm_pre[1] != frm_post[1]) {
+			printf("\nhit it %c %d->%d %c %d->%d\n",
+			       pipe_name(pipe), frm_pre[0], frm_post[0],
+			       pipe_name(pipe_2), frm_pre[1], frm_post[1]);
+		} else {
+			printf("\ndidn't hit it %c %d->%d %c %d->%d\n",
+			       pipe_name(pipe), frm_pre[0], frm_post[0],
+			       pipe_name(pipe_2), frm_pre[1], frm_post[1]);
+		}
+		printf("dsl %c %d->%d %c %d->%d\n",
+		       pipe_name(pipe), dsl_pre[0], dsl_post[0],
+		       pipe_name(pipe_2), dsl_pre[1], dsl_post[1]);
+		printf("dsparb %x -> %x -> %x, dsparb2 %x -> %x -> %x\n",
+		       saved, wr, read_reg(DSPARB), saved2, wr2, read_reg(DSPARB2));
+		sleep(1);
+	}
+}
+
 static const char *test_name(enum test test, int pipe, int bit, bool test_pixel_count)
 {
 	static char str[32];
@@ -941,6 +1047,9 @@  static const char *test_name(enum test test, int pipe, int bit, bool test_pixel_
 	case TEST_FIELD:
 		snprintf(str, sizeof str, "%s / pipe %c / Field", type, pipe_name(pipe));
 		return str;
+	case TEST_DSPARB:
+		snprintf(str, sizeof str, "%s / DSPARB", type);
+		return str;
 	default:
 		return "";
 	}
@@ -949,20 +1058,46 @@  static const char *test_name(enum test test, int pipe, int bit, bool test_pixel_
 static void __attribute__((noreturn)) usage(const char *name)
 {
 	fprintf(stderr, "Usage: %s [options]\n"
-		" -t,--test <pipestat|iir|framecount|flipcount|pan|flip|surflive|wrap|field>\n"
+		" -t,--test <pipestat|iir|framecount|flipcount|pan|flip|surflive|wrap|field|dsparb>\n"
 		" -p,--pipe <pipe>\n"
+		" -P,--Pipe <second pipe (dsparb test only)>\n"
 		" -b,--bit <bit>\n"
 		" -l,--line <target scanline/pixel>\n"
+		" -L,--Line <second target scanline (dsparb test only)>\n"
 		" -f,--fuzz <target fuzz>\n"
 		" -x,--pixel\n",
 		name);
 	exit(1);
 }
 
+static int parse_pipe(const char *str)
+{
+	int pipe;
+
+	if (str[0] == '\0' || str[1] != '\0')
+		return -1;
+
+	pipe = str[0];
+	if (pipe >= 'a')
+		pipe -= 'a';
+	else if (pipe >= 'A')
+		pipe -= 'A';
+	else if (pipe >= '0')
+		pipe -= '0';
+	else
+		return -1;
+
+	if (pipe < 0 || pipe > 2)
+		return -1;
+
+	return pipe;
+}
+
 int main(int argc, char *argv[])
 {
 	int fd, i;
 	int pipe = 0, bit = 0, target_scanline = 0, target_fuzz = 1;
+	int pipe_2 = 0, target_scanline_2 = 0;
 	bool test_pixelcount = false;
 	uint32_t devid;
 	uint32_t min[2*128] = {};
@@ -975,14 +1110,16 @@  int main(int argc, char *argv[])
 		static const struct option long_options[] = {
 			{ .name = "test", .has_arg = required_argument, },
 			{ .name = "pipe", .has_arg = required_argument, },
+			{ .name = "Pipe", .has_arg = required_argument, },
 			{ .name = "bit", .has_arg = required_argument, },
 			{ .name = "line", .has_arg = required_argument, },
+			{ .name = "Line", .has_arg = required_argument, },
 			{ .name = "fuzz", .has_arg = required_argument, },
 			{ .name = "pixel", .has_arg = no_argument, },
 			{ },
 		};
 
-		int opt = getopt_long(argc, argv, "t:p:b:l:f:x", long_options, NULL);
+		int opt = getopt_long(argc, argv, "t:p:P:b:l:L:f:x", long_options, NULL);
 		if (opt == -1)
 			break;
 
@@ -1006,22 +1143,19 @@  int main(int argc, char *argv[])
 				test = TEST_WRAP;
 			else if (!strcmp(optarg, "field"))
 				test = TEST_FIELD;
-			else
+			else if (!strcmp(optarg, "dsparb"))
+				test = TEST_DSPARB;
+		else
 				usage(argv[0]);
 			break;
 		case 'p':
-			if (optarg[1] != '\0')
+			pipe = parse_pipe(optarg);
+			if (pipe < 0)
 				usage(argv[0]);
-			pipe = optarg[0];
-			if (pipe >= 'a')
-				pipe -= 'a';
-			else if (pipe >= 'A')
-				pipe -= 'A';
-			else if (pipe >= '0')
-				pipe -= '0';
-			else
-				usage(argv[0]);
-			if (pipe < 0 || pipe > 2)
+			break;
+		case 'P':
+			pipe_2 = parse_pipe(optarg);
+			if (pipe_2 < 0)
 				usage(argv[0]);
 			break;
 		case 'b':
@@ -1034,6 +1168,11 @@  int main(int argc, char *argv[])
 			if (target_scanline < 0)
 				usage(argv[0]);
 			break;
+		case 'L':
+			target_scanline_2 = atoi(optarg);
+			if (target_scanline_2 < 0)
+				usage(argv[0]);
+			break;
 		case 'f':
 			target_fuzz = atoi(optarg);
 			if (target_fuzz <= 0)
@@ -1099,12 +1238,13 @@  int main(int argc, char *argv[])
 		}
 	} else if (IS_G4X(devid) ||
 		   IS_VALLEYVIEW(devid) || IS_CHERRYVIEW(devid)) {
+		int num_pipes = IS_CHERRYVIEW(devid) ? 3 : 2;
 		if (IS_VALLEYVIEW(devid) || IS_CHERRYVIEW(devid))
 			vlv_offset = 0x180000;
 		if (IS_CHERRYVIEW(devid))
 			pipe_offset[2] = 0x4000;
 
-		if (pipe > 1 && !IS_CHERRYVIEW(devid))
+		if (pipe >= num_pipes)
 			usage(argv[0]);
 
 		if (test_pixelcount)
@@ -1125,6 +1265,12 @@  int main(int argc, char *argv[])
 		case TEST_WRAP:
 		case TEST_FIELD:
 			break;
+		case TEST_DSPARB:
+			if (!IS_VALLEYVIEW(devid) && !IS_CHERRYVIEW(devid))
+				usage(argv[0]);
+			if (pipe_2 == pipe || pipe_2 >= num_pipes)
+				usage(argv[0]);
+			break;
 		default:
 			usage(argv[0]);
 		}
@@ -1259,6 +1405,10 @@  int main(int argc, char *argv[])
 	case TEST_FIELD:
 		poll_dsl_field(pipe, min, max, count);
 		break;
+	case TEST_DSPARB:
+		poll_frm_dsparb(devid, pipe, pipe_2,
+				target_scanline, target_scanline_2, min, max, count);
+		break;
 	default:
 		assert(0);
 	}