aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 00:56:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 00:56:47 -0500
commit3ef884b4c04e857c283cc77ca70ad8f638d94b0e (patch)
treec8c5b872e836e6ffe8bd08ab3477f9e8260575ed /drivers/gpu/drm/drm_crtc.c
parent4e5df8069b0e4e36c6b528b3be7da298e6f454cd (diff)
parent4361e52ad0372e6fd2240a2207b49a4de1f45ca9 (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.c176
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[] =
125DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, 125DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
126 drm_tv_subconnector_enum_list) 126 drm_tv_subconnector_enum_list)
127 127
128static 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
134DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
135 drm_dirty_info_enum_list)
136
128struct drm_conn_prop_enum_list { 137struct 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
250void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) 259struct 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)
802EXPORT_SYMBOL(drm_mode_create_dithering_property); 812EXPORT_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 */
821int 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}
842EXPORT_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
1796int 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
1853out_err2:
1854 kfree(clips);
1855out_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
2587int 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
2651out:
2652 mutex_unlock(&dev->mode_config.mutex);
2653 return ret;
2654}