Commit 960de2cf authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[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: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 4c16d6a0
...@@ -22,6 +22,41 @@ ...@@ -22,6 +22,41 @@
#include "vsp1_entity.h" #include "vsp1_entity.h"
#include "vsp1_video.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 * V4L2 Subdevice Operations
*/ */
...@@ -158,6 +193,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity, ...@@ -158,6 +193,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
if (i == ARRAY_SIZE(vsp1_routes)) if (i == ARRAY_SIZE(vsp1_routes))
return -EINVAL; return -EINVAL;
mutex_init(&entity->lock);
entity->vsp1 = vsp1; entity->vsp1 = vsp1;
entity->source_pad = num_pads - 1; entity->source_pad = num_pads - 1;
...@@ -191,4 +228,6 @@ void vsp1_entity_destroy(struct vsp1_entity *entity) ...@@ -191,4 +228,6 @@ void vsp1_entity_destroy(struct vsp1_entity *entity)
if (entity->subdev.ctrl_handler) if (entity->subdev.ctrl_handler)
v4l2_ctrl_handler_free(entity->subdev.ctrl_handler); v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
media_entity_cleanup(&entity->subdev.entity); media_entity_cleanup(&entity->subdev.entity);
mutex_destroy(&entity->lock);
} }
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#define __VSP1_ENTITY_H__ #define __VSP1_ENTITY_H__
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
...@@ -71,6 +72,9 @@ struct vsp1_entity { ...@@ -71,6 +72,9 @@ struct vsp1_entity {
struct v4l2_mbus_framefmt *formats; struct v4l2_mbus_framefmt *formats;
struct vsp1_video *video; 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) 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, ...@@ -92,4 +96,7 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity,
void vsp1_entity_init_formats(struct v4l2_subdev *subdev, void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
struct v4l2_subdev_fh *fh); 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__ */ #endif /* __VSP1_ENTITY_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment