blob: c7ab80b45e3f8d46805ffbfb2dab1f66a573ad84 [file] [log] [blame]
Dave Airlief453ba02008-11-07 14:05:41 -08001/*
2 * Copyright (c) 2006-2008 Intel Corporation
3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
4 * Copyright (c) 2008 Red Hat Inc.
5 *
6 * DRM core CRTC related functions
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that copyright
11 * notice and this permission notice appear in supporting documentation, and
12 * that the name of the copyright holders not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. The copyright holders make no representations
15 * about the suitability of this software for any purpose. It is provided "as
16 * is" without express or implied warranty.
17 *
18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 *
26 * Authors:
27 * Keith Packard
28 * Eric Anholt <eric@anholt.net>
29 * Dave Airlie <airlied@linux.ie>
30 * Jesse Barnes <jesse.barnes@intel.com>
31 */
32#include <linux/list.h>
33#include "drm.h"
34#include "drmP.h"
35#include "drm_crtc.h"
36
37struct drm_prop_enum_list {
38 int type;
39 char *name;
40};
41
42/* Avoid boilerplate. I'm tired of typing. */
43#define DRM_ENUM_NAME_FN(fnname, list) \
44 char *fnname(int val) \
45 { \
46 int i; \
47 for (i = 0; i < ARRAY_SIZE(list); i++) { \
48 if (list[i].type == val) \
49 return list[i].name; \
50 } \
51 return "(unknown)"; \
52 }
53
54/*
55 * Global properties
56 */
57static struct drm_prop_enum_list drm_dpms_enum_list[] =
58{ { DRM_MODE_DPMS_ON, "On" },
59 { DRM_MODE_DPMS_STANDBY, "Standby" },
60 { DRM_MODE_DPMS_SUSPEND, "Suspend" },
61 { DRM_MODE_DPMS_OFF, "Off" }
62};
63
64DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
65
66/*
67 * Optional properties
68 */
69static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
70{
71 { DRM_MODE_SCALE_NON_GPU, "Non-GPU" },
72 { DRM_MODE_SCALE_FULLSCREEN, "Fullscreen" },
73 { DRM_MODE_SCALE_NO_SCALE, "No scale" },
74 { DRM_MODE_SCALE_ASPECT, "Aspect" },
75};
76
77static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
78{
79 { DRM_MODE_DITHERING_OFF, "Off" },
80 { DRM_MODE_DITHERING_ON, "On" },
81};
82
83/*
84 * Non-global properties, but "required" for certain connectors.
85 */
86static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
87{
88 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
89 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
90 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */
91};
92
93DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
94
95static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
96{
97 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
98 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
99 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */
100};
101
102DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
103 drm_dvi_i_subconnector_enum_list)
104
105static struct drm_prop_enum_list drm_tv_select_enum_list[] =
106{
107 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
108 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
109 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
110 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
111};
112
113DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
114
115static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
116{
117 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
118 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
119 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
120 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
121};
122
123DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
124 drm_tv_subconnector_enum_list)
125
126struct drm_conn_prop_enum_list {
127 int type;
128 char *name;
129 int count;
130};
131
132/*
133 * Connector and encoder types.
134 */
135static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
136{ { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 },
137 { DRM_MODE_CONNECTOR_VGA, "VGA", 0 },
138 { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 },
139 { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 },
140 { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 },
141 { DRM_MODE_CONNECTOR_Composite, "Composite", 0 },
142 { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
143 { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
144 { DRM_MODE_CONNECTOR_Component, "Component", 0 },
145 { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 },
146 { DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
147 { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
148 { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
Francisco Jerez74bd3c22009-08-02 04:19:18 +0200149 { DRM_MODE_CONNECTOR_TV, "TV", 0 },
Dave Airlief453ba02008-11-07 14:05:41 -0800150};
151
152static struct drm_prop_enum_list drm_encoder_enum_list[] =
153{ { DRM_MODE_ENCODER_NONE, "None" },
154 { DRM_MODE_ENCODER_DAC, "DAC" },
155 { DRM_MODE_ENCODER_TMDS, "TMDS" },
156 { DRM_MODE_ENCODER_LVDS, "LVDS" },
157 { DRM_MODE_ENCODER_TVDAC, "TV" },
158};
159
160char *drm_get_encoder_name(struct drm_encoder *encoder)
161{
162 static char buf[32];
163
164 snprintf(buf, 32, "%s-%d",
165 drm_encoder_enum_list[encoder->encoder_type].name,
166 encoder->base.id);
167 return buf;
168}
169
170char *drm_get_connector_name(struct drm_connector *connector)
171{
172 static char buf[32];
173
174 snprintf(buf, 32, "%s-%d",
175 drm_connector_enum_list[connector->connector_type].name,
176 connector->connector_type_id);
177 return buf;
178}
179EXPORT_SYMBOL(drm_get_connector_name);
180
181char *drm_get_connector_status_name(enum drm_connector_status status)
182{
183 if (status == connector_status_connected)
184 return "connected";
185 else if (status == connector_status_disconnected)
186 return "disconnected";
187 else
188 return "unknown";
189}
190
191/**
192 * drm_mode_object_get - allocate a new identifier
193 * @dev: DRM device
194 * @ptr: object pointer, used to generate unique ID
195 * @type: object type
196 *
197 * LOCKING:
Dave Airlief453ba02008-11-07 14:05:41 -0800198 *
199 * Create a unique identifier based on @ptr in @dev's identifier space. Used
200 * for tracking modes, CRTCs and connectors.
201 *
202 * RETURNS:
203 * New unique (relative to other objects in @dev) integer identifier for the
204 * object.
205 */
206static int drm_mode_object_get(struct drm_device *dev,
207 struct drm_mode_object *obj, uint32_t obj_type)
208{
209 int new_id = 0;
210 int ret;
211
Dave Airlief453ba02008-11-07 14:05:41 -0800212again:
213 if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
214 DRM_ERROR("Ran out memory getting a mode number\n");
215 return -EINVAL;
216 }
217
Jesse Barnesad2563c2009-01-19 17:21:45 +1000218 mutex_lock(&dev->mode_config.idr_mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800219 ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
Jesse Barnesad2563c2009-01-19 17:21:45 +1000220 mutex_unlock(&dev->mode_config.idr_mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800221 if (ret == -EAGAIN)
222 goto again;
223
224 obj->id = new_id;
225 obj->type = obj_type;
226 return 0;
227}
228
229/**
230 * drm_mode_object_put - free an identifer
231 * @dev: DRM device
232 * @id: ID to free
233 *
234 * LOCKING:
235 * Caller must hold DRM mode_config lock.
236 *
237 * Free @id from @dev's unique identifier pool.
238 */
239static void drm_mode_object_put(struct drm_device *dev,
240 struct drm_mode_object *object)
241{
Jesse Barnesad2563c2009-01-19 17:21:45 +1000242 mutex_lock(&dev->mode_config.idr_mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800243 idr_remove(&dev->mode_config.crtc_idr, object->id);
Jesse Barnesad2563c2009-01-19 17:21:45 +1000244 mutex_unlock(&dev->mode_config.idr_mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800245}
246
247void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
248{
Jesse Barnesad2563c2009-01-19 17:21:45 +1000249 struct drm_mode_object *obj = NULL;
Dave Airlief453ba02008-11-07 14:05:41 -0800250
Jesse Barnesad2563c2009-01-19 17:21:45 +1000251 mutex_lock(&dev->mode_config.idr_mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800252 obj = idr_find(&dev->mode_config.crtc_idr, id);
253 if (!obj || (obj->type != type) || (obj->id != id))
Jesse Barnesad2563c2009-01-19 17:21:45 +1000254 obj = NULL;
255 mutex_unlock(&dev->mode_config.idr_mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800256
257 return obj;
258}
259EXPORT_SYMBOL(drm_mode_object_find);
260
261/**
262 * drm_crtc_from_fb - find the CRTC structure associated with an fb
263 * @dev: DRM device
264 * @fb: framebuffer in question
265 *
266 * LOCKING:
267 * Caller must hold mode_config lock.
268 *
269 * Find CRTC in the mode_config structure that matches @fb.
270 *
271 * RETURNS:
272 * Pointer to the CRTC or NULL if it wasn't found.
273 */
274struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
275 struct drm_framebuffer *fb)
276{
277 struct drm_crtc *crtc;
278
279 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
280 if (crtc->fb == fb)
281 return crtc;
282 }
283 return NULL;
284}
285
286/**
287 * drm_framebuffer_init - initialize a framebuffer
288 * @dev: DRM device
289 *
290 * LOCKING:
291 * Caller must hold mode config lock.
292 *
293 * Allocates an ID for the framebuffer's parent mode object, sets its mode
294 * functions & device file and adds it to the master fd list.
295 *
296 * RETURNS:
297 * Zero on success, error code on falure.
298 */
299int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
300 const struct drm_framebuffer_funcs *funcs)
301{
302 int ret;
303
304 ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
305 if (ret) {
306 return ret;
307 }
308
309 fb->dev = dev;
310 fb->funcs = funcs;
311 dev->mode_config.num_fb++;
312 list_add(&fb->head, &dev->mode_config.fb_list);
313
314 return 0;
315}
316EXPORT_SYMBOL(drm_framebuffer_init);
317
318/**
319 * drm_framebuffer_cleanup - remove a framebuffer object
320 * @fb: framebuffer to remove
321 *
322 * LOCKING:
323 * Caller must hold mode config lock.
324 *
325 * Scans all the CRTCs in @dev's mode_config. If they're using @fb, removes
326 * it, setting it to NULL.
327 */
328void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
329{
330 struct drm_device *dev = fb->dev;
331 struct drm_crtc *crtc;
332
333 /* remove from any CRTC */
334 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
335 if (crtc->fb == fb)
336 crtc->fb = NULL;
337 }
338
339 drm_mode_object_put(dev, &fb->base);
340 list_del(&fb->head);
341 dev->mode_config.num_fb--;
342}
343EXPORT_SYMBOL(drm_framebuffer_cleanup);
344
345/**
346 * drm_crtc_init - Initialise a new CRTC object
347 * @dev: DRM device
348 * @crtc: CRTC object to init
349 * @funcs: callbacks for the new CRTC
350 *
351 * LOCKING:
352 * Caller must hold mode config lock.
353 *
354 * Inits a new object created as base part of an driver crtc object.
355 */
356void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
357 const struct drm_crtc_funcs *funcs)
358{
359 crtc->dev = dev;
360 crtc->funcs = funcs;
361
362 mutex_lock(&dev->mode_config.mutex);
363 drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
364
365 list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
366 dev->mode_config.num_crtc++;
367 mutex_unlock(&dev->mode_config.mutex);
368}
369EXPORT_SYMBOL(drm_crtc_init);
370
371/**
372 * drm_crtc_cleanup - Cleans up the core crtc usage.
373 * @crtc: CRTC to cleanup
374 *
375 * LOCKING:
376 * Caller must hold mode config lock.
377 *
378 * Cleanup @crtc. Removes from drm modesetting space
379 * does NOT free object, caller does that.
380 */
381void drm_crtc_cleanup(struct drm_crtc *crtc)
382{
383 struct drm_device *dev = crtc->dev;
384
385 if (crtc->gamma_store) {
386 kfree(crtc->gamma_store);
387 crtc->gamma_store = NULL;
388 }
389
390 drm_mode_object_put(dev, &crtc->base);
391 list_del(&crtc->head);
392 dev->mode_config.num_crtc--;
393}
394EXPORT_SYMBOL(drm_crtc_cleanup);
395
396/**
397 * drm_mode_probed_add - add a mode to a connector's probed mode list
398 * @connector: connector the new mode
399 * @mode: mode data
400 *
401 * LOCKING:
402 * Caller must hold mode config lock.
403 *
404 * Add @mode to @connector's mode list for later use.
405 */
406void drm_mode_probed_add(struct drm_connector *connector,
407 struct drm_display_mode *mode)
408{
409 list_add(&mode->head, &connector->probed_modes);
410}
411EXPORT_SYMBOL(drm_mode_probed_add);
412
413/**
414 * drm_mode_remove - remove and free a mode
415 * @connector: connector list to modify
416 * @mode: mode to remove
417 *
418 * LOCKING:
419 * Caller must hold mode config lock.
420 *
421 * Remove @mode from @connector's mode list, then free it.
422 */
423void drm_mode_remove(struct drm_connector *connector,
424 struct drm_display_mode *mode)
425{
426 list_del(&mode->head);
427 kfree(mode);
428}
429EXPORT_SYMBOL(drm_mode_remove);
430
431/**
432 * drm_connector_init - Init a preallocated connector
433 * @dev: DRM device
434 * @connector: the connector to init
435 * @funcs: callbacks for this connector
436 * @name: user visible name of the connector
437 *
438 * LOCKING:
439 * Caller must hold @dev's mode_config lock.
440 *
441 * Initialises a preallocated connector. Connectors should be
442 * subclassed as part of driver connector objects.
443 */
444void drm_connector_init(struct drm_device *dev,
445 struct drm_connector *connector,
446 const struct drm_connector_funcs *funcs,
447 int connector_type)
448{
449 mutex_lock(&dev->mode_config.mutex);
450
451 connector->dev = dev;
452 connector->funcs = funcs;
453 drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
454 connector->connector_type = connector_type;
455 connector->connector_type_id =
456 ++drm_connector_enum_list[connector_type].count; /* TODO */
457 INIT_LIST_HEAD(&connector->user_modes);
458 INIT_LIST_HEAD(&connector->probed_modes);
459 INIT_LIST_HEAD(&connector->modes);
460 connector->edid_blob_ptr = NULL;
461
462 list_add_tail(&connector->head, &dev->mode_config.connector_list);
463 dev->mode_config.num_connector++;
464
465 drm_connector_attach_property(connector,
466 dev->mode_config.edid_property, 0);
467
468 drm_connector_attach_property(connector,
469 dev->mode_config.dpms_property, 0);
470
471 mutex_unlock(&dev->mode_config.mutex);
472}
473EXPORT_SYMBOL(drm_connector_init);
474
475/**
476 * drm_connector_cleanup - cleans up an initialised connector
477 * @connector: connector to cleanup
478 *
479 * LOCKING:
480 * Caller must hold @dev's mode_config lock.
481 *
482 * Cleans up the connector but doesn't free the object.
483 */
484void drm_connector_cleanup(struct drm_connector *connector)
485{
486 struct drm_device *dev = connector->dev;
487 struct drm_display_mode *mode, *t;
488
489 list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
490 drm_mode_remove(connector, mode);
491
492 list_for_each_entry_safe(mode, t, &connector->modes, head)
493 drm_mode_remove(connector, mode);
494
495 list_for_each_entry_safe(mode, t, &connector->user_modes, head)
496 drm_mode_remove(connector, mode);
497
498 mutex_lock(&dev->mode_config.mutex);
499 drm_mode_object_put(dev, &connector->base);
500 list_del(&connector->head);
501 mutex_unlock(&dev->mode_config.mutex);
502}
503EXPORT_SYMBOL(drm_connector_cleanup);
504
505void drm_encoder_init(struct drm_device *dev,
506 struct drm_encoder *encoder,
507 const struct drm_encoder_funcs *funcs,
508 int encoder_type)
509{
510 mutex_lock(&dev->mode_config.mutex);
511
512 encoder->dev = dev;
513
514 drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
515 encoder->encoder_type = encoder_type;
516 encoder->funcs = funcs;
517
518 list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
519 dev->mode_config.num_encoder++;
520
521 mutex_unlock(&dev->mode_config.mutex);
522}
523EXPORT_SYMBOL(drm_encoder_init);
524
525void drm_encoder_cleanup(struct drm_encoder *encoder)
526{
527 struct drm_device *dev = encoder->dev;
528 mutex_lock(&dev->mode_config.mutex);
529 drm_mode_object_put(dev, &encoder->base);
530 list_del(&encoder->head);
531 mutex_unlock(&dev->mode_config.mutex);
532}
533EXPORT_SYMBOL(drm_encoder_cleanup);
534
535/**
536 * drm_mode_create - create a new display mode
537 * @dev: DRM device
538 *
539 * LOCKING:
540 * Caller must hold DRM mode_config lock.
541 *
542 * Create a new drm_display_mode, give it an ID, and return it.
543 *
544 * RETURNS:
545 * Pointer to new mode on success, NULL on error.
546 */
547struct drm_display_mode *drm_mode_create(struct drm_device *dev)
548{
549 struct drm_display_mode *nmode;
550
551 nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
552 if (!nmode)
553 return NULL;
554
555 drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE);
556 return nmode;
557}
558EXPORT_SYMBOL(drm_mode_create);
559
560/**
561 * drm_mode_destroy - remove a mode
562 * @dev: DRM device
563 * @mode: mode to remove
564 *
565 * LOCKING:
566 * Caller must hold mode config lock.
567 *
568 * Free @mode's unique identifier, then free it.
569 */
570void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
571{
572 drm_mode_object_put(dev, &mode->base);
573
574 kfree(mode);
575}
576EXPORT_SYMBOL(drm_mode_destroy);
577
578static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
579{
580 struct drm_property *edid;
581 struct drm_property *dpms;
582 int i;
583
584 /*
585 * Standard properties (apply to all connectors)
586 */
587 edid = drm_property_create(dev, DRM_MODE_PROP_BLOB |
588 DRM_MODE_PROP_IMMUTABLE,
589 "EDID", 0);
590 dev->mode_config.edid_property = edid;
591
592 dpms = drm_property_create(dev, DRM_MODE_PROP_ENUM,
593 "DPMS", ARRAY_SIZE(drm_dpms_enum_list));
594 for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++)
595 drm_property_add_enum(dpms, i, drm_dpms_enum_list[i].type,
596 drm_dpms_enum_list[i].name);
597 dev->mode_config.dpms_property = dpms;
598
599 return 0;
600}
601
602/**
603 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
604 * @dev: DRM device
605 *
606 * Called by a driver the first time a DVI-I connector is made.
607 */
608int drm_mode_create_dvi_i_properties(struct drm_device *dev)
609{
610 struct drm_property *dvi_i_selector;
611 struct drm_property *dvi_i_subconnector;
612 int i;
613
614 if (dev->mode_config.dvi_i_select_subconnector_property)
615 return 0;
616
617 dvi_i_selector =
618 drm_property_create(dev, DRM_MODE_PROP_ENUM,
619 "select subconnector",
620 ARRAY_SIZE(drm_dvi_i_select_enum_list));
621 for (i = 0; i < ARRAY_SIZE(drm_dvi_i_select_enum_list); i++)
622 drm_property_add_enum(dvi_i_selector, i,
623 drm_dvi_i_select_enum_list[i].type,
624 drm_dvi_i_select_enum_list[i].name);
625 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
626
627 dvi_i_subconnector =
628 drm_property_create(dev, DRM_MODE_PROP_ENUM |
629 DRM_MODE_PROP_IMMUTABLE,
630 "subconnector",
631 ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
632 for (i = 0; i < ARRAY_SIZE(drm_dvi_i_subconnector_enum_list); i++)
633 drm_property_add_enum(dvi_i_subconnector, i,
634 drm_dvi_i_subconnector_enum_list[i].type,
635 drm_dvi_i_subconnector_enum_list[i].name);
636 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
637
638 return 0;
639}
640EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
641
642/**
643 * drm_create_tv_properties - create TV specific connector properties
644 * @dev: DRM device
645 * @num_modes: number of different TV formats (modes) supported
646 * @modes: array of pointers to strings containing name of each format
647 *
648 * Called by a driver's TV initialization routine, this function creates
649 * the TV specific connector properties for a given device. Caller is
650 * responsible for allocating a list of format names and passing them to
651 * this routine.
652 */
653int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
654 char *modes[])
655{
656 struct drm_property *tv_selector;
657 struct drm_property *tv_subconnector;
658 int i;
659
660 if (dev->mode_config.tv_select_subconnector_property)
661 return 0;
662
663 /*
664 * Basic connector properties
665 */
666 tv_selector = drm_property_create(dev, DRM_MODE_PROP_ENUM,
667 "select subconnector",
668 ARRAY_SIZE(drm_tv_select_enum_list));
669 for (i = 0; i < ARRAY_SIZE(drm_tv_select_enum_list); i++)
670 drm_property_add_enum(tv_selector, i,
671 drm_tv_select_enum_list[i].type,
672 drm_tv_select_enum_list[i].name);
673 dev->mode_config.tv_select_subconnector_property = tv_selector;
674
675 tv_subconnector =
676 drm_property_create(dev, DRM_MODE_PROP_ENUM |
677 DRM_MODE_PROP_IMMUTABLE, "subconnector",
678 ARRAY_SIZE(drm_tv_subconnector_enum_list));
679 for (i = 0; i < ARRAY_SIZE(drm_tv_subconnector_enum_list); i++)
680 drm_property_add_enum(tv_subconnector, i,
681 drm_tv_subconnector_enum_list[i].type,
682 drm_tv_subconnector_enum_list[i].name);
683 dev->mode_config.tv_subconnector_property = tv_subconnector;
684
685 /*
686 * Other, TV specific properties: margins & TV modes.
687 */
688 dev->mode_config.tv_left_margin_property =
689 drm_property_create(dev, DRM_MODE_PROP_RANGE,
690 "left margin", 2);
691 dev->mode_config.tv_left_margin_property->values[0] = 0;
692 dev->mode_config.tv_left_margin_property->values[1] = 100;
693
694 dev->mode_config.tv_right_margin_property =
695 drm_property_create(dev, DRM_MODE_PROP_RANGE,
696 "right margin", 2);
697 dev->mode_config.tv_right_margin_property->values[0] = 0;
698 dev->mode_config.tv_right_margin_property->values[1] = 100;
699
700 dev->mode_config.tv_top_margin_property =
701 drm_property_create(dev, DRM_MODE_PROP_RANGE,
702 "top margin", 2);
703 dev->mode_config.tv_top_margin_property->values[0] = 0;
704 dev->mode_config.tv_top_margin_property->values[1] = 100;
705
706 dev->mode_config.tv_bottom_margin_property =
707 drm_property_create(dev, DRM_MODE_PROP_RANGE,
708 "bottom margin", 2);
709 dev->mode_config.tv_bottom_margin_property->values[0] = 0;
710 dev->mode_config.tv_bottom_margin_property->values[1] = 100;
711
712 dev->mode_config.tv_mode_property =
713 drm_property_create(dev, DRM_MODE_PROP_ENUM,
714 "mode", num_modes);
715 for (i = 0; i < num_modes; i++)
716 drm_property_add_enum(dev->mode_config.tv_mode_property, i,
717 i, modes[i]);
718
719 return 0;
720}
721EXPORT_SYMBOL(drm_mode_create_tv_properties);
722
723/**
724 * drm_mode_create_scaling_mode_property - create scaling mode property
725 * @dev: DRM device
726 *
727 * Called by a driver the first time it's needed, must be attached to desired
728 * connectors.
729 */
730int drm_mode_create_scaling_mode_property(struct drm_device *dev)
731{
732 struct drm_property *scaling_mode;
733 int i;
734
735 if (dev->mode_config.scaling_mode_property)
736 return 0;
737
738 scaling_mode =
739 drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode",
740 ARRAY_SIZE(drm_scaling_mode_enum_list));
741 for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++)
742 drm_property_add_enum(scaling_mode, i,
743 drm_scaling_mode_enum_list[i].type,
744 drm_scaling_mode_enum_list[i].name);
745
746 dev->mode_config.scaling_mode_property = scaling_mode;
747
748 return 0;
749}
750EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
751
752/**
753 * drm_mode_create_dithering_property - create dithering property
754 * @dev: DRM device
755 *
756 * Called by a driver the first time it's needed, must be attached to desired
757 * connectors.
758 */
759int drm_mode_create_dithering_property(struct drm_device *dev)
760{
761 struct drm_property *dithering_mode;
762 int i;
763
764 if (dev->mode_config.dithering_mode_property)
765 return 0;
766
767 dithering_mode =
768 drm_property_create(dev, DRM_MODE_PROP_ENUM, "dithering",
769 ARRAY_SIZE(drm_dithering_mode_enum_list));
770 for (i = 0; i < ARRAY_SIZE(drm_dithering_mode_enum_list); i++)
771 drm_property_add_enum(dithering_mode, i,
772 drm_dithering_mode_enum_list[i].type,
773 drm_dithering_mode_enum_list[i].name);
774 dev->mode_config.dithering_mode_property = dithering_mode;
775
776 return 0;
777}
778EXPORT_SYMBOL(drm_mode_create_dithering_property);
779
780/**
781 * drm_mode_config_init - initialize DRM mode_configuration structure
782 * @dev: DRM device
783 *
784 * LOCKING:
785 * None, should happen single threaded at init time.
786 *
787 * Initialize @dev's mode_config structure, used for tracking the graphics
788 * configuration of @dev.
789 */
790void drm_mode_config_init(struct drm_device *dev)
791{
792 mutex_init(&dev->mode_config.mutex);
Jesse Barnesad2563c2009-01-19 17:21:45 +1000793 mutex_init(&dev->mode_config.idr_mutex);
Dave Airlief453ba02008-11-07 14:05:41 -0800794 INIT_LIST_HEAD(&dev->mode_config.fb_list);
795 INIT_LIST_HEAD(&dev->mode_config.fb_kernel_list);
796 INIT_LIST_HEAD(&dev->mode_config.crtc_list);
797 INIT_LIST_HEAD(&dev->mode_config.connector_list);
798 INIT_LIST_HEAD(&dev->mode_config.encoder_list);
799 INIT_LIST_HEAD(&dev->mode_config.property_list);
800 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
801 idr_init(&dev->mode_config.crtc_idr);
802
803 mutex_lock(&dev->mode_config.mutex);
804 drm_mode_create_standard_connector_properties(dev);
805 mutex_unlock(&dev->mode_config.mutex);
806
807 /* Just to be sure */
808 dev->mode_config.num_fb = 0;
809 dev->mode_config.num_connector = 0;
810 dev->mode_config.num_crtc = 0;
811 dev->mode_config.num_encoder = 0;
Dave Airlief453ba02008-11-07 14:05:41 -0800812}
813EXPORT_SYMBOL(drm_mode_config_init);
814
815int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
816{
817 uint32_t total_objects = 0;
818
819 total_objects += dev->mode_config.num_crtc;
820 total_objects += dev->mode_config.num_connector;
821 total_objects += dev->mode_config.num_encoder;
822
823 if (total_objects == 0)
824 return -EINVAL;
825
826 group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
827 if (!group->id_list)
828 return -ENOMEM;
829
830 group->num_crtcs = 0;
831 group->num_connectors = 0;
832 group->num_encoders = 0;
833 return 0;
834}
835
836int drm_mode_group_init_legacy_group(struct drm_device *dev,
837 struct drm_mode_group *group)
838{
839 struct drm_crtc *crtc;
840 struct drm_encoder *encoder;
841 struct drm_connector *connector;
842 int ret;
843
844 if ((ret = drm_mode_group_init(dev, group)))
845 return ret;
846
847 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
848 group->id_list[group->num_crtcs++] = crtc->base.id;
849
850 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
851 group->id_list[group->num_crtcs + group->num_encoders++] =
852 encoder->base.id;
853
854 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
855 group->id_list[group->num_crtcs + group->num_encoders +
856 group->num_connectors++] = connector->base.id;
857
858 return 0;
859}
860
861/**
862 * drm_mode_config_cleanup - free up DRM mode_config info
863 * @dev: DRM device
864 *
865 * LOCKING:
866 * Caller must hold mode config lock.
867 *
868 * Free up all the connectors and CRTCs associated with this DRM device, then
869 * free up the framebuffers and associated buffer objects.
870 *
871 * FIXME: cleanup any dangling user buffer objects too
872 */
873void drm_mode_config_cleanup(struct drm_device *dev)
874{
875 struct drm_connector *connector, *ot;
876 struct drm_crtc *crtc, *ct;
877 struct drm_encoder *encoder, *enct;
878 struct drm_framebuffer *fb, *fbt;
879 struct drm_property *property, *pt;
880
881 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
882 head) {
883 encoder->funcs->destroy(encoder);
884 }
885
886 list_for_each_entry_safe(connector, ot,
887 &dev->mode_config.connector_list, head) {
888 connector->funcs->destroy(connector);
889 }
890
891 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
892 head) {
893 drm_property_destroy(dev, property);
894 }
895
896 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
897 fb->funcs->destroy(fb);
898 }
899
900 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
901 crtc->funcs->destroy(crtc);
902 }
903
904}
905EXPORT_SYMBOL(drm_mode_config_cleanup);
906
Dave Airlief453ba02008-11-07 14:05:41 -0800907/**
908 * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
909 * @out: drm_mode_modeinfo struct to return to the user
910 * @in: drm_display_mode to use
911 *
912 * LOCKING:
913 * None.
914 *
915 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
916 * the user.
917 */
918void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
919 struct drm_display_mode *in)
920{
921 out->clock = in->clock;
922 out->hdisplay = in->hdisplay;
923 out->hsync_start = in->hsync_start;
924 out->hsync_end = in->hsync_end;
925 out->htotal = in->htotal;
926 out->hskew = in->hskew;
927 out->vdisplay = in->vdisplay;
928 out->vsync_start = in->vsync_start;
929 out->vsync_end = in->vsync_end;
930 out->vtotal = in->vtotal;
931 out->vscan = in->vscan;
932 out->vrefresh = in->vrefresh;
933 out->flags = in->flags;
934 out->type = in->type;
935 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
936 out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
937}
938
939/**
940 * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
941 * @out: drm_display_mode to return to the user
942 * @in: drm_mode_modeinfo to use
943 *
944 * LOCKING:
945 * None.
946 *
947 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
948 * the caller.
949 */
950void drm_crtc_convert_umode(struct drm_display_mode *out,
951 struct drm_mode_modeinfo *in)
952{
953 out->clock = in->clock;
954 out->hdisplay = in->hdisplay;
955 out->hsync_start = in->hsync_start;
956 out->hsync_end = in->hsync_end;
957 out->htotal = in->htotal;
958 out->hskew = in->hskew;
959 out->vdisplay = in->vdisplay;
960 out->vsync_start = in->vsync_start;
961 out->vsync_end = in->vsync_end;
962 out->vtotal = in->vtotal;
963 out->vscan = in->vscan;
964 out->vrefresh = in->vrefresh;
965 out->flags = in->flags;
966 out->type = in->type;
967 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
968 out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
969}
970
971/**
972 * drm_mode_getresources - get graphics configuration
973 * @inode: inode from the ioctl
974 * @filp: file * from the ioctl
975 * @cmd: cmd from ioctl
976 * @arg: arg from ioctl
977 *
978 * LOCKING:
979 * Takes mode config lock.
980 *
981 * Construct a set of configuration description structures and return
982 * them to the user, including CRTC, connector and framebuffer configuration.
983 *
984 * Called by the user via ioctl.
985 *
986 * RETURNS:
987 * Zero on success, errno on failure.
988 */
989int drm_mode_getresources(struct drm_device *dev, void *data,
990 struct drm_file *file_priv)
991{
992 struct drm_mode_card_res *card_res = data;
993 struct list_head *lh;
994 struct drm_framebuffer *fb;
995 struct drm_connector *connector;
996 struct drm_crtc *crtc;
997 struct drm_encoder *encoder;
998 int ret = 0;
999 int connector_count = 0;
1000 int crtc_count = 0;
1001 int fb_count = 0;
1002 int encoder_count = 0;
1003 int copied = 0, i;
1004 uint32_t __user *fb_id;
1005 uint32_t __user *crtc_id;
1006 uint32_t __user *connector_id;
1007 uint32_t __user *encoder_id;
1008 struct drm_mode_group *mode_group;
1009
1010 mutex_lock(&dev->mode_config.mutex);
1011
1012 /*
1013 * For the non-control nodes we need to limit the list of resources
1014 * by IDs in the group list for this node
1015 */
1016 list_for_each(lh, &file_priv->fbs)
1017 fb_count++;
1018
1019 mode_group = &file_priv->master->minor->mode_group;
1020 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1021
1022 list_for_each(lh, &dev->mode_config.crtc_list)
1023 crtc_count++;
1024
1025 list_for_each(lh, &dev->mode_config.connector_list)
1026 connector_count++;
1027
1028 list_for_each(lh, &dev->mode_config.encoder_list)
1029 encoder_count++;
1030 } else {
1031
1032 crtc_count = mode_group->num_crtcs;
1033 connector_count = mode_group->num_connectors;
1034 encoder_count = mode_group->num_encoders;
1035 }
1036
1037 card_res->max_height = dev->mode_config.max_height;
1038 card_res->min_height = dev->mode_config.min_height;
1039 card_res->max_width = dev->mode_config.max_width;
1040 card_res->min_width = dev->mode_config.min_width;
1041
1042 /* handle this in 4 parts */
1043 /* FBs */
1044 if (card_res->count_fbs >= fb_count) {
1045 copied = 0;
1046 fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
1047 list_for_each_entry(fb, &file_priv->fbs, head) {
1048 if (put_user(fb->base.id, fb_id + copied)) {
1049 ret = -EFAULT;
1050 goto out;
1051 }
1052 copied++;
1053 }
1054 }
1055 card_res->count_fbs = fb_count;
1056
1057 /* CRTCs */
1058 if (card_res->count_crtcs >= crtc_count) {
1059 copied = 0;
1060 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
1061 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1062 list_for_each_entry(crtc, &dev->mode_config.crtc_list,
1063 head) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001064 DRM_DEBUG_KMS("CRTC ID is %d\n", crtc->base.id);
Dave Airlief453ba02008-11-07 14:05:41 -08001065 if (put_user(crtc->base.id, crtc_id + copied)) {
1066 ret = -EFAULT;
1067 goto out;
1068 }
1069 copied++;
1070 }
1071 } else {
1072 for (i = 0; i < mode_group->num_crtcs; i++) {
1073 if (put_user(mode_group->id_list[i],
1074 crtc_id + copied)) {
1075 ret = -EFAULT;
1076 goto out;
1077 }
1078 copied++;
1079 }
1080 }
1081 }
1082 card_res->count_crtcs = crtc_count;
1083
1084 /* Encoders */
1085 if (card_res->count_encoders >= encoder_count) {
1086 copied = 0;
1087 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
1088 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1089 list_for_each_entry(encoder,
1090 &dev->mode_config.encoder_list,
1091 head) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001092 DRM_DEBUG_KMS("ENCODER ID is %d\n",
Dave Airlief453ba02008-11-07 14:05:41 -08001093 encoder->base.id);
1094 if (put_user(encoder->base.id, encoder_id +
1095 copied)) {
1096 ret = -EFAULT;
1097 goto out;
1098 }
1099 copied++;
1100 }
1101 } else {
1102 for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
1103 if (put_user(mode_group->id_list[i],
1104 encoder_id + copied)) {
1105 ret = -EFAULT;
1106 goto out;
1107 }
1108 copied++;
1109 }
1110
1111 }
1112 }
1113 card_res->count_encoders = encoder_count;
1114
1115 /* Connectors */
1116 if (card_res->count_connectors >= connector_count) {
1117 copied = 0;
1118 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
1119 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1120 list_for_each_entry(connector,
1121 &dev->mode_config.connector_list,
1122 head) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001123 DRM_DEBUG_KMS("CONNECTOR ID is %d\n",
Dave Airlief453ba02008-11-07 14:05:41 -08001124 connector->base.id);
1125 if (put_user(connector->base.id,
1126 connector_id + copied)) {
1127 ret = -EFAULT;
1128 goto out;
1129 }
1130 copied++;
1131 }
1132 } else {
1133 int start = mode_group->num_crtcs +
1134 mode_group->num_encoders;
1135 for (i = start; i < start + mode_group->num_connectors; i++) {
1136 if (put_user(mode_group->id_list[i],
1137 connector_id + copied)) {
1138 ret = -EFAULT;
1139 goto out;
1140 }
1141 copied++;
1142 }
1143 }
1144 }
1145 card_res->count_connectors = connector_count;
1146
Zhao Yakui58367ed2009-07-20 13:48:07 +08001147 DRM_DEBUG_KMS("Counted %d %d %d\n", card_res->count_crtcs,
Dave Airlief453ba02008-11-07 14:05:41 -08001148 card_res->count_connectors, card_res->count_encoders);
1149
1150out:
1151 mutex_unlock(&dev->mode_config.mutex);
1152 return ret;
1153}
1154
1155/**
1156 * drm_mode_getcrtc - get CRTC configuration
1157 * @inode: inode from the ioctl
1158 * @filp: file * from the ioctl
1159 * @cmd: cmd from ioctl
1160 * @arg: arg from ioctl
1161 *
1162 * LOCKING:
1163 * Caller? (FIXME)
1164 *
1165 * Construct a CRTC configuration structure to return to the user.
1166 *
1167 * Called by the user via ioctl.
1168 *
1169 * RETURNS:
1170 * Zero on success, errno on failure.
1171 */
1172int drm_mode_getcrtc(struct drm_device *dev,
1173 void *data, struct drm_file *file_priv)
1174{
1175 struct drm_mode_crtc *crtc_resp = data;
1176 struct drm_crtc *crtc;
1177 struct drm_mode_object *obj;
1178 int ret = 0;
1179
1180 mutex_lock(&dev->mode_config.mutex);
1181
1182 obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
1183 DRM_MODE_OBJECT_CRTC);
1184 if (!obj) {
1185 ret = -EINVAL;
1186 goto out;
1187 }
1188 crtc = obj_to_crtc(obj);
1189
1190 crtc_resp->x = crtc->x;
1191 crtc_resp->y = crtc->y;
1192 crtc_resp->gamma_size = crtc->gamma_size;
1193 if (crtc->fb)
1194 crtc_resp->fb_id = crtc->fb->base.id;
1195 else
1196 crtc_resp->fb_id = 0;
1197
1198 if (crtc->enabled) {
1199
1200 drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
1201 crtc_resp->mode_valid = 1;
1202
1203 } else {
1204 crtc_resp->mode_valid = 0;
1205 }
1206
1207out:
1208 mutex_unlock(&dev->mode_config.mutex);
1209 return ret;
1210}
1211
1212/**
1213 * drm_mode_getconnector - get connector configuration
1214 * @inode: inode from the ioctl
1215 * @filp: file * from the ioctl
1216 * @cmd: cmd from ioctl
1217 * @arg: arg from ioctl
1218 *
1219 * LOCKING:
1220 * Caller? (FIXME)
1221 *
1222 * Construct a connector configuration structure to return to the user.
1223 *
1224 * Called by the user via ioctl.
1225 *
1226 * RETURNS:
1227 * Zero on success, errno on failure.
1228 */
1229int drm_mode_getconnector(struct drm_device *dev, void *data,
1230 struct drm_file *file_priv)
1231{
1232 struct drm_mode_get_connector *out_resp = data;
1233 struct drm_mode_object *obj;
1234 struct drm_connector *connector;
1235 struct drm_display_mode *mode;
1236 int mode_count = 0;
1237 int props_count = 0;
1238 int encoders_count = 0;
1239 int ret = 0;
1240 int copied = 0;
1241 int i;
1242 struct drm_mode_modeinfo u_mode;
1243 struct drm_mode_modeinfo __user *mode_ptr;
1244 uint32_t __user *prop_ptr;
1245 uint64_t __user *prop_values;
1246 uint32_t __user *encoder_ptr;
1247
1248 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
1249
Zhao Yakui58367ed2009-07-20 13:48:07 +08001250 DRM_DEBUG_KMS("connector id %d:\n", out_resp->connector_id);
Dave Airlief453ba02008-11-07 14:05:41 -08001251
1252 mutex_lock(&dev->mode_config.mutex);
1253
1254 obj = drm_mode_object_find(dev, out_resp->connector_id,
1255 DRM_MODE_OBJECT_CONNECTOR);
1256 if (!obj) {
1257 ret = -EINVAL;
1258 goto out;
1259 }
1260 connector = obj_to_connector(obj);
1261
1262 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
1263 if (connector->property_ids[i] != 0) {
1264 props_count++;
1265 }
1266 }
1267
1268 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1269 if (connector->encoder_ids[i] != 0) {
1270 encoders_count++;
1271 }
1272 }
1273
1274 if (out_resp->count_modes == 0) {
1275 connector->funcs->fill_modes(connector,
1276 dev->mode_config.max_width,
1277 dev->mode_config.max_height);
1278 }
1279
1280 /* delayed so we get modes regardless of pre-fill_modes state */
1281 list_for_each_entry(mode, &connector->modes, head)
1282 mode_count++;
1283
1284 out_resp->connector_id = connector->base.id;
1285 out_resp->connector_type = connector->connector_type;
1286 out_resp->connector_type_id = connector->connector_type_id;
1287 out_resp->mm_width = connector->display_info.width_mm;
1288 out_resp->mm_height = connector->display_info.height_mm;
1289 out_resp->subpixel = connector->display_info.subpixel_order;
1290 out_resp->connection = connector->status;
1291 if (connector->encoder)
1292 out_resp->encoder_id = connector->encoder->base.id;
1293 else
1294 out_resp->encoder_id = 0;
1295
1296 /*
1297 * This ioctl is called twice, once to determine how much space is
1298 * needed, and the 2nd time to fill it.
1299 */
1300 if ((out_resp->count_modes >= mode_count) && mode_count) {
1301 copied = 0;
1302 mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr;
1303 list_for_each_entry(mode, &connector->modes, head) {
1304 drm_crtc_convert_to_umode(&u_mode, mode);
1305 if (copy_to_user(mode_ptr + copied,
1306 &u_mode, sizeof(u_mode))) {
1307 ret = -EFAULT;
1308 goto out;
1309 }
1310 copied++;
1311 }
1312 }
1313 out_resp->count_modes = mode_count;
1314
1315 if ((out_resp->count_props >= props_count) && props_count) {
1316 copied = 0;
1317 prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr);
1318 prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr);
1319 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
1320 if (connector->property_ids[i] != 0) {
1321 if (put_user(connector->property_ids[i],
1322 prop_ptr + copied)) {
1323 ret = -EFAULT;
1324 goto out;
1325 }
1326
1327 if (put_user(connector->property_values[i],
1328 prop_values + copied)) {
1329 ret = -EFAULT;
1330 goto out;
1331 }
1332 copied++;
1333 }
1334 }
1335 }
1336 out_resp->count_props = props_count;
1337
1338 if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
1339 copied = 0;
1340 encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr);
1341 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1342 if (connector->encoder_ids[i] != 0) {
1343 if (put_user(connector->encoder_ids[i],
1344 encoder_ptr + copied)) {
1345 ret = -EFAULT;
1346 goto out;
1347 }
1348 copied++;
1349 }
1350 }
1351 }
1352 out_resp->count_encoders = encoders_count;
1353
1354out:
1355 mutex_unlock(&dev->mode_config.mutex);
1356 return ret;
1357}
1358
1359int drm_mode_getencoder(struct drm_device *dev, void *data,
1360 struct drm_file *file_priv)
1361{
1362 struct drm_mode_get_encoder *enc_resp = data;
1363 struct drm_mode_object *obj;
1364 struct drm_encoder *encoder;
1365 int ret = 0;
1366
1367 mutex_lock(&dev->mode_config.mutex);
1368 obj = drm_mode_object_find(dev, enc_resp->encoder_id,
1369 DRM_MODE_OBJECT_ENCODER);
1370 if (!obj) {
1371 ret = -EINVAL;
1372 goto out;
1373 }
1374 encoder = obj_to_encoder(obj);
1375
1376 if (encoder->crtc)
1377 enc_resp->crtc_id = encoder->crtc->base.id;
1378 else
1379 enc_resp->crtc_id = 0;
1380 enc_resp->encoder_type = encoder->encoder_type;
1381 enc_resp->encoder_id = encoder->base.id;
1382 enc_resp->possible_crtcs = encoder->possible_crtcs;
1383 enc_resp->possible_clones = encoder->possible_clones;
1384
1385out:
1386 mutex_unlock(&dev->mode_config.mutex);
1387 return ret;
1388}
1389
1390/**
1391 * drm_mode_setcrtc - set CRTC configuration
1392 * @inode: inode from the ioctl
1393 * @filp: file * from the ioctl
1394 * @cmd: cmd from ioctl
1395 * @arg: arg from ioctl
1396 *
1397 * LOCKING:
1398 * Caller? (FIXME)
1399 *
1400 * Build a new CRTC configuration based on user request.
1401 *
1402 * Called by the user via ioctl.
1403 *
1404 * RETURNS:
1405 * Zero on success, errno on failure.
1406 */
1407int drm_mode_setcrtc(struct drm_device *dev, void *data,
1408 struct drm_file *file_priv)
1409{
1410 struct drm_mode_config *config = &dev->mode_config;
1411 struct drm_mode_crtc *crtc_req = data;
1412 struct drm_mode_object *obj;
1413 struct drm_crtc *crtc, *crtcfb;
1414 struct drm_connector **connector_set = NULL, *connector;
1415 struct drm_framebuffer *fb = NULL;
1416 struct drm_display_mode *mode = NULL;
1417 struct drm_mode_set set;
1418 uint32_t __user *set_connectors_ptr;
1419 int ret = 0;
1420 int i;
1421
1422 mutex_lock(&dev->mode_config.mutex);
1423 obj = drm_mode_object_find(dev, crtc_req->crtc_id,
1424 DRM_MODE_OBJECT_CRTC);
1425 if (!obj) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001426 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
Dave Airlief453ba02008-11-07 14:05:41 -08001427 ret = -EINVAL;
1428 goto out;
1429 }
1430 crtc = obj_to_crtc(obj);
1431
1432 if (crtc_req->mode_valid) {
1433 /* If we have a mode we need a framebuffer. */
1434 /* If we pass -1, set the mode with the currently bound fb */
1435 if (crtc_req->fb_id == -1) {
1436 list_for_each_entry(crtcfb,
1437 &dev->mode_config.crtc_list, head) {
1438 if (crtcfb == crtc) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001439 DRM_DEBUG_KMS("Using current fb for "
1440 "setmode\n");
Dave Airlief453ba02008-11-07 14:05:41 -08001441 fb = crtc->fb;
1442 }
1443 }
1444 } else {
1445 obj = drm_mode_object_find(dev, crtc_req->fb_id,
1446 DRM_MODE_OBJECT_FB);
1447 if (!obj) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001448 DRM_DEBUG_KMS("Unknown FB ID%d\n",
1449 crtc_req->fb_id);
Dave Airlief453ba02008-11-07 14:05:41 -08001450 ret = -EINVAL;
1451 goto out;
1452 }
1453 fb = obj_to_fb(obj);
1454 }
1455
1456 mode = drm_mode_create(dev);
1457 drm_crtc_convert_umode(mode, &crtc_req->mode);
1458 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1459 }
1460
1461 if (crtc_req->count_connectors == 0 && mode) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001462 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
Dave Airlief453ba02008-11-07 14:05:41 -08001463 ret = -EINVAL;
1464 goto out;
1465 }
1466
1467 if (crtc_req->count_connectors > 0 && !mode && !fb) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001468 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
Dave Airlief453ba02008-11-07 14:05:41 -08001469 crtc_req->count_connectors);
1470 ret = -EINVAL;
1471 goto out;
1472 }
1473
1474 if (crtc_req->count_connectors > 0) {
1475 u32 out_id;
1476
1477 /* Avoid unbounded kernel memory allocation */
1478 if (crtc_req->count_connectors > config->num_connector) {
1479 ret = -EINVAL;
1480 goto out;
1481 }
1482
1483 connector_set = kmalloc(crtc_req->count_connectors *
1484 sizeof(struct drm_connector *),
1485 GFP_KERNEL);
1486 if (!connector_set) {
1487 ret = -ENOMEM;
1488 goto out;
1489 }
1490
1491 for (i = 0; i < crtc_req->count_connectors; i++) {
1492 set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr;
1493 if (get_user(out_id, &set_connectors_ptr[i])) {
1494 ret = -EFAULT;
1495 goto out;
1496 }
1497
1498 obj = drm_mode_object_find(dev, out_id,
1499 DRM_MODE_OBJECT_CONNECTOR);
1500 if (!obj) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001501 DRM_DEBUG_KMS("Connector id %d unknown\n",
1502 out_id);
Dave Airlief453ba02008-11-07 14:05:41 -08001503 ret = -EINVAL;
1504 goto out;
1505 }
1506 connector = obj_to_connector(obj);
1507
1508 connector_set[i] = connector;
1509 }
1510 }
1511
1512 set.crtc = crtc;
1513 set.x = crtc_req->x;
1514 set.y = crtc_req->y;
1515 set.mode = mode;
1516 set.connectors = connector_set;
1517 set.num_connectors = crtc_req->count_connectors;
1518 set.fb =fb;
1519 ret = crtc->funcs->set_config(&set);
1520
1521out:
1522 kfree(connector_set);
1523 mutex_unlock(&dev->mode_config.mutex);
1524 return ret;
1525}
1526
1527int drm_mode_cursor_ioctl(struct drm_device *dev,
1528 void *data, struct drm_file *file_priv)
1529{
1530 struct drm_mode_cursor *req = data;
1531 struct drm_mode_object *obj;
1532 struct drm_crtc *crtc;
1533 int ret = 0;
1534
Zhao Yakui58367ed2009-07-20 13:48:07 +08001535 DRM_DEBUG_KMS("\n");
Dave Airlief453ba02008-11-07 14:05:41 -08001536
1537 if (!req->flags) {
1538 DRM_ERROR("no operation set\n");
1539 return -EINVAL;
1540 }
1541
1542 mutex_lock(&dev->mode_config.mutex);
Jakob Bornecrantze0c84632008-12-19 14:50:50 +10001543 obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
Dave Airlief453ba02008-11-07 14:05:41 -08001544 if (!obj) {
Zhao Yakui58367ed2009-07-20 13:48:07 +08001545 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
Dave Airlief453ba02008-11-07 14:05:41 -08001546 ret = -EINVAL;
1547 goto out;
1548 }
1549 crtc = obj_to_crtc(obj);
1550
1551 if (req->flags & DRM_MODE_CURSOR_BO) {
1552 if (!crtc->funcs->cursor_set) {
1553 DRM_ERROR("crtc does not support cursor\n");
1554 ret = -ENXIO;
1555 goto out;
1556 }
1557 /* Turns off the cursor if handle is 0 */
1558 ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
1559 req->width, req->height);
1560 }
1561
1562 if (req->flags & DRM_MODE_CURSOR_MOVE) {
1563 if (crtc->funcs->cursor_move) {
1564 ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
1565 } else {
1566 DRM_ERROR("crtc does not support cursor\n");
1567 ret = -EFAULT;
1568 goto out;
1569 }
1570 }
1571out:
1572 mutex_unlock(&dev->mode_config.mutex);
1573 return ret;
1574}
1575
1576/**
1577 * drm_mode_addfb - add an FB to the graphics configuration
1578 * @inode: inode from the ioctl
1579 * @filp: file * from the ioctl
1580 * @cmd: cmd from ioctl
1581 * @arg: arg from ioctl
1582 *
1583 * LOCKING:
1584 * Takes mode config lock.
1585 *
1586 * Add a new FB to the specified CRTC, given a user request.
1587 *
1588 * Called by the user via ioctl.
1589 *
1590 * RETURNS:
1591 * Zero on success, errno on failure.
1592 */
1593int drm_mode_addfb(struct drm_device *dev,
1594 void *data, struct drm_file *file_priv)
1595{
1596 struct drm_mode_fb_cmd *r = data;
1597 struct drm_mode_config *config = &dev->mode_config;
1598 struct drm_framebuffer *fb;
1599 int ret = 0;
1600
1601 if ((config->min_width > r->width) || (r->width > config->max_width)) {
1602 DRM_ERROR("mode new framebuffer width not within limits\n");
1603 return -EINVAL;
1604 }
1605 if ((config->min_height > r->height) || (r->height > config->max_height)) {
1606 DRM_ERROR("mode new framebuffer height not within limits\n");
1607 return -EINVAL;
1608 }
1609
1610 mutex_lock(&dev->mode_config.mutex);
1611
1612 /* TODO check buffer is sufficently large */
1613 /* TODO setup destructor callback */
1614
1615 fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
1616 if (!fb) {
1617 DRM_ERROR("could not create framebuffer\n");
1618 ret = -EINVAL;
1619 goto out;
1620 }
1621
Jakob Bornecrantze0c84632008-12-19 14:50:50 +10001622 r->fb_id = fb->base.id;
Dave Airlief453ba02008-11-07 14:05:41 -08001623 list_add(&fb->filp_head, &file_priv->fbs);
1624
1625out:
1626 mutex_unlock(&dev->mode_config.mutex);
1627 return ret;
1628}
1629
1630/**
1631 * drm_mode_rmfb - remove an FB from the configuration
1632 * @inode: inode from the ioctl
1633 * @filp: file * from the ioctl
1634 * @cmd: cmd from ioctl
1635 * @arg: arg from ioctl
1636 *
1637 * LOCKING:
1638 * Takes mode config lock.
1639 *
1640 * Remove the FB specified by the user.
1641 *
1642 * Called by the user via ioctl.
1643 *
1644 * RETURNS:
1645 * Zero on success, errno on failure.
1646 */
1647int drm_mode_rmfb(struct drm_device *dev,
1648 void *data, struct drm_file *file_priv)
1649{
1650 struct drm_mode_object *obj;
1651 struct drm_framebuffer *fb = NULL;
1652 struct drm_framebuffer *fbl = NULL;
1653 uint32_t *id = data;
1654 int ret = 0;
1655 int found = 0;
1656
1657 mutex_lock(&dev->mode_config.mutex);
1658 obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
1659 /* TODO check that we realy get a framebuffer back. */
1660 if (!obj) {
1661 DRM_ERROR("mode invalid framebuffer id\n");
1662 ret = -EINVAL;
1663 goto out;
1664 }
1665 fb = obj_to_fb(obj);
1666
1667 list_for_each_entry(fbl, &file_priv->fbs, filp_head)
1668 if (fb == fbl)
1669 found = 1;
1670
1671 if (!found) {
1672 DRM_ERROR("tried to remove a fb that we didn't own\n");
1673 ret = -EINVAL;
1674 goto out;
1675 }
1676
1677 /* TODO release all crtc connected to the framebuffer */
1678 /* TODO unhock the destructor from the buffer object */
1679
1680 list_del(&fb->filp_head);
1681 fb->funcs->destroy(fb);
1682
1683out:
1684 mutex_unlock(&dev->mode_config.mutex);
1685 return ret;
1686}
1687
1688/**
1689 * drm_mode_getfb - get FB info
1690 * @inode: inode from the ioctl
1691 * @filp: file * from the ioctl
1692 * @cmd: cmd from ioctl
1693 * @arg: arg from ioctl
1694 *
1695 * LOCKING:
1696 * Caller? (FIXME)
1697 *
1698 * Lookup the FB given its ID and return info about it.
1699 *
1700 * Called by the user via ioctl.
1701 *
1702 * RETURNS:
1703 * Zero on success, errno on failure.
1704 */
1705int drm_mode_getfb(struct drm_device *dev,
1706 void *data, struct drm_file *file_priv)
1707{
1708 struct drm_mode_fb_cmd *r = data;
1709 struct drm_mode_object *obj;
1710 struct drm_framebuffer *fb;
1711 int ret = 0;
1712
1713 mutex_lock(&dev->mode_config.mutex);
Jakob Bornecrantze0c84632008-12-19 14:50:50 +10001714 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
Dave Airlief453ba02008-11-07 14:05:41 -08001715 if (!obj) {
1716 DRM_ERROR("invalid framebuffer id\n");
1717 ret = -EINVAL;
1718 goto out;
1719 }
1720 fb = obj_to_fb(obj);
1721
1722 r->height = fb->height;
1723 r->width = fb->width;
1724 r->depth = fb->depth;
1725 r->bpp = fb->bits_per_pixel;
1726 r->pitch = fb->pitch;
1727 fb->funcs->create_handle(fb, file_priv, &r->handle);
1728
1729out:
1730 mutex_unlock(&dev->mode_config.mutex);
1731 return ret;
1732}
1733
1734/**
1735 * drm_fb_release - remove and free the FBs on this file
1736 * @filp: file * from the ioctl
1737 *
1738 * LOCKING:
1739 * Takes mode config lock.
1740 *
1741 * Destroy all the FBs associated with @filp.
1742 *
1743 * Called by the user via ioctl.
1744 *
1745 * RETURNS:
1746 * Zero on success, errno on failure.
1747 */
Kristian Høgsbergea39f832009-02-12 14:37:56 -05001748void drm_fb_release(struct drm_file *priv)
Dave Airlief453ba02008-11-07 14:05:41 -08001749{
Dave Airlief453ba02008-11-07 14:05:41 -08001750 struct drm_device *dev = priv->minor->dev;
1751 struct drm_framebuffer *fb, *tfb;
1752
1753 mutex_lock(&dev->mode_config.mutex);
1754 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
1755 list_del(&fb->filp_head);
1756 fb->funcs->destroy(fb);
1757 }
1758 mutex_unlock(&dev->mode_config.mutex);
1759}
1760
1761/**
1762 * drm_mode_attachmode - add a mode to the user mode list
1763 * @dev: DRM device
1764 * @connector: connector to add the mode to
1765 * @mode: mode to add
1766 *
1767 * Add @mode to @connector's user mode list.
1768 */
1769static int drm_mode_attachmode(struct drm_device *dev,
1770 struct drm_connector *connector,
1771 struct drm_display_mode *mode)
1772{
1773 int ret = 0;
1774
1775 list_add_tail(&mode->head, &connector->user_modes);
1776 return ret;
1777}
1778
1779int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
1780 struct drm_display_mode *mode)
1781{
1782 struct drm_connector *connector;
1783 int ret = 0;
1784 struct drm_display_mode *dup_mode;
1785 int need_dup = 0;
1786 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1787 if (!connector->encoder)
1788 break;
1789 if (connector->encoder->crtc == crtc) {
1790 if (need_dup)
1791 dup_mode = drm_mode_duplicate(dev, mode);
1792 else
1793 dup_mode = mode;
1794 ret = drm_mode_attachmode(dev, connector, dup_mode);
1795 if (ret)
1796 return ret;
1797 need_dup = 1;
1798 }
1799 }
1800 return 0;
1801}
1802EXPORT_SYMBOL(drm_mode_attachmode_crtc);
1803
1804static int drm_mode_detachmode(struct drm_device *dev,
1805 struct drm_connector *connector,
1806 struct drm_display_mode *mode)
1807{
1808 int found = 0;
1809 int ret = 0;
1810 struct drm_display_mode *match_mode, *t;
1811
1812 list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) {
1813 if (drm_mode_equal(match_mode, mode)) {
1814 list_del(&match_mode->head);
1815 drm_mode_destroy(dev, match_mode);
1816 found = 1;
1817 break;
1818 }
1819 }
1820
1821 if (!found)
1822 ret = -EINVAL;
1823
1824 return ret;
1825}
1826
1827int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
1828{
1829 struct drm_connector *connector;
1830
1831 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1832 drm_mode_detachmode(dev, connector, mode);
1833 }
1834 return 0;
1835}
1836EXPORT_SYMBOL(drm_mode_detachmode_crtc);
1837
1838/**
1839 * drm_fb_attachmode - Attach a user mode to an connector
1840 * @inode: inode from the ioctl
1841 * @filp: file * from the ioctl
1842 * @cmd: cmd from ioctl
1843 * @arg: arg from ioctl
1844 *
1845 * This attaches a user specified mode to an connector.
1846 * Called by the user via ioctl.
1847 *
1848 * RETURNS:
1849 * Zero on success, errno on failure.
1850 */
1851int drm_mode_attachmode_ioctl(struct drm_device *dev,
1852 void *data, struct drm_file *file_priv)
1853{
1854 struct drm_mode_mode_cmd *mode_cmd = data;
1855 struct drm_connector *connector;
1856 struct drm_display_mode *mode;
1857 struct drm_mode_object *obj;
1858 struct drm_mode_modeinfo *umode = &mode_cmd->mode;
1859 int ret = 0;
1860
1861 mutex_lock(&dev->mode_config.mutex);
1862
1863 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
1864 if (!obj) {
1865 ret = -EINVAL;
1866 goto out;
1867 }
1868 connector = obj_to_connector(obj);
1869
1870 mode = drm_mode_create(dev);
1871 if (!mode) {
1872 ret = -ENOMEM;
1873 goto out;
1874 }
1875
1876 drm_crtc_convert_umode(mode, umode);
1877
1878 ret = drm_mode_attachmode(dev, connector, mode);
1879out:
1880 mutex_unlock(&dev->mode_config.mutex);
1881 return ret;
1882}
1883
1884
1885/**
1886 * drm_fb_detachmode - Detach a user specified mode from an connector
1887 * @inode: inode from the ioctl
1888 * @filp: file * from the ioctl
1889 * @cmd: cmd from ioctl
1890 * @arg: arg from ioctl
1891 *
1892 * Called by the user via ioctl.
1893 *
1894 * RETURNS:
1895 * Zero on success, errno on failure.
1896 */
1897int drm_mode_detachmode_ioctl(struct drm_device *dev,
1898 void *data, struct drm_file *file_priv)
1899{
1900 struct drm_mode_object *obj;
1901 struct drm_mode_mode_cmd *mode_cmd = data;
1902 struct drm_connector *connector;
1903 struct drm_display_mode mode;
1904 struct drm_mode_modeinfo *umode = &mode_cmd->mode;
1905 int ret = 0;
1906
1907 mutex_lock(&dev->mode_config.mutex);
1908
1909 obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
1910 if (!obj) {
1911 ret = -EINVAL;
1912 goto out;
1913 }
1914 connector = obj_to_connector(obj);
1915
1916 drm_crtc_convert_umode(&mode, umode);
1917 ret = drm_mode_detachmode(dev, connector, &mode);
1918out:
1919 mutex_unlock(&dev->mode_config.mutex);
1920 return ret;
1921}
1922
1923struct drm_property *drm_property_create(struct drm_device *dev, int flags,
1924 const char *name, int num_values)
1925{
1926 struct drm_property *property = NULL;
1927
1928 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
1929 if (!property)
1930 return NULL;
1931
1932 if (num_values) {
1933 property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
1934 if (!property->values)
1935 goto fail;
1936 }
1937
1938 drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
1939 property->flags = flags;
1940 property->num_values = num_values;
1941 INIT_LIST_HEAD(&property->enum_blob_list);
1942
1943 if (name)
1944 strncpy(property->name, name, DRM_PROP_NAME_LEN);
1945
1946 list_add_tail(&property->head, &dev->mode_config.property_list);
1947 return property;
1948fail:
1949 kfree(property);
1950 return NULL;
1951}
1952EXPORT_SYMBOL(drm_property_create);
1953
1954int drm_property_add_enum(struct drm_property *property, int index,
1955 uint64_t value, const char *name)
1956{
1957 struct drm_property_enum *prop_enum;
1958
1959 if (!(property->flags & DRM_MODE_PROP_ENUM))
1960 return -EINVAL;
1961
1962 if (!list_empty(&property->enum_blob_list)) {
1963 list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
1964 if (prop_enum->value == value) {
1965 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
1966 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
1967 return 0;
1968 }
1969 }
1970 }
1971
1972 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
1973 if (!prop_enum)
1974 return -ENOMEM;
1975
1976 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
1977 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
1978 prop_enum->value = value;
1979
1980 property->values[index] = value;
1981 list_add_tail(&prop_enum->head, &property->enum_blob_list);
1982 return 0;
1983}
1984EXPORT_SYMBOL(drm_property_add_enum);
1985
1986void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
1987{
1988 struct drm_property_enum *prop_enum, *pt;
1989
1990 list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
1991 list_del(&prop_enum->head);
1992 kfree(prop_enum);
1993 }
1994
1995 if (property->num_values)
1996 kfree(property->values);
1997 drm_mode_object_put(dev, &property->base);
1998 list_del(&property->head);
1999 kfree(property);
2000}
2001EXPORT_SYMBOL(drm_property_destroy);
2002
2003int drm_connector_attach_property(struct drm_connector *connector,
2004 struct drm_property *property, uint64_t init_val)
2005{
2006 int i;
2007
2008 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
2009 if (connector->property_ids[i] == 0) {
2010 connector->property_ids[i] = property->base.id;
2011 connector->property_values[i] = init_val;
2012 break;
2013 }
2014 }
2015
2016 if (i == DRM_CONNECTOR_MAX_PROPERTY)
2017 return -EINVAL;
2018 return 0;
2019}
2020EXPORT_SYMBOL(drm_connector_attach_property);
2021
2022int drm_connector_property_set_value(struct drm_connector *connector,
2023 struct drm_property *property, uint64_t value)
2024{
2025 int i;
2026
2027 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
2028 if (connector->property_ids[i] == property->base.id) {
2029 connector->property_values[i] = value;
2030 break;
2031 }
2032 }
2033
2034 if (i == DRM_CONNECTOR_MAX_PROPERTY)
2035 return -EINVAL;
2036 return 0;
2037}
2038EXPORT_SYMBOL(drm_connector_property_set_value);
2039
2040int drm_connector_property_get_value(struct drm_connector *connector,
2041 struct drm_property *property, uint64_t *val)
2042{
2043 int i;
2044
2045 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
2046 if (connector->property_ids[i] == property->base.id) {
2047 *val = connector->property_values[i];
2048 break;
2049 }
2050 }
2051
2052 if (i == DRM_CONNECTOR_MAX_PROPERTY)
2053 return -EINVAL;
2054 return 0;
2055}
2056EXPORT_SYMBOL(drm_connector_property_get_value);
2057
2058int drm_mode_getproperty_ioctl(struct drm_device *dev,
2059 void *data, struct drm_file *file_priv)
2060{
2061 struct drm_mode_object *obj;
2062 struct drm_mode_get_property *out_resp = data;
2063 struct drm_property *property;
2064 int enum_count = 0;
2065 int blob_count = 0;
2066 int value_count = 0;
2067 int ret = 0, i;
2068 int copied;
2069 struct drm_property_enum *prop_enum;
2070 struct drm_mode_property_enum __user *enum_ptr;
2071 struct drm_property_blob *prop_blob;
2072 uint32_t *blob_id_ptr;
2073 uint64_t __user *values_ptr;
2074 uint32_t __user *blob_length_ptr;
2075
2076 mutex_lock(&dev->mode_config.mutex);
2077 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
2078 if (!obj) {
2079 ret = -EINVAL;
2080 goto done;
2081 }
2082 property = obj_to_property(obj);
2083
2084 if (property->flags & DRM_MODE_PROP_ENUM) {
2085 list_for_each_entry(prop_enum, &property->enum_blob_list, head)
2086 enum_count++;
2087 } else if (property->flags & DRM_MODE_PROP_BLOB) {
2088 list_for_each_entry(prop_blob, &property->enum_blob_list, head)
2089 blob_count++;
2090 }
2091
2092 value_count = property->num_values;
2093
2094 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
2095 out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
2096 out_resp->flags = property->flags;
2097
2098 if ((out_resp->count_values >= value_count) && value_count) {
2099 values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr;
2100 for (i = 0; i < value_count; i++) {
2101 if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
2102 ret = -EFAULT;
2103 goto done;
2104 }
2105 }
2106 }
2107 out_resp->count_values = value_count;
2108
2109 if (property->flags & DRM_MODE_PROP_ENUM) {
2110 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
2111 copied = 0;
2112 enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr;
2113 list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2114
2115 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
2116 ret = -EFAULT;
2117 goto done;
2118 }
2119
2120 if (copy_to_user(&enum_ptr[copied].name,
2121 &prop_enum->name, DRM_PROP_NAME_LEN)) {
2122 ret = -EFAULT;
2123 goto done;
2124 }
2125 copied++;
2126 }
2127 }
2128 out_resp->count_enum_blobs = enum_count;
2129 }
2130
2131 if (property->flags & DRM_MODE_PROP_BLOB) {
2132 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
2133 copied = 0;
2134 blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr;
2135 blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr;
2136
2137 list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
2138 if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
2139 ret = -EFAULT;
2140 goto done;
2141 }
2142
2143 if (put_user(prop_blob->length, blob_length_ptr + copied)) {
2144 ret = -EFAULT;
2145 goto done;
2146 }
2147
2148 copied++;
2149 }
2150 }
2151 out_resp->count_enum_blobs = blob_count;
2152 }
2153done:
2154 mutex_unlock(&dev->mode_config.mutex);
2155 return ret;
2156}
2157
2158static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
2159 void *data)
2160{
2161 struct drm_property_blob *blob;
2162
2163 if (!length || !data)
2164 return NULL;
2165
2166 blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
2167 if (!blob)
2168 return NULL;
2169
2170 blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob));
2171 blob->length = length;
2172
2173 memcpy(blob->data, data, length);
2174
2175 drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
2176
2177 list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
2178 return blob;
2179}
2180
2181static void drm_property_destroy_blob(struct drm_device *dev,
2182 struct drm_property_blob *blob)
2183{
2184 drm_mode_object_put(dev, &blob->base);
2185 list_del(&blob->head);
2186 kfree(blob);
2187}
2188
2189int drm_mode_getblob_ioctl(struct drm_device *dev,
2190 void *data, struct drm_file *file_priv)
2191{
2192 struct drm_mode_object *obj;
2193 struct drm_mode_get_blob *out_resp = data;
2194 struct drm_property_blob *blob;
2195 int ret = 0;
2196 void *blob_ptr;
2197
2198 mutex_lock(&dev->mode_config.mutex);
2199 obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
2200 if (!obj) {
2201 ret = -EINVAL;
2202 goto done;
2203 }
2204 blob = obj_to_blob(obj);
2205
2206 if (out_resp->length == blob->length) {
2207 blob_ptr = (void *)(unsigned long)out_resp->data;
2208 if (copy_to_user(blob_ptr, blob->data, blob->length)){
2209 ret = -EFAULT;
2210 goto done;
2211 }
2212 }
2213 out_resp->length = blob->length;
2214
2215done:
2216 mutex_unlock(&dev->mode_config.mutex);
2217 return ret;
2218}
2219
2220int drm_mode_connector_update_edid_property(struct drm_connector *connector,
2221 struct edid *edid)
2222{
2223 struct drm_device *dev = connector->dev;
2224 int ret = 0;
2225
2226 if (connector->edid_blob_ptr)
2227 drm_property_destroy_blob(dev, connector->edid_blob_ptr);
2228
2229 /* Delete edid, when there is none. */
2230 if (!edid) {
2231 connector->edid_blob_ptr = NULL;
2232 ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0);
2233 return ret;
2234 }
2235
2236 connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid);
2237
2238 ret = drm_connector_property_set_value(connector,
2239 dev->mode_config.edid_property,
2240 connector->edid_blob_ptr->base.id);
2241
2242 return ret;
2243}
2244EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
2245
2246int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
2247 void *data, struct drm_file *file_priv)
2248{
2249 struct drm_mode_connector_set_property *out_resp = data;
2250 struct drm_mode_object *obj;
2251 struct drm_property *property;
2252 struct drm_connector *connector;
2253 int ret = -EINVAL;
2254 int i;
2255
2256 mutex_lock(&dev->mode_config.mutex);
2257
2258 obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2259 if (!obj) {
2260 goto out;
2261 }
2262 connector = obj_to_connector(obj);
2263
2264 for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
2265 if (connector->property_ids[i] == out_resp->prop_id)
2266 break;
2267 }
2268
2269 if (i == DRM_CONNECTOR_MAX_PROPERTY) {
2270 goto out;
2271 }
2272
2273 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
2274 if (!obj) {
2275 goto out;
2276 }
2277 property = obj_to_property(obj);
2278
2279 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
2280 goto out;
2281
2282 if (property->flags & DRM_MODE_PROP_RANGE) {
2283 if (out_resp->value < property->values[0])
2284 goto out;
2285
2286 if (out_resp->value > property->values[1])
2287 goto out;
2288 } else {
2289 int found = 0;
2290 for (i = 0; i < property->num_values; i++) {
2291 if (property->values[i] == out_resp->value) {
2292 found = 1;
2293 break;
2294 }
2295 }
2296 if (!found) {
2297 goto out;
2298 }
2299 }
2300
Keith Packardc9fb15f2009-05-30 20:42:28 -07002301 /* Do DPMS ourselves */
2302 if (property == connector->dev->mode_config.dpms_property) {
2303 if (connector->funcs->dpms)
2304 (*connector->funcs->dpms)(connector, (int) out_resp->value);
2305 ret = 0;
2306 } else if (connector->funcs->set_property)
Dave Airlief453ba02008-11-07 14:05:41 -08002307 ret = connector->funcs->set_property(connector, property, out_resp->value);
2308
2309 /* store the property value if succesful */
2310 if (!ret)
2311 drm_connector_property_set_value(connector, property, out_resp->value);
2312out:
2313 mutex_unlock(&dev->mode_config.mutex);
2314 return ret;
2315}
2316
Dave Airlief453ba02008-11-07 14:05:41 -08002317int drm_mode_connector_attach_encoder(struct drm_connector *connector,
2318 struct drm_encoder *encoder)
2319{
2320 int i;
2321
2322 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
2323 if (connector->encoder_ids[i] == 0) {
2324 connector->encoder_ids[i] = encoder->base.id;
2325 return 0;
2326 }
2327 }
2328 return -ENOMEM;
2329}
2330EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
2331
2332void drm_mode_connector_detach_encoder(struct drm_connector *connector,
2333 struct drm_encoder *encoder)
2334{
2335 int i;
2336 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
2337 if (connector->encoder_ids[i] == encoder->base.id) {
2338 connector->encoder_ids[i] = 0;
2339 if (connector->encoder == encoder)
2340 connector->encoder = NULL;
2341 break;
2342 }
2343 }
2344}
2345EXPORT_SYMBOL(drm_mode_connector_detach_encoder);
2346
2347bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
2348 int gamma_size)
2349{
2350 crtc->gamma_size = gamma_size;
2351
2352 crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL);
2353 if (!crtc->gamma_store) {
2354 crtc->gamma_size = 0;
2355 return false;
2356 }
2357
2358 return true;
2359}
2360EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
2361
2362int drm_mode_gamma_set_ioctl(struct drm_device *dev,
2363 void *data, struct drm_file *file_priv)
2364{
2365 struct drm_mode_crtc_lut *crtc_lut = data;
2366 struct drm_mode_object *obj;
2367 struct drm_crtc *crtc;
2368 void *r_base, *g_base, *b_base;
2369 int size;
2370 int ret = 0;
2371
2372 mutex_lock(&dev->mode_config.mutex);
2373 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
2374 if (!obj) {
2375 ret = -EINVAL;
2376 goto out;
2377 }
2378 crtc = obj_to_crtc(obj);
2379
2380 /* memcpy into gamma store */
2381 if (crtc_lut->gamma_size != crtc->gamma_size) {
2382 ret = -EINVAL;
2383 goto out;
2384 }
2385
2386 size = crtc_lut->gamma_size * (sizeof(uint16_t));
2387 r_base = crtc->gamma_store;
2388 if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
2389 ret = -EFAULT;
2390 goto out;
2391 }
2392
2393 g_base = r_base + size;
2394 if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
2395 ret = -EFAULT;
2396 goto out;
2397 }
2398
2399 b_base = g_base + size;
2400 if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
2401 ret = -EFAULT;
2402 goto out;
2403 }
2404
2405 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size);
2406
2407out:
2408 mutex_unlock(&dev->mode_config.mutex);
2409 return ret;
2410
2411}
2412
2413int drm_mode_gamma_get_ioctl(struct drm_device *dev,
2414 void *data, struct drm_file *file_priv)
2415{
2416 struct drm_mode_crtc_lut *crtc_lut = data;
2417 struct drm_mode_object *obj;
2418 struct drm_crtc *crtc;
2419 void *r_base, *g_base, *b_base;
2420 int size;
2421 int ret = 0;
2422
2423 mutex_lock(&dev->mode_config.mutex);
2424 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
2425 if (!obj) {
2426 ret = -EINVAL;
2427 goto out;
2428 }
2429 crtc = obj_to_crtc(obj);
2430
2431 /* memcpy into gamma store */
2432 if (crtc_lut->gamma_size != crtc->gamma_size) {
2433 ret = -EINVAL;
2434 goto out;
2435 }
2436
2437 size = crtc_lut->gamma_size * (sizeof(uint16_t));
2438 r_base = crtc->gamma_store;
2439 if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
2440 ret = -EFAULT;
2441 goto out;
2442 }
2443
2444 g_base = r_base + size;
2445 if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
2446 ret = -EFAULT;
2447 goto out;
2448 }
2449
2450 b_base = g_base + size;
2451 if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
2452 ret = -EFAULT;
2453 goto out;
2454 }
2455out:
2456 mutex_unlock(&dev->mode_config.mutex);
2457 return ret;
2458}