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