[RFC/PATCH 2/5] drm: Connect live source to plane

Laurent Pinchart
2015-03-15T21:55:42Z

drivers/gpu/drm/armada/armada_overlay.c | 2 +-
drivers/gpu/drm/drm_atomic.c | 7 ++
drivers/gpu/drm/drm_atomic_helper.c | 4 +
drivers/gpu/drm/drm_crtc.c | 134 +++++++++++++++++++++++-----
drivers/gpu/drm/drm_fops.c | 6 +-
drivers/gpu/drm/drm_plane_helper.c | 1 +
drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +-
drivers/gpu/drm/exynos/exynos_drm_plane.c | 3 +-
drivers/gpu/drm/exynos/exynos_drm_plane.h | 3 +-
drivers/gpu/drm/i915/intel_display.c | 4 +-
drivers/gpu/drm/i915/intel_sprite.c | 2 +-
drivers/gpu/drm/imx/ipuv3-plane.c | 3 +-
drivers/gpu/drm/nouveau/dispnv04/overlay.c | 6 +-
drivers/gpu/drm/omapdrm/omap_plane.c | 1 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +-
drivers/gpu/drm/shmobile/shmob_drm_plane.c | 3 +-
drivers/gpu/drm/sti/sti_drm_plane.c | 3 +-
drivers/gpu/drm/sti/sti_hqvdp.c | 2 +-
include/drm/drmP.h | 3 +
include/drm/drm_atomic_helper.h | 1 +
include/drm/drm_crtc.h | 6 ++
include/drm/drm_plane_helper.h | 1 +
22 files changed, 165 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index c5b06fdb459c..4d5708bbee6e 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -99,7 +99,7 @@ static unsigned armada_limit(int start, unsigned size, unsigned max)

