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
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 <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 static int vidioc_enum_freq_bands(struct file
*file
, void *priv
,
251 struct v4l2_frequency_band
*band
)
253 struct snd_tea575x
*tea
= video_drvdata(file
);
256 if (band
->tuner
!= 0)
259 switch (band
->index
) {
262 index
= BAND_FM_JAPAN
;
276 *band
= bands
[index
];
277 if (!tea
->cannot_read_data
)
278 band
->capability
|= V4L2_TUNER_CAP_HWSEEK_BOUNDED
;
283 static int vidioc_g_tuner(struct file
*file
, void *priv
,
284 struct v4l2_tuner
*v
)
286 struct snd_tea575x
*tea
= video_drvdata(file
);
287 struct v4l2_frequency_band band_fm
= { 0, };
292 snd_tea575x_read(tea
);
293 vidioc_enum_freq_bands(file
, priv
, &band_fm
);
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
;
301 v
->rxsubchans
= tea
->stereo
? V4L2_TUNER_SUB_STEREO
: V4L2_TUNER_SUB_MONO
;
302 v
->audmode
= (tea
->val
& TEA575X_BIT_MONO
) ?
303 V4L2_TUNER_MODE_MONO
: V4L2_TUNER_MODE_STEREO
;
304 v
->signal
= tea
->tuned
? 0xffff : 0;
308 static int vidioc_s_tuner(struct file
*file
, void *priv
,
309 const struct v4l2_tuner
*v
)
311 struct snd_tea575x
*tea
= video_drvdata(file
);
312 u32 orig_val
= tea
->val
;
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
)
321 snd_tea575x_set_freq(tea
);
326 static int vidioc_g_frequency(struct file
*file
, void *priv
,
327 struct v4l2_frequency
*f
)
329 struct snd_tea575x
*tea
= video_drvdata(file
);
333 f
->type
= V4L2_TUNER_RADIO
;
334 f
->frequency
= tea
->freq
;
338 static int vidioc_s_frequency(struct file
*file
, void *priv
,
339 const struct v4l2_frequency
*f
)
341 struct snd_tea575x
*tea
= video_drvdata(file
);
343 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
346 if (tea
->has_am
&& f
->frequency
< (20000 * 16))
348 else if (tea
->tea5759
)
349 tea
->band
= BAND_FM_JAPAN
;
353 tea
->freq
= clamp_t(u32
, f
->frequency
, bands
[tea
->band
].rangelow
,
354 bands
[tea
->band
].rangehigh
);
355 snd_tea575x_set_freq(tea
);
359 static int vidioc_s_hw_freq_seek(struct file
*file
, void *fh
,
360 const struct v4l2_hw_freq_seek
*a
)
362 struct snd_tea575x
*tea
= video_drvdata(file
);
363 unsigned long timeout
;
366 if (tea
->cannot_read_data
)
368 if (a
->tuner
|| a
->wrap_around
)
371 if (file
->f_flags
& O_NONBLOCK
)
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
))
380 if (bands
[i
].rangelow
== a
->rangelow
&&
381 bands
[i
].rangehigh
== a
->rangehigh
)
384 if (i
== ARRAY_SIZE(bands
))
385 return -EINVAL
; /* No matching band found */
386 if (i
!= tea
->band
) {
388 tea
->freq
= clamp(tea
->freq
, bands
[i
].rangelow
,
390 snd_tea575x_set_freq(tea
);
394 spacing
= (tea
->band
== BAND_AM
) ? 5 : 50; /* kHz */
396 /* clear the frequency, HW will fill it in */
397 tea
->val
&= ~TEA575X_BIT_FREQ_MASK
;
398 tea
->val
|= TEA575X_BIT_SEARCH
;
400 tea
->val
|= TEA575X_BIT_UPDOWN
;
402 tea
->val
&= ~TEA575X_BIT_UPDOWN
;
403 snd_tea575x_write(tea
, tea
->val
);
404 timeout
= jiffies
+ msecs_to_jiffies(10000);
406 if (time_after(jiffies
, timeout
))
408 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
409 /* some signal arrived, stop search */
410 tea
->val
&= ~TEA575X_BIT_SEARCH
;
411 snd_tea575x_set_freq(tea
);
414 if (!(snd_tea575x_read(tea
) & TEA575X_BIT_SEARCH
)) {
417 /* Found a frequency, wait until it can be read */
418 for (i
= 0; i
< 100; i
++) {
420 freq
= snd_tea575x_get_freq(tea
);
421 if (freq
) /* available */
424 if (freq
== 0) /* shouldn't happen */
427 * if we moved by less than the spacing, or in the
428 * wrong direction, continue seeking
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
);
437 tea
->val
&= ~TEA575X_BIT_SEARCH
;
441 tea
->val
&= ~TEA575X_BIT_SEARCH
;
442 snd_tea575x_set_freq(tea
);
446 static int tea575x_s_ctrl(struct v4l2_ctrl
*ctrl
)
448 struct snd_tea575x
*tea
= container_of(ctrl
->handler
, struct snd_tea575x
, ctrl_handler
);
451 case V4L2_CID_AUDIO_MUTE
:
452 tea
->mute
= ctrl
->val
;
453 snd_tea575x_set_freq(tea
);
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
,
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
,
480 static const struct video_device tea575x_radio
= {
481 .ioctl_ops
= &tea575x_ioctl_ops
,
482 .release
= video_device_release_empty
,
485 static const struct v4l2_ctrl_ops tea575x_ctrl_ops
= {
486 .s_ctrl
= tea575x_s_ctrl
,
490 int snd_tea575x_hw_init(struct snd_tea575x
*tea
)
494 /* Not all devices can or know how to read the data back.
495 Such devices can set cannot_read_data to true. */
496 if (!tea
->cannot_read_data
) {
497 snd_tea575x_write(tea
, 0x55AA);
498 if (snd_tea575x_read(tea
) != 0x55AA)
502 tea
->val
= TEA575X_BIT_BAND_FM
| TEA575X_BIT_SEARCH_5_28
;
503 tea
->freq
= 90500 * 16; /* 90.5Mhz default */
504 snd_tea575x_set_freq(tea
);
508 EXPORT_SYMBOL(snd_tea575x_hw_init
);
510 int snd_tea575x_init(struct snd_tea575x
*tea
, struct module
*owner
)
512 int retval
= snd_tea575x_hw_init(tea
);
517 tea
->vd
= tea575x_radio
;
518 video_set_drvdata(&tea
->vd
, tea
);
519 mutex_init(&tea
->mutex
);
520 strlcpy(tea
->vd
.name
, tea
->v4l2_dev
->name
, sizeof(tea
->vd
.name
));
521 tea
->vd
.lock
= &tea
->mutex
;
522 tea
->vd
.v4l2_dev
= tea
->v4l2_dev
;
523 tea
->fops
= tea575x_fops
;
524 tea
->fops
.owner
= owner
;
525 tea
->vd
.fops
= &tea
->fops
;
526 set_bit(V4L2_FL_USE_FH_PRIO
, &tea
->vd
.flags
);
527 /* disable hw_freq_seek if we can't use it */
528 if (tea
->cannot_read_data
)
529 v4l2_disable_ioctl(&tea
->vd
, VIDIOC_S_HW_FREQ_SEEK
);
531 if (!tea
->cannot_mute
) {
532 tea
->vd
.ctrl_handler
= &tea
->ctrl_handler
;
533 v4l2_ctrl_handler_init(&tea
->ctrl_handler
, 1);
534 v4l2_ctrl_new_std(&tea
->ctrl_handler
, &tea575x_ctrl_ops
,
535 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
536 retval
= tea
->ctrl_handler
.error
;
538 v4l2_err(tea
->v4l2_dev
, "can't initialize controls\n");
539 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
544 retval
= tea
->ext_init(tea
);
546 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
551 v4l2_ctrl_handler_setup(&tea
->ctrl_handler
);
554 retval
= video_register_device(&tea
->vd
, VFL_TYPE_RADIO
, tea
->radio_nr
);
556 v4l2_err(tea
->v4l2_dev
, "can't register video device!\n");
557 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
564 void snd_tea575x_exit(struct snd_tea575x
*tea
)
566 video_unregister_device(&tea
->vd
);
567 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
570 static int __init
alsa_tea575x_module_init(void)
575 static void __exit
alsa_tea575x_module_exit(void)
579 module_init(alsa_tea575x_module_init
)
580 module_exit(alsa_tea575x_module_exit
)
582 EXPORT_SYMBOL(snd_tea575x_init
);
583 EXPORT_SYMBOL(snd_tea575x_exit
);
584 EXPORT_SYMBOL(snd_tea575x_set_freq
);