modetest.c revision ebd7904877d08525beb5039e4ea2f5b6c0a7c23f
1731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes/*
2731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * DRM based mode setting test program
3731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Copyright 2008 Tungsten Graphics
4731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes *   Jakob Bornecrantz <jakob@tungstengraphics.com>
5731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Copyright 2008 Intel Corporation
6731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes *   Jesse Barnes <jesse.barnes@intel.com>
7731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes *
8731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Permission is hereby granted, free of charge, to any person obtaining a
9731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * copy of this software and associated documentation files (the "Software"),
10731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * to deal in the Software without restriction, including without limitation
11731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * and/or sell copies of the Software, and to permit persons to whom the
13731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Software is furnished to do so, subject to the following conditions:
14731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes *
15731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * The above copyright notice and this permission notice shall be included in
16731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * all copies or substantial portions of the Software.
17731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes *
18731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * IN THE SOFTWARE.
25731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes */
26731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
27731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes/*
28731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * This fairly simple test program dumps output in a similar format to the
29731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * "xrandr" tool everyone knows & loves.  It's necessarily slightly different
30731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * since the kernel separates outputs into encoder and connector structures,
31731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * each with their own unique ID.  The program also allows test testing of the
32731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * memory management and mode setting APIs by allowing the user to specify a
33731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * connector and mode to use for mode setting.  If all works as expected, a
34731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * blue background should be painted on the monitor attached to the specified
35731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * connector after the selected mode is set.
36731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes *
37731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * TODO: use cairo to write the mode info on the selected output once
38731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes *       the mode has been programmed, along with possible test patterns.
39731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes */
407a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg#include "config.h"
417a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
42731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <assert.h>
43731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <stdio.h>
44731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <stdlib.h>
45731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <stdint.h>
46d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni#include <inttypes.h>
47731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <unistd.h>
48731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <string.h>
49731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <errno.h>
501e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg#include <sys/poll.h>
51e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell#include <sys/time.h>
52731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
53731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include "xf86drm.h"
54731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include "xf86drmMode.h"
55d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark#include "drm_fourcc.h"
568fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke#include "libkms.h"
57731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
58db004badef9315ba6a5f165d0974dd5afd5a6178Laurent Pinchart#include "buffers.h"
597a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
60731cd5526e5c732d51307b26e784f454a724a699Jesse BarnesdrmModeRes *resources;
61731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint fd, modes;
62731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
63731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
64731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
65731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesstruct type_name {
66731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int type;
67731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	char *name;
68731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes};
69731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
70731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#define type_name_fn(res) \
71731cd5526e5c732d51307b26e784f454a724a699Jesse Barneschar * res##_str(int type) {			\
729b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	unsigned int i;					\
73731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
74731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (res##_names[i].type == type)	\
75731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			return res##_names[i].name;	\
76731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}						\
77731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	return "(invalid)";				\
78731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
79731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
80731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesstruct type_name encoder_type_names[] = {
81731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_ENCODER_NONE, "none" },
82731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_ENCODER_DAC, "DAC" },
83731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_ENCODER_TMDS, "TMDS" },
84731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_ENCODER_LVDS, "LVDS" },
85731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_ENCODER_TVDAC, "TVDAC" },
86731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes};
87731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
88731cd5526e5c732d51307b26e784f454a724a699Jesse Barnestype_name_fn(encoder_type)
89731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
90731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesstruct type_name connector_status_names[] = {
91731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTED, "connected" },
92731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_DISCONNECTED, "disconnected" },
93731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_UNKNOWNCONNECTION, "unknown" },
94731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes};
95731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
96731cd5526e5c732d51307b26e784f454a724a699Jesse Barnestype_name_fn(connector_status)
97731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
98731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesstruct type_name connector_type_names[] = {
99731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_Unknown, "unknown" },
100731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_VGA, "VGA" },
101731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_DVII, "DVI-I" },
102731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_DVID, "DVI-D" },
103731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
104731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_Composite, "composite" },
105731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
106731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_LVDS, "LVDS" },
107731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_Component, "component" },
108731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
109731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
110731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
111731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
112b8abe6139e5c6779ee87d983346f0f65bf67462eJesse Barnes	{ DRM_MODE_CONNECTOR_TV, "TV" },
113b8abe6139e5c6779ee87d983346f0f65bf67462eJesse Barnes	{ DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
114731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes};
115731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
116731cd5526e5c732d51307b26e784f454a724a699Jesse Barnestype_name_fn(connector_type)
117731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
118c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg#define bit_name_fn(res)					\
119c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsbergchar * res##_str(int type) {					\
120c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	int i;							\
121c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	const char *sep = "";					\
122c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	for (i = 0; i < ARRAY_SIZE(res##_names); i++) {		\
123c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg		if (type & (1 << i)) {				\
124c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg			printf("%s%s", sep, res##_names[i]);	\
125c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg			sep = ", ";				\
126c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg		}						\
127c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	}							\
128c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg}
129c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
130c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsbergstatic const char *mode_type_names[] = {
131c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"builtin",
132c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"clock_c",
133c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"crtc_c",
134c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"preferred",
135c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"default",
136c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"userdef",
137c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"driver",
138c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg};
139c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
140c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsbergbit_name_fn(mode_type)
141c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
142c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsbergstatic const char *mode_flag_names[] = {
143c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"phsync",
144c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"nhsync",
145c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"pvsync",
146c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"nvsync",
147c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"interlace",
148c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"dblscan",
149c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"csync",
150c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"pcsync",
151c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"ncsync",
152c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"hskew",
153c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"bcast",
154c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"pixmux",
155c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"dblclk",
156c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"clkdiv2"
157c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg};
158c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
159c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsbergbit_name_fn(mode_flag)
160c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
161731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesvoid dump_encoders(void)
162731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
163731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeEncoder *encoder;
164731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i;
165731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
166731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	printf("Encoders:\n");
167731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
168731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < resources->count_encoders; i++) {
169731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		encoder = drmModeGetEncoder(fd, resources->encoders[i]);
170731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
171731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (!encoder) {
172731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			fprintf(stderr, "could not get encoder %i: %s\n",
173731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes				resources->encoders[i], strerror(errno));
174731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
175731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
176731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
177731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->encoder_id,
178731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->crtc_id,
179731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder_type_str(encoder->encoder_type),
180731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->possible_crtcs,
181731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->possible_clones);
182731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		drmModeFreeEncoder(encoder);
183731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1840243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
1850243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg}
1860243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg
1879fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsbergvoid dump_mode(drmModeModeInfo *mode)
1880243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg{
189c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf("  %s %d %d %d %d %d %d %d %d %d",
1900243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->name,
191694ef59532253727176ed0ce9077ae3ec41dd457Marcin Kościelnicki	       mode->vrefresh,
1920243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->hdisplay,
1930243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->hsync_start,
1940243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->hsync_end,
1950243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->htotal,
1960243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vdisplay,
1970243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vsync_start,
1980243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vsync_end,
1990243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vtotal);
200c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
201c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf(" flags: ");
202c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	mode_flag_str(mode->flags);
203c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf("; type: ");
204c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	mode_type_str(mode->type);
205c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf("\n");
206731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
207731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
2089fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsbergstatic void
209d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanonidump_blob(uint32_t blob_id)
210d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni{
211d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	uint32_t i;
212d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	unsigned char *blob_data;
213d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	drmModePropertyBlobPtr blob;
214d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
215d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	blob = drmModeGetPropertyBlob(fd, blob_id);
216d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (!blob)
217d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		return;
218d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
219d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	blob_data = blob->data;
220d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
221d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	for (i = 0; i < blob->length; i++) {
222d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		if (i % 16 == 0)
223d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf("\n\t\t\t");
224d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("%.2hhx", blob_data[i]);
225d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
226d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\n");
227d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
228d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	drmModeFreePropertyBlob(blob);
229d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni}
230d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
231d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanonistatic void
232d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanonidump_prop(uint32_t prop_id, uint64_t value)
2339fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg{
2349fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg	int i;
235d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	drmModePropertyPtr prop;
236d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
237d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	prop = drmModeGetProperty(fd, prop_id);
238d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
239d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\t%d", prop_id);
240d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (!prop) {
241d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
242d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		return;
243d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
244d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
245d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf(" %s:\n", prop->name);
246d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
247d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\t\tflags:");
248d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_PENDING)
249d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" pending");
250d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_RANGE)
251d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" range");
252d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
253d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" immutable");
254d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_ENUM)
255d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" enum");
2566df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark	if (prop->flags & DRM_MODE_PROP_BITMASK)
2576df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		printf(" bitmask");
258d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_BLOB)
259d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" blob");
260d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\n");
2619fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg
262d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_RANGE) {
263d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\t\tvalues:");
264d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		for (i = 0; i < prop->count_values; i++)
265d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf(" %"PRIu64, prop->values[i]);
266d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
2679fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg	}
268d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
269d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_ENUM) {
270d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\t\tenums:");
271d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		for (i = 0; i < prop->count_enums; i++)
272d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf(" %s=%llu", prop->enums[i].name,
273d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			       prop->enums[i].value);
274d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
2756df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark	} else if (prop->flags & DRM_MODE_PROP_BITMASK) {
2766df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		printf("\t\tvalues:");
2776df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		for (i = 0; i < prop->count_enums; i++)
2786df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark			printf(" %s=0x%llx", prop->enums[i].name,
2796df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark			       (1LL << prop->enums[i].value));
2806df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		printf("\n");
281d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	} else {
282d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		assert(prop->count_enums == 0);
283d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
284d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
285d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_BLOB) {
286d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\t\tblobs:\n");
287d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		for (i = 0; i < prop->count_blobs; i++)
288d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			dump_blob(prop->blob_ids[i]);
289d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
290d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	} else {
291d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		assert(prop->count_blobs == 0);
292d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
293d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
294d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\t\tvalue:");
295d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_BLOB)
296d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		dump_blob(value);
297d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	else
298d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" %"PRIu64"\n", value);
299d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
300d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	drmModeFreeProperty(prop);
3019fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg}
3029fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg
303731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesvoid dump_connectors(void)
304731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
305731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeConnector *connector;
306731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i, j;
307731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
308731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	printf("Connectors:\n");
3091e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n");
310731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < resources->count_connectors; i++) {
311731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		connector = drmModeGetConnector(fd, resources->connectors[i]);
312731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
313731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (!connector) {
314731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			fprintf(stderr, "could not get connector %i: %s\n",
315731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes				resources->connectors[i], strerror(errno));
316731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
317731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
318731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
3191e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t",
320731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->connector_id,
321731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->encoder_id,
322731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector_status_str(connector->connection),
323731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector_type_str(connector->connector_type),
324731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->mmWidth, connector->mmHeight,
325731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->count_modes);
326731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
3271e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		for (j = 0; j < connector->count_encoders; j++)
3281e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			printf("%s%d", j > 0 ? ", " : "", connector->encoders[j]);
3291e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		printf("\n");
3301e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
331a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni		if (connector->count_modes) {
332a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			printf("  modes:\n");
333d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf("\tname refresh (Hz) hdisp hss hse htot vdisp "
334a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			       "vss vse vtot)\n");
335a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			for (j = 0; j < connector->count_modes; j++)
336a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni				dump_mode(&connector->modes[j]);
337a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni
338a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			printf("  props:\n");
339d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			for (j = 0; j < connector->count_props; j++)
340d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni				dump_prop(connector->props[j],
341d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni					  connector->prop_values[j]);
342a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni		}
3439a37455b35d746d694760cfe8850a8bf856d73c9Marcin Kościelnicki
3449a37455b35d746d694760cfe8850a8bf856d73c9Marcin Kościelnicki		drmModeFreeConnector(connector);
345731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
3460243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
347731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
348731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
349731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesvoid dump_crtcs(void)
350731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
351731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeCrtc *crtc;
35286dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni	drmModeObjectPropertiesPtr props;
353731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i;
35486dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni	uint32_t j;
355731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
3560243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("CRTCs:\n");
3570243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("id\tfb\tpos\tsize\n");
358731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < resources->count_crtcs; i++) {
359731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
360731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
361731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (!crtc) {
362731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			fprintf(stderr, "could not get crtc %i: %s\n",
363731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes				resources->crtcs[i], strerror(errno));
364731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
365731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
3660243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
3670243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->crtc_id,
3680243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->buffer_id,
3690243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->x, crtc->y,
3700243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->width, crtc->height);
3710243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		dump_mode(&crtc->mode);
3720243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg
37386dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni		printf("  props:\n");
37486dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni		props = drmModeObjectGetProperties(fd, crtc->crtc_id,
37586dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni						   DRM_MODE_OBJECT_CRTC);
37686dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni		if (props) {
37786dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni			for (j = 0; j < props->count_props; j++)
37886dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni				dump_prop(props->props[j],
37986dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni					  props->prop_values[j]);
38086dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni			drmModeFreeObjectProperties(props);
38186dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni		} else {
38286dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni			printf("\tcould not get crtc properties: %s\n",
38386dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni			       strerror(errno));
38486dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni		}
38586dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni
386731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		drmModeFreeCrtc(crtc);
387731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
3880243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
389731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
390731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
391731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesvoid dump_framebuffers(void)
392731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
393731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeFB *fb;
394731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i;
395731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
3960243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("Frame buffers:\n");
3970243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("id\tsize\tpitch\n");
398731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < resources->count_fbs; i++) {
399731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		fb = drmModeGetFB(fd, resources->fbs[i]);
400731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
401731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (!fb) {
402731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			fprintf(stderr, "could not get fb %i: %s\n",
403731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes				resources->fbs[i], strerror(errno));
404731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
405731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
406e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell		printf("%u\t(%ux%u)\t%u\n",
4070243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       fb->fb_id,
408e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell		       fb->width, fb->height,
409e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell		       fb->pitch);
4100243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg
411731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		drmModeFreeFB(fb);
412731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
4130243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
414731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
415731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
416d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clarkstatic void dump_planes(void)
417d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark{
41825e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark	drmModeObjectPropertiesPtr props;
419d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	drmModePlaneRes *plane_resources;
420d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	drmModePlane *ovr;
4219b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	unsigned int i, j;
422d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
423d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	plane_resources = drmModeGetPlaneResources(fd);
424d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	if (!plane_resources) {
425d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
426d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			strerror(errno));
427d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return;
428d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
429d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
430d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	printf("Planes:\n");
431d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\n");
432d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	for (i = 0; i < plane_resources->count_planes; i++) {
433d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
434d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		if (!ovr) {
435d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			fprintf(stderr, "drmModeGetPlane failed: %s\n",
436d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark				strerror(errno));
437d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			continue;
438d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		}
439d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
440d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%d\n",
441d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		       ovr->plane_id, ovr->crtc_id, ovr->fb_id,
442d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		       ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
443d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		       ovr->gamma_size);
444d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
445d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		if (!ovr->count_formats)
446d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			continue;
447d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
448d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		printf("  formats:");
449d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		for (j = 0; j < ovr->count_formats; j++)
450d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			printf(" %4.4s", (char *)&ovr->formats[j]);
451d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		printf("\n");
452d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
45325e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark		printf("  props:\n");
45425e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark		props = drmModeObjectGetProperties(fd, ovr->plane_id,
45525e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark						   DRM_MODE_OBJECT_PLANE);
45625e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark		if (props) {
45725e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark			for (j = 0; j < props->count_props; j++)
45825e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark				dump_prop(props->props[j],
45925e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark					  props->prop_values[j]);
46025e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark			drmModeFreeObjectProperties(props);
46125e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark		} else {
46225e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark			printf("\tcould not get plane properties: %s\n",
46325e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark			       strerror(errno));
46425e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark		}
46525e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark
466d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		drmModeFreePlane(ovr);
467d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
468d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	printf("\n");
469d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
4700ef7644fe5161d3b50f9550ebbf8cbbabd51706fPaulo Zanoni	drmModeFreePlaneResources(plane_resources);
471d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	return;
472d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark}
473d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
474a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart/* -----------------------------------------------------------------------------
475a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart * Connectors and planes
476a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart */
477a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart
478731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes/*
479731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Mode setting with the kernel interfaces is a bit of a chore.
480731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * First you have to find the connector in question and make sure the
481731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * requested mode is available.
482731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Then you need to find the encoder attached to that connector so you
483731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * can bind it with a free crtc.
484731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes */
485669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsbergstruct connector {
486e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell	uint32_t id;
487669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	char mode_str[64];
488cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	char format_str[5];
489cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	unsigned int fourcc;
4909fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg	drmModeModeInfo *mode;
491669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	drmModeEncoder *encoder;
4928b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg	int crtc;
493d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	int pipe;
4941e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	unsigned int fb_id[2], current_fb_id;
4951e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	struct timeval start;
4961e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
4971e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	int swap_count;
498d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark};
499d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
500d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clarkstruct plane {
501d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	uint32_t con_id;  /* the id of connector to bind to */
502d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	uint32_t w, h;
503d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	unsigned int fb_id;
504b83ad866220911e5be1704e6df085705e5ba8eaeRob Clark	char format_str[5]; /* need to leave room for terminating \0 */
5050375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	unsigned int fourcc;
506d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark};
507669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg
508669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsbergstatic void
509669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsbergconnector_find_mode(struct connector *c)
510731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
511731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeConnector *connector;
512e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell	int i, j;
513731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
514731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	/* First, find the connector & mode */
515669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	c->mode = NULL;
516731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < resources->count_connectors; i++) {
517731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		connector = drmModeGetConnector(fd, resources->connectors[i]);
518731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
519731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (!connector) {
520731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			fprintf(stderr, "could not get connector %i: %s\n",
521731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes				resources->connectors[i], strerror(errno));
522731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			drmModeFreeConnector(connector);
523731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
524731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
525731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
526731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (!connector->count_modes) {
527731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			drmModeFreeConnector(connector);
528731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
529731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
530731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
531669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		if (connector->connector_id != c->id) {
532731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			drmModeFreeConnector(connector);
533731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
534731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
535731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
536731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		for (j = 0; j < connector->count_modes; j++) {
537669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			c->mode = &connector->modes[j];
538669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			if (!strcmp(c->mode->name, c->mode_str))
539731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes				break;
540731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
541731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
542731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		/* Found it, break out */
543669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		if (c->mode)
544731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
545731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
546731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		drmModeFreeConnector(connector);
547731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
548731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
549669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	if (!c->mode) {
550669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
551731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		return;
552731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
553731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
554731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	/* Now get the encoder */
555731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < resources->count_encoders; i++) {
556669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
557731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
558669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		if (!c->encoder) {
559731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			fprintf(stderr, "could not get encoder %i: %s\n",
560731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes				resources->encoders[i], strerror(errno));
561669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			drmModeFreeEncoder(c->encoder);
562731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
563731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
564731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
565669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		if (c->encoder->encoder_id  == connector->encoder_id)
566731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
567731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
568669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		drmModeFreeEncoder(c->encoder);
569669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	}
5708b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg
5718b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg	if (c->crtc == -1)
5728b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg		c->crtc = c->encoder->crtc_id;
573d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
574d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	/* and figure out which crtc index it is: */
575d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	for (i = 0; i < resources->count_crtcs; i++) {
576d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		if (c->crtc == resources->crtcs[i]) {
577d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			c->pipe = i;
578d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			break;
579d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		}
580d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
581d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
582669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg}
583669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg
5843fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart/* -------------------------------------------------------------------------- */
5853fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
5863fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchartvoid
5873fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchartpage_flip_handler(int fd, unsigned int frame,
5883fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		  unsigned int sec, unsigned int usec, void *data)
5893fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart{
5903fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	struct connector *c;
5913fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	unsigned int new_fb_id;
5923fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	struct timeval end;
5933fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	double t;
5943fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
5953fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	c = data;
5963fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (c->current_fb_id == c->fb_id[0])
5973fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		new_fb_id = c->fb_id[1];
5983fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	else
5993fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		new_fb_id = c->fb_id[0];
6003fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
6013fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	drmModePageFlip(fd, c->crtc, new_fb_id,
6023fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart			DRM_MODE_PAGE_FLIP_EVENT, c);
6033fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	c->current_fb_id = new_fb_id;
6043fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	c->swap_count++;
6053fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (c->swap_count == 60) {
6063fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		gettimeofday(&end, NULL);
6073fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		t = end.tv_sec + end.tv_usec * 1e-6 -
6083fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart			(c->start.tv_sec + c->start.tv_usec * 1e-6);
6093fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		fprintf(stderr, "freq: %.02fHz\n", c->swap_count / t);
6103fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		c->swap_count = 0;
6113fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		c->start = end;
6123fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	}
6133fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart}
6143fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
615d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clarkstatic int
616d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clarkset_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
617d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark{
618d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	drmModePlaneRes *plane_resources;
619d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	drmModePlane *ovr;
620d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
621d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	uint32_t plane_id = 0;
622d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	struct kms_bo *plane_bo;
6230375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	uint32_t plane_flags = 0;
6249b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	int ret, crtc_x, crtc_y, crtc_w, crtc_h;
6259b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	unsigned int i;
626d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
627d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	/* find an unused plane which can be connected to our crtc */
628d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	plane_resources = drmModeGetPlaneResources(fd);
629d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	if (!plane_resources) {
630d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
631d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			strerror(errno));
632d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return -1;
633d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
634d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
635d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	for (i = 0; i < plane_resources->count_planes && !plane_id; i++) {
636d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
637d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		if (!ovr) {
638d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			fprintf(stderr, "drmModeGetPlane failed: %s\n",
639d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark				strerror(errno));
640d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			return -1;
641d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		}
642d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
643d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		if ((ovr->possible_crtcs & (1 << c->pipe)) && !ovr->crtc_id)
644d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			plane_id = ovr->plane_id;
645d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
646d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		drmModeFreePlane(ovr);
647d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
648d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
649b83ad866220911e5be1704e6df085705e5ba8eaeRob Clark	fprintf(stderr, "testing %dx%d@%s overlay plane\n",
650b83ad866220911e5be1704e6df085705e5ba8eaeRob Clark			p->w, p->h, p->format_str);
651b83ad866220911e5be1704e6df085705e5ba8eaeRob Clark
652d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	if (!plane_id) {
653d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		fprintf(stderr, "failed to find plane!\n");
654d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return -1;
655d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
656d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
6570375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	plane_bo = create_test_buffer(kms, p->fourcc, p->w, p->h, handles,
658a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart				      pitches, offsets, PATTERN_TILES);
6593fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (plane_bo == NULL)
6603fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		return -1;
661d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
662d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	/* just use single plane format for now.. */
6630375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	if (drmModeAddFB2(fd, p->w, p->h, p->fourcc,
664d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			handles, pitches, offsets, &p->fb_id, plane_flags)) {
665d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
666d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return -1;
667d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
668d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
669d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	/* ok, boring.. but for now put in middle of screen: */
670d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	crtc_x = c->mode->hdisplay / 3;
671d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	crtc_y = c->mode->vdisplay / 3;
672d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	crtc_w = crtc_x;
673d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	crtc_h = crtc_y;
674d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
675d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	/* note src coords (last 4 args) are in Q16 format */
676d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	if (drmModeSetPlane(fd, plane_id, c->crtc, p->fb_id,
677d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			    plane_flags, crtc_x, crtc_y, crtc_w, crtc_h,
678d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			    0, 0, p->w << 16, p->h << 16)) {
679d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		fprintf(stderr, "failed to enable plane: %s\n",
680d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			strerror(errno));
681d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return -1;
682d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
683d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
684d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	return 0;
685d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark}
686d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
6877a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsbergstatic void
688d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clarkset_mode(struct connector *c, int count, struct plane *p, int plane_count,
689d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		int page_flip)
6907a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg{
6918fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	struct kms_driver *kms;
6928fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	struct kms_bo *bo, *other_bo;
6931e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	unsigned int fb_id, other_fb_id;
6943fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	int i, j, ret, width, height, x;
6953fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
6961e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	drmEventContext evctx;
6977a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
6987a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg	width = 0;
6997a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg	height = 0;
7007a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg	for (i = 0; i < count; i++) {
7017a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg		connector_find_mode(&c[i]);
7027a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg		if (c[i].mode == NULL)
7037a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg			continue;
7047a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg		width += c[i].mode->hdisplay;
7057a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg		if (height < c[i].mode->vdisplay)
7067a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg			height = c[i].mode->vdisplay;
7077a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg	}
7087a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
7098fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	ret = kms_create(fd, &kms);
7108fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	if (ret) {
7118fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke		fprintf(stderr, "failed to create kms driver: %s\n",
7128fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke			strerror(-ret));
7137a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg		return;
7147a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg	}
7157a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
716cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	bo = create_test_buffer(kms, c->fourcc, width, height, handles,
717a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart				pitches, offsets, PATTERN_SMPTE);
7183fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (bo == NULL)
7197a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg		return;
720731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
721cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	ret = drmModeAddFB2(fd, width, height, c->fourcc,
722cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart			    handles, pitches, offsets, &fb_id, 0);
723731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	if (ret) {
724680b9c4fa3dfb329bd74ec08c17cfc876ea2fc5bJakob Bornecrantz		fprintf(stderr, "failed to add fb (%ux%u): %s\n",
725680b9c4fa3dfb329bd74ec08c17cfc876ea2fc5bJakob Bornecrantz			width, height, strerror(errno));
726731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		return;
727731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
728731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
729669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	x = 0;
730669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	for (i = 0; i < count; i++) {
731669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		if (c[i].mode == NULL)
732669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			continue;
7338b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg
734cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		printf("setting mode %s@%s on connector %d, crtc %d\n",
735cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		       c[i].mode_str, c[i].format_str, c[i].id, c[i].crtc);
7368b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg
7378b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg		ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
738669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg				     &c[i].id, 1, c[i].mode);
739d23146f3f0ad14c8ad482a4832cae859c8d646f2Jakob Bornecrantz
740d23146f3f0ad14c8ad482a4832cae859c8d646f2Jakob Bornecrantz		/* XXX: Actually check if this is needed */
741d23146f3f0ad14c8ad482a4832cae859c8d646f2Jakob Bornecrantz		drmModeDirtyFB(fd, fb_id, NULL, 0);
742d23146f3f0ad14c8ad482a4832cae859c8d646f2Jakob Bornecrantz
743669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		x += c[i].mode->hdisplay;
744669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg
745669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		if (ret) {
746669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
747669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			return;
748669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		}
749d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
750d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		/* if we have a plane/overlay to show, set that up now: */
751d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		for (j = 0; j < plane_count; j++)
752d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			if (p[j].con_id == c[i].id)
753d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark				if (set_plane(kms, &c[i], &p[j]))
754d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark					return;
755731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
7561e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
7571e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	if (!page_flip)
7581e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		return;
7598fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke
760cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	other_bo = create_test_buffer(kms, c->fourcc, width, height, handles,
761a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart				      pitches, offsets, PATTERN_PLAIN);
7623fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (other_bo == NULL)
7631e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		return;
7641e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
765cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	ret = drmModeAddFB2(fd, width, height, c->fourcc, handles, pitches, offsets,
766cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart			    &other_fb_id, 0);
7671e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	if (ret) {
7681e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
7691e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		return;
7701e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	}
7711e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
7721e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	for (i = 0; i < count; i++) {
7731e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		if (c[i].mode == NULL)
7741e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			continue;
7751e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
7763c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz		ret = drmModePageFlip(fd, c[i].crtc, other_fb_id,
7773c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz				      DRM_MODE_PAGE_FLIP_EVENT, &c[i]);
7783c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz		if (ret) {
7793c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz			fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
7803c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz			return;
7813c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz		}
7821e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		gettimeofday(&c[i].start, NULL);
7831e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		c[i].swap_count = 0;
784e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell		c[i].fb_id[0] = fb_id;
785e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell		c[i].fb_id[1] = other_fb_id;
786a697fb6acad7992c3d23bb6a663663694782eb7bBenjamin Franzke		c[i].current_fb_id = other_fb_id;
7871e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	}
7881e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
7891e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	memset(&evctx, 0, sizeof evctx);
7901e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	evctx.version = DRM_EVENT_CONTEXT_VERSION;
7911e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	evctx.vblank_handler = NULL;
7926f1eba0548cd6a96e91a4e8be7b91ba6a936eb98Jesse Barnes	evctx.page_flip_handler = page_flip_handler;
7931e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
7941e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	while (1) {
795e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes#if 0
7961e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		struct pollfd pfd[2];
7971e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
7981e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[0].fd = 0;
7991e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[0].events = POLLIN;
8001e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[1].fd = fd;
8011e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[1].events = POLLIN;
8021e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
8031e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		if (poll(pfd, 2, -1) < 0) {
8041e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			fprintf(stderr, "poll error\n");
8051e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			break;
8061e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		}
8071e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
8081e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		if (pfd[0].revents)
8091e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			break;
810e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes#else
811e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
812e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		fd_set fds;
813e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		int ret;
814e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes
815e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		FD_ZERO(&fds);
816e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		FD_SET(0, &fds);
817e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		FD_SET(fd, &fds);
818e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		ret = select(fd + 1, &fds, NULL, NULL, &timeout);
819e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes
820e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		if (ret <= 0) {
821e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes			fprintf(stderr, "select timed out or error (ret %d)\n",
822e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes				ret);
823e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes			continue;
824e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		} else if (FD_ISSET(0, &fds)) {
825e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes			break;
826e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		}
827e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes#endif
8281e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
8291e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		drmHandleEvent(fd, &evctx);
8301e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	}
8318fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke
8328fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	kms_bo_destroy(&bo);
8338fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	kms_bo_destroy(&other_bo);
8348fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	kms_destroy(&kms);
835731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
836731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
837731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesextern char *optarg;
838731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesextern int optind, opterr, optopt;
839d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clarkstatic char optstr[] = "ecpmfs:P:v";
840731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
841cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart#define min(a, b)	((a) < (b) ? (a) : (b))
842cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
8430375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchartstatic int parse_connector(struct connector *c, const char *arg)
8440375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart{
845cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	unsigned int len;
846cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	const char *p;
847cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	char *endp;
848cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
8490375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	c->crtc = -1;
850cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	strcpy(c->format_str, "XR24");
851cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
852cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	c->id = strtoul(arg, &endp, 10);
853cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	if (*endp == '@') {
854cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		arg = endp + 1;
855cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		c->crtc = strtoul(arg, &endp, 10);
856cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	}
857cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	if (*endp != ':')
858cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		return -1;
8590375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
860cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	arg = endp + 1;
8610375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
862cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	p = strchrnul(arg, '@');
863cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	len = min(sizeof c->mode_str - 1, p - arg);
864cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	strncpy(c->mode_str, arg, len);
865cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	c->mode_str[len] = '\0';
8660375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
867cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	if (*p == '@') {
868cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		strncpy(c->format_str, p + 1, 4);
869cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		c->format_str[4] = '\0';
870ebd7904877d08525beb5039e4ea2f5b6c0a7c23fRob Clark	}
871cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
872ebd7904877d08525beb5039e4ea2f5b6c0a7c23fRob Clark	c->fourcc = format_fourcc(c->format_str);
873ebd7904877d08525beb5039e4ea2f5b6c0a7c23fRob Clark	if (c->fourcc == 0)  {
874ebd7904877d08525beb5039e4ea2f5b6c0a7c23fRob Clark		fprintf(stderr, "unknown format %s\n", c->format_str);
875ebd7904877d08525beb5039e4ea2f5b6c0a7c23fRob Clark		return -1;
876cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	}
877cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
878cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	return 0;
8790375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart}
8800375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
8810375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchartstatic int parse_plane(struct plane *p, const char *arg)
8820375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart{
8830375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	strcpy(p->format_str, "XR24");
8840375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
8850375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	if (sscanf(arg, "%d:%dx%d@%4s", &p->con_id, &p->w, &p->h, &p->format_str) != 4 &&
8860375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	    sscanf(arg, "%d:%dx%d", &p->con_id, &p->w, &p->h) != 3)
8870375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart		return -1;
8880375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
8890375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	p->fourcc = format_fourcc(p->format_str);
8900375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	if (p->fourcc == 0) {
8910375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart		fprintf(stderr, "unknown format %s\n", p->format_str);
8920375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart		return -1;
8930375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	}
8940375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
8950375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	return 0;
8960375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart}
8970375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
898731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesvoid usage(char *name)
899731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
900731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "usage: %s [-ecpmf]\n", name);
901731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\t-e\tlist encoders\n");
902731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\t-c\tlist connectors\n");
903d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
904731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\t-m\tlist modes\n");
905731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\t-f\tlist framebuffers\n");
9061e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
907cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	fprintf(stderr, "\t-s <connector_id>[@<crtc_id>]:<mode>[@<format>]\tset a mode\n");
908cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	fprintf(stderr, "\t-P <connector_id>:<w>x<h>[@<format>]\tset a plane\n");
909731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\n\tDefault is to dump all info.\n");
910731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	exit(0);
911731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
912731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
913731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#define dump_resource(res) if (res) dump_##res()
914731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
9159b44fbd393b8db571badae41881f490145404ae0Paulo Zanonistatic int page_flipping_supported(void)
91659d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg{
9178fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	/*FIXME: generic ioctl needed? */
9188fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	return 1;
9198fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke#if 0
92059d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	int ret, value;
92159d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	struct drm_i915_getparam gp;
92259d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
92359d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	gp.param = I915_PARAM_HAS_PAGEFLIPPING;
92459d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	gp.value = &value;
92559d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
92659d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
92759d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	if (ret) {
92859d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		fprintf(stderr, "drm_i915_getparam: %m\n");
92959d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		return 0;
93059d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	}
93159d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
932e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell	return *gp.value;
9338fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke#endif
93459d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg}
93559d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
936731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint main(int argc, char **argv)
937731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
938731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int c;
939d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
9401e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	int test_vsync = 0;
941e07b650662ea0529d99741691c47856ef1034c9cInki Dae	char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos" };
9429b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	unsigned int i;
9439b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	int count = 0, plane_count = 0;
944669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	struct connector con_args[2];
945b83ad866220911e5be1704e6df085705e5ba8eaeRob Clark	struct plane plane_args[2] = {0};
946669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg
947731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	opterr = 0;
948731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	while ((c = getopt(argc, argv, optstr)) != -1) {
949731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		switch (c) {
950731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 'e':
951731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			encoders = 1;
952731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
953731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 'c':
954731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			connectors = 1;
955731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
956731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 'p':
957731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			crtcs = 1;
958d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			planes = 1;
959731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
960731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 'm':
961731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			modes = 1;
962731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
963731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 'f':
964731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			framebuffers = 1;
965731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
9661e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		case 'v':
9671e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			test_vsync = 1;
9681e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			break;
969731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 's':
9700375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart			if (parse_connector(&con_args[count], optarg) < 0)
971669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg				usage(argv[0]);
972669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			count++;
973731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
974d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		case 'P':
9750375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart			if (parse_plane(&plane_args[plane_count], optarg) < 0)
976d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark				usage(argv[0]);
977d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			plane_count++;
978d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			break;
979731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		default:
980731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			usage(argv[0]);
981731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
982731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
983731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
984731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
985731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	if (argc == 1)
986d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		encoders = connectors = crtcs = planes = modes = framebuffers = 1;
987731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
988731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	for (i = 0; i < ARRAY_SIZE(modules); i++) {
989731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		printf("trying to load module %s...", modules[i]);
990731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		fd = drmOpen(modules[i], NULL);
991731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		if (fd < 0) {
992731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			printf("failed.\n");
993731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		} else {
994731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			printf("success.\n");
995731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
996731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
997731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
998731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
9999b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	if (test_vsync && !page_flipping_supported()) {
100059d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		fprintf(stderr, "page flipping not supported by drm.\n");
100159d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		return -1;
100259d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	}
100359d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
1004731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	if (i == ARRAY_SIZE(modules)) {
1005731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		fprintf(stderr, "failed to load any modules, aborting.\n");
1006731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		return -1;
1007731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1008731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1009731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	resources = drmModeGetResources(fd);
1010731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	if (!resources) {
1011731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		fprintf(stderr, "drmModeGetResources failed: %s\n",
1012731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			strerror(errno));
1013731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		drmClose(fd);
1014731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		return 1;
1015731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1016731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1017731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	dump_resource(encoders);
1018731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	dump_resource(connectors);
1019731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	dump_resource(crtcs);
1020d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	dump_resource(planes);
1021731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	dump_resource(framebuffers);
1022731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1023669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	if (count > 0) {
1024d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		set_mode(con_args, count, plane_args, plane_count, test_vsync);
10252c113a1b159f57ab94b54316ece49c677cfe04ceKristian Høgsberg		getchar();
1026731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1027731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1028731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeFreeResources(resources);
1029731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1030731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	return 0;
1031731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
1032