[media] solo6x10: implement the new motion detection controls
authorHans Verkuil <hans.verkuil@cisco.com>
Tue, 10 Jun 2014 10:37:30 +0000 (07:37 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Thu, 17 Jul 2014 14:57:30 +0000 (11:57 -0300)
Replace the custom ioctls to set motion detection thresholds by standard
matrix controls.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/staging/media/solo6x10/solo6x10-disp.c
drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
drivers/staging/media/solo6x10/solo6x10.h

index 145295a5db72baa1942217c4d5dc19023a278132..44d98b8ed749ea074d9363be67df1d9a60b9e905 100644 (file)
@@ -211,7 +211,7 @@ int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
 }
 
 int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
-               const struct solo_motion_thresholds *thresholds)
+               const u16 *thresholds)
 {
        u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
        u16 buf[64];
@@ -221,7 +221,7 @@ int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
        memset(buf, 0, sizeof(buf));
        for (y = 0; y < SOLO_MOTION_SZ; y++) {
                for (x = 0; x < SOLO_MOTION_SZ; x++)
-                       buf[x] = cpu_to_le16(thresholds->thresholds[y][x]);
+                       buf[x] = cpu_to_le16(thresholds[y * SOLO_MOTION_SZ + x]);
                ret |= solo_p2m_dma(solo_dev, 1, buf,
                        SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * sizeof(buf),
                        sizeof(buf), 0, 0);
index 37f7fd090bc29e2c99e2aa73063baf805ecf5668..f7ec94c39314212b9ddcb3a9fb0ceacf79e8b691 100644 (file)
@@ -1068,31 +1068,6 @@ static int solo_s_parm(struct file *file, void *priv,
        return solo_g_parm(file, priv, sp);
 }
 
-static long solo_enc_default(struct file *file, void *fh,
-                       bool valid_prio, unsigned int cmd, void *arg)
-{
-       struct solo_enc_dev *solo_enc = video_drvdata(file);
-       struct solo_dev *solo_dev = solo_enc->solo_dev;
-       struct solo_motion_thresholds *thresholds = arg;
-
-       switch (cmd) {
-       case SOLO_IOC_G_MOTION_THRESHOLDS:
-               *thresholds = solo_enc->motion_thresholds;
-               return 0;
-
-       case SOLO_IOC_S_MOTION_THRESHOLDS:
-               if (!valid_prio)
-                       return -EBUSY;
-               solo_enc->motion_thresholds = *thresholds;
-               if (solo_enc->motion_enabled && !solo_enc->motion_global)
-                       return solo_set_motion_block(solo_dev, solo_enc->ch,
-                                               &solo_enc->motion_thresholds);
-               return 0;
-       default:
-               return -ENOTTY;
-       }
-}
-
 static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct solo_enc_dev *solo_enc =
@@ -1111,25 +1086,30 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
        case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
                solo_enc->gop = ctrl->val;
                return 0;
-       case V4L2_CID_MOTION_THRESHOLD:
-               solo_enc->motion_thresh = ctrl->val;
+       case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
+               solo_enc->motion_thresh = ctrl->val << 8;
                if (!solo_enc->motion_global || !solo_enc->motion_enabled)
                        return 0;
                return solo_set_motion_threshold(solo_dev, solo_enc->ch,
-                       ctrl->val);
-       case V4L2_CID_MOTION_MODE:
-               solo_enc->motion_global = ctrl->val == 1;
-               solo_enc->motion_enabled = ctrl->val > 0;
+                               solo_enc->motion_thresh);
+       case V4L2_CID_DETECT_MD_MODE:
+               solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
+               solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
                if (ctrl->val) {
                        if (solo_enc->motion_global)
-                               solo_set_motion_threshold(solo_dev,
-                                       solo_enc->ch, solo_enc->motion_thresh);
+                               solo_set_motion_threshold(solo_dev, solo_enc->ch,
+                                       solo_enc->motion_thresh);
                        else
                                solo_set_motion_block(solo_dev, solo_enc->ch,
-                                               &solo_enc->motion_thresholds);
+                                       solo_enc->md_thresholds->p_cur.p_u16);
                }
                solo_motion_toggle(solo_enc, ctrl->val);
                return 0;
+       case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
+               if (solo_enc->motion_enabled && !solo_enc->motion_global)
+                       return solo_set_motion_block(solo_dev, solo_enc->ch,
+                                       solo_enc->md_thresholds->p_new.p_u16);
+               break;
        case V4L2_CID_OSD_TEXT:
                strcpy(solo_enc->osd_text, ctrl->p_new.p_char);
                err = solo_osd_print(solo_enc);
@@ -1181,7 +1161,6 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
        .vidioc_log_status              = v4l2_ctrl_log_status,
        .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
