Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 357166
b: refs/heads/master
c: fe0e990
h: refs/heads/master
v: v3
  • Loading branch information
Kirill Smelkov authored and Mauro Carvalho Chehab committed Dec 26, 2012
1 parent 4bb3aa1 commit f5b3a7f
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cb412a8da82233af001d13c28fc54f25a2001aef
refs/heads/master: fe0e990b22c24d53793c8cf246f0e535f31a4406
104 changes: 96 additions & 8 deletions trunk/drivers/media/platform/vivi.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,17 @@

#define VIVI_MODULE_NAME "vivi"

/* Wake up at about 30 fps */
#define WAKE_NUMERATOR 30
#define WAKE_DENOMINATOR 1001
/* Maximum allowed frame rate
*
* Vivi will allow setting timeperframe in [1/FPS_MAX - FPS_MAX/1] range.
*
* Ideally FPS_MAX should be infinity, i.e. practically UINT_MAX, but that
* might hit application errors when they manipulate these values.
*
* Besides, for tpf < 1ms image-generation logic should be changed, to avoid
* producing frames with equal content.
*/
#define FPS_MAX 1000

#define MAX_WIDTH 1920
#define MAX_HEIGHT 1200
Expand Down Expand Up @@ -69,6 +77,12 @@ MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
/* Global font descriptor */
static const u8 *font8x16;

/* timeperframe: min/max and default */
static const struct v4l2_fract
tpf_min = {.numerator = 1, .denominator = FPS_MAX},
tpf_max = {.numerator = FPS_MAX, .denominator = 1},
tpf_default = {.numerator = 1001, .denominator = 30000}; /* NTSC */

#define dprintk(dev, level, fmt, arg...) \
v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)

Expand Down Expand Up @@ -150,14 +164,14 @@ static struct vivi_fmt formats[] = {
},
};

static struct vivi_fmt *get_format(struct v4l2_format *f)
static struct vivi_fmt *__get_format(u32 pixelformat)
{
struct vivi_fmt *fmt;
unsigned int k;

for (k = 0; k < ARRAY_SIZE(formats); k++) {
fmt = &formats[k];
if (fmt->fourcc == f->fmt.pix.pixelformat)
if (fmt->fourcc == pixelformat)
break;
}

Expand All @@ -167,6 +181,11 @@ static struct vivi_fmt *get_format(struct v4l2_format *f)
return &formats[k];
}

static struct vivi_fmt *get_format(struct v4l2_format *f)
{
return __get_format(f->fmt.pix.pixelformat);
}

/* buffer for one video frame */
struct vivi_buffer {
/* common v4l buffer stuff -- must be first */
Expand Down Expand Up @@ -232,6 +251,7 @@ struct vivi_dev {

/* video capture */
struct vivi_fmt *fmt;
struct v4l2_fract timeperframe;
unsigned int width, height;
struct vb2_queue vb_vidq;
unsigned int field_count;
Expand Down Expand Up @@ -689,8 +709,8 @@ static void vivi_thread_tick(struct vivi_dev *dev)
dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
}

#define frames_to_ms(frames) \
((frames * WAKE_NUMERATOR * 1000) / WAKE_DENOMINATOR)
#define frames_to_ms(dev, frames) \
((frames * dev->timeperframe.numerator * 1000) / dev->timeperframe.denominator)

static void vivi_sleep(struct vivi_dev *dev)
{
Expand All @@ -706,7 +726,7 @@ static void vivi_sleep(struct vivi_dev *dev)
goto stop_task;

/* Calculate time to wake up */
timeout = msecs_to_jiffies(frames_to_ms(1));
timeout = msecs_to_jiffies(frames_to_ms(dev, 1));

vivi_thread_tick(dev);

Expand Down Expand Up @@ -1078,6 +1098,70 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
return 0;
}

/* timeperframe is arbitrary and continous */
static int vidioc_enum_frameintervals(struct file *file, void *priv,
struct v4l2_frmivalenum *fival)
{
struct vivi_fmt *fmt;

if (fival->index)
return -EINVAL;

fmt = __get_format(fival->pixel_format);
if (!fmt)
return -EINVAL;

/* regarding width & height - we support any */

fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;

/* fill in stepwise (step=1.0 is requred by V4L2 spec) */
fival->stepwise.min = tpf_min;
fival->stepwise.max = tpf_max;
fival->stepwise.step = (struct v4l2_fract) {1, 1};

return 0;
}

static int vidioc_g_parm(struct file *file, void *priv,
struct v4l2_streamparm *parm)
{
struct vivi_dev *dev = video_drvdata(file);

if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;

parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
parm->parm.capture.timeperframe = dev->timeperframe;
parm->parm.capture.readbuffers = 1;
return 0;
}

#define FRACT_CMP(a, OP, b) \
((u64)(a).numerator * (b).denominator OP (u64)(b).numerator * (a).denominator)

static int vidioc_s_parm(struct file *file, void *priv,
struct v4l2_streamparm *parm)
{
struct vivi_dev *dev = video_drvdata(file);
struct v4l2_fract tpf;

if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;

tpf = parm->parm.capture.timeperframe;

/* tpf: {*, 0} resets timing; clip to [min, max]*/
tpf = tpf.denominator ? tpf : tpf_default;
tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf;
tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf;

dev->timeperframe = tpf;
parm->parm.capture.timeperframe = tpf;
parm->parm.capture.readbuffers = 1;
return 0;
}

/* --- controls ---------------------------------------------- */

static int vivi_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Expand Down Expand Up @@ -1236,6 +1320,9 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
.vidioc_g_parm = vidioc_g_parm,
.vidioc_s_parm = vidioc_s_parm,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_log_status = v4l2_ctrl_log_status,
Expand Down Expand Up @@ -1294,6 +1381,7 @@ static int __init vivi_create_instance(int inst)
goto free_dev;

dev->fmt = &formats[0];
dev->timeperframe = tpf_default;
dev->width = 640;
dev->height = 480;
dev->pixelsize = dev->fmt->depth / 8;
Expand Down

0 comments on commit f5b3a7f

Please sign in to comment.