Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tea575x-tuner.c
Go to the documentation of this file.
1 /*
2  * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
3  *
4  * Copyright (c) 2004 Jaroslav Kysela <[email protected]>
5  *
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  */
22 
23 #include <asm/io.h>
24 #include <linux/delay.h>
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/slab.h>
28 #include <linux/sched.h>
29 #include <media/v4l2-device.h>
30 #include <media/v4l2-dev.h>
31 #include <media/v4l2-fh.h>
32 #include <media/v4l2-ioctl.h>
33 #include <media/v4l2-event.h>
34 #include <sound/tea575x-tuner.h>
35 
36 MODULE_AUTHOR("Jaroslav Kysela <[email protected]>");
37 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
38 MODULE_LICENSE("GPL");
39 
40 /*
41  * definitions
42  */
43 
44 #define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */
45 #define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */
46 #define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */
47 #define TEA575X_BIT_BAND_MASK (3<<20)
48 #define TEA575X_BIT_BAND_FM (0<<20)
49 #define TEA575X_BIT_BAND_MW (1<<20)
50 #define TEA575X_BIT_BAND_LW (2<<20)
51 #define TEA575X_BIT_BAND_SW (3<<20)
52 #define TEA575X_BIT_PORT_0 (1<<19) /* user bit */
53 #define TEA575X_BIT_PORT_1 (1<<18) /* user bit */
54 #define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */
55 #define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */
56 #define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */
57 #define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */
58 #define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */
59 #define TEA575X_BIT_DUMMY (1<<15) /* buffer */
60 #define TEA575X_BIT_FREQ_MASK 0x7fff
61 
63 
64 static const struct v4l2_frequency_band bands[] = {
65  {
66  .type = V4L2_TUNER_RADIO,
67  .index = 0,
70  .rangelow = 87500 * 16,
71  .rangehigh = 108000 * 16,
72  .modulation = V4L2_BAND_MODULATION_FM,
73  },
74  {
75  .type = V4L2_TUNER_RADIO,
76  .index = 0,
79  .rangelow = 76000 * 16,
80  .rangehigh = 91000 * 16,
81  .modulation = V4L2_BAND_MODULATION_FM,
82  },
83  {
84  .type = V4L2_TUNER_RADIO,
85  .index = 1,
87  .rangelow = 530 * 16,
88  .rangehigh = 1710 * 16,
89  .modulation = V4L2_BAND_MODULATION_AM,
90  },
91 };
92 
93 /*
94  * lowlevel part
95  */
96 
97 static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val)
98 {
99  u16 l;
100  u8 data;
101 
102  if (tea->ops->write_val)
103  return tea->ops->write_val(tea, val);
104 
105  tea->ops->set_direction(tea, 1);
106  udelay(16);
107 
108  for (l = 25; l > 0; l--) {
109  data = (val >> 24) & TEA575X_DATA;
110  val <<= 1; /* shift data */
111  tea->ops->set_pins(tea, data | TEA575X_WREN);
112  udelay(2);
113  tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK);
114  udelay(2);
115  tea->ops->set_pins(tea, data | TEA575X_WREN);
116  udelay(2);
117  }
118 
119  if (!tea->mute)
120  tea->ops->set_pins(tea, 0);
121 }
122 
123 static u32 snd_tea575x_read(struct snd_tea575x *tea)
124 {
125  u16 l, rdata;
126  u32 data = 0;
127 
128  if (tea->ops->read_val)
129  return tea->ops->read_val(tea);
130 
131  tea->ops->set_direction(tea, 0);
132  tea->ops->set_pins(tea, 0);
133  udelay(16);
134 
135  for (l = 24; l--;) {
136  tea->ops->set_pins(tea, TEA575X_CLK);
137  udelay(2);
138  if (!l)
139  tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1;
140  tea->ops->set_pins(tea, 0);
141  udelay(2);
142  data <<= 1; /* shift data */
143  rdata = tea->ops->get_pins(tea);
144  if (!l)
145  tea->stereo = (rdata & TEA575X_MOST) ? 0 : 1;
146  if (rdata & TEA575X_DATA)
147  data++;
148  udelay(2);
149  }
150 
151  if (tea->mute)
152  tea->ops->set_pins(tea, TEA575X_WREN);
153 
154  return data;
155 }
156 
157 static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val)
158 {
160 
161  if (freq == 0)
162  return freq;
163 
164  switch (tea->band) {
165  case BAND_FM:
166  /* freq *= 12.5 */
167  freq *= 125;
168  freq /= 10;
169  /* crystal fixup */
170  freq -= TEA575X_FMIF;
171  break;
172  case BAND_FM_JAPAN:
173  /* freq *= 12.5 */
174  freq *= 125;
175  freq /= 10;
176  /* crystal fixup */
177  freq += TEA575X_FMIF;
178  break;
179  case BAND_AM:
180  /* crystal fixup */
181  freq -= TEA575X_AMIF;
182  break;
183  }
184 
185  return clamp(freq * 16, bands[tea->band].rangelow,
186  bands[tea->band].rangehigh); /* from kHz */
187 }
188 
189 static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
190 {
191  return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea));
192 }
193 
195 {
196  u32 freq = tea->freq / 16; /* to kHz */
197  u32 band = 0;
198 
199  switch (tea->band) {
200  case BAND_FM:
201  band = TEA575X_BIT_BAND_FM;
202  /* crystal fixup */
203  freq += TEA575X_FMIF;
204  /* freq /= 12.5 */
205  freq *= 10;
206  freq /= 125;
207  break;
208  case BAND_FM_JAPAN:
209  band = TEA575X_BIT_BAND_FM;
210  /* crystal fixup */
211  freq -= TEA575X_FMIF;
212  /* freq /= 12.5 */
213  freq *= 10;
214  freq /= 125;
215  break;
216  case BAND_AM:
217  band = TEA575X_BIT_BAND_MW;
218  /* crystal fixup */
219  freq += TEA575X_AMIF;
220  break;
221  }
222 
223  tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK);
224  tea->val |= band;
225  tea->val |= freq & TEA575X_BIT_FREQ_MASK;
226  snd_tea575x_write(tea, tea->val);
227  tea->freq = snd_tea575x_val_to_freq(tea, tea->val);
228 }
229 
230 /*
231  * Linux Video interface
232  */
233 
234 static int vidioc_querycap(struct file *file, void *priv,
235  struct v4l2_capability *v)
236 {
237  struct snd_tea575x *tea = video_drvdata(file);
238 
239  strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
240  strlcpy(v->card, tea->card, sizeof(v->card));
241  strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
242  strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
244  if (!tea->cannot_read_data)
247  return 0;
248 }
249 
250 static int vidioc_enum_freq_bands(struct file *file, void *priv,
251  struct v4l2_frequency_band *band)
252 {
253  struct snd_tea575x *tea = video_drvdata(file);
254  int index;
255 
256  if (band->tuner != 0)
257  return -EINVAL;
258 
259  switch (band->index) {
260  case 0:
261  if (tea->tea5759)
262  index = BAND_FM_JAPAN;
263  else
264  index = BAND_FM;
265  break;
266  case 1:
267  if (tea->has_am) {
268  index = BAND_AM;
269  break;
270  }
271  /* Fall through */
272  default:
273  return -EINVAL;
274  }
275 
276  *band = bands[index];
277  if (!tea->cannot_read_data)
279 
280  return 0;
281 }
282 
283 static int vidioc_g_tuner(struct file *file, void *priv,
284  struct v4l2_tuner *v)
285 {
286  struct snd_tea575x *tea = video_drvdata(file);
287  struct v4l2_frequency_band band_fm = { 0, };
288 
289  if (v->index > 0)
290  return -EINVAL;
291 
292  snd_tea575x_read(tea);
293  vidioc_enum_freq_bands(file, priv, &band_fm);
294 
295  memset(v, 0, sizeof(*v));
296  strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name));
297  v->type = V4L2_TUNER_RADIO;
298  v->capability = band_fm.capability;
299  v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow;
300  v->rangehigh = band_fm.rangehigh;
302  v->audmode = (tea->val & TEA575X_BIT_MONO) ?
304  v->signal = tea->tuned ? 0xffff : 0;
305  return 0;
306 }
307 
308 static int vidioc_s_tuner(struct file *file, void *priv,
309  struct v4l2_tuner *v)
310 {
311  struct snd_tea575x *tea = video_drvdata(file);
312  u32 orig_val = tea->val;
313 
314  if (v->index)
315  return -EINVAL;
316  tea->val &= ~TEA575X_BIT_MONO;
317  if (v->audmode == V4L2_TUNER_MODE_MONO)
318  tea->val |= TEA575X_BIT_MONO;
319  /* Only apply changes if currently tuning FM */
320  if (tea->band != BAND_AM && tea->val != orig_val)
322 
323  return 0;
324 }
325 
326 static int vidioc_g_frequency(struct file *file, void *priv,
327  struct v4l2_frequency *f)
328 {
329  struct snd_tea575x *tea = video_drvdata(file);
330 
331  if (f->tuner != 0)
332  return -EINVAL;
333  f->type = V4L2_TUNER_RADIO;
334  f->frequency = tea->freq;
335  return 0;
336 }
337 
338 static int vidioc_s_frequency(struct file *file, void *priv,
339  struct v4l2_frequency *f)
340 {
341  struct snd_tea575x *tea = video_drvdata(file);
342 
343  if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
344  return -EINVAL;
345 
346  if (tea->has_am && f->frequency < (20000 * 16))
347  tea->band = BAND_AM;
348  else if (tea->tea5759)
349  tea->band = BAND_FM_JAPAN;
350  else
351  tea->band = BAND_FM;
352 
353  tea->freq = clamp(f->frequency, bands[tea->band].rangelow,
354  bands[tea->band].rangehigh);
356  return 0;
357 }
358 
359 static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
360  const struct v4l2_hw_freq_seek *a)
361 {
362  struct snd_tea575x *tea = video_drvdata(file);
363  unsigned long timeout;
364  int i, spacing;
365 
366  if (tea->cannot_read_data)
367  return -ENOTTY;
368  if (a->tuner || a->wrap_around)
369  return -EINVAL;
370 
371  if (file->f_flags & O_NONBLOCK)
372  return -EWOULDBLOCK;
373 
374  if (a->rangelow || a->rangehigh) {
375  for (i = 0; i < ARRAY_SIZE(bands); i++) {
376  if ((i == BAND_FM && tea->tea5759) ||
377  (i == BAND_FM_JAPAN && !tea->tea5759) ||
378  (i == BAND_AM && !tea->has_am))
379  continue;
380  if (bands[i].rangelow == a->rangelow &&
381  bands[i].rangehigh == a->rangehigh)
382  break;
383  }
384  if (i == ARRAY_SIZE(bands))
385  return -EINVAL; /* No matching band found */
386  if (i != tea->band) {
387  tea->band = i;
388  tea->freq = clamp(tea->freq, bands[i].rangelow,
389  bands[i].rangehigh);
391  }
392  }
393 
394  spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */
395 
396  /* clear the frequency, HW will fill it in */
397  tea->val &= ~TEA575X_BIT_FREQ_MASK;
398  tea->val |= TEA575X_BIT_SEARCH;
399  if (a->seek_upward)
400  tea->val |= TEA575X_BIT_UPDOWN;
401  else
402  tea->val &= ~TEA575X_BIT_UPDOWN;
403  snd_tea575x_write(tea, tea->val);
404  timeout = jiffies + msecs_to_jiffies(10000);
405  for (;;) {
406  if (time_after(jiffies, timeout))
407  break;
409  /* some signal arrived, stop search */
410  tea->val &= ~TEA575X_BIT_SEARCH;
412  return -ERESTARTSYS;
413  }
414  if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) {
415  u32 freq;
416 
417  /* Found a frequency, wait until it can be read */
418  for (i = 0; i < 100; i++) {
419  msleep(10);
420  freq = snd_tea575x_get_freq(tea);
421  if (freq) /* available */
422  break;
423  }
424  if (freq == 0) /* shouldn't happen */
425  break;
426  /*
427  * if we moved by less than the spacing, or in the
428  * wrong direction, continue seeking
429  */
430  if (abs(tea->freq - freq) < 16 * spacing ||
431  (a->seek_upward && freq < tea->freq) ||
432  (!a->seek_upward && freq > tea->freq)) {
433  snd_tea575x_write(tea, tea->val);
434  continue;
435  }
436  tea->freq = freq;
437  tea->val &= ~TEA575X_BIT_SEARCH;
438  return 0;
439  }
440  }
441  tea->val &= ~TEA575X_BIT_SEARCH;
443  return -ENODATA;
444 }
445 
446 static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl)
447 {
448  struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler);
449 
450  switch (ctrl->id) {
451  case V4L2_CID_AUDIO_MUTE:
452  tea->mute = ctrl->val;
454  return 0;
455  }
456 
457  return -EINVAL;
458 }
459 
460 static const struct v4l2_file_operations tea575x_fops = {
461  .unlocked_ioctl = video_ioctl2,
462  .open = v4l2_fh_open,
463  .release = v4l2_fh_release,
464  .poll = v4l2_ctrl_poll,
465 };
466 
467 static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
468  .vidioc_querycap = vidioc_querycap,
469  .vidioc_g_tuner = vidioc_g_tuner,
470  .vidioc_s_tuner = vidioc_s_tuner,
471  .vidioc_g_frequency = vidioc_g_frequency,
472  .vidioc_s_frequency = vidioc_s_frequency,
473  .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
474  .vidioc_enum_freq_bands = vidioc_enum_freq_bands,
475  .vidioc_log_status = v4l2_ctrl_log_status,
476  .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
477  .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
478 };
479 
480 static const struct video_device tea575x_radio = {
481  .ioctl_ops = &tea575x_ioctl_ops,
482  .release = video_device_release_empty,
483 };
484 
485 static const struct v4l2_ctrl_ops tea575x_ctrl_ops = {
486  .s_ctrl = tea575x_s_ctrl,
487 };
488 
489 /*
490  * initialize all the tea575x chips
491  */
492 int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
493 {
494  int retval;
495 
496  tea->mute = true;
497 
498  /* Not all devices can or know how to read the data back.
499  Such devices can set cannot_read_data to true. */
500  if (!tea->cannot_read_data) {
501  snd_tea575x_write(tea, 0x55AA);
502  if (snd_tea575x_read(tea) != 0x55AA)
503  return -ENODEV;
504  }
505 
507  tea->freq = 90500 * 16; /* 90.5Mhz default */
509 
510  tea->vd = tea575x_radio;
511  video_set_drvdata(&tea->vd, tea);
512  mutex_init(&tea->mutex);
513  strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
514  tea->vd.lock = &tea->mutex;
515  tea->vd.v4l2_dev = tea->v4l2_dev;
516  tea->fops = tea575x_fops;
517  tea->fops.owner = owner;
518  tea->vd.fops = &tea->fops;
519  set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
520  /* disable hw_freq_seek if we can't use it */
521  if (tea->cannot_read_data)
522  v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
523 
524  if (!tea->cannot_mute) {
525  tea->vd.ctrl_handler = &tea->ctrl_handler;
527  v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops,
528  V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
529  retval = tea->ctrl_handler.error;
530  if (retval) {
531  v4l2_err(tea->v4l2_dev, "can't initialize controls\n");
533  return retval;
534  }
535 
536  if (tea->ext_init) {
537  retval = tea->ext_init(tea);
538  if (retval) {
540  return retval;
541  }
542  }
543 
545  }
546 
547  retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr);
548  if (retval) {
549  v4l2_err(tea->v4l2_dev, "can't register video device!\n");
550  v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
551  return retval;
552  }
553 
554  return 0;
555 }
556 
557 void snd_tea575x_exit(struct snd_tea575x *tea)
558 {
560  v4l2_ctrl_handler_free(tea->vd.ctrl_handler);
561 }
562 
563 static int __init alsa_tea575x_module_init(void)
564 {
565  return 0;
566 }
567 
568 static void __exit alsa_tea575x_module_exit(void)
569 {
570 }
571 
572 module_init(alsa_tea575x_module_init)
573 module_exit(alsa_tea575x_module_exit)
574