The patch number 10771 was added via Mauro Carvalho Chehab <mche...@redhat.com> to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward compatible with older kernels. Compatibility modifications will be removed before inclusion into the mainstream Kernel If anyone has any objections, please let us know by sending a message to: Linux Media Mailing List <linux-me...@vger.kernel.org> ------ From: Mauro Carvalho Chehab <mche...@redhat.com> tea575x-tuner: convert it to V4L2 API Priority: normal Signed-off-by: Mauro Carvalho Chehab <mche...@redhat.com> --- linux/include/sound/tea575x-tuner.h | 22 - linux/sound/i2c/other/tea575x-tuner.c | 346 ++++++++++++++++---------- 2 files changed, 224 insertions(+), 144 deletions(-) diff -r b338640f0f67 -r 378d905783b1 linux/include/sound/tea575x-tuner.h --- a/linux/include/sound/tea575x-tuner.h Fri Feb 27 09:48:16 2009 -0300 +++ b/linux/include/sound/tea575x-tuner.h Fri Feb 27 11:51:24 2009 -0300 @@ -23,24 +23,16 @@ */ #include "compat.h" -#include <linux/videodev.h> +#include <linux/videodev2.h> #include <media/v4l2-dev.h> +#include <media/v4l2-ioctl.h> -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) -typedef struct snd_tea575x tea575x_t; -#else struct snd_tea575x; -#endif struct snd_tea575x_ops { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) - void (*write)(tea575x_t *tea, unsigned int val); - unsigned int (*read)(tea575x_t *tea); -#else void (*write)(struct snd_tea575x *tea, unsigned int val); unsigned int (*read)(struct snd_tea575x *tea); void (*mute)(struct snd_tea575x *tea, unsigned int mute); -#endif }; struct snd_tea575x { @@ -49,11 +41,10 @@ struct snd_tea575x { #else struct snd_card *card; #endif - struct video_device vd; /* video device */ - struct v4l2_file_operations fops; + struct video_device *vd; /* video device */ int dev_nr; /* requested device number + 1 */ - int vd_registered; /* video device is registered */ int tea5759; /* 5759 chip is present */ + int mute; /* Device is muted? */ unsigned int freq_fixup; /* crystal onboard */ unsigned int val; /* hw value */ unsigned long freq; /* frequency */ @@ -62,12 +53,7 @@ struct snd_tea575x { void *private_data; }; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) -void snd_tea575x_init(tea575x_t *tea); -void snd_tea575x_exit(tea575x_t *tea); -#else void snd_tea575x_init(struct snd_tea575x *tea); void snd_tea575x_exit(struct snd_tea575x *tea); -#endif #endif /* __SOUND_TEA575X_TUNER_H */ diff -r b338640f0f67 -r 378d905783b1 linux/sound/i2c/other/tea575x-tuner.c --- a/linux/sound/i2c/other/tea575x-tuner.c Fri Feb 27 09:48:16 2009 -0300 +++ b/linux/sound/i2c/other/tea575x-tuner.c Fri Feb 27 11:51:24 2009 -0300 @@ -31,6 +31,13 @@ MODULE_AUTHOR("Jaroslav Kysela <pe...@pe MODULE_AUTHOR("Jaroslav Kysela <pe...@perex.cz>"); MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); MODULE_LICENSE("GPL"); + +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +#define RADIO_VERSION KERNEL_VERSION(0,0,2) +#define FREQ_LO 87*16000 +#define FREQ_HI 108*16000 /* * definitions @@ -54,6 +61,17 @@ MODULE_LICENSE("GPL"); #define TEA575X_BIT_DUMMY (1<<15) /* buffer */ #define TEA575X_BIT_FREQ_MASK 0x7fff +static struct v4l2_queryctrl radio_qctrl[] = { + { + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .default_value = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, + } +}; + /* * lowlevel part */ @@ -89,124 +107,195 @@ static void snd_tea575x_set_freq(struct * Linux Video interface */ -static long snd_tea575x_ioctl(struct file *file, - unsigned int cmd, unsigned long data) -{ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) - tea575x_t *tea = video_drvdata(file); -#else - struct snd_tea575x *tea = video_drvdata(file); -#endif - void __user *arg = (void __user *)data; - - switch(cmd) { - case VIDIOCGCAP: - { - struct video_capability v; - v.type = VID_TYPE_TUNER; - v.channels = 1; - v.audios = 1; - /* No we don't do pictures */ - v.maxwidth = 0; - v.maxheight = 0; - v.minwidth = 0; - v.minheight = 0; - strcpy(v.name, tea->tea5759 ? "TEA5759" : "TEA5757"); - if (copy_to_user(arg,&v,sizeof(v))) - return -EFAULT; +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + struct snd_tea575x *tea = video_drvdata(file); + + strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757"); + strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver)); + strlcpy(v->card, "Maestro Radio", sizeof(v->card)); + sprintf(v->bus_info, "PCI"); + v->version = RADIO_VERSION; + v->capabilities = V4L2_CAP_TUNER; + return 0; +} + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + if (v->index > 0) + return -EINVAL; + + strcpy(v->name, "FM"); + v->type = V4L2_TUNER_RADIO; + v->rangelow = FREQ_LO; + v->rangehigh = FREQ_HI; + v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; + v->capability = V4L2_TUNER_CAP_LOW; + v->audmode = V4L2_TUNER_MODE_MONO; + v->signal = 0xffff; + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + if (v->index > 0) + return -EINVAL; + return 0; +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct snd_tea575x *tea = video_drvdata(file); + + f->type = V4L2_TUNER_RADIO; + f->frequency = tea->freq; + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct snd_tea575x *tea = video_drvdata(file); + + if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) + return -EINVAL; + + tea->freq = f->frequency; + + snd_tea575x_set_freq(tea); + + return 0; +} + +static int vidioc_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index > 1) + return -EINVAL; + + strcpy(a->name, "Radio"); + a->capability = V4L2_AUDCAP_STEREO; + return 0; +} + +static int vidioc_s_audio(struct file *file, void *priv, + struct v4l2_audio *a) +{ + if (a->index != 0) + return -EINVAL; + return 0; +} + +static int vidioc_queryctrl(struct file *file, void *priv, + struct v4l2_queryctrl *qc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { + if (qc->id && qc->id == radio_qctrl[i].id) { + memcpy(qc, &(radio_qctrl[i]), + sizeof(*qc)); return 0; } - case VIDIOCGTUNER: - { - struct video_tuner v; - if (copy_from_user(&v, arg,sizeof(v))!=0) - return -EFAULT; - if (v.tuner) /* Only 1 tuner */ - return -EINVAL; - v.rangelow = (87*16000); - v.rangehigh = (108*16000); - v.flags = VIDEO_TUNER_LOW; - v.mode = VIDEO_MODE_AUTO; - strcpy(v.name, "FM"); - v.signal = 0xFFFF; - if (copy_to_user(arg, &v, sizeof(v))) - return -EFAULT; + } + return -EINVAL; +} + +static int vidioc_g_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct snd_tea575x *tea = video_drvdata(file); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17) + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (tea->ops->mute) { + ctrl->value = tea->mute; return 0; } - case VIDIOCSTUNER: - { - struct video_tuner v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; - if(v.tuner!=0) - return -EINVAL; - /* Only 1 tuner so no setting needed ! */ + } +#endif + return -EINVAL; +} + +static int vidioc_s_ctrl(struct file *file, void *priv, + struct v4l2_control *ctrl) +{ + struct snd_tea575x *tea = video_drvdata(file); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17) + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + if (tea->ops->mute) { + tea->ops->mute(tea, ctrl->value); + tea->mute = 1; return 0; } - case VIDIOCGFREQ: - if(copy_to_user(arg, &tea->freq, sizeof(tea->freq))) - return -EFAULT; - return 0; - case VIDIOCSFREQ: - if(copy_from_user(&tea->freq, arg, sizeof(tea->freq))) - return -EFAULT; - snd_tea575x_set_freq(tea); - return 0; - case VIDIOCGAUDIO: - { - struct video_audio v; - memset(&v, 0, sizeof(v)); - strcpy(v.name, "Radio"); - if(copy_to_user(arg,&v, sizeof(v))) - return -EFAULT; - return 0; - } - case VIDIOCSAUDIO: - { - struct video_audio v; - if(copy_from_user(&v, arg, sizeof(v))) - return -EFAULT; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17) - if (tea->ops->mute) - tea->ops->mute(tea, - (v.flags & - VIDEO_AUDIO_MUTE) ? 1 : 0); -#endif - if(v.audio) - return -EINVAL; - return 0; - } - default: - return -ENOIOCTLCMD; - } -} - -static void snd_tea575x_release(struct video_device *vfd) -{ + } +#endif + return -EINVAL; +} + +static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) +{ + if (i != 0) + return -EINVAL; + return 0; } static int snd_tea575x_exclusive_open(struct file *file) { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) - tea575x_t *tea = video_drvdata(file); -#else - struct snd_tea575x *tea = video_drvdata(file); -#endif + struct snd_tea575x *tea = video_drvdata(file); return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0; } static int snd_tea575x_exclusive_release(struct file *file) { -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) - tea575x_t *tea = video_drvdata(file); -#else - struct snd_tea575x *tea = video_drvdata(file); -#endif + struct snd_tea575x *tea = video_drvdata(file); clear_bit(0, &tea->in_use); return 0; } + +static const struct v4l2_file_operations tea575x_fops = { + .owner = THIS_MODULE, + .open = snd_tea575x_exclusive_open, + .release = snd_tea575x_exclusive_release, + .ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops tea575x_ioctl_ops = { + .vidioc_querycap = vidioc_querycap, + .vidioc_g_tuner = vidioc_g_tuner, + .vidioc_s_tuner = vidioc_s_tuner, + .vidioc_g_audio = vidioc_g_audio, + .vidioc_s_audio = vidioc_s_audio, + .vidioc_g_input = vidioc_g_input, + .vidioc_s_input = vidioc_s_input, + .vidioc_g_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_queryctrl = vidioc_queryctrl, + .vidioc_g_ctrl = vidioc_g_ctrl, + .vidioc_s_ctrl = vidioc_s_ctrl, +}; + +static struct video_device tea575x_radio = { + .name = "tea575x-tuner", + .fops = &tea575x_fops, + .ioctl_ops = &tea575x_ioctl_ops, + .release = video_device_release, +}; /* * initialize all the tea575x chips @@ -217,51 +306,56 @@ void snd_tea575x_init(struct snd_tea575x void snd_tea575x_init(struct snd_tea575x *tea) #endif { + int retval; unsigned int val; + struct video_device *tea575x_radio_inst; val = tea->ops->read(tea); if (val == 0x1ffffff || val == 0) { - snd_printk(KERN_ERR "Cannot find TEA575x chip\n"); + snd_printk(KERN_ERR "tea575x-tuner: Cannot find TEA575x chip\n"); return; } - memset(&tea->vd, 0, sizeof(tea->vd)); - strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio"); - tea->vd.release = snd_tea575x_release; - video_set_drvdata(&tea->vd, tea); - tea->vd.fops = &tea->fops; tea->in_use = 0; - tea->fops.owner = tea->card->module; - tea->fops.open = snd_tea575x_exclusive_open; - tea->fops.release = snd_tea575x_exclusive_release; - tea->fops.ioctl = snd_tea575x_ioctl; - if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) { - snd_printk(KERN_ERR "unable to register tea575x tuner\n"); - return; - } - tea->vd_registered = 1; - tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; tea->freq = 90500 * 16; /* 90.5Mhz default */ + tea575x_radio_inst = video_device_alloc(); + if (tea575x_radio_inst == NULL) { + printk(KERN_ERR "tea575x-tuner: not enough memory\n"); + return; + } + + memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio)); + + strcpy(tea575x_radio.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio"); + + video_set_drvdata(tea575x_radio_inst, tea); + + retval = video_register_device(tea575x_radio_inst, VFL_TYPE_RADIO, radio_nr); + if (retval) { + printk(KERN_ERR "tea575x-tuner: can't register video device!\n"); + kfree (tea575x_radio_inst); + return; + } + snd_tea575x_set_freq(tea); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17) /* mute on init */ - if (tea->ops->mute) + if (tea->ops->mute) { tea->ops->mute(tea, 1); -#endif -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) -void snd_tea575x_exit(tea575x_t *tea) -#else + tea->mute = 1; + } +#endif + tea->vd = tea575x_radio_inst; +} + void snd_tea575x_exit(struct snd_tea575x *tea) -#endif -{ - if (tea->vd_registered) { - video_unregister_device(&tea->vd); - tea->vd_registered = 0; +{ + if (tea->vd) { + video_unregister_device(tea->vd); + tea->vd = NULL; } } --- Patch is available at: http://linuxtv.org/hg/v4l-dvb/rev/378d905783b1c63ce9e615821eb5c010ab21ded4 _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits