1ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <stdio.h>
2ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <stdlib.h>
3ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <fcntl.h>
4ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <unistd.h>
5ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <string.h>
62e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul#include <getopt.h>
7ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
8ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <drm.h>
9ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <drm_fourcc.h>
10ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <errno.h>
11ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <xf86drm.h>
12ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include <xf86drmMode.h>
13ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
14ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include "bo.h"
15ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include "dev.h"
16ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul#include "modeset.h"
17ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
182e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paulstatic void show_usage(char *name)
192e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul{
202e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	printf("Usage: %s [OPTION]\n", name);
212e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	printf("   -c, --card      Index of dri card (ie: /dev/dri/cardN)\n");
222e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	printf("   -r, --crtc      Index of crtc to use for test\n");
232e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	printf("\n\n");
242e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul}
252e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul
262e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paulvoid parse_arguments(int argc, char *argv[], int *card, int *crtc)
272e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul{
282e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	static struct option options[] = {
292e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		{ "card", required_argument, NULL, 'c' },
302e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		{ "crtc", required_argument, NULL, 'r' },
312e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		{ "help", no_argument, NULL, 'h' },
322e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	};
332e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	int option_index = 0;
342e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	int c;
352e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul
362e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	*card = -1;
372e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	*crtc = -1;
382e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	do {
392e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		c = getopt_long(argc, argv, "c:r:h", options, &option_index);
402e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		switch (c) {
412e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		case 0:
422e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		case 'h':
432e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			show_usage(argv[0]);
442e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			exit(0);
452e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		case -1:
462e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			break;
472e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		case 'c':
482e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			if (optarg[0] < '0' || optarg[0] > '9') {
492e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul				printf("Invalid card value '%s'!\n", optarg);
502e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul				show_usage(argv[0]);
512e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul				exit(-1);
522e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			}
532e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			*card = optarg[0] - '0';
542e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			break;
552e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		case 'r':
562e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			if (optarg[0] < '0' || optarg[0] > '9') {
572e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul				printf("Invalid crtc value '%s'!\n", optarg);
582e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul				show_usage(argv[0]);
592e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul				exit(-1);
602e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			}
612e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			*crtc = optarg[0] - '0';
622e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul			break;
632e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		}
642e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	} while (c != -1);
652e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul
662e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	if (*card < 0 || *crtc < 0) {
672e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		show_usage(argv[0]);
682e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul		exit(-1);
692e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	}
702e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul}
712e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul
72ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paulstatic uint32_t get_prop_id(struct sp_dev *dev,
73ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeObjectPropertiesPtr props, const char *name)
74ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul{
75ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	drmModePropertyPtr p;
76ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	uint32_t i, prop_id = 0; /* Property ID should always be > 0 */
77ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
78ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	for (i = 0; !prop_id && i < props->count_props; i++) {
79ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		p = drmModeGetProperty(dev->fd, props->props[i]);
80ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!strcmp(p->name, name))
81ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			prop_id = p->prop_id;
82ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		drmModeFreeProperty(p);
83ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
84ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (!prop_id)
85ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("Could not find %s property\n", name);
86ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	return prop_id;
87ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul}
88ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
89ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paulstatic int get_supported_format(struct sp_plane *plane, uint32_t *format)
90ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul{
91ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	uint32_t i;
92ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
93ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	for (i = 0; i < plane->plane->count_formats; i++) {
94ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (plane->plane->formats[i] == DRM_FORMAT_XRGB8888 ||
95ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		    plane->plane->formats[i] == DRM_FORMAT_ARGB8888 ||
965ba2bf74d75d9753f9aec1e83798070e78918109Benjamin Gaignard		    plane->plane->formats[i] == DRM_FORMAT_RGBA8888 ||
975ba2bf74d75d9753f9aec1e83798070e78918109Benjamin Gaignard		    plane->plane->formats[i] == DRM_FORMAT_NV12) {
98ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			*format = plane->plane->formats[i];
99ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			return 0;
100ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
101ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
102ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	printf("No suitable formats found!\n");
103ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	return -ENOENT;
104ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul}
105ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
1062e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paulstruct sp_dev *create_sp_dev(int card)
107ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul{
108ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	struct sp_dev *dev;
109ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	int ret, fd, i, j;
110ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	drmModeRes *r = NULL;
111ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	drmModePlaneRes *pr = NULL;
1122e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	char card_path[256];
1132e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul
1142e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	snprintf(card_path, sizeof(card_path), "/dev/dri/card%d", card);
115ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
1162e205d896cfea030d2ce7f577afeb3cc4db30ec4Sean Paul	fd = open(card_path, O_RDWR);
117ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (fd < 0) {
118ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to open card0\n");
119ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		return NULL;
120ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
121ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
122ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev = calloc(1, sizeof(*dev));
123ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (!dev) {
124ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to allocate dev\n");
125ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		return NULL;
126ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
127ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
128ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->fd = fd;
129085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul
130ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
131ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (ret) {
132ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to set client cap\n");
133ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		goto err;
134ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
135ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
136085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul	ret = drmSetClientCap(dev->fd, DRM_CLIENT_CAP_ATOMIC, 1);
137085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul	if (ret) {
138085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		printf("Failed to set atomic cap %d", ret);
139085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		goto err;
140085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul	}
141085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul
142ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	r = drmModeGetResources(dev->fd);
143ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (!r) {
144ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to get r\n");
145ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		goto err;
146ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
147ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
148ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->num_connectors = r->count_connectors;
149085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul	dev->connectors = calloc(dev->num_connectors,
150085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul				sizeof(struct sp_connector));
151ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (!dev->connectors) {
152ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to allocate connectors\n");
153ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		goto err;
154ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
155ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	for (i = 0; i < dev->num_connectors; i++) {
156085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		drmModeObjectPropertiesPtr props;
157085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		dev->connectors[i].conn = drmModeGetConnector(dev->fd,
158ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul					r->connectors[i]);
159085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		if (!dev->connectors[i].conn) {
160ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			printf("failed to get connector %d\n", i);
161ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
162ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
163085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul
164085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		props = drmModeObjectGetProperties(dev->fd, r->connectors[i],
165085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul				DRM_MODE_OBJECT_CONNECTOR);
166085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		if (!props) {
167085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul			printf("failed to get connector properties\n");
168085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul			goto err;
169085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		}
170085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul
171085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		dev->connectors[i].crtc_id_pid = get_prop_id(dev, props,
172085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul								"CRTC_ID");
173085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		drmModeFreeObjectProperties(props);
174085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		if (!dev->connectors[i].crtc_id_pid)
175085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul			goto err;
176ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
177ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
178ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->num_encoders = r->count_encoders;
179ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->encoders = calloc(dev->num_encoders, sizeof(*dev->encoders));
180ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (!dev->encoders) {
181ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to allocate encoders\n");
182ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		goto err;
183ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
184ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	for (i = 0; i < dev->num_encoders; i++) {
185ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		dev->encoders[i] = drmModeGetEncoder(dev->fd, r->encoders[i]);
186ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!dev->encoders[i]) {
187ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			printf("failed to get encoder %d\n", i);
188ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
189ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
190ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
191ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
192ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->num_crtcs = r->count_crtcs;
193ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->crtcs = calloc(dev->num_crtcs, sizeof(struct sp_crtc));
194ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (!dev->crtcs) {
195ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to allocate crtcs\n");
196ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		goto err;
197ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
198ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	for (i = 0; i < dev->num_crtcs; i++) {
199085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		drmModeObjectPropertiesPtr props;
200085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul
201ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		dev->crtcs[i].crtc = drmModeGetCrtc(dev->fd, r->crtcs[i]);
202ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!dev->crtcs[i].crtc) {
203ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			printf("failed to get crtc %d\n", i);
204ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
205ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
206ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		dev->crtcs[i].pipe = i;
207ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		dev->crtcs[i].num_planes = 0;
208085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul
209085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		props = drmModeObjectGetProperties(dev->fd, r->crtcs[i],
210085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul				DRM_MODE_OBJECT_CRTC);
211085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		if (!props) {
212085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul			printf("failed to get crtc properties\n");
213085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul			goto err;
214085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		}
215085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul
216085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		dev->crtcs[i].mode_pid = get_prop_id(dev, props, "MODE_ID");
2179d5cde03d9c5499e29a12541087f4dff31141e70Sean Paul		dev->crtcs[i].active_pid = get_prop_id(dev, props, "ACTIVE");
218085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul		drmModeFreeObjectProperties(props);
2199d5cde03d9c5499e29a12541087f4dff31141e70Sean Paul		if (!dev->crtcs[i].mode_pid || !dev->crtcs[i].active_pid)
220085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul			goto err;
221ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
222ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
223ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	pr = drmModeGetPlaneResources(dev->fd);
224ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (!pr) {
225ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		printf("failed to get plane resources\n");
226ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		goto err;
227ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
228ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->num_planes = pr->count_planes;
229ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	dev->planes = calloc(dev->num_planes, sizeof(struct sp_plane));
230ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	for(i = 0; i < dev->num_planes; i++) {
231ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		drmModeObjectPropertiesPtr props;
232ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		struct sp_plane *plane = &dev->planes[i];
233ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
234ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->dev = dev;
235ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->plane = drmModeGetPlane(dev->fd, pr->planes[i]);
236ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->plane) {
237ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			printf("failed to get plane %d\n", i);
238ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
239ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
240ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->bo = NULL;
241ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->in_use = 0;
242ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
243ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		ret = get_supported_format(plane, &plane->format);
244ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (ret) {
245ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			printf("failed to get supported format: %d\n", ret);
246ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
247ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
248ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
249ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		for (j = 0; j < dev->num_crtcs; j++) {
250ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			if (plane->plane->possible_crtcs & (1 << j))
251ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul				dev->crtcs[j].num_planes++;
252ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
253ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
254ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		props = drmModeObjectGetProperties(dev->fd, pr->planes[i],
255ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul				DRM_MODE_OBJECT_PLANE);
256ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!props) {
257ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			printf("failed to get plane properties\n");
258ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
259ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
260ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->crtc_pid = get_prop_id(dev, props, "CRTC_ID");
261ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->crtc_pid) {
262ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
263ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
264ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
265ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->fb_pid = get_prop_id(dev, props, "FB_ID");
266ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->fb_pid) {
267ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
268ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
269ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
270ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->crtc_x_pid = get_prop_id(dev, props, "CRTC_X");
271ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->crtc_x_pid) {
272ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
273ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
274ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
275ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->crtc_y_pid = get_prop_id(dev, props, "CRTC_Y");
276ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->crtc_y_pid) {
277ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
278ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
279ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
280ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->crtc_w_pid = get_prop_id(dev, props, "CRTC_W");
281ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->crtc_w_pid) {
282ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
283ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
284ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
285ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->crtc_h_pid = get_prop_id(dev, props, "CRTC_H");
286ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->crtc_h_pid) {
287ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
288ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
289ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
290ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->src_x_pid = get_prop_id(dev, props, "SRC_X");
291ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->src_x_pid) {
292ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
293ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
294ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
295ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->src_y_pid = get_prop_id(dev, props, "SRC_Y");
296ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->src_y_pid) {
297ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
298ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
299ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
300ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->src_w_pid = get_prop_id(dev, props, "SRC_W");
301ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->src_w_pid) {
302ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
303ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
304ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
305ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		plane->src_h_pid = get_prop_id(dev, props, "SRC_H");
306ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		if (!plane->src_h_pid) {
307ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			drmModeFreeObjectProperties(props);
308ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			goto err;
309ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
310ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		drmModeFreeObjectProperties(props);
311ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
312ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
313ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (pr)
314ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		drmModeFreePlaneResources(pr);
315ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (r)
316ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		drmModeFreeResources(r);
317ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
318ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	return dev;
319ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paulerr:
320ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (pr)
321ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		drmModeFreePlaneResources(pr);
322ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (r)
323ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		drmModeFreeResources(r);
324ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	destroy_sp_dev(dev);
325ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	return NULL;
326ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul}
327ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
328ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paulvoid destroy_sp_dev(struct sp_dev *dev)
329ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul{
330ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	int i;
331ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
332ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (dev->planes) {
333ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		for (i = 0; i< dev->num_planes; i++) {
334ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			if (dev->planes[i].in_use)
335ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul				put_sp_plane(&dev->planes[i]);
336ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			if (dev->planes[i].plane)
337ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul				drmModeFreePlane(dev->planes[i].plane);
338ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			if (dev->planes[i].bo)
339ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul				free_sp_bo(dev->planes[i].bo);
340ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
341ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		free(dev->planes);
342ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
343ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (dev->crtcs) {
344ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		for (i = 0; i< dev->num_crtcs; i++) {
345ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			if (dev->crtcs[i].crtc)
346ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul				drmModeFreeCrtc(dev->crtcs[i].crtc);
347ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
348ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		free(dev->crtcs);
349ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
350ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (dev->encoders) {
351ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		for (i = 0; i< dev->num_encoders; i++) {
352ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul			if (dev->encoders[i])
353ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul				drmModeFreeEncoder(dev->encoders[i]);
354ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
355ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		free(dev->encoders);
356ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
357ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	if (dev->connectors) {
358ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		for (i = 0; i< dev->num_connectors; i++) {
359085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul			if (dev->connectors[i].conn)
360085db961ef8c2b6d7c939fe1fda8152e40b23071Sean Paul				drmModeFreeConnector(dev->connectors[i].conn);
361ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		}
362ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul		free(dev->connectors);
363ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	}
364ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul
365ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	close(dev->fd);
366ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul	free(dev);
367ef6e8f241ab759e3f707c33d5c700baadae5badbSean Paul}
368