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

Commit bac63981 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[media] cx88: first phase to convert cx88 to the control framework

parent 902e197d
Loading
Loading
Loading
Loading
+7 −24
Original line number Diff line number Diff line
@@ -585,13 +585,10 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
{
	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
	struct cx88_core *core = chip->core;
	struct v4l2_control client_ctl;
	int left = value->value.integer.value[0];
	int right = value->value.integer.value[1];
	int v, b;

	memset(&client_ctl, 0, sizeof(client_ctl));

	/* Pass volume & balance onto any WM8775 */
	if (left >= right) {
		v = left << 10;
@@ -600,13 +597,8 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
		v = right << 10;
		b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
	}
	client_ctl.value = v;
	client_ctl.id = V4L2_CID_AUDIO_VOLUME;
	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);

	client_ctl.value = b;
	client_ctl.id = V4L2_CID_AUDIO_BALANCE;
	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
	wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
	wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
}

/* OK - TODO: test it */
@@ -687,14 +679,8 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
		/* Pass mute onto any WM8775 */
		if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
		    ((1<<6) == bit)) {
			struct v4l2_control client_ctl;

			memset(&client_ctl, 0, sizeof(client_ctl));
			client_ctl.value = 0 != (vol & bit);
			client_ctl.id = V4L2_CID_AUDIO_MUTE;
			call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
		}
		    ((1<<6) == bit))
			wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
		ret = 1;
	}
	spin_unlock_irq(&chip->reg_lock);
@@ -724,13 +710,10 @@ static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
{
	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
	struct cx88_core *core = chip->core;
	struct v4l2_control client_ctl;

	memset(&client_ctl, 0, sizeof(client_ctl));
	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
	call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
	value->value.integer.value[0] = client_ctl.value ? 1 : 0;
	s32 val;

	val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
	value->value.integer.value[0] = val ? 1 : 0;
	return 0;
}

+0 −71
Original line number Diff line number Diff line
@@ -685,43 +685,6 @@ static struct videobuf_queue_ops blackbird_qops = {

/* ------------------------------------------------------------------ */

static const u32 *ctrl_classes[] = {
	cx88_user_ctrls,
	cx2341x_mpeg_ctrls,
	NULL
};

static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl)
{
	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
	if (qctrl->id == 0)
		return -EINVAL;

	/* Standard V4L2 controls */
	if (cx8800_ctrl_query(dev->core, qctrl) == 0)
		return 0;

	/* MPEG V4L2 controls */
	if (cx2341x_ctrl_query(&dev->params, qctrl))
		qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
	return 0;
}

/* ------------------------------------------------------------------ */
/* IOCTL Handlers                                                     */

static int vidioc_querymenu (struct file *file, void *priv,
				struct v4l2_querymenu *qmenu)
{
	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
	struct v4l2_queryctrl qctrl;

	qctrl.id = qmenu->id;
	blackbird_queryctrl(dev, &qctrl);
	return v4l2_ctrl_query_menu(qmenu, &qctrl,
			cx2341x_ctrl_get_menu(&dev->params, qmenu->id));
}

static int vidioc_querycap(struct file *file, void  *priv,
					struct v4l2_capability *cap)
{
@@ -917,20 +880,6 @@ static int vidioc_log_status (struct file *file, void *priv)
	return 0;
}

static int vidioc_queryctrl (struct file *file, void *priv,
				struct v4l2_queryctrl *qctrl)
{
	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;

	if (blackbird_queryctrl(dev, qctrl) == 0)
		return 0;

	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
	if (unlikely(qctrl->id == 0))
		return -EINVAL;
	return cx8800_ctrl_query(dev->core, qctrl);
}

