2
* Copyright � 2007 Red Hat, Inc.
3
* Copyright � 2008 Maarten Maathuis
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice (including the next
13
* paragraph) shall be included in all copies or substantial portions of the
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
* Dave Airlie <airlied@redhat.com>
35
#include "drmmode_display.h"
38
/* not using for the moment */
39
uint32_t drmmode_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch)
41
#if NOUVEAU_EXA_PIXMAPS
42
NVPtr pNv = NVPTR(pScrn);
45
/* temporary hack, allow old framebuffers to continue to exist and idle. */
47
nouveau_bo_del(pNv->FB_old);
51
pNv->FB_old = pNv->FB;
54
*pitch = NOUVEAU_ALIGN(*pitch, 64) * (pScrn->bitsPerPixel >> 3);
56
ret = nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
57
0, *pitch * NOUVEAU_ALIGN(height, 64), &pNv->FB)
62
ret = nouveau_bo_map(pNv->FB, NOUVEAU_BO_RDWR);
67
return pNv->FB.handle;
69
return 0; /* we have a fixed FB */
70
#endif /* NOUVEAU_EXA_PIXMAPS */
74
static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height);
78
drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
80
//xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
81
//drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private;
82
//drmmode_ptr drmmode = drmmode_crtc->drmmode;
85
ErrorF("resize called %d %d\n", width, height);
86
//ret = drmmode_resize_fb(scrn, drmmode, width, height);
87
scrn->virtualX = width;
88
scrn->virtualY = height;
94
drmmode_ConvertFromKMode(ScrnInfoPtr scrn,
95
struct drm_mode_modeinfo *kmode,
98
memset(mode, 0, sizeof(DisplayModeRec));
99
mode->status = MODE_OK;
101
mode->Clock = kmode->clock;
103
mode->HDisplay = kmode->hdisplay;
104
mode->HSyncStart = kmode->hsync_start;
105
mode->HSyncEnd = kmode->hsync_end;
106
mode->HTotal = kmode->htotal;
107
mode->HSkew = kmode->hskew;
109
mode->VDisplay = kmode->vdisplay;
110
mode->VSyncStart = kmode->vsync_start;
111
mode->VSyncEnd = kmode->vsync_end;
112
mode->VTotal = kmode->vtotal;
113
mode->VScan = kmode->vscan;
115
mode->Flags = kmode->flags; //& FLAG_BITS;
116
mode->name = strdup(kmode->name);
118
if (kmode->type & DRM_MODE_TYPE_DRIVER)
119
mode->type = M_T_DRIVER;
120
if (kmode->type & DRM_MODE_TYPE_PREFERRED)
121
mode->type |= M_T_PREFERRED;
122
xf86SetModeCrtc (mode, scrn->adjustFlags);
126
drmmode_ConvertToKMode(ScrnInfoPtr scrn,
127
struct drm_mode_modeinfo *kmode,
130
memset(kmode, 0, sizeof(*kmode));
132
kmode->clock = mode->Clock;
133
kmode->hdisplay = mode->HDisplay;
134
kmode->hsync_start = mode->HSyncStart;
135
kmode->hsync_end = mode->HSyncEnd;
136
kmode->htotal = mode->HTotal;
137
kmode->hskew = mode->HSkew;
139
kmode->vdisplay = mode->VDisplay;
140
kmode->vsync_start = mode->VSyncStart;
141
kmode->vsync_end = mode->VSyncEnd;
142
kmode->vtotal = mode->VTotal;
143
kmode->vscan = mode->VScan;
145
kmode->flags = mode->Flags; //& FLAG_BITS;
147
strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
148
kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
152
static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
153
drmmode_xf86crtc_resize
157
drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
163
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
164
Rotation rotation, int x, int y)
166
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
167
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
168
drmmode_ptr drmmode = drmmode_crtc->drmmode;
169
int saved_x, saved_y;
170
Rotation saved_rotation;
171
DisplayModeRec saved_mode;
172
uint32_t *output_ids;
173
int output_count = 0;
177
struct drm_mode_modeinfo kmode;
179
ErrorF("drmmode_set_mode_major called\n");
181
saved_mode = crtc->mode;
184
saved_rotation = crtc->rotation;
189
crtc->rotation = rotation;
191
output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
197
for (i = 0; i < xf86_config->num_output; i++) {
198
xf86OutputPtr output = xf86_config->output[i];
199
drmmode_output_private_ptr drmmode_output;
201
if (output->crtc != crtc)
204
drmmode_output = output->driver_private;
205
output_ids[output_count] = drmmode_output->mode_output->connector_id;
209
if (!xf86CrtcRotate(crtc, mode, rotation)) {
213
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
215
if (drmmode_crtc->shadow_id && crtc->rotatedData)
216
fb_id = drmmode_crtc->shadow_id;
218
fb_id = drmmode->fb_id;
219
ErrorF("fb id is %d\n", fb_id);
220
drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
221
fb_id, x, y, output_ids, output_count, &kmode);
227
crtc->rotation = saved_rotation;
228
crtc->mode = saved_mode;
237
drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
243
drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
245
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
246
drmmode_ptr drmmode = drmmode_crtc->drmmode;
248
drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
252
drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
254
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
256
NVPtr pNv = NVPTR(crtc->scrn);
257
uint32_t *dst = NULL;
259
if (drmmode_crtc->index == 1)
260
dst = (uint32_t *) pNv->Cursor2->map;
262
dst = (uint32_t *) pNv->Cursor->map;
264
/* Assume cursor is 64x64 */
265
memcpy(dst, (uint32_t *)image, 64 * 64 * 4);
270
drmmode_hide_cursor (xf86CrtcPtr crtc)
272
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
273
drmmode_ptr drmmode = drmmode_crtc->drmmode;
275
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
280
drmmode_show_cursor (xf86CrtcPtr crtc)
282
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
283
drmmode_ptr drmmode = drmmode_crtc->drmmode;
284
NVPtr pNv = NVPTR(crtc->scrn);
286
drm_handle_t handle = 0;
288
if (drmmode_crtc->index == 1)
289
handle = pNv->Cursor2->map_handle;
291
handle = pNv->Cursor->map_handle;
293
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
296
/* This stuff isn't ready for NOUVEAU_EXA_PIXMAPS, but can be easily ported. */
298
drmmode_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
300
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
301
drmmode_ptr drmmode = drmmode_crtc->drmmode;
302
ScrnInfoPtr pScrn = crtc->scrn;
303
NVPtr pNv = NVPTR(pScrn);
304
int size, pitch, ret;
306
ErrorF("drmmode_shadow_allocate\n");
308
pitch = width * (pScrn->bitsPerPixel/8);
309
size = pitch * height;
311
if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
312
64, size, &drmmode_crtc->shadow)) {
313
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate memory for shadow buffer!\n");
317
if (drmmode_crtc->shadow && nouveau_bo_map(drmmode_crtc->shadow, NOUVEAU_BO_RDWR)) {
318
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
319
"Failed to map shadow buffer.\n");
323
ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth, pScrn->bitsPerPixel, pitch, drmmode_crtc->shadow->map_handle, &drmmode_crtc->shadow_id);
327
/* for easy acces by exa */
328
pNv->shadow[drmmode_crtc->index] = drmmode_crtc->shadow;
330
return drmmode_crtc->shadow->map;
334
drmmode_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
336
ScrnInfoPtr pScrn = crtc->scrn;
338
PixmapPtr rotate_pixmap;
340
ErrorF("drmmode_shadow_create\n");
343
data = crtc->funcs->shadow_allocate (crtc, width, height);
345
pitch = width * (pScrn->bitsPerPixel/8);
347
rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
354
if (rotate_pixmap == NULL) {
355
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
356
"Couldn't allocate shadow pixmap for rotated CRTC\n");
359
return rotate_pixmap;
363
drmmode_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
365
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
366
drmmode_ptr drmmode = drmmode_crtc->drmmode;
367
ScrnInfoPtr pScrn = crtc->scrn;
368
NVPtr pNv = NVPTR(pScrn);
369
ScreenPtr pScreen = pScrn->pScreen;
371
ErrorF("drmmode_shadow_destroy\n");
374
pScreen->DestroyPixmap(rotate_pixmap);
376
if (drmmode_crtc->shadow_id) {
377
drmModeRmFB(drmmode->fd, drmmode_crtc->shadow_id);
378
drmmode_crtc->shadow_id = 0;
381
if (drmmode_crtc->shadow)
382
nouveau_bo_del(&drmmode_crtc->shadow);
384
drmmode_crtc->shadow = NULL;
386
/* for easy acces by exa */
387
pNv->shadow[drmmode_crtc->index] = NULL;
391
drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size)
393
ScrnInfoPtr pScrn = crtc->scrn;
394
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
395
drmmode_ptr drmmode = drmmode_crtc->drmmode;
398
ErrorF("drmmode_gamma_set\n");
400
ret = drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, size, (uint16_t *)red, (uint16_t *)green, (uint16_t *)blue);
402
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmModeCrtcSetGamma failed\n");
405
static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
406
.dpms = drmmode_crtc_dpms,
407
.set_mode_major = drmmode_set_mode_major,
408
.set_cursor_colors = drmmode_set_cursor_colors,
409
.set_cursor_position = drmmode_set_cursor_position,
410
.show_cursor = drmmode_show_cursor,
411
.hide_cursor = drmmode_hide_cursor,
412
.load_cursor_argb = drmmode_load_cursor_argb,
413
.shadow_create = drmmode_shadow_create,
414
.shadow_allocate = drmmode_shadow_allocate,
415
.shadow_destroy = drmmode_shadow_destroy,
416
.gamma_set = drmmode_gamma_set,
417
.destroy = NULL, /* XXX */
422
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
425
drmmode_crtc_private_ptr drmmode_crtc;
427
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
431
drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
432
drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
433
drmmode_crtc->drmmode = drmmode;
434
drmmode_crtc->index = num;
435
crtc->driver_private = drmmode_crtc;
440
static xf86OutputStatus
441
drmmode_output_detect(xf86OutputPtr output)
443
/* go to the hw and retrieve a new output struct */
444
drmmode_output_private_ptr drmmode_output = output->driver_private;
445
drmmode_ptr drmmode = drmmode_output->drmmode;
446
xf86OutputStatus status;
447
drmModeFreeConnector(drmmode_output->mode_output);
449
ErrorF("drmmode_output_detect called\n");
451
drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
453
switch (drmmode_output->mode_output->connection) {
454
case DRM_MODE_CONNECTED:
455
status = XF86OutputStatusConnected;
457
case DRM_MODE_DISCONNECTED:
458
status = XF86OutputStatusDisconnected;
461
case DRM_MODE_UNKNOWNCONNECTION:
462
status = XF86OutputStatusUnknown;
469
drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
474
static DisplayModePtr
475
drmmode_output_get_modes(xf86OutputPtr output)
477
drmmode_output_private_ptr drmmode_output = output->driver_private;
478
drmModeConnectorPtr koutput = drmmode_output->mode_output;
479
drmmode_ptr drmmode = drmmode_output->drmmode;
481
DisplayModePtr Modes = NULL, Mode;
482
drmModePropertyPtr props;
484
ErrorF("drmmode_output_get_modes called\n");
486
/* look for an EDID property */
487
for (i = 0; i < koutput->count_props; i++) {
488
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
489
if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
490
if (!strcmp(props->name, "EDID")) {
491
ErrorF("EDID property found\n");
492
if (drmmode_output->edid_blob)
493
drmModeFreePropertyBlob(drmmode_output->edid_blob);
494
drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
496
if (!drmmode_output->edid_blob)
497
ErrorF("No EDID blob\n");
499
drmModeFreeProperty(props);
503
if (drmmode_output->edid_blob)
504
xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data));
506
xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL));
508
/* modes should already be available */
509
for (i = 0; i < koutput->count_modes; i++) {
510
Mode = xnfalloc(sizeof(DisplayModeRec));
512
drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
513
Modes = xf86ModesAdd(Modes, Mode);
520
drmmode_output_destroy(xf86OutputPtr output)
522
drmmode_output_private_ptr drmmode_output = output->driver_private;
524
if (drmmode_output->edid_blob)
525
drmModeFreePropertyBlob(drmmode_output->edid_blob);
526
drmModeFreeConnector(drmmode_output->mode_output);
527
xfree(drmmode_output);
528
output->driver_private = NULL;
532
drmmode_output_dpms(xf86OutputPtr output, int mode)
534
drmmode_output_private_ptr drmmode_output = output->driver_private;
535
drmModeConnectorPtr koutput = drmmode_output->mode_output;
536
drmmode_ptr drmmode = drmmode_output->drmmode;
537
drmModePropertyPtr props;
540
ErrorF("drmmode_output_dpms called with mode %d\n", mode);
542
for (i = 0; i < koutput->count_props; i++) {
543
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
544
if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
545
if (!strcmp(props->name, "DPMS")) {
546
ErrorF("DPMS property found\n");
547
drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, props->prop_id, mode);
549
drmModeFreeProperty(props);
554
static const xf86OutputFuncsRec drmmode_output_funcs = {
555
.dpms = drmmode_output_dpms,
556
.detect = drmmode_output_detect,
557
.mode_valid = drmmode_output_mode_valid,
558
.get_modes = drmmode_output_get_modes,
559
.destroy = drmmode_output_destroy
562
static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
563
SubPixelHorizontalRGB,
564
SubPixelHorizontalBGR,
574
struct output_name output_names[] = {
582
drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
584
xf86OutputPtr output;
585
drmModeConnectorPtr koutput;
586
drmModeEncoderPtr kencoder;
587
drmmode_output_private_ptr drmmode_output;
590
ErrorF("drmmode_output_init\n");
592
koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
594
ErrorF("No connector\n");
598
kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
600
ErrorF("No encoder\n");
601
drmModeFreeConnector(koutput);
605
snprintf(name, 32, "%s-%d", output_names[koutput->connector_type].name, output_names[koutput->connector_type].count++);
607
output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
609
drmModeFreeEncoder(kencoder);
610
drmModeFreeConnector(koutput);
614
drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
615
if (!drmmode_output) {
616
xf86OutputDestroy(output);
617
drmModeFreeConnector(koutput);
618
drmModeFreeEncoder(kencoder);
622
drmmode_output->output_id = drmmode->mode_res->connectors[num];
623
drmmode_output->mode_output = koutput;
624
drmmode_output->mode_encoder = kencoder;
625
drmmode_output->drmmode = drmmode;
626
output->mm_width = koutput->mmWidth;
627
output->mm_height = koutput->mmHeight;
629
output->subpixel_order = subpixel_conv_table[koutput->subpixel];
630
output->driver_private = drmmode_output;
632
output->possible_crtcs = kencoder->possible_crtcs;
633
output->possible_clones = kencoder->possible_clones;
637
void drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height, int pitch, struct nouveau_bo *bo)
641
ErrorF("drmmode_set_fb is called\n");
643
ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
644
scrn->bitsPerPixel, pitch, bo->map_handle, &drmmode->fb_id);
647
ErrorF("Failed to add fb\n");
650
drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
651
if (!drmmode->mode_fb)
654
ErrorF("Add fb id %d %d %d\n", drmmode->fb_id, width, height);
658
static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height)
664
ErrorF("current width %d height %d\n", drmmode->mode_fb->width, drmmode->mode_fb->height);
666
if (drmmode->mode_fb->width == width && drmmode->mode_fb->height == height)
669
if (!drmmode->create_new_fb)
672
handle = drmmode->create_new_fb(scrn, width, height, &pitch);
676
ErrorF("pitch is %d\n", pitch);
677
ret = drmModeReplaceFB(drmmode->fd, drmmode->fb_id,
679
scrn->depth, scrn->depth, pitch,
685
drmModeFreeFB(drmmode->mode_fb);
686
drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
688
if (!drmmode->mode_fb)
695
Bool drmmode_pre_init(ScrnInfoPtr pScrn, char *busId, drmmode_ptr drmmode, int cpp)
697
xf86CrtcConfigPtr xf86_config = NULL;
701
drm_page_size = getpagesize();
703
/* Create a bus Id */
704
/* Low level DRM open */
705
ret = DRIOpenDRMMaster(pScrn, (drm_page_size > SAREA_MAX) ? drm_page_size : SAREA_MAX, busId, "nouveau");
707
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
708
"[dri] DRIGetVersion failed to open the DRM\n");
712
drmmode->fd = DRIMasterFD(pScrn);
714
xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
715
xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
718
drmmode->mode_res = drmModeGetResources(drmmode->fd);
719
if (!drmmode->mode_res)
722
xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
723
for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
724
drmmode_crtc_init(pScrn, drmmode, i);
726
for (i = 0; i < drmmode->mode_res->count_connectors; i++)
727
drmmode_output_init(pScrn, drmmode, i);
729
if (!xf86InitialConfiguration(pScrn, FALSE))
735
#endif /* XF86DRM_MODE */