-       .vidioc_default                 = solo_enc_default,
 };
 
 static const struct video_device solo_enc_template = {
@@ -1197,33 +1176,6 @@ static const struct v4l2_ctrl_ops solo_ctrl_ops = {
        .s_ctrl = solo_s_ctrl,
 };
 
-static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = {
-       .ops = &solo_ctrl_ops,
-       .id = V4L2_CID_MOTION_THRESHOLD,
-       .name = "Motion Detection Threshold",
-       .type = V4L2_CTRL_TYPE_INTEGER,
-       .max = 0xffff,
-       .def = SOLO_DEF_MOT_THRESH,
-       .step = 1,
-       .flags = V4L2_CTRL_FLAG_SLIDER,
-};
-
-static const char * const solo_motion_mode_menu[] = {
-       "Disabled",
-       "Global Threshold",
-       "Regional Threshold",
-       NULL
-};
-
-static const struct v4l2_ctrl_config solo_motion_enable_ctrl = {
-       .ops = &solo_ctrl_ops,
-       .id = V4L2_CID_MOTION_MODE,
-       .name = "Motion Detection Mode",
-       .type = V4L2_CTRL_TYPE_MENU,
-       .qmenu = solo_motion_mode_menu,
-       .max = 2,
-};
-
 static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
        .ops = &solo_ctrl_ops,
        .id = V4L2_CID_OSD_TEXT,
@@ -1233,13 +1185,22 @@ static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
        .step = 1,
 };
 
+/* Motion Detection Threshold matrix */
+static const struct v4l2_ctrl_config solo_md_thresholds = {
+       .ops = &solo_ctrl_ops,
+       .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
+       .dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
+       .def = SOLO_DEF_MOT_THRESH,
+       .max = 65535,
+       .step = 1,
+};
+
 static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
                                           u8 ch, unsigned nr)
 {
        struct solo_enc_dev *solo_enc;
        struct v4l2_ctrl_handler *hdl;
        int ret;
-       int x, y;
 
        solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
        if (!solo_enc)
@@ -1260,9 +1221,16 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
                        V4L2_CID_SHARPNESS, 0, 15, 1, 0);
        v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
                        V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
-       v4l2_ctrl_new_custom(hdl, &solo_motion_threshold_ctrl, NULL);
-       v4l2_ctrl_new_custom(hdl, &solo_motion_enable_ctrl, NULL);
+       v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
+                       V4L2_CID_DETECT_MD_MODE,
+                       V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
+                       V4L2_DETECT_MD_MODE_DISABLED);
+       v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+                       V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
+                       SOLO_DEF_MOT_THRESH >> 8);
        v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
+       solo_enc->md_thresholds =
+               v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
        if (hdl->error) {
                ret = hdl->error;
                goto hdl_free;
@@ -1283,11 +1251,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
        solo_enc->mode = SOLO_ENC_MODE_CIF;
        solo_enc->motion_global = true;
        solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
-       for (y = 0; y < SOLO_MOTION_SZ; y++)
-               for (x = 0; x < SOLO_MOTION_SZ; x++)
-                       solo_enc->motion_thresholds.thresholds[y][x] =
-                                                       SOLO_DEF_MOT_THRESH;
-
        solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
        solo_enc->vidq.ops = &solo_enc_video_qops;
index 8964f8be158e95dfcb0d60a075e4325371c977e5..19cb56b8ffb933c5da7edd9ac4b934d22b5cd58d 100644 (file)
 #endif
 
 #define SOLO_CID_CUSTOM_BASE           (V4L2_CID_USER_BASE | 0xf000)
-#define V4L2_CID_MOTION_MODE           (SOLO_CID_CUSTOM_BASE+0)
-#define V4L2_CID_MOTION_THRESHOLD      (SOLO_CID_CUSTOM_BASE+1)
 #define V4L2_CID_MOTION_TRACE          (SOLO_CID_CUSTOM_BASE+2)
 #define V4L2_CID_OSD_TEXT              (SOLO_CID_CUSTOM_BASE+3)
 
  * effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
  * The 5th sample on the 10th row is (10*64)+5 = 645.
  *
- * Using a 64x64 array will result in a problem on some architectures like
- * the powerpc where the size of the argument is limited to 13 bits.
- * Since both PAL and NTSC do not use the full table anyway I've chosen
- * to limit the array to 45x45 (45*16 = 720, which is the maximum PAL/NTSC
- * width).
+ * Internally it is stored as a 45x45 array (45*16 = 720, which is the
+ * maximum PAL/NTSC width).
  */
 #define SOLO_MOTION_SZ (45)
-struct solo_motion_thresholds {
-       __u16   thresholds[SOLO_MOTION_SZ][SOLO_MOTION_SZ];
-};
-
-#define SOLO_IOC_G_MOTION_THRESHOLDS   _IOR('V', BASE_VIDIOC_PRIVATE+0, struct solo_motion_thresholds)
-#define SOLO_IOC_S_MOTION_THRESHOLDS   _IOW('V', BASE_VIDIOC_PRIVATE+1, struct solo_motion_thresholds)
 
 enum SOLO_I2C_STATE {
        IIC_STATE_IDLE,
@@ -168,6 +157,7 @@ struct solo_enc_dev {
        struct solo_dev *solo_dev;
        /* V4L2 Items */
        struct v4l2_ctrl_handler hdl;
+       struct v4l2_ctrl *md_thresholds;
        struct video_device     *vfd;
        /* General accounting */
        struct mutex            lock;
@@ -176,7 +166,6 @@ struct solo_enc_dev {
        u8                      mode, gop, qp, interlaced, interval;
        u8                      bw_weight;
        u16                     motion_thresh;
-       struct solo_motion_thresholds motion_thresholds;
        bool                    motion_global;
        bool                    motion_enabled;
        u16                     width;
@@ -404,7 +393,7 @@ void solo_update_mode(struct solo_enc_dev *solo_enc);
 /* Set the threshold for motion detection */
 int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
 int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
-               const struct solo_motion_thresholds *thresholds);
+               const u16 *thresholds);
 #define SOLO_DEF_MOT_THRESH            0x0300
 
 /* Write text on OSD */