diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 00:56:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 00:56:47 -0500 |
commit | 3ef884b4c04e857c283cc77ca70ad8f638d94b0e (patch) | |
tree | c8c5b872e836e6ffe8bd08ab3477f9e8260575ed /drivers/gpu/drm/drm_crtc.c | |
parent | 4e5df8069b0e4e36c6b528b3be7da298e6f454cd (diff) | |
parent | 4361e52ad0372e6fd2240a2207b49a4de1f45ca9 (diff) |
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (189 commits)
drm/radeon/kms: fix warning about cur_placement being uninitialised.
drm/ttm: Print debug information on memory manager when eviction fails
drm: Add memory manager debug function
drm/radeon/kms: restore surface registers on resume.
drm/radeon/kms/r600/r700: fallback gracefully on ucode failure
drm/ttm: Initialize eviction placement in case the driver callback doesn't
drm/radeon/kms: cleanup structure and module if initialization fails
drm/radeon/kms: actualy set the eviction placements we choose
drm/radeon/kms: Fix NULL ptr dereference
drm/radeon/kms/avivo: add support for new pll selection algo
drm/radeon/kms/avivo: fix some bugs in the display bandwidth setup
drm/radeon/kms: fix return value from fence function.
drm/radeon: Remove tests for -ERESTART from the TTM code.
drm/ttm: Have the TTM code return -ERESTARTSYS instead of -ERESTART.
drm/radeon/kms: Convert radeon to new TTM validation API (V2)
drm/ttm: Rework validation & memory space allocation (V3)
drm: Add search/get functions to get a block in a specific range
drm/radeon/kms: fix avivo tiling regression since radeon object rework
drm/i915: Remove a debugging printk from hangcheck
drm/radeon/kms: make sure i2c id matches
...
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 176 |
1 files changed, 175 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3f7c500b2115..5124401f266a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -125,6 +125,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = | |||
125 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, | 125 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, |
126 | drm_tv_subconnector_enum_list) | 126 | drm_tv_subconnector_enum_list) |
127 | 127 | ||
128 | static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { | ||
129 | { DRM_MODE_DIRTY_OFF, "Off" }, | ||
130 | { DRM_MODE_DIRTY_ON, "On" }, | ||
131 | { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, | ||
132 | }; | ||
133 | |||
134 | DRM_ENUM_NAME_FN(drm_get_dirty_info_name, | ||
135 | drm_dirty_info_enum_list) | ||
136 | |||
128 | struct drm_conn_prop_enum_list { | 137 | struct drm_conn_prop_enum_list { |
129 | int type; | 138 | int type; |
130 | char *name; | 139 | char *name; |
@@ -247,7 +256,8 @@ static void drm_mode_object_put(struct drm_device *dev, | |||
247 | mutex_unlock(&dev->mode_config.idr_mutex); | 256 | mutex_unlock(&dev->mode_config.idr_mutex); |
248 | } | 257 | } |
249 | 258 | ||
250 | void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) | 259 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, |
260 | uint32_t id, uint32_t type) | ||
251 | { | 261 | { |
252 | struct drm_mode_object *obj = NULL; | 262 | struct drm_mode_object *obj = NULL; |
253 | 263 | ||
@@ -802,6 +812,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev) | |||
802 | EXPORT_SYMBOL(drm_mode_create_dithering_property); | 812 | EXPORT_SYMBOL(drm_mode_create_dithering_property); |
803 | 813 | ||
804 | /** | 814 | /** |
815 | * drm_mode_create_dirty_property - create dirty property | ||
816 | * @dev: DRM device | ||
817 | * | ||
818 | * Called by a driver the first time it's needed, must be attached to desired | ||
819 | * connectors. | ||
820 | */ | ||
821 | int drm_mode_create_dirty_info_property(struct drm_device *dev) | ||
822 | { | ||
823 | struct drm_property *dirty_info; | ||
824 | int i; | ||
825 | |||
826 | if (dev->mode_config.dirty_info_property) | ||
827 | return 0; | ||
828 | |||
829 | dirty_info = | ||
830 | drm_property_create(dev, DRM_MODE_PROP_ENUM | | ||
831 | DRM_MODE_PROP_IMMUTABLE, | ||
832 | "dirty", | ||
833 | ARRAY_SIZE(drm_dirty_info_enum_list)); | ||
834 | for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++) | ||
835 | drm_property_add_enum(dirty_info, i, | ||
836 | drm_dirty_info_enum_list[i].type, | ||
837 | drm_dirty_info_enum_list[i].name); | ||
838 | dev->mode_config.dirty_info_property = dirty_info; | ||
839 | |||
840 | return 0; | ||
841 | } | ||
842 | EXPORT_SYMBOL(drm_mode_create_dirty_info_property); | ||
843 | |||
844 | /** | ||
805 | * drm_mode_config_init - initialize DRM mode_configuration structure | 845 | * drm_mode_config_init - initialize DRM mode_configuration structure |
806 | * @dev: DRM device | 846 | * @dev: DRM device |
807 | * | 847 | * |
@@ -1753,6 +1793,71 @@ out: | |||
1753 | return ret; | 1793 | return ret; |
1754 | } | 1794 | } |
1755 | 1795 | ||
1796 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | ||
1797 | void *data, struct drm_file *file_priv) | ||
1798 | { | ||
1799 | struct drm_clip_rect __user *clips_ptr; | ||
1800 | struct drm_clip_rect *clips = NULL; | ||
1801 | struct drm_mode_fb_dirty_cmd *r = data; | ||
1802 | struct drm_mode_object *obj; | ||
1803 | struct drm_framebuffer *fb; | ||
1804 | unsigned flags; | ||
1805 | int num_clips; | ||
1806 | int ret = 0; | ||
1807 | |||
1808 | mutex_lock(&dev->mode_config.mutex); | ||
1809 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); | ||
1810 | if (!obj) { | ||
1811 | DRM_ERROR("invalid framebuffer id\n"); | ||
1812 | ret = -EINVAL; | ||
1813 | goto out_err1; | ||
1814 | } | ||
1815 | fb = obj_to_fb(obj); | ||
1816 | |||
1817 | num_clips = r->num_clips; | ||
1818 | clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; | ||
1819 | |||
1820 | if (!num_clips != !clips_ptr) { | ||
1821 | ret = -EINVAL; | ||
1822 | goto out_err1; | ||
1823 | } | ||
1824 | |||
1825 | flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; | ||
1826 | |||
1827 | /* If userspace annotates copy, clips must come in pairs */ | ||
1828 | if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { | ||
1829 | ret = -EINVAL; | ||
1830 | goto out_err1; | ||
1831 | } | ||
1832 | |||
1833 | if (num_clips && clips_ptr) { | ||
1834 | clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); | ||
1835 | if (!clips) { | ||
1836 | ret = -ENOMEM; | ||
1837 | goto out_err1; | ||
1838 | } | ||
1839 | |||
1840 | ret = copy_from_user(clips, clips_ptr, | ||
1841 | num_clips * sizeof(*clips)); | ||
1842 | if (ret) | ||
1843 | goto out_err2; | ||
1844 | } | ||
1845 | |||
1846 | if (fb->funcs->dirty) { | ||
1847 | ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips); | ||
1848 | } else { | ||
1849 | ret = -ENOSYS; | ||
1850 | goto out_err2; | ||
1851 | } | ||
1852 | |||
1853 | out_err2: | ||
1854 | kfree(clips); | ||
1855 | out_err1: | ||
1856 | mutex_unlock(&dev->mode_config.mutex); | ||
1857 | return ret; | ||
1858 | } | ||
1859 | |||
1860 | |||
1756 | /** | 1861 | /** |
1757 | * drm_fb_release - remove and free the FBs on this file | 1862 | * drm_fb_release - remove and free the FBs on this file |
1758 | * @filp: file * from the ioctl | 1863 | * @filp: file * from the ioctl |
@@ -2478,3 +2583,72 @@ out: | |||
2478 | mutex_unlock(&dev->mode_config.mutex); | 2583 | mutex_unlock(&dev->mode_config.mutex); |
2479 | return ret; | 2584 | return ret; |
2480 | } | 2585 | } |
2586 | |||
2587 | int drm_mode_page_flip_ioctl(struct drm_device *dev, | ||
2588 | void *data, struct drm_file *file_priv) | ||
2589 | { | ||
2590 | struct drm_mode_crtc_page_flip *page_flip = data; | ||
2591 | struct drm_mode_object *obj; | ||
2592 | struct drm_crtc *crtc; | ||
2593 | struct drm_framebuffer *fb; | ||
2594 | struct drm_pending_vblank_event *e = NULL; | ||
2595 | unsigned long flags; | ||
2596 | int ret = -EINVAL; | ||
2597 | |||
2598 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || | ||
2599 | page_flip->reserved != 0) | ||
2600 | return -EINVAL; | ||
2601 | |||
2602 | mutex_lock(&dev->mode_config.mutex); | ||
2603 | obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); | ||
2604 | if (!obj) | ||
2605 | goto out; | ||
2606 | crtc = obj_to_crtc(obj); | ||
2607 | |||
2608 | if (crtc->funcs->page_flip == NULL) | ||
2609 | goto out; | ||
2610 | |||
2611 | obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); | ||
2612 | if (!obj) | ||
2613 | goto out; | ||
2614 | fb = obj_to_fb(obj); | ||
2615 | |||
2616 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { | ||
2617 | ret = -ENOMEM; | ||
2618 | spin_lock_irqsave(&dev->event_lock, flags); | ||
2619 | if (file_priv->event_space < sizeof e->event) { | ||
2620 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2621 | goto out; | ||
2622 | } | ||
2623 | file_priv->event_space -= sizeof e->event; | ||
2624 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2625 | |||
2626 | e = kzalloc(sizeof *e, GFP_KERNEL); | ||
2627 | if (e == NULL) { | ||
2628 | spin_lock_irqsave(&dev->event_lock, flags); | ||
2629 | file_priv->event_space += sizeof e->event; | ||
2630 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2631 | goto out; | ||
2632 | } | ||
2633 | |||
2634 | e->event.base.type = DRM_EVENT_FLIP_COMPLETE; | ||
2635 | e->event.base.length = sizeof e->event; | ||
2636 | e->event.user_data = page_flip->user_data; | ||
2637 | e->base.event = &e->event.base; | ||
2638 | e->base.file_priv = file_priv; | ||
2639 | e->base.destroy = | ||
2640 | (void (*) (struct drm_pending_event *)) kfree; | ||
2641 | } | ||
2642 | |||
2643 | ret = crtc->funcs->page_flip(crtc, fb, e); | ||
2644 | if (ret) { | ||
2645 | spin_lock_irqsave(&dev->event_lock, flags); | ||
2646 | file_priv->event_space += sizeof e->event; | ||
2647 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2648 | kfree(e); | ||
2649 | } | ||
2650 | |||
2651 | out: | ||
2652 | mutex_unlock(&dev->mode_config.mutex); | ||
2653 | return ret; | ||
2654 | } | ||