1/*
2 * Copyright (c) 2006-2008 Intel Corporation
3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
4 *
5 * DRM core CRTC related functions
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that copyright
10 * notice and this permission notice appear in supporting documentation, and
11 * that the name of the copyright holders not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission.  The copyright holders make no representations
14 * about the suitability of this software for any purpose.  It is provided "as
15 * is" without express or implied warranty.
16 *
17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 * OF THIS SOFTWARE.
24 *
25 * Authors:
26 *      Keith Packard
27 *	Eric Anholt <eric@anholt.net>
28 *      Dave Airlie <airlied@linux.ie>
29 *      Jesse Barnes <jesse.barnes@intel.com>
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include <dev/drm2/drmP.h>
36#include <dev/drm2/drm_crtc.h>
37#include <dev/drm2/drm_fourcc.h>
38#include <dev/drm2/drm_crtc_helper.h>
39#include <dev/drm2/drm_fb_helper.h>
40#include <dev/drm2/drm_edid.h>
41
42/**
43 * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
44 * 						connector list
45 * @dev: drm device to operate on
46 *
47 * Some userspace presumes that the first connected connector is the main
48 * display, where it's supposed to display e.g. the login screen. For
49 * laptops, this should be the main panel. Use this function to sort all
50 * (eDP/LVDS) panels to the front of the connector list, instead of
51 * painstakingly trying to initialize them in the right order.
52 */
53void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
54{
55	struct drm_connector *connector, *tmp;
56	struct list_head panel_list;
57
58	INIT_LIST_HEAD(&panel_list);
59
60	list_for_each_entry_safe(connector, tmp,
61				 &dev->mode_config.connector_list, head) {
62		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
63		    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
64			list_move_tail(&connector->head, &panel_list);
65	}
66
67	list_splice(&panel_list, &dev->mode_config.connector_list);
68}
69EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
70
71static bool drm_kms_helper_poll = true;
72module_param_named(poll, drm_kms_helper_poll, bool, 0600);
73
74static void drm_mode_validate_flag(struct drm_connector *connector,
75				   int flags)
76{
77	struct drm_display_mode *mode;
78
79	if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
80		return;
81
82	list_for_each_entry(mode, &connector->modes, head) {
83		if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
84				!(flags & DRM_MODE_FLAG_INTERLACE))
85			mode->status = MODE_NO_INTERLACE;
86		if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
87				!(flags & DRM_MODE_FLAG_DBLSCAN))
88			mode->status = MODE_NO_DBLESCAN;
89	}
90
91	return;
92}
93
94/**
95 * drm_helper_probe_single_connector_modes - get complete set of display modes
96 * @connector: connector to probe
97 * @maxX: max width for modes
98 * @maxY: max height for modes
99 *
100 * LOCKING:
101 * Caller must hold mode config lock.
102 *
103 * Based on the helper callbacks implemented by @connector try to detect all
104 * valid modes.  Modes will first be added to the connector's probed_modes list,
105 * then culled (based on validity and the @maxX, @maxY parameters) and put into
106 * the normal modes list.
107 *
108 * Intended to be use as a generic implementation of the ->probe() @connector
109 * callback for drivers that use the crtc helpers for output mode filtering and
110 * detection.
111 *
112 * RETURNS:
113 * Number of modes found on @connector.
114 */
115int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
116					    uint32_t maxX, uint32_t maxY)
117{
118	struct drm_device *dev = connector->dev;
119	struct drm_display_mode *mode;
120	struct drm_connector_helper_funcs *connector_funcs =
121		connector->helper_private;
122	int count = 0;
123	int mode_flags = 0;
124
125	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
126			drm_get_connector_name(connector));
127	/* set all modes to the unverified state */
128	list_for_each_entry(mode, &connector->modes, head)
129		mode->status = MODE_UNVERIFIED;
130
131	if (connector->force) {
132		if (connector->force == DRM_FORCE_ON)
133			connector->status = connector_status_connected;
134		else
135			connector->status = connector_status_disconnected;
136		if (connector->funcs->force)
137			connector->funcs->force(connector);
138	} else {
139		connector->status = connector->funcs->detect(connector, true);
140	}
141
142	/* Re-enable polling in case the global poll config changed. */
143	if (drm_kms_helper_poll != dev->mode_config.poll_running)
144		drm_kms_helper_poll_enable(dev);
145
146	dev->mode_config.poll_running = drm_kms_helper_poll;
147
148	if (connector->status == connector_status_disconnected) {
149		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
150			connector->base.id, drm_get_connector_name(connector));
151		drm_mode_connector_update_edid_property(connector, NULL);
152		goto prune;
153	}
154
155#ifdef FREEBSD_NOTYET
156#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
157	count = drm_load_edid_firmware(connector);
158	if (count == 0)
159#endif
160#endif /* FREEBSD_NOTYET */
161		count = (*connector_funcs->get_modes)(connector);
162
163	if (count == 0 && connector->status == connector_status_connected)
164		count = drm_add_modes_noedid(connector, 1024, 768);
165	if (count == 0)
166		goto prune;
167
168	drm_mode_connector_list_update(connector);
169
170	if (maxX && maxY)
171		drm_mode_validate_size(dev, &connector->modes, maxX,
172				       maxY, 0);
173
174	if (connector->interlace_allowed)
175		mode_flags |= DRM_MODE_FLAG_INTERLACE;
176	if (connector->doublescan_allowed)
177		mode_flags |= DRM_MODE_FLAG_DBLSCAN;
178	drm_mode_validate_flag(connector, mode_flags);
179
180	list_for_each_entry(mode, &connector->modes, head) {
181		if (mode->status == MODE_OK)
182			mode->status = connector_funcs->mode_valid(connector,
183								   mode);
184	}
185
186prune:
187	drm_mode_prune_invalid(dev, &connector->modes, true);
188
189	if (list_empty(&connector->modes))
190		return 0;
191
192	list_for_each_entry(mode, &connector->modes, head)
193		mode->vrefresh = drm_mode_vrefresh(mode);
194
195	drm_mode_sort(&connector->modes);
196
197	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
198			drm_get_connector_name(connector));
199	list_for_each_entry(mode, &connector->modes, head) {
200		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
201		drm_mode_debug_printmodeline(mode);
202	}
203
204	return count;
205}
206EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
207
208/**
209 * drm_helper_encoder_in_use - check if a given encoder is in use
210 * @encoder: encoder to check
211 *
212 * LOCKING:
213 * Caller must hold mode config lock.
214 *
215 * Walk @encoders's DRM device's mode_config and see if it's in use.
216 *
217 * RETURNS:
218 * True if @encoder is part of the mode_config, false otherwise.
219 */
220bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
221{
222	struct drm_connector *connector;
223	struct drm_device *dev = encoder->dev;
224	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
225		if (connector->encoder == encoder)
226			return true;
227	return false;
228}
229EXPORT_SYMBOL(drm_helper_encoder_in_use);
230
231/**
232 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
233 * @crtc: CRTC to check
234 *
235 * LOCKING:
236 * Caller must hold mode config lock.
237 *
238 * Walk @crtc's DRM device's mode_config and see if it's in use.
239 *
240 * RETURNS:
241 * True if @crtc is part of the mode_config, false otherwise.
242 */
243bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
244{
245	struct drm_encoder *encoder;
246	struct drm_device *dev = crtc->dev;
247	/* FIXME: Locking around list access? */
248	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
249		if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
250			return true;
251	return false;
252}
253EXPORT_SYMBOL(drm_helper_crtc_in_use);
254
255static void
256drm_encoder_disable(struct drm_encoder *encoder)
257{
258	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
259
260	if (encoder_funcs->disable)
261		(*encoder_funcs->disable)(encoder);
262	else
263		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
264}
265
266/**
267 * drm_helper_disable_unused_functions - disable unused objects
268 * @dev: DRM device
269 *
270 * LOCKING:
271 * Caller must hold mode config lock.
272 *
273 * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
274 * by calling its dpms function, which should power it off.
275 */
276void drm_helper_disable_unused_functions(struct drm_device *dev)
277{
278	struct drm_encoder *encoder;
279	struct drm_connector *connector;
280	struct drm_crtc *crtc;
281
282	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
283		if (!connector->encoder)
284			continue;
285		if (connector->status == connector_status_disconnected)
286			connector->encoder = NULL;
287	}
288
289	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
290		if (!drm_helper_encoder_in_use(encoder)) {
291			drm_encoder_disable(encoder);
292			/* disconnector encoder from any connector */
293			encoder->crtc = NULL;
294		}
295	}
296
297	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
298		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
299		crtc->enabled = drm_helper_crtc_in_use(crtc);
300		if (!crtc->enabled) {
301			if (crtc_funcs->disable)
302				(*crtc_funcs->disable)(crtc);
303			else
304				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
305			crtc->fb = NULL;
306		}
307	}
308}
309EXPORT_SYMBOL(drm_helper_disable_unused_functions);
310
311/**
312 * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
313 * @encoder: encoder to test
314 * @crtc: crtc to test
315 *
316 * Return false if @encoder can't be driven by @crtc, true otherwise.
317 */
318static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
319				struct drm_crtc *crtc)
320{
321	struct drm_device *dev;
322	struct drm_crtc *tmp;
323	int crtc_mask = 1;
324
325	if (crtc == NULL)
326		printf("checking null crtc?\n");
327
328	dev = crtc->dev;
329
330	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
331		if (tmp == crtc)
332			break;
333		crtc_mask <<= 1;
334	}
335
336	if (encoder->possible_crtcs & crtc_mask)
337		return true;
338	return false;
339}
340
341/*
342 * Check the CRTC we're going to map each output to vs. its current
343 * CRTC.  If they don't match, we have to disable the output and the CRTC
344 * since the driver will have to re-route things.
345 */
346static void
347drm_crtc_prepare_encoders(struct drm_device *dev)
348{
349	struct drm_encoder_helper_funcs *encoder_funcs;
350	struct drm_encoder *encoder;
351
352	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
353		encoder_funcs = encoder->helper_private;
354		/* Disable unused encoders */
355		if (encoder->crtc == NULL)
356			drm_encoder_disable(encoder);
357		/* Disable encoders whose CRTC is about to change */
358		if (encoder_funcs->get_crtc &&
359		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
360			drm_encoder_disable(encoder);
361	}
362}
363
364/**
365 * drm_crtc_helper_set_mode - internal helper to set a mode
366 * @crtc: CRTC to program
367 * @mode: mode to use
368 * @x: horizontal offset into the surface
369 * @y: vertical offset into the surface
370 * @old_fb: old framebuffer, for cleanup
371 *
372 * LOCKING:
373 * Caller must hold mode config lock.
374 *
375 * Try to set @mode on @crtc.  Give @crtc and its associated connectors a chance
376 * to fixup or reject the mode prior to trying to set it. This is an internal
377 * helper that drivers could e.g. use to update properties that require the
378 * entire output pipe to be disabled and re-enabled in a new configuration. For
379 * example for changing whether audio is enabled on a hdmi link or for changing
380 * panel fitter or dither attributes. It is also called by the
381 * drm_crtc_helper_set_config() helper function to drive the mode setting
382 * sequence.
383 *
384 * RETURNS:
385 * True if the mode was set successfully, or false otherwise.
386 */
387bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
388			      struct drm_display_mode *mode,
389			      int x, int y,
390			      struct drm_framebuffer *old_fb)
391{
392	struct drm_device *dev = crtc->dev;
393	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
394	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
395	struct drm_encoder_helper_funcs *encoder_funcs;
396	int saved_x, saved_y;
397	struct drm_encoder *encoder;
398	bool ret = true;
399
400	crtc->enabled = drm_helper_crtc_in_use(crtc);
401	if (!crtc->enabled)
402		return true;
403
404	adjusted_mode = drm_mode_duplicate(dev, mode);
405	if (!adjusted_mode)
406		return false;
407
408	saved_hwmode = crtc->hwmode;
409	saved_mode = crtc->mode;
410	saved_x = crtc->x;
411	saved_y = crtc->y;
412
413	/* Update crtc values up front so the driver can rely on them for mode
414	 * setting.
415	 */
416	crtc->mode = *mode;
417	crtc->x = x;
418	crtc->y = y;
419
420	/* Pass our mode to the connectors and the CRTC to give them a chance to
421	 * adjust it according to limitations or connector properties, and also
422	 * a chance to reject the mode entirely.
423	 */
424	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
425
426		if (encoder->crtc != crtc)
427			continue;
428		encoder_funcs = encoder->helper_private;
429		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
430						      adjusted_mode))) {
431			DRM_DEBUG_KMS("Encoder fixup failed\n");
432			goto done;
433		}
434	}
435
436	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
437		DRM_DEBUG_KMS("CRTC fixup failed\n");
438		goto done;
439	}
440	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
441
442	/* Prepare the encoders and CRTCs before setting the mode. */
443	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
444
445		if (encoder->crtc != crtc)
446			continue;
447		encoder_funcs = encoder->helper_private;
448		/* Disable the encoders as the first thing we do. */
449		encoder_funcs->prepare(encoder);
450	}
451
452	drm_crtc_prepare_encoders(dev);
453
454	crtc_funcs->prepare(crtc);
455
456	/* Set up the DPLL and any encoders state that needs to adjust or depend
457	 * on the DPLL.
458	 */
459	ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
460	if (!ret)
461	    goto done;
462
463	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
464
465		if (encoder->crtc != crtc)
466			continue;
467
468		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
469			encoder->base.id, drm_get_encoder_name(encoder),
470			mode->base.id, mode->name);
471		encoder_funcs = encoder->helper_private;
472		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
473	}
474
475	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
476	crtc_funcs->commit(crtc);
477
478	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
479
480		if (encoder->crtc != crtc)
481			continue;
482
483		encoder_funcs = encoder->helper_private;
484		encoder_funcs->commit(encoder);
485
486	}
487
488	/* Store real post-adjustment hardware mode. */
489	crtc->hwmode = *adjusted_mode;
490
491	/* Calculate and store various constants which
492	 * are later needed by vblank and swap-completion
493	 * timestamping. They are derived from true hwmode.
494	 */
495	drm_calc_timestamping_constants(crtc);
496
497	/* FIXME: add subpixel order */
498done:
499	drm_mode_destroy(dev, adjusted_mode);
500	if (!ret) {
501		crtc->hwmode = saved_hwmode;
502		crtc->mode = saved_mode;
503		crtc->x = saved_x;
504		crtc->y = saved_y;
505	}
506
507	return ret;
508}
509EXPORT_SYMBOL(drm_crtc_helper_set_mode);
510
511
512static int
513drm_crtc_helper_disable(struct drm_crtc *crtc)
514{
515	struct drm_device *dev = crtc->dev;
516	struct drm_connector *connector;
517	struct drm_encoder *encoder;
518
519	/* Decouple all encoders and their attached connectors from this crtc */
520	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
521		if (encoder->crtc != crtc)
522			continue;
523
524		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
525			if (connector->encoder != encoder)
526				continue;
527
528			connector->encoder = NULL;
529		}
530	}
531
532	drm_helper_disable_unused_functions(dev);
533	return 0;
534}
535
536/**
537 * drm_crtc_helper_set_config - set a new config from userspace
538 * @set: mode set configuration
539 *
540 * LOCKING:
541 * Caller must hold mode config lock.
542 *
543 * Setup a new configuration, provided by the upper layers (either an ioctl call
544 * from userspace or internally e.g. from the fbdev suppport code) in @set, and
545 * enable it. This is the main helper functions for drivers that implement
546 * kernel mode setting with the crtc helper functions and the assorted
547 * ->prepare(), ->modeset() and ->commit() helper callbacks.
548 *
549 * RETURNS:
550 * Returns 0 on success, -ERRNO on failure.
551 */
552int drm_crtc_helper_set_config(struct drm_mode_set *set)
553{
554	struct drm_device *dev;
555	struct drm_crtc *save_crtcs, *new_crtc, *crtc;
556	struct drm_encoder *save_encoders, *new_encoder, *encoder;
557	struct drm_framebuffer *old_fb = NULL;
558	bool mode_changed = false; /* if true do a full mode set */
559	bool fb_changed = false; /* if true and !mode_changed just do a flip */
560	struct drm_connector *save_connectors, *connector;
561	int count = 0, ro, fail = 0;
562	struct drm_crtc_helper_funcs *crtc_funcs;
563	struct drm_mode_set save_set;
564	int ret;
565	int i;
566
567	DRM_DEBUG_KMS("\n");
568
569	if (!set)
570		return -EINVAL;
571
572	if (!set->crtc)
573		return -EINVAL;
574
575	if (!set->crtc->helper_private)
576		return -EINVAL;
577
578	crtc_funcs = set->crtc->helper_private;
579
580	if (!set->mode)
581		set->fb = NULL;
582
583	if (set->fb) {
584		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
585				set->crtc->base.id, set->fb->base.id,
586				(int)set->num_connectors, set->x, set->y);
587	} else {
588		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
589		return drm_crtc_helper_disable(set->crtc);
590	}
591
592	dev = set->crtc->dev;
593
594	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
595	 * connector data. */
596	save_crtcs = malloc(dev->mode_config.num_crtc *
597			     sizeof(struct drm_crtc), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
598	if (!save_crtcs)
599		return -ENOMEM;
600
601	save_encoders = malloc(dev->mode_config.num_encoder *
602				sizeof(struct drm_encoder), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
603	if (!save_encoders) {
604		free(save_crtcs, DRM_MEM_KMS);
605		return -ENOMEM;
606	}
607
608	save_connectors = malloc(dev->mode_config.num_connector *
609				sizeof(struct drm_connector), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
610	if (!save_connectors) {
611		free(save_crtcs, DRM_MEM_KMS);
612		free(save_encoders, DRM_MEM_KMS);
613		return -ENOMEM;
614	}
615
616	/* Copy data. Note that driver private data is not affected.
617	 * Should anything bad happen only the expected state is
618	 * restored, not the drivers personal bookkeeping.
619	 */
620	count = 0;
621	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
622		save_crtcs[count++] = *crtc;
623	}
624
625	count = 0;
626	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
627		save_encoders[count++] = *encoder;
628	}
629
630	count = 0;
631	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
632		save_connectors[count++] = *connector;
633	}
634
635	save_set.crtc = set->crtc;
636	save_set.mode = &set->crtc->mode;
637	save_set.x = set->crtc->x;
638	save_set.y = set->crtc->y;
639	save_set.fb = set->crtc->fb;
640
641	/* We should be able to check here if the fb has the same properties
642	 * and then just flip_or_move it */
643	if (set->crtc->fb != set->fb) {
644		/* If we have no fb then treat it as a full mode set */
645		if (set->crtc->fb == NULL) {
646			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
647			mode_changed = true;
648		} else if (set->fb == NULL) {
649			mode_changed = true;
650		} else if (set->fb->depth != set->crtc->fb->depth) {
651			mode_changed = true;
652		} else if (set->fb->bits_per_pixel !=
653			   set->crtc->fb->bits_per_pixel) {
654			mode_changed = true;
655		} else
656			fb_changed = true;
657	}
658
659	if (set->x != set->crtc->x || set->y != set->crtc->y)
660		fb_changed = true;
661
662	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
663		DRM_DEBUG_KMS("modes are different, full mode set\n");
664		drm_mode_debug_printmodeline(&set->crtc->mode);
665		drm_mode_debug_printmodeline(set->mode);
666		mode_changed = true;
667	}
668
669	/* a) traverse passed in connector list and get encoders for them */
670	count = 0;
671	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
672		struct drm_connector_helper_funcs *connector_funcs =
673			connector->helper_private;
674		new_encoder = connector->encoder;
675		for (ro = 0; ro < set->num_connectors; ro++) {
676			if (set->connectors[ro] == connector) {
677				new_encoder = connector_funcs->best_encoder(connector);
678				/* if we can't get an encoder for a connector
679				   we are setting now - then fail */
680				if (new_encoder == NULL)
681					/* don't break so fail path works correct */
682					fail = 1;
683				break;
684			}
685		}
686
687		if (new_encoder != connector->encoder) {
688			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
689			mode_changed = true;
690			/* If the encoder is reused for another connector, then
691			 * the appropriate crtc will be set later.
692			 */
693			if (connector->encoder)
694				connector->encoder->crtc = NULL;
695			connector->encoder = new_encoder;
696		}
697	}
698
699	if (fail) {
700		ret = -EINVAL;
701		goto fail;
702	}
703
704	count = 0;
705	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
706		if (!connector->encoder)
707			continue;
708
709		if (connector->encoder->crtc == set->crtc)
710			new_crtc = NULL;
711		else
712			new_crtc = connector->encoder->crtc;
713
714		for (ro = 0; ro < set->num_connectors; ro++) {
715			if (set->connectors[ro] == connector)
716				new_crtc = set->crtc;
717		}
718
719		/* Make sure the new CRTC will work with the encoder */
720		if (new_crtc &&
721		    !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
722			ret = -EINVAL;
723			goto fail;
724		}
725		if (new_crtc != connector->encoder->crtc) {
726			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
727			mode_changed = true;
728			connector->encoder->crtc = new_crtc;
729		}
730		if (new_crtc) {
731			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
732				connector->base.id, drm_get_connector_name(connector),
733				new_crtc->base.id);
734		} else {
735			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
736				connector->base.id, drm_get_connector_name(connector));
737		}
738	}
739
740	/* mode_set_base is not a required function */
741	if (fb_changed && !crtc_funcs->mode_set_base)
742		mode_changed = true;
743
744	if (mode_changed) {
745		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
746		if (set->crtc->enabled) {
747			DRM_DEBUG_KMS("attempting to set mode from"
748					" userspace\n");
749			drm_mode_debug_printmodeline(set->mode);
750			old_fb = set->crtc->fb;
751			set->crtc->fb = set->fb;
752			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
753						      set->x, set->y,
754						      old_fb)) {
755				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
756					  set->crtc->base.id);
757				set->crtc->fb = old_fb;
758				ret = -EINVAL;
759				goto fail;
760			}
761			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
762			for (i = 0; i < set->num_connectors; i++) {
763				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
764					      drm_get_connector_name(set->connectors[i]));
765				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
766			}
767		}
768		drm_helper_disable_unused_functions(dev);
769	} else if (fb_changed) {
770		set->crtc->x = set->x;
771		set->crtc->y = set->y;
772
773		old_fb = set->crtc->fb;
774		if (set->crtc->fb != set->fb)
775			set->crtc->fb = set->fb;
776		ret = crtc_funcs->mode_set_base(set->crtc,
777						set->x, set->y, old_fb);
778		if (ret != 0) {
779			set->crtc->fb = old_fb;
780			goto fail;
781		}
782	}
783
784	free(save_connectors, DRM_MEM_KMS);
785	free(save_encoders, DRM_MEM_KMS);
786	free(save_crtcs, DRM_MEM_KMS);
787	return 0;
788
789fail:
790	/* Restore all previous data. */
791	count = 0;
792	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
793		*crtc = save_crtcs[count++];
794	}
795
796	count = 0;
797	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
798		*encoder = save_encoders[count++];
799	}
800
801	count = 0;
802	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
803		*connector = save_connectors[count++];
804	}
805
806	/* Try to restore the config */
807	if (mode_changed &&
808	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
809				      save_set.y, save_set.fb))
810		DRM_ERROR("failed to restore config after modeset failure\n");
811
812	free(save_connectors, DRM_MEM_KMS);
813	free(save_encoders, DRM_MEM_KMS);
814	free(save_crtcs, DRM_MEM_KMS);
815	return ret;
816}
817EXPORT_SYMBOL(drm_crtc_helper_set_config);
818
819static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
820{
821	int dpms = DRM_MODE_DPMS_OFF;
822	struct drm_connector *connector;
823	struct drm_device *dev = encoder->dev;
824
825	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
826		if (connector->encoder == encoder)
827			if (connector->dpms < dpms)
828				dpms = connector->dpms;
829	return dpms;
830}
831
832static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
833{
834	int dpms = DRM_MODE_DPMS_OFF;
835	struct drm_connector *connector;
836	struct drm_device *dev = crtc->dev;
837
838	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
839		if (connector->encoder && connector->encoder->crtc == crtc)
840			if (connector->dpms < dpms)
841				dpms = connector->dpms;
842	return dpms;
843}
844
845/**
846 * drm_helper_connector_dpms() - connector dpms helper implementation
847 * @connector: affected connector
848 * @mode: DPMS mode
849 *
850 * This is the main helper function provided by the crtc helper framework for
851 * implementing the DPMS connector attribute. It computes the new desired DPMS
852 * state for all encoders and crtcs in the output mesh and calls the ->dpms()
853 * callback provided by the driver appropriately.
854 */
855void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
856{
857	struct drm_encoder *encoder = connector->encoder;
858	struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
859	int old_dpms;
860
861	if (mode == connector->dpms)
862		return;
863
864	old_dpms = connector->dpms;
865	connector->dpms = mode;
866
867	/* from off to on, do crtc then encoder */
868	if (mode < old_dpms) {
869		if (crtc) {
870			struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
871			if (crtc_funcs->dpms)
872				(*crtc_funcs->dpms) (crtc,
873						     drm_helper_choose_crtc_dpms(crtc));
874		}
875		if (encoder) {
876			struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
877			if (encoder_funcs->dpms)
878				(*encoder_funcs->dpms) (encoder,
879							drm_helper_choose_encoder_dpms(encoder));
880		}
881	}
882
883	/* from on to off, do encoder then crtc */
884	if (mode > old_dpms) {
885		if (encoder) {
886			struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
887			if (encoder_funcs->dpms)
888				(*encoder_funcs->dpms) (encoder,
889							drm_helper_choose_encoder_dpms(encoder));
890		}
891		if (crtc) {
892			struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
893			if (crtc_funcs->dpms)
894				(*crtc_funcs->dpms) (crtc,
895						     drm_helper_choose_crtc_dpms(crtc));
896		}
897	}
898
899	return;
900}
901EXPORT_SYMBOL(drm_helper_connector_dpms);
902
903int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
904				   struct drm_mode_fb_cmd2 *mode_cmd)
905{
906	int i;
907
908	fb->width = mode_cmd->width;
909	fb->height = mode_cmd->height;
910	for (i = 0; i < 4; i++) {
911		fb->pitches[i] = mode_cmd->pitches[i];
912		fb->offsets[i] = mode_cmd->offsets[i];
913	}
914	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
915				    &fb->bits_per_pixel);
916	fb->pixel_format = mode_cmd->pixel_format;
917
918	return 0;
919}
920EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
921
922int drm_helper_resume_force_mode(struct drm_device *dev)
923{
924	struct drm_crtc *crtc;
925	struct drm_encoder *encoder;
926	struct drm_encoder_helper_funcs *encoder_funcs;
927	struct drm_crtc_helper_funcs *crtc_funcs;
928	int ret;
929
930	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
931
932		if (!crtc->enabled)
933			continue;
934
935		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
936					       crtc->x, crtc->y, crtc->fb);
937
938		if (ret == false)
939			DRM_ERROR("failed to set mode on crtc %p\n", crtc);
940
941		/* Turn off outputs that were already powered off */
942		if (drm_helper_choose_crtc_dpms(crtc)) {
943			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
944
945				if(encoder->crtc != crtc)
946					continue;
947
948				encoder_funcs = encoder->helper_private;
949				if (encoder_funcs->dpms)
950					(*encoder_funcs->dpms) (encoder,
951								drm_helper_choose_encoder_dpms(encoder));
952			}
953
954			crtc_funcs = crtc->helper_private;
955			if (crtc_funcs->dpms)
956				(*crtc_funcs->dpms) (crtc,
957						     drm_helper_choose_crtc_dpms(crtc));
958		}
959	}
960	/* disable the unused connectors while restoring the modesetting */
961	drm_helper_disable_unused_functions(dev);
962	return 0;
963}
964EXPORT_SYMBOL(drm_helper_resume_force_mode);
965
966void drm_kms_helper_hotplug_event(struct drm_device *dev)
967{
968	/* send a uevent + call fbdev */
969#ifdef FREEBSD_NOTYET
970	drm_sysfs_hotplug_event(dev);
971#endif /* FREEBSD_NOTYET */
972	if (dev->mode_config.funcs->output_poll_changed)
973		dev->mode_config.funcs->output_poll_changed(dev);
974}
975EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
976
977#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
978static void output_poll_execute(void *ctx, int pending)
979{
980	struct drm_device *dev = ctx;
981	struct drm_connector *connector;
982	enum drm_connector_status old_status;
983	bool repoll = false, changed = false;
984
985	if (!drm_kms_helper_poll)
986		return;
987
988	sx_xlock(&dev->mode_config.mutex);
989	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
990
991		/* Ignore forced connectors. */
992		if (connector->force)
993			continue;
994
995		/* Ignore HPD capable connectors and connectors where we don't
996		 * want any hotplug detection at all for polling. */
997		if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
998			continue;
999
1000		repoll = true;
1001
1002		old_status = connector->status;
1003		/* if we are connected and don't want to poll for disconnect
1004		   skip it */
1005		if (old_status == connector_status_connected &&
1006		    !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
1007			continue;
1008
1009		connector->status = connector->funcs->detect(connector, false);
1010		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
1011			      connector->base.id,
1012			      drm_get_connector_name(connector),
1013			      old_status, connector->status);
1014		if (old_status != connector->status)
1015			changed = true;
1016	}
1017
1018	sx_xunlock(&dev->mode_config.mutex);
1019
1020	if (changed)
1021		drm_kms_helper_hotplug_event(dev);
1022
1023	if (repoll)
1024		taskqueue_enqueue_timeout(taskqueue_thread,
1025		    &dev->mode_config.output_poll_work,
1026		    DRM_OUTPUT_POLL_PERIOD);
1027}
1028
1029void drm_kms_helper_poll_disable(struct drm_device *dev)
1030{
1031	if (!dev->mode_config.poll_enabled)
1032		return;
1033	taskqueue_cancel_timeout(taskqueue_thread,
1034	    &dev->mode_config.output_poll_work, NULL);
1035}
1036EXPORT_SYMBOL(drm_kms_helper_poll_disable);
1037
1038void drm_kms_helper_poll_enable(struct drm_device *dev)
1039{
1040	bool poll = false;
1041	struct drm_connector *connector;
1042
1043	if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
1044		return;
1045
1046	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1047		if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
1048					 DRM_CONNECTOR_POLL_DISCONNECT))
1049			poll = true;
1050	}
1051
1052	if (poll)
1053		taskqueue_enqueue_timeout(taskqueue_thread,
1054		    &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
1055}
1056EXPORT_SYMBOL(drm_kms_helper_poll_enable);
1057
1058void drm_kms_helper_poll_init(struct drm_device *dev)
1059{
1060	TIMEOUT_TASK_INIT(taskqueue_thread, &dev->mode_config.output_poll_work,
1061	    0, output_poll_execute, dev);
1062	dev->mode_config.poll_enabled = true;
1063
1064	drm_kms_helper_poll_enable(dev);
1065}
1066EXPORT_SYMBOL(drm_kms_helper_poll_init);
1067
1068void drm_kms_helper_poll_fini(struct drm_device *dev)
1069{
1070	drm_kms_helper_poll_disable(dev);
1071}
1072EXPORT_SYMBOL(drm_kms_helper_poll_fini);
1073
1074void drm_helper_hpd_irq_event(struct drm_device *dev)
1075{
1076	struct drm_connector *connector;
1077	enum drm_connector_status old_status;
1078	bool changed = false;
1079
1080	if (!dev->mode_config.poll_enabled)
1081		return;
1082
1083	sx_xlock(&dev->mode_config.mutex);
1084	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1085
1086		/* Only handle HPD capable connectors. */
1087		if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
1088			continue;
1089
1090		old_status = connector->status;
1091
1092		connector->status = connector->funcs->detect(connector, false);
1093		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
1094			      connector->base.id,
1095			      drm_get_connector_name(connector),
1096			      old_status, connector->status);
1097		if (old_status != connector->status)
1098			changed = true;
1099	}
1100
1101	sx_xunlock(&dev->mode_config.mutex);
1102
1103	if (changed)
1104		drm_kms_helper_hotplug_event(dev);
1105}
1106EXPORT_SYMBOL(drm_helper_hpd_irq_event);
1107