V4L/DVB (6911): Converted bttv to use video_ioctl2

Signed-off-by: Douglas Schilling Landgraf <dougsland@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index e04113f..d6a305d 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -476,7 +476,7 @@
 /* ----------------------------------------------------------------------- */
 /* bttv format list
    packed pixel formats must come first */
-static const struct bttv_format bttv_formats[] = {
+static const struct bttv_format formats[] = {
 	{
 		.name     = "8 bpp, gray",
 		.fourcc   = V4L2_PIX_FMT_GREY,
@@ -609,7 +609,7 @@
 		.flags    = FORMAT_FLAGS_RAW,
 	}
 };
-static const unsigned int BTTV_FORMATS = ARRAY_SIZE(bttv_formats);
+static const unsigned int FORMATS = ARRAY_SIZE(formats);
 
 /* ----------------------------------------------------------------------- */
 
@@ -787,6 +787,16 @@
 };
 static const int BTTV_CTLS = ARRAY_SIZE(bttv_ctls);
 
+static const struct v4l2_queryctrl *ctrl_by_id(int id)
+{
+	int i;
+
+	for (i = 0; i < BTTV_CTLS; i++)
+		if (bttv_ctls[i].id == id)
+			return bttv_ctls+i;
+	return NULL;
+}
+
 /* ----------------------------------------------------------------------- */
 /* resource management                                                     */
 
@@ -1432,157 +1442,6 @@
 	set_input(btv, btv->input, btv->tvnorm);
 }
 
-static int get_control(struct bttv *btv, struct v4l2_control *c)
-{
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		c->value = btv->bright;
-		break;
-	case V4L2_CID_HUE:
-		c->value = btv->hue;
-		break;
-	case V4L2_CID_CONTRAST:
-		c->value = btv->contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		c->value = btv->saturation;
-		break;
-
-	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c);
-		break;
-
-	case V4L2_CID_PRIVATE_CHROMA_AGC:
-		c->value = btv->opt_chroma_agc;
-		break;
-	case V4L2_CID_PRIVATE_COMBFILTER:
-		c->value = btv->opt_combfilter;
-		break;
-	case V4L2_CID_PRIVATE_LUMAFILTER:
-		c->value = btv->opt_lumafilter;
-		break;
-	case V4L2_CID_PRIVATE_AUTOMUTE:
-		c->value = btv->opt_automute;
-		break;
-	case V4L2_CID_PRIVATE_AGC_CRUSH:
-		c->value = btv->opt_adc_crush;
-		break;
-	case V4L2_CID_PRIVATE_VCR_HACK:
-		c->value = btv->opt_vcr_hack;
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-		c->value = btv->opt_whitecrush_upper;
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-		c->value = btv->opt_whitecrush_lower;
-		break;
-	case V4L2_CID_PRIVATE_UV_RATIO:
-		c->value = btv->opt_uv_ratio;
-		break;
-	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-		c->value = btv->opt_full_luma_range;
-		break;
-	case V4L2_CID_PRIVATE_CORING:
-		c->value = btv->opt_coring;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int set_control(struct bttv *btv, struct v4l2_control *c)
-{
-	int val;
-
-	switch (c->id) {
-	case V4L2_CID_BRIGHTNESS:
-		bt848_bright(btv,c->value);
-		break;
-	case V4L2_CID_HUE:
-		bt848_hue(btv,c->value);
-		break;
-	case V4L2_CID_CONTRAST:
-		bt848_contrast(btv,c->value);
-		break;
-	case V4L2_CID_SATURATION:
-		bt848_sat(btv,c->value);
-		break;
-	case V4L2_CID_AUDIO_MUTE:
-		audio_mute(btv, c->value);
-		/* fall through */
-	case V4L2_CID_AUDIO_VOLUME:
-		if (btv->volume_gpio) {
-			btv->volume_gpio (btv, c->value);
-		}
-		bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
-		break;
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c);
-		break;
-
-	case V4L2_CID_PRIVATE_CHROMA_AGC:
-		btv->opt_chroma_agc = c->value;
-		val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
-		btwrite(val, BT848_E_SCLOOP);
-		btwrite(val, BT848_O_SCLOOP);
-		break;
-	case V4L2_CID_PRIVATE_COMBFILTER:
-		btv->opt_combfilter = c->value;
-		break;
-	case V4L2_CID_PRIVATE_LUMAFILTER:
-		btv->opt_lumafilter = c->value;
-		if (btv->opt_lumafilter) {
-			btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
-			btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
-		} else {
-			btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
-			btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
-		}
-		break;
-	case V4L2_CID_PRIVATE_AUTOMUTE:
-		btv->opt_automute = c->value;
-		break;
-	case V4L2_CID_PRIVATE_AGC_CRUSH:
-		btv->opt_adc_crush = c->value;
-		btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
-			BT848_ADC);
-		break;
-	case V4L2_CID_PRIVATE_VCR_HACK:
-		btv->opt_vcr_hack = c->value;
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
-		btv->opt_whitecrush_upper = c->value;
-		btwrite(c->value, BT848_WC_UP);
-		break;
-	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
-		btv->opt_whitecrush_lower = c->value;
-		btwrite(c->value, BT848_WC_DOWN);
-		break;
-	case V4L2_CID_PRIVATE_UV_RATIO:
-		btv->opt_uv_ratio = c->value;
-		bt848_sat(btv, btv->saturation);
-		break;
-	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
-		btv->opt_full_luma_range = c->value;
-		btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
-		break;
-	case V4L2_CID_PRIVATE_CORING:
-		btv->opt_coring = c->value;
-		btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
 /* ----------------------------------------------------------------------- */
 
 void bttv_gpio_tracking(struct bttv *btv, char *comment)
@@ -1616,11 +1475,11 @@
 {
 	unsigned int i;
 
-	for (i = 0; i < BTTV_FORMATS; i++) {
-		if (-1 == bttv_formats[i].fourcc)
+	for (i = 0; i < FORMATS; i++) {
+		if (-1 == formats[i].fourcc)
 			continue;
-		if (bttv_formats[i].fourcc == fourcc)
-			return bttv_formats+i;
+		if (formats[i].fourcc == fourcc)
+			return formats+i;
 	}
 	return NULL;
 }
@@ -1821,184 +1680,399 @@
 	.buf_release  = buffer_release,
 };
 
-static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
 {
-	switch (cmd) {
-	case VIDIOC_ENUMSTD:
-	{
-		struct v4l2_standard *e = arg;
-		unsigned int index = e->index;
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+	unsigned int i;
+	int err;
 
-		if (index >= BTTV_TVNORMS)
-			return -EINVAL;
-		v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
-					 bttv_tvnorms[e->index].name);
-		e->index = index;
-		return 0;
-	}
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *id = arg;
-		*id = bttv_tvnorms[btv->tvnorm].v4l2_id;
-		return 0;
-	}
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *id = arg;
-		unsigned int i;
+	err = v4l2_prio_check(&btv->prio, &fh->prio);
+	if (0 != err)
+		return err;
 
-		for (i = 0; i < BTTV_TVNORMS; i++)
-			if (*id & bttv_tvnorms[i].v4l2_id)
-				break;
-		if (i == BTTV_TVNORMS)
-			return -EINVAL;
+	for (i = 0; i < BTTV_TVNORMS; i++)
+		if (*id & bttv_tvnorms[i].v4l2_id)
+			break;
+	if (i == BTTV_TVNORMS)
+		return -EINVAL;
 
-		mutex_lock(&btv->lock);
-		set_tvnorm(btv,i);
-		mutex_unlock(&btv->lock);
-		return 0;
-	}
-	case VIDIOC_QUERYSTD:
-	{
-		v4l2_std_id *id = arg;
+	mutex_lock(&btv->lock);
+	set_tvnorm(btv, i);
+	mutex_unlock(&btv->lock);
 
-		if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
-			*id = V4L2_STD_625_50;
-		else
-			*id = V4L2_STD_525_60;
-		return 0;
+	return 0;
+}
+
+static int vidioc_querystd(struct file *file, void *f, v4l2_std_id *id)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
+		*id = V4L2_STD_625_50;
+	else
+		*id = V4L2_STD_525_60;
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+					struct v4l2_input *i)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	unsigned int n;
+
+	n = i->index;
+
+	if (n >= bttv_tvcards[btv->c.type].video_inputs)
+		return -EINVAL;
+
+	memset(i, 0, sizeof(*i));
+
+	i->index    = n;
+	i->type     = V4L2_INPUT_TYPE_CAMERA;
+	i->audioset = 1;
+
+	if (i->index == bttv_tvcards[btv->c.type].tuner) {
+		sprintf(i->name, "Television");
+		i->type  = V4L2_INPUT_TYPE_TUNER;
+		i->tuner = 0;
+	} else if (i->index == btv->svhs) {
+		sprintf(i->name, "S-Video");
+	} else {
+		sprintf(i->name, "Composite%d", i->index);
 	}
 
