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.c182
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[] =
125DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, 126DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
126 drm_tv_subconnector_enum_list) 127 drm_tv_subconnector_enum_list)
127 128
129static 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
135DRM_ENUM_NAME_FN(drm_get_dirty_info_name,
136 drm_dirty_info_enum_list)
137
128struct drm_conn_prop_enum_list { 138struct 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
154static struct drm_prop_enum_list drm_encoder_enum_list[] = 165static 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
250void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) 261struct 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 */
277int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, 289int 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)
802EXPORT_SYMBOL(drm_mode_create_dithering_property); 814EXPORT_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 */
823int 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}
844EXPORT_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
1798int 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
1855out_err2:
1856 kfree(clips);
1857out_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);
2334out: 2441out:
@@ -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
2589int 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
2653out:
2654 mutex_unlock(&dev->mode_config.mutex);
2655 return ret;
2656}