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 */
401ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding
418e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#ifdef HAVE_CONFIG_H
427a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg#include "config.h"
438e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#endif
447a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
45731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <assert.h>
462c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart#include <ctype.h>
477badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart#include <stdbool.h>
48731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <stdio.h>
49731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <stdlib.h>
50731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <stdint.h>
51d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni#include <inttypes.h>
52731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <unistd.h>
53731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <string.h>
541785e2e1f9e876f114465ecf6b6df1428b246833Greg Hackmann#include <strings.h>
55731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include <errno.h>
561e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg#include <sys/poll.h>
57e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell#include <sys/time.h>
58731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
59731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include "xf86drm.h"
60731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes#include "xf86drmMode.h"
61d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark#include "drm_fourcc.h"
62731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
631ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding#include "util/common.h"
641ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding#include "util/format.h"
654664d657ead5ff176c92e8ac54e09ead2e6d94caThierry Reding#include "util/kms.h"
661ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding#include "util/pattern.h"
671ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding
68db004badef9315ba6a5f165d0974dd5afd5a6178Laurent Pinchart#include "buffers.h"
690e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include "cursor.h"
707a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
7102fa8f79b05456184028f014432647b19601a288Laurent Pinchartstruct crtc {
7202fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeCrtc *crtc;
7302fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeObjectProperties *props;
7402fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModePropertyRes **props_info;
7556592680bbb1bb73d08bdce317046d0401dcfba0Laurent Pinchart	drmModeModeInfo *mode;
7602fa8f79b05456184028f014432647b19601a288Laurent Pinchart};
7702fa8f79b05456184028f014432647b19601a288Laurent Pinchart
7802fa8f79b05456184028f014432647b19601a288Laurent Pinchartstruct encoder {
7902fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeEncoder *encoder;
8002fa8f79b05456184028f014432647b19601a288Laurent Pinchart};
8102fa8f79b05456184028f014432647b19601a288Laurent Pinchart
8202fa8f79b05456184028f014432647b19601a288Laurent Pinchartstruct connector {
8302fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeConnector *connector;
8402fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeObjectProperties *props;
8502fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModePropertyRes **props_info;
86f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	char *name;
8702fa8f79b05456184028f014432647b19601a288Laurent Pinchart};
8802fa8f79b05456184028f014432647b19601a288Laurent Pinchart
8902fa8f79b05456184028f014432647b19601a288Laurent Pinchartstruct fb {
9002fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeFB *fb;
9102fa8f79b05456184028f014432647b19601a288Laurent Pinchart};
9202fa8f79b05456184028f014432647b19601a288Laurent Pinchart
9302fa8f79b05456184028f014432647b19601a288Laurent Pinchartstruct plane {
9402fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModePlane *plane;
9502fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeObjectProperties *props;
9602fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModePropertyRes **props_info;
9702fa8f79b05456184028f014432647b19601a288Laurent Pinchart};
9802fa8f79b05456184028f014432647b19601a288Laurent Pinchart
9902fa8f79b05456184028f014432647b19601a288Laurent Pinchartstruct resources {
10002fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModeRes *res;
10102fa8f79b05456184028f014432647b19601a288Laurent Pinchart	drmModePlaneRes *plane_res;
10202fa8f79b05456184028f014432647b19601a288Laurent Pinchart
10302fa8f79b05456184028f014432647b19601a288Laurent Pinchart	struct crtc *crtcs;
10402fa8f79b05456184028f014432647b19601a288Laurent Pinchart	struct encoder *encoders;
10502fa8f79b05456184028f014432647b19601a288Laurent Pinchart	struct connector *connectors;
10602fa8f79b05456184028f014432647b19601a288Laurent Pinchart	struct fb *fbs;
10702fa8f79b05456184028f014432647b19601a288Laurent Pinchart	struct plane *planes;
10802fa8f79b05456184028f014432647b19601a288Laurent Pinchart};
10902fa8f79b05456184028f014432647b19601a288Laurent Pinchart
110549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstruct device {
111549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	int fd;
112549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart
113549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	struct resources *resources;
1143813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
1153813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	struct {
1163813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		unsigned int width;
1173813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		unsigned int height;
1183813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
1193813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		unsigned int fb_id;
120d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart		struct bo *bo;
1219915e68b3b4d69101f3cb6609e796fb8f63320e2Joonyoung Shim		struct bo *cursor_bo;
1223813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	} mode;
123549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart};
124731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
125fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clarkstatic inline int64_t U642I64(uint64_t val)
126fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark{
127fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	return (int64_t)*((int64_t *)&val);
128fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark}
129731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
130c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg#define bit_name_fn(res)					\
131ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchartconst char * res##_str(int type) {				\
132ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchart	unsigned int i;						\
133c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	const char *sep = "";					\
134c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	for (i = 0; i < ARRAY_SIZE(res##_names); i++) {		\
135c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg		if (type & (1 << i)) {				\
136c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg			printf("%s%s", sep, res##_names[i]);	\
137c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg			sep = ", ";				\
138c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg		}						\
139c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	}							\
1406fa2b29d226306870eebe93afb2106ca7d79569bTobias Klausmann	return NULL;						\
141c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg}
142c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
143c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsbergstatic const char *mode_type_names[] = {
144c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"builtin",
145c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"clock_c",
146c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"crtc_c",
147c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"preferred",
148c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"default",
149c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"userdef",
150c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"driver",
151c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg};
152c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
153ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchartstatic bit_name_fn(mode_type)
154c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
155c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsbergstatic const char *mode_flag_names[] = {
156c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"phsync",
157c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"nhsync",
158c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"pvsync",
159c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"nvsync",
160c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"interlace",
161c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"dblscan",
162c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"csync",
163c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"pcsync",
164c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"ncsync",
165c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"hskew",
166c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"bcast",
167c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"pixmux",
168c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"dblclk",
169c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	"clkdiv2"
170c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg};
171c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
172ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchartstatic bit_name_fn(mode_flag)
173c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
174549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void dump_encoders(struct device *dev)
175731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
176731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeEncoder *encoder;
177731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i;
178731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
179731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	printf("Encoders:\n");
180731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
181549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	for (i = 0; i < dev->resources->res->count_encoders; i++) {
182549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		encoder = dev->resources->encoders[i].encoder;
18302fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (!encoder)
184731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
18502fa8f79b05456184028f014432647b19601a288Laurent Pinchart
186731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
187731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->encoder_id,
188731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->crtc_id,
1894664d657ead5ff176c92e8ac54e09ead2e6d94caThierry Reding		       util_lookup_encoder_type_name(encoder->encoder_type),
190731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->possible_crtcs,
191731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       encoder->possible_clones);
192731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1930243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
1940243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg}
1950243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg
196ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchartstatic void dump_mode(drmModeModeInfo *mode)
1970243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg{
198c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf("  %s %d %d %d %d %d %d %d %d %d",
1990243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->name,
200694ef59532253727176ed0ce9077ae3ec41dd457Marcin Kościelnicki	       mode->vrefresh,
2010243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->hdisplay,
2020243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->hsync_start,
2030243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->hsync_end,
2040243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->htotal,
2050243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vdisplay,
2060243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vsync_start,
2070243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vsync_end,
2080243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	       mode->vtotal);
209c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg
210c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf(" flags: ");
211c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	mode_flag_str(mode->flags);
212c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf("; type: ");
213c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	mode_type_str(mode->type);
214c0ed9b23ecb48b8301f66d2270e638249709e94eKristian Høgsberg	printf("\n");
215731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
216731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
217549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void dump_blob(struct device *dev, uint32_t blob_id)
218d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni{
219d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	uint32_t i;
220d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	unsigned char *blob_data;
221d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	drmModePropertyBlobPtr blob;
222d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
223549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	blob = drmModeGetPropertyBlob(dev->fd, blob_id);
224c2c0346e1f5ddec4f6497d7c6359157c5f32d442Ville Syrjälä	if (!blob) {
225c2c0346e1f5ddec4f6497d7c6359157c5f32d442Ville Syrjälä		printf("\n");
226d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		return;
227c2c0346e1f5ddec4f6497d7c6359157c5f32d442Ville Syrjälä	}
228d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
229d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	blob_data = blob->data;
230d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
231d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	for (i = 0; i < blob->length; i++) {
232d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		if (i % 16 == 0)
233d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf("\n\t\t\t");
234d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("%.2hhx", blob_data[i]);
235d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
236d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\n");
237d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
238d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	drmModeFreePropertyBlob(blob);
239d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni}
240d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
241549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void dump_prop(struct device *dev, drmModePropertyPtr prop,
242549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		      uint32_t prop_id, uint64_t value)
2439fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg{
2449fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg	int i;
245d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\t%d", prop_id);
246d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (!prop) {
247d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
248d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		return;
249d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
250d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
251d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf(" %s:\n", prop->name);
252d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
253d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\t\tflags:");
254d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_PENDING)
255d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" pending");
256d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
257d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" immutable");
258fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
259fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark		printf(" signed range");
260fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE))
261fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark		printf(" range");
262fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM))
263d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" enum");
264fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK))
2656df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		printf(" bitmask");
266fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
267d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" blob");
268fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_OBJECT))
269fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark		printf(" object");
270d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\n");
2719fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg
272fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
273fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark		printf("\t\tvalues:");
274fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark		for (i = 0; i < prop->count_values; i++)
275fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark			printf(" %"PRId64, U642I64(prop->values[i]));
276fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark		printf("\n");
277fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	}
278fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark
279fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE)) {
280d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\t\tvalues:");
281d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		for (i = 0; i < prop->count_values; i++)
282d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf(" %"PRIu64, prop->values[i]);
283d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
2849fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg	}
285d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
286fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM)) {
287d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\t\tenums:");
288d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		for (i = 0; i < prop->count_enums; i++)
289d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf(" %s=%llu", prop->enums[i].name,
290d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			       prop->enums[i].value);
291d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
292fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	} else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
2936df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		printf("\t\tvalues:");
2946df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		for (i = 0; i < prop->count_enums; i++)
2956df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark			printf(" %s=0x%llx", prop->enums[i].name,
2966df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark			       (1LL << prop->enums[i].value));
2976df9e6af4b34ef2c5278941ee78de029e4040485Rob Clark		printf("\n");
298d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	} else {
299d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		assert(prop->count_enums == 0);
300d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
301d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
302fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB)) {
303d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\t\tblobs:\n");
304d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		for (i = 0; i < prop->count_blobs; i++)
305549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart			dump_blob(dev, prop->blob_ids[i]);
306d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf("\n");
307d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	} else {
308d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		assert(prop->count_blobs == 0);
309d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	}
310d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni
311d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	printf("\t\tvalue:");
312fb4177046de19730a784c3c16e4b73aab0ec6e41Rob Clark	if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
313549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		dump_blob(dev, value);
314d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni	else
315d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni		printf(" %"PRIu64"\n", value);
3169fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg}
3179fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg
318549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void dump_connectors(struct device *dev)
319731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
320731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i, j;
321731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
322731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	printf("Connectors:\n");
323f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	printf("id\tencoder\tstatus\t\tname\t\tsize (mm)\tmodes\tencoders\n");
324549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	for (i = 0; i < dev->resources->res->count_connectors; i++) {
325549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		struct connector *_connector = &dev->resources->connectors[i];
32602fa8f79b05456184028f014432647b19601a288Laurent Pinchart		drmModeConnector *connector = _connector->connector;
32702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (!connector)
328731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
329731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
330f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		printf("%d\t%d\t%s\t%-15s\t%dx%d\t\t%d\t",
331731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->connector_id,
332731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->encoder_id,
3334664d657ead5ff176c92e8ac54e09ead2e6d94caThierry Reding		       util_lookup_connector_status_name(connector->connection),
334f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		       _connector->name,
335731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->mmWidth, connector->mmHeight,
336731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		       connector->count_modes);
337731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
3381e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		for (j = 0; j < connector->count_encoders; j++)
3391e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			printf("%s%d", j > 0 ? ", " : "", connector->encoders[j]);
3401e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		printf("\n");
3411e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
342a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni		if (connector->count_modes) {
343a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			printf("  modes:\n");
344d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22Paulo Zanoni			printf("\tname refresh (Hz) hdisp hss hse htot vdisp "
345a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			       "vss vse vtot)\n");
346a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			for (j = 0; j < connector->count_modes; j++)
347a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni				dump_mode(&connector->modes[j]);
34802fa8f79b05456184028f014432647b19601a288Laurent Pinchart		}
349a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni
35002fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (_connector->props) {
351a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni			printf("  props:\n");
35202fa8f79b05456184028f014432647b19601a288Laurent Pinchart			for (j = 0; j < (int)_connector->props->count_props; j++)
353549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart				dump_prop(dev, _connector->props_info[j],
35402fa8f79b05456184028f014432647b19601a288Laurent Pinchart					  _connector->props->props[j],
35502fa8f79b05456184028f014432647b19601a288Laurent Pinchart					  _connector->props->prop_values[j]);
356a10bcaaf668ab16233df10c2742dcb497e17d588Paulo Zanoni		}
357731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
3580243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
359731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
360731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
361549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void dump_crtcs(struct device *dev)
362731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
363731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i;
36486dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni	uint32_t j;
365731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
3660243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("CRTCs:\n");
3670243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("id\tfb\tpos\tsize\n");
368549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	for (i = 0; i < dev->resources->res->count_crtcs; i++) {
369549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		struct crtc *_crtc = &dev->resources->crtcs[i];
37002fa8f79b05456184028f014432647b19601a288Laurent Pinchart		drmModeCrtc *crtc = _crtc->crtc;
37102fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (!crtc)
372731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
37302fa8f79b05456184028f014432647b19601a288Laurent Pinchart
3740243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
3750243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->crtc_id,
3760243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->buffer_id,
3770243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->x, crtc->y,
3780243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		       crtc->width, crtc->height);
3790243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg		dump_mode(&crtc->mode);
3800243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg
38102fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (_crtc->props) {
38202fa8f79b05456184028f014432647b19601a288Laurent Pinchart			printf("  props:\n");
38302fa8f79b05456184028f014432647b19601a288Laurent Pinchart			for (j = 0; j < _crtc->props->count_props; j++)
384549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart				dump_prop(dev, _crtc->props_info[j],
38502fa8f79b05456184028f014432647b19601a288Laurent Pinchart					  _crtc->props->props[j],
38602fa8f79b05456184028f014432647b19601a288Laurent Pinchart					  _crtc->props->prop_values[j]);
38786dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni		} else {
38802fa8f79b05456184028f014432647b19601a288Laurent Pinchart			printf("  no properties found\n");
38986dece4cf2f7180b854fbd318fa1a57793f0deacPaulo Zanoni		}
390731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
3910243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
392731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
393731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
394549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void dump_framebuffers(struct device *dev)
395731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
396731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeFB *fb;
397731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int i;
398731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
3990243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("Frame buffers:\n");
4000243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("id\tsize\tpitch\n");
401549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	for (i = 0; i < dev->resources->res->count_fbs; i++) {
402549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		fb = dev->resources->fbs[i].fb;
40302fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (!fb)
404731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			continue;
40502fa8f79b05456184028f014432647b19601a288Laurent Pinchart
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);
410731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
4110243c9f801a35de3465a0321c02f18a4d07ce5b8Kristian Høgsberg	printf("\n");
412731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
413731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
414549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void dump_planes(struct device *dev)
415d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark{
4169b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	unsigned int i, j;
417d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
418d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	printf("Planes:\n");
4198e56579b203a11c718c5e3da6fdb03b4f9b9fe56Ville Syrjälä	printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\tpossible crtcs\n");
42002fa8f79b05456184028f014432647b19601a288Laurent Pinchart
421549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	if (!dev->resources->plane_res)
42202fa8f79b05456184028f014432647b19601a288Laurent Pinchart		return;
42302fa8f79b05456184028f014432647b19601a288Laurent Pinchart
424549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	for (i = 0; i < dev->resources->plane_res->count_planes; i++) {
425549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		struct plane *plane = &dev->resources->planes[i];
42602fa8f79b05456184028f014432647b19601a288Laurent Pinchart		drmModePlane *ovr = plane->plane;
42702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (!ovr)
428d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			continue;
429d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
4308e56579b203a11c718c5e3da6fdb03b4f9b9fe56Ville Syrjälä		printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%-8d\t0x%08x\n",
431d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		       ovr->plane_id, ovr->crtc_id, ovr->fb_id,
432d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		       ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
4338e56579b203a11c718c5e3da6fdb03b4f9b9fe56Ville Syrjälä		       ovr->gamma_size, ovr->possible_crtcs);
434d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
435d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		if (!ovr->count_formats)
436d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			continue;
437d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
438d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		printf("  formats:");
439d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		for (j = 0; j < ovr->count_formats; j++)
440d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			printf(" %4.4s", (char *)&ovr->formats[j]);
441d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		printf("\n");
442d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
44302fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (plane->props) {
44402fa8f79b05456184028f014432647b19601a288Laurent Pinchart			printf("  props:\n");
44502fa8f79b05456184028f014432647b19601a288Laurent Pinchart			for (j = 0; j < plane->props->count_props; j++)
446549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart				dump_prop(dev, plane->props_info[j],
44702fa8f79b05456184028f014432647b19601a288Laurent Pinchart					  plane->props->props[j],
44802fa8f79b05456184028f014432647b19601a288Laurent Pinchart					  plane->props->prop_values[j]);
44925e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark		} else {
45002fa8f79b05456184028f014432647b19601a288Laurent Pinchart			printf("  no properties found\n");
45125e4cb4659c62817aae2ca3b83f2d4f598d6474bRob Clark		}
452d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
453d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	printf("\n");
454d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
455d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	return;
456d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark}
457d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
45802fa8f79b05456184028f014432647b19601a288Laurent Pinchartstatic void free_resources(struct resources *res)
45902fa8f79b05456184028f014432647b19601a288Laurent Pinchart{
460f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	int i;
461f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
46202fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (!res)
46302fa8f79b05456184028f014432647b19601a288Laurent Pinchart		return;
46402fa8f79b05456184028f014432647b19601a288Laurent Pinchart
46502fa8f79b05456184028f014432647b19601a288Laurent Pinchart#define free_resource(_res, __res, type, Type)					\
46602fa8f79b05456184028f014432647b19601a288Laurent Pinchart	do {									\
46702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (!(_res)->type##s)						\
46802fa8f79b05456184028f014432647b19601a288Laurent Pinchart			break;							\
46902fa8f79b05456184028f014432647b19601a288Laurent Pinchart		for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) {	\
47002fa8f79b05456184028f014432647b19601a288Laurent Pinchart			if (!(_res)->type##s[i].type)				\
47102fa8f79b05456184028f014432647b19601a288Laurent Pinchart				break;						\
47202fa8f79b05456184028f014432647b19601a288Laurent Pinchart			drmModeFree##Type((_res)->type##s[i].type);		\
47302fa8f79b05456184028f014432647b19601a288Laurent Pinchart		}								\
47402fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free((_res)->type##s);						\
47502fa8f79b05456184028f014432647b19601a288Laurent Pinchart	} while (0)
47602fa8f79b05456184028f014432647b19601a288Laurent Pinchart
47702fa8f79b05456184028f014432647b19601a288Laurent Pinchart#define free_properties(_res, __res, type)					\
47802fa8f79b05456184028f014432647b19601a288Laurent Pinchart	do {									\
47902fa8f79b05456184028f014432647b19601a288Laurent Pinchart		for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) {	\
48002fa8f79b05456184028f014432647b19601a288Laurent Pinchart			drmModeFreeObjectProperties(res->type##s[i].props);	\
48102fa8f79b05456184028f014432647b19601a288Laurent Pinchart			free(res->type##s[i].props_info);			\
48202fa8f79b05456184028f014432647b19601a288Laurent Pinchart		}								\
48302fa8f79b05456184028f014432647b19601a288Laurent Pinchart	} while (0)
48402fa8f79b05456184028f014432647b19601a288Laurent Pinchart
48502fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (res->res) {
48602fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free_properties(res, res, crtc);
48702fa8f79b05456184028f014432647b19601a288Laurent Pinchart
48802fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free_resource(res, res, crtc, Crtc);
48902fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free_resource(res, res, encoder, Encoder);
490f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
491f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		for (i = 0; i < res->res->count_connectors; i++)
492f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			free(res->connectors[i].name);
493f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
49402fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free_resource(res, res, connector, Connector);
49502fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free_resource(res, res, fb, FB);
49602fa8f79b05456184028f014432647b19601a288Laurent Pinchart
49702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		drmModeFreeResources(res->res);
49802fa8f79b05456184028f014432647b19601a288Laurent Pinchart	}
49902fa8f79b05456184028f014432647b19601a288Laurent Pinchart
50002fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (res->plane_res) {
50102fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free_properties(res, plane_res, plane);
50202fa8f79b05456184028f014432647b19601a288Laurent Pinchart
50302fa8f79b05456184028f014432647b19601a288Laurent Pinchart		free_resource(res, plane_res, plane, Plane);
50402fa8f79b05456184028f014432647b19601a288Laurent Pinchart
50502fa8f79b05456184028f014432647b19601a288Laurent Pinchart		drmModeFreePlaneResources(res->plane_res);
50602fa8f79b05456184028f014432647b19601a288Laurent Pinchart	}
50702fa8f79b05456184028f014432647b19601a288Laurent Pinchart
50802fa8f79b05456184028f014432647b19601a288Laurent Pinchart	free(res);
50902fa8f79b05456184028f014432647b19601a288Laurent Pinchart}
51002fa8f79b05456184028f014432647b19601a288Laurent Pinchart
511549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic struct resources *get_resources(struct device *dev)
51202fa8f79b05456184028f014432647b19601a288Laurent Pinchart{
51302fa8f79b05456184028f014432647b19601a288Laurent Pinchart	struct resources *res;
51456592680bbb1bb73d08bdce317046d0401dcfba0Laurent Pinchart	int i;
51502fa8f79b05456184028f014432647b19601a288Laurent Pinchart
516128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov	res = calloc(1, sizeof(*res));
51702fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (res == 0)
51802fa8f79b05456184028f014432647b19601a288Laurent Pinchart		return NULL;
51902fa8f79b05456184028f014432647b19601a288Laurent Pinchart
5201fec623b029747fa811fab9b52effd8993fc605bRob Clark	drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
5210f45884ffc7a46dd4aef14ae6d227a10d8d24fd7Rob Clark	drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
5221fec623b029747fa811fab9b52effd8993fc605bRob Clark
523549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	res->res = drmModeGetResources(dev->fd);
52402fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (!res->res) {
52502fa8f79b05456184028f014432647b19601a288Laurent Pinchart		fprintf(stderr, "drmModeGetResources failed: %s\n",
52602fa8f79b05456184028f014432647b19601a288Laurent Pinchart			strerror(errno));
52702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		goto error;
52802fa8f79b05456184028f014432647b19601a288Laurent Pinchart	}
52902fa8f79b05456184028f014432647b19601a288Laurent Pinchart
530128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov	res->crtcs = calloc(res->res->count_crtcs, sizeof(*res->crtcs));
531128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov	res->encoders = calloc(res->res->count_encoders, sizeof(*res->encoders));
532128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov	res->connectors = calloc(res->res->count_connectors, sizeof(*res->connectors));
533128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov	res->fbs = calloc(res->res->count_fbs, sizeof(*res->fbs));
53402fa8f79b05456184028f014432647b19601a288Laurent Pinchart
53502fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (!res->crtcs || !res->encoders || !res->connectors || !res->fbs)
53602fa8f79b05456184028f014432647b19601a288Laurent Pinchart		goto error;
53702fa8f79b05456184028f014432647b19601a288Laurent Pinchart
53802fa8f79b05456184028f014432647b19601a288Laurent Pinchart#define get_resource(_res, __res, type, Type)					\
53902fa8f79b05456184028f014432647b19601a288Laurent Pinchart	do {									\
54002fa8f79b05456184028f014432647b19601a288Laurent Pinchart		for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) {	\
54102fa8f79b05456184028f014432647b19601a288Laurent Pinchart			(_res)->type##s[i].type =				\
542549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart				drmModeGet##Type(dev->fd, (_res)->__res->type##s[i]); \
54302fa8f79b05456184028f014432647b19601a288Laurent Pinchart			if (!(_res)->type##s[i].type)				\
54402fa8f79b05456184028f014432647b19601a288Laurent Pinchart				fprintf(stderr, "could not get %s %i: %s\n",	\
54502fa8f79b05456184028f014432647b19601a288Laurent Pinchart					#type, (_res)->__res->type##s[i],	\
54602fa8f79b05456184028f014432647b19601a288Laurent Pinchart					strerror(errno));			\
54702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		}								\
54802fa8f79b05456184028f014432647b19601a288Laurent Pinchart	} while (0)
54902fa8f79b05456184028f014432647b19601a288Laurent Pinchart
55002fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_resource(res, res, crtc, Crtc);
55102fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_resource(res, res, encoder, Encoder);
55202fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_resource(res, res, connector, Connector);
55302fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_resource(res, res, fb, FB);
55402fa8f79b05456184028f014432647b19601a288Laurent Pinchart
555f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	/* Set the name of all connectors based on the type name and the per-type ID. */
556f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	for (i = 0; i < res->res->count_connectors; i++) {
557f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		struct connector *connector = &res->connectors[i];
5584664d657ead5ff176c92e8ac54e09ead2e6d94caThierry Reding		drmModeConnector *conn = connector->connector;
559f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
560f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		asprintf(&connector->name, "%s-%u",
5614664d657ead5ff176c92e8ac54e09ead2e6d94caThierry Reding			 util_lookup_connector_type_name(conn->connector_type),
5624664d657ead5ff176c92e8ac54e09ead2e6d94caThierry Reding			 conn->connector_type_id);
563f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	}
564f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
56502fa8f79b05456184028f014432647b19601a288Laurent Pinchart#define get_properties(_res, __res, type, Type)					\
56602fa8f79b05456184028f014432647b19601a288Laurent Pinchart	do {									\
56702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) {	\
56802fa8f79b05456184028f014432647b19601a288Laurent Pinchart			struct type *obj = &res->type##s[i];			\
56902fa8f79b05456184028f014432647b19601a288Laurent Pinchart			unsigned int j;						\
57002fa8f79b05456184028f014432647b19601a288Laurent Pinchart			obj->props =						\
571549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart				drmModeObjectGetProperties(dev->fd, obj->type->type##_id, \
57202fa8f79b05456184028f014432647b19601a288Laurent Pinchart							   DRM_MODE_OBJECT_##Type); \
57302fa8f79b05456184028f014432647b19601a288Laurent Pinchart			if (!obj->props) {					\
57402fa8f79b05456184028f014432647b19601a288Laurent Pinchart				fprintf(stderr,					\
57502fa8f79b05456184028f014432647b19601a288Laurent Pinchart					"could not get %s %i properties: %s\n", \
57602fa8f79b05456184028f014432647b19601a288Laurent Pinchart					#type, obj->type->type##_id,		\
57702fa8f79b05456184028f014432647b19601a288Laurent Pinchart					strerror(errno));			\
57802fa8f79b05456184028f014432647b19601a288Laurent Pinchart				continue;					\
57902fa8f79b05456184028f014432647b19601a288Laurent Pinchart			}							\
580128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov			obj->props_info = calloc(obj->props->count_props,	\
581128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov						 sizeof(*obj->props_info));	\
58202fa8f79b05456184028f014432647b19601a288Laurent Pinchart			if (!obj->props_info)					\
58302fa8f79b05456184028f014432647b19601a288Laurent Pinchart				continue;					\
58402fa8f79b05456184028f014432647b19601a288Laurent Pinchart			for (j = 0; j < obj->props->count_props; ++j)		\
58502fa8f79b05456184028f014432647b19601a288Laurent Pinchart				obj->props_info[j] =				\
586549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart					drmModeGetProperty(dev->fd, obj->props->props[j]); \
58702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		}								\
58802fa8f79b05456184028f014432647b19601a288Laurent Pinchart	} while (0)
58902fa8f79b05456184028f014432647b19601a288Laurent Pinchart
59002fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_properties(res, res, crtc, CRTC);
59102fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_properties(res, res, connector, CONNECTOR);
59202fa8f79b05456184028f014432647b19601a288Laurent Pinchart
59356592680bbb1bb73d08bdce317046d0401dcfba0Laurent Pinchart	for (i = 0; i < res->res->count_crtcs; ++i)
59456592680bbb1bb73d08bdce317046d0401dcfba0Laurent Pinchart		res->crtcs[i].mode = &res->crtcs[i].crtc->mode;
59556592680bbb1bb73d08bdce317046d0401dcfba0Laurent Pinchart
596549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	res->plane_res = drmModeGetPlaneResources(dev->fd);
59702fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (!res->plane_res) {
59802fa8f79b05456184028f014432647b19601a288Laurent Pinchart		fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
59902fa8f79b05456184028f014432647b19601a288Laurent Pinchart			strerror(errno));
60002fa8f79b05456184028f014432647b19601a288Laurent Pinchart		return res;
60102fa8f79b05456184028f014432647b19601a288Laurent Pinchart	}
60202fa8f79b05456184028f014432647b19601a288Laurent Pinchart
603128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov	res->planes = calloc(res->plane_res->count_planes, sizeof(*res->planes));
60402fa8f79b05456184028f014432647b19601a288Laurent Pinchart	if (!res->planes)
60502fa8f79b05456184028f014432647b19601a288Laurent Pinchart		goto error;
60602fa8f79b05456184028f014432647b19601a288Laurent Pinchart
60702fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_resource(res, plane_res, plane, Plane);
60802fa8f79b05456184028f014432647b19601a288Laurent Pinchart	get_properties(res, plane_res, plane, PLANE);
60902fa8f79b05456184028f014432647b19601a288Laurent Pinchart
61002fa8f79b05456184028f014432647b19601a288Laurent Pinchart	return res;
61102fa8f79b05456184028f014432647b19601a288Laurent Pinchart
61202fa8f79b05456184028f014432647b19601a288Laurent Pincharterror:
61302fa8f79b05456184028f014432647b19601a288Laurent Pinchart	free_resources(res);
61402fa8f79b05456184028f014432647b19601a288Laurent Pinchart	return NULL;
61502fa8f79b05456184028f014432647b19601a288Laurent Pinchart}
61602fa8f79b05456184028f014432647b19601a288Laurent Pinchart
617a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchartstatic int get_crtc_index(struct device *dev, uint32_t id)
618a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart{
619a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart	int i;
620a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart
621a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart	for (i = 0; i < dev->resources->res->count_crtcs; ++i) {
622a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart		drmModeCrtc *crtc = dev->resources->crtcs[i].crtc;
623a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart		if (crtc && crtc->crtc_id == id)
624a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart			return i;
625a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart	}
626a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart
627a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart	return -1;
628a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart}
629a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart
630f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Redingstatic drmModeConnector *get_connector_by_name(struct device *dev, const char *name)
631f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding{
632f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	struct connector *connector;
633f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	int i;
634f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
635f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	for (i = 0; i < dev->resources->res->count_connectors; i++) {
636f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		connector = &dev->resources->connectors[i];
637f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
638f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		if (strcmp(connector->name, name) == 0)
639f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			return connector->connector;
640f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	}
641f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
642f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	return NULL;
643f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding}
644f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
6452c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchartstatic drmModeConnector *get_connector_by_id(struct device *dev, uint32_t id)
6462c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart{
6472c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	drmModeConnector *connector;
6482c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	int i;
6492c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
6502c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	for (i = 0; i < dev->resources->res->count_connectors; i++) {
6512c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		connector = dev->resources->connectors[i].connector;
6522c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		if (connector && connector->connector_id == id)
6532c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			return connector;
6542c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	}
6552c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
6562c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	return NULL;
6572c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart}
6582c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
6592c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchartstatic drmModeEncoder *get_encoder_by_id(struct device *dev, uint32_t id)
6602c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart{
6612c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	drmModeEncoder *encoder;
6622c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	int i;
6632c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
6642c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	for (i = 0; i < dev->resources->res->count_encoders; i++) {
6652c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		encoder = dev->resources->encoders[i].encoder;
6662c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		if (encoder && encoder->encoder_id == id)
6672c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			return encoder;
6682c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	}
6692c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
6702c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	return NULL;
6712c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart}
6722c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
673a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart/* -----------------------------------------------------------------------------
674b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart * Pipes and planes
675a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart */
676a94ee624292bff96ea1d38e8a0a3fbeefec42fb6Laurent Pinchart
677731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes/*
678731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Mode setting with the kernel interfaces is a bit of a chore.
679731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * First you have to find the connector in question and make sure the
680731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * requested mode is available.
681731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * Then you need to find the encoder attached to that connector so you
682731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes * can bind it with a free crtc.
683731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes */
684b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchartstruct pipe_arg {
685f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	const char **cons;
6862c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	uint32_t *con_ids;
6872c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	unsigned int num_cons;
688a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart	uint32_t crtc_id;
689669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	char mode_str[64];
690cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	char format_str[5];
691de0970203091618834e4753c14d5169770797800Vincent ABRIOU	unsigned int vrefresh;
692cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	unsigned int fourcc;
6939fc85b4084b69fefab3dbdf1f6cf97ccb47c963aKristian Høgsberg	drmModeModeInfo *mode;
694a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart	struct crtc *crtc;
6951e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	unsigned int fb_id[2], current_fb_id;
6961e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	struct timeval start;
6971e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
6981e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	int swap_count;
699d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark};
700d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
70102fa8f79b05456184028f014432647b19601a288Laurent Pinchartstruct plane_arg {
702eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart	uint32_t crtc_id;  /* the id of CRTC to bind to */
7037badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	bool has_position;
7047badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	int32_t x, y;
705d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	uint32_t w, h;
706d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin	double scale;
707d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	unsigned int fb_id;
7084d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim	struct bo *bo;
709b83ad866220911e5be1704e6df085705e5ba8eaeRob Clark	char format_str[5]; /* need to leave room for terminating \0 */
7100375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	unsigned int fourcc;
711d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark};
712669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg
7132c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchartstatic drmModeModeInfo *
714de0970203091618834e4753c14d5169770797800Vincent ABRIOUconnector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str,
715de0970203091618834e4753c14d5169770797800Vincent ABRIOU        const unsigned int vrefresh)
716731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
717731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	drmModeConnector *connector;
7182c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	drmModeModeInfo *mode;
7192c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	int i;
720731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
7212c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	connector = get_connector_by_id(dev, con_id);
7222c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	if (!connector || !connector->count_modes)
7232c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		return NULL;
7242c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7252c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	for (i = 0; i < connector->count_modes; i++) {
7262c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		mode = &connector->modes[i];
727de0970203091618834e4753c14d5169770797800Vincent ABRIOU		if (!strcmp(mode->name, mode_str)) {
728de0970203091618834e4753c14d5169770797800Vincent ABRIOU			/* If the vertical refresh frequency is not specified then return the
729de0970203091618834e4753c14d5169770797800Vincent ABRIOU			 * first mode that match with the name. Else, return the mode that match
730de0970203091618834e4753c14d5169770797800Vincent ABRIOU			 * the name and the specified vertical refresh frequency.
731de0970203091618834e4753c14d5169770797800Vincent ABRIOU			 */
732de0970203091618834e4753c14d5169770797800Vincent ABRIOU			if (vrefresh == 0)
733de0970203091618834e4753c14d5169770797800Vincent ABRIOU				return mode;
734de0970203091618834e4753c14d5169770797800Vincent ABRIOU			else if (mode->vrefresh == vrefresh)
735de0970203091618834e4753c14d5169770797800Vincent ABRIOU				return mode;
736de0970203091618834e4753c14d5169770797800Vincent ABRIOU		}
7372c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	}
7382c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7392c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	return NULL;
7402c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart}
7412c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7422c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchartstatic struct crtc *pipe_find_crtc(struct device *dev, struct pipe_arg *pipe)
7432c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart{
7442c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	uint32_t possible_crtcs = ~0;
7452c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	uint32_t active_crtcs = 0;
7462c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	unsigned int crtc_idx;
7472c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	unsigned int i;
7482c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	int j;
7492c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7502c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	for (i = 0; i < pipe->num_cons; ++i) {
751a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart		uint32_t crtcs_for_connector = 0;
7522c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		drmModeConnector *connector;
7532c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		drmModeEncoder *encoder;
754a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart		int idx;
7552c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7562c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		connector = get_connector_by_id(dev, pipe->con_ids[i]);
75702fa8f79b05456184028f014432647b19601a288Laurent Pinchart		if (!connector)
7582c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			return NULL;
759731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
760a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart		for (j = 0; j < connector->count_encoders; ++j) {
761a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart			encoder = get_encoder_by_id(dev, connector->encoders[j]);
762a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart			if (!encoder)
763a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart				continue;
764731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
765a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart			crtcs_for_connector |= encoder->possible_crtcs;
766731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
767a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart			idx = get_crtc_index(dev, encoder->crtc_id);
768a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart			if (idx >= 0)
769a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart				active_crtcs |= 1 << idx;
770731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
771a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart
772a4f2f1b9d1c0b6b7f740951525a14b3d328f0acfLaurent Pinchart		possible_crtcs &= crtcs_for_connector;
773731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
774731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
7752c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	if (!possible_crtcs)
7762c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		return NULL;
7772c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7782c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	/* Return the first possible and active CRTC if one exists, or the first
7792c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	 * possible CRTC otherwise.
7802c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	 */
7812c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	if (possible_crtcs & active_crtcs)
7822c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		crtc_idx = ffs(possible_crtcs & active_crtcs);
7832c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	else
7842c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		crtc_idx = ffs(possible_crtcs);
7852c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7862c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	return &dev->resources->crtcs[crtc_idx - 1];
7872c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart}
7882c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7892c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchartstatic int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe)
7902c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart{
7914a8da02e524d5d70ec638477e36fcafd2c8152ecEmil Velikov	drmModeModeInfo *mode = NULL;
7922c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	int i;
7932c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7942c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	pipe->mode = NULL;
7952c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
7962c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	for (i = 0; i < (int)pipe->num_cons; i++) {
7972c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		mode = connector_find_mode(dev, pipe->con_ids[i],
798de0970203091618834e4753c14d5169770797800Vincent ABRIOU					   pipe->mode_str, pipe->vrefresh);
7992c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		if (mode == NULL) {
8002c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			fprintf(stderr,
801f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding				"failed to find mode \"%s\" for connector %s\n",
802f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding				pipe->mode_str, pipe->cons[i]);
8032c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			return -EINVAL;
8042c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		}
805731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
806731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
807a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart	/* If the CRTC ID was specified, get the corresponding CRTC. Otherwise
8082c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	 * locate a CRTC that can be attached to all the connectors.
809a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart	 */
8102c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	if (pipe->crtc_id != (uint32_t)-1) {
8112c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		for (i = 0; i < dev->resources->res->count_crtcs; i++) {
8122c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			struct crtc *crtc = &dev->resources->crtcs[i];
8132c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
8142c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			if (pipe->crtc_id == crtc->crtc->crtc_id) {
8152c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart				pipe->crtc = crtc;
816a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart				break;
817a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart			}
818a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart		}
8192c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	} else {
8202c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		pipe->crtc = pipe_find_crtc(dev, pipe);
821a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart	}
822a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart
8232c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	if (!pipe->crtc) {
8242c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		fprintf(stderr, "failed to find CRTC for pipe\n");
8252c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		return -EINVAL;
8262c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	}
827731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
8282c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	pipe->mode = mode;
8292c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	pipe->crtc->mode = mode;
830a6349d0a0f9d3e017ac761ba912279c7d1e94eb7Laurent Pinchart
8312c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	return 0;
832669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg}
833669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg
834d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart/* -----------------------------------------------------------------------------
835d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart * Properties
836d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart */
837d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
838d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchartstruct property_arg {
839d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	uint32_t obj_id;
840d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	uint32_t obj_type;
841d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	char name[DRM_PROP_NAME_LEN+1];
842d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	uint32_t prop_id;
843d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	uint64_t value;
844d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart};
845d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
846549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchartstatic void set_property(struct device *dev, struct property_arg *p)
847d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart{
8484a8da02e524d5d70ec638477e36fcafd2c8152ecEmil Velikov	drmModeObjectProperties *props = NULL;
8494a8da02e524d5d70ec638477e36fcafd2c8152ecEmil Velikov	drmModePropertyRes **props_info = NULL;
850d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	const char *obj_type;
851d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	int ret;
852d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	int i;
853d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
854d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	p->obj_type = 0;
855d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	p->prop_id = 0;
856d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
857d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart#define find_object(_res, __res, type, Type)					\
858d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	do {									\
859d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) {	\
860d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			struct type *obj = &(_res)->type##s[i];			\
861d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			if (obj->type->type##_id != p->obj_id)			\
862d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart				continue;					\
863d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			p->obj_type = DRM_MODE_OBJECT_##Type;			\
864d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			obj_type = #Type;					\
865d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			props = obj->props;					\
866d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			props_info = obj->props_info;				\
867d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		}								\
868d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	} while(0)								\
869d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
870549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	find_object(dev->resources, res, crtc, CRTC);
871d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	if (p->obj_type == 0)
872549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		find_object(dev->resources, res, connector, CONNECTOR);
873d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	if (p->obj_type == 0)
874549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		find_object(dev->resources, plane_res, plane, PLANE);
875d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	if (p->obj_type == 0) {
876d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		fprintf(stderr, "Object %i not found, can't set property\n",
877d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			p->obj_id);
878d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			return;
879d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	}
880d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
881d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	if (!props) {
882d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		fprintf(stderr, "%s %i has no properties\n",
883d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			obj_type, p->obj_id);
884d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		return;
885d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	}
886d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
887d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	for (i = 0; i < (int)props->count_props; ++i) {
888d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		if (!props_info[i])
889d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			continue;
890d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		if (strcmp(props_info[i]->name, p->name) == 0)
891d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			break;
892d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	}
893d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
894d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	if (i == (int)props->count_props) {
895d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		fprintf(stderr, "%s %i has no %s property\n",
896d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			obj_type, p->obj_id, p->name);
897d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		return;
898d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	}
899d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
900d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	p->prop_id = props->props[i];
901d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
902549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
903549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart				       p->prop_id, p->value);
904d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	if (ret < 0)
905d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n",
906d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			obj_type, p->obj_id, p->name, p->value, strerror(errno));
907d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart}
908d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
9093fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart/* -------------------------------------------------------------------------- */
9103fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
911ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchartstatic void
9123fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchartpage_flip_handler(int fd, unsigned int frame,
9133fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		  unsigned int sec, unsigned int usec, void *data)
9143fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart{
915b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	struct pipe_arg *pipe;
9163fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	unsigned int new_fb_id;
9173fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	struct timeval end;
9183fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	double t;
9193fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
920b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	pipe = data;
921b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	if (pipe->current_fb_id == pipe->fb_id[0])
922b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		new_fb_id = pipe->fb_id[1];
9233fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	else
924b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		new_fb_id = pipe->fb_id[0];
9253fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
9262c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	drmModePageFlip(fd, pipe->crtc->crtc->crtc_id, new_fb_id,
927b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			DRM_MODE_PAGE_FLIP_EVENT, pipe);
928b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	pipe->current_fb_id = new_fb_id;
929b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	pipe->swap_count++;
930b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	if (pipe->swap_count == 60) {
9313fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		gettimeofday(&end, NULL);
9323fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		t = end.tv_sec + end.tv_usec * 1e-6 -
933b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			(pipe->start.tv_sec + pipe->start.tv_usec * 1e-6);
934b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		fprintf(stderr, "freq: %.02fHz\n", pipe->swap_count / t);
935b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->swap_count = 0;
936b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->start = end;
9373fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	}
9383fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart}
9393fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart
940360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobistatic bool format_support(const drmModePlanePtr ovr, uint32_t fmt)
941360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi{
942360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi	unsigned int i;
943360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi
944360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi	for (i = 0; i < ovr->count_formats; ++i) {
945360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi		if (ovr->formats[i] == fmt)
946360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi			return true;
947360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi	}
948360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi
949360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi	return false;
950360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi}
951360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi
952eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchartstatic int set_plane(struct device *dev, struct plane_arg *p)
953d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark{
954d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	drmModePlane *ovr;
955b1d19de76468fdb4ae7cb87791c77d1f8839a573Tobias Jakobi	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
956d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	uint32_t plane_id = 0;
957d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart	struct bo *plane_bo;
9580375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	uint32_t plane_flags = 0;
959ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchart	int crtc_x, crtc_y, crtc_w, crtc_h;
9603813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	struct crtc *crtc = NULL;
961605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart	unsigned int pipe;
9629b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	unsigned int i;
963d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
964605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart	/* Find an unused plane which can be connected to our CRTC. Find the
965605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart	 * CRTC index first, then iterate over available planes.
966605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart	 */
967605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart	for (i = 0; i < (unsigned int)dev->resources->res->count_crtcs; i++) {
968eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart		if (p->crtc_id == dev->resources->res->crtcs[i]) {
969eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart			crtc = &dev->resources->crtcs[i];
970605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart			pipe = i;
971605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart			break;
972605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart		}
973605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart	}
974605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart
975eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart	if (!crtc) {
976eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart		fprintf(stderr, "CRTC %u not found\n", p->crtc_id);
977605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart		return -1;
978605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart	}
979605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart
980549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	for (i = 0; i < dev->resources->plane_res->count_planes && !plane_id; i++) {
981549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		ovr = dev->resources->planes[i].plane;
982360a7eacd4961ceab72554d36917f031a05ed030Tobias Jakobi		if (!ovr || !format_support(ovr, p->fourcc))
98302fa8f79b05456184028f014432647b19601a288Laurent Pinchart			continue;
984d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
985605efd7e05e94b8d9d742d3a8af1040776e2742dLaurent Pinchart		if ((ovr->possible_crtcs & (1 << pipe)) && !ovr->crtc_id)
986d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			plane_id = ovr->plane_id;
987d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
988d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
989d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	if (!plane_id) {
990eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart		fprintf(stderr, "no unused plane available for CRTC %u\n",
991eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart			crtc->crtc->crtc_id);
992d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return -1;
993d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
994d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
995581c7cf86a96a81e76288c8abca03c7f29eac3afLaurent Pinchart	fprintf(stderr, "testing %dx%d@%s overlay plane %u\n",
996581c7cf86a96a81e76288c8abca03c7f29eac3afLaurent Pinchart		p->w, p->h, p->format_str, plane_id);
997581c7cf86a96a81e76288c8abca03c7f29eac3afLaurent Pinchart
998d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart	plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h, handles,
9991ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding			     pitches, offsets, UTIL_PATTERN_TILES);
10003fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (plane_bo == NULL)
10013fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart		return -1;
1002d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
10034d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim	p->bo = plane_bo;
10044d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim
1005d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	/* just use single plane format for now.. */
1006549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	if (drmModeAddFB2(dev->fd, p->w, p->h, p->fourcc,
1007d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			handles, pitches, offsets, &p->fb_id, plane_flags)) {
1008d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
1009d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return -1;
1010d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
1011d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
1012d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin	crtc_w = p->w * p->scale;
1013d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin	crtc_h = p->h * p->scale;
10147badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	if (!p->has_position) {
10157badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		/* Default to the middle of the screen */
1016d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin		crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
1017d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin		crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
10187badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	} else {
10197badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		crtc_x = p->x;
10207badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		crtc_y = p->y;
10217badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	}
1022d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
1023d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	/* note src coords (last 4 args) are in Q16 format */
1024eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart	if (drmModeSetPlane(dev->fd, plane_id, crtc->crtc->crtc_id, p->fb_id,
1025d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			    plane_flags, crtc_x, crtc_y, crtc_w, crtc_h,
1026d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			    0, 0, p->w << 16, p->h << 16)) {
1027d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		fprintf(stderr, "failed to enable plane: %s\n",
1028d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			strerror(errno));
1029d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark		return -1;
1030d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	}
1031d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
1032eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart	ovr->crtc_id = crtc->crtc->crtc_id;
103302fa8f79b05456184028f014432647b19601a288Laurent Pinchart
1034d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	return 0;
1035d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark}
1036d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark
10374d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shimstatic void clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
10384d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim{
10394d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim	unsigned int i;
10404d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim
10414d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim	for (i = 0; i < count; i++) {
10424d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim		if (p[i].fb_id)
10434d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim			drmModeRmFB(dev->fd, p[i].fb_id);
10444d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim		if (p[i].bo)
10454d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim			bo_destroy(p[i].bo);
10464d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim	}
10474d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim}
10484d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim
10494d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim
1050b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchartstatic void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
10517a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg{
1052b1d19de76468fdb4ae7cb87791c77d1f8839a573Tobias Jakobi	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
10533813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	unsigned int fb_id;
1054d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart	struct bo *bo;
10553813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	unsigned int i;
10562c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	unsigned int j;
10573813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	int ret, x;
10583813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
10593813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	dev->mode.width = 0;
10603813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	dev->mode.height = 0;
1061bcaaa75cf482c7d218340c850ffc01f04b78b3ddJoonyoung Shim	dev->mode.fb_id = 0;
10627a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
10637a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg	for (i = 0; i < count; i++) {
1064b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		struct pipe_arg *pipe = &pipes[i];
1065b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart
10662c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		ret = pipe_find_crtc_and_mode(dev, pipe);
10672c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		if (ret < 0)
10687a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg			continue;
10692c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
1070b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		dev->mode.width += pipe->mode->hdisplay;
1071b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		if (dev->mode.height < pipe->mode->vdisplay)
1072b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			dev->mode.height = pipe->mode->vdisplay;
10737a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg	}
10747a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg
10751ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding	bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width,
10761ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding		       dev->mode.height, handles, pitches, offsets,
10771ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding		       UTIL_PATTERN_SMPTE);
10783fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (bo == NULL)
10797a389aab86bde183de8806878b8cf055f662ee73Kristian Høgsberg		return;
1080731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
108121170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shim	dev->mode.bo = bo;
108221170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shim
1083b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	ret = drmModeAddFB2(dev->fd, dev->mode.width, dev->mode.height,
1084b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			    pipes[0].fourcc, handles, pitches, offsets, &fb_id, 0);
1085731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	if (ret) {
1086680b9c4fa3dfb329bd74ec08c17cfc876ea2fc5bJakob Bornecrantz		fprintf(stderr, "failed to add fb (%ux%u): %s\n",
10873813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart			dev->mode.width, dev->mode.height, strerror(errno));
1088731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		return;
1089731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1090731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
109121170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shim	dev->mode.fb_id = fb_id;
109221170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shim
1093669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	x = 0;
1094669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg	for (i = 0; i < count; i++) {
1095b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		struct pipe_arg *pipe = &pipes[i];
1096b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart
1097b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		if (pipe->mode == NULL)
1098669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			continue;
10998b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg
1100de0970203091618834e4753c14d5169770797800Vincent ABRIOU		printf("setting mode %s-%dHz@%s on connectors ",
1101de0970203091618834e4753c14d5169770797800Vincent ABRIOU		       pipe->mode_str, pipe->mode->vrefresh, pipe->format_str);
11022c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		for (j = 0; j < pipe->num_cons; ++j)
1103f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			printf("%s, ", pipe->cons[j]);
11042c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		printf("crtc %d\n", pipe->crtc->crtc->crtc_id);
11058b8803695b24d4cb4d041437a4709be06e59471bKristian Høgsberg
11062c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		ret = drmModeSetCrtc(dev->fd, pipe->crtc->crtc->crtc_id, fb_id,
11072c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart				     x, 0, pipe->con_ids, pipe->num_cons,
11082c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart				     pipe->mode);
1109d23146f3f0ad14c8ad482a4832cae859c8d646f2Jakob Bornecrantz
1110d23146f3f0ad14c8ad482a4832cae859c8d646f2Jakob Bornecrantz		/* XXX: Actually check if this is needed */
1111549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		drmModeDirtyFB(dev->fd, fb_id, NULL, 0);
1112d23146f3f0ad14c8ad482a4832cae859c8d646f2Jakob Bornecrantz
1113b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		x += pipe->mode->hdisplay;
1114669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg
1115669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		if (ret) {
1116669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
1117669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg			return;
1118669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg		}
1119731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
11203813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart}
11211e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
11224e4d79d4cae92c5ec29882cea9b8f7e8355f1232Joonyoung Shimstatic void clear_mode(struct device *dev)
11234e4d79d4cae92c5ec29882cea9b8f7e8355f1232Joonyoung Shim{
1124bcaaa75cf482c7d218340c850ffc01f04b78b3ddJoonyoung Shim	if (dev->mode.fb_id)
1125bcaaa75cf482c7d218340c850ffc01f04b78b3ddJoonyoung Shim		drmModeRmFB(dev->fd, dev->mode.fb_id);
11264e4d79d4cae92c5ec29882cea9b8f7e8355f1232Joonyoung Shim	if (dev->mode.bo)
11274e4d79d4cae92c5ec29882cea9b8f7e8355f1232Joonyoung Shim		bo_destroy(dev->mode.bo);
11283813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart}
11293813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
11303813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchartstatic void set_planes(struct device *dev, struct plane_arg *p, unsigned int count)
11313813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart{
11323813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	unsigned int i;
11333813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
11343813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	/* set up planes/overlays */
11353813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	for (i = 0; i < count; i++)
11363813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		if (set_plane(dev, &p[i]))
11373813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart			return;
11383813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart}
11393813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
11400e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic void set_cursors(struct device *dev, struct pipe_arg *pipes, unsigned int count)
11410e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{
1142b1d19de76468fdb4ae7cb87791c77d1f8839a573Tobias Jakobi	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
1143d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart	struct bo *bo;
11440e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	unsigned int i;
11450e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	int ret;
11460e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
11470e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	/* maybe make cursor width/height configurable some day */
11480e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	uint32_t cw = 64;
11490e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	uint32_t ch = 64;
11500e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
11510e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	/* create cursor bo.. just using PATTERN_PLAIN as it has
11520e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	 * translucent alpha
11530e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	 */
1154d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart	bo = bo_create(dev->fd, DRM_FORMAT_ARGB8888, cw, ch, handles, pitches,
11551ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding		       offsets, UTIL_PATTERN_PLAIN);
11560e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	if (bo == NULL)
11570e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		return;
11580e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
11599915e68b3b4d69101f3cb6609e796fb8f63320e2Joonyoung Shim	dev->mode.cursor_bo = bo;
11609915e68b3b4d69101f3cb6609e796fb8f63320e2Joonyoung Shim
11610e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	for (i = 0; i < count; i++) {
11620e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		struct pipe_arg *pipe = &pipes[i];
11630e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		ret = cursor_init(dev->fd, handles[0],
11640e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark				pipe->crtc->crtc->crtc_id,
11650e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark				pipe->mode->hdisplay, pipe->mode->vdisplay,
11660e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark				cw, ch);
11670e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		if (ret) {
11680e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark			fprintf(stderr, "failed to init cursor for CRTC[%u]\n",
11690e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark					pipe->crtc_id);
11700e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark			return;
11710e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		}
11720e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	}
11730e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
11740e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	cursor_start();
11750e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark}
11760e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
11770e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic void clear_cursors(struct device *dev)
11780e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{
11790e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	cursor_stop();
11809915e68b3b4d69101f3cb6609e796fb8f63320e2Joonyoung Shim
11819915e68b3b4d69101f3cb6609e796fb8f63320e2Joonyoung Shim	if (dev->mode.cursor_bo)
11829915e68b3b4d69101f3cb6609e796fb8f63320e2Joonyoung Shim		bo_destroy(dev->mode.cursor_bo);
11830e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark}
11840e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
1185b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchartstatic void test_page_flip(struct device *dev, struct pipe_arg *pipes, unsigned int count)
11863813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart{
1187b1d19de76468fdb4ae7cb87791c77d1f8839a573Tobias Jakobi	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
11883813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	unsigned int other_fb_id;
1189d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart	struct bo *other_bo;
11903813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	drmEventContext evctx;
11913813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	unsigned int i;
11923813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	int ret;
1193549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart
11941ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding	other_bo = bo_create(dev->fd, pipes[0].fourcc, dev->mode.width,
11951ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding			     dev->mode.height, handles, pitches, offsets,
11961ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding			     UTIL_PATTERN_PLAIN);
11973fdc1777ee156ebfa4281b49d8783adbbcae3ee1Laurent Pinchart	if (other_bo == NULL)
11981e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		return;
11991e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
1200b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	ret = drmModeAddFB2(dev->fd, dev->mode.width, dev->mode.height,
1201b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			    pipes[0].fourcc, handles, pitches, offsets,
1202b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			    &other_fb_id, 0);
12031e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	if (ret) {
12041e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
120521170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shim		goto err;
12061e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	}
12071e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
12081e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	for (i = 0; i < count; i++) {
1209b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		struct pipe_arg *pipe = &pipes[i];
1210b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart
1211b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		if (pipe->mode == NULL)
12121e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			continue;
12131e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
12142c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		ret = drmModePageFlip(dev->fd, pipe->crtc->crtc->crtc_id,
12152c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart				      other_fb_id, DRM_MODE_PAGE_FLIP_EVENT,
12162c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart				      pipe);
12173c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz		if (ret) {
12183c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz			fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
121921170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shim			goto err_rmfb;
12203c8adda6e1e6b0471b3d70a63d795622bbeb1580Jakob Bornecrantz		}
1221b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		gettimeofday(&pipe->start, NULL);
1222b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->swap_count = 0;
1223b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->fb_id[0] = dev->mode.fb_id;
1224b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->fb_id[1] = other_fb_id;
1225b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->current_fb_id = other_fb_id;
12261e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	}
12271e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
12281e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	memset(&evctx, 0, sizeof evctx);
12291e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	evctx.version = DRM_EVENT_CONTEXT_VERSION;
12301e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	evctx.vblank_handler = NULL;
12316f1eba0548cd6a96e91a4e8be7b91ba6a936eb98Jesse Barnes	evctx.page_flip_handler = page_flip_handler;
12326e84ada4ccf604c32a008fc20c00d79302135601Hyungwon Hwang
12331e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	while (1) {
1234e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes#if 0
12351e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		struct pollfd pfd[2];
12361e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
12371e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[0].fd = 0;
12381e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[0].events = POLLIN;
12391e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[1].fd = fd;
12401e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		pfd[1].events = POLLIN;
12411e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
12421e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		if (poll(pfd, 2, -1) < 0) {
12431e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			fprintf(stderr, "poll error\n");
12441e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			break;
12451e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		}
12461e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
12471e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg		if (pfd[0].revents)
12481e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			break;
1249e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes#else
1250e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
1251e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		fd_set fds;
1252e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes
1253e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		FD_ZERO(&fds);
1254e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		FD_SET(0, &fds);
1255549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		FD_SET(dev->fd, &fds);
1256549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		ret = select(dev->fd + 1, &fds, NULL, NULL, &timeout);
1257e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes
1258e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		if (ret <= 0) {
1259e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes			fprintf(stderr, "select timed out or error (ret %d)\n",
1260e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes				ret);
1261e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes			continue;
1262e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		} else if (FD_ISSET(0, &fds)) {
1263e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes			break;
1264e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes		}
1265e6b3f906cef26e1efb8625f5dd4e460b4c79a771Jesse Barnes#endif
12661e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg
1267549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		drmHandleEvent(dev->fd, &evctx);
12681e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	}
12698fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke
127021170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shimerr_rmfb:
1271bcaaa75cf482c7d218340c850ffc01f04b78b3ddJoonyoung Shim	drmModeRmFB(dev->fd, other_fb_id);
127221170a8c63d2e994317b785f7f7e78ab7e0a4ac4Joonyoung Shimerr:
1273d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart	bo_destroy(other_bo);
1274731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
1275731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1276cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart#define min(a, b)	((a) < (b) ? (a) : (b))
1277cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
1278b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchartstatic int parse_connector(struct pipe_arg *pipe, const char *arg)
12790375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart{
1280cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	unsigned int len;
12812c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	unsigned int i;
1282cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	const char *p;
1283cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	char *endp;
1284cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
1285de0970203091618834e4753c14d5169770797800Vincent ABRIOU	pipe->vrefresh = 0;
1286b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	pipe->crtc_id = (uint32_t)-1;
1287b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	strcpy(pipe->format_str, "XR24");
1288cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
12892c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	/* Count the number of connectors and allocate them. */
12902c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	pipe->num_cons = 1;
1291f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	for (p = arg; *p && *p != ':' && *p != '@'; ++p) {
12922c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		if (*p == ',')
12932c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			pipe->num_cons++;
12942c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	}
12952c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
1296128344c2cf22385dedece5a3d774d3a24527d2deEmil Velikov	pipe->con_ids = calloc(pipe->num_cons, sizeof(*pipe->con_ids));
1297f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	pipe->cons = calloc(pipe->num_cons, sizeof(*pipe->cons));
1298f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	if (pipe->con_ids == NULL || pipe->cons == NULL)
12992c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		return -1;
13002c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
13012c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	/* Parse the connectors. */
13022c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	for (i = 0, p = arg; i < pipe->num_cons; ++i, p = endp + 1) {
1303f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		endp = strpbrk(p, ",@:");
1304f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		if (!endp)
1305f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			break;
1306f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
1307f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		pipe->cons[i] = strndup(p, endp - p);
1308f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
13092c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		if (*endp != ',')
13102c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart			break;
13112c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	}
13122c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
13132c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	if (i != pipe->num_cons - 1)
13142c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart		return -1;
13152c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart
13162c5ee84d30cbd3fba61a8426b1e6bdd4f385de13Laurent Pinchart	/* Parse the remaining parameters. */
1317cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	if (*endp == '@') {
1318cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		arg = endp + 1;
1319b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->crtc_id = strtoul(arg, &endp, 10);
1320cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	}
1321cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	if (*endp != ':')
1322cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart		return -1;
13230375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
1324cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	arg = endp + 1;
13250375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
1326de0970203091618834e4753c14d5169770797800Vincent ABRIOU	/* Search for the vertical refresh or the format. */
1327de0970203091618834e4753c14d5169770797800Vincent ABRIOU	p = strpbrk(arg, "-@");
1328de0970203091618834e4753c14d5169770797800Vincent ABRIOU	if (p == NULL)
1329de0970203091618834e4753c14d5169770797800Vincent ABRIOU		p = arg + strlen(arg);
1330b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	len = min(sizeof pipe->mode_str - 1, (unsigned int)(p - arg));
1331b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	strncpy(pipe->mode_str, arg, len);
1332b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	pipe->mode_str[len] = '\0';
13330375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
1334de0970203091618834e4753c14d5169770797800Vincent ABRIOU	if (*p == '-') {
1335de0970203091618834e4753c14d5169770797800Vincent ABRIOU		pipe->vrefresh = strtoul(p + 1, &endp, 10);
1336de0970203091618834e4753c14d5169770797800Vincent ABRIOU		p = endp;
1337de0970203091618834e4753c14d5169770797800Vincent ABRIOU	}
1338de0970203091618834e4753c14d5169770797800Vincent ABRIOU
1339cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	if (*p == '@') {
1340b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		strncpy(pipe->format_str, p + 1, 4);
1341b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		pipe->format_str[4] = '\0';
1342ebd7904877d08525beb5039e4ea2f5b6c0a7c23fRob Clark	}
1343cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
13441ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding	pipe->fourcc = util_format_fourcc(pipe->format_str);
1345b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	if (pipe->fourcc == 0)  {
1346b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart		fprintf(stderr, "unknown format %s\n", pipe->format_str);
1347ebd7904877d08525beb5039e4ea2f5b6c0a7c23fRob Clark		return -1;
1348cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	}
1349cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart
1350cc90ffa9b18fc6f925a3a2c36131332b8af558f8Laurent Pinchart	return 0;
13510375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart}
13520375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
13537badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchartstatic int parse_plane(struct plane_arg *plane, const char *p)
13540375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart{
13557badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	char *end;
13560375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
1357eabf199dffb0d42e959c50aa820b39228196e031Laurent Pinchart	plane->crtc_id = strtoul(p, &end, 10);
13587badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	if (*end != ':')
13597badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		return -EINVAL;
13607badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart
13617badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	p = end + 1;
13627badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	plane->w = strtoul(p, &end, 10);
13637badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	if (*end != 'x')
13647badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		return -EINVAL;
13657badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart
13667badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	p = end + 1;
13677badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	plane->h = strtoul(p, &end, 10);
13687badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart
13697badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	if (*end == '+' || *end == '-') {
13707badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		plane->x = strtol(end, &end, 10);
13717badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		if (*end != '+' && *end != '-')
13727badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart			return -EINVAL;
13737badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		plane->y = strtol(end, &end, 10);
13747badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart
13757badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		plane->has_position = true;
13767badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	}
13777badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart
1378d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin	if (*end == '*') {
1379d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin		p = end + 1;
1380d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin		plane->scale = strtod(p, &end);
1381d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin		if (plane->scale <= 0.0)
1382d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin			return -EINVAL;
1383d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin	} else {
1384d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin		plane->scale = 1.0;
1385d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin	}
1386d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin
13877badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	if (*end == '@') {
13887badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		p = end + 1;
13897badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		if (strlen(p) != 4)
13907badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart			return -EINVAL;
13917badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart
13927badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		strcpy(plane->format_str, p);
13937badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	} else {
13947badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		strcpy(plane->format_str, "XR24");
13957badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	}
13967badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart
13971ec3c44bdd38051d870f64d0b2cc7dbd59760386Thierry Reding	plane->fourcc = util_format_fourcc(plane->format_str);
13987badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart	if (plane->fourcc == 0) {
13997badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		fprintf(stderr, "unknown format %s\n", plane->format_str);
14007badcca4925480ffdc4f3aa5efb88624ce451e70Laurent Pinchart		return -EINVAL;
14010375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	}
14020375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
14030375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart	return 0;
14040375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart}
14050375222c714e8b7ba55f12d5cb389383be1cf54dLaurent Pinchart
1406d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchartstatic int parse_property(struct property_arg *p, const char *arg)
1407d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart{
1408d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	if (sscanf(arg, "%d:%32[^:]:%" SCNu64, &p->obj_id, p->name, &p->value) != 3)
1409d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		return -1;
1410d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
1411d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	p->obj_type = 0;
1412d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	p->name[DRM_PROP_NAME_LEN] = '\0';
1413d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
1414d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	return 0;
1415d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart}
1416d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
1417ca9c8f06e0f560082dcd0943e9be29ba9a915ee3Laurent Pinchartstatic void usage(char *name)
1418731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
14190e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
1420ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart
1421ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart	fprintf(stderr, "\n Query options:\n\n");
1422731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\t-c\tlist connectors\n");
1423ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart	fprintf(stderr, "\t-e\tlist encoders\n");
1424731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\t-f\tlist framebuffers\n");
1425ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart	fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
1426ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart
1427ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart	fprintf(stderr, "\n Test options:\n\n");
1428d8954154fe20036f442e249d964b575a7374c571Ilia Mirkin	fprintf(stderr, "\t-P <crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\n");
1429de0970203091618834e4753c14d5169770797800Vincent ABRIOU	fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:<mode>[-<vrefresh>][@<format>]\tset a mode\n");
14300e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	fprintf(stderr, "\t-C\ttest hw cursor\n");
1431ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart	fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
1432d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
1433ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart
143445901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart	fprintf(stderr, "\n Generic options:\n\n");
1435ab52756a3632fdc38a915a9bbda0b2089b09e38eLaurent Pinchart	fprintf(stderr, "\t-d\tdrop master after mode set\n");
143645901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart	fprintf(stderr, "\t-M module\tuse the given driver\n");
1437b50826dbd6a10e89ed03c23a16bf62e7d554a2d6Ilia Mirkin	fprintf(stderr, "\t-D device\tuse the given device\n");
143845901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart
1439731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	fprintf(stderr, "\n\tDefault is to dump all info.\n");
1440731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	exit(0);
1441731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
1442731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
14439b44fbd393b8db571badae41881f490145404ae0Paulo Zanonistatic int page_flipping_supported(void)
144459d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg{
14458fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	/*FIXME: generic ioctl needed? */
14468fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke	return 1;
14478fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke#if 0
144859d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	int ret, value;
144959d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	struct drm_i915_getparam gp;
145059d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
145159d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	gp.param = I915_PARAM_HAS_PAGEFLIPPING;
145259d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	gp.value = &value;
145359d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
145459d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
145559d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	if (ret) {
145659d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		fprintf(stderr, "drm_i915_getparam: %m\n");
145759d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		return 0;
145859d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	}
145959d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
1460e4a519635f75bde38aeb5b09f2ff4efbf73453e9Matthew W. S. Bell	return *gp.value;
14618fef29093fae2a08f8c1cb4946687bf4bb62a1caBenjamin Franzke#endif
146259d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg}
146359d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
14640e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic int cursor_supported(void)
14650e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{
14660e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	/*FIXME: generic ioctl needed? */
14670e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	return 1;
14680e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark}
14690e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
1470f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Redingstatic int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
1471f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding{
1472f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	drmModeConnector *connector;
1473f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	unsigned int i;
1474f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	uint32_t id;
1475f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	char *endp;
1476f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
1477f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	for (i = 0; i < pipe->num_cons; i++) {
1478f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		id = strtoul(pipe->cons[i], &endp, 10);
1479f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		if (endp == pipe->cons[i]) {
1480f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			connector = get_connector_by_name(dev, pipe->cons[i]);
1481f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			if (!connector) {
1482f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding				fprintf(stderr, "no connector named '%s'\n",
1483f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding					pipe->cons[i]);
1484f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding				return -ENODEV;
1485f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			}
1486f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
1487f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			id = connector->connector_id;
1488f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		}
1489f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
1490f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		pipe->con_ids[i] = id;
1491f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	}
1492f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
1493f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	return 0;
1494f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding}
1495f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
14960e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic char optstr[] = "cdD:efM:P:ps:Cvw:";
1497ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart
1498731cd5526e5c732d51307b26e784f454a724a699Jesse Barnesint main(int argc, char **argv)
1499731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes{
1500549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	struct device dev;
1501549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart
1502731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	int c;
1503d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark	int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
1504ab52756a3632fdc38a915a9bbda0b2089b09e38eLaurent Pinchart	int drop_master = 0;
15051e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg	int test_vsync = 0;
15060e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	int test_cursor = 0;
1507b50826dbd6a10e89ed03c23a16bf62e7d554a2d6Ilia Mirkin	char *device = NULL;
150845901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart	char *module = NULL;
15099b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	unsigned int i;
1510f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	unsigned int count = 0, plane_count = 0;
1511d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	unsigned int prop_count = 0;
1512b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart	struct pipe_arg *pipe_args = NULL;
15136e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart	struct plane_arg *plane_args = NULL;
1514d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	struct property_arg *prop_args = NULL;
151545901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart	unsigned int args = 0;
1516549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	int ret;
1517549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart
15183813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	memset(&dev, 0, sizeof dev);
15193813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
1520731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	opterr = 0;
1521731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	while ((c = getopt(argc, argv, optstr)) != -1) {
152245901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart		args++;
152345901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart
1524731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		switch (c) {
1525731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 'c':
1526731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			connectors = 1;
1527731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
1528b50826dbd6a10e89ed03c23a16bf62e7d554a2d6Ilia Mirkin		case 'D':
1529b50826dbd6a10e89ed03c23a16bf62e7d554a2d6Ilia Mirkin			device = optarg;
1530b50826dbd6a10e89ed03c23a16bf62e7d554a2d6Ilia Mirkin			args--;
1531b50826dbd6a10e89ed03c23a16bf62e7d554a2d6Ilia Mirkin			break;
1532ab52756a3632fdc38a915a9bbda0b2089b09e38eLaurent Pinchart		case 'd':
1533ab52756a3632fdc38a915a9bbda0b2089b09e38eLaurent Pinchart			drop_master = 1;
1534ab52756a3632fdc38a915a9bbda0b2089b09e38eLaurent Pinchart			break;
1535ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart		case 'e':
1536ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			encoders = 1;
1537ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			break;
1538ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart		case 'f':
1539ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			framebuffers = 1;
1540731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
154145901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart		case 'M':
154245901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart			module = optarg;
154345901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart			/* Preserve the default behaviour of dumping all information. */
154445901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart			args--;
154545901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart			break;
1546ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart		case 'P':
15476e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart			plane_args = realloc(plane_args,
15486e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart					     (plane_count + 1) * sizeof *plane_args);
15496e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart			if (plane_args == NULL) {
15506e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart				fprintf(stderr, "memory allocation failed\n");
15516e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart				return 1;
15526e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart			}
1553c78917ee4fe6c787a5de9aaccc5319fdffc9a354Emil Velikov			memset(&plane_args[plane_count], 0, sizeof(*plane_args));
15546e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart
1555ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			if (parse_plane(&plane_args[plane_count], optarg) < 0)
1556ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart				usage(argv[0]);
15576e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart
1558ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			plane_count++;
1559731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
1560ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart		case 'p':
1561ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			crtcs = 1;
1562ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			planes = 1;
15631e1b3c0a93281ce8df42bbdddfe3e51dccc4d5eaKristian Høgsberg			break;
1564731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		case 's':
1565b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			pipe_args = realloc(pipe_args,
1566b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart					    (count + 1) * sizeof *pipe_args);
1567b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			if (pipe_args == NULL) {
15686e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart				fprintf(stderr, "memory allocation failed\n");
15696e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart				return 1;
15706e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart			}
1571c78917ee4fe6c787a5de9aaccc5319fdffc9a354Emil Velikov			memset(&pipe_args[count], 0, sizeof(*pipe_args));
15726e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart
1573b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			if (parse_connector(&pipe_args[count], optarg) < 0)
1574669fde3472ae71c55cc7526e3b3bd6fe00d6a5a5Kristian Høgsberg				usage(argv[0]);
15756e0c74c5f8860748f03dad4548d3ef2cf2df5489Laurent Pinchart
15766e84ada4ccf604c32a008fc20c00d79302135601Hyungwon Hwang			count++;
1577731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
15780e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		case 'C':
15790e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark			test_cursor = 1;
15800e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark			break;
1581ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart		case 'v':
1582ef07acf5b79f86ef86efe6e72c1de5726c97e41dLaurent Pinchart			test_vsync = 1;
1583d55de747a2bdec5b4885a6c86ea6707e15dfefb5Rob Clark			break;
1584d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart		case 'w':
1585d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			prop_args = realloc(prop_args,
1586d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart					   (prop_count + 1) * sizeof *prop_args);
1587d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			if (prop_args == NULL) {
1588d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart				fprintf(stderr, "memory allocation failed\n");
1589d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart				return 1;
1590d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			}
1591c78917ee4fe6c787a5de9aaccc5319fdffc9a354Emil Velikov			memset(&prop_args[prop_count], 0, sizeof(*prop_args));
1592d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
1593d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			if (parse_property(&prop_args[prop_count], optarg) < 0)
1594d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart				usage(argv[0]);
1595d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
1596d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			prop_count++;
1597d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart			break;
1598731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		default:
1599731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			usage(argv[0]);
1600731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes			break;
1601731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		}
1602731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1603731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
160445901fdae66441ffec681e3dbd46b5530107a045Laurent Pinchart	if (!args)
1605dab3c80203e562cfdbe33e7d1627c9dde2f5a7deLaurent Pinchart		encoders = connectors = crtcs = planes = framebuffers = 1;
1606731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1607c26266fcd082a8b67d1f32f5e5351cfa82c7accbThierry Reding	dev.fd = util_open(module, device);
1608c26266fcd082a8b67d1f32f5e5351cfa82c7accbThierry Reding	if (dev.fd < 0)
1609c26266fcd082a8b67d1f32f5e5351cfa82c7accbThierry Reding		return -1;
1610731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
16119b44fbd393b8db571badae41881f490145404ae0Paulo Zanoni	if (test_vsync && !page_flipping_supported()) {
161259d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		fprintf(stderr, "page flipping not supported by drm.\n");
161359d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg		return -1;
161459d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg	}
161559d97e7d6807d9cd076d4e8374aca1d9e8027a6bKristian Høgsberg
16163813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	if (test_vsync && !count) {
16173813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		fprintf(stderr, "page flipping requires at least one -s option.\n");
16183813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		return -1;
16193813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	}
16203813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
16210e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	if (test_cursor && !cursor_supported()) {
16220e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		fprintf(stderr, "hw cursor not supported by drm.\n");
16230e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		return -1;
16240e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark	}
16250e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
1626549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	dev.resources = get_resources(&dev);
1627549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	if (!dev.resources) {
1628549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		drmClose(dev.fd);
1629731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes		return 1;
1630731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1631731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1632f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	for (i = 0; i < count; i++) {
1633f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		if (pipe_resolve_connectors(&dev, &pipe_args[i]) < 0) {
1634f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			free_resources(dev.resources);
1635f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			drmClose(dev.fd);
1636f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding			return 1;
1637f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding		}
1638f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding	}
1639f05a74fb9cb07a02c9bade65d66ba6949a2567a2Thierry Reding
1640549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart#define dump_resource(dev, res) if (res) dump_##res(dev)
1641549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart
1642549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	dump_resource(&dev, encoders);
1643549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	dump_resource(&dev, connectors);
1644549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	dump_resource(&dev, crtcs);
1645549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	dump_resource(&dev, planes);
1646549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	dump_resource(&dev, framebuffers);
1647731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1648d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart	for (i = 0; i < prop_count; ++i)
1649549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		set_property(&dev, &prop_args[i]);
1650d725227cec822b8cfbeb541be17aae30b7612b9fLaurent Pinchart
16513813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart	if (count || plane_count) {
1652d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart		uint64_t cap = 0;
1653d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart
1654d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart		ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
1655d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart		if (ret || cap == 0) {
1656d7c0a08bc576deb07df6c3f91f393ca8edd0c4bfLaurent Pinchart			fprintf(stderr, "driver doesn't support the dumb buffer API\n");
1657549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart			return 1;
1658549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart		}
1659549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart
16603813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		if (count)
1661b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			set_mode(&dev, pipe_args, count);
16623813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
16633813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		if (plane_count)
16643813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart			set_planes(&dev, plane_args, plane_count);
16653813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
16660e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		if (test_cursor)
16670e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark			set_cursors(&dev, pipe_args, count);
16680e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
16693813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart		if (test_vsync)
1670b1e0bdeb70b68754c6c4ab1c7d0161709960d49cLaurent Pinchart			test_page_flip(&dev, pipe_args, count);
16713813e0f8e1ee4885823cdd0b50b05970257adddcLaurent Pinchart
1672ab52756a3632fdc38a915a9bbda0b2089b09e38eLaurent Pinchart		if (drop_master)
1673549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart			drmDropMaster(dev.fd);
1674549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart
16750e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		getchar();
16760e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
16770e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark		if (test_cursor)
16780e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark			clear_cursors(&dev);
16790e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark
16804d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim		if (plane_count)
16814d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim			clear_planes(&dev, plane_args, plane_count);
16824d760d7f46b96a88a2e5f21fa983c4806ece1219Joonyoung Shim
16834e4d79d4cae92c5ec29882cea9b8f7e8355f1232Joonyoung Shim		if (count)
16844e4d79d4cae92c5ec29882cea9b8f7e8355f1232Joonyoung Shim			clear_mode(&dev);
1685731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	}
1686731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1687549fe0ba627a67b6ae1334eb5cf274a3dfb1fd69Laurent Pinchart	free_resources(dev.resources);
1688731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes
1689731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes	return 0;
1690731cd5526e5c732d51307b26e784f454a724a699Jesse Barnes}
1691