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