LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_client_modeset.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 500 0.6 %
Date: 2023-04-06 08:38:28 Functions: 1 19 5.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: MIT
       2             : /*
       3             :  * Copyright 2018 Noralf Trønnes
       4             :  * Copyright (c) 2006-2009 Red Hat Inc.
       5             :  * Copyright (c) 2006-2008 Intel Corporation
       6             :  *   Jesse Barnes <jesse.barnes@intel.com>
       7             :  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
       8             :  */
       9             : 
      10             : #include "drm/drm_modeset_lock.h"
      11             : #include <linux/module.h>
      12             : #include <linux/mutex.h>
      13             : #include <linux/slab.h>
      14             : #include <linux/string_helpers.h>
      15             : 
      16             : #include <drm/drm_atomic.h>
      17             : #include <drm/drm_client.h>
      18             : #include <drm/drm_connector.h>
      19             : #include <drm/drm_crtc.h>
      20             : #include <drm/drm_device.h>
      21             : #include <drm/drm_drv.h>
      22             : #include <drm/drm_edid.h>
      23             : #include <drm/drm_encoder.h>
      24             : #include <drm/drm_print.h>
      25             : 
      26             : #include "drm_crtc_internal.h"
      27             : #include "drm_internal.h"
      28             : 
      29             : #define DRM_CLIENT_MAX_CLONED_CONNECTORS        8
      30             : 
      31             : struct drm_client_offset {
      32             :         int x, y;
      33             : };
      34             : 
      35           0 : int drm_client_modeset_create(struct drm_client_dev *client)
      36             : {
      37           0 :         struct drm_device *dev = client->dev;
      38           0 :         unsigned int num_crtc = dev->mode_config.num_crtc;
      39           0 :         unsigned int max_connector_count = 1;
      40             :         struct drm_mode_set *modeset;
      41             :         struct drm_crtc *crtc;
      42           0 :         unsigned int i = 0;
      43             : 
      44             :         /* Add terminating zero entry to enable index less iteration */
      45           0 :         client->modesets = kcalloc(num_crtc + 1, sizeof(*client->modesets), GFP_KERNEL);
      46           0 :         if (!client->modesets)
      47             :                 return -ENOMEM;
      48             : 
      49           0 :         mutex_init(&client->modeset_mutex);
      50             : 
      51           0 :         drm_for_each_crtc(crtc, dev)
      52           0 :                 client->modesets[i++].crtc = crtc;
      53             : 
      54             :         /* Cloning is only supported in the single crtc case. */
      55           0 :         if (num_crtc == 1)
      56           0 :                 max_connector_count = DRM_CLIENT_MAX_CLONED_CONNECTORS;
      57             : 
      58           0 :         for (modeset = client->modesets; modeset->crtc; modeset++) {
      59           0 :                 modeset->connectors = kcalloc(max_connector_count,
      60             :                                               sizeof(*modeset->connectors), GFP_KERNEL);
      61           0 :                 if (!modeset->connectors)
      62             :                         goto err_free;
      63             :         }
      64             : 
      65             :         return 0;
      66             : 
      67             : err_free:
      68           0 :         drm_client_modeset_free(client);
      69             : 
      70           0 :         return -ENOMEM;
      71             : }
      72             : 
      73           0 : static void drm_client_modeset_release(struct drm_client_dev *client)
      74             : {
      75             :         struct drm_mode_set *modeset;
      76             :         unsigned int i;
      77             : 
      78           0 :         drm_client_for_each_modeset(modeset, client) {
      79           0 :                 drm_mode_destroy(client->dev, modeset->mode);
      80           0 :                 modeset->mode = NULL;
      81           0 :                 modeset->fb = NULL;
      82             : 
      83           0 :                 for (i = 0; i < modeset->num_connectors; i++) {
      84           0 :                         drm_connector_put(modeset->connectors[i]);
      85           0 :                         modeset->connectors[i] = NULL;
      86             :                 }
      87           0 :                 modeset->num_connectors = 0;
      88             :         }
      89           0 : }
      90             : 
      91           0 : void drm_client_modeset_free(struct drm_client_dev *client)
      92             : {
      93             :         struct drm_mode_set *modeset;
      94             : 
      95           0 :         mutex_lock(&client->modeset_mutex);
      96             : 
      97           0 :         drm_client_modeset_release(client);
      98             : 
      99           0 :         drm_client_for_each_modeset(modeset, client)
     100           0 :                 kfree(modeset->connectors);
     101             : 
     102           0 :         mutex_unlock(&client->modeset_mutex);
     103             : 
     104           0 :         mutex_destroy(&client->modeset_mutex);
     105           0 :         kfree(client->modesets);
     106           0 : }
     107             : 
     108             : static struct drm_mode_set *
     109             : drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc)
     110             : {
     111             :         struct drm_mode_set *modeset;
     112             : 
     113           0 :         drm_client_for_each_modeset(modeset, client)
     114           0 :                 if (modeset->crtc == crtc)
     115             :                         return modeset;
     116             : 
     117             :         return NULL;
     118             : }
     119             : 
     120             : static struct drm_display_mode *
     121             : drm_connector_get_tiled_mode(struct drm_connector *connector)
     122             : {
     123             :         struct drm_display_mode *mode;
     124             : 
     125           0 :         list_for_each_entry(mode, &connector->modes, head) {
     126           0 :                 if (mode->hdisplay == connector->tile_h_size &&
     127           0 :                     mode->vdisplay == connector->tile_v_size)
     128             :                         return mode;
     129             :         }
     130             :         return NULL;
     131             : }
     132             : 
     133             : static struct drm_display_mode *
     134             : drm_connector_fallback_non_tiled_mode(struct drm_connector *connector)
     135             : {
     136             :         struct drm_display_mode *mode;
     137             : 
     138           0 :         list_for_each_entry(mode, &connector->modes, head) {
     139           0 :                 if (mode->hdisplay == connector->tile_h_size &&
     140           0 :                     mode->vdisplay == connector->tile_v_size)
     141           0 :                         continue;
     142             :                 return mode;
     143             :         }
     144             :         return NULL;
     145             : }
     146             : 
     147             : static struct drm_display_mode *
     148             : drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height)
     149             : {
     150             :         struct drm_display_mode *mode;
     151             : 
     152           0 :         list_for_each_entry(mode, &connector->modes, head) {
     153           0 :                 if (mode->hdisplay > width ||
     154           0 :                     mode->vdisplay > height)
     155           0 :                         continue;
     156           0 :                 if (mode->type & DRM_MODE_TYPE_PREFERRED)
     157             :                         return mode;
     158             :         }
     159             :         return NULL;
     160             : }
     161             : 
     162           5 : static struct drm_display_mode *drm_connector_pick_cmdline_mode(struct drm_connector *connector)
     163             : {
     164             :         struct drm_cmdline_mode *cmdline_mode;
     165             :         struct drm_display_mode *mode;
     166             :         bool prefer_non_interlace;
     167             : 
     168             :         /*
     169             :          * Find a user-defined mode. If the user gave us a valid
     170             :          * mode on the kernel command line, it will show up in this
     171             :          * list.
     172             :          */
     173             : 
     174          95 :         list_for_each_entry(mode, &connector->modes, head) {
     175          95 :                 if (mode->type & DRM_MODE_TYPE_USERDEF)
     176             :                         return mode;
     177             :         }
     178             : 
     179           0 :         cmdline_mode = &connector->cmdline_mode;
     180           0 :         if (cmdline_mode->specified == false)
     181             :                 return NULL;
     182             : 
     183             :         /*
     184             :          * Attempt to find a matching mode in the list of modes we
     185             :          * have gotten so far.
     186             :          */
     187             : 
     188           0 :         prefer_non_interlace = !cmdline_mode->interlace;
     189             : again:
     190           0 :         list_for_each_entry(mode, &connector->modes, head) {
     191             :                 /* check width/height */
     192           0 :                 if (mode->hdisplay != cmdline_mode->xres ||
     193           0 :                     mode->vdisplay != cmdline_mode->yres)
     194           0 :                         continue;
     195             : 
     196           0 :                 if (cmdline_mode->refresh_specified) {
     197           0 :                         if (drm_mode_vrefresh(mode) != cmdline_mode->refresh)
     198           0 :                                 continue;
     199             :                 }
     200             : 
     201           0 :                 if (cmdline_mode->interlace) {
     202           0 :                         if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
     203           0 :                                 continue;
     204           0 :                 } else if (prefer_non_interlace) {
     205           0 :                         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
     206           0 :                                 continue;
     207             :                 }
     208             :                 return mode;
     209             :         }
     210             : 
     211           0 :         if (prefer_non_interlace) {
     212             :                 prefer_non_interlace = false;
     213             :                 goto again;
     214             :         }
     215             : 
     216             :         return NULL;
     217             : }
     218             : 
     219             : static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
     220             : {
     221             :         bool enable;
     222             : 
     223           0 :         if (connector->display_info.non_desktop)
     224             :                 return false;
     225             : 
     226             :         if (strict)
     227           0 :                 enable = connector->status == connector_status_connected;
     228             :         else
     229           0 :                 enable = connector->status != connector_status_disconnected;
     230             : 
     231             :         return enable;
     232             : }
     233             : 
     234           0 : static void drm_client_connectors_enabled(struct drm_connector **connectors,
     235             :                                           unsigned int connector_count,
     236             :                                           bool *enabled)
     237             : {
     238           0 :         bool any_enabled = false;
     239             :         struct drm_connector *connector;
     240           0 :         int i = 0;
     241             : 
     242           0 :         for (i = 0; i < connector_count; i++) {
     243           0 :                 connector = connectors[i];
     244           0 :                 enabled[i] = drm_connector_enabled(connector, true);
     245           0 :                 DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
     246             :                               connector->display_info.non_desktop ? "non desktop" : str_yes_no(enabled[i]));
     247             : 
     248           0 :                 any_enabled |= enabled[i];
     249             :         }
     250             : 
     251           0 :         if (any_enabled)
     252             :                 return;
     253             : 
     254           0 :         for (i = 0; i < connector_count; i++)
     255           0 :                 enabled[i] = drm_connector_enabled(connectors[i], false);
     256             : }
     257             : 
     258           0 : static bool drm_client_target_cloned(struct drm_device *dev,
     259             :                                      struct drm_connector **connectors,
     260             :                                      unsigned int connector_count,
     261             :                                      struct drm_display_mode **modes,
     262             :                                      struct drm_client_offset *offsets,
     263             :                                      bool *enabled, int width, int height)
     264             : {
     265             :         int count, i, j;
     266           0 :         bool can_clone = false;
     267             :         struct drm_display_mode *dmt_mode, *mode;
     268             : 
     269             :         /* only contemplate cloning in the single crtc case */
     270           0 :         if (dev->mode_config.num_crtc > 1)
     271             :                 return false;
     272             : 
     273             :         count = 0;
     274           0 :         for (i = 0; i < connector_count; i++) {
     275           0 :                 if (enabled[i])
     276           0 :                         count++;
     277             :         }
     278             : 
     279             :         /* only contemplate cloning if more than one connector is enabled */
     280           0 :         if (count <= 1)
     281             :                 return false;
     282             : 
     283             :         /* check the command line or if nothing common pick 1024x768 */
     284             :         can_clone = true;
     285           0 :         for (i = 0; i < connector_count; i++) {
     286           0 :                 if (!enabled[i])
     287           0 :                         continue;
     288           0 :                 modes[i] = drm_connector_pick_cmdline_mode(connectors[i]);
     289           0 :                 if (!modes[i]) {
     290             :                         can_clone = false;
     291             :                         break;
     292             :                 }
     293           0 :                 for (j = 0; j < i; j++) {
     294           0 :                         if (!enabled[j])
     295           0 :                                 continue;
     296           0 :                         if (!drm_mode_match(modes[j], modes[i],
     297             :                                             DRM_MODE_MATCH_TIMINGS |
     298             :                                             DRM_MODE_MATCH_CLOCK |
     299             :                                             DRM_MODE_MATCH_FLAGS |
     300             :                                             DRM_MODE_MATCH_3D_FLAGS))
     301           0 :                                 can_clone = false;
     302             :                 }
     303             :         }
     304             : 
     305           0 :         if (can_clone) {
     306           0 :                 DRM_DEBUG_KMS("can clone using command line\n");
     307             :                 return true;
     308             :         }
     309             : 
     310             :         /* try and find a 1024x768 mode on each connector */
     311           0 :         can_clone = true;
     312           0 :         dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
     313             : 
     314           0 :         for (i = 0; i < connector_count; i++) {
     315           0 :                 if (!enabled[i])
     316           0 :                         continue;
     317             : 
     318           0 :                 list_for_each_entry(mode, &connectors[i]->modes, head) {
     319           0 :                         if (drm_mode_match(mode, dmt_mode,
     320             :                                            DRM_MODE_MATCH_TIMINGS |
     321             :                                            DRM_MODE_MATCH_CLOCK |
     322             :                                            DRM_MODE_MATCH_FLAGS |
     323             :                                            DRM_MODE_MATCH_3D_FLAGS))
     324           0 :                                 modes[i] = mode;
     325             :                 }
     326           0 :                 if (!modes[i])
     327           0 :                         can_clone = false;
     328             :         }
     329             : 
     330           0 :         if (can_clone) {
     331           0 :                 DRM_DEBUG_KMS("can clone using 1024x768\n");
     332             :                 return true;
     333             :         }
     334           0 :         DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
     335             :         return false;
     336             : }
     337             : 
     338           0 : static int drm_client_get_tile_offsets(struct drm_connector **connectors,
     339             :                                        unsigned int connector_count,
     340             :                                        struct drm_display_mode **modes,
     341             :                                        struct drm_client_offset *offsets,
     342             :                                        int idx,
     343             :                                        int h_idx, int v_idx)
     344             : {
     345             :         struct drm_connector *connector;
     346             :         int i;
     347           0 :         int hoffset = 0, voffset = 0;
     348             : 
     349           0 :         for (i = 0; i < connector_count; i++) {
     350           0 :                 connector = connectors[i];
     351           0 :                 if (!connector->has_tile)
     352           0 :                         continue;
     353             : 
     354           0 :                 if (!modes[i] && (h_idx || v_idx)) {
     355           0 :                         DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
     356             :                                       connector->base.id);
     357           0 :                         continue;
     358             :                 }
     359           0 :                 if (connector->tile_h_loc < h_idx)
     360           0 :                         hoffset += modes[i]->hdisplay;
     361             : 
     362           0 :                 if (connector->tile_v_loc < v_idx)
     363           0 :                         voffset += modes[i]->vdisplay;
     364             :         }
     365           0 :         offsets[idx].x = hoffset;
     366           0 :         offsets[idx].y = voffset;
     367           0 :         DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx);
     368           0 :         return 0;
     369             : }
     370             : 
     371           0 : static bool drm_client_target_preferred(struct drm_connector **connectors,
     372             :                                         unsigned int connector_count,
     373             :                                         struct drm_display_mode **modes,
     374             :                                         struct drm_client_offset *offsets,
     375             :                                         bool *enabled, int width, int height)
     376             : {
     377           0 :         const u64 mask = BIT_ULL(connector_count) - 1;
     378             :         struct drm_connector *connector;
     379           0 :         u64 conn_configured = 0;
     380           0 :         int tile_pass = 0;
     381           0 :         int num_tiled_conns = 0;
     382             :         int i;
     383             : 
     384           0 :         for (i = 0; i < connector_count; i++) {
     385           0 :                 if (connectors[i]->has_tile &&
     386           0 :                     connectors[i]->status == connector_status_connected)
     387           0 :                         num_tiled_conns++;
     388             :         }
     389             : 
     390             : retry:
     391           0 :         for (i = 0; i < connector_count; i++) {
     392           0 :                 connector = connectors[i];
     393             : 
     394           0 :                 if (conn_configured & BIT_ULL(i))
     395           0 :                         continue;
     396             : 
     397           0 :                 if (enabled[i] == false) {
     398           0 :                         conn_configured |= BIT_ULL(i);
     399           0 :                         continue;
     400             :                 }
     401             : 
     402             :                 /* first pass over all the untiled connectors */
     403           0 :                 if (tile_pass == 0 && connector->has_tile)
     404           0 :                         continue;
     405             : 
     406           0 :                 if (tile_pass == 1) {
     407           0 :                         if (connector->tile_h_loc != 0 ||
     408             :                             connector->tile_v_loc != 0)
     409           0 :                                 continue;
     410             : 
     411             :                 } else {
     412           0 :                         if (connector->tile_h_loc != tile_pass - 1 &&
     413           0 :                             connector->tile_v_loc != tile_pass - 1)
     414             :                         /* if this tile_pass doesn't cover any of the tiles - keep going */
     415           0 :                                 continue;
     416             : 
     417             :                         /*
     418             :                          * find the tile offsets for this pass - need to find
     419             :                          * all tiles left and above
     420             :                          */
     421           0 :                         drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i,
     422           0 :                                                     connector->tile_h_loc, connector->tile_v_loc);
     423             :                 }
     424           0 :                 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
     425             :                               connector->base.id);
     426             : 
     427             :                 /* got for command line mode first */
     428           0 :                 modes[i] = drm_connector_pick_cmdline_mode(connector);
     429           0 :                 if (!modes[i]) {
     430           0 :                         DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n",
     431             :                                       connector->base.id, connector->tile_group ? connector->tile_group->id : 0);
     432           0 :                         modes[i] = drm_connector_has_preferred_mode(connector, width, height);
     433             :                 }
     434             :                 /* No preferred modes, pick one off the list */
     435           0 :                 if (!modes[i] && !list_empty(&connector->modes)) {
     436           0 :                         list_for_each_entry(modes[i], &connector->modes, head)
     437             :                                 break;
     438             :                 }
     439             :                 /*
     440             :                  * In case of tiled mode if all tiles not present fallback to
     441             :                  * first available non tiled mode.
     442             :                  * After all tiles are present, try to find the tiled mode
     443             :                  * for all and if tiled mode not present due to fbcon size
     444             :                  * limitations, use first non tiled mode only for
     445             :                  * tile 0,0 and set to no mode for all other tiles.
     446             :                  */
     447           0 :                 if (connector->has_tile) {
     448           0 :                         if (num_tiled_conns <
     449           0 :                             connector->num_h_tile * connector->num_v_tile ||
     450           0 :                             (connector->tile_h_loc == 0 &&
     451           0 :                              connector->tile_v_loc == 0 &&
     452           0 :                              !drm_connector_get_tiled_mode(connector))) {
     453           0 :                                 DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n",
     454             :                                               connector->base.id);
     455           0 :                                 modes[i] = drm_connector_fallback_non_tiled_mode(connector);
     456             :                         } else {
     457           0 :                                 modes[i] = drm_connector_get_tiled_mode(connector);
     458             :                         }
     459             :                 }
     460             : 
     461           0 :                 DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
     462             :                           "none");
     463           0 :                 conn_configured |= BIT_ULL(i);
     464             :         }
     465             : 
     466           0 :         if ((conn_configured & mask) != mask) {
     467           0 :                 tile_pass++;
     468           0 :                 goto retry;
     469             :         }
     470           0 :         return true;
     471             : }
     472             : 
     473             : static bool connector_has_possible_crtc(struct drm_connector *connector,
     474             :                                         struct drm_crtc *crtc)
     475             : {
     476             :         struct drm_encoder *encoder;
     477             : 
     478           0 :         drm_connector_for_each_possible_encoder(connector, encoder) {
     479           0 :                 if (encoder->possible_crtcs & drm_crtc_mask(crtc))
     480             :                         return true;
     481             :         }
     482             : 
     483             :         return false;
     484             : }
     485             : 
     486           0 : static int drm_client_pick_crtcs(struct drm_client_dev *client,
     487             :                                  struct drm_connector **connectors,
     488             :                                  unsigned int connector_count,
     489             :                                  struct drm_crtc **best_crtcs,
     490             :                                  struct drm_display_mode **modes,
     491             :                                  int n, int width, int height)
     492             : {
     493           0 :         struct drm_device *dev = client->dev;
     494             :         struct drm_connector *connector;
     495             :         int my_score, best_score, score;
     496             :         struct drm_crtc **crtcs, *crtc;
     497             :         struct drm_mode_set *modeset;
     498             :         int o;
     499             : 
     500           0 :         if (n == connector_count)
     501             :                 return 0;
     502             : 
     503           0 :         connector = connectors[n];
     504             : 
     505           0 :         best_crtcs[n] = NULL;
     506           0 :         best_score = drm_client_pick_crtcs(client, connectors, connector_count,
     507             :                                            best_crtcs, modes, n + 1, width, height);
     508           0 :         if (modes[n] == NULL)
     509             :                 return best_score;
     510             : 
     511           0 :         crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
     512           0 :         if (!crtcs)
     513             :                 return best_score;
     514             : 
     515           0 :         my_score = 1;
     516           0 :         if (connector->status == connector_status_connected)
     517           0 :                 my_score++;
     518           0 :         if (connector->cmdline_mode.specified)
     519           0 :                 my_score++;
     520           0 :         if (drm_connector_has_preferred_mode(connector, width, height))
     521           0 :                 my_score++;
     522             : 
     523             :         /*
     524             :          * select a crtc for this connector and then attempt to configure
     525             :          * remaining connectors
     526             :          */
     527           0 :         drm_client_for_each_modeset(modeset, client) {
     528           0 :                 crtc = modeset->crtc;
     529             : 
     530           0 :                 if (!connector_has_possible_crtc(connector, crtc))
     531           0 :                         continue;
     532             : 
     533           0 :                 for (o = 0; o < n; o++)
     534           0 :                         if (best_crtcs[o] == crtc)
     535             :                                 break;
     536             : 
     537           0 :                 if (o < n) {
     538             :                         /* ignore cloning unless only a single crtc */
     539           0 :                         if (dev->mode_config.num_crtc > 1)
     540           0 :                                 continue;
     541             : 
     542           0 :                         if (!drm_mode_equal(modes[o], modes[n]))
     543           0 :                                 continue;
     544             :                 }
     545             : 
     546           0 :                 crtcs[n] = crtc;
     547           0 :                 memcpy(crtcs, best_crtcs, n * sizeof(*crtcs));
     548           0 :                 score = my_score + drm_client_pick_crtcs(client, connectors, connector_count,
     549             :                                                          crtcs, modes, n + 1, width, height);
     550           0 :                 if (score > best_score) {
     551           0 :                         best_score = score;
     552           0 :                         memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs));
     553             :                 }
     554             :         }
     555             : 
     556           0 :         kfree(crtcs);
     557           0 :         return best_score;
     558             : }
     559             : 
     560             : /* Try to read the BIOS display configuration and use it for the initial config */
     561           0 : static bool drm_client_firmware_config(struct drm_client_dev *client,
     562             :                                        struct drm_connector **connectors,
     563             :                                        unsigned int connector_count,
     564             :                                        struct drm_crtc **crtcs,
     565             :                                        struct drm_display_mode **modes,
     566             :                                        struct drm_client_offset *offsets,
     567             :                                        bool *enabled, int width, int height)
     568             : {
     569           0 :         const int count = min_t(unsigned int, connector_count, BITS_PER_LONG);
     570             :         unsigned long conn_configured, conn_seq, mask;
     571           0 :         struct drm_device *dev = client->dev;
     572             :         int i, j;
     573             :         bool *save_enabled;
     574           0 :         bool fallback = true, ret = true;
     575           0 :         int num_connectors_enabled = 0;
     576           0 :         int num_connectors_detected = 0;
     577           0 :         int num_tiled_conns = 0;
     578             :         struct drm_modeset_acquire_ctx ctx;
     579             : 
     580           0 :         if (!drm_drv_uses_atomic_modeset(dev))
     581             :                 return false;
     582             : 
     583           0 :         if (WARN_ON(count <= 0))
     584             :                 return false;
     585             : 
     586           0 :         save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
     587           0 :         if (!save_enabled)
     588             :                 return false;
     589             : 
     590           0 :         drm_modeset_acquire_init(&ctx, 0);
     591             : 
     592           0 :         while (drm_modeset_lock_all_ctx(dev, &ctx) != 0)
     593           0 :                 drm_modeset_backoff(&ctx);
     594             : 
     595           0 :         memcpy(save_enabled, enabled, count);
     596           0 :         mask = GENMASK(count - 1, 0);
     597           0 :         conn_configured = 0;
     598           0 :         for (i = 0; i < count; i++) {
     599           0 :                 if (connectors[i]->has_tile &&
     600           0 :                     connectors[i]->status == connector_status_connected)
     601           0 :                         num_tiled_conns++;
     602             :         }
     603             : retry:
     604           0 :         conn_seq = conn_configured;
     605           0 :         for (i = 0; i < count; i++) {
     606             :                 struct drm_connector *connector;
     607             :                 struct drm_encoder *encoder;
     608             :                 struct drm_crtc *new_crtc;
     609             : 
     610           0 :                 connector = connectors[i];
     611             : 
     612           0 :                 if (conn_configured & BIT(i))
     613           0 :                         continue;
     614             : 
     615           0 :                 if (conn_seq == 0 && !connector->has_tile)
     616           0 :                         continue;
     617             : 
     618           0 :                 if (connector->status == connector_status_connected)
     619           0 :                         num_connectors_detected++;
     620             : 
     621           0 :                 if (!enabled[i]) {
     622           0 :                         DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
     623             :                                       connector->name);
     624           0 :                         conn_configured |= BIT(i);
     625           0 :                         continue;
     626             :                 }
     627             : 
     628           0 :                 if (connector->force == DRM_FORCE_OFF) {
     629           0 :                         DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
     630             :                                       connector->name);
     631           0 :                         enabled[i] = false;
     632           0 :                         continue;
     633             :                 }
     634             : 
     635           0 :                 encoder = connector->state->best_encoder;
     636           0 :                 if (!encoder || WARN_ON(!connector->state->crtc)) {
     637           0 :                         if (connector->force > DRM_FORCE_OFF)
     638             :                                 goto bail;
     639             : 
     640           0 :                         DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
     641             :                                       connector->name);
     642           0 :                         enabled[i] = false;
     643           0 :                         conn_configured |= BIT(i);
     644           0 :                         continue;
     645             :                 }
     646             : 
     647           0 :                 num_connectors_enabled++;
     648             : 
     649           0 :                 new_crtc = connector->state->crtc;
     650             : 
     651             :                 /*
     652             :                  * Make sure we're not trying to drive multiple connectors
     653             :                  * with a single CRTC, since our cloning support may not
     654             :                  * match the BIOS.
     655             :                  */
     656           0 :                 for (j = 0; j < count; j++) {
     657           0 :                         if (crtcs[j] == new_crtc) {
     658           0 :                                 DRM_DEBUG_KMS("fallback: cloned configuration\n");
     659             :                                 goto bail;
     660             :                         }
     661             :                 }
     662             : 
     663           0 :                 DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
     664             :                               connector->name);
     665             : 
     666             :                 /* go for command line mode first */
     667           0 :                 modes[i] = drm_connector_pick_cmdline_mode(connector);
     668             : 
     669             :                 /* try for preferred next */
     670           0 :                 if (!modes[i]) {
     671           0 :                         DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
     672             :                                       connector->name, connector->has_tile);
     673           0 :                         modes[i] = drm_connector_has_preferred_mode(connector, width, height);
     674             :                 }
     675             : 
     676             :                 /* No preferred mode marked by the EDID? Are there any modes? */
     677           0 :                 if (!modes[i] && !list_empty(&connector->modes)) {
     678           0 :                         DRM_DEBUG_KMS("using first mode listed on connector %s\n",
     679             :                                       connector->name);
     680           0 :                         modes[i] = list_first_entry(&connector->modes,
     681             :                                                     struct drm_display_mode,
     682             :                                                     head);
     683             :                 }
     684             : 
     685             :                 /* last resort: use current mode */
     686           0 :                 if (!modes[i]) {
     687             :                         /*
     688             :                          * IMPORTANT: We want to use the adjusted mode (i.e.
     689             :                          * after the panel fitter upscaling) as the initial
     690             :                          * config, not the input mode, which is what crtc->mode
     691             :                          * usually contains. But since our current
     692             :                          * code puts a mode derived from the post-pfit timings
     693             :                          * into crtc->mode this works out correctly.
     694             :                          *
     695             :                          * This is crtc->mode and not crtc->state->mode for the
     696             :                          * fastboot check to work correctly.
     697             :                          */
     698           0 :                         DRM_DEBUG_KMS("looking for current mode on connector %s\n",
     699             :                                       connector->name);
     700           0 :                         modes[i] = &connector->state->crtc->mode;
     701             :                 }
     702             :                 /*
     703             :                  * In case of tiled modes, if all tiles are not present
     704             :                  * then fallback to a non tiled mode.
     705             :                  */
     706           0 :                 if (connector->has_tile &&
     707           0 :                     num_tiled_conns < connector->num_h_tile * connector->num_v_tile) {
     708           0 :                         DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n",
     709             :                                       connector->base.id);
     710           0 :                         modes[i] = drm_connector_fallback_non_tiled_mode(connector);
     711             :                 }
     712           0 :                 crtcs[i] = new_crtc;
     713             : 
     714           0 :                 DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n",
     715             :                               connector->name,
     716             :                               connector->state->crtc->base.id,
     717             :                               connector->state->crtc->name,
     718             :                               modes[i]->hdisplay, modes[i]->vdisplay,
     719             :                               modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "");
     720             : 
     721           0 :                 fallback = false;
     722           0 :                 conn_configured |= BIT(i);
     723             :         }
     724             : 
     725           0 :         if ((conn_configured & mask) != mask && conn_configured != conn_seq)
     726             :                 goto retry;
     727             : 
     728             :         /*
     729             :          * If the BIOS didn't enable everything it could, fall back to have the
     730             :          * same user experiencing of lighting up as much as possible like the
     731             :          * fbdev helper library.
     732             :          */
     733           0 :         if (num_connectors_enabled != num_connectors_detected &&
     734           0 :             num_connectors_enabled < dev->mode_config.num_crtc) {
     735           0 :                 DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
     736           0 :                 DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
     737             :                               num_connectors_detected);
     738           0 :                 fallback = true;
     739             :         }
     740             : 
     741           0 :         if (fallback) {
     742             : bail:
     743           0 :                 DRM_DEBUG_KMS("Not using firmware configuration\n");
     744           0 :                 memcpy(enabled, save_enabled, count);
     745           0 :                 ret = false;
     746             :         }
     747             : 
     748           0 :         drm_modeset_drop_locks(&ctx);
     749           0 :         drm_modeset_acquire_fini(&ctx);
     750             : 
     751           0 :         kfree(save_enabled);
     752             :         return ret;
     753             : }
     754             : 
     755             : /**
     756             :  * drm_client_modeset_probe() - Probe for displays
     757             :  * @client: DRM client
     758             :  * @width: Maximum display mode width (optional)
     759             :  * @height: Maximum display mode height (optional)
     760             :  *
     761             :  * This function sets up display pipelines for enabled connectors and stores the
     762             :  * config in the client's modeset array.
     763             :  *
     764             :  * Returns:
     765             :  * Zero on success or negative error code on failure.
     766             :  */
     767           0 : int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height)
     768             : {
     769           0 :         struct drm_connector *connector, **connectors = NULL;
     770             :         struct drm_connector_list_iter conn_iter;
     771           0 :         struct drm_device *dev = client->dev;
     772           0 :         unsigned int total_modes_count = 0;
     773             :         struct drm_client_offset *offsets;
     774           0 :         unsigned int connector_count = 0;
     775             :         struct drm_display_mode **modes;
     776             :         struct drm_crtc **crtcs;
     777           0 :         int i, ret = 0;
     778             :         bool *enabled;
     779             : 
     780           0 :         DRM_DEBUG_KMS("\n");
     781             : 
     782           0 :         if (!width)
     783           0 :                 width = dev->mode_config.max_width;
     784           0 :         if (!height)
     785           0 :                 height = dev->mode_config.max_height;
     786             : 
     787           0 :         drm_connector_list_iter_begin(dev, &conn_iter);
     788           0 :         drm_client_for_each_connector_iter(connector, &conn_iter) {
     789             :                 struct drm_connector **tmp;
     790             : 
     791           0 :                 tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL);
     792           0 :                 if (!tmp) {
     793             :                         ret = -ENOMEM;
     794             :                         goto free_connectors;
     795             :                 }
     796             : 
     797           0 :                 connectors = tmp;
     798           0 :                 drm_connector_get(connector);
     799           0 :                 connectors[connector_count++] = connector;
     800             :         }
     801           0 :         drm_connector_list_iter_end(&conn_iter);
     802             : 
     803           0 :         if (!connector_count)
     804             :                 return 0;
     805             : 
     806           0 :         crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
     807           0 :         modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL);
     808           0 :         offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL);
     809           0 :         enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL);
     810           0 :         if (!crtcs || !modes || !enabled || !offsets) {
     811           0 :                 DRM_ERROR("Memory allocation failed\n");
     812           0 :                 ret = -ENOMEM;
     813           0 :                 goto out;
     814             :         }
     815             : 
     816           0 :         mutex_lock(&client->modeset_mutex);
     817             : 
     818           0 :         mutex_lock(&dev->mode_config.mutex);
     819           0 :         for (i = 0; i < connector_count; i++)
     820           0 :                 total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height);
     821           0 :         if (!total_modes_count)
     822           0 :                 DRM_DEBUG_KMS("No connectors reported connected with modes\n");
     823           0 :         drm_client_connectors_enabled(connectors, connector_count, enabled);
     824             : 
     825           0 :         if (!drm_client_firmware_config(client, connectors, connector_count, crtcs,
     826             :                                         modes, offsets, enabled, width, height)) {
     827           0 :                 memset(modes, 0, connector_count * sizeof(*modes));
     828           0 :                 memset(crtcs, 0, connector_count * sizeof(*crtcs));
     829           0 :                 memset(offsets, 0, connector_count * sizeof(*offsets));
     830             : 
     831           0 :                 if (!drm_client_target_cloned(dev, connectors, connector_count, modes,
     832           0 :                                               offsets, enabled, width, height) &&
     833           0 :                     !drm_client_target_preferred(connectors, connector_count, modes,
     834             :                                                  offsets, enabled, width, height))
     835           0 :                         DRM_ERROR("Unable to find initial modes\n");
     836             : 
     837           0 :                 DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
     838             :                               width, height);
     839             : 
     840           0 :                 drm_client_pick_crtcs(client, connectors, connector_count,
     841             :                                       crtcs, modes, 0, width, height);
     842             :         }
     843           0 :         mutex_unlock(&dev->mode_config.mutex);
     844             : 
     845           0 :         drm_client_modeset_release(client);
     846             : 
     847           0 :         for (i = 0; i < connector_count; i++) {
     848           0 :                 struct drm_display_mode *mode = modes[i];
     849           0 :                 struct drm_crtc *crtc = crtcs[i];
     850           0 :                 struct drm_client_offset *offset = &offsets[i];
     851             : 
     852           0 :                 if (mode && crtc) {
     853           0 :                         struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc);
     854           0 :                         struct drm_connector *connector = connectors[i];
     855             : 
     856           0 :                         DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
     857             :                                       mode->name, crtc->base.id, offset->x, offset->y);
     858             : 
     859           0 :                         if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS ||
     860             :                                          (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) {
     861             :                                 ret = -EINVAL;
     862             :                                 break;
     863             :                         }
     864             : 
     865           0 :                         modeset->mode = drm_mode_duplicate(dev, mode);
     866           0 :                         drm_connector_get(connector);
     867           0 :                         modeset->connectors[modeset->num_connectors++] = connector;
     868           0 :                         modeset->x = offset->x;
     869           0 :                         modeset->y = offset->y;
     870             :                 }
     871             :         }
     872             : 
     873           0 :         mutex_unlock(&client->modeset_mutex);
     874             : out:
     875           0 :         kfree(crtcs);
     876           0 :         kfree(modes);
     877           0 :         kfree(offsets);
     878           0 :         kfree(enabled);
     879             : free_connectors:
     880           0 :         for (i = 0; i < connector_count; i++)
     881           0 :                 drm_connector_put(connectors[i]);
     882           0 :         kfree(connectors);
     883             : 
     884           0 :         return ret;
     885             : }
     886             : EXPORT_SYMBOL(drm_client_modeset_probe);
     887             : 
     888             : /**
     889             :  * drm_client_rotation() - Check the initial rotation value
     890             :  * @modeset: DRM modeset
     891             :  * @rotation: Returned rotation value
     892             :  *
     893             :  * This function checks if the primary plane in @modeset can hw rotate
     894             :  * to match the rotation needed on its connector.
     895             :  *
     896             :  * Note: Currently only 0 and 180 degrees are supported.
     897             :  *
     898             :  * Return:
     899             :  * True if the plane can do the rotation, false otherwise.
     900             :  */
     901           0 : bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
     902             : {
     903           0 :         struct drm_connector *connector = modeset->connectors[0];
     904           0 :         struct drm_plane *plane = modeset->crtc->primary;
     905             :         struct drm_cmdline_mode *cmdline;
     906           0 :         u64 valid_mask = 0;
     907             :         unsigned int i;
     908             : 
     909           0 :         if (!modeset->num_connectors)
     910             :                 return false;
     911             : 
     912           0 :         switch (connector->display_info.panel_orientation) {
     913             :         case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP:
     914           0 :                 *rotation = DRM_MODE_ROTATE_180;
     915           0 :                 break;
     916             :         case DRM_MODE_PANEL_ORIENTATION_LEFT_UP:
     917           0 :                 *rotation = DRM_MODE_ROTATE_90;
     918           0 :                 break;
     919             :         case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP:
     920           0 :                 *rotation = DRM_MODE_ROTATE_270;
     921           0 :                 break;
     922             :         default:
     923           0 :                 *rotation = DRM_MODE_ROTATE_0;
     924             :         }
     925             : 
     926             :         /**
     927             :          * The panel already defined the default rotation
     928             :          * through its orientation. Whatever has been provided
     929             :          * on the command line needs to be added to that.
     930             :          *
     931             :          * Unfortunately, the rotations are at different bit
     932             :          * indices, so the math to add them up are not as
     933             :          * trivial as they could.
     934             :          *
     935             :          * Reflections on the other hand are pretty trivial to deal with, a
     936             :          * simple XOR between the two handle the addition nicely.
     937             :          */
     938           0 :         cmdline = &connector->cmdline_mode;
     939           0 :         if (cmdline->specified && cmdline->rotation_reflection) {
     940             :                 unsigned int cmdline_rest, panel_rest;
     941             :                 unsigned int cmdline_rot, panel_rot;
     942             :                 unsigned int sum_rot, sum_rest;
     943             : 
     944           0 :                 panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
     945           0 :                 cmdline_rot = ilog2(cmdline->rotation_reflection & DRM_MODE_ROTATE_MASK);
     946           0 :                 sum_rot = (panel_rot + cmdline_rot) % 4;
     947             : 
     948           0 :                 panel_rest = *rotation & ~DRM_MODE_ROTATE_MASK;
     949           0 :                 cmdline_rest = cmdline->rotation_reflection & ~DRM_MODE_ROTATE_MASK;
     950           0 :                 sum_rest = panel_rest ^ cmdline_rest;
     951             : 
     952           0 :                 *rotation = (1 << sum_rot) | sum_rest;
     953             :         }
     954             : 
     955             :         /*
     956             :          * TODO: support 90 / 270 degree hardware rotation,
     957             :          * depending on the hardware this may require the framebuffer
     958             :          * to be in a specific tiling format.
     959             :          */
     960           0 :         if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
     961           0 :              (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
     962           0 :             !plane->rotation_property)
     963             :                 return false;
     964             : 
     965           0 :         for (i = 0; i < plane->rotation_property->num_values; i++)
     966           0 :                 valid_mask |= (1ULL << plane->rotation_property->values[i]);
     967             : 
     968           0 :         if (!(*rotation & valid_mask))
     969             :                 return false;
     970             : 
     971           0 :         return true;
     972             : }
     973             : EXPORT_SYMBOL(drm_client_rotation);
     974             : 
     975           0 : static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active, bool check)
     976             : {
     977           0 :         struct drm_device *dev = client->dev;
     978             :         struct drm_plane *plane;
     979             :         struct drm_atomic_state *state;
     980             :         struct drm_modeset_acquire_ctx ctx;
     981             :         struct drm_mode_set *mode_set;
     982             :         int ret;
     983             : 
     984           0 :         drm_modeset_acquire_init(&ctx, 0);
     985             : 
     986           0 :         state = drm_atomic_state_alloc(dev);
     987           0 :         if (!state) {
     988             :                 ret = -ENOMEM;
     989             :                 goto out_ctx;
     990             :         }
     991             : 
     992           0 :         state->acquire_ctx = &ctx;
     993             : retry:
     994           0 :         drm_for_each_plane(plane, dev) {
     995             :                 struct drm_plane_state *plane_state;
     996             : 
     997           0 :                 plane_state = drm_atomic_get_plane_state(state, plane);
     998           0 :                 if (IS_ERR(plane_state)) {
     999           0 :                         ret = PTR_ERR(plane_state);
    1000           0 :                         goto out_state;
    1001             :                 }
    1002             : 
    1003           0 :                 plane_state->rotation = DRM_MODE_ROTATE_0;
    1004             : 
    1005             :                 /* disable non-primary: */
    1006           0 :                 if (plane->type == DRM_PLANE_TYPE_PRIMARY)
    1007           0 :                         continue;
    1008             : 
    1009           0 :                 ret = __drm_atomic_helper_disable_plane(plane, plane_state);
    1010           0 :                 if (ret != 0)
    1011             :                         goto out_state;
    1012             :         }
    1013             : 
    1014           0 :         drm_client_for_each_modeset(mode_set, client) {
    1015           0 :                 struct drm_plane *primary = mode_set->crtc->primary;
    1016             :                 unsigned int rotation;
    1017             : 
    1018           0 :                 if (drm_client_rotation(mode_set, &rotation)) {
    1019             :                         struct drm_plane_state *plane_state;
    1020             : 
    1021             :                         /* Cannot fail as we've already gotten the plane state above */
    1022           0 :                         plane_state = drm_atomic_get_new_plane_state(state, primary);
    1023           0 :                         plane_state->rotation = rotation;
    1024             :                 }
    1025             : 
    1026           0 :                 ret = __drm_atomic_helper_set_config(mode_set, state);
    1027           0 :                 if (ret != 0)
    1028             :                         goto out_state;
    1029             : 
    1030             :                 /*
    1031             :                  * __drm_atomic_helper_set_config() sets active when a
    1032             :                  * mode is set, unconditionally clear it if we force DPMS off
    1033             :                  */
    1034           0 :                 if (!active) {
    1035           0 :                         struct drm_crtc *crtc = mode_set->crtc;
    1036           0 :                         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
    1037             : 
    1038           0 :                         crtc_state->active = false;
    1039             :                 }
    1040             :         }
    1041             : 
    1042           0 :         if (check)
    1043           0 :                 ret = drm_atomic_check_only(state);
    1044             :         else
    1045           0 :                 ret = drm_atomic_commit(state);
    1046             : 
    1047             : out_state:
    1048           0 :         if (ret == -EDEADLK)
    1049             :                 goto backoff;
    1050             : 
    1051             :         drm_atomic_state_put(state);
    1052             : out_ctx:
    1053           0 :         drm_modeset_drop_locks(&ctx);
    1054           0 :         drm_modeset_acquire_fini(&ctx);
    1055             : 
    1056           0 :         return ret;
    1057             : 
    1058             : backoff:
    1059           0 :         drm_atomic_state_clear(state);
    1060           0 :         drm_modeset_backoff(&ctx);
    1061             : 
    1062           0 :         goto retry;
    1063             : }
    1064             : 
    1065           0 : static int drm_client_modeset_commit_legacy(struct drm_client_dev *client)
    1066             : {
    1067           0 :         struct drm_device *dev = client->dev;
    1068             :         struct drm_mode_set *mode_set;
    1069             :         struct drm_plane *plane;
    1070           0 :         int ret = 0;
    1071             : 
    1072           0 :         drm_modeset_lock_all(dev);
    1073           0 :         drm_for_each_plane(plane, dev) {
    1074           0 :                 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
    1075           0 :                         drm_plane_force_disable(plane);
    1076             : 
    1077           0 :                 if (plane->rotation_property)
    1078           0 :                         drm_mode_plane_set_obj_prop(plane,
    1079             :                                                     plane->rotation_property,
    1080             :                                                     DRM_MODE_ROTATE_0);
    1081             :         }
    1082             : 
    1083           0 :         drm_client_for_each_modeset(mode_set, client) {
    1084           0 :                 struct drm_crtc *crtc = mode_set->crtc;
    1085             : 
    1086           0 :                 if (crtc->funcs->cursor_set2) {
    1087           0 :                         ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
    1088           0 :                         if (ret)
    1089             :                                 goto out;
    1090           0 :                 } else if (crtc->funcs->cursor_set) {
    1091           0 :                         ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
    1092           0 :                         if (ret)
    1093             :                                 goto out;
    1094             :                 }
    1095             : 
    1096           0 :                 ret = drm_mode_set_config_internal(mode_set);
    1097           0 :                 if (ret)
    1098             :                         goto out;
    1099             :         }
    1100             : out:
    1101           0 :         drm_modeset_unlock_all(dev);
    1102             : 
    1103           0 :         return ret;
    1104             : }
    1105             : 
    1106             : /**
    1107             :  * drm_client_modeset_check() - Check modeset configuration
    1108             :  * @client: DRM client
    1109             :  *
    1110             :  * Check modeset configuration.
    1111             :  *
    1112             :  * Returns:
    1113             :  * Zero on success or negative error code on failure.
    1114             :  */
    1115           0 : int drm_client_modeset_check(struct drm_client_dev *client)
    1116             : {
    1117             :         int ret;
    1118             : 
    1119           0 :         if (!drm_drv_uses_atomic_modeset(client->dev))
    1120             :                 return 0;
    1121             : 
    1122           0 :         mutex_lock(&client->modeset_mutex);
    1123           0 :         ret = drm_client_modeset_commit_atomic(client, true, true);
    1124           0 :         mutex_unlock(&client->modeset_mutex);
    1125             : 
    1126           0 :         return ret;
    1127             : }
    1128             : EXPORT_SYMBOL(drm_client_modeset_check);
    1129             : 
    1130             : /**
    1131             :  * drm_client_modeset_commit_locked() - Force commit CRTC configuration
    1132             :  * @client: DRM client
    1133             :  *
    1134             :  * Commit modeset configuration to crtcs without checking if there is a DRM
    1135             :  * master. The assumption is that the caller already holds an internal DRM
    1136             :  * master reference acquired with drm_master_internal_acquire().
    1137             :  *
    1138             :  * Returns:
    1139             :  * Zero on success or negative error code on failure.
    1140             :  */
    1141           0 : int drm_client_modeset_commit_locked(struct drm_client_dev *client)
    1142             : {
    1143           0 :         struct drm_device *dev = client->dev;
    1144             :         int ret;
    1145             : 
    1146           0 :         mutex_lock(&client->modeset_mutex);
    1147           0 :         if (drm_drv_uses_atomic_modeset(dev))
    1148           0 :                 ret = drm_client_modeset_commit_atomic(client, true, false);
    1149             :         else
    1150           0 :                 ret = drm_client_modeset_commit_legacy(client);
    1151           0 :         mutex_unlock(&client->modeset_mutex);
    1152             : 
    1153           0 :         return ret;
    1154             : }
    1155             : EXPORT_SYMBOL(drm_client_modeset_commit_locked);
    1156             : 
    1157             : /**
    1158             :  * drm_client_modeset_commit() - Commit CRTC configuration
    1159             :  * @client: DRM client
    1160             :  *
    1161             :  * Commit modeset configuration to crtcs.
    1162             :  *
    1163             :  * Returns:
    1164             :  * Zero on success or negative error code on failure.
    1165             :  */
    1166           0 : int drm_client_modeset_commit(struct drm_client_dev *client)
    1167             : {
    1168           0 :         struct drm_device *dev = client->dev;
    1169             :         int ret;
    1170             : 
    1171           0 :         if (!drm_master_internal_acquire(dev))
    1172             :                 return -EBUSY;
    1173             : 
    1174           0 :         ret = drm_client_modeset_commit_locked(client);
    1175             : 
    1176           0 :         drm_master_internal_release(dev);
    1177             : 
    1178           0 :         return ret;
    1179             : }
    1180             : EXPORT_SYMBOL(drm_client_modeset_commit);
    1181             : 
    1182           0 : static void drm_client_modeset_dpms_legacy(struct drm_client_dev *client, int dpms_mode)
    1183             : {
    1184           0 :         struct drm_device *dev = client->dev;
    1185             :         struct drm_connector *connector;
    1186             :         struct drm_mode_set *modeset;
    1187             :         struct drm_modeset_acquire_ctx ctx;
    1188             :         int j;
    1189             :         int ret;
    1190             : 
    1191           0 :         DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
    1192           0 :         drm_client_for_each_modeset(modeset, client) {
    1193           0 :                 if (!modeset->crtc->enabled)
    1194           0 :                         continue;
    1195             : 
    1196           0 :                 for (j = 0; j < modeset->num_connectors; j++) {
    1197           0 :                         connector = modeset->connectors[j];
    1198           0 :                         connector->funcs->dpms(connector, dpms_mode);
    1199           0 :                         drm_object_property_set_value(&connector->base,
    1200             :                                 dev->mode_config.dpms_property, dpms_mode);
    1201             :                 }
    1202             :         }
    1203           0 :         DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
    1204           0 : }
    1205             : 
    1206             : /**
    1207             :  * drm_client_modeset_dpms() - Set DPMS mode
    1208             :  * @client: DRM client
    1209             :  * @mode: DPMS mode
    1210             :  *
    1211             :  * Note: For atomic drivers @mode is reduced to on/off.
    1212             :  *
    1213             :  * Returns:
    1214             :  * Zero on success or negative error code on failure.
    1215             :  */
    1216           0 : int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
    1217             : {
    1218           0 :         struct drm_device *dev = client->dev;
    1219           0 :         int ret = 0;
    1220             : 
    1221           0 :         if (!drm_master_internal_acquire(dev))
    1222             :                 return -EBUSY;
    1223             : 
    1224           0 :         mutex_lock(&client->modeset_mutex);
    1225           0 :         if (drm_drv_uses_atomic_modeset(dev))
    1226           0 :                 ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON, false);
    1227             :         else
    1228           0 :                 drm_client_modeset_dpms_legacy(client, mode);
    1229           0 :         mutex_unlock(&client->modeset_mutex);
    1230             : 
    1231           0 :         drm_master_internal_release(dev);
    1232             : 
    1233           0 :         return ret;
    1234             : }
    1235             : EXPORT_SYMBOL(drm_client_modeset_dpms);
    1236             : 
    1237             : #ifdef CONFIG_DRM_KUNIT_TEST
    1238             : #include "tests/drm_client_modeset_test.c"
    1239             : #endif

Generated by: LCOV version 1.14