[alsa-devel] [PATCH 0/2] tea575x: Move from sound to media
Hello, TEA575x is neither a sound device nor an i2c device. Let's finally move it from sound/i2c/other to drivers/media/radio.
Tested with snd-es1968, snd-fm801 and radio-sf16fmr2.
Move include/sound/tea575x-tuner.h to include/media/tea575x.h and update files that include it.
Signed-off-by: Ondrej Zary linux@rainbow-software.org --- drivers/media/radio/radio-maxiradio.c | 2 +- drivers/media/radio/radio-sf16fmr2.c | 2 +- drivers/media/radio/radio-shark.c | 2 +- include/media/tea575x.h | 79 +++++++++++++++++++++++++++++++++ include/sound/tea575x-tuner.h | 79 --------------------------------- sound/i2c/other/tea575x-tuner.c | 2 +- sound/pci/es1968.c | 2 +- sound/pci/fm801.c | 2 +- 8 files changed, 85 insertions(+), 85 deletions(-) create mode 100644 include/media/tea575x.h delete mode 100644 include/sound/tea575x-tuner.h
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 1d1c9e1..5236035 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -42,7 +42,7 @@ #include <linux/videodev2.h> #include <linux/io.h> #include <linux/slab.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-fh.h> diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 9c09904..f1e3714 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -14,7 +14,7 @@ #include <linux/io.h> /* outb, outb_p */ #include <linux/isa.h> #include <linux/pnp.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h>
MODULE_AUTHOR("Ondrej Zary"); MODULE_DESCRIPTION("MediaForte SF16-FMR2 and SF16-FMD2 FM radio card driver"); diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 8fa18ab..b914772 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -33,7 +33,7 @@ #include <linux/usb.h> #include <linux/workqueue.h> #include <media/v4l2-device.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h>
#if defined(CONFIG_LEDS_CLASS) || \ (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) diff --git a/include/media/tea575x.h b/include/media/tea575x.h new file mode 100644 index 0000000..2d4fa59 --- /dev/null +++ b/include/media/tea575x.h @@ -0,0 +1,79 @@ +#ifndef __SOUND_TEA575X_TUNER_H +#define __SOUND_TEA575X_TUNER_H + +/* + * ALSA driver for TEA5757/5759 Philips AM/FM tuner chips + * + * Copyright (c) 2004 Jaroslav Kysela perex@perex.cz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/videodev2.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-dev.h> +#include <media/v4l2-device.h> + +#define TEA575X_FMIF 10700 +#define TEA575X_AMIF 450 + +#define TEA575X_DATA (1 << 0) +#define TEA575X_CLK (1 << 1) +#define TEA575X_WREN (1 << 2) +#define TEA575X_MOST (1 << 3) + +struct snd_tea575x; + +struct snd_tea575x_ops { + /* Drivers using snd_tea575x must either define read_ and write_val */ + void (*write_val)(struct snd_tea575x *tea, u32 val); + u32 (*read_val)(struct snd_tea575x *tea); + /* Or define the 3 pin functions */ + void (*set_pins)(struct snd_tea575x *tea, u8 pins); + u8 (*get_pins)(struct snd_tea575x *tea); + void (*set_direction)(struct snd_tea575x *tea, bool output); +}; + +struct snd_tea575x { + struct v4l2_device *v4l2_dev; + struct v4l2_file_operations fops; + struct video_device vd; /* video device */ + int radio_nr; /* radio_nr */ + bool tea5759; /* 5759 chip is present */ + bool has_am; /* Device can tune to AM freqs */ + bool cannot_read_data; /* Device cannot read the data pin */ + bool cannot_mute; /* Device cannot mute */ + bool mute; /* Device is muted? */ + bool stereo; /* receiving stereo */ + bool tuned; /* tuned to a station */ + unsigned int val; /* hw value */ + u32 band; /* 0: FM, 1: FM-Japan, 2: AM */ + u32 freq; /* frequency */ + struct mutex mutex; + struct snd_tea575x_ops *ops; + void *private_data; + u8 card[32]; + u8 bus_info[32]; + struct v4l2_ctrl_handler ctrl_handler; + int (*ext_init)(struct snd_tea575x *tea); +}; + +int snd_tea575x_hw_init(struct snd_tea575x *tea); +int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); +void snd_tea575x_exit(struct snd_tea575x *tea); +void snd_tea575x_set_freq(struct snd_tea575x *tea); + +#endif /* __SOUND_TEA575X_TUNER_H */ diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h deleted file mode 100644 index 2d4fa59..0000000 --- a/include/sound/tea575x-tuner.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef __SOUND_TEA575X_TUNER_H -#define __SOUND_TEA575X_TUNER_H - -/* - * ALSA driver for TEA5757/5759 Philips AM/FM tuner chips - * - * Copyright (c) 2004 Jaroslav Kysela perex@perex.cz - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/videodev2.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-device.h> - -#define TEA575X_FMIF 10700 -#define TEA575X_AMIF 450 - -#define TEA575X_DATA (1 << 0) -#define TEA575X_CLK (1 << 1) -#define TEA575X_WREN (1 << 2) -#define TEA575X_MOST (1 << 3) - -struct snd_tea575x; - -struct snd_tea575x_ops { - /* Drivers using snd_tea575x must either define read_ and write_val */ - void (*write_val)(struct snd_tea575x *tea, u32 val); - u32 (*read_val)(struct snd_tea575x *tea); - /* Or define the 3 pin functions */ - void (*set_pins)(struct snd_tea575x *tea, u8 pins); - u8 (*get_pins)(struct snd_tea575x *tea); - void (*set_direction)(struct snd_tea575x *tea, bool output); -}; - -struct snd_tea575x { - struct v4l2_device *v4l2_dev; - struct v4l2_file_operations fops; - struct video_device vd; /* video device */ - int radio_nr; /* radio_nr */ - bool tea5759; /* 5759 chip is present */ - bool has_am; /* Device can tune to AM freqs */ - bool cannot_read_data; /* Device cannot read the data pin */ - bool cannot_mute; /* Device cannot mute */ - bool mute; /* Device is muted? */ - bool stereo; /* receiving stereo */ - bool tuned; /* tuned to a station */ - unsigned int val; /* hw value */ - u32 band; /* 0: FM, 1: FM-Japan, 2: AM */ - u32 freq; /* frequency */ - struct mutex mutex; - struct snd_tea575x_ops *ops; - void *private_data; - u8 card[32]; - u8 bus_info[32]; - struct v4l2_ctrl_handler ctrl_handler; - int (*ext_init)(struct snd_tea575x *tea); -}; - -int snd_tea575x_hw_init(struct snd_tea575x *tea); -int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); -void snd_tea575x_exit(struct snd_tea575x *tea); -void snd_tea575x_set_freq(struct snd_tea575x *tea); - -#endif /* __SOUND_TEA575X_TUNER_H */ diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 46ec4dff..cef0698 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -31,7 +31,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h>
MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz"); MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5e2ec96..b0e3d92 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -113,7 +113,7 @@ #include <sound/initval.h>
#ifdef CONFIG_SND_ES1968_RADIO -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #endif
#define CARD_NAME "ESS Maestro1/2" diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 706c5b6..45bc8a9 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -37,7 +37,7 @@ #include <asm/io.h>
#ifdef CONFIG_SND_FM801_TEA575X_BOOL -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #endif
MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz");
Move tea575x from sound/i2c/other to drivers/media/radio Includes Kconfig changes by Hans Verkuil.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Signed-off-by: Ondrej Zary linux@rainbow-software.org --- drivers/media/radio/Kconfig | 12 +- drivers/media/radio/Makefile | 1 + drivers/media/radio/tea575x.c | 584 +++++++++++++++++++++++++++++++++++++++ sound/i2c/other/Makefile | 2 - sound/i2c/other/tea575x-tuner.c | 584 --------------------------------------- sound/pci/Kconfig | 9 +- 6 files changed, 598 insertions(+), 594 deletions(-) create mode 100644 drivers/media/radio/tea575x.c delete mode 100644 sound/i2c/other/tea575x-tuner.c
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index d529ba7..39882dd 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -12,6 +12,9 @@ menuconfig RADIO_ADAPTERS
if RADIO_ADAPTERS && VIDEO_V4L2
+config RADIO_TEA575X + tristate + config RADIO_SI470X bool "Silicon Labs Si470x FM Radio Receiver support" depends on VIDEO_V4L2 @@ -61,7 +64,8 @@ config USB_DSBR
config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio" - depends on VIDEO_V4L2 && PCI && SND + depends on VIDEO_V4L2 && PCI + select RADIO_TEA575X ---help--- Choose Y here if you have this radio card. This card may also be found as Gemtek PCI FM. @@ -76,7 +80,8 @@ config RADIO_MAXIRADIO
config RADIO_SHARK tristate "Griffin radioSHARK USB radio receiver" - depends on USB && SND + depends on USB + select RADIO_TEA575X ---help--- Choose Y here if you have this radio receiver.
@@ -393,7 +398,8 @@ config RADIO_SF16FMI
config RADIO_SF16FMR2 tristate "SF16-FMR2/SF16-FMD2 Radio" - depends on ISA && VIDEO_V4L2 && SND + depends on ISA && VIDEO_V4L2 + select RADIO_TEA575X ---help--- Choose Y here if you have one of these FM radio cards.
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 0dcdb32..3b64560 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_RADIO_TEF6862) += tef6862.o obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o obj-$(CONFIG_RADIO_WL128X) += wl128x/ +obj-$(CONFIG_RADIO_TEA575X) += tea575x.o
shark2-objs := radio-shark2.o radio-tea5777.o
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c new file mode 100644 index 0000000..cef0698 --- /dev/null +++ b/drivers/media/radio/tea575x.c @@ -0,0 +1,584 @@ +/* + * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips + * + * Copyright (c) 2004 Jaroslav Kysela perex@perex.cz + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <asm/io.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <media/v4l2-device.h> +#include <media/v4l2-dev.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-event.h> +#include <media/tea575x.h> + +MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz"); +MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); +MODULE_LICENSE("GPL"); + +/* + * definitions + */ + +#define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ +#define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ +#define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ +#define TEA575X_BIT_BAND_MASK (3<<20) +#define TEA575X_BIT_BAND_FM (0<<20) +#define TEA575X_BIT_BAND_MW (1<<20) +#define TEA575X_BIT_BAND_LW (2<<20) +#define TEA575X_BIT_BAND_SW (3<<20) +#define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ +#define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ +#define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ +#define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ +#define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ +#define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ +#define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ +#define TEA575X_BIT_DUMMY (1<<15) /* buffer */ +#define TEA575X_BIT_FREQ_MASK 0x7fff + +enum { BAND_FM, BAND_FM_JAPAN, BAND_AM }; + +static const struct v4l2_frequency_band bands[] = { + { + .type = V4L2_TUNER_RADIO, + .index = 0, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 87500 * 16, + .rangehigh = 108000 * 16, + .modulation = V4L2_BAND_MODULATION_FM, + }, + { + .type = V4L2_TUNER_RADIO, + .index = 0, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 76000 * 16, + .rangehigh = 91000 * 16, + .modulation = V4L2_BAND_MODULATION_FM, + }, + { + .type = V4L2_TUNER_RADIO, + .index = 1, + .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, + .rangelow = 530 * 16, + .rangehigh = 1710 * 16, + .modulation = V4L2_BAND_MODULATION_AM, + }, +}; + +/* + * lowlevel part + */ + +static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) +{ + u16 l; + u8 data; + + if (tea->ops->write_val) + return tea->ops->write_val(tea, val); + + tea->ops->set_direction(tea, 1); + udelay(16); + + for (l = 25; l > 0; l--) { + data = (val >> 24) & TEA575X_DATA; + val <<= 1; /* shift data */ + tea->ops->set_pins(tea, data | TEA575X_WREN); + udelay(2); + tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); + udelay(2); + tea->ops->set_pins(tea, data | TEA575X_WREN); + udelay(2); + } + + if (!tea->mute) + tea->ops->set_pins(tea, 0); +} + +static u32 snd_tea575x_read(struct snd_tea575x *tea) +{ + u16 l, rdata; + u32 data = 0; + + if (tea->ops->read_val) + return tea->ops->read_val(tea); + + tea->ops->set_direction(tea, 0); + tea->ops->set_pins(tea, 0); + udelay(16); + + for (l = 24; l--;) { + tea->ops->set_pins(tea, TEA575X_CLK); + udelay(2); + if (!l) + tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; + tea->ops->set_pins(tea, 0); + udelay(2); + data <<= 1; /* shift data */ + rdata = tea->ops->get_pins(tea); + if (!l) + tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; + if (rdata & TEA575X_DATA) + data++; + udelay(2); + } + + if (tea->mute) + tea->ops->set_pins(tea, TEA575X_WREN); + + return data; +} + +static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) +{ + u32 freq = val & TEA575X_BIT_FREQ_MASK; + + if (freq == 0) + return freq; + + switch (tea->band) { + case BAND_FM: + /* freq *= 12.5 */ + freq *= 125; + freq /= 10; + /* crystal fixup */ + freq -= TEA575X_FMIF; + break; + case BAND_FM_JAPAN: + /* freq *= 12.5 */ + freq *= 125; + freq /= 10; + /* crystal fixup */ + freq += TEA575X_FMIF; + break; + case BAND_AM: + /* crystal fixup */ + freq -= TEA575X_AMIF; + break; + } + + return clamp(freq * 16, bands[tea->band].rangelow, + bands[tea->band].rangehigh); /* from kHz */ +} + +static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) +{ + return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea)); +} + +void snd_tea575x_set_freq(struct snd_tea575x *tea) +{ + u32 freq = tea->freq / 16; /* to kHz */ + u32 band = 0; + + switch (tea->band) { + case BAND_FM: + band = TEA575X_BIT_BAND_FM; + /* crystal fixup */ + freq += TEA575X_FMIF; + /* freq /= 12.5 */ + freq *= 10; + freq /= 125; + break; + case BAND_FM_JAPAN: + band = TEA575X_BIT_BAND_FM; + /* crystal fixup */ + freq -= TEA575X_FMIF; + /* freq /= 12.5 */ + freq *= 10; + freq /= 125; + break; + case BAND_AM: + band = TEA575X_BIT_BAND_MW; + /* crystal fixup */ + freq += TEA575X_AMIF; + break; + } + + tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK); + tea->val |= band; + tea->val |= freq & TEA575X_BIT_FREQ_MASK; + snd_tea575x_write(tea, tea->val); + tea->freq = snd_tea575x_val_to_freq(tea, tea->val); +} + +/* + * Linux Video interface + */ + +static int vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *v) +{ + struct snd_tea575x *tea = video_drvdata(file); + + strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); + strlcpy(v->card, tea->card, sizeof(v->card)); + strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); + strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + if (!tea->cannot_read_data) + v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int vidioc_enum_freq_bands(struct file *file, void *priv, + struct v4l2_frequency_band *band) +{ + struct snd_tea575x *tea = video_drvdata(file); + int index; + + if (band->tuner != 0) + return -EINVAL; + + switch (band->index) { + case 0: + if (tea->tea5759) + index = BAND_FM_JAPAN; + else + index = BAND_FM; + break; + case 1: + if (tea->has_am) { + index = BAND_AM; + break; + } + /* Fall through */ + default: + return -EINVAL; + } + + *band = bands[index]; + if (!tea->cannot_read_data) + band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; + + return 0; +} + +static int vidioc_g_tuner(struct file *file, void *priv, + struct v4l2_tuner *v) +{ + struct snd_tea575x *tea = video_drvdata(file); + struct v4l2_frequency_band band_fm = { 0, }; + + if (v->index > 0) + return -EINVAL; + + snd_tea575x_read(tea); + vidioc_enum_freq_bands(file, priv, &band_fm); + + memset(v, 0, sizeof(*v)); + strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); + v->type = V4L2_TUNER_RADIO; + v->capability = band_fm.capability; + v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow; + v->rangehigh = band_fm.rangehigh; + v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; + v->audmode = (tea->val & TEA575X_BIT_MONO) ? + V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; + v->signal = tea->tuned ? 0xffff : 0; + return 0; +} + +static int vidioc_s_tuner(struct file *file, void *priv, + const struct v4l2_tuner *v) +{ + struct snd_tea575x *tea = video_drvdata(file); + u32 orig_val = tea->val; + + if (v->index) + return -EINVAL; + tea->val &= ~TEA575X_BIT_MONO; + if (v->audmode == V4L2_TUNER_MODE_MONO) + tea->val |= TEA575X_BIT_MONO; + /* Only apply changes if currently tuning FM */ + if (tea->band != BAND_AM && tea->val != orig_val) + snd_tea575x_set_freq(tea); + + return 0; +} + +static int vidioc_g_frequency(struct file *file, void *priv, + struct v4l2_frequency *f) +{ + struct snd_tea575x *tea = video_drvdata(file); + + if (f->tuner != 0) + return -EINVAL; + f->type = V4L2_TUNER_RADIO; + f->frequency = tea->freq; + return 0; +} + +static int vidioc_s_frequency(struct file *file, void *priv, + const struct v4l2_frequency *f) +{ + struct snd_tea575x *tea = video_drvdata(file); + + if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) + return -EINVAL; + + if (tea->has_am && f->frequency < (20000 * 16)) + tea->band = BAND_AM; + else if (tea->tea5759) + tea->band = BAND_FM_JAPAN; + else + tea->band = BAND_FM; + + tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow, + bands[tea->band].rangehigh); + snd_tea575x_set_freq(tea); + return 0; +} + +static int vidioc_s_hw_freq_seek(struct file *file, void *fh, + const struct v4l2_hw_freq_seek *a) +{ + struct snd_tea575x *tea = video_drvdata(file); + unsigned long timeout; + int i, spacing; + + if (tea->cannot_read_data) + return -ENOTTY; + if (a->tuner || a->wrap_around) + return -EINVAL; + + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + + if (a->rangelow || a->rangehigh) { + for (i = 0; i < ARRAY_SIZE(bands); i++) { + if ((i == BAND_FM && tea->tea5759) || + (i == BAND_FM_JAPAN && !tea->tea5759) || + (i == BAND_AM && !tea->has_am)) + continue; + if (bands[i].rangelow == a->rangelow && + bands[i].rangehigh == a->rangehigh) + break; + } + if (i == ARRAY_SIZE(bands)) + return -EINVAL; /* No matching band found */ + if (i != tea->band) { + tea->band = i; + tea->freq = clamp(tea->freq, bands[i].rangelow, + bands[i].rangehigh); + snd_tea575x_set_freq(tea); + } + } + + spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */ + + /* clear the frequency, HW will fill it in */ + tea->val &= ~TEA575X_BIT_FREQ_MASK; + tea->val |= TEA575X_BIT_SEARCH; + if (a->seek_upward) + tea->val |= TEA575X_BIT_UPDOWN; + else + tea->val &= ~TEA575X_BIT_UPDOWN; + snd_tea575x_write(tea, tea->val); + timeout = jiffies + msecs_to_jiffies(10000); + for (;;) { + if (time_after(jiffies, timeout)) + break; + if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { + /* some signal arrived, stop search */ + tea->val &= ~TEA575X_BIT_SEARCH; + snd_tea575x_set_freq(tea); + return -ERESTARTSYS; + } + if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) { + u32 freq; + + /* Found a frequency, wait until it can be read */ + for (i = 0; i < 100; i++) { + msleep(10); + freq = snd_tea575x_get_freq(tea); + if (freq) /* available */ + break; + } + if (freq == 0) /* shouldn't happen */ + break; + /* + * if we moved by less than the spacing, or in the + * wrong direction, continue seeking + */ + if (abs(tea->freq - freq) < 16 * spacing || + (a->seek_upward && freq < tea->freq) || + (!a->seek_upward && freq > tea->freq)) { + snd_tea575x_write(tea, tea->val); + continue; + } + tea->freq = freq; + tea->val &= ~TEA575X_BIT_SEARCH; + return 0; + } + } + tea->val &= ~TEA575X_BIT_SEARCH; + snd_tea575x_set_freq(tea); + return -ENODATA; +} + +static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + tea->mute = ctrl->val; + snd_tea575x_set_freq(tea); + return 0; + } + + return -EINVAL; +} + +static const struct v4l2_file_operations tea575x_fops = { + .unlocked_ioctl = video_ioctl2, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, +}; + +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_frequency = vidioc_g_frequency, + .vidioc_s_frequency = vidioc_s_frequency, + .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, + .vidioc_enum_freq_bands = vidioc_enum_freq_bands, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct video_device tea575x_radio = { + .ioctl_ops = &tea575x_ioctl_ops, + .release = video_device_release_empty, +}; + +static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { + .s_ctrl = tea575x_s_ctrl, +}; + + +int snd_tea575x_hw_init(struct snd_tea575x *tea) +{ + tea->mute = true; + + /* Not all devices can or know how to read the data back. + Such devices can set cannot_read_data to true. */ + if (!tea->cannot_read_data) { + snd_tea575x_write(tea, 0x55AA); + if (snd_tea575x_read(tea) != 0x55AA) + return -ENODEV; + } + + tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28; + tea->freq = 90500 * 16; /* 90.5Mhz default */ + snd_tea575x_set_freq(tea); + + return 0; +} +EXPORT_SYMBOL(snd_tea575x_hw_init); + +int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) +{ + int retval = snd_tea575x_hw_init(tea); + + if (retval) + return retval; + + tea->vd = tea575x_radio; + video_set_drvdata(&tea->vd, tea); + mutex_init(&tea->mutex); + strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); + tea->vd.lock = &tea->mutex; + tea->vd.v4l2_dev = tea->v4l2_dev; + tea->fops = tea575x_fops; + tea->fops.owner = owner; + tea->vd.fops = &tea->fops; + set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); + /* disable hw_freq_seek if we can't use it */ + if (tea->cannot_read_data) + v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK); + + if (!tea->cannot_mute) { + tea->vd.ctrl_handler = &tea->ctrl_handler; + v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); + v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + retval = tea->ctrl_handler.error; + if (retval) { + v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); + v4l2_ctrl_handler_free(&tea->ctrl_handler); + return retval; + } + + if (tea->ext_init) { + retval = tea->ext_init(tea); + if (retval) { + v4l2_ctrl_handler_free(&tea->ctrl_handler); + return retval; + } + } + + v4l2_ctrl_handler_setup(&tea->ctrl_handler); + } + + retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); + if (retval) { + v4l2_err(tea->v4l2_dev, "can't register video device!\n"); + v4l2_ctrl_handler_free(tea->vd.ctrl_handler); + return retval; + } + + return 0; +} + +void snd_tea575x_exit(struct snd_tea575x *tea) +{ + video_unregister_device(&tea->vd); + v4l2_ctrl_handler_free(tea->vd.ctrl_handler); +} + +static int __init alsa_tea575x_module_init(void) +{ + return 0; +} + +static void __exit alsa_tea575x_module_exit(void) +{ +} + +module_init(alsa_tea575x_module_init) +module_exit(alsa_tea575x_module_exit) + +EXPORT_SYMBOL(snd_tea575x_init); +EXPORT_SYMBOL(snd_tea575x_exit); +EXPORT_SYMBOL(snd_tea575x_set_freq); diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index c95d8f1..5526b03 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile @@ -8,10 +8,8 @@ snd-ak4117-objs := ak4117.o snd-ak4113-objs := ak4113.o snd-ak4xxx-adda-objs := ak4xxx-adda.o snd-pt2258-objs := pt2258.o -snd-tea575x-tuner-objs := tea575x-tuner.o
# Module Dependency obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o -obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c deleted file mode 100644 index cef0698..0000000 --- a/sound/i2c/other/tea575x-tuner.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips - * - * Copyright (c) 2004 Jaroslav Kysela perex@perex.cz - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <asm/io.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <media/v4l2-device.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-event.h> -#include <media/tea575x.h> - -MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz"); -MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); -MODULE_LICENSE("GPL"); - -/* - * definitions - */ - -#define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ -#define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ -#define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ -#define TEA575X_BIT_BAND_MASK (3<<20) -#define TEA575X_BIT_BAND_FM (0<<20) -#define TEA575X_BIT_BAND_MW (1<<20) -#define TEA575X_BIT_BAND_LW (2<<20) -#define TEA575X_BIT_BAND_SW (3<<20) -#define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ -#define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ -#define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ -#define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ -#define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ -#define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ -#define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ -#define TEA575X_BIT_DUMMY (1<<15) /* buffer */ -#define TEA575X_BIT_FREQ_MASK 0x7fff - -enum { BAND_FM, BAND_FM_JAPAN, BAND_AM }; - -static const struct v4l2_frequency_band bands[] = { - { - .type = V4L2_TUNER_RADIO, - .index = 0, - .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 87500 * 16, - .rangehigh = 108000 * 16, - .modulation = V4L2_BAND_MODULATION_FM, - }, - { - .type = V4L2_TUNER_RADIO, - .index = 0, - .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | - V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 76000 * 16, - .rangehigh = 91000 * 16, - .modulation = V4L2_BAND_MODULATION_FM, - }, - { - .type = V4L2_TUNER_RADIO, - .index = 1, - .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS, - .rangelow = 530 * 16, - .rangehigh = 1710 * 16, - .modulation = V4L2_BAND_MODULATION_AM, - }, -}; - -/* - * lowlevel part - */ - -static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) -{ - u16 l; - u8 data; - - if (tea->ops->write_val) - return tea->ops->write_val(tea, val); - - tea->ops->set_direction(tea, 1); - udelay(16); - - for (l = 25; l > 0; l--) { - data = (val >> 24) & TEA575X_DATA; - val <<= 1; /* shift data */ - tea->ops->set_pins(tea, data | TEA575X_WREN); - udelay(2); - tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK); - udelay(2); - tea->ops->set_pins(tea, data | TEA575X_WREN); - udelay(2); - } - - if (!tea->mute) - tea->ops->set_pins(tea, 0); -} - -static u32 snd_tea575x_read(struct snd_tea575x *tea) -{ - u16 l, rdata; - u32 data = 0; - - if (tea->ops->read_val) - return tea->ops->read_val(tea); - - tea->ops->set_direction(tea, 0); - tea->ops->set_pins(tea, 0); - udelay(16); - - for (l = 24; l--;) { - tea->ops->set_pins(tea, TEA575X_CLK); - udelay(2); - if (!l) - tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1; - tea->ops->set_pins(tea, 0); - udelay(2); - data <<= 1; /* shift data */ - rdata = tea->ops->get_pins(tea); - if (!l) - tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1; - if (rdata & TEA575X_DATA) - data++; - udelay(2); - } - - if (tea->mute) - tea->ops->set_pins(tea, TEA575X_WREN); - - return data; -} - -static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) -{ - u32 freq = val & TEA575X_BIT_FREQ_MASK; - - if (freq == 0) - return freq; - - switch (tea->band) { - case BAND_FM: - /* freq *= 12.5 */ - freq *= 125; - freq /= 10; - /* crystal fixup */ - freq -= TEA575X_FMIF; - break; - case BAND_FM_JAPAN: - /* freq *= 12.5 */ - freq *= 125; - freq /= 10; - /* crystal fixup */ - freq += TEA575X_FMIF; - break; - case BAND_AM: - /* crystal fixup */ - freq -= TEA575X_AMIF; - break; - } - - return clamp(freq * 16, bands[tea->band].rangelow, - bands[tea->band].rangehigh); /* from kHz */ -} - -static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) -{ - return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea)); -} - -void snd_tea575x_set_freq(struct snd_tea575x *tea) -{ - u32 freq = tea->freq / 16; /* to kHz */ - u32 band = 0; - - switch (tea->band) { - case BAND_FM: - band = TEA575X_BIT_BAND_FM; - /* crystal fixup */ - freq += TEA575X_FMIF; - /* freq /= 12.5 */ - freq *= 10; - freq /= 125; - break; - case BAND_FM_JAPAN: - band = TEA575X_BIT_BAND_FM; - /* crystal fixup */ - freq -= TEA575X_FMIF; - /* freq /= 12.5 */ - freq *= 10; - freq /= 125; - break; - case BAND_AM: - band = TEA575X_BIT_BAND_MW; - /* crystal fixup */ - freq += TEA575X_AMIF; - break; - } - - tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK); - tea->val |= band; - tea->val |= freq & TEA575X_BIT_FREQ_MASK; - snd_tea575x_write(tea, tea->val); - tea->freq = snd_tea575x_val_to_freq(tea, tea->val); -} - -/* - * Linux Video interface - */ - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - - strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); - strlcpy(v->card, tea->card, sizeof(v->card)); - strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); - strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); - v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; - if (!tea->cannot_read_data) - v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; - v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int vidioc_enum_freq_bands(struct file *file, void *priv, - struct v4l2_frequency_band *band) -{ - struct snd_tea575x *tea = video_drvdata(file); - int index; - - if (band->tuner != 0) - return -EINVAL; - - switch (band->index) { - case 0: - if (tea->tea5759) - index = BAND_FM_JAPAN; - else - index = BAND_FM; - break; - case 1: - if (tea->has_am) { - index = BAND_AM; - break; - } - /* Fall through */ - default: - return -EINVAL; - } - - *band = bands[index]; - if (!tea->cannot_read_data) - band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED; - - return 0; -} - -static int vidioc_g_tuner(struct file *file, void *priv, - struct v4l2_tuner *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - struct v4l2_frequency_band band_fm = { 0, }; - - if (v->index > 0) - return -EINVAL; - - snd_tea575x_read(tea); - vidioc_enum_freq_bands(file, priv, &band_fm); - - memset(v, 0, sizeof(*v)); - strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); - v->type = V4L2_TUNER_RADIO; - v->capability = band_fm.capability; - v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow; - v->rangehigh = band_fm.rangehigh; - v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; - v->audmode = (tea->val & TEA575X_BIT_MONO) ? - V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO; - v->signal = tea->tuned ? 0xffff : 0; - return 0; -} - -static int vidioc_s_tuner(struct file *file, void *priv, - const struct v4l2_tuner *v) -{ - struct snd_tea575x *tea = video_drvdata(file); - u32 orig_val = tea->val; - - if (v->index) - return -EINVAL; - tea->val &= ~TEA575X_BIT_MONO; - if (v->audmode == V4L2_TUNER_MODE_MONO) - tea->val |= TEA575X_BIT_MONO; - /* Only apply changes if currently tuning FM */ - if (tea->band != BAND_AM && tea->val != orig_val) - snd_tea575x_set_freq(tea); - - return 0; -} - -static int vidioc_g_frequency(struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (f->tuner != 0) - return -EINVAL; - f->type = V4L2_TUNER_RADIO; - f->frequency = tea->freq; - return 0; -} - -static int vidioc_s_frequency(struct file *file, void *priv, - const struct v4l2_frequency *f) -{ - struct snd_tea575x *tea = video_drvdata(file); - - if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) - return -EINVAL; - - if (tea->has_am && f->frequency < (20000 * 16)) - tea->band = BAND_AM; - else if (tea->tea5759) - tea->band = BAND_FM_JAPAN; - else - tea->band = BAND_FM; - - tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow, - bands[tea->band].rangehigh); - snd_tea575x_set_freq(tea); - return 0; -} - -static int vidioc_s_hw_freq_seek(struct file *file, void *fh, - const struct v4l2_hw_freq_seek *a) -{ - struct snd_tea575x *tea = video_drvdata(file); - unsigned long timeout; - int i, spacing; - - if (tea->cannot_read_data) - return -ENOTTY; - if (a->tuner || a->wrap_around) - return -EINVAL; - - if (file->f_flags & O_NONBLOCK) - return -EWOULDBLOCK; - - if (a->rangelow || a->rangehigh) { - for (i = 0; i < ARRAY_SIZE(bands); i++) { - if ((i == BAND_FM && tea->tea5759) || - (i == BAND_FM_JAPAN && !tea->tea5759) || - (i == BAND_AM && !tea->has_am)) - continue; - if (bands[i].rangelow == a->rangelow && - bands[i].rangehigh == a->rangehigh) - break; - } - if (i == ARRAY_SIZE(bands)) - return -EINVAL; /* No matching band found */ - if (i != tea->band) { - tea->band = i; - tea->freq = clamp(tea->freq, bands[i].rangelow, - bands[i].rangehigh); - snd_tea575x_set_freq(tea); - } - } - - spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */ - - /* clear the frequency, HW will fill it in */ - tea->val &= ~TEA575X_BIT_FREQ_MASK; - tea->val |= TEA575X_BIT_SEARCH; - if (a->seek_upward) - tea->val |= TEA575X_BIT_UPDOWN; - else - tea->val &= ~TEA575X_BIT_UPDOWN; - snd_tea575x_write(tea, tea->val); - timeout = jiffies + msecs_to_jiffies(10000); - for (;;) { - if (time_after(jiffies, timeout)) - break; - if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { - /* some signal arrived, stop search */ - tea->val &= ~TEA575X_BIT_SEARCH; - snd_tea575x_set_freq(tea); - return -ERESTARTSYS; - } - if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) { - u32 freq; - - /* Found a frequency, wait until it can be read */ - for (i = 0; i < 100; i++) { - msleep(10); - freq = snd_tea575x_get_freq(tea); - if (freq) /* available */ - break; - } - if (freq == 0) /* shouldn't happen */ - break; - /* - * if we moved by less than the spacing, or in the - * wrong direction, continue seeking - */ - if (abs(tea->freq - freq) < 16 * spacing || - (a->seek_upward && freq < tea->freq) || - (!a->seek_upward && freq > tea->freq)) { - snd_tea575x_write(tea, tea->val); - continue; - } - tea->freq = freq; - tea->val &= ~TEA575X_BIT_SEARCH; - return 0; - } - } - tea->val &= ~TEA575X_BIT_SEARCH; - snd_tea575x_set_freq(tea); - return -ENODATA; -} - -static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - tea->mute = ctrl->val; - snd_tea575x_set_freq(tea); - return 0; - } - - return -EINVAL; -} - -static const struct v4l2_file_operations tea575x_fops = { - .unlocked_ioctl = video_ioctl2, - .open = v4l2_fh_open, - .release = v4l2_fh_release, - .poll = v4l2_ctrl_poll, -}; - -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_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek, - .vidioc_enum_freq_bands = vidioc_enum_freq_bands, - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct video_device tea575x_radio = { - .ioctl_ops = &tea575x_ioctl_ops, - .release = video_device_release_empty, -}; - -static const struct v4l2_ctrl_ops tea575x_ctrl_ops = { - .s_ctrl = tea575x_s_ctrl, -}; - - -int snd_tea575x_hw_init(struct snd_tea575x *tea) -{ - tea->mute = true; - - /* Not all devices can or know how to read the data back. - Such devices can set cannot_read_data to true. */ - if (!tea->cannot_read_data) { - snd_tea575x_write(tea, 0x55AA); - if (snd_tea575x_read(tea) != 0x55AA) - return -ENODEV; - } - - tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28; - tea->freq = 90500 * 16; /* 90.5Mhz default */ - snd_tea575x_set_freq(tea); - - return 0; -} -EXPORT_SYMBOL(snd_tea575x_hw_init); - -int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) -{ - int retval = snd_tea575x_hw_init(tea); - - if (retval) - return retval; - - tea->vd = tea575x_radio; - video_set_drvdata(&tea->vd, tea); - mutex_init(&tea->mutex); - strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); - tea->vd.lock = &tea->mutex; - tea->vd.v4l2_dev = tea->v4l2_dev; - tea->fops = tea575x_fops; - tea->fops.owner = owner; - tea->vd.fops = &tea->fops; - set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags); - /* disable hw_freq_seek if we can't use it */ - if (tea->cannot_read_data) - v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK); - - if (!tea->cannot_mute) { - tea->vd.ctrl_handler = &tea->ctrl_handler; - v4l2_ctrl_handler_init(&tea->ctrl_handler, 1); - v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, - V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); - retval = tea->ctrl_handler.error; - if (retval) { - v4l2_err(tea->v4l2_dev, "can't initialize controls\n"); - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } - - if (tea->ext_init) { - retval = tea->ext_init(tea); - if (retval) { - v4l2_ctrl_handler_free(&tea->ctrl_handler); - return retval; - } - } - - v4l2_ctrl_handler_setup(&tea->ctrl_handler); - } - - retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr); - if (retval) { - v4l2_err(tea->v4l2_dev, "can't register video device!\n"); - v4l2_ctrl_handler_free(tea->vd.ctrl_handler); - return retval; - } - - return 0; -} - -void snd_tea575x_exit(struct snd_tea575x *tea) -{ - video_unregister_device(&tea->vd); - v4l2_ctrl_handler_free(tea->vd.ctrl_handler); -} - -static int __init alsa_tea575x_module_init(void) -{ - return 0; -} - -static void __exit alsa_tea575x_module_exit(void) -{ -} - -module_init(alsa_tea575x_module_init) -module_exit(alsa_tea575x_module_exit) - -EXPORT_SYMBOL(snd_tea575x_init); -EXPORT_SYMBOL(snd_tea575x_exit); -EXPORT_SYMBOL(snd_tea575x_set_freq); diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index fe6fa93..9df80ef 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -1,10 +1,5 @@ # ALSA PCI drivers
-config SND_TEA575X - tristate - depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK - default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK - menuconfig SND_PCI bool "PCI sound devices" depends on PCI @@ -542,7 +537,9 @@ config SND_ES1968_INPUT config SND_ES1968_RADIO bool "Enable TEA5757 radio tuner support for es1968" depends on SND_ES1968 + depends on MEDIA_RADIO_SUPPORT depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968 + select RADIO_TEA575X help Say Y here to include support for TEA5757 radio tuner integrated on some MediaForte cards (e.g. SF64-PCE2). @@ -562,7 +559,9 @@ config SND_FM801 config SND_FM801_TEA575X_BOOL bool "ForteMedia FM801 + TEA5757 tuner" depends on SND_FM801 + depends on MEDIA_RADIO_SUPPORT depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801 + select RADIO_TEA575X help Say Y here to include support for soundcards based on the ForteMedia FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and
Hi Ondrej!
On 07/28/2013 10:01 PM, Ondrej Zary wrote:
Move tea575x from sound/i2c/other to drivers/media/radio Includes Kconfig changes by Hans Verkuil.
Signed-off-by: Hans Verkuil hans.verkuil@cisco.com Signed-off-by: Ondrej Zary linux@rainbow-software.org
Acked-by: Hans Verkuil hans.verkuil@cisco.com
If this can be acked by an alsa maintainer, then I can merge it into the media tree.
I really like these changes: the Kconfig part is simplified and it makes much more sense to have this driver in drivers/media.
Regards,
Hans
drivers/media/radio/Kconfig | 12 +- drivers/media/radio/Makefile | 1 + drivers/media/radio/tea575x.c | 584 +++++++++++++++++++++++++++++++++++++++ sound/i2c/other/Makefile | 2 - sound/i2c/other/tea575x-tuner.c | 584 --------------------------------------- sound/pci/Kconfig | 9 +- 6 files changed, 598 insertions(+), 594 deletions(-) create mode 100644 drivers/media/radio/tea575x.c delete mode 100644 sound/i2c/other/tea575x-tuner.c
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index d529ba7..39882dd 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -12,6 +12,9 @@ menuconfig RADIO_ADAPTERS
if RADIO_ADAPTERS && VIDEO_V4L2
+config RADIO_TEA575X
- tristate
config RADIO_SI470X bool "Silicon Labs Si470x FM Radio Receiver support" depends on VIDEO_V4L2 @@ -61,7 +64,8 @@ config USB_DSBR
config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio"
- depends on VIDEO_V4L2 && PCI && SND
- depends on VIDEO_V4L2 && PCI
- select RADIO_TEA575X ---help--- Choose Y here if you have this radio card. This card may also be found as Gemtek PCI FM.
@@ -76,7 +80,8 @@ config RADIO_MAXIRADIO
config RADIO_SHARK tristate "Griffin radioSHARK USB radio receiver"
- depends on USB && SND
- depends on USB
- select RADIO_TEA575X ---help--- Choose Y here if you have this radio receiver.
@@ -393,7 +398,8 @@ config RADIO_SF16FMI
config RADIO_SF16FMR2 tristate "SF16-FMR2/SF16-FMD2 Radio"
- depends on ISA && VIDEO_V4L2 && SND
- depends on ISA && VIDEO_V4L2
- select RADIO_TEA575X ---help--- Choose Y here if you have one of these FM radio cards.
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile index 0dcdb32..3b64560 100644 --- a/drivers/media/radio/Makefile +++ b/drivers/media/radio/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_RADIO_TEF6862) += tef6862.o obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o obj-$(CONFIG_RADIO_WL128X) += wl128x/ +obj-$(CONFIG_RADIO_TEA575X) += tea575x.o
shark2-objs := radio-shark2.o radio-tea5777.o
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c new file mode 100644 index 0000000..cef0698 --- /dev/null +++ b/drivers/media/radio/tea575x.c @@ -0,0 +1,584 @@ +/*
- ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
- Copyright (c) 2004 Jaroslav Kysela perex@perex.cz
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+#include <asm/io.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <media/v4l2-device.h> +#include <media/v4l2-dev.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-event.h> +#include <media/tea575x.h>
+MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz"); +MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); +MODULE_LICENSE("GPL");
+/*
- definitions
- */
+#define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ +#define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ +#define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ +#define TEA575X_BIT_BAND_MASK (3<<20) +#define TEA575X_BIT_BAND_FM (0<<20) +#define TEA575X_BIT_BAND_MW (1<<20) +#define TEA575X_BIT_BAND_LW (2<<20) +#define TEA575X_BIT_BAND_SW (3<<20) +#define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ +#define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ +#define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ +#define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ +#define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ +#define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ +#define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ +#define TEA575X_BIT_DUMMY (1<<15) /* buffer */ +#define TEA575X_BIT_FREQ_MASK 0x7fff
+enum { BAND_FM, BAND_FM_JAPAN, BAND_AM };
+static const struct v4l2_frequency_band bands[] = {
- {
.type = V4L2_TUNER_RADIO,
.index = 0,
.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 87500 * 16,
.rangehigh = 108000 * 16,
.modulation = V4L2_BAND_MODULATION_FM,
- },
- {
.type = V4L2_TUNER_RADIO,
.index = 0,
.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 76000 * 16,
.rangehigh = 91000 * 16,
.modulation = V4L2_BAND_MODULATION_FM,
- },
- {
.type = V4L2_TUNER_RADIO,
.index = 1,
.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 530 * 16,
.rangehigh = 1710 * 16,
.modulation = V4L2_BAND_MODULATION_AM,
- },
+};
+/*
- lowlevel part
- */
+static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) +{
- u16 l;
- u8 data;
- if (tea->ops->write_val)
return tea->ops->write_val(tea, val);
- tea->ops->set_direction(tea, 1);
- udelay(16);
- for (l = 25; l > 0; l--) {
data = (val >> 24) & TEA575X_DATA;
val <<= 1; /* shift data */
tea->ops->set_pins(tea, data | TEA575X_WREN);
udelay(2);
tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK);
udelay(2);
tea->ops->set_pins(tea, data | TEA575X_WREN);
udelay(2);
- }
- if (!tea->mute)
tea->ops->set_pins(tea, 0);
+}
+static u32 snd_tea575x_read(struct snd_tea575x *tea) +{
- u16 l, rdata;
- u32 data = 0;
- if (tea->ops->read_val)
return tea->ops->read_val(tea);
- tea->ops->set_direction(tea, 0);
- tea->ops->set_pins(tea, 0);
- udelay(16);
- for (l = 24; l--;) {
tea->ops->set_pins(tea, TEA575X_CLK);
udelay(2);
if (!l)
tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1;
tea->ops->set_pins(tea, 0);
udelay(2);
data <<= 1; /* shift data */
rdata = tea->ops->get_pins(tea);
if (!l)
tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1;
if (rdata & TEA575X_DATA)
data++;
udelay(2);
- }
- if (tea->mute)
tea->ops->set_pins(tea, TEA575X_WREN);
- return data;
+}
+static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) +{
- u32 freq = val & TEA575X_BIT_FREQ_MASK;
- if (freq == 0)
return freq;
- switch (tea->band) {
- case BAND_FM:
/* freq *= 12.5 */
freq *= 125;
freq /= 10;
/* crystal fixup */
freq -= TEA575X_FMIF;
break;
- case BAND_FM_JAPAN:
/* freq *= 12.5 */
freq *= 125;
freq /= 10;
/* crystal fixup */
freq += TEA575X_FMIF;
break;
- case BAND_AM:
/* crystal fixup */
freq -= TEA575X_AMIF;
break;
- }
- return clamp(freq * 16, bands[tea->band].rangelow,
bands[tea->band].rangehigh); /* from kHz */
+}
+static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) +{
- return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea));
+}
+void snd_tea575x_set_freq(struct snd_tea575x *tea) +{
- u32 freq = tea->freq / 16; /* to kHz */
- u32 band = 0;
- switch (tea->band) {
- case BAND_FM:
band = TEA575X_BIT_BAND_FM;
/* crystal fixup */
freq += TEA575X_FMIF;
/* freq /= 12.5 */
freq *= 10;
freq /= 125;
break;
- case BAND_FM_JAPAN:
band = TEA575X_BIT_BAND_FM;
/* crystal fixup */
freq -= TEA575X_FMIF;
/* freq /= 12.5 */
freq *= 10;
freq /= 125;
break;
- case BAND_AM:
band = TEA575X_BIT_BAND_MW;
/* crystal fixup */
freq += TEA575X_AMIF;
break;
- }
- tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK);
- tea->val |= band;
- tea->val |= freq & TEA575X_BIT_FREQ_MASK;
- snd_tea575x_write(tea, tea->val);
- tea->freq = snd_tea575x_val_to_freq(tea, tea->val);
+}
+/*
- Linux Video interface
- */
+static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
+{
- struct snd_tea575x *tea = video_drvdata(file);
- strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
- strlcpy(v->card, tea->card, sizeof(v->card));
- strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
- strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
- v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- if (!tea->cannot_read_data)
v->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
- v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
- return 0;
+}
+static int vidioc_enum_freq_bands(struct file *file, void *priv,
struct v4l2_frequency_band *band)
+{
- struct snd_tea575x *tea = video_drvdata(file);
- int index;
- if (band->tuner != 0)
return -EINVAL;
- switch (band->index) {
- case 0:
if (tea->tea5759)
index = BAND_FM_JAPAN;
else
index = BAND_FM;
break;
- case 1:
if (tea->has_am) {
index = BAND_AM;
break;
}
/* Fall through */
- default:
return -EINVAL;
- }
- *band = bands[index];
- if (!tea->cannot_read_data)
band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED;
- return 0;
+}
+static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
+{
- struct snd_tea575x *tea = video_drvdata(file);
- struct v4l2_frequency_band band_fm = { 0, };
- if (v->index > 0)
return -EINVAL;
- snd_tea575x_read(tea);
- vidioc_enum_freq_bands(file, priv, &band_fm);
- memset(v, 0, sizeof(*v));
- strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name));
- v->type = V4L2_TUNER_RADIO;
- v->capability = band_fm.capability;
- v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow;
- v->rangehigh = band_fm.rangehigh;
- v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
- v->audmode = (tea->val & TEA575X_BIT_MONO) ?
V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO;
- v->signal = tea->tuned ? 0xffff : 0;
- return 0;
+}
+static int vidioc_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *v)
+{
- struct snd_tea575x *tea = video_drvdata(file);
- u32 orig_val = tea->val;
- if (v->index)
return -EINVAL;
- tea->val &= ~TEA575X_BIT_MONO;
- if (v->audmode == V4L2_TUNER_MODE_MONO)
tea->val |= TEA575X_BIT_MONO;
- /* Only apply changes if currently tuning FM */
- if (tea->band != BAND_AM && tea->val != orig_val)
snd_tea575x_set_freq(tea);
- return 0;
+}
+static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
+{
- struct snd_tea575x *tea = video_drvdata(file);
- if (f->tuner != 0)
return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = tea->freq;
- return 0;
+}
+static int vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
+{
- struct snd_tea575x *tea = video_drvdata(file);
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
- if (tea->has_am && f->frequency < (20000 * 16))
tea->band = BAND_AM;
- else if (tea->tea5759)
tea->band = BAND_FM_JAPAN;
- else
tea->band = BAND_FM;
- tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow,
bands[tea->band].rangehigh);
- snd_tea575x_set_freq(tea);
- return 0;
+}
+static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
const struct v4l2_hw_freq_seek *a)
+{
- struct snd_tea575x *tea = video_drvdata(file);
- unsigned long timeout;
- int i, spacing;
- if (tea->cannot_read_data)
return -ENOTTY;
- if (a->tuner || a->wrap_around)
return -EINVAL;
- if (file->f_flags & O_NONBLOCK)
return -EWOULDBLOCK;
- if (a->rangelow || a->rangehigh) {
for (i = 0; i < ARRAY_SIZE(bands); i++) {
if ((i == BAND_FM && tea->tea5759) ||
(i == BAND_FM_JAPAN && !tea->tea5759) ||
(i == BAND_AM && !tea->has_am))
continue;
if (bands[i].rangelow == a->rangelow &&
bands[i].rangehigh == a->rangehigh)
break;
}
if (i == ARRAY_SIZE(bands))
return -EINVAL; /* No matching band found */
if (i != tea->band) {
tea->band = i;
tea->freq = clamp(tea->freq, bands[i].rangelow,
bands[i].rangehigh);
snd_tea575x_set_freq(tea);
}
- }
- spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */
- /* clear the frequency, HW will fill it in */
- tea->val &= ~TEA575X_BIT_FREQ_MASK;
- tea->val |= TEA575X_BIT_SEARCH;
- if (a->seek_upward)
tea->val |= TEA575X_BIT_UPDOWN;
- else
tea->val &= ~TEA575X_BIT_UPDOWN;
- snd_tea575x_write(tea, tea->val);
- timeout = jiffies + msecs_to_jiffies(10000);
- for (;;) {
if (time_after(jiffies, timeout))
break;
if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
/* some signal arrived, stop search */
tea->val &= ~TEA575X_BIT_SEARCH;
snd_tea575x_set_freq(tea);
return -ERESTARTSYS;
}
if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) {
u32 freq;
/* Found a frequency, wait until it can be read */
for (i = 0; i < 100; i++) {
msleep(10);
freq = snd_tea575x_get_freq(tea);
if (freq) /* available */
break;
}
if (freq == 0) /* shouldn't happen */
break;
/*
* if we moved by less than the spacing, or in the
* wrong direction, continue seeking
*/
if (abs(tea->freq - freq) < 16 * spacing ||
(a->seek_upward && freq < tea->freq) ||
(!a->seek_upward && freq > tea->freq)) {
snd_tea575x_write(tea, tea->val);
continue;
}
tea->freq = freq;
tea->val &= ~TEA575X_BIT_SEARCH;
return 0;
}
- }
- tea->val &= ~TEA575X_BIT_SEARCH;
- snd_tea575x_set_freq(tea);
- return -ENODATA;
+}
+static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) +{
- struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler);
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
tea->mute = ctrl->val;
snd_tea575x_set_freq(tea);
return 0;
- }
- return -EINVAL;
+}
+static const struct v4l2_file_operations tea575x_fops = {
- .unlocked_ioctl = video_ioctl2,
- .open = v4l2_fh_open,
- .release = v4l2_fh_release,
- .poll = v4l2_ctrl_poll,
+};
+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_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
- .vidioc_enum_freq_bands = vidioc_enum_freq_bands,
- .vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+static const struct video_device tea575x_radio = {
- .ioctl_ops = &tea575x_ioctl_ops,
- .release = video_device_release_empty,
+};
+static const struct v4l2_ctrl_ops tea575x_ctrl_ops = {
- .s_ctrl = tea575x_s_ctrl,
+};
+int snd_tea575x_hw_init(struct snd_tea575x *tea) +{
- tea->mute = true;
- /* Not all devices can or know how to read the data back.
Such devices can set cannot_read_data to true. */
- if (!tea->cannot_read_data) {
snd_tea575x_write(tea, 0x55AA);
if (snd_tea575x_read(tea) != 0x55AA)
return -ENODEV;
- }
- tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28;
- tea->freq = 90500 * 16; /* 90.5Mhz default */
- snd_tea575x_set_freq(tea);
- return 0;
+} +EXPORT_SYMBOL(snd_tea575x_hw_init);
+int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) +{
- int retval = snd_tea575x_hw_init(tea);
- if (retval)
return retval;
- tea->vd = tea575x_radio;
- video_set_drvdata(&tea->vd, tea);
- mutex_init(&tea->mutex);
- strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
- tea->vd.lock = &tea->mutex;
- tea->vd.v4l2_dev = tea->v4l2_dev;
- tea->fops = tea575x_fops;
- tea->fops.owner = owner;
- tea->vd.fops = &tea->fops;
- set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
- /* disable hw_freq_seek if we can't use it */
- if (tea->cannot_read_data)
v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
- if (!tea->cannot_mute) {
tea->vd.ctrl_handler = &tea->ctrl_handler;
v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
retval = tea->ctrl_handler.error;
if (retval) {
v4l2_err(tea->v4l2_dev, "can't initialize controls\n");
v4l2_ctrl_handler_free(&tea->ctrl_handler);
return retval;
}
if (tea->ext_init) {
retval = tea->ext_init(tea);
if (retval) {
v4l2_ctrl_handler_free(&tea->ctrl_handler);
return retval;
}
}
v4l2_ctrl_handler_setup(&tea->ctrl_handler);
- }
- retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr);
- if (retval) {
v4l2_err(tea->v4l2_dev, "can't register video device!\n");
v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
return retval;
- }
- return 0;
+}
+void snd_tea575x_exit(struct snd_tea575x *tea) +{
- video_unregister_device(&tea->vd);
- v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
+}
+static int __init alsa_tea575x_module_init(void) +{
- return 0;
+}
+static void __exit alsa_tea575x_module_exit(void) +{ +}
+module_init(alsa_tea575x_module_init) +module_exit(alsa_tea575x_module_exit)
+EXPORT_SYMBOL(snd_tea575x_init); +EXPORT_SYMBOL(snd_tea575x_exit); +EXPORT_SYMBOL(snd_tea575x_set_freq); diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index c95d8f1..5526b03 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile @@ -8,10 +8,8 @@ snd-ak4117-objs := ak4117.o snd-ak4113-objs := ak4113.o snd-ak4xxx-adda-objs := ak4xxx-adda.o snd-pt2258-objs := pt2258.o -snd-tea575x-tuner-objs := tea575x-tuner.o
# Module Dependency obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4113.o snd-ak4xxx-adda.o snd-pt2258.o -obj-$(CONFIG_SND_TEA575X) += snd-tea575x-tuner.o diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c deleted file mode 100644 index cef0698..0000000 --- a/sound/i2c/other/tea575x-tuner.c +++ /dev/null @@ -1,584 +0,0 @@ -/*
- ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
- Copyright (c) 2004 Jaroslav Kysela perex@perex.cz
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <asm/io.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <media/v4l2-device.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-event.h> -#include <media/tea575x.h>
-MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz"); -MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); -MODULE_LICENSE("GPL");
-/*
- definitions
- */
-#define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */ -#define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */ -#define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */ -#define TEA575X_BIT_BAND_MASK (3<<20) -#define TEA575X_BIT_BAND_FM (0<<20) -#define TEA575X_BIT_BAND_MW (1<<20) -#define TEA575X_BIT_BAND_LW (2<<20) -#define TEA575X_BIT_BAND_SW (3<<20) -#define TEA575X_BIT_PORT_0 (1<<19) /* user bit */ -#define TEA575X_BIT_PORT_1 (1<<18) /* user bit */ -#define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */ -#define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */ -#define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */ -#define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */ -#define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */ -#define TEA575X_BIT_DUMMY (1<<15) /* buffer */ -#define TEA575X_BIT_FREQ_MASK 0x7fff
-enum { BAND_FM, BAND_FM_JAPAN, BAND_AM };
-static const struct v4l2_frequency_band bands[] = {
- {
.type = V4L2_TUNER_RADIO,
.index = 0,
.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 87500 * 16,
.rangehigh = 108000 * 16,
.modulation = V4L2_BAND_MODULATION_FM,
- },
- {
.type = V4L2_TUNER_RADIO,
.index = 0,
.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 76000 * 16,
.rangehigh = 91000 * 16,
.modulation = V4L2_BAND_MODULATION_FM,
- },
- {
.type = V4L2_TUNER_RADIO,
.index = 1,
.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
.rangelow = 530 * 16,
.rangehigh = 1710 * 16,
.modulation = V4L2_BAND_MODULATION_AM,
- },
-};
-/*
- lowlevel part
- */
-static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val) -{
- u16 l;
- u8 data;
- if (tea->ops->write_val)
return tea->ops->write_val(tea, val);
- tea->ops->set_direction(tea, 1);
- udelay(16);
- for (l = 25; l > 0; l--) {
data = (val >> 24) & TEA575X_DATA;
val <<= 1; /* shift data */
tea->ops->set_pins(tea, data | TEA575X_WREN);
udelay(2);
tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK);
udelay(2);
tea->ops->set_pins(tea, data | TEA575X_WREN);
udelay(2);
- }
- if (!tea->mute)
tea->ops->set_pins(tea, 0);
-}
-static u32 snd_tea575x_read(struct snd_tea575x *tea) -{
- u16 l, rdata;
- u32 data = 0;
- if (tea->ops->read_val)
return tea->ops->read_val(tea);
- tea->ops->set_direction(tea, 0);
- tea->ops->set_pins(tea, 0);
- udelay(16);
- for (l = 24; l--;) {
tea->ops->set_pins(tea, TEA575X_CLK);
udelay(2);
if (!l)
tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1;
tea->ops->set_pins(tea, 0);
udelay(2);
data <<= 1; /* shift data */
rdata = tea->ops->get_pins(tea);
if (!l)
tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1;
if (rdata & TEA575X_DATA)
data++;
udelay(2);
- }
- if (tea->mute)
tea->ops->set_pins(tea, TEA575X_WREN);
- return data;
-}
-static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val) -{
- u32 freq = val & TEA575X_BIT_FREQ_MASK;
- if (freq == 0)
return freq;
- switch (tea->band) {
- case BAND_FM:
/* freq *= 12.5 */
freq *= 125;
freq /= 10;
/* crystal fixup */
freq -= TEA575X_FMIF;
break;
- case BAND_FM_JAPAN:
/* freq *= 12.5 */
freq *= 125;
freq /= 10;
/* crystal fixup */
freq += TEA575X_FMIF;
break;
- case BAND_AM:
/* crystal fixup */
freq -= TEA575X_AMIF;
break;
- }
- return clamp(freq * 16, bands[tea->band].rangelow,
bands[tea->band].rangehigh); /* from kHz */
-}
-static u32 snd_tea575x_get_freq(struct snd_tea575x *tea) -{
- return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea));
-}
-void snd_tea575x_set_freq(struct snd_tea575x *tea) -{
- u32 freq = tea->freq / 16; /* to kHz */
- u32 band = 0;
- switch (tea->band) {
- case BAND_FM:
band = TEA575X_BIT_BAND_FM;
/* crystal fixup */
freq += TEA575X_FMIF;
/* freq /= 12.5 */
freq *= 10;
freq /= 125;
break;
- case BAND_FM_JAPAN:
band = TEA575X_BIT_BAND_FM;
/* crystal fixup */
freq -= TEA575X_FMIF;
/* freq /= 12.5 */
freq *= 10;
freq /= 125;
break;
- case BAND_AM:
band = TEA575X_BIT_BAND_MW;
/* crystal fixup */
freq += TEA575X_AMIF;
break;
- }
- tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK);
- tea->val |= band;
- tea->val |= freq & TEA575X_BIT_FREQ_MASK;
- snd_tea575x_write(tea, tea->val);
- tea->freq = snd_tea575x_val_to_freq(tea, tea->val);
-}
-/*
- Linux Video interface
- */
-static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *v)
-{
- struct snd_tea575x *tea = video_drvdata(file);
- strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
- strlcpy(v->card, tea->card, sizeof(v->card));
- strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
- strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
- v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
- if (!tea->cannot_read_data)
v->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
- v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
- return 0;
-}
-static int vidioc_enum_freq_bands(struct file *file, void *priv,
struct v4l2_frequency_band *band)
-{
- struct snd_tea575x *tea = video_drvdata(file);
- int index;
- if (band->tuner != 0)
return -EINVAL;
- switch (band->index) {
- case 0:
if (tea->tea5759)
index = BAND_FM_JAPAN;
else
index = BAND_FM;
break;
- case 1:
if (tea->has_am) {
index = BAND_AM;
break;
}
/* Fall through */
- default:
return -EINVAL;
- }
- *band = bands[index];
- if (!tea->cannot_read_data)
band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED;
- return 0;
-}
-static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
-{
- struct snd_tea575x *tea = video_drvdata(file);
- struct v4l2_frequency_band band_fm = { 0, };
- if (v->index > 0)
return -EINVAL;
- snd_tea575x_read(tea);
- vidioc_enum_freq_bands(file, priv, &band_fm);
- memset(v, 0, sizeof(*v));
- strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name));
- v->type = V4L2_TUNER_RADIO;
- v->capability = band_fm.capability;
- v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow;
- v->rangehigh = band_fm.rangehigh;
- v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
- v->audmode = (tea->val & TEA575X_BIT_MONO) ?
V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO;
- v->signal = tea->tuned ? 0xffff : 0;
- return 0;
-}
-static int vidioc_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *v)
-{
- struct snd_tea575x *tea = video_drvdata(file);
- u32 orig_val = tea->val;
- if (v->index)
return -EINVAL;
- tea->val &= ~TEA575X_BIT_MONO;
- if (v->audmode == V4L2_TUNER_MODE_MONO)
tea->val |= TEA575X_BIT_MONO;
- /* Only apply changes if currently tuning FM */
- if (tea->band != BAND_AM && tea->val != orig_val)
snd_tea575x_set_freq(tea);
- return 0;
-}
-static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
-{
- struct snd_tea575x *tea = video_drvdata(file);
- if (f->tuner != 0)
return -EINVAL;
- f->type = V4L2_TUNER_RADIO;
- f->frequency = tea->freq;
- return 0;
-}
-static int vidioc_s_frequency(struct file *file, void *priv,
const struct v4l2_frequency *f)
-{
- struct snd_tea575x *tea = video_drvdata(file);
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
- if (tea->has_am && f->frequency < (20000 * 16))
tea->band = BAND_AM;
- else if (tea->tea5759)
tea->band = BAND_FM_JAPAN;
- else
tea->band = BAND_FM;
- tea->freq = clamp_t(u32, f->frequency, bands[tea->band].rangelow,
bands[tea->band].rangehigh);
- snd_tea575x_set_freq(tea);
- return 0;
-}
-static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
const struct v4l2_hw_freq_seek *a)
-{
- struct snd_tea575x *tea = video_drvdata(file);
- unsigned long timeout;
- int i, spacing;
- if (tea->cannot_read_data)
return -ENOTTY;
- if (a->tuner || a->wrap_around)
return -EINVAL;
- if (file->f_flags & O_NONBLOCK)
return -EWOULDBLOCK;
- if (a->rangelow || a->rangehigh) {
for (i = 0; i < ARRAY_SIZE(bands); i++) {
if ((i == BAND_FM && tea->tea5759) ||
(i == BAND_FM_JAPAN && !tea->tea5759) ||
(i == BAND_AM && !tea->has_am))
continue;
if (bands[i].rangelow == a->rangelow &&
bands[i].rangehigh == a->rangehigh)
break;
}
if (i == ARRAY_SIZE(bands))
return -EINVAL; /* No matching band found */
if (i != tea->band) {
tea->band = i;
tea->freq = clamp(tea->freq, bands[i].rangelow,
bands[i].rangehigh);
snd_tea575x_set_freq(tea);
}
- }
- spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */
- /* clear the frequency, HW will fill it in */
- tea->val &= ~TEA575X_BIT_FREQ_MASK;
- tea->val |= TEA575X_BIT_SEARCH;
- if (a->seek_upward)
tea->val |= TEA575X_BIT_UPDOWN;
- else
tea->val &= ~TEA575X_BIT_UPDOWN;
- snd_tea575x_write(tea, tea->val);
- timeout = jiffies + msecs_to_jiffies(10000);
- for (;;) {
if (time_after(jiffies, timeout))
break;
if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
/* some signal arrived, stop search */
tea->val &= ~TEA575X_BIT_SEARCH;
snd_tea575x_set_freq(tea);
return -ERESTARTSYS;
}
if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) {
u32 freq;
/* Found a frequency, wait until it can be read */
for (i = 0; i < 100; i++) {
msleep(10);
freq = snd_tea575x_get_freq(tea);
if (freq) /* available */
break;
}
if (freq == 0) /* shouldn't happen */
break;
/*
* if we moved by less than the spacing, or in the
* wrong direction, continue seeking
*/
if (abs(tea->freq - freq) < 16 * spacing ||
(a->seek_upward && freq < tea->freq) ||
(!a->seek_upward && freq > tea->freq)) {
snd_tea575x_write(tea, tea->val);
continue;
}
tea->freq = freq;
tea->val &= ~TEA575X_BIT_SEARCH;
return 0;
}
- }
- tea->val &= ~TEA575X_BIT_SEARCH;
- snd_tea575x_set_freq(tea);
- return -ENODATA;
-}
-static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) -{
- struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler);
- switch (ctrl->id) {
- case V4L2_CID_AUDIO_MUTE:
tea->mute = ctrl->val;
snd_tea575x_set_freq(tea);
return 0;
- }
- return -EINVAL;
-}
-static const struct v4l2_file_operations tea575x_fops = {
- .unlocked_ioctl = video_ioctl2,
- .open = v4l2_fh_open,
- .release = v4l2_fh_release,
- .poll = v4l2_ctrl_poll,
-};
-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_frequency = vidioc_g_frequency,
- .vidioc_s_frequency = vidioc_s_frequency,
- .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
- .vidioc_enum_freq_bands = vidioc_enum_freq_bands,
- .vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-static const struct video_device tea575x_radio = {
- .ioctl_ops = &tea575x_ioctl_ops,
- .release = video_device_release_empty,
-};
-static const struct v4l2_ctrl_ops tea575x_ctrl_ops = {
- .s_ctrl = tea575x_s_ctrl,
-};
-int snd_tea575x_hw_init(struct snd_tea575x *tea) -{
- tea->mute = true;
- /* Not all devices can or know how to read the data back.
Such devices can set cannot_read_data to true. */
- if (!tea->cannot_read_data) {
snd_tea575x_write(tea, 0x55AA);
if (snd_tea575x_read(tea) != 0x55AA)
return -ENODEV;
- }
- tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28;
- tea->freq = 90500 * 16; /* 90.5Mhz default */
- snd_tea575x_set_freq(tea);
- return 0;
-} -EXPORT_SYMBOL(snd_tea575x_hw_init);
-int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) -{
- int retval = snd_tea575x_hw_init(tea);
- if (retval)
return retval;
- tea->vd = tea575x_radio;
- video_set_drvdata(&tea->vd, tea);
- mutex_init(&tea->mutex);
- strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
- tea->vd.lock = &tea->mutex;
- tea->vd.v4l2_dev = tea->v4l2_dev;
- tea->fops = tea575x_fops;
- tea->fops.owner = owner;
- tea->vd.fops = &tea->fops;
- set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
- /* disable hw_freq_seek if we can't use it */
- if (tea->cannot_read_data)
v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
- if (!tea->cannot_mute) {
tea->vd.ctrl_handler = &tea->ctrl_handler;
v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
retval = tea->ctrl_handler.error;
if (retval) {
v4l2_err(tea->v4l2_dev, "can't initialize controls\n");
v4l2_ctrl_handler_free(&tea->ctrl_handler);
return retval;
}
if (tea->ext_init) {
retval = tea->ext_init(tea);
if (retval) {
v4l2_ctrl_handler_free(&tea->ctrl_handler);
return retval;
}
}
v4l2_ctrl_handler_setup(&tea->ctrl_handler);
- }
- retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr);
- if (retval) {
v4l2_err(tea->v4l2_dev, "can't register video device!\n");
v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
return retval;
- }
- return 0;
-}
-void snd_tea575x_exit(struct snd_tea575x *tea) -{
- video_unregister_device(&tea->vd);
- v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
-}
-static int __init alsa_tea575x_module_init(void) -{
- return 0;
-}
-static void __exit alsa_tea575x_module_exit(void) -{ -}
-module_init(alsa_tea575x_module_init) -module_exit(alsa_tea575x_module_exit)
-EXPORT_SYMBOL(snd_tea575x_init); -EXPORT_SYMBOL(snd_tea575x_exit); -EXPORT_SYMBOL(snd_tea575x_set_freq); diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index fe6fa93..9df80ef 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -1,10 +1,5 @@ # ALSA PCI drivers
-config SND_TEA575X
- tristate
- depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK
- default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK
menuconfig SND_PCI bool "PCI sound devices" depends on PCI @@ -542,7 +537,9 @@ config SND_ES1968_INPUT config SND_ES1968_RADIO bool "Enable TEA5757 radio tuner support for es1968" depends on SND_ES1968
- depends on MEDIA_RADIO_SUPPORT depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968
- select RADIO_TEA575X help Say Y here to include support for TEA5757 radio tuner integrated on some MediaForte cards (e.g. SF64-PCE2).
@@ -562,7 +559,9 @@ config SND_FM801 config SND_FM801_TEA575X_BOOL bool "ForteMedia FM801 + TEA5757 tuner" depends on SND_FM801
- depends on MEDIA_RADIO_SUPPORT depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801
- select RADIO_TEA575X help Say Y here to include support for soundcards based on the ForteMedia FM801 chip with a TEA5757 tuner (MediaForte SF256-PCS, SF256-PCP and
Hi Ondrej!
On 07/28/2013 10:01 PM, Ondrej Zary wrote:
Move include/sound/tea575x-tuner.h to include/media/tea575x.h and update files that include it.
Signed-off-by: Ondrej Zary linux@rainbow-software.org
Acked-by: Hans Verkuil hans.verkuil@cisco.com
If this can be acked by an alsa maintainer, then I can merge it into the media tree.
Regards,
Hans
drivers/media/radio/radio-maxiradio.c | 2 +- drivers/media/radio/radio-sf16fmr2.c | 2 +- drivers/media/radio/radio-shark.c | 2 +- include/media/tea575x.h | 79 +++++++++++++++++++++++++++++++++ include/sound/tea575x-tuner.h | 79 --------------------------------- sound/i2c/other/tea575x-tuner.c | 2 +- sound/pci/es1968.c | 2 +- sound/pci/fm801.c | 2 +- 8 files changed, 85 insertions(+), 85 deletions(-) create mode 100644 include/media/tea575x.h delete mode 100644 include/sound/tea575x-tuner.h
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index 1d1c9e1..5236035 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -42,7 +42,7 @@ #include <linux/videodev2.h> #include <linux/io.h> #include <linux/slab.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-fh.h> diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 9c09904..f1e3714 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -14,7 +14,7 @@ #include <linux/io.h> /* outb, outb_p */ #include <linux/isa.h> #include <linux/pnp.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h>
MODULE_AUTHOR("Ondrej Zary"); MODULE_DESCRIPTION("MediaForte SF16-FMR2 and SF16-FMD2 FM radio card driver"); diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 8fa18ab..b914772 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -33,7 +33,7 @@ #include <linux/usb.h> #include <linux/workqueue.h> #include <media/v4l2-device.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h>
#if defined(CONFIG_LEDS_CLASS) || \ (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) diff --git a/include/media/tea575x.h b/include/media/tea575x.h new file mode 100644 index 0000000..2d4fa59 --- /dev/null +++ b/include/media/tea575x.h @@ -0,0 +1,79 @@ +#ifndef __SOUND_TEA575X_TUNER_H +#define __SOUND_TEA575X_TUNER_H
+/*
- ALSA driver for TEA5757/5759 Philips AM/FM tuner chips
- Copyright (c) 2004 Jaroslav Kysela perex@perex.cz
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+#include <linux/videodev2.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-dev.h> +#include <media/v4l2-device.h>
+#define TEA575X_FMIF 10700 +#define TEA575X_AMIF 450
+#define TEA575X_DATA (1 << 0) +#define TEA575X_CLK (1 << 1) +#define TEA575X_WREN (1 << 2) +#define TEA575X_MOST (1 << 3)
+struct snd_tea575x;
+struct snd_tea575x_ops {
- /* Drivers using snd_tea575x must either define read_ and write_val */
- void (*write_val)(struct snd_tea575x *tea, u32 val);
- u32 (*read_val)(struct snd_tea575x *tea);
- /* Or define the 3 pin functions */
- void (*set_pins)(struct snd_tea575x *tea, u8 pins);
- u8 (*get_pins)(struct snd_tea575x *tea);
- void (*set_direction)(struct snd_tea575x *tea, bool output);
+};
+struct snd_tea575x {
- struct v4l2_device *v4l2_dev;
- struct v4l2_file_operations fops;
- struct video_device vd; /* video device */
- int radio_nr; /* radio_nr */
- bool tea5759; /* 5759 chip is present */
- bool has_am; /* Device can tune to AM freqs */
- bool cannot_read_data; /* Device cannot read the data pin */
- bool cannot_mute; /* Device cannot mute */
- bool mute; /* Device is muted? */
- bool stereo; /* receiving stereo */
- bool tuned; /* tuned to a station */
- unsigned int val; /* hw value */
- u32 band; /* 0: FM, 1: FM-Japan, 2: AM */
- u32 freq; /* frequency */
- struct mutex mutex;
- struct snd_tea575x_ops *ops;
- void *private_data;
- u8 card[32];
- u8 bus_info[32];
- struct v4l2_ctrl_handler ctrl_handler;
- int (*ext_init)(struct snd_tea575x *tea);
+};
+int snd_tea575x_hw_init(struct snd_tea575x *tea); +int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); +void snd_tea575x_exit(struct snd_tea575x *tea); +void snd_tea575x_set_freq(struct snd_tea575x *tea);
+#endif /* __SOUND_TEA575X_TUNER_H */ diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h deleted file mode 100644 index 2d4fa59..0000000 --- a/include/sound/tea575x-tuner.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef __SOUND_TEA575X_TUNER_H -#define __SOUND_TEA575X_TUNER_H
-/*
- ALSA driver for TEA5757/5759 Philips AM/FM tuner chips
- Copyright (c) 2004 Jaroslav Kysela perex@perex.cz
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/videodev2.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-dev.h> -#include <media/v4l2-device.h>
-#define TEA575X_FMIF 10700 -#define TEA575X_AMIF 450
-#define TEA575X_DATA (1 << 0) -#define TEA575X_CLK (1 << 1) -#define TEA575X_WREN (1 << 2) -#define TEA575X_MOST (1 << 3)
-struct snd_tea575x;
-struct snd_tea575x_ops {
- /* Drivers using snd_tea575x must either define read_ and write_val */
- void (*write_val)(struct snd_tea575x *tea, u32 val);
- u32 (*read_val)(struct snd_tea575x *tea);
- /* Or define the 3 pin functions */
- void (*set_pins)(struct snd_tea575x *tea, u8 pins);
- u8 (*get_pins)(struct snd_tea575x *tea);
- void (*set_direction)(struct snd_tea575x *tea, bool output);
-};
-struct snd_tea575x {
- struct v4l2_device *v4l2_dev;
- struct v4l2_file_operations fops;
- struct video_device vd; /* video device */
- int radio_nr; /* radio_nr */
- bool tea5759; /* 5759 chip is present */
- bool has_am; /* Device can tune to AM freqs */
- bool cannot_read_data; /* Device cannot read the data pin */
- bool cannot_mute; /* Device cannot mute */
- bool mute; /* Device is muted? */
- bool stereo; /* receiving stereo */
- bool tuned; /* tuned to a station */
- unsigned int val; /* hw value */
- u32 band; /* 0: FM, 1: FM-Japan, 2: AM */
- u32 freq; /* frequency */
- struct mutex mutex;
- struct snd_tea575x_ops *ops;
- void *private_data;
- u8 card[32];
- u8 bus_info[32];
- struct v4l2_ctrl_handler ctrl_handler;
- int (*ext_init)(struct snd_tea575x *tea);
-};
-int snd_tea575x_hw_init(struct snd_tea575x *tea); -int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner); -void snd_tea575x_exit(struct snd_tea575x *tea); -void snd_tea575x_set_freq(struct snd_tea575x *tea);
-#endif /* __SOUND_TEA575X_TUNER_H */ diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 46ec4dff..cef0698 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -31,7 +31,7 @@ #include <media/v4l2-fh.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h>
MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz"); MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips"); diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5e2ec96..b0e3d92 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -113,7 +113,7 @@ #include <sound/initval.h>
#ifdef CONFIG_SND_ES1968_RADIO -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #endif
#define CARD_NAME "ESS Maestro1/2" diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 706c5b6..45bc8a9 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -37,7 +37,7 @@ #include <asm/io.h>
#ifdef CONFIG_SND_FM801_TEA575X_BOOL -#include <sound/tea575x-tuner.h> +#include <media/tea575x.h> #endif
MODULE_AUTHOR("Jaroslav Kysela perex@perex.cz");
At Sun, 28 Jul 2013 22:01:42 +0200, Ondrej Zary wrote:
Hello, TEA575x is neither a sound device nor an i2c device. Let's finally move it from sound/i2c/other to drivers/media/radio.
Tested with snd-es1968, snd-fm801 and radio-sf16fmr2.
Good to resolve messes there now.
For both patches, Acked-by: Takashi Iwai tiwai@suse.de
Feel free to move them into media git tree for 3.12 kernel.
thanks,
Takashi
participants (3)
-
Hans Verkuil
-
Ondrej Zary
-
Takashi Iwai