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