summaryrefslogtreecommitdiff
path: root/sound/i2c/other/tea575x-tuner.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/i2c/other/tea575x-tuner.c')
-rw-r--r--sound/i2c/other/tea575x-tuner.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index b291bd86c4ca..a63faec5e7fd 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -89,7 +89,7 @@ static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val)
tea->ops->set_pins(tea, 0);
}
-static unsigned int snd_tea575x_read(struct snd_tea575x *tea)
+static u32 snd_tea575x_read(struct snd_tea575x *tea)
{
u16 l, rdata;
u32 data = 0;
@@ -120,6 +120,25 @@ static unsigned int snd_tea575x_read(struct snd_tea575x *tea)
return data;
}
+static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
+{
+ u32 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
+
+ if (freq == 0)
+ return freq;
+
+ /* freq *= 12.5 */
+ freq *= 125;
+ freq /= 10;
+ /* crystal fixup */
+ if (tea->tea5759)
+ freq += TEA575X_FMIF;
+ else
+ freq -= TEA575X_FMIF;
+
+ return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */
+}
+
static void snd_tea575x_set_freq(struct snd_tea575x *tea)
{
u32 freq = tea->freq;
@@ -225,38 +244,62 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
struct v4l2_hw_freq_seek *a)
{
struct snd_tea575x *tea = video_drvdata(file);
+ unsigned long timeout;
+ int i;
if (tea->cannot_read_data)
return -ENOTTY;
if (a->tuner || a->wrap_around)
return -EINVAL;
+
+ /* clear the frequency, HW will fill it in */
+ tea->val &= ~TEA575X_BIT_FREQ_MASK;
tea->val |= TEA575X_BIT_SEARCH;
- tea->val &= ~TEA575X_BIT_UPDOWN;
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 (;;) {
- unsigned val = snd_tea575x_read(tea);
-
- if (!(val & TEA575X_BIT_SEARCH)) {
- /* Found a frequency */
- val &= TEA575X_BIT_FREQ_MASK;
- val = (val * 10) / 125;
- if (tea->tea5759)
- val += TEA575X_FMIF;
- else
- val -= TEA575X_FMIF;
- tea->freq = clamp(val * 16, FREQ_LO, FREQ_HI);
- return 0;
- }
+ 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_write(tea, tea->val);
+ 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 50 kHz, or in the wrong
+ * direction, continue seeking
+ */
+ if (abs(tea->freq - freq) < 16 * 50 ||
+ (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;
+ }
}
- return 0;
+ tea->val &= ~TEA575X_BIT_SEARCH;
+ snd_tea575x_set_freq(tea);
+ return -EAGAIN;
}
static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -320,7 +363,7 @@ int snd_tea575x_init(struct snd_tea575x *tea)
return -ENODEV;
}
- tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
+ tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28;
tea->freq = 90500 * 16; /* 90.5Mhz default */
snd_tea575x_set_freq(tea);