drmmode_display.c revision 0d16fef4
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#include <sys/ioctl.h>
34#include <time.h>
35#include "cursorstr.h"
36#include "damagestr.h"
37#include "micmap.h"
38#include "xf86cmap.h"
39#include "radeon.h"
40#include "radeon_bo_helper.h"
41#include "radeon_glamor.h"
42#include "radeon_list.h"
43#include "radeon_reg.h"
44
45#ifdef RADEON_PIXMAP_SHARING
46#include <dri.h>
47#endif
48
49#include "drmmode_display.h"
50
51/* DPMS */
52#ifdef HAVE_XEXTPROTO_71
53#include <X11/extensions/dpmsconst.h>
54#else
55#define DPMS_SERVER
56#include <X11/extensions/dpms.h>
57#endif
58
59#define DEFAULT_NOMINAL_FRAME_RATE 60
60
61static Bool
62drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height);
63
64static Bool
65RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
66{
67    int i = 0;
68    char s1[20];
69
70    do {
71	switch(*s) {
72	case ',':
73  	    s1[i] = '\0';
74	    i = 0;
75	    if (strcmp(s1, output_name) == 0)
76		return TRUE;
77	    break;
78	case ' ':
79	case '\t':
80	case '\n':
81	case '\r':
82	    break;
83	default:
84	    s1[i] = *s;
85	    i++;
86	    break;
87	}
88    } while(*s++);
89
90    s1[i] = '\0';
91    if (strcmp(s1, output_name) == 0)
92	return TRUE;
93
94    return FALSE;
95}
96
97static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
98					  int width, int height,
99					  int depth, int bpp,
100					  struct radeon_bo *bo, struct radeon_surface *psurf)
101{
102	RADEONInfoPtr info = RADEONPTR(pScrn);
103	ScreenPtr pScreen = pScrn->pScreen;
104	PixmapPtr pixmap;
105	struct radeon_surface *surface;
106	uint32_t tiling;
107
108	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth,
109					  RADEON_CREATE_PIXMAP_SCANOUT);
110	if (!pixmap)
111		return NULL;
112
113	if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height,
114					    depth, bpp, -1, NULL)) {
115		return NULL;
116	}
117
118	if (!info->use_glamor)
119		exaMoveInPixmap(pixmap);
120	radeon_set_pixmap_bo(pixmap, bo);
121	if (info->ChipFamily >= CHIP_FAMILY_R600) {
122		surface = radeon_get_pixmap_surface(pixmap);
123		if (surface && psurf)
124			*surface = *psurf;
125		else if (surface) {
126			memset(surface, 0, sizeof(struct radeon_surface));
127			surface->npix_x = width;
128			surface->npix_y = height;
129			surface->npix_z = 1;
130			surface->blk_w = 1;
131			surface->blk_h = 1;
132			surface->blk_d = 1;
133			surface->array_size = 1;
134			surface->last_level = 0;
135			surface->bpe = bpp / 8;
136			surface->nsamples = 1;
137			surface->flags = RADEON_SURF_SCANOUT;
138			/* we are requiring a recent enough libdrm version */
139			surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
140			surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
141			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
142			tiling = radeon_get_pixmap_tiling_flags(pixmap);
143			if (tiling & RADEON_TILING_MICRO) {
144				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
145				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
146			}
147			if (tiling & RADEON_TILING_MACRO) {
148				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
149				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
150			}
151			if (radeon_surface_best(info->surf_man, surface)) {
152				return NULL;
153			}
154			if (radeon_surface_init(info->surf_man, surface)) {
155				return NULL;
156			}
157		}
158	}
159
160	if (info->use_glamor &&
161	    !radeon_glamor_create_textured_pixmap(pixmap,
162						  radeon_get_pixmap_private(pixmap))) {
163		pScreen->DestroyPixmap(pixmap);
164	  	return NULL;
165	}
166
167	return pixmap;
168}
169
170static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap)
171{
172	ScreenPtr pScreen = pixmap->drawable.pScreen;
173
174	(*pScreen->DestroyPixmap)(pixmap);
175}
176
177static void
178drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
179		     drmModeModeInfo *kmode,
180		     DisplayModePtr	mode)
181{
182	memset(mode, 0, sizeof(DisplayModeRec));
183	mode->status = MODE_OK;
184
185	mode->Clock = kmode->clock;
186
187	mode->HDisplay = kmode->hdisplay;
188	mode->HSyncStart = kmode->hsync_start;
189	mode->HSyncEnd = kmode->hsync_end;
190	mode->HTotal = kmode->htotal;
191	mode->HSkew = kmode->hskew;
192
193	mode->VDisplay = kmode->vdisplay;
194	mode->VSyncStart = kmode->vsync_start;
195	mode->VSyncEnd = kmode->vsync_end;
196	mode->VTotal = kmode->vtotal;
197	mode->VScan = kmode->vscan;
198
199	mode->Flags = kmode->flags; //& FLAG_BITS;
200	mode->name = strdup(kmode->name);
201
202	if (kmode->type & DRM_MODE_TYPE_DRIVER)
203		mode->type = M_T_DRIVER;
204	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
205		mode->type |= M_T_PREFERRED;
206	xf86SetModeCrtc (mode, scrn->adjustFlags);
207}
208
209static void
210drmmode_ConvertToKMode(ScrnInfoPtr	scrn,
211		     drmModeModeInfo *kmode,
212		     DisplayModePtr	mode)
213{
214	memset(kmode, 0, sizeof(*kmode));
215
216	kmode->clock = mode->Clock;
217	kmode->hdisplay = mode->HDisplay;
218	kmode->hsync_start = mode->HSyncStart;
219	kmode->hsync_end = mode->HSyncEnd;
220	kmode->htotal = mode->HTotal;
221	kmode->hskew = mode->HSkew;
222
223	kmode->vdisplay = mode->VDisplay;
224	kmode->vsync_start = mode->VSyncStart;
225	kmode->vsync_end = mode->VSyncEnd;
226	kmode->vtotal = mode->VTotal;
227	kmode->vscan = mode->VScan;
228
229	kmode->flags = mode->Flags; //& FLAG_BITS;
230	if (mode->name)
231		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
232	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
233
234}
235
236/*
237 * Retrieves present time in microseconds that is compatible
238 * with units used by vblank timestamps. Depending on the kernel
239 * version and DRM kernel module configuration, the vblank
240 * timestamp can either be in real time or monotonic time
241 */
242int drmmode_get_current_ust(int drm_fd, CARD64 *ust)
243{
244	uint64_t cap_value;
245	int ret;
246	struct timespec now;
247
248	ret = drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap_value);
249	if (ret || !cap_value)
250		/* old kernel or drm_timestamp_monotonic turned off */
251		ret = clock_gettime(CLOCK_REALTIME, &now);
252	else
253		ret = clock_gettime(CLOCK_MONOTONIC, &now);
254	if (ret)
255		return ret;
256	*ust = ((CARD64)now.tv_sec * 1000000) + ((CARD64)now.tv_nsec / 1000);
257	return 0;
258}
259
260/*
261 * Get current frame count and frame count timestamp of the crtc.
262 */
263int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
264{
265    ScrnInfoPtr scrn = crtc->scrn;
266    RADEONInfoPtr info = RADEONPTR(scrn);
267    drmVBlank vbl;
268    int ret;
269
270    vbl.request.type = DRM_VBLANK_RELATIVE;
271    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
272    vbl.request.sequence = 0;
273
274    ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
275    if (ret) {
276	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
277		   "get vblank counter failed: %s\n", strerror(errno));
278	return ret;
279    }
280
281    *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
282    *msc = vbl.reply.sequence;
283
284    return Success;
285}
286
287static void
288drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
289{
290	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
291	ScrnInfoPtr scrn = crtc->scrn;
292	RADEONInfoPtr info = RADEONPTR(scrn);
293	CARD64 ust;
294	int ret;
295
296	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
297		drmVBlank vbl;
298
299		/*
300		 * On->Off transition: record the last vblank time,
301		 * sequence number and frame period.
302		 */
303		vbl.request.type = DRM_VBLANK_RELATIVE;
304		vbl.request.type |= radeon_populate_vbl_request_type(crtc);
305		vbl.request.sequence = 0;
306		ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
307		if (ret)
308			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
309				   "%s cannot get last vblank counter\n",
310				   __func__);
311		else {
312			CARD64 seq = (CARD64)vbl.reply.sequence;
313			CARD64 nominal_frame_rate, pix_in_frame;
314
315			ust = ((CARD64)vbl.reply.tval_sec * 1000000) +
316				vbl.reply.tval_usec;
317			drmmode_crtc->dpms_last_ust = ust;
318			drmmode_crtc->dpms_last_seq = seq;
319			nominal_frame_rate = crtc->mode.Clock;
320			nominal_frame_rate *= 1000;
321			pix_in_frame = crtc->mode.HTotal * crtc->mode.VTotal;
322			if (nominal_frame_rate == 0 || pix_in_frame == 0)
323				nominal_frame_rate = DEFAULT_NOMINAL_FRAME_RATE;
324			else
325				nominal_frame_rate /= pix_in_frame;
326			drmmode_crtc->dpms_last_fps = nominal_frame_rate;
327		}
328	} else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) {
329		/*
330		 * Off->On transition: calculate and accumulate the
331		 * number of interpolated vblanks while we were in Off state
332		 */
333		ret = drmmode_get_current_ust(info->dri2.drm_fd, &ust);
334		if (ret)
335			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
336				   "%s cannot get current time\n", __func__);
337		else if (drmmode_crtc->dpms_last_ust) {
338			CARD64 time_elapsed, delta_seq;
339			time_elapsed = ust - drmmode_crtc->dpms_last_ust;
340			delta_seq = time_elapsed * drmmode_crtc->dpms_last_fps;
341			delta_seq /= 1000000;
342			drmmode_crtc->interpolated_vblanks += delta_seq;
343
344		}
345	}
346	drmmode_crtc->dpms_mode = mode;
347}
348
349static void
350drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
351{
352	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
353	drmmode_ptr drmmode = drmmode_crtc->drmmode;
354
355	/* Disable unused CRTCs */
356	if (!crtc->enabled || mode != DPMSModeOn)
357		drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
358			       0, 0, 0, NULL, 0, NULL);
359	else if (drmmode_crtc->dpms_mode != DPMSModeOn)
360		crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
361					    crtc->x, crtc->y);
362}
363
364#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
365
366static PixmapPtr
367create_pixmap_for_fbcon(drmmode_ptr drmmode,
368			ScrnInfoPtr pScrn, int fbcon_id)
369{
370	RADEONInfoPtr info = RADEONPTR(pScrn);
371	PixmapPtr pixmap = info->fbcon_pixmap;
372	struct radeon_bo *bo;
373	drmModeFBPtr fbcon;
374	struct drm_gem_flink flink;
375
376	if (pixmap)
377	    return pixmap;
378
379	fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
380	if (fbcon == NULL)
381		return NULL;
382
383	if (fbcon->depth != pScrn->depth ||
384	    fbcon->width != pScrn->virtualX ||
385	    fbcon->height != pScrn->virtualY)
386		goto out_free_fb;
387
388	flink.handle = fbcon->handle;
389	if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
390		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
391			   "Couldn't flink fbcon handle\n");
392		goto out_free_fb;
393	}
394
395	bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
396	if (bo == NULL) {
397		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
398			   "Couldn't allocate bo for fbcon handle\n");
399		goto out_free_fb;
400	}
401
402	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
403					  fbcon->depth, fbcon->bpp, bo, NULL);
404	info->fbcon_pixmap = pixmap;
405	radeon_bo_unref(bo);
406out_free_fb:
407	drmModeFreeFB(fbcon);
408	return pixmap;
409}
410
411static void
412destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn)
413{
414	RADEONInfoPtr info = RADEONPTR(pScrn);
415
416	/* XXX: The current GPUVM support in the kernel doesn't allow removing
417	 * the virtual address range for this BO, so we need to keep around
418	 * the pixmap to avoid breaking glamor with GPUVM
419	 */
420	if (info->use_glamor && info->ChipFamily >= CHIP_FAMILY_CAYMAN)
421		return;
422
423	if (info->fbcon_pixmap)
424		pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
425	info->fbcon_pixmap = NULL;
426}
427
428void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
429{
430	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
431	RADEONInfoPtr info = RADEONPTR(pScrn);
432	PixmapPtr src, dst;
433	ScreenPtr pScreen = pScrn->pScreen;
434	int fbcon_id = 0;
435	Bool force;
436	GCPtr gc;
437	int i;
438
439	for (i = 0; i < xf86_config->num_crtc; i++) {
440		drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private;
441
442		if (drmmode_crtc->mode_crtc->buffer_id)
443			fbcon_id = drmmode_crtc->mode_crtc->buffer_id;
444	}
445
446	if (!fbcon_id)
447		return;
448
449	if (fbcon_id == drmmode->fb_id) {
450		/* in some rare case there might be no fbcon and we might already
451		 * be the one with the current fb to avoid a false deadlck in
452		 * kernel ttm code just do nothing as anyway there is nothing
453		 * to do
454		 */
455		return;
456	}
457
458	src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id);
459	if (!src)
460		return;
461
462	dst = pScreen->GetScreenPixmap(pScreen);
463
464	gc = GetScratchGC(pScrn->depth, pScreen);
465	ValidateGC(&dst->drawable, gc);
466
467	force = info->accel_state->force;
468	info->accel_state->force = TRUE;
469	(*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0,
470			     pScrn->virtualX, pScrn->virtualY, 0, 0);
471	info->accel_state->force = force;
472
473	FreeScratchGC(gc);
474
475	radeon_cs_flush_indirect(pScrn);
476	radeon_bo_wait(info->front_bo);
477
478	pScreen->canDoBGNoneRoot = TRUE;
479	destroy_pixmap_for_fbcon(pScrn);
480	return;
481}
482
483#endif /* GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 */
484
485static void
486drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
487			     struct drmmode_scanout *scanout)
488{
489	if (scanout->pixmap) {
490		drmmode_destroy_bo_pixmap(scanout->pixmap);
491		scanout->pixmap = NULL;
492	}
493
494	if (scanout->bo) {
495		drmModeRmFB(drmmode->fd, scanout->fb_id);
496		scanout->fb_id = 0;
497		radeon_bo_unmap(scanout->bo);
498		radeon_bo_unref(scanout->bo);
499		scanout->bo = NULL;
500	}
501
502	if (scanout->damage) {
503		DamageDestroy(scanout->damage);
504		scanout->damage = NULL;
505	}
506}
507
508void
509drmmode_scanout_free(ScrnInfoPtr scrn)
510{
511	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
512	int c;
513
514	for (c = 0; c < xf86_config->num_crtc; c++) {
515		drmmode_crtc_private_ptr drmmode_crtc =
516			xf86_config->crtc[c]->driver_private;
517
518		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
519					     &drmmode_crtc->scanout[0]);
520		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
521					     &drmmode_crtc->scanout[1]);
522	}
523}
524
525static void *
526drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc,
527			      struct drmmode_scanout *scanout,
528			      int width, int height)
529{
530	ScrnInfoPtr pScrn = crtc->scrn;
531	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
532	drmmode_ptr drmmode = drmmode_crtc->drmmode;
533	struct radeon_surface surface;
534	uint32_t tiling;
535	int ret;
536	int pitch;
537
538	if (scanout->bo) {
539		if (scanout->width == width && scanout->height == height)
540			return scanout->bo->ptr;
541
542		drmmode_crtc_scanout_destroy(drmmode, scanout);
543	}
544
545	scanout->bo = radeon_alloc_pixmap_bo(pScrn, width, height, pScrn->depth,
546					     RADEON_CREATE_PIXMAP_TILING_MACRO |
547					     RADEON_CREATE_PIXMAP_TILING_MICRO,
548					     pScrn->bitsPerPixel, &pitch,
549					     &surface, &tiling);
550	if (scanout->bo == NULL)
551		return NULL;
552
553	radeon_bo_map(scanout->bo, 1);
554
555	ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth,
556			   pScrn->bitsPerPixel, pitch,
557			   scanout->bo->handle,
558			   &scanout->fb_id);
559	if (ret) {
560		ErrorF("failed to add scanout fb\n");
561		radeon_bo_unref(scanout->bo);
562		scanout->bo = NULL;
563		return NULL;
564	}
565
566	scanout->width = width;
567	scanout->height = height;
568	return scanout->bo->ptr;
569}
570
571static PixmapPtr
572drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
573			    int width, int height)
574{
575	ScrnInfoPtr pScrn = crtc->scrn;
576	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
577	drmmode_ptr drmmode = drmmode_crtc->drmmode;
578
579	if (scanout->pixmap) {
580		if (scanout->width == width && scanout->height == height)
581			return scanout->pixmap;
582
583		drmmode_crtc_scanout_destroy(drmmode, scanout);
584	}
585
586	if (!scanout->bo) {
587		if (!drmmode_crtc_scanout_allocate(crtc, scanout, width, height))
588			return NULL;
589	}
590
591	scanout->pixmap = drmmode_create_bo_pixmap(pScrn,
592						 width, height,
593						 pScrn->depth,
594						 pScrn->bitsPerPixel,
595						 scanout->bo, NULL);
596	if (scanout->pixmap == NULL)
597		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
598			   "Couldn't allocate scanout pixmap for CRTC\n");
599
600	return scanout->pixmap;
601}
602
603static void
604radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure)
605{
606	/* Only keep track of the extents */
607	RegionUninit(&damage->damage);
608	damage->damage.data = NULL;
609}
610
611static Bool
612drmmode_can_use_hw_cursor(xf86CrtcPtr crtc)
613{
614	RADEONInfoPtr info = RADEONPTR(crtc->scrn);
615
616	/* Check for Option "SWcursor" */
617	if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
618		return FALSE;
619
620	/* Fall back to SW cursor if the CRTC is transformed */
621	if (crtc->transformPresent)
622		return FALSE;
623
624#if XF86_CRTC_VERSION >= 4
625	/* Xorg doesn't correctly handle cursor position transform in the
626	 * rotation case
627	 */
628	if (crtc->driverIsPerformingTransform &&
629	    (crtc->rotation & 0xf) != RR_Rotate_0)
630		return FALSE;
631#endif
632
633#ifdef RADEON_PIXMAP_SHARING
634	/* HW cursor not supported yet with RandR 1.4 multihead */
635	if (!xorg_list_is_empty(&crtc->scrn->pScreen->pixmap_dirty_list))
636		return FALSE;
637#endif
638
639	return TRUE;
640}
641
642#if XF86_CRTC_VERSION >= 4
643
644static Bool
645drmmode_handle_transform(xf86CrtcPtr crtc)
646{
647	RADEONInfoPtr info = RADEONPTR(crtc->scrn);
648	Bool ret;
649
650	crtc->driverIsPerformingTransform = info->tear_free &&
651		!crtc->transformPresent && crtc->rotation != RR_Rotate_0;
652
653	ret = xf86CrtcRotate(crtc);
654
655	crtc->driverIsPerformingTransform &= ret && crtc->transform_in_use;
656
657	return ret;
658}
659
660#else
661
662static Bool
663drmmode_handle_transform(xf86CrtcPtr crtc)
664{
665	return xf86CrtcRotate(crtc);
666}
667
668#endif
669
670static Bool
671drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
672		     Rotation rotation, int x, int y)
673{
674	ScrnInfoPtr pScrn = crtc->scrn;
675	ScreenPtr pScreen = pScrn->pScreen;
676	RADEONInfoPtr info = RADEONPTR(pScrn);
677	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
678	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
679	drmmode_ptr drmmode = drmmode_crtc->drmmode;
680	int saved_x, saved_y;
681	Rotation saved_rotation;
682	DisplayModeRec saved_mode;
683	uint32_t *output_ids = NULL;
684	int output_count = 0;
685	Bool ret = TRUE;
686	int i;
687	int fb_id;
688	drmModeModeInfo kmode;
689	int pitch;
690	uint32_t tiling_flags = 0;
691
692	if (info->allowColorTiling) {
693		if (info->ChipFamily >= CHIP_FAMILY_R600)
694			tiling_flags |= RADEON_TILING_MICRO;
695		else
696			tiling_flags |= RADEON_TILING_MACRO;
697	}
698
699	pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
700		info->pixel_bytes;
701	if (info->ChipFamily >= CHIP_FAMILY_R600) {
702		pitch = info->front_surface.level[0].pitch_bytes;
703	}
704
705	if (drmmode->fb_id == 0) {
706		ret = drmModeAddFB(drmmode->fd,
707				   pScrn->virtualX, pScrn->virtualY,
708                                   pScrn->depth, pScrn->bitsPerPixel,
709				   pitch,
710				   info->front_bo->handle,
711                                   &drmmode->fb_id);
712                if (ret < 0) {
713                        ErrorF("failed to add fb\n");
714                        return FALSE;
715                }
716        }
717
718	saved_mode = crtc->mode;
719	saved_x = crtc->x;
720	saved_y = crtc->y;
721	saved_rotation = crtc->rotation;
722
723	if (mode) {
724		crtc->mode = *mode;
725		crtc->x = x;
726		crtc->y = y;
727		crtc->rotation = rotation;
728
729		output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
730		if (!output_ids) {
731			ret = FALSE;
732			goto done;
733		}
734
735		for (i = 0; i < xf86_config->num_output; i++) {
736			xf86OutputPtr output = xf86_config->output[i];
737			drmmode_output_private_ptr drmmode_output;
738
739			if (output->crtc != crtc)
740				continue;
741
742			drmmode_output = output->driver_private;
743			output_ids[output_count] = drmmode_output->mode_output->connector_id;
744			output_count++;
745		}
746
747		if (!drmmode_handle_transform(crtc))
748			goto done;
749
750		crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
751				       crtc->gamma_blue, crtc->gamma_size);
752
753		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
754
755		fb_id = drmmode->fb_id;
756#ifdef RADEON_PIXMAP_SHARING
757		if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
758			x = drmmode_crtc->prime_pixmap_x;
759			y = 0;
760
761			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
762			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
763		} else
764#endif
765		if (drmmode_crtc->rotate.fb_id) {
766			fb_id = drmmode_crtc->rotate.fb_id;
767			x = y = 0;
768
769			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
770			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
771		} else if (info->tear_free ||
772#if XF86_CRTC_VERSION >= 4
773			   crtc->driverIsPerformingTransform ||
774#endif
775			   info->shadow_primary) {
776			for (i = 0; i < (info->tear_free ? 2 : 1); i++) {
777				drmmode_crtc_scanout_create(crtc,
778							    &drmmode_crtc->scanout[i],
779							    mode->HDisplay,
780							    mode->VDisplay);
781
782				if (drmmode_crtc->scanout[i].pixmap) {
783					RegionPtr pRegion;
784					BoxPtr pBox;
785
786					if (!drmmode_crtc->scanout[i].damage) {
787						drmmode_crtc->scanout[i].damage =
788							DamageCreate(radeon_screen_damage_report,
789								     NULL, DamageReportRawRegion,
790								     TRUE, pScreen, NULL);
791						DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
792							       drmmode_crtc->scanout[i].damage);
793					}
794
795					pRegion = DamageRegion(drmmode_crtc->scanout[i].damage);
796					RegionUninit(pRegion);
797					pRegion->data = NULL;
798					pBox = RegionExtents(pRegion);
799					pBox->x1 = min(pBox->x1, x);
800					pBox->y1 = min(pBox->y1, y);
801
802					switch (crtc->rotation & 0xf) {
803					case RR_Rotate_90:
804					case RR_Rotate_270:
805						pBox->x2 = max(pBox->x2, x + mode->VDisplay);
806						pBox->y2 = max(pBox->y2, y + mode->HDisplay);
807						break;
808					default:
809						pBox->x2 = max(pBox->x2, x + mode->HDisplay);
810						pBox->y2 = max(pBox->y2, y + mode->VDisplay);
811					}
812				}
813			}
814
815			if (drmmode_crtc->scanout[0].pixmap &&
816			    (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) {
817				drmmode_crtc->scanout_id = 0;
818				fb_id = drmmode_crtc->scanout[0].fb_id;
819				x = y = 0;
820
821				radeon_scanout_update_handler(crtc, 0, 0, drmmode_crtc);
822				radeon_bo_wait(drmmode_crtc->scanout[0].bo);
823			}
824		}
825
826		/* Wait for any pending flip to finish */
827		do {} while (drmmode_crtc->flip_pending &&
828			     drmHandleEvent(drmmode->fd,
829					    &drmmode->event_context) > 0);
830
831		if (drmModeSetCrtc(drmmode->fd,
832				   drmmode_crtc->mode_crtc->crtc_id,
833				   fb_id, x, y, output_ids,
834				   output_count, &kmode) != 0) {
835			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
836				   "failed to set mode: %s", strerror(errno));
837			ret = FALSE;
838			goto done;
839		} else
840			ret = TRUE;
841
842		if (pScreen)
843			xf86CrtcSetScreenSubpixelOrder(pScreen);
844
845		drmmode_crtc->need_modeset = FALSE;
846
847		/* go through all the outputs and force DPMS them back on? */
848		for (i = 0; i < xf86_config->num_output; i++) {
849			xf86OutputPtr output = xf86_config->output[i];
850
851			if (output->crtc != crtc)
852				continue;
853
854			output->funcs->dpms(output, DPMSModeOn);
855		}
856	}
857
858	/* Compute index of this CRTC into xf86_config->crtc */
859	for (i = 0; i < xf86_config->num_crtc; i++) {
860		if (xf86_config->crtc[i] != crtc)
861			continue;
862
863		if (!crtc->enabled || drmmode_can_use_hw_cursor(crtc))
864			info->hwcursor_disabled &= ~(1 << i);
865		else
866			info->hwcursor_disabled |= 1 << i;
867
868		break;
869	}
870
871#ifndef HAVE_XF86_CURSOR_RESET_CURSOR
872	if (!info->hwcursor_disabled)
873		xf86_reload_cursors(pScreen);
874#endif
875
876done:
877	if (!ret) {
878		crtc->x = saved_x;
879		crtc->y = saved_y;
880		crtc->rotation = saved_rotation;
881		crtc->mode = saved_mode;
882	} else
883		crtc->active = TRUE;
884
885	free(output_ids);
886
887	return ret;
888}
889
890static void
891drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
892{
893
894}
895
896static void
897drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
898{
899	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
900	drmmode_ptr drmmode = drmmode_crtc->drmmode;
901
902#if XF86_CRTC_VERSION >= 4
903	if (crtc->driverIsPerformingTransform) {
904		x += crtc->x;
905		y += crtc->y;
906		xf86CrtcTransformCursorPos(crtc, &x, &y);
907	}
908#endif
909
910	drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
911}
912
913#if XF86_CRTC_VERSION >= 4
914
915static int
916drmmode_cursor_src_offset(Rotation rotation, int width, int height,
917			  int x_dst, int y_dst)
918{
919	int t;
920
921	switch (rotation & 0xf) {
922	case RR_Rotate_90:
923		t = x_dst;
924		x_dst = height - y_dst - 1;
925		y_dst = t;
926		break;
927	case RR_Rotate_180:
928		x_dst = width - x_dst - 1;
929		y_dst = height - y_dst - 1;
930		break;
931	case RR_Rotate_270:
932		t = x_dst;
933		x_dst = y_dst;
934		y_dst = width - t - 1;
935		break;
936	}
937
938	if (rotation & RR_Reflect_X)
939		x_dst = width - x_dst - 1;
940	if (rotation & RR_Reflect_Y)
941		y_dst = height - y_dst - 1;
942
943	return y_dst * height + x_dst;
944}
945
946#endif
947
948static void
949drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
950{
951	ScrnInfoPtr pScrn = crtc->scrn;
952	RADEONInfoPtr info = RADEONPTR(pScrn);
953	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
954	uint32_t *ptr;
955
956	/* cursor should be mapped already */
957	ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
958
959#if XF86_CRTC_VERSION >= 4
960	if (crtc->driverIsPerformingTransform) {
961		uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h;
962		int dstx, dsty;
963		int srcoffset;
964
965		for (dsty = 0; dsty < cursor_h; dsty++) {
966			for (dstx = 0; dstx < cursor_w; dstx++) {
967				srcoffset = drmmode_cursor_src_offset(crtc->rotation,
968								      cursor_w,
969								      cursor_h,
970								      dstx, dsty);
971
972				ptr[dsty * info->cursor_w + dstx] =
973					cpu_to_le32(image[srcoffset]);
974			}
975		}
976	} else
977#endif
978	{
979		uint32_t cursor_size = info->cursor_w * info->cursor_h;
980		int i;
981
982		for (i = 0; i < cursor_size; i++)
983			ptr[i] = cpu_to_le32(image[i]);
984	}
985}
986
987#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
988
989static Bool drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 * image)
990{
991	if (!drmmode_can_use_hw_cursor(crtc))
992		return FALSE;
993
994	drmmode_load_cursor_argb(crtc, image);
995	return TRUE;
996}
997
998#endif
999
1000static void
1001drmmode_hide_cursor (xf86CrtcPtr crtc)
1002{
1003	ScrnInfoPtr pScrn = crtc->scrn;
1004	RADEONInfoPtr info = RADEONPTR(pScrn);
1005	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1006	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1007
1008	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
1009			 info->cursor_w, info->cursor_h);
1010
1011}
1012
1013static void
1014drmmode_show_cursor (xf86CrtcPtr crtc)
1015{
1016	ScrnInfoPtr pScrn = crtc->scrn;
1017	RADEONInfoPtr info = RADEONPTR(pScrn);
1018	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1019	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1020	uint32_t handle = drmmode_crtc->cursor_bo->handle;
1021	static Bool use_set_cursor2 = TRUE;
1022
1023	if (use_set_cursor2) {
1024	    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
1025	    CursorPtr cursor = xf86_config->cursor;
1026	    int ret;
1027
1028	    ret =
1029		drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1030				  handle, info->cursor_w, info->cursor_h,
1031				  cursor->bits->xhot, cursor->bits->yhot);
1032	    if (ret == -EINVAL)
1033		use_set_cursor2 = FALSE;
1034	    else
1035		return;
1036	}
1037
1038	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
1039			 info->cursor_w, info->cursor_h);
1040}
1041
1042static void *
1043drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
1044{
1045	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1046
1047	return drmmode_crtc_scanout_allocate(crtc, &drmmode_crtc->rotate,
1048					     width, height);
1049}
1050
1051static PixmapPtr
1052drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
1053{
1054	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1055
1056	/* Xorg passes in the return value of drmmode_crtc_shadow_allocate
1057	 * for data, but that's redundant for drmmode_crtc_scanout_create.
1058	 */
1059	return drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width,
1060					   height);
1061}
1062
1063static void
1064drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
1065{
1066	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1067	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1068
1069	drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->rotate);
1070}
1071
1072static void
1073drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
1074                      uint16_t *blue, int size)
1075{
1076	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1077	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1078
1079	drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1080			    size, red, green, blue);
1081}
1082
1083#ifdef RADEON_PIXMAP_SHARING
1084static Bool
1085drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
1086{
1087	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
1088	PixmapPtr screenpix = screen->GetScreenPixmap(screen);
1089	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
1090	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1091	int c, total_width = 0, max_height = 0, this_x = 0;
1092
1093	if (!ppix) {
1094		if (crtc->randr_crtc->scanout_pixmap)
1095			PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
1096		drmmode_crtc->prime_pixmap_x = 0;
1097		return TRUE;
1098	}
1099
1100	/* iterate over all the attached crtcs -
1101	   work out bounding box */
1102	for (c = 0; c < xf86_config->num_crtc; c++) {
1103		xf86CrtcPtr iter = xf86_config->crtc[c];
1104		if (!iter->enabled && iter != crtc)
1105			continue;
1106		if (iter == crtc) {
1107			this_x = total_width;
1108			total_width += ppix->drawable.width;
1109			if (max_height < ppix->drawable.height)
1110				max_height = ppix->drawable.height;
1111		} else {
1112			total_width += iter->mode.HDisplay;
1113			if (max_height < iter->mode.VDisplay)
1114				max_height = iter->mode.VDisplay;
1115		}
1116#if !defined(HAS_DIRTYTRACKING_ROTATION) && !defined(HAS_DIRTYTRACKING2)
1117		if (iter != crtc) {
1118			ErrorF("Cannot do multiple crtcs without X server dirty tracking 2 interface\n");
1119			return FALSE;
1120		}
1121#endif
1122	}
1123
1124	if (total_width != screenpix->drawable.width ||
1125	    max_height != screenpix->drawable.height) {
1126		Bool ret;
1127		ret = drmmode_xf86crtc_resize(crtc->scrn, total_width, max_height);
1128		if (ret == FALSE)
1129			return FALSE;
1130
1131		screenpix = screen->GetScreenPixmap(screen);
1132		screen->width = screenpix->drawable.width = total_width;
1133		screen->height = screenpix->drawable.height = max_height;
1134	}
1135	drmmode_crtc->prime_pixmap_x = this_x;
1136#ifdef HAS_DIRTYTRACKING_ROTATION
1137	PixmapStartDirtyTracking(ppix, screenpix, 0, 0, this_x, 0, RR_Rotate_0);
1138#elif defined(HAS_DIRTYTRACKING2)
1139	PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0);
1140#else
1141	PixmapStartDirtyTracking(ppix, screenpix, 0, 0);
1142#endif
1143	return TRUE;
1144}
1145#endif
1146
1147static xf86CrtcFuncsRec drmmode_crtc_funcs = {
1148    .dpms = drmmode_crtc_dpms,
1149    .set_mode_major = drmmode_set_mode_major,
1150    .set_cursor_colors = drmmode_set_cursor_colors,
1151    .set_cursor_position = drmmode_set_cursor_position,
1152    .show_cursor = drmmode_show_cursor,
1153    .hide_cursor = drmmode_hide_cursor,
1154    .load_cursor_argb = drmmode_load_cursor_argb,
1155#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
1156    .load_cursor_argb_check = drmmode_load_cursor_argb_check,
1157#endif
1158
1159    .gamma_set = drmmode_crtc_gamma_set,
1160    .shadow_create = drmmode_crtc_shadow_create,
1161    .shadow_allocate = drmmode_crtc_shadow_allocate,
1162    .shadow_destroy = drmmode_crtc_shadow_destroy,
1163    .destroy = NULL, /* XXX */
1164#ifdef RADEON_PIXMAP_SHARING
1165    .set_scanout_pixmap = drmmode_set_scanout_pixmap,
1166#endif
1167};
1168
1169int drmmode_get_crtc_id(xf86CrtcPtr crtc)
1170{
1171	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1172	return drmmode_crtc->hw_id;
1173}
1174
1175void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
1176{
1177	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1178	ScrnInfoPtr pScrn = crtc->scrn;
1179	RADEONInfoPtr info = RADEONPTR(pScrn);
1180	struct drm_radeon_info ginfo;
1181	int r;
1182	uint32_t tmp;
1183
1184	memset(&ginfo, 0, sizeof(ginfo));
1185	ginfo.request = 0x4;
1186	tmp = drmmode_crtc->mode_crtc->crtc_id;
1187	ginfo.value = (uintptr_t)&tmp;
1188	r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1189	if (r) {
1190		drmmode_crtc->hw_id = -1;
1191		return;
1192	}
1193	drmmode_crtc->hw_id = tmp;
1194}
1195
1196static unsigned int
1197drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
1198{
1199	xf86CrtcPtr crtc;
1200	drmmode_crtc_private_ptr drmmode_crtc;
1201	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1202
1203	crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
1204	if (crtc == NULL)
1205		return 0;
1206
1207	drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
1208	drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
1209	drmmode_crtc->drmmode = drmmode;
1210	drmmode_crtc->dpms_mode = DPMSModeOff;
1211	crtc->driver_private = drmmode_crtc;
1212	drmmode_crtc_hw_id(crtc);
1213
1214	/* Mark num'th crtc as in use on this device. */
1215	pRADEONEnt->assigned_crtcs |= (1 << num);
1216	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1217		       "Allocated crtc nr. %d to this screen.\n", num);
1218
1219	return 1;
1220}
1221
1222static xf86OutputStatus
1223drmmode_output_detect(xf86OutputPtr output)
1224{
1225	/* go to the hw and retrieve a new output struct */
1226	drmmode_output_private_ptr drmmode_output = output->driver_private;
1227	drmmode_ptr drmmode = drmmode_output->drmmode;
1228	xf86OutputStatus status;
1229	drmModeFreeConnector(drmmode_output->mode_output);
1230
1231	drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
1232	if (!drmmode_output->mode_output)
1233		return XF86OutputStatusDisconnected;
1234
1235	switch (drmmode_output->mode_output->connection) {
1236	case DRM_MODE_CONNECTED:
1237		status = XF86OutputStatusConnected;
1238		break;
1239	case DRM_MODE_DISCONNECTED:
1240		status = XF86OutputStatusDisconnected;
1241		break;
1242	default:
1243	case DRM_MODE_UNKNOWNCONNECTION:
1244		status = XF86OutputStatusUnknown;
1245		break;
1246	}
1247	return status;
1248}
1249
1250static Bool
1251drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
1252{
1253	return MODE_OK;
1254}
1255
1256static DisplayModePtr
1257drmmode_output_get_modes(xf86OutputPtr output)
1258{
1259	drmmode_output_private_ptr drmmode_output = output->driver_private;
1260	drmModeConnectorPtr koutput = drmmode_output->mode_output;
1261	drmmode_ptr drmmode = drmmode_output->drmmode;
1262	int i;
1263	DisplayModePtr Modes = NULL, Mode;
1264	drmModePropertyPtr props;
1265	xf86MonPtr mon = NULL;
1266
1267	if (!koutput)
1268		return NULL;
1269
1270	/* look for an EDID property */
1271	for (i = 0; i < koutput->count_props; i++) {
1272		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
1273		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
1274			if (!strcmp(props->name, "EDID")) {
1275				if (drmmode_output->edid_blob)
1276					drmModeFreePropertyBlob(drmmode_output->edid_blob);
1277				drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
1278			}
1279		}
1280		if (props)
1281			drmModeFreeProperty(props);
1282	}
1283
1284	if (drmmode_output->edid_blob) {
1285		mon = xf86InterpretEDID(output->scrn->scrnIndex,
1286					drmmode_output->edid_blob->data);
1287		if (mon && drmmode_output->edid_blob->length > 128)
1288			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
1289	}
1290	xf86OutputSetEDID(output, mon);
1291
1292	/* modes should already be available */
1293	for (i = 0; i < koutput->count_modes; i++) {
1294		Mode = xnfalloc(sizeof(DisplayModeRec));
1295
1296		drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
1297		Modes = xf86ModesAdd(Modes, Mode);
1298
1299	}
1300	return Modes;
1301}
1302
1303static void
1304drmmode_output_destroy(xf86OutputPtr output)
1305{
1306	drmmode_output_private_ptr drmmode_output = output->driver_private;
1307	int i;
1308
1309	if (drmmode_output->edid_blob)
1310		drmModeFreePropertyBlob(drmmode_output->edid_blob);
1311	for (i = 0; i < drmmode_output->num_props; i++) {
1312		drmModeFreeProperty(drmmode_output->props[i].mode_prop);
1313		free(drmmode_output->props[i].atoms);
1314	}
1315	for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
1316		drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
1317	}
1318	free(drmmode_output->mode_encoders);
1319	free(drmmode_output->props);
1320	drmModeFreeConnector(drmmode_output->mode_output);
1321	free(drmmode_output);
1322	output->driver_private = NULL;
1323}
1324
1325static void
1326drmmode_output_dpms(xf86OutputPtr output, int mode)
1327{
1328	drmmode_output_private_ptr drmmode_output = output->driver_private;
1329	xf86CrtcPtr crtc = output->crtc;
1330	drmModeConnectorPtr koutput = drmmode_output->mode_output;
1331	drmmode_ptr drmmode = drmmode_output->drmmode;
1332
1333	if (!koutput)
1334		return;
1335
1336	if (mode != DPMSModeOn && crtc)
1337		drmmode_do_crtc_dpms(crtc, mode);
1338
1339	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
1340				    drmmode_output->dpms_enum_id, mode);
1341
1342	if (mode == DPMSModeOn && crtc) {
1343	    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1344
1345	    if (drmmode_crtc->need_modeset)
1346		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x,
1347				       crtc->y);
1348	    else
1349		drmmode_do_crtc_dpms(crtc, mode);
1350	}
1351}
1352
1353
1354static Bool
1355drmmode_property_ignore(drmModePropertyPtr prop)
1356{
1357    if (!prop)
1358	return TRUE;
1359    /* ignore blob prop */
1360    if (prop->flags & DRM_MODE_PROP_BLOB)
1361	return TRUE;
1362    /* ignore standard property */
1363    if (!strcmp(prop->name, "EDID") ||
1364	    !strcmp(prop->name, "DPMS"))
1365	return TRUE;
1366
1367    return FALSE;
1368}
1369
1370static void
1371drmmode_output_create_resources(xf86OutputPtr output)
1372{
1373    drmmode_output_private_ptr drmmode_output = output->driver_private;
1374    drmModeConnectorPtr mode_output = drmmode_output->mode_output;
1375    drmmode_ptr drmmode = drmmode_output->drmmode;
1376    drmModePropertyPtr drmmode_prop;
1377    int i, j, err;
1378
1379    drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
1380    if (!drmmode_output->props)
1381	return;
1382
1383    drmmode_output->num_props = 0;
1384    for (i = 0, j = 0; i < mode_output->count_props; i++) {
1385	drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
1386	if (drmmode_property_ignore(drmmode_prop)) {
1387	    drmModeFreeProperty(drmmode_prop);
1388	    continue;
1389	}
1390	drmmode_output->props[j].mode_prop = drmmode_prop;
1391	drmmode_output->props[j].value = mode_output->prop_values[i];
1392	drmmode_output->num_props++;
1393	j++;
1394    }
1395
1396    for (i = 0; i < drmmode_output->num_props; i++) {
1397	drmmode_prop_ptr p = &drmmode_output->props[i];
1398	drmmode_prop = p->mode_prop;
1399
1400	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
1401	    INT32 range[2];
1402	    INT32 value = p->value;
1403
1404	    p->num_atoms = 1;
1405	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
1406	    if (!p->atoms)
1407		continue;
1408	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1409	    range[0] = drmmode_prop->values[0];
1410	    range[1] = drmmode_prop->values[1];
1411	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1412		    FALSE, TRUE,
1413		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1414		    2, range);
1415	    if (err != 0) {
1416		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1417			"RRConfigureOutputProperty error, %d\n", err);
1418	    }
1419	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1420		    XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE);
1421	    if (err != 0) {
1422		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1423			"RRChangeOutputProperty error, %d\n", err);
1424	    }
1425	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
1426	    p->num_atoms = drmmode_prop->count_enums + 1;
1427	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
1428	    if (!p->atoms)
1429		continue;
1430	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1431	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
1432		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
1433		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
1434	    }
1435	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1436		    FALSE, FALSE,
1437		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1438		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
1439	    if (err != 0) {
1440		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1441			"RRConfigureOutputProperty error, %d\n", err);
1442	    }
1443	    for (j = 0; j < drmmode_prop->count_enums; j++)
1444		if (drmmode_prop->enums[j].value == p->value)
1445		    break;
1446	    /* there's always a matching value */
1447	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1448		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
1449	    if (err != 0) {
1450		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1451			"RRChangeOutputProperty error, %d\n", err);
1452	    }
1453	}
1454    }
1455}
1456
1457static Bool
1458drmmode_output_set_property(xf86OutputPtr output, Atom property,
1459		RRPropertyValuePtr value)
1460{
1461    drmmode_output_private_ptr drmmode_output = output->driver_private;
1462    drmmode_ptr drmmode = drmmode_output->drmmode;
1463    int i;
1464
1465    for (i = 0; i < drmmode_output->num_props; i++) {
1466	drmmode_prop_ptr p = &drmmode_output->props[i];
1467
1468	if (p->atoms[0] != property)
1469	    continue;
1470
1471	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
1472	    uint32_t val;
1473
1474	    if (value->type != XA_INTEGER || value->format != 32 ||
1475		    value->size != 1)
1476		return FALSE;
1477	    val = *(uint32_t *)value->data;
1478
1479	    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
1480		    p->mode_prop->prop_id, (uint64_t)val);
1481	    return TRUE;
1482	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
1483	    Atom	atom;
1484	    const char	*name;
1485	    int		j;
1486
1487	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
1488		return FALSE;
1489	    memcpy(&atom, value->data, 4);
1490	    name = NameForAtom(atom);
1491
1492	    /* search for matching name string, then set its value down */
1493	    for (j = 0; j < p->mode_prop->count_enums; j++) {
1494		if (!strcmp(p->mode_prop->enums[j].name, name)) {
1495		    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
1496			    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
1497		    return TRUE;
1498		}
1499	    }
1500	}
1501    }
1502
1503    return TRUE;
1504}
1505
1506static Bool
1507drmmode_output_get_property(xf86OutputPtr output, Atom property)
1508{
1509    return TRUE;
1510}
1511
1512static const xf86OutputFuncsRec drmmode_output_funcs = {
1513    .dpms = drmmode_output_dpms,
1514    .create_resources = drmmode_output_create_resources,
1515    .set_property = drmmode_output_set_property,
1516    .get_property = drmmode_output_get_property,
1517#if 0
1518
1519    .save = drmmode_crt_save,
1520    .restore = drmmode_crt_restore,
1521    .mode_fixup = drmmode_crt_mode_fixup,
1522    .prepare = drmmode_output_prepare,
1523    .mode_set = drmmode_crt_mode_set,
1524    .commit = drmmode_output_commit,
1525#endif
1526    .detect = drmmode_output_detect,
1527    .mode_valid = drmmode_output_mode_valid,
1528
1529    .get_modes = drmmode_output_get_modes,
1530    .destroy = drmmode_output_destroy
1531};
1532
1533static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
1534				      SubPixelHorizontalRGB,
1535				      SubPixelHorizontalBGR,
1536				      SubPixelVerticalRGB,
1537				      SubPixelVerticalBGR,
1538				      SubPixelNone };
1539
1540const char *output_names[] = { "None",
1541			       "VGA",
1542			       "DVI",
1543			       "DVI",
1544			       "DVI",
1545			       "Composite",
1546			       "S-video",
1547			       "LVDS",
1548			       "CTV",
1549			       "DIN",
1550			       "DisplayPort",
1551			       "HDMI",
1552			       "HDMI",
1553			       "TV",
1554			       "eDP"
1555};
1556
1557#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
1558
1559static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id)
1560{
1561	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1562	int i;
1563	for (i = 0; i < xf86_config->num_output; i++) {
1564		xf86OutputPtr output = xf86_config->output[i];
1565		drmmode_output_private_ptr drmmode_output;
1566
1567		drmmode_output = output->driver_private;
1568		if (drmmode_output->output_id == id)
1569			return output;
1570	}
1571	return NULL;
1572}
1573
1574static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path)
1575{
1576	char *conn;
1577	char conn_id[5];
1578	int id, len;
1579	char *blob_data;
1580
1581	if (!path_blob)
1582		return -1;
1583
1584	blob_data = path_blob->data;
1585	/* we only handle MST paths for now */
1586	if (strncmp(blob_data, "mst:", 4))
1587		return -1;
1588
1589	conn = strchr(blob_data + 4, '-');
1590	if (!conn)
1591		return -1;
1592	len = conn - (blob_data + 4);
1593	if (len + 1 > 5)
1594		return -1;
1595	memcpy(conn_id, blob_data + 4, len);
1596	conn_id[len] = '\0';
1597	id = strtoul(conn_id, NULL, 10);
1598
1599	*conn_base_id = id;
1600
1601	*path = conn + 1;
1602	return 0;
1603}
1604
1605static void
1606drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
1607		    drmModePropertyBlobPtr path_blob, int *num_dvi, int *num_hdmi)
1608{
1609	xf86OutputPtr output;
1610	int conn_id;
1611	char *extra_path;
1612
1613	output = NULL;
1614	if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0)
1615		output = find_output(pScrn, conn_id);
1616	if (output) {
1617		snprintf(name, 32, "%s-%s", output->name, extra_path);
1618	} else {
1619		if (koutput->connector_type >= NUM_OUTPUT_NAMES)
1620			snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
1621				 koutput->connector_type_id - 1);
1622#ifdef RADEON_PIXMAP_SHARING
1623		else if (pScrn->is_gpu)
1624			snprintf(name, 32, "%s-%d-%d",
1625				 output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
1626				 koutput->connector_type_id - 1);
1627#endif
1628		else {
1629			/* need to do smart conversion here for compat with non-kms ATI driver */
1630			if (koutput->connector_type_id == 1) {
1631				switch(koutput->connector_type) {
1632				case DRM_MODE_CONNECTOR_DVII:
1633				case DRM_MODE_CONNECTOR_DVID:
1634				case DRM_MODE_CONNECTOR_DVIA:
1635					snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
1636					(*num_dvi)++;
1637					break;
1638				case DRM_MODE_CONNECTOR_HDMIA:
1639				case DRM_MODE_CONNECTOR_HDMIB:
1640					snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
1641					(*num_hdmi)++;
1642					break;
1643				case DRM_MODE_CONNECTOR_VGA:
1644				case DRM_MODE_CONNECTOR_DisplayPort:
1645					snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
1646						 koutput->connector_type_id - 1);
1647					break;
1648				default:
1649					snprintf(name, 32, "%s", output_names[koutput->connector_type]);
1650					break;
1651				}
1652			} else {
1653				snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
1654					 koutput->connector_type_id - 1);
1655			}
1656		}
1657	}
1658}
1659
1660static unsigned int
1661drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic)
1662{
1663	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1664	RADEONInfoPtr info = RADEONPTR(pScrn);
1665	xf86OutputPtr output;
1666	drmModeConnectorPtr koutput;
1667	drmModeEncoderPtr *kencoders = NULL;
1668	drmmode_output_private_ptr drmmode_output;
1669	drmModePropertyPtr props;
1670	drmModePropertyBlobPtr path_blob = NULL;
1671	char name[32];
1672	int i;
1673	const char *s;
1674
1675	koutput = drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
1676	if (!koutput)
1677		return 0;
1678
1679	for (i = 0; i < koutput->count_props; i++) {
1680		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
1681		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
1682			if (!strcmp(props->name, "PATH")) {
1683				path_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
1684				drmModeFreeProperty(props);
1685				break;
1686			}
1687			drmModeFreeProperty(props);
1688		}
1689	}
1690
1691	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
1692	if (!kencoders) {
1693		goto out_free_encoders;
1694	}
1695
1696	for (i = 0; i < koutput->count_encoders; i++) {
1697		kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
1698		if (!kencoders[i]) {
1699			goto out_free_encoders;
1700		}
1701	}
1702
1703	drmmode_create_name(pScrn, koutput, name, path_blob, num_dvi, num_hdmi);
1704	if (path_blob)
1705		drmModeFreePropertyBlob(path_blob);
1706
1707	if (path_blob && dynamic) {
1708		/* See if we have an output with this name already
1709		 * and hook stuff up.
1710		 */
1711		for (i = 0; i < xf86_config->num_output; i++) {
1712			output = xf86_config->output[i];
1713
1714			if (strncmp(output->name, name, 32))
1715				continue;
1716
1717			drmmode_output = output->driver_private;
1718			drmmode_output->output_id = mode_res->connectors[num];
1719			drmmode_output->mode_output = koutput;
1720			for (i = 0; i < koutput->count_encoders; i++)
1721				drmModeFreeEncoder(kencoders[i]);
1722			free(kencoders);
1723			return 0;
1724		}
1725	}
1726
1727	if (xf86IsEntityShared(pScrn->entityList[0])) {
1728		if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) {
1729			if (!RADEONZaphodStringMatches(pScrn, s, name))
1730				goto out_free_encoders;
1731		} else {
1732			if (!info->IsSecondary && (num != 0))
1733				goto out_free_encoders;
1734			else if (info->IsSecondary && (num != 1))
1735				goto out_free_encoders;
1736		}
1737	}
1738
1739	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
1740	if (!output) {
1741		goto out_free_encoders;
1742	}
1743
1744	drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
1745	if (!drmmode_output) {
1746		xf86OutputDestroy(output);
1747		goto out_free_encoders;
1748	}
1749
1750	drmmode_output->output_id = mode_res->connectors[num];
1751	drmmode_output->mode_output = koutput;
1752	drmmode_output->mode_encoders = kencoders;
1753	drmmode_output->drmmode = drmmode;
1754	output->mm_width = koutput->mmWidth;
1755	output->mm_height = koutput->mmHeight;
1756
1757	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
1758	output->interlaceAllowed = TRUE;
1759	output->doubleScanAllowed = TRUE;
1760	output->driver_private = drmmode_output;
1761
1762	output->possible_crtcs = 0xffffffff;
1763	for (i = 0; i < koutput->count_encoders; i++) {
1764		output->possible_crtcs &= kencoders[i]->possible_crtcs;
1765	}
1766	/* work out the possible clones later */
1767	output->possible_clones = 0;
1768
1769	for (i = 0; i < koutput->count_props; i++) {
1770		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
1771		if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
1772			if (!strcmp(props->name, "DPMS")) {
1773				drmmode_output->dpms_enum_id = koutput->props[i];
1774				drmModeFreeProperty(props);
1775				break;
1776			}
1777			drmModeFreeProperty(props);
1778		}
1779	}
1780
1781	if (dynamic) {
1782		output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
1783		drmmode_output_create_resources(output);
1784	}
1785
1786	return 1;
1787out_free_encoders:
1788	if (kencoders){
1789		for (i = 0; i < koutput->count_encoders; i++)
1790			drmModeFreeEncoder(kencoders[i]);
1791		free(kencoders);
1792	}
1793	drmModeFreeConnector(koutput);
1794	return 0;
1795}
1796
1797uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
1798{
1799	drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
1800	int i;
1801	xf86OutputPtr clone_output;
1802	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1803	int index_mask = 0;
1804
1805	if (drmmode_output->enc_clone_mask == 0)
1806		return index_mask;
1807
1808	for (i = 0; i < xf86_config->num_output; i++) {
1809		clone_output = xf86_config->output[i];
1810		clone_drmout = clone_output->driver_private;
1811		if (output == clone_output)
1812			continue;
1813
1814		if (clone_drmout->enc_mask == 0)
1815			continue;
1816		if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
1817			index_mask |= (1 << i);
1818	}
1819	return index_mask;
1820}
1821
1822
1823static void
1824drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res)
1825{
1826	int i, j;
1827	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1828
1829	for (i = 0; i < xf86_config->num_output; i++) {
1830		xf86OutputPtr output = xf86_config->output[i];
1831		drmmode_output_private_ptr drmmode_output;
1832
1833		drmmode_output = output->driver_private;
1834		drmmode_output->enc_clone_mask = 0xff;
1835		/* and all the possible encoder clones for this output together */
1836		for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
1837		{
1838			int k;
1839			for (k = 0; k < mode_res->count_encoders; k++) {
1840				if (mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
1841					drmmode_output->enc_mask |= (1 << k);
1842			}
1843
1844			drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
1845		}
1846	}
1847
1848	for (i = 0; i < xf86_config->num_output; i++) {
1849		xf86OutputPtr output = xf86_config->output[i];
1850		output->possible_clones = find_clones(scrn, output);
1851	}
1852}
1853
1854/* returns height alignment in pixels */
1855int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling)
1856{
1857	RADEONInfoPtr info = RADEONPTR(scrn);
1858	int height_align = 1;
1859
1860	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1861		if (tiling & RADEON_TILING_MACRO)
1862			height_align =  info->num_channels * 8;
1863		else if (tiling & RADEON_TILING_MICRO)
1864			height_align = 8;
1865		else
1866			height_align = 8;
1867	} else {
1868		if (tiling & RADEON_TILING_MICRO_SQUARE)
1869			height_align =  32;
1870		else if (tiling)
1871			height_align = 16;
1872		else
1873			height_align = 1;
1874	}
1875	return height_align;
1876}
1877
1878/* returns pitch alignment in pixels */
1879int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1880{
1881	RADEONInfoPtr info = RADEONPTR(scrn);
1882	int pitch_align = 1;
1883
1884	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1885		if (tiling & RADEON_TILING_MACRO) {
1886			/* general surface requirements */
1887			pitch_align = MAX(info->num_banks,
1888					  (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8;
1889			/* further restrictions for scanout */
1890			pitch_align = MAX(info->num_banks * 8, pitch_align);
1891		} else if (tiling & RADEON_TILING_MICRO) {
1892			/* general surface requirements */
1893			pitch_align = MAX(8, (info->group_bytes / (8 * bpe)));
1894			/* further restrictions for scanout */
1895			pitch_align = MAX(info->group_bytes / bpe, pitch_align);
1896		} else {
1897			if (info->have_tiling_info)
1898				/* linear aligned requirements */
1899				pitch_align = MAX(64, info->group_bytes / bpe);
1900			else
1901				/* default to 512 elements if we don't know the real
1902				 * group size otherwise the kernel may reject the CS
1903				 * if the group sizes don't match as the pitch won't
1904				 * be aligned properly.
1905				 */
1906				pitch_align = 512;
1907		}
1908	} else {
1909		/* general surface requirements */
1910		if (tiling)
1911			pitch_align = 256 / bpe;
1912		else
1913			pitch_align = 64;
1914	}
1915	return pitch_align;
1916}
1917
1918/* returns base alignment in bytes */
1919int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1920{
1921	RADEONInfoPtr info = RADEONPTR(scrn);
1922	int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling);
1923	int height_align = drmmode_get_height_align(scrn, tiling);
1924	int base_align = RADEON_GPU_PAGE_SIZE;
1925
1926	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1927		if (tiling & RADEON_TILING_MACRO)
1928			base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe,
1929					 pixel_align * bpe * height_align);
1930		else {
1931			if (info->have_tiling_info)
1932				base_align = info->group_bytes;
1933			else
1934				/* default to 512 if we don't know the real
1935				 * group size otherwise the kernel may reject the CS
1936				 * if the group sizes don't match as the base won't
1937				 * be aligned properly.
1938				 */
1939				base_align = 512;
1940		}
1941	}
1942	return base_align;
1943}
1944
1945static Bool
1946drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
1947{
1948	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1949	drmmode_crtc_private_ptr
1950		    drmmode_crtc = xf86_config->crtc[0]->driver_private;
1951	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1952	RADEONInfoPtr info = RADEONPTR(scrn);
1953	struct radeon_bo *old_front = NULL;
1954	Bool	    ret;
1955	ScreenPtr   screen = xf86ScrnToScreen(scrn);
1956	uint32_t    old_fb_id;
1957	int	    i, pitch, old_width, old_height, old_pitch;
1958	int aligned_height;
1959	uint32_t screen_size;
1960	int cpp = info->pixel_bytes;
1961	struct radeon_bo *front_bo;
1962	struct radeon_surface surface;
1963	struct radeon_surface *psurface;
1964	uint32_t tiling_flags = 0, base_align;
1965	PixmapPtr ppix = screen->GetScreenPixmap(screen);
1966	void *fb_shadow;
1967	xRectangle rect;
1968	Bool force;
1969	GCPtr gc;
1970
1971	if (scrn->virtualX == width && scrn->virtualY == height)
1972		return TRUE;
1973
1974	front_bo = info->front_bo;
1975	radeon_cs_flush_indirect(scrn);
1976
1977	if (front_bo)
1978		radeon_bo_wait(front_bo);
1979
1980	if (info->allowColorTiling && !info->shadow_primary) {
1981		if (info->ChipFamily >= CHIP_FAMILY_R600) {
1982			if (info->allowColorTiling2D) {
1983				tiling_flags |= RADEON_TILING_MACRO;
1984			} else {
1985				tiling_flags |= RADEON_TILING_MICRO;
1986			}
1987		} else
1988			tiling_flags |= RADEON_TILING_MACRO;
1989	}
1990
1991	pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
1992	aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
1993	screen_size = RADEON_ALIGN(pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
1994	base_align = 4096;
1995	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1996		memset(&surface, 0, sizeof(struct radeon_surface));
1997		surface.npix_x = width;
1998		surface.npix_y = height;
1999		surface.npix_z = 1;
2000		surface.blk_w = 1;
2001		surface.blk_h = 1;
2002		surface.blk_d = 1;
2003		surface.array_size = 1;
2004		surface.last_level = 0;
2005		surface.bpe = cpp;
2006		surface.nsamples = 1;
2007		surface.flags = RADEON_SURF_SCANOUT;
2008		/* we are requiring a recent enough libdrm version */
2009		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
2010		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
2011		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
2012		if (tiling_flags & RADEON_TILING_MICRO) {
2013			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
2014			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2015		}
2016		if (tiling_flags & RADEON_TILING_MACRO) {
2017			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
2018			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2019		}
2020		if (radeon_surface_best(info->surf_man, &surface)) {
2021			return FALSE;
2022		}
2023		if (radeon_surface_init(info->surf_man, &surface)) {
2024			return FALSE;
2025		}
2026		screen_size = surface.bo_size;
2027		base_align = surface.bo_alignment;
2028		pitch = surface.level[0].pitch_bytes;
2029		tiling_flags = 0;
2030		switch (surface.level[0].mode) {
2031		case RADEON_SURF_MODE_2D:
2032			tiling_flags |= RADEON_TILING_MACRO;
2033			tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
2034			tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
2035			tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
2036			if (surface.tile_split)
2037				tiling_flags |= eg_tile_split(surface.tile_split)
2038						<< RADEON_TILING_EG_TILE_SPLIT_SHIFT;
2039			break;
2040		case RADEON_SURF_MODE_1D:
2041			tiling_flags |= RADEON_TILING_MICRO;
2042			break;
2043		default:
2044			break;
2045		}
2046		info->front_surface = surface;
2047	}
2048
2049	xf86DrvMsg(scrn->scrnIndex, X_INFO,
2050		   "Allocate new frame buffer %dx%d stride %d\n",
2051		   width, height, pitch / cpp);
2052
2053	old_width = scrn->virtualX;
2054	old_height = scrn->virtualY;
2055	old_pitch = scrn->displayWidth;
2056	old_fb_id = drmmode->fb_id;
2057	old_front = info->front_bo;
2058
2059	scrn->virtualX = width;
2060	scrn->virtualY = height;
2061	scrn->displayWidth = pitch / cpp;
2062
2063	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align,
2064					info->shadow_primary ?
2065					RADEON_GEM_DOMAIN_GTT :
2066					RADEON_GEM_DOMAIN_VRAM,
2067					tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0);
2068	if (!info->front_bo)
2069		goto fail;
2070
2071#if X_BYTE_ORDER == X_BIG_ENDIAN
2072	switch (cpp) {
2073	case 4:
2074	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
2075	    break;
2076	case 2:
2077	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
2078	    break;
2079	}
2080	if (info->ChipFamily < CHIP_FAMILY_R600 &&
2081	    info->r600_shadow_fb && tiling_flags)
2082	    tiling_flags |= RADEON_TILING_SURFACE;
2083#endif
2084	if (tiling_flags)
2085	    radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
2086
2087	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
2088			   scrn->bitsPerPixel, pitch,
2089			   info->front_bo->handle,
2090			   &drmmode->fb_id);
2091	if (ret)
2092		goto fail;
2093
2094	if (!info->r600_shadow_fb) {
2095		radeon_set_pixmap_bo(ppix, info->front_bo);
2096		psurface = radeon_get_pixmap_surface(ppix);
2097		*psurface = info->front_surface;
2098		screen->ModifyPixmapHeader(ppix,
2099					   width, height, -1, -1, pitch, NULL);
2100	} else {
2101		if (radeon_bo_map(info->front_bo, 1))
2102			goto fail;
2103		fb_shadow = calloc(1, screen_size);
2104		if (fb_shadow == NULL)
2105			goto fail;
2106		free(info->fb_shadow);
2107		info->fb_shadow = fb_shadow;
2108		screen->ModifyPixmapHeader(ppix,
2109					   width, height, -1, -1, pitch,
2110					   info->fb_shadow);
2111	}
2112#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,9,99,1,0)
2113	scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
2114#endif
2115
2116	if (info->use_glamor)
2117		radeon_glamor_create_screen_resources(scrn->pScreen);
2118
2119	/* Clear new buffer */
2120	gc = GetScratchGC(ppix->drawable.depth, scrn->pScreen);
2121	force = info->accel_state->force;
2122	info->accel_state->force = TRUE;
2123	ValidateGC(&ppix->drawable, gc);
2124	rect.x = 0;
2125	rect.y = 0;
2126	rect.width = width;
2127	rect.height = height;
2128	(*gc->ops->PolyFillRect)(&ppix->drawable, gc, 1, &rect);
2129	FreeScratchGC(gc);
2130	info->accel_state->force = force;
2131	radeon_cs_flush_indirect(scrn);
2132	radeon_bo_wait(info->front_bo);
2133
2134	for (i = 0; i < xf86_config->num_crtc; i++) {
2135		xf86CrtcPtr crtc = xf86_config->crtc[i];
2136
2137		if (!crtc->enabled)
2138			continue;
2139
2140		drmmode_set_mode_major(crtc, &crtc->mode,
2141				       crtc->rotation, crtc->x, crtc->y);
2142	}
2143
2144	if (old_fb_id)
2145		drmModeRmFB(drmmode->fd, old_fb_id);
2146	if (old_front)
2147		radeon_bo_unref(old_front);
2148
2149	radeon_kms_update_vram_limit(scrn, screen_size);
2150	return TRUE;
2151
2152 fail:
2153	if (info->front_bo)
2154		radeon_bo_unref(info->front_bo);
2155	info->front_bo = old_front;
2156	scrn->virtualX = old_width;
2157	scrn->virtualY = old_height;
2158	scrn->displayWidth = old_pitch;
2159	drmmode->fb_id = old_fb_id;
2160
2161	return FALSE;
2162}
2163
2164static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
2165	drmmode_xf86crtc_resize
2166};
2167
2168static void
2169drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
2170{
2171	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2172	drmmode_flipdata_ptr flipdata = event_data;
2173
2174	if (--flipdata->flip_count == 0) {
2175		if (flipdata->fe_crtc)
2176			crtc = flipdata->fe_crtc;
2177		flipdata->abort(crtc, flipdata->event_data);
2178		free(flipdata);
2179	}
2180
2181	drmmode_crtc->flip_pending = FALSE;
2182}
2183
2184static void
2185drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data)
2186{
2187	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2188	RADEONInfoPtr info = RADEONPTR(crtc->scrn);
2189	drmmode_flipdata_ptr flipdata = event_data;
2190
2191	/* Is this the event whose info shall be delivered to higher level? */
2192	if (crtc == flipdata->fe_crtc) {
2193		/* Yes: Cache msc, ust for later delivery. */
2194		flipdata->fe_frame = frame;
2195		flipdata->fe_usec = usec;
2196	}
2197
2198	if (--flipdata->flip_count == 0) {
2199		/* Deliver cached msc, ust from reference crtc to flip event handler */
2200		if (flipdata->fe_crtc)
2201			crtc = flipdata->fe_crtc;
2202		flipdata->handler(crtc, flipdata->fe_frame, flipdata->fe_usec,
2203				  flipdata->event_data);
2204
2205		/* Release framebuffer */
2206		drmModeRmFB(info->drmmode.fd, flipdata->old_fb_id);
2207
2208		free(flipdata);
2209	}
2210
2211	drmmode_crtc->flip_pending = FALSE;
2212}
2213
2214
2215static void
2216drm_wakeup_handler(pointer data, int err, pointer p)
2217{
2218	drmmode_ptr drmmode = data;
2219	fd_set *read_mask = p;
2220
2221	if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) {
2222		drmHandleEvent(drmmode->fd, &drmmode->event_context);
2223	}
2224}
2225
2226Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
2227{
2228	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2229	RADEONInfoPtr info = RADEONPTR(pScrn);
2230	int i, num_dvi = 0, num_hdmi = 0;
2231	drmModeResPtr mode_res;
2232	unsigned int crtcs_needed = 0;
2233#ifdef RADEON_PIXMAP_SHARING
2234	char *bus_id_string, *provider_name;
2235#endif
2236
2237	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
2238
2239	drmmode->scrn = pScrn;
2240	drmmode->cpp = cpp;
2241	mode_res = drmModeGetResources(drmmode->fd);
2242	if (!mode_res)
2243		return FALSE;
2244
2245	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2246		       "Initializing outputs ...\n");
2247	for (i = 0; i < mode_res->count_connectors; i++)
2248		crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res,
2249						    i, &num_dvi, &num_hdmi, 0);
2250	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2251		       "%d crtcs needed for screen.\n", crtcs_needed);
2252
2253	if (info->r600_shadow_fb) {
2254		/* Rotation requires hardware acceleration */
2255		drmmode_crtc_funcs.shadow_allocate = NULL;
2256		drmmode_crtc_funcs.shadow_create = NULL;
2257		drmmode_crtc_funcs.shadow_destroy = NULL;
2258	}
2259
2260	drmmode->count_crtcs = mode_res->count_crtcs;
2261	xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height);
2262
2263	for (i = 0; i < mode_res->count_crtcs; i++)
2264		if (!xf86IsEntityShared(pScrn->entityList[0]) ||
2265		    (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i))))
2266			crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
2267
2268	/* All ZaphodHeads outputs provided with matching crtcs? */
2269	if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
2270		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2271			   "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n",
2272			   crtcs_needed);
2273
2274	/* workout clones */
2275	drmmode_clones_init(pScrn, drmmode, mode_res);
2276
2277#ifdef RADEON_PIXMAP_SHARING
2278	bus_id_string = DRICreatePCIBusID(info->PciInfo);
2279	XNFasprintf(&provider_name, "%s @ %s", pScrn->chipset, bus_id_string);
2280	free(bus_id_string);
2281	xf86ProviderSetup(pScrn, NULL, provider_name);
2282	free(provider_name);
2283#endif
2284
2285	xf86InitialConfiguration(pScrn, TRUE);
2286
2287	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
2288	drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
2289	drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
2290
2291	drmModeFreeResources(mode_res);
2292	return TRUE;
2293}
2294
2295void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
2296{
2297	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2298	RADEONInfoPtr info = RADEONPTR(pScrn);
2299
2300	if (info->dri2.pKernelDRMVersion->version_minor < 4)
2301		return;
2302
2303	info->drmmode_inited = TRUE;
2304	if (pRADEONEnt->fd_wakeup_registered != serverGeneration) {
2305		AddGeneralSocket(drmmode->fd);
2306		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2307				drm_wakeup_handler, drmmode);
2308		pRADEONEnt->fd_wakeup_registered = serverGeneration;
2309		pRADEONEnt->fd_wakeup_ref = 1;
2310	} else
2311		pRADEONEnt->fd_wakeup_ref++;
2312}
2313
2314void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
2315{
2316	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2317	RADEONInfoPtr info = RADEONPTR(pScrn);
2318
2319	if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited)
2320		return;
2321
2322	if (pRADEONEnt->fd_wakeup_registered == serverGeneration &&
2323	    !--pRADEONEnt->fd_wakeup_ref) {
2324		RemoveGeneralSocket(drmmode->fd);
2325		RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2326				drm_wakeup_handler, drmmode);
2327	}
2328}
2329
2330
2331Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
2332{
2333	drmmode->bufmgr = bufmgr;
2334	return TRUE;
2335}
2336
2337
2338
2339void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
2340{
2341	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2342	xf86CrtcPtr crtc = xf86_config->crtc[id];
2343	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2344
2345	drmmode_crtc->cursor_bo = bo;
2346}
2347
2348void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
2349{
2350	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
2351	xf86OutputPtr  output = config->output[config->compat_output];
2352	xf86CrtcPtr	crtc = output->crtc;
2353
2354	if (crtc && crtc->enabled) {
2355		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
2356				       x, y);
2357	}
2358}
2359
2360Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
2361			       Bool set_hw)
2362{
2363	xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
2364	int c;
2365
2366	for (c = 0; c < config->num_crtc; c++) {
2367		xf86CrtcPtr	crtc = config->crtc[c];
2368		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2369		xf86OutputPtr	output = NULL;
2370		int		o;
2371
2372		/* Skip disabled CRTCs */
2373		if (!crtc->enabled) {
2374			if (set_hw) {
2375				drmmode_do_crtc_dpms(crtc, DPMSModeOff);
2376				drmModeSetCrtc(drmmode->fd,
2377					       drmmode_crtc->mode_crtc->crtc_id,
2378					       0, 0, 0, NULL, 0, NULL);
2379			}
2380			continue;
2381		}
2382
2383		if (config->output[config->compat_output]->crtc == crtc)
2384			output = config->output[config->compat_output];
2385		else
2386		{
2387			for (o = 0; o < config->num_output; o++)
2388				if (config->output[o]->crtc == crtc)
2389				{
2390					output = config->output[o];
2391					break;
2392				}
2393		}
2394		/* paranoia */
2395		if (!output)
2396			continue;
2397
2398		/* Mark that we'll need to re-set the mode for sure */
2399		memset(&crtc->mode, 0, sizeof(crtc->mode));
2400		if (!crtc->desiredMode.CrtcHDisplay)
2401		{
2402			DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
2403
2404			if (!mode)
2405				return FALSE;
2406			crtc->desiredMode = *mode;
2407			crtc->desiredRotation = RR_Rotate_0;
2408			crtc->desiredX = 0;
2409			crtc->desiredY = 0;
2410		}
2411
2412		if (set_hw) {
2413			if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
2414							 crtc->desiredX, crtc->desiredY))
2415				return FALSE;
2416		} else {
2417			crtc->mode = crtc->desiredMode;
2418			crtc->rotation = crtc->desiredRotation;
2419			crtc->x = crtc->desiredX;
2420			crtc->y = crtc->desiredY;
2421			if (!drmmode_handle_transform(crtc))
2422				return FALSE;
2423		}
2424	}
2425	return TRUE;
2426}
2427
2428static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
2429                                 int *indices, LOCO *colors, VisualPtr pVisual)
2430{
2431    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2432    uint16_t       lut_r[256], lut_g[256], lut_b[256];
2433    int index, j, i;
2434    int c;
2435
2436    for (c = 0; c < xf86_config->num_crtc; c++) {
2437        xf86CrtcPtr crtc = xf86_config->crtc[c];
2438	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2439
2440        for (i = 0 ; i < 256; i++) {
2441            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
2442            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
2443            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
2444        }
2445
2446        switch(pScrn->depth) {
2447        case 15:
2448            for (i = 0; i < numColors; i++) {
2449                index = indices[i];
2450                for (j = 0; j < 8; j++) {
2451                    lut_r[index * 8 + j] = colors[index].red << 6;
2452                    lut_g[index * 8 + j] = colors[index].green << 6;
2453                    lut_b[index * 8 + j] = colors[index].blue << 6;
2454                }
2455            }
2456         break;
2457         case 16:
2458             for (i = 0; i < numColors; i++) {
2459                 index = indices[i];
2460
2461                  if (i <= 31) {
2462                      for (j = 0; j < 8; j++) {
2463                          lut_r[index * 8 + j] = colors[index].red << 6;
2464                          lut_b[index * 8 + j] = colors[index].blue << 6;
2465                      }
2466                  }
2467
2468                  for (j = 0; j < 4; j++) {
2469                      lut_g[index * 4 + j] = colors[index].green << 6;
2470                  }
2471              }
2472	  break;
2473          default:
2474              for (i = 0; i < numColors; i++) {
2475                  index = indices[i];
2476                  lut_r[index] = colors[index].red << 6;
2477                  lut_g[index] = colors[index].green << 6;
2478                  lut_b[index] = colors[index].blue << 6;
2479              }
2480              break;
2481          }
2482
2483    /* Make the change through RandR */
2484        if (crtc->randr_crtc)
2485            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
2486        else
2487            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
2488     }
2489}
2490
2491Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
2492{
2493    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2494
2495    if (xf86_config->num_crtc) {
2496	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2497		       "Initializing kms color map\n");
2498	if (!miCreateDefColormap(pScreen))
2499	    return FALSE;
2500	/* all radeons support 10 bit CLUTs */
2501	if (!xf86HandleColormaps(pScreen, 256, 10,
2502				 drmmode_load_palette, NULL,
2503				 CMAP_PALETTED_TRUECOLOR
2504#if 0 /* This option messes up text mode! (eich@suse.de) */
2505				 | CMAP_LOAD_EVEN_IF_OFFSCREEN
2506#endif
2507				 | CMAP_RELOAD_ON_MODE_SWITCH))
2508	    return FALSE;
2509    }
2510    return TRUE;
2511}
2512
2513void
2514radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode)
2515{
2516	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
2517	drmModeResPtr mode_res;
2518	int i, j;
2519	Bool found;
2520	Bool changed = FALSE;
2521
2522	mode_res = drmModeGetResources(drmmode->fd);
2523	if (!mode_res)
2524		goto out;
2525
2526restart_destroy:
2527	for (i = 0; i < config->num_output; i++) {
2528		xf86OutputPtr output = config->output[i];
2529		drmmode_output_private_ptr drmmode_output = output->driver_private;
2530		found = FALSE;
2531		for (j = 0; j < mode_res->count_connectors; j++) {
2532			if (mode_res->connectors[j] == drmmode_output->output_id) {
2533				found = TRUE;
2534				break;
2535			}
2536		}
2537		if (found)
2538			continue;
2539
2540		drmModeFreeConnector(drmmode_output->mode_output);
2541		drmmode_output->mode_output = NULL;
2542		drmmode_output->output_id = -1;
2543
2544		changed = TRUE;
2545		if (drmmode->delete_dp_12_displays) {
2546			RROutputDestroy(output->randr_output);
2547			xf86OutputDestroy(output);
2548			goto restart_destroy;
2549		}
2550	}
2551
2552	/* find new output ids we don't have outputs for */
2553	for (i = 0; i < mode_res->count_connectors; i++) {
2554		found = FALSE;
2555
2556		for (j = 0; j < config->num_output; j++) {
2557			xf86OutputPtr output = config->output[j];
2558			drmmode_output_private_ptr drmmode_output;
2559
2560			drmmode_output = output->driver_private;
2561			if (mode_res->connectors[i] == drmmode_output->output_id) {
2562				found = TRUE;
2563				break;
2564			}
2565		}
2566		if (found)
2567			continue;
2568
2569		changed = TRUE;
2570		drmmode_output_init(scrn, drmmode, mode_res, i, NULL, NULL, 1);
2571	}
2572
2573	if (changed) {
2574#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0)
2575		RRSetChanged(xf86ScrnToScreen(scrn));
2576#else
2577		rrScrPrivPtr rrScrPriv = rrGetScrPriv(scrn->pScreen);
2578		rrScrPriv->changed = TRUE;
2579#endif
2580		RRTellChanged(xf86ScrnToScreen(scrn));
2581	}
2582
2583	drmModeFreeResources(mode_res);
2584out:
2585	RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
2586}
2587#ifdef HAVE_LIBUDEV
2588static void
2589drmmode_handle_uevents(int fd, void *closure)
2590{
2591	drmmode_ptr drmmode = closure;
2592	ScrnInfoPtr scrn = drmmode->scrn;
2593	struct udev_device *dev;
2594	dev = udev_monitor_receive_device(drmmode->uevent_monitor);
2595	if (!dev)
2596		return;
2597
2598	radeon_mode_hotplug(scrn, drmmode);
2599	udev_device_unref(dev);
2600}
2601#endif
2602
2603void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
2604{
2605#ifdef HAVE_LIBUDEV
2606	struct udev *u;
2607	struct udev_monitor *mon;
2608
2609	u = udev_new();
2610	if (!u)
2611		return;
2612	mon = udev_monitor_new_from_netlink(u, "udev");
2613	if (!mon) {
2614		udev_unref(u);
2615		return;
2616	}
2617
2618	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
2619							    "drm",
2620							    "drm_minor") < 0 ||
2621	    udev_monitor_enable_receiving(mon) < 0) {
2622		udev_monitor_unref(mon);
2623		udev_unref(u);
2624		return;
2625	}
2626
2627	drmmode->uevent_handler =
2628		xf86AddGeneralHandler(udev_monitor_get_fd(mon),
2629				      drmmode_handle_uevents,
2630				      drmmode);
2631
2632	drmmode->uevent_monitor = mon;
2633#endif
2634}
2635
2636void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
2637{
2638#ifdef HAVE_LIBUDEV
2639	if (drmmode->uevent_handler) {
2640		struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
2641		xf86RemoveGeneralHandler(drmmode->uevent_handler);
2642
2643		udev_monitor_unref(drmmode->uevent_monitor);
2644		udev_unref(u);
2645	}
2646#endif
2647}
2648
2649Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
2650			uint32_t new_front_handle, uint64_t id, void *data,
2651			int ref_crtc_hw_id, radeon_drm_handler_proc handler,
2652			radeon_drm_abort_proc abort)
2653{
2654	RADEONInfoPtr info = RADEONPTR(scrn);
2655	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
2656	xf86CrtcPtr crtc = NULL;
2657	drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
2658	drmmode_ptr drmmode = drmmode_crtc->drmmode;
2659	unsigned int pitch;
2660	int i;
2661	uint32_t tiling_flags = 0;
2662	drmmode_flipdata_ptr flipdata;
2663	uintptr_t drm_queue_seq = 0;
2664
2665	if (info->allowColorTiling) {
2666		if (info->ChipFamily >= CHIP_FAMILY_R600)
2667			tiling_flags |= RADEON_TILING_MICRO;
2668		else
2669			tiling_flags |= RADEON_TILING_MACRO;
2670	}
2671
2672	pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->pixel_bytes, tiling_flags)) *
2673		info->pixel_bytes;
2674	if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
2675		pitch = info->front_surface.level[0].pitch_bytes;
2676	}
2677
2678        flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
2679        if (!flipdata) {
2680             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2681                        "flip queue: data alloc failed.\n");
2682             goto error;
2683        }
2684
2685	/*
2686	 * Create a new handle for the back buffer
2687	 */
2688	flipdata->old_fb_id = drmmode->fb_id;
2689	if (drmModeAddFB(drmmode->fd, scrn->virtualX, scrn->virtualY,
2690			 scrn->depth, scrn->bitsPerPixel, pitch,
2691			 new_front_handle, &drmmode->fb_id))
2692		goto error;
2693
2694	/*
2695	 * Queue flips on all enabled CRTCs
2696	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
2697	 * Right now it assumes a single shared fb across all CRTCs, with the
2698	 * kernel fixing up the offset of each CRTC as necessary.
2699	 *
2700	 * Also, flips queued on disabled or incorrectly configured displays
2701	 * may never complete; this is a configuration error.
2702	 */
2703
2704        flipdata->event_data = data;
2705        flipdata->handler = handler;
2706        flipdata->abort = abort;
2707
2708	for (i = 0; i < config->num_crtc; i++) {
2709		crtc = config->crtc[i];
2710
2711		if (!crtc->enabled)
2712			continue;
2713
2714		flipdata->flip_count++;
2715		drmmode_crtc = crtc->driver_private;
2716
2717		/* Only the reference crtc will finally deliver its page flip
2718		 * completion event. All other crtc's events will be discarded.
2719		 */
2720		if (drmmode_crtc->hw_id == ref_crtc_hw_id)
2721			flipdata->fe_crtc = crtc;
2722
2723		drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id,
2724						       flipdata,
2725						       drmmode_flip_handler,
2726						       drmmode_flip_abort);
2727		if (!drm_queue_seq) {
2728			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2729				   "Allocating DRM queue event entry failed.\n");
2730			goto error;
2731		}
2732
2733		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
2734				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT,
2735				    (void*)drm_queue_seq)) {
2736			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2737				   "flip queue failed: %s\n", strerror(errno));
2738			goto error;
2739		}
2740		drmmode_crtc->flip_pending = TRUE;
2741		drm_queue_seq = 0;
2742	}
2743
2744	if (flipdata->flip_count > 0)
2745		return TRUE;
2746
2747error:
2748	if (flipdata && flipdata->flip_count <= 1) {
2749		drmModeRmFB(drmmode->fd, drmmode->fb_id);
2750		drmmode->fb_id = flipdata->old_fb_id;
2751	}
2752
2753	if (drm_queue_seq)
2754		radeon_drm_abort_entry(drm_queue_seq);
2755	else if (crtc)
2756		drmmode_flip_abort(crtc, flipdata);
2757	else if (flipdata && flipdata->flip_count <= 1)
2758		free(flipdata);
2759
2760	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
2761		   strerror(errno));
2762	return FALSE;
2763}
2764