LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_probe_helper.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 273 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 16 0.0 %
Branches: 0 208 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2006-2008 Intel Corporation
       3                 :            :  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
       4                 :            :  *
       5                 :            :  * DRM core CRTC related functions
       6                 :            :  *
       7                 :            :  * Permission to use, copy, modify, distribute, and sell this software and its
       8                 :            :  * documentation for any purpose is hereby granted without fee, provided that
       9                 :            :  * the above copyright notice appear in all copies and that both that copyright
      10                 :            :  * notice and this permission notice appear in supporting documentation, and
      11                 :            :  * that the name of the copyright holders not be used in advertising or
      12                 :            :  * publicity pertaining to distribution of the software without specific,
      13                 :            :  * written prior permission.  The copyright holders make no representations
      14                 :            :  * about the suitability of this software for any purpose.  It is provided "as
      15                 :            :  * is" without express or implied warranty.
      16                 :            :  *
      17                 :            :  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
      18                 :            :  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
      19                 :            :  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
      20                 :            :  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
      21                 :            :  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
      22                 :            :  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
      23                 :            :  * OF THIS SOFTWARE.
      24                 :            :  *
      25                 :            :  * Authors:
      26                 :            :  *      Keith Packard
      27                 :            :  *      Eric Anholt <eric@anholt.net>
      28                 :            :  *      Dave Airlie <airlied@linux.ie>
      29                 :            :  *      Jesse Barnes <jesse.barnes@intel.com>
      30                 :            :  */
      31                 :            : 
      32                 :            : #include <linux/export.h>
      33                 :            : #include <linux/moduleparam.h>
      34                 :            : 
      35                 :            : #include <drm/drm_bridge.h>
      36                 :            : #include <drm/drm_client.h>
      37                 :            : #include <drm/drm_crtc.h>
      38                 :            : #include <drm/drm_edid.h>
      39                 :            : #include <drm/drm_fb_helper.h>
      40                 :            : #include <drm/drm_fourcc.h>
      41                 :            : #include <drm/drm_modeset_helper_vtables.h>
      42                 :            : #include <drm/drm_print.h>
      43                 :            : #include <drm/drm_probe_helper.h>
      44                 :            : #include <drm/drm_sysfs.h>
      45                 :            : 
      46                 :            : #include "drm_crtc_helper_internal.h"
      47                 :            : 
      48                 :            : /**
      49                 :            :  * DOC: output probing helper overview
      50                 :            :  *
      51                 :            :  * This library provides some helper code for output probing. It provides an
      52                 :            :  * implementation of the core &drm_connector_funcs.fill_modes interface with
      53                 :            :  * drm_helper_probe_single_connector_modes().
      54                 :            :  *
      55                 :            :  * It also provides support for polling connectors with a work item and for
      56                 :            :  * generic hotplug interrupt handling where the driver doesn't or cannot keep
      57                 :            :  * track of a per-connector hpd interrupt.
      58                 :            :  *
      59                 :            :  * This helper library can be used independently of the modeset helper library.
      60                 :            :  * Drivers can also overwrite different parts e.g. use their own hotplug
      61                 :            :  * handling code to avoid probing unrelated outputs.
      62                 :            :  *
      63                 :            :  * The probe helpers share the function table structures with other display
      64                 :            :  * helper libraries. See &struct drm_connector_helper_funcs for the details.
      65                 :            :  */
      66                 :            : 
      67                 :            : static bool drm_kms_helper_poll = true;
      68                 :            : module_param_named(poll, drm_kms_helper_poll, bool, 0600);
      69                 :            : 
      70                 :            : static enum drm_mode_status
      71                 :          0 : drm_mode_validate_flag(const struct drm_display_mode *mode,
      72                 :            :                        int flags)
      73                 :            : {
      74                 :          0 :         if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
      75         [ #  # ]:          0 :             !(flags & DRM_MODE_FLAG_INTERLACE))
      76                 :            :                 return MODE_NO_INTERLACE;
      77                 :            : 
      78         [ #  # ]:          0 :         if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
      79         [ #  # ]:          0 :             !(flags & DRM_MODE_FLAG_DBLSCAN))
      80                 :            :                 return MODE_NO_DBLESCAN;
      81                 :            : 
      82         [ #  # ]:          0 :         if ((mode->flags & DRM_MODE_FLAG_3D_MASK) &&
      83         [ #  # ]:          0 :             !(flags & DRM_MODE_FLAG_3D_MASK))
      84                 :          0 :                 return MODE_NO_STEREO;
      85                 :            : 
      86                 :            :         return MODE_OK;
      87                 :            : }
      88                 :            : 
      89                 :            : static enum drm_mode_status
      90                 :          0 : drm_mode_validate_pipeline(struct drm_display_mode *mode,
      91                 :            :                             struct drm_connector *connector)
      92                 :            : {
      93                 :          0 :         struct drm_device *dev = connector->dev;
      94                 :          0 :         enum drm_mode_status ret = MODE_OK;
      95                 :          0 :         struct drm_encoder *encoder;
      96                 :            : 
      97                 :            :         /* Step 1: Validate against connector */
      98                 :          0 :         ret = drm_connector_mode_valid(connector, mode);
      99         [ #  # ]:          0 :         if (ret != MODE_OK)
     100                 :            :                 return ret;
     101                 :            : 
     102                 :            :         /* Step 2: Validate against encoders and crtcs */
     103   [ #  #  #  # ]:          0 :         drm_connector_for_each_possible_encoder(connector, encoder) {
     104                 :          0 :                 struct drm_bridge *bridge;
     105                 :          0 :                 struct drm_crtc *crtc;
     106                 :            : 
     107                 :          0 :                 ret = drm_encoder_mode_valid(encoder, mode);
     108         [ #  # ]:          0 :                 if (ret != MODE_OK) {
     109                 :            :                         /* No point in continuing for crtc check as this encoder
     110                 :            :                          * will not accept the mode anyway. If all encoders
     111                 :            :                          * reject the mode then, at exit, ret will not be
     112                 :            :                          * MODE_OK. */
     113                 :          0 :                         continue;
     114                 :            :                 }
     115                 :            : 
     116         [ #  # ]:          0 :                 bridge = drm_bridge_chain_get_first_bridge(encoder);
     117                 :          0 :                 ret = drm_bridge_chain_mode_valid(bridge, mode);
     118         [ #  # ]:          0 :                 if (ret != MODE_OK) {
     119                 :            :                         /* There is also no point in continuing for crtc check
     120                 :            :                          * here. */
     121                 :          0 :                         continue;
     122                 :            :                 }
     123                 :            : 
     124         [ #  # ]:          0 :                 drm_for_each_crtc(crtc, dev) {
     125         [ #  # ]:          0 :                         if (!drm_encoder_crtc_ok(encoder, crtc))
     126                 :          0 :                                 continue;
     127                 :            : 
     128                 :          0 :                         ret = drm_crtc_mode_valid(crtc, mode);
     129         [ #  # ]:          0 :                         if (ret == MODE_OK) {
     130                 :            :                                 /* If we get to this point there is at least
     131                 :            :                                  * one combination of encoder+crtc that works
     132                 :            :                                  * for this mode. Lets return now. */
     133                 :          0 :                                 return ret;
     134                 :            :                         }
     135                 :            :                 }
     136                 :            :         }
     137                 :            : 
     138                 :            :         return ret;
     139                 :            : }
     140                 :            : 
     141                 :          0 : static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
     142                 :            : {
     143                 :          0 :         struct drm_cmdline_mode *cmdline_mode;
     144                 :          0 :         struct drm_display_mode *mode;
     145                 :            : 
     146                 :          0 :         cmdline_mode = &connector->cmdline_mode;
     147         [ #  # ]:          0 :         if (!cmdline_mode->specified)
     148                 :            :                 return 0;
     149                 :            : 
     150                 :            :         /* Only add a GTF mode if we find no matching probed modes */
     151         [ #  # ]:          0 :         list_for_each_entry(mode, &connector->probed_modes, head) {
     152         [ #  # ]:          0 :                 if (mode->hdisplay != cmdline_mode->xres ||
     153         [ #  # ]:          0 :                     mode->vdisplay != cmdline_mode->yres)
     154                 :          0 :                         continue;
     155                 :            : 
     156         [ #  # ]:          0 :                 if (cmdline_mode->refresh_specified) {
     157                 :            :                         /* The probed mode's vrefresh is set until later */
     158         [ #  # ]:          0 :                         if (drm_mode_vrefresh(mode) != cmdline_mode->refresh)
     159                 :          0 :                                 continue;
     160                 :            :                 }
     161                 :            : 
     162                 :            :                 return 0;
     163                 :            :         }
     164                 :            : 
     165                 :          0 :         mode = drm_mode_create_from_cmdline_mode(connector->dev,
     166                 :            :                                                  cmdline_mode);
     167         [ #  # ]:          0 :         if (mode == NULL)
     168                 :            :                 return 0;
     169                 :            : 
     170                 :          0 :         drm_mode_probed_add(connector, mode);
     171                 :          0 :         return 1;
     172                 :            : }
     173                 :            : 
     174                 :          0 : enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
     175                 :            :                                          const struct drm_display_mode *mode)
     176                 :            : {
     177                 :          0 :         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
     178                 :            : 
     179   [ #  #  #  #  :          0 :         if (!crtc_funcs || !crtc_funcs->mode_valid)
             #  #  #  # ]
     180                 :            :                 return MODE_OK;
     181                 :            : 
     182                 :          0 :         return crtc_funcs->mode_valid(crtc, mode);
     183                 :            : }
     184                 :            : 
     185                 :          0 : enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
     186                 :            :                                             const struct drm_display_mode *mode)
     187                 :            : {
     188                 :          0 :         const struct drm_encoder_helper_funcs *encoder_funcs =
     189                 :            :                 encoder->helper_private;
     190                 :            : 
     191   [ #  #  #  #  :          0 :         if (!encoder_funcs || !encoder_funcs->mode_valid)
             #  #  #  # ]
     192                 :            :                 return MODE_OK;
     193                 :            : 
     194                 :          0 :         return encoder_funcs->mode_valid(encoder, mode);
     195                 :            : }
     196                 :            : 
     197                 :          0 : enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
     198                 :            :                                               struct drm_display_mode *mode)
     199                 :            : {
     200                 :          0 :         const struct drm_connector_helper_funcs *connector_funcs =
     201                 :            :                 connector->helper_private;
     202                 :            : 
     203   [ #  #  #  #  :          0 :         if (!connector_funcs || !connector_funcs->mode_valid)
             #  #  #  # ]
     204                 :            :                 return MODE_OK;
     205                 :            : 
     206                 :          0 :         return connector_funcs->mode_valid(connector, mode);
     207                 :            : }
     208                 :            : 
     209                 :            : #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
     210                 :            : /**
     211                 :            :  * drm_kms_helper_poll_enable - re-enable output polling.
     212                 :            :  * @dev: drm_device
     213                 :            :  *
     214                 :            :  * This function re-enables the output polling work, after it has been
     215                 :            :  * temporarily disabled using drm_kms_helper_poll_disable(), for example over
     216                 :            :  * suspend/resume.
     217                 :            :  *
     218                 :            :  * Drivers can call this helper from their device resume implementation. It is
     219                 :            :  * not an error to call this even when output polling isn't enabled.
     220                 :            :  *
     221                 :            :  * Note that calls to enable and disable polling must be strictly ordered, which
     222                 :            :  * is automatically the case when they're only call from suspend/resume
     223                 :            :  * callbacks.
     224                 :            :  */
     225                 :          0 : void drm_kms_helper_poll_enable(struct drm_device *dev)
     226                 :            : {
     227                 :          0 :         bool poll = false;
     228                 :          0 :         struct drm_connector *connector;
     229                 :          0 :         struct drm_connector_list_iter conn_iter;
     230                 :          0 :         unsigned long delay = DRM_OUTPUT_POLL_PERIOD;
     231                 :            : 
     232   [ #  #  #  # ]:          0 :         if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
     233                 :          0 :                 return;
     234                 :            : 
     235                 :          0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     236         [ #  # ]:          0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     237         [ #  # ]:          0 :                 if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
     238                 :            :                                          DRM_CONNECTOR_POLL_DISCONNECT))
     239                 :          0 :                         poll = true;
     240                 :            :         }
     241                 :          0 :         drm_connector_list_iter_end(&conn_iter);
     242                 :            : 
     243         [ #  # ]:          0 :         if (dev->mode_config.delayed_event) {
     244                 :            :                 /*
     245                 :            :                  * FIXME:
     246                 :            :                  *
     247                 :            :                  * Use short (1s) delay to handle the initial delayed event.
     248                 :            :                  * This delay should not be needed, but Optimus/nouveau will
     249                 :            :                  * fail in a mysterious way if the delayed event is handled as
     250                 :            :                  * soon as possible like it is done in
     251                 :            :                  * drm_helper_probe_single_connector_modes() in case the poll
     252                 :            :                  * was enabled before.
     253                 :            :                  */
     254                 :            :                 poll = true;
     255                 :            :                 delay = HZ;
     256                 :            :         }
     257                 :            : 
     258         [ #  # ]:          0 :         if (poll)
     259                 :          0 :                 schedule_delayed_work(&dev->mode_config.output_poll_work, delay);
     260                 :            : }
     261                 :            : EXPORT_SYMBOL(drm_kms_helper_poll_enable);
     262                 :            : 
     263                 :            : static enum drm_connector_status
     264                 :          0 : drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force)
     265                 :            : {
     266                 :          0 :         const struct drm_connector_helper_funcs *funcs = connector->helper_private;
     267                 :          0 :         struct drm_modeset_acquire_ctx ctx;
     268                 :          0 :         int ret;
     269                 :            : 
     270                 :          0 :         drm_modeset_acquire_init(&ctx, 0);
     271                 :            : 
     272                 :          0 : retry:
     273                 :          0 :         ret = drm_modeset_lock(&connector->dev->mode_config.connection_mutex, &ctx);
     274         [ #  # ]:          0 :         if (!ret) {
     275         [ #  # ]:          0 :                 if (funcs->detect_ctx)
     276                 :          0 :                         ret = funcs->detect_ctx(connector, &ctx, force);
     277         [ #  # ]:          0 :                 else if (connector->funcs->detect)
     278                 :          0 :                         ret = connector->funcs->detect(connector, force);
     279                 :            :                 else
     280                 :            :                         ret = connector_status_connected;
     281                 :            :         }
     282                 :            : 
     283         [ #  # ]:          0 :         if (ret == -EDEADLK) {
     284                 :          0 :                 drm_modeset_backoff(&ctx);
     285                 :          0 :                 goto retry;
     286                 :            :         }
     287                 :            : 
     288   [ #  #  #  # ]:          0 :         if (WARN_ON(ret < 0))
     289                 :          0 :                 ret = connector_status_unknown;
     290                 :            : 
     291                 :          0 :         drm_modeset_drop_locks(&ctx);
     292                 :          0 :         drm_modeset_acquire_fini(&ctx);
     293                 :            : 
     294                 :          0 :         return ret;
     295                 :            : }
     296                 :            : 
     297                 :            : /**
     298                 :            :  * drm_helper_probe_detect - probe connector status
     299                 :            :  * @connector: connector to probe
     300                 :            :  * @ctx: acquire_ctx, or NULL to let this function handle locking.
     301                 :            :  * @force: Whether destructive probe operations should be performed.
     302                 :            :  *
     303                 :            :  * This function calls the detect callbacks of the connector.
     304                 :            :  * This function returns &drm_connector_status, or
     305                 :            :  * if @ctx is set, it might also return -EDEADLK.
     306                 :            :  */
     307                 :            : int
     308                 :          0 : drm_helper_probe_detect(struct drm_connector *connector,
     309                 :            :                         struct drm_modeset_acquire_ctx *ctx,
     310                 :            :                         bool force)
     311                 :            : {
     312                 :          0 :         const struct drm_connector_helper_funcs *funcs = connector->helper_private;
     313                 :          0 :         struct drm_device *dev = connector->dev;
     314                 :          0 :         int ret;
     315                 :            : 
     316         [ #  # ]:          0 :         if (!ctx)
     317                 :          0 :                 return drm_helper_probe_detect_ctx(connector, force);
     318                 :            : 
     319                 :          0 :         ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
     320         [ #  # ]:          0 :         if (ret)
     321                 :            :                 return ret;
     322                 :            : 
     323         [ #  # ]:          0 :         if (funcs->detect_ctx)
     324                 :          0 :                 return funcs->detect_ctx(connector, ctx, force);
     325         [ #  # ]:          0 :         else if (connector->funcs->detect)
     326                 :          0 :                 return connector->funcs->detect(connector, force);
     327                 :            :         else
     328                 :            :                 return connector_status_connected;
     329                 :            : }
     330                 :            : EXPORT_SYMBOL(drm_helper_probe_detect);
     331                 :            : 
     332                 :            : /**
     333                 :            :  * drm_helper_probe_single_connector_modes - get complete set of display modes
     334                 :            :  * @connector: connector to probe
     335                 :            :  * @maxX: max width for modes
     336                 :            :  * @maxY: max height for modes
     337                 :            :  *
     338                 :            :  * Based on the helper callbacks implemented by @connector in struct
     339                 :            :  * &drm_connector_helper_funcs try to detect all valid modes.  Modes will first
     340                 :            :  * be added to the connector's probed_modes list, then culled (based on validity
     341                 :            :  * and the @maxX, @maxY parameters) and put into the normal modes list.
     342                 :            :  *
     343                 :            :  * Intended to be used as a generic implementation of the
     344                 :            :  * &drm_connector_funcs.fill_modes() vfunc for drivers that use the CRTC helpers
     345                 :            :  * for output mode filtering and detection.
     346                 :            :  *
     347                 :            :  * The basic procedure is as follows
     348                 :            :  *
     349                 :            :  * 1. All modes currently on the connector's modes list are marked as stale
     350                 :            :  *
     351                 :            :  * 2. New modes are added to the connector's probed_modes list with
     352                 :            :  *    drm_mode_probed_add(). New modes start their life with status as OK.
     353                 :            :  *    Modes are added from a single source using the following priority order.
     354                 :            :  *
     355                 :            :  *    - &drm_connector_helper_funcs.get_modes vfunc
     356                 :            :  *    - if the connector status is connector_status_connected, standard
     357                 :            :  *      VESA DMT modes up to 1024x768 are automatically added
     358                 :            :  *      (drm_add_modes_noedid())
     359                 :            :  *
     360                 :            :  *    Finally modes specified via the kernel command line (video=...) are
     361                 :            :  *    added in addition to what the earlier probes produced
     362                 :            :  *    (drm_helper_probe_add_cmdline_mode()). These modes are generated
     363                 :            :  *    using the VESA GTF/CVT formulas.
     364                 :            :  *
     365                 :            :  * 3. Modes are moved from the probed_modes list to the modes list. Potential
     366                 :            :  *    duplicates are merged together (see drm_connector_list_update()).
     367                 :            :  *    After this step the probed_modes list will be empty again.
     368                 :            :  *
     369                 :            :  * 4. Any non-stale mode on the modes list then undergoes validation
     370                 :            :  *
     371                 :            :  *    - drm_mode_validate_basic() performs basic sanity checks
     372                 :            :  *    - drm_mode_validate_size() filters out modes larger than @maxX and @maxY
     373                 :            :  *      (if specified)
     374                 :            :  *    - drm_mode_validate_flag() checks the modes against basic connector
     375                 :            :  *      capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
     376                 :            :  *    - the optional &drm_connector_helper_funcs.mode_valid helper can perform
     377                 :            :  *      driver and/or sink specific checks
     378                 :            :  *    - the optional &drm_crtc_helper_funcs.mode_valid,
     379                 :            :  *      &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
     380                 :            :  *      helpers can perform driver and/or source specific checks which are also
     381                 :            :  *      enforced by the modeset/atomic helpers
     382                 :            :  *
     383                 :            :  * 5. Any mode whose status is not OK is pruned from the connector's modes list,
     384                 :            :  *    accompanied by a debug message indicating the reason for the mode's
     385                 :            :  *    rejection (see drm_mode_prune_invalid()).
     386                 :            :  *
     387                 :            :  * Returns:
     388                 :            :  * The number of modes found on @connector.
     389                 :            :  */
     390                 :          0 : int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
     391                 :            :                                             uint32_t maxX, uint32_t maxY)
     392                 :            : {
     393                 :          0 :         struct drm_device *dev = connector->dev;
     394                 :          0 :         struct drm_display_mode *mode;
     395                 :          0 :         const struct drm_connector_helper_funcs *connector_funcs =
     396                 :            :                 connector->helper_private;
     397                 :          0 :         int count = 0, ret;
     398                 :          0 :         int mode_flags = 0;
     399                 :          0 :         bool verbose_prune = true;
     400                 :          0 :         enum drm_connector_status old_status;
     401                 :          0 :         struct drm_modeset_acquire_ctx ctx;
     402                 :            : 
     403         [ #  # ]:          0 :         WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
     404                 :            : 
     405                 :          0 :         drm_modeset_acquire_init(&ctx, 0);
     406                 :            : 
     407                 :          0 :         DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
     408                 :            :                         connector->name);
     409                 :            : 
     410                 :            : retry:
     411                 :          0 :         ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
     412         [ #  # ]:          0 :         if (ret == -EDEADLK) {
     413                 :          0 :                 drm_modeset_backoff(&ctx);
     414                 :          0 :                 goto retry;
     415                 :            :         } else
     416         [ #  # ]:          0 :                 WARN_ON(ret < 0);
     417                 :            : 
     418                 :            :         /* set all old modes to the stale state */
     419         [ #  # ]:          0 :         list_for_each_entry(mode, &connector->modes, head)
     420                 :          0 :                 mode->status = MODE_STALE;
     421                 :            : 
     422                 :          0 :         old_status = connector->status;
     423                 :            : 
     424         [ #  # ]:          0 :         if (connector->force) {
     425         [ #  # ]:          0 :                 if (connector->force == DRM_FORCE_ON ||
     426                 :            :                     connector->force == DRM_FORCE_ON_DIGITAL)
     427                 :          0 :                         connector->status = connector_status_connected;
     428                 :            :                 else
     429                 :          0 :                         connector->status = connector_status_disconnected;
     430         [ #  # ]:          0 :                 if (connector->funcs->force)
     431                 :          0 :                         connector->funcs->force(connector);
     432                 :            :         } else {
     433                 :          0 :                 ret = drm_helper_probe_detect(connector, &ctx, true);
     434                 :            : 
     435         [ #  # ]:          0 :                 if (ret == -EDEADLK) {
     436                 :          0 :                         drm_modeset_backoff(&ctx);
     437                 :          0 :                         goto retry;
     438   [ #  #  #  # ]:          0 :                 } else if (WARN(ret < 0, "Invalid return value %i for connector detection\n", ret))
     439                 :          0 :                         ret = connector_status_unknown;
     440                 :            : 
     441                 :          0 :                 connector->status = ret;
     442                 :            :         }
     443                 :            : 
     444                 :            :         /*
     445                 :            :          * Normally either the driver's hpd code or the poll loop should
     446                 :            :          * pick up any changes and fire the hotplug event. But if
     447                 :            :          * userspace sneaks in a probe, we might miss a change. Hence
     448                 :            :          * check here, and if anything changed start the hotplug code.
     449                 :            :          */
     450         [ #  # ]:          0 :         if (old_status != connector->status) {
     451                 :          0 :                 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
     452                 :            :                               connector->base.id,
     453                 :            :                               connector->name,
     454                 :            :                               drm_get_connector_status_name(old_status),
     455                 :            :                               drm_get_connector_status_name(connector->status));
     456                 :            : 
     457                 :            :                 /*
     458                 :            :                  * The hotplug event code might call into the fb
     459                 :            :                  * helpers, and so expects that we do not hold any
     460                 :            :                  * locks. Fire up the poll struct instead, it will
     461                 :            :                  * disable itself again.
     462                 :            :                  */
     463                 :          0 :                 dev->mode_config.delayed_event = true;
     464         [ #  # ]:          0 :                 if (dev->mode_config.poll_enabled)
     465                 :          0 :                         schedule_delayed_work(&dev->mode_config.output_poll_work,
     466                 :            :                                               0);
     467                 :            :         }
     468                 :            : 
     469                 :            :         /* Re-enable polling in case the global poll config changed. */
     470         [ #  # ]:          0 :         if (drm_kms_helper_poll != dev->mode_config.poll_running)
     471                 :          0 :                 drm_kms_helper_poll_enable(dev);
     472                 :            : 
     473                 :          0 :         dev->mode_config.poll_running = drm_kms_helper_poll;
     474                 :            : 
     475         [ #  # ]:          0 :         if (connector->status == connector_status_disconnected) {
     476                 :          0 :                 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
     477                 :            :                         connector->base.id, connector->name);
     478                 :          0 :                 drm_connector_update_edid_property(connector, NULL);
     479                 :          0 :                 verbose_prune = false;
     480                 :          0 :                 goto prune;
     481                 :            :         }
     482                 :            : 
     483                 :          0 :         count = (*connector_funcs->get_modes)(connector);
     484                 :            : 
     485                 :            :         /*
     486                 :            :          * Fallback for when DDC probe failed in drm_get_edid() and thus skipped
     487                 :            :          * override/firmware EDID.
     488                 :            :          */
     489   [ #  #  #  # ]:          0 :         if (count == 0 && connector->status == connector_status_connected)
     490                 :          0 :                 count = drm_add_override_edid_modes(connector);
     491                 :            : 
     492   [ #  #  #  # ]:          0 :         if (count == 0 && connector->status == connector_status_connected)
     493                 :          0 :                 count = drm_add_modes_noedid(connector, 1024, 768);
     494                 :          0 :         count += drm_helper_probe_add_cmdline_mode(connector);
     495         [ #  # ]:          0 :         if (count == 0)
     496                 :          0 :                 goto prune;
     497                 :            : 
     498                 :          0 :         drm_connector_list_update(connector);
     499                 :            : 
     500         [ #  # ]:          0 :         if (connector->interlace_allowed)
     501                 :          0 :                 mode_flags |= DRM_MODE_FLAG_INTERLACE;
     502         [ #  # ]:          0 :         if (connector->doublescan_allowed)
     503                 :          0 :                 mode_flags |= DRM_MODE_FLAG_DBLSCAN;
     504         [ #  # ]:          0 :         if (connector->stereo_allowed)
     505                 :          0 :                 mode_flags |= DRM_MODE_FLAG_3D_MASK;
     506                 :            : 
     507         [ #  # ]:          0 :         list_for_each_entry(mode, &connector->modes, head) {
     508         [ #  # ]:          0 :                 if (mode->status == MODE_OK)
     509                 :          0 :                         mode->status = drm_mode_validate_driver(dev, mode);
     510                 :            : 
     511         [ #  # ]:          0 :                 if (mode->status == MODE_OK)
     512                 :          0 :                         mode->status = drm_mode_validate_size(mode, maxX, maxY);
     513                 :            : 
     514         [ #  # ]:          0 :                 if (mode->status == MODE_OK)
     515         [ #  # ]:          0 :                         mode->status = drm_mode_validate_flag(mode, mode_flags);
     516                 :            : 
     517         [ #  # ]:          0 :                 if (mode->status == MODE_OK)
     518                 :          0 :                         mode->status = drm_mode_validate_pipeline(mode,
     519                 :            :                                                                   connector);
     520                 :            : 
     521         [ #  # ]:          0 :                 if (mode->status == MODE_OK)
     522                 :          0 :                         mode->status = drm_mode_validate_ycbcr420(mode,
     523                 :            :                                                                   connector);
     524                 :            :         }
     525                 :            : 
     526                 :          0 : prune:
     527                 :          0 :         drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
     528                 :            : 
     529                 :          0 :         drm_modeset_drop_locks(&ctx);
     530                 :          0 :         drm_modeset_acquire_fini(&ctx);
     531                 :            : 
     532         [ #  # ]:          0 :         if (list_empty(&connector->modes))
     533                 :            :                 return 0;
     534                 :            : 
     535         [ #  # ]:          0 :         list_for_each_entry(mode, &connector->modes, head)
     536                 :          0 :                 mode->vrefresh = drm_mode_vrefresh(mode);
     537                 :            : 
     538                 :          0 :         drm_mode_sort(&connector->modes);
     539                 :            : 
     540                 :          0 :         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
     541                 :            :                         connector->name);
     542         [ #  # ]:          0 :         list_for_each_entry(mode, &connector->modes, head) {
     543                 :          0 :                 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
     544                 :          0 :                 drm_mode_debug_printmodeline(mode);
     545                 :            :         }
     546                 :            : 
     547                 :            :         return count;
     548                 :            : }
     549                 :            : EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
     550                 :            : 
     551                 :            : /**
     552                 :            :  * drm_kms_helper_hotplug_event - fire off KMS hotplug events
     553                 :            :  * @dev: drm_device whose connector state changed
     554                 :            :  *
     555                 :            :  * This function fires off the uevent for userspace and also calls the
     556                 :            :  * output_poll_changed function, which is most commonly used to inform the fbdev
     557                 :            :  * emulation code and allow it to update the fbcon output configuration.
     558                 :            :  *
     559                 :            :  * Drivers should call this from their hotplug handling code when a change is
     560                 :            :  * detected. Note that this function does not do any output detection of its
     561                 :            :  * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the
     562                 :            :  * driver already.
     563                 :            :  *
     564                 :            :  * This function must be called from process context with no mode
     565                 :            :  * setting locks held.
     566                 :            :  */
     567                 :          0 : void drm_kms_helper_hotplug_event(struct drm_device *dev)
     568                 :            : {
     569                 :            :         /* send a uevent + call fbdev */
     570                 :          0 :         drm_sysfs_hotplug_event(dev);
     571         [ #  # ]:          0 :         if (dev->mode_config.funcs->output_poll_changed)
     572                 :          0 :                 dev->mode_config.funcs->output_poll_changed(dev);
     573                 :            : 
     574                 :          0 :         drm_client_dev_hotplug(dev);
     575                 :          0 : }
     576                 :            : EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
     577                 :            : 
     578                 :          0 : static void output_poll_execute(struct work_struct *work)
     579                 :            : {
     580         [ #  # ]:          0 :         struct delayed_work *delayed_work = to_delayed_work(work);
     581                 :          0 :         struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
     582                 :          0 :         struct drm_connector *connector;
     583                 :          0 :         struct drm_connector_list_iter conn_iter;
     584                 :          0 :         enum drm_connector_status old_status;
     585                 :          0 :         bool repoll = false, changed;
     586                 :            : 
     587         [ #  # ]:          0 :         if (!dev->mode_config.poll_enabled)
     588                 :          0 :                 return;
     589                 :            : 
     590                 :            :         /* Pick up any changes detected by the probe functions. */
     591                 :          0 :         changed = dev->mode_config.delayed_event;
     592                 :          0 :         dev->mode_config.delayed_event = false;
     593                 :            : 
     594         [ #  # ]:          0 :         if (!drm_kms_helper_poll)
     595                 :          0 :                 goto out;
     596                 :            : 
     597         [ #  # ]:          0 :         if (!mutex_trylock(&dev->mode_config.mutex)) {
     598                 :          0 :                 repoll = true;
     599                 :          0 :                 goto out;
     600                 :            :         }
     601                 :            : 
     602                 :          0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     603         [ #  # ]:          0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     604                 :            :                 /* Ignore forced connectors. */
     605         [ #  # ]:          0 :                 if (connector->force)
     606                 :          0 :                         continue;
     607                 :            : 
     608                 :            :                 /* Ignore HPD capable connectors and connectors where we don't
     609                 :            :                  * want any hotplug detection at all for polling. */
     610         [ #  # ]:          0 :                 if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
     611                 :          0 :                         continue;
     612                 :            : 
     613                 :          0 :                 old_status = connector->status;
     614                 :            :                 /* if we are connected and don't want to poll for disconnect
     615                 :            :                    skip it */
     616   [ #  #  #  # ]:          0 :                 if (old_status == connector_status_connected &&
     617                 :            :                     !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
     618                 :          0 :                         continue;
     619                 :            : 
     620                 :          0 :                 repoll = true;
     621                 :            : 
     622                 :          0 :                 connector->status = drm_helper_probe_detect(connector, NULL, false);
     623         [ #  # ]:          0 :                 if (old_status != connector->status) {
     624                 :          0 :                         const char *old, *new;
     625                 :            : 
     626                 :            :                         /*
     627                 :            :                          * The poll work sets force=false when calling detect so
     628                 :            :                          * that drivers can avoid to do disruptive tests (e.g.
     629                 :            :                          * when load detect cycles could cause flickering on
     630                 :            :                          * other, running displays). This bears the risk that we
     631                 :            :                          * flip-flop between unknown here in the poll work and
     632                 :            :                          * the real state when userspace forces a full detect
     633                 :            :                          * call after receiving a hotplug event due to this
     634                 :            :                          * change.
     635                 :            :                          *
     636                 :            :                          * Hence clamp an unknown detect status to the old
     637                 :            :                          * value.
     638                 :            :                          */
     639         [ #  # ]:          0 :                         if (connector->status == connector_status_unknown) {
     640                 :          0 :                                 connector->status = old_status;
     641                 :          0 :                                 continue;
     642                 :            :                         }
     643                 :            : 
     644                 :          0 :                         old = drm_get_connector_status_name(old_status);
     645                 :          0 :                         new = drm_get_connector_status_name(connector->status);
     646                 :            : 
     647                 :          0 :                         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] "
     648                 :            :                                       "status updated from %s to %s\n",
     649                 :            :                                       connector->base.id,
     650                 :            :                                       connector->name,
     651                 :            :                                       old, new);
     652                 :            : 
     653                 :          0 :                         changed = true;
     654                 :            :                 }
     655                 :            :         }
     656                 :          0 :         drm_connector_list_iter_end(&conn_iter);
     657                 :            : 
     658                 :          0 :         mutex_unlock(&dev->mode_config.mutex);
     659                 :            : 
     660                 :          0 : out:
     661         [ #  # ]:          0 :         if (changed)
     662                 :          0 :                 drm_kms_helper_hotplug_event(dev);
     663                 :            : 
     664         [ #  # ]:          0 :         if (repoll)
     665                 :          0 :                 schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
     666                 :            : }
     667                 :            : 
     668                 :            : /**
     669                 :            :  * drm_kms_helper_is_poll_worker - is %current task an output poll worker?
     670                 :            :  *
     671                 :            :  * Determine if %current task is an output poll worker.  This can be used
     672                 :            :  * to select distinct code paths for output polling versus other contexts.
     673                 :            :  *
     674                 :            :  * One use case is to avoid a deadlock between the output poll worker and
     675                 :            :  * the autosuspend worker wherein the latter waits for polling to finish
     676                 :            :  * upon calling drm_kms_helper_poll_disable(), while the former waits for
     677                 :            :  * runtime suspend to finish upon calling pm_runtime_get_sync() in a
     678                 :            :  * connector ->detect hook.
     679                 :            :  */
     680                 :          0 : bool drm_kms_helper_is_poll_worker(void)
     681                 :            : {
     682                 :          0 :         struct work_struct *work = current_work();
     683                 :            : 
     684   [ #  #  #  # ]:          0 :         return work && work->func == output_poll_execute;
     685                 :            : }
     686                 :            : EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
     687                 :            : 
     688                 :            : /**
     689                 :            :  * drm_kms_helper_poll_disable - disable output polling
     690                 :            :  * @dev: drm_device
     691                 :            :  *
     692                 :            :  * This function disables the output polling work.
     693                 :            :  *
     694                 :            :  * Drivers can call this helper from their device suspend implementation. It is
     695                 :            :  * not an error to call this even when output polling isn't enabled or already
     696                 :            :  * disabled. Polling is re-enabled by calling drm_kms_helper_poll_enable().
     697                 :            :  *
     698                 :            :  * Note that calls to enable and disable polling must be strictly ordered, which
     699                 :            :  * is automatically the case when they're only call from suspend/resume
     700                 :            :  * callbacks.
     701                 :            :  */
     702                 :          0 : void drm_kms_helper_poll_disable(struct drm_device *dev)
     703                 :            : {
     704         [ #  # ]:          0 :         if (!dev->mode_config.poll_enabled)
     705                 :            :                 return;
     706                 :          0 :         cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
     707                 :            : }
     708                 :            : EXPORT_SYMBOL(drm_kms_helper_poll_disable);
     709                 :            : 
     710                 :            : /**
     711                 :            :  * drm_kms_helper_poll_init - initialize and enable output polling
     712                 :            :  * @dev: drm_device
     713                 :            :  *
     714                 :            :  * This function intializes and then also enables output polling support for
     715                 :            :  * @dev. Drivers which do not have reliable hotplug support in hardware can use
     716                 :            :  * this helper infrastructure to regularly poll such connectors for changes in
     717                 :            :  * their connection state.
     718                 :            :  *
     719                 :            :  * Drivers can control which connectors are polled by setting the
     720                 :            :  * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On
     721                 :            :  * connectors where probing live outputs can result in visual distortion drivers
     722                 :            :  * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this.
     723                 :            :  * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are
     724                 :            :  * completely ignored by the polling logic.
     725                 :            :  *
     726                 :            :  * Note that a connector can be both polled and probed from the hotplug handler,
     727                 :            :  * in case the hotplug interrupt is known to be unreliable.
     728                 :            :  */
     729                 :          0 : void drm_kms_helper_poll_init(struct drm_device *dev)
     730                 :            : {
     731                 :          0 :         INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
     732                 :          0 :         dev->mode_config.poll_enabled = true;
     733                 :            : 
     734                 :          0 :         drm_kms_helper_poll_enable(dev);
     735                 :          0 : }
     736                 :            : EXPORT_SYMBOL(drm_kms_helper_poll_init);
     737                 :            : 
     738                 :            : /**
     739                 :            :  * drm_kms_helper_poll_fini - disable output polling and clean it up
     740                 :            :  * @dev: drm_device
     741                 :            :  */
     742                 :          0 : void drm_kms_helper_poll_fini(struct drm_device *dev)
     743                 :            : {
     744         [ #  # ]:          0 :         if (!dev->mode_config.poll_enabled)
     745                 :            :                 return;
     746                 :            : 
     747                 :          0 :         dev->mode_config.poll_enabled = false;
     748                 :          0 :         cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
     749                 :            : }
     750                 :            : EXPORT_SYMBOL(drm_kms_helper_poll_fini);
     751                 :            : 
     752                 :            : /**
     753                 :            :  * drm_helper_hpd_irq_event - hotplug processing
     754                 :            :  * @dev: drm_device
     755                 :            :  *
     756                 :            :  * Drivers can use this helper function to run a detect cycle on all connectors
     757                 :            :  * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All
     758                 :            :  * other connectors are ignored, which is useful to avoid reprobing fixed
     759                 :            :  * panels.
     760                 :            :  *
     761                 :            :  * This helper function is useful for drivers which can't or don't track hotplug
     762                 :            :  * interrupts for each connector.
     763                 :            :  *
     764                 :            :  * Drivers which support hotplug interrupts for each connector individually and
     765                 :            :  * which have a more fine-grained detect logic should bypass this code and
     766                 :            :  * directly call drm_kms_helper_hotplug_event() in case the connector state
     767                 :            :  * changed.
     768                 :            :  *
     769                 :            :  * This function must be called from process context with no mode
     770                 :            :  * setting locks held.
     771                 :            :  *
     772                 :            :  * Note that a connector can be both polled and probed from the hotplug handler,
     773                 :            :  * in case the hotplug interrupt is known to be unreliable.
     774                 :            :  */
     775                 :          0 : bool drm_helper_hpd_irq_event(struct drm_device *dev)
     776                 :            : {
     777                 :          0 :         struct drm_connector *connector;
     778                 :          0 :         struct drm_connector_list_iter conn_iter;
     779                 :          0 :         enum drm_connector_status old_status;
     780                 :          0 :         bool changed = false;
     781                 :            : 
     782         [ #  # ]:          0 :         if (!dev->mode_config.poll_enabled)
     783                 :            :                 return false;
     784                 :            : 
     785                 :          0 :         mutex_lock(&dev->mode_config.mutex);
     786                 :          0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     787         [ #  # ]:          0 :         drm_for_each_connector_iter(connector, &conn_iter) {
     788                 :            :                 /* Only handle HPD capable connectors. */
     789         [ #  # ]:          0 :                 if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
     790                 :          0 :                         continue;
     791                 :            : 
     792                 :          0 :                 old_status = connector->status;
     793                 :            : 
     794                 :          0 :                 connector->status = drm_helper_probe_detect(connector, NULL, false);
     795                 :          0 :                 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
     796                 :            :                               connector->base.id,
     797                 :            :                               connector->name,
     798                 :            :                               drm_get_connector_status_name(old_status),
     799                 :            :                               drm_get_connector_status_name(connector->status));
     800         [ #  # ]:          0 :                 if (old_status != connector->status)
     801                 :          0 :                         changed = true;
     802                 :            :         }
     803                 :          0 :         drm_connector_list_iter_end(&conn_iter);
     804                 :          0 :         mutex_unlock(&dev->mode_config.mutex);
     805                 :            : 
     806         [ #  # ]:          0 :         if (changed)
     807                 :          0 :                 drm_kms_helper_hotplug_event(dev);
     808                 :            : 
     809                 :            :         return changed;
     810                 :            : }
     811                 :            : EXPORT_SYMBOL(drm_helper_hpd_irq_event);

Generated by: LCOV version 1.14