2
* Copyright © 2007 Red Hat, Inc.
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:
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
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 FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
* Dave Airlie <airlied@redhat.com>
33
#include <sys/ioctl.h>
36
#include "X11/Xatom.h"
43
#include "via_driver.h"
46
#ifdef HAVE_XEXTPROTO_71
47
#include <X11/extensions/dpmsconst.h>
50
#include <X11/extensions/dpms.h>
54
window_belongs_to_crtc(ScrnInfoPtr pScrn, int x, int y, int w, int h)
56
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
57
int largest = 0, area = 0, i;
58
BoxRec crtc_area, overlap;
59
xf86CrtcPtr best = NULL;
61
for (i = 0; i < xf86_config->num_crtc; i++) {
62
xf86CrtcPtr crtc = xf86_config->crtc[i];
65
crtc_area.x1 = crtc->x;
66
crtc_area.x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
67
crtc_area.y1 = crtc->y;
68
crtc_area.y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
69
overlap.x1 = crtc_area.x1 > x ? crtc_area.x1 : x;
70
overlap.x2 = crtc_area.x2 < x + w ? crtc_area.x2 : x + w;
71
overlap.y1 = crtc_area.y1 > y ? crtc_area.y1 : y;
72
overlap.y2 = crtc_area.y2 < y ? crtc_area.y2 : y + h;
74
if (overlap.x1 >= overlap.x2 || overlap.y1 >= overlap.y2)
75
overlap.x1 = overlap.x2 = overlap.y1 = overlap.y2 = 0;
77
area = (overlap.x2 - overlap.x1) * (overlap.y2 - overlap.y1);
88
drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
91
memset(mode, 0, sizeof(DisplayModeRec));
92
mode->status = MODE_OK;
94
mode->Clock = kmode->clock;
96
mode->HDisplay = kmode->hdisplay;
97
mode->HSyncStart = kmode->hsync_start;
98
mode->HSyncEnd = kmode->hsync_end;
99
mode->HTotal = kmode->htotal;
100
mode->HSkew = kmode->hskew;
102
mode->VDisplay = kmode->vdisplay;
103
mode->VSyncStart = kmode->vsync_start;
104
mode->VSyncEnd = kmode->vsync_end;
105
mode->VTotal = kmode->vtotal;
106
mode->VScan = kmode->vscan;
108
mode->Flags = kmode->flags; //& FLAG_BITS;
109
mode->name = strdup(kmode->name);
111
if (kmode->type & DRM_MODE_TYPE_DRIVER)
112
mode->type = M_T_DRIVER;
113
if (kmode->type & DRM_MODE_TYPE_PREFERRED)
114
mode->type |= M_T_PREFERRED;
115
xf86SetModeCrtc(mode, pScrn->adjustFlags);
119
drmmode_ConvertToKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
122
memset(kmode, 0, sizeof(*kmode));
124
kmode->clock = mode->Clock;
125
kmode->hdisplay = mode->HDisplay;
126
kmode->hsync_start = mode->HSyncStart;
127
kmode->hsync_end = mode->HSyncEnd;
128
kmode->htotal = mode->HTotal;
129
kmode->hskew = mode->HSkew;
131
kmode->vdisplay = mode->VDisplay;
132
kmode->vsync_start = mode->VSyncStart;
133
kmode->vsync_end = mode->VSyncEnd;
134
kmode->vtotal = mode->VTotal;
135
kmode->vscan = mode->VScan;
137
kmode->flags = mode->Flags; //& FLAG_BITS;
139
strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
140
kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
144
drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
147
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
148
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
149
drmmode_ptr drmmode = drmmode_crtc->drmmode;
151
/* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
152
if (mode == DPMSModeOff) {
153
drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
154
0, 0, 0, NULL, 0, NULL);
160
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
161
Rotation rotation, int x, int y)
163
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
164
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
165
drmmode_ptr drmmode = drmmode_crtc->drmmode;
166
ScrnInfoPtr pScrn = crtc->scrn;
167
int output_count = 0, ret, i;
168
uint32_t *output_ids = NULL;
169
drmModeModeInfo kmode;
171
if (!mode || !xf86CrtcRotate(crtc))
174
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
178
for (i = 0; i < xf86_config->num_output; i++) {
179
xf86OutputPtr output = xf86_config->output[i];
180
drmmode_output_private_ptr drmmode_output;
182
if (output->crtc != crtc)
185
drmmode_output = output->driver_private;
186
output_ids[output_count] = drmmode_output->mode_output->connector_id;
190
xf86SetModeDefaultName(mode);
191
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
193
if (drmmode->fb_id == 0) {
194
ret = drmModeAddFB(drmmode->fd, pScrn->virtualX, pScrn->virtualY,
195
pScrn->depth, pScrn->bitsPerPixel,
196
drmmode->front_bo->pitch,
197
drmmode->front_bo->handle,
200
ErrorF("failed to add fb %d\n", ret);
205
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
206
drmmode->fb_id, x, y, output_ids, output_count, &kmode);
208
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "failed to set mode: %s",
213
if (crtc->scrn->pScreen)
214
xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
216
/* go through all the outputs and force DPMS them back on? */
217
for (i = 0; i < xf86_config->num_output; i++) {
218
xf86OutputPtr output = xf86_config->output[i];
220
if (output->crtc != crtc)
223
output->funcs->dpms(output, DPMSModeOn);
226
#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
227
crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
228
crtc->gamma_blue, crtc->gamma_size);
231
if (pScrn->pScreen && drmmode->hwcursor)
232
xf86_reload_cursors(pScrn->pScreen);
235
return (ret < 0 ? FALSE : TRUE);
239
drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
244
drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
246
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
247
drmmode_ptr drmmode = drmmode_crtc->drmmode;
249
drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
253
drmmode_hide_cursor (xf86CrtcPtr crtc)
255
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
256
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
257
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
258
drmmode_ptr drmmode = drmmode_crtc->drmmode;
260
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
261
cursor_info->MaxWidth, cursor_info->MaxHeight);
265
drmmode_show_cursor (xf86CrtcPtr crtc)
267
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
268
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
269
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
270
uint32_t handle = drmmode_crtc->cursor_bo->handle;
271
drmmode_ptr drmmode = drmmode_crtc->drmmode;
273
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
274
cursor_info->MaxWidth, cursor_info->MaxHeight);
278
drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
280
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
281
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
282
xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
283
uint32_t handle = drmmode_crtc->cursor_bo->handle, *ptr;
285
/* cursor should be mapped already */
286
ptr = drm_bo_map(crtc->scrn, drmmode_crtc->cursor_bo);
287
memset(ptr, 0x00, drmmode_crtc->cursor_bo->size);
288
memcpy(ptr, image, drmmode_crtc->cursor_bo->size);
289
drm_bo_unmap(crtc->scrn, drmmode_crtc->cursor_bo);
291
if (drmModeSetCursor(drmmode_crtc->drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
292
handle, cursor_info->MaxWidth, cursor_info->MaxHeight)) {
293
drmmode_ptr drmmode = drmmode_crtc->drmmode;
295
cursor_info->MaxWidth = cursor_info->MaxHeight = 0;
296
drmmode->hwcursor = FALSE;
301
drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
302
uint16_t *blue, int size)
304
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
305
drmmode_ptr drmmode = drmmode_crtc->drmmode;
307
drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
308
size, red, green, blue);
311
static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
312
.dpms = drmmode_crtc_dpms,
313
.set_mode_major = drmmode_set_mode_major,
314
.set_cursor_colors = drmmode_set_cursor_colors,
315
.set_cursor_position = drmmode_set_cursor_position,
316
.show_cursor = drmmode_show_cursor,
317
.hide_cursor = drmmode_hide_cursor,
318
.load_cursor_argb = drmmode_load_cursor_argb,
319
.gamma_set = drmmode_crtc_gamma_set,
324
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
326
drmmode_crtc_private_ptr drmmode_crtc;
329
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
333
drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
334
drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
335
drmmode_crtc->drmmode = drmmode;
336
crtc->driver_private = drmmode_crtc;
340
* Handle KMS xf86Outputs
343
drmmode_property_ignore(drmModePropertyPtr prop)
348
/* ignore blob prop */
349
if (prop->flags & DRM_MODE_PROP_BLOB)
352
/* ignore standard property */
353
if (!strcmp(prop->name, "EDID") ||
354
!strcmp(prop->name, "DPMS"))
361
drmmode_output_dpms(xf86OutputPtr output, int mode)
363
drmmode_output_private_ptr drmmode_output = output->driver_private;
364
drmModeConnectorPtr koutput = drmmode_output->mode_output;
365
drmmode_ptr drmmode = drmmode_output->drmmode;
367
drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
368
drmmode_output->dpms_enum_id, mode);
373
drmmode_output_create_resources(xf86OutputPtr output)
375
drmmode_output_private_ptr drmmode_output = output->driver_private;
376
drmModeConnectorPtr mode_output = drmmode_output->mode_output;
377
drmmode_ptr drmmode = drmmode_output->drmmode;
378
drmModePropertyPtr drmmode_prop;
381
drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
382
if (!drmmode_output->props)
385
drmmode_output->num_props = 0;
386
for (i = 0, j = 0; i < mode_output->count_props; i++) {
387
drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
389
if (drmmode_property_ignore(drmmode_prop)) {
390
drmModeFreeProperty(drmmode_prop);
393
drmmode_output->props[j].mode_prop = drmmode_prop;
394
drmmode_output->props[j].value = mode_output->prop_values[i];
395
drmmode_output->num_props++;
399
for (i = 0; i < drmmode_output->num_props; i++) {
400
drmmode_prop_ptr p = &drmmode_output->props[i];
401
drmmode_prop = p->mode_prop;
403
if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
405
INT32 value = p->value;
408
p->atoms = calloc(p->num_atoms, sizeof(Atom));
411
p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
412
range[0] = drmmode_prop->values[0];
413
range[1] = drmmode_prop->values[1];
414
err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
416
drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
419
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
420
"RRConfigureOutputProperty error, %d\n", err);
422
err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
423
XA_INTEGER, 32, PropModeReplace, 1,
424
&value, FALSE, TRUE);
426
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
427
"RRChangeOutputProperty error, %d\n", err);
430
} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
431
p->num_atoms = drmmode_prop->count_enums + 1;
432
p->atoms = calloc(p->num_atoms, sizeof(Atom));
436
p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
437
for (j = 1; j <= drmmode_prop->count_enums; j++) {
438
struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
440
p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
442
err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
444
drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
445
p->num_atoms - 1, (INT32 *)&p->atoms[1]);
447
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
448
"RRConfigureOutputProperty error, %d\n", err);
451
for (j = 0; j < drmmode_prop->count_enums; j++)
452
if (drmmode_prop->enums[j].value == p->value)
455
/* there's always a matching value */
456
err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
457
XA_ATOM, 32, PropModeReplace, 1,
458
&p->atoms[j+1], FALSE, TRUE);
460
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
461
"RRChangeOutputProperty error, %d\n", err);
468
drmmode_output_set_property(xf86OutputPtr output, Atom property,
469
RRPropertyValuePtr value)
471
drmmode_output_private_ptr drmmode_output = output->driver_private;
472
drmmode_ptr drmmode = drmmode_output->drmmode;
475
for (i = 0; i < drmmode_output->num_props; i++) {
476
drmmode_prop_ptr p = &drmmode_output->props[i];
478
if (p->atoms[0] != property)
481
if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
484
if (value->type != XA_INTEGER || value->format != 32 ||
487
val = *(uint32_t *)value->data;
489
drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
490
p->mode_prop->prop_id, (uint64_t)val);
492
} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
497
if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
499
memcpy(&atom, value->data, 4);
500
name = NameForAtom(atom);
502
/* search for matching name string, then set its value down */
503
for (j = 0; j < p->mode_prop->count_enums; j++) {
504
if (!strcmp(p->mode_prop->enums[j].name, name)) {
505
drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
506
p->mode_prop->prop_id, p->mode_prop->enums[j].value);
516
drmmode_output_get_property(xf86OutputPtr output, Atom property)
521
static xf86OutputStatus
522
drmmode_output_detect(xf86OutputPtr output)
524
/* go to the hw and retrieve a new output struct */
525
drmmode_output_private_ptr drmmode_output = output->driver_private;
526
drmmode_ptr drmmode = drmmode_output->drmmode;
527
xf86OutputStatus status;
529
drmModeFreeConnector(drmmode_output->mode_output);
530
drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
532
switch (drmmode_output->mode_output->connection) {
533
case DRM_MODE_CONNECTED:
534
status = XF86OutputStatusConnected;
536
case DRM_MODE_DISCONNECTED:
537
status = XF86OutputStatusDisconnected;
540
case DRM_MODE_UNKNOWNCONNECTION:
541
status = XF86OutputStatusUnknown;
548
drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
553
static DisplayModePtr
554
drmmode_output_get_modes(xf86OutputPtr output)
556
drmmode_output_private_ptr drmmode_output = output->driver_private;
557
drmModeConnectorPtr koutput = drmmode_output->mode_output;
558
drmmode_ptr drmmode = drmmode_output->drmmode;
559
DisplayModePtr Modes = NULL, Mode;
560
drmModePropertyPtr props;
561
xf86MonPtr mon = NULL;
564
/* look for an EDID property */
565
for (i = 0; i < koutput->count_props; i++) {
566
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
567
if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
568
if (!strcmp(props->name, "EDID")) {
569
if (drmmode_output->edid_blob)
570
drmModeFreePropertyBlob(drmmode_output->edid_blob);
571
drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
573
drmModeFreeProperty(props);
577
if (drmmode_output->edid_blob) {
578
mon = xf86InterpretEDID(output->scrn->scrnIndex,
579
drmmode_output->edid_blob->data);
580
if (mon && drmmode_output->edid_blob->length > 128)
581
mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
583
xf86OutputSetEDID(output, mon);
585
/* modes should already be available */
586
for (i = 0; i < koutput->count_modes; i++) {
587
Mode = xnfalloc(sizeof(DisplayModeRec));
589
drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
590
Modes = xf86ModesAdd(Modes, Mode);
597
drmmode_output_destroy(xf86OutputPtr output)
599
drmmode_output_private_ptr drmmode_output = output->driver_private;
602
if (drmmode_output->edid_blob)
603
drmModeFreePropertyBlob(drmmode_output->edid_blob);
605
for (i = 0; i < drmmode_output->num_props; i++) {
606
drmModeFreeProperty(drmmode_output->props[i].mode_prop);
607
free(drmmode_output->props[i].atoms);
610
for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
611
drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
612
free(drmmode_output->mode_encoders);
614
free(drmmode_output->props);
615
drmModeFreeConnector(drmmode_output->mode_output);
616
free(drmmode_output);
617
output->driver_private = NULL;
620
static const xf86OutputFuncsRec drmmode_output_funcs = {
621
.dpms = drmmode_output_dpms,
622
.create_resources = drmmode_output_create_resources,
623
#ifdef RANDR_12_INTERFACE
624
.set_property = drmmode_output_set_property,
625
.get_property = drmmode_output_get_property,
627
.detect = drmmode_output_detect,
628
.mode_valid = drmmode_output_mode_valid,
629
.get_modes = drmmode_output_get_modes,
630
.destroy = drmmode_output_destroy
633
static int subpixel_conv_table[7] = {
636
SubPixelHorizontalRGB,
637
SubPixelHorizontalBGR,
643
const char *output_names[] = {
662
drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
664
xf86OutputPtr output;
665
drmModeConnectorPtr koutput;
666
drmModeEncoderPtr *kencoders = NULL;
667
drmmode_output_private_ptr drmmode_output;
668
drmModePropertyPtr props;
672
koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
676
kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
678
goto out_free_encoders;
681
for (i = 0; i < koutput->count_encoders; i++) {
682
kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
684
goto out_free_encoders;
688
/* need to do smart conversion here for compat with non-kms ATI driver */
689
snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
691
output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
693
goto out_free_encoders;
696
drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
697
if (!drmmode_output) {
698
xf86OutputDestroy(output);
699
goto out_free_encoders;
702
drmmode_output->output_id = drmmode->mode_res->connectors[num];
703
drmmode_output->mode_output = koutput;
704
drmmode_output->mode_encoders = kencoders;
705
drmmode_output->drmmode = drmmode;
706
output->mm_width = koutput->mmWidth;
707
output->mm_height = koutput->mmHeight;
709
output->subpixel_order = subpixel_conv_table[koutput->subpixel];
710
output->interlaceAllowed = TRUE;
711
output->doubleScanAllowed = TRUE;
712
output->driver_private = drmmode_output;
714
output->possible_crtcs = 0x7f;
715
for (i = 0; i < koutput->count_encoders; i++)
716
output->possible_crtcs &= kencoders[i]->possible_crtcs;
718
/* work out the possible clones later */
719
output->possible_clones = 0;
721
for (i = 0; i < koutput->count_props; i++) {
722
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
723
if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
724
if (!strcmp(props->name, "DPMS")) {
725
drmmode_output->dpms_enum_id = koutput->props[i];
726
drmModeFreeProperty(props);
729
drmModeFreeProperty(props);
736
for (i = 0; i < koutput->count_encoders; i++)
737
drmModeFreeEncoder(kencoders[i]);
740
drmModeFreeConnector(koutput);
743
uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
745
drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
746
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
747
xf86OutputPtr clone_output;
748
int index_mask = 0, i;
750
if (drmmode_output->enc_clone_mask == 0)
753
for (i = 0; i < xf86_config->num_output; i++) {
754
clone_output = xf86_config->output[i];
755
clone_drmout = clone_output->driver_private;
756
if (output == clone_output)
758
if (clone_drmout->enc_mask == 0)
760
if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
761
index_mask |= (1 << i);
767
drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
769
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
772
for (i = 0; i < xf86_config->num_output; i++) {
773
xf86OutputPtr output = xf86_config->output[i];
774
drmmode_output_private_ptr drmmode_output;
776
drmmode_output = output->driver_private;
777
drmmode_output->enc_clone_mask = 0xff;
778
/* and all the possible encoder clones for this output together */
779
for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) {
782
for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
783
if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
784
drmmode_output->enc_mask |= (1 << k);
787
drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
791
for (i = 0; i < xf86_config->num_output; i++) {
792
xf86OutputPtr output = xf86_config->output[i];
793
output->possible_clones = find_clones(scrn, output);
797
Bool KMSCrtcInit(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
801
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "KMSCrtcInit\n"));
803
drmmode->scrn = pScrn;
804
drmmode->mode_res = drmModeGetResources(drmmode->fd);
805
if (!drmmode->mode_res)
808
xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
809
for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
810
if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
811
drmmode_crtc_init(pScrn, drmmode, i);
813
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
814
drmmode_output_init(pScrn, drmmode, i);
817
drmmode_clones_init(pScrn, drmmode);
823
drmmode_handle_uevents(int fd, void *closure)
825
drmmode_ptr drmmode = closure;
826
ScrnInfoPtr scrn = drmmode->scrn;
827
struct udev_device *dev;
829
dev = udev_monitor_receive_device(drmmode->uevent_monitor);
833
RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
834
udev_device_unref(dev);
838
void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
841
struct udev_monitor *mon;
848
mon = udev_monitor_new_from_netlink(u, "udev");
854
if (udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", "drm_minor") < 0 ||
855
udev_monitor_enable_receiving(mon) < 0) {
856
udev_monitor_unref(mon);
861
drmmode->uevent_handler = xf86AddGeneralHandler(udev_monitor_get_fd(mon),
862
drmmode_handle_uevents,
864
drmmode->uevent_monitor = mon;
868
void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
871
if (drmmode->uevent_handler) {
872
struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
874
xf86RemoveGeneralHandler(drmmode->uevent_handler);
876
udev_monitor_unref(drmmode->uevent_monitor);