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.
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
23 #include <linux/delay.h>
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #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 <media/tea575x.h>
36 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
37 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
38 MODULE_LICENSE("GPL");
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
62 enum { BAND_FM
, BAND_FM_JAPAN
, BAND_AM
};
64 static const struct v4l2_frequency_band bands
[] = {
66 .type
= V4L2_TUNER_RADIO
,
68 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
|
69 V4L2_TUNER_CAP_FREQ_BANDS
,
70 .rangelow
= 87500 * 16,
71 .rangehigh
= 108000 * 16,
72 .modulation
= V4L2_BAND_MODULATION_FM
,
75 .type
= V4L2_TUNER_RADIO
,
77 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
|
78 V4L2_TUNER_CAP_FREQ_BANDS
,
79 .rangelow
= 76000 * 16,
80 .rangehigh
= 91000 * 16,
81 .modulation
= V4L2_BAND_MODULATION_FM
,
84 .type
= V4L2_TUNER_RADIO
,
86 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_FREQ_BANDS
,
88 .rangehigh
= 1710 * 16,
89 .modulation
= V4L2_BAND_MODULATION_AM
,
97 static void snd_tea575x_write(struct snd_tea575x
*tea
, unsigned int val
)
102 if (tea
->ops
->write_val
)
103 return tea
->ops
->write_val(tea
, val
);
105 tea
->ops
->set_direction(tea
, 1);
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
);
113 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
| TEA575X_CLK
);
115 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
);
120 tea
->ops
->set_pins(tea
, 0);
123 static u32
snd_tea575x_read(struct snd_tea575x
*tea
)
128 if (tea
->ops
->read_val
)
129 return tea
->ops
->read_val(tea
);
131 tea
->ops
->set_direction(tea
, 0);
132 tea
->ops
->set_pins(tea
, 0);
136 tea
->ops
->set_pins(tea
, TEA575X_CLK
);
139 tea
->tuned
= tea
->ops
->get_pins(tea
) & TEA575X_MOST
? 0 : 1;
140 tea
->ops
->set_pins(tea
, 0);
142 data
<<= 1; /* shift data */
143 rdata
= tea
->ops
->get_pins(tea
);
145 tea
->stereo
= (rdata
& TEA575X_MOST
) ? 0 : 1;
146 if (rdata
& TEA575X_DATA
)
152 tea
->ops
->set_pins(tea
, TEA575X_WREN
);
157 static u32
snd_tea575x_val_to_freq(struct snd_tea575x
*tea
, u32 val
)
159 u32 freq
= val
& TEA575X_BIT_FREQ_MASK
;
170 freq
-= TEA575X_FMIF
;
177 freq
+= TEA575X_FMIF
;
181 freq
-= TEA575X_AMIF
;
185 return clamp(freq
* 16, bands
[tea
->band
].rangelow
,
186 bands
[tea
->band
].rangehigh
); /* from kHz */
189 static u32
snd_tea575x_get_freq(struct snd_tea575x
*tea
)
191 return snd_tea575x_val_to_freq(tea
, snd_tea575x_read(tea
));
194 void snd_tea575x_set_freq(struct snd_tea575x
*tea
)
196 u32 freq
= tea
->freq
/ 16; /* to kHz */
201 band
= TEA575X_BIT_BAND_FM
;
203 freq
+= TEA575X_FMIF
;
209 band
= TEA575X_BIT_BAND_FM
;
211 freq
-= TEA575X_FMIF
;
217 band
= TEA575X_BIT_BAND_MW
;
219 freq
+= TEA575X_AMIF
;
223 tea
->val
&= ~(TEA575X_BIT_FREQ_MASK
| TEA575X_BIT_BAND_MASK
);
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
);
231 * Linux Video interface
234 static int vidioc_querycap(struct file
*file
, void *priv
,
235 struct v4l2_capability
*v
)
237 struct snd_tea575x
*tea
= video_drvdata(file
);
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
));
243 v
->device_caps
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
244 if (!tea
->cannot_read_data
)
245 v
->device_caps
|= V4L2_CAP_HW_FREQ_SEEK
;
246 v
->capabilities
= v
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
250 int snd_tea575x_enum_freq_bands(struct snd_tea575x
*tea
,
251 struct v4l2_frequency_band
*band
)
255 if (band
->tuner
!= 0)
258 switch (band
->index
) {
261 index
= BAND_FM_JAPAN
;
275 *band
= bands
[index
];
276 if (!tea
->cannot_read_data
)
277 band
->capability
|= V4L2_TUNER_CAP_HWSEEK_BOUNDED
;
281 EXPORT_SYMBOL(snd_tea575x_enum_freq_bands
);
283 static int vidioc_enum_freq_bands(struct file
*file
, void *priv
,
284 struct v4l2_frequency_band
*band
)
286 struct snd_tea575x
*tea
= video_drvdata(file
);
288 return snd_tea575x_enum_freq_bands(tea
, band
);
291 int snd_tea575x_g_tuner(struct snd_tea575x
*tea
, struct v4l2_tuner
*v
)
293 struct v4l2_frequency_band band_fm
= { 0, };
298 snd_tea575x_read(tea
);
299 snd_tea575x_enum_freq_bands(tea
, &band_fm
);
301 memset(v
, 0, sizeof(*v
));
302 strlcpy(v
->name
, tea
->has_am
? "FM/AM" : "FM", sizeof(v
->name
));
303 v
->type
= V4L2_TUNER_RADIO
;
304 v
->capability
= band_fm
.capability
;
305 v
->rangelow
= tea
->has_am
? bands
[BAND_AM
].rangelow
: band_fm
.rangelow
;
306 v
->rangehigh
= band_fm
.rangehigh
;
307 v
->rxsubchans
= tea
->stereo
? V4L2_TUNER_SUB_STEREO
: V4L2_TUNER_SUB_MONO
;
308 v
->audmode
= (tea
->val
& TEA575X_BIT_MONO
) ?
309 V4L2_TUNER_MODE_MONO
: V4L2_TUNER_MODE_STEREO
;
310 v
->signal
= tea
->tuned
? 0xffff : 0;
313 EXPORT_SYMBOL(snd_tea575x_g_tuner
);
315 static int vidioc_g_tuner(struct file
*file
, void *priv
,
316 struct v4l2_tuner
*v
)
318 struct snd_tea575x
*tea
= video_drvdata(file
);
320 return snd_tea575x_g_tuner(tea
, v
);
323 static int vidioc_s_tuner(struct file
*file
, void *priv
,
324 const struct v4l2_tuner
*v
)
326 struct snd_tea575x
*tea
= video_drvdata(file
);
327 u32 orig_val
= tea
->val
;
331 tea
->val
&= ~TEA575X_BIT_MONO
;
332 if (v
->audmode
== V4L2_TUNER_MODE_MONO
)
333 tea
->val
|= TEA575X_BIT_MONO
;
334 /* Only apply changes if currently tuning FM */
335 if (tea
->band
!= BAND_AM
&& tea
->val
!= orig_val
)
336 snd_tea575x_set_freq(tea
);
341 static int vidioc_g_frequency(struct file
*file
, void *priv
,
342 struct v4l2_frequency
*f
)
344 struct snd_tea575x
*tea
= video_drvdata(file
);
348 f
->type
= V4L2_TUNER_RADIO
;
349 f
->frequency
= tea
->freq
;
353 static int vidioc_s_frequency(struct file
*file
, void *priv
,
354 const struct v4l2_frequency
*f
)
356 struct snd_tea575x
*tea
= video_drvdata(file
);
358 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
361 if (tea
->has_am
&& f
->frequency
< (20000 * 16))
363 else if (tea
->tea5759
)
364 tea
->band
= BAND_FM_JAPAN
;
368 tea
->freq
= clamp_t(u32
, f
->frequency
, bands
[tea
->band
].rangelow
,
369 bands
[tea
->band
].rangehigh
);
370 snd_tea575x_set_freq(tea
);
374 int snd_tea575x_s_hw_freq_seek(struct file
*file
, struct snd_tea575x
*tea
,
375 const struct v4l2_hw_freq_seek
*a
)
377 unsigned long timeout
;
380 if (tea
->cannot_read_data
)
382 if (a
->tuner
|| a
->wrap_around
)
385 if (file
->f_flags
& O_NONBLOCK
)
388 if (a
->rangelow
|| a
->rangehigh
) {
389 for (i
= 0; i
< ARRAY_SIZE(bands
); i
++) {
390 if ((i
== BAND_FM
&& tea
->tea5759
) ||
391 (i
== BAND_FM_JAPAN
&& !tea
->tea5759
) ||
392 (i
== BAND_AM
&& !tea
->has_am
))
394 if (bands
[i
].rangelow
== a
->rangelow
&&
395 bands
[i
].rangehigh
== a
->rangehigh
)
398 if (i
== ARRAY_SIZE(bands
))
399 return -EINVAL
; /* No matching band found */
400 if (i
!= tea
->band
) {
402 tea
->freq
= clamp(tea
->freq
, bands
[i
].rangelow
,
404 snd_tea575x_set_freq(tea
);
408 spacing
= (tea
->band
== BAND_AM
) ? 5 : 50; /* kHz */
410 /* clear the frequency, HW will fill it in */
411 tea
->val
&= ~TEA575X_BIT_FREQ_MASK
;
412 tea
->val
|= TEA575X_BIT_SEARCH
;
414 tea
->val
|= TEA575X_BIT_UPDOWN
;
416 tea
->val
&= ~TEA575X_BIT_UPDOWN
;
417 snd_tea575x_write(tea
, tea
->val
);
418 timeout
= jiffies
+ msecs_to_jiffies(10000);
420 if (time_after(jiffies
, timeout
))
422 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
423 /* some signal arrived, stop search */
424 tea
->val
&= ~TEA575X_BIT_SEARCH
;
425 snd_tea575x_set_freq(tea
);
428 if (!(snd_tea575x_read(tea
) & TEA575X_BIT_SEARCH
)) {
431 /* Found a frequency, wait until it can be read */
432 for (i
= 0; i
< 100; i
++) {
434 freq
= snd_tea575x_get_freq(tea
);
435 if (freq
) /* available */
438 if (freq
== 0) /* shouldn't happen */
441 * if we moved by less than the spacing, or in the
442 * wrong direction, continue seeking
444 if (abs(tea
->freq
- freq
) < 16 * spacing
||
445 (a
->seek_upward
&& freq
< tea
->freq
) ||
446 (!a
->seek_upward
&& freq
> tea
->freq
)) {
447 snd_tea575x_write(tea
, tea
->val
);
451 tea
->val
&= ~TEA575X_BIT_SEARCH
;
455 tea
->val
&= ~TEA575X_BIT_SEARCH
;
456 snd_tea575x_set_freq(tea
);
459 EXPORT_SYMBOL(snd_tea575x_s_hw_freq_seek
);
461 static int vidioc_s_hw_freq_seek(struct file
*file
, void *fh
,
462 const struct v4l2_hw_freq_seek
*a
)
464 struct snd_tea575x
*tea
= video_drvdata(file
);
466 return snd_tea575x_s_hw_freq_seek(file
, tea
, a
);
469 static int tea575x_s_ctrl(struct v4l2_ctrl
*ctrl
)
471 struct snd_tea575x
*tea
= container_of(ctrl
->handler
, struct snd_tea575x
, ctrl_handler
);
474 case V4L2_CID_AUDIO_MUTE
:
475 tea
->mute
= ctrl
->val
;
476 snd_tea575x_set_freq(tea
);
483 static const struct v4l2_file_operations tea575x_fops
= {
484 .unlocked_ioctl
= video_ioctl2
,
485 .open
= v4l2_fh_open
,
486 .release
= v4l2_fh_release
,
487 .poll
= v4l2_ctrl_poll
,
490 static const struct v4l2_ioctl_ops tea575x_ioctl_ops
= {
491 .vidioc_querycap
= vidioc_querycap
,
492 .vidioc_g_tuner
= vidioc_g_tuner
,
493 .vidioc_s_tuner
= vidioc_s_tuner
,
494 .vidioc_g_frequency
= vidioc_g_frequency
,
495 .vidioc_s_frequency
= vidioc_s_frequency
,
496 .vidioc_s_hw_freq_seek
= vidioc_s_hw_freq_seek
,
497 .vidioc_enum_freq_bands
= vidioc_enum_freq_bands
,
498 .vidioc_log_status
= v4l2_ctrl_log_status
,
499 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
500 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
503 static const struct video_device tea575x_radio
= {
504 .ioctl_ops
= &tea575x_ioctl_ops
,
505 .release
= video_device_release_empty
,
508 static const struct v4l2_ctrl_ops tea575x_ctrl_ops
= {
509 .s_ctrl
= tea575x_s_ctrl
,
513 int snd_tea575x_hw_init(struct snd_tea575x
*tea
)
517 /* Not all devices can or know how to read the data back.
518 Such devices can set cannot_read_data to true. */
519 if (!tea
->cannot_read_data
) {
520 snd_tea575x_write(tea
, 0x55AA);
521 if (snd_tea575x_read(tea
) != 0x55AA)
525 tea
->val
= TEA575X_BIT_BAND_FM
| TEA575X_BIT_SEARCH_5_28
;
526 tea
->freq
= 90500 * 16; /* 90.5Mhz default */
527 snd_tea575x_set_freq(tea
);
531 EXPORT_SYMBOL(snd_tea575x_hw_init
);
533 int snd_tea575x_init(struct snd_tea575x
*tea
, struct module
*owner
)
535 int retval
= snd_tea575x_hw_init(tea
);
540 tea
->vd
= tea575x_radio
;
541 video_set_drvdata(&tea
->vd
, tea
);
542 mutex_init(&tea
->mutex
);
543 strlcpy(tea
->vd
.name
, tea
->v4l2_dev
->name
, sizeof(tea
->vd
.name
));
544 tea
->vd
.lock
= &tea
->mutex
;
545 tea
->vd
.v4l2_dev
= tea
->v4l2_dev
;
546 tea
->fops
= tea575x_fops
;
547 tea
->fops
.owner
= owner
;
548 tea
->vd
.fops
= &tea
->fops
;
549 /* disable hw_freq_seek if we can't use it */
550 if (tea
->cannot_read_data
)
551 v4l2_disable_ioctl(&tea
->vd
, VIDIOC_S_HW_FREQ_SEEK
);
553 if (!tea
->cannot_mute
) {
554 tea
->vd
.ctrl_handler
= &tea
->ctrl_handler
;
555 v4l2_ctrl_handler_init(&tea
->ctrl_handler
, 1);
556 v4l2_ctrl_new_std(&tea
->ctrl_handler
, &tea575x_ctrl_ops
,
557 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
558 retval
= tea
->ctrl_handler
.error
;
560 v4l2_err(tea
->v4l2_dev
, "can't initialize controls\n");
561 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
566 retval
= tea
->ext_init(tea
);
568 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
573 v4l2_ctrl_handler_setup(&tea
->ctrl_handler
);
576 retval
= video_register_device(&tea
->vd
, VFL_TYPE_RADIO
, tea
->radio_nr
);
578 v4l2_err(tea
->v4l2_dev
, "can't register video device!\n");
579 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
586 void snd_tea575x_exit(struct snd_tea575x
*tea
)
588 video_unregister_device(&tea
->vd
);
589 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
592 static int __init
alsa_tea575x_module_init(void)
597 static void __exit
alsa_tea575x_module_exit(void)
601 module_init(alsa_tea575x_module_init
)
602 module_exit(alsa_tea575x_module_exit
)
604 EXPORT_SYMBOL(snd_tea575x_init
);
605 EXPORT_SYMBOL(snd_tea575x_exit
);
606 EXPORT_SYMBOL(snd_tea575x_set_freq
);