Home | History | Annotate | Line # | Download | only in drm
drm_crtc_helper.c revision 1.6
      1 /*	$NetBSD: drm_crtc_helper.c,v 1.6 2020/02/14 14:34:57 maya Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2006-2008 Intel Corporation
      5  * Copyright (c) 2007 Dave Airlie <airlied (at) linux.ie>
      6  *
      7  * DRM core CRTC related functions
      8  *
      9  * Permission to use, copy, modify, distribute, and sell this software and its
     10  * documentation for any purpose is hereby granted without fee, provided that
     11  * the above copyright notice appear in all copies and that both that copyright
     12  * notice and this permission notice appear in supporting documentation, and
     13  * that the name of the copyright holders not be used in advertising or
     14  * publicity pertaining to distribution of the software without specific,
     15  * written prior permission.  The copyright holders make no representations
     16  * about the suitability of this software for any purpose.  It is provided "as
     17  * is" without express or implied warranty.
     18  *
     19  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     20  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     21  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     22  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     23  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     24  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     25  * OF THIS SOFTWARE.
     26  *
     27  * Authors:
     28  *      Keith Packard
     29  *	Eric Anholt <eric (at) anholt.net>
     30  *      Dave Airlie <airlied (at) linux.ie>
     31  *      Jesse Barnes <jesse.barnes (at) intel.com>
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: drm_crtc_helper.c,v 1.6 2020/02/14 14:34:57 maya Exp $");
     36 
     37 #include <linux/kernel.h>
     38 #include <linux/export.h>
     39 #include <linux/moduleparam.h>
     40 
     41 #include <drm/drmP.h>
     42 #include <drm/drm_atomic.h>
     43 #include <drm/drm_crtc.h>
     44 #include <drm/drm_fourcc.h>
     45 #include <drm/drm_crtc_helper.h>
     46 #ifndef __NetBSD__
     47 #include <drm/drm_fb_helper.h>
     48 #endif
     49 #include <drm/drm_plane_helper.h>
     50 #include <drm/drm_atomic_helper.h>
     51 #include <drm/drm_edid.h>
     52 
     53 /**
     54  * DOC: overview
     55  *
     56  * The CRTC modeset helper library provides a default set_config implementation
     57  * in drm_crtc_helper_set_config(). Plus a few other convenience functions using
     58  * the same callbacks which drivers can use to e.g. restore the modeset
     59  * configuration on resume with drm_helper_resume_force_mode().
     60  *
     61  * The driver callbacks are mostly compatible with the atomic modeset helpers,
     62  * except for the handling of the primary plane: Atomic helpers require that the
     63  * primary plane is implemented as a real standalone plane and not directly tied
     64  * to the CRTC state. For easier transition this library provides functions to
     65  * implement the old semantics required by the CRTC helpers using the new plane
     66  * and atomic helper callbacks.
     67  *
     68  * Drivers are strongly urged to convert to the atomic helpers (by way of first
     69  * converting to the plane helpers). New drivers must not use these functions
     70  * but need to implement the atomic interface instead, potentially using the
     71  * atomic helpers for that.
     72  */
     73 MODULE_AUTHOR("David Airlie, Jesse Barnes");
     74 MODULE_DESCRIPTION("DRM KMS helper");
     75 MODULE_LICENSE("GPL and additional rights");
     76 
     77 /**
     78  * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
     79  * 						connector list
     80  * @dev: drm device to operate on
     81  *
     82  * Some userspace presumes that the first connected connector is the main
     83  * display, where it's supposed to display e.g. the login screen. For
     84  * laptops, this should be the main panel. Use this function to sort all
     85  * (eDP/LVDS) panels to the front of the connector list, instead of
     86  * painstakingly trying to initialize them in the right order.
     87  */
     88 void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
     89 {
     90 	struct drm_connector *connector, *tmp;
     91 	struct list_head panel_list;
     92 
     93 	INIT_LIST_HEAD(&panel_list);
     94 
     95 	list_for_each_entry_safe(connector, tmp,
     96 				 &dev->mode_config.connector_list, head) {
     97 		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
     98 		    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
     99 			list_move_tail(&connector->head, &panel_list);
    100 	}
    101 
    102 	list_splice(&panel_list, &dev->mode_config.connector_list);
    103 }
    104 EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
    105 
    106 /**
    107  * drm_helper_encoder_in_use - check if a given encoder is in use
    108  * @encoder: encoder to check
    109  *
    110  * Checks whether @encoder is with the current mode setting output configuration
    111  * in use by any connector. This doesn't mean that it is actually enabled since
    112  * the DPMS state is tracked separately.
    113  *
    114  * Returns:
    115  * True if @encoder is used, false otherwise.
    116  */
    117 bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
    118 {
    119 	struct drm_connector *connector;
    120 	struct drm_device *dev = encoder->dev;
    121 
    122 	/*
    123 	 * We can expect this mutex to be locked if we are not panicking.
    124 	 * Locking is currently fubar in the panic handler.
    125 	 */
    126 	if (!oops_in_progress) {
    127 		WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
    128 		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
    129 	}
    130 
    131 	drm_for_each_connector(connector, dev)
    132 		if (connector->encoder == encoder)
    133 			return true;
    134 	return false;
    135 }
    136 EXPORT_SYMBOL(drm_helper_encoder_in_use);
    137 
    138 /**
    139  * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
    140  * @crtc: CRTC to check
    141  *
    142  * Checks whether @crtc is with the current mode setting output configuration
    143  * in use by any connector. This doesn't mean that it is actually enabled since
    144  * the DPMS state is tracked separately.
    145  *
    146  * Returns:
    147  * True if @crtc is used, false otherwise.
    148  */
    149 bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
    150 {
    151 	struct drm_encoder *encoder;
    152 	struct drm_device *dev = crtc->dev;
    153 
    154 	/*
    155 	 * We can expect this mutex to be locked if we are not panicking.
    156 	 * Locking is currently fubar in the panic handler.
    157 	 */
    158 	if (!oops_in_progress)
    159 		WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
    160 
    161 	drm_for_each_encoder(encoder, dev)
    162 		if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
    163 			return true;
    164 	return false;
    165 }
    166 EXPORT_SYMBOL(drm_helper_crtc_in_use);
    167 
    168 static void
    169 drm_encoder_disable(struct drm_encoder *encoder)
    170 {
    171 	const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
    172 
    173 	drm_bridge_disable(encoder->bridge);
    174 
    175 	if (encoder_funcs->disable)
    176 		(*encoder_funcs->disable)(encoder);
    177 	else
    178 		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
    179 
    180 	drm_bridge_post_disable(encoder->bridge);
    181 }
    182 
    183 static void __drm_helper_disable_unused_functions(struct drm_device *dev)
    184 {
    185 	struct drm_encoder *encoder;
    186 	struct drm_crtc *crtc;
    187 
    188 	drm_warn_on_modeset_not_all_locked(dev);
    189 
    190 	drm_for_each_encoder(encoder, dev) {
    191 		if (!drm_helper_encoder_in_use(encoder)) {
    192 			drm_encoder_disable(encoder);
    193 			/* disconnect encoder from any connector */
    194 			encoder->crtc = NULL;
    195 		}
    196 	}
    197 
    198 	drm_for_each_crtc(crtc, dev) {
    199 		const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
    200 		crtc->enabled = drm_helper_crtc_in_use(crtc);
    201 		if (!crtc->enabled) {
    202 			if (crtc_funcs->disable)
    203 				(*crtc_funcs->disable)(crtc);
    204 			else
    205 				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
    206 			crtc->primary->fb = NULL;
    207 		}
    208 	}
    209 }
    210 
    211 /**
    212  * drm_helper_disable_unused_functions - disable unused objects
    213  * @dev: DRM device
    214  *
    215  * This function walks through the entire mode setting configuration of @dev. It
    216  * will remove any crtc links of unused encoders and encoder links of
    217  * disconnected connectors. Then it will disable all unused encoders and crtcs
    218  * either by calling their disable callback if available or by calling their
    219  * dpms callback with DRM_MODE_DPMS_OFF.
    220  */
    221 void drm_helper_disable_unused_functions(struct drm_device *dev)
    222 {
    223 	drm_modeset_lock_all(dev);
    224 	__drm_helper_disable_unused_functions(dev);
    225 	drm_modeset_unlock_all(dev);
    226 }
    227 EXPORT_SYMBOL(drm_helper_disable_unused_functions);
    228 
    229 /*
    230  * Check the CRTC we're going to map each output to vs. its current
    231  * CRTC.  If they don't match, we have to disable the output and the CRTC
    232  * since the driver will have to re-route things.
    233  */
    234 static void
    235 drm_crtc_prepare_encoders(struct drm_device *dev)
    236 {
    237 	const struct drm_encoder_helper_funcs *encoder_funcs;
    238 	struct drm_encoder *encoder;
    239 
    240 	drm_for_each_encoder(encoder, dev) {
    241 		encoder_funcs = encoder->helper_private;
    242 		/* Disable unused encoders */
    243 		if (encoder->crtc == NULL)
    244 			drm_encoder_disable(encoder);
    245 		/* Disable encoders whose CRTC is about to change */
    246 		if (encoder_funcs->get_crtc &&
    247 		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
    248 			drm_encoder_disable(encoder);
    249 	}
    250 }
    251 
    252 /**
    253  * drm_crtc_helper_set_mode - internal helper to set a mode
    254  * @crtc: CRTC to program
    255  * @mode: mode to use
    256  * @x: horizontal offset into the surface
    257  * @y: vertical offset into the surface
    258  * @old_fb: old framebuffer, for cleanup
    259  *
    260  * Try to set @mode on @crtc.  Give @crtc and its associated connectors a chance
    261  * to fixup or reject the mode prior to trying to set it. This is an internal
    262  * helper that drivers could e.g. use to update properties that require the
    263  * entire output pipe to be disabled and re-enabled in a new configuration. For
    264  * example for changing whether audio is enabled on a hdmi link or for changing
    265  * panel fitter or dither attributes. It is also called by the
    266  * drm_crtc_helper_set_config() helper function to drive the mode setting
    267  * sequence.
    268  *
    269  * Returns:
    270  * True if the mode was set successfully, false otherwise.
    271  */
    272 bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
    273 			      struct drm_display_mode *mode,
    274 			      int x, int y,
    275 			      struct drm_framebuffer *old_fb)
    276 {
    277 	struct drm_device *dev = crtc->dev;
    278 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
    279 	const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
    280 	const struct drm_encoder_helper_funcs *encoder_funcs;
    281 	int saved_x, saved_y;
    282 	bool saved_enabled;
    283 	struct drm_encoder *encoder;
    284 	bool ret = true;
    285 
    286 	drm_warn_on_modeset_not_all_locked(dev);
    287 
    288 	saved_enabled = crtc->enabled;
    289 	crtc->enabled = drm_helper_crtc_in_use(crtc);
    290 	if (!crtc->enabled)
    291 		return true;
    292 
    293 	adjusted_mode = drm_mode_duplicate(dev, mode);
    294 	if (!adjusted_mode) {
    295 		crtc->enabled = saved_enabled;
    296 		return false;
    297 	}
    298 
    299 	saved_mode = crtc->mode;
    300 	saved_hwmode = crtc->hwmode;
    301 	saved_x = crtc->x;
    302 	saved_y = crtc->y;
    303 
    304 	/* Update crtc values up front so the driver can rely on them for mode
    305 	 * setting.
    306 	 */
    307 	crtc->mode = *mode;
    308 	crtc->x = x;
    309 	crtc->y = y;
    310 
    311 	/* Pass our mode to the connectors and the CRTC to give them a chance to
    312 	 * adjust it according to limitations or connector properties, and also
    313 	 * a chance to reject the mode entirely.
    314 	 */
    315 	drm_for_each_encoder(encoder, dev) {
    316 
    317 		if (encoder->crtc != crtc)
    318 			continue;
    319 
    320 		ret = drm_bridge_mode_fixup(encoder->bridge,
    321 			mode, adjusted_mode);
    322 		if (!ret) {
    323 			DRM_DEBUG_KMS("Bridge fixup failed\n");
    324 			goto done;
    325 		}
    326 
    327 		encoder_funcs = encoder->helper_private;
    328 		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
    329 						      adjusted_mode))) {
    330 			DRM_DEBUG_KMS("Encoder fixup failed\n");
    331 			goto done;
    332 		}
    333 	}
    334 
    335 	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
    336 		DRM_DEBUG_KMS("CRTC fixup failed\n");
    337 		goto done;
    338 	}
    339 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
    340 
    341 	crtc->hwmode = *adjusted_mode;
    342 
    343 	/* Prepare the encoders and CRTCs before setting the mode. */
    344 	drm_for_each_encoder(encoder, dev) {
    345 
    346 		if (encoder->crtc != crtc)
    347 			continue;
    348 
    349 		drm_bridge_disable(encoder->bridge);
    350 
    351 		encoder_funcs = encoder->helper_private;
    352 		/* Disable the encoders as the first thing we do. */
    353 		encoder_funcs->prepare(encoder);
    354 
    355 		drm_bridge_post_disable(encoder->bridge);
    356 	}
    357 
    358 	drm_crtc_prepare_encoders(dev);
    359 
    360 	crtc_funcs->prepare(crtc);
    361 
    362 	/* Set up the DPLL and any encoders state that needs to adjust or depend
    363 	 * on the DPLL.
    364 	 */
    365 	ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
    366 	if (!ret)
    367 	    goto done;
    368 
    369 	drm_for_each_encoder(encoder, dev) {
    370 
    371 		if (encoder->crtc != crtc)
    372 			continue;
    373 
    374 		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
    375 			encoder->base.id, encoder->name,
    376 			mode->base.id, mode->name);
    377 		encoder_funcs = encoder->helper_private;
    378 		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
    379 
    380 		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
    381 	}
    382 
    383 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
    384 	crtc_funcs->commit(crtc);
    385 
    386 	drm_for_each_encoder(encoder, dev) {
    387 
    388 		if (encoder->crtc != crtc)
    389 			continue;
    390 
    391 		drm_bridge_pre_enable(encoder->bridge);
    392 
    393 		encoder_funcs = encoder->helper_private;
    394 		encoder_funcs->commit(encoder);
    395 
    396 		drm_bridge_enable(encoder->bridge);
    397 	}
    398 
    399 	/* Calculate and store various constants which
    400 	 * are later needed by vblank and swap-completion
    401 	 * timestamping. They are derived from true hwmode.
    402 	 */
    403 	drm_calc_timestamping_constants(crtc, &crtc->hwmode);
    404 
    405 	/* FIXME: add subpixel order */
    406 done:
    407 	drm_mode_destroy(dev, adjusted_mode);
    408 	if (!ret) {
    409 		crtc->enabled = saved_enabled;
    410 		crtc->mode = saved_mode;
    411 		crtc->hwmode = saved_hwmode;
    412 		crtc->x = saved_x;
    413 		crtc->y = saved_y;
    414 	}
    415 
    416 	return ret;
    417 }
    418 EXPORT_SYMBOL(drm_crtc_helper_set_mode);
    419 
    420 static void
    421 drm_crtc_helper_disable(struct drm_crtc *crtc)
    422 {
    423 	struct drm_device *dev = crtc->dev;
    424 	struct drm_connector *connector;
    425 	struct drm_encoder *encoder;
    426 
    427 	/* Decouple all encoders and their attached connectors from this crtc */
    428 	drm_for_each_encoder(encoder, dev) {
    429 		if (encoder->crtc != crtc)
    430 			continue;
    431 
    432 		drm_for_each_connector(connector, dev) {
    433 			if (connector->encoder != encoder)
    434 				continue;
    435 
    436 			connector->encoder = NULL;
    437 
    438 			/*
    439 			 * drm_helper_disable_unused_functions() ought to be
    440 			 * doing this, but since we've decoupled the encoder
    441 			 * from the connector above, the required connection
    442 			 * between them is henceforth no longer available.
    443 			 */
    444 			connector->dpms = DRM_MODE_DPMS_OFF;
    445 		}
    446 	}
    447 
    448 	__drm_helper_disable_unused_functions(dev);
    449 }
    450 
    451 /**
    452  * drm_crtc_helper_set_config - set a new config from userspace
    453  * @set: mode set configuration
    454  *
    455  * Setup a new configuration, provided by the upper layers (either an ioctl call
    456  * from userspace or internally e.g. from the fbdev support code) in @set, and
    457  * enable it. This is the main helper functions for drivers that implement
    458  * kernel mode setting with the crtc helper functions and the assorted
    459  * ->prepare(), ->modeset() and ->commit() helper callbacks.
    460  *
    461  * Returns:
    462  * Returns 0 on success, negative errno numbers on failure.
    463  */
    464 int drm_crtc_helper_set_config(struct drm_mode_set *set)
    465 {
    466 	struct drm_device *dev;
    467 	struct drm_crtc *new_crtc;
    468 	struct drm_encoder *save_encoders, *new_encoder, *encoder;
    469 	bool mode_changed = false; /* if true do a full mode set */
    470 	bool fb_changed = false; /* if true and !mode_changed just do a flip */
    471 	struct drm_connector *save_connectors, *connector;
    472 	int count = 0, ro, fail = 0;
    473 	const struct drm_crtc_helper_funcs *crtc_funcs;
    474 	struct drm_mode_set save_set;
    475 	int ret;
    476 	int i;
    477 
    478 	DRM_DEBUG_KMS("\n");
    479 
    480 	BUG_ON(!set);
    481 	BUG_ON(!set->crtc);
    482 	BUG_ON(!set->crtc->helper_private);
    483 
    484 	/* Enforce sane interface api - has been abused by the fb helper. */
    485 	BUG_ON(!set->mode && set->fb);
    486 	BUG_ON(set->fb && set->num_connectors == 0);
    487 
    488 	crtc_funcs = set->crtc->helper_private;
    489 
    490 	if (!set->mode)
    491 		set->fb = NULL;
    492 
    493 	if (set->fb) {
    494 		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
    495 				set->crtc->base.id, set->fb->base.id,
    496 				(int)set->num_connectors, set->x, set->y);
    497 	} else {
    498 		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
    499 		drm_crtc_helper_disable(set->crtc);
    500 		return 0;
    501 	}
    502 
    503 	dev = set->crtc->dev;
    504 
    505 	drm_warn_on_modeset_not_all_locked(dev);
    506 
    507 	/*
    508 	 * Allocate space for the backup of all (non-pointer) encoder and
    509 	 * connector data.
    510 	 */
    511 	save_encoders = kzalloc(dev->mode_config.num_encoder *
    512 				sizeof(struct drm_encoder), GFP_KERNEL);
    513 	if (!save_encoders)
    514 		return -ENOMEM;
    515 
    516 	save_connectors = kzalloc(dev->mode_config.num_connector *
    517 				sizeof(struct drm_connector), GFP_KERNEL);
    518 	if (!save_connectors) {
    519 		kfree(save_encoders);
    520 		return -ENOMEM;
    521 	}
    522 
    523 	/*
    524 	 * Copy data. Note that driver private data is not affected.
    525 	 * Should anything bad happen only the expected state is
    526 	 * restored, not the drivers personal bookkeeping.
    527 	 */
    528 	count = 0;
    529 	drm_for_each_encoder(encoder, dev) {
    530 		save_encoders[count++] = *encoder;
    531 	}
    532 
    533 	count = 0;
    534 	drm_for_each_connector(connector, dev) {
    535 		save_connectors[count++] = *connector;
    536 	}
    537 
    538 	save_set.crtc = set->crtc;
    539 	save_set.mode = &set->crtc->mode;
    540 	save_set.x = set->crtc->x;
    541 	save_set.y = set->crtc->y;
    542 	save_set.fb = set->crtc->primary->fb;
    543 
    544 	/* We should be able to check here if the fb has the same properties
    545 	 * and then just flip_or_move it */
    546 	if (set->crtc->primary->fb != set->fb) {
    547 		/* If we have no fb then treat it as a full mode set */
    548 		if (set->crtc->primary->fb == NULL) {
    549 			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
    550 			mode_changed = true;
    551 		} else if (set->fb == NULL) {
    552 			mode_changed = true;
    553 		} else if (set->fb->pixel_format !=
    554 			   set->crtc->primary->fb->pixel_format) {
    555 			mode_changed = true;
    556 		} else
    557 			fb_changed = true;
    558 	}
    559 
    560 	if (set->x != set->crtc->x || set->y != set->crtc->y)
    561 		fb_changed = true;
    562 
    563 	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
    564 		DRM_DEBUG_KMS("modes are different, full mode set\n");
    565 		drm_mode_debug_printmodeline(&set->crtc->mode);
    566 		drm_mode_debug_printmodeline(set->mode);
    567 		mode_changed = true;
    568 	}
    569 
    570 	/* a) traverse passed in connector list and get encoders for them */
    571 	count = 0;
    572 	drm_for_each_connector(connector, dev) {
    573 		const struct drm_connector_helper_funcs *connector_funcs =
    574 			connector->helper_private;
    575 		new_encoder = connector->encoder;
    576 		for (ro = 0; ro < set->num_connectors; ro++) {
    577 			if (set->connectors[ro] == connector) {
    578 				new_encoder = connector_funcs->best_encoder(connector);
    579 				/* if we can't get an encoder for a connector
    580 				   we are setting now - then fail */
    581 				if (new_encoder == NULL)
    582 					/* don't break so fail path works correct */
    583 					fail = 1;
    584 
    585 				if (connector->dpms != DRM_MODE_DPMS_ON) {
    586 					DRM_DEBUG_KMS("connector dpms not on, full mode switch\n");
    587 					mode_changed = true;
    588 				}
    589 
    590 				break;
    591 			}
    592 		}
    593 
    594 		if (new_encoder != connector->encoder) {
    595 			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
    596 			mode_changed = true;
    597 			/* If the encoder is reused for another connector, then
    598 			 * the appropriate crtc will be set later.
    599 			 */
    600 			if (connector->encoder)
    601 				connector->encoder->crtc = NULL;
    602 			connector->encoder = new_encoder;
    603 		}
    604 	}
    605 
    606 	if (fail) {
    607 		ret = -EINVAL;
    608 		goto fail;
    609 	}
    610 
    611 	count = 0;
    612 	drm_for_each_connector(connector, dev) {
    613 		if (!connector->encoder)
    614 			continue;
    615 
    616 		if (connector->encoder->crtc == set->crtc)
    617 			new_crtc = NULL;
    618 		else
    619 			new_crtc = connector->encoder->crtc;
    620 
    621 		for (ro = 0; ro < set->num_connectors; ro++) {
    622 			if (set->connectors[ro] == connector)
    623 				new_crtc = set->crtc;
    624 		}
    625 
    626 		/* Make sure the new CRTC will work with the encoder */
    627 		if (new_crtc &&
    628 		    !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
    629 			ret = -EINVAL;
    630 			goto fail;
    631 		}
    632 		if (new_crtc != connector->encoder->crtc) {
    633 			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
    634 			mode_changed = true;
    635 			connector->encoder->crtc = new_crtc;
    636 		}
    637 		if (new_crtc) {
    638 			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
    639 				connector->base.id, connector->name,
    640 				new_crtc->base.id);
    641 		} else {
    642 			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
    643 				connector->base.id, connector->name);
    644 		}
    645 	}
    646 
    647 	/* mode_set_base is not a required function */
    648 	if (fb_changed && !crtc_funcs->mode_set_base)
    649 		mode_changed = true;
    650 
    651 	if (mode_changed) {
    652 		if (drm_helper_crtc_in_use(set->crtc)) {
    653 			DRM_DEBUG_KMS("attempting to set mode from"
    654 					" userspace\n");
    655 			drm_mode_debug_printmodeline(set->mode);
    656 			set->crtc->primary->fb = set->fb;
    657 			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
    658 						      set->x, set->y,
    659 						      save_set.fb)) {
    660 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
    661 					  set->crtc->base.id);
    662 				set->crtc->primary->fb = save_set.fb;
    663 				ret = -EINVAL;
    664 				goto fail;
    665 			}
    666 			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
    667 			for (i = 0; i < set->num_connectors; i++) {
    668 				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
    669 					      set->connectors[i]->name);
    670 				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
    671 			}
    672 		}
    673 		__drm_helper_disable_unused_functions(dev);
    674 	} else if (fb_changed) {
    675 		set->crtc->x = set->x;
    676 		set->crtc->y = set->y;
    677 		set->crtc->primary->fb = set->fb;
    678 		ret = crtc_funcs->mode_set_base(set->crtc,
    679 						set->x, set->y, save_set.fb);
    680 		if (ret != 0) {
    681 			set->crtc->x = save_set.x;
    682 			set->crtc->y = save_set.y;
    683 			set->crtc->primary->fb = save_set.fb;
    684 			goto fail;
    685 		}
    686 	}
    687 
    688 	kfree(save_connectors);
    689 	kfree(save_encoders);
    690 	return 0;
    691 
    692 fail:
    693 	/* Restore all previous data. */
    694 	count = 0;
    695 	drm_for_each_encoder(encoder, dev) {
    696 		*encoder = save_encoders[count++];
    697 	}
    698 
    699 	count = 0;
    700 	drm_for_each_connector(connector, dev) {
    701 		*connector = save_connectors[count++];
    702 	}
    703 
    704 	/* Try to restore the config */
    705 	if (mode_changed &&
    706 	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
    707 				      save_set.y, save_set.fb))
    708 		DRM_ERROR("failed to restore config after modeset failure\n");
    709 
    710 	kfree(save_connectors);
    711 	kfree(save_encoders);
    712 	return ret;
    713 }
    714 EXPORT_SYMBOL(drm_crtc_helper_set_config);
    715 
    716 static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
    717 {
    718 	int dpms = DRM_MODE_DPMS_OFF;
    719 	struct drm_connector *connector;
    720 	struct drm_device *dev = encoder->dev;
    721 
    722 	drm_for_each_connector(connector, dev)
    723 		if (connector->encoder == encoder)
    724 			if (connector->dpms < dpms)
    725 				dpms = connector->dpms;
    726 	return dpms;
    727 }
    728 
    729 /* Helper which handles bridge ordering around encoder dpms */
    730 static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
    731 {
    732 	struct drm_bridge *bridge = encoder->bridge;
    733 	const struct drm_encoder_helper_funcs *encoder_funcs;
    734 
    735 	if (mode == DRM_MODE_DPMS_ON)
    736 		drm_bridge_pre_enable(bridge);
    737 	else
    738 		drm_bridge_disable(bridge);
    739 
    740 	encoder_funcs = encoder->helper_private;
    741 	if (encoder_funcs->dpms)
    742 		encoder_funcs->dpms(encoder, mode);
    743 
    744 	if (mode == DRM_MODE_DPMS_ON)
    745 		drm_bridge_enable(bridge);
    746 	else
    747 		drm_bridge_post_disable(bridge);
    748 }
    749 
    750 static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
    751 {
    752 	int dpms = DRM_MODE_DPMS_OFF;
    753 	struct drm_connector *connector;
    754 	struct drm_device *dev = crtc->dev;
    755 
    756 	drm_for_each_connector(connector, dev)
    757 		if (connector->encoder && connector->encoder->crtc == crtc)
    758 			if (connector->dpms < dpms)
    759 				dpms = connector->dpms;
    760 	return dpms;
    761 }
    762 
    763 /**
    764  * drm_helper_connector_dpms() - connector dpms helper implementation
    765  * @connector: affected connector
    766  * @mode: DPMS mode
    767  *
    768  * This is the main helper function provided by the crtc helper framework for
    769  * implementing the DPMS connector attribute. It computes the new desired DPMS
    770  * state for all encoders and crtcs in the output mesh and calls the ->dpms()
    771  * callback provided by the driver appropriately.
    772  *
    773  * Returns:
    774  * Always returns 0.
    775  */
    776 int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
    777 {
    778 	struct drm_encoder *encoder = connector->encoder;
    779 	struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
    780 	int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
    781 
    782 	if (mode == connector->dpms)
    783 		return 0;
    784 
    785 	old_dpms = connector->dpms;
    786 	connector->dpms = mode;
    787 
    788 	if (encoder)
    789 		encoder_dpms = drm_helper_choose_encoder_dpms(encoder);
    790 
    791 	/* from off to on, do crtc then encoder */
    792 	if (mode < old_dpms) {
    793 		if (crtc) {
    794 			const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
    795 			if (crtc_funcs->dpms)
    796 				(*crtc_funcs->dpms) (crtc,
    797 						     drm_helper_choose_crtc_dpms(crtc));
    798 		}
    799 		if (encoder)
    800 			drm_helper_encoder_dpms(encoder, encoder_dpms);
    801 	}
    802 
    803 	/* from on to off, do encoder then crtc */
    804 	if (mode > old_dpms) {
    805 		if (encoder)
    806 			drm_helper_encoder_dpms(encoder, encoder_dpms);
    807 		if (crtc) {
    808 			const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
    809 			if (crtc_funcs->dpms)
    810 				(*crtc_funcs->dpms) (crtc,
    811 						     drm_helper_choose_crtc_dpms(crtc));
    812 		}
    813 	}
    814 
    815 	return 0;
    816 }
    817 EXPORT_SYMBOL(drm_helper_connector_dpms);
    818 
    819 /**
    820  * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
    821  * @fb: drm_framebuffer object to fill out
    822  * @mode_cmd: metadata from the userspace fb creation request
    823  *
    824  * This helper can be used in a drivers fb_create callback to pre-fill the fb's
    825  * metadata fields.
    826  */
    827 void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
    828 				    struct drm_mode_fb_cmd2 *mode_cmd)
    829 {
    830 	int i;
    831 
    832 	fb->width = mode_cmd->width;
    833 	fb->height = mode_cmd->height;
    834 	for (i = 0; i < 4; i++) {
    835 		fb->pitches[i] = mode_cmd->pitches[i];
    836 		fb->offsets[i] = mode_cmd->offsets[i];
    837 		fb->modifier[i] = mode_cmd->modifier[i];
    838 	}
    839 	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
    840 				    &fb->bits_per_pixel);
    841 	fb->pixel_format = mode_cmd->pixel_format;
    842 	fb->flags = mode_cmd->flags;
    843 }
    844 EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
    845 
    846 /**
    847  * drm_helper_resume_force_mode - force-restore mode setting configuration
    848  * @dev: drm_device which should be restored
    849  *
    850  * Drivers which use the mode setting helpers can use this function to
    851  * force-restore the mode setting configuration e.g. on resume or when something
    852  * else might have trampled over the hw state (like some overzealous old BIOSen
    853  * tended to do).
    854  *
    855  * This helper doesn't provide a error return value since restoring the old
    856  * config should never fail due to resource allocation issues since the driver
    857  * has successfully set the restored configuration already. Hence this should
    858  * boil down to the equivalent of a few dpms on calls, which also don't provide
    859  * an error code.
    860  *
    861  * Drivers where simply restoring an old configuration again might fail (e.g.
    862  * due to slight differences in allocating shared resources when the
    863  * configuration is restored in a different order than when userspace set it up)
    864  * need to use their own restore logic.
    865  */
    866 void drm_helper_resume_force_mode(struct drm_device *dev)
    867 {
    868 	struct drm_crtc *crtc;
    869 	struct drm_encoder *encoder;
    870 	const struct drm_crtc_helper_funcs *crtc_funcs;
    871 	int encoder_dpms;
    872 	bool ret;
    873 
    874 	drm_modeset_lock_all(dev);
    875 	drm_for_each_crtc(crtc, dev) {
    876 
    877 		if (!crtc->enabled)
    878 			continue;
    879 
    880 		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
    881 					       crtc->x, crtc->y, crtc->primary->fb);
    882 
    883 		/* Restoring the old config should never fail! */
    884 		if (ret == false)
    885 			DRM_ERROR("failed to set mode on crtc %p\n", crtc);
    886 
    887 		/* Turn off outputs that were already powered off */
    888 		if (drm_helper_choose_crtc_dpms(crtc)) {
    889 			drm_for_each_encoder(encoder, dev) {
    890 
    891 				if(encoder->crtc != crtc)
    892 					continue;
    893 
    894 				encoder_dpms = drm_helper_choose_encoder_dpms(
    895 							encoder);
    896 
    897 				drm_helper_encoder_dpms(encoder, encoder_dpms);
    898 			}
    899 
    900 			crtc_funcs = crtc->helper_private;
    901 			if (crtc_funcs->dpms)
    902 				(*crtc_funcs->dpms) (crtc,
    903 						     drm_helper_choose_crtc_dpms(crtc));
    904 		}
    905 	}
    906 
    907 	/* disable the unused connectors while restoring the modesetting */
    908 	__drm_helper_disable_unused_functions(dev);
    909 	drm_modeset_unlock_all(dev);
    910 }
    911 EXPORT_SYMBOL(drm_helper_resume_force_mode);
    912 
    913 /**
    914  * drm_helper_crtc_mode_set - mode_set implementation for atomic plane helpers
    915  * @crtc: DRM CRTC
    916  * @mode: DRM display mode which userspace requested
    917  * @adjusted_mode: DRM display mode adjusted by ->mode_fixup callbacks
    918  * @x: x offset of the CRTC scanout area on the underlying framebuffer
    919  * @y: y offset of the CRTC scanout area on the underlying framebuffer
    920  * @old_fb: previous framebuffer
    921  *
    922  * This function implements a callback useable as the ->mode_set callback
    923  * required by the crtc helpers. Besides the atomic plane helper functions for
    924  * the primary plane the driver must also provide the ->mode_set_nofb callback
    925  * to set up the crtc.
    926  *
    927  * This is a transitional helper useful for converting drivers to the atomic
    928  * interfaces.
    929  */
    930 int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
    931 			     struct drm_display_mode *adjusted_mode, int x, int y,
    932 			     struct drm_framebuffer *old_fb)
    933 {
    934 	struct drm_crtc_state *crtc_state;
    935 	const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
    936 	int ret;
    937 
    938 	if (crtc->funcs->atomic_duplicate_state)
    939 		crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
    940 	else {
    941 		if (!crtc->state)
    942 			drm_atomic_helper_crtc_reset(crtc);
    943 
    944 		crtc_state = drm_atomic_helper_crtc_duplicate_state(crtc);
    945 	}
    946 
    947 	if (!crtc_state)
    948 		return -ENOMEM;
    949 
    950 	crtc_state->planes_changed = true;
    951 	crtc_state->mode_changed = true;
    952 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
    953 	if (ret)
    954 		goto out;
    955 	drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode);
    956 
    957 	if (crtc_funcs->atomic_check) {
    958 		ret = crtc_funcs->atomic_check(crtc, crtc_state);
    959 		if (ret)
    960 			goto out;
    961 	}
    962 
    963 	swap(crtc->state, crtc_state);
    964 
    965 	crtc_funcs->mode_set_nofb(crtc);
    966 
    967 	ret = drm_helper_crtc_mode_set_base(crtc, x, y, old_fb);
    968 
    969 out:
    970 	if (crtc_state) {
    971 		if (crtc->funcs->atomic_destroy_state)
    972 			crtc->funcs->atomic_destroy_state(crtc, crtc_state);
    973 		else
    974 			drm_atomic_helper_crtc_destroy_state(crtc, crtc_state);
    975 	}
    976 
    977 	return ret;
    978 }
    979 EXPORT_SYMBOL(drm_helper_crtc_mode_set);
    980 
    981 /**
    982  * drm_helper_crtc_mode_set_base - mode_set_base implementation for atomic plane helpers
    983  * @crtc: DRM CRTC
    984  * @x: x offset of the CRTC scanout area on the underlying framebuffer
    985  * @y: y offset of the CRTC scanout area on the underlying framebuffer
    986  * @old_fb: previous framebuffer
    987  *
    988  * This function implements a callback useable as the ->mode_set_base used
    989  * required by the crtc helpers. The driver must provide the atomic plane helper
    990  * functions for the primary plane.
    991  *
    992  * This is a transitional helper useful for converting drivers to the atomic
    993  * interfaces.
    994  */
    995 int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
    996 				  struct drm_framebuffer *old_fb)
    997 {
    998 	struct drm_plane_state *plane_state;
    999 	struct drm_plane *plane = crtc->primary;
   1000 
   1001 	if (plane->funcs->atomic_duplicate_state)
   1002 		plane_state = plane->funcs->atomic_duplicate_state(plane);
   1003 	else if (plane->state)
   1004 		plane_state = drm_atomic_helper_plane_duplicate_state(plane);
   1005 	else
   1006 		plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
   1007 	if (!plane_state)
   1008 		return -ENOMEM;
   1009 	plane_state->plane = plane;
   1010 
   1011 	plane_state->crtc = crtc;
   1012 	drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb);
   1013 	plane_state->crtc_x = 0;
   1014 	plane_state->crtc_y = 0;
   1015 	plane_state->crtc_h = crtc->mode.vdisplay;
   1016 	plane_state->crtc_w = crtc->mode.hdisplay;
   1017 	plane_state->src_x = x << 16;
   1018 	plane_state->src_y = y << 16;
   1019 	plane_state->src_h = crtc->mode.vdisplay << 16;
   1020 	plane_state->src_w = crtc->mode.hdisplay << 16;
   1021 
   1022 	return drm_plane_helper_commit(plane, plane_state, old_fb);
   1023 }
   1024 EXPORT_SYMBOL(drm_helper_crtc_mode_set_base);
   1025