Rev 2160 | Rev 3192 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2160 | Rev 3031 | ||
---|---|---|---|
Line 29... | Line 29... | ||
29 | * Dave Airlie |
29 | * Dave Airlie |
30 | * Jesse Barnes |
30 | * Jesse Barnes |
31 | */ |
31 | */ |
32 | #include |
32 | #include |
33 | #include |
33 | #include |
34 | #include "drm.h" |
34 | #include |
35 | #include "drmP.h" |
35 | #include |
36 | #include "drm_crtc.h" |
36 | #include |
37 | #include "drm_edid.h" |
37 | #include |
38 | - | ||
39 | struct drm_prop_enum_list { |
38 | #include |
40 | int type; |
- | |
41 | char *name; |
- | |
42 | }; |
- | |
Line 43... | Line 39... | ||
43 | 39 | ||
44 | /* Avoid boilerplate. I'm tired of typing. */ |
40 | /* Avoid boilerplate. I'm tired of typing. */ |
45 | #define DRM_ENUM_NAME_FN(fnname, list) \ |
41 | #define DRM_ENUM_NAME_FN(fnname, list) \ |
46 | char *fnname(int val) \ |
42 | char *fnname(int val) \ |
Line 160... | Line 156... | ||
160 | { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 }, |
156 | { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 }, |
161 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 }, |
157 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 }, |
162 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 }, |
158 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 }, |
163 | { DRM_MODE_CONNECTOR_TV, "TV", 0 }, |
159 | { DRM_MODE_CONNECTOR_TV, "TV", 0 }, |
164 | { DRM_MODE_CONNECTOR_eDP, "eDP", 0 }, |
160 | { DRM_MODE_CONNECTOR_eDP, "eDP", 0 }, |
- | 161 | { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0}, |
|
165 | }; |
162 | }; |
Line 166... | Line 163... | ||
166 | 163 | ||
167 | static struct drm_prop_enum_list drm_encoder_enum_list[] = |
164 | static struct drm_prop_enum_list drm_encoder_enum_list[] = |
168 | { { DRM_MODE_ENCODER_NONE, "None" }, |
165 | { { DRM_MODE_ENCODER_NONE, "None" }, |
169 | { DRM_MODE_ENCODER_DAC, "DAC" }, |
166 | { DRM_MODE_ENCODER_DAC, "DAC" }, |
170 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, |
167 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, |
171 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, |
168 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, |
- | 169 | { DRM_MODE_ENCODER_TVDAC, "TV" }, |
|
172 | { DRM_MODE_ENCODER_TVDAC, "TV" }, |
170 | { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, |
Line 173... | Line 171... | ||
173 | }; |
171 | }; |
174 | 172 | ||
175 | char *drm_get_encoder_name(struct drm_encoder *encoder) |
173 | char *drm_get_encoder_name(struct drm_encoder *encoder) |
Line 226... | Line 224... | ||
226 | int ret; |
224 | int ret; |
Line 227... | Line 225... | ||
227 | 225 | ||
228 | again: |
226 | again: |
229 | if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { |
227 | if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) { |
230 | DRM_ERROR("Ran out memory getting a mode number\n"); |
228 | DRM_ERROR("Ran out memory getting a mode number\n"); |
231 | return -EINVAL; |
229 | return -ENOMEM; |
Line 232... | Line 230... | ||
232 | } |
230 | } |
233 | 231 | ||
234 | mutex_lock(&dev->mode_config.idr_mutex); |
232 | mutex_lock(&dev->mode_config.idr_mutex); |
235 | ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); |
233 | ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); |
236 | mutex_unlock(&dev->mode_config.idr_mutex); |
234 | mutex_unlock(&dev->mode_config.idr_mutex); |
- | 235 | if (ret == -EAGAIN) |
|
- | 236 | goto again; |
|
Line 237... | Line 237... | ||
237 | if (ret == -EAGAIN) |
237 | else if (ret) |
238 | goto again; |
238 | return ret; |
239 | 239 | ||
240 | obj->id = new_id; |
240 | obj->id = new_id; |
Line 292... | Line 292... | ||
292 | const struct drm_framebuffer_funcs *funcs) |
292 | const struct drm_framebuffer_funcs *funcs) |
293 | { |
293 | { |
294 | int ret; |
294 | int ret; |
Line 295... | Line 295... | ||
295 | 295 | ||
296 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); |
296 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); |
297 | if (ret) { |
297 | if (ret) |
298 | return ret; |
- | |
Line 299... | Line 298... | ||
299 | } |
298 | return ret; |
300 | 299 | ||
301 | fb->dev = dev; |
300 | fb->dev = dev; |
302 | fb->funcs = funcs; |
301 | fb->funcs = funcs; |
Line 318... | Line 317... | ||
318 | * it, setting it to NULL. |
317 | * it, setting it to NULL. |
319 | */ |
318 | */ |
320 | void drm_framebuffer_cleanup(struct drm_framebuffer *fb) |
319 | void drm_framebuffer_cleanup(struct drm_framebuffer *fb) |
321 | { |
320 | { |
322 | struct drm_device *dev = fb->dev; |
321 | struct drm_device *dev = fb->dev; |
323 | struct drm_crtc *crtc; |
- | |
324 | struct drm_mode_set set; |
- | |
325 | int ret; |
- | |
326 | 322 | /* |
|
327 | /* remove from any CRTC */ |
- | |
328 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
323 | * This could be moved to drm_framebuffer_remove(), but for |
329 | if (crtc->fb == fb) { |
- | |
330 | /* should turn off the crtc */ |
324 | * debugging is nice to keep around the list of fb's that are |
331 | memset(&set, 0, sizeof(struct drm_mode_set)); |
325 | * no longer associated w/ a drm_file but are not unreferenced |
332 | set.crtc = crtc; |
- | |
333 | set.fb = NULL; |
- | |
334 | ret = crtc->funcs->set_config(&set); |
326 | * yet. (i915 and omapdrm have debugfs files which will show |
335 | if (ret) |
327 | * this.) |
336 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); |
- | |
337 | } |
328 | */ |
338 | } |
- | |
339 | - | ||
340 | drm_mode_object_put(dev, &fb->base); |
329 | drm_mode_object_put(dev, &fb->base); |
341 | list_del(&fb->head); |
330 | list_del(&fb->head); |
342 | dev->mode_config.num_fb--; |
331 | dev->mode_config.num_fb--; |
343 | } |
332 | } |
344 | EXPORT_SYMBOL(drm_framebuffer_cleanup); |
333 | EXPORT_SYMBOL(drm_framebuffer_cleanup); |
Line -... | Line 334... | ||
- | 334 | ||
- | 335 | ||
- | 336 | ||
- | 337 | ||
345 | 338 | ||
346 | /** |
339 | /** |
347 | * drm_crtc_init - Initialise a new CRTC object |
340 | * drm_crtc_init - Initialise a new CRTC object |
348 | * @dev: DRM device |
341 | * @dev: DRM device |
349 | * @crtc: CRTC object to init |
342 | * @crtc: CRTC object to init |
350 | * @funcs: callbacks for the new CRTC |
343 | * @funcs: callbacks for the new CRTC |
351 | * |
344 | * |
352 | * LOCKING: |
345 | * LOCKING: |
353 | * Caller must hold mode config lock. |
346 | * Takes mode_config lock. |
354 | * |
347 | * |
- | 348 | * Inits a new object created as base part of an driver crtc object. |
|
- | 349 | * |
|
- | 350 | * RETURNS: |
|
355 | * Inits a new object created as base part of an driver crtc object. |
351 | * Zero on success, error code on failure. |
356 | */ |
352 | */ |
357 | void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, |
353 | int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, |
358 | const struct drm_crtc_funcs *funcs) |
354 | const struct drm_crtc_funcs *funcs) |
- | 355 | { |
|
- | 356 | int ret; |
|
359 | { |
357 | |
360 | crtc->dev = dev; |
358 | crtc->dev = dev; |
- | 359 | crtc->funcs = funcs; |
|
Line 361... | Line 360... | ||
361 | crtc->funcs = funcs; |
360 | crtc->invert_dimensions = false; |
- | 361 | ||
362 | 362 | mutex_lock(&dev->mode_config.mutex); |
|
- | 363 | ||
- | 364 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
|
- | 365 | if (ret) |
|
- | 366 | goto out; |
|
Line 363... | Line 367... | ||
363 | mutex_lock(&dev->mode_config.mutex); |
367 | |
364 | drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
368 | crtc->base.properties = &crtc->properties; |
- | 369 | ||
- | 370 | list_add_tail(&crtc->head, &dev->mode_config.crtc_list); |
|
365 | 371 | dev->mode_config.num_crtc++; |
|
- | 372 | ||
- | 373 | out: |
|
366 | list_add_tail(&crtc->head, &dev->mode_config.crtc_list); |
374 | mutex_unlock(&dev->mode_config.mutex); |
367 | dev->mode_config.num_crtc++; |
375 | |
Line 368... | Line 376... | ||
368 | mutex_unlock(&dev->mode_config.mutex); |
376 | return ret; |
369 | } |
377 | } |
Line 423... | Line 431... | ||
423 | */ |
431 | */ |
424 | void drm_mode_remove(struct drm_connector *connector, |
432 | void drm_mode_remove(struct drm_connector *connector, |
425 | struct drm_display_mode *mode) |
433 | struct drm_display_mode *mode) |
426 | { |
434 | { |
427 | list_del(&mode->head); |
435 | list_del(&mode->head); |
428 | kfree(mode); |
436 | drm_mode_destroy(connector->dev, mode); |
429 | } |
437 | } |
430 | EXPORT_SYMBOL(drm_mode_remove); |
438 | EXPORT_SYMBOL(drm_mode_remove); |
Line 431... | Line 439... | ||
431 | 439 | ||
432 | /** |
440 | /** |
Line 435... | Line 443... | ||
435 | * @connector: the connector to init |
443 | * @connector: the connector to init |
436 | * @funcs: callbacks for this connector |
444 | * @funcs: callbacks for this connector |
437 | * @name: user visible name of the connector |
445 | * @name: user visible name of the connector |
438 | * |
446 | * |
439 | * LOCKING: |
447 | * LOCKING: |
440 | * Caller must hold @dev's mode_config lock. |
448 | * Takes mode config lock. |
441 | * |
449 | * |
442 | * Initialises a preallocated connector. Connectors should be |
450 | * Initialises a preallocated connector. Connectors should be |
443 | * subclassed as part of driver connector objects. |
451 | * subclassed as part of driver connector objects. |
- | 452 | * |
|
- | 453 | * RETURNS: |
|
- | 454 | * Zero on success, error code on failure. |
|
444 | */ |
455 | */ |
445 | void drm_connector_init(struct drm_device *dev, |
456 | int drm_connector_init(struct drm_device *dev, |
446 | struct drm_connector *connector, |
457 | struct drm_connector *connector, |
447 | const struct drm_connector_funcs *funcs, |
458 | const struct drm_connector_funcs *funcs, |
448 | int connector_type) |
459 | int connector_type) |
449 | { |
460 | { |
- | 461 | int ret; |
|
- | 462 | ||
450 | mutex_lock(&dev->mode_config.mutex); |
463 | mutex_lock(&dev->mode_config.mutex); |
Line -... | Line 464... | ||
- | 464 | ||
- | 465 | ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); |
|
- | 466 | if (ret) |
|
- | 467 | goto out; |
|
- | 468 | ||
451 | 469 | connector->base.properties = &connector->properties; |
|
452 | connector->dev = dev; |
470 | connector->dev = dev; |
453 | connector->funcs = funcs; |
- | |
454 | drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); |
471 | connector->funcs = funcs; |
455 | connector->connector_type = connector_type; |
472 | connector->connector_type = connector_type; |
456 | connector->connector_type_id = |
473 | connector->connector_type_id = |
457 | ++drm_connector_enum_list[connector_type].count; /* TODO */ |
474 | ++drm_connector_enum_list[connector_type].count; /* TODO */ |
458 | INIT_LIST_HEAD(&connector->user_modes); |
475 | INIT_LIST_HEAD(&connector->user_modes); |
Line 461... | Line 478... | ||
461 | connector->edid_blob_ptr = NULL; |
478 | connector->edid_blob_ptr = NULL; |
Line 462... | Line 479... | ||
462 | 479 | ||
463 | list_add_tail(&connector->head, &dev->mode_config.connector_list); |
480 | list_add_tail(&connector->head, &dev->mode_config.connector_list); |
Line -... | Line 481... | ||
- | 481 | dev->mode_config.num_connector++; |
|
464 | dev->mode_config.num_connector++; |
482 | |
465 | 483 | if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) |
|
- | 484 | drm_connector_attach_property(connector, |
|
Line 466... | Line 485... | ||
466 | drm_connector_attach_property(connector, |
485 | dev->mode_config.edid_property, |
467 | dev->mode_config.edid_property, 0); |
486 | 0); |
Line -... | Line 487... | ||
- | 487 | ||
468 | 488 | drm_connector_attach_property(connector, |
|
- | 489 | dev->mode_config.dpms_property, 0); |
|
- | 490 | ||
469 | drm_connector_attach_property(connector, |
491 | out: |
470 | dev->mode_config.dpms_property, 0); |
492 | mutex_unlock(&dev->mode_config.mutex); |
Line 471... | Line 493... | ||
471 | 493 | ||
472 | mutex_unlock(&dev->mode_config.mutex); |
494 | return ret; |
473 | } |
495 | } |
474 | EXPORT_SYMBOL(drm_connector_init); |
496 | EXPORT_SYMBOL(drm_connector_init); |
475 | 497 | ||
476 | /** |
498 | /** |
477 | * drm_connector_cleanup - cleans up an initialised connector |
499 | * drm_connector_cleanup - cleans up an initialised connector |
478 | * @connector: connector to cleanup |
500 | * @connector: connector to cleanup |
479 | * |
501 | * |
480 | * LOCKING: |
502 | * LOCKING: |
481 | * Caller must hold @dev's mode_config lock. |
503 | * Takes mode config lock. |
Line 502... | Line 524... | ||
502 | dev->mode_config.num_connector--; |
524 | dev->mode_config.num_connector--; |
503 | mutex_unlock(&dev->mode_config.mutex); |
525 | mutex_unlock(&dev->mode_config.mutex); |
504 | } |
526 | } |
505 | EXPORT_SYMBOL(drm_connector_cleanup); |
527 | EXPORT_SYMBOL(drm_connector_cleanup); |
Line -... | Line 528... | ||
- | 528 | ||
- | 529 | void drm_connector_unplug_all(struct drm_device *dev) |
|
- | 530 | { |
|
- | 531 | struct drm_connector *connector; |
|
- | 532 | ||
- | 533 | /* taking the mode config mutex ends up in a clash with sysfs */ |
|
- | 534 | // list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
|
- | 535 | // drm_sysfs_connector_remove(connector); |
|
- | 536 | ||
- | 537 | } |
|
- | 538 | EXPORT_SYMBOL(drm_connector_unplug_all); |
|
506 | 539 | ||
507 | void drm_encoder_init(struct drm_device *dev, |
540 | int drm_encoder_init(struct drm_device *dev, |
508 | struct drm_encoder *encoder, |
541 | struct drm_encoder *encoder, |
509 | const struct drm_encoder_funcs *funcs, |
542 | const struct drm_encoder_funcs *funcs, |
510 | int encoder_type) |
543 | int encoder_type) |
- | 544 | { |
|
- | 545 | int ret; |
|
511 | { |
546 | |
Line -... | Line 547... | ||
- | 547 | mutex_lock(&dev->mode_config.mutex); |
|
- | 548 | ||
512 | mutex_lock(&dev->mode_config.mutex); |
549 | ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); |
Line 513... | Line 550... | ||
513 | 550 | if (ret) |
|
514 | encoder->dev = dev; |
551 | goto out; |
515 | 552 | ||
Line 516... | Line 553... | ||
516 | drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); |
553 | encoder->dev = dev; |
517 | encoder->encoder_type = encoder_type; |
554 | encoder->encoder_type = encoder_type; |
Line -... | Line 555... | ||
- | 555 | encoder->funcs = funcs; |
|
518 | encoder->funcs = funcs; |
556 | |
- | 557 | list_add_tail(&encoder->head, &dev->mode_config.encoder_list); |
|
- | 558 | dev->mode_config.num_encoder++; |
|
519 | 559 | ||
520 | list_add_tail(&encoder->head, &dev->mode_config.encoder_list); |
560 | out: |
Line 521... | Line 561... | ||
521 | dev->mode_config.num_encoder++; |
561 | mutex_unlock(&dev->mode_config.mutex); |
522 | 562 | ||
Line 533... | Line 573... | ||
533 | dev->mode_config.num_encoder--; |
573 | dev->mode_config.num_encoder--; |
534 | mutex_unlock(&dev->mode_config.mutex); |
574 | mutex_unlock(&dev->mode_config.mutex); |
535 | } |
575 | } |
536 | EXPORT_SYMBOL(drm_encoder_cleanup); |
576 | EXPORT_SYMBOL(drm_encoder_cleanup); |
Line -... | Line 577... | ||
- | 577 | ||
- | 578 | int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, |
|
- | 579 | unsigned long possible_crtcs, |
|
- | 580 | const struct drm_plane_funcs *funcs, |
|
- | 581 | const uint32_t *formats, uint32_t format_count, |
|
- | 582 | bool priv) |
|
- | 583 | { |
|
- | 584 | int ret; |
|
- | 585 | ||
- | 586 | mutex_lock(&dev->mode_config.mutex); |
|
- | 587 | ||
- | 588 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
|
- | 589 | if (ret) |
|
- | 590 | goto out; |
|
- | 591 | ||
- | 592 | plane->base.properties = &plane->properties; |
|
- | 593 | plane->dev = dev; |
|
- | 594 | plane->funcs = funcs; |
|
- | 595 | plane->format_types = kmalloc(sizeof(uint32_t) * format_count, |
|
- | 596 | GFP_KERNEL); |
|
- | 597 | if (!plane->format_types) { |
|
- | 598 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); |
|
- | 599 | drm_mode_object_put(dev, &plane->base); |
|
- | 600 | ret = -ENOMEM; |
|
- | 601 | goto out; |
|
- | 602 | } |
|
- | 603 | ||
- | 604 | memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); |
|
- | 605 | plane->format_count = format_count; |
|
- | 606 | plane->possible_crtcs = possible_crtcs; |
|
- | 607 | ||
- | 608 | /* private planes are not exposed to userspace, but depending on |
|
- | 609 | * display hardware, might be convenient to allow sharing programming |
|
- | 610 | * for the scanout engine with the crtc implementation. |
|
- | 611 | */ |
|
- | 612 | if (!priv) { |
|
- | 613 | list_add_tail(&plane->head, &dev->mode_config.plane_list); |
|
- | 614 | dev->mode_config.num_plane++; |
|
- | 615 | } else { |
|
- | 616 | INIT_LIST_HEAD(&plane->head); |
|
- | 617 | } |
|
- | 618 | ||
- | 619 | out: |
|
- | 620 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 621 | ||
- | 622 | return ret; |
|
- | 623 | } |
|
- | 624 | EXPORT_SYMBOL(drm_plane_init); |
|
- | 625 | ||
- | 626 | void drm_plane_cleanup(struct drm_plane *plane) |
|
- | 627 | { |
|
- | 628 | struct drm_device *dev = plane->dev; |
|
- | 629 | ||
- | 630 | mutex_lock(&dev->mode_config.mutex); |
|
- | 631 | kfree(plane->format_types); |
|
- | 632 | drm_mode_object_put(dev, &plane->base); |
|
- | 633 | /* if not added to a list, it must be a private plane */ |
|
- | 634 | if (!list_empty(&plane->head)) { |
|
- | 635 | list_del(&plane->head); |
|
- | 636 | dev->mode_config.num_plane--; |
|
- | 637 | } |
|
- | 638 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 639 | } |
|
- | 640 | EXPORT_SYMBOL(drm_plane_cleanup); |
|
537 | 641 | ||
538 | /** |
642 | /** |
539 | * drm_mode_create - create a new display mode |
643 | * drm_mode_create - create a new display mode |
540 | * @dev: DRM device |
644 | * @dev: DRM device |
541 | * |
645 | * |
Line 553... | Line 657... | ||
553 | 657 | ||
554 | nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); |
658 | nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); |
555 | if (!nmode) |
659 | if (!nmode) |
Line 556... | Line 660... | ||
556 | return NULL; |
660 | return NULL; |
- | 661 | ||
- | 662 | if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) { |
|
- | 663 | kfree(nmode); |
|
- | 664 | return NULL; |
|
557 | 665 | } |
|
558 | drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE); |
666 | |
559 | return nmode; |
667 | return nmode; |
Line 560... | Line 668... | ||
560 | } |
668 | } |
Line 570... | Line 678... | ||
570 | * |
678 | * |
571 | * Free @mode's unique identifier, then free it. |
679 | * Free @mode's unique identifier, then free it. |
572 | */ |
680 | */ |
573 | void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) |
681 | void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) |
574 | { |
682 | { |
- | 683 | if (!mode) |
|
- | 684 | return; |
|
- | 685 | ||
575 | drm_mode_object_put(dev, &mode->base); |
686 | drm_mode_object_put(dev, &mode->base); |
Line 576... | Line 687... | ||
576 | 687 | ||
577 | kfree(mode); |
688 | kfree(mode); |
578 | } |
689 | } |
Line 579... | Line 690... | ||
579 | EXPORT_SYMBOL(drm_mode_destroy); |
690 | EXPORT_SYMBOL(drm_mode_destroy); |
580 | 691 | ||
581 | static int drm_mode_create_standard_connector_properties(struct drm_device *dev) |
692 | static int drm_mode_create_standard_connector_properties(struct drm_device *dev) |
582 | { |
693 | { |
583 | struct drm_property *edid; |
- | |
Line 584... | Line 694... | ||
584 | struct drm_property *dpms; |
694 | struct drm_property *edid; |
585 | int i; |
695 | struct drm_property *dpms; |
586 | 696 | ||
587 | /* |
697 | /* |
588 | * Standard properties (apply to all connectors) |
698 | * Standard properties (apply to all connectors) |
589 | */ |
699 | */ |
590 | edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | |
700 | edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | |
Line 591... | Line 701... | ||
591 | DRM_MODE_PROP_IMMUTABLE, |
701 | DRM_MODE_PROP_IMMUTABLE, |
592 | "EDID", 0); |
702 | "EDID", 0); |
593 | dev->mode_config.edid_property = edid; |
703 | dev->mode_config.edid_property = edid; |
594 | - | ||
595 | dpms = drm_property_create(dev, DRM_MODE_PROP_ENUM, |
- | |
596 | "DPMS", ARRAY_SIZE(drm_dpms_enum_list)); |
704 | |
Line 597... | Line 705... | ||
597 | for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) |
705 | dpms = drm_property_create_enum(dev, 0, |
598 | drm_property_add_enum(dpms, i, drm_dpms_enum_list[i].type, |
706 | "DPMS", drm_dpms_enum_list, |
Line 610... | Line 718... | ||
610 | */ |
718 | */ |
611 | int drm_mode_create_dvi_i_properties(struct drm_device *dev) |
719 | int drm_mode_create_dvi_i_properties(struct drm_device *dev) |
612 | { |
720 | { |
613 | struct drm_property *dvi_i_selector; |
721 | struct drm_property *dvi_i_selector; |
614 | struct drm_property *dvi_i_subconnector; |
722 | struct drm_property *dvi_i_subconnector; |
615 | int i; |
- | |
Line 616... | Line 723... | ||
616 | 723 | ||
617 | if (dev->mode_config.dvi_i_select_subconnector_property) |
724 | if (dev->mode_config.dvi_i_select_subconnector_property) |
Line 618... | Line 725... | ||
618 | return 0; |
725 | return 0; |
619 | 726 | ||
620 | dvi_i_selector = |
727 | dvi_i_selector = |
- | 728 | drm_property_create_enum(dev, 0, |
|
621 | drm_property_create(dev, DRM_MODE_PROP_ENUM, |
729 | "select subconnector", |
622 | "select subconnector", |
- | |
623 | ARRAY_SIZE(drm_dvi_i_select_enum_list)); |
- | |
624 | for (i = 0; i < ARRAY_SIZE(drm_dvi_i_select_enum_list); i++) |
- | |
625 | drm_property_add_enum(dvi_i_selector, i, |
- | |
626 | drm_dvi_i_select_enum_list[i].type, |
730 | drm_dvi_i_select_enum_list, |
Line 627... | Line -... | ||
627 | drm_dvi_i_select_enum_list[i].name); |
- | |
628 | dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; |
731 | ARRAY_SIZE(drm_dvi_i_select_enum_list)); |
629 | - | ||
630 | dvi_i_subconnector = |
732 | dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; |
- | 733 | ||
631 | drm_property_create(dev, DRM_MODE_PROP_ENUM | |
734 | dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
632 | DRM_MODE_PROP_IMMUTABLE, |
- | |
633 | "subconnector", |
- | |
634 | ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); |
- | |
635 | for (i = 0; i < ARRAY_SIZE(drm_dvi_i_subconnector_enum_list); i++) |
- | |
636 | drm_property_add_enum(dvi_i_subconnector, i, |
735 | "subconnector", |
Line 637... | Line 736... | ||
637 | drm_dvi_i_subconnector_enum_list[i].type, |
736 | drm_dvi_i_subconnector_enum_list, |
638 | drm_dvi_i_subconnector_enum_list[i].name); |
737 | ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); |
639 | dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; |
738 | dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; |
Line 664... | Line 763... | ||
664 | return 0; |
763 | return 0; |
Line 665... | Line 764... | ||
665 | 764 | ||
666 | /* |
765 | /* |
667 | * Basic connector properties |
766 | * Basic connector properties |
668 | */ |
767 | */ |
669 | tv_selector = drm_property_create(dev, DRM_MODE_PROP_ENUM, |
768 | tv_selector = drm_property_create_enum(dev, 0, |
- | 769 | "select subconnector", |
|
670 | "select subconnector", |
770 | drm_tv_select_enum_list, |
671 | ARRAY_SIZE(drm_tv_select_enum_list)); |
- | |
672 | for (i = 0; i < ARRAY_SIZE(drm_tv_select_enum_list); i++) |
- | |
673 | drm_property_add_enum(tv_selector, i, |
- | |
674 | drm_tv_select_enum_list[i].type, |
- | |
675 | drm_tv_select_enum_list[i].name); |
771 | ARRAY_SIZE(drm_tv_select_enum_list)); |
Line 676... | Line 772... | ||
676 | dev->mode_config.tv_select_subconnector_property = tv_selector; |
772 | dev->mode_config.tv_select_subconnector_property = tv_selector; |
677 | 773 | ||
678 | tv_subconnector = |
774 | tv_subconnector = |
- | 775 | drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
|
679 | drm_property_create(dev, DRM_MODE_PROP_ENUM | |
776 | "subconnector", |
680 | DRM_MODE_PROP_IMMUTABLE, "subconnector", |
- | |
681 | ARRAY_SIZE(drm_tv_subconnector_enum_list)); |
- | |
682 | for (i = 0; i < ARRAY_SIZE(drm_tv_subconnector_enum_list); i++) |
- | |
683 | drm_property_add_enum(tv_subconnector, i, |
- | |
684 | drm_tv_subconnector_enum_list[i].type, |
777 | drm_tv_subconnector_enum_list, |
Line 685... | Line 778... | ||
685 | drm_tv_subconnector_enum_list[i].name); |
778 | ARRAY_SIZE(drm_tv_subconnector_enum_list)); |
686 | dev->mode_config.tv_subconnector_property = tv_subconnector; |
779 | dev->mode_config.tv_subconnector_property = tv_subconnector; |
687 | 780 | ||
688 | /* |
781 | /* |
689 | * Other, TV specific properties: margins & TV modes. |
782 | * Other, TV specific properties: margins & TV modes. |
690 | */ |
- | |
691 | dev->mode_config.tv_left_margin_property = |
- | |
692 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
- | |
Line 693... | Line 783... | ||
693 | "left margin", 2); |
783 | */ |
694 | dev->mode_config.tv_left_margin_property->values[0] = 0; |
784 | dev->mode_config.tv_left_margin_property = |
695 | dev->mode_config.tv_left_margin_property->values[1] = 100; |
- | |
696 | - | ||
697 | dev->mode_config.tv_right_margin_property = |
- | |
Line 698... | Line 785... | ||
698 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
785 | drm_property_create_range(dev, 0, "left margin", 0, 100); |
699 | "right margin", 2); |
786 | |
700 | dev->mode_config.tv_right_margin_property->values[0] = 0; |
- | |
701 | dev->mode_config.tv_right_margin_property->values[1] = 100; |
- | |
702 | - | ||
Line 703... | Line 787... | ||
703 | dev->mode_config.tv_top_margin_property = |
787 | dev->mode_config.tv_right_margin_property = |
704 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
788 | drm_property_create_range(dev, 0, "right margin", 0, 100); |
705 | "top margin", 2); |
- | |
706 | dev->mode_config.tv_top_margin_property->values[0] = 0; |
- | |
707 | dev->mode_config.tv_top_margin_property->values[1] = 100; |
- | |
Line 708... | Line 789... | ||
708 | 789 | ||
709 | dev->mode_config.tv_bottom_margin_property = |
790 | dev->mode_config.tv_top_margin_property = |
710 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
791 | drm_property_create_range(dev, 0, "top margin", 0, 100); |
711 | "bottom margin", 2); |
792 | |
712 | dev->mode_config.tv_bottom_margin_property->values[0] = 0; |
793 | dev->mode_config.tv_bottom_margin_property = |
713 | dev->mode_config.tv_bottom_margin_property->values[1] = 100; |
794 | drm_property_create_range(dev, 0, "bottom margin", 0, 100); |
Line 714... | Line 795... | ||
714 | 795 | ||
715 | dev->mode_config.tv_mode_property = |
796 | dev->mode_config.tv_mode_property = |
716 | drm_property_create(dev, DRM_MODE_PROP_ENUM, |
- | |
717 | "mode", num_modes); |
- | |
718 | for (i = 0; i < num_modes; i++) |
- | |
Line 719... | Line 797... | ||
719 | drm_property_add_enum(dev->mode_config.tv_mode_property, i, |
797 | drm_property_create(dev, DRM_MODE_PROP_ENUM, |
720 | i, modes[i]); |
798 | "mode", num_modes); |
721 | - | ||
722 | dev->mode_config.tv_brightness_property = |
- | |
723 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
- | |
Line 724... | Line 799... | ||
724 | "brightness", 2); |
799 | for (i = 0; i < num_modes; i++) |
725 | dev->mode_config.tv_brightness_property->values[0] = 0; |
800 | drm_property_add_enum(dev->mode_config.tv_mode_property, i, |
726 | dev->mode_config.tv_brightness_property->values[1] = 100; |
- | |
727 | - | ||
728 | dev->mode_config.tv_contrast_property = |
- | |
Line 729... | Line 801... | ||
729 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
801 | i, modes[i]); |
730 | "contrast", 2); |
802 | |
731 | dev->mode_config.tv_contrast_property->values[0] = 0; |
- | |
732 | dev->mode_config.tv_contrast_property->values[1] = 100; |
- | |
733 | - | ||
Line 734... | Line 803... | ||
734 | dev->mode_config.tv_flicker_reduction_property = |
803 | dev->mode_config.tv_brightness_property = |
735 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
804 | drm_property_create_range(dev, 0, "brightness", 0, 100); |
736 | "flicker reduction", 2); |
- | |
737 | dev->mode_config.tv_flicker_reduction_property->values[0] = 0; |
- | |
738 | dev->mode_config.tv_flicker_reduction_property->values[1] = 100; |
- | |
Line 739... | Line 805... | ||
739 | 805 | ||
740 | dev->mode_config.tv_overscan_property = |
806 | dev->mode_config.tv_contrast_property = |
741 | drm_property_create(dev, DRM_MODE_PROP_RANGE, |
- | |
742 | "overscan", 2); |
- | |
743 | dev->mode_config.tv_overscan_property->values[0] = 0; |
- | |
Line 744... | Line 807... | ||
744 | dev->mode_config.tv_overscan_property->values[1] = 100; |
807 | drm_property_create_range(dev, 0, "contrast", 0, 100); |
745 | 808 | ||
746 | dev->mode_config.tv_saturation_property = |
809 | dev->mode_config.tv_flicker_reduction_property = |
Line 767... | Line 830... | ||
767 | * connectors. |
830 | * connectors. |
768 | */ |
831 | */ |
769 | int drm_mode_create_scaling_mode_property(struct drm_device *dev) |
832 | int drm_mode_create_scaling_mode_property(struct drm_device *dev) |
770 | { |
833 | { |
771 | struct drm_property *scaling_mode; |
834 | struct drm_property *scaling_mode; |
772 | int i; |
- | |
Line 773... | Line 835... | ||
773 | 835 | ||
774 | if (dev->mode_config.scaling_mode_property) |
836 | if (dev->mode_config.scaling_mode_property) |
Line 775... | Line 837... | ||
775 | return 0; |
837 | return 0; |
776 | 838 | ||
- | 839 | scaling_mode = |
|
777 | scaling_mode = |
840 | drm_property_create_enum(dev, 0, "scaling mode", |
778 | drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode", |
- | |
779 | ARRAY_SIZE(drm_scaling_mode_enum_list)); |
- | |
780 | for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) |
- | |
781 | drm_property_add_enum(scaling_mode, i, |
- | |
Line 782... | Line 841... | ||
782 | drm_scaling_mode_enum_list[i].type, |
841 | drm_scaling_mode_enum_list, |
Line 783... | Line 842... | ||
783 | drm_scaling_mode_enum_list[i].name); |
842 | ARRAY_SIZE(drm_scaling_mode_enum_list)); |
784 | 843 | ||
Line 796... | Line 855... | ||
796 | * connectors. |
855 | * connectors. |
797 | */ |
856 | */ |
798 | int drm_mode_create_dithering_property(struct drm_device *dev) |
857 | int drm_mode_create_dithering_property(struct drm_device *dev) |
799 | { |
858 | { |
800 | struct drm_property *dithering_mode; |
859 | struct drm_property *dithering_mode; |
801 | int i; |
- | |
Line 802... | Line 860... | ||
802 | 860 | ||
803 | if (dev->mode_config.dithering_mode_property) |
861 | if (dev->mode_config.dithering_mode_property) |
Line 804... | Line 862... | ||
804 | return 0; |
862 | return 0; |
805 | 863 | ||
- | 864 | dithering_mode = |
|
806 | dithering_mode = |
865 | drm_property_create_enum(dev, 0, "dithering", |
807 | drm_property_create(dev, DRM_MODE_PROP_ENUM, "dithering", |
- | |
808 | ARRAY_SIZE(drm_dithering_mode_enum_list)); |
- | |
809 | for (i = 0; i < ARRAY_SIZE(drm_dithering_mode_enum_list); i++) |
- | |
810 | drm_property_add_enum(dithering_mode, i, |
- | |
811 | drm_dithering_mode_enum_list[i].type, |
866 | drm_dithering_mode_enum_list, |
Line 812... | Line 867... | ||
812 | drm_dithering_mode_enum_list[i].name); |
867 | ARRAY_SIZE(drm_dithering_mode_enum_list)); |
813 | dev->mode_config.dithering_mode_property = dithering_mode; |
868 | dev->mode_config.dithering_mode_property = dithering_mode; |
814 | 869 | ||
Line 824... | Line 879... | ||
824 | * connectors. |
879 | * connectors. |
825 | */ |
880 | */ |
826 | int drm_mode_create_dirty_info_property(struct drm_device *dev) |
881 | int drm_mode_create_dirty_info_property(struct drm_device *dev) |
827 | { |
882 | { |
828 | struct drm_property *dirty_info; |
883 | struct drm_property *dirty_info; |
829 | int i; |
- | |
Line 830... | Line 884... | ||
830 | 884 | ||
831 | if (dev->mode_config.dirty_info_property) |
885 | if (dev->mode_config.dirty_info_property) |
Line 832... | Line 886... | ||
832 | return 0; |
886 | return 0; |
833 | 887 | ||
834 | dirty_info = |
- | |
835 | drm_property_create(dev, DRM_MODE_PROP_ENUM | |
888 | dirty_info = |
- | 889 | drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
|
836 | DRM_MODE_PROP_IMMUTABLE, |
890 | "dirty", |
837 | "dirty", |
- | |
838 | ARRAY_SIZE(drm_dirty_info_enum_list)); |
- | |
839 | for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++) |
- | |
840 | drm_property_add_enum(dirty_info, i, |
- | |
841 | drm_dirty_info_enum_list[i].type, |
891 | drm_dirty_info_enum_list, |
Line 842... | Line 892... | ||
842 | drm_dirty_info_enum_list[i].name); |
892 | ARRAY_SIZE(drm_dirty_info_enum_list)); |
843 | dev->mode_config.dirty_info_property = dirty_info; |
893 | dev->mode_config.dirty_info_property = dirty_info; |
844 | 894 | ||
Line 864... | Line 914... | ||
864 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
914 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
865 | INIT_LIST_HEAD(&dev->mode_config.connector_list); |
915 | INIT_LIST_HEAD(&dev->mode_config.connector_list); |
866 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
916 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
867 | INIT_LIST_HEAD(&dev->mode_config.property_list); |
917 | INIT_LIST_HEAD(&dev->mode_config.property_list); |
868 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
918 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
- | 919 | INIT_LIST_HEAD(&dev->mode_config.plane_list); |
|
869 | idr_init(&dev->mode_config.crtc_idr); |
920 | idr_init(&dev->mode_config.crtc_idr); |
Line 870... | Line 921... | ||
870 | 921 | ||
871 | mutex_lock(&dev->mode_config.mutex); |
922 | mutex_lock(&dev->mode_config.mutex); |
872 | drm_mode_create_standard_connector_properties(dev); |
923 | drm_mode_create_standard_connector_properties(dev); |
Line 920... | Line 971... | ||
920 | group->id_list[group->num_crtcs + group->num_encoders + |
971 | group->id_list[group->num_crtcs + group->num_encoders + |
921 | group->num_connectors++] = connector->base.id; |
972 | group->num_connectors++] = connector->base.id; |
Line 922... | Line 973... | ||
922 | 973 | ||
923 | return 0; |
974 | return 0; |
- | 975 | } |
|
Line 924... | Line 976... | ||
924 | } |
976 | EXPORT_SYMBOL(drm_mode_group_init_legacy_group); |
925 | 977 | ||
926 | /** |
978 | /** |
927 | * drm_mode_config_cleanup - free up DRM mode_config info |
979 | * drm_mode_config_cleanup - free up DRM mode_config info |
Line 940... | Line 992... | ||
940 | struct drm_connector *connector, *ot; |
992 | struct drm_connector *connector, *ot; |
941 | struct drm_crtc *crtc, *ct; |
993 | struct drm_crtc *crtc, *ct; |
942 | struct drm_encoder *encoder, *enct; |
994 | struct drm_encoder *encoder, *enct; |
943 | struct drm_framebuffer *fb, *fbt; |
995 | struct drm_framebuffer *fb, *fbt; |
944 | struct drm_property *property, *pt; |
996 | struct drm_property *property, *pt; |
- | 997 | struct drm_plane *plane, *plt; |
|
Line 945... | Line 998... | ||
945 | 998 | ||
946 | list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, |
999 | list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, |
947 | head) { |
1000 | head) { |
948 | encoder->funcs->destroy(encoder); |
1001 | encoder->funcs->destroy(encoder); |
Line 956... | Line 1009... | ||
956 | list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, |
1009 | list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, |
957 | head) { |
1010 | head) { |
958 | drm_property_destroy(dev, property); |
1011 | drm_property_destroy(dev, property); |
959 | } |
1012 | } |
Line 960... | Line 1013... | ||
960 | 1013 | ||
- | 1014 | list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, |
|
961 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { |
1015 | head) { |
962 | fb->funcs->destroy(fb); |
1016 | plane->funcs->destroy(plane); |
Line 963... | Line 1017... | ||
963 | } |
1017 | } |
964 | 1018 | ||
965 | list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { |
1019 | list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { |
Line -... | Line 1020... | ||
- | 1020 | crtc->funcs->destroy(crtc); |
|
- | 1021 | } |
|
966 | crtc->funcs->destroy(crtc); |
1022 | |
967 | } |
1023 | idr_remove_all(&dev->mode_config.crtc_idr); |
Line 968... | Line 1024... | ||
968 | 1024 | idr_destroy(&dev->mode_config.crtc_idr); |
|
969 | } |
1025 | } |
Line 978... | Line 1034... | ||
978 | * None. |
1034 | * None. |
979 | * |
1035 | * |
980 | * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to |
1036 | * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to |
981 | * the user. |
1037 | * the user. |
982 | */ |
1038 | */ |
983 | void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, |
1039 | static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, |
984 | struct drm_display_mode *in) |
1040 | const struct drm_display_mode *in) |
985 | { |
1041 | { |
- | 1042 | WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || |
|
- | 1043 | in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || |
|
- | 1044 | in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || |
|
- | 1045 | in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || |
|
- | 1046 | in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX, |
|
- | 1047 | "timing values too large for mode info\n"); |
|
- | 1048 | ||
986 | out->clock = in->clock; |
1049 | out->clock = in->clock; |
987 | out->hdisplay = in->hdisplay; |
1050 | out->hdisplay = in->hdisplay; |
988 | out->hsync_start = in->hsync_start; |
1051 | out->hsync_start = in->hsync_start; |
989 | out->hsync_end = in->hsync_end; |
1052 | out->hsync_end = in->hsync_end; |
990 | out->htotal = in->htotal; |
1053 | out->htotal = in->htotal; |
Line 1009... | Line 1072... | ||
1009 | * LOCKING: |
1072 | * LOCKING: |
1010 | * None. |
1073 | * None. |
1011 | * |
1074 | * |
1012 | * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to |
1075 | * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to |
1013 | * the caller. |
1076 | * the caller. |
- | 1077 | * |
|
- | 1078 | * RETURNS: |
|
- | 1079 | * Zero on success, errno on failure. |
|
1014 | */ |
1080 | */ |
1015 | void drm_crtc_convert_umode(struct drm_display_mode *out, |
1081 | static int drm_crtc_convert_umode(struct drm_display_mode *out, |
1016 | struct drm_mode_modeinfo *in) |
1082 | const struct drm_mode_modeinfo *in) |
1017 | { |
1083 | { |
- | 1084 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) |
|
- | 1085 | return -ERANGE; |
|
- | 1086 | ||
1018 | out->clock = in->clock; |
1087 | out->clock = in->clock; |
1019 | out->hdisplay = in->hdisplay; |
1088 | out->hdisplay = in->hdisplay; |
1020 | out->hsync_start = in->hsync_start; |
1089 | out->hsync_start = in->hsync_start; |
1021 | out->hsync_end = in->hsync_end; |
1090 | out->hsync_end = in->hsync_end; |
1022 | out->htotal = in->htotal; |
1091 | out->htotal = in->htotal; |
Line 1029... | Line 1098... | ||
1029 | out->vrefresh = in->vrefresh; |
1098 | out->vrefresh = in->vrefresh; |
1030 | out->flags = in->flags; |
1099 | out->flags = in->flags; |
1031 | out->type = in->type; |
1100 | out->type = in->type; |
1032 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); |
1101 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); |
1033 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; |
1102 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; |
- | 1103 | ||
- | 1104 | return 0; |
|
1034 | } |
1105 | } |
Line 1035... | Line 1106... | ||
1035 | 1106 | ||
1036 | 1107 | ||
Line 1229... | Line 1300... | ||
1229 | * @filp: file * from the ioctl |
1300 | * @filp: file * from the ioctl |
1230 | * @cmd: cmd from ioctl |
1301 | * @cmd: cmd from ioctl |
1231 | * @arg: arg from ioctl |
1302 | * @arg: arg from ioctl |
1232 | * |
1303 | * |
1233 | * LOCKING: |
1304 | * LOCKING: |
1234 | * Caller? (FIXME) |
1305 | * Takes mode config lock. |
1235 | * |
1306 | * |
1236 | * Construct a CRTC configuration structure to return to the user. |
1307 | * Construct a CRTC configuration structure to return to the user. |
1237 | * |
1308 | * |
1238 | * Called by the user via ioctl. |
1309 | * Called by the user via ioctl. |
1239 | * |
1310 | * |
Line 1289... | Line 1360... | ||
1289 | * @filp: file * from the ioctl |
1360 | * @filp: file * from the ioctl |
1290 | * @cmd: cmd from ioctl |
1361 | * @cmd: cmd from ioctl |
1291 | * @arg: arg from ioctl |
1362 | * @arg: arg from ioctl |
1292 | * |
1363 | * |
1293 | * LOCKING: |
1364 | * LOCKING: |
1294 | * Caller? (FIXME) |
1365 | * Takes mode config lock. |
1295 | * |
1366 | * |
1296 | * Construct a connector configuration structure to return to the user. |
1367 | * Construct a connector configuration structure to return to the user. |
1297 | * |
1368 | * |
1298 | * Called by the user via ioctl. |
1369 | * Called by the user via ioctl. |
1299 | * |
1370 | * |
Line 1334... | Line 1405... | ||
1334 | ret = -EINVAL; |
1405 | ret = -EINVAL; |
1335 | goto out; |
1406 | goto out; |
1336 | } |
1407 | } |
1337 | connector = obj_to_connector(obj); |
1408 | connector = obj_to_connector(obj); |
Line 1338... | Line -... | ||
1338 | - | ||
1339 | for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { |
1409 | |
1340 | if (connector->property_ids[i] != 0) { |
- | |
1341 | props_count++; |
- | |
1342 | } |
- | |
Line 1343... | Line 1410... | ||
1343 | } |
1410 | props_count = connector->properties.count; |
1344 | 1411 | ||
1345 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
1412 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
1346 | if (connector->encoder_ids[i] != 0) { |
1413 | if (connector->encoder_ids[i] != 0) { |
Line 1374... | Line 1441... | ||
1374 | * This ioctl is called twice, once to determine how much space is |
1441 | * This ioctl is called twice, once to determine how much space is |
1375 | * needed, and the 2nd time to fill it. |
1442 | * needed, and the 2nd time to fill it. |
1376 | */ |
1443 | */ |
1377 | if ((out_resp->count_modes >= mode_count) && mode_count) { |
1444 | if ((out_resp->count_modes >= mode_count) && mode_count) { |
1378 | copied = 0; |
1445 | copied = 0; |
1379 | mode_ptr = (struct drm_mode_modeinfo *)(unsigned long)out_resp->modes_ptr; |
1446 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; |
1380 | list_for_each_entry(mode, &connector->modes, head) { |
1447 | list_for_each_entry(mode, &connector->modes, head) { |
1381 | drm_crtc_convert_to_umode(&u_mode, mode); |
1448 | drm_crtc_convert_to_umode(&u_mode, mode); |
1382 | if (copy_to_user(mode_ptr + copied, |
1449 | if (copy_to_user(mode_ptr + copied, |
1383 | &u_mode, sizeof(u_mode))) { |
1450 | &u_mode, sizeof(u_mode))) { |
1384 | ret = -EFAULT; |
1451 | ret = -EFAULT; |
Line 1389... | Line 1456... | ||
1389 | } |
1456 | } |
1390 | out_resp->count_modes = mode_count; |
1457 | out_resp->count_modes = mode_count; |
Line 1391... | Line 1458... | ||
1391 | 1458 | ||
1392 | if ((out_resp->count_props >= props_count) && props_count) { |
1459 | if ((out_resp->count_props >= props_count) && props_count) { |
1393 | copied = 0; |
1460 | copied = 0; |
1394 | prop_ptr = (uint32_t *)(unsigned long)(out_resp->props_ptr); |
1461 | prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); |
1395 | prop_values = (uint64_t *)(unsigned long)(out_resp->prop_values_ptr); |
1462 | prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); |
1396 | for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { |
- | |
1397 | if (connector->property_ids[i] != 0) { |
1463 | for (i = 0; i < connector->properties.count; i++) { |
1398 | if (put_user(connector->property_ids[i], |
1464 | if (put_user(connector->properties.ids[i], |
1399 | prop_ptr + copied)) { |
1465 | prop_ptr + copied)) { |
1400 | ret = -EFAULT; |
1466 | ret = -EFAULT; |
1401 | goto out; |
1467 | goto out; |
Line 1402... | Line 1468... | ||
1402 | } |
1468 | } |
1403 | 1469 | ||
1404 | if (put_user(connector->property_values[i], |
1470 | if (put_user(connector->properties.values[i], |
1405 | prop_values + copied)) { |
1471 | prop_values + copied)) { |
1406 | ret = -EFAULT; |
1472 | ret = -EFAULT; |
1407 | goto out; |
1473 | goto out; |
1408 | } |
1474 | } |
1409 | copied++; |
1475 | copied++; |
1410 | } |
- | |
1411 | } |
1476 | } |
Line 1412... | Line 1477... | ||
1412 | } |
1477 | } |
1413 | out_resp->count_props = props_count; |
1478 | out_resp->count_props = props_count; |
1414 | 1479 | ||
1415 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { |
1480 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { |
1416 | copied = 0; |
1481 | copied = 0; |
1417 | encoder_ptr = (uint32_t *)(unsigned long)(out_resp->encoders_ptr); |
1482 | encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr); |
1418 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
1483 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
1419 | if (connector->encoder_ids[i] != 0) { |
1484 | if (connector->encoder_ids[i] != 0) { |
Line 1466... | Line 1531... | ||
1466 | mutex_unlock(&dev->mode_config.mutex); |
1531 | mutex_unlock(&dev->mode_config.mutex); |
1467 | return ret; |
1532 | return ret; |
1468 | } |
1533 | } |
Line 1469... | Line 1534... | ||
1469 | 1534 | ||
- | 1535 | /** |
|
- | 1536 | * drm_mode_getplane_res - get plane info |
|
- | 1537 | * @dev: DRM device |
|
- | 1538 | * @data: ioctl data |
|
- | 1539 | * @file_priv: DRM file info |
|
- | 1540 | * |
|
- | 1541 | * LOCKING: |
|
- | 1542 | * Takes mode config lock. |
|
- | 1543 | * |
|
- | 1544 | * Return an plane count and set of IDs. |
|
- | 1545 | */ |
|
- | 1546 | int drm_mode_getplane_res(struct drm_device *dev, void *data, |
|
- | 1547 | struct drm_file *file_priv) |
|
- | 1548 | { |
|
- | 1549 | struct drm_mode_get_plane_res *plane_resp = data; |
|
- | 1550 | struct drm_mode_config *config; |
|
- | 1551 | struct drm_plane *plane; |
|
- | 1552 | uint32_t __user *plane_ptr; |
|
- | 1553 | int copied = 0, ret = 0; |
|
- | 1554 | ||
- | 1555 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|
- | 1556 | return -EINVAL; |
|
- | 1557 | ||
- | 1558 | mutex_lock(&dev->mode_config.mutex); |
|
- | 1559 | config = &dev->mode_config; |
|
- | 1560 | ||
- | 1561 | /* |
|
- | 1562 | * This ioctl is called twice, once to determine how much space is |
|
- | 1563 | * needed, and the 2nd time to fill it. |
|
- | 1564 | */ |
|
- | 1565 | if (config->num_plane && |
|
- | 1566 | (plane_resp->count_planes >= config->num_plane)) { |
|
- | 1567 | plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; |
|
- | 1568 | ||
- | 1569 | list_for_each_entry(plane, &config->plane_list, head) { |
|
- | 1570 | if (put_user(plane->base.id, plane_ptr + copied)) { |
|
- | 1571 | ret = -EFAULT; |
|
- | 1572 | goto out; |
|
- | 1573 | } |
|
- | 1574 | copied++; |
|
- | 1575 | } |
|
- | 1576 | } |
|
- | 1577 | plane_resp->count_planes = config->num_plane; |
|
- | 1578 | ||
- | 1579 | out: |
|
- | 1580 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 1581 | return ret; |
|
- | 1582 | } |
|
- | 1583 | ||
- | 1584 | /** |
|
- | 1585 | * drm_mode_getplane - get plane info |
|
- | 1586 | * @dev: DRM device |
|
- | 1587 | * @data: ioctl data |
|
- | 1588 | * @file_priv: DRM file info |
|
- | 1589 | * |
|
- | 1590 | * LOCKING: |
|
- | 1591 | * Takes mode config lock. |
|
- | 1592 | * |
|
- | 1593 | * Return plane info, including formats supported, gamma size, any |
|
- | 1594 | * current fb, etc. |
|
- | 1595 | */ |
|
- | 1596 | int drm_mode_getplane(struct drm_device *dev, void *data, |
|
- | 1597 | struct drm_file *file_priv) |
|
- | 1598 | { |
|
- | 1599 | struct drm_mode_get_plane *plane_resp = data; |
|
- | 1600 | struct drm_mode_object *obj; |
|
- | 1601 | struct drm_plane *plane; |
|
- | 1602 | uint32_t __user *format_ptr; |
|
- | 1603 | int ret = 0; |
|
- | 1604 | ||
- | 1605 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|
- | 1606 | return -EINVAL; |
|
- | 1607 | ||
- | 1608 | mutex_lock(&dev->mode_config.mutex); |
|
- | 1609 | obj = drm_mode_object_find(dev, plane_resp->plane_id, |
|
- | 1610 | DRM_MODE_OBJECT_PLANE); |
|
- | 1611 | if (!obj) { |
|
- | 1612 | ret = -ENOENT; |
|
- | 1613 | goto out; |
|
- | 1614 | } |
|
- | 1615 | plane = obj_to_plane(obj); |
|
- | 1616 | ||
- | 1617 | if (plane->crtc) |
|
- | 1618 | plane_resp->crtc_id = plane->crtc->base.id; |
|
- | 1619 | else |
|
- | 1620 | plane_resp->crtc_id = 0; |
|
- | 1621 | ||
- | 1622 | if (plane->fb) |
|
- | 1623 | plane_resp->fb_id = plane->fb->base.id; |
|
- | 1624 | else |
|
- | 1625 | plane_resp->fb_id = 0; |
|
- | 1626 | ||
- | 1627 | plane_resp->plane_id = plane->base.id; |
|
- | 1628 | plane_resp->possible_crtcs = plane->possible_crtcs; |
|
- | 1629 | plane_resp->gamma_size = plane->gamma_size; |
|
- | 1630 | ||
- | 1631 | /* |
|
- | 1632 | * This ioctl is called twice, once to determine how much space is |
|
- | 1633 | * needed, and the 2nd time to fill it. |
|
- | 1634 | */ |
|
- | 1635 | if (plane->format_count && |
|
- | 1636 | (plane_resp->count_format_types >= plane->format_count)) { |
|
- | 1637 | format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr; |
|
- | 1638 | if (copy_to_user(format_ptr, |
|
- | 1639 | plane->format_types, |
|
- | 1640 | sizeof(uint32_t) * plane->format_count)) { |
|
- | 1641 | ret = -EFAULT; |
|
- | 1642 | goto out; |
|
- | 1643 | } |
|
- | 1644 | } |
|
- | 1645 | plane_resp->count_format_types = plane->format_count; |
|
- | 1646 | ||
- | 1647 | out: |
|
- | 1648 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 1649 | return ret; |
|
- | 1650 | } |
|
- | 1651 | ||
- | 1652 | /** |
|
- | 1653 | * drm_mode_setplane - set up or tear down an plane |
|
- | 1654 | * @dev: DRM device |
|
- | 1655 | * @data: ioctl data* |
|
- | 1656 | * @file_prive: DRM file info |
|
- | 1657 | * |
|
- | 1658 | * LOCKING: |
|
- | 1659 | * Takes mode config lock. |
|
- | 1660 | * |
|
- | 1661 | * Set plane info, including placement, fb, scaling, and other factors. |
|
- | 1662 | * Or pass a NULL fb to disable. |
|
- | 1663 | */ |
|
- | 1664 | int drm_mode_setplane(struct drm_device *dev, void *data, |
|
- | 1665 | struct drm_file *file_priv) |
|
- | 1666 | { |
|
- | 1667 | struct drm_mode_set_plane *plane_req = data; |
|
- | 1668 | struct drm_mode_object *obj; |
|
- | 1669 | struct drm_plane *plane; |
|
- | 1670 | struct drm_crtc *crtc; |
|
- | 1671 | struct drm_framebuffer *fb; |
|
- | 1672 | int ret = 0; |
|
- | 1673 | unsigned int fb_width, fb_height; |
|
- | 1674 | int i; |
|
- | 1675 | ||
- | 1676 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|
- | 1677 | return -EINVAL; |
|
- | 1678 | ||
- | 1679 | mutex_lock(&dev->mode_config.mutex); |
|
- | 1680 | ||
- | 1681 | /* |
|
- | 1682 | * First, find the plane, crtc, and fb objects. If not available, |
|
- | 1683 | * we don't bother to call the driver. |
|
- | 1684 | */ |
|
- | 1685 | obj = drm_mode_object_find(dev, plane_req->plane_id, |
|
- | 1686 | DRM_MODE_OBJECT_PLANE); |
|
- | 1687 | if (!obj) { |
|
- | 1688 | DRM_DEBUG_KMS("Unknown plane ID %d\n", |
|
- | 1689 | plane_req->plane_id); |
|
- | 1690 | ret = -ENOENT; |
|
- | 1691 | goto out; |
|
- | 1692 | } |
|
- | 1693 | plane = obj_to_plane(obj); |
|
- | 1694 | ||
- | 1695 | /* No fb means shut it down */ |
|
- | 1696 | if (!plane_req->fb_id) { |
|
- | 1697 | plane->funcs->disable_plane(plane); |
|
- | 1698 | plane->crtc = NULL; |
|
- | 1699 | plane->fb = NULL; |
|
- | 1700 | goto out; |
|
- | 1701 | } |
|
- | 1702 | ||
- | 1703 | obj = drm_mode_object_find(dev, plane_req->crtc_id, |
|
- | 1704 | DRM_MODE_OBJECT_CRTC); |
|
- | 1705 | if (!obj) { |
|
- | 1706 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", |
|
- | 1707 | plane_req->crtc_id); |
|
- | 1708 | ret = -ENOENT; |
|
- | 1709 | goto out; |
|
- | 1710 | } |
|
- | 1711 | crtc = obj_to_crtc(obj); |
|
- | 1712 | ||
- | 1713 | obj = drm_mode_object_find(dev, plane_req->fb_id, |
|
- | 1714 | DRM_MODE_OBJECT_FB); |
|
- | 1715 | if (!obj) { |
|
- | 1716 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", |
|
- | 1717 | plane_req->fb_id); |
|
- | 1718 | ret = -ENOENT; |
|
- | 1719 | goto out; |
|
- | 1720 | } |
|
- | 1721 | fb = obj_to_fb(obj); |
|
- | 1722 | ||
- | 1723 | /* Check whether this plane supports the fb pixel format. */ |
|
- | 1724 | for (i = 0; i < plane->format_count; i++) |
|
- | 1725 | if (fb->pixel_format == plane->format_types[i]) |
|
- | 1726 | break; |
|
- | 1727 | if (i == plane->format_count) { |
|
- | 1728 | DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format); |
|
- | 1729 | ret = -EINVAL; |
|
- | 1730 | goto out; |
|
- | 1731 | } |
|
- | 1732 | ||
- | 1733 | fb_width = fb->width << 16; |
|
- | 1734 | fb_height = fb->height << 16; |
|
- | 1735 | ||
- | 1736 | /* Make sure source coordinates are inside the fb. */ |
|
- | 1737 | if (plane_req->src_w > fb_width || |
|
- | 1738 | plane_req->src_x > fb_width - plane_req->src_w || |
|
- | 1739 | plane_req->src_h > fb_height || |
|
- | 1740 | plane_req->src_y > fb_height - plane_req->src_h) { |
|
- | 1741 | DRM_DEBUG_KMS("Invalid source coordinates " |
|
- | 1742 | "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", |
|
- | 1743 | plane_req->src_w >> 16, |
|
- | 1744 | ((plane_req->src_w & 0xffff) * 15625) >> 10, |
|
- | 1745 | plane_req->src_h >> 16, |
|
- | 1746 | ((plane_req->src_h & 0xffff) * 15625) >> 10, |
|
- | 1747 | plane_req->src_x >> 16, |
|
- | 1748 | ((plane_req->src_x & 0xffff) * 15625) >> 10, |
|
- | 1749 | plane_req->src_y >> 16, |
|
- | 1750 | ((plane_req->src_y & 0xffff) * 15625) >> 10); |
|
- | 1751 | ret = -ENOSPC; |
|
- | 1752 | goto out; |
|
- | 1753 | } |
|
- | 1754 | ||
- | 1755 | /* Give drivers some help against integer overflows */ |
|
- | 1756 | if (plane_req->crtc_w > INT_MAX || |
|
- | 1757 | plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || |
|
- | 1758 | plane_req->crtc_h > INT_MAX || |
|
- | 1759 | plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { |
|
- | 1760 | DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", |
|
- | 1761 | plane_req->crtc_w, plane_req->crtc_h, |
|
- | 1762 | plane_req->crtc_x, plane_req->crtc_y); |
|
- | 1763 | ret = -ERANGE; |
|
- | 1764 | goto out; |
|
- | 1765 | } |
|
- | 1766 | ||
- | 1767 | ret = plane->funcs->update_plane(plane, crtc, fb, |
|
- | 1768 | plane_req->crtc_x, plane_req->crtc_y, |
|
- | 1769 | plane_req->crtc_w, plane_req->crtc_h, |
|
- | 1770 | plane_req->src_x, plane_req->src_y, |
|
- | 1771 | plane_req->src_w, plane_req->src_h); |
|
- | 1772 | if (!ret) { |
|
- | 1773 | plane->crtc = crtc; |
|
- | 1774 | plane->fb = fb; |
|
- | 1775 | } |
|
- | 1776 | ||
- | 1777 | out: |
|
- | 1778 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 1779 | ||
- | 1780 | return ret; |
|
- | 1781 | } |
|
- | 1782 | ||
1470 | /** |
1783 | /** |
1471 | * drm_mode_setcrtc - set CRTC configuration |
1784 | * drm_mode_setcrtc - set CRTC configuration |
1472 | * @inode: inode from the ioctl |
1785 | * @inode: inode from the ioctl |
1473 | * @filp: file * from the ioctl |
1786 | * @filp: file * from the ioctl |
1474 | * @cmd: cmd from ioctl |
1787 | * @cmd: cmd from ioctl |
1475 | * @arg: arg from ioctl |
1788 | * @arg: arg from ioctl |
1476 | * |
1789 | * |
1477 | * LOCKING: |
1790 | * LOCKING: |
1478 | * Caller? (FIXME) |
1791 | * Takes mode config lock. |
1479 | * |
1792 | * |
1480 | * Build a new CRTC configuration based on user request. |
1793 | * Build a new CRTC configuration based on user request. |
1481 | * |
1794 | * |
1482 | * Called by the user via ioctl. |
1795 | * Called by the user via ioctl. |
Line 1488... | Line 1801... | ||
1488 | struct drm_file *file_priv) |
1801 | struct drm_file *file_priv) |
1489 | { |
1802 | { |
1490 | struct drm_mode_config *config = &dev->mode_config; |
1803 | struct drm_mode_config *config = &dev->mode_config; |
1491 | struct drm_mode_crtc *crtc_req = data; |
1804 | struct drm_mode_crtc *crtc_req = data; |
1492 | struct drm_mode_object *obj; |
1805 | struct drm_mode_object *obj; |
1493 | struct drm_crtc *crtc, *crtcfb; |
1806 | struct drm_crtc *crtc; |
1494 | struct drm_connector **connector_set = NULL, *connector; |
1807 | struct drm_connector **connector_set = NULL, *connector; |
1495 | struct drm_framebuffer *fb = NULL; |
1808 | struct drm_framebuffer *fb = NULL; |
1496 | struct drm_display_mode *mode = NULL; |
1809 | struct drm_display_mode *mode = NULL; |
1497 | struct drm_mode_set set; |
1810 | struct drm_mode_set set; |
1498 | uint32_t __user *set_connectors_ptr; |
1811 | uint32_t __user *set_connectors_ptr; |
1499 | int ret = 0; |
1812 | int ret; |
1500 | int i; |
1813 | int i; |
Line 1501... | Line 1814... | ||
1501 | 1814 | ||
1502 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1815 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line -... | Line 1816... | ||
- | 1816 | return -EINVAL; |
|
- | 1817 | ||
- | 1818 | /* For some reason crtc x/y offsets are signed internally. */ |
|
- | 1819 | if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) |
|
1503 | return -EINVAL; |
1820 | return -ERANGE; |
1504 | 1821 | ||
1505 | mutex_lock(&dev->mode_config.mutex); |
1822 | mutex_lock(&dev->mode_config.mutex); |
1506 | obj = drm_mode_object_find(dev, crtc_req->crtc_id, |
1823 | obj = drm_mode_object_find(dev, crtc_req->crtc_id, |
1507 | DRM_MODE_OBJECT_CRTC); |
1824 | DRM_MODE_OBJECT_CRTC); |
Line 1512... | Line 1829... | ||
1512 | } |
1829 | } |
1513 | crtc = obj_to_crtc(obj); |
1830 | crtc = obj_to_crtc(obj); |
1514 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
1831 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
Line 1515... | Line 1832... | ||
1515 | 1832 | ||
- | 1833 | if (crtc_req->mode_valid) { |
|
1516 | if (crtc_req->mode_valid) { |
1834 | int hdisplay, vdisplay; |
1517 | /* If we have a mode we need a framebuffer. */ |
1835 | /* If we have a mode we need a framebuffer. */ |
1518 | /* If we pass -1, set the mode with the currently bound fb */ |
1836 | /* If we pass -1, set the mode with the currently bound fb */ |
1519 | if (crtc_req->fb_id == -1) { |
- | |
1520 | list_for_each_entry(crtcfb, |
- | |
1521 | &dev->mode_config.crtc_list, head) { |
1837 | if (crtc_req->fb_id == -1) { |
1522 | if (crtcfb == crtc) { |
1838 | if (!crtc->fb) { |
1523 | DRM_DEBUG_KMS("Using current fb for " |
- | |
1524 | "setmode\n"); |
1839 | DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); |
1525 | fb = crtc->fb; |
1840 | ret = -EINVAL; |
1526 | } |
1841 | goto out; |
- | 1842 | } |
|
1527 | } |
1843 | fb = crtc->fb; |
1528 | } else { |
1844 | } else { |
1529 | obj = drm_mode_object_find(dev, crtc_req->fb_id, |
1845 | obj = drm_mode_object_find(dev, crtc_req->fb_id, |
1530 | DRM_MODE_OBJECT_FB); |
1846 | DRM_MODE_OBJECT_FB); |
1531 | if (!obj) { |
1847 | if (!obj) { |
Line 1536... | Line 1852... | ||
1536 | } |
1852 | } |
1537 | fb = obj_to_fb(obj); |
1853 | fb = obj_to_fb(obj); |
1538 | } |
1854 | } |
Line 1539... | Line 1855... | ||
1539 | 1855 | ||
- | 1856 | mode = drm_mode_create(dev); |
|
- | 1857 | if (!mode) { |
|
- | 1858 | ret = -ENOMEM; |
|
- | 1859 | goto out; |
|
- | 1860 | } |
|
1540 | mode = drm_mode_create(dev); |
1861 | |
- | 1862 | ret = drm_crtc_convert_umode(mode, &crtc_req->mode); |
|
- | 1863 | if (ret) { |
|
- | 1864 | DRM_DEBUG_KMS("Invalid mode\n"); |
|
- | 1865 | goto out; |
|
- | 1866 | } |
|
1541 | drm_crtc_convert_umode(mode, &crtc_req->mode); |
1867 | |
- | 1868 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
|
- | 1869 | ||
- | 1870 | hdisplay = mode->hdisplay; |
|
- | 1871 | vdisplay = mode->vdisplay; |
|
- | 1872 | ||
- | 1873 | if (crtc->invert_dimensions) |
|
- | 1874 | swap(hdisplay, vdisplay); |
|
- | 1875 | ||
- | 1876 | if (hdisplay > fb->width || |
|
- | 1877 | vdisplay > fb->height || |
|
- | 1878 | crtc_req->x > fb->width - hdisplay || |
|
- | 1879 | crtc_req->y > fb->height - vdisplay) { |
|
- | 1880 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", |
|
- | 1881 | fb->width, fb->height, |
|
- | 1882 | hdisplay, vdisplay, crtc_req->x, crtc_req->y, |
|
- | 1883 | crtc->invert_dimensions ? " (inverted)" : ""); |
|
- | 1884 | ret = -ENOSPC; |
|
- | 1885 | goto out; |
|
1542 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
1886 | } |
Line 1543... | Line 1887... | ||
1543 | } |
1887 | } |
1544 | 1888 | ||
1545 | if (crtc_req->count_connectors == 0 && mode) { |
1889 | if (crtc_req->count_connectors == 0 && mode) { |
Line 1571... | Line 1915... | ||
1571 | ret = -ENOMEM; |
1915 | ret = -ENOMEM; |
1572 | goto out; |
1916 | goto out; |
1573 | } |
1917 | } |
Line 1574... | Line 1918... | ||
1574 | 1918 | ||
1575 | for (i = 0; i < crtc_req->count_connectors; i++) { |
1919 | for (i = 0; i < crtc_req->count_connectors; i++) { |
1576 | set_connectors_ptr = (uint32_t *)(unsigned long)crtc_req->set_connectors_ptr; |
1920 | set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; |
1577 | if (get_user(out_id, &set_connectors_ptr[i])) { |
1921 | if (get_user(out_id, &set_connectors_ptr[i])) { |
1578 | ret = -EFAULT; |
1922 | ret = -EFAULT; |
1579 | goto out; |
1923 | goto out; |
Line 1605... | Line 1949... | ||
1605 | set.fb = fb; |
1949 | set.fb = fb; |
1606 | ret = crtc->funcs->set_config(&set); |
1950 | ret = crtc->funcs->set_config(&set); |
Line 1607... | Line 1951... | ||
1607 | 1951 | ||
1608 | out: |
1952 | out: |
- | 1953 | kfree(connector_set); |
|
1609 | kfree(connector_set); |
1954 | drm_mode_destroy(dev, mode); |
1610 | mutex_unlock(&dev->mode_config.mutex); |
1955 | mutex_unlock(&dev->mode_config.mutex); |
1611 | return ret; |
1956 | return ret; |
Line 1612... | Line 1957... | ||
1612 | } |
1957 | } |
Line 1620... | Line 1965... | ||
1620 | int ret = 0; |
1965 | int ret = 0; |
Line 1621... | Line 1966... | ||
1621 | 1966 | ||
1622 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1967 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 1623... | Line 1968... | ||
1623 | return -EINVAL; |
1968 | return -EINVAL; |
1624 | - | ||
1625 | if (!req->flags) { |
1969 | |
1626 | DRM_ERROR("no operation set\n"); |
- | |
Line 1627... | Line 1970... | ||
1627 | return -EINVAL; |
1970 | if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) |
1628 | } |
1971 | return -EINVAL; |
1629 | 1972 | ||
1630 | mutex_lock(&dev->mode_config.mutex); |
1973 | mutex_lock(&dev->mode_config.mutex); |
Line 1636... | Line 1979... | ||
1636 | } |
1979 | } |
1637 | crtc = obj_to_crtc(obj); |
1980 | crtc = obj_to_crtc(obj); |
Line 1638... | Line 1981... | ||
1638 | 1981 | ||
1639 | if (req->flags & DRM_MODE_CURSOR_BO) { |
1982 | if (req->flags & DRM_MODE_CURSOR_BO) { |
1640 | if (!crtc->funcs->cursor_set) { |
- | |
1641 | DRM_ERROR("crtc does not support cursor\n"); |
1983 | if (!crtc->funcs->cursor_set) { |
1642 | ret = -ENXIO; |
1984 | ret = -ENXIO; |
1643 | goto out; |
1985 | goto out; |
1644 | } |
1986 | } |
1645 | /* Turns off the cursor if handle is 0 */ |
1987 | /* Turns off the cursor if handle is 0 */ |
Line 1649... | Line 1991... | ||
1649 | 1991 | ||
1650 | if (req->flags & DRM_MODE_CURSOR_MOVE) { |
1992 | if (req->flags & DRM_MODE_CURSOR_MOVE) { |
1651 | if (crtc->funcs->cursor_move) { |
1993 | if (crtc->funcs->cursor_move) { |
1652 | ret = crtc->funcs->cursor_move(crtc, req->x, req->y); |
1994 | ret = crtc->funcs->cursor_move(crtc, req->x, req->y); |
1653 | } else { |
- | |
1654 | DRM_ERROR("crtc does not support cursor\n"); |
1995 | } else { |
1655 | ret = -EFAULT; |
1996 | ret = -EFAULT; |
1656 | goto out; |
1997 | goto out; |
1657 | } |
1998 | } |
1658 | } |
1999 | } |
1659 | out: |
2000 | out: |
1660 | mutex_unlock(&dev->mode_config.mutex); |
2001 | mutex_unlock(&dev->mode_config.mutex); |
1661 | return ret; |
2002 | return ret; |
- | 2003 | } |
|
- | 2004 | #endif |
|
- | 2005 | /* Original addfb only supported RGB formats, so figure out which one */ |
|
- | 2006 | uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) |
|
- | 2007 | { |
|
- | 2008 | uint32_t fmt; |
|
- | 2009 | ||
- | 2010 | switch (bpp) { |
|
- | 2011 | case 8: |
|
- | 2012 | fmt = DRM_FORMAT_RGB332; |
|
- | 2013 | break; |
|
- | 2014 | case 16: |
|
- | 2015 | if (depth == 15) |
|
- | 2016 | fmt = DRM_FORMAT_XRGB1555; |
|
- | 2017 | else |
|
- | 2018 | fmt = DRM_FORMAT_RGB565; |
|
- | 2019 | break; |
|
- | 2020 | case 24: |
|
- | 2021 | fmt = DRM_FORMAT_RGB888; |
|
- | 2022 | break; |
|
- | 2023 | case 32: |
|
- | 2024 | if (depth == 24) |
|
- | 2025 | fmt = DRM_FORMAT_XRGB8888; |
|
- | 2026 | else if (depth == 30) |
|
- | 2027 | fmt = DRM_FORMAT_XRGB2101010; |
|
- | 2028 | else |
|
- | 2029 | fmt = DRM_FORMAT_ARGB8888; |
|
- | 2030 | break; |
|
- | 2031 | default: |
|
- | 2032 | DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n"); |
|
- | 2033 | fmt = DRM_FORMAT_XRGB8888; |
|
- | 2034 | break; |
|
Line -... | Line 2035... | ||
- | 2035 | } |
|
- | 2036 | ||
- | 2037 | return fmt; |
|
- | 2038 | } |
|
1662 | } |
2039 | EXPORT_SYMBOL(drm_mode_legacy_fb_format); |
1663 | 2040 | #if 0 |
|
1664 | /** |
2041 | /** |
1665 | * drm_mode_addfb - add an FB to the graphics configuration |
2042 | * drm_mode_addfb - add an FB to the graphics configuration |
1666 | * @inode: inode from the ioctl |
2043 | * @inode: inode from the ioctl |
Line 1679... | Line 2056... | ||
1679 | * Zero on success, errno on failure. |
2056 | * Zero on success, errno on failure. |
1680 | */ |
2057 | */ |
1681 | int drm_mode_addfb(struct drm_device *dev, |
2058 | int drm_mode_addfb(struct drm_device *dev, |
1682 | void *data, struct drm_file *file_priv) |
2059 | void *data, struct drm_file *file_priv) |
1683 | { |
2060 | { |
1684 | struct drm_mode_fb_cmd *r = data; |
2061 | struct drm_mode_fb_cmd *or = data; |
- | 2062 | struct drm_mode_fb_cmd2 r = {}; |
|
1685 | struct drm_mode_config *config = &dev->mode_config; |
2063 | struct drm_mode_config *config = &dev->mode_config; |
1686 | struct drm_framebuffer *fb; |
2064 | struct drm_framebuffer *fb; |
1687 | int ret = 0; |
2065 | int ret = 0; |
Line -... | Line 2066... | ||
- | 2066 | ||
- | 2067 | /* Use new struct with format internally */ |
|
- | 2068 | r.fb_id = or->fb_id; |
|
- | 2069 | r.width = or->width; |
|
- | 2070 | r.height = or->height; |
|
- | 2071 | r.pitches[0] = or->pitch; |
|
- | 2072 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); |
|
- | 2073 | r.handles[0] = or->handle; |
|
- | 2074 | ||
- | 2075 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|
- | 2076 | return -EINVAL; |
|
- | 2077 | ||
- | 2078 | if ((config->min_width > r.width) || (r.width > config->max_width)) |
|
- | 2079 | return -EINVAL; |
|
- | 2080 | ||
- | 2081 | if ((config->min_height > r.height) || (r.height > config->max_height)) |
|
- | 2082 | return -EINVAL; |
|
- | 2083 | ||
- | 2084 | mutex_lock(&dev->mode_config.mutex); |
|
- | 2085 | ||
- | 2086 | /* TODO check buffer is sufficiently large */ |
|
- | 2087 | /* TODO setup destructor callback */ |
|
- | 2088 | ||
- | 2089 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); |
|
- | 2090 | if (IS_ERR(fb)) { |
|
- | 2091 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
|
- | 2092 | ret = PTR_ERR(fb); |
|
- | 2093 | goto out; |
|
- | 2094 | } |
|
- | 2095 | ||
- | 2096 | or->fb_id = fb->base.id; |
|
- | 2097 | list_add(&fb->filp_head, &file_priv->fbs); |
|
- | 2098 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
|
- | 2099 | ||
- | 2100 | out: |
|
- | 2101 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 2102 | return ret; |
|
- | 2103 | } |
|
- | 2104 | ||
- | 2105 | static int format_check(const struct drm_mode_fb_cmd2 *r) |
|
- | 2106 | { |
|
- | 2107 | uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; |
|
- | 2108 | ||
- | 2109 | switch (format) { |
|
- | 2110 | case DRM_FORMAT_C8: |
|
- | 2111 | case DRM_FORMAT_RGB332: |
|
- | 2112 | case DRM_FORMAT_BGR233: |
|
- | 2113 | case DRM_FORMAT_XRGB4444: |
|
- | 2114 | case DRM_FORMAT_XBGR4444: |
|
- | 2115 | case DRM_FORMAT_RGBX4444: |
|
- | 2116 | case DRM_FORMAT_BGRX4444: |
|
- | 2117 | case DRM_FORMAT_ARGB4444: |
|
- | 2118 | case DRM_FORMAT_ABGR4444: |
|
- | 2119 | case DRM_FORMAT_RGBA4444: |
|
- | 2120 | case DRM_FORMAT_BGRA4444: |
|
- | 2121 | case DRM_FORMAT_XRGB1555: |
|
- | 2122 | case DRM_FORMAT_XBGR1555: |
|
- | 2123 | case DRM_FORMAT_RGBX5551: |
|
- | 2124 | case DRM_FORMAT_BGRX5551: |
|
- | 2125 | case DRM_FORMAT_ARGB1555: |
|
- | 2126 | case DRM_FORMAT_ABGR1555: |
|
- | 2127 | case DRM_FORMAT_RGBA5551: |
|
- | 2128 | case DRM_FORMAT_BGRA5551: |
|
- | 2129 | case DRM_FORMAT_RGB565: |
|
- | 2130 | case DRM_FORMAT_BGR565: |
|
- | 2131 | case DRM_FORMAT_RGB888: |
|
- | 2132 | case DRM_FORMAT_BGR888: |
|
- | 2133 | case DRM_FORMAT_XRGB8888: |
|
- | 2134 | case DRM_FORMAT_XBGR8888: |
|
- | 2135 | case DRM_FORMAT_RGBX8888: |
|
- | 2136 | case DRM_FORMAT_BGRX8888: |
|
- | 2137 | case DRM_FORMAT_ARGB8888: |
|
- | 2138 | case DRM_FORMAT_ABGR8888: |
|
- | 2139 | case DRM_FORMAT_RGBA8888: |
|
- | 2140 | case DRM_FORMAT_BGRA8888: |
|
- | 2141 | case DRM_FORMAT_XRGB2101010: |
|
- | 2142 | case DRM_FORMAT_XBGR2101010: |
|
- | 2143 | case DRM_FORMAT_RGBX1010102: |
|
- | 2144 | case DRM_FORMAT_BGRX1010102: |
|
- | 2145 | case DRM_FORMAT_ARGB2101010: |
|
- | 2146 | case DRM_FORMAT_ABGR2101010: |
|
- | 2147 | case DRM_FORMAT_RGBA1010102: |
|
- | 2148 | case DRM_FORMAT_BGRA1010102: |
|
- | 2149 | case DRM_FORMAT_YUYV: |
|
- | 2150 | case DRM_FORMAT_YVYU: |
|
- | 2151 | case DRM_FORMAT_UYVY: |
|
- | 2152 | case DRM_FORMAT_VYUY: |
|
- | 2153 | case DRM_FORMAT_AYUV: |
|
- | 2154 | case DRM_FORMAT_NV12: |
|
- | 2155 | case DRM_FORMAT_NV21: |
|
- | 2156 | case DRM_FORMAT_NV16: |
|
- | 2157 | case DRM_FORMAT_NV61: |
|
- | 2158 | case DRM_FORMAT_NV24: |
|
- | 2159 | case DRM_FORMAT_NV42: |
|
- | 2160 | case DRM_FORMAT_YUV410: |
|
- | 2161 | case DRM_FORMAT_YVU410: |
|
- | 2162 | case DRM_FORMAT_YUV411: |
|
- | 2163 | case DRM_FORMAT_YVU411: |
|
- | 2164 | case DRM_FORMAT_YUV420: |
|
- | 2165 | case DRM_FORMAT_YVU420: |
|
- | 2166 | case DRM_FORMAT_YUV422: |
|
- | 2167 | case DRM_FORMAT_YVU422: |
|
- | 2168 | case DRM_FORMAT_YUV444: |
|
- | 2169 | case DRM_FORMAT_YVU444: |
|
- | 2170 | return 0; |
|
- | 2171 | default: |
|
- | 2172 | return -EINVAL; |
|
- | 2173 | } |
|
- | 2174 | } |
|
- | 2175 | ||
- | 2176 | static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) |
|
- | 2177 | { |
|
- | 2178 | int ret, hsub, vsub, num_planes, i; |
|
- | 2179 | ||
- | 2180 | ret = format_check(r); |
|
- | 2181 | if (ret) { |
|
- | 2182 | DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format); |
|
- | 2183 | return ret; |
|
- | 2184 | } |
|
- | 2185 | ||
- | 2186 | hsub = drm_format_horz_chroma_subsampling(r->pixel_format); |
|
- | 2187 | vsub = drm_format_vert_chroma_subsampling(r->pixel_format); |
|
- | 2188 | num_planes = drm_format_num_planes(r->pixel_format); |
|
- | 2189 | ||
- | 2190 | if (r->width == 0 || r->width % hsub) { |
|
- | 2191 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); |
|
- | 2192 | return -EINVAL; |
|
- | 2193 | } |
|
- | 2194 | ||
- | 2195 | if (r->height == 0 || r->height % vsub) { |
|
- | 2196 | DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); |
|
- | 2197 | return -EINVAL; |
|
- | 2198 | } |
|
- | 2199 | ||
- | 2200 | for (i = 0; i < num_planes; i++) { |
|
- | 2201 | unsigned int width = r->width / (i != 0 ? hsub : 1); |
|
- | 2202 | ||
- | 2203 | if (!r->handles[i]) { |
|
- | 2204 | DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); |
|
- | 2205 | return -EINVAL; |
|
- | 2206 | } |
|
- | 2207 | ||
- | 2208 | if (r->pitches[i] < drm_format_plane_cpp(r->pixel_format, i) * width) { |
|
- | 2209 | DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); |
|
- | 2210 | return -EINVAL; |
|
- | 2211 | } |
|
- | 2212 | } |
|
- | 2213 | ||
- | 2214 | return 0; |
|
- | 2215 | } |
|
- | 2216 | ||
- | 2217 | /** |
|
- | 2218 | * drm_mode_addfb2 - add an FB to the graphics configuration |
|
- | 2219 | * @inode: inode from the ioctl |
|
- | 2220 | * @filp: file * from the ioctl |
|
- | 2221 | * @cmd: cmd from ioctl |
|
- | 2222 | * @arg: arg from ioctl |
|
- | 2223 | * |
|
- | 2224 | * LOCKING: |
|
- | 2225 | * Takes mode config lock. |
|
- | 2226 | * |
|
- | 2227 | * Add a new FB to the specified CRTC, given a user request with format. |
|
- | 2228 | * |
|
- | 2229 | * Called by the user via ioctl. |
|
- | 2230 | * |
|
- | 2231 | * RETURNS: |
|
- | 2232 | * Zero on success, errno on failure. |
|
- | 2233 | */ |
|
- | 2234 | int drm_mode_addfb2(struct drm_device *dev, |
|
- | 2235 | void *data, struct drm_file *file_priv) |
|
- | 2236 | { |
|
- | 2237 | struct drm_mode_fb_cmd2 *r = data; |
|
- | 2238 | struct drm_mode_config *config = &dev->mode_config; |
|
- | 2239 | struct drm_framebuffer *fb; |
|
- | 2240 | int ret; |
|
1688 | 2241 | ||
1689 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2242 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 1690... | Line 2243... | ||
1690 | return -EINVAL; |
2243 | return -EINVAL; |
1691 | 2244 | ||
- | 2245 | if ((config->min_width > r->width) || (r->width > config->max_width)) { |
|
1692 | if ((config->min_width > r->width) || (r->width > config->max_width)) { |
2246 | DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", |
1693 | DRM_ERROR("mode new framebuffer width not within limits\n"); |
2247 | r->width, config->min_width, config->max_width); |
1694 | return -EINVAL; |
2248 | return -EINVAL; |
1695 | } |
2249 | } |
- | 2250 | if ((config->min_height > r->height) || (r->height > config->max_height)) { |
|
1696 | if ((config->min_height > r->height) || (r->height > config->max_height)) { |
2251 | DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", |
1697 | DRM_ERROR("mode new framebuffer height not within limits\n"); |
2252 | r->height, config->min_height, config->max_height); |
Line 1698... | Line 2253... | ||
1698 | return -EINVAL; |
2253 | return -EINVAL; |
- | 2254 | } |
|
- | 2255 | ||
Line 1699... | Line 2256... | ||
1699 | } |
2256 | ret = framebuffer_check(r); |
1700 | - | ||
Line 1701... | Line 2257... | ||
1701 | mutex_lock(&dev->mode_config.mutex); |
2257 | if (ret) |
1702 | 2258 | return ret; |
|
1703 | /* TODO check buffer is sufficiently large */ |
2259 | |
1704 | /* TODO setup destructor callback */ |
2260 | mutex_lock(&dev->mode_config.mutex); |
1705 | 2261 | ||
1706 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
2262 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
Line 1707... | Line 2263... | ||
1707 | if (IS_ERR(fb)) { |
2263 | if (IS_ERR(fb)) { |
Line 1751... | Line 2307... | ||
1751 | 2307 | ||
1752 | mutex_lock(&dev->mode_config.mutex); |
2308 | mutex_lock(&dev->mode_config.mutex); |
1753 | obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); |
2309 | obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); |
1754 | /* TODO check that we really get a framebuffer back. */ |
2310 | /* TODO check that we really get a framebuffer back. */ |
1755 | if (!obj) { |
- | |
1756 | DRM_ERROR("mode invalid framebuffer id\n"); |
2311 | if (!obj) { |
1757 | ret = -EINVAL; |
2312 | ret = -EINVAL; |
1758 | goto out; |
2313 | goto out; |
1759 | } |
2314 | } |
Line 1760... | Line 2315... | ||
1760 | fb = obj_to_fb(obj); |
2315 | fb = obj_to_fb(obj); |
1761 | 2316 | ||
1762 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) |
2317 | list_for_each_entry(fbl, &file_priv->fbs, filp_head) |
Line 1763... | Line 2318... | ||
1763 | if (fb == fbl) |
2318 | if (fb == fbl) |
1764 | found = 1; |
- | |
1765 | 2319 | found = 1; |
|
1766 | if (!found) { |
2320 | |
1767 | DRM_ERROR("tried to remove a fb that we didn't own\n"); |
2321 | if (!found) { |
Line 1768... | Line -... | ||
1768 | ret = -EINVAL; |
- | |
1769 | goto out; |
- | |
1770 | } |
- | |
1771 | - | ||
1772 | /* TODO release all crtc connected to the framebuffer */ |
2322 | ret = -EINVAL; |
Line 1773... | Line 2323... | ||
1773 | /* TODO unhock the destructor from the buffer object */ |
2323 | goto out; |
1774 | 2324 | } |
|
1775 | list_del(&fb->filp_head); |
2325 | |
1776 | fb->funcs->destroy(fb); |
2326 | drm_framebuffer_remove(fb); |
Line 1786... | Line 2336... | ||
1786 | * @filp: file * from the ioctl |
2336 | * @filp: file * from the ioctl |
1787 | * @cmd: cmd from ioctl |
2337 | * @cmd: cmd from ioctl |
1788 | * @arg: arg from ioctl |
2338 | * @arg: arg from ioctl |
1789 | * |
2339 | * |
1790 | * LOCKING: |
2340 | * LOCKING: |
1791 | * Caller? (FIXME) |
2341 | * Takes mode config lock. |
1792 | * |
2342 | * |
1793 | * Lookup the FB given its ID and return info about it. |
2343 | * Lookup the FB given its ID and return info about it. |
1794 | * |
2344 | * |
1795 | * Called by the user via ioctl. |
2345 | * Called by the user via ioctl. |
1796 | * |
2346 | * |
Line 1809... | Line 2359... | ||
1809 | return -EINVAL; |
2359 | return -EINVAL; |
Line 1810... | Line 2360... | ||
1810 | 2360 | ||
1811 | mutex_lock(&dev->mode_config.mutex); |
2361 | mutex_lock(&dev->mode_config.mutex); |
1812 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
2362 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
1813 | if (!obj) { |
- | |
1814 | DRM_ERROR("invalid framebuffer id\n"); |
2363 | if (!obj) { |
1815 | ret = -EINVAL; |
2364 | ret = -EINVAL; |
1816 | goto out; |
2365 | goto out; |
1817 | } |
2366 | } |
Line 1818... | Line 2367... | ||
1818 | fb = obj_to_fb(obj); |
2367 | fb = obj_to_fb(obj); |
1819 | 2368 | ||
1820 | r->height = fb->height; |
2369 | r->height = fb->height; |
1821 | r->width = fb->width; |
2370 | r->width = fb->width; |
1822 | r->depth = fb->depth; |
2371 | r->depth = fb->depth; |
1823 | r->bpp = fb->bits_per_pixel; |
2372 | r->bpp = fb->bits_per_pixel; |
Line 1824... | Line 2373... | ||
1824 | r->pitch = fb->pitch; |
2373 | r->pitch = fb->pitches[0]; |
1825 | fb->funcs->create_handle(fb, file_priv, &r->handle); |
2374 | fb->funcs->create_handle(fb, file_priv, &r->handle); |
1826 | 2375 | ||
Line 1837... | Line 2386... | ||
1837 | struct drm_mode_fb_dirty_cmd *r = data; |
2386 | struct drm_mode_fb_dirty_cmd *r = data; |
1838 | struct drm_mode_object *obj; |
2387 | struct drm_mode_object *obj; |
1839 | struct drm_framebuffer *fb; |
2388 | struct drm_framebuffer *fb; |
1840 | unsigned flags; |
2389 | unsigned flags; |
1841 | int num_clips; |
2390 | int num_clips; |
1842 | int ret = 0; |
2391 | int ret; |
Line 1843... | Line 2392... | ||
1843 | 2392 | ||
1844 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2393 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 1845... | Line 2394... | ||
1845 | return -EINVAL; |
2394 | return -EINVAL; |
1846 | 2395 | ||
1847 | mutex_lock(&dev->mode_config.mutex); |
2396 | mutex_lock(&dev->mode_config.mutex); |
1848 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
- | |
1849 | if (!obj) { |
2397 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
1850 | DRM_ERROR("invalid framebuffer id\n"); |
2398 | if (!obj) { |
1851 | ret = -EINVAL; |
2399 | ret = -EINVAL; |
1852 | goto out_err1; |
2400 | goto out_err1; |
Line 1853... | Line 2401... | ||
1853 | } |
2401 | } |
1854 | fb = obj_to_fb(obj); |
2402 | fb = obj_to_fb(obj); |
Line 1855... | Line 2403... | ||
1855 | 2403 | ||
1856 | num_clips = r->num_clips; |
2404 | num_clips = r->num_clips; |
1857 | clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; |
2405 | clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; |
1858 | 2406 | ||
Line 1868... | Line 2416... | ||
1868 | ret = -EINVAL; |
2416 | ret = -EINVAL; |
1869 | goto out_err1; |
2417 | goto out_err1; |
1870 | } |
2418 | } |
Line 1871... | Line 2419... | ||
1871 | 2419 | ||
- | 2420 | if (num_clips && clips_ptr) { |
|
- | 2421 | if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { |
|
- | 2422 | ret = -EINVAL; |
|
- | 2423 | goto out_err1; |
|
1872 | if (num_clips && clips_ptr) { |
2424 | } |
1873 | clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); |
2425 | clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); |
1874 | if (!clips) { |
2426 | if (!clips) { |
1875 | ret = -ENOMEM; |
2427 | ret = -ENOMEM; |
1876 | goto out_err1; |
2428 | goto out_err1; |
Line 1919... | Line 2471... | ||
1919 | struct drm_device *dev = priv->minor->dev; |
2471 | struct drm_device *dev = priv->minor->dev; |
1920 | struct drm_framebuffer *fb, *tfb; |
2472 | struct drm_framebuffer *fb, *tfb; |
Line 1921... | Line 2473... | ||
1921 | 2473 | ||
1922 | mutex_lock(&dev->mode_config.mutex); |
2474 | mutex_lock(&dev->mode_config.mutex); |
1923 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
- | |
1924 | list_del(&fb->filp_head); |
2475 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
1925 | fb->funcs->destroy(fb); |
2476 | drm_framebuffer_remove(fb); |
1926 | } |
2477 | } |
1927 | mutex_unlock(&dev->mode_config.mutex); |
2478 | mutex_unlock(&dev->mode_config.mutex); |
1928 | } |
2479 | } |
Line 1934... | Line 2485... | ||
1934 | * @connector: connector to add the mode to |
2485 | * @connector: connector to add the mode to |
1935 | * @mode: mode to add |
2486 | * @mode: mode to add |
1936 | * |
2487 | * |
1937 | * Add @mode to @connector's user mode list. |
2488 | * Add @mode to @connector's user mode list. |
1938 | */ |
2489 | */ |
1939 | static int drm_mode_attachmode(struct drm_device *dev, |
2490 | static void drm_mode_attachmode(struct drm_device *dev, |
1940 | struct drm_connector *connector, |
2491 | struct drm_connector *connector, |
1941 | struct drm_display_mode *mode) |
2492 | struct drm_display_mode *mode) |
1942 | { |
2493 | { |
1943 | int ret = 0; |
- | |
1944 | - | ||
1945 | list_add_tail(&mode->head, &connector->user_modes); |
2494 | list_add_tail(&mode->head, &connector->user_modes); |
1946 | return ret; |
- | |
1947 | } |
2495 | } |
Line 1948... | Line 2496... | ||
1948 | 2496 | ||
1949 | int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, |
2497 | int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, |
1950 | struct drm_display_mode *mode) |
2498 | const struct drm_display_mode *mode) |
1951 | { |
2499 | { |
1952 | struct drm_connector *connector; |
2500 | struct drm_connector *connector; |
1953 | int ret = 0; |
2501 | int ret = 0; |
1954 | struct drm_display_mode *dup_mode; |
2502 | struct drm_display_mode *dup_mode, *next; |
- | 2503 | LIST_HEAD(list); |
|
1955 | int need_dup = 0; |
2504 | |
1956 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
2505 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
1957 | if (!connector->encoder) |
2506 | if (!connector->encoder) |
1958 | break; |
2507 | continue; |
1959 | if (connector->encoder->crtc == crtc) { |
- | |
1960 | if (need_dup) |
2508 | if (connector->encoder->crtc == crtc) { |
1961 | dup_mode = drm_mode_duplicate(dev, mode); |
- | |
1962 | else |
2509 | dup_mode = drm_mode_duplicate(dev, mode); |
1963 | dup_mode = mode; |
- | |
1964 | ret = drm_mode_attachmode(dev, connector, dup_mode); |
- | |
1965 | if (ret) |
2510 | if (!dup_mode) { |
1966 | return ret; |
2511 | ret = -ENOMEM; |
1967 | need_dup = 1; |
2512 | goto out; |
- | 2513 | } |
|
1968 | } |
2514 | list_add_tail(&dup_mode->head, &list); |
- | 2515 | } |
|
- | 2516 | } |
|
- | 2517 | ||
- | 2518 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
- | 2519 | if (!connector->encoder) |
|
- | 2520 | continue; |
|
- | 2521 | if (connector->encoder->crtc == crtc) |
|
- | 2522 | list_move_tail(list.next, &connector->user_modes); |
|
- | 2523 | } |
|
- | 2524 | ||
- | 2525 | WARN_ON(!list_empty(&list)); |
|
- | 2526 | ||
- | 2527 | out: |
|
- | 2528 | list_for_each_entry_safe(dup_mode, next, &list, head) |
|
- | 2529 | drm_mode_destroy(dev, dup_mode); |
|
1969 | } |
2530 | |
1970 | return 0; |
2531 | return ret; |
1971 | } |
2532 | } |
Line 1972... | Line 2533... | ||
1972 | EXPORT_SYMBOL(drm_mode_attachmode_crtc); |
2533 | EXPORT_SYMBOL(drm_mode_attachmode_crtc); |
1973 | 2534 | ||
Line 2026... | Line 2587... | ||
2026 | struct drm_mode_mode_cmd *mode_cmd = data; |
2587 | struct drm_mode_mode_cmd *mode_cmd = data; |
2027 | struct drm_connector *connector; |
2588 | struct drm_connector *connector; |
2028 | struct drm_display_mode *mode; |
2589 | struct drm_display_mode *mode; |
2029 | struct drm_mode_object *obj; |
2590 | struct drm_mode_object *obj; |
2030 | struct drm_mode_modeinfo *umode = &mode_cmd->mode; |
2591 | struct drm_mode_modeinfo *umode = &mode_cmd->mode; |
2031 | int ret = 0; |
2592 | int ret; |
Line 2032... | Line 2593... | ||
2032 | 2593 | ||
2033 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2594 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2034... | Line 2595... | ||
2034 | return -EINVAL; |
2595 | return -EINVAL; |
Line 2046... | Line 2607... | ||
2046 | if (!mode) { |
2607 | if (!mode) { |
2047 | ret = -ENOMEM; |
2608 | ret = -ENOMEM; |
2048 | goto out; |
2609 | goto out; |
2049 | } |
2610 | } |
Line 2050... | Line 2611... | ||
2050 | 2611 | ||
- | 2612 | ret = drm_crtc_convert_umode(mode, umode); |
|
- | 2613 | if (ret) { |
|
- | 2614 | DRM_DEBUG_KMS("Invalid mode\n"); |
|
- | 2615 | drm_mode_destroy(dev, mode); |
|
- | 2616 | goto out; |
|
Line 2051... | Line 2617... | ||
2051 | drm_crtc_convert_umode(mode, umode); |
2617 | } |
2052 | 2618 | ||
2053 | ret = drm_mode_attachmode(dev, connector, mode); |
2619 | drm_mode_attachmode(dev, connector, mode); |
2054 | out: |
2620 | out: |
2055 | mutex_unlock(&dev->mode_config.mutex); |
2621 | mutex_unlock(&dev->mode_config.mutex); |
Line 2075... | Line 2641... | ||
2075 | struct drm_mode_object *obj; |
2641 | struct drm_mode_object *obj; |
2076 | struct drm_mode_mode_cmd *mode_cmd = data; |
2642 | struct drm_mode_mode_cmd *mode_cmd = data; |
2077 | struct drm_connector *connector; |
2643 | struct drm_connector *connector; |
2078 | struct drm_display_mode mode; |
2644 | struct drm_display_mode mode; |
2079 | struct drm_mode_modeinfo *umode = &mode_cmd->mode; |
2645 | struct drm_mode_modeinfo *umode = &mode_cmd->mode; |
2080 | int ret = 0; |
2646 | int ret; |
Line 2081... | Line 2647... | ||
2081 | 2647 | ||
2082 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2648 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2083... | Line 2649... | ||
2083 | return -EINVAL; |
2649 | return -EINVAL; |
Line 2089... | Line 2655... | ||
2089 | ret = -EINVAL; |
2655 | ret = -EINVAL; |
2090 | goto out; |
2656 | goto out; |
2091 | } |
2657 | } |
2092 | connector = obj_to_connector(obj); |
2658 | connector = obj_to_connector(obj); |
Line 2093... | Line 2659... | ||
2093 | 2659 | ||
- | 2660 | ret = drm_crtc_convert_umode(&mode, umode); |
|
- | 2661 | if (ret) { |
|
- | 2662 | DRM_DEBUG_KMS("Invalid mode\n"); |
|
- | 2663 | goto out; |
|
- | 2664 | } |
|
2094 | drm_crtc_convert_umode(&mode, umode); |
2665 | |
2095 | ret = drm_mode_detachmode(dev, connector, &mode); |
2666 | ret = drm_mode_detachmode(dev, connector, &mode); |
2096 | out: |
2667 | out: |
2097 | mutex_unlock(&dev->mode_config.mutex); |
2668 | mutex_unlock(&dev->mode_config.mutex); |
2098 | return ret; |
2669 | return ret; |
Line 2101... | Line 2672... | ||
2101 | 2672 | ||
2102 | struct drm_property *drm_property_create(struct drm_device *dev, int flags, |
2673 | struct drm_property *drm_property_create(struct drm_device *dev, int flags, |
2103 | const char *name, int num_values) |
2674 | const char *name, int num_values) |
2104 | { |
2675 | { |
- | 2676 | struct drm_property *property = NULL; |
|
Line 2105... | Line 2677... | ||
2105 | struct drm_property *property = NULL; |
2677 | int ret; |
2106 | 2678 | ||
2107 | property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); |
2679 | property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); |
Line 2112... | Line 2684... | ||
2112 | property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); |
2684 | property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); |
2113 | if (!property->values) |
2685 | if (!property->values) |
2114 | goto fail; |
2686 | goto fail; |
2115 | } |
2687 | } |
Line 2116... | Line 2688... | ||
2116 | 2688 | ||
- | 2689 | ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); |
|
- | 2690 | if (ret) |
|
- | 2691 | goto fail; |
|
2117 | drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); |
2692 | |
2118 | property->flags = flags; |
2693 | property->flags = flags; |
2119 | property->num_values = num_values; |
2694 | property->num_values = num_values; |
Line 2120... | Line 2695... | ||
2120 | INIT_LIST_HEAD(&property->enum_blob_list); |
2695 | INIT_LIST_HEAD(&property->enum_blob_list); |
2121 | 2696 | ||
- | 2697 | if (name) { |
|
- | 2698 | strncpy(property->name, name, DRM_PROP_NAME_LEN); |
|
Line 2122... | Line 2699... | ||
2122 | if (name) |
2699 | property->name[DRM_PROP_NAME_LEN-1] = '\0'; |
2123 | strncpy(property->name, name, DRM_PROP_NAME_LEN); |
2700 | } |
2124 | 2701 | ||
- | 2702 | list_add_tail(&property->head, &dev->mode_config.property_list); |
|
2125 | list_add_tail(&property->head, &dev->mode_config.property_list); |
2703 | return property; |
2126 | return property; |
2704 | fail: |
2127 | fail: |
2705 | kfree(property->values); |
2128 | kfree(property); |
2706 | kfree(property); |
Line -... | Line 2707... | ||
- | 2707 | return NULL; |
|
- | 2708 | } |
|
- | 2709 | EXPORT_SYMBOL(drm_property_create); |
|
- | 2710 | ||
- | 2711 | struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, |
|
- | 2712 | const char *name, |
|
- | 2713 | const struct drm_prop_enum_list *props, |
|
- | 2714 | int num_values) |
|
- | 2715 | { |
|
- | 2716 | struct drm_property *property; |
|
- | 2717 | int i, ret; |
|
- | 2718 | ||
- | 2719 | flags |= DRM_MODE_PROP_ENUM; |
|
- | 2720 | ||
- | 2721 | property = drm_property_create(dev, flags, name, num_values); |
|
- | 2722 | if (!property) |
|
- | 2723 | return NULL; |
|
- | 2724 | ||
- | 2725 | for (i = 0; i < num_values; i++) { |
|
- | 2726 | ret = drm_property_add_enum(property, i, |
|
- | 2727 | props[i].type, |
|
- | 2728 | props[i].name); |
|
- | 2729 | if (ret) { |
|
- | 2730 | drm_property_destroy(dev, property); |
|
- | 2731 | return NULL; |
|
- | 2732 | } |
|
- | 2733 | } |
|
- | 2734 | ||
- | 2735 | return property; |
|
- | 2736 | } |
|
- | 2737 | EXPORT_SYMBOL(drm_property_create_enum); |
|
- | 2738 | ||
- | 2739 | struct drm_property *drm_property_create_bitmask(struct drm_device *dev, |
|
- | 2740 | int flags, const char *name, |
|
- | 2741 | const struct drm_prop_enum_list *props, |
|
- | 2742 | int num_values) |
|
- | 2743 | { |
|
- | 2744 | struct drm_property *property; |
|
- | 2745 | int i, ret; |
|
- | 2746 | ||
- | 2747 | flags |= DRM_MODE_PROP_BITMASK; |
|
- | 2748 | ||
- | 2749 | property = drm_property_create(dev, flags, name, num_values); |
|
- | 2750 | if (!property) |
|
- | 2751 | return NULL; |
|
- | 2752 | ||
- | 2753 | for (i = 0; i < num_values; i++) { |
|
- | 2754 | ret = drm_property_add_enum(property, i, |
|
- | 2755 | props[i].type, |
|
- | 2756 | props[i].name); |
|
- | 2757 | if (ret) { |
|
- | 2758 | drm_property_destroy(dev, property); |
|
- | 2759 | return NULL; |
|
- | 2760 | } |
|
- | 2761 | } |
|
- | 2762 | ||
- | 2763 | return property; |
|
- | 2764 | } |
|
- | 2765 | EXPORT_SYMBOL(drm_property_create_bitmask); |
|
- | 2766 | ||
- | 2767 | struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, |
|
- | 2768 | const char *name, |
|
- | 2769 | uint64_t min, uint64_t max) |
|
- | 2770 | { |
|
- | 2771 | struct drm_property *property; |
|
- | 2772 | ||
- | 2773 | flags |= DRM_MODE_PROP_RANGE; |
|
- | 2774 | ||
- | 2775 | property = drm_property_create(dev, flags, name, 2); |
|
- | 2776 | if (!property) |
|
- | 2777 | return NULL; |
|
- | 2778 | ||
- | 2779 | property->values[0] = min; |
|
- | 2780 | property->values[1] = max; |
|
- | 2781 | ||
2129 | return NULL; |
2782 | return property; |
2130 | } |
2783 | } |
2131 | EXPORT_SYMBOL(drm_property_create); |
2784 | EXPORT_SYMBOL(drm_property_create_range); |
2132 | 2785 | ||
Line -... | Line 2786... | ||
- | 2786 | int drm_property_add_enum(struct drm_property *property, int index, |
|
- | 2787 | uint64_t value, const char *name) |
|
- | 2788 | { |
|
- | 2789 | struct drm_property_enum *prop_enum; |
|
- | 2790 | ||
- | 2791 | if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) |
|
- | 2792 | return -EINVAL; |
|
2133 | int drm_property_add_enum(struct drm_property *property, int index, |
2793 | |
2134 | uint64_t value, const char *name) |
2794 | /* |
Line 2135... | Line 2795... | ||
2135 | { |
2795 | * Bitmask enum properties have the additional constraint of values |
2136 | struct drm_property_enum *prop_enum; |
2796 | * from 0 to 63 |
2137 | 2797 | */ |
|
Line 2177... | Line 2837... | ||
2177 | list_del(&property->head); |
2837 | list_del(&property->head); |
2178 | kfree(property); |
2838 | kfree(property); |
2179 | } |
2839 | } |
2180 | EXPORT_SYMBOL(drm_property_destroy); |
2840 | EXPORT_SYMBOL(drm_property_destroy); |
Line 2181... | Line 2841... | ||
2181 | 2841 | ||
2182 | int drm_connector_attach_property(struct drm_connector *connector, |
2842 | void drm_connector_attach_property(struct drm_connector *connector, |
2183 | struct drm_property *property, uint64_t init_val) |
2843 | struct drm_property *property, uint64_t init_val) |
- | 2844 | { |
|
2184 | { |
2845 | drm_object_attach_property(&connector->base, property, init_val); |
- | 2846 | } |
|
Line 2185... | Line -... | ||
2185 | int i; |
- | |
2186 | 2847 | EXPORT_SYMBOL(drm_connector_attach_property); |
|
2187 | for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { |
2848 | |
- | 2849 | int drm_connector_property_set_value(struct drm_connector *connector, |
|
2188 | if (connector->property_ids[i] == 0) { |
2850 | struct drm_property *property, uint64_t value) |
2189 | connector->property_ids[i] = property->base.id; |
- | |
2190 | connector->property_values[i] = init_val; |
2851 | { |
- | 2852 | return drm_object_property_set_value(&connector->base, property, value); |
|
- | 2853 | } |
|
- | 2854 | EXPORT_SYMBOL(drm_connector_property_set_value); |
|
- | 2855 | ||
- | 2856 | int drm_connector_property_get_value(struct drm_connector *connector, |
|
- | 2857 | struct drm_property *property, uint64_t *val) |
|
2191 | break; |
2858 | { |
- | 2859 | return drm_object_property_get_value(&connector->base, property, val); |
|
Line -... | Line 2860... | ||
- | 2860 | } |
|
- | 2861 | EXPORT_SYMBOL(drm_connector_property_get_value); |
|
- | 2862 | ||
- | 2863 | void drm_object_attach_property(struct drm_mode_object *obj, |
|
- | 2864 | struct drm_property *property, |
|
- | 2865 | uint64_t init_val) |
|
2192 | } |
2866 | { |
- | 2867 | int count = obj->properties->count; |
|
- | 2868 | ||
- | 2869 | if (count == DRM_OBJECT_MAX_PROPERTY) { |
|
2193 | } |
2870 | WARN(1, "Failed to attach object property (type: 0x%x). Please " |
2194 | 2871 | "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " |
|
2195 | if (i == DRM_CONNECTOR_MAX_PROPERTY) |
2872 | "you see this message on the same object type.\n", |
2196 | return -EINVAL; |
- | |
Line -... | Line 2873... | ||
- | 2873 | obj->type); |
|
- | 2874 | return; |
|
- | 2875 | } |
|
- | 2876 | ||
- | 2877 | obj->properties->ids[count] = property->base.id; |
|
- | 2878 | obj->properties->values[count] = init_val; |
|
2197 | return 0; |
2879 | obj->properties->count++; |
2198 | } |
2880 | } |
2199 | EXPORT_SYMBOL(drm_connector_attach_property); |
2881 | EXPORT_SYMBOL(drm_object_attach_property); |
2200 | 2882 | ||
Line 2201... | Line 2883... | ||
2201 | int drm_connector_property_set_value(struct drm_connector *connector, |
2883 | int drm_object_property_set_value(struct drm_mode_object *obj, |
2202 | struct drm_property *property, uint64_t value) |
2884 | struct drm_property *property, uint64_t val) |
2203 | { |
2885 | { |
2204 | int i; |
2886 | int i; |
2205 | 2887 | ||
2206 | for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { |
2888 | for (i = 0; i < obj->properties->count; i++) { |
Line 2207... | Line -... | ||
2207 | if (connector->property_ids[i] == property->base.id) { |
- | |
2208 | connector->property_values[i] = value; |
2889 | if (obj->properties->ids[i] == property->base.id) { |
2209 | break; |
- | |
2210 | } |
2890 | obj->properties->values[i] = val; |
2211 | } |
2891 | return 0; |
Line 2212... | Line 2892... | ||
2212 | 2892 | } |
|
2213 | if (i == DRM_CONNECTOR_MAX_PROPERTY) |
2893 | } |
2214 | return -EINVAL; |
2894 | |
2215 | return 0; |
2895 | return -EINVAL; |
Line 2216... | Line 2896... | ||
2216 | } |
2896 | } |
2217 | EXPORT_SYMBOL(drm_connector_property_set_value); |
2897 | EXPORT_SYMBOL(drm_object_property_set_value); |
2218 | 2898 | ||
2219 | int drm_connector_property_get_value(struct drm_connector *connector, |
2899 | int drm_object_property_get_value(struct drm_mode_object *obj, |
2220 | struct drm_property *property, uint64_t *val) |
2900 | struct drm_property *property, uint64_t *val) |
2221 | { |
2901 | { |
Line 2222... | Line -... | ||
2222 | int i; |
- | |
2223 | 2902 | int i; |
|
2224 | for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { |
- | |
2225 | if (connector->property_ids[i] == property->base.id) { |
2903 | |
2226 | *val = connector->property_values[i]; |
2904 | for (i = 0; i < obj->properties->count; i++) { |
Line 2227... | Line 2905... | ||
2227 | break; |
2905 | if (obj->properties->ids[i] == property->base.id) { |
2228 | } |
2906 | *val = obj->properties->values[i]; |
2229 | } |
2907 | return 0; |
2230 | 2908 | } |
|
Line 2247... | Line 2925... | ||
2247 | int ret = 0, i; |
2925 | int ret = 0, i; |
2248 | int copied; |
2926 | int copied; |
2249 | struct drm_property_enum *prop_enum; |
2927 | struct drm_property_enum *prop_enum; |
2250 | struct drm_mode_property_enum __user *enum_ptr; |
2928 | struct drm_mode_property_enum __user *enum_ptr; |
2251 | struct drm_property_blob *prop_blob; |
2929 | struct drm_property_blob *prop_blob; |
2252 | uint32_t *blob_id_ptr; |
2930 | uint32_t __user *blob_id_ptr; |
2253 | uint64_t __user *values_ptr; |
2931 | uint64_t __user *values_ptr; |
2254 | uint32_t __user *blob_length_ptr; |
2932 | uint32_t __user *blob_length_ptr; |
Line 2255... | Line 2933... | ||
2255 | 2933 | ||
2256 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2934 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2262... | Line 2940... | ||
2262 | ret = -EINVAL; |
2940 | ret = -EINVAL; |
2263 | goto done; |
2941 | goto done; |
2264 | } |
2942 | } |
2265 | property = obj_to_property(obj); |
2943 | property = obj_to_property(obj); |
Line 2266... | Line 2944... | ||
2266 | 2944 | ||
2267 | if (property->flags & DRM_MODE_PROP_ENUM) { |
2945 | if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { |
2268 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) |
2946 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) |
2269 | enum_count++; |
2947 | enum_count++; |
2270 | } else if (property->flags & DRM_MODE_PROP_BLOB) { |
2948 | } else if (property->flags & DRM_MODE_PROP_BLOB) { |
2271 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) |
2949 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) |
Line 2277... | Line 2955... | ||
2277 | strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); |
2955 | strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); |
2278 | out_resp->name[DRM_PROP_NAME_LEN-1] = 0; |
2956 | out_resp->name[DRM_PROP_NAME_LEN-1] = 0; |
2279 | out_resp->flags = property->flags; |
2957 | out_resp->flags = property->flags; |
Line 2280... | Line 2958... | ||
2280 | 2958 | ||
2281 | if ((out_resp->count_values >= value_count) && value_count) { |
2959 | if ((out_resp->count_values >= value_count) && value_count) { |
2282 | values_ptr = (uint64_t *)(unsigned long)out_resp->values_ptr; |
2960 | values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr; |
2283 | for (i = 0; i < value_count; i++) { |
2961 | for (i = 0; i < value_count; i++) { |
2284 | if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { |
2962 | if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { |
2285 | ret = -EFAULT; |
2963 | ret = -EFAULT; |
2286 | goto done; |
2964 | goto done; |
2287 | } |
2965 | } |
2288 | } |
2966 | } |
2289 | } |
2967 | } |
Line 2290... | Line 2968... | ||
2290 | out_resp->count_values = value_count; |
2968 | out_resp->count_values = value_count; |
2291 | 2969 | ||
2292 | if (property->flags & DRM_MODE_PROP_ENUM) { |
2970 | if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { |
2293 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { |
2971 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { |
2294 | copied = 0; |
2972 | copied = 0; |
Line 2295... | Line 2973... | ||
2295 | enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; |
2973 | enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; |
2296 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) { |
2974 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) { |
2297 | 2975 | ||
Line 2312... | Line 2990... | ||
2312 | } |
2990 | } |
Line 2313... | Line 2991... | ||
2313 | 2991 | ||
2314 | if (property->flags & DRM_MODE_PROP_BLOB) { |
2992 | if (property->flags & DRM_MODE_PROP_BLOB) { |
2315 | if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { |
2993 | if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { |
2316 | copied = 0; |
2994 | copied = 0; |
2317 | blob_id_ptr = (uint32_t *)(unsigned long)out_resp->enum_blob_ptr; |
2995 | blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; |
Line 2318... | Line 2996... | ||
2318 | blob_length_ptr = (uint32_t *)(unsigned long)out_resp->values_ptr; |
2996 | blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr; |
2319 | 2997 | ||
2320 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) { |
2998 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) { |
2321 | if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { |
2999 | if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { |
Line 2341... | Line 3019... | ||
2341 | 3019 | ||
2342 | static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, |
3020 | static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, |
2343 | void *data) |
3021 | void *data) |
2344 | { |
3022 | { |
- | 3023 | struct drm_property_blob *blob; |
|
Line 2345... | Line 3024... | ||
2345 | struct drm_property_blob *blob; |
3024 | int ret; |
2346 | 3025 | ||
Line 2347... | Line 3026... | ||
2347 | if (!length || !data) |
3026 | if (!length || !data) |
2348 | return NULL; |
3027 | return NULL; |
2349 | 3028 | ||
Line 2350... | Line 3029... | ||
2350 | blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); |
3029 | blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); |
- | 3030 | if (!blob) |
|
- | 3031 | return NULL; |
|
- | 3032 | ||
- | 3033 | ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); |
|
- | 3034 | if (ret) { |
|
2351 | if (!blob) |
3035 | kfree(blob); |
Line 2352... | Line 3036... | ||
2352 | return NULL; |
3036 | return NULL; |
Line 2353... | Line -... | ||
2353 | - | ||
2354 | blob->data = (void *)((char *)blob + sizeof(struct drm_property_blob)); |
- | |
2355 | blob->length = length; |
3037 | } |
2356 | 3038 | ||
2357 | memcpy(blob->data, data, length); |
3039 | blob->length = length; |
Line 2358... | Line 3040... | ||
2358 | 3040 | ||
Line 2376... | Line 3058... | ||
2376 | { |
3058 | { |
2377 | struct drm_mode_object *obj; |
3059 | struct drm_mode_object *obj; |
2378 | struct drm_mode_get_blob *out_resp = data; |
3060 | struct drm_mode_get_blob *out_resp = data; |
2379 | struct drm_property_blob *blob; |
3061 | struct drm_property_blob *blob; |
2380 | int ret = 0; |
3062 | int ret = 0; |
2381 | void *blob_ptr; |
3063 | void __user *blob_ptr; |
Line 2382... | Line 3064... | ||
2382 | 3064 | ||
2383 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3065 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2384... | Line 3066... | ||
2384 | return -EINVAL; |
3066 | return -EINVAL; |
Line 2390... | Line 3072... | ||
2390 | goto done; |
3072 | goto done; |
2391 | } |
3073 | } |
2392 | blob = obj_to_blob(obj); |
3074 | blob = obj_to_blob(obj); |
Line 2393... | Line 3075... | ||
2393 | 3075 | ||
2394 | if (out_resp->length == blob->length) { |
3076 | if (out_resp->length == blob->length) { |
2395 | blob_ptr = (void *)(unsigned long)out_resp->data; |
3077 | blob_ptr = (void __user *)(unsigned long)out_resp->data; |
2396 | if (copy_to_user(blob_ptr, blob->data, blob->length)){ |
3078 | if (copy_to_user(blob_ptr, blob->data, blob->length)){ |
2397 | ret = -EFAULT; |
3079 | ret = -EFAULT; |
2398 | goto done; |
3080 | goto done; |
2399 | } |
3081 | } |
Line 2408... | Line 3090... | ||
2408 | 3090 | ||
2409 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
3091 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
2410 | struct edid *edid) |
3092 | struct edid *edid) |
2411 | { |
3093 | { |
2412 | struct drm_device *dev = connector->dev; |
3094 | struct drm_device *dev = connector->dev; |
Line 2413... | Line 3095... | ||
2413 | int ret = 0, size; |
3095 | int ret, size; |
2414 | 3096 | ||
Line 2415... | Line 3097... | ||
2415 | if (connector->edid_blob_ptr) |
3097 | if (connector->edid_blob_ptr) |
Line 2433... | Line 3115... | ||
2433 | return ret; |
3115 | return ret; |
2434 | } |
3116 | } |
2435 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); |
3117 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); |
Line 2436... | Line 3118... | ||
2436 | 3118 | ||
- | 3119 | #if 0 |
|
2437 | #if 0 |
3120 | |
- | 3121 | static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, |
|
- | 3122 | struct drm_property *property, |
|
- | 3123 | uint64_t value) |
|
- | 3124 | { |
|
- | 3125 | int ret = -EINVAL; |
|
- | 3126 | struct drm_connector *connector = obj_to_connector(obj); |
|
- | 3127 | ||
- | 3128 | /* Do DPMS ourselves */ |
|
- | 3129 | if (property == connector->dev->mode_config.dpms_property) { |
|
- | 3130 | if (connector->funcs->dpms) |
|
- | 3131 | (*connector->funcs->dpms)(connector, (int)value); |
|
- | 3132 | ret = 0; |
|
- | 3133 | } else if (connector->funcs->set_property) |
|
- | 3134 | ret = connector->funcs->set_property(connector, property, value); |
|
- | 3135 | ||
- | 3136 | /* store the property value if successful */ |
|
- | 3137 | if (!ret) |
|
- | 3138 | drm_connector_property_set_value(connector, property, value); |
|
- | 3139 | return ret; |
|
- | 3140 | } |
|
- | 3141 | ||
- | 3142 | static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, |
|
- | 3143 | struct drm_property *property, |
|
- | 3144 | uint64_t value) |
|
- | 3145 | { |
|
- | 3146 | int ret = -EINVAL; |
|
- | 3147 | struct drm_crtc *crtc = obj_to_crtc(obj); |
|
- | 3148 | ||
- | 3149 | if (crtc->funcs->set_property) |
|
- | 3150 | ret = crtc->funcs->set_property(crtc, property, value); |
|
- | 3151 | if (!ret) |
|
- | 3152 | drm_object_property_set_value(obj, property, value); |
|
- | 3153 | ||
- | 3154 | return ret; |
|
- | 3155 | } |
|
- | 3156 | ||
2438 | int drm_mode_connector_property_set_ioctl(struct drm_device *dev, |
3157 | static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj, |
- | 3158 | struct drm_property *property, |
|
2439 | void *data, struct drm_file *file_priv) |
3159 | uint64_t value) |
2440 | { |
- | |
2441 | struct drm_mode_connector_set_property *out_resp = data; |
- | |
2442 | struct drm_mode_object *obj; |
- | |
2443 | struct drm_property *property; |
- | |
2444 | struct drm_connector *connector; |
3160 | { |
- | 3161 | int ret = -EINVAL; |
|
- | 3162 | struct drm_plane *plane = obj_to_plane(obj); |
|
- | 3163 | ||
- | 3164 | if (plane->funcs->set_property) |
|
- | 3165 | ret = plane->funcs->set_property(plane, property, value); |
|
- | 3166 | if (!ret) |
|
- | 3167 | drm_object_property_set_value(obj, property, value); |
|
- | 3168 | ||
- | 3169 | return ret; |
|
- | 3170 | } |
|
- | 3171 | ||
- | 3172 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, |
|
- | 3173 | struct drm_file *file_priv) |
|
- | 3174 | { |
|
- | 3175 | struct drm_mode_obj_get_properties *arg = data; |
|
- | 3176 | struct drm_mode_object *obj; |
|
2445 | int ret = -EINVAL; |
3177 | int ret = 0; |
- | 3178 | int i; |
|
- | 3179 | int copied = 0; |
|
- | 3180 | int props_count = 0; |
|
- | 3181 | uint32_t __user *props_ptr; |
|
Line 2446... | Line 3182... | ||
2446 | int i; |
3182 | uint64_t __user *prop_values_ptr; |
2447 | 3183 | ||
Line 2448... | Line 3184... | ||
2448 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3184 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2449... | Line 3185... | ||
2449 | return -EINVAL; |
3185 | return -EINVAL; |
2450 | 3186 | ||
- | 3187 | mutex_lock(&dev->mode_config.mutex); |
|
2451 | mutex_lock(&dev->mode_config.mutex); |
3188 | |
2452 | 3189 | obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); |
|
2453 | obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); |
3190 | if (!obj) { |
2454 | if (!obj) { |
- | |
2455 | goto out; |
3191 | ret = -EINVAL; |
2456 | } |
- | |
2457 | connector = obj_to_connector(obj); |
3192 | goto out; |
2458 | 3193 | } |
|
Line -... | Line 3194... | ||
- | 3194 | if (!obj->properties) { |
|
- | 3195 | ret = -EINVAL; |
|
- | 3196 | goto out; |
|
- | 3197 | } |
|
- | 3198 | ||
- | 3199 | props_count = obj->properties->count; |
|
- | 3200 | ||
- | 3201 | /* This ioctl is called twice, once to determine how much space is |
|
- | 3202 | * needed, and the 2nd time to fill it. */ |
|
2459 | for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) { |
3203 | if ((arg->count_props >= props_count) && props_count) { |
- | 3204 | copied = 0; |
|
- | 3205 | props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); |
|
- | 3206 | prop_values_ptr = (uint64_t __user *)(unsigned long) |
|
2460 | if (connector->property_ids[i] == out_resp->prop_id) |
3207 | (arg->prop_values_ptr); |
2461 | break; |
3208 | for (i = 0; i < props_count; i++) { |
2462 | } |
- | |
2463 | 3209 | if (put_user(obj->properties->ids[i], |
|
- | 3210 | props_ptr + copied)) { |
|
2464 | if (i == DRM_CONNECTOR_MAX_PROPERTY) { |
3211 | ret = -EFAULT; |
2465 | goto out; |
3212 | goto out; |
2466 | } |
3213 | } |
- | 3214 | if (put_user(obj->properties->values[i], |
|
- | 3215 | prop_values_ptr + copied)) { |
|
- | 3216 | ret = -EFAULT; |
|
2467 | 3217 | goto out; |
|
- | 3218 | } |
|
- | 3219 | copied++; |
|
- | 3220 | } |
|
- | 3221 | } |
|
Line -... | Line 3222... | ||
- | 3222 | arg->count_props = props_count; |
|
- | 3223 | out: |
|
- | 3224 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 3225 | return ret; |
|
- | 3226 | } |
|
- | 3227 | ||
- | 3228 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, |
|
- | 3229 | struct drm_file *file_priv) |
|
- | 3230 | { |
|
- | 3231 | struct drm_mode_obj_set_property *arg = data; |
|
2468 | obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); |
3232 | struct drm_mode_object *arg_obj; |
- | 3233 | struct drm_mode_object *prop_obj; |
|
- | 3234 | struct drm_property *property; |
|
- | 3235 | int ret = -EINVAL; |
|
- | 3236 | int i; |
|
- | 3237 | ||
- | 3238 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
|
- | 3239 | return -EINVAL; |
|
- | 3240 | ||
2469 | if (!obj) { |
3241 | mutex_lock(&dev->mode_config.mutex); |
Line -... | Line 3242... | ||
- | 3242 | ||
2470 | goto out; |
3243 | arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); |
- | 3244 | if (!arg_obj) |
|
- | 3245 | goto out; |
|
2471 | } |
3246 | if (!arg_obj->properties) |
2472 | property = obj_to_property(obj); |
3247 | goto out; |
Line 2473... | Line 3248... | ||
2473 | 3248 | ||
- | 3249 | for (i = 0; i < arg_obj->properties->count; i++) |
|
- | 3250 | if (arg_obj->properties->ids[i] == arg->prop_id) |
|
2474 | if (property->flags & DRM_MODE_PROP_IMMUTABLE) |
3251 | break; |
2475 | goto out; |
- | |
2476 | - | ||
2477 | if (property->flags & DRM_MODE_PROP_RANGE) { |
3252 | |
2478 | if (out_resp->value < property->values[0]) |
- | |
2479 | goto out; |
- | |
2480 | - | ||
2481 | if (out_resp->value > property->values[1]) |
- | |
2482 | goto out; |
3253 | if (i == arg_obj->properties->count) |
2483 | } else { |
3254 | goto out; |
2484 | int found = 0; |
3255 | |
2485 | for (i = 0; i < property->num_values; i++) { |
- | |
2486 | if (property->values[i] == out_resp->value) { |
- | |
Line 2487... | Line 3256... | ||
2487 | found = 1; |
3256 | prop_obj = drm_mode_object_find(dev, arg->prop_id, |
- | 3257 | DRM_MODE_OBJECT_PROPERTY); |
|
2488 | break; |
3258 | if (!prop_obj) |
2489 | } |
3259 | goto out; |
- | 3260 | property = obj_to_property(prop_obj); |
|
- | 3261 | ||
2490 | } |
3262 | if (!drm_property_change_is_valid(property, arg->value)) |
2491 | if (!found) { |
3263 | goto out; |
2492 | goto out; |
3264 | |
2493 | } |
3265 | switch (arg_obj->type) { |
- | 3266 | case DRM_MODE_OBJECT_CONNECTOR: |
|
- | 3267 | ret = drm_mode_connector_set_obj_prop(arg_obj, property, |
|
Line 2494... | Line -... | ||
2494 | } |
- | |
2495 | - | ||
2496 | /* Do DPMS ourselves */ |
- | |
2497 | if (property == connector->dev->mode_config.dpms_property) { |
3268 | arg->value); |
2498 | if (connector->funcs->dpms) |
3269 | break; |
2499 | (*connector->funcs->dpms)(connector, (int) out_resp->value); |
3270 | case DRM_MODE_OBJECT_CRTC: |
2500 | ret = 0; |
3271 | ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); |
2501 | } else if (connector->funcs->set_property) |
3272 | break; |
Line 2538... | Line 3309... | ||
2538 | } |
3309 | } |
2539 | } |
3310 | } |
2540 | } |
3311 | } |
2541 | EXPORT_SYMBOL(drm_mode_connector_detach_encoder); |
3312 | EXPORT_SYMBOL(drm_mode_connector_detach_encoder); |
Line 2542... | Line 3313... | ||
2542 | 3313 | ||
2543 | bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
3314 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
2544 | int gamma_size) |
3315 | int gamma_size) |
2545 | { |
3316 | { |
Line 2546... | Line 3317... | ||
2546 | crtc->gamma_size = gamma_size; |
3317 | crtc->gamma_size = gamma_size; |
2547 | 3318 | ||
2548 | crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); |
3319 | crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); |
2549 | if (!crtc->gamma_store) { |
3320 | if (!crtc->gamma_store) { |
2550 | crtc->gamma_size = 0; |
3321 | crtc->gamma_size = 0; |
Line 2551... | Line 3322... | ||
2551 | return false; |
3322 | return -ENOMEM; |
2552 | } |
3323 | } |
2553 | 3324 | ||
Line 2554... | Line 3325... | ||
2554 | return true; |
3325 | return 0; |
2555 | } |
3326 | } |
Line 2575... | Line 3346... | ||
2575 | ret = -EINVAL; |
3346 | ret = -EINVAL; |
2576 | goto out; |
3347 | goto out; |
2577 | } |
3348 | } |
2578 | crtc = obj_to_crtc(obj); |
3349 | crtc = obj_to_crtc(obj); |
Line -... | Line 3350... | ||
- | 3350 | ||
- | 3351 | if (crtc->funcs->gamma_set == NULL) { |
|
- | 3352 | ret = -ENOSYS; |
|
- | 3353 | goto out; |
|
- | 3354 | } |
|
2579 | 3355 | ||
2580 | /* memcpy into gamma store */ |
3356 | /* memcpy into gamma store */ |
2581 | if (crtc_lut->gamma_size != crtc->gamma_size) { |
3357 | if (crtc_lut->gamma_size != crtc->gamma_size) { |
2582 | ret = -EINVAL; |
3358 | ret = -EINVAL; |
2583 | goto out; |
3359 | goto out; |
Line 2680... | Line 3456... | ||
2680 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
3456 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
2681 | if (connector->funcs->reset) |
3457 | if (connector->funcs->reset) |
2682 | connector->funcs->reset(connector); |
3458 | connector->funcs->reset(connector); |
2683 | } |
3459 | } |
2684 | EXPORT_SYMBOL(drm_mode_config_reset);>>>>>>>>>>>>>>>>>>>>>>>>>>> |
3460 | EXPORT_SYMBOL(drm_mode_config_reset); |
- | 3461 | /* |
|
- | 3462 | * Just need to support RGB formats here for compat with code that doesn't |
|
- | 3463 | * use pixel formats directly yet. |
|
- | 3464 | */ |
|
- | 3465 | void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, |
|
- | 3466 | int *bpp) |
|
- | 3467 | { |
|
- | 3468 | switch (format) { |
|
- | 3469 | case DRM_FORMAT_RGB332: |
|
- | 3470 | case DRM_FORMAT_BGR233: |
|
- | 3471 | *depth = 8; |
|
- | 3472 | *bpp = 8; |
|
- | 3473 | break; |
|
- | 3474 | case DRM_FORMAT_XRGB1555: |
|
- | 3475 | case DRM_FORMAT_XBGR1555: |
|
- | 3476 | case DRM_FORMAT_RGBX5551: |
|
- | 3477 | case DRM_FORMAT_BGRX5551: |
|
- | 3478 | case DRM_FORMAT_ARGB1555: |
|
- | 3479 | case DRM_FORMAT_ABGR1555: |
|
- | 3480 | case DRM_FORMAT_RGBA5551: |
|
- | 3481 | case DRM_FORMAT_BGRA5551: |
|
- | 3482 | *depth = 15; |
|
- | 3483 | *bpp = 16; |
|
- | 3484 | break; |
|
- | 3485 | case DRM_FORMAT_RGB565: |
|
- | 3486 | case DRM_FORMAT_BGR565: |
|
- | 3487 | *depth = 16; |
|
- | 3488 | *bpp = 16; |
|
- | 3489 | break; |
|
- | 3490 | case DRM_FORMAT_RGB888: |
|
- | 3491 | case DRM_FORMAT_BGR888: |
|
- | 3492 | *depth = 24; |
|
- | 3493 | *bpp = 24; |
|
- | 3494 | break; |
|
- | 3495 | case DRM_FORMAT_XRGB8888: |
|
- | 3496 | case DRM_FORMAT_XBGR8888: |
|
- | 3497 | case DRM_FORMAT_RGBX8888: |
|
- | 3498 | case DRM_FORMAT_BGRX8888: |
|
- | 3499 | *depth = 24; |
|
- | 3500 | *bpp = 32; |
|
- | 3501 | break; |
|
- | 3502 | case DRM_FORMAT_XRGB2101010: |
|
- | 3503 | case DRM_FORMAT_XBGR2101010: |
|
- | 3504 | case DRM_FORMAT_RGBX1010102: |
|
- | 3505 | case DRM_FORMAT_BGRX1010102: |
|
- | 3506 | case DRM_FORMAT_ARGB2101010: |
|
- | 3507 | case DRM_FORMAT_ABGR2101010: |
|
- | 3508 | case DRM_FORMAT_RGBA1010102: |
|
- | 3509 | case DRM_FORMAT_BGRA1010102: |
|
- | 3510 | *depth = 30; |
|
- | 3511 | *bpp = 32; |
|
- | 3512 | break; |
|
- | 3513 | case DRM_FORMAT_ARGB8888: |
|
- | 3514 | case DRM_FORMAT_ABGR8888: |
|
- | 3515 | case DRM_FORMAT_RGBA8888: |
|
- | 3516 | case DRM_FORMAT_BGRA8888: |
|
- | 3517 | *depth = 32; |
|
- | 3518 | *bpp = 32; |
|
- | 3519 | break; |
|
- | 3520 | default: |
|
- | 3521 | DRM_DEBUG_KMS("unsupported pixel format\n"); |
|
- | 3522 | *depth = 0; |
|
- | 3523 | *bpp = 0; |
|
- | 3524 | break; |
|
- | 3525 | } |
|
- | 3526 | } |
|
- | 3527 | EXPORT_SYMBOL(drm_fb_get_bpp_depth); |
|
- | 3528 | ||
- | 3529 | /** |
|
- | 3530 | * drm_format_num_planes - get the number of planes for format |
|
- | 3531 | * @format: pixel format (DRM_FORMAT_*) |
|
- | 3532 | * |
|
- | 3533 | * RETURNS: |
|
- | 3534 | * The number of planes used by the specified pixel format. |
|
- | 3535 | */ |
|
- | 3536 | int drm_format_num_planes(uint32_t format) |
|
- | 3537 | { |
|
- | 3538 | switch (format) { |
|
- | 3539 | case DRM_FORMAT_YUV410: |
|
- | 3540 | case DRM_FORMAT_YVU410: |
|
- | 3541 | case DRM_FORMAT_YUV411: |
|
- | 3542 | case DRM_FORMAT_YVU411: |
|
- | 3543 | case DRM_FORMAT_YUV420: |
|
- | 3544 | case DRM_FORMAT_YVU420: |
|
- | 3545 | case DRM_FORMAT_YUV422: |
|
- | 3546 | case DRM_FORMAT_YVU422: |
|
- | 3547 | case DRM_FORMAT_YUV444: |
|
- | 3548 | case DRM_FORMAT_YVU444: |
|
- | 3549 | return 3; |
|
- | 3550 | case DRM_FORMAT_NV12: |
|
- | 3551 | case DRM_FORMAT_NV21: |
|
- | 3552 | case DRM_FORMAT_NV16: |
|
- | 3553 | case DRM_FORMAT_NV61: |
|
- | 3554 | case DRM_FORMAT_NV24: |
|
- | 3555 | case DRM_FORMAT_NV42: |
|
- | 3556 | return 2; |
|
- | 3557 | default: |
|
- | 3558 | return 1; |
|
- | 3559 | } |
|
- | 3560 | } |
|
- | 3561 | EXPORT_SYMBOL(drm_format_num_planes); |
|
- | 3562 | ||
- | 3563 | /** |
|
- | 3564 | * drm_format_plane_cpp - determine the bytes per pixel value |
|
- | 3565 | * @format: pixel format (DRM_FORMAT_*) |
|
- | 3566 | * @plane: plane index |
|
- | 3567 | * |
|
- | 3568 | * RETURNS: |
|
- | 3569 | * The bytes per pixel value for the specified plane. |
|
- | 3570 | */ |
|
- | 3571 | int drm_format_plane_cpp(uint32_t format, int plane) |
|
- | 3572 | { |
|
- | 3573 | unsigned int depth; |
|
- | 3574 | int bpp; |
|
- | 3575 | ||
- | 3576 | if (plane >= drm_format_num_planes(format)) |
|
- | 3577 | return 0; |
|
- | 3578 | ||
- | 3579 | switch (format) { |
|
- | 3580 | case DRM_FORMAT_YUYV: |
|
- | 3581 | case DRM_FORMAT_YVYU: |
|
- | 3582 | case DRM_FORMAT_UYVY: |
|
- | 3583 | case DRM_FORMAT_VYUY: |
|
- | 3584 | return 2; |
|
- | 3585 | case DRM_FORMAT_NV12: |
|
- | 3586 | case DRM_FORMAT_NV21: |
|
- | 3587 | case DRM_FORMAT_NV16: |
|
- | 3588 | case DRM_FORMAT_NV61: |
|
- | 3589 | case DRM_FORMAT_NV24: |
|
- | 3590 | case DRM_FORMAT_NV42: |
|
- | 3591 | return plane ? 2 : 1; |
|
- | 3592 | case DRM_FORMAT_YUV410: |
|
- | 3593 | case DRM_FORMAT_YVU410: |
|
- | 3594 | case DRM_FORMAT_YUV411: |
|
- | 3595 | case DRM_FORMAT_YVU411: |
|
- | 3596 | case DRM_FORMAT_YUV420: |
|
- | 3597 | case DRM_FORMAT_YVU420: |
|
- | 3598 | case DRM_FORMAT_YUV422: |
|
- | 3599 | case DRM_FORMAT_YVU422: |
|
- | 3600 | case DRM_FORMAT_YUV444: |
|
- | 3601 | case DRM_FORMAT_YVU444: |
|
- | 3602 | return 1; |
|
- | 3603 | default: |
|
- | 3604 | drm_fb_get_bpp_depth(format, &depth, &bpp); |
|
- | 3605 | return bpp >> 3; |
|
- | 3606 | } |
|
- | 3607 | } |
|
- | 3608 | EXPORT_SYMBOL(drm_format_plane_cpp); |
|
- | 3609 | ||
- | 3610 | /** |
|
- | 3611 | * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor |
|
- | 3612 | * @format: pixel format (DRM_FORMAT_*) |
|
- | 3613 | * |
|
- | 3614 | * RETURNS: |
|
- | 3615 | * The horizontal chroma subsampling factor for the |
|
- | 3616 | * specified pixel format. |
|
- | 3617 | */ |
|
- | 3618 | int drm_format_horz_chroma_subsampling(uint32_t format) |
|
- | 3619 | { |
|
- | 3620 | switch (format) { |
|
- | 3621 | case DRM_FORMAT_YUV411: |
|
- | 3622 | case DRM_FORMAT_YVU411: |
|
- | 3623 | case DRM_FORMAT_YUV410: |
|
- | 3624 | case DRM_FORMAT_YVU410: |
|
- | 3625 | return 4; |
|
- | 3626 | case DRM_FORMAT_YUYV: |
|
- | 3627 | case DRM_FORMAT_YVYU: |
|
- | 3628 | case DRM_FORMAT_UYVY: |
|
- | 3629 | case DRM_FORMAT_VYUY: |
|
- | 3630 | case DRM_FORMAT_NV12: |
|
- | 3631 | case DRM_FORMAT_NV21: |
|
- | 3632 | case DRM_FORMAT_NV16: |
|
- | 3633 | case DRM_FORMAT_NV61: |
|
- | 3634 | case DRM_FORMAT_YUV422: |
|
- | 3635 | case DRM_FORMAT_YVU422: |
|
- | 3636 | case DRM_FORMAT_YUV420: |
|
- | 3637 | case DRM_FORMAT_YVU420: |
|
- | 3638 | return 2; |
|
- | 3639 | default: |
|
- | 3640 | return 1; |
|
- | 3641 | } |
|
- | 3642 | } |
|
- | 3643 | EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); |
|
- | 3644 | ||
- | 3645 | /** |
|
- | 3646 | * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor |
|
- | 3647 | * @format: pixel format (DRM_FORMAT_*) |
|
- | 3648 | * |
|
- | 3649 | * RETURNS: |
|
- | 3650 | * The vertical chroma subsampling factor for the |
|
- | 3651 | * specified pixel format. |
|
- | 3652 | */ |
|
- | 3653 | int drm_format_vert_chroma_subsampling(uint32_t format) |
|
- | 3654 | { |
|
- | 3655 | switch (format) { |
|
- | 3656 | case DRM_FORMAT_YUV410: |
|
- | 3657 | case DRM_FORMAT_YVU410: |
|
- | 3658 | return 4; |
|
- | 3659 | case DRM_FORMAT_YUV420: |
|
- | 3660 | case DRM_FORMAT_YVU420: |
|
- | 3661 | case DRM_FORMAT_NV12: |
|
- | 3662 | case DRM_FORMAT_NV21: |
|
- | 3663 | return 2; |
|
- | 3664 | default: |
|
- | 3665 | return 1; |
|
- | 3666 | } |
|
- | 3667 | } |
|
- | 3668 | EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);>>>>>>>>>>=>=>>>>><>><>>>>>>>>>> |