cx23885: Add basic analog radio support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Basic implemenetation of radio support, also working support for
DVR3200H tuners (xc2028 and xc4000).
From f2cd361613526d3fb400becf8d6618745f44e59d Mon Sep 17 00:00:00 2001
From: Miroslav <thunder.m@xxxxxxxx>
Date: Sat, 17 Dec 2011 01:23:22 +0100
Subject: [PATCH] Add support for radio tuners to cx23885 driver, and add example of radio support
 for Leadtek DVR3200 H tuners.

---
 drivers/media/video/cx23885/cx23885-cards.c |  160 ++++++++++++++++++-
 drivers/media/video/cx23885/cx23885-video.c |  222 ++++++++++++++++++++++++---
 drivers/media/video/cx23885/cx23885.h       |   23 +++-
 3 files changed, 374 insertions(+), 31 deletions(-)

diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 187c462..240e7dd 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -205,35 +205,79 @@ struct cx23885_board cx23885_boards[] = {
 	},
 	[CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = {
 		.name		= "Leadtek Winfast PxDVR3200 H",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_ENCODER,
 		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_XC2028,
+		.tuner_addr	= 0x61,
+		.radio_type	= UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_bus	= 1,
+		.input		= {{
+			.type	= CX23885_VMUX_TELEVISION,
+			.vmux	= CX25840_VIN2_CH1 |
+				  CX25840_VIN5_CH2 |
+				  CX25840_NONE0_CH3,
+			.gpio0	= 0,
+		}, {
+			.type	= CX23885_VMUX_COMPOSITE1,
+			.vmux	= CX25840_COMPOSITE1,
+			.gpio0	= 0,
+		}, {
+			.type	= CX23885_VMUX_SVIDEO,
+			.vmux	= CX25840_SVIDEO_LUMA3 |
+				  CX25840_SVIDEO_CHROMA4,
+			.gpio0	= 0,
+		}, {
+			.type	= CX23885_VMUX_COMPONENT,
+			.vmux	= CX25840_VIN7_CH1 |
+				  CX25840_VIN6_CH2 |
+				  CX25840_VIN8_CH3 |
+				  CX25840_COMPONENT_ON,
+			.gpio0	= 0,
+		} },
+		.radio = {
+			.type	= CX23885_RADIO,
+			.gpio0	= 0,
+		},
 	},
 	[CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000] = {
 		.name		= "Leadtek Winfast PxDVR3200 H XC4000",
 		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_ENCODER,
 		.portc		= CX23885_MPEG_DVB,
 		.tuner_type	= TUNER_XC4000,
 		.tuner_addr	= 0x61,
 		.radio_type	= UNSET,
 		.radio_addr	= ADDR_UNSET,
+		.tuner_bus	= 1,
 		.input		= {{
 			.type	= CX23885_VMUX_TELEVISION,
 			.vmux	= CX25840_VIN2_CH1 |
 				  CX25840_VIN5_CH2 |
 				  CX25840_NONE0_CH3,
+			.gpio0	= 0,
 		}, {
 			.type	= CX23885_VMUX_COMPOSITE1,
 			.vmux	= CX25840_COMPOSITE1,
+			.gpio0	= 0,
 		}, {
 			.type	= CX23885_VMUX_SVIDEO,
 			.vmux	= CX25840_SVIDEO_LUMA3 |
 				  CX25840_SVIDEO_CHROMA4,
+			.gpio0	= 0,
 		}, {
 			.type	= CX23885_VMUX_COMPONENT,
 			.vmux	= CX25840_VIN7_CH1 |
 				  CX25840_VIN6_CH2 |
 				  CX25840_VIN8_CH3 |
 				  CX25840_COMPONENT_ON,
+			.gpio0	= 0,
 		} },
+		.radio = {
+			.type	= CX23885_RADIO,
+			.gpio0	= 0,
+		},
 	},
 	[CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = {
 		.name		= "Compro VideoMate E650F",
@@ -818,27 +862,95 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
 			dev->name, tv.model);
 }
 
+static int cx23885_xc2028_leadtek_callback(struct cx23885_dev *dev,
+					   int command, int arg)
+{
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		/* GPIO 12 (xc2028 tuner reset) */
+		cx_set(GP0_IO, 0x00040000);
+		mdelay(50);
+		cx_clear(GP0_IO, 0x00000004);
+		mdelay(75);
+		cx_set(GP0_IO, 0x00040004);
+		mdelay(75);
+		return 0;
+	case XC2028_RESET_CLK:
+	case XC2028_I2C_FLUSH:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int cx23885_xc4000_leadtek_callback(struct cx23885_dev *dev,
+					   int command, int arg)
+{
+	switch (command) {
+	case XC4000_TUNER_RESET:
+		/* GPIO 12 (xc4000 tuner reset) */
+		cx_set(GP0_IO, 0x00040000);
+		mdelay(50);
+		cx_clear(GP0_IO, 0x00000004);
+		mdelay(75);
+		cx_set(GP0_IO, 0x00040004);
+		mdelay(75);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int cx23885_xc2028_tuner_callback(struct cx23885_dev *dev,
+					 int command, int arg)
+{
+	/* Board-specific callbacks */
+	switch (dev->board) {
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+		return cx23885_xc2028_leadtek_callback(dev, command, arg);
+	}
+
+	return -EINVAL;
+}
+
+static int cx23885_xc4000_tuner_callback(struct cx23885_dev *dev,
+					 int command, int arg)
+{
+	/* Board-specific callbacks */
+	switch (dev->board) {
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+		return cx23885_xc4000_leadtek_callback(dev, command, arg);
+	}
+
+	return -EINVAL;
+}
+
 int cx23885_tuner_callback(void *priv, int component, int command, int arg)
 {
 	struct cx23885_tsport *port = priv;
-	struct cx23885_dev *dev = port->dev;
+	struct cx23885_dev *dev;
 	u32 bitmask = 0;
 
-	if (command == XC2028_RESET_CLK)
-		return 0;
+	if (!port) {
+		printk(KERN_ERR "cx23885: Error - private data undefined.\n");
+		return -EINVAL;
+	}
+
+	dev = port->dev;
 
-	if (command != 0) {
-		printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
-			__func__, command);
+	if (!dev) {
+		printk(KERN_ERR "cx23885: Error - device struct undefined.\n");
 		return -EINVAL;
 	}
 
 	switch (dev->board) {
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+		printk(KERN_INFO "%s: Calling XC2028/3028 callback\n", dev->name);
+		return cx23885_xc2028_tuner_callback(dev, command, arg);
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+		printk(KERN_INFO "%s: Calling XC4000 callback\n", dev->name);
+		return cx23885_xc4000_tuner_callback(dev, command, arg);
 	case CX23885_BOARD_HAUPPAUGE_HVR1400:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500:
 	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
-	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
@@ -861,6 +973,9 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
 	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
 		altera_ci_tuner_reset(dev, port->nr);
 		break;
+	default:
+		printk(KERN_ERR "cx23885: Error: Calling callback for card %d\n", dev->board);
+		break;
 	}
 
 	if (bitmask) {
@@ -872,6 +987,7 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg)
 
 	return 0;
 }
+EXPORT_SYMBOL(cx23885_tuner_callback);
 
 void cx23885_gpio_setup(struct cx23885_dev *dev)
 {
@@ -999,7 +1115,11 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
 		cx_set(GP0_IO, 0x000f000f);
 		break;
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+		cx23885_xc2028_leadtek_callback(dev, XC2028_TUNER_RESET, 0);
+		break;
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+		cx23885_xc4000_leadtek_callback(dev, XC4000_TUNER_RESET, 0);
+		break;
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
 	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
@@ -1312,6 +1432,30 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
 	}
 }
 
+void cx23885_setup_xc3028(struct cx23885_dev *dev, struct xc2028_ctrl *ctl)
+{
+	memset(ctl, 0, sizeof(*ctl));
+
+	ctl->fname   = XC2028_DEFAULT_FIRMWARE;
+	ctl->max_len = 64;
+
+	switch (dev->board) {
+	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+		break;
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+		ctl->demod = XC3028_FE_ZARLINK456;
+		break;
+	default:
+		ctl->demod = XC3028_FE_OREN538;
+		ctl->mts = 1;
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(cx23885_setup_xc3028);
+
 void cx23885_card_setup(struct cx23885_dev *dev)
 {
 	struct cx23885_tsport *ts1 = &dev->ts1;
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index e730b92..9a8fab1 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -36,6 +36,7 @@
 #include <media/v4l2-ioctl.h>
 #include "cx23885-ioctl.h"
 #include "tuner-xc2028.h"
+#include "xc4000.h"
 
 #include <media/cx25840.h>
 
@@ -501,7 +502,6 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
 	/* Tell the internal A/V decoder */
 	v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
 			INPUT(input)->vmux, 0, 0);
-
 	if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
 		(dev->board == CX23885_BOARD_MPX885)) {
 		/* Configure audio routing */
@@ -871,20 +871,37 @@ static int video_open(struct file *file)
 	fh->height   = 240;
 	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_YUYV);
 
+	mutex_lock(&dev->lock);
+
 	videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
 			    &dev->pci->dev, &dev->slock,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_INTERLACED,
 			    sizeof(struct cx23885_buffer),
 			    fh, NULL);
-
 	videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
-		&dev->pci->dev, &dev->slock,
-		V4L2_BUF_TYPE_VBI_CAPTURE,
-		V4L2_FIELD_SEQ_TB,
-		sizeof(struct cx23885_buffer),
-		fh, NULL);
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VBI_CAPTURE,
+			    V4L2_FIELD_SEQ_TB,
+			    sizeof(struct cx23885_buffer),
+			    fh, NULL);
 
+	if (fh->radio) {
+		dprintk(1,"video_open: setting radio device\n");
+		cx_write(GPIO_3, cx23885_boards[dev->board].radio.gpio3);
+		cx_write(GPIO_0, cx23885_boards[dev->board].radio.gpio0);
+		cx_write(GPIO_1, cx23885_boards[dev->board].radio.gpio1);
+		cx_write(GPIO_2, cx23885_boards[dev->board].radio.gpio2);
+		if (cx23885_boards[dev->board].radio.amux) {
+			/* switch audio input and set tvaudio here */
+		} else {
+			/* set tvaudio here */
+		}
+		call_all(dev, tuner, s_radio);
+	}
+
+	dev->users++;
+	mutex_unlock(&dev->lock);
 
 	dprintk(1, "post videobuf_queue_init()\n");
 
@@ -981,13 +998,24 @@ static int video_release(struct file *file)
 	}
 
 	videobuf_mmap_free(&fh->vidq);
