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