aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2013-03-18 07:43:14 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-25 07:51:50 -0400
commitf5df0b7ff57732f938373f49e89ca219d4717836 (patch)
treed252e97ccf1f235be73c9213dcbe3a9d4229c2ee
parent69996873478d75381d14abbc9e768cc38d82e94b (diff)
[media] solo6x10: clean up motion detection handling
An earlier patch temporarily disabled regional motion detection. This patch adds it back: the 'Motion Detection Enable' control is now a 'Motion Detection Mode'. And to set/get the regional thresholds two new ioctls were added to get/set those thresholds. The BUF_FLAG constants were also updated to prevent clashing with existing buffer flags. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/staging/media/solo6x10/disp.c37
-rw-r--r--drivers/staging/media/solo6x10/solo6x10.h27
-rw-r--r--drivers/staging/media/solo6x10/v4l2-enc.c87
3 files changed, 97 insertions, 54 deletions
diff --git a/drivers/staging/media/solo6x10/disp.c b/drivers/staging/media/solo6x10/disp.c
index 7007006e9638..78070c843f90 100644
--- a/drivers/staging/media/solo6x10/disp.c
+++ b/drivers/staging/media/solo6x10/disp.c
@@ -201,31 +201,22 @@ int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
201 val, SOLO_MOT_THRESH_SIZE); 201 val, SOLO_MOT_THRESH_SIZE);
202} 202}
203 203
204int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch, u16 val, 204int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
205 u16 block) 205 const struct solo_motion_thresholds *thresholds)
206{ 206{
207 u16 buf[64]; 207 u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
208 u32 addr; 208 u16 buf[SOLO_MOTION_SZ];
209 int re; 209 int x, y;
210 210 int ret = 0;
211 addr = SOLO_MOTION_EXT_ADDR(solo_dev) +
212 SOLO_MOT_FLAG_AREA +
213 (SOLO_MOT_THRESH_SIZE * 2 * ch) +
214 (block * 2);
215
216 /* Read and write only on a 128-byte boundary; 4-byte writes with
217 solo_p2m_dma silently failed. Bluecherry bug #908. */
218 re = solo_p2m_dma(solo_dev, 0, &buf, addr & ~0x7f, sizeof(buf), 0, 0);
219 if (re)
220 return re;
221
222 buf[(addr & 0x7f) / 2] = val;
223
224 re = solo_p2m_dma(solo_dev, 1, &buf, addr & ~0x7f, sizeof(buf), 0, 0);
225 if (re)
226 return re;
227 211
228 return 0; 212 for (y = 0; y < SOLO_MOTION_SZ; y++) {
213 for (x = 0; x < SOLO_MOTION_SZ; x++)
214 buf[x] = cpu_to_le16(thresholds->thresholds[y][x]);
215 ret |= solo_p2m_dma(solo_dev, 1, buf,
216 SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * sizeof(buf),
217 sizeof(buf), 0, 0);
218 }
219 return ret;
229} 220}
230 221
231/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k 222/* First 8k is motion flag (512 bytes * 16). Following that is an 8k+8k
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index 94ac294fb048..da7611ea0e7e 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -98,16 +98,30 @@
98#define SOLO_DEFAULT_QP 3 98#define SOLO_DEFAULT_QP 3
99 99
100#ifndef V4L2_BUF_FLAG_MOTION_ON 100#ifndef V4L2_BUF_FLAG_MOTION_ON
101#define V4L2_BUF_FLAG_MOTION_ON 0x0400 101#define V4L2_BUF_FLAG_MOTION_ON 0x10000
102#define V4L2_BUF_FLAG_MOTION_DETECTED 0x0800 102#define V4L2_BUF_FLAG_MOTION_DETECTED 0x20000
103#endif 103#endif
104 104
105#define SOLO_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000) 105#define SOLO_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
106#define V4L2_CID_MOTION_ENABLE (SOLO_CID_CUSTOM_BASE+0) 106#define V4L2_CID_MOTION_MODE (SOLO_CID_CUSTOM_BASE+0)
107#define V4L2_CID_MOTION_THRESHOLD (SOLO_CID_CUSTOM_BASE+1) 107#define V4L2_CID_MOTION_THRESHOLD (SOLO_CID_CUSTOM_BASE+1)
108#define V4L2_CID_MOTION_TRACE (SOLO_CID_CUSTOM_BASE+2) 108#define V4L2_CID_MOTION_TRACE (SOLO_CID_CUSTOM_BASE+2)
109#define V4L2_CID_OSD_TEXT (SOLO_CID_CUSTOM_BASE+3) 109#define V4L2_CID_OSD_TEXT (SOLO_CID_CUSTOM_BASE+3)
110 110
111/*
112 * Motion thresholds are in a table of 64x64 samples, with
113 * each sample representing 16x16 pixels of the source. In
114 * effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
115 * The 5th sample on the 10th row is (10*64)+5 = 645.
116 */
117#define SOLO_MOTION_SZ (64)
118struct solo_motion_thresholds {
119 __u16 thresholds[SOLO_MOTION_SZ][SOLO_MOTION_SZ];
120};
121
122#define SOLO_IOC_G_MOTION_THRESHOLDS _IOR('V', BASE_VIDIOC_PRIVATE+0, struct solo_motion_thresholds)
123#define SOLO_IOC_S_MOTION_THRESHOLDS _IOW('V', BASE_VIDIOC_PRIVATE+1, struct solo_motion_thresholds)
124
111enum SOLO_I2C_STATE { 125enum SOLO_I2C_STATE {
112 IIC_STATE_IDLE, 126 IIC_STATE_IDLE,
113 IIC_STATE_START, 127 IIC_STATE_START,
@@ -157,6 +171,9 @@ struct solo_enc_dev {
157 u8 mode, gop, qp, interlaced, interval; 171 u8 mode, gop, qp, interlaced, interval;
158 u8 bw_weight; 172 u8 bw_weight;
159 u16 motion_thresh; 173 u16 motion_thresh;
174 struct solo_motion_thresholds motion_thresholds;
175 bool motion_global;
176 bool motion_enabled;
160 u16 width; 177 u16 width;
161 u16 height; 178 u16 height;
162 179
@@ -381,8 +398,8 @@ void solo_update_mode(struct solo_enc_dev *solo_enc);
381 398
382/* Set the threshold for motion detection */ 399/* Set the threshold for motion detection */
383int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val); 400int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
384int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch, u16 val, 401int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
385 u16 block); 402 const struct solo_motion_thresholds *thresholds);
386#define SOLO_DEF_MOT_THRESH 0x0300 403#define SOLO_DEF_MOT_THRESH 0x0300
387 404
388/* Write text on OSD */ 405/* Write text on OSD */
diff --git a/drivers/staging/media/solo6x10/v4l2-enc.c b/drivers/staging/media/solo6x10/v4l2-enc.c
index 0efb6237f685..b1fa78b2eaff 100644
--- a/drivers/staging/media/solo6x10/v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/v4l2-enc.c
@@ -511,6 +511,8 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
511 int ret; 511 int ret;
512 512
513 /* Check for motion flags */ 513 /* Check for motion flags */
514 vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_MOTION_ON |
515 V4L2_BUF_FLAG_MOTION_DETECTED);
514 if (solo_is_motion_on(solo_enc)) { 516 if (solo_is_motion_on(solo_enc)) {
515 vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_ON; 517 vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_ON;
516 if (enc_buf->motion) 518 if (enc_buf->motion)
@@ -1018,6 +1020,31 @@ static int solo_s_parm(struct file *file, void *priv,
1018 return 0; 1020 return 0;
1019} 1021}
1020 1022
1023static long solo_enc_default(struct file *file, void *fh,
1024 bool valid_prio, int cmd, void *arg)
1025{
1026 struct solo_enc_dev *solo_enc = video_drvdata(file);
1027 struct solo_dev *solo_dev = solo_enc->solo_dev;
1028 struct solo_motion_thresholds *thresholds = arg;
1029
1030 switch (cmd) {
1031 case SOLO_IOC_G_MOTION_THRESHOLDS:
1032 *thresholds = solo_enc->motion_thresholds;
1033 return 0;
1034
1035 case SOLO_IOC_S_MOTION_THRESHOLDS:
1036 if (!valid_prio)
1037 return -EBUSY;
1038 solo_enc->motion_thresholds = *thresholds;
1039 if (solo_enc->motion_enabled && !solo_enc->motion_global)
1040 return solo_set_motion_block(solo_dev, solo_enc->ch,
1041 &solo_enc->motion_thresholds);
1042 return 0;
1043 default:
1044 return -ENOTTY;
1045 }
1046}
1047
1021static int solo_s_ctrl(struct v4l2_ctrl *ctrl) 1048static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
1022{ 1049{
1023 struct solo_enc_dev *solo_enc = 1050 struct solo_enc_dev *solo_enc =
@@ -1036,28 +1063,22 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
1036 case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 1063 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1037 solo_enc->gop = ctrl->val; 1064 solo_enc->gop = ctrl->val;
1038 return 0; 1065 return 0;
1039 case V4L2_CID_MOTION_THRESHOLD: { 1066 case V4L2_CID_MOTION_THRESHOLD:
1040 u16 block = (ctrl->val >> 16) & 0xffff; 1067 solo_enc->motion_thresh = ctrl->val;
1041 u16 value = ctrl->val & 0xffff; 1068 if (!solo_enc->motion_global || !solo_enc->motion_enabled)
1042 1069 return 0;
1043 /* Motion thresholds are in a table of 64x64 samples, with 1070 return solo_set_motion_threshold(solo_dev, solo_enc->ch, ctrl->val);
1044 * each sample representing 16x16 pixels of the source. In 1071 case V4L2_CID_MOTION_MODE:
1045 * effect, 44x30 samples are used for NTSC, and 44x36 for PAL. 1072 solo_enc->motion_global = ctrl->val == 1;
1046 * The 5th sample on the 10th row is (10*64)+5 = 645. 1073 solo_enc->motion_enabled = ctrl->val > 0;
1047 * 1074 if (ctrl->val) {
1048 * Block is 0 to set the threshold globally, or any positive 1075 if (solo_enc->motion_global)
1049 * number under 2049 to set block-1 individually. */ 1076 solo_set_motion_threshold(solo_dev, solo_enc->ch,
1050 /* Currently we limit support to block 0 only. A later patch 1077 solo_enc->motion_thresh);
1051 * will add a new ioctl to set all other blocks. */ 1078 else
1052 if (block == 0) { 1079 solo_set_motion_block(solo_dev, solo_enc->ch,
1053 solo_enc->motion_thresh = value; 1080 &solo_enc->motion_thresholds);
1054 return solo_set_motion_threshold(solo_dev,
1055 solo_enc->ch, value);
1056 } 1081 }
1057 return solo_set_motion_block(solo_dev, solo_enc->ch,
1058 value, block - 1);
1059 }
1060 case V4L2_CID_MOTION_ENABLE:
1061 solo_motion_toggle(solo_enc, ctrl->val); 1082 solo_motion_toggle(solo_enc, ctrl->val);
1062 return 0; 1083 return 0;
1063 case V4L2_CID_OSD_TEXT: 1084 case V4L2_CID_OSD_TEXT:
@@ -1111,6 +1132,7 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
1111 .vidioc_log_status = v4l2_ctrl_log_status, 1132 .vidioc_log_status = v4l2_ctrl_log_status,
1112 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 1133 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1113 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1134 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1135 .vidioc_default = solo_enc_default,
1114}; 1136};
1115 1137
1116static const struct video_device solo_enc_template = { 1138static const struct video_device solo_enc_template = {
@@ -1137,13 +1159,20 @@ static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = {
1137 .flags = V4L2_CTRL_FLAG_SLIDER, 1159 .flags = V4L2_CTRL_FLAG_SLIDER,
1138}; 1160};
1139 1161
1162static const char * const solo_motion_mode_menu[] = {
1163 "Disabled",
1164 "Global Threshold",
1165 "Regional Threshold",
1166 NULL
1167};
1168
1140static const struct v4l2_ctrl_config solo_motion_enable_ctrl = { 1169static const struct v4l2_ctrl_config solo_motion_enable_ctrl = {
1141 .ops = &solo_ctrl_ops, 1170 .ops = &solo_ctrl_ops,
1142 .id = V4L2_CID_MOTION_ENABLE, 1171 .id = V4L2_CID_MOTION_MODE,
1143 .name = "Motion Detection Enable", 1172 .name = "Motion Detection Mode",
1144 .type = V4L2_CTRL_TYPE_BOOLEAN, 1173 .type = V4L2_CTRL_TYPE_MENU,
1145 .max = 1, 1174 .qmenu = solo_motion_mode_menu,
1146 .step = 1, 1175 .max = 2,
1147}; 1176};
1148 1177
1149static const struct v4l2_ctrl_config solo_osd_text_ctrl = { 1178static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
@@ -1161,6 +1190,7 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
1161 struct solo_enc_dev *solo_enc; 1190 struct solo_enc_dev *solo_enc;
1162 struct v4l2_ctrl_handler *hdl; 1191 struct v4l2_ctrl_handler *hdl;
1163 int ret; 1192 int ret;
1193 int x, y;
1164 1194
1165 solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL); 1195 solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
1166 if (!solo_enc) 1196 if (!solo_enc)
@@ -1201,7 +1231,12 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
1201 solo_enc->gop = solo_dev->fps; 1231 solo_enc->gop = solo_dev->fps;
1202 solo_enc->interval = 1; 1232 solo_enc->interval = 1;
1203 solo_enc->mode = SOLO_ENC_MODE_CIF; 1233 solo_enc->mode = SOLO_ENC_MODE_CIF;
1234 solo_enc->motion_global = true;
1204 solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH; 1235 solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
1236 for (y = 0; y < SOLO_MOTION_SZ; y++)
1237 for (x = 0; x < SOLO_MOTION_SZ; x++)
1238 solo_enc->motion_thresholds.thresholds[y][x] =
1239 SOLO_DEF_MOT_THRESH;
1205 1240
1206 solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1241 solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1207 solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; 1242 solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;