-	case VIDIOC_ENUMINPUT:
-	{
-		struct v4l2_input *i = arg;
-		unsigned int n;
-
-		n = i->index;
-		if (n >= bttv_tvcards[btv->c.type].video_inputs)
-			return -EINVAL;
-		memset(i,0,sizeof(*i));
-		i->index    = n;
-		i->type     = V4L2_INPUT_TYPE_CAMERA;
-		i->audioset = 1;
-		if (i->index == bttv_tvcards[btv->c.type].tuner) {
-			sprintf(i->name, "Television");
-			i->type  = V4L2_INPUT_TYPE_TUNER;
-			i->tuner = 0;
-		} else if (i->index == btv->svhs) {
-			sprintf(i->name, "S-Video");
-		} else {
-			sprintf(i->name,"Composite%d",i->index);
-		}
-		if (i->index == btv->input) {
-			__u32 dstatus = btread(BT848_DSTATUS);
-			if (0 == (dstatus & BT848_DSTATUS_PRES))
-				i->status |= V4L2_IN_ST_NO_SIGNAL;
-			if (0 == (dstatus & BT848_DSTATUS_HLOC))
-				i->status |= V4L2_IN_ST_NO_H_LOCK;
-		}
-		for (n = 0; n < BTTV_TVNORMS; n++)
-			i->std |= bttv_tvnorms[n].v4l2_id;
-		return 0;
-	}
-	case VIDIOC_G_INPUT:
-	{
-		int *i = arg;
-		*i = btv->input;
-		return 0;
-	}
-	case VIDIOC_S_INPUT:
-	{
-		unsigned int *i = arg;
-
-		if (*i > bttv_tvcards[btv->c.type].video_inputs)
-			return -EINVAL;
-		mutex_lock(&btv->lock);
-		set_input(btv, *i, btv->tvnorm);
-		mutex_unlock(&btv->lock);
-		return 0;
+	if (i->index == btv->input) {
+		__u32 dstatus = btread(BT848_DSTATUS);
+		if (0 == (dstatus & BT848_DSTATUS_PRES))
+			i->status |= V4L2_IN_ST_NO_SIGNAL;
+		if (0 == (dstatus & BT848_DSTATUS_HLOC))
+			i->status |= V4L2_IN_ST_NO_H_LOCK;
 	}
 
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
+	for (n = 0; n < BTTV_TVNORMS; n++)
+		i->std |= bttv_tvnorms[n].v4l2_id;
 
-		if (UNSET == bttv_tvcards[btv->c.type].tuner)
-			return -EINVAL;
-		if (0 != t->index)
-			return -EINVAL;
-		mutex_lock(&btv->lock);
-		bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+	return 0;
+}
 
-		if (btv->audio_mode_gpio) {
-			btv->audio_mode_gpio (btv,t,1);
-		}
-		mutex_unlock(&btv->lock);
-		return 0;
-	}
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
 
-	case VIDIOC_G_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
+	*i = btv->input;
+	return 0;
+}
 
-		memset(f,0,sizeof(*f));
-		f->type = V4L2_TUNER_ANALOG_TV;
-		f->frequency = btv->freq;
-		return 0;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
 
-		if (unlikely(f->tuner != 0))
-			return -EINVAL;
-		if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
-			return -EINVAL;
-		mutex_lock(&btv->lock);
-		btv->freq = f->frequency;
-		bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f);
-		if (btv->has_matchbox && btv->radio_user)
-			tea5757_set_freq(btv,btv->freq);
-		mutex_unlock(&btv->lock);
-		return 0;
-	}
-	case VIDIOC_LOG_STATUS:
-	{
-		printk(KERN_INFO "bttv%d: =================  START STATUS CARD #%d  =================\n", btv->c.nr, btv->c.nr);
-		bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
-		printk(KERN_INFO "bttv%d: ==================  END STATUS CARD #%d  ==================\n", btv->c.nr, btv->c.nr);
-		return 0;
-	}
-	case VIDIOC_G_CTRL:
-		return get_control(btv,arg);
-	case VIDIOC_S_CTRL:
-		return set_control(btv,arg);
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-	case VIDIOC_DBG_G_REGISTER:
-	case VIDIOC_DBG_S_REGISTER:
-	{
-		struct v4l2_register *reg = arg;
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
-			return -EINVAL;
-		/* bt848 has a 12-bit register space */
-		reg->reg &= 0xfff;
-		if (cmd == VIDIOC_DBG_G_REGISTER)
-			reg->val = btread(reg->reg);
-		else
-			btwrite(reg->val, reg->reg);
-		return 0;
-	}
-#endif
+	int err;
 
+	err = v4l2_prio_check(&btv->prio, &fh->prio);
+	if (0 != err)
+		return err;
+
+	if (i > bttv_tvcards[btv->c.type].video_inputs)
+		return -EINVAL;
+
+	mutex_lock(&btv->lock);
+	set_input(btv, i, btv->tvnorm);
+	mutex_unlock(&btv->lock);
+	return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *t)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+	int err;
+
+	err = v4l2_prio_check(&btv->prio, &fh->prio);
+	if (0 != err)
+		return err;
+
+	if (UNSET == bttv_tvcards[btv->c.type].tuner)
+		return -EINVAL;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	mutex_lock(&btv->lock);
+	bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t);
+
+	if (btv->audio_mode_gpio)
+		btv->audio_mode_gpio(btv, t, 1);
+
+	mutex_unlock(&btv->lock);
+
+	return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+	int err;
+
+	err = v4l2_prio_check(&btv->prio, &fh->prio);
+	if (0 != err)
+		return err;
+
+	f->type = V4L2_TUNER_ANALOG_TV;
+	f->frequency = btv->freq;
+
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+	int err;
+
+	err = v4l2_prio_check(&btv->prio, &fh->prio);
+	if (0 != err)
+		return err;
+
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+	if (unlikely(f->type != V4L2_TUNER_ANALOG_TV))
+		return -EINVAL;
+	mutex_lock(&btv->lock);
+	btv->freq = f->frequency;
+	bttv_call_i2c_clients(btv, VIDIOC_S_FREQUENCY, f);
+	if (btv->has_matchbox && btv->radio_user)
+		tea5757_set_freq(btv, btv->freq);
+	mutex_unlock(&btv->lock);
+	return 0;
+}
+
+static int vidioc_log_status(struct file *file, void *f)
+{
+	struct bttv_fh *fh  = f;
+	struct bttv *btv = fh->btv;
+
+	printk(KERN_INFO "bttv%d: ========  START STATUS CARD #%d  ========\n",
+			btv->c.nr, btv->c.nr);
+	bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL);
+	printk(KERN_INFO "bttv%d: ========  END STATUS CARD   #%d  ========\n",
+			btv->c.nr, btv->c.nr);
+	return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+					struct v4l2_control *c)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		c->value = btv->bright;
+		break;
+	case V4L2_CID_HUE:
+		c->value = btv->hue;
+		break;
+	case V4L2_CID_CONTRAST:
+		c->value = btv->contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		c->value = btv->saturation;
+		break;
+
+	case V4L2_CID_AUDIO_MUTE:
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		bttv_call_i2c_clients(btv, VIDIOC_G_CTRL, c);
+		break;
+
+	case V4L2_CID_PRIVATE_CHROMA_AGC:
+		c->value = btv->opt_chroma_agc;
+		break;
+	case V4L2_CID_PRIVATE_COMBFILTER:
+		c->value = btv->opt_combfilter;
+		break;
+	case V4L2_CID_PRIVATE_LUMAFILTER:
+		c->value = btv->opt_lumafilter;
+		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		c->value = btv->opt_automute;
+		break;
+	case V4L2_CID_PRIVATE_AGC_CRUSH:
+		c->value = btv->opt_adc_crush;
+		break;
+	case V4L2_CID_PRIVATE_VCR_HACK:
+		c->value = btv->opt_vcr_hack;
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
+		c->value = btv->opt_whitecrush_upper;
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
+		c->value = btv->opt_whitecrush_lower;
+		break;
+	case V4L2_CID_PRIVATE_UV_RATIO:
+		c->value = btv->opt_uv_ratio;
+		break;
+	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+		c->value = btv->opt_full_luma_range;
+		break;
+	case V4L2_CID_PRIVATE_CORING:
+		c->value = btv->opt_coring;
+		break;
 	default:
