modetest.c revision 18210155
118210155Smrg/*
218210155Smrg * DRM based mode setting test program
318210155Smrg * Copyright 2008 Tungsten Graphics
418210155Smrg *   Jakob Bornecrantz <jakob@tungstengraphics.com>
518210155Smrg * Copyright 2008 Intel Corporation
618210155Smrg *   Jesse Barnes <jesse.barnes@intel.com>
718210155Smrg *
818210155Smrg * Permission is hereby granted, free of charge, to any person obtaining a
918210155Smrg * copy of this software and associated documentation files (the "Software"),
1018210155Smrg * to deal in the Software without restriction, including without limitation
1118210155Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1218210155Smrg * and/or sell copies of the Software, and to permit persons to whom the
1318210155Smrg * Software is furnished to do so, subject to the following conditions:
1418210155Smrg *
1518210155Smrg * The above copyright notice and this permission notice shall be included in
1618210155Smrg * all copies or substantial portions of the Software.
1718210155Smrg *
1818210155Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1918210155Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2018210155Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2118210155Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2218210155Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2318210155Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2418210155Smrg * IN THE SOFTWARE.
2518210155Smrg */
2618210155Smrg
2718210155Smrg/*
2818210155Smrg * This fairly simple test program dumps output in a similar format to the
2918210155Smrg * "xrandr" tool everyone knows & loves.  It's necessarily slightly different
3018210155Smrg * since the kernel separates outputs into encoder and connector structures,
3118210155Smrg * each with their own unique ID.  The program also allows test testing of the
3218210155Smrg * memory management and mode setting APIs by allowing the user to specify a
3318210155Smrg * connector and mode to use for mode setting.  If all works as expected, a
3418210155Smrg * blue background should be painted on the monitor attached to the specified
3518210155Smrg * connector after the selected mode is set.
3618210155Smrg *
3718210155Smrg * TODO: use cairo to write the mode info on the selected output once
3818210155Smrg *       the mode has been programmed, along with possible test patterns.
3918210155Smrg */
4018210155Smrg#include "config.h"
4118210155Smrg
4218210155Smrg#include <assert.h>
4318210155Smrg#include <stdio.h>
4418210155Smrg#include <stdlib.h>
4518210155Smrg#include <stdint.h>
4618210155Smrg#include <unistd.h>
4718210155Smrg#include <string.h>
4818210155Smrg#include <errno.h>
4918210155Smrg
5018210155Smrg#include "xf86drm.h"
5118210155Smrg#include "xf86drmMode.h"
5218210155Smrg#include "intel_bufmgr.h"
5318210155Smrg
5418210155Smrg#ifdef HAVE_CAIRO
5518210155Smrg#include <math.h>
5618210155Smrg#include <cairo.h>
5718210155Smrg#endif
5818210155Smrg
5918210155SmrgdrmModeRes *resources;
6018210155Smrgint fd, modes;
6118210155Smrg
6218210155Smrg#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
6318210155Smrg
6418210155Smrgstruct type_name {
6518210155Smrg	int type;
6618210155Smrg	char *name;
6718210155Smrg};
6818210155Smrg
6918210155Smrg#define type_name_fn(res) \
7018210155Smrgchar * res##_str(int type) {			\
7118210155Smrg	int i;						\
7218210155Smrg	for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
7318210155Smrg		if (res##_names[i].type == type)	\
7418210155Smrg			return res##_names[i].name;	\
7518210155Smrg	}						\
7618210155Smrg	return "(invalid)";				\
7718210155Smrg}
7818210155Smrg
7918210155Smrgstruct type_name encoder_type_names[] = {
8018210155Smrg	{ DRM_MODE_ENCODER_NONE, "none" },
8118210155Smrg	{ DRM_MODE_ENCODER_DAC, "DAC" },
8218210155Smrg	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
8318210155Smrg	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
8418210155Smrg	{ DRM_MODE_ENCODER_TVDAC, "TVDAC" },
8518210155Smrg};
8618210155Smrg
8718210155Smrgtype_name_fn(encoder_type)
8818210155Smrg
8918210155Smrgstruct type_name connector_status_names[] = {
9018210155Smrg	{ DRM_MODE_CONNECTED, "connected" },
9118210155Smrg	{ DRM_MODE_DISCONNECTED, "disconnected" },
9218210155Smrg	{ DRM_MODE_UNKNOWNCONNECTION, "unknown" },
9318210155Smrg};
9418210155Smrg
9518210155Smrgtype_name_fn(connector_status)
9618210155Smrg
9718210155Smrgstruct type_name connector_type_names[] = {
9818210155Smrg	{ DRM_MODE_CONNECTOR_Unknown, "unknown" },
9918210155Smrg	{ DRM_MODE_CONNECTOR_VGA, "VGA" },
10018210155Smrg	{ DRM_MODE_CONNECTOR_DVII, "DVI-I" },
10118210155Smrg	{ DRM_MODE_CONNECTOR_DVID, "DVI-D" },
10218210155Smrg	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
10318210155Smrg	{ DRM_MODE_CONNECTOR_Composite, "composite" },
10418210155Smrg	{ DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
10518210155Smrg	{ DRM_MODE_CONNECTOR_LVDS, "LVDS" },
10618210155Smrg	{ DRM_MODE_CONNECTOR_Component, "component" },
10718210155Smrg	{ DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
10818210155Smrg	{ DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
10918210155Smrg	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
11018210155Smrg	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
11118210155Smrg};
11218210155Smrg
11318210155Smrgtype_name_fn(connector_type)
11418210155Smrg
11518210155Smrgvoid dump_encoders(void)
11618210155Smrg{
11718210155Smrg	drmModeEncoder *encoder;
11818210155Smrg	int i;
11918210155Smrg
12018210155Smrg	printf("Encoders:\n");
12118210155Smrg	printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
12218210155Smrg	for (i = 0; i < resources->count_encoders; i++) {
12318210155Smrg		encoder = drmModeGetEncoder(fd, resources->encoders[i]);
12418210155Smrg
12518210155Smrg		if (!encoder) {
12618210155Smrg			fprintf(stderr, "could not get encoder %i: %s\n",
12718210155Smrg				resources->encoders[i], strerror(errno));
12818210155Smrg			continue;
12918210155Smrg		}
13018210155Smrg		printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
13118210155Smrg		       encoder->encoder_id,
13218210155Smrg		       encoder->crtc_id,
13318210155Smrg		       encoder_type_str(encoder->encoder_type),
13418210155Smrg		       encoder->possible_crtcs,
13518210155Smrg		       encoder->possible_clones);
13618210155Smrg		drmModeFreeEncoder(encoder);
13718210155Smrg	}
13818210155Smrg	printf("\n");
13918210155Smrg}
14018210155Smrg
14118210155Smrgvoid dump_mode(drmModeModeInfo *mode)
14218210155Smrg{
14318210155Smrg	printf("  %s %.02f %d %d %d %d %d %d %d %d\n",
14418210155Smrg	       mode->name,
14518210155Smrg	       (float)mode->vrefresh / 1000,
14618210155Smrg	       mode->hdisplay,
14718210155Smrg	       mode->hsync_start,
14818210155Smrg	       mode->hsync_end,
14918210155Smrg	       mode->htotal,
15018210155Smrg	       mode->vdisplay,
15118210155Smrg	       mode->vsync_start,
15218210155Smrg	       mode->vsync_end,
15318210155Smrg	       mode->vtotal);
15418210155Smrg}
15518210155Smrg
15618210155Smrgstatic void
15718210155Smrgdump_props(drmModeConnector *connector)
15818210155Smrg{
15918210155Smrg	drmModePropertyPtr props;
16018210155Smrg	int i;
16118210155Smrg
16218210155Smrg	for (i = 0; i < connector->count_props; i++) {
16318210155Smrg		props = drmModeGetProperty(fd, connector->props[i]);
16418210155Smrg		printf("\t%s, flags %d\n", props->name, props->flags);
16518210155Smrg		drmModeFreeProperty(props);
16618210155Smrg	}
16718210155Smrg}
16818210155Smrg
16918210155Smrgvoid dump_connectors(void)
17018210155Smrg{
17118210155Smrg	drmModeConnector *connector;
17218210155Smrg	int i, j;
17318210155Smrg
17418210155Smrg	printf("Connectors:\n");
17518210155Smrg	printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
17618210155Smrg	for (i = 0; i < resources->count_connectors; i++) {
17718210155Smrg		connector = drmModeGetConnector(fd, resources->connectors[i]);
17818210155Smrg
17918210155Smrg		if (!connector) {
18018210155Smrg			fprintf(stderr, "could not get connector %i: %s\n",
18118210155Smrg				resources->connectors[i], strerror(errno));
18218210155Smrg			continue;
18318210155Smrg		}
18418210155Smrg
18518210155Smrg		printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
18618210155Smrg		       connector->connector_id,
18718210155Smrg		       connector->encoder_id,
18818210155Smrg		       connector_status_str(connector->connection),
18918210155Smrg		       connector_type_str(connector->connector_type),
19018210155Smrg		       connector->mmWidth, connector->mmHeight,
19118210155Smrg		       connector->count_modes);
19218210155Smrg
19318210155Smrg		if (!connector->count_modes)
19418210155Smrg			continue;
19518210155Smrg
19618210155Smrg		printf("  modes:\n");
19718210155Smrg		printf("  name refresh (Hz) hdisp hss hse htot vdisp "
19818210155Smrg		       "vss vse vtot)\n");
19918210155Smrg		for (j = 0; j < connector->count_modes; j++)
20018210155Smrg			dump_mode(&connector->modes[j]);
20118210155Smrg
20218210155Smrg		drmModeFreeConnector(connector);
20318210155Smrg
20418210155Smrg		printf("  props:\n");
20518210155Smrg		dump_props(connector);
20618210155Smrg	}
20718210155Smrg	printf("\n");
20818210155Smrg}
20918210155Smrg
21018210155Smrgvoid dump_crtcs(void)
21118210155Smrg{
21218210155Smrg	drmModeCrtc *crtc;
21318210155Smrg	int i;
21418210155Smrg
21518210155Smrg	printf("CRTCs:\n");
21618210155Smrg	printf("id\tfb\tpos\tsize\n");
21718210155Smrg	for (i = 0; i < resources->count_crtcs; i++) {
21818210155Smrg		crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
21918210155Smrg
22018210155Smrg		if (!crtc) {
22118210155Smrg			fprintf(stderr, "could not get crtc %i: %s\n",
22218210155Smrg				resources->crtcs[i], strerror(errno));
22318210155Smrg			continue;
22418210155Smrg		}
22518210155Smrg		printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
22618210155Smrg		       crtc->crtc_id,
22718210155Smrg		       crtc->buffer_id,
22818210155Smrg		       crtc->x, crtc->y,
22918210155Smrg		       crtc->width, crtc->height);
23018210155Smrg		dump_mode(&crtc->mode);
23118210155Smrg
23218210155Smrg		drmModeFreeCrtc(crtc);
23318210155Smrg	}
23418210155Smrg	printf("\n");
23518210155Smrg}
23618210155Smrg
23718210155Smrgvoid dump_framebuffers(void)
23818210155Smrg{
23918210155Smrg	drmModeFB *fb;
24018210155Smrg	int i;
24118210155Smrg
24218210155Smrg	printf("Frame buffers:\n");
24318210155Smrg	printf("id\tsize\tpitch\n");
24418210155Smrg	for (i = 0; i < resources->count_fbs; i++) {
24518210155Smrg		fb = drmModeGetFB(fd, resources->fbs[i]);
24618210155Smrg
24718210155Smrg		if (!fb) {
24818210155Smrg			fprintf(stderr, "could not get fb %i: %s\n",
24918210155Smrg				resources->fbs[i], strerror(errno));
25018210155Smrg			continue;
25118210155Smrg		}
25218210155Smrg		printf("%d\t(%dx%d)\t%d\n",
25318210155Smrg		       fb->fb_id,
25418210155Smrg		       fb->width, fb->height);
25518210155Smrg
25618210155Smrg		drmModeFreeFB(fb);
25718210155Smrg	}
25818210155Smrg	printf("\n");
25918210155Smrg}
26018210155Smrg
26118210155Smrg/*
26218210155Smrg * Mode setting with the kernel interfaces is a bit of a chore.
26318210155Smrg * First you have to find the connector in question and make sure the
26418210155Smrg * requested mode is available.
26518210155Smrg * Then you need to find the encoder attached to that connector so you
26618210155Smrg * can bind it with a free crtc.
26718210155Smrg */
26818210155Smrgstruct connector {
26918210155Smrg	int id;
27018210155Smrg	char mode_str[64];
27118210155Smrg	drmModeModeInfo *mode;
27218210155Smrg	drmModeEncoder *encoder;
27318210155Smrg	int crtc;
27418210155Smrg};
27518210155Smrg
27618210155Smrgstatic void
27718210155Smrgconnector_find_mode(struct connector *c)
27818210155Smrg{
27918210155Smrg	drmModeConnector *connector;
28018210155Smrg	int i, j, size, ret, width, height;
28118210155Smrg
28218210155Smrg	/* First, find the connector & mode */
28318210155Smrg	c->mode = NULL;
28418210155Smrg	for (i = 0; i < resources->count_connectors; i++) {
28518210155Smrg		connector = drmModeGetConnector(fd, resources->connectors[i]);
28618210155Smrg
28718210155Smrg		if (!connector) {
28818210155Smrg			fprintf(stderr, "could not get connector %i: %s\n",
28918210155Smrg				resources->connectors[i], strerror(errno));
29018210155Smrg			drmModeFreeConnector(connector);
29118210155Smrg			continue;
29218210155Smrg		}
29318210155Smrg
29418210155Smrg		if (!connector->count_modes) {
29518210155Smrg			drmModeFreeConnector(connector);
29618210155Smrg			continue;
29718210155Smrg		}
29818210155Smrg
29918210155Smrg		if (connector->connector_id != c->id) {
30018210155Smrg			drmModeFreeConnector(connector);
30118210155Smrg			continue;
30218210155Smrg		}
30318210155Smrg
30418210155Smrg		for (j = 0; j < connector->count_modes; j++) {
30518210155Smrg			c->mode = &connector->modes[j];
30618210155Smrg			if (!strcmp(c->mode->name, c->mode_str))
30718210155Smrg				break;
30818210155Smrg		}
30918210155Smrg
31018210155Smrg		/* Found it, break out */
31118210155Smrg		if (c->mode)
31218210155Smrg			break;
31318210155Smrg
31418210155Smrg		drmModeFreeConnector(connector);
31518210155Smrg	}
31618210155Smrg
31718210155Smrg	if (!c->mode) {
31818210155Smrg		fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
31918210155Smrg		return;
32018210155Smrg	}
32118210155Smrg
32218210155Smrg	/* Now get the encoder */
32318210155Smrg	for (i = 0; i < resources->count_encoders; i++) {
32418210155Smrg		c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
32518210155Smrg
32618210155Smrg		if (!c->encoder) {
32718210155Smrg			fprintf(stderr, "could not get encoder %i: %s\n",
32818210155Smrg				resources->encoders[i], strerror(errno));
32918210155Smrg			drmModeFreeEncoder(c->encoder);
33018210155Smrg			continue;
33118210155Smrg		}
33218210155Smrg
33318210155Smrg		if (c->encoder->encoder_id  == connector->encoder_id)
33418210155Smrg			break;
33518210155Smrg
33618210155Smrg		drmModeFreeEncoder(c->encoder);
33718210155Smrg	}
33818210155Smrg
33918210155Smrg	if (c->crtc == -1)
34018210155Smrg		c->crtc = c->encoder->crtc_id;
34118210155Smrg}
34218210155Smrg
34318210155Smrg#ifdef HAVE_CAIRO
34418210155Smrg
34518210155Smrgstatic int
34618210155Smrgcreate_test_buffer(drm_intel_bufmgr *bufmgr,
34718210155Smrg		   int width, int height, int *stride_out, drm_intel_bo **bo_out)
34818210155Smrg{
34918210155Smrg	drm_intel_bo *bo;
35018210155Smrg	unsigned int *fb_ptr;
35118210155Smrg	int size, ret, i, stride;
35218210155Smrg	div_t d;
35318210155Smrg	cairo_surface_t *surface;
35418210155Smrg	cairo_t *cr;
35518210155Smrg	char buf[64];
35618210155Smrg	int x, y;
35718210155Smrg
35818210155Smrg	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
35918210155Smrg	stride = cairo_image_surface_get_stride(surface);
36018210155Smrg	size = stride * height;
36118210155Smrg	fb_ptr = (unsigned int *) cairo_image_surface_get_data(surface);
36218210155Smrg
36318210155Smrg	/* paint the buffer with colored tiles */
36418210155Smrg	for (i = 0; i < width * height; i++) {
36518210155Smrg		d = div(i, width);
36618210155Smrg		fb_ptr[i] = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
36718210155Smrg	}
36818210155Smrg
36918210155Smrg	cr = cairo_create(surface);
37018210155Smrg	cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
37118210155Smrg	for (x = 0; x < width; x += 250)
37218210155Smrg		for (y = 0; y < height; y += 250) {
37318210155Smrg			cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
37418210155Smrg			cairo_move_to(cr, x, y - 20);
37518210155Smrg			cairo_line_to(cr, x, y + 20);
37618210155Smrg			cairo_move_to(cr, x - 20, y);
37718210155Smrg			cairo_line_to(cr, x + 20, y);
37818210155Smrg			cairo_new_sub_path(cr);
37918210155Smrg			cairo_arc(cr, x, y, 10, 0, M_PI * 2);
38018210155Smrg			cairo_set_line_width(cr, 4);
38118210155Smrg			cairo_set_source_rgb(cr, 0, 0, 0);
38218210155Smrg			cairo_stroke_preserve(cr);
38318210155Smrg			cairo_set_source_rgb(cr, 1, 1, 1);
38418210155Smrg			cairo_set_line_width(cr, 2);
38518210155Smrg			cairo_stroke(cr);
38618210155Smrg			snprintf(buf, sizeof buf, "%d, %d", x, y);
38718210155Smrg			cairo_move_to(cr, x + 20, y + 20);
38818210155Smrg			cairo_text_path(cr, buf);
38918210155Smrg			cairo_set_source_rgb(cr, 0, 0, 0);
39018210155Smrg			cairo_stroke_preserve(cr);
39118210155Smrg			cairo_set_source_rgb(cr, 1, 1, 1);
39218210155Smrg			cairo_fill(cr);
39318210155Smrg		}
39418210155Smrg
39518210155Smrg	cairo_destroy(cr);
39618210155Smrg
39718210155Smrg	bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096);
39818210155Smrg	if (!bo) {
39918210155Smrg		fprintf(stderr, "failed to alloc buffer: %s\n",
40018210155Smrg			strerror(errno));
40118210155Smrg		return -1;
40218210155Smrg	}
40318210155Smrg
40418210155Smrg	drm_intel_bo_subdata(bo, 0, size, fb_ptr);
40518210155Smrg
40618210155Smrg	cairo_surface_destroy(surface);
40718210155Smrg
40818210155Smrg	*bo_out = bo;
40918210155Smrg	*stride_out = stride;
41018210155Smrg
41118210155Smrg	return 0;
41218210155Smrg}
41318210155Smrg
41418210155Smrg#else
41518210155Smrg
41618210155Smrgstatic int
41718210155Smrgcreate_test_buffer(drm_intel_bufmgr *bufmgr,
41818210155Smrg		   int width, int height, int *stride_out, drm_intel_bo **bo_out)
41918210155Smrg{
42018210155Smrg	drm_intel_bo *bo;
42118210155Smrg	unsigned int *fb_ptr;
42218210155Smrg	int size, ret, i, stride;
42318210155Smrg	div_t d;
42418210155Smrg
42518210155Smrg	/* Mode size at 32 bpp */
42618210155Smrg	stride = width * 4;
42718210155Smrg	size = stride * height;
42818210155Smrg
42918210155Smrg	bo = drm_intel_bo_alloc(bufmgr, "frontbuffer", size, 4096);
43018210155Smrg	if (!bo) {
43118210155Smrg		fprintf(stderr, "failed to alloc buffer: %s\n",
43218210155Smrg			strerror(errno));
43318210155Smrg		return -1;
43418210155Smrg	}
43518210155Smrg
43618210155Smrg	ret = drm_intel_gem_bo_map_gtt(bo);
43718210155Smrg	if (ret) {
43818210155Smrg		fprintf(stderr, "failed to GTT map buffer: %s\n",
43918210155Smrg			strerror(errno));
44018210155Smrg		return -1;
44118210155Smrg	}
44218210155Smrg
44318210155Smrg	fb_ptr = bo->virtual;
44418210155Smrg
44518210155Smrg	/* paint the buffer with colored tiles */
44618210155Smrg	for (i = 0; i < width * height; i++) {
44718210155Smrg		d = div(i, width);
44818210155Smrg		fb_ptr[i] = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
44918210155Smrg	}
45018210155Smrg	drm_intel_bo_unmap(bo);
45118210155Smrg
45218210155Smrg	*bo_out = bo;
45318210155Smrg	*stride_out = stride;
45418210155Smrg
45518210155Smrg	return 0;
45618210155Smrg}
45718210155Smrg
45818210155Smrg#endif
45918210155Smrg
46018210155Smrgstatic void
46118210155Smrgset_mode(struct connector *c, int count)
46218210155Smrg{
46318210155Smrg	drmModeConnector *connector;
46418210155Smrg	drmModeEncoder *encoder = NULL;
46518210155Smrg	struct drm_mode_modeinfo *mode = NULL;
46618210155Smrg	drm_intel_bufmgr *bufmgr;
46718210155Smrg	drm_intel_bo *bo;
46818210155Smrg	unsigned int fb_id;
46918210155Smrg	int i, j, ret, width, height, x, stride;
47018210155Smrg
47118210155Smrg	width = 0;
47218210155Smrg	height = 0;
47318210155Smrg	for (i = 0; i < count; i++) {
47418210155Smrg		connector_find_mode(&c[i]);
47518210155Smrg		if (c[i].mode == NULL)
47618210155Smrg			continue;
47718210155Smrg		width += c[i].mode->hdisplay;
47818210155Smrg		if (height < c[i].mode->vdisplay)
47918210155Smrg			height = c[i].mode->vdisplay;
48018210155Smrg	}
48118210155Smrg
48218210155Smrg	bufmgr = drm_intel_bufmgr_gem_init(fd, 2<<20);
48318210155Smrg	if (!bufmgr) {
48418210155Smrg		fprintf(stderr, "failed to init bufmgr: %s\n", strerror(errno));
48518210155Smrg		return;
48618210155Smrg	}
48718210155Smrg
48818210155Smrg	if (create_test_buffer(bufmgr, width, height, &stride, &bo))
48918210155Smrg		return;
49018210155Smrg
49118210155Smrg	ret = drmModeAddFB(fd, width, height, 32, 32, stride, bo->handle,
49218210155Smrg			   &fb_id);
49318210155Smrg	if (ret) {
49418210155Smrg		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
49518210155Smrg		return;
49618210155Smrg	}
49718210155Smrg
49818210155Smrg	x = 0;
49918210155Smrg	for (i = 0; i < count; i++) {
50018210155Smrg		int crtc_id;
50118210155Smrg		if (c[i].mode == NULL)
50218210155Smrg			continue;
50318210155Smrg
50418210155Smrg		printf("setting mode %s on connector %d, crtc %d\n",
50518210155Smrg		       c[i].mode_str, c[i].id, c[i].crtc);
50618210155Smrg
50718210155Smrg		ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
50818210155Smrg				     &c[i].id, 1, c[i].mode);
50918210155Smrg		x += c[i].mode->hdisplay;
51018210155Smrg
51118210155Smrg		if (ret) {
51218210155Smrg			fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
51318210155Smrg			return;
51418210155Smrg		}
51518210155Smrg	}
51618210155Smrg}
51718210155Smrg
51818210155Smrgextern char *optarg;
51918210155Smrgextern int optind, opterr, optopt;
52018210155Smrgstatic char optstr[] = "ecpmfs:";
52118210155Smrg
52218210155Smrgvoid usage(char *name)
52318210155Smrg{
52418210155Smrg	fprintf(stderr, "usage: %s [-ecpmf]\n", name);
52518210155Smrg	fprintf(stderr, "\t-e\tlist encoders\n");
52618210155Smrg	fprintf(stderr, "\t-c\tlist connectors\n");
52718210155Smrg	fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
52818210155Smrg	fprintf(stderr, "\t-m\tlist modes\n");
52918210155Smrg	fprintf(stderr, "\t-f\tlist framebuffers\n");
53018210155Smrg	fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
53118210155Smrg	fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
53218210155Smrg	fprintf(stderr, "\n\tDefault is to dump all info.\n");
53318210155Smrg	exit(0);
53418210155Smrg}
53518210155Smrg
53618210155Smrg#define dump_resource(res) if (res) dump_##res()
53718210155Smrg
53818210155Smrgint main(int argc, char **argv)
53918210155Smrg{
54018210155Smrg	int c;
54118210155Smrg	int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
54218210155Smrg	char *modules[] = { "i915", "radeon" };
54318210155Smrg	char *modeset = NULL, *mode, *connector;
54418210155Smrg	int i, connector_id, count = 0;
54518210155Smrg	struct connector con_args[2];
54618210155Smrg
54718210155Smrg	opterr = 0;
54818210155Smrg	while ((c = getopt(argc, argv, optstr)) != -1) {
54918210155Smrg		switch (c) {
55018210155Smrg		case 'e':
55118210155Smrg			encoders = 1;
55218210155Smrg			break;
55318210155Smrg		case 'c':
55418210155Smrg			connectors = 1;
55518210155Smrg			break;
55618210155Smrg		case 'p':
55718210155Smrg			crtcs = 1;
55818210155Smrg			break;
55918210155Smrg		case 'm':
56018210155Smrg			modes = 1;
56118210155Smrg			break;
56218210155Smrg		case 'f':
56318210155Smrg			framebuffers = 1;
56418210155Smrg			break;
56518210155Smrg		case 's':
56618210155Smrg			modeset = strdup(optarg);
56718210155Smrg			con_args[count].crtc = -1;
56818210155Smrg			if (sscanf(optarg, "%d:%64s",
56918210155Smrg				   &con_args[count].id,
57018210155Smrg				   &con_args[count].mode_str) != 2 &&
57118210155Smrg			    sscanf(optarg, "%d@%d:%64s",
57218210155Smrg				   &con_args[count].id,
57318210155Smrg				   &con_args[count].crtc,
57418210155Smrg				   &con_args[count].mode_str) != 3)
57518210155Smrg				usage(argv[0]);
57618210155Smrg			count++;
57718210155Smrg			break;
57818210155Smrg		default:
57918210155Smrg			usage(argv[0]);
58018210155Smrg			break;
58118210155Smrg		}
58218210155Smrg	}
58318210155Smrg
58418210155Smrg	if (argc == 1)
58518210155Smrg		encoders = connectors = crtcs = modes = framebuffers = 1;
58618210155Smrg
58718210155Smrg	for (i = 0; i < ARRAY_SIZE(modules); i++) {
58818210155Smrg		printf("trying to load module %s...", modules[i]);
58918210155Smrg		fd = drmOpen(modules[i], NULL);
59018210155Smrg		if (fd < 0) {
59118210155Smrg			printf("failed.\n");
59218210155Smrg		} else {
59318210155Smrg			printf("success.\n");
59418210155Smrg			break;
59518210155Smrg		}
59618210155Smrg	}
59718210155Smrg
59818210155Smrg	if (i == ARRAY_SIZE(modules)) {
59918210155Smrg		fprintf(stderr, "failed to load any modules, aborting.\n");
60018210155Smrg		return -1;
60118210155Smrg	}
60218210155Smrg
60318210155Smrg	resources = drmModeGetResources(fd);
60418210155Smrg	if (!resources) {
60518210155Smrg		fprintf(stderr, "drmModeGetResources failed: %s\n",
60618210155Smrg			strerror(errno));
60718210155Smrg		drmClose(fd);
60818210155Smrg		return 1;
60918210155Smrg	}
61018210155Smrg
61118210155Smrg	dump_resource(encoders);
61218210155Smrg	dump_resource(connectors);
61318210155Smrg	dump_resource(crtcs);
61418210155Smrg	dump_resource(framebuffers);
61518210155Smrg
61618210155Smrg	if (count > 0) {
61718210155Smrg		set_mode(con_args, count);
61818210155Smrg		getchar();
61918210155Smrg	}
62018210155Smrg
62118210155Smrg	drmModeFreeResources(resources);
62218210155Smrg
62318210155Smrg	return 0;
62418210155Smrg}
625