aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-02-27 03:31:58 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-03-19 10:28:52 -0400
commitbc2b395c031430639e5ad5dcb2669cfcf1fa5fd2 (patch)
tree25905d7ccff4904a10187effa2fafec5daccb6d4 /sound
parentd4ecc83b79cc290eadf1ffb33a589c3c72bbc295 (diff)
[media] tea575x: fix HW seek
Fix HW seek in TEA575x to work properly: - a delay must be present after search start and before first register read or the seek does weird things - when the search stops, the new frequency is not available immediately, we must wait until it appears in the register (fortunately, we can clear the frequency bits when starting the search as it starts at the frequency currently set, not from the value written) - sometimes, seek remains on the current frequency (or moves only a little), so repeat it until it moves by at least 50 kHz Signed-off-by: Ondrej Zary <linux@rainbow-software.org> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'sound')
-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)
89 tea->ops->set_pins(tea, 0); 89 tea->ops->set_pins(tea, 0);
90} 90}
91 91
92static unsigned int snd_tea575x_read(struct snd_tea575x *tea) 92static u32 snd_tea575x_read(struct snd_tea575x *tea)
93{ 93{
94 u16 l, rdata; 94 u16 l, rdata;
95 u32 data = 0; 95 u32 data = 0;
@@ -120,6 +120,25 @@ static unsigned int snd_tea575x_read(struct snd_tea575x *tea)
120 return data; 120 return data;
121} 121}
122 122
123static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
124{
125 u32 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
126
127 if (freq == 0)
128 return freq;
129
130 /* freq *= 12.5 */
131 freq *= 125;
132 freq /= 10;
133 /* crystal fixup */
134 if (tea->tea5759)
135 freq += TEA575X_FMIF;
136 else
137 freq -= TEA575X_FMIF;
138
139 return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */
140}
141
123static void snd_tea575x_set_freq(struct snd_tea575x *tea) 142static void snd_tea575x_set_freq(struct snd_tea575x *tea)
124{ 143{
125 u32 freq = tea->freq; 144 u32 freq = tea->freq;
@@ -225,38 +244,62 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
225 struct v4l2_hw_freq_seek *a) 244 struct v4l2_hw_freq_seek *a)
226{ 245{
227 struct snd_tea575x *tea = video_drvdata(file); 246 struct snd_tea575x *tea = video_drvdata(file);
247 unsigned long timeout;
248 int i;
228 249
229 if (tea->cannot_read_data) 250 if (tea->cannot_read_data)
230 return -ENOTTY; 251 return -ENOTTY;
231 if (a->tuner || a->wrap_around) 252 if (a->tuner || a->wrap_around)
232 return -EINVAL; 253 return -EINVAL;
254
255 /* clear the frequency, HW will fill it in */
256 tea->val &= ~TEA575X_BIT_FREQ_MASK;
233 tea->val |= TEA575X_BIT_SEARCH; 257 tea->val |= TEA575X_BIT_SEARCH;
234 tea->val &= ~TEA575X_BIT_UPDOWN;
235 if (a->seek_upward) 258 if (a->seek_upward)
236 tea->val |= TEA575X_BIT_UPDOWN; 259 tea->val |= TEA575X_BIT_UPDOWN;
260 else
261 tea->val &= ~TEA575X_BIT_UPDOWN;
237 snd_tea575x_write(tea, tea->val); 262 snd_tea575x_write(tea, tea->val);
263 timeout = jiffies + msecs_to_jiffies(10000);
238 for (;;) { 264 for (;;) {
239 unsigned val = snd_tea575x_read(tea); 265 if (time_after(jiffies, timeout))
240 266 break;
241 if (!(val & TEA575X_BIT_SEARCH)) {
242 /* Found a frequency */
243 val &= TEA575X_BIT_FREQ_MASK;
244 val = (val * 10) / 125;
245 if (tea->tea5759)
246 val += TEA575X_FMIF;
247 else
248 val -= TEA575X_FMIF;
249 tea->freq = clamp(val * 16, FREQ_LO, FREQ_HI);
250 return 0;
251 }
252 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { 267 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
253 /* some signal arrived, stop search */ 268 /* some signal arrived, stop search */
254 tea->val &= ~TEA575X_BIT_SEARCH; 269 tea->val &= ~TEA575X_BIT_SEARCH;
255 snd_tea575x_write(tea, tea->val); 270 snd_tea575x_set_freq(tea);
256 return -ERESTARTSYS; 271 return -ERESTARTSYS;
257 } 272 }
273 if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) {
274 u32 freq;
275
276 /* Found a frequency, wait until it can be read */
277 for (i = 0; i < 100; i++) {
278 msleep(10);
279 freq = snd_tea575x_get_freq(tea);
280 if (freq) /* available */
281 break;
282 }
283 if (freq == 0) /* shouldn't happen */
284 break;
285 /*
286 * if we moved by less than 50 kHz, or in the wrong
287 * direction, continue seeking
288 */
289 if (abs(tea->freq - freq) < 16 * 50 ||
290 (a->seek_upward && freq < tea->freq) ||
291 (!a->seek_upward && freq > tea->freq)) {
292 snd_tea575x_write(tea, tea->val);
293 continue;
294 }
295 tea->freq = freq;
296 tea->val &= ~TEA575X_BIT_SEARCH;
297 return 0;
298 }
258 } 299 }
259 return 0; 300 tea->val &= ~TEA575X_BIT_SEARCH;
301 snd_tea575x_set_freq(tea);
302 return -EAGAIN;
260} 303}
261 304
262static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl) 305static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -320,7 +363,7 @@ int snd_tea575x_init(struct snd_tea575x *tea)
320 return -ENODEV; 363 return -ENODEV;
321 } 364 }
322 365
323 tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40; 366 tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28;
324 tea->freq = 90500 * 16; /* 90.5Mhz default */ 367 tea->freq = 90500 * 16; /* 90.5Mhz default */
325 snd_tea575x_set_freq(tea); 368 snd_tea575x_set_freq(tea);
326 369