OSDN Git Service

Changed mode config spinlock to mutex
[android-x86/external-libdrm.git] / linux-core / drm_crtc.c
1 /*
2  * Copyright (c) 2006-2007 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 #include <linux/list.h>
32 #include "drm.h"
33 #include "drmP.h"
34 #include "drm_crtc.h"
35
36 /**
37  * drm_idr_get - allocate a new identifier
38  * @dev: DRM device
39  * @ptr: object pointer, used to generate unique ID
40  *
41  * LOCKING:
42  * Caller must hold DRM mode_config lock.
43  *
44  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
45  * for tracking modes, CRTCs and outputs.
46  *
47  * RETURNS:
48  * New unique (relative to other objects in @dev) integer identifier for the
49  * object.
50  */
51 int drm_idr_get(struct drm_device *dev, void *ptr)
52 {
53         int new_id = 0;
54         int ret;
55 again:
56         if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
57                 DRM_ERROR("Ran out memory getting a mode number\n");
58                 return 0;
59         }
60
61         ret = idr_get_new_above(&dev->mode_config.crtc_idr, ptr, 1, &new_id);
62         if (ret == -EAGAIN)
63                 goto again;     
64
65         return new_id;
66 }
67
68 /**
69  * drm_idr_put - free an identifer
70  * @dev: DRM device
71  * @id: ID to free
72  *
73  * LOCKING:
74  * Caller must hold DRM mode_config lock.
75  *
76  * Free @id from @dev's unique identifier pool.
77  */
78 void drm_idr_put(struct drm_device *dev, int id)
79 {
80         idr_remove(&dev->mode_config.crtc_idr, id);
81 }
82
83 /**
84  * drm_crtc_from_fb - find the CRTC structure associated with an fb
85  * @dev: DRM device
86  * @fb: framebuffer in question
87  *
88  * LOCKING:
89  * Caller must hold mode_config lock.
90  *
91  * Find CRTC in the mode_config structure that matches @fb.
92  *
93  * RETURNS:
94  * Pointer to the CRTC or NULL if it wasn't found.
95  */
96 struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
97                                   struct drm_framebuffer *fb)
98 {
99         struct drm_crtc *crtc;
100
101         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
102                 if (crtc->fb == fb)
103                         return crtc;
104         }
105         return NULL;
106 }
107
108 /**
109  * drm_framebuffer_create - create a new framebuffer object
110  * @dev: DRM device
111  *
112  * LOCKING:
113  * Caller must hold mode config lock.
114  *
115  * Creates a new framebuffer objects and adds it to @dev's DRM mode_config.
116  *
117  * RETURNS:
118  * Pointer to new framebuffer or NULL on error.
119  */
120 struct drm_framebuffer *drm_framebuffer_create(drm_device_t *dev)
121 {
122         struct drm_framebuffer *fb;
123
124         /* Limit to single framebuffer for now */
125         if (dev->mode_config.num_fb > 1) {
126                 mutex_unlock(&dev->mode_config.mutex);
127                 DRM_ERROR("Attempt to add multiple framebuffers failed\n");
128                 return NULL;
129         }
130
131         fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL);
132         if (!fb)
133                 return NULL;
134         
135         fb->id = drm_idr_get(dev, fb);
136         fb->dev = dev;
137         dev->mode_config.num_fb++;
138         list_add(&fb->head, &dev->mode_config.fb_list);
139
140         return fb;
141 }
142 EXPORT_SYMBOL(drm_framebuffer_create);
143
144 /**
145  * drm_framebuffer_destroy - remove a framebuffer object
146  * @fb: framebuffer to remove
147  *
148  * LOCKING:
149  * Caller must hold mode config lock.
150  *
151  * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
152  * it, setting it to NULL.
153  */
154 void drm_framebuffer_destroy(struct drm_framebuffer *fb)
155 {
156         drm_device_t *dev = fb->dev;
157         struct drm_crtc *crtc;
158
159         /* remove from any CRTC */
160         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
161                 if (crtc->fb == fb)
162                         crtc->fb = NULL;
163         }
164
165         drm_idr_put(dev, fb->id);
166         list_del(&fb->head);
167         dev->mode_config.num_fb--;
168
169         kfree(fb);
170 }
171 EXPORT_SYMBOL(drm_framebuffer_destroy);
172
173 /**
174  * drm_crtc_create - create a new CRTC object
175  * @dev: DRM device
176  * @funcs: callbacks for the new CRTC
177  *
178  * LOCKING:
179  * Caller must hold mode config lock.
180  *
181  * Creates a new CRTC object and adds it to @dev's mode_config structure.
182  *
183  * RETURNS:
184  * Pointer to new CRTC object or NULL on error.
185  */
186 struct drm_crtc *drm_crtc_create(drm_device_t *dev,
187                                  const struct drm_crtc_funcs *funcs)
188 {
189         struct drm_crtc *crtc;
190
191         crtc = kzalloc(sizeof(struct drm_crtc), GFP_KERNEL);
192         if (!crtc)
193                 return NULL;
194
195         crtc->dev = dev;
196         crtc->funcs = funcs;
197
198         crtc->id = drm_idr_get(dev, crtc);
199
200         list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
201         dev->mode_config.num_crtc++;
202
203         return crtc;
204 }
205 EXPORT_SYMBOL(drm_crtc_create);
206
207 /**
208  * drm_crtc_destroy - remove a CRTC object
209  * @crtc: CRTC to remove
210  *
211  * LOCKING:
212  * Caller must hold mode config lock.
213  *
214  * Cleanup @crtc.  Calls @crtc's cleanup function, then removes @crtc from
215  * its associated DRM device's mode_config.  Frees it afterwards.
216  */
217 void drm_crtc_destroy(struct drm_crtc *crtc)
218 {
219         drm_device_t *dev = crtc->dev;
220
221         if (crtc->funcs->cleanup)
222                 (*crtc->funcs->cleanup)(crtc);
223
224         drm_idr_put(dev, crtc->id);
225         list_del(&crtc->head);
226         dev->mode_config.num_crtc--;
227         kfree(crtc);
228 }
229 EXPORT_SYMBOL(drm_crtc_destroy);
230
231 /**
232  * drm_crtc_in_use - check if a given CRTC is in a mode_config
233  * @crtc: CRTC to check
234  *
235  * LOCKING:
236  * Caller must hold mode config lock.
237  *
238  * Walk @crtc's DRM device's mode_config and see if it's in use.
239  *
240  * RETURNS:
241  * True if @crtc is part of the mode_config, false otherwise.
242  */
243 bool drm_crtc_in_use(struct drm_crtc *crtc)
244 {
245         struct drm_output *output;
246         drm_device_t *dev = crtc->dev;
247         /* FIXME: Locking around list access? */
248         list_for_each_entry(output, &dev->mode_config.output_list, head)
249                 if (output->crtc == crtc)
250                         return true;
251         return false;
252 }
253 EXPORT_SYMBOL(drm_crtc_in_use);
254
255 /*
256  * Detailed mode info for a standard 640x480@60Hz monitor
257  */
258 static struct drm_display_mode std_mode[] = {
259         { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
260                    752, 800, 0, 480, 490, 492, 525, 0,
261                    V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
262 };
263
264 /**
265  * drm_crtc_probe_output_modes - get complete set of display modes
266  * @dev: DRM device
267  * @maxX: max width for modes
268  * @maxY: max height for modes
269  *
270  * LOCKING:
271  * Caller must hold mode config lock.
272  *
273  * Based on @dev's mode_config layout, scan all the outputs and try to detect
274  * modes on them.  Modes will first be added to the output's probed_modes
275  * list, then culled (based on validity and the @maxX, @maxY parameters) and
276  * put into the normal modes list.
277  *
278  * Intended to be used either at bootup time or when major configuration
279  * changes have occurred.
280  *
281  * FIXME: take into account monitor limits
282  */
283 void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY)
284 {
285         struct drm_output *output;
286         struct drm_display_mode *mode, *t;
287         int ret;
288         //if (maxX == 0 || maxY == 0) 
289         // TODO
290
291         list_for_each_entry(output, &dev->mode_config.output_list, head) {
292
293                 /* set all modes to the unverified state */
294                 list_for_each_entry_safe(mode, t, &output->modes, head)
295                         mode->status = MODE_UNVERIFIED;
296                 
297                 output->status = (*output->funcs->detect)(output);
298
299                 if (output->status == output_status_disconnected) {
300                         DRM_DEBUG("%s is disconnected\n", output->name);
301                         /* TODO set EDID to NULL */
302                         continue;
303                 }
304
305                 ret = (*output->funcs->get_modes)(output);
306
307                 if (ret) {
308                         drm_mode_output_list_update(output);
309                 }
310
311                 if (maxX && maxY)
312                         drm_mode_validate_size(dev, &output->modes, maxX,
313                                                maxY, 0);
314                 list_for_each_entry_safe(mode, t, &output->modes, head) {
315                         if (mode->status == MODE_OK)
316                                 mode->status = (*output->funcs->mode_valid)(output,mode);
317                 }
318                 
319
320                 drm_mode_prune_invalid(dev, &output->modes, TRUE);
321
322                 if (list_empty(&output->modes)) {
323                         struct drm_display_mode *stdmode;
324
325                         DRM_DEBUG("No valid modes on %s\n", output->name);
326
327                         /* Should we do this here ???
328                          * When no valid EDID modes are available we end up
329                          * here and bailed in the past, now we add a standard
330                          * 640x480@60Hz mode and carry on.
331                          */
332                         stdmode = drm_mode_duplicate(dev, &std_mode[0]);
333                         drm_mode_probed_add(output, stdmode);
334                         drm_mode_list_concat(&output->probed_modes,
335                                              &output->modes);
336
337                         DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
338                                                                 output->name);
339                 }
340
341                 drm_mode_sort(&output->modes);
342
343                 DRM_DEBUG("Probed modes for %s\n", output->name);
344                 list_for_each_entry_safe(mode, t, &output->modes, head) {
345                         mode->vrefresh = drm_mode_vrefresh(mode);
346
347                         drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
348                         drm_mode_debug_printmodeline(dev, mode);
349                 }
350         }
351 }
352
353 /**
354  * drm_crtc_set_mode - set a mode
355  * @crtc: CRTC to program
356  * @mode: mode to use
357  * @x: width of mode
358  * @y: height of mode
359  *
360  * LOCKING:
361  * Caller must hold mode config lock.
362  *
363  * Try to set @mode on @crtc.  Give @crtc and its associated outputs a chance
364  * to fixup or reject the mode prior to trying to set it.
365  *
366  * RETURNS:
367  * True if the mode was set successfully, or false otherwise.
368  */
369 bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
370                        int x, int y)
371 {
372         drm_device_t *dev = crtc->dev;
373         struct drm_display_mode *adjusted_mode, saved_mode;
374         int saved_x, saved_y;
375         bool didLock = false;
376         bool ret = false;
377         struct drm_output *output;
378
379         adjusted_mode = drm_mode_duplicate(dev, mode);
380
381         crtc->enabled = drm_crtc_in_use(crtc);
382
383         if (!crtc->enabled) {
384                 return true;
385         }
386
387         didLock = crtc->funcs->lock(crtc);
388
389         saved_mode = crtc->mode;
390         saved_x = crtc->x;
391         saved_y = crtc->y;
392         
393         /* Update crtc values up front so the driver can rely on them for mode
394          * setting.
395          */
396         crtc->mode = *mode;
397         crtc->x = x;
398         crtc->y = y;
399
400         /* XXX short-circuit changes to base location only */
401         
402         /* Pass our mode to the outputs and the CRTC to give them a chance to
403          * adjust it according to limitations or output properties, and also
404          * a chance to reject the mode entirely.
405          */
406         list_for_each_entry(output, &dev->mode_config.output_list, head) {
407                 
408                 if (output->crtc != crtc)
409                         continue;
410                 
411                 if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
412                         goto done;
413                 }
414         }
415         
416         if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
417                 goto done;
418         }
419
420         /* Prepare the outputs and CRTCs before setting the mode. */
421         list_for_each_entry(output, &dev->mode_config.output_list, head) {
422
423                 if (output->crtc != crtc)
424                         continue;
425                 
426                 /* Disable the output as the first thing we do. */
427                 output->funcs->prepare(output);
428         }
429         
430         crtc->funcs->prepare(crtc);
431         
432         /* Set up the DPLL and any output state that needs to adjust or depend
433          * on the DPLL.
434          */
435         crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
436         list_for_each_entry(output, &dev->mode_config.output_list, head) {
437                 if (output->crtc == crtc) {
438                         dev_warn(&output->dev->pdev->dev, "%s: set mode %s\n",
439                                 output->name, mode->name);
440                         output->funcs->mode_set(output, mode, adjusted_mode);
441                 }
442         }
443         
444         /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
445         crtc->funcs->commit(crtc);
446         list_for_each_entry(output, &dev->mode_config.output_list, head) {
447                 if (output->crtc == crtc) {
448                         output->funcs->commit(output);
449 #if 0 // TODO def RANDR_12_INTERFACE
450                         if (output->randr_output)
451                                 RRPostPendingProperties (output->randr_output);
452 #endif
453                 }
454         }
455         
456         /* XXX free adjustedmode */
457         drm_mode_destroy(dev, adjusted_mode);
458         ret = TRUE;
459         /* TODO */
460 //      if (scrn->pScreen)
461 //              drm_crtc_set_screen_sub_pixel_order(dev);
462
463 done:
464         if (!ret) {
465                 crtc->x = saved_x;
466                 crtc->y = saved_y;
467                 crtc->mode = saved_mode;
468         }
469         
470         if (didLock)
471                 crtc->funcs->unlock (crtc);
472         
473         return ret;
474 }
475 EXPORT_SYMBOL(drm_crtc_set_mode);
476
477 /**
478  * drm_disable_unused_functions - disable unused objects
479  * @dev: DRM device
480  *
481  * LOCKING:
482  * Caller must hold mode config lock.
483  *
484  * If an output or CRTC isn't part of @dev's mode_config, it can be disabled
485  * by calling its dpms function, which should power it off.
486  */
487 void drm_disable_unused_functions(struct drm_device *dev)
488 {
489         struct drm_output *output;
490         struct drm_crtc *crtc;
491
492         list_for_each_entry(output, &dev->mode_config.output_list, head) {
493                 if (!output->crtc)
494                         (*output->funcs->dpms)(output, DPMSModeOff);
495         }
496
497         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
498                 if (!crtc->enabled)
499                         crtc->funcs->dpms(crtc, DPMSModeOff);
500         }
501 }
502         
503 /**
504  * drm_mode_probed_add - add a mode to the specified output's probed mode list
505  * @output: output the new mode
506  * @mode: mode data
507  *
508  * LOCKING:
509  * Caller must hold mode config lock.
510  * 
511  * Add @mode to @output's mode list for later use.
512  */
513 void drm_mode_probed_add(struct drm_output *output,
514                          struct drm_display_mode *mode)
515 {
516         list_add(&mode->head, &output->probed_modes);
517 }
518 EXPORT_SYMBOL(drm_mode_probed_add);
519
520 /**
521  * drm_mode_remove - remove and free a mode
522  * @output: output list to modify
523  * @mode: mode to remove
524  *
525  * LOCKING:
526  * Caller must hold mode config lock.
527  * 
528  * Remove @mode from @output's mode list, then free it.
529  */
530 void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode)
531 {
532         list_del(&mode->head);
533         kfree(mode);
534 }
535 EXPORT_SYMBOL(drm_mode_remove);
536
537 /**
538  * drm_output_create - create a new output
539  * @dev: DRM device
540  * @funcs: callbacks for this output
541  * @name: user visible name of the output
542  *
543  * LOCKING:
544  * Caller must hold @dev's mode_config lock.
545  *
546  * Creates a new drm_output structure and adds it to @dev's mode_config
547  * structure.
548  *
549  * RETURNS:
550  * Pointer to the new output or NULL on error.
551  */
552 struct drm_output *drm_output_create(drm_device_t *dev,
553                                      const struct drm_output_funcs *funcs,
554                                      const char *name)
555 {
556         struct drm_output *output = NULL;
557
558         output = kzalloc(sizeof(struct drm_output), GFP_KERNEL);
559         if (!output)
560                 return NULL;
561                 
562         output->dev = dev;
563         output->funcs = funcs;
564         output->id = drm_idr_get(dev, output);
565         if (name)
566                 strncpy(output->name, name, DRM_OUTPUT_LEN);
567         output->name[DRM_OUTPUT_LEN - 1] = 0;
568         output->subpixel_order = SubPixelUnknown;
569         INIT_LIST_HEAD(&output->probed_modes);
570         INIT_LIST_HEAD(&output->modes);
571         /* randr_output? */
572         /* output_set_monitor(output)? */
573         /* check for output_ignored(output)? */
574
575         mutex_lock(&dev->mode_config.mutex);
576         list_add_tail(&output->head, &dev->mode_config.output_list);
577         dev->mode_config.num_output++;
578
579         mutex_unlock(&dev->mode_config.mutex);
580
581         return output;
582
583 }
584 EXPORT_SYMBOL(drm_output_create);
585
586 /**
587  * drm_output_destroy - remove an output
588  * @output: output to remove
589  *
590  * LOCKING:
591  * Caller must hold @dev's mode_config lock.
592  *
593  * Call @output's cleanup function, then remove the output from the DRM
594  * mode_config after freeing @output's modes.
595  */
596 void drm_output_destroy(struct drm_output *output)
597 {
598         struct drm_device *dev = output->dev;
599         struct drm_display_mode *mode, *t;
600
601         if (*output->funcs->cleanup)
602                 (*output->funcs->cleanup)(output);
603
604         list_for_each_entry_safe(mode, t, &output->probed_modes, head)
605                 drm_mode_remove(output, mode);
606
607         list_for_each_entry_safe(mode, t, &output->modes, head)
608                 drm_mode_remove(output, mode);
609
610         mutex_lock(&dev->mode_config.mutex);
611         drm_idr_put(dev, output->id);
612         list_del(&output->head);
613         mutex_unlock(&dev->mode_config.mutex);
614         kfree(output);
615 }
616 EXPORT_SYMBOL(drm_output_destroy);
617
618 /**
619  * drm_output_rename - rename an output
620  * @output: output to rename
621  * @name: new user visible name
622  *
623  * LOCKING:
624  * None.
625  *
626  * Simply stuff a new name into @output's name field, based on @name.
627  *
628  * RETURNS:
629  * True if the name was changed, false otherwise.
630  */
631 bool drm_output_rename(struct drm_output *output, const char *name)
632 {
633         if (!name)
634                 return false;
635
636         strncpy(output->name, name, DRM_OUTPUT_LEN);
637         output->name[DRM_OUTPUT_LEN - 1] = 0;
638
639         DRM_DEBUG("Changed name to %s\n", output->name);
640 //      drm_output_set_monitor(output);
641 //      if (drm_output_ignored(output))
642 //              return FALSE;
643
644         return TRUE;
645 }
646 EXPORT_SYMBOL(drm_output_rename);
647
648 /**
649  * drm_mode_create - create a new display mode
650  * @dev: DRM device
651  *
652  * LOCKING:
653  * None.
654  *
655  * Create a new drm_display_mode, give it an ID, and return it.
656  *
657  * RETURNS:
658  * Pointer to new mode on success, NULL on error.
659  */
660 struct drm_display_mode *drm_mode_create(struct drm_device *dev)
661 {
662         struct drm_display_mode *nmode;
663
664         nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
665         if (!nmode)
666                 return NULL;
667
668         nmode->mode_id = drm_idr_get(dev, nmode);
669         return nmode;
670 }
671 EXPORT_SYMBOL(drm_mode_create);
672
673 /**
674  * drm_mode_destroy - remove a mode
675  * @dev: DRM device
676  * @mode: mode to remove
677  *
678  * LOCKING:
679  * Caller must hold mode config lock.
680  *
681  * Free @mode's unique identifier, then free it.
682  */
683 void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
684 {
685         drm_idr_put(dev, mode->mode_id);
686
687         kfree(mode);
688 }
689 EXPORT_SYMBOL(drm_mode_destroy);
690
691 /**
692  * drm_mode_config_init - initialize DRM mode_configuration structure
693  * @dev: DRM device
694  *
695  * LOCKING:
696  * None, should happen single threaded at init time.
697  *
698  * Initialize @dev's mode_config structure, used for tracking the graphics
699  * configuration of @dev.
700  */
701 void drm_mode_config_init(drm_device_t *dev)
702 {
703         mutex_init(&dev->mode_config.mutex);
704         INIT_LIST_HEAD(&dev->mode_config.fb_list);
705         INIT_LIST_HEAD(&dev->mode_config.crtc_list);
706         INIT_LIST_HEAD(&dev->mode_config.output_list);
707         INIT_LIST_HEAD(&dev->mode_config.usermode_list);
708         idr_init(&dev->mode_config.crtc_idr);
709 }
710 EXPORT_SYMBOL(drm_mode_config_init);
711
712 /**
713  * drm_get_buffer_object - find the buffer object for a given handle
714  * @dev: DRM device
715  * @bo: pointer to caller's buffer_object pointer
716  * @handle: handle to lookup
717  *
718  * LOCKING:
719  * Must take @dev's struct_mutex to protect buffer object lookup.
720  *
721  * Given @handle, lookup the buffer object in @dev and put it in the caller's
722  * @bo pointer.
723  *
724  * RETURNS:
725  * Zero on success, -EINVAL if the handle couldn't be found.
726  */
727 static int drm_get_buffer_object(drm_device_t *dev, struct drm_buffer_object **bo, unsigned long handle)
728 {
729         drm_user_object_t *uo;
730         drm_hash_item_t *hash;
731         int ret;
732
733         *bo = NULL;
734
735         mutex_lock(&dev->struct_mutex);
736         ret = drm_ht_find_item(&dev->object_hash, handle, &hash);
737         if (ret) {
738                 DRM_ERROR("Couldn't find handle.\n");
739                 ret = -EINVAL;
740                 goto out_err;
741         }
742
743         uo = drm_hash_entry(hash, drm_user_object_t, hash);
744         if (uo->type != drm_buffer_type) {
745                 ret = -EINVAL;
746                 goto out_err;
747         }
748         
749         *bo = drm_user_object_entry(uo, drm_buffer_object_t, base);
750         ret = 0;
751 out_err:
752         mutex_unlock(&dev->struct_mutex);
753         return ret;
754 }
755
756 /**
757  * drm_pick_crtcs - pick crtcs for output devices
758  * @dev: DRM device
759  *
760  * LOCKING:
761  * Caller must hold mode config lock.
762  */
763 static void drm_pick_crtcs (drm_device_t *dev)
764 {
765         int c, o;
766         struct drm_output *output, *output_equal;
767         struct drm_crtc   *crtc;
768         struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
769
770         list_for_each_entry(output, &dev->mode_config.output_list, head) {
771                 output->crtc = NULL;
772     
773                 /* Don't hook up outputs that are disconnected ??
774                  *
775                  * This is debateable. Do we want fixed /dev/fbX or
776                  * dynamic on hotplug (need mode code for that though) ?
777                  *
778                  * If we don't hook up outputs now, then we only create
779                  * /dev/fbX for the output that's enabled, that's good as
780                  * the users console will be on that output.
781                  *
782                  * If we do hook up outputs that are disconnected now, then
783                  * the user may end up having to muck about with the fbcon
784                  * map flags to assign his console to the enabled output. Ugh.
785                  */
786                 if (output->status != output_status_connected)
787                         continue;
788
789                 des_mode = NULL;
790                 list_for_each_entry(des_mode, &output->modes, head) {
791                         if (des_mode->type & DRM_MODE_TYPE_PREFERRED)
792                                 break;
793                 }
794
795                 /* No preferred mode, let's just select the first available */
796                 if (!des_mode || !(des_mode->type & DRM_MODE_TYPE_PREFERRED)) {
797                         list_for_each_entry(des_mode, &output->modes, head) {
798                                 if (des_mode)
799                                         break;
800                         }
801                 }
802
803                 c = -1;
804                 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
805                         c++;
806                         if ((output->possible_crtcs & (1 << c)) == 0)
807                                 continue;
808         
809 #if 0 /* should we try and clone ?? - code not tested - FIXME */
810                         o = -1;
811                         list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
812                                 o++;
813                                 if (output->id == output_equal->id)
814                                         continue;
815
816                                 list_for_each_entry(modes, &output->modes, head) {
817                                         list_for_each_entry(modes_equal, &output_equal->modes, head) {
818                                                 if (drm_mode_equal (modes, modes_equal)) {
819                                                         if ((output->possible_clones & (1 << o))) {
820                                                                 goto clone;
821                                                         }
822                                                 }
823                                         }
824                                 }
825                         }
826
827 clone:
828 #endif
829                         /* Found a CRTC to attach to, do it ! */
830                         output->crtc = crtc;
831                         output->crtc->desired_mode = des_mode;
832                         output->initial_x = 0;
833                         output->initial_y = 0;
834                         DRM_DEBUG("Desired mode for CRTC %d is %s\n",c,des_mode->name);
835                         break;
836                 }
837         }
838 }
839
840
841 /**
842  * drm_initial_config - setup a sane initial output configuration
843  * @dev: DRM device
844  * @can_grow: this configuration is growable
845  *
846  * LOCKING:
847  * Called at init time, must take mode config lock.
848  *
849  * Scan the CRTCs and outputs and try to put together an initial setup.
850  * At the moment, this is a cloned configuration across all heads with
851  * a new framebuffer object as the backing store.
852  *
853  * RETURNS:
854  * Zero if everything went ok, nonzero otherwise.
855  */
856 bool drm_initial_config(drm_device_t *dev, bool can_grow)
857 {
858         struct drm_output *output;
859         int ret = false;
860
861         mutex_lock(&dev->mode_config.mutex);
862
863         drm_crtc_probe_output_modes(dev, 2048, 2048);
864
865         drm_pick_crtcs(dev);
866
867         list_for_each_entry(output, &dev->mode_config.output_list, head) {
868
869                 /* can't setup the output if there's no assigned crtc or mode */
870                 if (!output->crtc || !output->crtc->desired_mode)
871                         continue;
872
873                 dev->driver->fb_probe(dev, output->crtc);
874         }
875         drm_disable_unused_functions(dev);
876
877         mutex_unlock(&dev->mode_config.mutex);
878         return ret;
879 }
880 EXPORT_SYMBOL(drm_initial_config);
881
882 /**
883  * drm_mode_config_cleanup - free up DRM mode_config info
884  * @dev: DRM device
885  *
886  * LOCKING:
887  * Caller must hold mode config lock.
888  *
889  * Free up all the outputs and CRTCs associated with this DRM device, then
890  * free up the framebuffers and associated buffer objects.
891  *
892  * FIXME: cleanup any dangling user buffer objects too
893  */
894 void drm_mode_config_cleanup(drm_device_t *dev)
895 {
896         struct drm_output *output, *ot;
897         struct drm_crtc *crtc, *ct;
898         struct drm_framebuffer *fb, *fbt;
899         struct drm_display_mode *mode, *mt;
900         list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) {
901                 drm_output_destroy(output);
902         }
903
904         list_for_each_entry_safe(mode, mt, &dev->mode_config.usermode_list, head) {
905                 drm_mode_destroy(dev, mode);
906         }
907                 
908         list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
909                 dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
910                 /* If this FB was the kernel one, free it */
911                 if (fb->bo->type == drm_bo_type_kernel) {
912                         mutex_lock(&dev->struct_mutex);
913                         drm_bo_usage_deref_locked(&fb->bo);
914                         mutex_unlock(&dev->struct_mutex);
915                 }
916                 drm_framebuffer_destroy(fb);
917         }
918
919         list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
920                 drm_crtc_destroy(crtc);
921         }
922
923 }
924 EXPORT_SYMBOL(drm_mode_config_cleanup);
925
926 /**
927  * drm_crtc_set_config - set a new config from userspace
928  * @crtc: CRTC to setup
929  * @crtc_info: user provided configuration
930  * @new_mode: new mode to set
931  * @output_set: set of outputs for the new config
932  * @fb: new framebuffer
933  *
934  * LOCKING:
935  * Caller must hold mode config lock.
936  *
937  * Setup a new configuration, provided by the user in @crtc_info, and enable
938  * it.
939  *
940  * RETURNS:
941  * Zero. (FIXME)
942  */
943 int drm_crtc_set_config(struct drm_crtc *crtc, struct drm_mode_crtc *crtc_info, struct drm_display_mode *new_mode, struct drm_output **output_set, struct drm_framebuffer *fb)
944 {
945         drm_device_t *dev = crtc->dev;
946         struct drm_crtc **save_crtcs, *new_crtc;
947         bool save_enabled = crtc->enabled;
948         bool changed;
949         struct drm_output *output;
950         int count = 0, ro;
951
952         save_crtcs = kzalloc(dev->mode_config.num_crtc * sizeof(struct drm_crtc *), GFP_KERNEL);
953         if (!save_crtcs)
954                 return -ENOMEM;
955
956         if (crtc->fb != fb)
957                 changed = true;
958
959         if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
960                 changed = true;
961
962         if (new_mode && (crtc->mode.mode_id != new_mode->mode_id))
963                 changed = true;
964
965         list_for_each_entry(output, &dev->mode_config.output_list, head) {
966                 save_crtcs[count++] = output->crtc;
967
968                 if (output->crtc == crtc)
969                         new_crtc = NULL;
970                 else
971                         new_crtc = output->crtc;
972
973                 for (ro = 0; ro < crtc_info->count_outputs; ro++) {
974                         if (output_set[ro] == output)
975                                 new_crtc = crtc;
976                 }
977                 if (new_crtc != output->crtc) {
978                         changed = true;
979                         output->crtc = new_crtc;
980                 }
981         }
982
983         if (changed) {
984                 crtc->fb = fb;
985                 crtc->enabled = (new_mode != NULL);
986                 if (new_mode != NULL) {
987                         DRM_DEBUG("attempting to set mode from userspace\n");
988                         drm_mode_debug_printmodeline(dev, new_mode);
989                         if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x,
990                                                crtc_info->y)) {
991                                 crtc->enabled = save_enabled;
992                                 count = 0;
993                                 list_for_each_entry(output, &dev->mode_config.output_list, head)
994                                         output->crtc = save_crtcs[count++];
995                                 kfree(save_crtcs);
996                                 return -EINVAL;
997                         }
998                         crtc->desired_x = crtc_info->x;
999                         crtc->desired_y = crtc_info->y;
1000                         crtc->desired_mode = new_mode;
1001                 }
1002                 drm_disable_unused_functions(dev);
1003         }
1004         kfree(save_crtcs);
1005         return 0;
1006 }
1007
1008 /**
1009  * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
1010  * @out: drm_mode_modeinfo struct to return to the user
1011  * @in: drm_display_mode to use
1012  *
1013  * LOCKING:
1014  * None.
1015  *
1016  * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
1017  * the user.
1018  */
1019 void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in)
1020 {
1021
1022         out->id = in->mode_id;
1023         out->clock = in->clock;
1024         out->hdisplay = in->hdisplay;
1025         out->hsync_start = in->hsync_start;
1026         out->hsync_end = in->hsync_end;
1027         out->htotal = in->htotal;
1028         out->hskew = in->hskew;
1029         out->vdisplay = in->vdisplay;
1030         out->vsync_start = in->vsync_start;
1031         out->vsync_end = in->vsync_end;
1032         out->vtotal = in->vtotal;
1033         out->vscan = in->vscan;
1034         out->vrefresh = in->vrefresh;
1035         out->flags = in->flags;
1036         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1037         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1038 }
1039
1040 /**
1041  * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
1042  * @out: drm_display_mode to return to the user
1043  * @in: drm_mode_modeinfo to use
1044  *
1045  * LOCKING:
1046  * None.
1047  *
1048  * Convert a drmo_mode_modeinfo into a drm_display_mode structure to return to
1049  * the caller.
1050  */
1051 void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modeinfo *in)
1052 {
1053         out->clock = in->clock;
1054         out->hdisplay = in->hdisplay;
1055         out->hsync_start = in->hsync_start;
1056         out->hsync_end = in->hsync_end;
1057         out->htotal = in->htotal;
1058         out->hskew = in->hskew;
1059         out->vdisplay = in->vdisplay;
1060         out->vsync_start = in->vsync_start;
1061         out->vsync_end = in->vsync_end;
1062         out->vtotal = in->vtotal;
1063         out->vscan = in->vscan;
1064         out->vrefresh = in->vrefresh;
1065         out->flags = in->flags;
1066         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1067         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1068 }
1069         
1070 /**
1071  * drm_mode_getresources - get graphics configuration
1072  * @inode: inode from the ioctl
1073  * @filp: file * from the ioctl
1074  * @cmd: cmd from ioctl
1075  * @arg: arg from ioctl
1076  *
1077  * LOCKING:
1078  * Takes mode config lock.
1079  *
1080  * Construct a set of configuration description structures and return
1081  * them to the user, including CRTC, output and framebuffer configuration.
1082  *
1083  * Called by the user via ioctl.
1084  *
1085  * RETURNS:
1086  * Zero on success, errno on failure.
1087  */
1088 int drm_mode_getresources(struct inode *inode, struct file *filp,
1089                           unsigned int cmd, unsigned long arg)
1090 {
1091         drm_file_t *priv = filp->private_data;
1092         drm_device_t *dev = priv->head->dev;
1093         struct drm_mode_card_res __user *argp = (void __user *)arg;
1094         struct drm_mode_card_res card_res;
1095         struct list_head *lh;
1096         struct drm_framebuffer *fb;
1097         struct drm_output *output;
1098         struct drm_crtc *crtc;
1099         struct drm_mode_modeinfo u_mode;
1100         struct drm_display_mode *mode;
1101         int ret = 0;
1102         int mode_count= 0;
1103         int output_count = 0;
1104         int crtc_count = 0;
1105         int fb_count = 0;
1106         int copied = 0;
1107         
1108         memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
1109
1110         mutex_lock(&dev->mode_config.mutex);
1111
1112         list_for_each(lh, &dev->mode_config.fb_list)
1113                 fb_count++;
1114
1115         list_for_each(lh, &dev->mode_config.crtc_list)
1116                 crtc_count++;
1117
1118         list_for_each_entry(output, &dev->mode_config.output_list,
1119                             head) {
1120                 output_count++;
1121                 list_for_each(lh, &output->modes)
1122                         mode_count++;
1123         }
1124         list_for_each(lh, &dev->mode_config.usermode_list)
1125                 mode_count++;
1126
1127         if (copy_from_user(&card_res, argp, sizeof(card_res))) {
1128                 ret = -EFAULT;
1129                 goto out_unlock;
1130         }
1131
1132         if (card_res.count_modes == 0) {
1133                 DRM_DEBUG("probing modes %dx%d\n", dev->mode_config.max_width, dev->mode_config.max_height);
1134                 drm_crtc_probe_output_modes(dev, dev->mode_config.max_width, dev->mode_config.max_height);
1135                 mode_count = 0;
1136                 list_for_each_entry(output, &dev->mode_config.output_list, head) {
1137                         list_for_each(lh, &output->modes)
1138                                 mode_count++;
1139                 }
1140                 list_for_each(lh, &dev->mode_config.usermode_list)
1141                         mode_count++;
1142         }
1143
1144         /* handle this in 4 parts */
1145         /* FBs */
1146         if (card_res.count_fbs >= fb_count) {
1147                 copied = 0;
1148                 list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
1149                         if (put_user(fb->id, &card_res.fb_id[copied++])) {
1150                                 ret = -EFAULT;
1151                                 goto done;
1152                         }
1153                 }
1154         }
1155         card_res.count_fbs = fb_count;
1156
1157         /* CRTCs */
1158         if (card_res.count_crtcs >= crtc_count) {
1159                 copied = 0;
1160                 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){
1161                         DRM_DEBUG("CRTC ID is %d\n", crtc->id);
1162                         if (put_user(crtc->id, &card_res.crtc_id[copied++])) {
1163                                 ret = -EFAULT;
1164                                 goto done;
1165                         }
1166                 }
1167         }
1168         card_res.count_crtcs = crtc_count;
1169
1170
1171         /* Outputs */
1172         if (card_res.count_outputs >= output_count) {
1173                 copied = 0;
1174                 list_for_each_entry(output, &dev->mode_config.output_list,
1175                                     head) {
1176                         DRM_DEBUG("OUTPUT ID is %d\n", output->id);
1177                         if (put_user(output->id, &card_res.output_id[copied++])) {
1178                                 ret = -EFAULT;
1179                                 goto done;
1180                         }
1181                 }
1182         }
1183         card_res.count_outputs = output_count;
1184         
1185         /* Modes */
1186         if (card_res.count_modes >= mode_count) {
1187                 copied = 0;
1188                 list_for_each_entry(output, &dev->mode_config.output_list,
1189                                     head) {
1190                         list_for_each_entry(mode, &output->modes, head) {
1191                                 drm_crtc_convert_to_umode(&u_mode, mode);
1192                                 if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) {
1193                                         ret = -EFAULT;
1194                                         goto done;
1195                                 }
1196                         }
1197                 }
1198                 /* add in user modes */
1199                 list_for_each_entry(mode, &dev->mode_config.usermode_list, head) {
1200                         drm_crtc_convert_to_umode(&u_mode, mode);
1201                         if (copy_to_user(&card_res.modes[copied++], &u_mode, sizeof(struct drm_mode_modeinfo))) {
1202                                 ret = -EFAULT;
1203                                 goto done;
1204                         }
1205                 }
1206         }
1207         card_res.count_modes = mode_count;
1208
1209 done:
1210         DRM_DEBUG("Counted %d %d %d\n", card_res.count_crtcs,
1211                   card_res.count_outputs,
1212                   card_res.count_modes);
1213         
1214         if (copy_to_user(argp, &card_res, sizeof(card_res)))
1215                 ret = -EFAULT;
1216
1217 out_unlock:
1218         mutex_unlock(&dev->mode_config.mutex);
1219         return ret;
1220 }
1221
1222 /**
1223  * drm_mode_getcrtc - get CRTC configuration
1224  * @inode: inode from the ioctl
1225  * @filp: file * from the ioctl
1226  * @cmd: cmd from ioctl
1227  * @arg: arg from ioctl
1228  *
1229  * LOCKING:
1230  * Caller? (FIXME)
1231  *
1232  * Construct a CRTC configuration structure to return to the user.
1233  *
1234  * Called by the user via ioctl.
1235  *
1236  * RETURNS:
1237  * Zero on success, errno on failure.
1238  */
1239 int drm_mode_getcrtc(struct inode *inode, struct file *filp,
1240                      unsigned int cmd, unsigned long arg)
1241 {
1242         drm_file_t *priv = filp->private_data;
1243         drm_device_t *dev = priv->head->dev;
1244         struct drm_mode_crtc __user *argp = (void __user *)arg;
1245         struct drm_mode_crtc crtc_resp;
1246         struct drm_crtc *crtc;
1247         struct drm_output *output;
1248         int ocount;
1249         int ret = 0;
1250
1251         if (copy_from_user(&crtc_resp, argp, sizeof(crtc_resp)))
1252                 return -EFAULT;
1253
1254         mutex_lock(&dev->mode_config.mutex);
1255         crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp.crtc_id);
1256         if (!crtc || (crtc->id != crtc_resp.crtc_id)) {
1257                 ret = -EINVAL;
1258                 goto out;
1259         }
1260
1261         crtc_resp.x = crtc->x;
1262         crtc_resp.y = crtc->y;
1263         crtc_resp.fb_id = 1;
1264
1265         crtc_resp.outputs = 0;
1266         if (crtc->enabled) {
1267
1268                 crtc_resp.mode = crtc->mode.mode_id;
1269                 ocount = 0;
1270                 list_for_each_entry(output, &dev->mode_config.output_list, head) {
1271                         if (output->crtc == crtc)
1272                                 crtc_resp.outputs |= 1 << (ocount++);
1273                 }
1274         } else {
1275                 crtc_resp.mode = 0;
1276         }
1277
1278         if (copy_to_user(argp, &crtc_resp, sizeof(crtc_resp)))
1279                 ret = -EFAULT;
1280
1281 out:
1282         mutex_unlock(&dev->mode_config.mutex);
1283         return ret;
1284 }
1285
1286 /**
1287  * drm_mode_getoutput - get output configuration
1288  * @inode: inode from the ioctl
1289  * @filp: file * from the ioctl
1290  * @cmd: cmd from ioctl
1291  * @arg: arg from ioctl
1292  *
1293  * LOCKING:
1294  * Caller? (FIXME)
1295  *
1296  * Construct a output configuration structure to return to the user.
1297  *
1298  * Called by the user via ioctl.
1299  *
1300  * RETURNS:
1301  * Zero on success, errno on failure.
1302  */
1303 int drm_mode_getoutput(struct inode *inode, struct file *filp,
1304                        unsigned int cmd, unsigned long arg)
1305 {
1306         drm_file_t *priv = filp->private_data;
1307         drm_device_t *dev = priv->head->dev;
1308         struct drm_mode_get_output __user *argp = (void __user *)arg;
1309         struct drm_mode_get_output out_resp;
1310         struct drm_output *output;
1311         struct drm_display_mode *mode;
1312         int mode_count = 0;
1313         int ret = 0;
1314         int copied = 0;
1315         int i;
1316
1317         if (copy_from_user(&out_resp, argp, sizeof(out_resp)))
1318                 return -EFAULT; 
1319
1320         DRM_DEBUG("output id %d:\n", out_resp.output);
1321
1322         mutex_lock(&dev->mode_config.mutex);
1323         output= idr_find(&dev->mode_config.crtc_idr, out_resp.output);
1324         if (!output || (output->id != out_resp.output)) {
1325                 ret = -EINVAL;
1326                 goto out_unlock;
1327         }
1328
1329         list_for_each_entry(mode, &output->modes, head)
1330                 mode_count++;
1331         
1332         for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++)
1333                 if (output->user_mode_ids[i] != 0)
1334                         mode_count++;
1335
1336         strncpy(out_resp.name, output->name, DRM_OUTPUT_NAME_LEN);
1337         out_resp.name[DRM_OUTPUT_NAME_LEN-1] = 0;
1338
1339         out_resp.mm_width = output->mm_width;
1340         out_resp.mm_height = output->mm_height;
1341         out_resp.subpixel = output->subpixel_order;
1342         out_resp.connection = output->status;
1343         if (output->crtc)
1344                 out_resp.crtc = output->crtc->id;
1345         else
1346                 out_resp.crtc = 0;
1347
1348         if ((out_resp.count_modes >= mode_count) && mode_count) {
1349                 copied = 0;
1350                 list_for_each_entry(mode, &output->modes, head) {
1351                         if (put_user(mode->mode_id, &out_resp.modes[copied++])) {
1352                                 ret = -EFAULT;
1353                                 goto done;
1354                         }
1355                 }
1356                 for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
1357                         if (output->user_mode_ids[i] != 0)
1358                                 if (put_user(output->user_mode_ids[i], &out_resp.modes[copied++])) {
1359                                         ret = -EFAULT;
1360                                         goto done;
1361                                 }
1362                 }
1363                         
1364         }
1365         out_resp.count_modes = mode_count;
1366
1367 done:
1368         if (copy_to_user(argp, &out_resp, sizeof(out_resp)))
1369                 ret = -EFAULT;
1370
1371 out_unlock:
1372         mutex_unlock(&dev->mode_config.mutex);
1373         return ret;
1374 }
1375
1376 /**
1377  * drm_mode_setcrtc - set CRTC configuration
1378  * @inode: inode from the ioctl
1379  * @filp: file * from the ioctl
1380  * @cmd: cmd from ioctl
1381  * @arg: arg from ioctl
1382  *
1383  * LOCKING:
1384  * Caller? (FIXME)
1385  *
1386  * Build a new CRTC configuration based on user request.
1387  *
1388  * Called by the user via ioctl.
1389  *
1390  * RETURNS:
1391  * Zero on success, errno on failure.
1392  */
1393 int drm_mode_setcrtc(struct inode *inode, struct file *filp,
1394                      unsigned int cmd, unsigned long arg)
1395 {
1396         drm_file_t *priv = filp->private_data;
1397         drm_device_t *dev = priv->head->dev;
1398         struct drm_mode_crtc __user *argp = (void __user *)arg;
1399         struct drm_mode_crtc crtc_req;
1400         struct drm_crtc *crtc;
1401         struct drm_output **output_set = NULL, *output;
1402         struct drm_display_mode *mode;
1403         struct drm_framebuffer *fb = NULL;
1404         int ret = 0;
1405         int i;
1406
1407         if (copy_from_user(&crtc_req, argp, sizeof(crtc_req)))
1408                 return -EFAULT;
1409
1410         mutex_lock(&dev->mode_config.mutex);
1411         crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req.crtc_id);
1412         if (!crtc || (crtc->id != crtc_req.crtc_id)) {
1413                 DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req.crtc_id);
1414                 ret = -EINVAL;
1415                 goto out;
1416         }
1417
1418         if (crtc_req.mode) {
1419                 /* if we have a mode we need a framebuffer */
1420                 if (crtc_req.fb_id) {
1421                         fb = idr_find(&dev->mode_config.crtc_idr, crtc_req.fb_id);
1422                         if (!fb || (fb->id != crtc_req.fb_id)) {
1423                                 DRM_DEBUG("Unknown FB ID%d\n", crtc_req.fb_id);
1424                                 ret = -EINVAL;
1425                                 goto out;
1426                         }
1427                 }
1428                 mode = idr_find(&dev->mode_config.crtc_idr, crtc_req.mode);
1429                 if (!mode || (mode->mode_id != crtc_req.mode)) {
1430                         struct drm_output *output;
1431                         
1432                         list_for_each_entry(output, 
1433                                             &dev->mode_config.output_list,
1434                                             head) {
1435                                 list_for_each_entry(mode, &output->modes,
1436                                                     head) {
1437                                         drm_mode_debug_printmodeline(dev, 
1438                                                                      mode);
1439                                 }
1440                         }
1441
1442                         DRM_DEBUG("Unknown mode id %d, %p\n", crtc_req.mode, mode);
1443                         ret = -EINVAL;
1444                         goto out;
1445                 }
1446         } else
1447                 mode = NULL;
1448
1449         if (crtc_req.count_outputs == 0 && mode) {
1450                 DRM_DEBUG("Count outputs is 0 but mode set\n");
1451                 ret = -EINVAL;
1452                 goto out;
1453         }
1454
1455         if (crtc_req.count_outputs > 0 && !mode && !fb) {
1456                 DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req.count_outputs);
1457                 ret = -EINVAL;
1458                 goto out;
1459         }
1460
1461         if (crtc_req.count_outputs > 0) {
1462                 u32 out_id;
1463                 output_set = kmalloc(crtc_req.count_outputs *
1464                                      sizeof(struct drm_output *), GFP_KERNEL);
1465                 if (!output_set) {
1466                         ret = -ENOMEM;
1467                         goto out;
1468                 }
1469
1470                 for (i = 0; i < crtc_req.count_outputs; i++) {
1471                         if (get_user(out_id, &crtc_req.set_outputs[i])) {
1472                                 ret = -EFAULT;
1473                                 goto out;
1474                         }
1475
1476                         output = idr_find(&dev->mode_config.crtc_idr, out_id);
1477                         if (!output || (out_id != output->id)) {
1478                                 DRM_DEBUG("Output id %d unknown\n", out_id);
1479                                 ret = -EINVAL;
1480                                 goto out;
1481                         }
1482
1483                         output_set[i] = output;
1484                 }
1485         }
1486                 
1487         ret = drm_crtc_set_config(crtc, &crtc_req, mode, output_set, fb);
1488
1489 out:
1490         mutex_unlock(&dev->mode_config.mutex);
1491         return ret;
1492 }
1493
1494 /**
1495  * drm_mode_addfb - add an FB to the graphics configuration
1496  * @inode: inode from the ioctl
1497  * @filp: file * from the ioctl
1498  * @cmd: cmd from ioctl
1499  * @arg: arg from ioctl
1500  *
1501  * LOCKING:
1502  * Takes mode config lock.
1503  *
1504  * Add a new FB to the specified CRTC, given a user request.
1505  *
1506  * Called by the user via ioctl.
1507  *
1508  * RETURNS:
1509  * Zero on success, errno on failure.
1510  */
1511 int drm_mode_addfb(struct inode *inode, struct file *filp,
1512                    unsigned int cmd, unsigned long arg)
1513 {
1514         struct drm_file *priv = filp->private_data;
1515         struct drm_device *dev = priv->head->dev;
1516         struct drm_mode_fb_cmd __user *argp = (void __user *)arg;
1517         struct drm_mode_fb_cmd r;
1518         struct drm_mode_config *config = &dev->mode_config;
1519         struct drm_framebuffer *fb;
1520         struct drm_buffer_object *bo;
1521         struct drm_crtc *crtc;
1522         int ret = 0;
1523
1524         if (copy_from_user(&r, argp, sizeof(r)))
1525                 return -EFAULT;
1526
1527         if ((config->min_width > r.width) || (r.width > config->max_width)) {
1528                 DRM_ERROR("mode new framebuffer width not within limits\n");
1529                 return -EINVAL;
1530         }
1531         if ((config->min_height > r.height) || (r.height > config->max_height)) {
1532                 DRM_ERROR("mode new framebuffer height not within limits\n");
1533                 return -EINVAL;
1534         }
1535
1536         mutex_lock(&dev->mode_config.mutex);
1537         /* TODO check limits are okay */
1538         ret = drm_get_buffer_object(dev, &bo, r.handle);
1539         if (ret || !bo) {
1540                 ret = -EINVAL;
1541                 goto out;
1542         }
1543
1544         /* TODO check buffer is sufficently large */
1545         /* TODO setup destructor callback */
1546
1547         fb = drm_framebuffer_create(dev);
1548         if (!fb) {
1549                 ret = -EINVAL;
1550                 goto out;
1551         }
1552
1553         fb->width = r.width;
1554         fb->height = r.height;
1555         fb->pitch = r.pitch;
1556         fb->bits_per_pixel = r.bpp;
1557         fb->depth = r.depth;
1558         fb->offset = bo->offset;
1559         fb->bo = bo;
1560
1561         r.buffer_id = fb->id;
1562
1563         list_add(&fb->filp_head, &priv->fbs);
1564
1565         if (copy_to_user(argp, &r, sizeof(r))) {
1566                 ret = -EFAULT;
1567                 goto out;
1568         }
1569                 
1570         /* FIXME: bind the fb to the right crtc */
1571         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1572                 crtc->fb = fb;
1573                 dev->driver->fb_probe(dev, crtc);
1574         }
1575
1576 out:
1577         mutex_unlock(&dev->mode_config.mutex);
1578         return ret;
1579 }
1580
1581 /**
1582  * drm_mode_rmfb - remove an FB from the configuration
1583  * @inode: inode from the ioctl
1584  * @filp: file * from the ioctl
1585  * @cmd: cmd from ioctl
1586  * @arg: arg from ioctl
1587  *
1588  * LOCKING:
1589  * Takes mode config lock.
1590  *
1591  * Remove the FB specified by the user.
1592  *
1593  * Called by the user via ioctl.
1594  *
1595  * RETURNS:
1596  * Zero on success, errno on failure.
1597  */
1598 int drm_mode_rmfb(struct inode *inode, struct file *filp,
1599                    unsigned int cmd, unsigned long arg)
1600 {
1601         drm_file_t *priv = filp->private_data;
1602         drm_device_t *dev = priv->head->dev;
1603         struct drm_framebuffer *fb = 0;
1604         uint32_t id = arg;
1605         int ret = 0;
1606
1607         mutex_lock(&dev->mode_config.mutex);
1608         fb = idr_find(&dev->mode_config.crtc_idr, id);
1609         /* TODO check that we realy get a framebuffer back. */
1610         if (!fb || (id != fb->id)) {
1611                 DRM_ERROR("mode invalid framebuffer id\n");
1612                 ret = -EINVAL;
1613                 goto out;
1614         }
1615
1616         dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
1617
1618         /* TODO check if we own the buffer */
1619         /* TODO release all crtc connected to the framebuffer */
1620         /* bind the fb to the crtc for now */
1621         /* TODO unhock the destructor from the buffer object */
1622
1623         drm_framebuffer_destroy(fb);
1624
1625 out:
1626         mutex_unlock(&dev->mode_config.mutex);
1627         return ret;
1628 }
1629
1630 /**
1631  * drm_mode_getfb - get FB info
1632  * @inode: inode from the ioctl
1633  * @filp: file * from the ioctl
1634  * @cmd: cmd from ioctl
1635  * @arg: arg from ioctl
1636  *
1637  * LOCKING:
1638  * Caller? (FIXME)
1639  *
1640  * Lookup the FB given its ID and return info about it.
1641  *
1642  * Called by the user via ioctl.
1643  *
1644  * RETURNS:
1645  * Zero on success, errno on failure.
1646  */
1647 int drm_mode_getfb(struct inode *inode, struct file *filp,
1648                    unsigned int cmd, unsigned long arg)
1649 {
1650         drm_file_t *priv = filp->private_data;
1651         drm_device_t *dev = priv->head->dev;    
1652         struct drm_mode_fb_cmd __user *argp = (void __user *)arg;
1653         struct drm_mode_fb_cmd r;
1654         struct drm_framebuffer *fb;
1655         int ret = 0;
1656
1657         if (copy_from_user(&r, argp, sizeof(r)))
1658                 return -EFAULT;
1659
1660         mutex_lock(&dev->mode_config.mutex);
1661         fb = idr_find(&dev->mode_config.crtc_idr, r.buffer_id);
1662         if (!fb || (r.buffer_id != fb->id)) {
1663                 DRM_ERROR("invalid framebuffer id\n");
1664                 ret = -EINVAL;
1665                 goto out;
1666         }
1667
1668         r.height = fb->height;
1669         r.width = fb->width;
1670         r.depth = fb->depth;
1671         r.bpp = fb->bits_per_pixel;
1672         r.handle = fb->bo->base.hash.key;
1673         r.pitch = fb->pitch;
1674
1675         if (copy_to_user(argp, &r, sizeof(r)))
1676                 ret = -EFAULT;
1677
1678 out:
1679         mutex_unlock(&dev->mode_config.mutex);
1680         return ret;
1681 }
1682
1683 /**
1684  * drm_fb_release - remove and free the FBs on this file
1685  * @filp: file * from the ioctl
1686  *
1687  * LOCKING:
1688  * Takes mode config lock.
1689  *
1690  * Destroy all the FBs associated with @filp.
1691  *
1692  * Called by the user via ioctl.
1693  *
1694  * RETURNS:
1695  * Zero on success, errno on failure.
1696  */
1697 void drm_fb_release(struct file *filp)
1698 {
1699         drm_file_t *priv = filp->private_data;
1700         drm_device_t *dev = priv->head->dev;
1701         struct drm_framebuffer *fb, *tfb;
1702
1703         mutex_lock(&dev->mode_config.mutex);
1704         list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
1705                 list_del(&fb->filp_head);
1706                 dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
1707                 drm_framebuffer_destroy(fb);
1708         }
1709         mutex_unlock(&dev->mode_config.mutex);
1710 }
1711
1712 /**
1713  * drm_fb_newmode - adds a user defined mode
1714  * @inode: inode from the ioctl
1715  * @filp: file * from the ioctl
1716  * @cmd: cmd from ioctl
1717  * @arg: arg from ioctl
1718  *
1719  * Adds a user specified mode to the kernel.
1720  *
1721  * Called by the user via ioctl.
1722  *
1723  * RETURNS:
1724  * writes new mode id into arg.
1725  * Zero on success, errno on failure.
1726  */
1727 int drm_mode_addmode(struct inode *inode, struct file *filp,
1728                      unsigned int cmd, unsigned long arg)
1729 {
1730         drm_file_t *priv = filp->private_data;
1731         drm_device_t *dev = priv->head->dev;
1732         struct drm_mode_modeinfo __user *argp = (void __user *)arg;
1733         struct drm_mode_modeinfo new_mode;
1734         struct drm_display_mode *user_mode;
1735         int ret = 0;
1736
1737         if (copy_from_user(&new_mode, argp, sizeof(new_mode)))
1738                 return -EFAULT;
1739
1740         mutex_lock(&dev->mode_config.mutex);
1741         user_mode = drm_mode_create(dev);
1742         if (!user_mode) {
1743                 ret = -ENOMEM;
1744                 goto out;
1745         }
1746
1747         drm_crtc_convert_umode(user_mode, &new_mode);
1748         user_mode->type |= DRM_MODE_TYPE_USERDEF;
1749
1750         user_mode->output_count = 0;
1751
1752         list_add(&user_mode->head, &dev->mode_config.usermode_list);
1753
1754         new_mode.id = user_mode->mode_id;
1755         if (copy_to_user(argp, &new_mode, sizeof(new_mode)))
1756                 ret = -EFAULT;
1757
1758 out:
1759         mutex_unlock(&dev->mode_config.mutex);
1760         return ret;
1761 }
1762
1763 /**
1764  * drm_fb_rmmode - removes a user defined mode
1765  * @inode: inode from the ioctl
1766  * @filp: file * from the ioctl
1767  * @cmd: cmd from ioctl
1768  * @arg: arg from ioctl
1769  *
1770  * Remove the user defined mode specified by the user.
1771  *
1772  * Called by the user via ioctl
1773  *
1774  * RETURNS:
1775  * Zero on success, errno on failure.
1776  */
1777 int drm_mode_rmmode(struct inode *inode, struct file *filp,
1778                     unsigned int cmd, unsigned long arg)
1779 {
1780         drm_file_t *priv = filp->private_data;
1781         drm_device_t *dev = priv->head->dev;
1782         uint32_t id = arg;
1783         struct drm_display_mode *mode, *t;
1784         int ret = -EINVAL;
1785
1786         mutex_lock(&dev->mode_config.mutex);    
1787         mode = idr_find(&dev->mode_config.crtc_idr, id);
1788         if (!mode || (id != mode->mode_id)) {
1789                 ret = -EINVAL;
1790                 goto out;
1791         }
1792
1793         if (!(mode->type & DRM_MODE_TYPE_USERDEF)) {
1794                 ret = -EINVAL;
1795                 goto out;
1796         }
1797
1798         if (mode->output_count) {
1799                 ret = -EINVAL;
1800                 goto out;
1801         }
1802
1803         list_for_each_entry(t, &dev->mode_config.usermode_list, head) {
1804                 if (t == mode) {
1805                         list_del(&mode->head);
1806                         drm_mode_destroy(dev, mode);
1807                         ret = 0;
1808                         break;
1809                 }
1810         }
1811
1812 out:
1813         mutex_unlock(&dev->mode_config.mutex);
1814         return ret;
1815 }
1816
1817 /**
1818  * drm_fb_attachmode - Attach a user mode to an output
1819  * @inode: inode from the ioctl
1820  * @filp: file * from the ioctl
1821  * @cmd: cmd from ioctl
1822  * @arg: arg from ioctl
1823  *
1824  * This attaches a user specified mode to an output.
1825  * Called by the user via ioctl.
1826  *
1827  * RETURNS:
1828  * Zero on success, errno on failure.
1829  */
1830 int drm_mode_attachmode(struct inode *inode, struct file *filp,
1831                         unsigned int cmd, unsigned long arg)
1832 {
1833         drm_file_t *priv = filp->private_data;
1834         drm_device_t *dev = priv->head->dev;
1835         struct drm_mode_mode_cmd __user *argp = (void __user *)arg;
1836         struct drm_mode_mode_cmd mode_cmd;
1837         struct drm_output *output;
1838         struct drm_display_mode *mode;
1839         int i, ret = 0;
1840
1841         if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd)))
1842                 return -EFAULT;
1843
1844         mutex_lock(&dev->mode_config.mutex);
1845
1846         mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id);
1847         if (!mode || (mode->mode_id != mode_cmd.mode_id)) {
1848                 ret = -EINVAL;
1849                 goto out;
1850         }
1851
1852         output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id);
1853         if (!output || (output->id != mode_cmd.output_id)) {
1854                 ret = -EINVAL;
1855                 goto out;
1856         }
1857
1858         for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
1859                 if (output->user_mode_ids[i] == 0) {
1860                         output->user_mode_ids[i] = mode->mode_id;
1861                         mode->output_count++;
1862                         break;
1863                 }
1864         }
1865
1866         if (i == DRM_OUTPUT_MAX_UMODES)
1867                 ret = -ENOSPC;
1868
1869 out:
1870         mutex_unlock(&dev->mode_config.mutex);
1871         return ret;
1872 }
1873
1874
1875 /**
1876  * drm_fb_detachmode - Detach a user specified mode from an output
1877  * @inode: inode from the ioctl
1878  * @filp: file * from the ioctl
1879  * @cmd: cmd from ioctl
1880  * @arg: arg from ioctl
1881  *
1882  * Called by the user via ioctl.
1883  *
1884  * RETURNS:
1885  * Zero on success, errno on failure.
1886  */
1887 int drm_mode_detachmode(struct inode *inode, struct file *filp,
1888                         unsigned int cmd, unsigned long arg)
1889 {
1890         drm_file_t *priv = filp->private_data;
1891         drm_device_t *dev = priv->head->dev;
1892         struct drm_mode_mode_cmd __user *argp = (void __user *)arg;
1893         struct drm_mode_mode_cmd mode_cmd;
1894         struct drm_output *output;
1895         struct drm_display_mode *mode;
1896         int i, found = 0, ret = 0;
1897
1898         if (copy_from_user(&mode_cmd, argp, sizeof(mode_cmd)))
1899                 return -EFAULT;
1900
1901         mutex_lock(&dev->mode_config.mutex);
1902
1903         mode = idr_find(&dev->mode_config.crtc_idr, mode_cmd.mode_id);
1904         if (!mode || (mode->mode_id != mode_cmd.mode_id)) {
1905                 ret = -EINVAL;
1906                 goto out;
1907         }
1908
1909         output = idr_find(&dev->mode_config.crtc_idr, mode_cmd.output_id);
1910         if (!output || (output->id != mode_cmd.output_id)) {
1911                 ret = -EINVAL;
1912                 goto out;
1913         }
1914
1915
1916         for (i = 0; i < DRM_OUTPUT_MAX_UMODES; i++) {
1917                 if (output->user_mode_ids[i] == mode->mode_id) {
1918                         output->user_mode_ids[i] = 0;
1919                         mode->output_count--;
1920                         found = 1;
1921                 }
1922         }
1923
1924         if (!found)
1925                 ret = -EINVAL;
1926
1927 out:           
1928         mutex_unlock(&dev->mode_config.mutex);
1929         return ret;
1930 }