static int vidioc_enum_input (struct file *file, void *priv,
				struct v4l2_input *i)
{
@@ -938,22 +887,6 @@ static int vidioc_enum_input (struct file *file, void *priv,
	return cx88_enum_input (core,i);
}

static int vidioc_g_ctrl (struct file *file, void *priv,
				struct v4l2_control *ctl)
{
	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
	return
		cx88_get_control(core,ctl);
}

static int vidioc_s_ctrl (struct file *file, void *priv,
				struct v4l2_control *ctl)
{
	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
	return
		cx88_set_control(core,ctl);
}

static int vidioc_g_frequency (struct file *file, void *priv,
				struct v4l2_frequency *f)
{
@@ -1178,7 +1111,6 @@ static const struct v4l2_file_operations mpeg_fops =
};

static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
	.vidioc_querymenu     = vidioc_querymenu,
	.vidioc_querycap      = vidioc_querycap,
	.vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
	.vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
@@ -1195,10 +1127,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
	.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
	.vidioc_s_frequency   = vidioc_s_frequency,
	.vidioc_log_status    = vidioc_log_status,
	.vidioc_queryctrl     = vidioc_queryctrl,
	.vidioc_enum_input    = vidioc_enum_input,
	.vidioc_g_ctrl        = vidioc_g_ctrl,
	.vidioc_s_ctrl        = vidioc_s_ctrl,
	.vidioc_g_frequency   = vidioc_g_frequency,
	.vidioc_g_input       = vidioc_g_input,
	.vidioc_s_input       = vidioc_s_input,
+11 −0
Original line number Diff line number Diff line
@@ -3693,7 +3693,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
		return NULL;
	}

	if (v4l2_ctrl_handler_init(&core->hdl, 13)) {
		v4l2_device_unregister(&core->v4l2_dev);
		kfree(core);
		return NULL;
	}

	if (0 != cx88_get_resources(core, pci)) {
		v4l2_ctrl_handler_free(&core->hdl);
		v4l2_device_unregister(&core->v4l2_dev);
		kfree(core);
		return NULL;
@@ -3706,6 +3713,10 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
	core->bmmio = (u8 __iomem *)core->lmmio;

	if (core->lmmio == NULL) {
		release_mem_region(pci_resource_start(pci, 0),
			   pci_resource_len(pci, 0));
		v4l2_ctrl_handler_free(&core->hdl);
		v4l2_device_unregister(&core->v4l2_dev);
		kfree(core);
		return NULL;
	}
+2 −1
Original line number Diff line number Diff line
@@ -1030,7 +1030,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
		return NULL;
	*vfd = *template_;
	vfd->v4l2_dev = &core->v4l2_dev;
	vfd->parent = &pci->dev;
	vfd->ctrl_handler = &core->hdl;
	vfd->release = video_device_release;
	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
		 core->name, type, core->board.name);
@@ -1086,6 +1086,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
	iounmap(core->lmmio);
	cx88_devcount--;
	mutex_unlock(&devlist);
	v4l2_ctrl_handler_free(&core->hdl);
	v4l2_device_unregister(&core->v4l2_dev);
	kfree(core);
}
+159 −334
Original line number Diff line number Diff line
@@ -160,46 +160,51 @@ static const struct v4l2_queryctrl no_ctl = {
	.flags = V4L2_CTRL_FLAG_DISABLED,
};


struct cx88_ctrl {
	/* control information */
	u32 id;
	s32 minimum;
	s32 maximum;
	u32 step;
	s32 default_value;

	/* control register information */
	u32 off;
	u32 reg;
	u32 sreg;
	u32 mask;
	u32 shift;
};

