Re: cx23885: Add basic analog radio support

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

 



Em 14-01-2012 16:25, Miroslav Slugeň escreveu:
> New version of patch, fixed video modes for DVR3200 tuners and working
> audio mux.
> 
> 
> cx23885-add-basic-fm-radio-support_v3.patch

If you want it to be applied, please add your Signed-off-by on it.

See the patch review below.

Thanks,
Mauro
> 
> 
> Signed-off-by: Miroslav Slugen <thunder.mmm@xxxxxxxxx>
> From: Miroslav Slugen <thunder.mmm@xxxxxxxxx>
> 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.
> 
>  Version 3
> 
> diff -Naurp a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
> --- a/drivers/media/video/cx23885/cx23885-cards.c	2012-01-14 18:43:40.000000000 +0100
> +++ b/drivers/media/video/cx23885/cx23885-cards.c	2012-01-14 19:04:58.412366747 +0100
> @@ -205,35 +205,87 @@ 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,
> +			.amux	= CX25840_AUDIO8,
> +			.gpio0	= 0x704040,
> +		}, {
> +			.type	= CX23885_VMUX_COMPOSITE1,
> +			.vmux	= CX25840_VIN1_CH1,
> +			.amux	= CX25840_AUDIO7,
> +			.gpio0	= 0x704040,
> +		}, {
> +			.type	= CX23885_VMUX_SVIDEO,
> +			.vmux	= CX25840_VIN3_CH1 |
> +				  CX25840_SVIDEO_ON,
> +			.amux	= CX25840_AUDIO7,
> +			.gpio0	= 0x704040,
> +		}, {
> +			.type	= CX23885_VMUX_COMPONENT,
> +			.vmux	= CX25840_VIN7_CH1 |
> +				  CX25840_VIN6_CH2 |
> +				  CX25840_VIN8_CH3 |
> +				  CX25840_COMPONENT_ON,
> +			.amux	= CX25840_AUDIO7,
> +			.gpio0	= 0x704040,
> +		} },
> +		.radio = {
> +			.type	= CX23885_RADIO,
> +			.amux	= CX25840_AUDIO8,
> +			.gpio0	= 0x706060,
> +		},
>  	},
>  	[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,
> +				  CX25840_VIN5_CH2,
> +			.amux	= CX25840_AUDIO8,
> +			.gpio0	= 0x704040,
>  		}, {
>  			.type	= CX23885_VMUX_COMPOSITE1,
> -			.vmux	= CX25840_COMPOSITE1,
> +			.vmux	= CX25840_VIN1_CH1,
> +			.amux	= CX25840_AUDIO7,
> +			.gpio0	= 0x704040,
>  		}, {
>  			.type	= CX23885_VMUX_SVIDEO,
> -			.vmux	= CX25840_SVIDEO_LUMA3 |
> -				  CX25840_SVIDEO_CHROMA4,
> +			.vmux	= CX25840_VIN3_CH1 |
> +				  CX25840_SVIDEO_ON,
> +			.amux	= CX25840_AUDIO7,
> +			.gpio0	= 0x704040,
>  		}, {
>  			.type	= CX23885_VMUX_COMPONENT,
>  			.vmux	= CX25840_VIN7_CH1 |
>  				  CX25840_VIN6_CH2 |
>  				  CX25840_VIN8_CH3 |
>  				  CX25840_COMPONENT_ON,
> +			.amux	= CX25840_AUDIO7,
> +			.gpio0	= 0x704040,
>  		} },
> +		.radio = {
> +			.type	= CX23885_RADIO,
> +			.amux	= CX25840_AUDIO8,
> +			.gpio0	= 0x706060,
> +		},
>  	},
>  	[CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = {
>  		.name		= "Compro VideoMate E650F",
> @@ -818,27 +870,95 @@ static void hauppauge_eeprom(struct cx23
>  			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(75);
> +		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(75);
> +		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:

The changes don't seem to be cool on my eyes: if you're splitting the tuner callback
into a separate xc4000 and a separate xc2028 call, you need to move the board-specific
stuff into there; if not, then just put the code for Leadtek directly into this
routine. I would just move the code into the sub-routine, as the only thing you're
doing inside the cx23885_xc4000_tuner_callback()/cx23885_xc2028_tuner_callback(() is to
call another sub-routine.

> @@ -861,6 +981,9 @@ int cx23885_tuner_callback(void *priv, i
>  	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 +995,7 @@ int cx23885_tuner_callback(void *priv, i
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL(cx23885_tuner_callback);

Please use, instead, EXPORT_SYMBOL_GPL().
>  
>  void cx23885_gpio_setup(struct cx23885_dev *dev)
>  {
> @@ -999,7 +1123,11 @@ void cx23885_gpio_setup(struct cx23885_d
>  		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 +1440,30 @@ void cx23885_ir_pci_int_enable(struct cx
>  	}
>  }
>  
> +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 -Naurp a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
> --- a/drivers/media/video/cx23885/cx23885.h	2012-01-05 00:55:44.000000000 +0100
> +++ b/drivers/media/video/cx23885/cx23885.h	2012-01-14 18:48:44.172366746 +0100
> @@ -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 */
>  };
>  
> @@ -416,6 +418,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 +559,8 @@ extern void cx23885_gpio_setup(struct cx
>  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);
>  
> diff -Naurp a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
> --- a/drivers/media/video/cx23885/cx23885-video.c	2012-01-05 00:55:44.000000000 +0100
> +++ b/drivers/media/video/cx23885/cx23885-video.c	2012-01-14 19:11:43.148366748 +0100
> @@ -36,6 +36,7 @@
>  #include <media/v4l2-ioctl.h>
>  #include "cx23885-ioctl.h"
>  #include "tuner-xc2028.h"
> +#include "xc4000.h"
>  
>  #include <media/cx25840.h>
>  
> @@ -502,18 +503,6 @@ static int cx23885_video_mux(struct cx23
>  	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 */
> -		v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
> -			INPUT(input)->amux, 0, 0);
> -
> -		if (INPUT(input)->amux == CX25840_AUDIO7)
> -			cx23885_flatiron_mux(dev, 1);
> -		else if (INPUT(input)->amux == CX25840_AUDIO6)
> -			cx23885_flatiron_mux(dev, 2);
> -	}
> -

Hmm... why are you removing these? Won't it break support for this board?

>  	return 0;
>  }
>  
> @@ -521,6 +510,10 @@ static int cx23885_audio_mux(struct cx23
>  {
>  	dprintk(1, "%s(input=%d)\n", __func__, input);
>  
> +	/* Configure audio routing */
> +	v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
> +		INPUT(input)->amux, 0, 0);
> +
>  	/* The baseband video core of the cx23885 has two audio inputs.
>  	 * LR1 and LR2. In almost every single case so far only HVR1xxx
>  	 * cards we've only ever supported LR1. Time to support LR2,
> @@ -871,20 +864,29 @@ 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_0, cx23885_boards[dev->board].radio.gpio0);
> +		call_all(dev, tuner, s_radio);
> +	}
> +
> +	dev->users++;
> +	mutex_unlock(&dev->lock);
>  
>  	dprintk(1, "post videobuf_queue_init()\n");
>  
> @@ -981,13 +983,24 @@ static int video_release(struct file *fi
>  	}
>  
>  	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 +1268,13 @@ static int cx23885_enum_input(struct cx2
>  		[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 +1514,108 @@ static int vidioc_s_frequency(struct fil
>  }
>  
>  /* ----------------------------------------------------------- */
> +/* 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 +1763,43 @@ static const struct v4l2_file_operations
>  	.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 +1872,28 @@ int cx23885_video_register(struct cx2388
>  			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 +1925,21 @@ int cx23885_video_register(struct cx2388
>  	printk(KERN_INFO "%s: registered device %s\n",
>  	       dev->name, video_device_node_name(dev->vbi_dev));
>  
> +	if (cx23885_boards[dev->board].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);
>  
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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