drmmode_display.c revision de2362d3
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 "micmap.h"
36#include "xf86cmap.h"
37#include "radeon.h"
38#include "radeon_reg.h"
39#include "sarea.h"
40
41#include "drmmode_display.h"
42
43/* DPMS */
44#ifdef HAVE_XEXTPROTO_71
45#include <X11/extensions/dpmsconst.h>
46#else
47#define DPMS_SERVER
48#include <X11/extensions/dpms.h>
49#endif
50
51#define DEFAULT_NOMINAL_FRAME_RATE 60
52
53static Bool
54drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height);
55
56static Bool
57RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
58{
59    int i = 0;
60    char s1[20];
61
62    do {
63	switch(*s) {
64	case ',':
65  	    s1[i] = '\0';
66	    i = 0;
67	    if (strcmp(s1, output_name) == 0)
68		return TRUE;
69	    break;
70	case ' ':
71	case '\t':
72	case '\n':
73	case '\r':
74	    break;
75	default:
76	    s1[i] = *s;
77	    i++;
78	    break;
79	}
80    } while(*s++);
81
82    s1[i] = '\0';
83    if (strcmp(s1, output_name) == 0)
84	return TRUE;
85
86    return FALSE;
87}
88
89static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
90					  int width, int height,
91					  int depth, int bpp,
92					  int pitch, int tiling,
93					  struct radeon_bo *bo, struct radeon_surface *psurf)
94{
95	RADEONInfoPtr info = RADEONPTR(pScrn);
96	ScreenPtr pScreen = pScrn->pScreen;
97	PixmapPtr pixmap;
98	struct radeon_surface *surface;
99
100	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
101	if (!pixmap)
102		return NULL;
103
104	if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height,
105					    depth, bpp, pitch, NULL)) {
106		return NULL;
107	}
108
109	if (!info->use_glamor)
110		exaMoveInPixmap(pixmap);
111	radeon_set_pixmap_bo(pixmap, bo);
112	if (info->ChipFamily >= CHIP_FAMILY_R600) {
113		surface = radeon_get_pixmap_surface(pixmap);
114		if (surface && psurf)
115			*surface = *psurf;
116		else if (surface) {
117			memset(surface, 0, sizeof(struct radeon_surface));
118			surface->npix_x = width;
119			surface->npix_y = height;
120			surface->npix_z = 1;
121			surface->blk_w = 1;
122			surface->blk_h = 1;
123			surface->blk_d = 1;
124			surface->array_size = 1;
125			surface->last_level = 0;
126			surface->bpe = bpp / 8;
127			surface->nsamples = 1;
128			surface->flags = RADEON_SURF_SCANOUT;
129			/* we are requiring a recent enough libdrm version */
130			surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
131			surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
132			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
133			if (tiling & RADEON_TILING_MICRO) {
134				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
135				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
136			}
137			if (tiling & RADEON_TILING_MACRO) {
138				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
139				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
140			}
141			if (radeon_surface_best(info->surf_man, surface)) {
142				return NULL;
143			}
144			if (radeon_surface_init(info->surf_man, surface)) {
145				return NULL;
146			}
147		}
148	}
149
150	if (!radeon_glamor_create_textured_pixmap(pixmap)) {
151		pScreen->DestroyPixmap(pixmap);
152	  	return NULL;
153	}
154
155	return pixmap;
156}
157
158static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap)
159{
160	ScreenPtr pScreen = pixmap->drawable.pScreen;
161
162	(*pScreen->DestroyPixmap)(pixmap);
163}
164
165static void
166drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
167		     drmModeModeInfo *kmode,
168		     DisplayModePtr	mode)
169{
170	memset(mode, 0, sizeof(DisplayModeRec));
171	mode->status = MODE_OK;
172
173	mode->Clock = kmode->clock;
174
175	mode->HDisplay = kmode->hdisplay;
176	mode->HSyncStart = kmode->hsync_start;
177	mode->HSyncEnd = kmode->hsync_end;
178	mode->HTotal = kmode->htotal;
179	mode->HSkew = kmode->hskew;
180
181	mode->VDisplay = kmode->vdisplay;
182	mode->VSyncStart = kmode->vsync_start;
183	mode->VSyncEnd = kmode->vsync_end;
184	mode->VTotal = kmode->vtotal;
185	mode->VScan = kmode->vscan;
186
187	mode->Flags = kmode->flags; //& FLAG_BITS;
188	mode->name = strdup(kmode->name);
189
190	if (kmode->type & DRM_MODE_TYPE_DRIVER)
191		mode->type = M_T_DRIVER;
192	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
193		mode->type |= M_T_PREFERRED;
194	xf86SetModeCrtc (mode, scrn->adjustFlags);
195}
196
197static void
198drmmode_ConvertToKMode(ScrnInfoPtr	scrn,
199		     drmModeModeInfo *kmode,
200		     DisplayModePtr	mode)
201{
202	memset(kmode, 0, sizeof(*kmode));
203
204	kmode->clock = mode->Clock;
205	kmode->hdisplay = mode->HDisplay;
206	kmode->hsync_start = mode->HSyncStart;
207	kmode->hsync_end = mode->HSyncEnd;
208	kmode->htotal = mode->HTotal;
209	kmode->hskew = mode->HSkew;
210
211	kmode->vdisplay = mode->VDisplay;
212	kmode->vsync_start = mode->VSyncStart;
213	kmode->vsync_end = mode->VSyncEnd;
214	kmode->vtotal = mode->VTotal;
215	kmode->vscan = mode->VScan;
216
217	kmode->flags = mode->Flags; //& FLAG_BITS;
218	if (mode->name)
219		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
220	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
221
222}
223
224/*
225 * Retrieves present time in microseconds that is compatible
226 * with units used by vblank timestamps. Depending on the kernel
227 * version and DRM kernel module configuration, the vblank
228 * timestamp can either be in real time or monotonic time
229 */
230int drmmode_get_current_ust(int drm_fd, CARD64 *ust)
231{
232	uint64_t cap_value;
233	int ret;
234	struct timespec now;
235
236	ret = drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap_value);
237	if (ret || !cap_value)
238		/* old kernel or drm_timestamp_monotonic turned off */
239		ret = clock_gettime(CLOCK_REALTIME, &now);
240	else
241		ret = clock_gettime(CLOCK_MONOTONIC, &now);
242	if (ret)
243		return ret;
244	*ust = ((CARD64)now.tv_sec * 1000000) + ((CARD64)now.tv_nsec / 1000);
245	return 0;
246}
247
248static void
249drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
250{
251	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
252	ScrnInfoPtr scrn = crtc->scrn;
253	RADEONInfoPtr info = RADEONPTR(scrn);
254	CARD64 ust;
255	int ret;
256
257	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
258		drmVBlank vbl;
259
260		/*
261		 * On->Off transition: record the last vblank time,
262		 * sequence number and frame period.
263		 */
264		vbl.request.type = DRM_VBLANK_RELATIVE;
265		vbl.request.type |= radeon_populate_vbl_request_type(crtc);
266		vbl.request.sequence = 0;
267		ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
268		if (ret)
269			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
270				   "%s cannot get last vblank counter\n",
271				   __func__);
272		else {
273			CARD64 seq = (CARD64)vbl.reply.sequence;
274			CARD64 nominal_frame_rate, pix_in_frame;
275
276			ust = ((CARD64)vbl.reply.tval_sec * 1000000) +
277				vbl.reply.tval_usec;
278			drmmode_crtc->dpms_last_ust = ust;
279			drmmode_crtc->dpms_last_seq = seq;
280			nominal_frame_rate = crtc->mode.Clock;
281			nominal_frame_rate *= 1000;
282			pix_in_frame = crtc->mode.HTotal * crtc->mode.VTotal;
283			if (nominal_frame_rate == 0 || pix_in_frame == 0)
284				nominal_frame_rate = DEFAULT_NOMINAL_FRAME_RATE;
285			else
286				nominal_frame_rate /= pix_in_frame;
287			drmmode_crtc->dpms_last_fps = nominal_frame_rate;
288		}
289	} else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) {
290		/*
291		 * Off->On transition: calculate and accumulate the
292		 * number of interpolated vblanks while we were in Off state
293		 */
294		ret = drmmode_get_current_ust(info->dri2.drm_fd, &ust);
295		if (ret)
296			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
297				   "%s cannot get current time\n", __func__);
298		else if (drmmode_crtc->dpms_last_ust) {
299			CARD64 time_elapsed, delta_seq;
300			time_elapsed = ust - drmmode_crtc->dpms_last_ust;
301			delta_seq = time_elapsed * drmmode_crtc->dpms_last_fps;
302			delta_seq /= 1000000;
303			drmmode_crtc->interpolated_vblanks += delta_seq;
304
305		}
306	}
307	drmmode_crtc->dpms_mode = mode;
308}
309
310static void
311drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
312{
313	/* Nothing to do. drmmode_do_crtc_dpms() is called as appropriate */
314}
315
316static PixmapPtr
317create_pixmap_for_fbcon(drmmode_ptr drmmode,
318			ScrnInfoPtr pScrn, int fbcon_id)
319{
320	PixmapPtr pixmap = NULL;
321	struct radeon_bo *bo;
322	drmModeFBPtr fbcon;
323	struct drm_gem_flink flink;
324
325	fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
326	if (fbcon == NULL)
327		return NULL;
328
329	if (fbcon->depth != pScrn->depth ||
330	    fbcon->width != pScrn->virtualX ||
331	    fbcon->height != pScrn->virtualY)
332		goto out_free_fb;
333
334	flink.handle = fbcon->handle;
335	if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
336		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
337			   "Couldn't flink fbcon handle\n");
338		goto out_free_fb;
339	}
340
341	bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
342	if (bo == NULL) {
343		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
344			   "Couldn't allocate bo for fbcon handle\n");
345		goto out_free_fb;
346	}
347
348	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
349					  fbcon->depth, fbcon->bpp,
350					  fbcon->pitch, 0, bo, NULL);
351	radeon_bo_unref(bo);
352out_free_fb:
353	drmModeFreeFB(fbcon);
354	return pixmap;
355}
356
357void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
358{
359	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
360	RADEONInfoPtr info = RADEONPTR(pScrn);
361	PixmapPtr src, dst;
362	ScreenPtr pScreen = pScrn->pScreen;
363	int fbcon_id = 0;
364	int i;
365	int pitch;
366	uint32_t tiling_flags = 0;
367	Bool ret;
368
369	if (info->accelOn == FALSE || info->use_glamor)
370		goto fallback;
371
372	for (i = 0; i < xf86_config->num_crtc; i++) {
373		drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private;
374
375		if (drmmode_crtc->mode_crtc->buffer_id)
376			fbcon_id = drmmode_crtc->mode_crtc->buffer_id;
377	}
378
379	if (!fbcon_id)
380		goto fallback;
381
382	if (fbcon_id == drmmode->fb_id) {
383		/* in some rare case there might be no fbcon and we might already
384		 * be the one with the current fb to avoid a false deadlck in
385		 * kernel ttm code just do nothing as anyway there is nothing
386		 * to do
387		 */
388		return;
389	}
390
391	src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id);
392	if (!src)
393		goto fallback;
394
395	if (info->allowColorTiling) {
396		if (info->ChipFamily >= CHIP_FAMILY_R600) {
397			if (info->allowColorTiling2D) {
398				tiling_flags |= RADEON_TILING_MACRO;
399			} else {
400				tiling_flags |= RADEON_TILING_MICRO;
401			}
402		} else
403			tiling_flags |= RADEON_TILING_MACRO;
404	}
405
406	pitch = RADEON_ALIGN(pScrn->displayWidth,
407			     drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
408		info->pixel_bytes;
409
410	dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX,
411				       pScrn->virtualY, pScrn->depth,
412				       pScrn->bitsPerPixel, pitch,
413				       tiling_flags, info->front_bo, &info->front_surface);
414	if (!dst)
415		goto out_free_src;
416
417	ret = info->accel_state->exa->PrepareCopy (src, dst,
418						   -1, -1, GXcopy, FB_ALLONES);
419	if (!ret)
420	  goto out_free_src;
421	info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
422				      pScrn->virtualX, pScrn->virtualY);
423	info->accel_state->exa->DoneCopy (dst);
424	radeon_cs_flush_indirect(pScrn);
425
426#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
427	pScreen->canDoBGNoneRoot = TRUE;
428#endif
429	drmmode_destroy_bo_pixmap(dst);
430 out_free_src:
431	drmmode_destroy_bo_pixmap(src);
432	return;
433
434fallback:
435	/* map and memset the bo */
436	if (radeon_bo_map(info->front_bo, 1))
437		return;
438
439	memset(info->front_bo->ptr, 0x00, info->front_bo->size);
440	radeon_bo_unmap(info->front_bo);
441}
442
443static Bool
444drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
445		     Rotation rotation, int x, int y)
446{
447	ScrnInfoPtr pScrn = crtc->scrn;
448	RADEONInfoPtr info = RADEONPTR(pScrn);
449	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
450	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
451	drmmode_ptr drmmode = drmmode_crtc->drmmode;
452	int saved_x, saved_y;
453	Rotation saved_rotation;
454	DisplayModeRec saved_mode;
455	uint32_t *output_ids;
456	int output_count = 0;
457	Bool ret = TRUE;
458	int i;
459	int fb_id;
460	drmModeModeInfo kmode;
461	int pitch;
462	uint32_t tiling_flags = 0;
463	int height;
464
465	if (info->allowColorTiling) {
466		if (info->ChipFamily >= CHIP_FAMILY_R600)
467			tiling_flags |= RADEON_TILING_MICRO;
468		else
469			tiling_flags |= RADEON_TILING_MACRO;
470	}
471
472	pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
473		info->pixel_bytes;
474	height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags));
475	if (info->ChipFamily >= CHIP_FAMILY_R600) {
476		pitch = info->front_surface.level[0].pitch_bytes;
477	}
478
479	if (drmmode->fb_id == 0) {
480		ret = drmModeAddFB(drmmode->fd,
481				   pScrn->virtualX, height,
482                                   pScrn->depth, pScrn->bitsPerPixel,
483				   pitch,
484				   info->front_bo->handle,
485                                   &drmmode->fb_id);
486                if (ret < 0) {
487                        ErrorF("failed to add fb\n");
488                        return FALSE;
489                }
490        }
491
492	saved_mode = crtc->mode;
493	saved_x = crtc->x;
494	saved_y = crtc->y;
495	saved_rotation = crtc->rotation;
496
497	if (mode) {
498		crtc->mode = *mode;
499		crtc->x = x;
500		crtc->y = y;
501		crtc->rotation = rotation;
502		crtc->transformPresent = FALSE;
503	}
504
505	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
506	if (!output_ids) {
507		ret = FALSE;
508		goto done;
509	}
510
511	if (mode) {
512		for (i = 0; i < xf86_config->num_output; i++) {
513			xf86OutputPtr output = xf86_config->output[i];
514			drmmode_output_private_ptr drmmode_output;
515
516			if (output->crtc != crtc)
517				continue;
518
519			drmmode_output = output->driver_private;
520			output_ids[output_count] = drmmode_output->mode_output->connector_id;
521			output_count++;
522		}
523
524		if (!xf86CrtcRotate(crtc)) {
525			goto done;
526		}
527		crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
528				       crtc->gamma_blue, crtc->gamma_size);
529
530		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
531
532		fb_id = drmmode->fb_id;
533#ifdef RADEON_PIXMAP_SHARING
534		if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
535			x = drmmode_crtc->scanout_pixmap_x;
536			y = 0;
537		} else
538#endif
539		if (drmmode_crtc->rotate_fb_id) {
540			fb_id = drmmode_crtc->rotate_fb_id;
541			x = y = 0;
542		}
543		ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
544				     fb_id, x, y, output_ids, output_count, &kmode);
545		if (ret)
546			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
547				   "failed to set mode: %s", strerror(-ret));
548		else
549			ret = TRUE;
550
551		if (crtc->scrn->pScreen)
552			xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
553		/* go through all the outputs and force DPMS them back on? */
554		for (i = 0; i < xf86_config->num_output; i++) {
555			xf86OutputPtr output = xf86_config->output[i];
556
557			if (output->crtc != crtc)
558				continue;
559
560			output->funcs->dpms(output, DPMSModeOn);
561		}
562	}
563
564	if (pScrn->pScreen &&
565		!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
566		xf86_reload_cursors(pScrn->pScreen);
567
568done:
569	if (!ret) {
570		crtc->x = saved_x;
571		crtc->y = saved_y;
572		crtc->rotation = saved_rotation;
573		crtc->mode = saved_mode;
574	}
575#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
576	else
577		crtc->active = TRUE;
578#endif
579
580	return ret;
581}
582
583static void
584drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
585{
586
587}
588
589static void
590drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
591{
592	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
593	drmmode_ptr drmmode = drmmode_crtc->drmmode;
594
595	drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
596}
597
598static void
599drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
600{
601	ScrnInfoPtr pScrn = crtc->scrn;
602	RADEONInfoPtr info = RADEONPTR(pScrn);
603	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
604	int i;
605	uint32_t *ptr;
606	uint32_t cursor_size = info->cursor_w * info->cursor_h;
607
608	/* cursor should be mapped already */
609	ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
610
611	for (i = 0; i < cursor_size; i++)
612		ptr[i] = cpu_to_le32(image[i]);
613}
614
615
616static void
617drmmode_hide_cursor (xf86CrtcPtr crtc)
618{
619	ScrnInfoPtr pScrn = crtc->scrn;
620	RADEONInfoPtr info = RADEONPTR(pScrn);
621	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
622	drmmode_ptr drmmode = drmmode_crtc->drmmode;
623
624	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
625			 info->cursor_w, info->cursor_h);
626
627}
628
629static void
630drmmode_show_cursor (xf86CrtcPtr crtc)
631{
632	ScrnInfoPtr pScrn = crtc->scrn;
633	RADEONInfoPtr info = RADEONPTR(pScrn);
634	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
635	drmmode_ptr drmmode = drmmode_crtc->drmmode;
636	uint32_t handle = drmmode_crtc->cursor_bo->handle;
637
638	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
639			 info->cursor_w, info->cursor_h);
640}
641
642static void *
643drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
644{
645	ScrnInfoPtr pScrn = crtc->scrn;
646	RADEONInfoPtr info = RADEONPTR(pScrn);
647	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
648	drmmode_ptr drmmode = drmmode_crtc->drmmode;
649	int size;
650	struct radeon_bo *rotate_bo;
651	int ret;
652	unsigned long rotate_pitch;
653	int base_align;
654
655	/* rotation requires acceleration */
656	if (info->r600_shadow_fb) {
657		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
658			   "Rotation requires acceleration!\n");
659		return NULL;
660	}
661
662	rotate_pitch =
663		RADEON_ALIGN(width, drmmode_get_pitch_align(crtc->scrn, drmmode->cpp, 0)) * drmmode->cpp;
664	height = RADEON_ALIGN(height, drmmode_get_height_align(crtc->scrn, 0));
665	base_align = drmmode_get_base_align(crtc->scrn, drmmode->cpp, 0);
666	size = RADEON_ALIGN(rotate_pitch * height, RADEON_GPU_PAGE_SIZE);
667
668	rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
669	if (rotate_bo == NULL)
670		return NULL;
671
672	radeon_bo_map(rotate_bo, 1);
673
674	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
675			   crtc->scrn->bitsPerPixel, rotate_pitch,
676			   rotate_bo->handle,
677			   &drmmode_crtc->rotate_fb_id);
678	if (ret) {
679		ErrorF("failed to add rotate fb\n");
680	}
681
682	drmmode_crtc->rotate_bo = rotate_bo;
683	return drmmode_crtc->rotate_bo->ptr;
684}
685
686static PixmapPtr
687drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
688{
689	ScrnInfoPtr pScrn = crtc->scrn;
690	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
691	drmmode_ptr drmmode = drmmode_crtc->drmmode;
692	unsigned long rotate_pitch;
693	PixmapPtr rotate_pixmap;
694
695	if (!data)
696		data = drmmode_crtc_shadow_allocate (crtc, width, height);
697
698	rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp;
699
700	rotate_pixmap = drmmode_create_bo_pixmap(pScrn,
701						 width, height,
702						 pScrn->depth,
703						 pScrn->bitsPerPixel,
704						 rotate_pitch,
705						 0, drmmode_crtc->rotate_bo, NULL);
706	if (rotate_pixmap == NULL) {
707		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
708			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
709	}
710	return rotate_pixmap;
711
712}
713
714static void
715drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
716{
717	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
718	drmmode_ptr drmmode = drmmode_crtc->drmmode;
719
720	if (rotate_pixmap)
721		drmmode_destroy_bo_pixmap(rotate_pixmap);
722
723	if (data) {
724		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
725		drmmode_crtc->rotate_fb_id = 0;
726		radeon_bo_unmap(drmmode_crtc->rotate_bo);
727		radeon_bo_unref(drmmode_crtc->rotate_bo);
728		drmmode_crtc->rotate_bo = NULL;
729	}
730
731}
732
733static void
734drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
735                      uint16_t *blue, int size)
736{
737	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
738	drmmode_ptr drmmode = drmmode_crtc->drmmode;
739
740	drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
741			    size, red, green, blue);
742}
743
744#ifdef RADEON_PIXMAP_SHARING
745static Bool
746drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
747{
748	ScreenPtr screen = xf86ScrnToScreen(crtc->scrn);
749	PixmapPtr screenpix = screen->GetScreenPixmap(screen);
750	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
751	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
752	int c, total_width = 0, max_height = 0, this_x = 0;
753
754	if (!ppix) {
755		if (crtc->randr_crtc->scanout_pixmap)
756			PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
757		drmmode_crtc->scanout_pixmap_x = 0;
758		return TRUE;
759	}
760
761	/* iterate over all the attached crtcs -
762	   work out bounding box */
763	for (c = 0; c < xf86_config->num_crtc; c++) {
764		xf86CrtcPtr iter = xf86_config->crtc[c];
765		if (!iter->enabled && iter != crtc)
766			continue;
767		if (iter == crtc) {
768			this_x = total_width;
769			total_width += ppix->drawable.width;
770			if (max_height < ppix->drawable.height)
771				max_height = ppix->drawable.height;
772		} else {
773			total_width += iter->mode.HDisplay;
774			if (max_height < iter->mode.VDisplay)
775				max_height = iter->mode.VDisplay;
776		}
777#ifndef HAS_DIRTYTRACKING2
778		if (iter != crtc) {
779			ErrorF("Cannot do multiple crtcs without X server dirty tracking 2 interface\n");
780			return FALSE;
781		}
782#endif
783	}
784
785	if (total_width != screenpix->drawable.width ||
786	    max_height != screenpix->drawable.height) {
787		Bool ret;
788		ret = drmmode_xf86crtc_resize(crtc->scrn, total_width, max_height);
789		if (ret == FALSE)
790			return FALSE;
791
792		screenpix = screen->GetScreenPixmap(screen);
793		screen->width = screenpix->drawable.width = total_width;
794		screen->height = screenpix->drawable.height = max_height;
795	}
796	drmmode_crtc->scanout_pixmap_x = this_x;
797#ifdef HAS_DIRTYTRACKING2
798	PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0);
799#else
800	PixmapStartDirtyTracking(ppix, screenpix, 0, 0);
801#endif
802	return TRUE;
803}
804#endif
805
806static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
807    .dpms = drmmode_crtc_dpms,
808    .set_mode_major = drmmode_set_mode_major,
809    .set_cursor_colors = drmmode_set_cursor_colors,
810    .set_cursor_position = drmmode_set_cursor_position,
811    .show_cursor = drmmode_show_cursor,
812    .hide_cursor = drmmode_hide_cursor,
813    .load_cursor_argb = drmmode_load_cursor_argb,
814
815    .gamma_set = drmmode_crtc_gamma_set,
816    .shadow_create = drmmode_crtc_shadow_create,
817    .shadow_allocate = drmmode_crtc_shadow_allocate,
818    .shadow_destroy = drmmode_crtc_shadow_destroy,
819    .destroy = NULL, /* XXX */
820#ifdef RADEON_PIXMAP_SHARING
821    .set_scanout_pixmap = drmmode_set_scanout_pixmap,
822#endif
823};
824
825int drmmode_get_crtc_id(xf86CrtcPtr crtc)
826{
827	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
828	return drmmode_crtc->hw_id;
829}
830
831void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
832{
833	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
834	ScrnInfoPtr pScrn = crtc->scrn;
835	RADEONInfoPtr info = RADEONPTR(pScrn);
836	struct drm_radeon_info ginfo;
837	int r;
838	uint32_t tmp;
839
840	memset(&ginfo, 0, sizeof(ginfo));
841	ginfo.request = 0x4;
842	tmp = drmmode_crtc->mode_crtc->crtc_id;
843	ginfo.value = (uintptr_t)&tmp;
844	r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
845	if (r) {
846		drmmode_crtc->hw_id = -1;
847		return;
848	}
849	drmmode_crtc->hw_id = tmp;
850}
851
852static void
853drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
854{
855	xf86CrtcPtr crtc;
856	drmmode_crtc_private_ptr drmmode_crtc;
857
858	crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
859	if (crtc == NULL)
860		return;
861
862	drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
863	drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
864	drmmode_crtc->drmmode = drmmode;
865	crtc->driver_private = drmmode_crtc;
866	drmmode_crtc_hw_id(crtc);
867
868	return;
869}
870
871static xf86OutputStatus
872drmmode_output_detect(xf86OutputPtr output)
873{
874	/* go to the hw and retrieve a new output struct */
875	drmmode_output_private_ptr drmmode_output = output->driver_private;
876	drmmode_ptr drmmode = drmmode_output->drmmode;
877	xf86OutputStatus status;
878	drmModeFreeConnector(drmmode_output->mode_output);
879
880	drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
881	if (!drmmode_output->mode_output)
882		return XF86OutputStatusDisconnected;
883
884	switch (drmmode_output->mode_output->connection) {
885	case DRM_MODE_CONNECTED:
886		status = XF86OutputStatusConnected;
887		break;
888	case DRM_MODE_DISCONNECTED:
889		status = XF86OutputStatusDisconnected;
890		break;
891	default:
892	case DRM_MODE_UNKNOWNCONNECTION:
893		status = XF86OutputStatusUnknown;
894		break;
895	}
896	return status;
897}
898
899static Bool
900drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
901{
902	return MODE_OK;
903}
904
905static DisplayModePtr
906drmmode_output_get_modes(xf86OutputPtr output)
907{
908	drmmode_output_private_ptr drmmode_output = output->driver_private;
909	drmModeConnectorPtr koutput = drmmode_output->mode_output;
910	drmmode_ptr drmmode = drmmode_output->drmmode;
911	int i;
912	DisplayModePtr Modes = NULL, Mode;
913	drmModePropertyPtr props;
914	xf86MonPtr mon = NULL;
915
916	if (!koutput)
917		return NULL;
918
919	/* look for an EDID property */
920	for (i = 0; i < koutput->count_props; i++) {
921		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
922		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
923			if (!strcmp(props->name, "EDID")) {
924				if (drmmode_output->edid_blob)
925					drmModeFreePropertyBlob(drmmode_output->edid_blob);
926				drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
927			}
928		}
929		if (props)
930			drmModeFreeProperty(props);
931	}
932
933	if (drmmode_output->edid_blob) {
934		mon = xf86InterpretEDID(output->scrn->scrnIndex,
935					drmmode_output->edid_blob->data);
936		if (mon && drmmode_output->edid_blob->length > 128)
937			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
938	}
939	xf86OutputSetEDID(output, mon);
940
941	/* modes should already be available */
942	for (i = 0; i < koutput->count_modes; i++) {
943		Mode = xnfalloc(sizeof(DisplayModeRec));
944
945		drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
946		Modes = xf86ModesAdd(Modes, Mode);
947
948	}
949	return Modes;
950}
951
952static void
953drmmode_output_destroy(xf86OutputPtr output)
954{
955	drmmode_output_private_ptr drmmode_output = output->driver_private;
956	int i;
957
958	if (drmmode_output->edid_blob)
959		drmModeFreePropertyBlob(drmmode_output->edid_blob);
960	for (i = 0; i < drmmode_output->num_props; i++) {
961		drmModeFreeProperty(drmmode_output->props[i].mode_prop);
962		free(drmmode_output->props[i].atoms);
963	}
964	for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
965		drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
966	}
967	free(drmmode_output->mode_encoders);
968	free(drmmode_output->props);
969	drmModeFreeConnector(drmmode_output->mode_output);
970	free(drmmode_output);
971	output->driver_private = NULL;
972}
973
974static void
975drmmode_output_dpms(xf86OutputPtr output, int mode)
976{
977	drmmode_output_private_ptr drmmode_output = output->driver_private;
978	drmModeConnectorPtr koutput = drmmode_output->mode_output;
979	drmmode_ptr drmmode = drmmode_output->drmmode;
980
981	if (mode != DPMSModeOn && output->crtc)
982		drmmode_do_crtc_dpms(output->crtc, mode);
983
984	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
985				    drmmode_output->dpms_enum_id, mode);
986
987	if (mode == DPMSModeOn && output->crtc)
988		drmmode_do_crtc_dpms(output->crtc, mode);
989}
990
991
992static Bool
993drmmode_property_ignore(drmModePropertyPtr prop)
994{
995    if (!prop)
996	return TRUE;
997    /* ignore blob prop */
998    if (prop->flags & DRM_MODE_PROP_BLOB)
999	return TRUE;
1000    /* ignore standard property */
1001    if (!strcmp(prop->name, "EDID") ||
1002	    !strcmp(prop->name, "DPMS"))
1003	return TRUE;
1004
1005    return FALSE;
1006}
1007
1008static void
1009drmmode_output_create_resources(xf86OutputPtr output)
1010{
1011    drmmode_output_private_ptr drmmode_output = output->driver_private;
1012    drmModeConnectorPtr mode_output = drmmode_output->mode_output;
1013    drmmode_ptr drmmode = drmmode_output->drmmode;
1014    drmModePropertyPtr drmmode_prop;
1015    int i, j, err;
1016
1017    drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
1018    if (!drmmode_output->props)
1019	return;
1020
1021    drmmode_output->num_props = 0;
1022    for (i = 0, j = 0; i < mode_output->count_props; i++) {
1023	drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
1024	if (drmmode_property_ignore(drmmode_prop)) {
1025	    drmModeFreeProperty(drmmode_prop);
1026	    continue;
1027	}
1028	drmmode_output->props[j].mode_prop = drmmode_prop;
1029	drmmode_output->props[j].value = mode_output->prop_values[i];
1030	drmmode_output->num_props++;
1031	j++;
1032    }
1033
1034    for (i = 0; i < drmmode_output->num_props; i++) {
1035	drmmode_prop_ptr p = &drmmode_output->props[i];
1036	drmmode_prop = p->mode_prop;
1037
1038	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
1039	    INT32 range[2];
1040	    INT32 value = p->value;
1041
1042	    p->num_atoms = 1;
1043	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
1044	    if (!p->atoms)
1045		continue;
1046	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1047	    range[0] = drmmode_prop->values[0];
1048	    range[1] = drmmode_prop->values[1];
1049	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1050		    FALSE, TRUE,
1051		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1052		    2, range);
1053	    if (err != 0) {
1054		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1055			"RRConfigureOutputProperty error, %d\n", err);
1056	    }
1057	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1058		    XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE);
1059	    if (err != 0) {
1060		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1061			"RRChangeOutputProperty error, %d\n", err);
1062	    }
1063	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
1064	    p->num_atoms = drmmode_prop->count_enums + 1;
1065	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
1066	    if (!p->atoms)
1067		continue;
1068	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1069	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
1070		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
1071		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
1072	    }
1073	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1074		    FALSE, FALSE,
1075		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1076		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
1077	    if (err != 0) {
1078		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1079			"RRConfigureOutputProperty error, %d\n", err);
1080	    }
1081	    for (j = 0; j < drmmode_prop->count_enums; j++)
1082		if (drmmode_prop->enums[j].value == p->value)
1083		    break;
1084	    /* there's always a matching value */
1085	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1086		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
1087	    if (err != 0) {
1088		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1089			"RRChangeOutputProperty error, %d\n", err);
1090	    }
1091	}
1092    }
1093}
1094
1095static Bool
1096drmmode_output_set_property(xf86OutputPtr output, Atom property,
1097		RRPropertyValuePtr value)
1098{
1099    drmmode_output_private_ptr drmmode_output = output->driver_private;
1100    drmmode_ptr drmmode = drmmode_output->drmmode;
1101    int i;
1102
1103    for (i = 0; i < drmmode_output->num_props; i++) {
1104	drmmode_prop_ptr p = &drmmode_output->props[i];
1105
1106	if (p->atoms[0] != property)
1107	    continue;
1108
1109	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
1110	    uint32_t val;
1111
1112	    if (value->type != XA_INTEGER || value->format != 32 ||
1113		    value->size != 1)
1114		return FALSE;
1115	    val = *(uint32_t *)value->data;
1116
1117	    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
1118		    p->mode_prop->prop_id, (uint64_t)val);
1119	    return TRUE;
1120	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
1121	    Atom	atom;
1122	    const char	*name;
1123	    int		j;
1124
1125	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
1126		return FALSE;
1127	    memcpy(&atom, value->data, 4);
1128	    name = NameForAtom(atom);
1129
1130	    /* search for matching name string, then set its value down */
1131	    for (j = 0; j < p->mode_prop->count_enums; j++) {
1132		if (!strcmp(p->mode_prop->enums[j].name, name)) {
1133		    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
1134			    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
1135		    return TRUE;
1136		}
1137	    }
1138	}
1139    }
1140
1141    return TRUE;
1142}
1143
1144static Bool
1145drmmode_output_get_property(xf86OutputPtr output, Atom property)
1146{
1147    return TRUE;
1148}
1149
1150static const xf86OutputFuncsRec drmmode_output_funcs = {
1151    .dpms = drmmode_output_dpms,
1152    .create_resources = drmmode_output_create_resources,
1153    .set_property = drmmode_output_set_property,
1154    .get_property = drmmode_output_get_property,
1155#if 0
1156
1157    .save = drmmode_crt_save,
1158    .restore = drmmode_crt_restore,
1159    .mode_fixup = drmmode_crt_mode_fixup,
1160    .prepare = drmmode_output_prepare,
1161    .mode_set = drmmode_crt_mode_set,
1162    .commit = drmmode_output_commit,
1163#endif
1164    .detect = drmmode_output_detect,
1165    .mode_valid = drmmode_output_mode_valid,
1166
1167    .get_modes = drmmode_output_get_modes,
1168    .destroy = drmmode_output_destroy
1169};
1170
1171static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
1172				      SubPixelHorizontalRGB,
1173				      SubPixelHorizontalBGR,
1174				      SubPixelVerticalRGB,
1175				      SubPixelVerticalBGR,
1176				      SubPixelNone };
1177
1178const char *output_names[] = { "None",
1179			       "VGA",
1180			       "DVI",
1181			       "DVI",
1182			       "DVI",
1183			       "Composite",
1184			       "S-video",
1185			       "LVDS",
1186			       "CTV",
1187			       "DIN",
1188			       "DisplayPort",
1189			       "HDMI",
1190			       "HDMI",
1191			       "TV",
1192			       "eDP"
1193};
1194
1195#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
1196
1197static void
1198drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi)
1199{
1200	RADEONInfoPtr info = RADEONPTR(pScrn);
1201	xf86OutputPtr output;
1202	drmModeConnectorPtr koutput;
1203	drmModeEncoderPtr *kencoders = NULL;
1204	drmmode_output_private_ptr drmmode_output;
1205	drmModePropertyPtr props;
1206	char name[32];
1207	int i;
1208	const char *s;
1209
1210	koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
1211	if (!koutput)
1212		return;
1213
1214	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
1215	if (!kencoders) {
1216		goto out_free_encoders;
1217	}
1218
1219	for (i = 0; i < koutput->count_encoders; i++) {
1220		kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
1221		if (!kencoders[i]) {
1222			goto out_free_encoders;
1223		}
1224	}
1225
1226	if (koutput->connector_type >= NUM_OUTPUT_NAMES)
1227		snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
1228			 koutput->connector_type_id - 1);
1229#ifdef RADEON_PIXMAP_SHARING
1230	else if (pScrn->is_gpu)
1231		snprintf(name, 32, "%s-%d-%d",
1232			 output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
1233			 koutput->connector_type_id - 1);
1234#endif
1235	else {
1236		/* need to do smart conversion here for compat with non-kms ATI driver */
1237		if (koutput->connector_type_id == 1) {
1238			switch(koutput->connector_type) {
1239			case DRM_MODE_CONNECTOR_DVII:
1240			case DRM_MODE_CONNECTOR_DVID:
1241			case DRM_MODE_CONNECTOR_DVIA:
1242				snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
1243				(*num_dvi)++;
1244				break;
1245			case DRM_MODE_CONNECTOR_HDMIA:
1246			case DRM_MODE_CONNECTOR_HDMIB:
1247				snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
1248				(*num_hdmi)++;
1249				break;
1250			case DRM_MODE_CONNECTOR_VGA:
1251			case DRM_MODE_CONNECTOR_DisplayPort:
1252				snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
1253					 koutput->connector_type_id - 1);
1254				break;
1255			default:
1256				snprintf(name, 32, "%s", output_names[koutput->connector_type]);
1257				break;
1258			}
1259		} else {
1260			snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
1261				 koutput->connector_type_id - 1);
1262		}
1263	}
1264
1265	if (xf86IsEntityShared(pScrn->entityList[0])) {
1266		if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) {
1267			if (!RADEONZaphodStringMatches(pScrn, s, name))
1268				goto out_free_encoders;
1269		} else {
1270			if (info->IsPrimary && (num != 0))
1271				goto out_free_encoders;
1272			else if (info->IsSecondary && (num != 1))
1273				goto out_free_encoders;
1274		}
1275	}
1276
1277	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
1278	if (!output) {
1279		goto out_free_encoders;
1280	}
1281
1282	drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
1283	if (!drmmode_output) {
1284		xf86OutputDestroy(output);
1285		goto out_free_encoders;
1286	}
1287
1288	drmmode_output->output_id = drmmode->mode_res->connectors[num];
1289	drmmode_output->mode_output = koutput;
1290	drmmode_output->mode_encoders = kencoders;
1291	drmmode_output->drmmode = drmmode;
1292	output->mm_width = koutput->mmWidth;
1293	output->mm_height = koutput->mmHeight;
1294
1295	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
1296	output->interlaceAllowed = TRUE;
1297	output->doubleScanAllowed = TRUE;
1298	output->driver_private = drmmode_output;
1299
1300	output->possible_crtcs = 0xffffffff;
1301	for (i = 0; i < koutput->count_encoders; i++) {
1302		output->possible_crtcs &= kencoders[i]->possible_crtcs;
1303	}
1304	/* work out the possible clones later */
1305	output->possible_clones = 0;
1306
1307	for (i = 0; i < koutput->count_props; i++) {
1308		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
1309		if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
1310			if (!strcmp(props->name, "DPMS")) {
1311				drmmode_output->dpms_enum_id = koutput->props[i];
1312				drmModeFreeProperty(props);
1313				break;
1314			}
1315			drmModeFreeProperty(props);
1316		}
1317	}
1318
1319	return;
1320out_free_encoders:
1321	if (kencoders){
1322		for (i = 0; i < koutput->count_encoders; i++)
1323			drmModeFreeEncoder(kencoders[i]);
1324		free(kencoders);
1325	}
1326	drmModeFreeConnector(koutput);
1327
1328}
1329
1330uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
1331{
1332	drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
1333	int i;
1334	xf86OutputPtr clone_output;
1335	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1336	int index_mask = 0;
1337
1338	if (drmmode_output->enc_clone_mask == 0)
1339		return index_mask;
1340
1341	for (i = 0; i < xf86_config->num_output; i++) {
1342		clone_output = xf86_config->output[i];
1343		clone_drmout = clone_output->driver_private;
1344		if (output == clone_output)
1345			continue;
1346
1347		if (clone_drmout->enc_mask == 0)
1348			continue;
1349		if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
1350			index_mask |= (1 << i);
1351	}
1352	return index_mask;
1353}
1354
1355
1356static void
1357drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1358{
1359	int i, j;
1360	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1361
1362	for (i = 0; i < xf86_config->num_output; i++) {
1363		xf86OutputPtr output = xf86_config->output[i];
1364		drmmode_output_private_ptr drmmode_output;
1365
1366		drmmode_output = output->driver_private;
1367		drmmode_output->enc_clone_mask = 0xff;
1368		/* and all the possible encoder clones for this output together */
1369		for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
1370		{
1371			int k;
1372			for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
1373				if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
1374					drmmode_output->enc_mask |= (1 << k);
1375			}
1376
1377			drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
1378		}
1379	}
1380
1381	for (i = 0; i < xf86_config->num_output; i++) {
1382		xf86OutputPtr output = xf86_config->output[i];
1383		output->possible_clones = find_clones(scrn, output);
1384	}
1385}
1386
1387/* returns height alignment in pixels */
1388int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling)
1389{
1390	RADEONInfoPtr info = RADEONPTR(scrn);
1391	int height_align = 1;
1392
1393	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1394		if (tiling & RADEON_TILING_MACRO)
1395			height_align =  info->num_channels * 8;
1396		else if (tiling & RADEON_TILING_MICRO)
1397			height_align = 8;
1398		else
1399			height_align = 8;
1400	} else {
1401		if (tiling & RADEON_TILING_MICRO_SQUARE)
1402			height_align =  32;
1403		else if (tiling)
1404			height_align = 16;
1405		else
1406			height_align = 1;
1407	}
1408	return height_align;
1409}
1410
1411/* returns pitch alignment in pixels */
1412int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1413{
1414	RADEONInfoPtr info = RADEONPTR(scrn);
1415	int pitch_align = 1;
1416
1417	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1418		if (tiling & RADEON_TILING_MACRO) {
1419			/* general surface requirements */
1420			pitch_align = MAX(info->num_banks,
1421					  (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8;
1422			/* further restrictions for scanout */
1423			pitch_align = MAX(info->num_banks * 8, pitch_align);
1424		} else if (tiling & RADEON_TILING_MICRO) {
1425			/* general surface requirements */
1426			pitch_align = MAX(8, (info->group_bytes / (8 * bpe)));
1427			/* further restrictions for scanout */
1428			pitch_align = MAX(info->group_bytes / bpe, pitch_align);
1429		} else {
1430			if (info->have_tiling_info)
1431				/* linear aligned requirements */
1432				pitch_align = MAX(64, info->group_bytes / bpe);
1433			else
1434				/* default to 512 elements if we don't know the real
1435				 * group size otherwise the kernel may reject the CS
1436				 * if the group sizes don't match as the pitch won't
1437				 * be aligned properly.
1438				 */
1439				pitch_align = 512;
1440		}
1441	} else {
1442		/* general surface requirements */
1443		if (tiling)
1444			pitch_align = 256 / bpe;
1445		else
1446			pitch_align = 64;
1447	}
1448	return pitch_align;
1449}
1450
1451/* returns base alignment in bytes */
1452int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1453{
1454	RADEONInfoPtr info = RADEONPTR(scrn);
1455	int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling);
1456	int height_align = drmmode_get_height_align(scrn, tiling);
1457	int base_align = RADEON_GPU_PAGE_SIZE;
1458
1459	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1460		if (tiling & RADEON_TILING_MACRO)
1461			base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe,
1462					 pixel_align * bpe * height_align);
1463		else {
1464			if (info->have_tiling_info)
1465				base_align = info->group_bytes;
1466			else
1467				/* default to 512 if we don't know the real
1468				 * group size otherwise the kernel may reject the CS
1469				 * if the group sizes don't match as the base won't
1470				 * be aligned properly.
1471				 */
1472				base_align = 512;
1473		}
1474	}
1475	return base_align;
1476}
1477
1478static Bool
1479drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
1480{
1481	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1482	drmmode_crtc_private_ptr
1483		    drmmode_crtc = xf86_config->crtc[0]->driver_private;
1484	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1485	RADEONInfoPtr info = RADEONPTR(scrn);
1486	struct radeon_bo *old_front = NULL;
1487	Bool	    ret;
1488	ScreenPtr   screen = xf86ScrnToScreen(scrn);
1489	uint32_t    old_fb_id;
1490	int	    i, pitch, old_width, old_height, old_pitch;
1491	uint32_t screen_size;
1492	int cpp = info->pixel_bytes;
1493	struct radeon_bo *front_bo;
1494	struct radeon_surface surface;
1495	struct radeon_surface *psurface;
1496	uint32_t tiling_flags = 0, base_align;
1497	PixmapPtr ppix = screen->GetScreenPixmap(screen);
1498	void *fb_shadow;
1499
1500	if (scrn->virtualX == width && scrn->virtualY == height)
1501		return TRUE;
1502
1503	front_bo = info->front_bo;
1504	radeon_cs_flush_indirect(scrn);
1505
1506	if (front_bo)
1507		radeon_bo_wait(front_bo);
1508
1509	if (info->allowColorTiling) {
1510		if (info->ChipFamily >= CHIP_FAMILY_R600) {
1511			if (info->allowColorTiling2D) {
1512				tiling_flags |= RADEON_TILING_MACRO;
1513			} else {
1514				tiling_flags |= RADEON_TILING_MICRO;
1515			}
1516		} else
1517			tiling_flags |= RADEON_TILING_MACRO;
1518	}
1519
1520	pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
1521	height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
1522	screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
1523	base_align = 4096;
1524	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1525		memset(&surface, 0, sizeof(struct radeon_surface));
1526		surface.npix_x = width;
1527		surface.npix_y = height;
1528		surface.npix_z = 1;
1529		surface.blk_w = 1;
1530		surface.blk_h = 1;
1531		surface.blk_d = 1;
1532		surface.array_size = 1;
1533		surface.last_level = 0;
1534		surface.bpe = cpp;
1535		surface.nsamples = 1;
1536		surface.flags = RADEON_SURF_SCANOUT;
1537		/* we are requiring a recent enough libdrm version */
1538		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
1539		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
1540		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
1541		if (tiling_flags & RADEON_TILING_MICRO) {
1542			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
1543			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1544		}
1545		if (tiling_flags & RADEON_TILING_MACRO) {
1546			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
1547			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1548		}
1549		if (radeon_surface_best(info->surf_man, &surface)) {
1550			return FALSE;
1551		}
1552		if (radeon_surface_init(info->surf_man, &surface)) {
1553			return FALSE;
1554		}
1555		screen_size = surface.bo_size;
1556		base_align = surface.bo_alignment;
1557		pitch = surface.level[0].pitch_bytes;
1558		tiling_flags = 0;
1559		switch (surface.level[0].mode) {
1560		case RADEON_SURF_MODE_2D:
1561			tiling_flags |= RADEON_TILING_MACRO;
1562			tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
1563			tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
1564			tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
1565			tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
1566			break;
1567		case RADEON_SURF_MODE_1D:
1568			tiling_flags |= RADEON_TILING_MICRO;
1569			break;
1570		default:
1571			break;
1572		}
1573		info->front_surface = surface;
1574	}
1575
1576	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1577		   "Allocate new frame buffer %dx%d stride %d\n",
1578		   width, height, pitch / cpp);
1579
1580	old_width = scrn->virtualX;
1581	old_height = scrn->virtualY;
1582	old_pitch = scrn->displayWidth;
1583	old_fb_id = drmmode->fb_id;
1584	old_front = info->front_bo;
1585
1586	scrn->virtualX = width;
1587	scrn->virtualY = height;
1588	scrn->displayWidth = pitch / cpp;
1589
1590	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
1591	if (!info->front_bo)
1592		goto fail;
1593
1594#if X_BYTE_ORDER == X_BIG_ENDIAN
1595	switch (cpp) {
1596	case 4:
1597	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
1598	    break;
1599	case 2:
1600	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
1601	    break;
1602	}
1603	if (info->ChipFamily < CHIP_FAMILY_R600 &&
1604	    info->r600_shadow_fb && tiling_flags)
1605	    tiling_flags |= RADEON_TILING_SURFACE;
1606#endif
1607	if (tiling_flags)
1608	    radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
1609
1610	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
1611			   scrn->bitsPerPixel, pitch,
1612			   info->front_bo->handle,
1613			   &drmmode->fb_id);
1614	if (ret)
1615		goto fail;
1616
1617	if (!info->r600_shadow_fb) {
1618		radeon_set_pixmap_bo(ppix, info->front_bo);
1619		psurface = radeon_get_pixmap_surface(ppix);
1620		*psurface = info->front_surface;
1621		screen->ModifyPixmapHeader(ppix,
1622					   width, height, -1, -1, pitch, NULL);
1623	} else {
1624		if (radeon_bo_map(info->front_bo, 1))
1625			goto fail;
1626		fb_shadow = calloc(1, screen_size);
1627		if (fb_shadow == NULL)
1628			goto fail;
1629		free(info->fb_shadow);
1630		info->fb_shadow = fb_shadow;
1631		screen->ModifyPixmapHeader(ppix,
1632					   width, height, -1, -1, pitch,
1633					   info->fb_shadow);
1634	}
1635#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,9,99,1,0)
1636	scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
1637#endif
1638
1639	for (i = 0; i < xf86_config->num_crtc; i++) {
1640		xf86CrtcPtr crtc = xf86_config->crtc[i];
1641
1642		if (!crtc->enabled)
1643			continue;
1644
1645		drmmode_set_mode_major(crtc, &crtc->mode,
1646				       crtc->rotation, crtc->x, crtc->y);
1647	}
1648
1649	if (info->use_glamor)
1650		radeon_glamor_create_screen_resources(scrn->pScreen);
1651
1652	if (old_fb_id)
1653		drmModeRmFB(drmmode->fd, old_fb_id);
1654	if (old_front)
1655		radeon_bo_unref(old_front);
1656
1657	radeon_kms_update_vram_limit(scrn, screen_size);
1658	return TRUE;
1659
1660 fail:
1661	if (info->front_bo)
1662		radeon_bo_unref(info->front_bo);
1663	info->front_bo = old_front;
1664	scrn->virtualX = old_width;
1665	scrn->virtualY = old_height;
1666	scrn->displayWidth = old_pitch;
1667	drmmode->fb_id = old_fb_id;
1668
1669	return FALSE;
1670}
1671
1672static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
1673	drmmode_xf86crtc_resize
1674};
1675
1676static void
1677drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
1678			unsigned int tv_usec, void *event_data)
1679{
1680	radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data);
1681}
1682
1683static void
1684drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
1685		     unsigned int tv_usec, void *event_data)
1686{
1687	drmmode_flipevtcarrier_ptr flipcarrier = event_data;
1688	drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
1689	drmmode_ptr drmmode = flipdata->drmmode;
1690
1691	/* Is this the event whose info shall be delivered to higher level? */
1692	if (flipcarrier->dispatch_me) {
1693		/* Yes: Cache msc, ust for later delivery. */
1694		flipdata->fe_frame = frame;
1695		flipdata->fe_tv_sec = tv_sec;
1696		flipdata->fe_tv_usec = tv_usec;
1697	}
1698	free(flipcarrier);
1699
1700	/* Last crtc completed flip? */
1701	flipdata->flip_count--;
1702	if (flipdata->flip_count > 0)
1703		return;
1704
1705	/* Release framebuffer */
1706	drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
1707
1708	if (flipdata->event_data == NULL)
1709		return;
1710
1711	/* Deliver cached msc, ust from reference crtc to flip event handler */
1712	radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
1713				       flipdata->fe_tv_usec, flipdata->event_data);
1714
1715	free(flipdata);
1716}
1717
1718
1719static void
1720drm_wakeup_handler(pointer data, int err, pointer p)
1721{
1722	drmmode_ptr drmmode = data;
1723	fd_set *read_mask = p;
1724
1725	if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) {
1726		drmHandleEvent(drmmode->fd, &drmmode->event_context);
1727	}
1728}
1729
1730Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
1731{
1732	int i, num_dvi = 0, num_hdmi = 0;
1733
1734	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
1735
1736	drmmode->scrn = pScrn;
1737	drmmode->cpp = cpp;
1738	drmmode->mode_res = drmModeGetResources(drmmode->fd);
1739	if (!drmmode->mode_res)
1740		return FALSE;
1741
1742	xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
1743	for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
1744		if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
1745			drmmode_crtc_init(pScrn, drmmode, i);
1746
1747	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
1748		drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
1749
1750	/* workout clones */
1751	drmmode_clones_init(pScrn, drmmode);
1752
1753#ifdef RADEON_PIXMAP_SHARING
1754	xf86ProviderSetup(pScrn, NULL, "radeon");
1755#endif
1756
1757	xf86InitialConfiguration(pScrn, TRUE);
1758
1759	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
1760	drmmode->event_context.vblank_handler = drmmode_vblank_handler;
1761	drmmode->event_context.page_flip_handler = drmmode_flip_handler;
1762
1763	return TRUE;
1764}
1765
1766void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
1767{
1768	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1769	RADEONInfoPtr info = RADEONPTR(pScrn);
1770
1771	if (info->dri2.pKernelDRMVersion->version_minor < 4)
1772		return;
1773
1774	info->drmmode_inited = TRUE;
1775	if (pRADEONEnt->fd_wakeup_registered != serverGeneration) {
1776		AddGeneralSocket(drmmode->fd);
1777		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1778				drm_wakeup_handler, drmmode);
1779		pRADEONEnt->fd_wakeup_registered = serverGeneration;
1780		pRADEONEnt->fd_wakeup_ref = 1;
1781	} else
1782		pRADEONEnt->fd_wakeup_ref++;
1783}
1784
1785void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
1786{
1787	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1788	RADEONInfoPtr info = RADEONPTR(pScrn);
1789
1790	if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited)
1791		return;
1792
1793	if (pRADEONEnt->fd_wakeup_registered == serverGeneration &&
1794	    !--pRADEONEnt->fd_wakeup_ref) {
1795		RemoveGeneralSocket(drmmode->fd);
1796		RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1797				drm_wakeup_handler, drmmode);
1798	}
1799}
1800
1801
1802Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
1803{
1804	drmmode->bufmgr = bufmgr;
1805	return TRUE;
1806}
1807
1808
1809
1810void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
1811{
1812	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1813	xf86CrtcPtr crtc = xf86_config->crtc[id];
1814	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1815
1816	drmmode_crtc->cursor_bo = bo;
1817}
1818
1819void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
1820{
1821	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
1822	xf86OutputPtr  output = config->output[config->compat_output];
1823	xf86CrtcPtr	crtc = output->crtc;
1824
1825	if (crtc && crtc->enabled) {
1826		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
1827				       x, y);
1828	}
1829}
1830
1831Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
1832{
1833	xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
1834	int c;
1835
1836	drmmode_copy_fb(pScrn, drmmode);
1837
1838	for (c = 0; c < config->num_crtc; c++) {
1839		xf86CrtcPtr	crtc = config->crtc[c];
1840		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1841		xf86OutputPtr	output = NULL;
1842		int		o;
1843
1844		/* Skip disabled CRTCs */
1845		if (!crtc->enabled) {
1846			drmmode_do_crtc_dpms(crtc, DPMSModeOff);
1847			drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1848				       0, 0, 0, NULL, 0, NULL);
1849			continue;
1850		}
1851
1852		if (config->output[config->compat_output]->crtc == crtc)
1853			output = config->output[config->compat_output];
1854		else
1855		{
1856			for (o = 0; o < config->num_output; o++)
1857				if (config->output[o]->crtc == crtc)
1858				{
1859					output = config->output[o];
1860					break;
1861				}
1862		}
1863		/* paranoia */
1864		if (!output)
1865			continue;
1866
1867		/* Mark that we'll need to re-set the mode for sure */
1868		memset(&crtc->mode, 0, sizeof(crtc->mode));
1869		if (!crtc->desiredMode.CrtcHDisplay)
1870		{
1871			DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
1872
1873			if (!mode)
1874				return FALSE;
1875			crtc->desiredMode = *mode;
1876			crtc->desiredRotation = RR_Rotate_0;
1877			crtc->desiredX = 0;
1878			crtc->desiredY = 0;
1879		}
1880
1881		if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
1882						 crtc->desiredX, crtc->desiredY))
1883			return FALSE;
1884	}
1885	return TRUE;
1886}
1887
1888static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
1889                                 int *indices, LOCO *colors, VisualPtr pVisual)
1890{
1891    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1892    uint16_t       lut_r[256], lut_g[256], lut_b[256];
1893    int index, j, i;
1894    int c;
1895
1896    for (c = 0; c < xf86_config->num_crtc; c++) {
1897        xf86CrtcPtr crtc = xf86_config->crtc[c];
1898	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1899
1900        for (i = 0 ; i < 256; i++) {
1901            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
1902            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
1903            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
1904        }
1905
1906        switch(pScrn->depth) {
1907        case 15:
1908            for (i = 0; i < numColors; i++) {
1909                index = indices[i];
1910                for (j = 0; j < 8; j++) {
1911                    lut_r[index * 8 + j] = colors[index].red << 6;
1912                    lut_g[index * 8 + j] = colors[index].green << 6;
1913                    lut_b[index * 8 + j] = colors[index].blue << 6;
1914                }
1915            }
1916         break;
1917         case 16:
1918             for (i = 0; i < numColors; i++) {
1919                 index = indices[i];
1920
1921                  if (i <= 31) {
1922                      for (j = 0; j < 8; j++) {
1923                          lut_r[index * 8 + j] = colors[index].red << 6;
1924                          lut_b[index * 8 + j] = colors[index].blue << 6;
1925                      }
1926                  }
1927
1928                  for (j = 0; j < 4; j++) {
1929                      lut_g[index * 4 + j] = colors[index].green << 6;
1930                  }
1931              }
1932	  break;
1933          default:
1934              for (i = 0; i < numColors; i++) {
1935                  index = indices[i];
1936                  lut_r[index] = colors[index].red << 6;
1937                  lut_g[index] = colors[index].green << 6;
1938                  lut_b[index] = colors[index].blue << 6;
1939              }
1940              break;
1941          }
1942
1943    /* Make the change through RandR */
1944        if (crtc->randr_crtc)
1945            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
1946        else
1947            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
1948     }
1949}
1950
1951Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
1952{
1953    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1954
1955    if (xf86_config->num_crtc) {
1956	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1957		       "Initializing kms color map\n");
1958	if (!miCreateDefColormap(pScreen))
1959	    return FALSE;
1960	/* all radeons support 10 bit CLUTs */
1961	if (!xf86HandleColormaps(pScreen, 256, 10,
1962				 drmmode_load_palette, NULL,
1963				 CMAP_PALETTED_TRUECOLOR
1964#if 0 /* This option messes up text mode! (eich@suse.de) */
1965				 | CMAP_LOAD_EVEN_IF_OFFSCREEN
1966#endif
1967				 | CMAP_RELOAD_ON_MODE_SWITCH))
1968	    return FALSE;
1969    }
1970    return TRUE;
1971}
1972
1973#ifdef HAVE_LIBUDEV
1974static void
1975drmmode_handle_uevents(int fd, void *closure)
1976{
1977	drmmode_ptr drmmode = closure;
1978	ScrnInfoPtr scrn = drmmode->scrn;
1979	struct udev_device *dev;
1980	dev = udev_monitor_receive_device(drmmode->uevent_monitor);
1981	if (!dev)
1982		return;
1983
1984	RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
1985	udev_device_unref(dev);
1986}
1987#endif
1988
1989void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1990{
1991#ifdef HAVE_LIBUDEV
1992	struct udev *u;
1993	struct udev_monitor *mon;
1994
1995	u = udev_new();
1996	if (!u)
1997		return;
1998	mon = udev_monitor_new_from_netlink(u, "udev");
1999	if (!mon) {
2000		udev_unref(u);
2001		return;
2002	}
2003
2004	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
2005							    "drm",
2006							    "drm_minor") < 0 ||
2007	    udev_monitor_enable_receiving(mon) < 0) {
2008		udev_monitor_unref(mon);
2009		udev_unref(u);
2010		return;
2011	}
2012
2013	drmmode->uevent_handler =
2014		xf86AddGeneralHandler(udev_monitor_get_fd(mon),
2015				      drmmode_handle_uevents,
2016				      drmmode);
2017
2018	drmmode->uevent_monitor = mon;
2019#endif
2020}
2021
2022void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
2023{
2024#ifdef HAVE_LIBUDEV
2025	if (drmmode->uevent_handler) {
2026		struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
2027		xf86RemoveGeneralHandler(drmmode->uevent_handler);
2028
2029		udev_monitor_unref(drmmode->uevent_monitor);
2030		udev_unref(u);
2031	}
2032#endif
2033}
2034
2035Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id)
2036{
2037	RADEONInfoPtr info = RADEONPTR(scrn);
2038	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
2039	drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
2040	drmmode_ptr drmmode = drmmode_crtc->drmmode;
2041	unsigned int pitch;
2042	int i, old_fb_id;
2043	uint32_t tiling_flags = 0;
2044	int height, emitted = 0;
2045	drmmode_flipdata_ptr flipdata;
2046	drmmode_flipevtcarrier_ptr flipcarrier;
2047
2048	if (info->allowColorTiling) {
2049		if (info->ChipFamily >= CHIP_FAMILY_R600)
2050			tiling_flags |= RADEON_TILING_MICRO;
2051		else
2052			tiling_flags |= RADEON_TILING_MACRO;
2053	}
2054
2055	pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->pixel_bytes, tiling_flags)) *
2056		info->pixel_bytes;
2057	height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags));
2058	if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
2059		pitch = info->front_surface.level[0].pitch_bytes;
2060	}
2061
2062	/*
2063	 * Create a new handle for the back buffer
2064	 */
2065	old_fb_id = drmmode->fb_id;
2066	if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
2067			 scrn->depth, scrn->bitsPerPixel, pitch,
2068			 new_front->handle, &drmmode->fb_id))
2069		goto error_out;
2070
2071        flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
2072        if (!flipdata) {
2073             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2074                        "flip queue: data alloc failed.\n");
2075             goto error_undo;
2076        }
2077	/*
2078	 * Queue flips on all enabled CRTCs
2079	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
2080	 * Right now it assumes a single shared fb across all CRTCs, with the
2081	 * kernel fixing up the offset of each CRTC as necessary.
2082	 *
2083	 * Also, flips queued on disabled or incorrectly configured displays
2084	 * may never complete; this is a configuration error.
2085	 */
2086
2087        flipdata->event_data = data;
2088        flipdata->drmmode = drmmode;
2089
2090	for (i = 0; i < config->num_crtc; i++) {
2091		if (!config->crtc[i]->enabled)
2092			continue;
2093
2094		flipdata->flip_count++;
2095		drmmode_crtc = config->crtc[i]->driver_private;
2096
2097		flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec));
2098		if (!flipcarrier) {
2099			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2100				   "flip queue: carrier alloc failed.\n");
2101			if (emitted == 0)
2102				free(flipdata);
2103			goto error_undo;
2104		}
2105
2106		/* Only the reference crtc will finally deliver its page flip
2107		 * completion event. All other crtc's events will be discarded.
2108		 */
2109		flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
2110		flipcarrier->flipdata = flipdata;
2111
2112		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
2113				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
2114			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
2115				   "flip queue failed: %s\n", strerror(errno));
2116			free(flipcarrier);
2117			if (emitted == 0)
2118				free(flipdata);
2119			goto error_undo;
2120		}
2121		emitted++;
2122	}
2123
2124	flipdata->old_fb_id = old_fb_id;
2125	return TRUE;
2126
2127error_undo:
2128	drmModeRmFB(drmmode->fd, drmmode->fb_id);
2129	drmmode->fb_id = old_fb_id;
2130
2131error_out:
2132	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
2133		   strerror(errno));
2134	return FALSE;
2135}
2136
2137