2 * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
4 * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
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.
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.
19 #include <linux/delay.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/slab.h>
23 #include <linux/sched.h>
25 #include <media/v4l2-device.h>
26 #include <media/v4l2-dev.h>
27 #include <media/v4l2-fh.h>
28 #include <media/v4l2-ioctl.h>
29 #include <media/v4l2-event.h>
30 #include <media/drv-intf/tea575x.h>
32 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
33 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
34 MODULE_LICENSE("GPL");
40 #define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */
41 #define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */
42 #define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */
43 #define TEA575X_BIT_BAND_MASK (3<<20)
44 #define TEA575X_BIT_BAND_FM (0<<20)
45 #define TEA575X_BIT_BAND_MW (1<<20)
46 #define TEA575X_BIT_BAND_LW (2<<20)
47 #define TEA575X_BIT_BAND_SW (3<<20)
48 #define TEA575X_BIT_PORT_0 (1<<19) /* user bit */
49 #define TEA575X_BIT_PORT_1 (1<<18) /* user bit */
50 #define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */
51 #define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */
52 #define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */
53 #define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */
54 #define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */
55 #define TEA575X_BIT_DUMMY (1<<15) /* buffer */
56 #define TEA575X_BIT_FREQ_MASK 0x7fff
58 enum { BAND_FM
, BAND_FM_JAPAN
, BAND_AM
};
60 static const struct v4l2_frequency_band bands
[] = {
62 .type
= V4L2_TUNER_RADIO
,
64 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
|
65 V4L2_TUNER_CAP_FREQ_BANDS
,
66 .rangelow
= 87500 * 16,
67 .rangehigh
= 108000 * 16,
68 .modulation
= V4L2_BAND_MODULATION_FM
,
71 .type
= V4L2_TUNER_RADIO
,
73 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
|
74 V4L2_TUNER_CAP_FREQ_BANDS
,
75 .rangelow
= 76000 * 16,
76 .rangehigh
= 91000 * 16,
77 .modulation
= V4L2_BAND_MODULATION_FM
,
80 .type
= V4L2_TUNER_RADIO
,
82 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_FREQ_BANDS
,
84 .rangehigh
= 1710 * 16,
85 .modulation
= V4L2_BAND_MODULATION_AM
,
93 static void snd_tea575x_write(struct snd_tea575x
*tea
, unsigned int val
)
98 if (tea
->ops
->write_val
)
99 return tea
->ops
->write_val(tea
, val
);
101 tea
->ops
->set_direction(tea
, 1);
104 for (l
= 25; l
> 0; l
--) {
105 data
= (val
>> 24) & TEA575X_DATA
;
106 val
<<= 1; /* shift data */
107 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
);
109 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
| TEA575X_CLK
);
111 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
);
116 tea
->ops
->set_pins(tea
, 0);
119 static u32
snd_tea575x_read(struct snd_tea575x
*tea
)
124 if (tea
->ops
->read_val
)
125 return tea
->ops
->read_val(tea
);
127 tea
->ops
->set_direction(tea
, 0);
128 tea
->ops
->set_pins(tea
, 0);
132 tea
->ops
->set_pins(tea
, TEA575X_CLK
);
135 tea
->tuned
= tea
->ops
->get_pins(tea
) & TEA575X_MOST
? 0 : 1;
136 tea
->ops
->set_pins(tea
, 0);
138 data
<<= 1; /* shift data */
139 rdata
= tea
->ops
->get_pins(tea
);
141 tea
->stereo
= (rdata
& TEA575X_MOST
) ? 0 : 1;
142 if (rdata
& TEA575X_DATA
)
148 tea
->ops
->set_pins(tea
, TEA575X_WREN
);
153 static u32
snd_tea575x_val_to_freq(struct snd_tea575x
*tea
, u32 val
)
155 u32 freq
= val
& TEA575X_BIT_FREQ_MASK
;
166 freq
-= TEA575X_FMIF
;
173 freq
+= TEA575X_FMIF
;
177 freq
-= TEA575X_AMIF
;
181 return clamp(freq
* 16, bands
[tea
->band
].rangelow
,
182 bands
[tea
->band
].rangehigh
); /* from kHz */
185 static u32
snd_tea575x_get_freq(struct snd_tea575x
*tea
)
187 return snd_tea575x_val_to_freq(tea
, snd_tea575x_read(tea
));
190 void snd_tea575x_set_freq(struct snd_tea575x
*tea
)
192 u32 freq
= tea
->freq
/ 16; /* to kHz */
197 band
= TEA575X_BIT_BAND_FM
;
199 freq
+= TEA575X_FMIF
;
205 band
= TEA575X_BIT_BAND_FM
;
207 freq
-= TEA575X_FMIF
;
213 band
= TEA575X_BIT_BAND_MW
;
215 freq
+= TEA575X_AMIF
;
219 tea
->val
&= ~(TEA575X_BIT_FREQ_MASK
| TEA575X_BIT_BAND_MASK
);
221 tea
->val
|= freq
& TEA575X_BIT_FREQ_MASK
;
222 snd_tea575x_write(tea
, tea
->val
);
223 tea
->freq
= snd_tea575x_val_to_freq(tea
, tea
->val
);
225 EXPORT_SYMBOL(snd_tea575x_set_freq
);
228 * Linux Video interface
231 static int vidioc_querycap(struct file
*file
, void *priv
,
232 struct v4l2_capability
*v
)
234 struct snd_tea575x
*tea
= video_drvdata(file
);
236 strlcpy(v
->driver
, tea
->v4l2_dev
->name
, sizeof(v
->driver
));
237 strlcpy(v
->card
, tea
->card
, sizeof(v
->card
));
238 strlcat(v
->card
, tea
->tea5759
? " TEA5759" : " TEA5757", sizeof(v
->card
));
239 strlcpy(v
->bus_info
, tea
->bus_info
, sizeof(v
->bus_info
));
240 v
->device_caps
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
241 if (!tea
->cannot_read_data
)
242 v
->device_caps
|= V4L2_CAP_HW_FREQ_SEEK
;
243 v
->capabilities
= v
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
247 int snd_tea575x_enum_freq_bands(struct snd_tea575x
*tea
,
248 struct v4l2_frequency_band
*band
)
252 if (band
->tuner
!= 0)
255 switch (band
->index
) {
258 index
= BAND_FM_JAPAN
;
272 *band
= bands
[index
];
273 if (!tea
->cannot_read_data
)
274 band
->capability
|= V4L2_TUNER_CAP_HWSEEK_BOUNDED
;
278 EXPORT_SYMBOL(snd_tea575x_enum_freq_bands
);
280 static int vidioc_enum_freq_bands(struct file
*file
, void *priv
,
281 struct v4l2_frequency_band
*band
)
283 struct snd_tea575x
*tea
= video_drvdata(file
);
285 return snd_tea575x_enum_freq_bands(tea
, band
);
288 int snd_tea575x_g_tuner(struct snd_tea575x
*tea
, struct v4l2_tuner
*v
)
290 struct v4l2_frequency_band band_fm
= { 0, };
295 snd_tea575x_read(tea
);
296 snd_tea575x_enum_freq_bands(tea
, &band_fm
);
298 memset(v
, 0, sizeof(*v
));
299 strlcpy(v
->name
, tea
->has_am
? "FM/AM" : "FM", sizeof(v
->name
));
300 v
->type
= V4L2_TUNER_RADIO
;
301 v
->capability
= band_fm
.capability
;
302 v
->rangelow
= tea
->has_am
? bands
[BAND_AM
].rangelow
: band_fm
.rangelow
;
303 v
->rangehigh
= band_fm
.rangehigh
;
304 v
->rxsubchans
= tea
->stereo
? V4L2_TUNER_SUB_STEREO
: V4L2_TUNER_SUB_MONO
;
305 v
->audmode
= (tea
->val
& TEA575X_BIT_MONO
) ?
306 V4L2_TUNER_MODE_MONO
: V4L2_TUNER_MODE_STEREO
;
307 v
->signal
= tea
->tuned
? 0xffff : 0;
310 EXPORT_SYMBOL(snd_tea575x_g_tuner
);
312 static int vidioc_g_tuner(struct file
*file
, void *priv
,
313 struct v4l2_tuner
*v
)
315 struct snd_tea575x
*tea
= video_drvdata(file
);
317 return snd_tea575x_g_tuner(tea
, v
);
320 static int vidioc_s_tuner(struct file
*file
, void *priv
,
321 const struct v4l2_tuner
*v
)
323 struct snd_tea575x
*tea
= video_drvdata(file
);
324 u32 orig_val
= tea
->val
;
328 tea
->val
&= ~TEA575X_BIT_MONO
;
329 if (v
->audmode
== V4L2_TUNER_MODE_MONO
)
330 tea
->val
|= TEA575X_BIT_MONO
;
331 /* Only apply changes if currently tuning FM */
332 if (tea
->band
!= BAND_AM
&& tea
->val
!= orig_val
)
333 snd_tea575x_set_freq(tea
);
338 static int vidioc_g_frequency(struct file
*file
, void *priv
,
339 struct v4l2_frequency
*f
)
341 struct snd_tea575x
*tea
= video_drvdata(file
);
345 f
->type
= V4L2_TUNER_RADIO
;
346 f
->frequency
= tea
->freq
;
350 static int vidioc_s_frequency(struct file
*file
, void *priv
,
351 const struct v4l2_frequency
*f
)
353 struct snd_tea575x
*tea
= video_drvdata(file
);
355 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
358 if (tea
->has_am
&& f
->frequency
< (20000 * 16))
360 else if (tea
->tea5759
)
361 tea
->band
= BAND_FM_JAPAN
;
365 tea
->freq
= clamp_t(u32
, f
->frequency
, bands
[tea
->band
].rangelow
,
366 bands
[tea
->band
].rangehigh
);
367 snd_tea575x_set_freq(tea
);
371 int snd_tea575x_s_hw_freq_seek(struct file
*file
, struct snd_tea575x
*tea
,
372 const struct v4l2_hw_freq_seek
*a
)
374 unsigned long timeout
;
377 if (tea
->cannot_read_data
)
379 if (a
->tuner
|| a
->wrap_around
)
382 if (file
->f_flags
& O_NONBLOCK
)
385 if (a
->rangelow
|| a
->rangehigh
) {
386 for (i
= 0; i
< ARRAY_SIZE(bands
); i
++) {
387 if ((i
== BAND_FM
&& tea
->tea5759
) ||
388 (i
== BAND_FM_JAPAN
&& !tea
->tea5759
) ||
389 (i
== BAND_AM
&& !tea
->has_am
))
391 if (bands
[i
].rangelow
== a
->rangelow
&&
392 bands
[i
].rangehigh
== a
->rangehigh
)
395 if (i
== ARRAY_SIZE(bands
))
396 return -EINVAL
; /* No matching band found */
397 if (i
!= tea
->band
) {
399 tea
->freq
= clamp(tea
->freq
, bands
[i
].rangelow
,
401 snd_tea575x_set_freq(tea
);
405 spacing
= (tea
->band
== BAND_AM
) ? 5 : 50; /* kHz */
407 /* clear the frequency, HW will fill it in */
408 tea
->val
&= ~TEA575X_BIT_FREQ_MASK
;
409 tea
->val
|= TEA575X_BIT_SEARCH
;
411 tea
->val
|= TEA575X_BIT_UPDOWN
;
413 tea
->val
&= ~TEA575X_BIT_UPDOWN
;
414 snd_tea575x_write(tea
, tea
->val
);
415 timeout
= jiffies
+ msecs_to_jiffies(10000);
417 if (time_after(jiffies
, timeout
))
419 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
420 /* some signal arrived, stop search */
421 tea
->val
&= ~TEA575X_BIT_SEARCH
;
422 snd_tea575x_set_freq(tea
);
425 if (!(snd_tea575x_read(tea
) & TEA575X_BIT_SEARCH
)) {
428 /* Found a frequency, wait until it can be read */
429 for (i
= 0; i
< 100; i
++) {
431 freq
= snd_tea575x_get_freq(tea
);
432 if (freq
) /* available */
435 if (freq
== 0) /* shouldn't happen */
438 * if we moved by less than the spacing, or in the
439 * wrong direction, continue seeking
441 if (abs(tea
->freq
- freq
) < 16 * spacing
||
442 (a
->seek_upward
&& freq
< tea
->freq
) ||
443 (!a
->seek_upward
&& freq
> tea
->freq
)) {
444 snd_tea575x_write(tea
, tea
->val
);
448 tea
->val
&= ~TEA575X_BIT_SEARCH
;
452 tea
->val
&= ~TEA575X_BIT_SEARCH
;
453 snd_tea575x_set_freq(tea
);
456 EXPORT_SYMBOL(snd_tea575x_s_hw_freq_seek
);
458 static int vidioc_s_hw_freq_seek(struct file
*file
, void *fh
,
459 const struct v4l2_hw_freq_seek
*a
)
461 struct snd_tea575x
*tea
= video_drvdata(file
);
463 return snd_tea575x_s_hw_freq_seek(file
, tea
, a
);
466 static int tea575x_s_ctrl(struct v4l2_ctrl
*ctrl
)
468 struct snd_tea575x
*tea
= container_of(ctrl
->handler
, struct snd_tea575x
, ctrl_handler
);
471 case V4L2_CID_AUDIO_MUTE
:
472 tea
->mute
= ctrl
->val
;
473 snd_tea575x_set_freq(tea
);
480 static const struct v4l2_file_operations tea575x_fops
= {
481 .unlocked_ioctl
= video_ioctl2
,
482 .open
= v4l2_fh_open
,
483 .release
= v4l2_fh_release
,
484 .poll
= v4l2_ctrl_poll
,
487 static const struct v4l2_ioctl_ops tea575x_ioctl_ops
= {
488 .vidioc_querycap
= vidioc_querycap
,
489 .vidioc_g_tuner
= vidioc_g_tuner
,
490 .vidioc_s_tuner
= vidioc_s_tuner
,
491 .vidioc_g_frequency
= vidioc_g_frequency
,
492 .vidioc_s_frequency
= vidioc_s_frequency
,
493 .vidioc_s_hw_freq_seek
= vidioc_s_hw_freq_seek
,
494 .vidioc_enum_freq_bands
= vidioc_enum_freq_bands
,
495 .vidioc_log_status
= v4l2_ctrl_log_status
,
496 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
497 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
500 static const struct video_device tea575x_radio
= {
501 .ioctl_ops
= &tea575x_ioctl_ops
,
502 .release
= video_device_release_empty
,
505 static const struct v4l2_ctrl_ops tea575x_ctrl_ops
= {
506 .s_ctrl
= tea575x_s_ctrl
,
510 int snd_tea575x_hw_init(struct snd_tea575x
*tea
)
514 /* Not all devices can or know how to read the data back.
515 Such devices can set cannot_read_data to true. */
516 if (!tea
->cannot_read_data
) {
517 snd_tea575x_write(tea
, 0x55AA);
518 if (snd_tea575x_read(tea
) != 0x55AA)
522 tea
->val
= TEA575X_BIT_BAND_FM
| TEA575X_BIT_SEARCH_5_28
;
523 tea
->freq
= 90500 * 16; /* 90.5Mhz default */
524 snd_tea575x_set_freq(tea
);
528 EXPORT_SYMBOL(snd_tea575x_hw_init
);
530 int snd_tea575x_init(struct snd_tea575x
*tea
, struct module
*owner
)
532 int retval
= snd_tea575x_hw_init(tea
);
537 tea
->vd
= tea575x_radio
;
538 video_set_drvdata(&tea
->vd
, tea
);
539 mutex_init(&tea
->mutex
);
540 strlcpy(tea
->vd
.name
, tea
->v4l2_dev
->name
, sizeof(tea
->vd
.name
));
541 tea
->vd
.lock
= &tea
->mutex
;
542 tea
->vd
.v4l2_dev
= tea
->v4l2_dev
;
543 tea
->fops
= tea575x_fops
;
544 tea
->fops
.owner
= owner
;
545 tea
->vd
.fops
= &tea
->fops
;
546 /* disable hw_freq_seek if we can't use it */
547 if (tea
->cannot_read_data
)
548 v4l2_disable_ioctl(&tea
->vd
, VIDIOC_S_HW_FREQ_SEEK
);
550 if (!tea
->cannot_mute
) {
551 tea
->vd
.ctrl_handler
= &tea
->ctrl_handler
;
552 v4l2_ctrl_handler_init(&tea
->ctrl_handler
, 1);
553 v4l2_ctrl_new_std(&tea
->ctrl_handler
, &tea575x_ctrl_ops
,
554 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
555 retval
= tea
->ctrl_handler
.error
;
557 v4l2_err(tea
->v4l2_dev
, "can't initialize controls\n");
558 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
563 retval
= tea
->ext_init(tea
);
565 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
570 v4l2_ctrl_handler_setup(&tea
->ctrl_handler
);
573 retval
= video_register_device(&tea
->vd
, VFL_TYPE_RADIO
, tea
->radio_nr
);
575 v4l2_err(tea
->v4l2_dev
, "can't register video device!\n");
576 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
582 EXPORT_SYMBOL(snd_tea575x_init
);
584 void snd_tea575x_exit(struct snd_tea575x
*tea
)
586 video_unregister_device(&tea
->vd
);
587 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
589 EXPORT_SYMBOL(snd_tea575x_exit
);