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