+	videobuf_mmap_free(&fh->vbiq);
+
+	mutex_lock(&dev->lock);
 	file->private_data = NULL;
 	kfree(fh);
 
+	dev->users--;
+
 	/* We are not putting the tuner to sleep here on exit, because
 	 * we want to use the mpeg encoder in another session to capture
 	 * tuner video. Closing this will result in no video to the encoder.
 	 */
+#if 0
+	if (!dev->users)
+		call_all(dev, core, s_power, 0);
+#endif
+
+	mutex_unlock(&dev->lock);
 
 	return 0;
 }
@@ -1255,17 +1283,13 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
 		[CX23885_VMUX_DVB]        = "DVB",
 		[CX23885_VMUX_DEBUG]      = "for debug only",
 	};
-	unsigned int n;
+	unsigned int n = i->index;
 	dprintk(1, "%s()\n", __func__);
 
-	n = i->index;
 	if (n >= MAX_CX23885_INPUT)
 		return -EINVAL;
-
 	if (0 == INPUT(n)->type)
 		return -EINVAL;
-
-	i->index = n;
 	i->type  = V4L2_INPUT_TYPE_CAMERA;
 	strcpy(i->name, iname[INPUT(n)->type]);
 	if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) ||
@@ -1505,6 +1529,108 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 }
 
 /* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
+/* ----------------------------------------------------------- */
+
+static int radio_querycap (struct file *file, void  *priv,
+					struct v4l2_capability *cap)
+{
+	struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+
+	strcpy(cap->driver, "cx23885");
+	strlcpy(cap->card, cx23885_boards[dev->board].name, sizeof(cap->card));
+	sprintf(cap->bus_info,"PCIe:%s", pci_name(dev->pci));
+	cap->capabilities = V4L2_CAP_TUNER;
+	return 0;
+}
+
+static int radio_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+
+	if (unlikely(t->index > 0))
+		return -EINVAL;
+
+	strcpy(t->name, "Radio");
+	t->type = V4L2_TUNER_RADIO;
+
+	call_all(dev, tuner, g_tuner, t);
+	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)
+{
+	if (unlikely(a->index))
+		return -EINVAL;
+
+	strcpy(a->name,"Radio");
+	return 0;
+}
+
+/* FIXME: Should add a standard for radio */
+
+static int radio_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	call_all(dev, tuner, s_tuner, t);
+
+	return 0;
+}
+
+static int radio_s_audio (struct file *file, void *fh,
+			  struct v4l2_audio *a)
+{
+	return 0;
+}
+
+static int radio_s_input (struct file *file, void *fh, unsigned int i)
+{
+	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 < CX23885_CTLS; i++) {
+			if (cx23885_ctls[i].v.id == c->id)
+				break;
+		}
+		if (i == CX23885_CTLS) {
+			*c = no_ctl;
+			return 0;
+		}
+		*c = cx23885_ctls[i].v;
+	} else
+		*c = no_ctl;
+	return 0;
+}
+
+/* ----------------------------------------------------------- */
 
 static void cx23885_vid_timeout(unsigned long data)
 {
@@ -1652,12 +1778,43 @@ static const struct v4l2_file_operations radio_fops = {
 	.ioctl         = video_ioctl2,
 };
 
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+	.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_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
+	.vidioc_g_register    = cx23885_g_register,
+	.vidioc_s_register    = cx23885_s_register,
+#endif
+};
+
+static struct video_device cx23885_radio_template = {
+	.name                 = "cx23885-radio",
+	.fops                 = &radio_fops,
+	.ioctl_ops            = &radio_ioctl_ops,
+};
 
 void cx23885_video_unregister(struct cx23885_dev *dev)
 {
 	dprintk(1, "%s()\n", __func__);
 	cx23885_irq_remove(dev, 0x01);
 
+	if (dev->radio_dev) {
+		if (video_is_registered(dev->radio_dev))
+			video_unregister_device(dev->radio_dev);
+		else
+			video_device_release(dev->radio_dev);
+		dev->radio_dev = NULL;
+	}
 	if (dev->vbi_dev) {
 		if (video_is_registered(dev->vbi_dev))
 			video_unregister_device(dev->vbi_dev);
@@ -1730,22 +1887,28 @@ int cx23885_video_register(struct cx23885_dev *dev)
 			struct tuner_setup tun_setup;
 
 			memset(&tun_setup, 0, sizeof(tun_setup));
-			tun_setup.mode_mask = T_ANALOG_TV;
+
+			tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
 			tun_setup.type = dev->tuner_type;
 			tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+
 			tun_setup.tuner_callback = cx23885_tuner_callback;
 
 			v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
 
-			if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) {
-				struct xc2028_ctrl ctrl = {
-					.fname = XC2028_DEFAULT_FIRMWARE,
-					.max_len = 64
-				};
-				struct v4l2_priv_tun_config cfg = {
-					.tuner = dev->tuner_type,
-					.priv = &ctrl
-				};
+			if (dev->tuner_type == TUNER_XC2028) {
+				struct v4l2_priv_tun_config  cfg;
+				struct xc2028_ctrl           ctl;
+
+				/* Fills device-dependent initialization parameters */
+				cx23885_setup_xc3028(dev, &ctl);
+
+				memset(&cfg, 0, sizeof(cfg));
+				cfg.tuner = TUNER_XC2028;
+				cfg.priv  = &ctl;
+
+				printk(KERN_INFO "%s: Asking xc2028/3028 to load firmware %s\n",
+				       dev->name, ctl.fname);
 				v4l2_subdev_call(sd, tuner, s_config, &cfg);
 			}
 		}
@@ -1777,6 +1940,21 @@ int cx23885_video_register(struct cx23885_dev *dev)
 	printk(KERN_INFO "%s: registered device %s\n",
 	       dev->name, video_device_node_name(dev->vbi_dev));
 
+	if (dev->radio_type == CX23885_RADIO) {
+		dev->radio_dev = cx23885_vdev_init(dev, dev->pci,
+						&cx23885_radio_template, "radio");
+		video_set_drvdata(dev->radio_dev, dev);
+		err = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+					    radio_nr[dev->nr]);
+		if (err < 0) {
+			printk(KERN_ERR "%s: can't register radio device\n",
+			       dev->name);
+			goto fail_unreg;
+		}
+		printk(KERN_INFO "%s: registered device %s\n",
+		       dev->name, video_device_node_name(dev->radio_dev));
+	}
+
 	/* Register ALSA audio device */
 	dev->audio_dev = cx23885_audio_register(dev);
 
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index b49036f..5fe977e 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -35,6 +35,7 @@
 #include "btcx-risc.h"
 #include "cx23885-reg.h"
 #include "media/cx2341x.h"
