diff --git a/tests/testdisplay.c b/tests/testdisplay.c
index fe9ef36..1e2810a 100644
--- a/tests/testdisplay.c
+++ b/tests/testdisplay.c
@@ -69,6 +69,17 @@
 struct udev_monitor *uevent_monitor;
 drmModeRes *resources;
 int fd, modes;
+int dump_info = 0, test_all_modes=0, test_preferred_mode= 0, force_mode = 0;
+
+float force_clock;
+int	force_hdisplay;
+int	force_hsync_start;
+int	force_hsync_end;
+int	force_htotal;
+int	force_vdisplay;
+int	force_vsync_start;
+int	force_vsync_end;
+int	force_vtotal;
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
@@ -141,6 +152,86 @@ struct connector {
 	int crtc;
 };
 
+static void dump_mode(drmModeModeInfo *mode)
+{
+	printf("  %s %.01f %d %d %d %d %d %d %d %d\n",
+	       mode->name,
+	       (float)mode->vrefresh,
+	       mode->hdisplay,
+	       mode->hsync_start,
+	       mode->hsync_end,
+	       mode->htotal,
+	       mode->vdisplay,
+	       mode->vsync_start,
+	       mode->vsync_end,
+	       mode->vtotal);
+}
+
+static void dump_connectors(void)
+{
+	drmModeConnector *connector;
+	int i, j;
+
+	printf("Connectors:\n");
+	printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
+	for (i = 0; i < resources->count_connectors; i++) {
+		connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+		if (!connector) {
+			fprintf(stderr, "could not get connector %i: %s\n",
+				resources->connectors[i], strerror(errno));
+			continue;
+		}
+
+		printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
+		       connector->connector_id,
+		       connector->encoder_id,
+		       connector_status_str(connector->connection),
+		       connector_type_str(connector->connector_type),
+		       connector->mmWidth, connector->mmHeight,
+		       connector->count_modes);
+
+		if (!connector->count_modes)
+			continue;
+
+		printf("  modes:\n");
+		printf("  name refresh (Hz) hdisp hss hse htot vdisp "
+		       "vss vse vtot)\n");
+		for (j = 0; j < connector->count_modes; j++)
+			dump_mode(&connector->modes[j]);
+
+		drmModeFreeConnector(connector);
+	}
+	printf("\n");
+}
+
+static void dump_crtcs(void)
+{
+	drmModeCrtc *crtc;
+	int i;
+
+	printf("CRTCs:\n");
+	printf("id\tfb\tpos\tsize\n");
+	for (i = 0; i < resources->count_crtcs; i++) {
+		crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
+
+		if (!crtc) {
+			fprintf(stderr, "could not get crtc %i: %s\n",
+				resources->crtcs[i], strerror(errno));
+			continue;
+		}
+		printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+		       crtc->crtc_id,
+		       crtc->buffer_id,
+		       crtc->x, crtc->y,
+		       crtc->width, crtc->height);
+		dump_mode(&crtc->mode);
+
+		drmModeFreeCrtc(crtc);
+	}
+	printf("\n");
+}
+
 static void connector_find_preferred_mode(struct connector *c)
 {
 	drmModeConnector *connector;
@@ -420,16 +511,40 @@ set_mode(struct connector *c)
 	cairo_surface_t *surface;
 	cairo_t *cr;
 	char buf[128];
+	int j, test_mode_num;
 
 	width = 0;
 	height = 0;
 	connector_find_preferred_mode(c);
 	if (!c->mode_valid)
 		return;
-
+	if (test_preferred_mode|| force_mode)
+		test_mode_num = 1;
+	if (test_all_modes)
+		test_mode_num = c->connector->count_modes;
+	for (j = 0; j < test_mode_num; j++) {
+		if (test_all_modes)
+			c->mode = c->connector->modes[j];
+	width = 0;
+	height = 0;
 	width += c->mode.hdisplay;
 	if (height < c->mode.vdisplay)
 		height = c->mode.vdisplay;
+	if (force_mode){
+		width = force_hdisplay;
+		height = force_vdisplay;
+		c->mode.clock = force_clock*1000;
+		c->mode.hdisplay = force_hdisplay;
+		c->mode.hsync_start = force_hsync_start;
+		c->mode.hsync_end = force_hsync_end;
+		c->mode.htotal = force_htotal;
+		c->mode.vdisplay = force_vdisplay;
+		c->mode.vsync_start = force_vsync_start;
+		c->mode.vsync_end = force_vsync_end;
+		c->mode.vtotal = force_vtotal;
+		c->mode.vrefresh =(force_clock*1e6)/(force_htotal*force_vtotal);
+		sprintf(c->mode.name,"%d%s%d",width,"x",height);
+	}
 
 	bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20);
 	if (!bufmgr) {
@@ -468,6 +583,7 @@ set_mode(struct connector *c)
 	ret = drmModeAddFB(fd, width, height, 32, 32, stride, bo->handle,
 			   &fb_id);
 	if (ret) {
+		printf("drmModeAddFB:width =%d,height=%d\n",width,height);
 		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
 		return;
 	}
@@ -475,6 +591,7 @@ set_mode(struct connector *c)
 	if (!c->mode_valid)
 		return;
 
+	dump_mode(&c->mode);
 	ret = drmModeSetCrtc(fd, c->crtc, fb_id, 0, 0,
 			     &c->id, 1, &c->mode);
 
@@ -482,7 +599,9 @@ set_mode(struct connector *c)
 		fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
 		return;
 	}
-
+	if (test_all_modes)
+		sleep(5);
+}
 	drmModeFreeEncoder(c->encoder);
 	drmModeFreeConnector(c->connector);
 }
