| From 51e64f84d5cda37988092bfba75413931f6809d8 Mon Sep 17 00:00:00 2001 |
| From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Date: Sat, 31 May 2014 10:40:51 -0300 |
| Subject: [media] v4l: vsp1: Setup control handler automatically at stream on |
| time |
| |
| When setting a control directly on a subdev node the VSP1 driver doesn't |
| guarantee that the device is powered on. This leads to crashes when the |
| control handlers writes to hardware registers. One easy way to fix this |
| is to ensure that the device gets powered on when a subdev node is |
| opened. However, this consumes power unnecessarily, as there's no need |
| to power the device on when setting formats on the pipeline. |
| Furthermore, control handler setup at entity init time suffers from the |
| same problem as the device isn't powered on easier. |
| |
| Fix this by extend the entity base object to setup the control handler |
| automatically when starting the stream. Entities must then skip writing |
| to registers in the set control handler when not streaming, which can be |
| tested with the new vsp1_entity_is_streaming() helper function. |
| |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> |
| (cherry picked from commit 960de2cff49a4e5f45e6a60175f4298cc34dc526) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/media/platform/vsp1/vsp1_entity.c | 39 +++++++++++++++++++++++++++++++ |
| drivers/media/platform/vsp1/vsp1_entity.h | 7 ++++++ |
| 2 files changed, 46 insertions(+) |
| |
| diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c |
| index ceac0d7e5643..79af71d5e270 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_entity.c |
| +++ b/drivers/media/platform/vsp1/vsp1_entity.c |
| @@ -22,6 +22,41 @@ |
| #include "vsp1_entity.h" |
| #include "vsp1_video.h" |
| |
| +bool vsp1_entity_is_streaming(struct vsp1_entity *entity) |
| +{ |
| + bool streaming; |
| + |
| + mutex_lock(&entity->lock); |
| + streaming = entity->streaming; |
| + mutex_unlock(&entity->lock); |
| + |
| + return streaming; |
| +} |
| + |
| +int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming) |
| +{ |
| + int ret; |
| + |
| + mutex_lock(&entity->lock); |
| + entity->streaming = streaming; |
| + mutex_unlock(&entity->lock); |
| + |
| + if (!streaming) |
| + return 0; |
| + |
| + if (!entity->subdev.ctrl_handler) |
| + return 0; |
| + |
| + ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler); |
| + if (ret < 0) { |
| + mutex_lock(&entity->lock); |
| + entity->streaming = false; |
| + mutex_unlock(&entity->lock); |
| + } |
| + |
| + return ret; |
| +} |
| + |
| /* ----------------------------------------------------------------------------- |
| * V4L2 Subdevice Operations |
| */ |
| @@ -158,6 +193,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, |
| if (i == ARRAY_SIZE(vsp1_routes)) |
| return -EINVAL; |
| |
| + mutex_init(&entity->lock); |
| + |
| entity->vsp1 = vsp1; |
| entity->source_pad = num_pads - 1; |
| |
| @@ -191,4 +228,6 @@ void vsp1_entity_destroy(struct vsp1_entity *entity) |
| if (entity->subdev.ctrl_handler) |
| v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); |
| media_entity_cleanup(&entity->subdev.entity); |
| + |
| + mutex_destroy(&entity->lock); |
| } |
| diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h |
| index f0257f68f16a..aa20aaa58208 100644 |
| --- a/drivers/media/platform/vsp1/vsp1_entity.h |
| +++ b/drivers/media/platform/vsp1/vsp1_entity.h |
| @@ -14,6 +14,7 @@ |
| #define __VSP1_ENTITY_H__ |
| |
| #include <linux/list.h> |
| +#include <linux/mutex.h> |
| |
| #include <media/v4l2-subdev.h> |
| |
| @@ -71,6 +72,9 @@ struct vsp1_entity { |
| struct v4l2_mbus_framefmt *formats; |
| |
| struct vsp1_video *video; |
| + |
| + struct mutex lock; /* Protects the streaming field */ |
| + bool streaming; |
| }; |
| |
| static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev) |
| @@ -92,4 +96,7 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity, |
| void vsp1_entity_init_formats(struct v4l2_subdev *subdev, |
| struct v4l2_subdev_fh *fh); |
| |
| +bool vsp1_entity_is_streaming(struct vsp1_entity *entity); |
| +int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming); |
| + |
| #endif /* __VSP1_ENTITY_H__ */ |
| -- |
| 2.1.2 |
| |