summaryrefslogtreecommitdiff
path: root/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.31-drm-kms-flip.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.31-drm-kms-flip.patch')
-rw-r--r--meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.31-drm-kms-flip.patch307
1 files changed, 307 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.31-drm-kms-flip.patch b/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.31-drm-kms-flip.patch
new file mode 100644
index 000000000..1b85ecba0
--- /dev/null
+++ b/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.31-drm-kms-flip.patch
@@ -0,0 +1,307 @@
+From 4e8354884daa2ee3e491bae69a81f85a2d1ca8ba Mon Sep 17 00:00:00 2001
+From: Fei Jiang <fei.jiang@intel.com>
+Date: Mon, 3 Aug 2009 11:31:53 -0400
+Subject: [PATCH] change for general drm code to implement kms-flip feature
+
+
+Signed-off-by: Fei Jiang <fei.jiang@intel.com>
+---
+ drivers/gpu/drm/drm_crtc.c | 128 ++++++++++++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/drm_drv.c | 1 +
+ drivers/gpu/drm/drm_irq.c | 30 ++++++++++
+ include/drm/drm.h | 1 +
+ include/drm/drmP.h | 9 +++
+ include/drm/drm_crtc.h | 12 ++++
+ include/drm/drm_mode.h | 16 ++++++
+ 7 files changed, 197 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
+index 8fab789..3ada446
+--- a/drivers/gpu/drm/drm_crtc.c
++++ b/drivers/gpu/drm/drm_crtc.c
+@@ -2452,3 +2452,131 @@ out:
+ mutex_unlock(&dev->mode_config.mutex);
+ return ret;
+ }
++
++/**
++ * drm_mode_page_flip_ioctl - page flip ioctl
++ * @dev: DRM device
++ * @data: ioctl args
++ * @file_priv: file private data
++ *
++ * The page flip ioctl replaces the current front buffer with a new
++ * one, using the CRTC's set_base function, which should just update
++ * the front buffer base pointer. It's up to set_base to make
++ * sure the update doesn't result in tearing (on some hardware the
++ * base register is double buffered, so this is easy).
++ *
++ * Note that this covers just the simple case of flipping the front
++ * buffer immediately. Interval handling and interlaced modes have to
++ * be handled by userspace, or with new ioctls.
++ */
++int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv)
++{
++#if 0
++ struct drm_pending_flip *pending;
++#endif
++
++ struct drm_mode_page_flip *flip_data = data;
++ struct drm_mode_object *drm_obj, *fb_obj;
++ struct drm_crtc *crtc;
++ int ret = 0;
++
++ if (!(drm_core_check_feature(dev, DRIVER_MODESET)))
++ return -ENODEV;
++
++ /*
++ * Reject unknown flags so future userspace knows what we (don't)
++ * support
++ */
++ if (flip_data->flags & (~DRM_MODE_PAGE_FLIP_FLAGS_MASK)) {
++ DRM_DEBUG("bad page flip flags\n");
++ return -EINVAL;
++ }
++#if 0
++ pending = kzalloc(sizeof *pending, GFP_KERNEL);
++ if (pending == NULL)
++ return -ENOMEM;
++#endif
++ mutex_lock(&dev->struct_mutex);
++
++ fb_obj = drm_mode_object_find(dev, flip_data->fb_id,
++ DRM_MODE_OBJECT_FB);
++ if (!fb_obj) {
++ DRM_DEBUG("unknown fb %d\n", flip_data->fb_id);
++ ret = -ENOENT;
++ goto out_unlock;
++ }
++
++ drm_obj = drm_mode_object_find(dev, flip_data->crtc_id,
++ DRM_MODE_OBJECT_CRTC);
++ if (!drm_obj) {
++ DRM_DEBUG("unknown crtc %d\n", flip_data->crtc_id);
++ ret = -ENOENT;
++ goto out_unlock;
++ }
++ crtc = obj_to_crtc(drm_obj);
++ if (!crtc->enabled) {
++ DRM_DEBUG("crtc %d not enabled\n", flip_data->crtc_id);
++ ret = -EINVAL;
++ goto out_unlock;
++ }
++
++#if 0
++ if (crtc->fb->funcs->unpin == NULL) {
++ DRM_DEBUG("fb for crtc %d does not support delayed unpin\n",
++ flip_data->crtc_id);
++ ret = -ENODEV;
++ goto out_unlock;
++ }
++
++ pending->crtc = crtc;
++ pending->old_fb = crtc->fb;
++ pending->pipe = crtc->pipe;
++ pending->event.base.type = DRM_EVENT_MODE_PAGE_FLIP;
++ pending->event.base.length = sizeof pending->event;
++ pending->event.user_data = flip_data->user_data;
++ pending->pending_event.event = &pending->event.base;
++ pending->pending_event.file_priv = file_priv;
++ pending->pending_event.destroy =
++ (void (*) (struct drm_pending_event *)) kfree;
++
++ /* Get vblank ref for completion handling */
++ ret = drm_vblank_get(dev, crtc->pipe);
++ if (ret) {
++ DRM_DEBUG("failed to take vblank ref\n");
++ goto out_unlock;
++ }
++
++ pending->frame = drm_vblank_count(dev, crtc->pipe);
++ list_add_tail(&pending->link, &dev->flip_list);
++#endif
++
++ /*
++ * The set_base call will change the domain on the new fb,
++ * which will force the rendering to finish and block the
++ * ioctl. We need to do this last part from a work queue, to
++ * avoid blocking userspace here.
++ */
++ crtc->fb = obj_to_fb(fb_obj);
++retry_set:
++ ret = (*crtc->funcs->set_base)(crtc, 0, 0, NULL);
++ if (ret == -ERESTARTSYS)
++ goto retry_set;
++
++ if (ret) {
++ DRM_ERROR("set_base failed: %d\n", ret);
++ goto out_unlock;
++ }
++
++ mutex_unlock(&dev->struct_mutex);
++
++ return 0;
++
++out_unlock:
++ mutex_unlock(&dev->struct_mutex);
++#if 0
++ kfree(pending);
++#endif
++ return ret;
++}
++
+diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
+index 1ce7977..761c2ec
+--- a/drivers/gpu/drm/drm_drv.c
++++ b/drivers/gpu/drm/drm_drv.c
+@@ -145,6 +145,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
++ DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
+ };
+
+ #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
+diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
+index b4a3dbc..d5104df
+--- a/drivers/gpu/drm/drm_irq.c
++++ b/drivers/gpu/drm/drm_irq.c
+@@ -71,6 +71,28 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
+ return 0;
+ }
+
++#if 0
++static void drm_flip_work_func(struct work_struct *work)
++{
++ struct drm_device *dev =
++ container_of(work, struct drm_device, flip_work);
++#if 0
++ struct drm_pending_flip *f, *t;
++#endif
++ u32 frame;
++
++ mutex_lock(&dev->struct_mutex);
++
++ list_for_each_entry_safe(f, t, &dev->flip_list, link) {
++ frame = drm_vblank_count(dev, f->pipe);
++ if (vblank_after(frame, f->frame))
++ drm_finish_pending_flip(dev, f, frame);
++ }
++
++ mutex_unlock(&dev->struct_mutex);
++}
++#endif
++
+ static void vblank_disable_fn(unsigned long arg)
+ {
+ struct drm_device *dev = (struct drm_device *)arg;
+@@ -161,6 +183,11 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
+ atomic_set(&dev->vblank_refcount[i], 0);
+ }
+
++#if 0
++ INIT_LIST_HEAD(&dev->flip_list);
++ INIT_WORK(&dev->flip_work, drm_flip_work_func);
++#endif
++
+ dev->vblank_disable_allowed = 0;
+
+ return 0;
+@@ -626,5 +653,8 @@ void drm_handle_vblank(struct drm_device *dev, int crtc)
+ {
+ atomic_inc(&dev->_vblank_count[crtc]);
+ DRM_WAKEUP(&dev->vbl_queue[crtc]);
++#if 0
++ schedule_work(&dev->flip_work);
++#endif
+ }
+ EXPORT_SYMBOL(drm_handle_vblank);
+diff --git a/include/drm/drm.h b/include/drm/drm.h
+index 7cb50bd..78bd91b
+--- a/include/drm/drm.h
++++ b/include/drm/drm.h
+@@ -686,6 +686,7 @@ struct drm_gem_open {
+ #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
+ #define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
+ #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
++#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOW( 0xB0, struct drm_mode_page_flip)
+
+ /**
+ * Device specific ioctls should only be in their respective headers
+diff --git a/include/drm/drmP.h b/include/drm/drmP.h
+index c5122bf..36f9e6a
+--- a/include/drm/drmP.h
++++ b/include/drm/drmP.h
+@@ -976,6 +976,15 @@ struct drm_device {
+ cycles_t ctx_start;
+ cycles_t lck_start;
+
++ struct work_struct flip_work;
++
++#if 0
++ /**
++ * List of objects waiting on flip completion
++ */
++ struct list_head flip_list;
++#endif
++
+ struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+ wait_queue_head_t buf_readers; /**< Processes waiting to read */
+ wait_queue_head_t buf_writers; /**< Processes waiting to ctx switch */
+diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
+index 7300fb8..742c870
+--- a/include/drm/drm_crtc.h
++++ b/include/drm/drm_crtc.h
+@@ -331,6 +331,16 @@ struct drm_crtc_funcs {
+ void (*destroy)(struct drm_crtc *crtc);
+
+ int (*set_config)(struct drm_mode_set *set);
++
++ /*
++ * Move the crtc on the current fb to the given position.
++ * This function is optional. If old_fb is provided, the
++ * function will wait for vblank and unpin it. If old_fb is
++ * NULL, nothing is unpinned and the caller must call
++ * mode_unpin_fb to release the old framebuffer.
++ */
++ int (*set_base)(struct drm_crtc *crtc, int x, int y,
++ struct drm_framebuffer *old_fb);
+ };
+
+ /**
+@@ -736,4 +746,6 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
+ extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+ extern bool drm_detect_hdmi_monitor(struct edid *edid);
++extern int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv);
+ #endif /* __DRM_CRTC_H__ */
+diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
+index ae304cc..464b779
+--- a/include/drm/drm_mode.h
++++ b/include/drm/drm_mode.h
+@@ -265,4 +265,20 @@ struct drm_mode_crtc_lut {
+ __u64 blue;
+ };
+
++#define DRM_MODE_PAGE_FLIP_WAIT (1<<0) /* block on previous page flip */
++#define DRM_MODE_PAGE_FLIP_FLAGS_MASK (DRM_MODE_PAGE_FLIP_WAIT)
++
++struct drm_mode_page_flip {
++ /** Handle of new front buffer */
++ __u32 fb_id;
++ __u32 crtc_id;
++
++ /* 64 bit cookie returned to userspace in the page flip event. */
++ __u64 user_data;
++ /**
++ * page flip flags (wait on flip only for now)
++ */
++ __u32 flags;
++};
++
+ #endif
+--
+1.5.3.4
+