-		return -ENOIOCTLCMD;
-
+		return -EINVAL;
 	}
 	return 0;
 }
 
+static int vidioc_s_ctrl(struct file *file, void *f,
+					struct v4l2_control *c)
+{
+	int err;
+	int val;
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	err = v4l2_prio_check(&btv->prio, &fh->prio);
+	if (0 != err)
+		return err;
+
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		bt848_bright(btv, c->value);
+		break;
+	case V4L2_CID_HUE:
+		bt848_hue(btv, c->value);
+		break;
+	case V4L2_CID_CONTRAST:
+		bt848_contrast(btv, c->value);
+		break;
+	case V4L2_CID_SATURATION:
+		bt848_sat(btv, c->value);
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		audio_mute(btv, c->value);
+		/* fall through */
+	case V4L2_CID_AUDIO_VOLUME:
+		if (btv->volume_gpio)
+			btv->volume_gpio(btv, c->value);
+
+		bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
+		break;
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		bttv_call_i2c_clients(btv, VIDIOC_S_CTRL, c);
+		break;
+
+	case V4L2_CID_PRIVATE_CHROMA_AGC:
+		btv->opt_chroma_agc = c->value;
+		val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
+		btwrite(val, BT848_E_SCLOOP);
+		btwrite(val, BT848_O_SCLOOP);
+		break;
+	case V4L2_CID_PRIVATE_COMBFILTER:
+		btv->opt_combfilter = c->value;
+		break;
+	case V4L2_CID_PRIVATE_LUMAFILTER:
+		btv->opt_lumafilter = c->value;
+		if (btv->opt_lumafilter) {
+			btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
+			btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
+		} else {
+			btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
+			btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
+		}
+		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		btv->opt_automute = c->value;
+		break;
+	case V4L2_CID_PRIVATE_AGC_CRUSH:
+		btv->opt_adc_crush = c->value;
+		btwrite(BT848_ADC_RESERVED |
+				(btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+				BT848_ADC);
+		break;
+	case V4L2_CID_PRIVATE_VCR_HACK:
+		btv->opt_vcr_hack = c->value;
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
+		btv->opt_whitecrush_upper = c->value;
+		btwrite(c->value, BT848_WC_UP);
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
+		btv->opt_whitecrush_lower = c->value;
+		btwrite(c->value, BT848_WC_DOWN);
+		break;
+	case V4L2_CID_PRIVATE_UV_RATIO:
+		btv->opt_uv_ratio = c->value;
+		bt848_sat(btv, btv->saturation);
+		break;
+	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+		btv->opt_full_luma_range = c->value;
+		btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+		break;
+	case V4L2_CID_PRIVATE_CORING:
+		btv->opt_coring = c->value;
+		btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *f,
+					struct v4l2_register *reg)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+		return -EINVAL;
+
+	/* bt848 has a 12-bit register space */
+	reg->reg &= 0xfff;
+	reg->val = btread(reg->reg);
+
+	return 0;
+}
+
+static int vidioc_s_register(struct file *file, void *f,
+					struct v4l2_register *reg)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+		return -EINVAL;
+
+	/* bt848 has a 12-bit register space */
+	reg->reg &= 0xfff;
+	btwrite(reg->val, reg->reg);
+
+	return 0;
+}
+#endif
+
 /* Given cropping boundaries b and the scaled width and height of a
    single field or frame, which must not exceed hardware limits, this
    function adjusts the cropping parameters c. */
@@ -2373,652 +2447,633 @@
 	}
 }
 
-static int bttv_g_fmt(struct bttv_fh *fh, struct v4l2_format *f)
+static int vidioc_g_fmt_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
 {
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		memset(&f->fmt.pix,0,sizeof(struct v4l2_pix_format));
-		pix_format_set_size (&f->fmt.pix, fh->fmt,
-				     fh->width, fh->height);
-		f->fmt.pix.field        = fh->cap.field;
-		f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-		return 0;
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		memset(&f->fmt.win,0,sizeof(struct v4l2_window));
-		f->fmt.win.w     = fh->ov.w;
-		f->fmt.win.field = fh->ov.field;
-		return 0;
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		bttv_vbi_get_fmt(fh, &f->fmt.vbi);
-		return 0;
+	struct bttv_fh *fh  = priv;
+
+	pix_format_set_size(&f->fmt.pix, fh->fmt,
+				fh->width, fh->height);
+	f->fmt.pix.field        = fh->cap.field;
+	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+
+	return 0;
+}
+
+static int vidioc_g_fmt_overlay(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct bttv_fh *fh  = priv;
+
+	f->fmt.win.w     = fh->ov.w;
+	f->fmt.win.field = fh->ov.field;
+
+	return 0;
+}
+
+static int vidioc_try_fmt_cap(struct file *file, void *priv,
+						struct v4l2_format *f)
+{
+	const struct bttv_format *fmt;
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	enum v4l2_field field;
+	__s32 width, height;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+
+	if (V4L2_FIELD_ANY == field) {
+		__s32 height2;
+
+		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+		field = (f->fmt.pix.height > height2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
+	}
+
+	if (V4L2_FIELD_SEQ_BT == field)
+		field = V4L2_FIELD_SEQ_TB;
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_ALTERNATE:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	case V4L2_FIELD_SEQ_TB:
+		if (fmt->flags & FORMAT_FLAGS_PLANAR)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
+
+	width = f->fmt.pix.width;
+	height = f->fmt.pix.height;
+
+	/* update data for the application */
+	f->fmt.pix.field = field;
+	pix_format_set_size(&f->fmt.pix, fmt, width, height);
+
+	return 0;
 }
 
-static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
-			struct v4l2_format *f, int adjust_crop)
+static int vidioc_try_fmt_overlay(struct file *file, void *priv,
+						struct v4l2_format *f)
 {
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-	{
-		const struct bttv_format *fmt;
-		enum v4l2_field field;
-		__s32 width, height;
-		int rc;
+	struct bttv_fh *fh = priv;
 
-		fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-		if (NULL == fmt)
-			return -EINVAL;
-
-		field = f->fmt.pix.field;
-		if (V4L2_FIELD_ANY == field) {
-			__s32 height2;
-
-			height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-			field = (f->fmt.pix.height > height2)
-				? V4L2_FIELD_INTERLACED
-				: V4L2_FIELD_BOTTOM;
-		}
-		if (V4L2_FIELD_SEQ_BT == field)
-			field = V4L2_FIELD_SEQ_TB;
-		switch (field) {
-		case V4L2_FIELD_TOP:
-		case V4L2_FIELD_BOTTOM:
-		case V4L2_FIELD_ALTERNATE:
-		case V4L2_FIELD_INTERLACED:
-			break;
-		case V4L2_FIELD_SEQ_TB:
-			if (fmt->flags & FORMAT_FLAGS_PLANAR)
-				return -EINVAL;
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		width = f->fmt.pix.width;
-		height = f->fmt.pix.height;
-
-		rc = limit_scaled_size(fh, &width, &height, field,
-				       /* width_mask: 4 pixels */ ~3,
-				       /* width_bias: nearest */ 2,
-				       /* adjust_size */ 1,
-				       adjust_crop);
-		if (0 != rc)
-			return rc;
-
-		/* update data for the application */
-		f->fmt.pix.field = field;
-		pix_format_set_size(&f->fmt.pix, fmt, width, height);
-
-		return 0;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		return verify_window(fh, &f->fmt.win,
-				     /* adjust_size */ 1,
-				     /* adjust_crop */ 0);
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		return bttv_vbi_try_fmt(fh, &f->fmt.vbi);
-	default:
-		return -EINVAL;
-	}
+	return verify_window(fh, &f->fmt.win,
+			/* adjust_size */ 1,
+			/* adjust_crop */ 0);
 }
 
-static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv,
-		      struct v4l2_format *f)
+static int vidioc_s_fmt_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
 {
 	int retval;
+	const struct bttv_format *fmt;
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
 
-	switch (f->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-	{
-		const struct bttv_format *fmt;
+	retval = bttv_switch_type(fh, f->type);
+	if (0 != retval)
+		return retval;
 
-		retval = bttv_switch_type(fh,f->type);
-		if (0 != retval)
-			return retval;
-		retval = bttv_try_fmt(fh,btv,f, /* adjust_crop */ 1);
-		if (0 != retval)
-			return retval;
-		fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	retval = vidioc_try_fmt_cap(file, priv, f);
+	if (0 != retval)
+		return retval;
 
-		/* update our state informations */
-		mutex_lock(&fh->cap.lock);
-		fh->fmt              = fmt;
-		fh->cap.field        = f->fmt.pix.field;
-		fh->cap.last         = V4L2_FIELD_NONE;
-		fh->width            = f->fmt.pix.width;
-		fh->height           = f->fmt.pix.height;
-		btv->init.fmt        = fmt;
-		btv->init.width      = f->fmt.pix.width;
-		btv->init.height     = f->fmt.pix.height;
-		mutex_unlock(&fh->cap.lock);
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
-		return 0;
-	}
-	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-		if (no_overlay > 0) {
-			printk ("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-			return -EINVAL;
-		}
-		return setup_window(fh, btv, &f->fmt.win, 1);
-	case V4L2_BUF_TYPE_VBI_CAPTURE:
-		retval = bttv_switch_type(fh,f->type);
-		if (0 != retval)
-			return retval;
-		return bttv_vbi_set_fmt(fh, &f->fmt.vbi);
-	default:
-		return -EINVAL;
-	}
+	/* update our state informations */
+	mutex_lock(&fh->cap.lock);
+	fh->fmt              = fmt;
+	fh->cap.field        = f->fmt.pix.field;
+	fh->cap.last         = V4L2_FIELD_NONE;
+	fh->width            = f->fmt.pix.width;
+	fh->height           = f->fmt.pix.height;
+	btv->init.fmt        = fmt;
+	btv->init.width      = f->fmt.pix.width;
+	btv->init.height     = f->fmt.pix.height;
+	mutex_unlock(&fh->cap.lock);
+
+	return 0;
 }
 
-static int bttv_do_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg)
+static int vidioc_s_fmt_overlay(struct file *file, void *priv,
+				struct v4l2_format *f)
 {
-	struct bttv_fh *fh  = file->private_data;
-	struct bttv    *btv = fh->btv;
-	int retval = 0;
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
 
-	if (bttv_debug > 1)
-		v4l_print_ioctl(btv->c.name, cmd);
+	if (no_overlay > 0)
+		return -EINVAL;
 
-	if (btv->errors)
-		bttv_reinit_bt848(btv);
+	return setup_window(fh, btv, &f->fmt.win, 1);
+}
 
-	switch (cmd) {
-	case VIDIOC_S_CTRL:
-	case VIDIOC_S_STD:
-	case VIDIOC_S_INPUT:
-	case VIDIOC_S_TUNER:
-	case VIDIOC_S_FREQUENCY:
-		retval = v4l2_prio_check(&btv->prio,&fh->prio);
-		if (0 != retval)
-			return retval;
-	};
-
-	switch (cmd) {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *mbuf = arg;
-		unsigned int i;
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+	int retval;
+	unsigned int i;
+	struct bttv_fh *fh = priv;
 
-		retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,
-					     V4L2_MEMORY_MMAP);
-		if (retval < 0)
-			return retval;
-
-		gbuffers = retval;
-		memset(mbuf,0,sizeof(*mbuf));
-		mbuf->frames = gbuffers;
-		mbuf->size   = gbuffers * gbufsize;
-		for (i = 0; i < gbuffers; i++)
-			mbuf->offsets[i] = i * gbufsize;
-		return 0;
+	mutex_lock(&fh->cap.lock);
+	retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
+				     V4L2_MEMORY_MMAP);
+	if (retval < 0) {
+		mutex_unlock(&fh->cap.lock);
+		return retval;
 	}
+
+	gbuffers = retval;
+	memset(mbuf, 0, sizeof(*mbuf));
+	mbuf->frames = gbuffers;
+	mbuf->size   = gbuffers * gbufsize;
+
+	for (i = 0; i < gbuffers; i++)
+		mbuf->offsets[i] = i * gbufsize;
+
+	mutex_unlock(&fh->cap.lock);
+	return 0;
+}
 #endif
 
-	/* ***  v4l2  *** ************************************************ */
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
+static int vidioc_querycap(struct file *file, void  *priv,
+				struct v4l2_capability *cap)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
 
-		if (0 == v4l2)
-			return -EINVAL;
-		memset(cap, 0, sizeof (*cap));
-		strlcpy(cap->driver, "bttv", sizeof (cap->driver));
-		strlcpy(cap->card, btv->video_dev->name, sizeof (cap->card));
-		snprintf(cap->bus_info, sizeof (cap->bus_info),
-			 "PCI:%s", pci_name(btv->c.pci));
-		cap->version = BTTV_VERSION_CODE;
-		cap->capabilities =
-			V4L2_CAP_VIDEO_CAPTURE |
-			V4L2_CAP_VBI_CAPTURE |
-			V4L2_CAP_READWRITE |
-			V4L2_CAP_STREAMING;
-		if (no_overlay <= 0)
-			cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+	if (0 == v4l2)
+		return -EINVAL;
 
-		if (bttv_tvcards[btv->c.type].tuner != UNSET &&
-		    bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
-			cap->capabilities |= V4L2_CAP_TUNER;
-		return 0;
-	}
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *f = arg;
-		enum v4l2_buf_type type;
-		unsigned int i;
-		int index;
+	strlcpy(cap->driver, "bttv", sizeof(cap->driver));
+	strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "PCI:%s", pci_name(btv->c.pci));
+	cap->version = BTTV_VERSION_CODE;
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_VBI_CAPTURE |
+		V4L2_CAP_READWRITE |
+		V4L2_CAP_STREAMING;
+	if (no_overlay <= 0)
+		cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
 
-		type  = f->type;
-		if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {
-			/* vbi */
-			index = f->index;
-			if (0 != index)
-				return -EINVAL;
-			memset(f,0,sizeof(*f));
-			f->index       = index;
-			f->type        = type;
-			f->pixelformat = V4L2_PIX_FMT_GREY;
-			strcpy(f->description,"vbi data");
-			return 0;
-		}
-
-		/* video capture + overlay */
-		index = -1;
-		for (i = 0; i < BTTV_FORMATS; i++) {
-			if (bttv_formats[i].fourcc != -1)
-				index++;
-			if ((unsigned int)index == f->index)
-				break;
-		}
-		if (BTTV_FORMATS == i)
-			return -EINVAL;
-
-		switch (f->type) {
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-			break;
-		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-			if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED))
-				return -EINVAL;
-			break;
-		default:
-			return -EINVAL;
-		}
-		memset(f,0,sizeof(*f));
-		f->index       = index;
-		f->type        = type;
-		f->pixelformat = bttv_formats[i].fourcc;
-		strlcpy(f->description,bttv_formats[i].name,sizeof(f->description));
-		return 0;
-	}
-	case VIDIOC_TRY_FMT:
-	{
-		struct v4l2_format *f = arg;
-		return bttv_try_fmt(fh,btv,f, /* adjust_crop */ 0);
-	}
-	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format *f = arg;
-		return bttv_g_fmt(fh,f);
-	}
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *f = arg;
-		return bttv_s_fmt(fh,btv,f);
-	}
-
-	case VIDIOC_G_FBUF:
-	{
-		struct v4l2_framebuffer *fb = arg;
-
-		*fb = btv->fbuf;
-		fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-		if (fh->ovfmt)
-			fb->fmt.pixelformat  = fh->ovfmt->fourcc;
-		return 0;
-	}
-	case VIDIOC_OVERLAY:
-	{
-		struct bttv_buffer *new;
-		int *on = arg;
-
-		if (*on) {
-			/* verify args */
-			if (NULL == btv->fbuf.base)
-				return -EINVAL;
-			if (!fh->ov.setup_ok) {
-				dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr);
-				return -EINVAL;
-			}
-		}
-
-		if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
-			return -EBUSY;
-
-		mutex_lock(&fh->cap.lock);
-		if (*on) {
-			fh->ov.tvnorm = btv->tvnorm;
-			new = videobuf_pci_alloc(sizeof(*new));
-			bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
-		} else {
-			new = NULL;
-		}
-
-		/* switch over */
-		retval = bttv_switch_overlay(btv,fh,new);
-		mutex_unlock(&fh->cap.lock);
-		return retval;
-	}
-	case VIDIOC_S_FBUF:
-	{
-		struct v4l2_framebuffer *fb = arg;
-		const struct bttv_format *fmt;
-
-		if(!capable(CAP_SYS_ADMIN) &&
-		   !capable(CAP_SYS_RAWIO))
-			return -EPERM;
-
-		/* check args */
-		fmt = format_by_fourcc(fb->fmt.pixelformat);
-		if (NULL == fmt)
-			return -EINVAL;
-		if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
-			return -EINVAL;
-
-		retval = -EINVAL;
-		if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-			__s32 width = fb->fmt.width;
-			__s32 height = fb->fmt.height;
-
-			retval = limit_scaled_size(fh, &width, &height,
-						   V4L2_FIELD_INTERLACED,
-						   /* width_mask */ ~3,
-						   /* width_bias */ 2,
-						   /* adjust_size */ 0,
-						   /* adjust_crop */ 0);
-			if (0 != retval)
-				return retval;
-		}
-
-		/* ok, accept it */
-		mutex_lock(&fh->cap.lock);
-		btv->fbuf.base       = fb->base;
-		btv->fbuf.fmt.width  = fb->fmt.width;
-		btv->fbuf.fmt.height = fb->fmt.height;
-		if (0 != fb->fmt.bytesperline)
-			btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
-		else
-			btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
-
-		retval = 0;
-		fh->ovfmt = fmt;
-		btv->init.ovfmt = fmt;
-		if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
-			fh->ov.w.left   = 0;
-			fh->ov.w.top    = 0;
-			fh->ov.w.width  = fb->fmt.width;
-			fh->ov.w.height = fb->fmt.height;
-			btv->init.ov.w.width  = fb->fmt.width;
-			btv->init.ov.w.height = fb->fmt.height;
-				kfree(fh->ov.clips);
-			fh->ov.clips = NULL;
-			fh->ov.nclips = 0;
-
-			if (check_btres(fh, RESOURCE_OVERLAY)) {
-				struct bttv_buffer *new;
-
-				new = videobuf_pci_alloc(sizeof(*new));
-				new->crop = btv->crop[!!fh->do_crop].rect;
-				bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
-				retval = bttv_switch_overlay(btv,fh,new);
-			}
-		}
-		mutex_unlock(&fh->cap.lock);
-		return retval;
-	}
-	case VIDIOC_REQBUFS:
-		return videobuf_reqbufs(bttv_queue(fh),arg);
-	case VIDIOC_QUERYBUF:
-		return videobuf_querybuf(bttv_queue(fh),arg);
-	case VIDIOC_QBUF:
-	{
-		int res = bttv_resource(fh);
-
-		if (!check_alloc_btres(btv, fh, res))
-			return -EBUSY;
-		return videobuf_qbuf(bttv_queue(fh),arg);
-	}
-	case VIDIOC_DQBUF:
-		return videobuf_dqbuf(bttv_queue(fh),arg,
-				      file->f_flags & O_NONBLOCK);
-	case VIDIOC_STREAMON:
-	{
-		int res = bttv_resource(fh);
-
-		if (!check_alloc_btres(btv,fh,res))
-			return -EBUSY;
-		return videobuf_streamon(bttv_queue(fh));
-	}
-	case VIDIOC_STREAMOFF:
-	{
-		int res = bttv_resource(fh);
-
-		retval = videobuf_streamoff(bttv_queue(fh));
-		if (retval < 0)
-			return retval;
-		free_btres(btv,fh,res);
-		return 0;
-	}
-
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *c = arg;
-		int i;
-
-		if ((c->id <  V4L2_CID_BASE ||
-		     c->id >= V4L2_CID_LASTP1) &&
-		    (c->id <  V4L2_CID_PRIVATE_BASE ||
-		     c->id >= V4L2_CID_PRIVATE_LASTP1))
-			return -EINVAL;
-		for (i = 0; i < BTTV_CTLS; i++)
-			if (bttv_ctls[i].id == c->id)
-				break;
-		if (i == BTTV_CTLS) {
-			*c = no_ctl;
-			return 0;
-		}
-		*c = bttv_ctls[i];
-
-		if (!btv->volume_gpio &&
-		    (bttv_ctls[i].id == V4L2_CID_AUDIO_VOLUME))
-		*c = no_ctl;
-
-		return 0;
-	}
-	case VIDIOC_G_PARM:
-	{
-		struct v4l2_streamparm *parm = arg;
-		struct v4l2_standard s;
-		if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			return -EINVAL;
-		memset(parm,0,sizeof(*parm));
-		v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
-					 bttv_tvnorms[btv->tvnorm].name);
-		parm->parm.capture.timeperframe = s.frameperiod;
-		return 0;
-	}
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-
-		if (UNSET == bttv_tvcards[btv->c.type].tuner)
-			return -EINVAL;
-		if (0 != t->index)
-			return -EINVAL;
-		mutex_lock(&btv->lock);
-		memset(t,0,sizeof(*t));
-		t->rxsubchans = V4L2_TUNER_SUB_MONO;
-		bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
-		strcpy(t->name, "Television");
-		t->capability = V4L2_TUNER_CAP_NORM;
-		t->type       = V4L2_TUNER_ANALOG_TV;
-		if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
-			t->signal = 0xffff;
-
-		if (btv->audio_mode_gpio) {
-			btv->audio_mode_gpio (btv,t,0);
-		}
-
-		mutex_unlock(&btv->lock);
-		return 0;
-	}
-
-	case VIDIOC_G_PRIORITY:
-	{
-		enum v4l2_priority *p = arg;
-
-		*p = v4l2_prio_max(&btv->prio);
-		return 0;
-	}
-	case VIDIOC_S_PRIORITY:
-	{
-		enum v4l2_priority *prio = arg;
-
-		return v4l2_prio_change(&btv->prio, &fh->prio, *prio);
-	}
-
-	case VIDIOC_CROPCAP:
-	{
-		struct v4l2_cropcap *cap = arg;
-		enum v4l2_buf_type type;
-
-		type = cap->type;
-
-		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-		    type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-			return -EINVAL;
-
-		*cap = bttv_tvnorms[btv->tvnorm].cropcap;
-		cap->type = type;
-
-		return 0;
-	}
-	case VIDIOC_G_CROP:
-	{
-		struct v4l2_crop * crop = arg;
-
-		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-		    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-			return -EINVAL;
-
-		/* No fh->do_crop = 1; because btv->crop[1] may be
-		   inconsistent with fh->width or fh->height and apps
-		   do not expect a change here. */
-
-		crop->c = btv->crop[!!fh->do_crop].rect;
-
-		return 0;
-	}
-	case VIDIOC_S_CROP:
-	{
-		struct v4l2_crop *crop = arg;
-		const struct v4l2_rect *b;
-		struct bttv_crop c;
-		__s32 b_left;
-		__s32 b_top;
-		__s32 b_right;
-		__s32 b_bottom;
-
-		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-		    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-			return -EINVAL;
-
-		retval = v4l2_prio_check(&btv->prio,&fh->prio);
-		if (0 != retval)
-			return retval;
-
-		/* Make sure tvnorm, vbi_end and the current cropping
-		   parameters remain consistent until we're done. Note
-		   read() may change vbi_end in check_alloc_btres(). */
-		mutex_lock(&btv->lock);
-
-		retval = -EBUSY;
-
-		if (locked_btres(fh->btv, VIDEO_RESOURCES))
-			goto btv_unlock_and_return;
-
-		b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
-
-		b_left = b->left;
-		b_right = b_left + b->width;
-		b_bottom = b->top + b->height;
-
-		b_top = max(b->top, btv->vbi_end);
-		if (b_top + 32 >= b_bottom)
-			goto btv_unlock_and_return;
-
-		/* Min. scaled size 48 x 32. */
-		c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
-		c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
-
-		c.rect.width = clamp(crop->c.width,
-				     48, b_right - c.rect.left);
-
-		c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
-		/* Top and height must be a multiple of two. */
-		c.rect.top = (c.rect.top + 1) & ~1;
-
-		c.rect.height = clamp(crop->c.height,
-				      32, b_bottom - c.rect.top);
-		c.rect.height = (c.rect.height + 1) & ~1;
-
-		bttv_crop_calc_limits(&c);
-
-		btv->crop[1] = c;
-
-		mutex_unlock(&btv->lock);
-
-		fh->do_crop = 1;
-
-		mutex_lock(&fh->cap.lock);
-
-		if (fh->width < c.min_scaled_width) {
-			fh->width = c.min_scaled_width;
-			btv->init.width = c.min_scaled_width;
-		} else if (fh->width > c.max_scaled_width) {
-			fh->width = c.max_scaled_width;
-			btv->init.width = c.max_scaled_width;
-		}
-
-		if (fh->height < c.min_scaled_height) {
-			fh->height = c.min_scaled_height;
-			btv->init.height = c.min_scaled_height;
-		} else if (fh->height > c.max_scaled_height) {
-			fh->height = c.max_scaled_height;
-			btv->init.height = c.max_scaled_height;
-		}
-
-		mutex_unlock(&fh->cap.lock);
-
-		return 0;
-	}
-
-	case VIDIOC_ENUMSTD:
-	case VIDIOC_G_STD:
-	case VIDIOC_S_STD:
-	case VIDIOC_ENUMINPUT:
-	case VIDIOC_G_INPUT:
-	case VIDIOC_S_INPUT:
-	case VIDIOC_S_TUNER:
-	case VIDIOC_G_FREQUENCY:
-	case VIDIOC_S_FREQUENCY:
-	case VIDIOC_LOG_STATUS:
-	case VIDIOC_G_CTRL:
-	case VIDIOC_S_CTRL:
-	case VIDIOC_DBG_G_REGISTER:
-	case VIDIOC_DBG_S_REGISTER:
-		return bttv_common_ioctls(btv,cmd,arg);
-	default:
-		return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-						  bttv_do_ioctl);
-	}
+	if (bttv_tvcards[btv->c.type].tuner != UNSET &&
+	    bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)
+		cap->capabilities |= V4L2_CAP_TUNER;
 	return 0;
+}
 
- fh_unlock_and_return:
+static int vidioc_enum_fmt_cap(struct file *file, void  *priv,
+				struct v4l2_fmtdesc *f)
+{
+	if (f->index >= FORMATS)
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].fourcc;
+
+	return 0;
+}
+
+static int vidioc_enum_fmt_overlay(struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (no_overlay > 0) {
+		printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+		return -EINVAL;
+	}
+
+	if (f->index >= FORMATS)
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name,
+		sizeof(f->description));
+
+	f->pixelformat = formats[f->index].fourcc;
+
+	return 0;
+}
+
+static int vidioc_enum_fmt_vbi(struct file *file, void  *priv,
+				struct v4l2_fmtdesc *f)
+{
+	if (0 != f->index)
+		return -EINVAL;
+
+	f->pixelformat = V4L2_PIX_FMT_GREY;
+	strcpy(f->description, "vbi data");
+
+	return 0;
+}
+
+static int vidioc_g_fbuf(struct file *file, void *f,
+				struct v4l2_framebuffer *fb)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	*fb = btv->fbuf;
+	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+	if (fh->ovfmt)
+		fb->fmt.pixelformat  = fh->ovfmt->fourcc;
+	return 0;
+}
+
+static int vidioc_overlay(struct file *file, void *f, unsigned int on)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	struct bttv_buffer *new;
+	int retval;
+
+	if (on) {
+		/* verify args */
+		if (NULL == btv->fbuf.base)
+			return -EINVAL;
+		if (!fh->ov.setup_ok) {
+			dprintk("bttv%d: overlay: !setup_ok\n", btv->c.nr);
+			return -EINVAL;
+		}
+	}
+
+	if (!check_alloc_btres(btv, fh, RESOURCE_OVERLAY))
+		return -EBUSY;
+
+	mutex_lock(&fh->cap.lock);
+	if (on) {
+		fh->ov.tvnorm = btv->tvnorm;
+		new = videobuf_pci_alloc(sizeof(*new));
+		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+	} else {
+		new = NULL;
+	}
+
+	/* switch over */
+	retval = bttv_switch_overlay(btv, fh, new);
 	mutex_unlock(&fh->cap.lock);
 	return retval;
-
- btv_unlock_and_return:
-	mutex_unlock(&btv->lock);
-	return retval;
 }
 