static int
armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
{
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index a6caaae40b9e..0be059be2d58 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -384,6 +384,11 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
drm_atomic_set_fb_for_plane(state, fb);
if (fb)
drm_framebuffer_unreference(fb);
+ } else if (property == config->prop_src_id) {
+ struct drm_mode_object *obj;
+ obj = drm_mode_object_find(dev, val,
+ DRM_MODE_OBJECT_LIVE_SOURCE);
+ state->src = obj ? obj_to_live_source(obj) : NULL;
} else if (property == config->prop_crtc_id) {
struct drm_crtc *crtc = drm_crtc_find(dev, val);
return drm_atomic_set_crtc_for_plane(state, crtc);
@@ -432,6 +437,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,

if (property == config->prop_fb_id) {
*val = (state->fb) ? state->fb->base.id : 0;
+ } else if (property == config->prop_src_id) {
+ *val = (state->src) ? state->src->base.id : 0;
} else if (property == config->prop_crtc_id) {
*val = (state->crtc) ? state->crtc->base.id : 0;
} else if (property == config->prop_crtc_x) {
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index a7458813af2b..b182d9e6abba 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1342,6 +1342,7 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
* @plane: plane object to update
* @crtc: owning CRTC of owning plane
* @fb: framebuffer to flip onto plane
+ * @src: live source to connect to the plane
* @crtc_x: x offset of primary plane on crtc
* @crtc_y: y offset of primary plane on crtc
* @crtc_w: width of primary plane rectangle on crtc
@@ -1359,6 +1360,7 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
int drm_atomic_helper_update_plane(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
@@ -1384,6 +1386,7 @@ retry:
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, fb);
+ plane_state->src = src;
plane_state->crtc_x = crtc_x;
plane_state->crtc_y = crtc_y;
plane_state->crtc_h = crtc_h;
@@ -1466,6 +1469,7 @@ retry:
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, NULL);
+ plane_state->src = NULL;
plane_state->crtc_x = 0;
plane_state->crtc_y = 0;
plane_state->crtc_h = 0;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index a510c9742a16..f11960372307 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1183,6 +1183,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,

if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
+ drm_object_attach_property(&plane->base, config->prop_src_id, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
@@ -1315,6 +1316,31 @@ void drm_live_source_cleanup(struct drm_live_source *src)
}
EXPORT_SYMBOL(drm_live_source_cleanup);

+void drm_live_sources_release(struct drm_file *priv)
+{
+ struct drm_device *dev = priv->minor->dev;
+ struct drm_live_source *src, *next;
+ int ret;
+
+ drm_modeset_lock_all(dev);
+ mutex_lock(&priv->sources_lock);
+
+ list_for_each_entry_safe(src, next, &priv->sources, filp_head) {
+ list_del_init(&src->filp_head);
+ if (src->plane) {
+ ret = src->plane->funcs->disable_plane(src->plane);
+ if (ret)
+ DRM_ERROR("failed to disable plane with busy source\n");
+ src->plane->src = NULL;
+ src->plane->crtc = NULL;
+ src->plane = NULL;
+ }
+ }
+
+ mutex_unlock(&priv->sources_lock);
+ drm_modeset_unlock_all(dev);
+}
+
/**
* drm_plane_index - find the index of a registered plane
* @plane: plane to find index for
@@ -1468,6 +1494,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
dev->mode_config.prop_fb_id = prop;

prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+ "SRC_ID", DRM_MODE_OBJECT_FB);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_src_id = prop;
+
+ prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
"CRTC_ID", DRM_MODE_OBJECT_CRTC);
if (!prop)
return -ENOMEM;
@@ -2436,6 +2468,8 @@ int drm_mode_getplane(struct drm_device *dev, void *data,

if (plane->fb)
plane_resp->fb_id = plane->fb->base.id;
+ else if (plane->src)
+ plane_resp->fb_id = plane->src->base.id;
else
plane_resp->fb_id = 0;
drm_modeset_unlock(&plane->mutex);
@@ -2492,25 +2526,29 @@ int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
*
* src_{x,y,w,h} are provided in 16.16 fixed point format
*/
-static int __setplane_internal(struct drm_plane *plane,
+static int __setplane_internal(struct drm_file *file_priv,
+ struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int32_t crtc_x, int32_t crtc_y,
uint32_t crtc_w, uint32_t crtc_h,
/* src_{x,y,w,h} values are 16.16 fixed point */
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
+ unsigned int width, height;
+ uint32_t pixel_format;
int ret = 0;
- unsigned int fb_width, fb_height;

- /* No fb means shut it down */
- if (!fb) {
+ /* No fb and src means shut it down */
+ if (!fb && !src) {
plane->old_fb = plane->fb;
ret = plane->funcs->disable_plane(plane);
if (!ret) {
plane->crtc = NULL;
plane->fb = NULL;
+ plane->src = NULL;
} else {
plane->old_fb = NULL;
}
@@ -2524,22 +2562,50 @@ static int __setplane_internal(struct drm_plane *plane,
goto out;
}

- /* Check whether this plane supports the fb pixel format. */
- ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
+ /* Check whether this plane supports the pixel format. */
+ pixel_format = fb ? fb->pixel_format : src->pixel_format;
+ ret = drm_plane_check_pixel_format(plane, pixel_format);
if (ret) {
DRM_DEBUG_KMS("Invalid pixel format %s\n",
- drm_get_format_name(fb->pixel_format));
+ drm_get_format_name(pixel_format));
goto out;
}

- fb_width = fb->width << 16;
- fb_height = fb->height << 16;
+ /* Check whether the source can be associated with the plane. */
+ if (src) {
+ struct drm_device *dev = plane->dev;
+ unsigned int plane_mask = 1;
+ struct drm_plane *p;
+
+ if (src->plane && src->plane != plane) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ list_for_each_entry(p, &dev->mode_config.plane_list, head) {
+ if (p == plane)
+ break;
+ plane_mask <<= 1;
+ }
+
+ if (!(src->possible_planes & plane_mask)) {
+ DRM_DEBUG_KMS("Invalid source for plane\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* Make sure source coordinates are inside the source. */
+ if (fb) {
+ width = fb->width << 16;
+ height = fb->height << 16;
+ } else {
+ width = src->width << 16;
+ height = src->height << 16;
+ }

- /* Make sure source coordinates are inside the fb. */
- if (src_w > fb_width ||
- src_x > fb_width - src_w ||
- src_h > fb_height ||
- src_y > fb_height - src_h) {
+ if (src_w > width || src_x > width - src_w ||
+ src_h > height || src_y > height - src_h) {
DRM_DEBUG_KMS("Invalid source coordinates "
"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
@@ -2551,12 +2617,24 @@ static int __setplane_internal(struct drm_plane *plane,
}

plane->old_fb = plane->fb;
- ret = plane->funcs->update_plane(plane, crtc, fb,
+ ret = plane->funcs->update_plane(plane, crtc, fb, src,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h);
if (!ret) {
+ mutex_lock(&file_priv->sources_lock);
+ if (src) {
+ list_add_tail(&src->filp_head, &file_priv->sources);
+ src->plane = plane;
+ }
+ if (plane->src) {
+ list_del(&plane->src->filp_head);
+ plane->src->plane = NULL;
+ }
+ mutex_unlock(&file_priv->sources_lock);
+
plane->crtc = crtc;
plane->fb = fb;
+ plane->src = src;
fb = NULL;
} else {
plane->old_fb = NULL;
@@ -2572,9 +2650,11 @@ out:
return ret;
}

-static int setplane_internal(struct drm_plane *plane,
+static int setplane_internal(struct drm_file *file_priv,
+ struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int32_t crtc_x, int32_t crtc_y,
uint32_t crtc_w, uint32_t crtc_h,
/* src_{x,y,w,h} values are 16.16 fixed point */
@@ -2584,7 +2664,7 @@ static int setplane_internal(struct drm_plane *plane,
int ret;

drm_modeset_lock_all(plane->dev);
- ret = __setplane_internal(plane, crtc, fb,
+ ret = __setplane_internal(file_priv, plane, crtc, fb, src,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h);
drm_modeset_unlock_all(plane->dev);
@@ -2612,6 +2692,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
struct drm_plane *plane;
struct drm_crtc *crtc = NULL;
struct drm_framebuffer *fb = NULL;
+ struct drm_live_source *src = NULL;

if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -2628,8 +2709,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
}

/*
- * First, find the plane, crtc, and fb objects. If not available,
- * we don't bother to call the driver.
+ * First, find the plane, crtc, and fb or source objects. If not
+ * available, we don't bother to call the driver.
*/
plane = drm_plane_find(dev, plane_req->plane_id);
if (!plane) {
@@ -2641,7 +2722,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (plane_req->fb_id) {
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
if (!fb) {
- DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+ struct drm_mode_object *obj;
+
+ obj = drm_mode_object_find(dev, plane_req->fb_id,
+ DRM_MODE_OBJECT_LIVE_SOURCE);
+ if (obj)
+ src = obj_to_live_source(obj);
+ }
+
+ if (!fb && !src) {
+ DRM_DEBUG_KMS("Unknown framebuffer or live source ID %d\n",
plane_req->fb_id);
return -ENOENT;
}
@@ -2658,7 +2748,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
* setplane_internal will take care of deref'ing either the old or new
* framebuffer depending on success.
*/
- return setplane_internal(plane, crtc, fb,
+ return setplane_internal(file_priv, plane, crtc, fb, src,
plane_req->crtc_x, plane_req->crtc_y,
plane_req->crtc_w, plane_req->crtc_h,
plane_req->src_x, plane_req->src_y,
@@ -3199,7 +3289,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
* setplane_internal will take care of deref'ing either the old or new
* framebuffer depending on success.
*/
- ret = __setplane_internal(crtc->cursor, crtc, fb,
+ ret = __setplane_internal(file_priv, crtc->cursor, crtc, fb, NULL,
crtc_x, crtc_y, crtc_w, crtc_h,
0, 0, src_w, src_h);

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 076dd606b580..28591acf7e7a 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -167,6 +167,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
INIT_LIST_HEAD(&priv->lhead);
INIT_LIST_HEAD(&priv->fbs);
mutex_init(&priv->fbs_lock);
+ INIT_LIST_HEAD(&priv->sources);
+ mutex_init(&priv->sources_lock);
INIT_LIST_HEAD(&priv->event_list);
init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */
@@ -408,8 +410,10 @@ int drm_release(struct inode *inode, struct file *filp)

drm_events_release(file_priv);

- if (drm_core_check_feature(dev, DRIVER_MODESET))
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
drm_fb_release(file_priv);
+ drm_live_sources_release(file_priv);
+ }

if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_release(dev, file_priv);
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index b62b03635050..09bf8d9ba580 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -222,6 +222,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_update);
*/
int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *lsrc,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 48ccab7fdf63..95ded0286eb9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -127,7 +127,7 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
crtc_w = fb->width - x;
crtc_h = fb->height - y;

- return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
+ return exynos_update_plane(crtc->primary, crtc, fb, NULL, 0, 0,
crtc_w, crtc_h, x, y, crtc_w, crtc_h);
}

@@ -201,7 +201,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
crtc->primary->fb = fb;
crtc_w = fb->width - crtc->x;
crtc_h = fb->height - crtc->y;
- ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
+ ret = exynos_update_plane(crtc->primary, crtc, fb, NULL, 0, 0,
crtc_w, crtc_h, crtc->x, crtc->y,
crtc_w, crtc_h);
if (ret) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index a5616872eee7..693bfbf6b868 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -146,7 +146,8 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,

int
exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 9d3c374e7b3e..bffb282c4860 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -16,7 +16,8 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1aa1cbd16c19..3b72dc9a5676 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11242,7 +11242,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,

drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
ret = primary->funcs->update_plane(primary, &intel_crtc->base,
- fb, 0, 0,
+ fb, NULL, 0, 0,
hdisplay, vdisplay,
x << 16, y << 16,
hdisplay << 16, vdisplay << 16);
@@ -11717,7 +11717,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)

drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
ret = primary->funcs->update_plane(primary, set->crtc, set->fb,
- 0, 0, hdisplay, vdisplay,
+ NULL, 0, 0, hdisplay, vdisplay,
set->x << 16, set->y << 16,
hdisplay << 16, vdisplay << 16);

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 7051da7015d3..be382d02ce14 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1364,7 +1364,7 @@ int intel_plane_restore(struct drm_plane *plane)
if (!plane->crtc || !plane->fb)
return 0;

- return plane->funcs->update_plane(plane, plane->crtc, plane->fb,
+ return plane->funcs->update_plane(plane, plane->crtc, plane->fb, NULL,
plane->state->crtc_x, plane->state->crtc_y,
plane->state->crtc_w, plane->state->crtc_h,
plane->state->src_x, plane->state->src_y,
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 6987e16fe99b..a26d969fab0e 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -295,7 +295,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane)
*/

static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb,
+ struct drm_live_source *src, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 9f2498571d09..485d1de72460 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -91,7 +91,8 @@ cos_mul(int degrees, int factor)

static int
nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
@@ -341,7 +342,8 @@ err:

static int
nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index ee8e2b3a117e..953707c8a795 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -238,6 +238,7 @@ int omap_plane_mode_set(struct drm_plane *plane,

static int omap_plane_update(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 9a5c571b95fc..6c0767a03ad8 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -504,8 +504,9 @@ static int vop_win_queue_fb(struct vop_win *vop_win,

static int vop_update_plane_event(struct drm_plane *plane,
struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x,
- int crtc_y, unsigned int crtc_w,
+ struct drm_framebuffer *fb,
+ struct drm_live_source *src,
+ int crtc_x, int crtc_y, unsigned int crtc_w,
unsigned int crtc_h, uint32_t src_x,
uint32_t src_y, uint32_t src_w,
uint32_t src_h,
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
index 1805bb23b113..236613bcd571 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
@@ -174,7 +174,8 @@ void shmob_drm_plane_setup(struct drm_plane *plane)

static int
shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
index bb6a29339e10..f43a4341e59c 100644
--- a/drivers/gpu/drm/sti/sti_drm_plane.c
+++ b/drivers/gpu/drm/sti/sti_drm_plane.c
@@ -24,7 +24,8 @@ enum sti_layer_desc sti_layer_default_zorder[] = {

static int
sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index b0eb62de1b2e..4ec096e62d9e 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -533,7 +533,7 @@ static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)

/* prepare and commit VID plane */
hqvdp->vid_plane->funcs->update_plane(hqvdp->vid_plane,
- layer->crtc, layer->fb,
+ layer->crtc, layer->fb, NULL,
layer->dst_x, layer->dst_y,
layer->dst_w, layer->dst_h,
layer->src_x, layer->src_y,
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 63c0b0131f61..6adcdb99482a 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -322,6 +322,9 @@ struct drm_file {
struct list_head fbs;
struct mutex fbs_lock;

+ struct list_head sources;
+ struct mutex sources_lock;
+
wait_queue_head_t event_wait;
struct list_head event_list;
int event_space;
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 829280b56874..68b9bb68d015 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -62,6 +62,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev,
int drm_atomic_helper_update_plane(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 775a9a84c5bf..c66e23a60f75 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -759,6 +759,7 @@ struct drm_plane_state {

struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
+ struct drm_live_source *src;
struct fence *fence;

/* Signed dest location allows it to be partially off screen */
@@ -793,6 +794,7 @@ struct drm_plane_state {
struct drm_plane_funcs {
int (*update_plane)(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
@@ -857,6 +859,7 @@ struct drm_plane {

struct drm_crtc *crtc;
struct drm_framebuffer *fb;
+ struct drm_live_source *src;

struct drm_framebuffer *old_fb;

@@ -878,6 +881,7 @@ struct drm_live_source_funcs {
struct drm_live_source {
struct drm_device *dev;
struct list_head head;
+ struct list_head filp_head;

struct drm_mode_object base;

@@ -1149,6 +1153,7 @@ struct drm_mode_config {
struct drm_property *prop_crtc_w;
struct drm_property *prop_crtc_h;
struct drm_property *prop_fb_id;
+ struct drm_property *prop_src_id;
struct drm_property *prop_crtc_id;
struct drm_property *prop_active;

@@ -1311,6 +1316,7 @@ extern int drm_live_source_init(struct drm_device *dev,
const uint32_t *formats, uint32_t format_count,
const struct drm_live_source_funcs *funcs);
extern void drm_live_source_cleanup(struct drm_live_source *src);
+extern void drm_live_sources_release(struct drm_file *priv);

extern const char *drm_get_connector_status_name(enum drm_connector_status status);
extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
index e48157a5a59c..441cd55e094c 100644
--- a/include/drm/drm_plane_helper.h
+++ b/include/drm/drm_plane_helper.h
@@ -93,6 +93,7 @@ extern int drm_plane_helper_check_update(struct drm_plane *plane,
extern int drm_primary_helper_update(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
--
2.0.5