diff options
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.patch | 307 |
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 + |