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

Signed-off-by: Laurent Pinchart <[email protected]>
---
 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to