+#include "tuner-xc2028.h"
 
 #include <linux/mutex.h>
 
@@ -225,6 +226,7 @@ struct cx23885_board {
 	 */
 	u32			clk_freq;
 	struct cx23885_input    input[MAX_CX23885_INPUT];
+	struct cx23885_input    radio;
 	int			ci_type; /* for NetUP */
 };
 
@@ -234,6 +236,20 @@ struct cx23885_subid {
 	u32     card;
 };
 
+enum cx23885_tvaudio {
+	WW_NONE = 1,
+	WW_BTSC,
+	WW_BG,
+	WW_DK,
+	WW_I,
+	WW_L,
+	WW_EIAJ,
+	WW_I2SPT,
+	WW_FM,
+	WW_I2SADC,
+	WW_M
+};
+
 struct cx23885_i2c {
 	struct cx23885_dev *dev;
 
@@ -393,7 +409,7 @@ struct cx23885_dev {
 	u32                        resources;
 	unsigned int               input;
 	unsigned int               audinput; /* Selectable audio input */
-	u32                        tvaudio;
+	enum cx23885_tvaudio       tvaudio;
 	v4l2_std_id                tvnorm;
 	unsigned int               tuner_type;
 	unsigned char              tuner_addr;
@@ -416,6 +432,9 @@ struct cx23885_dev {
 
 	/* V4l */
 	u32                        freq;
+	int                        users;
+	int                        mpeg_users;
+
 	struct video_device        *video_dev;
 	struct video_device        *vbi_dev;
 	struct video_device        *radio_dev;
@@ -554,6 +573,8 @@ extern void cx23885_gpio_setup(struct cx23885_dev *dev);
 extern void cx23885_card_setup(struct cx23885_dev *dev);
 extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev);
 
+extern void cx23885_setup_xc3028(struct cx23885_dev *dev, struct xc2028_ctrl *ctl);
+
 extern int cx23885_dvb_register(struct cx23885_tsport *port);
 extern int cx23885_dvb_unregister(struct cx23885_tsport *port);
 
-- 
1.7.2.3


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux