Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8f5b2f5 authored by Jonathan Corbet's avatar Jonathan Corbet Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (4909): Add s/g_parm to cafe_ccic



Add s/g_parm support allowing applications to tweak the frame rate.

Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent a66d2336
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -1671,6 +1671,37 @@ static int cafe_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id *a)
	return 0;
}

/*
 * G/S_PARM.  Most of this is done by the sensor, but we are
 * the level which controls the number of read buffers.
 */
static int cafe_vidioc_g_parm(struct file *filp, void *priv,
		struct v4l2_streamparm *parms)
{
	struct cafe_camera *cam = priv;
	int ret;

	mutex_lock(&cam->s_mutex);
	ret = __cafe_cam_cmd(cam, VIDIOC_G_PARM, parms);
	mutex_unlock(&cam->s_mutex);
	parms->parm.capture.readbuffers = n_dma_bufs;
	return ret;
}

static int cafe_vidioc_s_parm(struct file *filp, void *priv,
		struct v4l2_streamparm *parms)
{
	struct cafe_camera *cam = priv;
	int ret;

	mutex_lock(&cam->s_mutex);
	ret = __cafe_cam_cmd(cam, VIDIOC_S_PARM, parms);
	mutex_unlock(&cam->s_mutex);
	parms->parm.capture.readbuffers = n_dma_bufs;
	return ret;
}


static void cafe_v4l_dev_release(struct video_device *vd)
{
	struct cafe_camera *cam = container_of(vd, struct cafe_camera, v4ldev);
@@ -1724,7 +1755,8 @@ static struct video_device cafe_v4l_template = {
	.vidioc_queryctrl	= cafe_vidioc_queryctrl,
	.vidioc_g_ctrl		= cafe_vidioc_g_ctrl,
	.vidioc_s_ctrl		= cafe_vidioc_s_ctrl,
	/* Do cropping someday */
	.vidioc_g_parm		= cafe_vidioc_g_parm,
	.vidioc_s_parm		= cafe_vidioc_s_parm,
};


+67 −5
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@ MODULE_LICENSE("GPL");
#define QCIF_WIDTH	176
#define	QCIF_HEIGHT	144

/*
 * Our nominal (default) frame rate.
 */
#define OV7670_FRAME_RATE 30

/*
 * The 7670 sits on i2c with ID 0x42
 */
@@ -291,7 +296,7 @@ static struct regval_list ov7670_default_regs[] = {
	{ 0xc9, 0x60 },		{ REG_COM16, 0x38 },
	{ 0x56, 0x40 },

	{ 0x34, 0x11 },		{ REG_COM11, COM11_EXP },
	{ 0x34, 0x11 },		{ REG_COM11, COM11_EXP|COM11_HZAUTO },
	{ 0xa4, 0x88 },		{ 0x96, 0 },
	{ 0x97, 0x30 },		{ 0x98, 0x20 },
	{ 0x99, 0x30 },		{ 0x9a, 0x84 },
@@ -721,6 +726,63 @@ static int ov7670_s_fmt(struct i2c_client *c, struct v4l2_format *fmt)
	return 0;
}

/*
 * Implement G/S_PARM.  There is a "high quality" mode we could try
 * to do someday; for now, we just do the frame rate tweak.
 */
static int ov7670_g_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
{
	struct v4l2_captureparm *cp = &parms->parm.capture;
	unsigned char clkrc;
	int ret;

	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
	ret = ov7670_read(c, REG_CLKRC, &clkrc);
	if (ret < 0)
		return ret;
	memset(cp, 0, sizeof(struct v4l2_captureparm));
	cp->capability = V4L2_CAP_TIMEPERFRAME;
	cp->timeperframe.numerator = 1;
	cp->timeperframe.denominator = OV7670_FRAME_RATE;
	if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1)
		cp->timeperframe.denominator /= (clkrc & CLK_SCALE);
	return 0;
}

static int ov7670_s_parm(struct i2c_client *c, struct v4l2_streamparm *parms)
{
	struct v4l2_captureparm *cp = &parms->parm.capture;
	struct v4l2_fract *tpf = &cp->timeperframe;
	unsigned char clkrc;
	int ret, div;

	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
	if (cp->extendedmode != 0)
		return -EINVAL;
	/*
	 * CLKRC has a reserved bit, so let's preserve it.
	 */
	ret = ov7670_read(c, REG_CLKRC, &clkrc);
	if (ret < 0)
		return ret;
	if (tpf->numerator == 0 || tpf->denominator == 0)
		div = 1;  /* Reset to full rate */
	else
		div = (tpf->numerator*OV7670_FRAME_RATE)/tpf->denominator;
	if (div == 0)
		div = 1;
	else if (div > CLK_SCALE)
		div = CLK_SCALE;
	clkrc = (clkrc & 0x80) | div;
	tpf->numerator = 1;
	tpf->denominator = OV7670_FRAME_RATE/div;
	return ov7670_write(c, REG_CLKRC, clkrc);
}



/*
 * Code for dealing with controls.
 */
@@ -1231,10 +1293,10 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd,
		return ov7670_s_ctrl(client, (struct v4l2_control *) arg);
	case VIDIOC_G_CTRL:
		return ov7670_g_ctrl(client, (struct v4l2_control *) arg);
	/* Todo:
	   g/s_parm
	   initialization
	*/
	case VIDIOC_S_PARM:
		return ov7670_s_parm(client, (struct v4l2_streamparm *) arg);
	case VIDIOC_G_PARM:
		return ov7670_g_parm(client, (struct v4l2_streamparm *) arg);
	}
	return -EINVAL;
}