diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-12-19 20:25:43 +0100 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-12-19 20:25:43 +0100 |
commit | b5546fb1de3f3859151a91e98ab0bd24b6789e2e (patch) | |
tree | 8e5283d6610e87d796e0d64b0a06c42469422b0d /vmwgfx/vmwgfx_output.c | |
parent | abf9cb75630cb27bb4741d194cb23014fe3d09b1 (diff) | |
parent | 5748c33535bc7d3009b9758653885e6ae0e73002 (diff) |
Merge branch 'vmwgfx_branch'
Diffstat (limited to 'vmwgfx/vmwgfx_output.c')
-rw-r--r-- | vmwgfx/vmwgfx_output.c | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c new file mode 100644 index 0000000..4f52f1d --- /dev/null +++ b/vmwgfx/vmwgfx_output.c | |||
@@ -0,0 +1,393 @@ | |||
1 | /* | ||
2 | * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the | ||
7 | * "Software"), to deal in the Software without restriction, including | ||
8 | * without limitation the rights to use, copy, modify, merge, publish, | ||
9 | * distribute, sub license, and/or sell copies of the Software, and to | ||
10 | * permit persons to whom the Software is furnished to do so, subject to | ||
11 | * the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the | ||
14 | * next paragraph) shall be included in all copies or substantial portions | ||
15 | * of the Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||
20 | * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||
21 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
24 | * | ||
25 | * | ||
26 | * Author: Alan Hourihane <alanh@tungstengraphics.com> | ||
27 | * Author: Jakob Bornecrantz <wallbraker@gmail.com> | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include "xorg-server.h" | ||
32 | #include <xf86.h> | ||
33 | #include <xf86i2c.h> | ||
34 | #include <xf86Crtc.h> | ||
35 | #include <errno.h> | ||
36 | #include <fcntl.h> | ||
37 | #include <unistd.h> | ||
38 | #include <stdio.h> | ||
39 | #include <stdlib.h> | ||
40 | #include <stdint.h> | ||
41 | #include <string.h> | ||
42 | #include <sys/stat.h> | ||
43 | #include <sys/types.h> | ||
44 | |||
45 | #ifdef HAVE_XEXTPROTO_71 | ||
46 | #include <X11/extensions/dpmsconst.h> | ||
47 | #else | ||
48 | #define DPMS_SERVER | ||
49 | #include <X11/extensions/dpms.h> | ||
50 | #endif | ||
51 | |||
52 | #include "vmwgfx_driver.h" | ||
53 | |||
54 | struct output_private | ||
55 | { | ||
56 | drmModeConnectorPtr drm_connector; | ||
57 | |||
58 | int c; | ||
59 | |||
60 | Bool is_implicit; | ||
61 | }; | ||
62 | |||
63 | static char *output_enum_list[] = { | ||
64 | "Unknown", | ||
65 | "VGA", | ||
66 | "DVI", | ||
67 | "DVI", | ||
68 | "DVI", | ||
69 | "Composite", | ||
70 | "SVIDEO", | ||
71 | "LVDS", | ||
72 | "CTV", | ||
73 | "DIN", | ||
74 | "DP", | ||
75 | "HDMI", | ||
76 | "HDMI", | ||
77 | "TV", | ||
78 | "EDP", | ||
79 | "Virtual", | ||
80 | }; | ||
81 | |||
82 | static void | ||
83 | output_create_resources(xf86OutputPtr output) | ||
84 | { | ||
85 | #ifdef RANDR_12_INTERFACE | ||
86 | #endif /* RANDR_12_INTERFACE */ | ||
87 | } | ||
88 | |||
89 | static void | ||
90 | output_dpms(xf86OutputPtr output, int mode) | ||
91 | { | ||
92 | } | ||
93 | |||
94 | static xf86OutputStatus | ||
95 | output_detect(xf86OutputPtr output) | ||
96 | { | ||
97 | modesettingPtr ms = modesettingPTR(output->scrn); | ||
98 | struct output_private *priv = output->driver_private; | ||
99 | drmModeConnectorPtr drm_connector; | ||
100 | xf86OutputStatus status; | ||
101 | |||
102 | drm_connector = drmModeGetConnector(ms->fd, priv->drm_connector->connector_id); | ||
103 | if (drm_connector) { | ||
104 | drmModeFreeConnector(priv->drm_connector); | ||
105 | priv->drm_connector = drm_connector; | ||
106 | } else { | ||
107 | drm_connector = priv->drm_connector; | ||
108 | } | ||
109 | |||
110 | switch (drm_connector->connection) { | ||
111 | case DRM_MODE_CONNECTED: | ||
112 | status = XF86OutputStatusConnected; | ||
113 | break; | ||
114 | case DRM_MODE_DISCONNECTED: | ||
115 | status = XF86OutputStatusDisconnected; | ||
116 | break; | ||
117 | default: | ||
118 | status = XF86OutputStatusUnknown; | ||
119 | } | ||
120 | |||
121 | return status; | ||
122 | } | ||
123 | |||
124 | static DisplayModePtr | ||
125 | output_get_modes(xf86OutputPtr output) | ||
126 | { | ||
127 | struct output_private *priv = output->driver_private; | ||
128 | drmModeConnectorPtr drm_connector = priv->drm_connector; | ||
129 | drmModeModeInfoPtr drm_mode = NULL; | ||
130 | DisplayModePtr modes = NULL, mode = NULL; | ||
131 | int i; | ||
132 | |||
133 | for (i = 0; i < drm_connector->count_modes; i++) { | ||
134 | drm_mode = &drm_connector->modes[i]; | ||
135 | if (drm_mode) { | ||
136 | mode = calloc(1, sizeof(DisplayModeRec)); | ||
137 | if (!mode) | ||
138 | continue; | ||
139 | mode->Clock = drm_mode->clock; | ||
140 | mode->HDisplay = drm_mode->hdisplay; | ||
141 | mode->HSyncStart = drm_mode->hsync_start; | ||
142 | mode->HSyncEnd = drm_mode->hsync_end; | ||
143 | mode->HTotal = drm_mode->htotal; | ||
144 | mode->VDisplay = drm_mode->vdisplay; | ||
145 | mode->VSyncStart = drm_mode->vsync_start; | ||
146 | mode->VSyncEnd = drm_mode->vsync_end; | ||
147 | mode->VTotal = drm_mode->vtotal; | ||
148 | mode->Flags = drm_mode->flags; | ||
149 | mode->HSkew = drm_mode->hskew; | ||
150 | mode->VScan = drm_mode->vscan; | ||
151 | mode->VRefresh = xf86ModeVRefresh(mode); | ||
152 | mode->Private = (void *)drm_mode; | ||
153 | mode->type = 0; | ||
154 | if (drm_mode->type & DRM_MODE_TYPE_PREFERRED) | ||
155 | mode->type |= M_T_PREFERRED; | ||
156 | if (drm_mode->type & DRM_MODE_TYPE_DRIVER) | ||
157 | mode->type |= M_T_DRIVER; | ||
158 | xf86SetModeDefaultName(mode); | ||
159 | modes = xf86ModesAdd(modes, mode); | ||
160 | xf86PrintModeline(0, mode); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | return modes; | ||
165 | } | ||
166 | |||
167 | static int | ||
168 | output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) | ||
169 | { | ||
170 | // modesettingPtr ms = modesettingPTR(output->scrn); | ||
171 | // CustomizerPtr cust = ms->cust; | ||
172 | |||
173 | #if 0 | ||
174 | if (cust && cust->winsys_check_fb_size && | ||
175 | !cust->winsys_check_fb_size(cust, pMode->HDisplay * | ||
176 | output->scrn->bitsPerPixel / 8, | ||
177 | pMode->VDisplay)) | ||
178 | return MODE_BAD; | ||
179 | #endif | ||
180 | return MODE_OK; | ||
181 | } | ||
182 | |||
183 | #ifdef RANDR_12_INTERFACE | ||
184 | static Bool | ||
185 | output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value) | ||
186 | { | ||
187 | return TRUE; | ||
188 | } | ||
189 | #endif /* RANDR_12_INTERFACE */ | ||
190 | |||
191 | #ifdef RANDR_13_INTERFACE | ||
192 | static Bool | ||
193 | output_get_property(xf86OutputPtr output, Atom property) | ||
194 | { | ||
195 | return TRUE; | ||
196 | } | ||
197 | #endif /* RANDR_13_INTERFACE */ | ||
198 | |||
199 | static void | ||
200 | output_destroy(xf86OutputPtr output) | ||
201 | { | ||
202 | struct output_private *priv = output->driver_private; | ||
203 | drmModeFreeConnector(priv->drm_connector); | ||
204 | free(priv); | ||
205 | output->driver_private = NULL; | ||
206 | } | ||
207 | |||
208 | static const xf86OutputFuncsRec output_funcs = { | ||
209 | .create_resources = output_create_resources, | ||
210 | #ifdef RANDR_12_INTERFACE | ||
211 | .set_property = output_set_property, | ||
212 | #endif | ||
213 | #ifdef RANDR_13_INTERFACE | ||
214 | .get_property = output_get_property, | ||
215 | #endif | ||
216 | .dpms = output_dpms, | ||
217 | .detect = output_detect, | ||
218 | |||
219 | .get_modes = output_get_modes, | ||
220 | .mode_valid = output_mode_valid, | ||
221 | .destroy = output_destroy, | ||
222 | }; | ||
223 | |||
224 | /** | ||
225 | * vmwgfx_output_explicit_overlap -- Check for explicit output overlaps | ||
226 | * | ||
227 | * This function returns TRUE iff the bounding box in screen space of an | ||
228 | * exlplicit output overlaps the bounding box in screen space of any other | ||
229 | * output. | ||
230 | */ | ||
231 | Bool | ||
232 | vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn) | ||
233 | { | ||
234 | xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); | ||
235 | xf86OutputPtr output; | ||
236 | ScreenPtr pScreen = pScrn->pScreen; | ||
237 | RegionRec output_union; | ||
238 | RegionRec cur_output; | ||
239 | RegionRec result; | ||
240 | struct output_private *priv; | ||
241 | xf86CrtcPtr crtc; | ||
242 | Bool overlap = FALSE; | ||
243 | int i; | ||
244 | |||
245 | (void) pScreen; | ||
246 | REGION_NULL(pScreen, &output_union); | ||
247 | REGION_NULL(pScreen, &cur_output); | ||
248 | REGION_NULL(pScreen, &result); | ||
249 | |||
250 | /* | ||
251 | * Collect a region of implicit outputs. These may overlap. | ||
252 | */ | ||
253 | for (i = 0; i < config->num_output; i++) { | ||
254 | output = config->output[i]; | ||
255 | priv = output->driver_private; | ||
256 | crtc = output->crtc; | ||
257 | |||
258 | if (!crtc || !crtc->enabled || !priv->is_implicit) | ||
259 | continue; | ||
260 | |||
261 | REGION_RESET(pScreen, &cur_output, &crtc->bounds); | ||
262 | REGION_UNION(pScreen, &output_union, &output_union, &cur_output); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Explicit outputs may not overlap any other output. | ||
267 | */ | ||
268 | for (i = 0; i < config->num_output; i++) { | ||
269 | output = config->output[i]; | ||
270 | priv = output->driver_private; | ||
271 | crtc = output->crtc; | ||
272 | |||
273 | if (!crtc || !crtc->enabled || priv->is_implicit) | ||
274 | continue; | ||
275 | |||
276 | REGION_RESET(pScreen, &cur_output, &crtc->bounds); | ||
277 | REGION_NULL(pScreen, &result); | ||
278 | REGION_INTERSECT(pScreen, &result, &output_union, &cur_output); | ||
279 | overlap = REGION_NOTEMPTY(vsaa->pScreen, &result); | ||
280 | if (overlap) | ||
281 | break; | ||
282 | |||
283 | REGION_UNION(pScreen, &output_union, &output_union, &cur_output); | ||
284 | } | ||
285 | |||
286 | REGION_UNINIT(pScreen, &output_union); | ||
287 | REGION_UNINIT(pScreen, &cur_output); | ||
288 | REGION_UNINIT(pScreen, &result); | ||
289 | |||
290 | return overlap; | ||
291 | } | ||
292 | |||
293 | void | ||
294 | xorg_output_init(ScrnInfoPtr pScrn) | ||
295 | { | ||
296 | modesettingPtr ms = modesettingPTR(pScrn); | ||
297 | xf86OutputPtr output; | ||
298 | drmModeResPtr res; | ||
299 | drmModeConnectorPtr drm_connector = NULL; | ||
300 | drmModeEncoderPtr drm_encoder = NULL; | ||
301 | struct output_private *priv; | ||
302 | char name[32]; | ||
303 | int c, p; | ||
304 | |||
305 | res = drmModeGetResources(ms->fd); | ||
306 | if (res == 0) { | ||
307 | DRV_ERROR("Failed drmModeGetResources\n"); | ||
308 | return; | ||
309 | } | ||
310 | |||
311 | for (c = 0; c < res->count_connectors; c++) { | ||
312 | Bool is_implicit = TRUE; | ||
313 | |||
314 | drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]); | ||
315 | if (!drm_connector) | ||
316 | goto out; | ||
317 | |||
318 | |||
319 | for (p = 0; p < drm_connector->count_props; p++) { | ||
320 | drmModePropertyPtr prop; | ||
321 | |||
322 | prop = drmModeGetProperty(ms->fd, drm_connector->props[p]); | ||
323 | |||
324 | if (prop) { | ||
325 | |||
326 | #if 0 | ||
327 | /* | ||
328 | * Disabled until we sort out what the interface should | ||
329 | * look like. | ||
330 | */ | ||
331 | |||
332 | if (strcmp(prop->name, "implicit placement") == 0) { | ||
333 | drmModeConnectorSetProperty(ms->fd, | ||
334 | drm_connector->connector_id, | ||
335 | prop->prop_id, | ||
336 | 0); | ||
337 | is_implicit = FALSE; | ||
338 | } | ||
339 | #endif | ||
340 | drmModeFreeProperty(prop); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | if (drm_connector->connector_type >= | ||
345 | sizeof(output_enum_list) / sizeof(output_enum_list[0])) | ||
346 | drm_connector->connector_type = 0; | ||
347 | |||
348 | snprintf(name, 32, "%s%d", | ||
349 | output_enum_list[drm_connector->connector_type], | ||
350 | drm_connector->connector_type_id); | ||
351 | |||
352 | |||
353 | priv = calloc(sizeof(*priv), 1); | ||
354 | if (!priv) { | ||
355 | continue; | ||
356 | } | ||
357 | |||
358 | output = xf86OutputCreate(pScrn, &output_funcs, name); | ||
359 | if (!output) { | ||
360 | free(priv); | ||
361 | continue; | ||
362 | } | ||
363 | |||
364 | priv->is_implicit = is_implicit; | ||
365 | |||
366 | drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]); | ||
367 | if (drm_encoder) { | ||
368 | output->possible_crtcs = drm_encoder->possible_crtcs; | ||
369 | output->possible_clones = drm_encoder->possible_clones; | ||
370 | } else { | ||
371 | output->possible_crtcs = 0; | ||
372 | output->possible_clones = 0; | ||
373 | } | ||
374 | priv->c = c; | ||
375 | priv->drm_connector = drm_connector; | ||
376 | output->driver_private = priv; | ||
377 | output->subpixel_order = SubPixelHorizontalRGB; | ||
378 | output->interlaceAllowed = FALSE; | ||
379 | output->doubleScanAllowed = FALSE; | ||
380 | } | ||
381 | |||
382 | out: | ||
383 | drmModeFreeResources(res); | ||
384 | } | ||
385 | |||
386 | unsigned | ||
387 | xorg_output_get_id(xf86OutputPtr output) | ||
388 | { | ||
389 | struct output_private *priv = output->driver_private; | ||
390 | return priv->drm_connector->connector_id; | ||
391 | } | ||
392 | |||
393 | /* vim: set sw=4 ts=8 sts=4: */ | ||