-static int bttv_ioctl(struct inode *inode, struct file *file,
-		      unsigned int cmd, unsigned long arg)
+static int vidioc_s_fbuf(struct file *file, void *f,
+				struct v4l2_framebuffer *fb)
 {
-	return video_usercopy(inode, file, cmd, arg, bttv_do_ioctl);
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	const struct bttv_format *fmt;
+	int retval;
+
+	if (!capable(CAP_SYS_ADMIN) &&
+		!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/* check args */
+	fmt = format_by_fourcc(fb->fmt.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+	if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
+		return -EINVAL;
+
+	retval = -EINVAL;
+	if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+		__s32 width = fb->fmt.width;
+		__s32 height = fb->fmt.height;
+
+		retval = limit_scaled_size(fh, &width, &height,
+					   V4L2_FIELD_INTERLACED,
+					   /* width_mask */ ~3,
+					   /* width_bias */ 2,
+					   /* adjust_size */ 0,
+					   /* adjust_crop */ 0);
+		if (0 != retval)
+			return retval;
+	}
+
+	/* ok, accept it */
+	mutex_lock(&fh->cap.lock);
+	btv->fbuf.base       = fb->base;
+	btv->fbuf.fmt.width  = fb->fmt.width;
+	btv->fbuf.fmt.height = fb->fmt.height;
+	if (0 != fb->fmt.bytesperline)
+		btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
+	else
+		btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
+
+	retval = 0;
+	fh->ovfmt = fmt;
+	btv->init.ovfmt = fmt;
+	if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+		fh->ov.w.left   = 0;
+		fh->ov.w.top    = 0;
+		fh->ov.w.width  = fb->fmt.width;
+		fh->ov.w.height = fb->fmt.height;
+		btv->init.ov.w.width  = fb->fmt.width;
+		btv->init.ov.w.height = fb->fmt.height;
+			kfree(fh->ov.clips);
+		fh->ov.clips = NULL;
+		fh->ov.nclips = 0;
+
+		if (check_btres(fh, RESOURCE_OVERLAY)) {
+			struct bttv_buffer *new;
+
+			new = videobuf_pci_alloc(sizeof(*new));
+			new->crop = btv->crop[!!fh->do_crop].rect;
+			bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+			retval = bttv_switch_overlay(btv, fh, new);
+		}
+	}
+	mutex_unlock(&fh->cap.lock);
+	return retval;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+				struct v4l2_requestbuffers *p)
+{
+	struct bttv_fh *fh = priv;
+	return videobuf_reqbufs(bttv_queue(fh), p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+				struct v4l2_buffer *b)
+{
+	struct bttv_fh *fh = priv;
+	return videobuf_querybuf(bttv_queue(fh), b);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	int res = bttv_resource(fh);
+
+	if (!check_alloc_btres(btv, fh, res))
+		return -EBUSY;
+
+	return videobuf_qbuf(bttv_queue(fh), b);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct bttv_fh *fh = priv;
+	return videobuf_dqbuf(bttv_queue(fh), b,
+			file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+					enum v4l2_buf_type type)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	int res = bttv_resource(fh);
+
+	if (!check_alloc_btres(btv, fh, res))
+		return -EBUSY;
+	return videobuf_streamon(bttv_queue(fh));
+}
+
+
+static int vidioc_streamoff(struct file *file, void *priv,
+					enum v4l2_buf_type type)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	int retval;
+	int res = bttv_resource(fh);
+
+
+	retval = videobuf_streamoff(bttv_queue(fh));
+	if (retval < 0)
+		return retval;
+	free_btres(btv, fh, res);
+	return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+					struct v4l2_queryctrl *c)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	const struct v4l2_queryctrl *ctrl;
+
+	if ((c->id <  V4L2_CID_BASE ||
+	     c->id >= V4L2_CID_LASTP1) &&
+	    (c->id <  V4L2_CID_PRIVATE_BASE ||
+	     c->id >= V4L2_CID_PRIVATE_LASTP1))
+		return -EINVAL;
+
+	ctrl = ctrl_by_id(c->id);
+	*c = (NULL != ctrl) ? *ctrl : no_ctl;
+
+	if (!btv->volume_gpio &&
+	    (ctrl->id == V4L2_CID_AUDIO_VOLUME))
+		* c = no_ctl;
+
+	return 0;
+}
+
+static int vidioc_g_parm(struct file *file, void *f,
+				struct v4l2_streamparm *parm)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	struct v4l2_standard s;
+
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,
+				 bttv_tvnorms[btv->tvnorm].name);
+	parm->parm.capture.timeperframe = s.frameperiod;
+	return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (UNSET == bttv_tvcards[btv->c.type].tuner)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	mutex_lock(&btv->lock);
+	memset(t, 0, sizeof(*t));
+	t->rxsubchans = V4L2_TUNER_SUB_MONO;
+	bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+	strcpy(t->name, "Television");
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->type       = V4L2_TUNER_ANALOG_TV;
+	if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
+		t->signal = 0xffff;
+
+	if (btv->audio_mode_gpio)
+		btv->audio_mode_gpio(btv, t, 0);
+
+	mutex_unlock(&btv->lock);
+	return 0;
+}
+
+static int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	*p = v4l2_prio_max(&btv->prio);
+
+	return 0;
+}
+
+static int vidioc_s_priority(struct file *file, void *f,
+					enum v4l2_priority prio)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	return v4l2_prio_change(&btv->prio, &fh->prio, prio);
+}
+
+static int vidioc_cropcap(struct file *file, void *priv,
+				struct v4l2_cropcap *cap)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+		return -EINVAL;
+
+	*cap = bttv_tvnorms[btv->tvnorm].cropcap;
+
+	return 0;
+}
+
+static int vidioc_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+		return -EINVAL;
+
+	/* No fh->do_crop = 1; because btv->crop[1] may be
+	   inconsistent with fh->width or fh->height and apps
+	   do not expect a change here. */
+
+	crop->c = btv->crop[!!fh->do_crop].rect;
+
+	return 0;
+}
+
+static int vidioc_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	const struct v4l2_rect *b;
+	int retval;
+	struct bttv_crop c;
+	__s32 b_left;
+	__s32 b_top;
+	__s32 b_right;
+	__s32 b_bottom;
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+		return -EINVAL;
+
+	retval = v4l2_prio_check(&btv->prio, &fh->prio);
+	if (0 != retval)
+		return retval;
+
+	/* Make sure tvnorm, vbi_end and the current cropping
+	   parameters remain consistent until we're done. Note
+	   read() may change vbi_end in check_alloc_btres(). */
+	mutex_lock(&btv->lock);
+
+	retval = -EBUSY;
+
+	if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
+		mutex_unlock(&btv->lock);
+		return retval;
+	}
+
+	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+	b_left = b->left;
+	b_right = b_left + b->width;
+	b_bottom = b->top + b->height;
+
+	b_top = max(b->top, btv->vbi_end);
+	if (b_top + 32 >= b_bottom) {
+		mutex_unlock(&btv->lock);
+		return retval;
+	}
+
+	/* Min. scaled size 48 x 32. */
+	c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
+	c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
+
+	c.rect.width = clamp(crop->c.width,
+			     48, b_right - c.rect.left);
+
+	c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
+	/* Top and height must be a multiple of two. */
+	c.rect.top = (c.rect.top + 1) & ~1;
+
+	c.rect.height = clamp(crop->c.height,
+			      32, b_bottom - c.rect.top);
+	c.rect.height = (c.rect.height + 1) & ~1;
+
+	bttv_crop_calc_limits(&c);
+
+	btv->crop[1] = c;
+
+	mutex_unlock(&btv->lock);
+
+	fh->do_crop = 1;
+
+	mutex_lock(&fh->cap.lock);
+
+	if (fh->width < c.min_scaled_width) {
+		fh->width = c.min_scaled_width;
+		btv->init.width = c.min_scaled_width;
+	} else if (fh->width > c.max_scaled_width) {
+		fh->width = c.max_scaled_width;
+		btv->init.width = c.max_scaled_width;
+	}
+
+	if (fh->height < c.min_scaled_height) {
+		fh->height = c.min_scaled_height;
+		btv->init.height = c.min_scaled_height;
+	} else if (fh->height > c.max_scaled_height) {
+		fh->height = c.max_scaled_height;
+		btv->init.height = c.max_scaled_height;
+	}
+
+	mutex_unlock(&fh->cap.lock);
+
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	strcpy(a->name, "audio");
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	return 0;
 }
 
 static ssize_t bttv_read(struct file *file, char __user *data,
@@ -3240,7 +3295,7 @@
 	.owner	  = THIS_MODULE,
 	.open	  = bttv_open,
 	.release  = bttv_release,
-	.ioctl	  = bttv_ioctl,
+	.ioctl	  = video_ioctl2,
 	.compat_ioctl	= v4l_compat_ioctl32,
 	.llseek	  = no_llseek,
 	.read	  = bttv_read,
@@ -3255,6 +3310,57 @@
 		    VID_TYPE_CLIPPING|VID_TYPE_SCALES,
 	.fops     = &bttv_fops,
 	.minor    = -1,
+	.vidioc_querycap                = vidioc_querycap,
+	.vidioc_enum_fmt_cap            = vidioc_enum_fmt_cap,
+	.vidioc_g_fmt_cap               = vidioc_g_fmt_cap,
+	.vidioc_try_fmt_cap             = vidioc_try_fmt_cap,
+	.vidioc_s_fmt_cap               = vidioc_s_fmt_cap,
+	.vidioc_enum_fmt_overlay        = vidioc_enum_fmt_overlay,
+	.vidioc_g_fmt_overlay           = vidioc_g_fmt_overlay,
+	.vidioc_try_fmt_overlay         = vidioc_try_fmt_overlay,
+	.vidioc_s_fmt_overlay           = vidioc_s_fmt_overlay,
+	.vidioc_enum_fmt_vbi            = vidioc_enum_fmt_vbi,
+	.vidioc_g_fmt_vbi               = vidioc_g_fmt_vbi,
+	.vidioc_try_fmt_vbi             = vidioc_try_fmt_vbi,
+	.vidioc_s_fmt_vbi               = vidioc_s_fmt_vbi,
+	.vidioc_g_audio                 = vidioc_g_audio,
+	.vidioc_s_audio                 = vidioc_s_audio,
+	.vidioc_cropcap                 = vidioc_cropcap,
+	.vidioc_reqbufs                 = vidioc_reqbufs,
+	.vidioc_querybuf                = vidioc_querybuf,
+	.vidioc_qbuf                    = vidioc_qbuf,
+	.vidioc_dqbuf                   = vidioc_dqbuf,
+	.vidioc_s_std                   = vidioc_s_std,
+	.vidioc_enum_input              = vidioc_enum_input,
+	.vidioc_g_input                 = vidioc_g_input,
+	.vidioc_s_input                 = vidioc_s_input,
+	.vidioc_queryctrl               = vidioc_queryctrl,
+	.vidioc_g_ctrl                  = vidioc_g_ctrl,
+	.vidioc_s_ctrl                  = vidioc_s_ctrl,
+	.vidioc_streamon                = vidioc_streamon,
+	.vidioc_streamoff               = vidioc_streamoff,
+	.vidioc_g_tuner                 = vidioc_g_tuner,
+	.vidioc_s_tuner                 = vidioc_s_tuner,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	.vidiocgmbuf                    = vidiocgmbuf,
+#endif
+	.vidioc_g_crop                  = vidioc_g_crop,
+	.vidioc_g_crop                  = vidioc_g_crop,
+	.vidioc_s_crop                  = vidioc_s_crop,
+	.vidioc_g_fbuf                  = vidioc_g_fbuf,
+	.vidioc_s_fbuf                  = vidioc_s_fbuf,
+	.vidioc_overlay                 = vidioc_overlay,
+	.vidioc_g_priority              = vidioc_g_priority,
+	.vidioc_s_priority              = vidioc_s_priority,
+	.vidioc_g_parm                  = vidioc_g_parm,
+	.vidioc_g_frequency             = vidioc_g_frequency,
+	.vidioc_s_frequency             = vidioc_s_frequency,
+	.vidioc_log_status		= vidioc_log_status,
+	.vidioc_querystd		= vidioc_querystd,
+	.vidioc_g_register		= vidioc_g_register,
+	.vidioc_s_register		= vidioc_s_register,
+	.tvnorms                        = BTTV_NORMS,
+	.current_norm                   = V4L2_STD_PAL,
 };
 
 static struct video_device bttv_vbi_template =
@@ -3301,7 +3407,7 @@
 
 static int radio_release(struct inode *inode, struct file *file)
 {
-	struct bttv        *btv = file->private_data;
+	struct bttv *btv = file->private_data;
 	struct rds_command cmd;
 
 	btv->radio_user--;
@@ -3311,67 +3417,116 @@
 	return 0;
 }
 
-static int radio_do_ioctl(struct inode *inode, struct file *file,
-			  unsigned int cmd, void *arg)
+static int radio_querycap(struct file *file, void *priv,
+					struct v4l2_capability *cap)
 {
-	struct bttv    *btv = file->private_data;
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
 
-	switch (cmd) {
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = arg;
+	strcpy(cap->driver, "bttv");
+	strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
+	sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
+	cap->version = BTTV_VERSION_CODE;
+	cap->capabilities = V4L2_CAP_TUNER;
 
-		memset(cap,0,sizeof(*cap));
-		strcpy(cap->driver, "bttv");
-		strlcpy(cap->card, btv->radio_dev->name,sizeof(cap->card));
-		sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci));
-		cap->version = BTTV_VERSION_CODE;
-		cap->capabilities = V4L2_CAP_TUNER;
-		return 0;
-	}
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *t = arg;
-
-		if (UNSET == bttv_tvcards[btv->c.type].tuner)
-			return -EINVAL;
-		if (0 != t->index)
-			return -EINVAL;
-		mutex_lock(&btv->lock);
-		memset(t,0,sizeof(*t));
-		strcpy(t->name, "Radio");
-		t->type = V4L2_TUNER_RADIO;
-
-		bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
-
-		if (btv->audio_mode_gpio) {
-			btv->audio_mode_gpio (btv,t,0);
-		}
-
-		mutex_unlock(&btv->lock);
-
-		return 0;
-	}
-	case VIDIOC_S_TUNER:
-	case VIDIOC_G_FREQUENCY:
-	case VIDIOC_S_FREQUENCY:
-	case VIDIOC_G_CTRL:
-	case VIDIOC_S_CTRL:
-	case VIDIOC_LOG_STATUS:
-	case VIDIOC_DBG_G_REGISTER:
-	case VIDIOC_DBG_S_REGISTER:
-		return bttv_common_ioctls(btv,cmd,arg);
-	default:
-		return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-						  radio_do_ioctl);
-	}
 	return 0;
 }
 