@@ -513,24 +632,40 @@ static void update_display(void)
 	if (!connectors)
 		return;
 
-	/* Find any connected displays */
-	for (c = 0; c < resources->count_connectors; c++) {
-		connectors[c].id = resources->connectors[c];
-		set_mode(&connectors[c]);
+	if (dump_info) {
+		dump_connectors();
+		dump_crtcs();
+	}
+	if (test_preferred_mode || test_all_modes || force_mode) {
+		/* Find any connected displays */
+		for (c = 0; c < resources->count_connectors; c++) {
+			connectors[c].id = resources->connectors[c];
+			set_mode(&connectors[c]);
+		}
 	}
 	drmModeFreeResources(resources);
+	if (dump_info || test_all_modes)
+		exit(0);
 }
 
 extern char *optarg;
 extern int optind, opterr, optopt;
-static char optstr[] = "h";
+static char optstr[] = "hiaf:";
 
 static void usage(char *name)
 {
-	fprintf(stderr, "usage: %s [-h]\n", name);
+	fprintf(stderr, "usage: %s [-hiaf:]\n", name);
+	fprintf(stderr, "\t-i\tdump info\n");
+	fprintf(stderr, "\t-a\ttest all modes\n");
+	fprintf(stderr, "\t-f\t<clock MHz>,<hdisp>,<hsync-start>,<hsync-end>,<htotal>,\n");
+	fprintf(stderr, "\t\t<vdisp>,<vsync-start>,<vsync-end>,<vtotal>\n");
+	fprintf(stderr, "\t\ttest force mode\n");
+	fprintf(stderr, "\tDefault is to test the preferred mode.\n");
 	exit(0);
 }
 
+#define dump_resource(res) if (res) dump_##res()
+
 static gboolean hotplug_event(GIOChannel *source, GIOCondition condition,
 			      gpointer data)
 {
@@ -590,6 +725,20 @@ int main(int argc, char **argv)
 	opterr = 0;
 	while ((c = getopt(argc, argv, optstr)) != -1) {
 		switch (c) {
+		case 'i':
+			dump_info = 1;
+			encoders = connectors = crtcs = modes = framebuffers = 1;
+			break;
+		case 'a':
+			test_all_modes = 1;
+			break;
+		case 'f':
+			force_mode = 1;
+			if(sscanf(optarg,"%f,%d,%d,%d,%d,%d,%d,%d,%d",
+				&force_clock,&force_hdisplay, &force_hsync_start,&force_hsync_end,&force_htotal,
+				&force_vdisplay, &force_vsync_start, &force_vsync_end, &force_vtotal)!= 9)
+				usage(argv[0]);
+			break;
 		default:
 			fprintf(stderr, "unknown option %c\n", c);
 			/* fall through */
@@ -598,9 +747,8 @@ int main(int argc, char **argv)
 			break;
 		}
 	}
-
 	if (argc == 1)
-		encoders = connectors = crtcs = modes = framebuffers = 1;
+		test_preferred_mode = 1;
 
 	for (i = 0; i < ARRAY_SIZE(modules); i++) {
 		fd = drmOpen(modules[i], NULL);
