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