-static int radio_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg)
+static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
 {
-	return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (UNSET == bttv_tvcards[btv->c.type].tuner)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+	mutex_lock(&btv->lock);
+	memset(t, 0, sizeof(*t));
+	strcpy(t->name, "Radio");
+	t->type = V4L2_TUNER_RADIO;
+
+	bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+
+	if (btv->audio_mode_gpio)
+		btv->audio_mode_gpio(btv, t, 0);
+
+	mutex_unlock(&btv->lock);
+
+	return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	if (i->index != 0)
+		return -EINVAL;
+
+	strcpy(i->name, "Radio");
+	 i->type = V4L2_INPUT_TYPE_TUNER;
+
+	return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	memset(a, 0, sizeof(*a));
+	strcpy(a->name, "Radio");
+	return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *t)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t);
+	return 0;
+}
+
+static int radio_s_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	return 0;
+}
+
+static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	return 0;
+}
+
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+	return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+					struct v4l2_queryctrl *c)
+{
+	const struct v4l2_queryctrl *ctrl;
+
+	if (c->id <  V4L2_CID_BASE ||
+			c->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+
+	if (c->id == V4L2_CID_AUDIO_MUTE) {
+		ctrl = ctrl_by_id(c->id);
+		*c = *ctrl;
+	} else
+		*c = no_ctl;
+
+	return 0;
+}
+
+static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
 }
 
 static ssize_t radio_read(struct file *file, char __user *data,
@@ -3407,7 +3562,7 @@
 	.open	  = radio_open,
 	.read     = radio_read,
 	.release  = radio_release,
-	.ioctl	  = radio_ioctl,
+	.ioctl	  = video_ioctl2,
 	.llseek	  = no_llseek,
 	.poll     = radio_poll,
 };
@@ -3418,6 +3573,20 @@
 	.type     = VID_TYPE_TUNER,
 	.fops     = &radio_fops,
 	.minor    = -1,
+	.vidioc_querycap        = radio_querycap,
+	.vidioc_g_tuner         = radio_g_tuner,
+	.vidioc_enum_input      = radio_enum_input,
+	.vidioc_g_audio         = radio_g_audio,
+	.vidioc_s_tuner         = radio_s_tuner,
+	.vidioc_s_audio         = radio_s_audio,
+	.vidioc_s_input         = radio_s_input,
+	.vidioc_s_std           = radio_s_std,
+	.vidioc_queryctrl       = radio_queryctrl,
+	.vidioc_g_input         = radio_g_input,
+	.vidioc_g_ctrl          = vidioc_g_ctrl,
+	.vidioc_s_ctrl          = vidioc_s_ctrl,
+	.vidioc_g_frequency     = vidioc_g_frequency,
+	.vidioc_s_frequency     = vidioc_s_frequency,
 };
 
 /* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index b924f05..da27081 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -236,10 +236,8 @@
 
 /* ----------------------------------------------------------------------- */
 
-static int
-try_fmt			(struct v4l2_vbi_format *	f,
-			 const struct bttv_tvnorm *	tvnorm,
-			 __s32				crop_start)
+static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
+			__s32 crop_start)
 {
 	__s32 min_start, max_start, max_end, f2_offset;
 	unsigned int i;
@@ -305,10 +303,9 @@
 	return 0;
 }
 
-int
-bttv_vbi_try_fmt	(struct bttv_fh *		fh,
-			 struct v4l2_vbi_format *	f)
+int vidioc_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
 {
+	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
 	const struct bttv_tvnorm *tvnorm;
 	__s32 crop_start;
@@ -320,13 +317,13 @@
 
 	mutex_unlock(&btv->lock);
 
-	return try_fmt(f, tvnorm, crop_start);
+	return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
 }
 
-int
-bttv_vbi_set_fmt	(struct bttv_fh *		fh,
-			 struct v4l2_vbi_format *	f)
+
+int vidioc_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
 {
+	struct bttv_fh *fh = f;
 	struct bttv *btv = fh->btv;
 	const struct bttv_tvnorm *tvnorm;
 	__s32 start1, end;
@@ -340,11 +337,12 @@
 
 	tvnorm = &bttv_tvnorms[btv->tvnorm];
 
-	rc = try_fmt(f, tvnorm, btv->crop_start);
+	rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
 	if (0 != rc)
 		goto fail;
 
-	start1 = f->start[1] - tvnorm->vbistart[1] + tvnorm->vbistart[0];
+	start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
+		tvnorm->vbistart[0];
 
 	/* First possible line of video capturing. Should be
 	   max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
@@ -352,11 +350,11 @@
 	   pretend the VBI and video capture window may overlap,
 	   so end = start + 1, the lowest possible value, times two
 	   because vbi_fmt.end counts field lines times two. */
-	end = max(f->start[0], start1) * 2 + 2;
+	end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
 
 	mutex_lock(&fh->vbi.lock);
 
-	fh->vbi_fmt.fmt    = *f;
+	fh->vbi_fmt.fmt    = frt->fmt.vbi;
 	fh->vbi_fmt.tvnorm = tvnorm;
 	fh->vbi_fmt.end    = end;
 
@@ -370,13 +368,13 @@
 	return rc;
 }
 
-void
-bttv_vbi_get_fmt	(struct bttv_fh *		fh,
-			 struct v4l2_vbi_format *	f)
+
+int vidioc_g_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
 {
+	struct bttv_fh *fh = f;
 	const struct bttv_tvnorm *tvnorm;
 
-	*f = fh->vbi_fmt.fmt;
+	frt->fmt.vbi = fh->vbi_fmt.fmt;
 
 	tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
 
@@ -391,28 +389,28 @@
 		max_end = (tvnorm->cropcap.bounds.top
 			   + tvnorm->cropcap.bounds.height) >> 1;
 
-		f->sampling_rate = tvnorm->Fsc;
+		frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
 
 		for (i = 0; i < 2; ++i) {
 			__s32 new_start;
 
-			new_start = f->start[i]
+			new_start = frt->fmt.vbi.start[i]
 				+ tvnorm->vbistart[i]
 				- fh->vbi_fmt.tvnorm->vbistart[i];
 
-			f->start[i] = min(new_start, max_end - 1);
-			f->count[i] = min((__s32) f->count[i],
-					  max_end - f->start[i]);
+			frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
+			frt->fmt.vbi.count[i] =
+				min((__s32) frt->fmt.vbi.count[i],
+					  max_end - frt->fmt.vbi.start[i]);
 
 			max_end += tvnorm->vbistart[1]
 				- tvnorm->vbistart[0];
 		}
 	}
+	return 0;
 }
 
-void
-bttv_vbi_fmt_reset	(struct bttv_vbi_fmt *		f,
-			 int				norm)
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm)
 {
 	const struct bttv_tvnorm *tvnorm;
 	unsigned int real_samples_per_line;
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 4a02f0a..2603030 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -84,6 +84,11 @@
 
 #define clamp(x, low, high) min (max (low, x), high)
 
+#define BTTV_NORMS    (\
+		V4L2_STD_PAL    | V4L2_STD_PAL_N | \
+		V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
+		V4L2_STD_NTSC   | V4L2_STD_PAL_M | \
+		V4L2_STD_PAL_60)
 /* ---------------------------------------------------------- */
 
 struct bttv_tvnorm {
@@ -252,9 +257,9 @@
 /* ---------------------------------------------------------- */
 /* bttv-vbi.c                                                 */
 
-int bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
-void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
-int bttv_vbi_set_fmt(struct bttv_fh *fh, struct v4l2_vbi_format *f);
+int vidioc_try_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
+int vidioc_g_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
+int vidioc_s_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f);
 
 extern struct videobuf_queue_ops bttv_vbi_qops;