1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
5 * Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
8 #include <linux/delay.h>
9 #include <linux/module.h>
10 #include <linux/init.h>
11 #include <linux/slab.h>
12 #include <linux/sched.h>
14 #include <media/v4l2-device.h>
15 #include <media/v4l2-dev.h>
16 #include <media/v4l2-fh.h>
17 #include <media/v4l2-ioctl.h>
18 #include <media/v4l2-event.h>
19 #include <media/drv-intf/tea575x.h>
21 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
22 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
23 MODULE_LICENSE("GPL");
29 #define TEA575X_BIT_SEARCH (1<<24) /* 1 = search action, 0 = tuned */
30 #define TEA575X_BIT_UPDOWN (1<<23) /* 0 = search down, 1 = search up */
31 #define TEA575X_BIT_MONO (1<<22) /* 0 = stereo, 1 = mono */
32 #define TEA575X_BIT_BAND_MASK (3<<20)
33 #define TEA575X_BIT_BAND_FM (0<<20)
34 #define TEA575X_BIT_BAND_MW (1<<20)
35 #define TEA575X_BIT_BAND_LW (2<<20)
36 #define TEA575X_BIT_BAND_SW (3<<20)
37 #define TEA575X_BIT_PORT_0 (1<<19) /* user bit */
38 #define TEA575X_BIT_PORT_1 (1<<18) /* user bit */
39 #define TEA575X_BIT_SEARCH_MASK (3<<16) /* search level */
40 #define TEA575X_BIT_SEARCH_5_28 (0<<16) /* FM >5uV, AM >28uV */
41 #define TEA575X_BIT_SEARCH_10_40 (1<<16) /* FM >10uV, AM > 40uV */
42 #define TEA575X_BIT_SEARCH_30_63 (2<<16) /* FM >30uV, AM > 63uV */
43 #define TEA575X_BIT_SEARCH_150_1000 (3<<16) /* FM > 150uV, AM > 1000uV */
44 #define TEA575X_BIT_DUMMY (1<<15) /* buffer */
45 #define TEA575X_BIT_FREQ_MASK 0x7fff
47 enum { BAND_FM
, BAND_FM_JAPAN
, BAND_AM
};
49 static const struct v4l2_frequency_band bands
[] = {
51 .type
= V4L2_TUNER_RADIO
,
53 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
|
54 V4L2_TUNER_CAP_FREQ_BANDS
,
55 .rangelow
= 87500 * 16,
56 .rangehigh
= 108000 * 16,
57 .modulation
= V4L2_BAND_MODULATION_FM
,
60 .type
= V4L2_TUNER_RADIO
,
62 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_STEREO
|
63 V4L2_TUNER_CAP_FREQ_BANDS
,
64 .rangelow
= 76000 * 16,
65 .rangehigh
= 91000 * 16,
66 .modulation
= V4L2_BAND_MODULATION_FM
,
69 .type
= V4L2_TUNER_RADIO
,
71 .capability
= V4L2_TUNER_CAP_LOW
| V4L2_TUNER_CAP_FREQ_BANDS
,
73 .rangehigh
= 1710 * 16,
74 .modulation
= V4L2_BAND_MODULATION_AM
,
82 static void snd_tea575x_write(struct snd_tea575x
*tea
, unsigned int val
)
87 if (tea
->ops
->write_val
)
88 return tea
->ops
->write_val(tea
, val
);
90 tea
->ops
->set_direction(tea
, 1);
93 for (l
= 25; l
> 0; l
--) {
94 data
= (val
>> 24) & TEA575X_DATA
;
95 val
<<= 1; /* shift data */
96 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
);
98 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
| TEA575X_CLK
);
100 tea
->ops
->set_pins(tea
, data
| TEA575X_WREN
);
105 tea
->ops
->set_pins(tea
, 0);
108 static u32
snd_tea575x_read(struct snd_tea575x
*tea
)
113 if (tea
->ops
->read_val
)
114 return tea
->ops
->read_val(tea
);
116 tea
->ops
->set_direction(tea
, 0);
117 tea
->ops
->set_pins(tea
, 0);
121 tea
->ops
->set_pins(tea
, TEA575X_CLK
);
124 tea
->tuned
= tea
->ops
->get_pins(tea
) & TEA575X_MOST
? 0 : 1;
125 tea
->ops
->set_pins(tea
, 0);
127 data
<<= 1; /* shift data */
128 rdata
= tea
->ops
->get_pins(tea
);
130 tea
->stereo
= (rdata
& TEA575X_MOST
) ? 0 : 1;
131 if (rdata
& TEA575X_DATA
)
137 tea
->ops
->set_pins(tea
, TEA575X_WREN
);
142 static u32
snd_tea575x_val_to_freq(struct snd_tea575x
*tea
, u32 val
)
144 u32 freq
= val
& TEA575X_BIT_FREQ_MASK
;
155 freq
-= TEA575X_FMIF
;
162 freq
+= TEA575X_FMIF
;
166 freq
-= TEA575X_AMIF
;
170 return clamp(freq
* 16, bands
[tea
->band
].rangelow
,
171 bands
[tea
->band
].rangehigh
); /* from kHz */
174 static u32
snd_tea575x_get_freq(struct snd_tea575x
*tea
)
176 return snd_tea575x_val_to_freq(tea
, snd_tea575x_read(tea
));
179 void snd_tea575x_set_freq(struct snd_tea575x
*tea
)
181 u32 freq
= tea
->freq
/ 16; /* to kHz */
186 band
= TEA575X_BIT_BAND_FM
;
188 freq
+= TEA575X_FMIF
;
194 band
= TEA575X_BIT_BAND_FM
;
196 freq
-= TEA575X_FMIF
;
202 band
= TEA575X_BIT_BAND_MW
;
204 freq
+= TEA575X_AMIF
;
208 tea
->val
&= ~(TEA575X_BIT_FREQ_MASK
| TEA575X_BIT_BAND_MASK
);
210 tea
->val
|= freq
& TEA575X_BIT_FREQ_MASK
;
211 snd_tea575x_write(tea
, tea
->val
);
212 tea
->freq
= snd_tea575x_val_to_freq(tea
, tea
->val
);
214 EXPORT_SYMBOL(snd_tea575x_set_freq
);
217 * Linux Video interface
220 static int vidioc_querycap(struct file
*file
, void *priv
,
221 struct v4l2_capability
*v
)
223 struct snd_tea575x
*tea
= video_drvdata(file
);
225 strscpy(v
->driver
, tea
->v4l2_dev
->name
, sizeof(v
->driver
));
226 strscpy(v
->card
, tea
->card
, sizeof(v
->card
));
227 strlcat(v
->card
, tea
->tea5759
? " TEA5759" : " TEA5757", sizeof(v
->card
));
228 strscpy(v
->bus_info
, tea
->bus_info
, sizeof(v
->bus_info
));
229 v
->device_caps
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
230 if (!tea
->cannot_read_data
)
231 v
->device_caps
|= V4L2_CAP_HW_FREQ_SEEK
;
232 v
->capabilities
= v
->device_caps
| V4L2_CAP_DEVICE_CAPS
;
236 int snd_tea575x_enum_freq_bands(struct snd_tea575x
*tea
,
237 struct v4l2_frequency_band
*band
)
241 if (band
->tuner
!= 0)
244 switch (band
->index
) {
247 index
= BAND_FM_JAPAN
;
261 *band
= bands
[index
];
262 if (!tea
->cannot_read_data
)
263 band
->capability
|= V4L2_TUNER_CAP_HWSEEK_BOUNDED
;
267 EXPORT_SYMBOL(snd_tea575x_enum_freq_bands
);
269 static int vidioc_enum_freq_bands(struct file
*file
, void *priv
,
270 struct v4l2_frequency_band
*band
)
272 struct snd_tea575x
*tea
= video_drvdata(file
);
274 return snd_tea575x_enum_freq_bands(tea
, band
);
277 int snd_tea575x_g_tuner(struct snd_tea575x
*tea
, struct v4l2_tuner
*v
)
279 struct v4l2_frequency_band band_fm
= { 0, };
284 snd_tea575x_read(tea
);
285 snd_tea575x_enum_freq_bands(tea
, &band_fm
);
287 memset(v
, 0, sizeof(*v
));
288 strscpy(v
->name
, tea
->has_am
? "FM/AM" : "FM", sizeof(v
->name
));
289 v
->type
= V4L2_TUNER_RADIO
;
290 v
->capability
= band_fm
.capability
;
291 v
->rangelow
= tea
->has_am
? bands
[BAND_AM
].rangelow
: band_fm
.rangelow
;
292 v
->rangehigh
= band_fm
.rangehigh
;
293 v
->rxsubchans
= tea
->stereo
? V4L2_TUNER_SUB_STEREO
: V4L2_TUNER_SUB_MONO
;
294 v
->audmode
= (tea
->val
& TEA575X_BIT_MONO
) ?
295 V4L2_TUNER_MODE_MONO
: V4L2_TUNER_MODE_STEREO
;
296 v
->signal
= tea
->tuned
? 0xffff : 0;
299 EXPORT_SYMBOL(snd_tea575x_g_tuner
);
301 static int vidioc_g_tuner(struct file
*file
, void *priv
,
302 struct v4l2_tuner
*v
)
304 struct snd_tea575x
*tea
= video_drvdata(file
);
306 return snd_tea575x_g_tuner(tea
, v
);
309 static int vidioc_s_tuner(struct file
*file
, void *priv
,
310 const struct v4l2_tuner
*v
)
312 struct snd_tea575x
*tea
= video_drvdata(file
);
313 u32 orig_val
= tea
->val
;
317 tea
->val
&= ~TEA575X_BIT_MONO
;
318 if (v
->audmode
== V4L2_TUNER_MODE_MONO
)
319 tea
->val
|= TEA575X_BIT_MONO
;
320 /* Only apply changes if currently tuning FM */
321 if (tea
->band
!= BAND_AM
&& tea
->val
!= orig_val
)
322 snd_tea575x_set_freq(tea
);
327 static int vidioc_g_frequency(struct file
*file
, void *priv
,
328 struct v4l2_frequency
*f
)
330 struct snd_tea575x
*tea
= video_drvdata(file
);
334 f
->type
= V4L2_TUNER_RADIO
;
335 f
->frequency
= tea
->freq
;
339 static int vidioc_s_frequency(struct file
*file
, void *priv
,
340 const struct v4l2_frequency
*f
)
342 struct snd_tea575x
*tea
= video_drvdata(file
);
344 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
347 if (tea
->has_am
&& f
->frequency
< (20000 * 16))
349 else if (tea
->tea5759
)
350 tea
->band
= BAND_FM_JAPAN
;
354 tea
->freq
= clamp_t(u32
, f
->frequency
, bands
[tea
->band
].rangelow
,
355 bands
[tea
->band
].rangehigh
);
356 snd_tea575x_set_freq(tea
);
360 int snd_tea575x_s_hw_freq_seek(struct file
*file
, struct snd_tea575x
*tea
,
361 const struct v4l2_hw_freq_seek
*a
)
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
);
445 EXPORT_SYMBOL(snd_tea575x_s_hw_freq_seek
);
447 static int vidioc_s_hw_freq_seek(struct file
*file
, void *fh
,
448 const struct v4l2_hw_freq_seek
*a
)
450 struct snd_tea575x
*tea
= video_drvdata(file
);
452 return snd_tea575x_s_hw_freq_seek(file
, tea
, a
);
455 static int tea575x_s_ctrl(struct v4l2_ctrl
*ctrl
)
457 struct snd_tea575x
*tea
= container_of(ctrl
->handler
, struct snd_tea575x
, ctrl_handler
);
460 case V4L2_CID_AUDIO_MUTE
:
461 tea
->mute
= ctrl
->val
;
462 snd_tea575x_set_freq(tea
);
469 static const struct v4l2_file_operations tea575x_fops
= {
470 .unlocked_ioctl
= video_ioctl2
,
471 .open
= v4l2_fh_open
,
472 .release
= v4l2_fh_release
,
473 .poll
= v4l2_ctrl_poll
,
476 static const struct v4l2_ioctl_ops tea575x_ioctl_ops
= {
477 .vidioc_querycap
= vidioc_querycap
,
478 .vidioc_g_tuner
= vidioc_g_tuner
,
479 .vidioc_s_tuner
= vidioc_s_tuner
,
480 .vidioc_g_frequency
= vidioc_g_frequency
,
481 .vidioc_s_frequency
= vidioc_s_frequency
,
482 .vidioc_s_hw_freq_seek
= vidioc_s_hw_freq_seek
,
483 .vidioc_enum_freq_bands
= vidioc_enum_freq_bands
,
484 .vidioc_log_status
= v4l2_ctrl_log_status
,
485 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
486 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
489 static const struct video_device tea575x_radio
= {
490 .ioctl_ops
= &tea575x_ioctl_ops
,
491 .release
= video_device_release_empty
,
494 static const struct v4l2_ctrl_ops tea575x_ctrl_ops
= {
495 .s_ctrl
= tea575x_s_ctrl
,
499 int snd_tea575x_hw_init(struct snd_tea575x
*tea
)
503 /* Not all devices can or know how to read the data back.
504 Such devices can set cannot_read_data to true. */
505 if (!tea
->cannot_read_data
) {
506 snd_tea575x_write(tea
, 0x55AA);
507 if (snd_tea575x_read(tea
) != 0x55AA)
511 tea
->val
= TEA575X_BIT_BAND_FM
| TEA575X_BIT_SEARCH_5_28
;
512 tea
->freq
= 90500 * 16; /* 90.5Mhz default */
513 snd_tea575x_set_freq(tea
);
517 EXPORT_SYMBOL(snd_tea575x_hw_init
);
519 int snd_tea575x_init(struct snd_tea575x
*tea
, struct module
*owner
)
521 int retval
= snd_tea575x_hw_init(tea
);
526 tea
->vd
= tea575x_radio
;
527 video_set_drvdata(&tea
->vd
, tea
);
528 mutex_init(&tea
->mutex
);
529 strscpy(tea
->vd
.name
, tea
->v4l2_dev
->name
, sizeof(tea
->vd
.name
));
530 tea
->vd
.lock
= &tea
->mutex
;
531 tea
->vd
.v4l2_dev
= tea
->v4l2_dev
;
532 tea
->fops
= tea575x_fops
;
533 tea
->fops
.owner
= owner
;
534 tea
->vd
.fops
= &tea
->fops
;
535 /* disable hw_freq_seek if we can't use it */
536 if (tea
->cannot_read_data
)
537 v4l2_disable_ioctl(&tea
->vd
, VIDIOC_S_HW_FREQ_SEEK
);
539 if (!tea
->cannot_mute
) {
540 tea
->vd
.ctrl_handler
= &tea
->ctrl_handler
;
541 v4l2_ctrl_handler_init(&tea
->ctrl_handler
, 1);
542 v4l2_ctrl_new_std(&tea
->ctrl_handler
, &tea575x_ctrl_ops
,
543 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
544 retval
= tea
->ctrl_handler
.error
;
546 v4l2_err(tea
->v4l2_dev
, "can't initialize controls\n");
547 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
552 retval
= tea
->ext_init(tea
);
554 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
559 v4l2_ctrl_handler_setup(&tea
->ctrl_handler
);
562 retval
= video_register_device(&tea
->vd
, VFL_TYPE_RADIO
, tea
->radio_nr
);
564 v4l2_err(tea
->v4l2_dev
, "can't register video device!\n");
565 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
571 EXPORT_SYMBOL(snd_tea575x_init
);
573 void snd_tea575x_exit(struct snd_tea575x
*tea
)
575 video_unregister_device(&tea
->vd
);
576 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
578 EXPORT_SYMBOL(snd_tea575x_exit
);