Implement short circuit for base change only
[profile/ivi/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 struct drm_prop_enum_list {
37         int type;
38         char *name;
39 };
40
41 /*
42  * Global properties
43  */
44 static struct drm_prop_enum_list drm_dpms_enum_list[] =
45 { { DPMSModeOn, "On" },
46   { DPMSModeStandby, "Standby" },
47   { DPMSModeSuspend, "Suspend" },
48   { DPMSModeOff, "Off" }
49 };
50 static struct drm_prop_enum_list drm_conn_enum_list[] = 
51 { { ConnectorVGA, "VGA" },
52   { ConnectorDVII, "DVI-I" },
53   { ConnectorDVID, "DVI-D" },
54   { ConnectorDVIA, "DVI-A" },
55   { ConnectorComposite, "Composite" },
56   { ConnectorSVIDEO, "SVIDEO" },
57   { ConnectorLVDS, "LVDS" },
58   { ConnectorComponent, "Component" },
59   { Connector9PinDIN, "9-pin DIN" },
60   { ConnectorDisplayPort, "DisplayPort" },
61   { ConnectorHDMIA, "HDMI Type A" },
62   { ConnectorHDMIB, "HDMI Type B" },
63 };
64 static struct drm_prop_enum_list drm_output_enum_list[] =
65 { { DRM_MODE_OUTPUT_NONE, "None" },
66   { DRM_MODE_OUTPUT_DAC, "DAC" },
67   { DRM_MODE_OUTPUT_TMDS, "TMDS" },
68   { DRM_MODE_OUTPUT_LVDS, "LVDS" },
69   { DRM_MODE_OUTPUT_TVDAC, "TV" },
70 };
71
72 char *drm_get_output_name(struct drm_output *output)
73 {
74         static char buf[32];
75
76         snprintf(buf, 32, "%s-%d", drm_output_enum_list[output->output_type].name,
77                  output->output_type_id);
78         return buf;
79 }
80
81 /**
82  * drm_idr_get - allocate a new identifier
83  * @dev: DRM device
84  * @ptr: object pointer, used to generate unique ID
85  *
86  * LOCKING:
87  * Caller must hold DRM mode_config lock.
88  *
89  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
90  * for tracking modes, CRTCs and outputs.
91  *
92  * RETURNS:
93  * New unique (relative to other objects in @dev) integer identifier for the
94  * object.
95  */
96 int drm_idr_get(struct drm_device *dev, void *ptr)
97 {
98         int new_id = 0;
99         int ret;
100 again:
101         if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
102                 DRM_ERROR("Ran out memory getting a mode number\n");
103                 return 0;
104         }
105
106         ret = idr_get_new_above(&dev->mode_config.crtc_idr, ptr, 1, &new_id);
107         if (ret == -EAGAIN)
108                 goto again;     
109
110         return new_id;
111 }
112
113 /**
114  * drm_idr_put - free an identifer
115  * @dev: DRM device
116  * @id: ID to free
117  *
118  * LOCKING:
119  * Caller must hold DRM mode_config lock.
120  *
121  * Free @id from @dev's unique identifier pool.
122  */
123 void drm_idr_put(struct drm_device *dev, int id)
124 {
125         idr_remove(&dev->mode_config.crtc_idr, id);
126 }
127
128 /**
129  * drm_crtc_from_fb - find the CRTC structure associated with an fb
130  * @dev: DRM device
131  * @fb: framebuffer in question
132  *
133  * LOCKING:
134  * Caller must hold mode_config lock.
135  *
136  * Find CRTC in the mode_config structure that matches @fb.
137  *
138  * RETURNS:
139  * Pointer to the CRTC or NULL if it wasn't found.
140  */
141 struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
142                                   struct drm_framebuffer *fb)
143 {
144         struct drm_crtc *crtc;
145
146         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
147                 if (crtc->fb == fb)
148                         return crtc;
149         }
150         return NULL;
151 }
152
153 /**
154  * drm_framebuffer_create - create a new framebuffer object
155  * @dev: DRM device
156  *
157  * LOCKING:
158  * Caller must hold mode config lock.
159  *
160  * Creates a new framebuffer objects and adds it to @dev's DRM mode_config.
161  *
162  * RETURNS:
163  * Pointer to new framebuffer or NULL on error.
164  */
165 struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev)
166 {
167         struct drm_framebuffer *fb;
168
169         fb = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL);
170         if (!fb)
171                 return NULL;
172         
173         fb->id = drm_idr_get(dev, fb);
174         fb->dev = dev;
175         dev->mode_config.num_fb++;
176         list_add(&fb->head, &dev->mode_config.fb_list);
177
178         return fb;
179 }
180 EXPORT_SYMBOL(drm_framebuffer_create);
181
182 /**
183  * drm_framebuffer_destroy - remove a framebuffer object
184  * @fb: framebuffer to remove
185  *
186  * LOCKING:
187  * Caller must hold mode config lock.
188  *
189  * Scans all the CRTCs in @dev's mode_config.  If they're using @fb, removes
190  * it, setting it to NULL.
191  */
192 void drm_framebuffer_destroy(struct drm_framebuffer *fb)
193 {
194         struct drm_device *dev = fb->dev;
195         struct drm_crtc *crtc;
196
197         /* remove from any CRTC */
198         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
199                 if (crtc->fb == fb)
200                         crtc->fb = NULL;
201         }
202
203         drm_idr_put(dev, fb->id);
204         list_del(&fb->head);
205         dev->mode_config.num_fb--;
206
207         kfree(fb);
208 }
209 EXPORT_SYMBOL(drm_framebuffer_destroy);
210
211 /**
212  * drm_crtc_create - create a new CRTC object
213  * @dev: DRM device
214  * @funcs: callbacks for the new CRTC
215  *
216  * LOCKING:
217  * Caller must hold mode config lock.
218  *
219  * Creates a new CRTC object and adds it to @dev's mode_config structure.
220  *
221  * RETURNS:
222  * Pointer to new CRTC object or NULL on error.
223  */
224 struct drm_crtc *drm_crtc_create(struct drm_device *dev,
225                                  const struct drm_crtc_funcs *funcs)
226 {
227         struct drm_crtc *crtc;
228
229         crtc = kzalloc(sizeof(struct drm_crtc), GFP_KERNEL);
230         if (!crtc)
231                 return NULL;
232
233         crtc->dev = dev;
234         crtc->funcs = funcs;
235
236         crtc->id = drm_idr_get(dev, crtc);
237
238         list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
239         dev->mode_config.num_crtc++;
240
241         return crtc;
242 }
243 EXPORT_SYMBOL(drm_crtc_create);
244
245 /**
246  * drm_crtc_destroy - remove a CRTC object
247  * @crtc: CRTC to remove
248  *
249  * LOCKING:
250  * Caller must hold mode config lock.
251  *
252  * Cleanup @crtc.  Calls @crtc's cleanup function, then removes @crtc from
253  * its associated DRM device's mode_config.  Frees it afterwards.
254  */
255 void drm_crtc_destroy(struct drm_crtc *crtc)
256 {
257         struct drm_device *dev = crtc->dev;
258
259         if (crtc->funcs->cleanup)
260                 (*crtc->funcs->cleanup)(crtc);
261
262         drm_idr_put(dev, crtc->id);
263         list_del(&crtc->head);
264         dev->mode_config.num_crtc--;
265         kfree(crtc);
266 }
267 EXPORT_SYMBOL(drm_crtc_destroy);
268
269 /**
270  * drm_crtc_in_use - check if a given CRTC is in a mode_config
271  * @crtc: CRTC to check
272  *
273  * LOCKING:
274  * Caller must hold mode config lock.
275  *
276  * Walk @crtc's DRM device's mode_config and see if it's in use.
277  *
278  * RETURNS:
279  * True if @crtc is part of the mode_config, false otherwise.
280  */
281 bool drm_crtc_in_use(struct drm_crtc *crtc)
282 {
283         struct drm_output *output;
284         struct drm_device *dev = crtc->dev;
285         /* FIXME: Locking around list access? */
286         list_for_each_entry(output, &dev->mode_config.output_list, head)
287                 if (output->crtc == crtc)
288                         return true;
289         return false;
290 }
291 EXPORT_SYMBOL(drm_crtc_in_use);
292
293 /*
294  * Detailed mode info for a standard 640x480@60Hz monitor
295  */
296 static struct drm_display_mode std_mode[] = {
297         { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
298                    752, 800, 0, 480, 490, 492, 525, 0,
299                    V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
300 };
301
302 /**
303  * drm_crtc_probe_output_modes - get complete set of display modes
304  * @dev: DRM device
305  * @maxX: max width for modes
306  * @maxY: max height for modes
307  *
308  * LOCKING:
309  * Caller must hold mode config lock.
310  *
311  * Based on @dev's mode_config layout, scan all the outputs and try to detect
312  * modes on them.  Modes will first be added to the output's probed_modes
313  * list, then culled (based on validity and the @maxX, @maxY parameters) and
314  * put into the normal modes list.
315  *
316  * Intended to be used either at bootup time or when major configuration
317  * changes have occurred.
318  *
319  * FIXME: take into account monitor limits
320  */
321 void drm_crtc_probe_single_output_modes(struct drm_output *output, int maxX, int maxY)
322 {
323         struct drm_device *dev = output->dev;
324         struct drm_display_mode *mode, *t;
325         int ret;
326         //if (maxX == 0 || maxY == 0) 
327         // TODO
328
329         /* set all modes to the unverified state */
330         list_for_each_entry_safe(mode, t, &output->modes, head)
331                 mode->status = MODE_UNVERIFIED;
332                 
333         output->status = (*output->funcs->detect)(output);
334         
335         if (output->status == output_status_disconnected) {
336                 DRM_DEBUG("%s is disconnected\n", drm_get_output_name(output));
337                 /* TODO set EDID to NULL */
338                 return;
339         }
340         
341         ret = (*output->funcs->get_modes)(output);
342         
343         if (ret) {
344                 drm_mode_output_list_update(output);
345         }
346         
347         if (maxX && maxY)
348                 drm_mode_validate_size(dev, &output->modes, maxX,
349                                        maxY, 0);
350         list_for_each_entry_safe(mode, t, &output->modes, head) {
351                 if (mode->status == MODE_OK)
352                         mode->status = (*output->funcs->mode_valid)(output,mode);
353         }
354         
355         
356         drm_mode_prune_invalid(dev, &output->modes, TRUE);
357         
358         if (list_empty(&output->modes)) {
359                 struct drm_display_mode *stdmode;
360                 
361                 DRM_DEBUG("No valid modes on %s\n", drm_get_output_name(output));
362                 
363                 /* Should we do this here ???
364                  * When no valid EDID modes are available we end up
365                  * here and bailed in the past, now we add a standard
366                  * 640x480@60Hz mode and carry on.
367                  */
368                 stdmode = drm_mode_duplicate(dev, &std_mode[0]);
369                 drm_mode_probed_add(output, stdmode);
370                 drm_mode_list_concat(&output->probed_modes,
371                                      &output->modes);
372                 
373                 DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
374                           drm_get_output_name(output));
375         }
376         
377         drm_mode_sort(&output->modes);
378         
379         DRM_DEBUG("Probed modes for %s\n", drm_get_output_name(output));
380         list_for_each_entry_safe(mode, t, &output->modes, head) {
381                 mode->vrefresh = drm_mode_vrefresh(mode);
382                 
383                 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
384                 drm_mode_debug_printmodeline(dev, mode);
385         }
386 }
387
388 void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY)
389 {
390         struct drm_output *output;
391
392         list_for_each_entry(output, &dev->mode_config.output_list, head) {
393                 drm_crtc_probe_single_output_modes(output, maxX, maxY);
394         }
395 }
396 EXPORT_SYMBOL(drm_crtc_probe_output_modes);
397
398 /**
399  * drm_crtc_set_mode - set a mode
400  * @crtc: CRTC to program
401  * @mode: mode to use
402  * @x: width of mode
403  * @y: height of mode
404  *
405  * LOCKING:
406  * Caller must hold mode config lock.
407  *
408  * Try to set @mode on @crtc.  Give @crtc and its associated outputs a chance
409  * to fixup or reject the mode prior to trying to set it.
410  *
411  * RETURNS:
412  * True if the mode was set successfully, or false otherwise.
413  */
414 bool drm_crtc_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
415                        int x, int y)
416 {
417         struct drm_device *dev = crtc->dev;
418         struct drm_display_mode *adjusted_mode, saved_mode;
419         int saved_x, saved_y;
420         bool didLock = false;
421         struct drm_output *output;
422
423         adjusted_mode = drm_mode_duplicate(dev, mode);
424
425         crtc->enabled = drm_crtc_in_use(crtc);
426
427         if (!crtc->enabled) {
428                 return true;
429         }
430
431         didLock = crtc->funcs->lock(crtc);
432
433         saved_mode = crtc->mode;
434         saved_x = crtc->x;
435         saved_y = crtc->y;
436         
437         /* Update crtc values up front so the driver can rely on them for mode
438          * setting.
439          */
440         crtc->mode = *mode;
441         crtc->x = x;
442         crtc->y = y;
443
444         if (drm_mode_equal(&saved_mode, &crtc->mode)) {
445                 if (saved_x != crtc->x || saved_y != crtc->y) {
446                         crtc->funcs->mode_set_base(crtc, crtc->x, crtc->y);
447                         goto done;
448                 }
449         }
450
451         /* Pass our mode to the outputs and the CRTC to give them a chance to
452          * adjust it according to limitations or output properties, and also
453          * a chance to reject the mode entirely.
454          */
455         list_for_each_entry(output, &dev->mode_config.output_list, head) {
456                 
457                 if (output->crtc != crtc)
458                         continue;
459                 
460                 if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
461                         goto done;
462                 }
463         }
464         
465         if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
466                 goto done;
467         }
468
469         /* Prepare the outputs and CRTCs before setting the mode. */
470         list_for_each_entry(output, &dev->mode_config.output_list, head) {
471
472                 if (output->crtc != crtc)
473                         continue;
474                 
475                 /* Disable the output as the first thing we do. */
476                 output->funcs->prepare(output);
477         }
478         
479         crtc->funcs->prepare(crtc);
480         
481         /* Set up the DPLL and any output state that needs to adjust or depend
482          * on the DPLL.
483          */
484         crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
485
486         list_for_each_entry(output, &dev->mode_config.output_list, head) {
487
488                 if (output->crtc != crtc)
489                         continue;
490                 
491                 DRM_INFO("%s: set mode %s %x\n", drm_get_output_name(output), mode->name, mode->mode_id);
492
493                 output->funcs->mode_set(output, mode, adjusted_mode);
494         }
495         
496         /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
497         crtc->funcs->commit(crtc);
498
499         list_for_each_entry(output, &dev->mode_config.output_list, head) {
500
501                 if (output->crtc != crtc)
502                         continue;
503                 
504                 output->funcs->commit(output);
505
506 #if 0 // TODO def RANDR_12_INTERFACE
507                 if (output->randr_output)
508                         RRPostPendingProperties (output->randr_output);
509 #endif
510         }
511         
512         /* XXX free adjustedmode */
513         drm_mode_destroy(dev, adjusted_mode);
514         /* TODO */
515 //      if (scrn->pScreen)
516 //              drm_crtc_set_screen_sub_pixel_order(dev);
517
518 done:
519         if (didLock)
520                 crtc->funcs->unlock (crtc);
521         
522         return true;
523 }
524 EXPORT_SYMBOL(drm_crtc_set_mode);
525
526 /**
527  * drm_disable_unused_functions - disable unused objects
528  * @dev: DRM device
529  *
530  * LOCKING:
531  * Caller must hold mode config lock.
532  *
533  * If an output or CRTC isn't part of @dev's mode_config, it can be disabled
534  * by calling its dpms function, which should power it off.
535  */
536 void drm_disable_unused_functions(struct drm_device *dev)
537 {
538         struct drm_output *output;
539         struct drm_crtc *crtc;
540
541         list_for_each_entry(output, &dev->mode_config.output_list, head) {
542                 if (!output->crtc)
543                         (*output->funcs->dpms)(output, DPMSModeOff);
544         }
545
546         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
547                 if (!crtc->enabled)
548                         crtc->funcs->dpms(crtc, DPMSModeOff);
549         }
550 }
551 EXPORT_SYMBOL(drm_disable_unused_functions);
552
553 /**
554  * drm_mode_probed_add - add a mode to the specified output's probed mode list
555  * @output: output the new mode
556  * @mode: mode data
557  *
558  * LOCKING:
559  * Caller must hold mode config lock.
560  * 
561  * Add @mode to @output's mode list for later use.
562  */
563 void drm_mode_probed_add(struct drm_output *output,
564                          struct drm_display_mode *mode)
565 {
566         list_add(&mode->head, &output->probed_modes);
567 }
568 EXPORT_SYMBOL(drm_mode_probed_add);
569
570 /**
571  * drm_mode_remove - remove and free a mode
572  * @output: output list to modify
573  * @mode: mode to remove
574  *
575  * LOCKING:
576  * Caller must hold mode config lock.
577  * 
578  * Remove @mode from @output's mode list, then free it.
579  */
580 void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode)
581 {
582         list_del(&mode->head);
583         kfree(mode);
584 }
585 EXPORT_SYMBOL(drm_mode_remove);
586
587 /**
588  * drm_output_create - create a new output
589  * @dev: DRM device
590  * @funcs: callbacks for this output
591  * @name: user visible name of the output
592  *
593  * LOCKING:
594  * Caller must hold @dev's mode_config lock.
595  *
596  * Creates a new drm_output structure and adds it to @dev's mode_config
597  * structure.
598  *
599  * RETURNS:
600  * Pointer to the new output or NULL on error.
601  */
602 struct drm_output *drm_output_create(struct drm_device *dev,
603                                      const struct drm_output_funcs *funcs,
604                                      int output_type)
605 {
606         struct drm_output *output = NULL;
607
608         output = kzalloc(sizeof(struct drm_output), GFP_KERNEL);
609         if (!output)
610                 return NULL;
611                 
612         output->dev = dev;
613         output->funcs = funcs;
614         output->id = drm_idr_get(dev, output);
615         output->output_type = output_type;
616         output->output_type_id = 1; /* TODO */
617         output->subpixel_order = SubPixelUnknown;
618         INIT_LIST_HEAD(&output->user_modes);
619         INIT_LIST_HEAD(&output->probed_modes);
620         INIT_LIST_HEAD(&output->modes);
621         /* randr_output? */
622         /* output_set_monitor(output)? */
623         /* check for output_ignored(output)? */
624
625         mutex_lock(&dev->mode_config.mutex);
626         list_add_tail(&output->head, &dev->mode_config.output_list);
627         dev->mode_config.num_output++;
628
629         drm_output_attach_property(output, dev->mode_config.edid_property, 0);
630
631         drm_output_attach_property(output, dev->mode_config.dpms_property, 0);
632
633         mutex_unlock(&dev->mode_config.mutex);
634
635         return output;
636
637 }
638 EXPORT_SYMBOL(drm_output_create);
639
640 /**
641  * drm_output_destroy - remove an output
642  * @output: output to remove
643  *
644  * LOCKING:
645  * Caller must hold @dev's mode_config lock.
646  *
647  * Call @output's cleanup function, then remove the output from the DRM
648  * mode_config after freeing @output's modes.
649  */
650 void drm_output_destroy(struct drm_output *output)
651 {
652         struct drm_device *dev = output->dev;
653         struct drm_display_mode *mode, *t;
654
655         if (*output->funcs->cleanup)
656                 (*output->funcs->cleanup)(output);
657
658         list_for_each_entry_safe(mode, t, &output->probed_modes, head)
659                 drm_mode_remove(output, mode);
660
661         list_for_each_entry_safe(mode, t, &output->modes, head)
662                 drm_mode_remove(output, mode);
663
664         list_for_each_entry_safe(mode, t, &output->user_modes, head)
665                 drm_mode_remove(output, mode);
666
667         mutex_lock(&dev->mode_config.mutex);
668         drm_idr_put(dev, output->id);
669         list_del(&output->head);
670         mutex_unlock(&dev->mode_config.mutex);
671         kfree(output);
672 }
673 EXPORT_SYMBOL(drm_output_destroy);
674
675
676 /**
677  * drm_mode_create - create a new display mode
678  * @dev: DRM device
679  *
680  * LOCKING:
681  * None.
682  *
683  * Create a new drm_display_mode, give it an ID, and return it.
684  *
685  * RETURNS:
686  * Pointer to new mode on success, NULL on error.
687  */
688 struct drm_display_mode *drm_mode_create(struct drm_device *dev)
689 {
690         struct drm_display_mode *nmode;
691
692         nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
693         if (!nmode)
694                 return NULL;
695
696         nmode->mode_id = drm_idr_get(dev, nmode);
697         return nmode;
698 }
699 EXPORT_SYMBOL(drm_mode_create);
700
701 /**
702  * drm_mode_destroy - remove a mode
703  * @dev: DRM device
704  * @mode: mode to remove
705  *
706  * LOCKING:
707  * Caller must hold mode config lock.
708  *
709  * Free @mode's unique identifier, then free it.
710  */
711 void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
712 {
713         drm_idr_put(dev, mode->mode_id);
714
715         kfree(mode);
716 }
717 EXPORT_SYMBOL(drm_mode_destroy);
718
719 static int drm_mode_create_standard_output_properties(struct drm_device *dev)
720 {
721         int i;
722
723         /*
724          * Standard properties (apply to all outputs)
725          */
726         dev->mode_config.edid_property =
727                 drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE,
728                                     "EDID", 0);
729
730         dev->mode_config.dpms_property =
731                 drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", 4);
732
733         for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++)
734                 drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name);
735
736         dev->mode_config.connector_type_property =
737                 drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE,
738                                     "Connector Type", 10);
739         for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++)
740                 drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name);
741
742         dev->mode_config.connector_num_property =
743                 drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE,
744                                     "Connector ID", 2);
745         dev->mode_config.connector_num_property->values[0] = 0;
746         dev->mode_config.connector_num_property->values[1] = 20;
747
748         /*
749          * TV specific properties
750          */
751         dev->mode_config.tv_left_margin_property =
752                 drm_property_create(dev, DRM_MODE_PROP_RANGE |
753                                     DRM_MODE_PROP_IMMUTABLE,
754                                     "left margin", 2);
755         dev->mode_config.tv_left_margin_property->values[0] = 0;
756         dev->mode_config.tv_left_margin_property->values[1] = 100;
757
758         dev->mode_config.tv_right_margin_property =
759                 drm_property_create(dev, DRM_MODE_PROP_RANGE |
760                                     DRM_MODE_PROP_IMMUTABLE,
761                                     "right margin", 2);
762         dev->mode_config.tv_right_margin_property->values[0] = 0;
763         dev->mode_config.tv_right_margin_property->values[1] = 100;
764
765         dev->mode_config.tv_top_margin_property =
766                 drm_property_create(dev, DRM_MODE_PROP_RANGE |
767                                     DRM_MODE_PROP_IMMUTABLE,
768                                     "top margin", 2);
769         dev->mode_config.tv_top_margin_property->values[0] = 0;
770         dev->mode_config.tv_top_margin_property->values[1] = 100;
771
772         dev->mode_config.tv_bottom_margin_property =
773                 drm_property_create(dev, DRM_MODE_PROP_RANGE |
774                                     DRM_MODE_PROP_IMMUTABLE,
775                                     "bottom margin", 2);
776         dev->mode_config.tv_bottom_margin_property->values[0] = 0;
777         dev->mode_config.tv_bottom_margin_property->values[1] = 100;
778
779
780         return 0;
781 }
782
783 /**
784  * drm_mode_config_init - initialize DRM mode_configuration structure
785  * @dev: DRM device
786  *
787  * LOCKING:
788  * None, should happen single threaded at init time.
789  *
790  * Initialize @dev's mode_config structure, used for tracking the graphics
791  * configuration of @dev.
792  */
793 void drm_mode_config_init(struct drm_device *dev)
794 {
795         mutex_init(&dev->mode_config.mutex);
796         INIT_LIST_HEAD(&dev->mode_config.fb_list);
797         INIT_LIST_HEAD(&dev->mode_config.crtc_list);
798         INIT_LIST_HEAD(&dev->mode_config.output_list);
799         INIT_LIST_HEAD(&dev->mode_config.property_list);
800         INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
801         idr_init(&dev->mode_config.crtc_idr);
802
803         drm_mode_create_standard_output_properties(dev);
804
805         /* Just to be sure */
806         dev->mode_config.num_fb = 0;
807         dev->mode_config.num_output = 0;
808         dev->mode_config.num_crtc = 0;
809         dev->mode_config.hotplug_counter = 0;
810 }
811 EXPORT_SYMBOL(drm_mode_config_init);
812
813 /**
814  * drm_get_buffer_object - find the buffer object for a given handle
815  * @dev: DRM device
816  * @bo: pointer to caller's buffer_object pointer
817  * @handle: handle to lookup
818  *
819  * LOCKING:
820  * Must take @dev's struct_mutex to protect buffer object lookup.
821  *
822  * Given @handle, lookup the buffer object in @dev and put it in the caller's
823  * @bo pointer.
824  *
825  * RETURNS:
826  * Zero on success, -EINVAL if the handle couldn't be found.
827  */
828 static int drm_get_buffer_object(struct drm_device *dev, struct drm_buffer_object **bo, unsigned long handle)
829 {
830         struct drm_user_object *uo;
831         struct drm_hash_item *hash;
832         int ret;
833
834         *bo = NULL;
835
836         mutex_lock(&dev->struct_mutex);
837         ret = drm_ht_find_item(&dev->object_hash, handle, &hash);
838         if (ret) {
839                 DRM_ERROR("Couldn't find handle.\n");
840                 ret = -EINVAL;
841                 goto out_err;
842         }
843
844         uo = drm_hash_entry(hash, struct drm_user_object, hash);
845         if (uo->type != drm_buffer_type) {
846                 ret = -EINVAL;
847                 goto out_err;
848         }
849         
850         *bo = drm_user_object_entry(uo, struct drm_buffer_object, base);
851         ret = 0;
852 out_err:
853         mutex_unlock(&dev->struct_mutex);
854         return ret;
855 }
856
857 /**
858  * drm_pick_crtcs - pick crtcs for output devices
859  * @dev: DRM device
860  *
861  * LOCKING:
862  * Caller must hold mode config lock.
863  */
864 static void drm_pick_crtcs (struct drm_device *dev)
865 {
866         int c, o, assigned;
867         struct drm_output *output, *output_equal;
868         struct drm_crtc   *crtc;
869         struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
870         int found;
871
872         list_for_each_entry(output, &dev->mode_config.output_list, head) {
873                 output->crtc = NULL;
874     
875                 /* Don't hook up outputs that are disconnected ??
876                  *
877                  * This is debateable. Do we want fixed /dev/fbX or
878                  * dynamic on hotplug (need mode code for that though) ?
879                  *
880                  * If we don't hook up outputs now, then we only create
881                  * /dev/fbX for the output that's enabled, that's good as
882                  * the users console will be on that output.
883                  *
884                  * If we do hook up outputs that are disconnected now, then
885                  * the user may end up having to muck about with the fbcon
886                  * map flags to assign his console to the enabled output. Ugh.
887                  */
888                 if (output->status != output_status_connected)
889                         continue;
890
891                 if (list_empty(&output->modes))
892                         continue;
893
894                 des_mode = NULL;
895                 found = 0;
896                 list_for_each_entry(des_mode, &output->modes, head) {
897                         if (des_mode->type & DRM_MODE_TYPE_PREFERRED) {
898                                 found = 1;
899                                 break;
900                         }
901                 }
902
903                 /* No preferred mode, let's just select the first available */
904                 if (!found) {
905                         des_mode = NULL;
906                         list_for_each_entry(des_mode, &output->modes, head) {
907                                 break;
908                         }
909                 }
910
911                 c = -1;
912                 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
913                         assigned = 0;
914
915                         c++;
916                         if ((output->possible_crtcs & (1 << c)) == 0)
917                                 continue;
918         
919                         list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
920                                 if (output->id == output_equal->id)
921                                         continue;
922
923                                 /* Find out if crtc has been assigned before */
924                                 if (output_equal->crtc == crtc)
925                                         assigned = 1;
926                         }
927
928 #if 1 /* continue for now */
929                         if (assigned)
930                                 continue;
931 #endif
932
933                         o = -1;
934                         list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
935                                 o++;
936                                 if (output->id == output_equal->id)
937                                         continue;
938
939                                 list_for_each_entry(modes, &output->modes, head) {
940                                         list_for_each_entry(modes_equal, &output_equal->modes, head) {
941                                                 if (drm_mode_equal (modes, modes_equal)) {
942                                                         if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) {
943                                                                 printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones);
944                                                                 assigned = 0;
945                                                                 goto clone;
946                                                         }
947                                                 }
948                                         }
949                                 }
950                         }
951
952 clone:
953                         /* crtc has been assigned skip it */
954                         if (assigned)
955                                 continue;
956
957                         /* Found a CRTC to attach to, do it ! */
958                         output->crtc = crtc;
959                         output->crtc->desired_mode = des_mode;
960                         output->initial_x = 0;
961                         output->initial_y = 0;
962                         DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->mode_id, des_mode->name);
963                         break;
964                 }
965         }
966 }
967 EXPORT_SYMBOL(drm_pick_crtcs);
968
969 /**
970  * drm_initial_config - setup a sane initial output configuration
971  * @dev: DRM device
972  * @can_grow: this configuration is growable
973  *
974  * LOCKING:
975  * Called at init time, must take mode config lock.
976  *
977  * Scan the CRTCs and outputs and try to put together an initial setup.
978  * At the moment, this is a cloned configuration across all heads with
979  * a new framebuffer object as the backing store.
980  *
981  * RETURNS:
982  * Zero if everything went ok, nonzero otherwise.
983  */
984 bool drm_initial_config(struct drm_device *dev, bool can_grow)
985 {
986         struct drm_output *output;
987         struct drm_crtc *crtc;
988         int ret = false;
989
990         mutex_lock(&dev->mode_config.mutex);
991
992         drm_crtc_probe_output_modes(dev, 2048, 2048);
993
994         drm_pick_crtcs(dev);
995
996         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
997
998                 /* can't setup the crtc if there's no assigned mode */
999                 if (!crtc->desired_mode)
1000                         continue;
1001
1002                 /* Now setup the fbdev for attached crtcs */
1003                 dev->driver->fb_probe(dev, crtc);
1004         }
1005
1006         /* This is a little screwy, as we've already walked the outputs 
1007          * above, but it's a little bit of magic too. There's the potential
1008          * for things not to get setup above if an existing device gets
1009          * re-assigned thus confusing the hardware. By walking the outputs
1010          * this fixes up their crtc's.
1011          */
1012         list_for_each_entry(output, &dev->mode_config.output_list, head) {
1013
1014                 /* can't setup the output if there's no assigned mode */
1015                 if (!output->crtc || !output->crtc->desired_mode)
1016                         continue;
1017
1018                 /* and needs an attached fb */
1019                 if (output->crtc->fb)
1020                         drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0);
1021         }
1022
1023         drm_disable_unused_functions(dev);
1024
1025         mutex_unlock(&dev->mode_config.mutex);
1026         return ret;
1027 }
1028 EXPORT_SYMBOL(drm_initial_config);
1029
1030 /**
1031  * drm_mode_config_cleanup - free up DRM mode_config info
1032  * @dev: DRM device
1033  *
1034  * LOCKING:
1035  * Caller must hold mode config lock.
1036  *
1037  * Free up all the outputs and CRTCs associated with this DRM device, then
1038  * free up the framebuffers and associated buffer objects.
1039  *
1040  * FIXME: cleanup any dangling user buffer objects too
1041  */
1042 void drm_mode_config_cleanup(struct drm_device *dev)
1043 {
1044         struct drm_output *output, *ot;
1045         struct drm_crtc *crtc, *ct;
1046         struct drm_framebuffer *fb, *fbt;
1047         struct drm_property *property, *pt;
1048
1049         list_for_each_entry_safe(output, ot, &dev->mode_config.output_list, head) {
1050                 drm_output_destroy(output);
1051         }
1052
1053         list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, head) {
1054                 drm_property_destroy(dev, property);
1055         }
1056
1057         list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
1058                 /* there should only be bo of kernel type left */
1059                 if (fb->bo->type != drm_bo_type_kernel)
1060                         drm_framebuffer_destroy(fb);
1061                 else
1062                         dev->driver->fb_remove(dev, drm_crtc_from_fb(dev, fb));
1063         }
1064
1065         list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
1066                 drm_crtc_destroy(crtc);
1067         }
1068
1069 }
1070 EXPORT_SYMBOL(drm_mode_config_cleanup);
1071
1072 /**
1073  * drm_crtc_set_config - set a new config from userspace
1074  * @crtc: CRTC to setup
1075  * @crtc_info: user provided configuration
1076  * @new_mode: new mode to set
1077  * @output_set: set of outputs for the new config
1078  * @fb: new framebuffer
1079  *
1080  * LOCKING:
1081  * Caller must hold mode config lock.
1082  *
1083  * Setup a new configuration, provided by the user in @crtc_info, and enable
1084  * it.
1085  *
1086  * RETURNS:
1087  * Zero. (FIXME)
1088  */
1089 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)
1090 {
1091         struct drm_device *dev = crtc->dev;
1092         struct drm_crtc **save_crtcs, *new_crtc;
1093         bool save_enabled = crtc->enabled;
1094         bool changed = false;
1095         bool flip_or_move = false;
1096         struct drm_output *output;
1097         int count = 0, ro;
1098
1099         /* this is meant to be num_output not num_crtc */
1100         save_crtcs = kzalloc(dev->mode_config.num_output * sizeof(struct drm_crtc *), GFP_KERNEL);
1101         if (!save_crtcs)
1102                 return -ENOMEM;
1103
1104         /* We should be able to check here if the fb has the same properties
1105          * and then just flip_or_move it */
1106         if (crtc->fb != fb)
1107                 changed = true;
1108
1109         if (crtc_info->x != crtc->x || crtc_info->y != crtc->y)
1110                 flip_or_move = true;
1111
1112         if (new_mode && !drm_mode_equal(new_mode, &crtc->mode))
1113                 changed = true;
1114
1115         list_for_each_entry(output, &dev->mode_config.output_list, head) {
1116                 save_crtcs[count++] = output->crtc;
1117
1118                 if (output->crtc == crtc)
1119                         new_crtc = NULL;
1120                 else
1121                         new_crtc = output->crtc;
1122
1123                 for (ro = 0; ro < crtc_info->count_outputs; ro++) {
1124                         if (output_set[ro] == output)
1125                                 new_crtc = crtc;
1126                 }
1127                 if (new_crtc != output->crtc) {
1128                         changed = true;
1129                         output->crtc = new_crtc;
1130                 }
1131         }
1132
1133         /* mode_set_base is not a required function */
1134         if (flip_or_move && !crtc->funcs->mode_set_base)
1135                 changed = true;
1136
1137         if (changed) {
1138                 crtc->fb = fb;
1139                 crtc->enabled = (new_mode != NULL);
1140                 if (new_mode != NULL) {
1141                         DRM_DEBUG("attempting to set mode from userspace\n");
1142                         drm_mode_debug_printmodeline(dev, new_mode);
1143                         if (!drm_crtc_set_mode(crtc, new_mode, crtc_info->x,
1144                                                crtc_info->y)) {
1145                                 crtc->enabled = save_enabled;
1146                                 count = 0;
1147                                 list_for_each_entry(output, &dev->mode_config.output_list, head)
1148                                         output->crtc = save_crtcs[count++];
1149                                 kfree(save_crtcs);
1150                                 return -EINVAL;
1151                         }
1152                         crtc->desired_x = crtc_info->x;
1153                         crtc->desired_y = crtc_info->y;
1154                         crtc->desired_mode = new_mode;
1155                 }
1156                 drm_disable_unused_functions(dev);
1157         } else if (flip_or_move) {
1158                 crtc->funcs->mode_set_base(crtc, crtc_info->x, crtc_info->y);
1159         }
1160
1161         kfree(save_crtcs);
1162         return 0;
1163 }
1164
1165 /**
1166  * drm_hotplug_stage_two
1167  * @dev DRM device
1168  * @output hotpluged output
1169  *
1170  * LOCKING.
1171  * Caller must hold mode config lock, function might grap struct lock.
1172  *
1173  * Stage two of a hotplug.
1174  *
1175  * RETURNS:
1176  * Zero on success, errno on failure.
1177  */
1178 int drm_hotplug_stage_two(struct drm_device *dev, struct drm_output *output,
1179                           bool connected)
1180 {
1181         int has_config = 0;
1182
1183         /* We might want to do something more here */
1184         if (!connected) {
1185                 DRM_DEBUG("not connected\n");
1186                 dev->mode_config.hotplug_counter++;
1187                 return 0;
1188         }
1189
1190         if (output->crtc && output->crtc->desired_mode) {
1191                 DRM_DEBUG("drm thinks that the output already has a config\n");
1192                 has_config = 1;
1193         }
1194
1195         drm_crtc_probe_output_modes(dev, 2048, 2048);
1196
1197         if (!has_config)
1198                 drm_pick_crtcs(dev);
1199
1200         if (!output->crtc || !output->crtc->desired_mode) {
1201                 DRM_DEBUG("could not find a desired mode or crtc for output\n");
1202                 goto out_err;
1203         }
1204
1205         /* We should realy check if there is a fb using this crtc */
1206         if (!has_config)
1207                 dev->driver->fb_probe(dev, output->crtc);
1208         else {
1209                 dev->driver->fb_resize(dev, output->crtc);
1210
1211                 if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0))
1212                         DRM_ERROR("failed to set mode after hotplug\n");
1213         }
1214
1215         drm_disable_unused_functions(dev);
1216
1217         dev->mode_config.hotplug_counter++;
1218         return 0;
1219
1220 out_err:
1221         dev->mode_config.hotplug_counter++;
1222         return 1;
1223 }
1224 EXPORT_SYMBOL(drm_hotplug_stage_two);
1225
1226 int drm_mode_hotplug_ioctl(struct drm_device *dev,
1227                            void *data, struct drm_file *file_priv)
1228 {
1229         struct drm_mode_hotplug *arg = data;
1230
1231         arg->counter = dev->mode_config.hotplug_counter;
1232
1233         return 0;
1234 }
1235
1236 /**
1237  * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
1238  * @out: drm_mode_modeinfo struct to return to the user
1239  * @in: drm_display_mode to use
1240  *
1241  * LOCKING:
1242  * None.
1243  *
1244  * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
1245  * the user.
1246  */
1247 void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, struct drm_display_mode *in)
1248 {
1249         out->clock = in->clock;
1250         out->hdisplay = in->hdisplay;
1251         out->hsync_start = in->hsync_start;
1252         out->hsync_end = in->hsync_end;
1253         out->htotal = in->htotal;
1254         out->hskew = in->hskew;
1255         out->vdisplay = in->vdisplay;
1256         out->vsync_start = in->vsync_start;
1257         out->vsync_end = in->vsync_end;
1258         out->vtotal = in->vtotal;
1259         out->vscan = in->vscan;
1260         out->vrefresh = in->vrefresh;
1261         out->flags = in->flags;
1262         out->type = in->type;
1263         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1264         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1265 }
1266
1267 /**
1268  * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
1269  * @out: drm_display_mode to return to the user
1270  * @in: drm_mode_modeinfo to use
1271  *
1272  * LOCKING:
1273  * None.
1274  *
1275  * Convert a drmo_mode_modeinfo into a drm_display_mode structure to return to
1276  * the caller.
1277  */
1278 void drm_crtc_convert_umode(struct drm_display_mode *out, struct drm_mode_modeinfo *in)
1279 {
1280         out->clock = in->clock;
1281         out->hdisplay = in->hdisplay;
1282         out->hsync_start = in->hsync_start;
1283         out->hsync_end = in->hsync_end;
1284         out->htotal = in->htotal;
1285         out->hskew = in->hskew;
1286         out->vdisplay = in->vdisplay;
1287         out->vsync_start = in->vsync_start;
1288         out->vsync_end = in->vsync_end;
1289         out->vtotal = in->vtotal;
1290         out->vscan = in->vscan;
1291         out->vrefresh = in->vrefresh;
1292         out->flags = in->flags;
1293         out->type = in->type;
1294         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1295         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1296 }
1297         
1298 /**
1299  * drm_mode_getresources - get graphics configuration
1300  * @inode: inode from the ioctl
1301  * @filp: file * from the ioctl
1302  * @cmd: cmd from ioctl
1303  * @arg: arg from ioctl
1304  *
1305  * LOCKING:
1306  * Takes mode config lock.
1307  *
1308  * Construct a set of configuration description structures and return
1309  * them to the user, including CRTC, output and framebuffer configuration.
1310  *
1311  * Called by the user via ioctl.
1312  *
1313  * RETURNS:
1314  * Zero on success, errno on failure.
1315  */
1316 int drm_mode_getresources(struct drm_device *dev,
1317                           void *data, struct drm_file *file_priv)
1318 {
1319         struct drm_mode_card_res *card_res = data;
1320         struct list_head *lh;
1321         struct drm_framebuffer *fb;
1322         struct drm_output *output;
1323         struct drm_crtc *crtc;
1324         int ret = 0;
1325         int output_count = 0;
1326         int crtc_count = 0;
1327         int fb_count = 0;
1328         int copied = 0;
1329         uint32_t __user *fb_id;
1330         uint32_t __user *crtc_id;
1331         uint32_t __user *output_id;
1332
1333         mutex_lock(&dev->mode_config.mutex);
1334
1335         list_for_each(lh, &dev->mode_config.fb_list)
1336                 fb_count++;
1337
1338         list_for_each(lh, &dev->mode_config.crtc_list)
1339                 crtc_count++;
1340
1341         list_for_each(lh, &dev->mode_config.output_list)
1342                 output_count++;
1343
1344         card_res->max_height = dev->mode_config.max_height;
1345         card_res->min_height = dev->mode_config.min_height;
1346         card_res->max_width = dev->mode_config.max_width;
1347         card_res->min_width = dev->mode_config.min_width;
1348
1349         /* handle this in 4 parts */
1350         /* FBs */
1351         if (card_res->count_fbs >= fb_count) {
1352                 copied = 0;
1353                 fb_id = (uint32_t *)(unsigned long)card_res->fb_id_ptr;
1354                 list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
1355                         if (put_user(fb->id, fb_id + copied)) {
1356                                 ret = -EFAULT;
1357                                 goto out;
1358                         }
1359                         copied++;
1360                 }
1361         }
1362         card_res->count_fbs = fb_count;
1363
1364         /* CRTCs */
1365         if (card_res->count_crtcs >= crtc_count) {
1366                 copied = 0;
1367                 crtc_id = (uint32_t *)(unsigned long)card_res->crtc_id_ptr;
1368                 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head){
1369                         DRM_DEBUG("CRTC ID is %d\n", crtc->id);
1370                         if (put_user(crtc->id, crtc_id + copied)) {
1371                                 ret = -EFAULT;
1372                                 goto out;
1373                         }
1374                         copied++;
1375                 }
1376         }
1377         card_res->count_crtcs = crtc_count;
1378
1379
1380         /* Outputs */
1381         if (card_res->count_outputs >= output_count) {
1382                 copied = 0;
1383                 output_id = (uint32_t *)(unsigned long)card_res->output_id_ptr;
1384                 list_for_each_entry(output, &dev->mode_config.output_list,
1385                                     head) {
1386                         DRM_DEBUG("OUTPUT ID is %d\n", output->id);
1387                         if (put_user(output->id, output_id + copied)) {
1388                                 ret = -EFAULT;
1389                                 goto out;
1390                         }
1391                         copied++;
1392                 }
1393         }
1394         card_res->count_outputs = output_count;
1395         
1396         DRM_DEBUG("Counted %d %d\n", card_res->count_crtcs,
1397                   card_res->count_outputs);
1398
1399 out:    
1400         mutex_unlock(&dev->mode_config.mutex);
1401         return ret;
1402 }
1403
1404 /**
1405  * drm_mode_getcrtc - get CRTC configuration
1406  * @inode: inode from the ioctl
1407  * @filp: file * from the ioctl
1408  * @cmd: cmd from ioctl
1409  * @arg: arg from ioctl
1410  *
1411  * LOCKING:
1412  * Caller? (FIXME)
1413  *
1414  * Construct a CRTC configuration structure to return to the user.
1415  *
1416  * Called by the user via ioctl.
1417  *
1418  * RETURNS:
1419  * Zero on success, errno on failure.
1420  */
1421 int drm_mode_getcrtc(struct drm_device *dev,
1422                      void *data, struct drm_file *file_priv)
1423 {
1424         struct drm_mode_crtc *crtc_resp = data;
1425         struct drm_crtc *crtc;
1426         struct drm_output *output;
1427         int ocount;
1428         int ret = 0;
1429
1430         mutex_lock(&dev->mode_config.mutex);
1431         crtc = idr_find(&dev->mode_config.crtc_idr, crtc_resp->crtc_id);
1432         if (!crtc || (crtc->id != crtc_resp->crtc_id)) {
1433                 ret = -EINVAL;
1434                 goto out;
1435         }
1436
1437         crtc_resp->x = crtc->x;
1438         crtc_resp->y = crtc->y;
1439
1440         if (crtc->fb)
1441                 crtc_resp->fb_id = crtc->fb->id;
1442         else
1443                 crtc_resp->fb_id = 0;
1444
1445         crtc_resp->outputs = 0;
1446         if (crtc->enabled) {
1447
1448                 drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
1449                 crtc_resp->mode_valid = 1;
1450                 ocount = 0;
1451                 list_for_each_entry(output, &dev->mode_config.output_list, head) {
1452                         if (output->crtc == crtc)
1453                                 crtc_resp->outputs |= 1 << (ocount++);
1454                 }
1455                 
1456         } else {
1457                 crtc_resp->mode_valid = 0;
1458         }
1459
1460 out:
1461         mutex_unlock(&dev->mode_config.mutex);
1462         return ret;
1463 }
1464
1465 /**
1466  * drm_mode_getoutput - get output configuration
1467  * @inode: inode from the ioctl
1468  * @filp: file * from the ioctl
1469  * @cmd: cmd from ioctl
1470  * @arg: arg from ioctl
1471  *
1472  * LOCKING:
1473  * Caller? (FIXME)
1474  *
1475  * Construct a output configuration structure to return to the user.
1476  *
1477  * Called by the user via ioctl.
1478  *
1479  * RETURNS:
1480  * Zero on success, errno on failure.
1481  */
1482 int drm_mode_getoutput(struct drm_device *dev,
1483                        void *data, struct drm_file *file_priv)
1484 {
1485         struct drm_mode_get_output *out_resp = data;
1486         struct drm_output *output;
1487         struct drm_display_mode *mode;
1488         int mode_count = 0;
1489         int props_count = 0;
1490         int ret = 0;
1491         int copied = 0;
1492         int i;
1493         struct drm_mode_modeinfo u_mode;
1494         struct drm_mode_modeinfo __user *mode_ptr;
1495         uint32_t __user *prop_ptr;
1496         uint64_t __user *prop_values;
1497
1498         memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
1499
1500         DRM_DEBUG("output id %d:\n", out_resp->output);
1501
1502         mutex_lock(&dev->mode_config.mutex);
1503         output= idr_find(&dev->mode_config.crtc_idr, out_resp->output);
1504         if (!output || (output->id != out_resp->output)) {
1505                 ret = -EINVAL;
1506                 goto out;
1507         }
1508
1509         list_for_each_entry(mode, &output->modes, head)
1510                 mode_count++;
1511         
1512         for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) {
1513                 if (output->property_ids[i] != 0) {
1514                         props_count++;
1515                 }
1516         }
1517
1518         if (out_resp->count_modes == 0) {
1519                 drm_crtc_probe_single_output_modes(output, dev->mode_config.max_width, dev->mode_config.max_height);
1520         }
1521
1522         out_resp->output_type = output->output_type;
1523         out_resp->output_type_id = output->output_type_id;
1524         out_resp->mm_width = output->mm_width;
1525         out_resp->mm_height = output->mm_height;
1526         out_resp->subpixel = output->subpixel_order;
1527         out_resp->connection = output->status;
1528         if (output->crtc)
1529                 out_resp->crtc = output->crtc->id;
1530         else
1531                 out_resp->crtc = 0;
1532
1533         out_resp->crtcs = output->possible_crtcs;
1534         out_resp->clones = output->possible_clones;
1535
1536         if ((out_resp->count_modes >= mode_count) && mode_count) {
1537                 copied = 0;
1538                 mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr;
1539                 list_for_each_entry(mode, &output->modes, head) {
1540                         drm_crtc_convert_to_umode(&u_mode, mode);
1541                         if (copy_to_user(mode_ptr + copied,
1542                                          &u_mode, sizeof(u_mode))) {
1543                                 ret = -EFAULT;
1544                                 goto out;
1545                         }
1546                         copied++;
1547                         
1548                 }
1549         }
1550         out_resp->count_modes = mode_count;
1551
1552         if ((out_resp->count_props >= props_count) && props_count) {
1553                 copied = 0;
1554                 prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr);
1555                 prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr);
1556                 for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) {
1557                         if (output->property_ids[i] != 0) {
1558                                 if (put_user(output->property_ids[i], prop_ptr + copied)) {
1559                                         ret = -EFAULT;
1560                                         goto out;
1561                                 }
1562
1563                                 if (put_user(output->property_values[i], prop_values + copied)) {
1564                                         ret = -EFAULT;
1565                                         goto out;
1566                                 }
1567                                 copied++;
1568                         }
1569                 }
1570         }
1571         out_resp->count_props = props_count;
1572
1573 out:
1574         mutex_unlock(&dev->mode_config.mutex);
1575         return ret;
1576 }
1577
1578 /**
1579  * drm_mode_setcrtc - set CRTC configuration
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  * Build a new CRTC configuration based on user request.
1589  *
1590  * Called by the user via ioctl.
1591  *
1592  * RETURNS:
1593  * Zero on success, errno on failure.
1594  */
1595 int drm_mode_setcrtc(struct drm_device *dev,
1596                      void *data, struct drm_file *file_priv)
1597 {
1598         struct drm_mode_crtc *crtc_req = data;
1599         struct drm_crtc *crtc, *crtcfb;
1600         struct drm_output **output_set = NULL, *output;
1601         struct drm_framebuffer *fb = NULL;
1602         struct drm_display_mode *mode = NULL;
1603         uint32_t __user *set_outputs_ptr;
1604         int ret = 0;
1605         int i;
1606
1607         mutex_lock(&dev->mode_config.mutex);
1608         crtc = idr_find(&dev->mode_config.crtc_idr, crtc_req->crtc_id);
1609         if (!crtc || (crtc->id != crtc_req->crtc_id)) {
1610                 DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id);
1611                 ret = -EINVAL;
1612                 goto out;
1613         }
1614
1615         if (crtc_req->mode_valid) {
1616                 /* If we have a mode we need a framebuffer. */
1617                 /* If we pass -1, set the mode with the currently bound fb */
1618                 if (crtc_req->fb_id == -1) {
1619                         list_for_each_entry(crtcfb, &dev->mode_config.crtc_list, head) {
1620                                 if (crtcfb == crtc) {
1621                                         DRM_INFO("Using current fb for setmode\n");
1622                                         fb = crtc->fb;          
1623                                 }
1624                         }
1625                 } else {
1626                         fb = idr_find(&dev->mode_config.crtc_idr, crtc_req->fb_id);
1627                         if (!fb || (fb->id != crtc_req->fb_id)) {
1628                                 DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id);
1629                                 ret = -EINVAL;
1630                                 goto out;
1631                         }
1632                 }
1633
1634                 mode = drm_mode_create(dev);
1635                 drm_crtc_convert_umode(mode, &crtc_req->mode);
1636                 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1637         }
1638
1639         if (crtc_req->count_outputs == 0 && mode) {
1640                 DRM_DEBUG("Count outputs is 0 but mode set\n");
1641                 ret = -EINVAL;
1642                 goto out;
1643         }
1644
1645         if (crtc_req->count_outputs > 0 && !mode && !fb) {
1646                 DRM_DEBUG("Count outputs is %d but no mode or fb set\n", crtc_req->count_outputs);
1647                 ret = -EINVAL;
1648                 goto out;
1649         }
1650
1651         if (crtc_req->count_outputs > 0) {
1652                 u32 out_id;
1653                 /* Maybe we should check that count_outputs is a sensible value. */
1654                 output_set = kmalloc(crtc_req->count_outputs *
1655                                      sizeof(struct drm_output *), GFP_KERNEL);
1656                 if (!output_set) {
1657                         ret = -ENOMEM;
1658                         goto out;
1659                 }
1660
1661                 for (i = 0; i < crtc_req->count_outputs; i++) {
1662                         set_outputs_ptr = (uint32_t *)(unsigned long)crtc_req->set_outputs_ptr;
1663                         if (get_user(out_id, &set_outputs_ptr[i])) {
1664                                 ret = -EFAULT;
1665                                 goto out;
1666                         }
1667
1668                         output = idr_find(&dev->mode_config.crtc_idr, out_id);
1669                         if (!output || (out_id != output->id)) {
1670                                 DRM_DEBUG("Output id %d unknown\n", out_id);
1671                                 ret = -EINVAL;
1672                                 goto out;
1673                         }
1674
1675                         output_set[i] = output;
1676                 }
1677         }
1678
1679         ret = drm_crtc_set_config(crtc, crtc_req, mode, output_set, fb);
1680
1681 out:
1682         kfree(output_set);
1683         mutex_unlock(&dev->mode_config.mutex);
1684         return ret;
1685 }
1686
1687 int drm_mode_cursor_ioctl(struct drm_device *dev,
1688                         void *data, struct drm_file *file_priv)
1689 {
1690         struct drm_mode_cursor *req = data;
1691         struct drm_crtc *crtc;
1692         struct drm_buffer_object *bo = NULL; /* must be set */
1693         int ret = 0;
1694
1695         DRM_DEBUG("\n");
1696
1697         if (!req->flags) {
1698                 DRM_ERROR("no operation set\n");
1699                 return -EINVAL;
1700         }
1701
1702         mutex_lock(&dev->mode_config.mutex);
1703         crtc = idr_find(&dev->mode_config.crtc_idr, req->crtc);
1704         if (!crtc || (crtc->id != req->crtc)) {
1705                 DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc);
1706                 ret = -EINVAL;
1707                 goto out;
1708         }
1709
1710         if (req->flags & DRM_MODE_CURSOR_BO) {
1711                 /* Turn of the cursor if handle is 0 */
1712                 if (req->handle)
1713                         ret = drm_get_buffer_object(dev, &bo, req->handle);
1714
1715                 if (ret) {
1716                         DRM_ERROR("invalid buffer id\n");
1717                         ret = -EINVAL;
1718                         goto out;
1719                 }
1720
1721                 if (crtc->funcs->cursor_set) {
1722                         ret = crtc->funcs->cursor_set(crtc, bo, req->width, req->height);
1723                 } else {
1724                         DRM_ERROR("crtc does not support cursor\n");
1725                         ret = -EFAULT;
1726                         goto out;
1727                 }
1728         }
1729
1730         if (req->flags & DRM_MODE_CURSOR_MOVE) {
1731                 if (crtc->funcs->cursor_move) {
1732                         ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
1733                 } else {
1734                         DRM_ERROR("crtc does not support cursor\n");
1735                         ret = -EFAULT;
1736                         goto out;
1737                 }
1738         }
1739 out:
1740         mutex_unlock(&dev->mode_config.mutex);
1741         return ret;
1742 }
1743
1744 /**
1745  * drm_mode_addfb - add an FB to the graphics configuration
1746  * @inode: inode from the ioctl
1747  * @filp: file * from the ioctl
1748  * @cmd: cmd from ioctl
1749  * @arg: arg from ioctl
1750  *
1751  * LOCKING:
1752  * Takes mode config lock.
1753  *
1754  * Add a new FB to the specified CRTC, given a user request.
1755  *
1756  * Called by the user via ioctl.
1757  *
1758  * RETURNS:
1759  * Zero on success, errno on failure.
1760  */
1761 int drm_mode_addfb(struct drm_device *dev,
1762                    void *data, struct drm_file *file_priv)
1763 {
1764         struct drm_mode_fb_cmd *r = data;
1765         struct drm_mode_config *config = &dev->mode_config;
1766         struct drm_framebuffer *fb;
1767         struct drm_buffer_object *bo;
1768         int ret = 0;
1769
1770         if ((config->min_width > r->width) || (r->width > config->max_width)) {
1771                 DRM_ERROR("mode new framebuffer width not within limits\n");
1772                 return -EINVAL;
1773         }
1774         if ((config->min_height > r->height) || (r->height > config->max_height)) {
1775                 DRM_ERROR("mode new framebuffer height not within limits\n");
1776                 return -EINVAL;
1777         }
1778
1779         mutex_lock(&dev->mode_config.mutex);
1780         /* TODO check limits are okay */
1781         ret = drm_get_buffer_object(dev, &bo, r->handle);
1782         if (ret || !bo) {
1783                 DRM_ERROR("BO handle not valid\n");
1784                 ret = -EINVAL;
1785                 goto out;
1786         }
1787
1788         /* TODO check buffer is sufficently large */
1789         /* TODO setup destructor callback */
1790
1791         fb = drm_framebuffer_create(dev);
1792         if (!fb) {
1793                 DRM_ERROR("could not create framebuffer\n");
1794                 ret = -EINVAL;
1795                 goto out;
1796         }
1797
1798         fb->width = r->width;
1799         fb->height = r->height;
1800         fb->pitch = r->pitch;
1801         fb->bits_per_pixel = r->bpp;
1802         fb->depth = r->depth;
1803         fb->bo = bo;
1804
1805         r->buffer_id = fb->id;
1806
1807         list_add(&fb->filp_head, &file_priv->fbs);
1808
1809 out:
1810         mutex_unlock(&dev->mode_config.mutex);
1811         return ret;
1812 }
1813
1814 /**
1815  * drm_mode_rmfb - remove an FB from the configuration
1816  * @inode: inode from the ioctl
1817  * @filp: file * from the ioctl
1818  * @cmd: cmd from ioctl
1819  * @arg: arg from ioctl
1820  *
1821  * LOCKING:
1822  * Takes mode config lock.
1823  *
1824  * Remove the FB specified by the user.
1825  *
1826  * Called by the user via ioctl.
1827  *
1828  * RETURNS:
1829  * Zero on success, errno on failure.
1830  */
1831 int drm_mode_rmfb(struct drm_device *dev,
1832                    void *data, struct drm_file *file_priv)
1833 {
1834         struct drm_framebuffer *fb = 0;
1835         struct drm_framebuffer *fbl = 0;
1836         uint32_t *id = data;
1837         int ret = 0;
1838         int found = 0;
1839
1840         mutex_lock(&dev->mode_config.mutex);
1841         fb = idr_find(&dev->mode_config.crtc_idr, *id);
1842         /* TODO check that we realy get a framebuffer back. */
1843         if (!fb || (*id != fb->id)) {
1844                 DRM_ERROR("mode invalid framebuffer id\n");
1845                 ret = -EINVAL;
1846                 goto out;
1847         }
1848
1849         list_for_each_entry(fbl, &file_priv->fbs, filp_head)
1850                 if (fb == fbl)
1851                         found = 1;
1852
1853         if (!found) {
1854                 DRM_ERROR("tried to remove a fb that we didn't own\n");
1855                 ret = -EINVAL;
1856                 goto out;
1857         }
1858
1859         /* TODO release all crtc connected to the framebuffer */
1860         /* TODO unhock the destructor from the buffer object */
1861
1862         if (fb->bo->type == drm_bo_type_kernel)
1863                 DRM_ERROR("the bo type should not be of kernel type\n");
1864
1865         list_del(&fb->filp_head);
1866         drm_framebuffer_destroy(fb);
1867
1868 out:
1869         mutex_unlock(&dev->mode_config.mutex);
1870         return ret;
1871 }
1872
1873 /**
1874  * drm_mode_getfb - get FB info
1875  * @inode: inode from the ioctl
1876  * @filp: file * from the ioctl
1877  * @cmd: cmd from ioctl
1878  * @arg: arg from ioctl
1879  *
1880  * LOCKING:
1881  * Caller? (FIXME)
1882  *
1883  * Lookup the FB given its ID and return info about it.
1884  *
1885  * Called by the user via ioctl.
1886  *
1887  * RETURNS:
1888  * Zero on success, errno on failure.
1889  */
1890 int drm_mode_getfb(struct drm_device *dev,
1891                    void *data, struct drm_file *file_priv)
1892 {
1893         struct drm_mode_fb_cmd *r = data;
1894         struct drm_framebuffer *fb;
1895         int ret = 0;
1896
1897         mutex_lock(&dev->mode_config.mutex);
1898         fb = idr_find(&dev->mode_config.crtc_idr, r->buffer_id);
1899         if (!fb || (r->buffer_id != fb->id)) {
1900                 DRM_ERROR("invalid framebuffer id\n");
1901                 ret = -EINVAL;
1902                 goto out;
1903         }
1904
1905         r->height = fb->height;
1906         r->width = fb->width;
1907         r->depth = fb->depth;
1908         r->bpp = fb->bits_per_pixel;
1909         r->handle = fb->bo->base.hash.key;
1910         r->pitch = fb->pitch;
1911
1912 out:
1913         mutex_unlock(&dev->mode_config.mutex);
1914         return ret;
1915 }
1916
1917 /**
1918  * drm_fb_release - remove and free the FBs on this file
1919  * @filp: file * from the ioctl
1920  *
1921  * LOCKING:
1922  * Takes mode config lock.
1923  *
1924  * Destroy all the FBs associated with @filp.
1925  *
1926  * Called by the user via ioctl.
1927  *
1928  * RETURNS:
1929  * Zero on success, errno on failure.
1930  */
1931 void drm_fb_release(struct file *filp)
1932 {
1933         struct drm_file *priv = filp->private_data;
1934         struct drm_device *dev = priv->minor->dev;
1935         struct drm_framebuffer *fb, *tfb;
1936
1937         mutex_lock(&dev->mode_config.mutex);
1938         list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
1939                 list_del(&fb->filp_head);
1940                 if (fb->bo->type == drm_bo_type_kernel)
1941                         DRM_ERROR("the bo type should not be of kernel_type, the kernel will probably explode, why Dave\n");
1942
1943                 drm_framebuffer_destroy(fb);
1944         }
1945         mutex_unlock(&dev->mode_config.mutex);
1946 }
1947
1948 /*
1949  *
1950  */
1951
1952 static int drm_mode_attachmode(struct drm_device *dev,
1953                                struct drm_output *output,
1954                                struct drm_display_mode *mode)
1955 {
1956         int ret = 0;
1957
1958         list_add_tail(&mode->head, &output->user_modes);
1959         return ret;
1960 }
1961
1962 int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
1963                              struct drm_display_mode *mode)
1964 {
1965         struct drm_output *output;
1966         int ret = 0;
1967         struct drm_display_mode *dup_mode;
1968         int need_dup = 0;
1969         list_for_each_entry(output, &dev->mode_config.output_list, head) {
1970                 if (output->crtc == crtc) {
1971                         if (need_dup)
1972                                 dup_mode = drm_mode_duplicate(dev, mode);
1973                         else
1974                                 dup_mode = mode;
1975                         ret = drm_mode_attachmode(dev, output, dup_mode); 
1976                         if (ret)
1977                                 return ret;
1978                         need_dup = 1;
1979                 }
1980         }
1981         return 0;
1982 }
1983 EXPORT_SYMBOL(drm_mode_attachmode_crtc);
1984
1985 static int drm_mode_detachmode(struct drm_device *dev,
1986                                struct drm_output *output,
1987                                struct drm_display_mode *mode)
1988 {
1989         int found = 0;
1990         int ret = 0;
1991         struct drm_display_mode *match_mode, *t;
1992
1993         list_for_each_entry_safe(match_mode, t, &output->user_modes, head) {
1994                 if (drm_mode_equal(match_mode, mode)) {
1995                         list_del(&match_mode->head);
1996                         drm_mode_destroy(dev, match_mode);
1997                         found = 1;
1998                         break;
1999                 }
2000         }
2001
2002         if (!found)
2003                 ret = -EINVAL;
2004
2005         return ret;
2006 }
2007
2008 int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
2009 {
2010         struct drm_output *output;
2011
2012         list_for_each_entry(output, &dev->mode_config.output_list, head) {
2013                 drm_mode_detachmode(dev, output, mode);
2014         }
2015         return 0;
2016 }
2017 EXPORT_SYMBOL(drm_mode_detachmode_crtc);
2018
2019 /**
2020  * drm_fb_attachmode - Attach a user mode to an output
2021  * @inode: inode from the ioctl
2022  * @filp: file * from the ioctl
2023  * @cmd: cmd from ioctl
2024  * @arg: arg from ioctl
2025  *
2026  * This attaches a user specified mode to an output.
2027  * Called by the user via ioctl.
2028  *
2029  * RETURNS:
2030  * Zero on success, errno on failure.
2031  */
2032 int drm_mode_attachmode_ioctl(struct drm_device *dev,
2033                               void *data, struct drm_file *file_priv)
2034 {
2035         struct drm_mode_mode_cmd *mode_cmd = data;
2036         struct drm_output *output;
2037         struct drm_display_mode *mode;
2038         struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2039         int ret = 0;
2040
2041         mutex_lock(&dev->mode_config.mutex);
2042
2043         output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id);
2044         if (!output || (output->id != mode_cmd->output_id)) {
2045                 ret = -EINVAL;
2046                 goto out;
2047         }
2048
2049         mode = drm_mode_create(dev);
2050         if (!mode) {
2051                 ret = -ENOMEM;
2052                 goto out;
2053         }
2054         
2055         drm_crtc_convert_umode(mode, umode);
2056
2057         ret = drm_mode_attachmode(dev, output, mode);
2058 out:
2059         mutex_unlock(&dev->mode_config.mutex);
2060         return ret;
2061 }
2062
2063
2064 /**
2065  * drm_fb_detachmode - Detach a user specified mode from an output
2066  * @inode: inode from the ioctl
2067  * @filp: file * from the ioctl
2068  * @cmd: cmd from ioctl
2069  * @arg: arg from ioctl
2070  *
2071  * Called by the user via ioctl.
2072  *
2073  * RETURNS:
2074  * Zero on success, errno on failure.
2075  */
2076 int drm_mode_detachmode_ioctl(struct drm_device *dev,
2077                               void *data, struct drm_file *file_priv)
2078 {
2079         struct drm_mode_mode_cmd *mode_cmd = data;
2080         struct drm_output *output;
2081         struct drm_display_mode mode;
2082         struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2083         int ret = 0;
2084
2085         mutex_lock(&dev->mode_config.mutex);
2086
2087         output = idr_find(&dev->mode_config.crtc_idr, mode_cmd->output_id);
2088         if (!output || (output->id != mode_cmd->output_id)) {
2089                 ret = -EINVAL;
2090                 goto out;
2091         }
2092         
2093         drm_crtc_convert_umode(&mode, umode);
2094         ret = drm_mode_detachmode(dev, output, &mode);
2095 out:           
2096         mutex_unlock(&dev->mode_config.mutex);
2097         return ret;
2098 }
2099
2100 struct drm_property *drm_property_create(struct drm_device *dev, int flags,
2101                                          const char *name, int num_values)
2102 {
2103         struct drm_property *property = NULL;
2104
2105         property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
2106         if (!property)
2107                 return NULL;
2108
2109         if (num_values) {
2110                 property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
2111                 if (!property->values)
2112                         goto fail;
2113         }
2114
2115         property->id = drm_idr_get(dev, property);
2116         property->flags = flags;
2117         property->num_values = num_values;
2118         INIT_LIST_HEAD(&property->enum_blob_list);
2119
2120         if (name)
2121                 strncpy(property->name, name, DRM_PROP_NAME_LEN);
2122
2123         list_add_tail(&property->head, &dev->mode_config.property_list);
2124         return property;
2125 fail:
2126         kfree(property);
2127         return NULL;
2128 }
2129 EXPORT_SYMBOL(drm_property_create);
2130
2131 int drm_property_add_enum(struct drm_property *property, int index,
2132                           uint64_t value, const char *name)
2133 {
2134         struct drm_property_enum *prop_enum;
2135
2136         if (!(property->flags & DRM_MODE_PROP_ENUM))
2137                 return -EINVAL;
2138
2139         if (!list_empty(&property->enum_blob_list)) {
2140                 list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2141                         if (prop_enum->value == value) {
2142                                 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 
2143                                 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2144                                 return 0;
2145                         }
2146                 }
2147         }
2148
2149         prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
2150         if (!prop_enum)
2151                 return -ENOMEM;
2152
2153         strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 
2154         prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2155         prop_enum->value = value;
2156
2157         property->values[index] = value;
2158         list_add_tail(&prop_enum->head, &property->enum_blob_list);
2159         return 0;
2160 }
2161 EXPORT_SYMBOL(drm_property_add_enum);
2162
2163 void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
2164 {
2165         struct drm_property_enum *prop_enum, *pt;
2166
2167         list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
2168                 list_del(&prop_enum->head);
2169                 kfree(prop_enum);
2170         }
2171
2172         if (property->num_values)
2173                 kfree(property->values);
2174         drm_idr_put(dev, property->id);
2175         list_del(&property->head);
2176         kfree(property);        
2177 }
2178 EXPORT_SYMBOL(drm_property_destroy);
2179
2180 int drm_output_attach_property(struct drm_output *output,
2181                                struct drm_property *property, uint64_t init_val)
2182 {
2183         int i;
2184
2185         for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) {
2186                 if (output->property_ids[i] == 0) {
2187                         output->property_ids[i] = property->id;
2188                         output->property_values[i] = init_val;
2189                         break;
2190                 }
2191         }
2192
2193         if (i == DRM_OUTPUT_MAX_PROPERTY)
2194                 return -EINVAL;
2195         return 0;
2196 }
2197 EXPORT_SYMBOL(drm_output_attach_property);
2198
2199 int drm_output_property_set_value(struct drm_output *output,
2200                                   struct drm_property *property, uint64_t value)
2201 {
2202         int i;
2203
2204         for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) {
2205                 if (output->property_ids[i] == property->id) {
2206                         output->property_values[i] = value;
2207                         break;
2208                 }
2209         }
2210
2211         if (i == DRM_OUTPUT_MAX_PROPERTY)
2212                 return -EINVAL;
2213         return 0;
2214 }
2215 EXPORT_SYMBOL(drm_output_property_set_value);
2216
2217 int drm_mode_getproperty_ioctl(struct drm_device *dev,
2218                                void *data, struct drm_file *file_priv)
2219 {
2220         struct drm_mode_get_property *out_resp = data;
2221         struct drm_property *property;
2222         int enum_count = 0;
2223         int blob_count = 0;
2224         int value_count = 0;
2225         int ret = 0, i;
2226         int copied;
2227         struct drm_property_enum *prop_enum;
2228         struct drm_mode_property_enum __user *enum_ptr;
2229         struct drm_property_blob *prop_blob;
2230         uint32_t *blob_id_ptr;
2231         uint64_t __user *values_ptr;
2232         uint32_t __user *blob_length_ptr;
2233
2234         mutex_lock(&dev->mode_config.mutex);
2235         property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id);
2236         if (!property || (property->id != out_resp->prop_id)) {
2237                 ret = -EINVAL;
2238                 goto done;
2239         }
2240
2241         if (property->flags & DRM_MODE_PROP_ENUM) {
2242                 list_for_each_entry(prop_enum, &property->enum_blob_list, head)
2243                         enum_count++;
2244         } else if (property->flags & DRM_MODE_PROP_BLOB) {
2245                 list_for_each_entry(prop_blob, &property->enum_blob_list, head)
2246                         blob_count++;
2247         }
2248
2249         value_count = property->num_values;
2250
2251         strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
2252         out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
2253         out_resp->flags = property->flags;
2254
2255         if ((out_resp->count_values >= value_count) && value_count) {
2256                 values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr;
2257                 for (i = 0; i < value_count; i++) {
2258                         if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
2259                                 ret = -EFAULT;
2260                                 goto done;
2261                         }
2262                 }
2263         }
2264         out_resp->count_values = value_count;
2265
2266         if (property->flags & DRM_MODE_PROP_ENUM) {
2267
2268                 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
2269                         copied = 0;
2270                         enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr;
2271                         list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2272                                 
2273                                 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
2274                                         ret = -EFAULT;
2275                                         goto done;
2276                                 }
2277                                 
2278                                 if (copy_to_user(&enum_ptr[copied].name,
2279                                                  &prop_enum->name, DRM_PROP_NAME_LEN)) {
2280                                         ret = -EFAULT;
2281                                         goto done;
2282                                 }
2283                                 copied++;
2284                         }
2285                 }
2286                 out_resp->count_enum_blobs = enum_count;
2287         }
2288
2289         if (property->flags & DRM_MODE_PROP_BLOB) {
2290                 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
2291                         copied = 0;
2292                         blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr;
2293                         blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr;
2294                         
2295                         list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
2296                                 if (put_user(prop_blob->id, blob_id_ptr + copied)) {
2297                                         ret = -EFAULT;
2298                                         goto done;
2299                                 }
2300                                 
2301                                 if (put_user(prop_blob->length, blob_length_ptr + copied)) {
2302                                         ret = -EFAULT;
2303                                         goto done;
2304                                 }
2305                                 
2306                                 copied++;
2307                         }
2308                 }
2309                 out_resp->count_enum_blobs = enum_count;
2310         }
2311 done:
2312         mutex_unlock(&dev->mode_config.mutex);
2313         return ret;
2314 }
2315
2316 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
2317                                                           void *data)
2318 {
2319         struct drm_property_blob *blob;
2320
2321         if (!length || !data)
2322                 return NULL;
2323
2324         blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
2325         if (!blob)
2326                 return NULL;
2327
2328         blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob));
2329         blob->length = length;
2330
2331         memcpy(blob->data, data, length);
2332
2333         blob->id = drm_idr_get(dev, blob);
2334         
2335         list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
2336         return blob;
2337 }
2338
2339 static void drm_property_destroy_blob(struct drm_device *dev,
2340                                struct drm_property_blob *blob)
2341 {
2342         drm_idr_put(dev, blob->id);
2343         list_del(&blob->head);
2344         kfree(blob);
2345 }
2346
2347 int drm_mode_getblob_ioctl(struct drm_device *dev,
2348                            void *data, struct drm_file *file_priv)
2349 {
2350         struct drm_mode_get_blob *out_resp = data;
2351         struct drm_property_blob *blob;
2352         int ret = 0;
2353         void *blob_ptr;
2354
2355         mutex_lock(&dev->mode_config.mutex);
2356         
2357         blob = idr_find(&dev->mode_config.crtc_idr, out_resp->blob_id);
2358         if (!blob || (blob->id != out_resp->blob_id)) {
2359                 ret = -EINVAL;
2360                 goto done;
2361         }
2362
2363         if (out_resp->length == blob->length) {
2364                 blob_ptr = (void *)(unsigned long)out_resp->data;
2365                 if (copy_to_user(blob_ptr, blob->data, blob->length)){
2366                         ret = -EFAULT;
2367                         goto done;
2368                 }
2369         }
2370         out_resp->length = blob->length;
2371
2372 done:
2373         mutex_unlock(&dev->mode_config.mutex);
2374         return ret;
2375 }
2376
2377 int drm_mode_output_update_edid_property(struct drm_output *output, struct edid *edid)
2378 {
2379         struct drm_device *dev = output->dev;
2380         int ret = 0;
2381         if (output->edid_blob_ptr)
2382                 drm_property_destroy_blob(dev, output->edid_blob_ptr);
2383
2384         output->edid_blob_ptr = drm_property_create_blob(output->dev, 128, edid);
2385         
2386         ret = drm_output_property_set_value(output, dev->mode_config.edid_property, output->edid_blob_ptr->id);
2387         return ret;
2388 }
2389 EXPORT_SYMBOL(drm_mode_output_update_edid_property);
2390
2391 int drm_mode_output_property_set_ioctl(struct drm_device *dev,
2392                                        void *data, struct drm_file *file_priv)
2393 {
2394         struct drm_mode_output_set_property *out_resp = data;
2395         struct drm_property *property;
2396         struct drm_output *output;
2397         int ret = -EINVAL;
2398         int i;
2399
2400         mutex_lock(&dev->mode_config.mutex);
2401         output = idr_find(&dev->mode_config.crtc_idr, out_resp->output_id);
2402         if (!output || (output->id != out_resp->output_id)) {
2403                 goto out;
2404         }
2405
2406         for (i = 0; i < DRM_OUTPUT_MAX_PROPERTY; i++) {
2407                 if (output->property_ids[i] == out_resp->prop_id)
2408                         break;
2409         }
2410
2411         if (i == DRM_OUTPUT_MAX_PROPERTY) {
2412                 goto out;
2413         }
2414         
2415         property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id);
2416         if (!property || (property->id != out_resp->prop_id)) {
2417                 goto out;
2418         }
2419
2420         if (property->flags & DRM_MODE_PROP_IMMUTABLE)
2421                 goto out;
2422
2423         if (property->flags & DRM_MODE_PROP_RANGE) {
2424                 if (out_resp->value < property->values[0])
2425                         goto out;
2426
2427                 if (out_resp->value > property->values[1])
2428                         goto out;
2429         } else {
2430                 int found = 0;
2431                 for (i = 0; i < property->num_values; i++) {
2432                         if (property->values[i] == out_resp->value) {
2433                                 found = 1;
2434                                 break;
2435                         }
2436                 }
2437                 if (!found) {
2438                         goto out;
2439                 }
2440         }
2441
2442         if (output->funcs->set_property)
2443                 ret = output->funcs->set_property(output, property, out_resp->value);
2444
2445 out:
2446         mutex_unlock(&dev->mode_config.mutex);
2447         return ret;
2448 }
2449