Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2006-2008 Intel Corporation
0003  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
0004  *
0005  * DRM core CRTC related functions
0006  *
0007  * Permission to use, copy, modify, distribute, and sell this software and its
0008  * documentation for any purpose is hereby granted without fee, provided that
0009  * the above copyright notice appear in all copies and that both that copyright
0010  * notice and this permission notice appear in supporting documentation, and
0011  * that the name of the copyright holders not be used in advertising or
0012  * publicity pertaining to distribution of the software without specific,
0013  * written prior permission.  The copyright holders make no representations
0014  * about the suitability of this software for any purpose.  It is provided "as
0015  * is" without express or implied warranty.
0016  *
0017  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0018  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
0019  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0020  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
0021  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
0022  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
0023  * OF THIS SOFTWARE.
0024  *
0025  * Authors:
0026  *      Keith Packard
0027  *  Eric Anholt <eric@anholt.net>
0028  *      Dave Airlie <airlied@linux.ie>
0029  *      Jesse Barnes <jesse.barnes@intel.com>
0030  */
0031 
0032 #include <linux/export.h>
0033 #include <linux/kernel.h>
0034 #include <linux/moduleparam.h>
0035 
0036 #include <drm/drm_atomic.h>
0037 #include <drm/drm_atomic_helper.h>
0038 #include <drm/drm_atomic_uapi.h>
0039 #include <drm/drm_bridge.h>
0040 #include <drm/drm_crtc.h>
0041 #include <drm/drm_crtc_helper.h>
0042 #include <drm/drm_drv.h>
0043 #include <drm/drm_edid.h>
0044 #include <drm/drm_encoder.h>
0045 #include <drm/drm_fb_helper.h>
0046 #include <drm/drm_fourcc.h>
0047 #include <drm/drm_framebuffer.h>
0048 #include <drm/drm_plane_helper.h>
0049 #include <drm/drm_print.h>
0050 #include <drm/drm_vblank.h>
0051 
0052 #include "drm_crtc_helper_internal.h"
0053 
0054 /**
0055  * DOC: overview
0056  *
0057  * The CRTC modeset helper library provides a default set_config implementation
0058  * in drm_crtc_helper_set_config(). Plus a few other convenience functions using
0059  * the same callbacks which drivers can use to e.g. restore the modeset
0060  * configuration on resume with drm_helper_resume_force_mode().
0061  *
0062  * Note that this helper library doesn't track the current power state of CRTCs
0063  * and encoders. It can call callbacks like &drm_encoder_helper_funcs.dpms even
0064  * though the hardware is already in the desired state. This deficiency has been
0065  * fixed in the atomic helpers.
0066  *
0067  * The driver callbacks are mostly compatible with the atomic modeset helpers,
0068  * except for the handling of the primary plane: Atomic helpers require that the
0069  * primary plane is implemented as a real standalone plane and not directly tied
0070  * to the CRTC state. For easier transition this library provides functions to
0071  * implement the old semantics required by the CRTC helpers using the new plane
0072  * and atomic helper callbacks.
0073  *
0074  * Drivers are strongly urged to convert to the atomic helpers (by way of first
0075  * converting to the plane helpers). New drivers must not use these functions
0076  * but need to implement the atomic interface instead, potentially using the
0077  * atomic helpers for that.
0078  *
0079  * These legacy modeset helpers use the same function table structures as
0080  * all other modesetting helpers. See the documentation for struct
0081  * &drm_crtc_helper_funcs, &struct drm_encoder_helper_funcs and struct
0082  * &drm_connector_helper_funcs.
0083  */
0084 
0085 /**
0086  * drm_helper_encoder_in_use - check if a given encoder is in use
0087  * @encoder: encoder to check
0088  *
0089  * Checks whether @encoder is with the current mode setting output configuration
0090  * in use by any connector. This doesn't mean that it is actually enabled since
0091  * the DPMS state is tracked separately.
0092  *
0093  * Returns:
0094  * True if @encoder is used, false otherwise.
0095  */
0096 bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
0097 {
0098     struct drm_connector *connector;
0099     struct drm_connector_list_iter conn_iter;
0100     struct drm_device *dev = encoder->dev;
0101 
0102     WARN_ON(drm_drv_uses_atomic_modeset(dev));
0103 
0104     /*
0105      * We can expect this mutex to be locked if we are not panicking.
0106      * Locking is currently fubar in the panic handler.
0107      */
0108     if (!oops_in_progress) {
0109         WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
0110         WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
0111     }
0112 
0113 
0114     drm_connector_list_iter_begin(dev, &conn_iter);
0115     drm_for_each_connector_iter(connector, &conn_iter) {
0116         if (connector->encoder == encoder) {
0117             drm_connector_list_iter_end(&conn_iter);
0118             return true;
0119         }
0120     }
0121     drm_connector_list_iter_end(&conn_iter);
0122     return false;
0123 }
0124 EXPORT_SYMBOL(drm_helper_encoder_in_use);
0125 
0126 /**
0127  * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
0128  * @crtc: CRTC to check
0129  *
0130  * Checks whether @crtc is with the current mode setting output configuration
0131  * in use by any connector. This doesn't mean that it is actually enabled since
0132  * the DPMS state is tracked separately.
0133  *
0134  * Returns:
0135  * True if @crtc is used, false otherwise.
0136  */
0137 bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
0138 {
0139     struct drm_encoder *encoder;
0140     struct drm_device *dev = crtc->dev;
0141 
0142     WARN_ON(drm_drv_uses_atomic_modeset(dev));
0143 
0144     /*
0145      * We can expect this mutex to be locked if we are not panicking.
0146      * Locking is currently fubar in the panic handler.
0147      */
0148     if (!oops_in_progress)
0149         WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
0150 
0151     drm_for_each_encoder(encoder, dev)
0152         if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
0153             return true;
0154     return false;
0155 }
0156 EXPORT_SYMBOL(drm_helper_crtc_in_use);
0157 
0158 static void
0159 drm_encoder_disable(struct drm_encoder *encoder)
0160 {
0161     const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
0162 
0163     if (!encoder_funcs)
0164         return;
0165 
0166     if (encoder_funcs->disable)
0167         (*encoder_funcs->disable)(encoder);
0168     else if (encoder_funcs->dpms)
0169         (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
0170 }
0171 
0172 static void __drm_helper_disable_unused_functions(struct drm_device *dev)
0173 {
0174     struct drm_encoder *encoder;
0175     struct drm_crtc *crtc;
0176 
0177     drm_warn_on_modeset_not_all_locked(dev);
0178 
0179     drm_for_each_encoder(encoder, dev) {
0180         if (!drm_helper_encoder_in_use(encoder)) {
0181             drm_encoder_disable(encoder);
0182             /* disconnect encoder from any connector */
0183             encoder->crtc = NULL;
0184         }
0185     }
0186 
0187     drm_for_each_crtc(crtc, dev) {
0188         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0189 
0190         crtc->enabled = drm_helper_crtc_in_use(crtc);
0191         if (!crtc->enabled) {
0192             if (crtc_funcs->disable)
0193                 (*crtc_funcs->disable)(crtc);
0194             else
0195                 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
0196             crtc->primary->fb = NULL;
0197         }
0198     }
0199 }
0200 
0201 /**
0202  * drm_helper_disable_unused_functions - disable unused objects
0203  * @dev: DRM device
0204  *
0205  * This function walks through the entire mode setting configuration of @dev. It
0206  * will remove any CRTC links of unused encoders and encoder links of
0207  * disconnected connectors. Then it will disable all unused encoders and CRTCs
0208  * either by calling their disable callback if available or by calling their
0209  * dpms callback with DRM_MODE_DPMS_OFF.
0210  *
0211  * NOTE:
0212  *
0213  * This function is part of the legacy modeset helper library and will cause
0214  * major confusion with atomic drivers. This is because atomic helpers guarantee
0215  * to never call ->disable() hooks on a disabled function, or ->enable() hooks
0216  * on an enabled functions. drm_helper_disable_unused_functions() on the other
0217  * hand throws such guarantees into the wind and calls disable hooks
0218  * unconditionally on unused functions.
0219  */
0220 void drm_helper_disable_unused_functions(struct drm_device *dev)
0221 {
0222     WARN_ON(drm_drv_uses_atomic_modeset(dev));
0223 
0224     drm_modeset_lock_all(dev);
0225     __drm_helper_disable_unused_functions(dev);
0226     drm_modeset_unlock_all(dev);
0227 }
0228 EXPORT_SYMBOL(drm_helper_disable_unused_functions);
0229 
0230 /*
0231  * Check the CRTC we're going to map each output to vs. its current
0232  * CRTC.  If they don't match, we have to disable the output and the CRTC
0233  * since the driver will have to re-route things.
0234  */
0235 static void
0236 drm_crtc_prepare_encoders(struct drm_device *dev)
0237 {
0238     const struct drm_encoder_helper_funcs *encoder_funcs;
0239     struct drm_encoder *encoder;
0240 
0241     drm_for_each_encoder(encoder, dev) {
0242         encoder_funcs = encoder->helper_private;
0243         if (!encoder_funcs)
0244             continue;
0245 
0246         /* Disable unused encoders */
0247         if (encoder->crtc == NULL)
0248             drm_encoder_disable(encoder);
0249     }
0250 }
0251 
0252 /**
0253  * drm_crtc_helper_set_mode - internal helper to set a mode
0254  * @crtc: CRTC to program
0255  * @mode: mode to use
0256  * @x: horizontal offset into the surface
0257  * @y: vertical offset into the surface
0258  * @old_fb: old framebuffer, for cleanup
0259  *
0260  * Try to set @mode on @crtc.  Give @crtc and its associated connectors a chance
0261  * to fixup or reject the mode prior to trying to set it. This is an internal
0262  * helper that drivers could e.g. use to update properties that require the
0263  * entire output pipe to be disabled and re-enabled in a new configuration. For
0264  * example for changing whether audio is enabled on a hdmi link or for changing
0265  * panel fitter or dither attributes. It is also called by the
0266  * drm_crtc_helper_set_config() helper function to drive the mode setting
0267  * sequence.
0268  *
0269  * Returns:
0270  * True if the mode was set successfully, false otherwise.
0271  */
0272 bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
0273                   struct drm_display_mode *mode,
0274                   int x, int y,
0275                   struct drm_framebuffer *old_fb)
0276 {
0277     struct drm_device *dev = crtc->dev;
0278     struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
0279     const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0280     const struct drm_encoder_helper_funcs *encoder_funcs;
0281     int saved_x, saved_y;
0282     bool saved_enabled;
0283     struct drm_encoder *encoder;
0284     bool ret = true;
0285 
0286     WARN_ON(drm_drv_uses_atomic_modeset(dev));
0287 
0288     drm_warn_on_modeset_not_all_locked(dev);
0289 
0290     saved_enabled = crtc->enabled;
0291     crtc->enabled = drm_helper_crtc_in_use(crtc);
0292     if (!crtc->enabled)
0293         return true;
0294 
0295     adjusted_mode = drm_mode_duplicate(dev, mode);
0296     if (!adjusted_mode) {
0297         crtc->enabled = saved_enabled;
0298         return false;
0299     }
0300 
0301     drm_mode_init(&saved_mode, &crtc->mode);
0302     drm_mode_init(&saved_hwmode, &crtc->hwmode);
0303     saved_x = crtc->x;
0304     saved_y = crtc->y;
0305 
0306     /* Update crtc values up front so the driver can rely on them for mode
0307      * setting.
0308      */
0309     drm_mode_copy(&crtc->mode, mode);
0310     crtc->x = x;
0311     crtc->y = y;
0312 
0313     /* Pass our mode to the connectors and the CRTC to give them a chance to
0314      * adjust it according to limitations or connector properties, and also
0315      * a chance to reject the mode entirely.
0316      */
0317     drm_for_each_encoder(encoder, dev) {
0318 
0319         if (encoder->crtc != crtc)
0320             continue;
0321 
0322         encoder_funcs = encoder->helper_private;
0323         if (!encoder_funcs)
0324             continue;
0325 
0326         encoder_funcs = encoder->helper_private;
0327         if (encoder_funcs->mode_fixup) {
0328             if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
0329                                   adjusted_mode))) {
0330                 DRM_DEBUG_KMS("Encoder fixup failed\n");
0331                 goto done;
0332             }
0333         }
0334     }
0335 
0336     if (crtc_funcs->mode_fixup) {
0337         if (!(ret = crtc_funcs->mode_fixup(crtc, mode,
0338                         adjusted_mode))) {
0339             DRM_DEBUG_KMS("CRTC fixup failed\n");
0340             goto done;
0341         }
0342     }
0343     DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
0344 
0345     drm_mode_copy(&crtc->hwmode, adjusted_mode);
0346 
0347     /* Prepare the encoders and CRTCs before setting the mode. */
0348     drm_for_each_encoder(encoder, dev) {
0349 
0350         if (encoder->crtc != crtc)
0351             continue;
0352 
0353         encoder_funcs = encoder->helper_private;
0354         if (!encoder_funcs)
0355             continue;
0356 
0357         /* Disable the encoders as the first thing we do. */
0358         if (encoder_funcs->prepare)
0359             encoder_funcs->prepare(encoder);
0360     }
0361 
0362     drm_crtc_prepare_encoders(dev);
0363 
0364     crtc_funcs->prepare(crtc);
0365 
0366     /* Set up the DPLL and any encoders state that needs to adjust or depend
0367      * on the DPLL.
0368      */
0369     ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
0370     if (!ret)
0371         goto done;
0372 
0373     drm_for_each_encoder(encoder, dev) {
0374 
0375         if (encoder->crtc != crtc)
0376             continue;
0377 
0378         encoder_funcs = encoder->helper_private;
0379         if (!encoder_funcs)
0380             continue;
0381 
0382         DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%s]\n",
0383             encoder->base.id, encoder->name, mode->name);
0384         if (encoder_funcs->mode_set)
0385             encoder_funcs->mode_set(encoder, mode, adjusted_mode);
0386     }
0387 
0388     /* Now enable the clocks, plane, pipe, and connectors that we set up. */
0389     crtc_funcs->commit(crtc);
0390 
0391     drm_for_each_encoder(encoder, dev) {
0392 
0393         if (encoder->crtc != crtc)
0394             continue;
0395 
0396         encoder_funcs = encoder->helper_private;
0397         if (!encoder_funcs)
0398             continue;
0399 
0400         if (encoder_funcs->commit)
0401             encoder_funcs->commit(encoder);
0402     }
0403 
0404     /* Calculate and store various constants which
0405      * are later needed by vblank and swap-completion
0406      * timestamping. They are derived from true hwmode.
0407      */
0408     drm_calc_timestamping_constants(crtc, &crtc->hwmode);
0409 
0410     /* FIXME: add subpixel order */
0411 done:
0412     drm_mode_destroy(dev, adjusted_mode);
0413     if (!ret) {
0414         crtc->enabled = saved_enabled;
0415         drm_mode_copy(&crtc->mode, &saved_mode);
0416         drm_mode_copy(&crtc->hwmode, &saved_hwmode);
0417         crtc->x = saved_x;
0418         crtc->y = saved_y;
0419     }
0420 
0421     return ret;
0422 }
0423 EXPORT_SYMBOL(drm_crtc_helper_set_mode);
0424 
0425 static void
0426 drm_crtc_helper_disable(struct drm_crtc *crtc)
0427 {
0428     struct drm_device *dev = crtc->dev;
0429     struct drm_connector *connector;
0430     struct drm_encoder *encoder;
0431 
0432     /* Decouple all encoders and their attached connectors from this crtc */
0433     drm_for_each_encoder(encoder, dev) {
0434         struct drm_connector_list_iter conn_iter;
0435 
0436         if (encoder->crtc != crtc)
0437             continue;
0438 
0439         drm_connector_list_iter_begin(dev, &conn_iter);
0440         drm_for_each_connector_iter(connector, &conn_iter) {
0441             if (connector->encoder != encoder)
0442                 continue;
0443 
0444             connector->encoder = NULL;
0445 
0446             /*
0447              * drm_helper_disable_unused_functions() ought to be
0448              * doing this, but since we've decoupled the encoder
0449              * from the connector above, the required connection
0450              * between them is henceforth no longer available.
0451              */
0452             connector->dpms = DRM_MODE_DPMS_OFF;
0453 
0454             /* we keep a reference while the encoder is bound */
0455             drm_connector_put(connector);
0456         }
0457         drm_connector_list_iter_end(&conn_iter);
0458     }
0459 
0460     __drm_helper_disable_unused_functions(dev);
0461 }
0462 
0463 /*
0464  * For connectors that support multiple encoders, either the
0465  * .atomic_best_encoder() or .best_encoder() operation must be implemented.
0466  */
0467 struct drm_encoder *
0468 drm_connector_get_single_encoder(struct drm_connector *connector)
0469 {
0470     struct drm_encoder *encoder;
0471 
0472     WARN_ON(hweight32(connector->possible_encoders) > 1);
0473     drm_connector_for_each_possible_encoder(connector, encoder)
0474         return encoder;
0475 
0476     return NULL;
0477 }
0478 
0479 /**
0480  * drm_crtc_helper_set_config - set a new config from userspace
0481  * @set: mode set configuration
0482  * @ctx: lock acquire context, not used here
0483  *
0484  * The drm_crtc_helper_set_config() helper function implements the of
0485  * &drm_crtc_funcs.set_config callback for drivers using the legacy CRTC
0486  * helpers.
0487  *
0488  * It first tries to locate the best encoder for each connector by calling the
0489  * connector @drm_connector_helper_funcs.best_encoder helper operation.
0490  *
0491  * After locating the appropriate encoders, the helper function will call the
0492  * mode_fixup encoder and CRTC helper operations to adjust the requested mode,
0493  * or reject it completely in which case an error will be returned to the
0494  * application. If the new configuration after mode adjustment is identical to
0495  * the current configuration the helper function will return without performing
0496  * any other operation.
0497  *
0498  * If the adjusted mode is identical to the current mode but changes to the
0499  * frame buffer need to be applied, the drm_crtc_helper_set_config() function
0500  * will call the CRTC &drm_crtc_helper_funcs.mode_set_base helper operation.
0501  *
0502  * If the adjusted mode differs from the current mode, or if the
0503  * ->mode_set_base() helper operation is not provided, the helper function
0504  * performs a full mode set sequence by calling the ->prepare(), ->mode_set()
0505  * and ->commit() CRTC and encoder helper operations, in that order.
0506  * Alternatively it can also use the dpms and disable helper operations. For
0507  * details see &struct drm_crtc_helper_funcs and struct
0508  * &drm_encoder_helper_funcs.
0509  *
0510  * This function is deprecated.  New drivers must implement atomic modeset
0511  * support, for which this function is unsuitable. Instead drivers should use
0512  * drm_atomic_helper_set_config().
0513  *
0514  * Returns:
0515  * Returns 0 on success, negative errno numbers on failure.
0516  */
0517 int drm_crtc_helper_set_config(struct drm_mode_set *set,
0518                    struct drm_modeset_acquire_ctx *ctx)
0519 {
0520     struct drm_device *dev;
0521     struct drm_crtc **save_encoder_crtcs, *new_crtc;
0522     struct drm_encoder **save_connector_encoders, *new_encoder, *encoder;
0523     bool mode_changed = false; /* if true do a full mode set */
0524     bool fb_changed = false; /* if true and !mode_changed just do a flip */
0525     struct drm_connector *connector;
0526     struct drm_connector_list_iter conn_iter;
0527     int count = 0, ro, fail = 0;
0528     const struct drm_crtc_helper_funcs *crtc_funcs;
0529     struct drm_mode_set save_set;
0530     int ret;
0531     int i;
0532 
0533     DRM_DEBUG_KMS("\n");
0534 
0535     BUG_ON(!set);
0536     BUG_ON(!set->crtc);
0537     BUG_ON(!set->crtc->helper_private);
0538 
0539     /* Enforce sane interface api - has been abused by the fb helper. */
0540     BUG_ON(!set->mode && set->fb);
0541     BUG_ON(set->fb && set->num_connectors == 0);
0542 
0543     crtc_funcs = set->crtc->helper_private;
0544 
0545     dev = set->crtc->dev;
0546     WARN_ON(drm_drv_uses_atomic_modeset(dev));
0547 
0548     if (!set->mode)
0549         set->fb = NULL;
0550 
0551     if (set->fb) {
0552         DRM_DEBUG_KMS("[CRTC:%d:%s] [FB:%d] #connectors=%d (x y) (%i %i)\n",
0553                   set->crtc->base.id, set->crtc->name,
0554                   set->fb->base.id,
0555                   (int)set->num_connectors, set->x, set->y);
0556     } else {
0557         DRM_DEBUG_KMS("[CRTC:%d:%s] [NOFB]\n",
0558                   set->crtc->base.id, set->crtc->name);
0559         drm_crtc_helper_disable(set->crtc);
0560         return 0;
0561     }
0562 
0563     drm_warn_on_modeset_not_all_locked(dev);
0564 
0565     /*
0566      * Allocate space for the backup of all (non-pointer) encoder and
0567      * connector data.
0568      */
0569     save_encoder_crtcs = kcalloc(dev->mode_config.num_encoder,
0570                 sizeof(struct drm_crtc *), GFP_KERNEL);
0571     if (!save_encoder_crtcs)
0572         return -ENOMEM;
0573 
0574     save_connector_encoders = kcalloc(dev->mode_config.num_connector,
0575                 sizeof(struct drm_encoder *), GFP_KERNEL);
0576     if (!save_connector_encoders) {
0577         kfree(save_encoder_crtcs);
0578         return -ENOMEM;
0579     }
0580 
0581     /*
0582      * Copy data. Note that driver private data is not affected.
0583      * Should anything bad happen only the expected state is
0584      * restored, not the drivers personal bookkeeping.
0585      */
0586     count = 0;
0587     drm_for_each_encoder(encoder, dev) {
0588         save_encoder_crtcs[count++] = encoder->crtc;
0589     }
0590 
0591     count = 0;
0592     drm_connector_list_iter_begin(dev, &conn_iter);
0593     drm_for_each_connector_iter(connector, &conn_iter)
0594         save_connector_encoders[count++] = connector->encoder;
0595     drm_connector_list_iter_end(&conn_iter);
0596 
0597     save_set.crtc = set->crtc;
0598     save_set.mode = &set->crtc->mode;
0599     save_set.x = set->crtc->x;
0600     save_set.y = set->crtc->y;
0601     save_set.fb = set->crtc->primary->fb;
0602 
0603     /* We should be able to check here if the fb has the same properties
0604      * and then just flip_or_move it */
0605     if (set->crtc->primary->fb != set->fb) {
0606         /* If we have no fb then treat it as a full mode set */
0607         if (set->crtc->primary->fb == NULL) {
0608             DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
0609             mode_changed = true;
0610         } else if (set->fb->format != set->crtc->primary->fb->format) {
0611             mode_changed = true;
0612         } else
0613             fb_changed = true;
0614     }
0615 
0616     if (set->x != set->crtc->x || set->y != set->crtc->y)
0617         fb_changed = true;
0618 
0619     if (!drm_mode_equal(set->mode, &set->crtc->mode)) {
0620         DRM_DEBUG_KMS("modes are different, full mode set\n");
0621         drm_mode_debug_printmodeline(&set->crtc->mode);
0622         drm_mode_debug_printmodeline(set->mode);
0623         mode_changed = true;
0624     }
0625 
0626     /* take a reference on all unbound connectors in set, reuse the
0627      * already taken reference for bound connectors
0628      */
0629     for (ro = 0; ro < set->num_connectors; ro++) {
0630         if (set->connectors[ro]->encoder)
0631             continue;
0632         drm_connector_get(set->connectors[ro]);
0633     }
0634 
0635     /* a) traverse passed in connector list and get encoders for them */
0636     count = 0;
0637     drm_connector_list_iter_begin(dev, &conn_iter);
0638     drm_for_each_connector_iter(connector, &conn_iter) {
0639         const struct drm_connector_helper_funcs *connector_funcs =
0640             connector->helper_private;
0641         new_encoder = connector->encoder;
0642         for (ro = 0; ro < set->num_connectors; ro++) {
0643             if (set->connectors[ro] == connector) {
0644                 if (connector_funcs->best_encoder)
0645                     new_encoder = connector_funcs->best_encoder(connector);
0646                 else
0647                     new_encoder = drm_connector_get_single_encoder(connector);
0648 
0649                 /* if we can't get an encoder for a connector
0650                    we are setting now - then fail */
0651                 if (new_encoder == NULL)
0652                     /* don't break so fail path works correct */
0653                     fail = 1;
0654 
0655                 if (connector->dpms != DRM_MODE_DPMS_ON) {
0656                     DRM_DEBUG_KMS("connector dpms not on, full mode switch\n");
0657                     mode_changed = true;
0658                 }
0659 
0660                 break;
0661             }
0662         }
0663 
0664         if (new_encoder != connector->encoder) {
0665             DRM_DEBUG_KMS("encoder changed, full mode switch\n");
0666             mode_changed = true;
0667             /* If the encoder is reused for another connector, then
0668              * the appropriate crtc will be set later.
0669              */
0670             if (connector->encoder)
0671                 connector->encoder->crtc = NULL;
0672             connector->encoder = new_encoder;
0673         }
0674     }
0675     drm_connector_list_iter_end(&conn_iter);
0676 
0677     if (fail) {
0678         ret = -EINVAL;
0679         goto fail;
0680     }
0681 
0682     count = 0;
0683     drm_connector_list_iter_begin(dev, &conn_iter);
0684     drm_for_each_connector_iter(connector, &conn_iter) {
0685         if (!connector->encoder)
0686             continue;
0687 
0688         if (connector->encoder->crtc == set->crtc)
0689             new_crtc = NULL;
0690         else
0691             new_crtc = connector->encoder->crtc;
0692 
0693         for (ro = 0; ro < set->num_connectors; ro++) {
0694             if (set->connectors[ro] == connector)
0695                 new_crtc = set->crtc;
0696         }
0697 
0698         /* Make sure the new CRTC will work with the encoder */
0699         if (new_crtc &&
0700             !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
0701             ret = -EINVAL;
0702             drm_connector_list_iter_end(&conn_iter);
0703             goto fail;
0704         }
0705         if (new_crtc != connector->encoder->crtc) {
0706             DRM_DEBUG_KMS("crtc changed, full mode switch\n");
0707             mode_changed = true;
0708             connector->encoder->crtc = new_crtc;
0709         }
0710         if (new_crtc) {
0711             DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d:%s]\n",
0712                       connector->base.id, connector->name,
0713                       new_crtc->base.id, new_crtc->name);
0714         } else {
0715             DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
0716                       connector->base.id, connector->name);
0717         }
0718     }
0719     drm_connector_list_iter_end(&conn_iter);
0720 
0721     /* mode_set_base is not a required function */
0722     if (fb_changed && !crtc_funcs->mode_set_base)
0723         mode_changed = true;
0724 
0725     if (mode_changed) {
0726         if (drm_helper_crtc_in_use(set->crtc)) {
0727             DRM_DEBUG_KMS("attempting to set mode from"
0728                     " userspace\n");
0729             drm_mode_debug_printmodeline(set->mode);
0730             set->crtc->primary->fb = set->fb;
0731             if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
0732                               set->x, set->y,
0733                               save_set.fb)) {
0734                 DRM_ERROR("failed to set mode on [CRTC:%d:%s]\n",
0735                       set->crtc->base.id, set->crtc->name);
0736                 set->crtc->primary->fb = save_set.fb;
0737                 ret = -EINVAL;
0738                 goto fail;
0739             }
0740             DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
0741             for (i = 0; i < set->num_connectors; i++) {
0742                 DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
0743                           set->connectors[i]->name);
0744                 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
0745             }
0746         }
0747         __drm_helper_disable_unused_functions(dev);
0748     } else if (fb_changed) {
0749         set->crtc->x = set->x;
0750         set->crtc->y = set->y;
0751         set->crtc->primary->fb = set->fb;
0752         ret = crtc_funcs->mode_set_base(set->crtc,
0753                         set->x, set->y, save_set.fb);
0754         if (ret != 0) {
0755             set->crtc->x = save_set.x;
0756             set->crtc->y = save_set.y;
0757             set->crtc->primary->fb = save_set.fb;
0758             goto fail;
0759         }
0760     }
0761 
0762     kfree(save_connector_encoders);
0763     kfree(save_encoder_crtcs);
0764     return 0;
0765 
0766 fail:
0767     /* Restore all previous data. */
0768     count = 0;
0769     drm_for_each_encoder(encoder, dev) {
0770         encoder->crtc = save_encoder_crtcs[count++];
0771     }
0772 
0773     count = 0;
0774     drm_connector_list_iter_begin(dev, &conn_iter);
0775     drm_for_each_connector_iter(connector, &conn_iter)
0776         connector->encoder = save_connector_encoders[count++];
0777     drm_connector_list_iter_end(&conn_iter);
0778 
0779     /* after fail drop reference on all unbound connectors in set, let
0780      * bound connectors keep their reference
0781      */
0782     for (ro = 0; ro < set->num_connectors; ro++) {
0783         if (set->connectors[ro]->encoder)
0784             continue;
0785         drm_connector_put(set->connectors[ro]);
0786     }
0787 
0788     /* Try to restore the config */
0789     if (mode_changed &&
0790         !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
0791                       save_set.y, save_set.fb))
0792         DRM_ERROR("failed to restore config after modeset failure\n");
0793 
0794     kfree(save_connector_encoders);
0795     kfree(save_encoder_crtcs);
0796     return ret;
0797 }
0798 EXPORT_SYMBOL(drm_crtc_helper_set_config);
0799 
0800 static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
0801 {
0802     int dpms = DRM_MODE_DPMS_OFF;
0803     struct drm_connector *connector;
0804     struct drm_connector_list_iter conn_iter;
0805     struct drm_device *dev = encoder->dev;
0806 
0807     drm_connector_list_iter_begin(dev, &conn_iter);
0808     drm_for_each_connector_iter(connector, &conn_iter)
0809         if (connector->encoder == encoder)
0810             if (connector->dpms < dpms)
0811                 dpms = connector->dpms;
0812     drm_connector_list_iter_end(&conn_iter);
0813 
0814     return dpms;
0815 }
0816 
0817 /* Helper which handles bridge ordering around encoder dpms */
0818 static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
0819 {
0820     const struct drm_encoder_helper_funcs *encoder_funcs;
0821 
0822     encoder_funcs = encoder->helper_private;
0823     if (!encoder_funcs)
0824         return;
0825 
0826     if (encoder_funcs->dpms)
0827         encoder_funcs->dpms(encoder, mode);
0828 }
0829 
0830 static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
0831 {
0832     int dpms = DRM_MODE_DPMS_OFF;
0833     struct drm_connector *connector;
0834     struct drm_connector_list_iter conn_iter;
0835     struct drm_device *dev = crtc->dev;
0836 
0837     drm_connector_list_iter_begin(dev, &conn_iter);
0838     drm_for_each_connector_iter(connector, &conn_iter)
0839         if (connector->encoder && connector->encoder->crtc == crtc)
0840             if (connector->dpms < dpms)
0841                 dpms = connector->dpms;
0842     drm_connector_list_iter_end(&conn_iter);
0843 
0844     return dpms;
0845 }
0846 
0847 /**
0848  * drm_helper_connector_dpms() - connector dpms helper implementation
0849  * @connector: affected connector
0850  * @mode: DPMS mode
0851  *
0852  * The drm_helper_connector_dpms() helper function implements the
0853  * &drm_connector_funcs.dpms callback for drivers using the legacy CRTC
0854  * helpers.
0855  *
0856  * This is the main helper function provided by the CRTC helper framework for
0857  * implementing the DPMS connector attribute. It computes the new desired DPMS
0858  * state for all encoders and CRTCs in the output mesh and calls the
0859  * &drm_crtc_helper_funcs.dpms and &drm_encoder_helper_funcs.dpms callbacks
0860  * provided by the driver.
0861  *
0862  * This function is deprecated.  New drivers must implement atomic modeset
0863  * support, where DPMS is handled in the DRM core.
0864  *
0865  * Returns:
0866  * Always returns 0.
0867  */
0868 int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
0869 {
0870     struct drm_encoder *encoder = connector->encoder;
0871     struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
0872     int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
0873 
0874     WARN_ON(drm_drv_uses_atomic_modeset(connector->dev));
0875 
0876     if (mode == connector->dpms)
0877         return 0;
0878 
0879     old_dpms = connector->dpms;
0880     connector->dpms = mode;
0881 
0882     if (encoder)
0883         encoder_dpms = drm_helper_choose_encoder_dpms(encoder);
0884 
0885     /* from off to on, do crtc then encoder */
0886     if (mode < old_dpms) {
0887         if (crtc) {
0888             const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0889 
0890             if (crtc_funcs->dpms)
0891                 (*crtc_funcs->dpms) (crtc,
0892                              drm_helper_choose_crtc_dpms(crtc));
0893         }
0894         if (encoder)
0895             drm_helper_encoder_dpms(encoder, encoder_dpms);
0896     }
0897 
0898     /* from on to off, do encoder then crtc */
0899     if (mode > old_dpms) {
0900         if (encoder)
0901             drm_helper_encoder_dpms(encoder, encoder_dpms);
0902         if (crtc) {
0903             const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
0904 
0905             if (crtc_funcs->dpms)
0906                 (*crtc_funcs->dpms) (crtc,
0907                              drm_helper_choose_crtc_dpms(crtc));
0908         }
0909     }
0910 
0911     return 0;
0912 }
0913 EXPORT_SYMBOL(drm_helper_connector_dpms);
0914 
0915 /**
0916  * drm_helper_resume_force_mode - force-restore mode setting configuration
0917  * @dev: drm_device which should be restored
0918  *
0919  * Drivers which use the mode setting helpers can use this function to
0920  * force-restore the mode setting configuration e.g. on resume or when something
0921  * else might have trampled over the hw state (like some overzealous old BIOSen
0922  * tended to do).
0923  *
0924  * This helper doesn't provide a error return value since restoring the old
0925  * config should never fail due to resource allocation issues since the driver
0926  * has successfully set the restored configuration already. Hence this should
0927  * boil down to the equivalent of a few dpms on calls, which also don't provide
0928  * an error code.
0929  *
0930  * Drivers where simply restoring an old configuration again might fail (e.g.
0931  * due to slight differences in allocating shared resources when the
0932  * configuration is restored in a different order than when userspace set it up)
0933  * need to use their own restore logic.
0934  *
0935  * This function is deprecated. New drivers should implement atomic mode-
0936  * setting and use the atomic suspend/resume helpers.
0937  *
0938  * See also:
0939  * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
0940  */
0941 void drm_helper_resume_force_mode(struct drm_device *dev)
0942 {
0943     struct drm_crtc *crtc;
0944     struct drm_encoder *encoder;
0945     const struct drm_crtc_helper_funcs *crtc_funcs;
0946     int encoder_dpms;
0947     bool ret;
0948 
0949     WARN_ON(drm_drv_uses_atomic_modeset(dev));
0950 
0951     drm_modeset_lock_all(dev);
0952     drm_for_each_crtc(crtc, dev) {
0953 
0954         if (!crtc->enabled)
0955             continue;
0956 
0957         ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
0958                            crtc->x, crtc->y, crtc->primary->fb);
0959 
0960         /* Restoring the old config should never fail! */
0961         if (ret == false)
0962             DRM_ERROR("failed to set mode on crtc %p\n", crtc);
0963 
0964         /* Turn off outputs that were already powered off */
0965         if (drm_helper_choose_crtc_dpms(crtc)) {
0966             drm_for_each_encoder(encoder, dev) {
0967 
0968                 if(encoder->crtc != crtc)
0969                     continue;
0970 
0971                 encoder_dpms = drm_helper_choose_encoder_dpms(
0972                             encoder);
0973 
0974                 drm_helper_encoder_dpms(encoder, encoder_dpms);
0975             }
0976 
0977             crtc_funcs = crtc->helper_private;
0978             if (crtc_funcs->dpms)
0979                 (*crtc_funcs->dpms) (crtc,
0980                              drm_helper_choose_crtc_dpms(crtc));
0981         }
0982     }
0983 
0984     /* disable the unused connectors while restoring the modesetting */
0985     __drm_helper_disable_unused_functions(dev);
0986     drm_modeset_unlock_all(dev);
0987 }
0988 EXPORT_SYMBOL(drm_helper_resume_force_mode);
0989 
0990 /**
0991  * drm_helper_force_disable_all - Forcibly turn off all enabled CRTCs
0992  * @dev: DRM device whose CRTCs to turn off
0993  *
0994  * Drivers may want to call this on unload to ensure that all displays are
0995  * unlit and the GPU is in a consistent, low power state. Takes modeset locks.
0996  *
0997  * Note: This should only be used by non-atomic legacy drivers. For an atomic
0998  * version look at drm_atomic_helper_shutdown().
0999  *
1000  * Returns:
1001  * Zero on success, error code on failure.
1002  */
1003 int drm_helper_force_disable_all(struct drm_device *dev)
1004 {
1005     struct drm_crtc *crtc;
1006     int ret = 0;
1007 
1008     drm_modeset_lock_all(dev);
1009     drm_for_each_crtc(crtc, dev)
1010         if (crtc->enabled) {
1011             struct drm_mode_set set = {
1012                 .crtc = crtc,
1013             };
1014 
1015             ret = drm_mode_set_config_internal(&set);
1016             if (ret)
1017                 goto out;
1018         }
1019 out:
1020     drm_modeset_unlock_all(dev);
1021     return ret;
1022 }
1023 EXPORT_SYMBOL(drm_helper_force_disable_all);