Subversion Repositories Kolibri OS

Rev

Rev 4560 | Rev 5271 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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/kernel.h>
  33. #include <linux/export.h>
  34. #include <linux/moduleparam.h>
  35.  
  36. #include <drm/drmP.h>
  37. #include <drm/drm_crtc.h>
  38. #include <drm/drm_fourcc.h>
  39. #include <drm/drm_crtc_helper.h>
  40. #include <drm/drm_fb_helper.h>
  41. #include <drm/drm_edid.h>
  42.  
  43. MODULE_AUTHOR("David Airlie, Jesse Barnes");
  44. MODULE_DESCRIPTION("DRM KMS helper");
  45. MODULE_LICENSE("GPL and additional rights");
  46.  
  47. /**
  48.  * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
  49.  *                                              connector list
  50.  * @dev: drm device to operate on
  51.  *
  52.  * Some userspace presumes that the first connected connector is the main
  53.  * display, where it's supposed to display e.g. the login screen. For
  54.  * laptops, this should be the main panel. Use this function to sort all
  55.  * (eDP/LVDS) panels to the front of the connector list, instead of
  56.  * painstakingly trying to initialize them in the right order.
  57.  */
  58. void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
  59. {
  60.         struct drm_connector *connector, *tmp;
  61.         struct list_head panel_list;
  62.  
  63.         INIT_LIST_HEAD(&panel_list);
  64.  
  65.         list_for_each_entry_safe(connector, tmp,
  66.                                  &dev->mode_config.connector_list, head) {
  67.                 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
  68.                     connector->connector_type == DRM_MODE_CONNECTOR_eDP)
  69.                         list_move_tail(&connector->head, &panel_list);
  70.         }
  71.  
  72.         list_splice(&panel_list, &dev->mode_config.connector_list);
  73. }
  74. EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
  75.  
  76. /**
  77.  * drm_helper_encoder_in_use - check if a given encoder is in use
  78.  * @encoder: encoder to check
  79.  *
  80.  * Checks whether @encoder is with the current mode setting output configuration
  81.  * in use by any connector. This doesn't mean that it is actually enabled since
  82.  * the DPMS state is tracked separately.
  83.  *
  84.  * Returns:
  85.  * True if @encoder is used, false otherwise.
  86.  */
  87. bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
  88. {
  89.         struct drm_connector *connector;
  90.         struct drm_device *dev = encoder->dev;
  91.         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  92.                 if (connector->encoder == encoder)
  93.                         return true;
  94.         return false;
  95. }
  96. EXPORT_SYMBOL(drm_helper_encoder_in_use);
  97.  
  98. /**
  99.  * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
  100.  * @crtc: CRTC to check
  101.  *
  102.  * Checks whether @crtc is with the current mode setting output configuration
  103.  * in use by any connector. This doesn't mean that it is actually enabled since
  104.  * the DPMS state is tracked separately.
  105.  *
  106.  * Returns:
  107.  * True if @crtc is used, false otherwise.
  108.  */
  109. bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
  110. {
  111.         struct drm_encoder *encoder;
  112.         struct drm_device *dev = crtc->dev;
  113.         /* FIXME: Locking around list access? */
  114.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
  115.                 if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
  116.                         return true;
  117.         return false;
  118. }
  119. EXPORT_SYMBOL(drm_helper_crtc_in_use);
  120.  
  121. static void
  122. drm_encoder_disable(struct drm_encoder *encoder)
  123. {
  124.         struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
  125.  
  126.         if (encoder->bridge)
  127.                 encoder->bridge->funcs->disable(encoder->bridge);
  128.  
  129.         if (encoder_funcs->disable)
  130.                 (*encoder_funcs->disable)(encoder);
  131.         else
  132.                 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
  133.  
  134.         if (encoder->bridge)
  135.                 encoder->bridge->funcs->post_disable(encoder->bridge);
  136. }
  137.  
  138. static void __drm_helper_disable_unused_functions(struct drm_device *dev)
  139. {
  140.         struct drm_encoder *encoder;
  141.         struct drm_crtc *crtc;
  142.  
  143.         drm_warn_on_modeset_not_all_locked(dev);
  144.  
  145.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  146.                 if (!drm_helper_encoder_in_use(encoder)) {
  147.                         drm_encoder_disable(encoder);
  148.                         /* disconnect encoder from any connector */
  149.                         encoder->crtc = NULL;
  150.                 }
  151.         }
  152.  
  153.         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  154.                 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  155.                 crtc->enabled = drm_helper_crtc_in_use(crtc);
  156.                 if (!crtc->enabled) {
  157.                         if (crtc_funcs->disable)
  158.                                 (*crtc_funcs->disable)(crtc);
  159.                         else
  160.                                 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
  161.                         crtc->primary->fb = NULL;
  162.                 }
  163.         }
  164. }
  165.  
  166. /**
  167.  * drm_helper_disable_unused_functions - disable unused objects
  168.  * @dev: DRM device
  169.  *
  170.  * This function walks through the entire mode setting configuration of @dev. It
  171.  * will remove any crtc links of unused encoders and encoder links of
  172.  * disconnected connectors. Then it will disable all unused encoders and crtcs
  173.  * either by calling their disable callback if available or by calling their
  174.  * dpms callback with DRM_MODE_DPMS_OFF.
  175.  */
  176. void drm_helper_disable_unused_functions(struct drm_device *dev)
  177. {
  178.         drm_modeset_lock_all(dev);
  179.         __drm_helper_disable_unused_functions(dev);
  180.         drm_modeset_unlock_all(dev);
  181. }
  182. EXPORT_SYMBOL(drm_helper_disable_unused_functions);
  183.  
  184. /*
  185.  * Check the CRTC we're going to map each output to vs. its current
  186.  * CRTC.  If they don't match, we have to disable the output and the CRTC
  187.  * since the driver will have to re-route things.
  188.  */
  189. static void
  190. drm_crtc_prepare_encoders(struct drm_device *dev)
  191. {
  192.         struct drm_encoder_helper_funcs *encoder_funcs;
  193.         struct drm_encoder *encoder;
  194.  
  195.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  196.                 encoder_funcs = encoder->helper_private;
  197.                 /* Disable unused encoders */
  198.                 if (encoder->crtc == NULL)
  199.                         drm_encoder_disable(encoder);
  200.                 /* Disable encoders whose CRTC is about to change */
  201.                 if (encoder_funcs->get_crtc &&
  202.                     encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
  203.                         drm_encoder_disable(encoder);
  204.         }
  205. }
  206.  
  207. /**
  208.  * drm_crtc_helper_set_mode - internal helper to set a mode
  209.  * @crtc: CRTC to program
  210.  * @mode: mode to use
  211.  * @x: horizontal offset into the surface
  212.  * @y: vertical offset into the surface
  213.  * @old_fb: old framebuffer, for cleanup
  214.  *
  215.  * Try to set @mode on @crtc.  Give @crtc and its associated connectors a chance
  216.  * to fixup or reject the mode prior to trying to set it. This is an internal
  217.  * helper that drivers could e.g. use to update properties that require the
  218.  * entire output pipe to be disabled and re-enabled in a new configuration. For
  219.  * example for changing whether audio is enabled on a hdmi link or for changing
  220.  * panel fitter or dither attributes. It is also called by the
  221.  * drm_crtc_helper_set_config() helper function to drive the mode setting
  222.  * sequence.
  223.  *
  224.  * Returns:
  225.  * True if the mode was set successfully, false otherwise.
  226.  */
  227. bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
  228.                               struct drm_display_mode *mode,
  229.                               int x, int y,
  230.                               struct drm_framebuffer *old_fb)
  231. {
  232.         struct drm_device *dev = crtc->dev;
  233.         struct drm_display_mode *adjusted_mode, saved_mode;
  234.         struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  235.         struct drm_encoder_helper_funcs *encoder_funcs;
  236.         int saved_x, saved_y;
  237.         bool saved_enabled;
  238.         struct drm_encoder *encoder;
  239.         bool ret = true;
  240.  
  241.         drm_warn_on_modeset_not_all_locked(dev);
  242.  
  243.         saved_enabled = crtc->enabled;
  244.         crtc->enabled = drm_helper_crtc_in_use(crtc);
  245.         if (!crtc->enabled)
  246.                 return true;
  247.  
  248.         adjusted_mode = drm_mode_duplicate(dev, mode);
  249.         if (!adjusted_mode) {
  250.                 crtc->enabled = saved_enabled;
  251.                 return false;
  252.         }
  253.  
  254.         saved_mode = crtc->mode;
  255.         saved_x = crtc->x;
  256.         saved_y = crtc->y;
  257.  
  258.         /* Update crtc values up front so the driver can rely on them for mode
  259.          * setting.
  260.          */
  261.         crtc->mode = *mode;
  262.         crtc->x = x;
  263.         crtc->y = y;
  264.  
  265.         /* Pass our mode to the connectors and the CRTC to give them a chance to
  266.          * adjust it according to limitations or connector properties, and also
  267.          * a chance to reject the mode entirely.
  268.          */
  269.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  270.  
  271.                 if (encoder->crtc != crtc)
  272.                         continue;
  273.  
  274.                 if (encoder->bridge && encoder->bridge->funcs->mode_fixup) {
  275.                         ret = encoder->bridge->funcs->mode_fixup(
  276.                                         encoder->bridge, mode, adjusted_mode);
  277.                         if (!ret) {
  278.                                 DRM_DEBUG_KMS("Bridge fixup failed\n");
  279.                                 goto done;
  280.                         }
  281.                 }
  282.  
  283.                 encoder_funcs = encoder->helper_private;
  284.                 if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
  285.                                                       adjusted_mode))) {
  286.                         DRM_DEBUG_KMS("Encoder fixup failed\n");
  287.                         goto done;
  288.                 }
  289.         }
  290.  
  291.         if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
  292.                 DRM_DEBUG_KMS("CRTC fixup failed\n");
  293.                 goto done;
  294.         }
  295.         DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
  296.  
  297.         /* Prepare the encoders and CRTCs before setting the mode. */
  298.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  299.  
  300.                 if (encoder->crtc != crtc)
  301.                         continue;
  302.  
  303.                 if (encoder->bridge)
  304.                         encoder->bridge->funcs->disable(encoder->bridge);
  305.  
  306.                 encoder_funcs = encoder->helper_private;
  307.                 /* Disable the encoders as the first thing we do. */
  308.                 encoder_funcs->prepare(encoder);
  309.  
  310.                 if (encoder->bridge)
  311.                         encoder->bridge->funcs->post_disable(encoder->bridge);
  312.         }
  313.  
  314.         drm_crtc_prepare_encoders(dev);
  315.  
  316.         crtc_funcs->prepare(crtc);
  317.  
  318.         /* Set up the DPLL and any encoders state that needs to adjust or depend
  319.          * on the DPLL.
  320.          */
  321.         ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
  322.         if (!ret)
  323.             goto done;
  324.  
  325.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  326.  
  327.                 if (encoder->crtc != crtc)
  328.                         continue;
  329.  
  330.                 DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
  331.                         encoder->base.id, encoder->name,
  332.                         mode->base.id, mode->name);
  333.                 encoder_funcs = encoder->helper_private;
  334.                 encoder_funcs->mode_set(encoder, mode, adjusted_mode);
  335.  
  336.                 if (encoder->bridge && encoder->bridge->funcs->mode_set)
  337.                         encoder->bridge->funcs->mode_set(encoder->bridge, mode,
  338.                                         adjusted_mode);
  339.         }
  340.  
  341.         /* Now enable the clocks, plane, pipe, and connectors that we set up. */
  342.         crtc_funcs->commit(crtc);
  343.  
  344.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  345.  
  346.                 if (encoder->crtc != crtc)
  347.                         continue;
  348.  
  349.                 if (encoder->bridge)
  350.                         encoder->bridge->funcs->pre_enable(encoder->bridge);
  351.  
  352.                 encoder_funcs = encoder->helper_private;
  353.                 encoder_funcs->commit(encoder);
  354.  
  355.                 if (encoder->bridge)
  356.                         encoder->bridge->funcs->enable(encoder->bridge);
  357.         }
  358.  
  359.         /* Store real post-adjustment hardware mode. */
  360.         crtc->hwmode = *adjusted_mode;
  361.  
  362.         /* Calculate and store various constants which
  363.          * are later needed by vblank and swap-completion
  364.          * timestamping. They are derived from true hwmode.
  365.          */
  366.         drm_calc_timestamping_constants(crtc, &crtc->hwmode);
  367.  
  368.         /* FIXME: add subpixel order */
  369. done:
  370.         drm_mode_destroy(dev, adjusted_mode);
  371.         if (!ret) {
  372.                 crtc->enabled = saved_enabled;
  373.                 crtc->mode = saved_mode;
  374.                 crtc->x = saved_x;
  375.                 crtc->y = saved_y;
  376.         }
  377.  
  378.         return ret;
  379. }
  380. EXPORT_SYMBOL(drm_crtc_helper_set_mode);
  381.  
  382. static void
  383. drm_crtc_helper_disable(struct drm_crtc *crtc)
  384. {
  385.         struct drm_device *dev = crtc->dev;
  386.         struct drm_connector *connector;
  387.         struct drm_encoder *encoder;
  388.  
  389.         /* Decouple all encoders and their attached connectors from this crtc */
  390.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  391.                 if (encoder->crtc != crtc)
  392.                         continue;
  393.  
  394.                 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  395.                         if (connector->encoder != encoder)
  396.                                 continue;
  397.  
  398.                         connector->encoder = NULL;
  399.  
  400.                         /*
  401.                          * drm_helper_disable_unused_functions() ought to be
  402.                          * doing this, but since we've decoupled the encoder
  403.                          * from the connector above, the required connection
  404.                          * between them is henceforth no longer available.
  405.                          */
  406.                         connector->dpms = DRM_MODE_DPMS_OFF;
  407.                 }
  408.         }
  409.  
  410.         __drm_helper_disable_unused_functions(dev);
  411. }
  412.  
  413. /**
  414.  * drm_crtc_helper_set_config - set a new config from userspace
  415.  * @set: mode set configuration
  416.  *
  417.  * Setup a new configuration, provided by the upper layers (either an ioctl call
  418.  * from userspace or internally e.g. from the fbdev support code) in @set, and
  419.  * enable it. This is the main helper functions for drivers that implement
  420.  * kernel mode setting with the crtc helper functions and the assorted
  421.  * ->prepare(), ->modeset() and ->commit() helper callbacks.
  422.  *
  423.  * Returns:
  424.  * Returns 0 on success, negative errno numbers on failure.
  425.  */
  426. int drm_crtc_helper_set_config(struct drm_mode_set *set)
  427. {
  428.         struct drm_device *dev;
  429.         struct drm_crtc *new_crtc;
  430.         struct drm_encoder *save_encoders, *new_encoder, *encoder;
  431.         bool mode_changed = false; /* if true do a full mode set */
  432.         bool fb_changed = false; /* if true and !mode_changed just do a flip */
  433.         struct drm_connector *save_connectors, *connector;
  434.         int count = 0, ro, fail = 0;
  435.         struct drm_crtc_helper_funcs *crtc_funcs;
  436.         struct drm_mode_set save_set;
  437.         int ret;
  438.         int i;
  439.  
  440.         DRM_DEBUG_KMS("\n");
  441.  
  442.         BUG_ON(!set);
  443.         BUG_ON(!set->crtc);
  444.         BUG_ON(!set->crtc->helper_private);
  445.  
  446.         /* Enforce sane interface api - has been abused by the fb helper. */
  447.         BUG_ON(!set->mode && set->fb);
  448.         BUG_ON(set->fb && set->num_connectors == 0);
  449.  
  450.         crtc_funcs = set->crtc->helper_private;
  451.  
  452.         if (!set->mode)
  453.                 set->fb = NULL;
  454.  
  455.         if (set->fb) {
  456.                 DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
  457.                                 set->crtc->base.id, set->fb->base.id,
  458.                   (int)set->num_connectors, set->x, set->y);
  459.         } else {
  460.                 DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
  461.                 drm_crtc_helper_disable(set->crtc);
  462.                 return 0;
  463.         }
  464.  
  465.         dev = set->crtc->dev;
  466.  
  467.         drm_warn_on_modeset_not_all_locked(dev);
  468.  
  469.         /*
  470.          * Allocate space for the backup of all (non-pointer) encoder and
  471.          * connector data.
  472.          */
  473.         save_encoders = kzalloc(dev->mode_config.num_encoder *
  474.                                 sizeof(struct drm_encoder), GFP_KERNEL);
  475.         if (!save_encoders)
  476.                 return -ENOMEM;
  477.  
  478.         save_connectors = kzalloc(dev->mode_config.num_connector *
  479.                                 sizeof(struct drm_connector), GFP_KERNEL);
  480.         if (!save_connectors) {
  481.                 kfree(save_encoders);
  482.                 return -ENOMEM;
  483.         }
  484.  
  485.         /*
  486.          * Copy data. Note that driver private data is not affected.
  487.          * Should anything bad happen only the expected state is
  488.          * restored, not the drivers personal bookkeeping.
  489.          */
  490.         count = 0;
  491.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  492.                 save_encoders[count++] = *encoder;
  493.         }
  494.  
  495.         count = 0;
  496.         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  497.                 save_connectors[count++] = *connector;
  498.         }
  499.  
  500.         save_set.crtc = set->crtc;
  501.         save_set.mode = &set->crtc->mode;
  502.         save_set.x = set->crtc->x;
  503.         save_set.y = set->crtc->y;
  504.         save_set.fb = set->crtc->primary->fb;
  505.  
  506.         /* We should be able to check here if the fb has the same properties
  507.          * and then just flip_or_move it */
  508.         if (set->crtc->primary->fb != set->fb) {
  509.                 /* If we have no fb then treat it as a full mode set */
  510.                 if (set->crtc->primary->fb == NULL) {
  511.                         DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
  512.                         mode_changed = true;
  513.                 } else if (set->fb == NULL) {
  514.                         mode_changed = true;
  515.                 } else if (set->fb->pixel_format !=
  516.                            set->crtc->primary->fb->pixel_format) {
  517.                         mode_changed = true;
  518.                 } else
  519.                         fb_changed = true;
  520.         }
  521.  
  522.         if (set->x != set->crtc->x || set->y != set->crtc->y)
  523.                 fb_changed = true;
  524.  
  525.         if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
  526.                 DRM_DEBUG_KMS("modes are different, full mode set\n");
  527.                 drm_mode_debug_printmodeline(&set->crtc->mode);
  528.                 drm_mode_debug_printmodeline(set->mode);
  529.                 mode_changed = true;
  530.         }
  531.  
  532.         /* a) traverse passed in connector list and get encoders for them */
  533.         count = 0;
  534.         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  535.                 struct drm_connector_helper_funcs *connector_funcs =
  536.                         connector->helper_private;
  537.                 new_encoder = connector->encoder;
  538.                 for (ro = 0; ro < set->num_connectors; ro++) {
  539.                         if (set->connectors[ro] == connector) {
  540.                                 new_encoder = connector_funcs->best_encoder(connector);
  541.                                 /* if we can't get an encoder for a connector
  542.                                    we are setting now - then fail */
  543.                                 if (new_encoder == NULL)
  544.                                         /* don't break so fail path works correct */
  545.                                         fail = 1;
  546.  
  547.                                 if (connector->dpms != DRM_MODE_DPMS_ON) {
  548.                                         DRM_DEBUG_KMS("connector dpms not on, full mode switch\n");
  549.                                         mode_changed = true;
  550.                                 }
  551.  
  552.                                 break;
  553.                         }
  554.                 }
  555.  
  556.                 if (new_encoder != connector->encoder) {
  557.                         DRM_DEBUG_KMS("encoder changed, full mode switch\n");
  558.                         mode_changed = true;
  559.                         /* If the encoder is reused for another connector, then
  560.                          * the appropriate crtc will be set later.
  561.                          */
  562.                         if (connector->encoder)
  563.                                 connector->encoder->crtc = NULL;
  564.                         connector->encoder = new_encoder;
  565.                 }
  566.         }
  567.  
  568.         if (fail) {
  569.                 ret = -EINVAL;
  570.                 goto fail;
  571.         }
  572.  
  573.         count = 0;
  574.         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  575.                 if (!connector->encoder)
  576.                         continue;
  577.  
  578.                 if (connector->encoder->crtc == set->crtc)
  579.                         new_crtc = NULL;
  580.                 else
  581.                         new_crtc = connector->encoder->crtc;
  582.  
  583.                 for (ro = 0; ro < set->num_connectors; ro++) {
  584.                         if (set->connectors[ro] == connector)
  585.                                 new_crtc = set->crtc;
  586.                 }
  587.  
  588.                 /* Make sure the new CRTC will work with the encoder */
  589.                 if (new_crtc &&
  590.                     !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
  591.                         ret = -EINVAL;
  592.                         goto fail;
  593.                 }
  594.                 if (new_crtc != connector->encoder->crtc) {
  595.                         DRM_DEBUG_KMS("crtc changed, full mode switch\n");
  596.                         mode_changed = true;
  597.                         connector->encoder->crtc = new_crtc;
  598.                 }
  599.                 if (new_crtc) {
  600.                         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
  601.                                 connector->base.id, connector->name,
  602.                                 new_crtc->base.id);
  603.                 } else {
  604.                         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
  605.                                 connector->base.id, connector->name);
  606.                 }
  607.         }
  608.  
  609.         /* mode_set_base is not a required function */
  610.         if (fb_changed && !crtc_funcs->mode_set_base)
  611.                 mode_changed = true;
  612.  
  613.         if (mode_changed) {
  614.                 if (drm_helper_crtc_in_use(set->crtc)) {
  615.                         DRM_DEBUG_KMS("attempting to set mode from"
  616.                                         " userspace\n");
  617.                         drm_mode_debug_printmodeline(set->mode);
  618.                         set->crtc->primary->fb = set->fb;
  619.                         if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
  620.                                                       set->x, set->y,
  621.                                                       save_set.fb)) {
  622.                                 DRM_ERROR("failed to set mode on [CRTC:%d]\n",
  623.                                           set->crtc->base.id);
  624.                                 set->crtc->primary->fb = save_set.fb;
  625.                                 ret = -EINVAL;
  626.                                 goto fail;
  627.                         }
  628.                         DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
  629.                         for (i = 0; i < set->num_connectors; i++) {
  630.                                 DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
  631.                                               set->connectors[i]->name);
  632.                                 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
  633.                         }
  634.                 }
  635.                 __drm_helper_disable_unused_functions(dev);
  636.         } else if (fb_changed) {
  637.                 set->crtc->x = set->x;
  638.                 set->crtc->y = set->y;
  639.                 set->crtc->primary->fb = set->fb;
  640.                 ret = crtc_funcs->mode_set_base(set->crtc,
  641.                                                 set->x, set->y, save_set.fb);
  642.                 if (ret != 0) {
  643.                         set->crtc->x = save_set.x;
  644.                         set->crtc->y = save_set.y;
  645.                         set->crtc->primary->fb = save_set.fb;
  646.                         goto fail;
  647.         }
  648.         }
  649.  
  650.         kfree(save_connectors);
  651.         kfree(save_encoders);
  652.         return 0;
  653.  
  654. fail:
  655.         /* Restore all previous data. */
  656.         count = 0;
  657.         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  658.                 *encoder = save_encoders[count++];
  659.         }
  660.  
  661.         count = 0;
  662.         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  663.                 *connector = save_connectors[count++];
  664.         }
  665.  
  666.         /* Try to restore the config */
  667.         if (mode_changed &&
  668.             !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
  669.                                       save_set.y, save_set.fb))
  670.                 DRM_ERROR("failed to restore config after modeset failure\n");
  671.  
  672.         kfree(save_connectors);
  673.         kfree(save_encoders);
  674.         return ret;
  675. }
  676. EXPORT_SYMBOL(drm_crtc_helper_set_config);
  677.  
  678. static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
  679. {
  680.         int dpms = DRM_MODE_DPMS_OFF;
  681.         struct drm_connector *connector;
  682.         struct drm_device *dev = encoder->dev;
  683.  
  684.         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  685.                 if (connector->encoder == encoder)
  686.                         if (connector->dpms < dpms)
  687.                                 dpms = connector->dpms;
  688.         return dpms;
  689. }
  690.  
  691. /* Helper which handles bridge ordering around encoder dpms */
  692. static void drm_helper_encoder_dpms(struct drm_encoder *encoder, int mode)
  693. {
  694.         struct drm_bridge *bridge = encoder->bridge;
  695.         struct drm_encoder_helper_funcs *encoder_funcs;
  696.  
  697.         if (bridge) {
  698.                 if (mode == DRM_MODE_DPMS_ON)
  699.                         bridge->funcs->pre_enable(bridge);
  700.                 else
  701.                         bridge->funcs->disable(bridge);
  702.         }
  703.  
  704.         encoder_funcs = encoder->helper_private;
  705.         if (encoder_funcs->dpms)
  706.                 encoder_funcs->dpms(encoder, mode);
  707.  
  708.         if (bridge) {
  709.                 if (mode == DRM_MODE_DPMS_ON)
  710.                         bridge->funcs->enable(bridge);
  711.                 else
  712.                         bridge->funcs->post_disable(bridge);
  713.         }
  714. }
  715.  
  716. static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
  717. {
  718.         int dpms = DRM_MODE_DPMS_OFF;
  719.         struct drm_connector *connector;
  720.         struct drm_device *dev = crtc->dev;
  721.  
  722.         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
  723.                 if (connector->encoder && connector->encoder->crtc == crtc)
  724.                         if (connector->dpms < dpms)
  725.                                 dpms = connector->dpms;
  726.         return dpms;
  727. }
  728.  
  729. /**
  730.  * drm_helper_connector_dpms() - connector dpms helper implementation
  731.  * @connector: affected connector
  732.  * @mode: DPMS mode
  733.  *
  734.  * This is the main helper function provided by the crtc helper framework for
  735.  * implementing the DPMS connector attribute. It computes the new desired DPMS
  736.  * state for all encoders and crtcs in the output mesh and calls the ->dpms()
  737.  * callback provided by the driver appropriately.
  738.  */
  739. void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
  740. {
  741.         struct drm_encoder *encoder = connector->encoder;
  742.         struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
  743.         int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF;
  744.  
  745.         if (mode == connector->dpms)
  746.                 return;
  747.  
  748.         old_dpms = connector->dpms;
  749.         connector->dpms = mode;
  750.  
  751.         if (encoder)
  752.                 encoder_dpms = drm_helper_choose_encoder_dpms(encoder);
  753.  
  754.         /* from off to on, do crtc then encoder */
  755.         if (mode < old_dpms) {
  756.                 if (crtc) {
  757.                         struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  758.                         if (crtc_funcs->dpms)
  759.                                 (*crtc_funcs->dpms) (crtc,
  760.                                                      drm_helper_choose_crtc_dpms(crtc));
  761.                 }
  762.                 if (encoder)
  763.                         drm_helper_encoder_dpms(encoder, encoder_dpms);
  764.         }
  765.  
  766.         /* from on to off, do encoder then crtc */
  767.         if (mode > old_dpms) {
  768.                 if (encoder)
  769.                         drm_helper_encoder_dpms(encoder, encoder_dpms);
  770.                 if (crtc) {
  771.                         struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
  772.                         if (crtc_funcs->dpms)
  773.                                 (*crtc_funcs->dpms) (crtc,
  774.                                                      drm_helper_choose_crtc_dpms(crtc));
  775.                 }
  776.         }
  777.  
  778.         return;
  779. }
  780. EXPORT_SYMBOL(drm_helper_connector_dpms);
  781.  
  782. /**
  783.  * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
  784.  * @fb: drm_framebuffer object to fill out
  785.  * @mode_cmd: metadata from the userspace fb creation request
  786.  *
  787.  * This helper can be used in a drivers fb_create callback to pre-fill the fb's
  788.  * metadata fields.
  789.  */
  790. void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
  791.                                    struct drm_mode_fb_cmd2 *mode_cmd)
  792. {
  793.         int i;
  794.  
  795.         fb->width = mode_cmd->width;
  796.         fb->height = mode_cmd->height;
  797.         for (i = 0; i < 4; i++) {
  798.                 fb->pitches[i] = mode_cmd->pitches[i];
  799.                 fb->offsets[i] = mode_cmd->offsets[i];
  800.         }
  801.         drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
  802.                                     &fb->bits_per_pixel);
  803.         fb->pixel_format = mode_cmd->pixel_format;
  804.         fb->flags = mode_cmd->flags;
  805. }
  806. EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
  807.  
  808. /**
  809.  * drm_helper_resume_force_mode - force-restore mode setting configuration
  810.  * @dev: drm_device which should be restored
  811.  *
  812.  * Drivers which use the mode setting helpers can use this function to
  813.  * force-restore the mode setting configuration e.g. on resume or when something
  814.  * else might have trampled over the hw state (like some overzealous old BIOSen
  815.  * tended to do).
  816.  *
  817.  * This helper doesn't provide a error return value since restoring the old
  818.  * config should never fail due to resource allocation issues since the driver
  819.  * has successfully set the restored configuration already. Hence this should
  820.  * boil down to the equivalent of a few dpms on calls, which also don't provide
  821.  * an error code.
  822.  *
  823.  * Drivers where simply restoring an old configuration again might fail (e.g.
  824.  * due to slight differences in allocating shared resources when the
  825.  * configuration is restored in a different order than when userspace set it up)
  826.  * need to use their own restore logic.
  827.  */
  828. void drm_helper_resume_force_mode(struct drm_device *dev)
  829. {
  830.         struct drm_crtc *crtc;
  831.         struct drm_encoder *encoder;
  832.         struct drm_crtc_helper_funcs *crtc_funcs;
  833.         int encoder_dpms;
  834.         bool ret;
  835.  
  836.         drm_modeset_lock_all(dev);
  837.         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
  838.  
  839.        if (!crtc->enabled)
  840.            continue;
  841.  
  842.                 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
  843.                                                crtc->x, crtc->y, crtc->primary->fb);
  844.  
  845.                 /* Restoring the old config should never fail! */
  846.                 if (ret == false)
  847.                         DRM_ERROR("failed to set mode on crtc %p\n", crtc);
  848.  
  849.                 /* Turn off outputs that were already powered off */
  850.                 if (drm_helper_choose_crtc_dpms(crtc)) {
  851.                         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
  852.  
  853.                                 if(encoder->crtc != crtc)
  854.                                         continue;
  855.  
  856.                                 encoder_dpms = drm_helper_choose_encoder_dpms(
  857.                                                         encoder);
  858.  
  859.                                 drm_helper_encoder_dpms(encoder, encoder_dpms);
  860.                         }
  861.  
  862.                                 crtc_funcs = crtc->helper_private;
  863.                                 if (crtc_funcs->dpms)
  864.                                         (*crtc_funcs->dpms) (crtc,
  865.                                                              drm_helper_choose_crtc_dpms(crtc));
  866.                         }
  867.                 }
  868.  
  869.         /* disable the unused connectors while restoring the modesetting */
  870.         __drm_helper_disable_unused_functions(dev);
  871.         drm_modeset_unlock_all(dev);
  872. }
  873. EXPORT_SYMBOL(drm_helper_resume_force_mode);
  874.