radeon: remove unused legacy state
[platform/upstream/libdrm.git] / linux-core / drm_crtc_helper.c
1 /* (c) 2006-2007 Intel Corporation
2  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
3  *
4  * DRM core CRTC related functions
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that copyright
9  * notice and this permission notice appear in supporting documentation, and
10  * that the name of the copyright holders not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  The copyright holders make no representations
13  * about the suitability of this software for any purpose.  It is provided "as
14  * is" without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  *
24  * Authors:
25  *      Keith Packard
26  *      Eric Anholt <eric@anholt.net>
27  *      Dave Airlie <airlied@linux.ie>
28  *      Jesse Barnes <jesse.barnes@intel.com>
29  */
30
31 #include "drmP.h"
32 #include "drm_crtc.h"
33 #include "drm_crtc_helper.h"
34
35 /*
36  * Detailed mode info for a standard 640x480@60Hz monitor
37  */
38 static struct drm_display_mode std_mode[] = {
39         { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
40                    752, 800, 0, 480, 490, 492, 525, 0,
41                    DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */
42 };
43
44 /**
45  * drm_helper_probe_connector_modes - get complete set of display modes
46  * @dev: DRM device
47  * @maxX: max width for modes
48  * @maxY: max height for modes
49  *
50  * LOCKING:
51  * Caller must hold mode config lock.
52  *
53  * Based on @dev's mode_config layout, scan all the connectors and try to detect
54  * modes on them.  Modes will first be added to the connector's probed_modes
55  * list, then culled (based on validity and the @maxX, @maxY parameters) and
56  * put into the normal modes list.
57  *
58  * Intended to be used either at bootup time or when major configuration
59  * changes have occurred.
60  *
61  * FIXME: take into account monitor limits
62  */
63 void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY)
64 {
65         struct drm_device *dev = connector->dev;
66         struct drm_display_mode *mode, *t;
67         struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
68         int ret;
69
70         DRM_DEBUG("%s\n", drm_get_connector_name(connector));
71         /* set all modes to the unverified state */
72         list_for_each_entry_safe(mode, t, &connector->modes, head)
73                 mode->status = MODE_UNVERIFIED;
74                 
75         connector->status = (*connector->funcs->detect)(connector);
76         
77         if (connector->status == connector_status_disconnected) {
78                 DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(connector));
79                 /* TODO set EDID to NULL */
80                 return;
81         }
82         
83         ret = (*connector_funcs->get_modes)(connector);
84         
85         if (ret) {
86                 drm_mode_connector_list_update(connector);
87         }
88         
89         if (maxX && maxY)
90                 drm_mode_validate_size(dev, &connector->modes, maxX,
91                                        maxY, 0);
92         list_for_each_entry_safe(mode, t, &connector->modes, head) {
93                 if (mode->status == MODE_OK)
94                         mode->status = (*connector_funcs->mode_valid)(connector,mode);
95         }
96         
97         
98         drm_mode_prune_invalid(dev, &connector->modes, true);
99         
100         if (list_empty(&connector->modes)) {
101                 struct drm_display_mode *stdmode;
102                 
103                 DRM_DEBUG("No valid modes on %s\n", drm_get_connector_name(connector));
104                 
105                 /* Should we do this here ???
106                  * When no valid EDID modes are available we end up
107                  * here and bailed in the past, now we add a standard
108                  * 640x480@60Hz mode and carry on.
109                  */
110                 stdmode = drm_mode_duplicate(dev, &std_mode[0]);
111                 drm_mode_probed_add(connector, stdmode);
112                 drm_mode_list_concat(&connector->probed_modes,
113                                      &connector->modes);
114                 
115                 DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
116                           drm_get_connector_name(connector));
117         }
118         
119         drm_mode_sort(&connector->modes);
120         
121         DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector));
122         list_for_each_entry_safe(mode, t, &connector->modes, head) {
123                 mode->vrefresh = drm_mode_vrefresh(mode);
124                 
125                 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
126                 drm_mode_debug_printmodeline(mode);
127         }
128 }
129 EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
130
131 void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, uint32_t maxY)
132 {
133         struct drm_connector *connector;
134
135         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
136                 drm_helper_probe_single_connector_modes(connector, maxX, maxY);
137         }
138 }
139 EXPORT_SYMBOL(drm_helper_probe_connector_modes);
140
141
142 /**
143  * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
144  * @crtc: CRTC to check
145  *
146  * LOCKING:
147  * Caller must hold mode config lock.
148  *
149  * Walk @crtc's DRM device's mode_config and see if it's in use.
150  *
151  * RETURNS:
152  * True if @crtc is part of the mode_config, false otherwise.
153  */
154 bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
155 {
156         struct drm_encoder *encoder;
157         struct drm_device *dev = crtc->dev;
158         /* FIXME: Locking around list access? */
159         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
160                 if (encoder->crtc == crtc)
161                         return true;
162         return false;
163 }
164 EXPORT_SYMBOL(drm_helper_crtc_in_use);
165
166 /**
167  * drm_disable_unused_functions - disable unused objects
168  * @dev: DRM device
169  *
170  * LOCKING:
171  * Caller must hold mode config lock.
172  *
173  * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
174  * by calling its dpms function, which should power it off.
175  */
176 void drm_helper_disable_unused_functions(struct drm_device *dev)
177 {
178         struct drm_encoder *encoder;
179         struct drm_encoder_helper_funcs *encoder_funcs;
180         struct drm_crtc *crtc;
181
182         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
183                 encoder_funcs = encoder->helper_private;
184                 if (!encoder->crtc)
185                         (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
186         }
187
188         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
189                 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
190                 crtc->enabled = drm_helper_crtc_in_use(crtc);
191                 if (!crtc->enabled) {
192                         crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
193                         crtc->fb = NULL;
194                 }
195         }
196 }
197 EXPORT_SYMBOL(drm_helper_disable_unused_functions);
198
199 /**
200  * drm_pick_crtcs - pick crtcs for connector devices
201  * @dev: DRM device
202  *
203  * LOCKING:
204  * Caller must hold mode config lock.
205  */
206 void drm_pick_crtcs (struct drm_device *dev)
207 {
208         int c, o, assigned;
209         struct drm_connector *connector, *connector_equal;
210         struct drm_encoder *encoder, *encoder_equal;
211         struct drm_crtc   *crtc;
212         struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
213         struct drm_connector_helper_funcs *connector_funcs;
214         int found;
215
216         DRM_DEBUG("\n");
217         /* clean out all the encoder/crtc combos */
218         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
219                 encoder->crtc = NULL;
220         }
221         
222         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
223                 connector_funcs = connector->helper_private;
224                 connector->encoder = NULL;
225
226                 /* Don't hook up connectors that are disconnected ??
227                  *
228                  * This is debateable. Do we want fixed /dev/fbX or
229                  * dynamic on hotplug (need mode code for that though) ?
230                  *
231                  * If we don't hook up connectors now, then we only create
232                  * /dev/fbX for the connector that's enabled, that's good as
233                  * the users console will be on that connector.
234                  *
235                  * If we do hook up connectors that are disconnected now, then
236                  * the user may end up having to muck about with the fbcon
237                  * map flags to assign his console to the enabled connector. Ugh.
238                  */
239                 if (connector->status != connector_status_connected)
240                         continue;
241
242                 if (list_empty(&connector->modes))
243                         continue;
244
245                 des_mode = NULL;
246                 found = 0;
247                 list_for_each_entry(des_mode, &connector->modes, head) {
248                         if (des_mode->type & DRM_MODE_TYPE_PREFERRED) {
249                                 found = 1;
250                                 break;
251                         }
252                 }
253
254                 /* No preferred mode, let's just select the first available */
255                 if (!found) {
256                         des_mode = NULL;
257                         list_for_each_entry(des_mode, &connector->modes, head) {
258                                 break;
259                         }
260                 }
261
262                 encoder = connector_funcs->best_encoder(connector);
263                 if (!encoder)
264                         continue;
265
266                 connector->encoder = encoder;
267
268                 c = -1;
269                 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
270                         assigned = 0;
271
272                         c++;
273                         if ((encoder->possible_crtcs & (1 << c)) == 0)
274                                 continue;
275         
276                         list_for_each_entry(encoder_equal, &dev->mode_config.encoder_list, head) {
277                                 if (encoder->base.id == encoder_equal->base.id)
278                                         continue;
279
280                                 /* Find out if crtc has been assigned before */
281                                 if (encoder_equal->crtc == crtc)
282                                         assigned = 1;
283                         }
284
285 #if 1 /* continue for now */
286                         if (assigned)
287                                 continue;
288 #endif
289
290                         o = -1;
291                         list_for_each_entry(connector_equal, &dev->mode_config.connector_list, head) {
292                                 o++;
293                                 if (connector->base.id == connector_equal->base.id)
294                                         continue;
295
296                                 encoder_equal = connector_equal->encoder;
297
298                                 if (!encoder_equal)
299                                         continue;
300
301                                 list_for_each_entry(modes, &connector->modes, head) {
302                                         list_for_each_entry(modes_equal, &connector_equal->modes, head) {
303                                                 if (drm_mode_equal (modes, modes_equal)) {
304                                                         if ((encoder->possible_clones & encoder_equal->possible_clones) && (connector_equal->encoder->crtc == crtc)) {
305                                                                 printk("Cloning %s (0x%x) to %s (0x%x)\n",drm_get_connector_name(connector),encoder->possible_clones,drm_get_connector_name(connector_equal),encoder_equal->possible_clones);
306                                                                 des_mode = modes;
307                                                                 assigned = 0;
308                                                                 goto clone;
309                                                         }
310                                                 }
311                                         }
312                                 }
313                         }
314
315 clone:
316                         /* crtc has been assigned skip it */
317                         if (assigned)
318                                 continue;
319
320                         /* Found a CRTC to attach to, do it ! */
321                         encoder->crtc = crtc;
322                         encoder->crtc->desired_mode = des_mode;
323                         connector->initial_x = 0;
324                         connector->initial_y = 0;
325                         DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->base.id, des_mode->name);
326                         break;
327                 }
328         }
329 }
330 EXPORT_SYMBOL(drm_pick_crtcs);
331
332 /**
333  * drm_crtc_set_mode - set a mode
334  * @crtc: CRTC to program
335  * @mode: mode to use
336  * @x: width of mode
337  * @y: height of mode
338  *
339  * LOCKING:
340  * Caller must hold mode config lock.
341  *
342  * Try to set @mode on @crtc.  Give @crtc and its associated connectors a chance
343  * to fixup or reject the mode prior to trying to set it.
344  *
345  * RETURNS:
346  * True if the mode was set successfully, or false otherwise.
347  */
348 bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
349                               int x, int y)
350 {
351         struct drm_device *dev = crtc->dev;
352         struct drm_display_mode *adjusted_mode, saved_mode;
353         struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
354         struct drm_encoder_helper_funcs *encoder_funcs;
355         int saved_x, saved_y;
356         struct drm_encoder *encoder;
357         bool ret = true;
358
359         adjusted_mode = drm_mode_duplicate(dev, mode);
360
361         crtc->enabled = drm_helper_crtc_in_use(crtc);
362
363         if (!crtc->enabled)
364                 return true;
365
366         saved_mode = crtc->mode;
367         saved_x = crtc->x;
368         saved_y = crtc->y;
369         
370         /* Update crtc values up front so the driver can rely on them for mode
371          * setting.
372          */
373         crtc->mode = *mode;
374         crtc->x = x;
375         crtc->y = y;
376
377         if (drm_mode_equal(&saved_mode, &crtc->mode)) {
378                 if (saved_x != crtc->x || saved_y != crtc->y) {
379                         crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y);
380                         goto done;
381                 }
382         }
383
384         /* Pass our mode to the connectors and the CRTC to give them a chance to
385          * adjust it according to limitations or connector properties, and also
386          * a chance to reject the mode entirely.
387          */
388         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
389                 
390                 if (encoder->crtc != crtc)
391                         continue;
392                 encoder_funcs = encoder->helper_private;
393                 if (!(ret = encoder_funcs->mode_fixup(encoder, mode, adjusted_mode))) {
394                         goto done;
395                 }
396         }
397         
398         if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
399                 goto done;
400         }
401
402         /* Prepare the encoders and CRTCs before setting the mode. */
403         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
404
405                 if (encoder->crtc != crtc)
406                         continue;
407                 encoder_funcs = encoder->helper_private;
408                 /* Disable the encoders as the first thing we do. */
409                 encoder_funcs->prepare(encoder);
410         }
411         
412         crtc_funcs->prepare(crtc);
413         
414         /* Set up the DPLL and any encoders state that needs to adjust or depend
415          * on the DPLL.
416          */
417         crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y);
418
419         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
420
421                 if (encoder->crtc != crtc)
422                         continue;
423                 
424                 DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder), mode->name, mode->base.id);
425                 encoder_funcs = encoder->helper_private;
426                 encoder_funcs->mode_set(encoder, mode, adjusted_mode);
427         }
428         
429         /* Now, enable the clocks, plane, pipe, and connectors that we set up. */
430         crtc_funcs->commit(crtc);
431
432         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
433
434                 if (encoder->crtc != crtc)
435                         continue;
436
437                 encoder_funcs = encoder->helper_private;
438                 encoder_funcs->commit(encoder);
439
440         }
441         
442         /* XXX free adjustedmode */
443         drm_mode_destroy(dev, adjusted_mode);
444         /* TODO */
445 //      if (scrn->pScreen)
446 //              drm_crtc_set_screen_sub_pixel_order(dev);
447
448 done:
449         if (!ret) { 
450                 crtc->mode = saved_mode;
451                 crtc->x = saved_x;
452                 crtc->y = saved_y;
453         }
454
455         return ret;
456 }
457 EXPORT_SYMBOL(drm_crtc_helper_set_mode);
458
459
460 /**
461  * drm_crtc_helper_set_config - set a new config from userspace
462  * @crtc: CRTC to setup
463  * @crtc_info: user provided configuration
464  * @new_mode: new mode to set
465  * @connector_set: set of connectors for the new config
466  * @fb: new framebuffer
467  *
468  * LOCKING:
469  * Caller must hold mode config lock.
470  *
471  * Setup a new configuration, provided by the user in @crtc_info, and enable
472  * it.
473  *
474  * RETURNS:
475  * Zero. (FIXME)
476  */
477 int drm_crtc_helper_set_config(struct drm_mode_set *set)
478 {
479         struct drm_device *dev;
480         struct drm_crtc **save_crtcs, *new_crtc;
481         struct drm_encoder **save_encoders, *new_encoder;
482         bool save_enabled;
483         bool changed = false;
484         bool flip_or_move = false;
485         struct drm_connector *connector;
486         int count = 0, ro, fail = 0;
487         struct drm_crtc_helper_funcs *crtc_funcs;
488         int ret = 0;
489
490         DRM_DEBUG("\n");
491
492         if (!set)
493                 return -EINVAL;
494
495         if (!set->crtc)
496                 return -EINVAL;
497
498         if (!set->crtc->helper_private)
499                 return -EINVAL;
500         
501         crtc_funcs = set->crtc->helper_private;
502        
503         DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %i (x, y) (%i, %i)\n", set->crtc, set->crtc->base.id, set->fb, set->connectors, set->num_connectors, set->x, set->y);
504
505         dev = set->crtc->dev;
506
507         /* save previous config */
508         save_enabled = set->crtc->enabled;
509
510         /* this is meant to be num_connector not num_crtc */
511         save_crtcs = kzalloc(dev->mode_config.num_connector * sizeof(struct drm_crtc *), GFP_KERNEL);
512         if (!save_crtcs)
513                 return -ENOMEM;
514
515         save_encoders = kzalloc(dev->mode_config.num_connector * sizeof(struct drm_encoders *), GFP_KERNEL);
516         if (!save_encoders) {
517                 kfree(save_crtcs);
518                 return -ENOMEM;
519         }
520
521         /* We should be able to check here if the fb has the same properties
522          * and then just flip_or_move it */
523         if (set->crtc->fb != set->fb) {
524                 /* if we have no fb then its a change not a flip */
525                 if (set->crtc->fb == NULL)
526                         changed = true;
527                 else
528                         flip_or_move = true;
529         }
530
531         if (set->x != set->crtc->x || set->y != set->crtc->y)
532                 flip_or_move = true;
533
534         if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
535                 DRM_DEBUG("modes are different\n");
536                 drm_mode_debug_printmodeline(&set->crtc->mode);
537                 drm_mode_debug_printmodeline(set->mode);
538                 changed = true;
539         }
540
541         /* a) traverse passed in connector list and get encoders for them */
542         count = 0;
543         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
544                 struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
545                 save_encoders[count++] = connector->encoder;
546                 new_encoder = connector->encoder;
547                 for (ro = 0; ro < set->num_connectors; ro++) {
548                         if (set->connectors[ro] == connector) {
549                                 new_encoder = connector_funcs->best_encoder(connector);
550                                 /* if we can't get an encoder for a connector
551                                    we are setting now - then fail */
552                                 if (new_encoder == NULL)
553                                         /* don't break so fail path works correct */
554                                         fail = 1;
555                                 break;
556                         }
557                 }
558
559                 if (new_encoder != connector->encoder) {
560                         changed = true;
561                         connector->encoder = new_encoder;
562                 }
563         }
564
565         if (fail) {
566                 ret = -EINVAL;
567                 goto fail_no_encoder;
568         }
569
570         count = 0;
571         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
572                 if (!connector->encoder)
573                         continue;
574
575                 save_crtcs[count++] = connector->encoder->crtc;
576
577                 if (connector->encoder->crtc == set->crtc)
578                         new_crtc = NULL;
579                 else
580                         new_crtc = connector->encoder->crtc;
581
582                 for (ro = 0; ro < set->num_connectors; ro++) {
583                         if (set->connectors[ro] == connector)
584                                 new_crtc = set->crtc;
585                 }
586                 if (new_crtc != connector->encoder->crtc) {
587                         changed = true;
588                         connector->encoder->crtc = new_crtc;
589                 }
590         }
591
592         /* mode_set_base is not a required function */
593         if (flip_or_move && !crtc_funcs->mode_set_base)
594                 changed = true;
595
596         if (changed) {
597                 set->crtc->fb = set->fb;
598                 set->crtc->enabled = (set->mode != NULL);
599                 if (set->mode != NULL) {
600                         DRM_DEBUG("attempting to set mode from userspace\n");
601                         drm_mode_debug_printmodeline(set->mode);
602                         if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x,
603                                                       set->y)) {
604                                 ret = -EINVAL;
605                                 goto fail_set_mode;
606                         }
607                         /* TODO are these needed? */
608                         set->crtc->desired_x = set->x;
609                         set->crtc->desired_y = set->y;
610                         set->crtc->desired_mode = set->mode;
611                 }
612                 drm_helper_disable_unused_functions(dev);
613         } else if (flip_or_move) {
614                 if (set->crtc->fb != set->fb)
615                         set->crtc->fb = set->fb;
616                 crtc_funcs->mode_set_base(set->crtc, set->x, set->y);
617         }
618
619         kfree(save_encoders);
620         kfree(save_crtcs);
621         return 0;
622
623 fail_set_mode:
624         set->crtc->enabled = save_enabled;
625         count = 0;
626         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
627                 connector->encoder->crtc = save_crtcs[count++];
628 fail_no_encoder:
629         kfree(save_crtcs);
630         count = 0;
631         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
632                 connector->encoder = save_encoders[count++];
633         }
634         kfree(save_encoders);
635         return ret;
636                 
637         
638 }
639 EXPORT_SYMBOL(drm_crtc_helper_set_config);
640
641 bool drm_helper_plugged_event(struct drm_device *dev)
642 {
643         DRM_DEBUG("\n");
644
645         drm_helper_probe_connector_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);
646
647         drm_pick_crtcs(dev);
648
649         /* alert the driver fb layer */
650         dev->mode_config.funcs->fb_changed(dev);
651
652         drm_helper_disable_unused_functions(dev);
653
654         drm_sysfs_hotplug_event(dev);
655         return true;
656 }
657 /**
658  * drm_initial_config - setup a sane initial connector configuration
659  * @dev: DRM device
660  * @can_grow: this configuration is growable
661  *
662  * LOCKING:
663  * Called at init time, must take mode config lock.
664  *
665  * Scan the CRTCs and connectors and try to put together an initial setup.
666  * At the moment, this is a cloned configuration across all heads with
667  * a new framebuffer object as the backing store.
668  *
669  * RETURNS:
670  * Zero if everything went ok, nonzero otherwise.
671  */
672 bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
673 {
674         int ret = false;
675
676         drm_helper_plugged_event(dev);
677         return ret;
678 }
679 EXPORT_SYMBOL(drm_helper_initial_config);
680
681 /**
682  * drm_hotplug_stage_two
683  * @dev DRM device
684  * @connector hotpluged connector
685  *
686  * LOCKING.
687  * Caller must hold mode config lock, function might grab struct lock.
688  *
689  * Stage two of a hotplug.
690  *
691  * RETURNS:
692  * Zero on success, errno on failure.
693  */
694 int drm_helper_hotplug_stage_two(struct drm_device *dev)
695 {
696         dev->mode_config.hotplug_counter++;
697
698         drm_helper_plugged_event(dev);
699
700         return 0;
701 }
702 EXPORT_SYMBOL(drm_helper_hotplug_stage_two);
703
704 int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
705                                    struct drm_mode_fb_cmd *mode_cmd)
706 {
707         fb->width = mode_cmd->width;
708         fb->height = mode_cmd->height;
709         fb->pitch = mode_cmd->pitch;
710         fb->bits_per_pixel = mode_cmd->bpp;
711         fb->depth = mode_cmd->depth;
712         fb->mm_handle = mode_cmd->handle;
713         
714         return 0;
715 }
716 EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
717
718