[PATCH v2 6/6] staging: media: omap4iss: ipipe: Expose the RGB2RGB blending matrix

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Expose the module as two controls, one for the 3x3 multiplier matrix and
one for the 3x1 offset vector.

Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
---
 drivers/staging/media/omap4iss/iss_ipipe.c | 129 ++++++++++++++++++++++++++++-
 drivers/staging/media/omap4iss/iss_ipipe.h |  17 ++++
 2 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c
index 73b165e..624c5d2 100644
--- a/drivers/staging/media/omap4iss/iss_ipipe.c
+++ b/drivers/staging/media/omap4iss/iss_ipipe.c
@@ -119,6 +119,105 @@ static void ipipe_configure(struct iss_ipipe_device *ipipe)
 }
 
 /* -----------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+#define OMAP4ISS_IPIPE_CID_BASE			(V4L2_CID_USER_BASE | 0xf000)
+#define OMAP4ISS_IPIPE_CID_RGB2RGB_MULT		(OMAP4ISS_IPIPE_CID_BASE + 0)
+#define OMAP4ISS_IPIPE_CID_RGB2RGB_OFFSET	(OMAP4ISS_IPIPE_CID_BASE + 1)
+
+/*
+ * ipipe_s_ctrl - Handle set control subdev method
+ * @ctrl: pointer to v4l2 control structure
+ */
+static int ipipe_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct iss_ipipe_device *ipipe =
+		container_of(ctrl->handler, struct iss_ipipe_device, ctrls);
+	struct iss_device *iss = to_iss_device(ipipe);
+	unsigned int i;
+
+	mutex_lock(&ipipe->lock);
+
+	if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED)
+		goto done;
+
+	switch (ctrl->id) {
+	case OMAP4ISS_IPIPE_CID_RGB2RGB_MULT:
+	case OMAP4ISS_IPIPE_CID_RGB2RGB_OFFSET:
+		ctrl = ipipe->rgb2rgb_mult;
+		for (i = 0; i < ctrl->elems; ++i)
+			iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE,
+				      IPIPE_RGB1_MUL_RR + 4 * i,
+				      ctrl->p_new.p_s16[i]);
+
+		ctrl = ipipe->rgb2rgb_offset;
+		for (i = 0; i < ctrl->elems; ++i)
+			iss_reg_write(iss, OMAP4_ISS_MEM_ISP_IPIPE,
+				      IPIPE_RGB1_OFT_OR + 4 * i,
+				      ctrl->p_new.p_s16[i]);
+		break;
+	}
+
+done:
+	mutex_unlock(&ipipe->lock);
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops ipipe_ctrl_ops = {
+	.s_ctrl = ipipe_s_ctrl,
+};
+
+static void ipipe_ctrl_type_init(const struct v4l2_ctrl *ctrl,
+				 union v4l2_ctrl_ptr ptr)
+{
+	unsigned int i;
+
+	switch (ctrl->id) {
+	case OMAP4ISS_IPIPE_CID_RGB2RGB_MULT:
+		/*
+		 * Initialize the diagonal to 1.0 and all other elements to
+		 * 0.0.
+		 */
+		for (i = 0; i < ctrl->elems; ++i)
+			ptr.p_s16[i] = (i % 4) ? 0 : 256;
+		break;
+	}
+}
+
+static const struct v4l2_ctrl_type_ops ipipe_ctrl_type_ops = {
+	.equal = v4l2_ctrl_type_std_equal,
+	.init = ipipe_ctrl_type_init,
+	.log = v4l2_ctrl_type_std_log,
+	.validate = v4l2_ctrl_type_std_validate,
+};
+
+static const struct v4l2_ctrl_config ipipe_ctrls[] = {
+	{
+		.ops = &ipipe_ctrl_ops,
+		.type_ops = &ipipe_ctrl_type_ops,
+		.id = OMAP4ISS_IPIPE_CID_RGB2RGB_MULT,
+		.name = "RGB2RGB Multiplier",
+		.type = V4L2_CTRL_TYPE_S16,
+		.def = 0,
+		.min = -2048,
+		.max = 2047,
+		.step = 1,
+		.dims = { 3, 3 },
+	}, {
+		.ops = &ipipe_ctrl_ops,
+		.id = OMAP4ISS_IPIPE_CID_RGB2RGB_OFFSET,
+		.name = "RGB2RGB Offset",
+		.type = V4L2_CTRL_TYPE_S16,
+		.def = 0,
+		.min = -4096,
+		.max = 4095,
+		.step = 1,
+		.dims = { 3 },
+	},
+};
+
+/* -----------------------------------------------------------------------------
  * V4L2 subdev operations
  */
 
@@ -133,9 +232,11 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
 	struct iss_device *iss = to_iss_device(ipipe);
 	int ret = 0;
 
