* [PATCH 0/6] snd_tea575x: Various patches
@ 2012-05-20 1:25 Hans de Goede
2012-05-20 1:25 ` [PATCH 1/6] snd_tea575x: Add write_/read_val operations Hans de Goede
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Hans de Goede @ 2012-05-20 1:25 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Ondrej Zary
Hi All,
This patch series contains various patches for the tea575x driver to prepare
for adding support for the Griffin radioSHARK device. The 6th patch adds
support for tuning AM, which depends on the discussions surrounding the
v4l2 API and radio devices with multiple tuners. I plan to add patches 1-5
to my next pull request to Mauro, I will leave patch 6 out until the API
discussion is done.
Regards,
Hans
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/6] snd_tea575x: Add write_/read_val operations
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
@ 2012-05-20 1:25 ` Hans de Goede
2012-05-20 1:25 ` [PATCH 2/6] snd_tea575x: Add a cannot_mute flag Hans de Goede
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2012-05-20 1:25 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Ondrej Zary, Hans de Goede
Some devices which use the tea575x tuner chip don't allow bit banging the
lines, instead they offer a method to directly set / get the contents of the
25 bit shift-register in the chip. Notably the Griffin radioSHARK USB radio
receiver does this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
CC: Ondrej Zary <linux@rainbow-software.org>
---
include/sound/tea575x-tuner.h | 4 ++++
sound/i2c/other/tea575x-tuner.c | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index ec3f910..1ae933f 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -37,6 +37,10 @@
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);
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 582aace..b74fc63 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -71,6 +71,9 @@ 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);
@@ -94,6 +97,9 @@ 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);
--
1.7.10
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/6] snd_tea575x: Add a cannot_mute flag
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
2012-05-20 1:25 ` [PATCH 1/6] snd_tea575x: Add write_/read_val operations Hans de Goede
@ 2012-05-20 1:25 ` Hans de Goede
2012-05-20 1:25 ` [PATCH 3/6] snd_tea575x: Report correct frequency range for EU/US versus JA models Hans de Goede
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2012-05-20 1:25 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Ondrej Zary, Hans de Goede
Some devices which use the tea575x tuner chip don't allow direct control
over the IO pins, and thus cannot mute the audio output.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
CC: Ondrej Zary <linux@rainbow-software.org>
---
include/sound/tea575x-tuner.h | 1 +
sound/i2c/other/tea575x-tuner.c | 35 +++++++++++++++++++----------------
2 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index 1ae933f..af58ad2 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -52,6 +52,7 @@ struct snd_tea575x {
int radio_nr; /* radio_nr */
bool tea5759; /* 5759 chip is present */
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 */
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index b74fc63..da49dd4 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -379,35 +379,38 @@ int snd_tea575x_init(struct snd_tea575x *tea)
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->vd.ctrl_handler = &tea->ctrl_handler;
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);
- 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 (!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;
}
- }
- v4l2_ctrl_handler_setup(&tea->ctrl_handler);
+ 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->ctrl_handler);
+ v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
return retval;
}
@@ -417,7 +420,7 @@ int snd_tea575x_init(struct snd_tea575x *tea)
void snd_tea575x_exit(struct snd_tea575x *tea)
{
video_unregister_device(&tea->vd);
- v4l2_ctrl_handler_free(&tea->ctrl_handler);
+ v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
}
static int __init alsa_tea575x_module_init(void)
--
1.7.10
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/6] snd_tea575x: Report correct frequency range for EU/US versus JA models
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
2012-05-20 1:25 ` [PATCH 1/6] snd_tea575x: Add write_/read_val operations Hans de Goede
2012-05-20 1:25 ` [PATCH 2/6] snd_tea575x: Add a cannot_mute flag Hans de Goede
@ 2012-05-20 1:25 ` Hans de Goede
2012-05-20 1:25 ` [PATCH 4/6] snd_tea575x: Make the module using snd_tea575x the fops owner Hans de Goede
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2012-05-20 1:25 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Ondrej Zary, Hans de Goede
My EU/US 5757 cannot tune below approx 86 Mhz, that is below that it
does not even generate the standard not tuned to anything radio noise anymore,
so clearly the 5757 cannot tune to the Japanese frequencies. This patch
assumes that likewise the 5759 cannot tune to the EU/US frequencies.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
CC: Ondrej Zary <linux@rainbow-software.org>
---
sound/i2c/other/tea575x-tuner.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index da49dd4..ddc08a8 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -37,8 +37,8 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
MODULE_LICENSE("GPL");
-#define FREQ_LO (76U * 16000)
-#define FREQ_HI (108U * 16000)
+#define FREQ_LO ((tea->tea5759 ? 760 : 875) * 1600U)
+#define FREQ_HI ((tea->tea5759 ? 910 : 1080) * 1600U)
/*
* definitions
--
1.7.10
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/6] snd_tea575x: Make the module using snd_tea575x the fops owner
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
` (2 preceding siblings ...)
2012-05-20 1:25 ` [PATCH 3/6] snd_tea575x: Report correct frequency range for EU/US versus JA models Hans de Goede
@ 2012-05-20 1:25 ` Hans de Goede
2012-05-20 1:25 ` [PATCH 5/6] snd_tea575x: set_freq: update cached freq to the actual achieved frequency Hans de Goede
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2012-05-20 1:25 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Ondrej Zary, Hans de Goede
Before this patch the owner field of the /dev/radio# device fops was set to
the snd-tea575x-tuner module itself. Meaning that the module which was using
it could be rmmod-ed while the device is open, and then BAD things happen.
I know, as I found out the hard way :)
Note that there is no need to also somehow increase the refcount of the
snd-tea575x-tuner module itself, since any drivers using it will have
symbolic references to it.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
CC: Ondrej Zary <linux@rainbow-software.org>
---
drivers/media/radio/radio-maxiradio.c | 2 +-
drivers/media/radio/radio-sf16fmr2.c | 2 +-
include/sound/tea575x-tuner.h | 3 ++-
sound/i2c/other/tea575x-tuner.c | 7 ++++---
sound/pci/es1968.c | 2 +-
sound/pci/fm801.c | 4 ++--
6 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 740a3d5..b415211 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -157,7 +157,7 @@ static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_devi
goto err_out_free_region;
dev->io = pci_resource_start(pdev, 0);
- if (snd_tea575x_init(&dev->tea)) {
+ if (snd_tea575x_init(&dev->tea, THIS_MODULE)) {
printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n");
goto err_out_free_region;
}
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 7c69214..59e1191 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -222,7 +222,7 @@ static int __devinit fmr2_probe(struct device *pdev, unsigned int dev)
snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "ISA:%s",
fmr2->v4l2_dev.name);
- if (snd_tea575x_init(&fmr2->tea)) {
+ if (snd_tea575x_init(&fmr2->tea, THIS_MODULE)) {
printk(KERN_ERR "radio-sf16fmr2: Unable to detect TEA575x tuner\n");
release_region(fmr2->io, 2);
kfree(fmr2);
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index af58ad2..fe8590c 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -48,6 +48,7 @@ struct snd_tea575x_ops {
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 */
@@ -67,7 +68,7 @@ struct snd_tea575x {
int (*ext_init)(struct snd_tea575x *tea);
};
-int snd_tea575x_init(struct snd_tea575x *tea);
+int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner);
void snd_tea575x_exit(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 ddc08a8..8c142e5 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -323,7 +323,6 @@ static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl)
}
static const struct v4l2_file_operations tea575x_fops = {
- .owner = THIS_MODULE,
.unlocked_ioctl = video_ioctl2,
.open = v4l2_fh_open,
.release = v4l2_fh_release,
@@ -343,7 +342,6 @@ static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
};
static const struct video_device tea575x_radio = {
- .fops = &tea575x_fops,
.ioctl_ops = &tea575x_ioctl_ops,
.release = video_device_release_empty,
};
@@ -355,7 +353,7 @@ static const struct v4l2_ctrl_ops tea575x_ctrl_ops = {
/*
* initialize all the tea575x chips
*/
-int snd_tea575x_init(struct snd_tea575x *tea)
+int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
{
int retval;
@@ -379,6 +377,9 @@ int snd_tea575x_init(struct snd_tea575x *tea)
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)
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index a8faae1..0f2811e 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2769,7 +2769,7 @@ static int __devinit snd_es1968_create(struct snd_card *card,
chip->tea.ops = &snd_es1968_tea_ops;
strlcpy(chip->tea.card, "SF64-PCE2", sizeof(chip->tea.card));
sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
- if (!snd_tea575x_init(&chip->tea))
+ if (!snd_tea575x_init(&chip->tea, THIS_MODULE))
printk(KERN_INFO "es1968: detected TEA575x radio\n");
#endif
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index a416ea8..5265c57 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1254,7 +1254,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
sprintf(chip->tea.bus_info, "PCI:%s", pci_name(pci));
if ((tea575x_tuner & TUNER_TYPE_MASK) > 0 &&
(tea575x_tuner & TUNER_TYPE_MASK) < 4) {
- if (snd_tea575x_init(&chip->tea)) {
+ if (snd_tea575x_init(&chip->tea, THIS_MODULE)) {
snd_printk(KERN_ERR "TEA575x radio not found\n");
snd_fm801_free(chip);
return -ENODEV;
@@ -1263,7 +1263,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
/* autodetect tuner connection */
for (tea575x_tuner = 1; tea575x_tuner <= 3; tea575x_tuner++) {
chip->tea575x_tuner = tea575x_tuner;
- if (!snd_tea575x_init(&chip->tea)) {
+ if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) {
snd_printk(KERN_INFO "detected TEA575x radio type %s\n",
get_tea575x_gpio(chip)->name);
break;
--
1.7.10
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/6] snd_tea575x: set_freq: update cached freq to the actual achieved frequency
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
` (3 preceding siblings ...)
2012-05-20 1:25 ` [PATCH 4/6] snd_tea575x: Make the module using snd_tea575x the fops owner Hans de Goede
@ 2012-05-20 1:25 ` Hans de Goede
2012-05-20 1:25 ` [PATCH 6/6] snd_tea575x: Add support for tuning AM Hans de Goede
2012-05-22 20:37 ` [PATCH 0/6] snd_tea575x: Various patches Ondrej Zary
6 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2012-05-20 1:25 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Ondrej Zary, Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
CC: Ondrej Zary <linux@rainbow-software.org>
---
sound/i2c/other/tea575x-tuner.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 8c142e5..d16f7b7 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -126,9 +126,9 @@ static u32 snd_tea575x_read(struct snd_tea575x *tea)
return data;
}
-static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
+static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val)
{
- u32 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
+ u32 freq = val & TEA575X_BIT_FREQ_MASK;
if (freq == 0)
return freq;
@@ -145,6 +145,11 @@ static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */
}
+static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
+{
+ return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea));
+}
+
static void snd_tea575x_set_freq(struct snd_tea575x *tea)
{
u32 freq = tea->freq;
@@ -162,6 +167,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea)
tea->val &= ~TEA575X_BIT_FREQ_MASK;
tea->val |= freq & TEA575X_BIT_FREQ_MASK;
snd_tea575x_write(tea, tea->val);
+ tea->freq = snd_tea575x_val_to_freq(tea, tea->val);
}
/*
--
1.7.10
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 6/6] snd_tea575x: Add support for tuning AM
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
` (4 preceding siblings ...)
2012-05-20 1:25 ` [PATCH 5/6] snd_tea575x: set_freq: update cached freq to the actual achieved frequency Hans de Goede
@ 2012-05-20 1:25 ` Hans de Goede
2012-05-22 20:37 ` [PATCH 0/6] snd_tea575x: Various patches Ondrej Zary
6 siblings, 0 replies; 8+ messages in thread
From: Hans de Goede @ 2012-05-20 1:25 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Ondrej Zary, Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
CC: Ondrej Zary <linux@rainbow-software.org>
---
include/sound/tea575x-tuner.h | 3 +
sound/i2c/other/tea575x-tuner.c | 164 ++++++++++++++++++++++++++++-----------
2 files changed, 121 insertions(+), 46 deletions(-)
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index fe8590c..602bddc 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -28,6 +28,7 @@
#include <media/v4l2-device.h>
#define TEA575X_FMIF 10700
+#define TEA575X_AMIF 450
#define TEA575X_DATA (1 << 0)
#define TEA575X_CLK (1 << 1)
@@ -52,12 +53,14 @@ struct snd_tea575x {
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 tuner; /* 0 == FM tuner, 1 == AM tuner */
u32 freq; /* frequency */
struct mutex mutex;
struct snd_tea575x_ops *ops;
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index d16f7b7..90e06e9 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -37,8 +37,15 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
MODULE_LICENSE("GPL");
-#define FREQ_LO ((tea->tea5759 ? 760 : 875) * 1600U)
-#define FREQ_HI ((tea->tea5759 ? 910 : 1080) * 1600U)
+#define FM_FREQ_LO ((tea->tea5759 ? 760 : 875) * 1600U)
+#define FM_FREQ_HI ((tea->tea5759 ? 910 : 1080) * 1600U)
+/* These are based on what the Griffin radioSHARK can do */
+#define AM_FREQ_LO ( 530 * 16U)
+#define AM_FREQ_HI (1710 * 16U)
+
+#define TUNER_FM 0
+#define TUNER_AM 1
+#define TUNER_MAX (tea->has_am ? TUNER_AM : TUNER_FM)
/*
* definitions
@@ -50,8 +57,8 @@ MODULE_LICENSE("GPL");
#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 (1<<21)
-#define TEA575X_BIT_BAND_SW (1<<22)
+#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 */
@@ -133,16 +140,25 @@ static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val)
if (freq == 0)
return freq;
- /* freq *= 12.5 */
- freq *= 125;
- freq /= 10;
- /* crystal fixup */
- if (tea->tea5759)
- freq += TEA575X_FMIF;
- else
- freq -= TEA575X_FMIF;
+ switch(tea->tuner) {
+ case TUNER_FM:
+ /* freq *= 12.5 */
+ freq *= 125;
+ freq /= 10;
+ /* crystal fixup */
+ if (tea->tea5759)
+ freq += TEA575X_FMIF;
+ else
+ freq -= TEA575X_FMIF;
+
+ return clamp(freq * 16, FM_FREQ_LO, FM_FREQ_HI); /* from kHz */
+ case TUNER_AM:
+ /* crystal fixup */
+ freq -= TEA575X_AMIF;
+ return clamp(freq * 16, AM_FREQ_LO, AM_FREQ_HI); /* from kHz */
+ }
- return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */
+ return 0; /* Never reached */
}
static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
@@ -154,16 +170,30 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea)
{
u32 freq = tea->freq;
- freq /= 16; /* to kHz */
- /* crystal fixup */
- if (tea->tea5759)
- freq -= TEA575X_FMIF;
- else
- freq += TEA575X_FMIF;
- /* freq /= 12.5 */
- freq *= 10;
- freq /= 125;
-
+ switch(tea->tuner) {
+ case TUNER_FM:
+ freq = clamp(freq, FM_FREQ_LO, FM_FREQ_HI) / 16; /* to kHz */
+ /* crystal fixup */
+ if (tea->tea5759)
+ freq -= TEA575X_FMIF;
+ else
+ freq += TEA575X_FMIF;
+ /* freq /= 12.5 */
+ freq *= 10;
+ freq /= 125;
+
+ tea->val &= ~TEA575X_BIT_BAND_MASK;
+ tea->val |= TEA575X_BIT_BAND_FM;
+ break;
+ case TUNER_AM:
+ freq = clamp(freq, AM_FREQ_LO, AM_FREQ_HI) / 16; /* to kHz */
+ /* crystal fixup */
+ freq += TEA575X_AMIF;
+
+ tea->val &= ~TEA575X_BIT_BAND_MASK;
+ tea->val |= TEA575X_BIT_BAND_MW;
+ break;
+ }
tea->val &= ~TEA575X_BIT_FREQ_MASK;
tea->val |= freq & TEA575X_BIT_FREQ_MASK;
snd_tea575x_write(tea, tea->val);
@@ -194,21 +224,39 @@ static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
struct snd_tea575x *tea = video_drvdata(file);
+ u32 tuner = v->index;
- if (v->index > 0)
+ if (tuner > TUNER_MAX)
return -EINVAL;
snd_tea575x_read(tea);
- strcpy(v->name, "FM");
+ memset(v, 0, sizeof(*v));
+ v->index = tuner;
v->type = V4L2_TUNER_RADIO;
- v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
- v->rangelow = FREQ_LO;
- v->rangehigh = FREQ_HI;
- 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;
+ v->signal = (tuner == tea->tuner && tea->tuned) ? 0xffff : 0;
+ v->capability = V4L2_TUNER_CAP_LOW;
+
+ switch (tuner) {
+ case TUNER_FM:
+ strcpy(v->name, "FM");
+ v->capability |= V4L2_TUNER_CAP_STEREO;
+ v->rangelow = FM_FREQ_LO;
+ v->rangehigh = FM_FREQ_HI;
+ 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;
+ break;
+ case TUNER_AM:
+ strcpy(v->name, "AM");
+ v->rangelow = AM_FREQ_LO;
+ v->rangehigh = AM_FREQ_HI;
+ v->rxsubchans = V4L2_TUNER_SUB_MONO;
+ v->audmode = V4L2_TUNER_MODE_MONO;
+ break;
+ }
+
return 0;
}
@@ -216,13 +264,26 @@ static int vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
struct snd_tea575x *tea = video_drvdata(file);
+ u32 orig_val = tea->val;
- if (v->index)
+ if (v->index > TUNER_MAX)
return -EINVAL;
- tea->val &= ~TEA575X_BIT_MONO;
- if (v->audmode == V4L2_TUNER_MODE_MONO)
- tea->val |= TEA575X_BIT_MONO;
- snd_tea575x_write(tea, tea->val);
+
+ switch (v->index) {
+ case TUNER_FM:
+ 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->tuner == TUNER_FM && tea->val != orig_val)
+ snd_tea575x_set_freq(tea);
+ break;
+ case TUNER_AM:
+ /* There are no modifiable settings on the AM tuner */
+ break;
+ }
+
return 0;
}
@@ -231,8 +292,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct snd_tea575x *tea = video_drvdata(file);
- if (f->tuner != 0)
- return -EINVAL;
+ f->tuner = tea->tuner;
f->type = V4L2_TUNER_RADIO;
f->frequency = tea->freq;
return 0;
@@ -243,11 +303,12 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct snd_tea575x *tea = video_drvdata(file);
- if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+ if (f->tuner > TUNER_MAX || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
tea->val &= ~TEA575X_BIT_SEARCH;
- tea->freq = clamp(f->frequency, FREQ_LO, FREQ_HI);
+ tea->tuner = f->tuner;
+ tea->freq = f->frequency;
snd_tea575x_set_freq(tea);
return 0;
}
@@ -257,12 +318,23 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
{
struct snd_tea575x *tea = video_drvdata(file);
unsigned long timeout;
- int i;
+ int i, spacing;
if (tea->cannot_read_data)
return -ENOTTY;
- if (a->tuner || a->wrap_around)
+ if (a->tuner > TUNER_MAX || a->wrap_around)
return -EINVAL;
+ if (a->tuner != tea->tuner)
+ return -EBUSY;
+
+ switch (tea->tuner) {
+ case TUNER_FM:
+ spacing = 50; /* kHz */
+ break;
+ case TUNER_AM:
+ spacing = 5; /* kHz */
+ break;
+ }
/* clear the frequency, HW will fill it in */
tea->val &= ~TEA575X_BIT_FREQ_MASK;
@@ -295,10 +367,10 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
if (freq == 0) /* shouldn't happen */
break;
/*
- * if we moved by less than 50 kHz, or in the wrong
- * direction, continue seeking
+ * if we moved by less than the spacing, or in the
+ * wrong direction, continue seeking
*/
- if (abs(tea->freq - freq) < 16 * 50 ||
+ 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);
--
1.7.10
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/6] snd_tea575x: Various patches
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
` (5 preceding siblings ...)
2012-05-20 1:25 ` [PATCH 6/6] snd_tea575x: Add support for tuning AM Hans de Goede
@ 2012-05-22 20:37 ` Ondrej Zary
6 siblings, 0 replies; 8+ messages in thread
From: Ondrej Zary @ 2012-05-22 20:37 UTC (permalink / raw)
To: Hans de Goede; +Cc: Linux Media Mailing List
On Sunday 20 May 2012 03:25:25 Hans de Goede wrote:
> Hi All,
>
> This patch series contains various patches for the tea575x driver to
> prepare for adding support for the Griffin radioSHARK device. The 6th patch
> adds support for tuning AM, which depends on the discussions surrounding
> the v4l2 API and radio devices with multiple tuners. I plan to add patches
> 1-5 to my next pull request to Mauro, I will leave patch 6 out until the
> API discussion is done.
I tested the patches with FM-only card (SF16-FMD2) and haven't found any
problems.
--
Ondrej Zary
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-05-22 20:37 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-20 1:25 [PATCH 0/6] snd_tea575x: Various patches Hans de Goede
2012-05-20 1:25 ` [PATCH 1/6] snd_tea575x: Add write_/read_val operations Hans de Goede
2012-05-20 1:25 ` [PATCH 2/6] snd_tea575x: Add a cannot_mute flag Hans de Goede
2012-05-20 1:25 ` [PATCH 3/6] snd_tea575x: Report correct frequency range for EU/US versus JA models Hans de Goede
2012-05-20 1:25 ` [PATCH 4/6] snd_tea575x: Make the module using snd_tea575x the fops owner Hans de Goede
2012-05-20 1:25 ` [PATCH 5/6] snd_tea575x: set_freq: update cached freq to the actual achieved frequency Hans de Goede
2012-05-20 1:25 ` [PATCH 6/6] snd_tea575x: Add support for tuning AM Hans de Goede
2012-05-22 20:37 ` [PATCH 0/6] snd_tea575x: Various patches Ondrej Zary
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.