aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5cae0b3eee9b..4fe321dc900c 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;
@@ -802,6 +811,36 @@ int drm_mode_create_dithering_property(struct drm_device *dev)
802EXPORT_SYMBOL(drm_mode_create_dithering_property); 811EXPORT_SYMBOL(drm_mode_create_dithering_property);
803 812
804/** 813/**
814 * drm_mode_create_dirty_property - create dirty property
815 * @dev: DRM device
816 *
817 * Called by a driver the first time it's needed, must be attached to desired
818 * connectors.
819 */
820int drm_mode_create_dirty_info_property(struct drm_device *dev)
821{
822 struct drm_property *dirty_info;
823 int i;
824
825 if (dev->mode_config.dirty_info_property)
826 return 0;
827
828 dirty_info =
829 drm_property_create(dev, DRM_MODE_PROP_ENUM |
830 DRM_MODE_PROP_IMMUTABLE,
831 "dirty",
832 ARRAY_SIZE(drm_dirty_info_enum_list));
833 for (i = 0; i < ARRAY_SIZE(drm_dirty_info_enum_list); i++)
834 drm_property_add_enum(dirty_info, i,
835 drm_dirty_info_enum_list[i].type,
836 drm_dirty_info_enum_list[i].name);
837 dev->mode_config.dirty_info_property = dirty_info;
838
839 return 0;
840}
841EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
842
843/**
805 * drm_mode_config_init - initialize DRM mode_configuration structure 844 * drm_mode_config_init - initialize DRM mode_configuration structure
806 * @dev: DRM device 845 * @dev: DRM device
807 * 846 *
@@ -1753,6 +1792,71 @@ out:
1753 return ret; 1792 return ret;
1754} 1793}
1755 1794
1795int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
1796 void *data, struct drm_file *file_priv)
1797{
1798 struct drm_clip_rect __user *clips_ptr;
1799 struct drm_clip_rect *clips = NULL;
1800 struct drm_mode_fb_dirty_cmd *r = data;
1801 struct drm_mode_object *obj;
1802 struct drm_framebuffer *fb;
1803 unsigned flags;
1804 int num_clips;
1805 int ret = 0;
1806
1807 mutex_lock(&dev->mode_config.mutex);
1808 obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
1809 if (!obj) {
1810 DRM_ERROR("invalid framebuffer id\n");
1811 ret = -EINVAL;
1812 goto out_err1;
1813 }
1814 fb = obj_to_fb(obj);
1815
1816 num_clips = r->num_clips;
1817 clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
1818
1819 if (!num_clips != !clips_ptr) {
1820 ret = -EINVAL;
1821 goto out_err1;
1822 }
1823
1824 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
1825
1826 /* If userspace annotates copy, clips must come in pairs */
1827 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
1828 ret = -EINVAL;
1829 goto out_err1;
1830 }
1831
1832 if (num_clips && clips_ptr) {
1833 clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
1834 if (!clips) {
1835 ret = -ENOMEM;
1836 goto out_err1;
1837 }
1838
1839 ret = copy_from_user(clips, clips_ptr,
1840 num_clips * sizeof(*clips));
1841 if (ret)
1842 goto out_err2;
1843 }
1844
1845 if (fb->funcs->dirty) {
1846 ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips);
1847 } else {
1848 ret = -ENOSYS;
1849 goto out_err2;
1850 }
1851
1852out_err2:
1853 kfree(clips);
1854out_err1:
1855 mutex_unlock(&dev->mode_config.mutex);
1856 return ret;
1857}
1858
1859
1756/** 1860/**
1757 * drm_fb_release - remove and free the FBs on this file 1861 * drm_fb_release - remove and free the FBs on this file
1758 * @filp: file * from the ioctl 1862 * @filp: file * from the ioctl
@@ -2478,3 +2582,72 @@ out:
2478 mutex_unlock(&dev->mode_config.mutex); 2582 mutex_unlock(&dev->mode_config.mutex);
2479 return ret; 2583 return ret;
2480} 2584}
2585
2586int drm_mode_page_flip_ioctl(struct drm_device *dev,
2587 void *data, struct drm_file *file_priv)
2588{
2589 struct drm_mode_crtc_page_flip *page_flip = data;
2590 struct drm_mode_object *obj;
2591 struct drm_crtc *crtc;
2592 struct drm_framebuffer *fb;
2593 struct drm_pending_vblank_event *e = NULL;
2594 unsigned long flags;
2595 int ret = -EINVAL;
2596
2597 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
2598 page_flip->reserved != 0)
2599 return -EINVAL;
2600
2601 mutex_lock(&dev->mode_config.mutex);
2602 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
2603 if (!obj)
2604 goto out;
2605 crtc = obj_to_crtc(obj);
2606
2607 if (crtc->funcs->page_flip == NULL)
2608 goto out;
2609
2610 obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
2611 if (!obj)
2612 goto out;
2613 fb = obj_to_fb(obj);
2614
2615 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
2616 ret = -ENOMEM;
2617 spin_lock_irqsave(&dev->event_lock, flags);
2618 if (file_priv->event_space < sizeof e->event) {
2619 spin_unlock_irqrestore(&dev->event_lock, flags);
2620 goto out;
2621 }
2622 file_priv->event_space -= sizeof e->event;
2623 spin_unlock_irqrestore(&dev->event_lock, flags);
2624
2625 e = kzalloc(sizeof *e, GFP_KERNEL);
2626 if (e == NULL) {
2627 spin_lock_irqsave(&dev->event_lock, flags);
2628 file_priv->event_space += sizeof e->event;
2629 spin_unlock_irqrestore(&dev->event_lock, flags);
2630 goto out;
2631 }
2632
2633 e->event.base.type = DRM_EVENT_VBLANK;
2634 e->event.base.length = sizeof e->event;
2635 e->event.user_data = page_flip->user_data;
2636 e->base.event = &e->event.base;
2637 e->base.file_priv = file_priv;
2638 e->base.destroy =
2639 (void (*) (struct drm_pending_event *)) kfree;
2640 }
2641
2642 ret = crtc->funcs->page_flip(crtc, fb, e);
2643 if (ret) {
2644 spin_lock_irqsave(&dev->event_lock, flags);
2645 file_priv->event_space += sizeof e->event;
2646 spin_unlock_irqrestore(&dev->event_lock, flags);
2647 kfree(e);
2648 }
2649
2650out:
2651 mutex_unlock(&dev->mode_config.mutex);
2652 return ret;
2653}