+	mutex_lock(&ipipe->lock);
+
 	if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED) {
 		if (enable == ISS_PIPELINE_STREAM_STOPPED)
-			return 0;
+			goto done;
 
 		omap4iss_isp_subclk_enable(iss, OMAP4_ISS_ISP_SUBCLK_IPIPE);
 
@@ -161,7 +262,7 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
 
 	case ISS_PIPELINE_STREAM_STOPPED:
 		if (ipipe->state == ISS_PIPELINE_STREAM_STOPPED)
-			return 0;
+			goto done;
 		if (omap4iss_module_sync_idle(&sd->entity, &ipipe->wait,
 					      &ipipe->stopping))
 			ret = -ETIMEDOUT;
@@ -172,6 +273,13 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
 	}
 
 	ipipe->state = enable;
+
+done:
+	mutex_unlock(&ipipe->lock);
+
+	if (enable == ISS_PIPELINE_STREAM_CONTINUOUS)
+		v4l2_ctrl_handler_setup(ipipe->subdev.ctrl_handler);
+
 	return ret;
 }
 
@@ -501,6 +609,20 @@ static int ipipe_init_entities(struct iss_ipipe_device *ipipe)
 	v4l2_set_subdevdata(sd, ipipe);
 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
+	v4l2_ctrl_handler_init(&ipipe->ctrls, 2);
+
+	ipipe->rgb2rgb_mult = v4l2_ctrl_new_custom(&ipipe->ctrls,
+						   &ipipe_ctrls[0], NULL);
+	ipipe->rgb2rgb_offset = v4l2_ctrl_new_custom(&ipipe->ctrls,
+						     &ipipe_ctrls[1], NULL);
+
+	if (ipipe->ctrls.error)
+		return ipipe->ctrls.error;
+
+	v4l2_ctrl_cluster(2, &ipipe->rgb2rgb_mult);
+
+	sd->ctrl_handler = &ipipe->ctrls;
+
 	pads[IPIPE_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
 	pads[IPIPE_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
 
@@ -554,6 +676,7 @@ int omap4iss_ipipe_init(struct iss_device *iss)
 
 	ipipe->state = ISS_PIPELINE_STREAM_STOPPED;
 	init_waitqueue_head(&ipipe->wait);
+	mutex_init(&ipipe->lock);
 
 	return ipipe_init_entities(ipipe);
 }
@@ -566,5 +689,7 @@ void omap4iss_ipipe_cleanup(struct iss_device *iss)
 {
 	struct iss_ipipe_device *ipipe = &iss->ipipe;
 
+	v4l2_ctrl_handler_free(&ipipe->ctrls);
 	media_entity_cleanup(&ipipe->subdev.entity);
+	mutex_destroy(&ipipe->lock);
 }
diff --git a/drivers/staging/media/omap4iss/iss_ipipe.h b/drivers/staging/media/omap4iss/iss_ipipe.h
index c22d904..7684271 100644
--- a/drivers/staging/media/omap4iss/iss_ipipe.h
+++ b/drivers/staging/media/omap4iss/iss_ipipe.h
@@ -14,6 +14,10 @@
 #ifndef OMAP4_ISS_IPIPE_H
 #define OMAP4_ISS_IPIPE_H
 
+#include <linux/mutex.h>
+
+#include <media/v4l2-ctrls.h>
+
 #include "iss_video.h"
 
 enum ipipe_input_entity {
@@ -34,9 +38,13 @@ enum ipipe_input_entity {
  * @subdev: V4L2 subdevice
  * @pads: Sink and source media entity pads
  * @formats: Active video formats
+ * @ctrls: Control handler
+ * @rgb2rgb_mult: RGB to RGB matrix multiplier control
+ * @rgb2rgb_offset: RGB to RGB matrix offset control
  * @input: Active input
  * @output: Active outputs
  * @error: A hardware error occurred during capture
+ * @lock: Protects the state field
  * @state: Streaming state
  * @wait: Wait queue used to stop the module
  * @stopping: Stopping state
@@ -46,10 +54,19 @@ struct iss_ipipe_device {
 	struct media_pad pads[IPIPE_PADS_NUM];
 	struct v4l2_mbus_framefmt formats[IPIPE_PADS_NUM];
 
+	struct v4l2_ctrl_handler ctrls;
+	struct {
+		/* RGB2RGB cluster */
+		struct v4l2_ctrl *rgb2rgb_mult;
+		struct v4l2_ctrl *rgb2rgb_offset;
+	};
+
 	enum ipipe_input_entity input;
 	unsigned int output;
 	unsigned int error;
 
+	struct mutex lock;
+	bool streaming;
 	enum iss_pipeline_stream_state state;
 	wait_queue_head_t wait;
 	atomic_t stopping;
-- 
2.0.5

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux