aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Smelkov <kirr@mns.spb.ru>2012-10-23 08:56:59 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-12-26 07:16:47 -0500
commitfe0e990b22c24d53793c8cf246f0e535f31a4406 (patch)
tree7ed485ce2e3874654ae7290bb4b694401b7d4d62
parentcb412a8da82233af001d13c28fc54f25a2001aef (diff)
[media] vivi: Teach it to tune FPS
I was testing my video-over-ethernet subsystem recently, and vivi seemed to be perfect video source for testing when one don't have lots of capture boards and cameras. Only its framerate was hardcoded to NTSC's 30fps, while in my country we usually use PAL (25 fps) and I needed that to precisely simulate bandwidth. That's why here is this patch with ->enum_frameintervals() and ->{g,s}_parm() implemented as suggested by Hans Verkuil which passes v4l2-compliance and manual testing through v4l2-ctl -P / -p <fps>. Regarding newly introduced __get_format(u32 pixelformat) I decided not to convert original get_format() to operate on fourcc codes, since >= 3 places in driver need to deal with v4l2_format and otherwise it won't be handy. [mchehab@redhat.com: Some CodingStyle fixes] Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru> Acked-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/platform/vivi.c104
1 files changed, 96 insertions, 8 deletions
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c
index 7abb046e0fa5..ec6508909f02 100644
--- a/drivers/media/platform/vivi.c
+++ b/drivers/media/platform/vivi.c
@@ -36,9 +36,17 @@
36 36
37#define VIVI_MODULE_NAME "vivi" 37#define VIVI_MODULE_NAME "vivi"
38 38
39/* Wake up at about 30 fps */ 39/* Maximum allowed frame rate
40#define WAKE_NUMERATOR 30 40 *
41#define WAKE_DENOMINATOR 1001 41 * Vivi will allow setting timeperframe in [1/FPS_MAX - FPS_MAX/1] range.
42 *
43 * Ideally FPS_MAX should be infinity, i.e. practically UINT_MAX, but that
44 * might hit application errors when they manipulate these values.
45 *
46 * Besides, for tpf < 1ms image-generation logic should be changed, to avoid
47 * producing frames with equal content.
48 */
49#define FPS_MAX 1000
42 50
43#define MAX_WIDTH 1920 51#define MAX_WIDTH 1920
44#define MAX_HEIGHT 1200 52#define MAX_HEIGHT 1200
@@ -69,6 +77,12 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
69/* Global font descriptor */ 77/* Global font descriptor */
70static const u8 *font8x16; 78static const u8 *font8x16;
71 79
80/* timeperframe: min/max and default */
81static const struct v4l2_fract
82 tpf_min = {.numerator = 1, .denominator = FPS_MAX},
83 tpf_max = {.numerator = FPS_MAX, .denominator = 1},
84 tpf_default = {.numerator = 1001, .denominator = 30000}; /* NTSC */
85
72#define dprintk(dev, level, fmt, arg...) \ 86#define dprintk(dev, level, fmt, arg...) \
73 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) 87 v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
74 88
@@ -150,14 +164,14 @@ static struct vivi_fmt formats[] = {
150 }, 164 },
151}; 165};
152 166
153static struct vivi_fmt *get_format(struct v4l2_format *f) 167static struct vivi_fmt *__get_format(u32 pixelformat)
154{ 168{
155 struct vivi_fmt *fmt; 169 struct vivi_fmt *fmt;
156 unsigned int k; 170 unsigned int k;
157 171
158 for (k = 0; k < ARRAY_SIZE(formats); k++) { 172 for (k = 0; k < ARRAY_SIZE(formats); k++) {
159 fmt = &formats[k]; 173 fmt = &formats[k];
160 if (fmt->fourcc == f->fmt.pix.pixelformat) 174 if (fmt->fourcc == pixelformat)
161 break; 175 break;
162 } 176 }
163 177
@@ -167,6 +181,11 @@ static struct vivi_fmt *get_format(struct v4l2_format *f)
167 return &formats[k]; 181 return &formats[k];
168} 182}
169 183
184static struct vivi_fmt *get_format(struct v4l2_format *f)
185{
186 return __get_format(f->fmt.pix.pixelformat);
187}
188
170/* buffer for one video frame */ 189/* buffer for one video frame */
171struct vivi_buffer { 190struct vivi_buffer {
172 /* common v4l buffer stuff -- must be first */ 191 /* common v4l buffer stuff -- must be first */
@@ -232,6 +251,7 @@ struct vivi_dev {
232 251
233 /* video capture */ 252 /* video capture */
234 struct vivi_fmt *fmt; 253 struct vivi_fmt *fmt;
254 struct v4l2_fract timeperframe;
235 unsigned int width, height; 255 unsigned int width, height;
236 struct vb2_queue vb_vidq; 256 struct vb2_queue vb_vidq;
237 unsigned int field_count; 257 unsigned int field_count;
@@ -689,8 +709,8 @@ static void vivi_thread_tick(struct vivi_dev *dev)
689 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index); 709 dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
690} 710}
691 711
692#define frames_to_ms(frames) \ 712#define frames_to_ms(dev, frames) \
693 ((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR) 713 ((frames * dev->timeperframe.numerator * 1000) / dev->timeperframe.denominator)
694 714
695static void vivi_sleep(struct vivi_dev *dev) 715static void vivi_sleep(struct vivi_dev *dev)
696{ 716{
@@ -706,7 +726,7 @@ static void vivi_sleep(struct vivi_dev *dev)
706 goto stop_task; 726 goto stop_task;
707 727
708 /* Calculate time to wake up */ 728 /* Calculate time to wake up */
709 timeout = msecs_to_jiffies(frames_to_ms(1)); 729 timeout = msecs_to_jiffies(frames_to_ms(dev, 1));
710 730
711 vivi_thread_tick(dev); 731 vivi_thread_tick(dev);
712 732
@@ -1078,6 +1098,70 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1078 return 0; 1098 return 0;
1079} 1099}
1080 1100
1101/* timeperframe is arbitrary and continous */
1102static int vidioc_enum_frameintervals(struct file *file, void *priv,
1103 struct v4l2_frmivalenum *fival)
1104{
1105 struct vivi_fmt *fmt;
1106
1107 if (fival->index)
1108 return -EINVAL;
1109
1110 fmt = __get_format(fival->pixel_format);
1111 if (!fmt)
1112 return -EINVAL;
1113
1114 /* regarding width & height - we support any */
1115
1116 fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
1117
1118 /* fill in stepwise (step=1.0 is requred by V4L2 spec) */
1119 fival->stepwise.min = tpf_min;
1120 fival->stepwise.max = tpf_max;
1121 fival->stepwise.step = (struct v4l2_fract) {1, 1};
1122
1123 return 0;
1124}
1125
1126static int vidioc_g_parm(struct file *file, void *priv,
1127 struct v4l2_streamparm *parm)
1128{
1129 struct vivi_dev *dev = video_drvdata(file);
1130
1131 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1132 return -EINVAL;
1133
1134 parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
1135 parm->parm.capture.timeperframe = dev->timeperframe;
1136 parm->parm.capture.readbuffers = 1;
1137 return 0;
1138}
1139
1140#define FRACT_CMP(a, OP, b) \
1141 ((u64)(a).numerator * (b).denominator OP (u64)(b).numerator * (a).denominator)
1142
1143static int vidioc_s_parm(struct file *file, void *priv,
1144 struct v4l2_streamparm *parm)
1145{
1146 struct vivi_dev *dev = video_drvdata(file);
1147 struct v4l2_fract tpf;
1148
1149 if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1150 return -EINVAL;
1151
1152 tpf = parm->parm.capture.timeperframe;
1153
1154 /* tpf: {*, 0} resets timing; clip to [min, max]*/
1155 tpf = tpf.denominator ? tpf : tpf_default;
1156 tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf;
1157 tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf;
1158
1159 dev->timeperframe = tpf;
1160 parm->parm.capture.timeperframe = tpf;
1161 parm->parm.capture.readbuffers = 1;
1162 return 0;
1163}
1164
1081/* --- controls ---------------------------------------------- */ 1165/* --- controls ---------------------------------------------- */
1082 1166
1083static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 1167static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
@@ -1236,6 +1320,9 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
1236 .vidioc_enum_input = vidioc_enum_input, 1320 .vidioc_enum_input = vidioc_enum_input,
1237 .vidioc_g_input = vidioc_g_input, 1321 .vidioc_g_input = vidioc_g_input,
1238 .vidioc_s_input = vidioc_s_input, 1322 .vidioc_s_input = vidioc_s_input,
1323 .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
1324 .vidioc_g_parm = vidioc_g_parm,
1325 .vidioc_s_parm = vidioc_s_parm,
1239 .vidioc_streamon = vb2_ioctl_streamon, 1326 .vidioc_streamon = vb2_ioctl_streamon,
1240 .vidioc_streamoff = vb2_ioctl_streamoff, 1327 .vidioc_streamoff = vb2_ioctl_streamoff,
1241 .vidioc_log_status = v4l2_ctrl_log_status, 1328 .vidioc_log_status = v4l2_ctrl_log_status,
@@ -1294,6 +1381,7 @@ static int __init vivi_create_instance(int inst)
1294 goto free_dev; 1381 goto free_dev;
1295 1382
1296 dev->fmt = &formats[0]; 1383 dev->fmt = &formats[0];
1384 dev->timeperframe = tpf_default;
1297 dev->width = 640; 1385 dev->width = 640;
1298 dev->height = 480; 1386 dev->height = 480;
1299 dev->pixelsize = dev->fmt->depth / 8; 1387 dev->pixelsize = dev->fmt->depth / 8;