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