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