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 <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/poll.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <sys/ioctl.h>
39 
40 #include "xorg-server.h"
41 #include "xorgVersion.h"
42 
43 #include "intel.h"
44 #include "intel_bufmgr.h"
45 #include "intel_options.h"
46 #include "backlight.h"
47 #include "xf86drm.h"
48 #include "xf86drmMode.h"
49 #include "X11/Xatom.h"
50 #if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H)
51 #include <X11/extensions/dpmsconst.h>
52 #else
53 #define DPMSModeOn 0
54 #define DPMSModeOff 3
55 #endif
56 #include "xf86DDC.h"
57 #include "fb.h"
58 
59 #if USE_UXA
60 #include "intel_uxa.h"
61 #endif
62 
63 #define KNOWN_MODE_FLAGS ((1<<14)-1)
64 
65 struct intel_drm_queue {
66         struct list list;
67         xf86CrtcPtr crtc;
68         uint32_t seq;
69         void *data;
70         ScrnInfoPtr scrn;
71         intel_drm_handler_proc handler;
72         intel_drm_abort_proc abort;
73 };
74 
75 static uint32_t intel_drm_seq;
76 static struct list intel_drm_queue;
77 
78 struct intel_mode {
79 	int fd;
80 	uint32_t fb_id;
81 	int cpp;
82 
83 	drmEventContext event_context;
84 	int old_fb_id;
85 	int flip_count;
86 	uint64_t fe_msc;
87 	uint64_t fe_usec;
88 
89 	struct list outputs;
90 	struct list crtcs;
91 
92 	struct {
93 		intel_pageflip_handler_proc handler;
94 		intel_pageflip_abort_proc abort;
95 		void *data;
96 	} pageflip;
97 };
98 
99 struct intel_pageflip {
100 	struct intel_mode *mode;
101 	Bool dispatch_me;
102 };
103 
104 struct intel_crtc {
105 	struct intel_mode *mode;
106 	drmModeModeInfo kmode;
107 	drmModeCrtcPtr mode_crtc;
108 	int pipe;
109 	dri_bo *cursor;
110 	dri_bo *rotate_bo;
111 	uint32_t rotate_pitch;
112 	uint32_t rotate_fb_id;
113 	xf86CrtcPtr crtc;
114 	struct list link;
115 	PixmapPtr scanout_pixmap;
116 	uint32_t scanout_fb_id;
117 	uint32_t msc_prev;
118 	uint64_t msc_high;
119 };
120 
121 struct intel_property {
122 	drmModePropertyPtr mode_prop;
123 	uint64_t value;
124 	int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
125 	Atom *atoms;
126 };
127 
128 struct intel_output {
129 	struct intel_mode *mode;
130 	int output_id;
131 	drmModeConnectorPtr mode_output;
132 	drmModeEncoderPtr *mode_encoders;
133 	drmModePropertyBlobPtr edid_blob;
134 	int num_props;
135 	struct intel_property *props;
136 	void *private_data;
137 
138 	Bool has_panel_limits;
139 	int panel_hdisplay;
140 	int panel_vdisplay;
141 
142 	int dpms_mode;
143 	struct backlight backlight;
144 	int backlight_active_level;
145 	xf86OutputPtr output;
146 	struct list link;
147 	int enc_mask;
148 	int enc_clone_mask;
149 };
150 
151 static void
152 intel_output_dpms(xf86OutputPtr output, int mode);
153 
154 static void
155 intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode);
156 
157 static inline int
crtc_id(struct intel_crtc * crtc)158 crtc_id(struct intel_crtc *crtc)
159 {
160 	return crtc->mode_crtc->crtc_id;
161 }
162 
163 static void
intel_output_backlight_set(xf86OutputPtr output,int level)164 intel_output_backlight_set(xf86OutputPtr output, int level)
165 {
166 	struct intel_output *intel_output = output->driver_private;
167 	if (backlight_set(&intel_output->backlight, level) < 0) {
168 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
169 			   "failed to set backlight %s to brightness level %d, disabling\n",
170 			   intel_output->backlight.iface, level);
171 		backlight_disable(&intel_output->backlight);
172 	}
173 }
174 
175 static int
intel_output_backlight_get(xf86OutputPtr output)176 intel_output_backlight_get(xf86OutputPtr output)
177 {
178 	struct intel_output *intel_output = output->driver_private;
179 	return backlight_get(&intel_output->backlight);
180 }
181 
182 static void
intel_output_backlight_init(xf86OutputPtr output)183 intel_output_backlight_init(xf86OutputPtr output)
184 {
185 	struct intel_output *intel_output = output->driver_private;
186 	intel_screen_private *intel = intel_get_screen_private(output->scrn);
187 	const char *str;
188 
189 #if !USE_BACKLIGHT
190 	return;
191 #endif
192 
193 	str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT);
194 	if (str != NULL) {
195 		if (backlight_exists(str)) {
196 			intel_output->backlight_active_level =
197 				backlight_open(&intel_output->backlight,
198 					       strdup(str));
199 			if (intel_output->backlight_active_level != -1) {
200 				xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,
201 					   "found backlight control interface %s\n", str);
202 				return;
203 			}
204 		}
205 
206 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
207 			   "unrecognised backlight control interface %s\n", str);
208 	}
209 
210 	intel_output->backlight_active_level =
211 		backlight_open(&intel_output->backlight, NULL);
212 	if (intel_output->backlight_active_level != -1) {
213 		xf86DrvMsg(output->scrn->scrnIndex, X_PROBED,
214 			   "found backlight control interface %s\n",
215 			   intel_output->backlight.iface);
216 		return;
217 	}
218 }
219 
220 static void
mode_from_kmode(ScrnInfoPtr scrn,drmModeModeInfoPtr kmode,DisplayModePtr mode)221 mode_from_kmode(ScrnInfoPtr scrn,
222 		drmModeModeInfoPtr kmode,
223 		DisplayModePtr	mode)
224 {
225 	memset(mode, 0, sizeof(DisplayModeRec));
226 	mode->status = MODE_OK;
227 
228 	mode->Clock = kmode->clock;
229 
230 	mode->HDisplay = kmode->hdisplay;
231 	mode->HSyncStart = kmode->hsync_start;
232 	mode->HSyncEnd = kmode->hsync_end;
233 	mode->HTotal = kmode->htotal;
234 	mode->HSkew = kmode->hskew;
235 
236 	mode->VDisplay = kmode->vdisplay;
237 	mode->VSyncStart = kmode->vsync_start;
238 	mode->VSyncEnd = kmode->vsync_end;
239 	mode->VTotal = kmode->vtotal;
240 	mode->VScan = kmode->vscan;
241 
242 	mode->Flags = kmode->flags;
243 	mode->name = strdup(kmode->name);
244 
245 	if (kmode->type & DRM_MODE_TYPE_DRIVER)
246 		mode->type = M_T_DRIVER;
247 	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
248 		mode->type |= M_T_PREFERRED;
249 
250 	if (mode->status == MODE_OK && kmode->flags & ~KNOWN_MODE_FLAGS)
251 		mode->status = MODE_BAD; /* unknown flags => unhandled */
252 
253 	xf86SetModeCrtc (mode, scrn->adjustFlags);
254 }
255 
256 static void
mode_to_kmode(ScrnInfoPtr scrn,drmModeModeInfoPtr kmode,DisplayModePtr mode)257 mode_to_kmode(ScrnInfoPtr scrn,
258 	      drmModeModeInfoPtr kmode,
259 	      DisplayModePtr mode)
260 {
261 	memset(kmode, 0, sizeof(*kmode));
262 
263 	kmode->clock = mode->Clock;
264 	kmode->hdisplay = mode->HDisplay;
265 	kmode->hsync_start = mode->HSyncStart;
266 	kmode->hsync_end = mode->HSyncEnd;
267 	kmode->htotal = mode->HTotal;
268 	kmode->hskew = mode->HSkew;
269 
270 	kmode->vdisplay = mode->VDisplay;
271 	kmode->vsync_start = mode->VSyncStart;
272 	kmode->vsync_end = mode->VSyncEnd;
273 	kmode->vtotal = mode->VTotal;
274 	kmode->vscan = mode->VScan;
275 
276 	kmode->flags = mode->Flags;
277 	if (mode->name)
278 		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
279 	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
280 }
281 
282 static void
intel_crtc_dpms(xf86CrtcPtr crtc,int mode)283 intel_crtc_dpms(xf86CrtcPtr crtc, int mode)
284 {
285 }
286 
287 void
intel_mode_disable_unused_functions(ScrnInfoPtr scrn)288 intel_mode_disable_unused_functions(ScrnInfoPtr scrn)
289 {
290 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
291 	struct intel_mode *mode = intel_get_screen_private(scrn)->modes;
292 	int i;
293 
294 	/* Force off for consistency between kernel and ddx */
295 	for (i = 0; i < xf86_config->num_crtc; i++) {
296 		xf86CrtcPtr crtc = xf86_config->crtc[i];
297 		if (!crtc->enabled)
298 			drmModeSetCrtc(mode->fd, crtc_id(crtc->driver_private),
299 				       0, 0, 0, NULL, 0, NULL);
300 	}
301 }
302 
303 static Bool
intel_crtc_apply(xf86CrtcPtr crtc)304 intel_crtc_apply(xf86CrtcPtr crtc)
305 {
306 	ScrnInfoPtr scrn = crtc->scrn;
307 	struct intel_crtc *intel_crtc = crtc->driver_private;
308 	struct intel_mode *mode = intel_crtc->mode;
309 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
310 	uint32_t *output_ids;
311 	int output_count = 0;
312 	int fb_id, x, y;
313 	int i, ret = FALSE;
314 
315 	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
316 	if (!output_ids)
317 		return FALSE;
318 
319 	for (i = 0; i < xf86_config->num_output; i++) {
320 		xf86OutputPtr output = xf86_config->output[i];
321 		struct intel_output *intel_output;
322 
323 		/* Make sure we mark the output as off (and save the backlight)
324 		 * before the kernel turns it off due to changing the pipe.
325 		 * This is necessary as the kernel may turn off the backlight
326 		 * and we lose track of the user settings.
327 		 */
328 		if (output->crtc == NULL)
329 			output->funcs->dpms(output, DPMSModeOff);
330 
331 		if (output->crtc != crtc)
332 			continue;
333 
334 		intel_output = output->driver_private;
335 		if (!intel_output->mode_output)
336 			return FALSE;
337 
338 		output_ids[output_count] =
339 			intel_output->mode_output->connector_id;
340 		output_count++;
341 	}
342 
343 	if (!intel_crtc->scanout_fb_id) {
344 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
345 		if (!xf86CrtcRotate(crtc, mode, rotation))
346 			goto done;
347 #else
348 		if (!xf86CrtcRotate(crtc))
349 			goto done;
350 #endif
351 	}
352 
353 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
354 	crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
355 			       crtc->gamma_blue, crtc->gamma_size);
356 #endif
357 
358 	x = crtc->x;
359 	y = crtc->y;
360 	fb_id = mode->fb_id;
361 	if (intel_crtc->rotate_fb_id) {
362 		fb_id = intel_crtc->rotate_fb_id;
363 		x = 0;
364 		y = 0;
365 	} else if (intel_crtc->scanout_fb_id && intel_crtc->scanout_pixmap->drawable.width >= crtc->mode.HDisplay && intel_crtc->scanout_pixmap->drawable.height >= crtc->mode.VDisplay) {
366 		fb_id = intel_crtc->scanout_fb_id;
367 		x = 0;
368 		y = 0;
369 	}
370 	ret = drmModeSetCrtc(mode->fd, crtc_id(intel_crtc),
371 			     fb_id, x, y, output_ids, output_count,
372 			     &intel_crtc->kmode);
373 	if (ret) {
374 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
375 			   "failed to set mode: %s\n", strerror(-ret));
376 		ret = FALSE;
377 	} else {
378 		ret = TRUE;
379 
380 		/* Force DPMS to On for all outputs, which the kernel will have done
381 		 * with the mode set. Also, restore the backlight level
382 		 */
383 		for (i = 0; i < xf86_config->num_output; i++) {
384 		    xf86OutputPtr output = xf86_config->output[i];
385 		    struct intel_output *intel_output;
386 
387 		    if (output->crtc != crtc)
388 			continue;
389 
390 		    intel_output = output->driver_private;
391 		    intel_output_dpms_backlight(output, intel_output->dpms_mode, DPMSModeOn);
392 		    intel_output->dpms_mode = DPMSModeOn;
393 		}
394 	}
395 
396 	if (scrn->pScreen)
397 		xf86_reload_cursors(scrn->pScreen);
398 
399 done:
400 	free(output_ids);
401 	return ret;
402 }
403 
404 static Bool
intel_crtc_set_mode_major(xf86CrtcPtr crtc,DisplayModePtr mode,Rotation rotation,int x,int y)405 intel_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
406 			  Rotation rotation, int x, int y)
407 {
408 	ScrnInfoPtr scrn = crtc->scrn;
409 	intel_screen_private *intel = intel_get_screen_private(scrn);
410 	struct intel_crtc *intel_crtc = crtc->driver_private;
411 	struct intel_mode *intel_mode = intel_crtc->mode;
412 	int saved_x, saved_y;
413 	Rotation saved_rotation;
414 	DisplayModeRec saved_mode;
415 	int ret = TRUE;
416 	unsigned int pitch = scrn->displayWidth * intel->cpp;
417 
418 	if (intel_mode->fb_id == 0) {
419 		ret = drmModeAddFB(intel_mode->fd,
420 				   scrn->virtualX, scrn->virtualY,
421 				   scrn->depth, scrn->bitsPerPixel,
422 				   pitch, intel->front_buffer->handle,
423 				   &intel_mode->fb_id);
424 		if (ret < 0) {
425 			ErrorF("failed to add fb\n");
426 			return FALSE;
427 		}
428 
429 		drm_intel_bo_disable_reuse(intel->front_buffer);
430 	}
431 
432 	saved_mode = crtc->mode;
433 	saved_x = crtc->x;
434 	saved_y = crtc->y;
435 	saved_rotation = crtc->rotation;
436 
437 	crtc->mode = *mode;
438 	crtc->x = x;
439 	crtc->y = y;
440 	crtc->rotation = rotation;
441 
442         intel_flush(intel);
443 
444 	mode_to_kmode(crtc->scrn, &intel_crtc->kmode, mode);
445 	ret = intel_crtc_apply(crtc);
446 	if (!ret) {
447 		crtc->x = saved_x;
448 		crtc->y = saved_y;
449 		crtc->rotation = saved_rotation;
450 		crtc->mode = saved_mode;
451 	}
452 	return ret;
453 }
454 
455 static void
intel_crtc_set_cursor_colors(xf86CrtcPtr crtc,int bg,int fg)456 intel_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
457 {
458 
459 }
460 
461 static void
intel_crtc_set_cursor_position(xf86CrtcPtr crtc,int x,int y)462 intel_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
463 {
464 	struct intel_crtc *intel_crtc = crtc->driver_private;
465 	struct intel_mode *mode = intel_crtc->mode;
466 
467 	drmModeMoveCursor(mode->fd, crtc_id(intel_crtc), x, y);
468 }
469 
470 static int
__intel_crtc_load_cursor_argb(xf86CrtcPtr crtc,CARD32 * image)471 __intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
472 {
473 	struct intel_crtc *intel_crtc = crtc->driver_private;
474 	int ret;
475 
476 	ret = dri_bo_subdata(intel_crtc->cursor, 0, 64*64*4, image);
477 	if (ret)
478 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
479 			   "failed to set cursor: %s\n", strerror(-ret));
480 
481 	return ret;
482 }
483 
484 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,2)
485 static Bool
intel_crtc_load_cursor_argb(xf86CrtcPtr crtc,CARD32 * image)486 intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
487 {
488 	return __intel_crtc_load_cursor_argb(crtc, image) == 0;
489 }
490 #else
491 static void
intel_crtc_load_cursor_argb(xf86CrtcPtr crtc,CARD32 * image)492 intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
493 {
494 	__intel_crtc_load_cursor_argb(crtc, image);
495 }
496 #endif
497 
498 static void
intel_crtc_hide_cursor(xf86CrtcPtr crtc)499 intel_crtc_hide_cursor(xf86CrtcPtr crtc)
500 {
501 	struct intel_crtc *intel_crtc = crtc->driver_private;
502 	struct intel_mode *mode = intel_crtc->mode;
503 
504 	drmModeSetCursor(mode->fd, crtc_id(intel_crtc), 0, 64, 64);
505 }
506 
507 static void
intel_crtc_show_cursor(xf86CrtcPtr crtc)508 intel_crtc_show_cursor(xf86CrtcPtr crtc)
509 {
510 	struct intel_crtc *intel_crtc = crtc->driver_private;
511 	struct intel_mode *mode = intel_crtc->mode;
512 
513 	drmModeSetCursor(mode->fd, crtc_id(intel_crtc),
514 			 intel_crtc->cursor->handle, 64, 64);
515 }
516 
517 static void *
intel_crtc_shadow_allocate(xf86CrtcPtr crtc,int width,int height)518 intel_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
519 {
520 	ScrnInfoPtr scrn = crtc->scrn;
521 	struct intel_crtc *intel_crtc = crtc->driver_private;
522 	struct intel_mode *mode = intel_crtc->mode;
523 	int rotate_pitch;
524 	uint32_t tiling;
525 	int ret;
526 
527 	intel_crtc->rotate_bo = intel_allocate_framebuffer(scrn,
528 							     width, height,
529 							     mode->cpp,
530 							     &rotate_pitch,
531 							     &tiling);
532 
533 	if (!intel_crtc->rotate_bo) {
534 		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
535 			   "Couldn't allocate shadow memory for rotated CRTC\n");
536 		return NULL;
537 	}
538 
539 	ret = drmModeAddFB(mode->fd, width, height, crtc->scrn->depth,
540 			   crtc->scrn->bitsPerPixel, rotate_pitch,
541 			   intel_crtc->rotate_bo->handle,
542 			   &intel_crtc->rotate_fb_id);
543 	if (ret) {
544 		ErrorF("failed to add rotate fb\n");
545 		drm_intel_bo_unreference(intel_crtc->rotate_bo);
546 		return NULL;
547 	}
548 
549 	intel_crtc->rotate_pitch = rotate_pitch;
550 	return intel_crtc->rotate_bo;
551 }
552 
553 static PixmapPtr
intel_create_pixmap_header(ScreenPtr pScreen,int width,int height,int depth,int bitsPerPixel,int devKind,void * pPixData)554 intel_create_pixmap_header(ScreenPtr pScreen, int width, int height, int depth,
555                            int bitsPerPixel, int devKind, void *pPixData)
556 {
557         PixmapPtr pixmap;
558 
559         /* width and height of 0 means don't allocate any pixmap data */
560         pixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0);
561 
562         if (pixmap) {
563                 if ((*pScreen->ModifyPixmapHeader) (pixmap, width, height, depth,
564                                                     bitsPerPixel, devKind, pPixData))
565                 {
566                         return pixmap;
567                 }
568                 (*pScreen->DestroyPixmap) (pixmap);
569         }
570         return NullPixmap;
571 }
572 
573 static PixmapPtr
intel_crtc_shadow_create(xf86CrtcPtr crtc,void * data,int width,int height)574 intel_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
575 {
576 	ScrnInfoPtr scrn = crtc->scrn;
577 	intel_screen_private *intel = intel_get_screen_private(scrn);
578 	struct intel_crtc *intel_crtc = crtc->driver_private;
579 	PixmapPtr rotate_pixmap;
580 
581 	if (!data) {
582 		data = intel_crtc_shadow_allocate (crtc, width, height);
583 		if (!data) {
584 			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
585 				   "Couldn't allocate shadow pixmap for rotated CRTC\n");
586 			return NULL;
587 		}
588 	}
589 	if (intel_crtc->rotate_bo == NULL) {
590 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
591 			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
592 		return NULL;
593 	}
594 
595 	rotate_pixmap = intel_create_pixmap_header(scrn->pScreen,
596                                                    width, height,
597                                                    scrn->depth,
598                                                    scrn->bitsPerPixel,
599                                                    intel_crtc->rotate_pitch,
600                                                    NULL);
601 
602 	if (rotate_pixmap == NULL) {
603 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
604 			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
605 		return NULL;
606 	}
607 
608 	intel_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_bo);
609 
610 	intel->shadow_present = TRUE;
611 
612 	return rotate_pixmap;
613 }
614 
615 static void
intel_crtc_shadow_destroy(xf86CrtcPtr crtc,PixmapPtr rotate_pixmap,void * data)616 intel_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
617 {
618 	ScrnInfoPtr scrn = crtc->scrn;
619 	intel_screen_private *intel = intel_get_screen_private(scrn);
620 	struct intel_crtc *intel_crtc = crtc->driver_private;
621 	struct intel_mode *mode = intel_crtc->mode;
622 
623 	if (rotate_pixmap) {
624                 intel_set_pixmap_bo(rotate_pixmap, NULL);
625                 rotate_pixmap->drawable.pScreen->DestroyPixmap(rotate_pixmap);
626 	}
627 
628 	if (data) {
629 		/* Be sure to sync acceleration before the memory gets
630 		 * unbound. */
631 		drmModeRmFB(mode->fd, intel_crtc->rotate_fb_id);
632 		intel_crtc->rotate_fb_id = 0;
633 
634 		dri_bo_unreference(intel_crtc->rotate_bo);
635 		intel_crtc->rotate_bo = NULL;
636 	}
637 
638 	intel->shadow_present = FALSE;
639 }
640 
641 static void
intel_crtc_gamma_set(xf86CrtcPtr crtc,CARD16 * red,CARD16 * green,CARD16 * blue,int size)642 intel_crtc_gamma_set(xf86CrtcPtr crtc,
643 		       CARD16 *red, CARD16 *green, CARD16 *blue, int size)
644 {
645 	struct intel_crtc *intel_crtc = crtc->driver_private;
646 	struct intel_mode *mode = intel_crtc->mode;
647 
648 	drmModeCrtcSetGamma(mode->fd, crtc_id(intel_crtc),
649 			    size, red, green, blue);
650 }
651 
652 static void
intel_crtc_destroy(xf86CrtcPtr crtc)653 intel_crtc_destroy(xf86CrtcPtr crtc)
654 {
655 	struct intel_crtc *intel_crtc = crtc->driver_private;
656 
657 	if (intel_crtc->cursor) {
658 		drmModeSetCursor(intel_crtc->mode->fd, crtc_id(intel_crtc), 0, 64, 64);
659 		drm_intel_bo_unreference(intel_crtc->cursor);
660 		intel_crtc->cursor = NULL;
661 	}
662 
663 	list_del(&intel_crtc->link);
664 	free(intel_crtc);
665 
666 	crtc->driver_private = NULL;
667 }
668 
669 #ifdef INTEL_PIXMAP_SHARING
670 static Bool
intel_set_scanout_pixmap(xf86CrtcPtr crtc,PixmapPtr ppix)671 intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
672 {
673 	struct intel_crtc *intel_crtc = crtc->driver_private;
674 	ScrnInfoPtr scrn = crtc->scrn;
675 	intel_screen_private *intel = intel_get_screen_private(scrn);
676 	dri_bo *bo;
677 
678 	if (ppix == intel_crtc->scanout_pixmap)
679 		return TRUE;
680 
681 	if (!ppix) {
682 		intel_crtc->scanout_pixmap = NULL;
683 		if (intel_crtc->scanout_fb_id) {
684 			drmModeRmFB(intel->drmSubFD, intel_crtc->scanout_fb_id);
685 			intel_crtc->scanout_fb_id = 0;
686 		}
687 		return TRUE;
688 	}
689 
690 	bo = intel_get_pixmap_bo(ppix);
691 	if (!bo)
692 		return FALSE;
693 
694 	if (intel->front_buffer)
695 		return FALSE;
696 
697 	drm_intel_bo_disable_reuse(bo);
698 
699 	intel_crtc->scanout_pixmap = ppix;
700 	return drmModeAddFB(intel->drmSubFD, ppix->drawable.width,
701 			   ppix->drawable.height, ppix->drawable.depth,
702 			   ppix->drawable.bitsPerPixel, ppix->devKind,
703 			   bo->handle, &intel_crtc->scanout_fb_id) == 0;
704 }
705 #endif
706 
707 static const xf86CrtcFuncsRec intel_crtc_funcs = {
708 	.dpms = intel_crtc_dpms,
709 	.set_mode_major = intel_crtc_set_mode_major,
710 	.set_cursor_colors = intel_crtc_set_cursor_colors,
711 	.set_cursor_position = intel_crtc_set_cursor_position,
712 	.show_cursor = intel_crtc_show_cursor,
713 	.hide_cursor = intel_crtc_hide_cursor,
714 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,3)
715 	.load_cursor_argb_check = intel_crtc_load_cursor_argb,
716 #else
717 	.load_cursor_argb = intel_crtc_load_cursor_argb,
718 #endif
719 	.shadow_create = intel_crtc_shadow_create,
720 	.shadow_allocate = intel_crtc_shadow_allocate,
721 	.shadow_destroy = intel_crtc_shadow_destroy,
722 	.gamma_set = intel_crtc_gamma_set,
723 	.destroy = intel_crtc_destroy,
724 #ifdef INTEL_PIXMAP_SHARING
725 	.set_scanout_pixmap = intel_set_scanout_pixmap,
726 #endif
727 };
728 
729 static void
intel_crtc_init(ScrnInfoPtr scrn,struct intel_mode * mode,drmModeResPtr mode_res,int num)730 intel_crtc_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res, int num)
731 {
732 	intel_screen_private *intel = intel_get_screen_private(scrn);
733 	xf86CrtcPtr crtc;
734 	struct intel_crtc *intel_crtc;
735 
736 	intel_crtc = calloc(sizeof(struct intel_crtc), 1);
737 	if (intel_crtc == NULL)
738 		return;
739 
740 	crtc = xf86CrtcCreate(scrn, &intel_crtc_funcs);
741 	if (crtc == NULL) {
742 		free(intel_crtc);
743 		return;
744 	}
745 
746 	intel_crtc->mode_crtc = drmModeGetCrtc(mode->fd,
747 					       mode_res->crtcs[num]);
748 	if (intel_crtc->mode_crtc == NULL) {
749 		free(intel_crtc);
750 		return;
751 	}
752 
753 	intel_crtc->mode = mode;
754 	crtc->driver_private = intel_crtc;
755 
756 	intel_crtc->pipe = drm_intel_get_pipe_from_crtc_id(intel->bufmgr,
757 							   crtc_id(intel_crtc));
758 
759 	intel_crtc->cursor = drm_intel_bo_alloc(intel->bufmgr, "ARGB cursor",
760 						4*64*64, 4096);
761 
762 	intel_crtc->crtc = crtc;
763 	list_add(&intel_crtc->link, &mode->crtcs);
764 }
765 
766 static Bool
is_panel(int type)767 is_panel(int type)
768 {
769 	return (type == DRM_MODE_CONNECTOR_LVDS ||
770 		type == DRM_MODE_CONNECTOR_eDP);
771 }
772 
773 static xf86OutputStatus
intel_output_detect(xf86OutputPtr output)774 intel_output_detect(xf86OutputPtr output)
775 {
776 	/* go to the hw and retrieve a new output struct */
777 	struct intel_output *intel_output = output->driver_private;
778 	struct intel_mode *mode = intel_output->mode;
779 	xf86OutputStatus status;
780 
781 	drmModeFreeConnector(intel_output->mode_output);
782 	intel_output->mode_output =
783 		drmModeGetConnector(mode->fd, intel_output->output_id);
784 	if (intel_output->mode_output == NULL) {
785 		/* and hope we are safe everywhere else */
786 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
787 			   "drmModeGetConnector failed, reporting output disconnected\n");
788 		return XF86OutputStatusDisconnected;
789 	}
790 
791 	switch (intel_output->mode_output->connection) {
792 	case DRM_MODE_CONNECTED:
793 		status = XF86OutputStatusConnected;
794 		break;
795 	case DRM_MODE_DISCONNECTED:
796 		status = XF86OutputStatusDisconnected;
797 		break;
798 	default:
799 	case DRM_MODE_UNKNOWNCONNECTION:
800 		status = XF86OutputStatusUnknown;
801 		break;
802 	}
803 	return status;
804 }
805 
806 static Bool
intel_output_mode_valid(xf86OutputPtr output,DisplayModePtr pModes)807 intel_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
808 {
809 	struct intel_output *intel_output = output->driver_private;
810 
811 	/*
812 	 * If the connector type is a panel, we will use the panel limit to
813 	 * verfiy whether the mode is valid.
814 	 */
815 	if (intel_output->has_panel_limits) {
816 		if (pModes->HDisplay > intel_output->panel_hdisplay ||
817 		    pModes->VDisplay > intel_output->panel_vdisplay)
818 			return MODE_PANEL;
819 	}
820 
821 	return MODE_OK;
822 }
823 
824 static void
intel_output_attach_edid(xf86OutputPtr output)825 intel_output_attach_edid(xf86OutputPtr output)
826 {
827 	struct intel_output *intel_output = output->driver_private;
828 	drmModeConnectorPtr koutput = intel_output->mode_output;
829 	struct intel_mode *mode = intel_output->mode;
830 	xf86MonPtr mon = NULL;
831 	int i;
832 
833 	if (!koutput) {
834 		xf86OutputSetEDID(output, mon);
835 		return;
836 	}
837 
838 	/* look for an EDID property */
839 	for (i = 0; i < koutput->count_props; i++) {
840 		drmModePropertyPtr props;
841 
842 		props = drmModeGetProperty(mode->fd, koutput->props[i]);
843 		if (!props)
844 			continue;
845 
846 		if (!(props->flags & DRM_MODE_PROP_BLOB)) {
847 			drmModeFreeProperty(props);
848 			continue;
849 		}
850 
851 		if (!strcmp(props->name, "EDID")) {
852 			drmModeFreePropertyBlob(intel_output->edid_blob);
853 			intel_output->edid_blob =
854 				drmModeGetPropertyBlob(mode->fd,
855 						       koutput->prop_values[i]);
856 		}
857 		drmModeFreeProperty(props);
858 	}
859 
860 	if (intel_output->edid_blob) {
861 		mon = xf86InterpretEDID(output->scrn->scrnIndex,
862 					intel_output->edid_blob->data);
863 
864 		if (mon && intel_output->edid_blob->length > 128)
865 			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
866 	}
867 
868 	xf86OutputSetEDID(output, mon);
869 }
870 
871 static void
intel_output_attach_tile(xf86OutputPtr output)872 intel_output_attach_tile(xf86OutputPtr output)
873 {
874 #if XF86_OUTPUT_VERSION >= 3
875 	struct intel_output *intel_output = output->driver_private;
876 	drmModeConnectorPtr koutput = intel_output->mode_output;
877 	struct intel_mode *mode = intel_output->mode;
878 	drmModePropertyBlobPtr blob = NULL;
879 	struct xf86CrtcTileInfo tile_info, *set = NULL;
880 	int i;
881 
882 	for (i = 0; koutput && i < koutput->count_props; i++) {
883 		drmModePropertyPtr props;
884 
885 		props = drmModeGetProperty(mode->fd, koutput->props[i]);
886 		if (!props)
887 			continue;
888 
889 		if (!(props->flags & DRM_MODE_PROP_BLOB)) {
890 			drmModeFreeProperty(props);
891 			continue;
892 		}
893 
894 		if (!strcmp(props->name, "TILE")) {
895 			blob = drmModeGetPropertyBlob(mode->fd,
896 						      koutput->prop_values[i]);
897 		}
898 		drmModeFreeProperty(props);
899 	}
900 
901 	if (blob) {
902 		if (xf86OutputParseKMSTile(blob->data,
903 					   blob->length,
904 					   &tile_info))
905 			set = &tile_info;
906 		drmModeFreePropertyBlob(blob);
907 	}
908 
909 	xf86OutputSetTile(output, set);
910 #endif
911 }
912 
913 static DisplayModePtr
intel_output_panel_edid(xf86OutputPtr output,DisplayModePtr modes)914 intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
915 {
916 	xf86MonPtr mon = output->MonInfo;
917 
918 	if (!mon || !GTF_SUPPORTED(mon->features.msc)) {
919 		DisplayModePtr i, m, p = NULL;
920 		int max_x = 0, max_y = 0;
921 		float max_vrefresh = 0.0;
922 
923 		for (m = modes; m; m = m->next) {
924 			if (m->type & M_T_PREFERRED)
925 				p = m;
926 			max_x = max(max_x, m->HDisplay);
927 			max_y = max(max_y, m->VDisplay);
928 			max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
929 		}
930 
931 		max_vrefresh = max(max_vrefresh, 60.0);
932 		max_vrefresh *= (1 + SYNC_TOLERANCE);
933 
934 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0)
935 		m = xf86GetDefaultModes();
936 #else
937 		m = xf86GetDefaultModes(0,0);
938 #endif
939 
940 		xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
941 
942 		for (i = m; i; i = i->next) {
943 			if (xf86ModeVRefresh(i) > max_vrefresh)
944 				i->status = MODE_VSYNC;
945 			if (p && i->HDisplay >= p->HDisplay &&
946 			    i->VDisplay >= p->VDisplay &&
947 			    xf86ModeVRefresh(i) >= xf86ModeVRefresh(p))
948 				i->status = MODE_VSYNC;
949 		}
950 
951 		xf86PruneInvalidModes(output->scrn, &m, FALSE);
952 
953 		modes = xf86ModesAdd(modes, m);
954 	}
955 
956 	return modes;
957 }
958 
959 static DisplayModePtr
intel_output_get_modes(xf86OutputPtr output)960 intel_output_get_modes(xf86OutputPtr output)
961 {
962 	struct intel_output *intel_output = output->driver_private;
963 	drmModeConnectorPtr koutput = intel_output->mode_output;
964 	DisplayModePtr Modes = NULL;
965 	int i;
966 
967 	intel_output_attach_edid(output);
968 	intel_output_attach_tile(output);
969 
970 	if (!koutput)
971 		return Modes;
972 
973 	/* modes should already be available */
974 	for (i = 0; i < koutput->count_modes; i++) {
975 		DisplayModePtr Mode;
976 
977 		Mode = calloc(1, sizeof(DisplayModeRec));
978 		if (Mode) {
979 			mode_from_kmode(output->scrn, &koutput->modes[i], Mode);
980 			Modes = xf86ModesAdd(Modes, Mode);
981 		}
982 	}
983 
984 	/*
985 	 * If the connector type is a panel, we will traverse the kernel mode to
986 	 * get the panel limit. And then add all the standard modes to fake
987 	 * the fullscreen experience.
988 	 * If it is incorrect, please fix me.
989 	 */
990 	intel_output->has_panel_limits = FALSE;
991 	if (is_panel(koutput->connector_type)) {
992 		for (i = 0; i < koutput->count_modes; i++) {
993 			drmModeModeInfo *mode_ptr;
994 
995 			mode_ptr = &koutput->modes[i];
996 			if (mode_ptr->hdisplay > intel_output->panel_hdisplay)
997 				intel_output->panel_hdisplay = mode_ptr->hdisplay;
998 			if (mode_ptr->vdisplay > intel_output->panel_vdisplay)
999 				intel_output->panel_vdisplay = mode_ptr->vdisplay;
1000 		}
1001 
1002 		intel_output->has_panel_limits =
1003 			intel_output->panel_hdisplay &&
1004 			intel_output->panel_vdisplay;
1005 
1006 		Modes = intel_output_panel_edid(output, Modes);
1007 	}
1008 
1009 	return Modes;
1010 }
1011 
1012 static void
intel_output_destroy(xf86OutputPtr output)1013 intel_output_destroy(xf86OutputPtr output)
1014 {
1015 	struct intel_output *intel_output = output->driver_private;
1016 	int i;
1017 
1018 	drmModeFreePropertyBlob(intel_output->edid_blob);
1019 
1020 	for (i = 0; i < intel_output->num_props; i++) {
1021 		drmModeFreeProperty(intel_output->props[i].mode_prop);
1022 		free(intel_output->props[i].atoms);
1023 	}
1024 	free(intel_output->props);
1025 	for (i = 0; i < intel_output->mode_output->count_encoders; i++) {
1026 		drmModeFreeEncoder(intel_output->mode_encoders[i]);
1027 	}
1028 	free(intel_output->mode_encoders);
1029 	drmModeFreeConnector(intel_output->mode_output);
1030 	intel_output->mode_output = NULL;
1031 
1032 	list_del(&intel_output->link);
1033 	backlight_close(&intel_output->backlight);
1034 	free(intel_output);
1035 
1036 	output->driver_private = NULL;
1037 }
1038 
1039 static void
intel_output_dpms_backlight(xf86OutputPtr output,int oldmode,int mode)1040 intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode)
1041 {
1042 	struct intel_output *intel_output = output->driver_private;
1043 
1044 	if (!intel_output->backlight.iface)
1045 		return;
1046 
1047 	if (mode == DPMSModeOn) {
1048 		/* If we're going from off->on we may need to turn on the backlight. */
1049 		if (oldmode != DPMSModeOn)
1050 			intel_output_backlight_set(output,
1051 						   intel_output->backlight_active_level);
1052 	} else {
1053 		/* Only save the current backlight value if we're going from on to off. */
1054 		if (oldmode == DPMSModeOn)
1055 			intel_output->backlight_active_level = intel_output_backlight_get(output);
1056 		intel_output_backlight_set(output, 0);
1057 	}
1058 }
1059 
1060 static void
intel_output_dpms(xf86OutputPtr output,int dpms)1061 intel_output_dpms(xf86OutputPtr output, int dpms)
1062 {
1063 	struct intel_output *intel_output = output->driver_private;
1064 	drmModeConnectorPtr koutput = intel_output->mode_output;
1065 	struct intel_mode *mode = intel_output->mode;
1066 	int i;
1067 
1068 	if (!koutput)
1069 		return;
1070 
1071 	for (i = 0; i < koutput->count_props; i++) {
1072 		drmModePropertyPtr props;
1073 
1074 		props = drmModeGetProperty(mode->fd, koutput->props[i]);
1075 		if (!props)
1076 			continue;
1077 
1078 		if (!strcmp(props->name, "DPMS")) {
1079 			/* Make sure to reverse the order between on and off. */
1080 			if (dpms != DPMSModeOn)
1081 				intel_output_dpms_backlight(output,
1082 							    intel_output->dpms_mode,
1083 							    dpms);
1084 
1085 			drmModeConnectorSetProperty(mode->fd,
1086 						    intel_output->output_id,
1087 						    props->prop_id,
1088 						    dpms);
1089 
1090 			if (dpms == DPMSModeOn)
1091 				intel_output_dpms_backlight(output,
1092 							    intel_output->dpms_mode,
1093 							    dpms);
1094 			intel_output->dpms_mode = dpms;
1095 			drmModeFreeProperty(props);
1096 			return;
1097 		}
1098 
1099 		drmModeFreeProperty(props);
1100 	}
1101 }
1102 
1103 int
intel_output_dpms_status(xf86OutputPtr output)1104 intel_output_dpms_status(xf86OutputPtr output)
1105 {
1106 	struct intel_output *intel_output = output->driver_private;
1107 	return intel_output->dpms_mode;
1108 }
1109 
1110 static Bool
intel_property_ignore(drmModePropertyPtr prop)1111 intel_property_ignore(drmModePropertyPtr prop)
1112 {
1113 	if (!prop)
1114 		return TRUE;
1115 
1116 	/* ignore blob prop */
1117 	if (prop->flags & DRM_MODE_PROP_BLOB)
1118 		return TRUE;
1119 
1120 	/* ignore standard property */
1121 	if (!strcmp(prop->name, "EDID") ||
1122 	    !strcmp(prop->name, "DPMS"))
1123 		return TRUE;
1124 
1125 	return FALSE;
1126 }
1127 
1128 static void
intel_output_create_ranged_atom(xf86OutputPtr output,Atom * atom,const char * name,INT32 min,INT32 max,uint64_t value,Bool immutable)1129 intel_output_create_ranged_atom(xf86OutputPtr output, Atom *atom,
1130 				const char *name, INT32 min, INT32 max,
1131 				uint64_t value, Bool immutable)
1132 {
1133 	int err;
1134 	INT32 atom_range[2];
1135 
1136 	atom_range[0] = min;
1137 	atom_range[1] = max;
1138 
1139 	*atom = MakeAtom(name, strlen(name), TRUE);
1140 
1141 	err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE,
1142 					TRUE, immutable, 2, atom_range);
1143 	if (err != 0)
1144 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1145 			   "RRConfigureOutputProperty error, %d\n", err);
1146 
1147 	err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER,
1148 				     32, PropModeReplace, 1, &value, FALSE,
1149 				     FALSE);
1150 	if (err != 0)
1151 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1152 			   "RRChangeOutputProperty error, %d\n", err);
1153 }
1154 
1155 #define BACKLIGHT_NAME             "Backlight"
1156 #define BACKLIGHT_DEPRECATED_NAME  "BACKLIGHT"
1157 static Atom backlight_atom, backlight_deprecated_atom;
1158 
1159 static void
intel_output_create_resources(xf86OutputPtr output)1160 intel_output_create_resources(xf86OutputPtr output)
1161 {
1162 	struct intel_output *intel_output = output->driver_private;
1163 	drmModeConnectorPtr mode_output = intel_output->mode_output;
1164 	struct intel_mode *mode = intel_output->mode;
1165 	int i, j, err;
1166 
1167 	intel_output->props = calloc(mode_output->count_props,
1168 				     sizeof(struct intel_property));
1169 	if (!intel_output->props)
1170 		return;
1171 
1172 	intel_output->num_props = 0;
1173 	for (i = j = 0; i < mode_output->count_props; i++) {
1174 		drmModePropertyPtr drmmode_prop;
1175 
1176 		drmmode_prop = drmModeGetProperty(mode->fd,
1177 						  mode_output->props[i]);
1178 		if (intel_property_ignore(drmmode_prop)) {
1179 			drmModeFreeProperty(drmmode_prop);
1180 			continue;
1181 		}
1182 
1183 		intel_output->props[j].mode_prop = drmmode_prop;
1184 		intel_output->props[j].value = mode_output->prop_values[i];
1185 		j++;
1186 	}
1187 	intel_output->num_props = j;
1188 
1189 	for (i = 0; i < intel_output->num_props; i++) {
1190 		struct intel_property *p = &intel_output->props[i];
1191 		drmModePropertyPtr drmmode_prop = p->mode_prop;
1192 
1193 		if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
1194 			p->num_atoms = 1;
1195 			p->atoms = calloc(p->num_atoms, sizeof(Atom));
1196 			if (!p->atoms)
1197 				continue;
1198 
1199 			intel_output_create_ranged_atom(output, &p->atoms[0],
1200 							drmmode_prop->name,
1201 							drmmode_prop->values[0],
1202 							drmmode_prop->values[1],
1203 							p->value,
1204 							drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE);
1205 
1206 		} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
1207 			p->num_atoms = drmmode_prop->count_enums + 1;
1208 			p->atoms = calloc(p->num_atoms, sizeof(Atom));
1209 			if (!p->atoms)
1210 				continue;
1211 
1212 			p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1213 			for (j = 1; j <= drmmode_prop->count_enums; j++) {
1214 				struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
1215 				p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
1216 			}
1217 
1218 			err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1219 							FALSE, FALSE,
1220 							drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1221 							p->num_atoms - 1, (INT32 *)&p->atoms[1]);
1222 			if (err != 0) {
1223 				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1224 					   "RRConfigureOutputProperty error, %d\n", err);
1225 			}
1226 
1227 			for (j = 0; j < drmmode_prop->count_enums; j++)
1228 				if (drmmode_prop->enums[j].value == p->value)
1229 					break;
1230 			/* there's always a matching value */
1231 			err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1232 						     XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE);
1233 			if (err != 0) {
1234 				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1235 					   "RRChangeOutputProperty error, %d\n", err);
1236 			}
1237 		}
1238 	}
1239 
1240 	if (intel_output->backlight.iface) {
1241 		/* Set up the backlight property, which takes effect
1242 		 * immediately and accepts values only within the
1243 		 * backlight_range.
1244 		 */
1245 		intel_output_create_ranged_atom(output, &backlight_atom,
1246 					BACKLIGHT_NAME, 0,
1247 					intel_output->backlight.max,
1248 					intel_output->backlight_active_level,
1249 					FALSE);
1250 		intel_output_create_ranged_atom(output,
1251 					&backlight_deprecated_atom,
1252 					BACKLIGHT_DEPRECATED_NAME, 0,
1253 					intel_output->backlight.max,
1254 					intel_output->backlight_active_level,
1255 					FALSE);
1256 	}
1257 }
1258 
1259 static Bool
intel_output_set_property(xf86OutputPtr output,Atom property,RRPropertyValuePtr value)1260 intel_output_set_property(xf86OutputPtr output, Atom property,
1261 			    RRPropertyValuePtr value)
1262 {
1263 	struct intel_output *intel_output = output->driver_private;
1264 	struct intel_mode *mode = intel_output->mode;
1265 	int i;
1266 
1267 	if (property == backlight_atom || property == backlight_deprecated_atom) {
1268 		INT32 val;
1269 
1270 		if (value->type != XA_INTEGER || value->format != 32 ||
1271 		    value->size != 1)
1272 		{
1273 			return FALSE;
1274 		}
1275 
1276 		val = *(INT32 *)value->data;
1277 		if (val < 0 || val > intel_output->backlight.max)
1278 			return FALSE;
1279 
1280 		if (intel_output->dpms_mode == DPMSModeOn)
1281 			intel_output_backlight_set(output, val);
1282 		intel_output->backlight_active_level = val;
1283 		return TRUE;
1284 	}
1285 
1286 	for (i = 0; i < intel_output->num_props; i++) {
1287 		struct intel_property *p = &intel_output->props[i];
1288 
1289 		if (p->atoms[0] != property)
1290 			continue;
1291 
1292 		if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
1293 			uint32_t val;
1294 
1295 			if (value->type != XA_INTEGER || value->format != 32 ||
1296 			    value->size != 1)
1297 				return FALSE;
1298 			val = *(uint32_t *)value->data;
1299 
1300 			drmModeConnectorSetProperty(mode->fd, intel_output->output_id,
1301 						    p->mode_prop->prop_id, (uint64_t)val);
1302 			return TRUE;
1303 		} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
1304 			Atom	atom;
1305 			const char	*name;
1306 			int		j;
1307 
1308 			if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
1309 				return FALSE;
1310 			memcpy(&atom, value->data, 4);
1311 			name = NameForAtom(atom);
1312 			if (name == NULL)
1313 				return FALSE;
1314 
1315 			/* search for matching name string, then set its value down */
1316 			for (j = 0; j < p->mode_prop->count_enums; j++) {
1317 				if (!strcmp(p->mode_prop->enums[j].name, name)) {
1318 					drmModeConnectorSetProperty(mode->fd, intel_output->output_id,
1319 								    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
1320 					return TRUE;
1321 				}
1322 			}
1323 			return FALSE;
1324 		}
1325 	}
1326 
1327 	/* We didn't recognise this property, just report success in order
1328 	 * to allow the set to continue, otherwise we break setting of
1329 	 * common properties like EDID.
1330 	 */
1331 	return TRUE;
1332 }
1333 
1334 static Bool
intel_output_get_property(xf86OutputPtr output,Atom property)1335 intel_output_get_property(xf86OutputPtr output, Atom property)
1336 {
1337 	struct intel_output *intel_output = output->driver_private;
1338 	int err;
1339 
1340 	if (property == backlight_atom || property == backlight_deprecated_atom) {
1341 		INT32 val;
1342 
1343 		if (!intel_output->backlight.iface)
1344 			return FALSE;
1345 
1346 		if (intel_output->dpms_mode == DPMSModeOn) {
1347 			val = intel_output_backlight_get(output);
1348 			if (val < 0)
1349 				return FALSE;
1350 		} else {
1351 			val = intel_output->backlight_active_level;
1352 		}
1353 
1354 		err = RRChangeOutputProperty(output->randr_output, property,
1355 					     XA_INTEGER, 32, PropModeReplace, 1, &val,
1356 					     FALSE, FALSE);
1357 		if (err != 0) {
1358 			xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1359 				   "RRChangeOutputProperty error, %d\n", err);
1360 			return FALSE;
1361 		}
1362 
1363 		return TRUE;
1364 	}
1365 
1366 	return FALSE;
1367 }
1368 
1369 static const xf86OutputFuncsRec intel_output_funcs = {
1370 	.create_resources = intel_output_create_resources,
1371 #ifdef RANDR_12_INTERFACE
1372 	.set_property = intel_output_set_property,
1373 	.get_property = intel_output_get_property,
1374 #endif
1375 	.dpms = intel_output_dpms,
1376 #if 0
1377 
1378 	.save = drmmode_crt_save,
1379 	.restore = drmmode_crt_restore,
1380 	.mode_fixup = drmmode_crt_mode_fixup,
1381 	.prepare = intel_output_prepare,
1382 	.mode_set = drmmode_crt_mode_set,
1383 	.commit = intel_output_commit,
1384 #endif
1385 	.detect = intel_output_detect,
1386 	.mode_valid = intel_output_mode_valid,
1387 
1388 	.get_modes = intel_output_get_modes,
1389 	.destroy = intel_output_destroy
1390 };
1391 
1392 static const int subpixel_conv_table[7] = {
1393        	0,
1394        	SubPixelUnknown,
1395 	SubPixelHorizontalRGB,
1396 	SubPixelHorizontalBGR,
1397 	SubPixelVerticalRGB,
1398 	SubPixelVerticalBGR,
1399 	SubPixelNone
1400 };
1401 
1402 static const char *output_names[] = {
1403        	"None",
1404 	"VGA",
1405 	"DVI",
1406 	"DVI",
1407 	"DVI",
1408 	"Composite",
1409 	"TV",
1410 	"LVDS",
1411 	"CTV",
1412 	"DIN",
1413 	"DP",
1414 	"HDMI",
1415 	"HDMI",
1416 	"TV",
1417 	"eDP",
1418 };
1419 
find_output(ScrnInfoPtr pScrn,int id)1420 static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id)
1421 {
1422 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1423 	int i;
1424 	for (i = 0; i < xf86_config->num_output; i++) {
1425 		xf86OutputPtr output = xf86_config->output[i];
1426 		struct intel_output *intel_output;
1427 
1428 		intel_output = output->driver_private;
1429 		if (intel_output->output_id == id)
1430 			return output;
1431 	}
1432 	return NULL;
1433 }
1434 
parse_path_blob(drmModePropertyBlobPtr path_blob,int * conn_base_id,char ** path)1435 static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path)
1436 {
1437 	char *conn;
1438 	char conn_id[5];
1439 	int id, len;
1440 	char *blob_data;
1441 
1442 	if (!path_blob)
1443 		return -1;
1444 
1445 	blob_data = path_blob->data;
1446 	/* we only handle MST paths for now */
1447 	if (strncmp(blob_data, "mst:", 4))
1448 		return -1;
1449 
1450 	conn = strchr(blob_data + 4, '-');
1451 	if (!conn)
1452 		return -1;
1453 	len = conn - (blob_data + 4);
1454 	if (len + 1 > 5)
1455 		return -1;
1456 	memcpy(conn_id, blob_data + 4, len);
1457 	conn_id[len] = '\0';
1458 	id = strtoul(conn_id, NULL, 10);
1459 
1460 	*conn_base_id = id;
1461 
1462 	*path = conn + 1;
1463 	return 0;
1464 }
1465 
1466 static void
drmmode_create_name(ScrnInfoPtr pScrn,drmModeConnectorPtr koutput,char * name,drmModePropertyBlobPtr path_blob)1467 drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
1468 		    drmModePropertyBlobPtr path_blob)
1469 {
1470 	xf86OutputPtr output;
1471 	int conn_id;
1472 	char *extra_path;
1473 
1474 	output = NULL;
1475 	if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0)
1476 		output = find_output(pScrn, conn_id);
1477 	if (output) {
1478 		snprintf(name, 32, "%s-%s", output->name, extra_path);
1479 	} else {
1480 		const char *output_name;
1481 
1482 		if (koutput->connector_type < ARRAY_SIZE(output_names))
1483 			output_name = output_names[koutput->connector_type];
1484 		else
1485 			output_name = "UNKNOWN";
1486 
1487 		snprintf(name, 32, "%s-%d",
1488 			 output_name, koutput->connector_type_id);
1489 	}
1490 }
1491 
1492 static void
intel_output_init(ScrnInfoPtr scrn,struct intel_mode * mode,drmModeResPtr mode_res,int num,int dynamic)1493 intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res, int num, int dynamic)
1494 {
1495 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1496 	xf86OutputPtr output;
1497 	drmModeConnectorPtr koutput;
1498 	drmModeEncoderPtr *kencoders = NULL;
1499 	struct intel_output *intel_output;
1500 	char name[32];
1501 	drmModePropertyPtr props;
1502 	drmModePropertyBlobPtr path_blob = NULL;
1503 	int i;
1504 
1505 	koutput = drmModeGetConnector(mode->fd,
1506 				      mode_res->connectors[num]);
1507 	if (!koutput)
1508 		return;
1509 	for (i = 0; i < koutput->count_props; i++) {
1510 		props = drmModeGetProperty(mode->fd, koutput->props[i]);
1511 		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
1512 			if (!strcmp(props->name, "PATH")) {
1513 				path_blob = drmModeGetPropertyBlob(mode->fd, koutput->prop_values[i]);
1514 
1515 				drmModeFreeProperty(props);
1516 				break;
1517 			}
1518 			drmModeFreeProperty(props);
1519 		}
1520 	}
1521 
1522 	drmmode_create_name(scrn, koutput, name, path_blob);
1523 	if (path_blob)
1524 		drmModeFreePropertyBlob(path_blob);
1525 
1526 	if (path_blob && dynamic) {
1527 		/* See if we have an output with this name already
1528 		 * and hook stuff up.
1529 		 */
1530 		for (i = 0; i < xf86_config->num_output; i++) {
1531 			output = xf86_config->output[i];
1532 
1533 			if (strncmp(output->name, name, 32))
1534 				continue;
1535 
1536 			intel_output = output->driver_private;
1537 			intel_output->output_id = mode_res->connectors[num];
1538 			intel_output->mode_output = koutput;
1539 			RROutputChanged(output->randr_output, TRUE);
1540 			return;
1541 		}
1542 	}
1543 	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
1544 	if (!kencoders) {
1545 		goto out_free_encoders;
1546 	}
1547 
1548 	for (i = 0; i < koutput->count_encoders; i++) {
1549 		kencoders[i] = drmModeGetEncoder(mode->fd, koutput->encoders[i]);
1550 		if (!kencoders[i])
1551 			goto out_free_encoders;
1552 	}
1553 
1554 	output = xf86OutputCreate (scrn, &intel_output_funcs, name);
1555 	if (!output) {
1556 		goto out_free_encoders;
1557 	}
1558 
1559 	intel_output = calloc(sizeof(struct intel_output), 1);
1560 	if (!intel_output) {
1561 		xf86OutputDestroy(output);
1562 		goto out_free_encoders;
1563 	}
1564 
1565 	intel_output->output_id = mode_res->connectors[num];
1566 	intel_output->mode_output = koutput;
1567 	intel_output->mode_encoders = kencoders;
1568 	intel_output->mode = mode;
1569 
1570 	output->mm_width = koutput->mmWidth;
1571 	output->mm_height = koutput->mmHeight;
1572 
1573 	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
1574 	output->driver_private = intel_output;
1575 
1576 	if (is_panel(koutput->connector_type))
1577 		intel_output_backlight_init(output);
1578 
1579 	output->possible_crtcs = 0x7f;
1580 	for (i = 0; i < koutput->count_encoders; i++) {
1581 		output->possible_crtcs &= kencoders[i]->possible_crtcs;
1582 	}
1583 	output->interlaceAllowed = TRUE;
1584 
1585 	intel_output->output = output;
1586 
1587 	if (dynamic) {
1588 		output->randr_output = RROutputCreate(xf86ScrnToScreen(scrn), output->name, strlen(output->name), output);
1589 		intel_output_create_resources(output);
1590 	}
1591 
1592 	list_add(&intel_output->link, &mode->outputs);
1593 	return;
1594 
1595 out_free_encoders:
1596 	if (kencoders) {
1597 		for (i = 0; i < koutput->count_encoders; i++)
1598 			drmModeFreeEncoder(kencoders[i]);
1599 		free(kencoders);
1600 	}
1601 	drmModeFreeConnector(koutput);
1602 }
1603 
1604 static Bool
intel_xf86crtc_resize(ScrnInfoPtr scrn,int width,int height)1605 intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
1606 {
1607 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1608 	struct intel_crtc *intel_crtc = xf86_config->crtc[0]->driver_private;
1609 	struct intel_mode *mode = intel_crtc->mode;
1610 	intel_screen_private *intel = intel_get_screen_private(scrn);
1611 	drm_intel_bo *old_front = NULL;
1612 	Bool	    ret;
1613 	uint32_t    old_fb_id;
1614 	int	    i, old_width, old_height, old_pitch;
1615 	int pitch;
1616 	uint32_t tiling;
1617 
1618 	if (scrn->virtualX == width && scrn->virtualY == height)
1619 		return TRUE;
1620 
1621         intel_flush(intel);
1622 
1623 	old_width = scrn->virtualX;
1624 	old_height = scrn->virtualY;
1625 	old_pitch = scrn->displayWidth;
1626 	old_fb_id = mode->fb_id;
1627 	old_front = intel->front_buffer;
1628 
1629 	if (intel->back_buffer) {
1630 		drm_intel_bo_unreference(intel->back_buffer);
1631 		intel->back_buffer = NULL;
1632 	}
1633 
1634 	intel->front_buffer = intel_allocate_framebuffer(scrn,
1635 							 width, height,
1636 							 intel->cpp,
1637 							 &pitch, &tiling);
1638 	if (!intel->front_buffer)
1639 		goto fail;
1640 
1641 	ret = drmModeAddFB(mode->fd, width, height, scrn->depth,
1642 			   scrn->bitsPerPixel, pitch,
1643 			   intel->front_buffer->handle,
1644 			   &mode->fb_id);
1645 	if (ret)
1646 		goto fail;
1647 
1648 	intel->front_pitch = pitch;
1649 	intel->front_tiling = tiling;
1650 
1651 	scrn->virtualX = width;
1652 	scrn->virtualY = height;
1653 
1654 	if (!intel_uxa_create_screen_resources(scrn->pScreen))
1655 		goto fail;
1656 
1657 	for (i = 0; i < xf86_config->num_crtc; i++) {
1658 		xf86CrtcPtr crtc = xf86_config->crtc[i];
1659 
1660 		if (!crtc->enabled)
1661 			continue;
1662 
1663 		if (!intel_crtc_apply(crtc))
1664 			goto fail;
1665 	}
1666 
1667 	if (old_fb_id)
1668 		drmModeRmFB(mode->fd, old_fb_id);
1669 	if (old_front)
1670 		drm_intel_bo_unreference(old_front);
1671 
1672 	return TRUE;
1673 
1674 fail:
1675 	if (intel->front_buffer)
1676 		drm_intel_bo_unreference(intel->front_buffer);
1677 	intel->front_buffer = old_front;
1678 	scrn->virtualX = old_width;
1679 	scrn->virtualY = old_height;
1680 	scrn->displayWidth = old_pitch;
1681 	if (old_fb_id != mode->fb_id)
1682 		drmModeRmFB(mode->fd, mode->fb_id);
1683 	mode->fb_id = old_fb_id;
1684 
1685 	return FALSE;
1686 }
1687 
1688 static void
1689 intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
1690                         uint64_t frame, uint64_t usec, void *data);
1691 
1692 static void
1693 intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data);
1694 
1695 static void
1696 intel_pageflip_complete(struct intel_mode *mode);
1697 
1698 Bool
intel_do_pageflip(intel_screen_private * intel,dri_bo * new_front,int ref_crtc_hw_id,Bool async,void * pageflip_data,intel_pageflip_handler_proc pageflip_handler,intel_pageflip_abort_proc pageflip_abort)1699 intel_do_pageflip(intel_screen_private *intel,
1700 		  dri_bo *new_front,
1701 		  int ref_crtc_hw_id,
1702 		  Bool async,
1703 		  void *pageflip_data,
1704 		  intel_pageflip_handler_proc pageflip_handler,
1705 		  intel_pageflip_abort_proc pageflip_abort)
1706 {
1707 	ScrnInfoPtr scrn = intel->scrn;
1708 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1709 	struct intel_crtc *crtc = config->crtc[0]->driver_private;
1710 	struct intel_mode *mode = crtc->mode;
1711 	unsigned int pitch = scrn->displayWidth * intel->cpp;
1712 	struct intel_pageflip *flip;
1713 	uint32_t new_fb_id;
1714 	uint32_t flags;
1715 	uint32_t seq;
1716 	int err = 0;
1717 	int i;
1718 
1719 	/*
1720 	 * We only have a single length queue in the kernel, so any
1721 	 * attempts to schedule a second flip before processing the first
1722 	 * is a bug. Punt it back to the caller.
1723 	 */
1724 	if (mode->flip_count)
1725 		return FALSE;
1726 
1727 	/*
1728 	 * Create a new handle for the back buffer
1729 	 */
1730 	if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
1731 			 scrn->depth, scrn->bitsPerPixel, pitch,
1732 			 new_front->handle, &new_fb_id)) {
1733 		err = errno;
1734 		goto error_out;
1735 	}
1736 
1737 	drm_intel_bo_disable_reuse(new_front);
1738         intel_flush(intel);
1739 
1740 	/*
1741 	 * Queue flips on all enabled CRTCs
1742 	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
1743 	 * Right now it assumes a single shared fb across all CRTCs, with the
1744 	 * kernel fixing up the offset of each CRTC as necessary.
1745 	 *
1746 	 * Also, flips queued on disabled or incorrectly configured displays
1747 	 * may never complete; this is a configuration error.
1748 	 */
1749 	mode->fe_msc = 0;
1750 	mode->fe_usec = 0;
1751 	memset(&mode->pageflip, 0, sizeof(mode->pageflip));
1752 
1753 	flags = DRM_MODE_PAGE_FLIP_EVENT;
1754 	if (async)
1755 		flags |= DRM_MODE_PAGE_FLIP_ASYNC;
1756 	for (i = 0; i < config->num_crtc; i++) {
1757 		if (!intel_crtc_on(config->crtc[i]))
1758 			continue;
1759 
1760 		crtc = config->crtc[i]->driver_private;
1761 
1762 		flip = calloc(1, sizeof(struct intel_pageflip));
1763 		if (flip == NULL) {
1764 			err = errno;
1765 			goto error_undo;
1766 		}
1767 
1768 		/* Only the reference crtc will finally deliver its page flip
1769 		 * completion event. All other crtc's events will be discarded.
1770 		 */
1771 		flip->dispatch_me = (intel_crtc_to_pipe(crtc->crtc) == ref_crtc_hw_id);
1772 		flip->mode = mode;
1773 
1774 		seq = intel_drm_queue_alloc(scrn, config->crtc[i], flip, intel_pageflip_handler, intel_pageflip_abort);
1775 		if (!seq) {
1776 			err = errno;
1777 			free(flip);
1778 			goto error_undo;
1779 		}
1780 
1781 		mode->flip_count++;
1782 
1783 		if (drmModePageFlip(mode->fd,
1784 				    crtc_id(crtc),
1785 				    new_fb_id,
1786 				    flags, (void *)(uintptr_t)seq)) {
1787 			err = errno;
1788 			intel_drm_abort_seq(scrn, seq);
1789 			goto error_undo;
1790 		}
1791 	}
1792 
1793 	mode->old_fb_id = mode->fb_id;
1794 	mode->fb_id = new_fb_id;
1795 
1796 	mode->pageflip.data = pageflip_data;
1797 	mode->pageflip.handler = pageflip_handler;
1798 	mode->pageflip.abort = pageflip_abort;
1799 
1800 	if (!mode->flip_count)
1801 		intel_pageflip_complete(mode);
1802 
1803 	return TRUE;
1804 
1805 error_undo:
1806 	drmModeRmFB(mode->fd, new_fb_id);
1807 	for (i = 0; i < config->num_crtc; i++) {
1808 		if (config->crtc[i]->enabled)
1809 			intel_crtc_apply(config->crtc[i]);
1810 	}
1811 
1812 error_out:
1813 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
1814 		   strerror(err));
1815 
1816 	mode->flip_count = 0;
1817 	return FALSE;
1818 }
1819 
1820 static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = {
1821 	.resize = intel_xf86crtc_resize,
1822 };
1823 
1824 /*
1825  * Enqueue a potential drm response; when the associated response
1826  * appears, we've got data to pass to the handler from here
1827  */
1828 uint32_t
intel_drm_queue_alloc(ScrnInfoPtr scrn,xf86CrtcPtr crtc,void * data,intel_drm_handler_proc handler,intel_drm_abort_proc abort)1829 intel_drm_queue_alloc(ScrnInfoPtr scrn,
1830 		      xf86CrtcPtr crtc,
1831 		      void *data,
1832 		      intel_drm_handler_proc handler,
1833 		      intel_drm_abort_proc abort)
1834 {
1835 	struct intel_drm_queue  *q;
1836 
1837 	q = calloc(1, sizeof(struct intel_drm_queue));
1838 	if (!q)
1839 		return 0;
1840 
1841 	if (!intel_drm_seq)
1842 		++intel_drm_seq;
1843 	q->seq = intel_drm_seq++;
1844 	q->scrn = scrn;
1845 	q->crtc = crtc;
1846 	q->data = data;
1847 	q->handler = handler;
1848 	q->abort = abort;
1849 
1850 	list_add(&q->list, &intel_drm_queue);
1851 
1852 	return q->seq;
1853 }
1854 
1855 /*
1856  * Abort one queued DRM entry, removing it
1857  * from the list, calling the abort function and
1858  * freeing the memory
1859  */
1860 static void
intel_drm_abort_one(struct intel_drm_queue * q)1861 intel_drm_abort_one(struct intel_drm_queue *q)
1862 {
1863 	list_del(&q->list);
1864 	q->abort(q->scrn, q->crtc, q->data);
1865 	free(q);
1866 }
1867 
1868 /*
1869  * Externally usable abort function that uses a callback to match a single queued
1870  * entry to abort
1871  */
1872 void
intel_drm_abort(ScrnInfoPtr scrn,Bool (* match)(void * data,void * match_data),void * match_data)1873 intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data)
1874 {
1875 	struct intel_drm_queue *q;
1876 
1877 	list_for_each_entry(q, &intel_drm_queue, list) {
1878 		if (match(q->data, match_data)) {
1879 			intel_drm_abort_one(q);
1880 			break;
1881 		}
1882 	}
1883 }
1884 
1885 /*
1886  * Abort by drm queue sequence number
1887  */
1888 void
intel_drm_abort_seq(ScrnInfoPtr scrn,uint32_t seq)1889 intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq)
1890 {
1891 	struct intel_drm_queue *q;
1892 
1893 	list_for_each_entry(q, &intel_drm_queue, list) {
1894 		if (q->seq == seq) {
1895 			intel_drm_abort_one(q);
1896 			break;
1897 		}
1898 	}
1899 }
1900 
1901 /*
1902  * Abort all queued entries on a specific scrn, used
1903  * when resetting the X server
1904  */
1905 static void
intel_drm_abort_scrn(ScrnInfoPtr scrn)1906 intel_drm_abort_scrn(ScrnInfoPtr scrn)
1907 {
1908 	struct intel_drm_queue *q, *tmp;
1909 
1910 	list_for_each_entry_safe(q, tmp, &intel_drm_queue, list) {
1911 		if (q->scrn == scrn)
1912 			intel_drm_abort_one(q);
1913 	}
1914 }
1915 
pipe_select(int pipe)1916 static uint32_t pipe_select(int pipe)
1917 {
1918 	if (pipe > 1)
1919 		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
1920 	else if (pipe > 0)
1921 		return DRM_VBLANK_SECONDARY;
1922 	else
1923 		return 0;
1924 }
1925 
1926 /*
1927  * Get the current msc/ust value from the kernel
1928  */
1929 static int
intel_get_msc_ust(ScrnInfoPtr scrn,xf86CrtcPtr crtc,uint32_t * msc,uint64_t * ust)1930 intel_get_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint32_t *msc, uint64_t *ust)
1931 {
1932 	intel_screen_private *intel = intel_get_screen_private(scrn);
1933 	drmVBlank vbl;
1934 
1935 	/* Get current count */
1936 	vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(intel_crtc_to_pipe(crtc));
1937 	vbl.request.sequence = 0;
1938 	vbl.request.signal = 0;
1939 	if (drmWaitVBlank(intel->drmSubFD, &vbl)) {
1940 		*msc = 0;
1941 		*ust = 0;
1942 		return BadMatch;
1943 	} else {
1944 		*msc = vbl.reply.sequence;
1945 		*ust = (CARD64) vbl.reply.tval_sec * 1000000 + vbl.reply.tval_usec;
1946 		return Success;
1947 	}
1948 }
1949 
1950 /*
1951  * Convert a 32-bit kernel MSC sequence number to a 64-bit local sequence
1952  * number, adding in the vblank_offset and high 32 bits, and dealing
1953  * with 64-bit wrapping
1954  */
1955 uint64_t
intel_sequence_to_crtc_msc(xf86CrtcPtr crtc,uint32_t sequence)1956 intel_sequence_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence)
1957 {
1958 	struct intel_crtc *intel_crtc = crtc->driver_private;
1959 
1960         if ((int32_t) (sequence - intel_crtc->msc_prev) < -0x40000000)
1961                 intel_crtc->msc_high += 0x100000000L;
1962         intel_crtc->msc_prev = sequence;
1963         return intel_crtc->msc_high + sequence;
1964 }
1965 
1966 /*
1967  * Get the current 64-bit adjust MSC and UST value
1968  */
1969 int
intel_get_crtc_msc_ust(ScrnInfoPtr scrn,xf86CrtcPtr crtc,uint64_t * msc,uint64_t * ust)1970 intel_get_crtc_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t *msc, uint64_t *ust)
1971 {
1972         uint32_t sequence;
1973         int ret;
1974 
1975         ret = intel_get_msc_ust(scrn, crtc, &sequence, ust);
1976 	if (ret)
1977 		return ret;
1978 
1979         *msc = intel_sequence_to_crtc_msc(crtc, sequence);
1980         return 0;
1981 }
1982 
1983 uint32_t
intel_crtc_msc_to_sequence(ScrnInfoPtr scrn,xf86CrtcPtr crtc,uint64_t expect)1984 intel_crtc_msc_to_sequence(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t expect)
1985 {
1986         return (uint32_t)expect;
1987 }
1988 
1989 /*
1990  * General DRM kernel handler. Looks for the matching sequence number in the
1991  * drm event queue and calls the handler for it.
1992  */
1993 static void
intel_drm_handler(int fd,uint32_t frame,uint32_t sec,uint32_t usec,void * user_ptr)1994 intel_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec, void *user_ptr)
1995 {
1996 	uint32_t user_data = (intptr_t)user_ptr;
1997 	struct intel_drm_queue *q;
1998 
1999 	list_for_each_entry(q, &intel_drm_queue, list) {
2000 		if (q->seq == user_data) {
2001 			list_del(&q->list);
2002 			q->handler(q->scrn, q->crtc,
2003 				   intel_sequence_to_crtc_msc(q->crtc, frame),
2004 				   (uint64_t)sec * 1000000 + usec, q->data);
2005 			free(q);
2006 			break;
2007 		}
2008 	}
2009 }
2010 
2011 
2012 /*
2013  * Notify the page flip caller that the flip is
2014  * complete
2015  */
2016 static void
intel_pageflip_complete(struct intel_mode * mode)2017 intel_pageflip_complete(struct intel_mode *mode)
2018 {
2019 	if (!mode->pageflip.handler)
2020 		return;
2021 
2022 	/* Release framebuffer */
2023 	drmModeRmFB(mode->fd, mode->old_fb_id);
2024 	mode->pageflip.handler(mode->fe_msc, mode->fe_usec,
2025 			       mode->pageflip.data);
2026 }
2027 
2028 /*
2029  * One pageflip event has completed. Update the saved msc/ust values
2030  * as needed, then check to see if the whole set of events are
2031  * complete and notify the application at that point
2032  */
2033 static struct intel_mode *
intel_handle_pageflip(struct intel_pageflip * flip,uint64_t msc,uint64_t usec)2034 intel_handle_pageflip(struct intel_pageflip *flip, uint64_t msc, uint64_t usec)
2035 {
2036 	struct intel_mode *mode = flip->mode;
2037 
2038 	if (flip->dispatch_me) {
2039 		/* Yes: Cache msc, ust for later delivery. */
2040 		mode->fe_msc = msc;
2041 		mode->fe_usec = usec;
2042 	}
2043 	free(flip);
2044 
2045 	/* Last crtc completed flip? */
2046 	mode->flip_count--;
2047 	if (mode->flip_count > 0)
2048 		return NULL;
2049 
2050 	return mode;
2051 }
2052 
2053 /*
2054  * Called from the DRM event queue when a single flip has completed
2055  */
2056 static void
intel_pageflip_handler(ScrnInfoPtr scrn,xf86CrtcPtr crtc,uint64_t msc,uint64_t usec,void * data)2057 intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
2058 		       uint64_t msc, uint64_t usec, void *data)
2059 {
2060 	struct intel_pageflip   *flip = data;
2061 	struct intel_mode       *mode = intel_handle_pageflip(flip, msc, usec);
2062 
2063 	if (!mode)
2064 		return;
2065 
2066 	intel_pageflip_complete(mode);
2067 }
2068 
2069 /*
2070  * Called from the DRM queue abort code when a flip has been aborted
2071  */
2072 static void
intel_pageflip_abort(ScrnInfoPtr scrn,xf86CrtcPtr crtc,void * data)2073 intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data)
2074 {
2075 	struct intel_pageflip   *flip = data;
2076 	struct intel_mode       *mode = intel_handle_pageflip(flip, 0, 0);
2077 
2078 	if (!mode)
2079 		return;
2080 
2081 	if (!mode->pageflip.abort)
2082 		return;
2083 
2084 	/* Release framebuffer */
2085 	drmModeRmFB(mode->fd, mode->old_fb_id);
2086 	mode->pageflip.abort(mode->pageflip.data);
2087 }
2088 
2089 /*
2090  * Check for pending DRM events and process them.
2091  */
2092 #if !HAVE_NOTIFY_FD
2093 static void
drm_wakeup_handler(pointer data,int err,pointer p)2094 drm_wakeup_handler(pointer data, int err, pointer p)
2095 {
2096 	struct intel_mode *mode;
2097 	fd_set *read_mask;
2098 
2099 	if (data == NULL || err < 0)
2100 		return;
2101 
2102 	mode = data;
2103 	read_mask = p;
2104 	if (FD_ISSET(mode->fd, read_mask))
2105 		drmHandleEvent(mode->fd, &mode->event_context);
2106 }
2107 #else
2108 static void
drm_notify_fd(int fd,int ready,void * data)2109 drm_notify_fd(int fd, int ready, void *data)
2110 {
2111 	struct intel_mode *mode = data;
2112 	drmHandleEvent(mode->fd, &mode->event_context);
2113 }
2114 #endif
2115 
2116 /*
2117  * If there are any available, read drm_events
2118  */
2119 int
intel_mode_read_drm_events(struct intel_screen_private * intel)2120 intel_mode_read_drm_events(struct intel_screen_private *intel)
2121 {
2122 	struct intel_mode *mode = intel->modes;
2123 	struct pollfd p = { .fd = mode->fd, .events = POLLIN };
2124 	int r;
2125 
2126 	do {
2127 		r = poll(&p, 1, 0);
2128 	} while (r == -1 && (errno == EINTR || errno == EAGAIN));
2129 
2130 	if (r <= 0)
2131 		return 0;
2132 
2133 	return drmHandleEvent(mode->fd, &mode->event_context);
2134 }
2135 
2136 /*
2137  * Libdrm's possible_clones is a mask of encoders, Xorg's possible_clones is a
2138  * mask of outputs. This function sets Xorg's possible_clones based on the
2139  * values read from libdrm.
2140  */
find_clones(ScrnInfoPtr scrn,xf86OutputPtr output)2141 static uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
2142 {
2143 	struct intel_output *intel_output = output->driver_private, *clone_drmout;
2144 	int i;
2145 	xf86OutputPtr clone_output;
2146 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2147 	int index_mask = 0;
2148 
2149 	if (intel_output->enc_clone_mask == 0)
2150 		return index_mask;
2151 
2152 	for (i = 0; i < xf86_config->num_output; i++) {
2153 		clone_output = xf86_config->output[i];
2154 		clone_drmout = clone_output->driver_private;
2155 		if (output == clone_output)
2156 			continue;
2157 
2158 		if (clone_drmout->enc_mask == 0)
2159 			continue;
2160 		if (intel_output->enc_clone_mask == clone_drmout->enc_mask)
2161 			index_mask |= (1 << i);
2162 	}
2163 	return index_mask;
2164 }
2165 static void
intel_compute_possible_clones(ScrnInfoPtr scrn,struct intel_mode * mode,drmModeResPtr mode_res)2166 intel_compute_possible_clones(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res)
2167 {
2168 	int i, j;
2169 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2170 
2171 	for (i = 0; i < xf86_config->num_output; i++) {
2172 		xf86OutputPtr output = xf86_config->output[i];
2173 		struct intel_output *intel_output;
2174 
2175 		intel_output = output->driver_private;
2176 		intel_output->enc_clone_mask = 0xff;
2177 		/* and all the possible encoder clones for this output together */
2178 		for (j = 0; j < intel_output->mode_output->count_encoders; j++)
2179 		{
2180 			int k;
2181 			for (k = 0; k < mode_res->count_encoders; k++) {
2182 				if (mode_res->encoders[k] == intel_output->mode_encoders[j]->encoder_id)
2183 					intel_output->enc_mask |= (1 << k);
2184 			}
2185 
2186 			intel_output->enc_clone_mask &= intel_output->mode_encoders[j]->possible_clones;
2187 		}
2188 	}
2189 
2190 	for (i = 0; i < xf86_config->num_output; i++) {
2191 		xf86OutputPtr output = xf86_config->output[i];
2192 		output->possible_clones = find_clones(scrn, output);
2193 	}
2194 }
2195 
intel_mode_pre_init(ScrnInfoPtr scrn,int fd,int cpp)2196 Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
2197 {
2198 	intel_screen_private *intel = intel_get_screen_private(scrn);
2199 	struct drm_i915_getparam gp;
2200 	struct intel_mode *mode;
2201 	unsigned int i;
2202 	int has_flipping;
2203 	drmModeResPtr mode_res;
2204 
2205 	mode = calloc(1, sizeof *mode);
2206 	if (!mode)
2207 		return FALSE;
2208 
2209 	mode->fd = fd;
2210 
2211 	list_init(&mode->crtcs);
2212 	list_init(&mode->outputs);
2213 
2214 	xf86CrtcConfigInit(scrn, &intel_xf86crtc_config_funcs);
2215 
2216 	mode->cpp = cpp;
2217 	mode_res = drmModeGetResources(mode->fd);
2218 	if (!mode_res) {
2219 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2220 			   "failed to get resources: %s\n", strerror(errno));
2221 		free(mode);
2222 		return FALSE;
2223 	}
2224 
2225 	xf86CrtcSetSizeRange(scrn, 320, 200, mode_res->max_width,
2226 			     mode_res->max_height);
2227 	for (i = 0; i < mode_res->count_crtcs; i++)
2228 		intel_crtc_init(scrn, mode, mode_res, i);
2229 
2230 	for (i = 0; i < mode_res->count_connectors; i++)
2231 		intel_output_init(scrn, mode, mode_res, i, 0);
2232 
2233 	intel_compute_possible_clones(scrn, mode, mode_res);
2234 
2235 #ifdef INTEL_PIXMAP_SHARING
2236 	xf86ProviderSetup(scrn, NULL, "Intel");
2237 #endif
2238 
2239 	xf86InitialConfiguration(scrn, TRUE);
2240 
2241 	mode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
2242 	mode->event_context.vblank_handler = intel_drm_handler;
2243 	mode->event_context.page_flip_handler = intel_drm_handler;
2244 
2245 	/* XXX assumes only one intel screen */
2246 	list_init(&intel_drm_queue);
2247 	intel_drm_seq = 0;
2248 
2249 	has_flipping = 0;
2250 	gp.param = I915_PARAM_HAS_PAGEFLIPPING;
2251 	gp.value = &has_flipping;
2252 	(void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp,
2253 				  sizeof(gp));
2254 	if (has_flipping && intel->swapbuffers_wait) {
2255 		xf86DrvMsg(scrn->scrnIndex, X_INFO,
2256 			   "Kernel page flipping support detected, enabling\n");
2257 		intel->use_pageflipping = TRUE;
2258 	}
2259 
2260 	intel->modes = mode;
2261 	drmModeFreeResources(mode_res);
2262 	return TRUE;
2263 }
2264 
2265 void
intel_mode_init(struct intel_screen_private * intel)2266 intel_mode_init(struct intel_screen_private *intel)
2267 {
2268 	struct intel_mode *mode = intel->modes;
2269 
2270 	/* We need to re-register the mode->fd for the synchronisation
2271 	 * feedback on every server generation, so perform the
2272 	 * registration within ScreenInit and not PreInit.
2273 	 */
2274 	mode->flip_count = 0;
2275 	SetNotifyFd(mode->fd, drm_notify_fd, X_NOTIFY_READ, mode);
2276 #if !HAVE_NOTIFY_FD
2277 	RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2278 				       drm_wakeup_handler, mode);
2279 #endif
2280 }
2281 
2282 void
intel_mode_remove_fb(intel_screen_private * intel)2283 intel_mode_remove_fb(intel_screen_private *intel)
2284 {
2285 	struct intel_mode *mode = intel->modes;
2286 
2287 	if (mode->fb_id) {
2288 		drmModeRmFB(mode->fd, mode->fb_id);
2289 		mode->fb_id = 0;
2290 	}
2291 }
2292 
2293 void
intel_mode_close(intel_screen_private * intel)2294 intel_mode_close(intel_screen_private *intel)
2295 {
2296 	struct intel_mode *mode = intel->modes;
2297 
2298 	if (mode == NULL)
2299 		return;
2300 
2301         intel_drm_abort_scrn(intel->scrn);
2302 
2303 #if !HAVE_NOTIFY_FD
2304 	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2305 				     drm_wakeup_handler, mode);
2306 #endif
2307 	RemoveNotifyFd(mode->fd);
2308 }
2309 
2310 void
intel_mode_fini(intel_screen_private * intel)2311 intel_mode_fini(intel_screen_private *intel)
2312 {
2313 	struct intel_mode *mode = intel->modes;
2314 
2315 	if (mode == NULL)
2316 		return;
2317 
2318 	while(!list_is_empty(&mode->crtcs)) {
2319 		xf86CrtcDestroy(list_first_entry(&mode->crtcs,
2320 						 struct intel_crtc,
2321 						 link)->crtc);
2322 	}
2323 
2324 	while(!list_is_empty(&mode->outputs)) {
2325 		xf86OutputDestroy(list_first_entry(&mode->outputs,
2326 						   struct intel_output,
2327 						   link)->output);
2328 	}
2329 
2330 	if (mode->fb_id)
2331 		drmModeRmFB(mode->fd, mode->fb_id);
2332 
2333 	/* mode->rotate_fb_id should have been destroyed already */
2334 
2335 	free(mode);
2336 	intel->modes = NULL;
2337 }
2338 
2339 /* for the mode overlay */
2340 int
intel_crtc_id(xf86CrtcPtr crtc)2341 intel_crtc_id(xf86CrtcPtr crtc)
2342 {
2343 	return crtc_id(crtc->driver_private);
2344 }
2345 
intel_crtc_to_pipe(xf86CrtcPtr crtc)2346 int intel_crtc_to_pipe(xf86CrtcPtr crtc)
2347 {
2348 	struct intel_crtc *intel_crtc = crtc->driver_private;
2349 	return intel_crtc->pipe;
2350 }
2351 
intel_crtc_on(xf86CrtcPtr crtc)2352 Bool intel_crtc_on(xf86CrtcPtr crtc)
2353 {
2354 	struct intel_crtc *intel_crtc = crtc->driver_private;
2355 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
2356 	drmModeCrtcPtr drm_crtc;
2357 	Bool ret;
2358 	int i;
2359 
2360 	if (!crtc->enabled)
2361 		return FALSE;
2362 
2363 	/* Kernel manages CRTC status based on output config */
2364 	ret = FALSE;
2365 	for (i = 0; i < xf86_config->num_output; i++) {
2366 		xf86OutputPtr output = xf86_config->output[i];
2367 		if (output->crtc == crtc &&
2368 		    intel_output_dpms_status(output) == DPMSModeOn) {
2369 			ret = TRUE;
2370 			break;
2371 		}
2372 	}
2373 	if (!ret)
2374 		return FALSE;
2375 
2376 	/* And finally check with the kernel that the fb is bound */
2377 	drm_crtc = drmModeGetCrtc(intel_crtc->mode->fd, crtc_id(intel_crtc));
2378 	if (drm_crtc == NULL)
2379 		return FALSE;
2380 
2381 	ret = (drm_crtc->mode_valid &&
2382 	       (intel_crtc->mode->fb_id == drm_crtc->buffer_id ||
2383 		intel_crtc->mode->old_fb_id == drm_crtc->buffer_id));
2384 	free(drm_crtc);
2385 
2386 	return ret;
2387 }
2388 
2389 
2390 static PixmapPtr
intel_create_pixmap_for_bo(ScreenPtr pScreen,dri_bo * bo,int width,int height,int depth,int bpp,int pitch)2391 intel_create_pixmap_for_bo(ScreenPtr pScreen, dri_bo *bo,
2392 			   int width, int height,
2393 			   int depth, int bpp,
2394 			   int pitch)
2395 {
2396 	PixmapPtr pixmap;
2397 
2398 	pixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0);
2399 	if (pixmap == NullPixmap)
2400 		return pixmap;
2401 
2402 	if (!pScreen->ModifyPixmapHeader(pixmap,
2403 					 width, height,
2404 					 depth, bpp,
2405 					 pitch, NULL)) {
2406 		pScreen->DestroyPixmap(pixmap);
2407 		return NullPixmap;
2408 	}
2409 
2410 	intel_set_pixmap_bo(pixmap, bo);
2411 	return pixmap;
2412 }
2413 
2414 static PixmapPtr
intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn,int fbcon_id)2415 intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn, int fbcon_id)
2416 {
2417 	ScreenPtr pScreen = xf86ScrnToScreen(scrn);
2418 	intel_screen_private *intel = intel_get_screen_private(scrn);
2419 	struct intel_mode *mode = intel->modes;
2420 	int fd = mode->fd;
2421 	drmModeFBPtr fbcon;
2422 	struct drm_gem_flink flink;
2423 	drm_intel_bo *bo;
2424 	PixmapPtr pixmap = NullPixmap;
2425 
2426 	fbcon = drmModeGetFB(fd, fbcon_id);
2427 	if (fbcon == NULL)
2428 		return NULL;
2429 
2430 	if (fbcon->depth != scrn->depth ||
2431 	    fbcon->width != scrn->virtualX ||
2432 	    fbcon->height != scrn->virtualY)
2433 		goto out_free_fb;
2434 
2435 	flink.handle = fbcon->handle;
2436 	if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
2437 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2438 			   "Couldn't flink fbcon handle\n");
2439 		goto out_free_fb;
2440 	}
2441 
2442 	bo = drm_intel_bo_gem_create_from_name(intel->bufmgr,
2443 					       "fbcon", flink.name);
2444 	if (bo == NULL) {
2445 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2446 			   "Couldn't allocate bo for fbcon handle\n");
2447 		goto out_free_fb;
2448 	}
2449 
2450 	pixmap = intel_create_pixmap_for_bo(pScreen, bo,
2451 					    fbcon->width, fbcon->height,
2452 					    fbcon->depth, fbcon->bpp,
2453 					    fbcon->pitch);
2454 	if (pixmap == NullPixmap)
2455 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2456 			   "Couldn't allocate pixmap fbcon contents\n");
2457 	drm_intel_bo_unreference(bo);
2458 out_free_fb:
2459 	drmModeFreeFB(fbcon);
2460 
2461 	return pixmap;
2462 }
2463 
intel_copy_fb(ScrnInfoPtr scrn)2464 void intel_copy_fb(ScrnInfoPtr scrn)
2465 {
2466 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2467 	ScreenPtr pScreen = xf86ScrnToScreen(scrn);
2468 	intel_screen_private *intel = intel_get_screen_private(scrn);
2469 	PixmapPtr src, dst;
2470 	unsigned int pitch = scrn->displayWidth * intel->cpp;
2471 	struct intel_crtc *intel_crtc;
2472 	int i, fbcon_id;
2473 
2474 	if (intel->force_fallback)
2475 		return;
2476 
2477 	fbcon_id = 0;
2478 	for (i = 0; i < xf86_config->num_crtc; i++) {
2479 		intel_crtc = xf86_config->crtc[i]->driver_private;
2480 		if (intel_crtc->mode_crtc->buffer_id)
2481 			fbcon_id = intel_crtc->mode_crtc->buffer_id;
2482 	}
2483 	if (!fbcon_id)
2484 		return;
2485 
2486 	src = intel_create_pixmap_for_fbcon(scrn, fbcon_id);
2487 	if (src == NULL)
2488 		return;
2489 
2490 	/* We dont have a screen Pixmap yet */
2491 	dst = intel_create_pixmap_for_bo(pScreen, intel->front_buffer,
2492 					 scrn->virtualX, scrn->virtualY,
2493 					 scrn->depth, scrn->bitsPerPixel,
2494 					 pitch);
2495 	if (dst == NullPixmap)
2496 		goto cleanup_src;
2497 
2498 	if (!intel->uxa_driver->prepare_copy(src, dst,
2499 					     -1, -1,
2500 					     GXcopy, FB_ALLONES))
2501 		goto cleanup_dst;
2502 
2503 	intel->uxa_driver->copy(dst,
2504 				0, 0,
2505 				0, 0,
2506 				scrn->virtualX, scrn->virtualY);
2507 	intel->uxa_driver->done_copy(dst);
2508 #if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0)
2509 	pScreen->canDoBGNoneRoot = TRUE;
2510 #endif
2511 
2512 cleanup_dst:
2513 	(*pScreen->DestroyPixmap)(dst);
2514 cleanup_src:
2515 	(*pScreen->DestroyPixmap)(src);
2516 }
2517 
2518 void
intel_mode_hotplug(struct intel_screen_private * intel)2519 intel_mode_hotplug(struct intel_screen_private *intel)
2520 {
2521 	ScrnInfoPtr scrn = intel->scrn;
2522 	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
2523 	drmModeResPtr mode_res;
2524 	int i, j;
2525 	Bool found;
2526 	Bool changed = FALSE;
2527 
2528 	mode_res = drmModeGetResources(intel->drmSubFD);
2529 	if (!mode_res)
2530 		goto out;
2531 
2532 	for (i = 0; i < config->num_output; i++) {
2533 		xf86OutputPtr output = config->output[i];
2534 		struct intel_output *intel_output;
2535 
2536 		intel_output = output->driver_private;
2537 		found = FALSE;
2538 		for (j = 0; j < mode_res->count_connectors; j++) {
2539 			if (mode_res->connectors[j] == intel_output->output_id) {
2540 				found = TRUE;
2541 				break;
2542 			}
2543 		}
2544 		if (found)
2545 			continue;
2546 
2547 		drmModeFreeConnector(intel_output->mode_output);
2548 		intel_output->mode_output = NULL;
2549 		intel_output->output_id = -1;
2550 		RROutputChanged(output->randr_output, TRUE);
2551 
2552 		changed = TRUE;
2553 	}
2554 
2555 	/* find new output ids we don't have outputs for */
2556 	for (i = 0; i < mode_res->count_connectors; i++) {
2557 		found = FALSE;
2558 
2559 		for (j = 0; j < config->num_output; j++) {
2560 			xf86OutputPtr output = config->output[j];
2561 			struct intel_output *intel_output;
2562 
2563 			intel_output = output->driver_private;
2564 			if (mode_res->connectors[i] == intel_output->output_id) {
2565 				found = TRUE;
2566 				break;
2567 			}
2568 		}
2569 		if (found)
2570 			continue;
2571 
2572 		changed = TRUE;
2573 		intel_output_init(scrn, intel->modes, mode_res, i, 1);
2574 	}
2575 
2576 	if (changed)
2577 		RRTellChanged(xf86ScrnToScreen(scrn));
2578 
2579 	drmModeFreeResources(mode_res);
2580 out:
2581 	RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
2582 }
2583 
intel_box_intersect(BoxPtr dest,BoxPtr a,BoxPtr b)2584 void intel_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
2585 {
2586 	dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
2587 	dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
2588 	if (dest->x1 >= dest->x2) {
2589 		dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
2590 		return;
2591 	}
2592 
2593 	dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
2594 	dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
2595 	if (dest->y1 >= dest->y2)
2596 		dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
2597 }
2598 
intel_crtc_box(xf86CrtcPtr crtc,BoxPtr crtc_box)2599 void intel_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
2600 {
2601 	if (crtc->enabled) {
2602 		crtc_box->x1 = crtc->x;
2603 		crtc_box->x2 =
2604 		    crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
2605 		crtc_box->y1 = crtc->y;
2606 		crtc_box->y2 =
2607 		    crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
2608 	} else
2609 		crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
2610 }
2611 
intel_box_area(BoxPtr box)2612 static int intel_box_area(BoxPtr box)
2613 {
2614 	return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
2615 }
2616 
2617 /*
2618  * Return the crtc covering 'box'. If two crtcs cover a portion of
2619  * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
2620  * with greater coverage
2621  */
2622 
2623 xf86CrtcPtr
intel_covering_crtc(ScrnInfoPtr scrn,BoxPtr box,xf86CrtcPtr desired,BoxPtr crtc_box_ret)2624 intel_covering_crtc(ScrnInfoPtr scrn,
2625 		    BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret)
2626 {
2627 	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2628 	xf86CrtcPtr crtc, best_crtc;
2629 	int coverage, best_coverage;
2630 	int c;
2631 	BoxRec crtc_box, cover_box;
2632 
2633 	best_crtc = NULL;
2634 	best_coverage = 0;
2635 	crtc_box_ret->x1 = 0;
2636 	crtc_box_ret->x2 = 0;
2637 	crtc_box_ret->y1 = 0;
2638 	crtc_box_ret->y2 = 0;
2639 	for (c = 0; c < xf86_config->num_crtc; c++) {
2640 		crtc = xf86_config->crtc[c];
2641 
2642 		/* If the CRTC is off, treat it as not covering */
2643 		if (!intel_crtc_on(crtc))
2644 			continue;
2645 
2646 		intel_crtc_box(crtc, &crtc_box);
2647 		intel_box_intersect(&cover_box, &crtc_box, box);
2648 		coverage = intel_box_area(&cover_box);
2649 		if (coverage && crtc == desired) {
2650 			*crtc_box_ret = crtc_box;
2651 			return crtc;
2652 		}
2653 		if (coverage > best_coverage) {
2654 			*crtc_box_ret = crtc_box;
2655 			best_crtc = crtc;
2656 			best_coverage = coverage;
2657 		}
2658 	}
2659 	return best_crtc;
2660 }
2661