diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/gpu/drm/drm_crtc.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 182 |
1 files changed, 179 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5cae0b3eee9b..61b9bcfdf040 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -30,6 +30,7 @@ | |||
30 | * Jesse Barnes <jesse.barnes@intel.com> | 30 | * Jesse Barnes <jesse.barnes@intel.com> |
31 | */ | 31 | */ |
32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
33 | #include <linux/slab.h> | ||
33 | #include "drm.h" | 34 | #include "drm.h" |
34 | #include "drmP.h" | 35 | #include "drmP.h" |
35 | #include "drm_crtc.h" | 36 | #include "drm_crtc.h" |
@@ -125,6 +126,15 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = | |||
125 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, | 126 | DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, |
126 | drm_tv_subconnector_enum_list) | 127 | drm_tv_subconnector_enum_list) |
127 | 128 | ||
129 | static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { | ||
130 | { DRM_MODE_DIRTY_OFF, "Off" }, | ||
131 | { DRM_MODE_DIRTY_ON, "On" }, | ||
132 | { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, | ||
133 | }; | ||
134 | |||
135 | DRM_ENUM_NAME_FN(drm_get_dirty_info_name, | ||
136 | drm_dirty_info_enum_list) | ||
137 | |||
128 | struct drm_conn_prop_enum_list { | 138 | struct drm_conn_prop_enum_list { |
129 | int type; | 139 | int type; |
130 | char *name; | 140 | char *name; |
@@ -149,6 +159,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = | |||
149 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, | 159 | { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, |
150 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, | 160 | { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, |
151 | { DRM_MODE_CONNECTOR_TV, "TV", 0 }, | 161 | { DRM_MODE_CONNECTOR_TV, "TV", 0 }, |
162 | { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 }, | ||
152 | }; | 163 | }; |
153 | 164 | ||
154 | static struct drm_prop_enum_list drm_encoder_enum_list[] = | 165 | static struct drm_prop_enum_list drm_encoder_enum_list[] = |
@@ -247,7 +258,8 @@ static void drm_mode_object_put(struct drm_device *dev, | |||
247 | mutex_unlock(&dev->mode_config.idr_mutex); | 258 | mutex_unlock(&dev->mode_config.idr_mutex); |
248 | } | 259 | } |
249 | 260 | ||
250 | void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) | 261 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, |
262 | uint32_t id, uint32_t type) | ||
251 | { | 263 | { |
252 | struct drm_mode_object *obj = NULL; | 264 | struct drm_mode_object *obj = NULL; |
253 | 265 | ||
@@ -272,7 +284,7 @@ EXPORT_SYMBOL(drm_mode_object_find); | |||
272 | * functions & device file and adds it to the master fd list. | 284 | * functions & device file and adds it to the master fd list. |
273 | * | 285 | * |
274 | * RETURNS: | 286 | * RETURNS: |
275 | * Zero on success, error code on falure. | 287 | * Zero on success, error code on failure. |
276 | */ | 288 | */ |
277 | int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, | 289 | int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, |
278 | const struct drm_framebuffer_funcs *funcs) | 290 | const struct drm_framebuffer_funcs *funcs) |
@@ -802,6 +814,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev) | |||
802 | EXPORT_SYMBOL(drm_mode_create_dithering_property); | 814 | EXPORT_SYMBOL(drm_mode_create_dithering_property); |
803 | 815 | ||
804 | /** | 816 | /** |
817 | * drm_mode_create_dirty_property - create dirty property | ||
818 | * @dev: DRM device | ||
819 | * | ||
820 | * Called by a driver the first time it's needed, must be attached to desired | ||
821 | * connectors. | ||
822 | */ | ||
823 | int drm_mode_create_dirty_info_property(struct drm_device *dev) | ||
824 | { | ||
825 | struct drm_property *dirty_info; | ||
826 | int i; | ||
827 | |||
828 | if (dev->mode_config.dirty_info_property) | ||
829 | return 0; | ||
830 | |||
831 | dirty_info = | ||
832 | drm_property_create(dev, DRM_MODE_PROP_ENUM | | ||
833 | DRM_MODE_PROP_IMMUTABLE, | ||
834 | "dirty", | ||
835 | ARRAY_SIZE(drm_dirty_info_enum_list)); | ||
836 | for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++) | ||
837 | drm_property_add_enum(dirty_info, i, | ||
838 | drm_dirty_info_enum_list[i].type, | ||
839 | drm_dirty_info_enum_list[i].name); | ||
840 | dev->mode_config.dirty_info_property = dirty_info; | ||
841 | |||
842 | return 0; | ||
843 | } | ||
844 | EXPORT_SYMBOL(drm_mode_create_dirty_info_property); | ||
845 | |||
846 | /** | ||
805 | * drm_mode_config_init - initialize DRM mode_configuration structure | 847 | * drm_mode_config_init - initialize DRM mode_configuration structure |
806 | * @dev: DRM device | 848 | * @dev: DRM device |
807 | * | 849 | * |
@@ -1753,6 +1795,71 @@ out: | |||
1753 | return ret; | 1795 | return ret; |
1754 | } | 1796 | } |
1755 | 1797 | ||
1798 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | ||
1799 | void *data, struct drm_file *file_priv) | ||
1800 | { | ||
1801 | struct drm_clip_rect __user *clips_ptr; | ||
1802 | struct drm_clip_rect *clips = NULL; | ||
1803 | struct drm_mode_fb_dirty_cmd *r = data; | ||
1804 | struct drm_mode_object *obj; | ||
1805 | struct drm_framebuffer *fb; | ||
1806 | unsigned flags; | ||
1807 | int num_clips; | ||
1808 | int ret = 0; | ||
1809 | |||
1810 | mutex_lock(&dev->mode_config.mutex); | ||
1811 | obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); | ||
1812 | if (!obj) { | ||
1813 | DRM_ERROR("invalid framebuffer id\n"); | ||
1814 | ret = -EINVAL; | ||
1815 | goto out_err1; | ||
1816 | } | ||
1817 | fb = obj_to_fb(obj); | ||
1818 | |||
1819 | num_clips = r->num_clips; | ||
1820 | clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr; | ||
1821 | |||
1822 | if (!num_clips != !clips_ptr) { | ||
1823 | ret = -EINVAL; | ||
1824 | goto out_err1; | ||
1825 | } | ||
1826 | |||
1827 | flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; | ||
1828 | |||
1829 | /* If userspace annotates copy, clips must come in pairs */ | ||
1830 | if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { | ||
1831 | ret = -EINVAL; | ||
1832 | goto out_err1; | ||
1833 | } | ||
1834 | |||
1835 | if (num_clips && clips_ptr) { | ||
1836 | clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); | ||
1837 | if (!clips) { | ||
1838 | ret = -ENOMEM; | ||
1839 | goto out_err1; | ||
1840 | } | ||
1841 | |||
1842 | ret = copy_from_user(clips, clips_ptr, | ||
1843 | num_clips * sizeof(*clips)); | ||
1844 | if (ret) | ||
1845 | goto out_err2; | ||
1846 | } | ||
1847 | |||
1848 | if (fb->funcs->dirty) { | ||
1849 | ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips); | ||
1850 | } else { | ||
1851 | ret = -ENOSYS; | ||
1852 | goto out_err2; | ||
1853 | } | ||
1854 | |||
1855 | out_err2: | ||
1856 | kfree(clips); | ||
1857 | out_err1: | ||
1858 | mutex_unlock(&dev->mode_config.mutex); | ||
1859 | return ret; | ||
1860 | } | ||
1861 | |||
1862 | |||
1756 | /** | 1863 | /** |
1757 | * drm_fb_release - remove and free the FBs on this file | 1864 | * drm_fb_release - remove and free the FBs on this file |
1758 | * @filp: file * from the ioctl | 1865 | * @filp: file * from the ioctl |
@@ -2328,7 +2435,7 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, | |||
2328 | } else if (connector->funcs->set_property) | 2435 | } else if (connector->funcs->set_property) |
2329 | ret = connector->funcs->set_property(connector, property, out_resp->value); | 2436 | ret = connector->funcs->set_property(connector, property, out_resp->value); |
2330 | 2437 | ||
2331 | /* store the property value if succesful */ | 2438 | /* store the property value if successful */ |
2332 | if (!ret) | 2439 | if (!ret) |
2333 | drm_connector_property_set_value(connector, property, out_resp->value); | 2440 | drm_connector_property_set_value(connector, property, out_resp->value); |
2334 | out: | 2441 | out: |
@@ -2478,3 +2585,72 @@ out: | |||
2478 | mutex_unlock(&dev->mode_config.mutex); | 2585 | mutex_unlock(&dev->mode_config.mutex); |
2479 | return ret; | 2586 | return ret; |
2480 | } | 2587 | } |
2588 | |||
2589 | int drm_mode_page_flip_ioctl(struct drm_device *dev, | ||
2590 | void *data, struct drm_file *file_priv) | ||
2591 | { | ||
2592 | struct drm_mode_crtc_page_flip *page_flip = data; | ||
2593 | struct drm_mode_object *obj; | ||
2594 | struct drm_crtc *crtc; | ||
2595 | struct drm_framebuffer *fb; | ||
2596 | struct drm_pending_vblank_event *e = NULL; | ||
2597 | unsigned long flags; | ||
2598 | int ret = -EINVAL; | ||
2599 | |||
2600 | if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || | ||
2601 | page_flip->reserved != 0) | ||
2602 | return -EINVAL; | ||
2603 | |||
2604 | mutex_lock(&dev->mode_config.mutex); | ||
2605 | obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); | ||
2606 | if (!obj) | ||
2607 | goto out; | ||
2608 | crtc = obj_to_crtc(obj); | ||
2609 | |||
2610 | if (crtc->funcs->page_flip == NULL) | ||
2611 | goto out; | ||
2612 | |||
2613 | obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB); | ||
2614 | if (!obj) | ||
2615 | goto out; | ||
2616 | fb = obj_to_fb(obj); | ||
2617 | |||
2618 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { | ||
2619 | ret = -ENOMEM; | ||
2620 | spin_lock_irqsave(&dev->event_lock, flags); | ||
2621 | if (file_priv->event_space < sizeof e->event) { | ||
2622 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2623 | goto out; | ||
2624 | } | ||
2625 | file_priv->event_space -= sizeof e->event; | ||
2626 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2627 | |||
2628 | e = kzalloc(sizeof *e, GFP_KERNEL); | ||
2629 | if (e == NULL) { | ||
2630 | spin_lock_irqsave(&dev->event_lock, flags); | ||
2631 | file_priv->event_space += sizeof e->event; | ||
2632 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2633 | goto out; | ||
2634 | } | ||
2635 | |||
2636 | e->event.base.type = DRM_EVENT_FLIP_COMPLETE; | ||
2637 | e->event.base.length = sizeof e->event; | ||
2638 | e->event.user_data = page_flip->user_data; | ||
2639 | e->base.event = &e->event.base; | ||
2640 | e->base.file_priv = file_priv; | ||
2641 | e->base.destroy = | ||
2642 | (void (*) (struct drm_pending_event *)) kfree; | ||
2643 | } | ||
2644 | |||
2645 | ret = crtc->funcs->page_flip(crtc, fb, e); | ||
2646 | if (ret) { | ||
2647 | spin_lock_irqsave(&dev->event_lock, flags); | ||
2648 | file_priv->event_space += sizeof e->event; | ||
2649 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
2650 | kfree(e); | ||
2651 | } | ||
2652 | |||
2653 | out: | ||
2654 | mutex_unlock(&dev->mode_config.mutex); | ||
2655 | return ret; | ||
2656 | } | ||