require libnouveau_drm 0.0.109.1
[nouveau] / src / drmmode_display.c
1 /*
2  * Copyright © 2007 Red Hat, Inc.
3  * Copyright © 2008 Maarten Maathuis
4  *
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:
11  *
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
14  * Software.
15  *
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
22  * SOFTWARE.
23  *
24  * Authors:
25  *    Dave Airlie <airlied@redhat.com>
26  *
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #ifdef XF86DRM_MODE
34
35 #include "drmmode_display.h"
36 #include "sarea.h"
37 #include "X11/Xatom.h"
38
39 static uint64_t
40 nouveau_bo_get_drm_map(struct nouveau_bo *bo)
41 {
42         return 0xdeadbeef;
43 }
44
45 #if 0
46 /* not using for the moment */
47 uint32_t drmmode_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch)
48 {
49         NVPtr pNv = NVPTR(pScrn);
50         int ret = 0;
51
52         /* temporary hack, allow old framebuffers to continue to exist and idle. */
53         if (pNv->FB_old) {
54                 nouveau_bo_ref(NULL, pNv->FB_old);
55                 pNv->FB_old = NULL;
56         }
57
58         pNv->FB_old = pNv->FB;
59         pNv->FB = NULL;
60
61         *pitch = NOUVEAU_ALIGN(*pitch, 64) * (pScrn->bitsPerPixel >> 3);
62
63         ret = nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
64                         0, *pitch * NOUVEAU_ALIGN(height, 64), &pNv->FB)
65
66         if (ret)
67                 return 0;
68
69         ret = nouveau_bo_map(pNv->FB, NOUVEAU_BO_RDWR);
70
71         if (ret)
72                 return 0;
73
74         return pNv->FB.handle;
75 }
76 #endif
77
78 #if 0
79 static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height);
80 #endif
81
82 static Bool
83 drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
84 {
85         //xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
86         //drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private;
87         //drmmode_ptr drmmode = drmmode_crtc->drmmode;
88         //Bool ret;
89
90         ErrorF("resize called %d %d\n", width, height);
91         //ret = drmmode_resize_fb(scrn, drmmode, width, height);
92         scrn->virtualX = width;
93         scrn->virtualY = height;
94
95         return TRUE; //ret;
96 }
97
98 static void
99 drmmode_ConvertFromKMode(ScrnInfoPtr    scrn,
100                         struct drm_mode_modeinfo *kmode,
101                         DisplayModePtr  mode)
102 {
103         memset(mode, 0, sizeof(DisplayModeRec));
104         mode->status = MODE_OK;
105
106         mode->Clock = kmode->clock;
107
108         mode->HDisplay = kmode->hdisplay;
109         mode->HSyncStart = kmode->hsync_start;
110         mode->HSyncEnd = kmode->hsync_end;
111         mode->HTotal = kmode->htotal;
112         mode->HSkew = kmode->hskew;
113
114         mode->VDisplay = kmode->vdisplay;
115         mode->VSyncStart = kmode->vsync_start;
116         mode->VSyncEnd = kmode->vsync_end;
117         mode->VTotal = kmode->vtotal;
118         mode->VScan = kmode->vscan;
119
120         mode->Flags = kmode->flags; //& FLAG_BITS;
121         mode->name = strdup(kmode->name);
122
123         if (kmode->type & DRM_MODE_TYPE_DRIVER)
124                 mode->type = M_T_DRIVER;
125         if (kmode->type & DRM_MODE_TYPE_PREFERRED)
126                 mode->type |= M_T_PREFERRED;
127         xf86SetModeCrtc (mode, scrn->adjustFlags);
128 }
129
130 static void
131 drmmode_ConvertToKMode(ScrnInfoPtr      scrn,
132                 struct drm_mode_modeinfo *kmode,
133                 DisplayModePtr  mode)
134 {
135         memset(kmode, 0, sizeof(*kmode));
136
137         kmode->clock = mode->Clock;
138         kmode->hdisplay = mode->HDisplay;
139         kmode->hsync_start = mode->HSyncStart;
140         kmode->hsync_end = mode->HSyncEnd;
141         kmode->htotal = mode->HTotal;
142         kmode->hskew = mode->HSkew;
143
144         kmode->vdisplay = mode->VDisplay;
145         kmode->vsync_start = mode->VSyncStart;
146         kmode->vsync_end = mode->VSyncEnd;
147         kmode->vtotal = mode->VTotal;
148         kmode->vscan = mode->VScan;
149
150         kmode->flags = mode->Flags; //& FLAG_BITS;
151         if (mode->name)
152                 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
153         kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
154
155 }
156
157 static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
158         drmmode_xf86crtc_resize
159 };
160
161 static void
162 drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
163 {
164         return;
165 }
166
167 static Bool
168 drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
169                         Rotation rotation, int x, int y)
170 {
171         xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
172         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
173         drmmode_ptr drmmode = drmmode_crtc->drmmode;
174         int saved_x, saved_y;
175         Rotation saved_rotation;
176         DisplayModeRec saved_mode;
177         uint32_t *output_ids;
178         int output_count = 0;
179         int ret = TRUE;
180         int i;
181         int fb_id;
182         struct drm_mode_modeinfo kmode;
183
184         ErrorF("drmmode_set_mode_major called\n");
185
186         saved_mode = crtc->mode;
187         saved_x = crtc->x;
188         saved_y = crtc->y;
189         saved_rotation = crtc->rotation;
190
191         crtc->mode = *mode;
192         crtc->x = x;
193         crtc->y = y;
194         crtc->rotation = rotation;
195
196         output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output);
197         if (!output_ids) {
198                 ret = FALSE;
199                 goto done;
200         }
201
202         for (i = 0; i < xf86_config->num_output; i++) {
203                 xf86OutputPtr output = xf86_config->output[i];
204                 drmmode_output_private_ptr drmmode_output;
205
206                 if (output->crtc != crtc)
207                         continue;
208
209                 drmmode_output = output->driver_private;
210                 output_ids[output_count] = drmmode_output->mode_output->connector_id;
211                 output_count++;
212         }
213
214         if (!xf86CrtcRotate(crtc, mode, rotation)) {
215                 goto done;
216         }
217
218         drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
219
220         if (drmmode_crtc->shadow_id && crtc->rotatedData)
221                 fb_id = drmmode_crtc->shadow_id;
222         else
223                 fb_id = drmmode->fb_id;
224         ErrorF("fb id is %d\n", fb_id);
225         drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
226                         fb_id, x, y, output_ids, output_count, &kmode);
227
228 done:
229         if (!ret) {
230                 crtc->x = saved_x;
231                 crtc->y = saved_y;
232                 crtc->rotation = saved_rotation;
233                 crtc->mode = saved_mode;
234         }
235
236         if (output_ids)
237                 xfree(output_ids);
238         return ret;
239 }
240
241 static void
242 drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
243 {
244   
245 }
246
247 static void
248 drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
249 {
250         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
251         drmmode_ptr drmmode = drmmode_crtc->drmmode;
252
253         drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
254 }
255
256 static void
257 drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
258 {
259         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
260
261         NVPtr pNv = NVPTR(crtc->scrn);
262         uint32_t *dst = NULL;
263
264         if (drmmode_crtc->index == 1)
265                 dst = (uint32_t *) pNv->Cursor2->map;
266         else
267                 dst = (uint32_t *) pNv->Cursor->map;
268
269         /* Assume cursor is 64x64 */
270         memcpy(dst, (uint32_t *)image, 64 * 64 * 4);
271 }
272
273
274 static void
275 drmmode_hide_cursor (xf86CrtcPtr crtc)
276 {
277         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
278         drmmode_ptr drmmode = drmmode_crtc->drmmode;
279
280         drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
281
282 }
283
284 static void
285 drmmode_show_cursor (xf86CrtcPtr crtc)
286 {
287         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
288         drmmode_ptr drmmode = drmmode_crtc->drmmode;
289         NVPtr pNv = NVPTR(crtc->scrn);
290
291         drm_handle_t handle = 0;
292
293         if (drmmode_crtc->index == 1)
294                 handle = nouveau_bo_get_drm_map(pNv->Cursor2);
295         else
296                 handle = nouveau_bo_get_drm_map(pNv->Cursor);
297
298         drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
299 }
300
301 /* This stuff isn't ready for NOUVEAU_EXA_PIXMAPS, but can be easily ported. */
302 static void *
303 drmmode_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
304 {
305         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
306         drmmode_ptr drmmode = drmmode_crtc->drmmode;
307         ScrnInfoPtr pScrn = crtc->scrn;
308         NVPtr pNv = NVPTR(pScrn);
309         int size, pitch, ret;
310
311         ErrorF("drmmode_shadow_allocate\n");
312
313         pitch = width * (pScrn->bitsPerPixel/8);
314         size = pitch * height;
315
316         if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN,
317                         64, size, &drmmode_crtc->shadow)) {
318                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate memory for shadow buffer!\n");
319                 return NULL;
320         }
321
322         if (drmmode_crtc->shadow && nouveau_bo_map(drmmode_crtc->shadow, NOUVEAU_BO_RDWR)) {
323                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
324                                 "Failed to map shadow buffer.\n");
325                 return NULL;
326         }
327
328         ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth, pScrn->bitsPerPixel, pitch, nouveau_bo_get_drm_map(drmmode_crtc->shadow), &drmmode_crtc->shadow_id);
329         if (ret)
330                 return NULL;
331
332         /* for easy acces by exa */
333         pNv->shadow[drmmode_crtc->index] = drmmode_crtc->shadow;
334
335         return drmmode_crtc->shadow->map;
336 }
337
338 static PixmapPtr
339 drmmode_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
340 {
341         ScrnInfoPtr pScrn = crtc->scrn;
342         uint32_t pitch;
343         PixmapPtr rotate_pixmap;
344
345         ErrorF("drmmode_shadow_create\n");
346
347         if (!data)
348                 data = crtc->funcs->shadow_allocate (crtc, width, height);
349
350         pitch = width * (pScrn->bitsPerPixel/8);
351
352         rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
353                                                 width, height,
354                                                 pScrn->depth,
355                                                 pScrn->bitsPerPixel,
356                                                 pitch,
357                                                 data);
358
359         if (rotate_pixmap == NULL) {
360                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
361                         "Couldn't allocate shadow pixmap for rotated CRTC\n");
362         }
363
364         return rotate_pixmap;
365 }
366
367 static void
368 drmmode_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
369 {
370         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
371         drmmode_ptr drmmode = drmmode_crtc->drmmode;
372         ScrnInfoPtr pScrn = crtc->scrn;
373         NVPtr pNv = NVPTR(pScrn);
374         ScreenPtr pScreen = pScrn->pScreen;
375
376         ErrorF("drmmode_shadow_destroy\n");
377
378         if (rotate_pixmap)
379                 pScreen->DestroyPixmap(rotate_pixmap);
380
381         if (drmmode_crtc->shadow_id) {
382                 drmModeRmFB(drmmode->fd, drmmode_crtc->shadow_id);
383                 drmmode_crtc->shadow_id = 0;
384         }
385
386         if (drmmode_crtc->shadow)
387                 nouveau_bo_ref(NULL, &drmmode_crtc->shadow);
388
389         drmmode_crtc->shadow = NULL;
390
391         /* for easy acces by exa */
392         pNv->shadow[drmmode_crtc->index] = NULL;
393 }
394
395 static void
396 drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size)
397 {
398         ScrnInfoPtr pScrn = crtc->scrn;
399         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
400         drmmode_ptr drmmode = drmmode_crtc->drmmode;
401         int ret;
402
403         ErrorF("drmmode_gamma_set\n");
404
405         ret = drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, size, (uint16_t *)red, (uint16_t *)green, (uint16_t *)blue);
406         if (ret)
407                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmModeCrtcSetGamma failed\n");
408 }
409
410 static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
411         .dpms = drmmode_crtc_dpms,
412         .set_mode_major = drmmode_set_mode_major,
413         .set_cursor_colors = drmmode_set_cursor_colors,
414         .set_cursor_position = drmmode_set_cursor_position,
415         .show_cursor = drmmode_show_cursor,
416         .hide_cursor = drmmode_hide_cursor,
417         .load_cursor_argb = drmmode_load_cursor_argb,
418         .shadow_create = drmmode_shadow_create,
419         .shadow_allocate = drmmode_shadow_allocate,
420         .shadow_destroy = drmmode_shadow_destroy,
421         .gamma_set = drmmode_gamma_set,
422         .destroy = NULL, /* XXX */
423 };
424
425
426 static void
427 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
428 {
429         xf86CrtcPtr crtc;
430         drmmode_crtc_private_ptr drmmode_crtc;
431
432         crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
433         if (crtc == NULL)
434                 return;
435
436         drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
437         drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
438         drmmode_crtc->drmmode = drmmode;
439         drmmode_crtc->index = num;
440         crtc->driver_private = drmmode_crtc;
441
442         return;
443 }
444
445 static xf86OutputStatus
446 drmmode_output_detect(xf86OutputPtr output)
447 {
448         /* go to the hw and retrieve a new output struct */
449         drmmode_output_private_ptr drmmode_output = output->driver_private;
450         drmmode_ptr drmmode = drmmode_output->drmmode;
451         xf86OutputStatus status;
452         drmModeFreeConnector(drmmode_output->mode_output);
453
454         ErrorF("drmmode_output_detect called\n");
455
456         drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
457
458         switch (drmmode_output->mode_output->connection) {
459         case DRM_MODE_CONNECTED:
460                 status = XF86OutputStatusConnected;
461                 break;
462         case DRM_MODE_DISCONNECTED:
463                 status = XF86OutputStatusDisconnected;
464                 break;
465         default:
466         case DRM_MODE_UNKNOWNCONNECTION:
467                 status = XF86OutputStatusUnknown;
468                 break;
469         }
470         return status;
471 }
472
473 static Bool
474 drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
475 {
476         return MODE_OK;
477 }
478
479 static DisplayModePtr
480 drmmode_output_get_modes(xf86OutputPtr output)
481 {
482         drmmode_output_private_ptr drmmode_output = output->driver_private;
483         drmModeConnectorPtr koutput = drmmode_output->mode_output;
484         drmmode_ptr drmmode = drmmode_output->drmmode;
485         int i;
486         DisplayModePtr Modes = NULL, Mode;
487         drmModePropertyPtr props;
488
489         ErrorF("drmmode_output_get_modes called\n");
490
491         /* look for an EDID property */
492         for (i = 0; i < koutput->count_props; i++) {
493                 props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
494                 if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
495                         if (!strcmp(props->name, "EDID")) {
496                                 ErrorF("EDID property found\n");
497                                 if (drmmode_output->edid_blob)
498                                         drmModeFreePropertyBlob(drmmode_output->edid_blob);
499                                 drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
500
501                                 if (!drmmode_output->edid_blob)
502                                         ErrorF("No EDID blob\n");
503                         }
504                         drmModeFreeProperty(props);
505                 }
506         }
507
508         if (drmmode_output->edid_blob)
509                 xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data));
510         else
511                 xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL));
512
513         /* modes should already be available */
514         for (i = 0; i < koutput->count_modes; i++) {
515                 Mode = xnfalloc(sizeof(DisplayModeRec));
516
517                 drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
518                 Modes = xf86ModesAdd(Modes, Mode);
519
520         }
521         return Modes;
522 }
523
524 static void
525 drmmode_output_destroy(xf86OutputPtr output)
526 {
527         drmmode_output_private_ptr drmmode_output = output->driver_private;
528
529         if (drmmode_output->edid_blob)
530                 drmModeFreePropertyBlob(drmmode_output->edid_blob);
531         drmModeFreeConnector(drmmode_output->mode_output);
532         xfree(drmmode_output);
533         output->driver_private = NULL;
534 }
535
536 static void
537 drmmode_output_dpms(xf86OutputPtr output, int mode)
538 {
539         drmmode_output_private_ptr drmmode_output = output->driver_private;
540         drmModeConnectorPtr koutput = drmmode_output->mode_output;
541         drmmode_ptr drmmode = drmmode_output->drmmode;
542         drmModePropertyPtr props;
543         int i;
544
545         ErrorF("drmmode_output_dpms called with mode %d\n", mode);
546
547         for (i = 0; i < koutput->count_props; i++) {
548                 props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
549                 if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
550                         if (!strcmp(props->name, "DPMS")) {
551                                 ErrorF("DPMS property found\n");
552                                 drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, props->prop_id, mode); 
553                         }
554                         drmModeFreeProperty(props);
555                 }
556         }
557 }
558
559 /*
560  * Output properties.
561  */
562
563 /*
564  * Several scaling modes exist, let the user choose.
565  */
566 #define SCALING_MODE_NAME "SCALING_MODE"
567 static const struct {
568         char *name;
569         int mode;
570 } scaling_mode[] = {
571         { "non-gpu", DRM_MODE_SCALE_NON_GPU },
572         { "fullscreen", DRM_MODE_SCALE_FULLSCREEN },
573         { "aspect", DRM_MODE_SCALE_ASPECT },
574         { "noscale", DRM_MODE_SCALE_NO_SCALE },
575         { NULL, 0xFFFF /* invalid */ }
576 };
577 static Atom scaling_mode_atom;
578
579 #define DITHERING_MODE_NAME "DITHERING"
580 static const struct {
581         char *name;
582         int mode;
583 } dithering_mode[] = {
584         { "off", DRM_MODE_DITHERING_OFF },
585         { "on", DRM_MODE_DITHERING_ON },
586         { NULL, 0xFFFF /* invalid */ }
587 };
588 static Atom dithering_atom;
589
590 int
591 drmmode_scaling_mode_lookup(char *name, int size)
592 {
593         int i;
594
595         /* for when name is zero terminated */
596         if (size < 0)
597                 size = strlen(name);
598
599         for (i = 0; scaling_mode[i].name; i++)
600                 /* We're getting non-terminated strings */
601                 if (strlen(scaling_mode[i].name) >= size &&
602                                 !strncasecmp(name, scaling_mode[i].name, size))
603                         break;
604
605         return scaling_mode[i].mode;
606 }
607
608 int
609 drmmode_dithering_lookup(char *name, int size)
610 {
611         int i;
612
613         /* for when name is zero terminated */
614         if (size < 0)
615                 size = strlen(name);
616
617         for (i = 0; dithering_mode[i].name; i++)
618                 /* We're getting non-terminated strings */
619                 if (strlen(dithering_mode[i].name) >= size &&
620                                 !strncasecmp(name, dithering_mode[i].name, size))
621                         break;
622
623         return dithering_mode[i].mode;
624 }
625
626
627 void
628 drmmode_output_create_resources(xf86OutputPtr output)
629 {
630         ScrnInfoPtr pScrn = output->scrn;
631         int error;
632
633         /*
634          * Setup scaling mode property.
635          */
636         scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
637
638         error = RRConfigureOutputProperty(output->randr_output,
639                                         scaling_mode_atom, FALSE, FALSE, FALSE,
640                                         0, NULL);
641
642         if (error != 0) {
643                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
644                         "RRConfigureOutputProperty error, %d\n", error);
645         }
646
647         /* property has unknown initial value (for the moment) */
648
649         /*
650          * Setup dithering property.
651          */
652         dithering_atom = MakeAtom(DITHERING_MODE_NAME, sizeof(DITHERING_MODE_NAME) - 1, TRUE);
653
654         error = RRConfigureOutputProperty(output->randr_output,
655                                         dithering_atom, FALSE, FALSE, FALSE,
656                                         0, NULL);
657
658         if (error != 0) {
659                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
660                         "RRConfigureOutputProperty error, %d\n", error);
661         }
662
663         /* property has unknown initial value (for the moment) */
664 }
665
666 Bool
667 drmmode_output_set_property(xf86OutputPtr output, Atom property,
668                                 RRPropertyValuePtr value)
669 {
670         drmmode_output_private_ptr drmmode_output = output->driver_private;
671         drmModeConnectorPtr koutput = drmmode_output->mode_output;
672         drmmode_ptr drmmode = drmmode_output->drmmode;
673         drmModePropertyPtr props;
674         int i, mode, rval = 0;
675
676         if (property == scaling_mode_atom) {
677                 char *name = NULL;
678
679                 if (value->type != XA_STRING || value->format != 8)
680                         return FALSE;
681
682                 name = (char *) value->data;
683
684                 /* Match a string to a scaling mode */
685                 mode = drmmode_scaling_mode_lookup(name, value->size);
686                 if (mode == 0xFFFF)
687                         return FALSE;
688
689                 for (i = 0; i < koutput->count_props; i++) {
690                         props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
691                         if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
692                                 if (!strcmp(props->name, "scaling mode")) {
693                                         ErrorF("scaling mode property found\n");
694                                         rval = drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, props->prop_id, mode); 
695                                 }
696                                 drmModeFreeProperty(props);
697                         }
698                 }
699
700                 if (rval)
701                         return FALSE;
702
703                 return TRUE;
704         } else if (property == dithering_atom) {
705                 char *name = NULL;
706
707                 if (value->type != XA_STRING || value->format != 8)
708                         return FALSE;
709
710                 name = (char *) value->data;
711
712                 /* Match a string to a scaling mode */
713                 mode = drmmode_dithering_lookup(name, value->size);
714                 if (mode == 0xFFFF)
715                         return FALSE;
716
717                 for (i = 0; i < koutput->count_props; i++) {
718                         props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
719                         if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
720                                 if (!strcmp(props->name, "dithering")) {
721                                         ErrorF("dithering property found\n");
722                                         rval = drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id, props->prop_id, mode); 
723                                 }
724                                 drmModeFreeProperty(props);
725                         }
726                 }
727
728                 if (rval)
729                         return FALSE;
730
731                 return TRUE;
732         }
733
734         return FALSE;
735 }
736
737 static const xf86OutputFuncsRec drmmode_output_funcs = {
738         .dpms = drmmode_output_dpms,
739         .detect = drmmode_output_detect,
740         .mode_valid = drmmode_output_mode_valid,
741         .get_modes = drmmode_output_get_modes,
742         .destroy = drmmode_output_destroy,
743         .create_resources = drmmode_output_create_resources,
744         .set_property = drmmode_output_set_property,
745 };
746
747 static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
748                                       SubPixelHorizontalRGB,
749                                       SubPixelHorizontalBGR,
750                                       SubPixelVerticalRGB,
751                                       SubPixelVerticalBGR,
752                                       SubPixelNone };
753
754 struct output_name {
755         const char *name;
756         int count;
757 };
758
759 struct output_name output_names[] = {
760         { "None", 0 },
761         { "VGA", 0 },
762         { "DVI-I", 0 },
763         { "DVI-D", 0 },
764 };
765
766 static void
767 drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
768 {
769         xf86OutputPtr output;
770         drmModeConnectorPtr koutput;
771         drmModeEncoderPtr kencoder;
772         drmmode_output_private_ptr drmmode_output;
773         char name[32];
774
775         ErrorF("drmmode_output_init\n");
776
777         koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
778         if (!koutput) {
779                 ErrorF("No connector\n");
780                 return;
781         }
782
783         kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
784         if (!kencoder) {
785                 ErrorF("No encoder\n");
786                 drmModeFreeConnector(koutput);
787                 return;
788         }
789
790         snprintf(name, 32, "%s-%d", output_names[koutput->connector_type].name, output_names[koutput->connector_type].count++);
791
792         output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
793         if (!output) {
794                 drmModeFreeEncoder(kencoder);
795                 drmModeFreeConnector(koutput);
796                 return;
797         }
798
799         drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
800         if (!drmmode_output) {
801                 xf86OutputDestroy(output);
802                 drmModeFreeConnector(koutput);
803                 drmModeFreeEncoder(kencoder);
804                 return;
805         }
806
807         drmmode_output->output_id = drmmode->mode_res->connectors[num];
808         drmmode_output->mode_output = koutput;
809         drmmode_output->mode_encoder = kencoder;
810         drmmode_output->drmmode = drmmode;
811         output->mm_width = koutput->mmWidth;
812         output->mm_height = koutput->mmHeight;
813
814         output->subpixel_order = subpixel_conv_table[koutput->subpixel];
815         output->driver_private = drmmode_output;
816
817         output->possible_crtcs = kencoder->possible_crtcs;
818         output->possible_clones = kencoder->possible_clones;
819
820         return;
821 }
822
823 void drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height, int pitch, struct nouveau_bo *bo)
824 {
825         int ret;
826
827         ErrorF("drmmode_set_fb is called\n");
828
829         ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
830                            scrn->bitsPerPixel, pitch, nouveau_bo_get_drm_map(bo), &drmmode->fb_id);
831
832         if (ret) {
833                 ErrorF("Failed to add fb\n");
834         }
835
836         drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
837         if (!drmmode->mode_fb)
838                 return;
839
840         ErrorF("Add fb id %d %d %d\n", drmmode->fb_id, width, height);
841 }
842
843 #if 0
844 static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height)
845 {
846         uint32_t handle;
847         int pitch;
848         int ret;
849
850         ErrorF("current width %d height %d\n", drmmode->mode_fb->width, drmmode->mode_fb->height);
851
852         if (drmmode->mode_fb->width == width && drmmode->mode_fb->height == height)
853                 return TRUE;
854
855         if (!drmmode->create_new_fb)
856                 return FALSE;
857
858         handle = drmmode->create_new_fb(scrn, width, height, &pitch);
859         if (handle == 0)
860                 return FALSE;
861
862         ErrorF("pitch is %d\n", pitch);
863         ret = drmModeReplaceFB(drmmode->fd, drmmode->fb_id, 
864                                width, height,
865                                scrn->depth, scrn->depth, pitch,
866                                handle);
867
868         if (ret)
869                 return FALSE;
870
871         drmModeFreeFB(drmmode->mode_fb);
872         drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id);
873
874         if (!drmmode->mode_fb)
875                 return FALSE;
876
877         return TRUE;
878 }
879 #endif
880
881 Bool drmmode_pre_init(ScrnInfoPtr pScrn, char *busId, drmmode_ptr drmmode, int cpp)
882 {
883         xf86CrtcConfigPtr xf86_config = NULL;
884         int i, ret;
885
886         int drm_page_size;
887         drm_page_size = getpagesize();
888
889         /* Create a bus Id */
890         /* Low level DRM open */
891         ret = DRIOpenDRMMaster(pScrn, (drm_page_size > SAREA_MAX) ? drm_page_size : SAREA_MAX, busId, "nouveau");
892         if (!ret) {
893                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
894                         "[dri] DRIGetVersion failed to open the DRM\n");
895                 return FALSE;
896         }
897
898         drmmode->fd = DRIMasterFD(pScrn);
899
900         xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
901         xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
902
903         drmmode->cpp = cpp;
904         drmmode->mode_res = drmModeGetResources(drmmode->fd);
905         if (!drmmode->mode_res)
906                 return FALSE;
907
908         xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
909         for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
910                 drmmode_crtc_init(pScrn, drmmode, i);
911
912         for (i = 0; i < drmmode->mode_res->count_connectors; i++)
913                 drmmode_output_init(pScrn, drmmode, i);
914
915         if (!xf86InitialConfiguration(pScrn, FALSE))
916                 return FALSE;
917
918         return TRUE;
919 }
920
921 #endif /* XF86DRM_MODE */