drmmode_display.c revision 921a55d8
1/*
2 * Copyright © 2007 Red Hat, Inc.
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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Dave Airlie <airlied@redhat.com>
25 *
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <errno.h>
33#ifdef XF86DRM_MODE
34#include <sys/ioctl.h>
35#include "micmap.h"
36#include "xf86cmap.h"
37#include "radeon.h"
38#include "radeon_reg.h"
39#include "radeon_drm.h"
40#include "sarea.h"
41
42#include "drmmode_display.h"
43
44/* DPMS */
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
52static PixmapPtr drmmode_create_bo_pixmap(ScreenPtr pScreen,
53					  int width, int height,
54					  int depth, int bpp,
55					  int pitch, struct radeon_bo *bo)
56{
57	PixmapPtr pixmap;
58
59	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
60	if (!pixmap)
61		return NULL;
62
63	if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height,
64					    depth, bpp, pitch, NULL)) {
65		return NULL;
66	}
67
68	exaMoveInPixmap(pixmap);
69	radeon_set_pixmap_bo(pixmap, bo);
70
71	return pixmap;
72}
73
74static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap)
75{
76	ScreenPtr pScreen = pixmap->drawable.pScreen;
77
78	(*pScreen->DestroyPixmap)(pixmap);
79}
80
81static void
82drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
83		     drmModeModeInfo *kmode,
84		     DisplayModePtr	mode)
85{
86	memset(mode, 0, sizeof(DisplayModeRec));
87	mode->status = MODE_OK;
88
89	mode->Clock = kmode->clock;
90
91	mode->HDisplay = kmode->hdisplay;
92	mode->HSyncStart = kmode->hsync_start;
93	mode->HSyncEnd = kmode->hsync_end;
94	mode->HTotal = kmode->htotal;
95	mode->HSkew = kmode->hskew;
96
97	mode->VDisplay = kmode->vdisplay;
98	mode->VSyncStart = kmode->vsync_start;
99	mode->VSyncEnd = kmode->vsync_end;
100	mode->VTotal = kmode->vtotal;
101	mode->VScan = kmode->vscan;
102
103	mode->Flags = kmode->flags; //& FLAG_BITS;
104	mode->name = strdup(kmode->name);
105
106	if (kmode->type & DRM_MODE_TYPE_DRIVER)
107		mode->type = M_T_DRIVER;
108	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
109		mode->type |= M_T_PREFERRED;
110	xf86SetModeCrtc (mode, scrn->adjustFlags);
111}
112
113static void
114drmmode_ConvertToKMode(ScrnInfoPtr	scrn,
115		     drmModeModeInfo *kmode,
116		     DisplayModePtr	mode)
117{
118	memset(kmode, 0, sizeof(*kmode));
119
120	kmode->clock = mode->Clock;
121	kmode->hdisplay = mode->HDisplay;
122	kmode->hsync_start = mode->HSyncStart;
123	kmode->hsync_end = mode->HSyncEnd;
124	kmode->htotal = mode->HTotal;
125	kmode->hskew = mode->HSkew;
126
127	kmode->vdisplay = mode->VDisplay;
128	kmode->vsync_start = mode->VSyncStart;
129	kmode->vsync_end = mode->VSyncEnd;
130	kmode->vtotal = mode->VTotal;
131	kmode->vscan = mode->VScan;
132
133	kmode->flags = mode->Flags; //& FLAG_BITS;
134	if (mode->name)
135		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
136	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
137
138}
139
140static void
141drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
142{
143#if 0
144	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
145//	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
146//	drmmode_ptr drmmode = drmmode_crtc->drmmode;
147
148	/* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
149	if (mode == DPMSModeOff) {
150//		drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
151//			       0, 0, 0, NULL, 0, NULL);
152	}
153#endif
154}
155
156static PixmapPtr
157create_pixmap_for_fbcon(drmmode_ptr drmmode,
158			ScrnInfoPtr pScrn, int crtc_id)
159{
160	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
161	drmmode_crtc_private_ptr drmmode_crtc;
162	ScreenPtr pScreen = pScrn->pScreen;
163	PixmapPtr pixmap;
164	struct radeon_bo *bo;
165	drmModeFBPtr fbcon;
166	struct drm_gem_flink flink;
167
168	drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private;
169
170	fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
171	if (fbcon == NULL)
172		return NULL;
173
174	flink.handle = fbcon->handle;
175	if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
176		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
177			   "Couldn't flink fbcon handle\n");
178		return NULL;
179	}
180
181	bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
182	if (bo == NULL) {
183		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
184			   "Couldn't allocate bo for fbcon handle\n");
185		return NULL;
186	}
187
188	pixmap = drmmode_create_bo_pixmap(pScreen, fbcon->width, fbcon->height,
189					  fbcon->depth, fbcon->bpp,
190					  fbcon->pitch, bo);
191	if (!pixmap)
192		return NULL;
193
194	radeon_bo_unref(bo);
195	drmModeFreeFB(fbcon);
196	return pixmap;
197}
198
199void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
200{
201	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
202	RADEONInfoPtr info = RADEONPTR(pScrn);
203	PixmapPtr src, dst;
204	ScreenPtr pScreen = pScrn->pScreen;
205	int crtc_id = 0;
206	int i;
207	int pitch;
208	uint32_t tiling_flags = 0;
209	Bool ret;
210
211	if (info->accelOn == FALSE)
212		return;
213
214	for (i = 0; i < xf86_config->num_crtc; i++) {
215		xf86CrtcPtr crtc = xf86_config->crtc[i];
216		drmmode_crtc_private_ptr drmmode_crtc;
217
218		drmmode_crtc = crtc->driver_private;
219		if (drmmode_crtc->mode_crtc->buffer_id)
220			crtc_id = i;
221	}
222
223	src = create_pixmap_for_fbcon(drmmode, pScrn, crtc_id);
224	if (!src)
225		return;
226
227	if (info->allowColorTiling) {
228		if (info->ChipFamily >= CHIP_FAMILY_R600)
229			tiling_flags |= RADEON_TILING_MICRO;
230		else
231			tiling_flags |= RADEON_TILING_MACRO;
232	}
233
234	pitch = RADEON_ALIGN(pScrn->displayWidth,
235			     drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
236		info->CurrentLayout.pixel_bytes;
237
238	dst = drmmode_create_bo_pixmap(pScreen, pScrn->virtualX,
239				       pScrn->virtualY, pScrn->depth,
240				       pScrn->bitsPerPixel, pitch,
241				       info->front_bo);
242	if (!dst)
243		goto out_free_src;
244
245	ret = info->accel_state->exa->PrepareCopy (src, dst,
246						   -1, -1, GXcopy, FB_ALLONES);
247	if (!ret)
248	  goto out_free_src;
249	info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
250				      pScrn->virtualX, pScrn->virtualY);
251	info->accel_state->exa->DoneCopy (dst);
252	radeon_cs_flush_indirect(pScrn);
253
254	drmmode_destroy_bo_pixmap(dst);
255 out_free_src:
256	drmmode_destroy_bo_pixmap(src);
257
258}
259
260static Bool
261drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
262		     Rotation rotation, int x, int y)
263{
264	ScrnInfoPtr pScrn = crtc->scrn;
265	RADEONInfoPtr info = RADEONPTR(pScrn);
266	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
267	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
268	drmmode_ptr drmmode = drmmode_crtc->drmmode;
269	int saved_x, saved_y;
270	Rotation saved_rotation;
271	DisplayModeRec saved_mode;
272	uint32_t *output_ids;
273	int output_count = 0;
274	Bool ret = TRUE;
275	int i;
276	int fb_id;
277	drmModeModeInfo kmode;
278	int pitch;
279	uint32_t tiling_flags = 0;
280	int height;
281
282	if (info->allowColorTiling) {
283		if (info->ChipFamily >= CHIP_FAMILY_R600)
284			tiling_flags |= RADEON_TILING_MICRO;
285		else
286			tiling_flags |= RADEON_TILING_MACRO;
287	}
288
289	pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
290		info->CurrentLayout.pixel_bytes;
291	height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags));
292
293	if (drmmode->fb_id == 0) {
294		ret = drmModeAddFB(drmmode->fd,
295				   pScrn->virtualX, height,
296                                   pScrn->depth, pScrn->bitsPerPixel,
297				   pitch,
298				   info->front_bo->handle,
299                                   &drmmode->fb_id);
300                if (ret < 0) {
301                        ErrorF("failed to add fb\n");
302                        return FALSE;
303                }
304        }
305
306	saved_mode = crtc->mode;
307	saved_x = crtc->x;
308	saved_y = crtc->y;
309	saved_rotation = crtc->rotation;
310
311	if (mode) {
312		crtc->mode = *mode;
313		crtc->x = x;
314		crtc->y = y;
315		crtc->rotation = rotation;
316#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0)
317		crtc->transformPresent = FALSE;
318#endif
319	}
320
321	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
322	if (!output_ids) {
323		ret = FALSE;
324		goto done;
325	}
326
327	if (mode) {
328		for (i = 0; i < xf86_config->num_output; i++) {
329			xf86OutputPtr output = xf86_config->output[i];
330			drmmode_output_private_ptr drmmode_output;
331
332			if (output->crtc != crtc)
333				continue;
334
335			drmmode_output = output->driver_private;
336			output_ids[output_count] = drmmode_output->mode_output->connector_id;
337			output_count++;
338		}
339
340		if (!xf86CrtcRotate(crtc)) {
341			goto done;
342		}
343#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
344		crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
345				       crtc->gamma_blue, crtc->gamma_size);
346#endif
347
348		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
349
350		fb_id = drmmode->fb_id;
351		if (drmmode_crtc->rotate_fb_id) {
352			fb_id = drmmode_crtc->rotate_fb_id;
353			x = y = 0;
354		}
355		ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
356				     fb_id, x, y, output_ids, output_count, &kmode);
357		if (ret)
358			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
359				   "failed to set mode: %s", strerror(-ret));
360		else
361			ret = TRUE;
362
363		if (crtc->scrn->pScreen)
364			xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
365		/* go through all the outputs and force DPMS them back on? */
366		for (i = 0; i < xf86_config->num_output; i++) {
367			xf86OutputPtr output = xf86_config->output[i];
368
369			if (output->crtc != crtc)
370				continue;
371
372			output->funcs->dpms(output, DPMSModeOn);
373		}
374	}
375
376	if (pScrn->pScreen &&
377		!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
378		xf86_reload_cursors(pScrn->pScreen);
379
380done:
381	if (!ret) {
382		crtc->x = saved_x;
383		crtc->y = saved_y;
384		crtc->rotation = saved_rotation;
385		crtc->mode = saved_mode;
386	}
387#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
388	else
389		crtc->active = TRUE;
390#endif
391
392	return ret;
393}
394
395static void
396drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
397{
398
399}
400
401static void
402drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
403{
404	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
405	drmmode_ptr drmmode = drmmode_crtc->drmmode;
406
407	drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
408}
409
410static void
411drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
412{
413	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
414	void *ptr;
415
416	/* cursor should be mapped already */
417	ptr = drmmode_crtc->cursor_bo->ptr;
418
419	memcpy (ptr, image, 64 * 64 * 4);
420
421	return;
422}
423
424
425static void
426drmmode_hide_cursor (xf86CrtcPtr crtc)
427{
428	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
429	drmmode_ptr drmmode = drmmode_crtc->drmmode;
430
431	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
432
433}
434
435static void
436drmmode_show_cursor (xf86CrtcPtr crtc)
437{
438	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
439	drmmode_ptr drmmode = drmmode_crtc->drmmode;
440	uint32_t handle = drmmode_crtc->cursor_bo->handle;
441
442	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
443}
444
445static void *
446drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
447{
448	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
449	drmmode_ptr drmmode = drmmode_crtc->drmmode;
450	int size;
451	struct radeon_bo *rotate_bo;
452	int ret;
453	unsigned long rotate_pitch;
454	int base_align;
455
456	rotate_pitch =
457		RADEON_ALIGN(width, drmmode_get_pitch_align(crtc->scrn, drmmode->cpp, 0)) * drmmode->cpp;
458	height = RADEON_ALIGN(height, drmmode_get_height_align(crtc->scrn, 0));
459	base_align = drmmode_get_base_align(crtc->scrn, drmmode->cpp, 0);
460	size = RADEON_ALIGN(rotate_pitch * height, RADEON_GPU_PAGE_SIZE);
461
462	rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
463	if (rotate_bo == NULL)
464		return NULL;
465
466	radeon_bo_map(rotate_bo, 1);
467
468	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
469			   crtc->scrn->bitsPerPixel, rotate_pitch,
470			   rotate_bo->handle,
471			   &drmmode_crtc->rotate_fb_id);
472	if (ret) {
473		ErrorF("failed to add rotate fb\n");
474	}
475
476	drmmode_crtc->rotate_bo = rotate_bo;
477	return drmmode_crtc->rotate_bo->ptr;
478}
479
480static PixmapPtr
481drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
482{
483	ScrnInfoPtr pScrn = crtc->scrn;
484	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
485	drmmode_ptr drmmode = drmmode_crtc->drmmode;
486	unsigned long rotate_pitch;
487	PixmapPtr rotate_pixmap;
488
489	if (!data)
490		data = drmmode_crtc_shadow_allocate (crtc, width, height);
491
492	rotate_pitch = RADEON_ALIGN(width, 64) * drmmode->cpp;
493
494	rotate_pixmap = drmmode_create_bo_pixmap(pScrn->pScreen,
495						 width, height,
496						 pScrn->depth,
497						 pScrn->bitsPerPixel,
498						 rotate_pitch,
499						 drmmode_crtc->rotate_bo);
500	if (rotate_pixmap == NULL) {
501		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
502			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
503	}
504	return rotate_pixmap;
505
506}
507
508static void
509drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
510{
511	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
512	drmmode_ptr drmmode = drmmode_crtc->drmmode;
513
514	if (rotate_pixmap)
515		drmmode_destroy_bo_pixmap(rotate_pixmap);
516
517	if (data) {
518		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
519		drmmode_crtc->rotate_fb_id = 0;
520		radeon_bo_unmap(drmmode_crtc->rotate_bo);
521		radeon_bo_unref(drmmode_crtc->rotate_bo);
522		drmmode_crtc->rotate_bo = NULL;
523	}
524
525}
526
527static void
528drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
529                      uint16_t *blue, int size)
530{
531	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
532	drmmode_ptr drmmode = drmmode_crtc->drmmode;
533
534	drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
535			    size, red, green, blue);
536}
537
538static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
539    .dpms = drmmode_crtc_dpms,
540    .set_mode_major = drmmode_set_mode_major,
541    .set_cursor_colors = drmmode_set_cursor_colors,
542    .set_cursor_position = drmmode_set_cursor_position,
543    .show_cursor = drmmode_show_cursor,
544    .hide_cursor = drmmode_hide_cursor,
545    .load_cursor_argb = drmmode_load_cursor_argb,
546
547    .gamma_set = drmmode_crtc_gamma_set,
548    .shadow_create = drmmode_crtc_shadow_create,
549    .shadow_allocate = drmmode_crtc_shadow_allocate,
550    .shadow_destroy = drmmode_crtc_shadow_destroy,
551    .destroy = NULL, /* XXX */
552};
553
554int drmmode_get_crtc_id(xf86CrtcPtr crtc)
555{
556	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
557	return drmmode_crtc->hw_id;
558}
559
560void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
561{
562	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
563	ScrnInfoPtr pScrn = crtc->scrn;
564	RADEONInfoPtr info = RADEONPTR(pScrn);
565	struct drm_radeon_info ginfo;
566	int r;
567	uint32_t tmp;
568
569	memset(&ginfo, 0, sizeof(ginfo));
570	ginfo.request = 0x4;
571	tmp = drmmode_crtc->mode_crtc->crtc_id;
572	ginfo.value = (uintptr_t)&tmp;
573	r = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
574	if (r) {
575		drmmode_crtc->hw_id = -1;
576		return;
577	}
578	drmmode_crtc->hw_id = tmp;
579}
580
581static void
582drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
583{
584	xf86CrtcPtr crtc;
585	drmmode_crtc_private_ptr drmmode_crtc;
586
587	crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
588	if (crtc == NULL)
589		return;
590
591	drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
592	drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
593	drmmode_crtc->drmmode = drmmode;
594	crtc->driver_private = drmmode_crtc;
595	drmmode_crtc_hw_id(crtc);
596
597	return;
598}
599
600static xf86OutputStatus
601drmmode_output_detect(xf86OutputPtr output)
602{
603	/* go to the hw and retrieve a new output struct */
604	drmmode_output_private_ptr drmmode_output = output->driver_private;
605	drmmode_ptr drmmode = drmmode_output->drmmode;
606	xf86OutputStatus status;
607	drmModeFreeConnector(drmmode_output->mode_output);
608
609	drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
610
611	switch (drmmode_output->mode_output->connection) {
612	case DRM_MODE_CONNECTED:
613		status = XF86OutputStatusConnected;
614		break;
615	case DRM_MODE_DISCONNECTED:
616		status = XF86OutputStatusDisconnected;
617		break;
618	default:
619	case DRM_MODE_UNKNOWNCONNECTION:
620		status = XF86OutputStatusUnknown;
621		break;
622	}
623	return status;
624}
625
626static Bool
627drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
628{
629	return MODE_OK;
630}
631
632static DisplayModePtr
633drmmode_output_get_modes(xf86OutputPtr output)
634{
635	drmmode_output_private_ptr drmmode_output = output->driver_private;
636	drmModeConnectorPtr koutput = drmmode_output->mode_output;
637	drmmode_ptr drmmode = drmmode_output->drmmode;
638	int i;
639	DisplayModePtr Modes = NULL, Mode;
640	drmModePropertyPtr props;
641	xf86MonPtr mon = NULL;
642
643	/* look for an EDID property */
644	for (i = 0; i < koutput->count_props; i++) {
645		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
646		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
647			if (!strcmp(props->name, "EDID")) {
648				if (drmmode_output->edid_blob)
649					drmModeFreePropertyBlob(drmmode_output->edid_blob);
650				drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
651			}
652			drmModeFreeProperty(props);
653		}
654	}
655
656	if (drmmode_output->edid_blob) {
657		mon = xf86InterpretEDID(output->scrn->scrnIndex,
658					drmmode_output->edid_blob->data);
659		if (mon && drmmode_output->edid_blob->length > 128)
660			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
661	}
662	xf86OutputSetEDID(output, mon);
663
664	/* modes should already be available */
665	for (i = 0; i < koutput->count_modes; i++) {
666		Mode = xnfalloc(sizeof(DisplayModeRec));
667
668		drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
669		Modes = xf86ModesAdd(Modes, Mode);
670
671	}
672	return Modes;
673}
674
675static void
676drmmode_output_destroy(xf86OutputPtr output)
677{
678	drmmode_output_private_ptr drmmode_output = output->driver_private;
679	int i;
680
681	if (drmmode_output->edid_blob)
682		drmModeFreePropertyBlob(drmmode_output->edid_blob);
683	for (i = 0; i < drmmode_output->num_props; i++) {
684		drmModeFreeProperty(drmmode_output->props[i].mode_prop);
685		free(drmmode_output->props[i].atoms);
686	}
687	for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
688		drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
689		free(drmmode_output->mode_encoders);
690	}
691	free(drmmode_output->props);
692	drmModeFreeConnector(drmmode_output->mode_output);
693	free(drmmode_output);
694	output->driver_private = NULL;
695}
696
697static void
698drmmode_output_dpms(xf86OutputPtr output, int mode)
699{
700	drmmode_output_private_ptr drmmode_output = output->driver_private;
701	drmModeConnectorPtr koutput = drmmode_output->mode_output;
702	drmmode_ptr drmmode = drmmode_output->drmmode;
703
704	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
705				    drmmode_output->dpms_enum_id, mode);
706	return;
707}
708
709
710static Bool
711drmmode_property_ignore(drmModePropertyPtr prop)
712{
713    if (!prop)
714	return TRUE;
715    /* ignore blob prop */
716    if (prop->flags & DRM_MODE_PROP_BLOB)
717	return TRUE;
718    /* ignore standard property */
719    if (!strcmp(prop->name, "EDID") ||
720	    !strcmp(prop->name, "DPMS"))
721	return TRUE;
722
723    return FALSE;
724}
725
726static void
727drmmode_output_create_resources(xf86OutputPtr output)
728{
729    drmmode_output_private_ptr drmmode_output = output->driver_private;
730    drmModeConnectorPtr mode_output = drmmode_output->mode_output;
731    drmmode_ptr drmmode = drmmode_output->drmmode;
732    drmModePropertyPtr drmmode_prop;
733    int i, j, err;
734
735    drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
736    if (!drmmode_output->props)
737	return;
738
739    drmmode_output->num_props = 0;
740    for (i = 0, j = 0; i < mode_output->count_props; i++) {
741	drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
742	if (drmmode_property_ignore(drmmode_prop)) {
743	    drmModeFreeProperty(drmmode_prop);
744	    continue;
745	}
746	drmmode_output->props[j].mode_prop = drmmode_prop;
747	drmmode_output->props[j].value = mode_output->prop_values[i];
748	drmmode_output->num_props++;
749	j++;
750    }
751
752    for (i = 0; i < drmmode_output->num_props; i++) {
753	drmmode_prop_ptr p = &drmmode_output->props[i];
754	drmmode_prop = p->mode_prop;
755
756	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
757	    INT32 range[2];
758	    INT32 value = p->value;
759
760	    p->num_atoms = 1;
761	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
762	    if (!p->atoms)
763		continue;
764	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
765	    range[0] = drmmode_prop->values[0];
766	    range[1] = drmmode_prop->values[1];
767	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
768		    FALSE, TRUE,
769		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
770		    2, range);
771	    if (err != 0) {
772		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
773			"RRConfigureOutputProperty error, %d\n", err);
774	    }
775	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
776		    XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE);
777	    if (err != 0) {
778		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
779			"RRChangeOutputProperty error, %d\n", err);
780	    }
781	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
782	    p->num_atoms = drmmode_prop->count_enums + 1;
783	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
784	    if (!p->atoms)
785		continue;
786	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
787	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
788		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
789		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
790	    }
791	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
792		    FALSE, FALSE,
793		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
794		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
795	    if (err != 0) {
796		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
797			"RRConfigureOutputProperty error, %d\n", err);
798	    }
799	    for (j = 0; j < drmmode_prop->count_enums; j++)
800		if (drmmode_prop->enums[j].value == p->value)
801		    break;
802	    /* there's always a matching value */
803	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
804		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
805	    if (err != 0) {
806		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
807			"RRChangeOutputProperty error, %d\n", err);
808	    }
809	}
810    }
811}
812
813static Bool
814drmmode_output_set_property(xf86OutputPtr output, Atom property,
815		RRPropertyValuePtr value)
816{
817    drmmode_output_private_ptr drmmode_output = output->driver_private;
818    drmmode_ptr drmmode = drmmode_output->drmmode;
819    int i;
820
821    for (i = 0; i < drmmode_output->num_props; i++) {
822	drmmode_prop_ptr p = &drmmode_output->props[i];
823
824	if (p->atoms[0] != property)
825	    continue;
826
827	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
828	    uint32_t val;
829
830	    if (value->type != XA_INTEGER || value->format != 32 ||
831		    value->size != 1)
832		return FALSE;
833	    val = *(uint32_t *)value->data;
834
835	    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
836		    p->mode_prop->prop_id, (uint64_t)val);
837	    return TRUE;
838	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
839	    Atom	atom;
840	    const char	*name;
841	    int		j;
842
843	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
844		return FALSE;
845	    memcpy(&atom, value->data, 4);
846	    name = NameForAtom(atom);
847
848	    /* search for matching name string, then set its value down */
849	    for (j = 0; j < p->mode_prop->count_enums; j++) {
850		if (!strcmp(p->mode_prop->enums[j].name, name)) {
851		    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
852			    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
853		    return TRUE;
854		}
855	    }
856	}
857    }
858
859    return TRUE;
860}
861
862static Bool
863drmmode_output_get_property(xf86OutputPtr output, Atom property)
864{
865    return TRUE;
866}
867
868static const xf86OutputFuncsRec drmmode_output_funcs = {
869    .dpms = drmmode_output_dpms,
870    .create_resources = drmmode_output_create_resources,
871#ifdef RANDR_12_INTERFACE
872    .set_property = drmmode_output_set_property,
873    .get_property = drmmode_output_get_property,
874#endif
875#if 0
876
877    .save = drmmode_crt_save,
878    .restore = drmmode_crt_restore,
879    .mode_fixup = drmmode_crt_mode_fixup,
880    .prepare = drmmode_output_prepare,
881    .mode_set = drmmode_crt_mode_set,
882    .commit = drmmode_output_commit,
883#endif
884    .detect = drmmode_output_detect,
885    .mode_valid = drmmode_output_mode_valid,
886
887    .get_modes = drmmode_output_get_modes,
888    .destroy = drmmode_output_destroy
889};
890
891static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
892				      SubPixelHorizontalRGB,
893				      SubPixelHorizontalBGR,
894				      SubPixelVerticalRGB,
895				      SubPixelVerticalBGR,
896				      SubPixelNone };
897
898const char *output_names[] = { "None",
899			       "VGA",
900			       "DVI",
901			       "DVI",
902			       "DVI",
903			       "Composite",
904			       "S-video",
905			       "LVDS",
906			       "CTV",
907			       "DIN",
908			       "DisplayPort",
909			       "HDMI",
910			       "HDMI",
911			       "TV",
912			       "eDP"
913};
914
915static void
916drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi)
917{
918	RADEONInfoPtr info = RADEONPTR(pScrn);
919	xf86OutputPtr output;
920	drmModeConnectorPtr koutput;
921	drmModeEncoderPtr *kencoders = NULL;
922	drmmode_output_private_ptr drmmode_output;
923	drmModePropertyPtr props;
924	char name[32];
925	int i;
926	const char *s;
927
928	koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
929	if (!koutput)
930		return;
931
932	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
933	if (!kencoders) {
934		goto out_free_encoders;
935	}
936
937	for (i = 0; i < koutput->count_encoders; i++) {
938		kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
939		if (!kencoders[i]) {
940			goto out_free_encoders;
941		}
942	}
943
944	/* need to do smart conversion here for compat with non-kms ATI driver */
945	if (koutput->connector_type_id == 1) {
946	    switch(koutput->connector_type) {
947	    case DRM_MODE_CONNECTOR_DVII:
948	    case DRM_MODE_CONNECTOR_DVID:
949	    case DRM_MODE_CONNECTOR_DVIA:
950		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
951		(*num_dvi)++;
952		break;
953	    case DRM_MODE_CONNECTOR_HDMIA:
954	    case DRM_MODE_CONNECTOR_HDMIB:
955		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
956		(*num_hdmi)++;
957		break;
958	    case DRM_MODE_CONNECTOR_VGA:
959	    case DRM_MODE_CONNECTOR_DisplayPort:
960		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
961		break;
962	    default:
963		snprintf(name, 32, "%s", output_names[koutput->connector_type]);
964		break;
965	    }
966	} else {
967	    snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
968	}
969
970	if (xf86IsEntityShared(pScrn->entityList[0])) {
971		if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) {
972			if (!RADEONZaphodStringMatches(pScrn, s, name))
973				goto out_free_encoders;
974		} else {
975			if (info->IsPrimary && (num != 0))
976				goto out_free_encoders;
977			else if (info->IsSecondary && (num != 1))
978				goto out_free_encoders;
979		}
980	}
981
982	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
983	if (!output) {
984		goto out_free_encoders;
985	}
986
987	drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
988	if (!drmmode_output) {
989		xf86OutputDestroy(output);
990		goto out_free_encoders;
991	}
992
993	drmmode_output->output_id = drmmode->mode_res->connectors[num];
994	drmmode_output->mode_output = koutput;
995	drmmode_output->mode_encoders = kencoders;
996	drmmode_output->drmmode = drmmode;
997	output->mm_width = koutput->mmWidth;
998	output->mm_height = koutput->mmHeight;
999
1000	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
1001	output->interlaceAllowed = TRUE;
1002	output->doubleScanAllowed = TRUE;
1003	output->driver_private = drmmode_output;
1004
1005	output->possible_crtcs = 0x7f;
1006	for (i = 0; i < koutput->count_encoders; i++) {
1007		output->possible_crtcs &= kencoders[i]->possible_crtcs;
1008	}
1009	/* work out the possible clones later */
1010	output->possible_clones = 0;
1011
1012	for (i = 0; i < koutput->count_props; i++) {
1013		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
1014		if (props && (props->flags && DRM_MODE_PROP_ENUM)) {
1015			if (!strcmp(props->name, "DPMS")) {
1016				drmmode_output->dpms_enum_id = koutput->props[i];
1017				drmModeFreeProperty(props);
1018				break;
1019			}
1020			drmModeFreeProperty(props);
1021		}
1022	}
1023
1024	return;
1025out_free_encoders:
1026	if (kencoders){
1027		for (i = 0; i < koutput->count_encoders; i++)
1028			drmModeFreeEncoder(kencoders[i]);
1029		free(kencoders);
1030	}
1031	drmModeFreeConnector(koutput);
1032
1033}
1034
1035uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
1036{
1037	drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
1038	int i;
1039	xf86OutputPtr clone_output;
1040	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1041	int index_mask = 0;
1042
1043	if (drmmode_output->enc_clone_mask == 0)
1044		return index_mask;
1045
1046	for (i = 0; i < xf86_config->num_output; i++) {
1047		clone_output = xf86_config->output[i];
1048		clone_drmout = clone_output->driver_private;
1049		if (output == clone_output)
1050			continue;
1051
1052		if (clone_drmout->enc_mask == 0)
1053			continue;
1054		if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
1055			index_mask |= (1 << i);
1056	}
1057	return index_mask;
1058}
1059
1060
1061static void
1062drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1063{
1064	int i, j;
1065	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1066
1067	for (i = 0; i < xf86_config->num_output; i++) {
1068		xf86OutputPtr output = xf86_config->output[i];
1069		drmmode_output_private_ptr drmmode_output;
1070
1071		drmmode_output = output->driver_private;
1072		drmmode_output->enc_clone_mask = 0xff;
1073		/* and all the possible encoder clones for this output together */
1074		for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
1075		{
1076			int k;
1077			for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
1078				if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
1079					drmmode_output->enc_mask |= (1 << k);
1080			}
1081
1082			drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
1083		}
1084	}
1085
1086	for (i = 0; i < xf86_config->num_output; i++) {
1087		xf86OutputPtr output = xf86_config->output[i];
1088		output->possible_clones = find_clones(scrn, output);
1089	}
1090}
1091
1092/* returns height alignment in pixels */
1093int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling)
1094{
1095	RADEONInfoPtr info = RADEONPTR(scrn);
1096	int height_align = 1;
1097
1098	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1099		if (tiling & RADEON_TILING_MACRO)
1100			height_align =  info->num_channels * 8;
1101		else if (tiling & RADEON_TILING_MICRO)
1102			height_align = 8;
1103		else
1104			height_align = 8;
1105	} else {
1106		if (tiling)
1107			height_align = 16;
1108		else
1109			height_align = 1;
1110	}
1111	return height_align;
1112}
1113
1114/* returns pitch alignment in pixels */
1115int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1116{
1117	RADEONInfoPtr info = RADEONPTR(scrn);
1118	int pitch_align = 1;
1119
1120	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1121		if (tiling & RADEON_TILING_MACRO) {
1122			/* general surface requirements */
1123			pitch_align = MAX(info->num_banks,
1124					  (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8;
1125			/* further restrictions for scanout */
1126			pitch_align = MAX(info->num_banks * 8, pitch_align);
1127		} else if (tiling & RADEON_TILING_MICRO) {
1128			/* general surface requirements */
1129			pitch_align = MAX(8, (info->group_bytes / (8 * bpe)));
1130			/* further restrictions for scanout */
1131			pitch_align = MAX(info->group_bytes / bpe, pitch_align);
1132		} else {
1133			/* general surface requirements */
1134			pitch_align = info->group_bytes / bpe;
1135			/* further restrictions for scanout */
1136			pitch_align = MAX(32, pitch_align);
1137		}
1138	} else {
1139		/* general surface requirements */
1140		if (tiling)
1141			pitch_align = 256 / bpe;
1142		else
1143			pitch_align = 64;
1144	}
1145	return pitch_align;
1146}
1147
1148/* returns base alignment in bytes */
1149int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1150{
1151	RADEONInfoPtr info = RADEONPTR(scrn);
1152	int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling);
1153	int height_align = drmmode_get_height_align(scrn, tiling);
1154	int base_align = RADEON_GPU_PAGE_SIZE;
1155
1156	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1157		if (tiling & RADEON_TILING_MACRO)
1158			base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe,
1159					 pixel_align * bpe * height_align);
1160		else
1161			base_align = info->group_bytes;
1162	}
1163	return base_align;
1164}
1165
1166static Bool
1167drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
1168{
1169	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1170	drmmode_crtc_private_ptr
1171		    drmmode_crtc = xf86_config->crtc[0]->driver_private;
1172	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1173	RADEONInfoPtr info = RADEONPTR(scrn);
1174	struct radeon_bo *old_front = NULL;
1175	Bool	    ret;
1176	ScreenPtr   screen = screenInfo.screens[scrn->scrnIndex];
1177	uint32_t    old_fb_id;
1178	int	    i, pitch, old_width, old_height, old_pitch;
1179	int screen_size;
1180	int cpp = info->CurrentLayout.pixel_bytes;
1181	struct radeon_bo *front_bo;
1182	uint32_t tiling_flags = 0;
1183	PixmapPtr ppix = screen->GetScreenPixmap(screen);
1184	void *fb_shadow;
1185
1186	if (scrn->virtualX == width && scrn->virtualY == height)
1187		return TRUE;
1188
1189	front_bo = info->front_bo;
1190	radeon_cs_flush_indirect(scrn);
1191
1192	if (front_bo)
1193		radeon_bo_wait(front_bo);
1194
1195	if (info->allowColorTiling) {
1196		if (info->ChipFamily >= CHIP_FAMILY_R600)
1197			tiling_flags |= RADEON_TILING_MICRO;
1198		else
1199			tiling_flags |= RADEON_TILING_MACRO;
1200	}
1201
1202	pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
1203	height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
1204	screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
1205
1206	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1207		   "Allocate new frame buffer %dx%d stride %d\n",
1208		   width, height, pitch / cpp);
1209
1210	old_width = scrn->virtualX;
1211	old_height = scrn->virtualY;
1212	old_pitch = scrn->displayWidth;
1213	old_fb_id = drmmode->fb_id;
1214	old_front = info->front_bo;
1215
1216	scrn->virtualX = width;
1217	scrn->virtualY = height;
1218	scrn->displayWidth = pitch / cpp;
1219
1220	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, 0, RADEON_GEM_DOMAIN_VRAM, 0);
1221	if (!info->front_bo)
1222		goto fail;
1223
1224#if X_BYTE_ORDER == X_BIG_ENDIAN
1225	switch (cpp) {
1226	case 4:
1227	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
1228	    break;
1229	case 2:
1230	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
1231	    break;
1232	}
1233#endif
1234	if (tiling_flags)
1235	    radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
1236
1237	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
1238			   scrn->bitsPerPixel, pitch,
1239			   info->front_bo->handle,
1240			   &drmmode->fb_id);
1241	if (ret)
1242		goto fail;
1243
1244	if (!info->r600_shadow_fb) {
1245		radeon_set_pixmap_bo(ppix, info->front_bo);
1246		screen->ModifyPixmapHeader(ppix,
1247					   width, height, -1, -1, pitch, NULL);
1248	} else {
1249		if (radeon_bo_map(info->front_bo, 1))
1250			goto fail;
1251		fb_shadow = calloc(1, screen_size);
1252		if (fb_shadow == NULL)
1253			goto fail;
1254		free(info->fb_shadow);
1255		info->fb_shadow = fb_shadow;
1256		screen->ModifyPixmapHeader(ppix,
1257					   width, height, -1, -1, pitch,
1258					   info->fb_shadow);
1259	}
1260#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,9,99,1,0)
1261	scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
1262#endif
1263
1264	for (i = 0; i < xf86_config->num_crtc; i++) {
1265		xf86CrtcPtr crtc = xf86_config->crtc[i];
1266
1267		if (!crtc->enabled)
1268			continue;
1269
1270		drmmode_set_mode_major(crtc, &crtc->mode,
1271				       crtc->rotation, crtc->x, crtc->y);
1272	}
1273
1274	if (old_fb_id)
1275		drmModeRmFB(drmmode->fd, old_fb_id);
1276	if (old_front)
1277		radeon_bo_unref(old_front);
1278
1279	radeon_kms_update_vram_limit(scrn, screen_size);
1280	return TRUE;
1281
1282 fail:
1283	if (info->front_bo)
1284		radeon_bo_unref(info->front_bo);
1285	info->front_bo = old_front;
1286	scrn->virtualX = old_width;
1287	scrn->virtualY = old_height;
1288	scrn->displayWidth = old_pitch;
1289	drmmode->fb_id = old_fb_id;
1290
1291	return FALSE;
1292}
1293
1294static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
1295	drmmode_xf86crtc_resize
1296};
1297
1298static void
1299drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
1300			unsigned int tv_usec, void *event_data)
1301{
1302	radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data);
1303}
1304
1305static void
1306drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
1307		     unsigned int tv_usec, void *event_data)
1308{
1309	drmmode_flipevtcarrier_ptr flipcarrier = event_data;
1310	drmmode_ptr drmmode = flipcarrier->drmmode;
1311
1312	/* Is this the event whose info shall be delivered to higher level? */
1313	if (flipcarrier->dispatch_me) {
1314		/* Yes: Cache msc, ust for later delivery. */
1315		drmmode->fe_frame = frame;
1316		drmmode->fe_tv_sec = tv_sec;
1317		drmmode->fe_tv_usec = tv_usec;
1318	}
1319	free(flipcarrier);
1320
1321	/* Last crtc completed flip? */
1322	drmmode->flip_count--;
1323	if (drmmode->flip_count > 0)
1324		return;
1325
1326	/* Release framebuffer */
1327	drmModeRmFB(drmmode->fd, drmmode->old_fb_id);
1328
1329	if (drmmode->event_data == NULL)
1330		return;
1331
1332	/* Deliver cached msc, ust from reference crtc to flip event handler */
1333	radeon_dri2_flip_event_handler(drmmode->fe_frame, drmmode->fe_tv_sec,
1334				       drmmode->fe_tv_usec, drmmode->event_data);
1335}
1336
1337
1338static void
1339drm_wakeup_handler(pointer data, int err, pointer p)
1340{
1341	drmmode_ptr drmmode = data;
1342	fd_set *read_mask = p;
1343
1344	if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) {
1345		drmHandleEvent(drmmode->fd, &drmmode->event_context);
1346	}
1347}
1348
1349Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
1350{
1351	RADEONEntPtr pRADEONEnt   = RADEONEntPriv(pScrn);
1352	xf86CrtcConfigPtr xf86_config;
1353	RADEONInfoPtr info = RADEONPTR(pScrn);
1354	int i, num_dvi = 0, num_hdmi = 0;
1355
1356	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
1357	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1358
1359	drmmode->scrn = pScrn;
1360	drmmode->cpp = cpp;
1361	drmmode->mode_res = drmModeGetResources(drmmode->fd);
1362	if (!drmmode->mode_res)
1363		return FALSE;
1364
1365	xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
1366	for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
1367		if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
1368			drmmode_crtc_init(pScrn, drmmode, i);
1369
1370	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
1371		drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
1372
1373	/* workout clones */
1374	drmmode_clones_init(pScrn, drmmode);
1375
1376	xf86InitialConfiguration(pScrn, TRUE);
1377
1378	drmmode->flip_count = 0;
1379	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
1380	drmmode->event_context.vblank_handler = drmmode_vblank_handler;
1381	drmmode->event_context.page_flip_handler = drmmode_flip_handler;
1382	if (!pRADEONEnt->fd_wakeup_registered && info->dri->pKernelDRMVersion->version_minor >= 4) {
1383		drmmode->flip_count = 0;
1384		AddGeneralSocket(drmmode->fd);
1385		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1386				drm_wakeup_handler, drmmode);
1387		pRADEONEnt->fd_wakeup_registered = TRUE;
1388	}
1389
1390	return TRUE;
1391}
1392
1393Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
1394{
1395	drmmode->bufmgr = bufmgr;
1396	return TRUE;
1397}
1398
1399
1400
1401void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
1402{
1403	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1404	xf86CrtcPtr crtc = xf86_config->crtc[id];
1405	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1406
1407	drmmode_crtc->cursor_bo = bo;
1408}
1409
1410void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags)
1411{
1412	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
1413	xf86OutputPtr  output = config->output[config->compat_output];
1414	xf86CrtcPtr	crtc = output->crtc;
1415
1416	if (crtc && crtc->enabled) {
1417		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
1418				       x, y);
1419	}
1420}
1421
1422Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
1423{
1424	xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
1425	int c;
1426
1427	drmmode_copy_fb(pScrn, drmmode);
1428
1429	for (c = 0; c < config->num_crtc; c++) {
1430		xf86CrtcPtr	crtc = config->crtc[c];
1431		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1432		xf86OutputPtr	output = NULL;
1433		int		o;
1434
1435		/* Skip disabled CRTCs */
1436		if (!crtc->enabled) {
1437			drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1438				       0, 0, 0, NULL, 0, NULL);
1439			continue;
1440		}
1441
1442		if (config->output[config->compat_output]->crtc == crtc)
1443			output = config->output[config->compat_output];
1444		else
1445		{
1446			for (o = 0; o < config->num_output; o++)
1447				if (config->output[o]->crtc == crtc)
1448				{
1449					output = config->output[o];
1450					break;
1451				}
1452		}
1453		/* paranoia */
1454		if (!output)
1455			continue;
1456
1457		/* Mark that we'll need to re-set the mode for sure */
1458		memset(&crtc->mode, 0, sizeof(crtc->mode));
1459		if (!crtc->desiredMode.CrtcHDisplay)
1460		{
1461			DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
1462
1463			if (!mode)
1464				return FALSE;
1465			crtc->desiredMode = *mode;
1466			crtc->desiredRotation = RR_Rotate_0;
1467			crtc->desiredX = 0;
1468			crtc->desiredY = 0;
1469		}
1470
1471		if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
1472						 crtc->desiredX, crtc->desiredY))
1473			return FALSE;
1474	}
1475	return TRUE;
1476}
1477
1478static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
1479                                 int *indices, LOCO *colors, VisualPtr pVisual)
1480{
1481    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1482    uint16_t       lut_r[256], lut_g[256], lut_b[256];
1483    int index, j, i;
1484    int c;
1485
1486    for (c = 0; c < xf86_config->num_crtc; c++) {
1487        xf86CrtcPtr crtc = xf86_config->crtc[c];
1488	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1489
1490        for (i = 0 ; i < 256; i++) {
1491            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
1492            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
1493            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
1494        }
1495
1496        switch(pScrn->depth) {
1497        case 15:
1498            for (i = 0; i < numColors; i++) {
1499                index = indices[i];
1500                for (j = 0; j < 8; j++) {
1501                    lut_r[index * 8 + j] = colors[index].red << 6;
1502                    lut_g[index * 8 + j] = colors[index].green << 6;
1503                    lut_b[index * 8 + j] = colors[index].blue << 6;
1504                }
1505            }
1506         break;
1507         case 16:
1508             for (i = 0; i < numColors; i++) {
1509                 index = indices[i];
1510
1511                  if (i <= 31) {
1512                      for (j = 0; j < 8; j++) {
1513                          lut_r[index * 8 + j] = colors[index].red << 6;
1514                          lut_b[index * 8 + j] = colors[index].blue << 6;
1515                      }
1516                  }
1517
1518                  for (j = 0; j < 4; j++) {
1519                      lut_g[index * 4 + j] = colors[index].green << 6;
1520                  }
1521              }
1522	  break;
1523          default:
1524              for (i = 0; i < numColors; i++) {
1525                  index = indices[i];
1526                  lut_r[index] = colors[index].red << 6;
1527                  lut_g[index] = colors[index].green << 6;
1528                  lut_b[index] = colors[index].blue << 6;
1529              }
1530              break;
1531          }
1532
1533    /* Make the change through RandR */
1534#ifdef RANDR_12_INTERFACE
1535        if (crtc->randr_crtc)
1536            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
1537        else
1538#endif
1539            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
1540     }
1541}
1542
1543Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
1544{
1545    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1546                  "Initializing kms color map\n");
1547    if (!miCreateDefColormap(pScreen))
1548        return FALSE;
1549    /* all radeons support 10 bit CLUTs */
1550    if (!xf86HandleColormaps(pScreen, 256, 10,
1551                             drmmode_load_palette, NULL,
1552                             CMAP_PALETTED_TRUECOLOR
1553#if 0 /* This option messes up text mode! (eich@suse.de) */
1554                             | CMAP_LOAD_EVEN_IF_OFFSCREEN
1555#endif
1556                             | CMAP_RELOAD_ON_MODE_SWITCH))
1557         return FALSE;
1558    return TRUE;
1559}
1560
1561#ifdef HAVE_LIBUDEV
1562static void
1563drmmode_handle_uevents(int fd, void *closure)
1564{
1565	drmmode_ptr drmmode = closure;
1566	ScrnInfoPtr scrn = drmmode->scrn;
1567	struct udev_device *dev;
1568	dev = udev_monitor_receive_device(drmmode->uevent_monitor);
1569	if (!dev)
1570		return;
1571
1572	RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE);
1573	udev_device_unref(dev);
1574}
1575#endif
1576
1577void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1578{
1579#ifdef HAVE_LIBUDEV
1580	struct udev *u;
1581	struct udev_monitor *mon;
1582
1583	u = udev_new();
1584	if (!u)
1585		return;
1586	mon = udev_monitor_new_from_netlink(u, "udev");
1587	if (!mon) {
1588		udev_unref(u);
1589		return;
1590	}
1591
1592	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
1593							    "drm",
1594							    "drm_minor") < 0 ||
1595	    udev_monitor_enable_receiving(mon) < 0) {
1596		udev_monitor_unref(mon);
1597		udev_unref(u);
1598		return;
1599	}
1600
1601	drmmode->uevent_handler =
1602		xf86AddGeneralHandler(udev_monitor_get_fd(mon),
1603				      drmmode_handle_uevents,
1604				      drmmode);
1605
1606	drmmode->uevent_monitor = mon;
1607#endif
1608}
1609
1610void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1611{
1612#ifdef HAVE_LIBUDEV
1613	if (drmmode->uevent_handler) {
1614		struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
1615		xf86RemoveGeneralHandler(drmmode->uevent_handler);
1616
1617		udev_monitor_unref(drmmode->uevent_monitor);
1618		udev_unref(u);
1619	}
1620#endif
1621}
1622
1623Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id)
1624{
1625	RADEONInfoPtr info = RADEONPTR(scrn);
1626	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1627	drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
1628	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1629	unsigned int pitch;
1630	int i, old_fb_id;
1631	uint32_t tiling_flags = 0;
1632	int height;
1633	drmmode_flipevtcarrier_ptr flipcarrier;
1634
1635	if (info->allowColorTiling) {
1636		if (info->ChipFamily >= CHIP_FAMILY_R600)
1637			tiling_flags |= RADEON_TILING_MICRO;
1638		else
1639			tiling_flags |= RADEON_TILING_MACRO;
1640	}
1641
1642	pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
1643		info->CurrentLayout.pixel_bytes;
1644	height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags));
1645
1646	/*
1647	 * Create a new handle for the back buffer
1648	 */
1649	old_fb_id = drmmode->fb_id;
1650	if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
1651			 scrn->depth, scrn->bitsPerPixel, pitch,
1652			 new_front->handle, &drmmode->fb_id))
1653		goto error_out;
1654
1655	/*
1656	 * Queue flips on all enabled CRTCs
1657	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
1658	 * Right now it assumes a single shared fb across all CRTCs, with the
1659	 * kernel fixing up the offset of each CRTC as necessary.
1660	 *
1661	 * Also, flips queued on disabled or incorrectly configured displays
1662	 * may never complete; this is a configuration error.
1663	 */
1664	drmmode->fe_frame = 0;
1665	drmmode->fe_tv_sec = 0;
1666	drmmode->fe_tv_usec = 0;
1667
1668	for (i = 0; i < config->num_crtc; i++) {
1669		if (!config->crtc[i]->enabled)
1670			continue;
1671
1672		drmmode->event_data = data;
1673		drmmode->flip_count++;
1674		drmmode_crtc = config->crtc[i]->driver_private;
1675
1676		flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec));
1677		if (!flipcarrier) {
1678			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1679				   "flip queue: carrier alloc failed.\n");
1680			goto error_undo;
1681		}
1682
1683		/* Only the reference crtc will finally deliver its page flip
1684		 * completion event. All other crtc's events will be discarded.
1685		 */
1686		flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
1687		flipcarrier->drmmode = drmmode;
1688
1689		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1690				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
1691			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1692				   "flip queue failed: %s\n", strerror(errno));
1693			free(flipcarrier);
1694			goto error_undo;
1695		}
1696	}
1697
1698	drmmode->old_fb_id = old_fb_id;
1699	return TRUE;
1700
1701error_undo:
1702	drmModeRmFB(drmmode->fd, drmmode->fb_id);
1703	drmmode->fb_id = old_fb_id;
1704
1705error_out:
1706	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
1707		   strerror(errno));
1708	return FALSE;
1709}
1710
1711#endif
1712