tea575x.c revision 54f6019b5860ec062d1149b3a97a5a63ad3e4da9
1/*
2 *   ALSA driver for TEA5757/5759 Philips AM/FM radio tuner chips
3 *
4 *	Copyright (c) 2004 Jaroslav Kysela <perex@perex.cz>
5 *
6 *
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.
11 *
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.
16 *
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
20 *
21 */
22
23#include <asm/io.h>
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 <sound/tea575x-tuner.h>
35
36MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
37MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
38MODULE_LICENSE("GPL");
39
40#define FREQ_LO		 (76U * 16000)
41#define FREQ_HI		(108U * 16000)
42
43/*
44 * definitions
45 */
46
47#define TEA575X_BIT_SEARCH	(1<<24)		/* 1 = search action, 0 = tuned */
48#define TEA575X_BIT_UPDOWN	(1<<23)		/* 0 = search down, 1 = search up */
49#define TEA575X_BIT_MONO	(1<<22)		/* 0 = stereo, 1 = mono */
50#define TEA575X_BIT_BAND_MASK	(3<<20)
51#define TEA575X_BIT_BAND_FM	(0<<20)
52#define TEA575X_BIT_BAND_MW	(1<<20)
53#define TEA575X_BIT_BAND_LW	(1<<21)
54#define TEA575X_BIT_BAND_SW	(1<<22)
55#define TEA575X_BIT_PORT_0	(1<<19)		/* user bit */
56#define TEA575X_BIT_PORT_1	(1<<18)		/* user bit */
57#define TEA575X_BIT_SEARCH_MASK	(3<<16)		/* search level */
58#define TEA575X_BIT_SEARCH_5_28	     (0<<16)	/* FM >5uV, AM >28uV */
59#define TEA575X_BIT_SEARCH_10_40     (1<<16)	/* FM >10uV, AM > 40uV */
60#define TEA575X_BIT_SEARCH_30_63     (2<<16)	/* FM >30uV, AM > 63uV */
61#define TEA575X_BIT_SEARCH_150_1000  (3<<16)	/* FM > 150uV, AM > 1000uV */
62#define TEA575X_BIT_DUMMY	(1<<15)		/* buffer */
63#define TEA575X_BIT_FREQ_MASK	0x7fff
64
65/*
66 * lowlevel part
67 */
68
69static void snd_tea575x_write(struct snd_tea575x *tea, unsigned int val)
70{
71	u16 l;
72	u8 data;
73
74	tea->ops->set_direction(tea, 1);
75	udelay(16);
76
77	for (l = 25; l > 0; l--) {
78		data = (val >> 24) & TEA575X_DATA;
79		val <<= 1;			/* shift data */
80		tea->ops->set_pins(tea, data | TEA575X_WREN);
81		udelay(2);
82		tea->ops->set_pins(tea, data | TEA575X_WREN | TEA575X_CLK);
83		udelay(2);
84		tea->ops->set_pins(tea, data | TEA575X_WREN);
85		udelay(2);
86	}
87
88	if (!tea->mute)
89		tea->ops->set_pins(tea, 0);
90}
91
92static u32 snd_tea575x_read(struct snd_tea575x *tea)
93{
94	u16 l, rdata;
95	u32 data = 0;
96
97	tea->ops->set_direction(tea, 0);
98	tea->ops->set_pins(tea, 0);
99	udelay(16);
100
101	for (l = 24; l--;) {
102		tea->ops->set_pins(tea, TEA575X_CLK);
103		udelay(2);
104		if (!l)
105			tea->tuned = tea->ops->get_pins(tea) & TEA575X_MOST ? 0 : 1;
106		tea->ops->set_pins(tea, 0);
107		udelay(2);
108		data <<= 1;			/* shift data */
109		rdata = tea->ops->get_pins(tea);
110		if (!l)
111			tea->stereo = (rdata & TEA575X_MOST) ?  0 : 1;
112		if (rdata & TEA575X_DATA)
113			data++;
114		udelay(2);
115	}
116
117	if (tea->mute)
118		tea->ops->set_pins(tea, TEA575X_WREN);
119
120	return data;
121}
122
123static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
124{
125	u32 freq = snd_tea575x_read(tea) & TEA575X_BIT_FREQ_MASK;
126
127	if (freq == 0)
128		return freq;
129
130	/* freq *= 12.5 */
131	freq *= 125;
132	freq /= 10;
133	/* crystal fixup */
134	if (tea->tea5759)
135		freq += TEA575X_FMIF;
136	else
137		freq -= TEA575X_FMIF;
138
139	return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */
140}
141
142static void snd_tea575x_set_freq(struct snd_tea575x *tea)
143{
144	u32 freq = tea->freq;
145
146	freq /= 16;		/* to kHz */
147	/* crystal fixup */
148	if (tea->tea5759)
149		freq -= TEA575X_FMIF;
150	else
151		freq += TEA575X_FMIF;
152	/* freq /= 12.5 */
153	freq *= 10;
154	freq /= 125;
155
156	tea->val &= ~TEA575X_BIT_FREQ_MASK;
157	tea->val |= freq & TEA575X_BIT_FREQ_MASK;
158	snd_tea575x_write(tea, tea->val);
159}
160
161/*
162 * Linux Video interface
163 */
164
165static int vidioc_querycap(struct file *file, void  *priv,
166					struct v4l2_capability *v)
167{
168	struct snd_tea575x *tea = video_drvdata(file);
169
170	strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver));
171	strlcpy(v->card, tea->card, sizeof(v->card));
172	strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card));
173	strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info));
174	v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
175	if (!tea->cannot_read_data)
176		v->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
177	v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS;
178	return 0;
179}
180
181static int vidioc_g_tuner(struct file *file, void *priv,
182					struct v4l2_tuner *v)
183{
184	struct snd_tea575x *tea = video_drvdata(file);
185
186	if (v->index > 0)
187		return -EINVAL;
188
189	snd_tea575x_read(tea);
190
191	strcpy(v->name, "FM");
192	v->type = V4L2_TUNER_RADIO;
193	v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
194	if (!tea->cannot_read_data)
195		v->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED;
196	v->rangelow = FREQ_LO;
197	v->rangehigh = FREQ_HI;
198	v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
199	v->audmode = (tea->val & TEA575X_BIT_MONO) ?
200		V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO;
201	v->signal = tea->tuned ? 0xffff : 0;
202	return 0;
203}
204
205static int vidioc_s_tuner(struct file *file, void *priv,
206					struct v4l2_tuner *v)
207{
208	struct snd_tea575x *tea = video_drvdata(file);
209
210	if (v->index)
211		return -EINVAL;
212	tea->val &= ~TEA575X_BIT_MONO;
213	if (v->audmode == V4L2_TUNER_MODE_MONO)
214		tea->val |= TEA575X_BIT_MONO;
215	snd_tea575x_write(tea, tea->val);
216	return 0;
217}
218
219static int vidioc_g_frequency(struct file *file, void *priv,
220					struct v4l2_frequency *f)
221{
222	struct snd_tea575x *tea = video_drvdata(file);
223
224	if (f->tuner != 0)
225		return -EINVAL;
226	f->type = V4L2_TUNER_RADIO;
227	f->frequency = tea->freq;
228	return 0;
229}
230
231static int vidioc_s_frequency(struct file *file, void *priv,
232					struct v4l2_frequency *f)
233{
234	struct snd_tea575x *tea = video_drvdata(file);
235
236	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
237		return -EINVAL;
238
239	tea->val &= ~TEA575X_BIT_SEARCH;
240	tea->freq = clamp(f->frequency, FREQ_LO, FREQ_HI);
241	snd_tea575x_set_freq(tea);
242	return 0;
243}
244
245static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
246					struct v4l2_hw_freq_seek *a)
247{
248	struct snd_tea575x *tea = video_drvdata(file);
249	unsigned long timeout;
250	int i;
251
252	if (tea->cannot_read_data)
253		return -ENOTTY;
254	if (a->tuner || a->wrap_around)
255		return -EINVAL;
256
257	/* clear the frequency, HW will fill it in */
258	tea->val &= ~TEA575X_BIT_FREQ_MASK;
259	tea->val |= TEA575X_BIT_SEARCH;
260	if (a->seek_upward)
261		tea->val |= TEA575X_BIT_UPDOWN;
262	else
263		tea->val &= ~TEA575X_BIT_UPDOWN;
264	snd_tea575x_write(tea, tea->val);
265	timeout = jiffies + msecs_to_jiffies(10000);
266	for (;;) {
267		if (time_after(jiffies, timeout))
268			break;
269		if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
270			/* some signal arrived, stop search */
271			tea->val &= ~TEA575X_BIT_SEARCH;
272			snd_tea575x_set_freq(tea);
273			return -ERESTARTSYS;
274		}
275		if (!(snd_tea575x_read(tea) & TEA575X_BIT_SEARCH)) {
276			u32 freq;
277
278			/* Found a frequency, wait until it can be read */
279			for (i = 0; i < 100; i++) {
280				msleep(10);
281				freq = snd_tea575x_get_freq(tea);
282				if (freq) /* available */
283					break;
284			}
285			if (freq == 0) /* shouldn't happen */
286				break;
287			/*
288			 * if we moved by less than 50 kHz, or in the wrong
289			 * direction, continue seeking
290			 */
291			if (abs(tea->freq - freq) < 16 * 50 ||
292					(a->seek_upward && freq < tea->freq) ||
293					(!a->seek_upward && freq > tea->freq)) {
294				snd_tea575x_write(tea, tea->val);
295				continue;
296			}
297			tea->freq = freq;
298			tea->val &= ~TEA575X_BIT_SEARCH;
299			return 0;
300		}
301	}
302	tea->val &= ~TEA575X_BIT_SEARCH;
303	snd_tea575x_set_freq(tea);
304	return -ENODATA;
305}
306
307static int tea575x_s_ctrl(struct v4l2_ctrl *ctrl)
308{
309	struct snd_tea575x *tea = container_of(ctrl->handler, struct snd_tea575x, ctrl_handler);
310
311	switch (ctrl->id) {
312	case V4L2_CID_AUDIO_MUTE:
313		tea->mute = ctrl->val;
314		snd_tea575x_set_freq(tea);
315		return 0;
316	}
317
318	return -EINVAL;
319}
320
321static const struct v4l2_file_operations tea575x_fops = {
322	.owner		= THIS_MODULE,
323	.unlocked_ioctl	= video_ioctl2,
324	.open           = v4l2_fh_open,
325	.release        = v4l2_fh_release,
326	.poll           = v4l2_ctrl_poll,
327};
328
329static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
330	.vidioc_querycap    = vidioc_querycap,
331	.vidioc_g_tuner     = vidioc_g_tuner,
332	.vidioc_s_tuner     = vidioc_s_tuner,
333	.vidioc_g_frequency = vidioc_g_frequency,
334	.vidioc_s_frequency = vidioc_s_frequency,
335	.vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
336	.vidioc_log_status  = v4l2_ctrl_log_status,
337	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
338	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
339};
340
341static const struct video_device tea575x_radio = {
342	.fops           = &tea575x_fops,
343	.ioctl_ops 	= &tea575x_ioctl_ops,
344	.release        = video_device_release_empty,
345};
346
347static const struct v4l2_ctrl_ops tea575x_ctrl_ops = {
348	.s_ctrl = tea575x_s_ctrl,
349};
350
351/*
352 * initialize all the tea575x chips
353 */
354int snd_tea575x_init(struct snd_tea575x *tea)
355{
356	int retval;
357
358	tea->mute = true;
359
360	/* Not all devices can or know how to read the data back.
361	   Such devices can set cannot_read_data to true. */
362	if (!tea->cannot_read_data) {
363		snd_tea575x_write(tea, 0x55AA);
364		if (snd_tea575x_read(tea) != 0x55AA)
365			return -ENODEV;
366	}
367
368	tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_5_28;
369	tea->freq = 90500 * 16;		/* 90.5Mhz default */
370	snd_tea575x_set_freq(tea);
371
372	tea->vd = tea575x_radio;
373	video_set_drvdata(&tea->vd, tea);
374	mutex_init(&tea->mutex);
375	strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name));
376	tea->vd.lock = &tea->mutex;
377	tea->vd.v4l2_dev = tea->v4l2_dev;
378	tea->vd.ctrl_handler = &tea->ctrl_handler;
379	set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
380	/* disable hw_freq_seek if we can't use it */
381	if (tea->cannot_read_data)
382		v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
383
384	v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
385	v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
386	retval = tea->ctrl_handler.error;
387	if (retval) {
388		v4l2_err(tea->v4l2_dev, "can't initialize controls\n");
389		v4l2_ctrl_handler_free(&tea->ctrl_handler);
390		return retval;
391	}
392
393	if (tea->ext_init) {
394		retval = tea->ext_init(tea);
395		if (retval) {
396			v4l2_ctrl_handler_free(&tea->ctrl_handler);
397			return retval;
398		}
399	}
400
401	v4l2_ctrl_handler_setup(&tea->ctrl_handler);
402
403	retval = video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->radio_nr);
404	if (retval) {
405		v4l2_err(tea->v4l2_dev, "can't register video device!\n");
406		v4l2_ctrl_handler_free(&tea->ctrl_handler);
407		return retval;
408	}
409
410	return 0;
411}
412
413void snd_tea575x_exit(struct snd_tea575x *tea)
414{
415	video_unregister_device(&tea->vd);
416	v4l2_ctrl_handler_free(&tea->ctrl_handler);
417}
418
419static int __init alsa_tea575x_module_init(void)
420{
421	return 0;
422}
423
424static void __exit alsa_tea575x_module_exit(void)
425{
426}
427
428module_init(alsa_tea575x_module_init)
429module_exit(alsa_tea575x_module_exit)
430
431EXPORT_SYMBOL(snd_tea575x_init);
432EXPORT_SYMBOL(snd_tea575x_exit);
433