Home | History | Annotate | Download | only in kms
      1 /*
      2  * Copyright  2014 NVIDIA Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #include <stdio.h>
     25 #include <string.h>
     26 #include <unistd.h>
     27 
     28 #include "util/common.h"
     29 #include "libkms-test.h"
     30 
     31 static const char *const connector_names[] = {
     32 	"Unknown",
     33 	"VGA",
     34 	"DVI-I",
     35 	"DVI-D",
     36 	"DVI-A",
     37 	"Composite",
     38 	"SVIDEO",
     39 	"LVDS",
     40 	"Component",
     41 	"9PinDIN",
     42 	"DisplayPort",
     43 	"HDMI-A",
     44 	"HDMI-B",
     45 	"TV",
     46 	"eDP",
     47 	"Virtual",
     48 	"DSI",
     49 };
     50 
     51 static void kms_device_probe_screens(struct kms_device *device)
     52 {
     53 	unsigned int counts[ARRAY_SIZE(connector_names)];
     54 	struct kms_screen *screen;
     55 	drmModeRes *res;
     56 	int i;
     57 
     58 	memset(counts, 0, sizeof(counts));
     59 
     60 	res = drmModeGetResources(device->fd);
     61 	if (!res)
     62 		return;
     63 
     64 	device->screens = calloc(res->count_connectors, sizeof(screen));
     65 	if (!device->screens)
     66 		goto err_free_resources;
     67 
     68 	for (i = 0; i < res->count_connectors; i++) {
     69 		unsigned int *count;
     70 		const char *type;
     71 		int len;
     72 
     73 		screen = kms_screen_create(device, res->connectors[i]);
     74 		if (!screen)
     75 			continue;
     76 
     77 		/* assign a unique name to this screen */
     78 		type = connector_names[screen->type];
     79 		count = &counts[screen->type];
     80 
     81 		len = snprintf(NULL, 0, "%s-%u", type, *count);
     82 
     83 		screen->name = malloc(len + 1);
     84 		if (!screen->name) {
     85 			free(screen);
     86 			continue;
     87 		}
     88 
     89 		snprintf(screen->name, len + 1, "%s-%u", type, *count);
     90 		(*count)++;
     91 
     92 		device->screens[i] = screen;
     93 		device->num_screens++;
     94 	}
     95 
     96 err_free_resources:
     97 	drmModeFreeResources(res);
     98 }
     99 
    100 static void kms_device_probe_crtcs(struct kms_device *device)
    101 {
    102 	struct kms_crtc *crtc;
    103 	drmModeRes *res;
    104 	int i;
    105 
    106 	res = drmModeGetResources(device->fd);
    107 	if (!res)
    108 		return;
    109 
    110 	device->crtcs = calloc(res->count_crtcs, sizeof(crtc));
    111 	if (!device->crtcs)
    112 		goto err_free_resources;
    113 
    114 	for (i = 0; i < res->count_crtcs; i++) {
    115 		crtc = kms_crtc_create(device, res->crtcs[i]);
    116 		if (!crtc)
    117 			continue;
    118 
    119 		device->crtcs[i] = crtc;
    120 		device->num_crtcs++;
    121 	}
    122 
    123 err_free_resources:
    124 	drmModeFreeResources(res);
    125 }
    126 
    127 static void kms_device_probe_planes(struct kms_device *device)
    128 {
    129 	struct kms_plane *plane;
    130 	drmModePlaneRes *res;
    131 	unsigned int i;
    132 
    133 	res = drmModeGetPlaneResources(device->fd);
    134 	if (!res)
    135 		return;
    136 
    137 	device->planes = calloc(res->count_planes, sizeof(plane));
    138 	if (!device->planes)
    139 		goto err_free_resources;
    140 
    141 	for (i = 0; i < res->count_planes; i++) {
    142 		plane = kms_plane_create(device, res->planes[i]);
    143 		if (!plane)
    144 			continue;
    145 
    146 		device->planes[i] = plane;
    147 		device->num_planes++;
    148 	}
    149 
    150 err_free_resources:
    151 	drmModeFreePlaneResources(res);
    152 }
    153 
    154 static void kms_device_probe(struct kms_device *device)
    155 {
    156 	kms_device_probe_screens(device);
    157 	kms_device_probe_crtcs(device);
    158 	kms_device_probe_planes(device);
    159 }
    160 
    161 struct kms_device *kms_device_open(int fd)
    162 {
    163 	struct kms_device *device;
    164 
    165 	device = calloc(1, sizeof(*device));
    166 	if (!device)
    167 		return NULL;
    168 
    169 	device->fd = fd;
    170 
    171 	kms_device_probe(device);
    172 
    173 	return device;
    174 }
    175 
    176 void kms_device_close(struct kms_device *device)
    177 {
    178 	unsigned int i;
    179 
    180 	for (i = 0; i < device->num_planes; i++)
    181 		kms_plane_free(device->planes[i]);
    182 
    183 	free(device->planes);
    184 
    185 	for (i = 0; i < device->num_crtcs; i++)
    186 		kms_crtc_free(device->crtcs[i]);
    187 
    188 	free(device->crtcs);
    189 
    190 	for (i = 0; i < device->num_screens; i++)
    191 		kms_screen_free(device->screens[i]);
    192 
    193 	free(device->screens);
    194 
    195 	if (device->fd >= 0)
    196 		close(device->fd);
    197 
    198 	free(device);
    199 }
    200 
    201 struct kms_plane *kms_device_find_plane_by_type(struct kms_device *device,
    202 						uint32_t type,
    203 						unsigned int index)
    204 {
    205 	unsigned int i;
    206 
    207 	for (i = 0; i < device->num_planes; i++) {
    208 		if (device->planes[i]->type == type) {
    209 			if (index == 0)
    210 				return device->planes[i];
    211 
    212 			index--;
    213 		}
    214 	}
    215 
    216 	return NULL;
    217 }
    218