static const struct cx88_ctrl cx8800_ctls[] = {
	/* --- video --- */
	{
		.v = {
		.id            = V4L2_CID_BRIGHTNESS,
			.name          = "Brightness",
		.minimum       = 0x00,
		.maximum       = 0xff,
		.step          = 1,
		.default_value = 0x7f,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.off           = 128,
		.reg           = MO_CONTR_BRIGHT,
		.mask          = 0x00ff,
		.shift         = 0,
	},{
		.v = {
		.id            = V4L2_CID_CONTRAST,
			.name          = "Contrast",
		.minimum       = 0,
		.maximum       = 0xff,
		.step          = 1,
		.default_value = 0x3f,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.off           = 0,
		.reg           = MO_CONTR_BRIGHT,
		.mask          = 0xff00,
		.shift         = 8,
	},{
		.v = {
		.id            = V4L2_CID_HUE,
			.name          = "Hue",
		.minimum       = 0,
		.maximum       = 0xff,
		.step          = 1,
		.default_value = 0x7f,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.off           = 128,
		.reg           = MO_HUE,
		.mask          = 0x00ff,
@@ -208,29 +213,21 @@ static const struct cx88_ctrl cx8800_ctls[] = {
		/* strictly, this only describes only U saturation.
		 * V saturation is handled specially through code.
		 */
		.v = {
		.id            = V4L2_CID_SATURATION,
			.name          = "Saturation",
		.minimum       = 0,
		.maximum       = 0xff,
		.step          = 1,
		.default_value = 0x7f,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.off           = 0,
		.reg           = MO_UV_SATURATION,
		.mask          = 0x00ff,
		.shift         = 0,
	}, {
		.v = {
		.id            = V4L2_CID_SHARPNESS,
			.name          = "Sharpness",
		.minimum       = 0,
		.maximum       = 4,
		.step          = 1,
		.default_value = 0x0,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.off           = 0,
		/* NOTE: the value is converted and written to both even
		   and odd registers in the code */
@@ -238,132 +235,69 @@ static const struct cx88_ctrl cx8800_ctls[] = {
		.mask          = 7 << 7,
		.shift         = 7,
	}, {
		.v = {
		.id            = V4L2_CID_CHROMA_AGC,
			.name          = "Chroma AGC",
		.minimum       = 0,
		.maximum       = 1,
		.default_value = 0x1,
			.type          = V4L2_CTRL_TYPE_BOOLEAN,
		},
		.reg           = MO_INPUT_FORMAT,
		.mask          = 1 << 10,
		.shift         = 10,
	}, {
		.v = {
		.id            = V4L2_CID_COLOR_KILLER,
			.name          = "Color killer",
		.minimum       = 0,
		.maximum       = 1,
		.default_value = 0x1,
			.type          = V4L2_CTRL_TYPE_BOOLEAN,
		},
		.reg           = MO_INPUT_FORMAT,
		.mask          = 1 << 9,
		.shift         = 9,
	}, {
		.v = {
		.id            = V4L2_CID_BAND_STOP_FILTER,
			.name          = "Notch filter",
		.minimum       = 0,
		.maximum       = 1,
		.step          = 1,
		.default_value = 0x0,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.off           = 0,
		.reg           = MO_HTOTAL,
		.mask          = 3 << 11,
		.shift         = 11,
	}, {
		/* --- audio --- */
		.v = {
		.id            = V4L2_CID_AUDIO_MUTE,
			.name          = "Mute",
		.minimum       = 0,
		.maximum       = 1,
		.default_value = 1,
			.type          = V4L2_CTRL_TYPE_BOOLEAN,
		},
		.reg           = AUD_VOL_CTL,
		.sreg          = SHADOW_AUD_VOL_CTL,
		.mask          = (1 << 6),
		.shift         = 6,
	},{
		.v = {
		.id            = V4L2_CID_AUDIO_VOLUME,
			.name          = "Volume",
		.minimum       = 0,
		.maximum       = 0x3f,
		.step          = 1,
		.default_value = 0x3f,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.reg           = AUD_VOL_CTL,
		.sreg          = SHADOW_AUD_VOL_CTL,
		.mask          = 0x3f,
		.shift         = 0,
	},{
		.v = {
		.id            = V4L2_CID_AUDIO_BALANCE,
			.name          = "Balance",
		.minimum       = 0,
		.maximum       = 0x7f,
		.step          = 1,
		.default_value = 0x40,
			.type          = V4L2_CTRL_TYPE_INTEGER,
		},
		.reg           = AUD_BAL_CTL,
		.sreg          = SHADOW_AUD_BAL_CTL,
		.mask          = 0x7f,
		.shift         = 0,
	}
};
enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) };

/* Must be sorted from low to high control ID! */
const u32 cx88_user_ctrls[] = {
	V4L2_CID_USER_CLASS,
	V4L2_CID_BRIGHTNESS,
	V4L2_CID_CONTRAST,
	V4L2_CID_SATURATION,
	V4L2_CID_HUE,
	V4L2_CID_AUDIO_VOLUME,
	V4L2_CID_AUDIO_BALANCE,
	V4L2_CID_AUDIO_MUTE,
	V4L2_CID_SHARPNESS,
	V4L2_CID_CHROMA_AGC,
	V4L2_CID_COLOR_KILLER,
	V4L2_CID_BAND_STOP_FILTER,
	0
};
EXPORT_SYMBOL(cx88_user_ctrls);
enum { CX8800_CTLS = ARRAY_SIZE(cx8800_ctls) };

static const u32 * const ctrl_classes[] = {
	cx88_user_ctrls,
	NULL
};

int cx8800_ctrl_query(struct cx88_core *core, struct v4l2_queryctrl *qctrl)
{
	int i;

	if (qctrl->id < V4L2_CID_BASE ||
	    qctrl->id >= V4L2_CID_LASTP1)
		return -EINVAL;
	for (i = 0; i < CX8800_CTLS; i++)
		if (cx8800_ctls[i].v.id == qctrl->id)
			break;
	if (i == CX8800_CTLS) {
		*qctrl = no_ctl;
		return 0;
	}
	*qctrl = cx8800_ctls[i].v;
	/* Report chroma AGC as inactive when SECAM is selected */
	if (cx8800_ctls[i].v.id == V4L2_CID_CHROMA_AGC &&
	    core->tvnorm & V4L2_STD_SECAM)
		qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;

	return 0;
}
EXPORT_SYMBOL(cx8800_ctrl_query);
@@ -974,98 +908,43 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
/* ------------------------------------------------------------------ */
/* VIDEO CTRL IOCTLS                                                  */

int cx88_get_control (struct cx88_core  *core, struct v4l2_control *ctl)
{
	const struct cx88_ctrl  *c    = NULL;
	u32 value;
	int i;

	for (i = 0; i < CX8800_CTLS; i++)
		if (cx8800_ctls[i].v.id == ctl->id)
			c = &cx8800_ctls[i];
	if (unlikely(NULL == c))
		return -EINVAL;

	value = c->sreg ? cx_sread(c->sreg) : cx_read(c->reg);
	switch (ctl->id) {
	case V4L2_CID_AUDIO_BALANCE:
		ctl->value = ((value & 0x7f) < 0x40) ? ((value & 0x7f) + 0x40)
					: (0x7f - (value & 0x7f));
		break;
	case V4L2_CID_AUDIO_VOLUME:
		ctl->value = 0x3f - (value & 0x3f);
		break;
	case V4L2_CID_SHARPNESS:
		ctl->value = ((value & 0x0200) ? (((value & 0x0180) >> 7) + 1)
						 : 0);
		break;
	default:
		ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
		break;
	}
	dprintk(1,"get_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
				ctl->id, c->v.name, ctl->value, c->reg,
				value,c->mask, c->sreg ? " [shadowed]" : "");
	return 0;
}
EXPORT_SYMBOL(cx88_get_control);

int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
static int cx8800_s_ctrl(struct v4l2_ctrl *ctrl)
{
	const struct cx88_ctrl *c = NULL;
	struct cx88_core *core =
		container_of(ctrl->handler, struct cx88_core, hdl);
	const struct cx88_ctrl *cc = ctrl->priv;
	u32 value,mask;
	int i;

	for (i = 0; i < CX8800_CTLS; i++) {
		if (cx8800_ctls[i].v.id == ctl->id) {
			c = &cx8800_ctls[i];
		}
	}
	if (unlikely(NULL == c))
		return -EINVAL;

	if (ctl->value < c->v.minimum)
		ctl->value = c->v.minimum;
	if (ctl->value > c->v.maximum)
		ctl->value = c->v.maximum;

	/* Pass changes onto any WM8775 */
	if (core->board.audio_chip == V4L2_IDENT_WM8775) {
		struct v4l2_control client_ctl;
		memset(&client_ctl, 0, sizeof(client_ctl));
		client_ctl.id = ctl->id;

		switch (ctl->id) {
		switch (ctrl->id) {
		case V4L2_CID_AUDIO_MUTE:
			client_ctl.value = ctl->value;
			wm8775_s_ctrl(core, ctrl->id, ctrl->val);
			break;
		case V4L2_CID_AUDIO_VOLUME:
			client_ctl.value = (ctl->value) ?
				(0x90 + ctl->value) << 8 : 0;
			wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ?
						(0x90 + ctrl->val) << 8 : 0);
			break;
		case V4L2_CID_AUDIO_BALANCE:
			client_ctl.value = ctl->value << 9;
			wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9);
			break;
		default:
			client_ctl.id = 0;
			break;
		}
		if (client_ctl.id)
			call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
	}

	mask=c->mask;
	switch (ctl->id) {
	mask = cc->mask;
	switch (ctrl->id) {
	case V4L2_CID_AUDIO_BALANCE:
		value = (ctl->value < 0x40) ? (0x7f - ctl->value) : (ctl->value - 0x40);
		value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40);
		break;
	case V4L2_CID_AUDIO_VOLUME:
		value = 0x3f - (ctl->value & 0x3f);
		value = 0x3f - (ctrl->val & 0x3f);
		break;
	case V4L2_CID_SATURATION:
		/* special v_sat handling */

		value = ((ctl->value - c->off) << c->shift) & c->mask;
		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;

		if (core->tvnorm & V4L2_STD_SECAM) {
			/* For SECAM, both U and V sat should be equal */
@@ -1078,44 +957,29 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
		break;
	case V4L2_CID_SHARPNESS:
		/* 0b000, 0b100, 0b101, 0b110, or 0b111 */
		value = (ctl->value < 1 ? 0 : ((ctl->value + 3) << 7));
		value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7));
		/* needs to be set for both fields */
		cx_andor(MO_FILTER_EVEN, mask, value);
		break;
	case V4L2_CID_CHROMA_AGC:
		/* Do not allow chroma AGC to be enabled for SECAM */
		value = ((ctl->value - c->off) << c->shift) & c->mask;
		if (core->tvnorm & V4L2_STD_SECAM && value)
		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
		if ((core->tvnorm & V4L2_STD_SECAM) && value)
			return -EINVAL;
		break;
	default:
		value = ((ctl->value - c->off) << c->shift) & c->mask;
		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
		break;
	}
	dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
				ctl->id, c->v.name, ctl->value, c->reg, value,
				mask, c->sreg ? " [shadowed]" : "");
	if (c->sreg) {
		cx_sandor(c->sreg, c->reg, mask, value);
	} else {
		cx_andor(c->reg, mask, value);
	}
				ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
				mask, cc->sreg ? " [shadowed]" : "");
	if (cc->sreg)
		cx_sandor(cc->sreg, cc->reg, mask, value);
	else
		cx_andor(cc->reg, mask, value);
	return 0;
}
EXPORT_SYMBOL(cx88_set_control);

static void init_controls(struct cx88_core *core)
{
	struct v4l2_control ctrl;
	int i;

	for (i = 0; i < CX8800_CTLS; i++) {
		ctrl.id=cx8800_ctls[i].v.id;
		ctrl.value=cx8800_ctls[i].v.default_value;

		cx88_set_control(core, &ctrl);
	}
}

/* ------------------------------------------------------------------ */
/* VIDEO IOCTLS                                                       */
@@ -1382,35 +1246,6 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
	return 0;
}



static int vidioc_queryctrl (struct file *file, void *priv,
				struct v4l2_queryctrl *qctrl)
{
	struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;

	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
	if (unlikely(qctrl->id == 0))
		return -EINVAL;
	return cx8800_ctrl_query(core, qctrl);
}

static int vidioc_g_ctrl (struct file *file, void *priv,
				struct v4l2_control *ctl)
{
	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
	return
		cx88_get_control(core,ctl);
}

static int vidioc_s_ctrl (struct file *file, void *priv,
				struct v4l2_control *ctl)
{
	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
	return
		cx88_set_control(core,ctl);
}

static int vidioc_g_tuner (struct file *file, void *priv,
				struct v4l2_tuner *t)
{
@@ -1563,29 +1398,6 @@ static int radio_s_tuner (struct file *file, void *priv,
	return 0;
}

static int radio_queryctrl (struct file *file, void *priv,
			    struct v4l2_queryctrl *c)
{
	int i;

	if (c->id <  V4L2_CID_BASE ||
		c->id >= V4L2_CID_LASTP1)
		return -EINVAL;
	if (c->id == V4L2_CID_AUDIO_MUTE ||
		c->id == V4L2_CID_AUDIO_VOLUME ||
		c->id == V4L2_CID_AUDIO_BALANCE) {
		for (i = 0; i < CX8800_CTLS; i++) {
			if (cx8800_ctls[i].v.id == c->id)
				break;
		}
		if (i == CX8800_CTLS)
			return -EINVAL;
		*c = cx8800_ctls[i].v;
	} else
		*c = no_ctl;
	return 0;
}

/* ----------------------------------------------------------- */

static void cx8800_vid_timeout(unsigned long data)
@@ -1739,9 +1551,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
	.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,
@@ -1776,9 +1585,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
	.vidioc_querycap      = vidioc_querycap,
	.vidioc_g_tuner       = radio_g_tuner,
	.vidioc_s_tuner       = radio_s_tuner,
	.vidioc_queryctrl     = radio_queryctrl,
	.vidioc_g_ctrl        = vidioc_g_ctrl,
	.vidioc_s_ctrl        = vidioc_s_ctrl,
	.vidioc_g_frequency   = vidioc_g_frequency,
	.vidioc_s_frequency   = vidioc_s_frequency,
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1793,6 +1599,10 @@ static const struct video_device cx8800_radio_template = {
	.ioctl_ops 	      = &radio_ioctl_ops,
};

static const struct v4l2_ctrl_ops cx8800_ctrl_ops = {
	.s_ctrl = cx8800_s_ctrl,
};

/* ----------------------------------------------------------- */

static void cx8800_unregister_video(struct cx8800_dev *dev)
@@ -1825,8 +1635,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
{
	struct cx8800_dev *dev;
	struct cx88_core *core;

	int err;
	int i;

	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
	if (NULL == dev)
@@ -1897,6 +1707,19 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
	}
	cx_set(MO_PCI_INTMSK, core->pci_irqmask);

	for (i = 0; i < CX8800_CTLS; i++) {
		const struct cx88_ctrl *cc = &cx8800_ctls[i];
		struct v4l2_ctrl *vc;

		vc = v4l2_ctrl_new_std(&core->hdl, &cx8800_ctrl_ops,
			cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
		if (vc == NULL) {
			err = core->hdl.error;
			goto fail_core;
		}
		vc->priv = (void *)cc;
	}

	/* load and configure helper modules */

	if (core->board.audio_chip == V4L2_IDENT_WM8775) {
@@ -1914,9 +1737,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,

		sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
				&wm8775_info, NULL);
		if (sd != NULL)
		if (sd != NULL) {
			core->sd_wm8775 = sd;
			sd->grp_id = WM8775_GID;
		}
	}

	if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
		/* This probes for a tda9874 as is used on some
@@ -1946,7 +1771,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
	/* initial device configuration */
	mutex_lock(&core->lock);
	cx88_set_tvnorm(core, core->tvnorm);
	init_controls(core);
	v4l2_ctrl_handler_setup(&core->hdl);
	cx88_video_mux(core, 0);

	/* register v4l devices */
Loading