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
));
232 int snd_tea575x_enum_freq_bands(struct snd_tea575x
*tea
,
233 struct v4l2_frequency_band
*band
)
237 if (band
->tuner
!= 0)
240 switch (band
->index
) {
243 index
= BAND_FM_JAPAN
;
257 *band
= bands
[index
];
258 if (!tea
->cannot_read_data
)
259 band
->capability
|= V4L2_TUNER_CAP_HWSEEK_BOUNDED
;
263 EXPORT_SYMBOL(snd_tea575x_enum_freq_bands
);
265 static int vidioc_enum_freq_bands(struct file
*file
, void *priv
,
266 struct v4l2_frequency_band
*band
)
268 struct snd_tea575x
*tea
= video_drvdata(file
);
270 return snd_tea575x_enum_freq_bands(tea
, band
);
273 int snd_tea575x_g_tuner(struct snd_tea575x
*tea
, struct v4l2_tuner
*v
)
275 struct v4l2_frequency_band band_fm
= { 0, };
280 snd_tea575x_read(tea
);
281 snd_tea575x_enum_freq_bands(tea
, &band_fm
);
283 memset(v
, 0, sizeof(*v
));
284 strscpy(v
->name
, tea
->has_am
? "FM/AM" : "FM", sizeof(v
->name
));
285 v
->type
= V4L2_TUNER_RADIO
;
286 v
->capability
= band_fm
.capability
;
287 v
->rangelow
= tea
->has_am
? bands
[BAND_AM
].rangelow
: band_fm
.rangelow
;
288 v
->rangehigh
= band_fm
.rangehigh
;
289 v
->rxsubchans
= tea
->stereo
? V4L2_TUNER_SUB_STEREO
: V4L2_TUNER_SUB_MONO
;
290 v
->audmode
= (tea
->val
& TEA575X_BIT_MONO
) ?
291 V4L2_TUNER_MODE_MONO
: V4L2_TUNER_MODE_STEREO
;
292 v
->signal
= tea
->tuned
? 0xffff : 0;
295 EXPORT_SYMBOL(snd_tea575x_g_tuner
);
297 static int vidioc_g_tuner(struct file
*file
, void *priv
,
298 struct v4l2_tuner
*v
)
300 struct snd_tea575x
*tea
= video_drvdata(file
);
302 return snd_tea575x_g_tuner(tea
, v
);
305 static int vidioc_s_tuner(struct file
*file
, void *priv
,
306 const struct v4l2_tuner
*v
)
308 struct snd_tea575x
*tea
= video_drvdata(file
);
309 u32 orig_val
= tea
->val
;
313 tea
->val
&= ~TEA575X_BIT_MONO
;
314 if (v
->audmode
== V4L2_TUNER_MODE_MONO
)
315 tea
->val
|= TEA575X_BIT_MONO
;
316 /* Only apply changes if currently tuning FM */
317 if (tea
->band
!= BAND_AM
&& tea
->val
!= orig_val
)
318 snd_tea575x_set_freq(tea
);
323 static int vidioc_g_frequency(struct file
*file
, void *priv
,
324 struct v4l2_frequency
*f
)
326 struct snd_tea575x
*tea
= video_drvdata(file
);
330 f
->type
= V4L2_TUNER_RADIO
;
331 f
->frequency
= tea
->freq
;
335 static int vidioc_s_frequency(struct file
*file
, void *priv
,
336 const struct v4l2_frequency
*f
)
338 struct snd_tea575x
*tea
= video_drvdata(file
);
340 if (f
->tuner
!= 0 || f
->type
!= V4L2_TUNER_RADIO
)
343 if (tea
->has_am
&& f
->frequency
< (20000 * 16))
345 else if (tea
->tea5759
)
346 tea
->band
= BAND_FM_JAPAN
;
350 tea
->freq
= clamp_t(u32
, f
->frequency
, bands
[tea
->band
].rangelow
,
351 bands
[tea
->band
].rangehigh
);
352 snd_tea575x_set_freq(tea
);
356 int snd_tea575x_s_hw_freq_seek(struct file
*file
, struct snd_tea575x
*tea
,
357 const struct v4l2_hw_freq_seek
*a
)
359 unsigned long timeout
;
362 if (tea
->cannot_read_data
)
364 if (a
->tuner
|| a
->wrap_around
)
367 if (file
->f_flags
& O_NONBLOCK
)
370 if (a
->rangelow
|| a
->rangehigh
) {
371 for (i
= 0; i
< ARRAY_SIZE(bands
); i
++) {
372 if ((i
== BAND_FM
&& tea
->tea5759
) ||
373 (i
== BAND_FM_JAPAN
&& !tea
->tea5759
) ||
374 (i
== BAND_AM
&& !tea
->has_am
))
376 if (bands
[i
].rangelow
== a
->rangelow
&&
377 bands
[i
].rangehigh
== a
->rangehigh
)
380 if (i
== ARRAY_SIZE(bands
))
381 return -EINVAL
; /* No matching band found */
382 if (i
!= tea
->band
) {
384 tea
->freq
= clamp(tea
->freq
, bands
[i
].rangelow
,
386 snd_tea575x_set_freq(tea
);
390 spacing
= (tea
->band
== BAND_AM
) ? 5 : 50; /* kHz */
392 /* clear the frequency, HW will fill it in */
393 tea
->val
&= ~TEA575X_BIT_FREQ_MASK
;
394 tea
->val
|= TEA575X_BIT_SEARCH
;
396 tea
->val
|= TEA575X_BIT_UPDOWN
;
398 tea
->val
&= ~TEA575X_BIT_UPDOWN
;
399 snd_tea575x_write(tea
, tea
->val
);
400 timeout
= jiffies
+ msecs_to_jiffies(10000);
402 if (time_after(jiffies
, timeout
))
404 if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
405 /* some signal arrived, stop search */
406 tea
->val
&= ~TEA575X_BIT_SEARCH
;
407 snd_tea575x_set_freq(tea
);
410 if (!(snd_tea575x_read(tea
) & TEA575X_BIT_SEARCH
)) {
413 /* Found a frequency, wait until it can be read */
414 for (i
= 0; i
< 100; i
++) {
416 freq
= snd_tea575x_get_freq(tea
);
417 if (freq
) /* available */
420 if (freq
== 0) /* shouldn't happen */
423 * if we moved by less than the spacing, or in the
424 * wrong direction, continue seeking
426 if (abs(tea
->freq
- freq
) < 16 * spacing
||
427 (a
->seek_upward
&& freq
< tea
->freq
) ||
428 (!a
->seek_upward
&& freq
> tea
->freq
)) {
429 snd_tea575x_write(tea
, tea
->val
);
433 tea
->val
&= ~TEA575X_BIT_SEARCH
;
437 tea
->val
&= ~TEA575X_BIT_SEARCH
;
438 snd_tea575x_set_freq(tea
);
441 EXPORT_SYMBOL(snd_tea575x_s_hw_freq_seek
);
443 static int vidioc_s_hw_freq_seek(struct file
*file
, void *fh
,
444 const struct v4l2_hw_freq_seek
*a
)
446 struct snd_tea575x
*tea
= video_drvdata(file
);
448 return snd_tea575x_s_hw_freq_seek(file
, tea
, a
);
451 static int tea575x_s_ctrl(struct v4l2_ctrl
*ctrl
)
453 struct snd_tea575x
*tea
= container_of(ctrl
->handler
, struct snd_tea575x
, ctrl_handler
);
456 case V4L2_CID_AUDIO_MUTE
:
457 tea
->mute
= ctrl
->val
;
458 snd_tea575x_set_freq(tea
);
465 static const struct v4l2_file_operations tea575x_fops
= {
466 .unlocked_ioctl
= video_ioctl2
,
467 .open
= v4l2_fh_open
,
468 .release
= v4l2_fh_release
,
469 .poll
= v4l2_ctrl_poll
,
472 static const struct v4l2_ioctl_ops tea575x_ioctl_ops
= {
473 .vidioc_querycap
= vidioc_querycap
,
474 .vidioc_g_tuner
= vidioc_g_tuner
,
475 .vidioc_s_tuner
= vidioc_s_tuner
,
476 .vidioc_g_frequency
= vidioc_g_frequency
,
477 .vidioc_s_frequency
= vidioc_s_frequency
,
478 .vidioc_s_hw_freq_seek
= vidioc_s_hw_freq_seek
,
479 .vidioc_enum_freq_bands
= vidioc_enum_freq_bands
,
480 .vidioc_log_status
= v4l2_ctrl_log_status
,
481 .vidioc_subscribe_event
= v4l2_ctrl_subscribe_event
,
482 .vidioc_unsubscribe_event
= v4l2_event_unsubscribe
,
485 static const struct video_device tea575x_radio
= {
486 .ioctl_ops
= &tea575x_ioctl_ops
,
487 .release
= video_device_release_empty
,
490 static const struct v4l2_ctrl_ops tea575x_ctrl_ops
= {
491 .s_ctrl
= tea575x_s_ctrl
,
495 int snd_tea575x_hw_init(struct snd_tea575x
*tea
)
499 /* Not all devices can or know how to read the data back.
500 Such devices can set cannot_read_data to true. */
501 if (!tea
->cannot_read_data
) {
502 snd_tea575x_write(tea
, 0x55AA);
503 if (snd_tea575x_read(tea
) != 0x55AA)
507 tea
->val
= TEA575X_BIT_BAND_FM
| TEA575X_BIT_SEARCH_5_28
;
508 tea
->freq
= 90500 * 16; /* 90.5Mhz default */
509 snd_tea575x_set_freq(tea
);
513 EXPORT_SYMBOL(snd_tea575x_hw_init
);
515 int snd_tea575x_init(struct snd_tea575x
*tea
, struct module
*owner
)
517 int retval
= snd_tea575x_hw_init(tea
);
522 tea
->vd
= tea575x_radio
;
523 video_set_drvdata(&tea
->vd
, tea
);
524 mutex_init(&tea
->mutex
);
525 strscpy(tea
->vd
.name
, tea
->v4l2_dev
->name
, sizeof(tea
->vd
.name
));
526 tea
->vd
.lock
= &tea
->mutex
;
527 tea
->vd
.v4l2_dev
= tea
->v4l2_dev
;
528 tea
->vd
.device_caps
= V4L2_CAP_TUNER
| V4L2_CAP_RADIO
;
529 if (!tea
->cannot_read_data
)
530 tea
->vd
.device_caps
|= V4L2_CAP_HW_FREQ_SEEK
;
531 tea
->fops
= tea575x_fops
;
532 tea
->fops
.owner
= owner
;
533 tea
->vd
.fops
= &tea
->fops
;
534 /* disable hw_freq_seek if we can't use it */
535 if (tea
->cannot_read_data
)
536 v4l2_disable_ioctl(&tea
->vd
, VIDIOC_S_HW_FREQ_SEEK
);
538 if (!tea
->cannot_mute
) {
539 tea
->vd
.ctrl_handler
= &tea
->ctrl_handler
;
540 v4l2_ctrl_handler_init(&tea
->ctrl_handler
, 1);
541 v4l2_ctrl_new_std(&tea
->ctrl_handler
, &tea575x_ctrl_ops
,
542 V4L2_CID_AUDIO_MUTE
, 0, 1, 1, 1);
543 retval
= tea
->ctrl_handler
.error
;
545 v4l2_err(tea
->v4l2_dev
, "can't initialize controls\n");
546 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
551 retval
= tea
->ext_init(tea
);
553 v4l2_ctrl_handler_free(&tea
->ctrl_handler
);
558 v4l2_ctrl_handler_setup(&tea
->ctrl_handler
);
561 retval
= video_register_device(&tea
->vd
, VFL_TYPE_RADIO
, tea
->radio_nr
);
563 v4l2_err(tea
->v4l2_dev
, "can't register video device!\n");
564 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
570 EXPORT_SYMBOL(snd_tea575x_init
);
572 void snd_tea575x_exit(struct snd_tea575x
*tea
)
574 video_unregister_device(&tea
->vd
);
575 v4l2_ctrl_handler_free(tea
->vd
.ctrl_handler
);
577 EXPORT_SYMBOL(snd_tea575x_exit
);