c4c6ef73f9bf5ee32ee1f97ee62251b51d6339a1
[pandora-kernel.git] / sound / i2c / other / tea575x-tuner.c
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/interrupt.h>
26 #include <linux/init.h>
27 #include <linux/version.h>
28 #include <sound/core.h>
29 #include <sound/tea575x-tuner.h>
30
31 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
32 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
33 MODULE_LICENSE("GPL");
34
35 static int radio_nr = -1;
36 module_param(radio_nr, int, 0);
37
38 #define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
39 #define FREQ_LO          (87 * 16000)
40 #define FREQ_HI         (108 * 16000)
41
42 /*
43  * definitions
44  */
45
46 #define TEA575X_BIT_SEARCH      (1<<24)         /* 1 = search action, 0 = tuned */
47 #define TEA575X_BIT_UPDOWN      (1<<23)         /* 0 = search down, 1 = search up */
48 #define TEA575X_BIT_MONO        (1<<22)         /* 0 = stereo, 1 = mono */
49 #define TEA575X_BIT_BAND_MASK   (3<<20)
50 #define TEA575X_BIT_BAND_FM     (0<<20)
51 #define TEA575X_BIT_BAND_MW     (1<<20)
52 #define TEA575X_BIT_BAND_LW     (1<<21)
53 #define TEA575X_BIT_BAND_SW     (1<<22)
54 #define TEA575X_BIT_PORT_0      (1<<19)         /* user bit */
55 #define TEA575X_BIT_PORT_1      (1<<18)         /* user bit */
56 #define TEA575X_BIT_SEARCH_MASK (3<<16)         /* search level */
57 #define TEA575X_BIT_SEARCH_5_28      (0<<16)    /* FM >5uV, AM >28uV */
58 #define TEA575X_BIT_SEARCH_10_40     (1<<16)    /* FM >10uV, AM > 40uV */
59 #define TEA575X_BIT_SEARCH_30_63     (2<<16)    /* FM >30uV, AM > 63uV */
60 #define TEA575X_BIT_SEARCH_150_1000  (3<<16)    /* FM > 150uV, AM > 1000uV */
61 #define TEA575X_BIT_DUMMY       (1<<15)         /* buffer */
62 #define TEA575X_BIT_FREQ_MASK   0x7fff
63
64 static struct v4l2_queryctrl radio_qctrl[] = {
65         {
66                 .id            = V4L2_CID_AUDIO_MUTE,
67                 .name          = "Mute",
68                 .minimum       = 0,
69                 .maximum       = 1,
70                 .default_value = 1,
71                 .type          = V4L2_CTRL_TYPE_BOOLEAN,
72         }
73 };
74
75 /*
76  * lowlevel part
77  */
78
79 static void snd_tea575x_set_freq(struct snd_tea575x *tea)
80 {
81         unsigned long freq;
82
83         freq = tea->freq / 16;          /* to kHz */
84         if (freq > 108000)
85                 freq = 108000;
86         if (freq < 87000)
87                 freq = 87000;
88         /* crystal fixup */
89         if (tea->tea5759)
90                 freq -= tea->freq_fixup;
91         else
92                 freq += tea->freq_fixup;
93         /* freq /= 12.5 */
94         freq *= 10;
95         freq /= 125;
96
97         tea->val &= ~TEA575X_BIT_FREQ_MASK;
98         tea->val |= freq & TEA575X_BIT_FREQ_MASK;
99         tea->ops->write(tea, tea->val);
100 }
101
102 /*
103  * Linux Video interface
104  */
105
106 static int vidioc_querycap(struct file *file, void  *priv,
107                                         struct v4l2_capability *v)
108 {
109         struct snd_tea575x *tea = video_drvdata(file);
110
111         strcpy(v->card, tea->tea5759 ? "TEA5759" : "TEA5757");
112         strlcpy(v->driver, "tea575x-tuner", sizeof(v->driver));
113         strlcpy(v->card, "Maestro Radio", sizeof(v->card));
114         sprintf(v->bus_info, "PCI");
115         v->version = RADIO_VERSION;
116         v->capabilities = V4L2_CAP_TUNER;
117         return 0;
118 }
119
120 static int vidioc_g_tuner(struct file *file, void *priv,
121                                         struct v4l2_tuner *v)
122 {
123         if (v->index > 0)
124                 return -EINVAL;
125
126         strcpy(v->name, "FM");
127         v->type = V4L2_TUNER_RADIO;
128         v->rangelow = FREQ_LO;
129         v->rangehigh = FREQ_HI;
130         v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
131         v->capability = V4L2_TUNER_CAP_LOW;
132         v->audmode = V4L2_TUNER_MODE_MONO;
133         v->signal = 0xffff;
134         return 0;
135 }
136
137 static int vidioc_s_tuner(struct file *file, void *priv,
138                                         struct v4l2_tuner *v)
139 {
140         if (v->index > 0)
141                 return -EINVAL;
142         return 0;
143 }
144
145 static int vidioc_g_frequency(struct file *file, void *priv,
146                                         struct v4l2_frequency *f)
147 {
148         struct snd_tea575x *tea = video_drvdata(file);
149
150         f->type = V4L2_TUNER_RADIO;
151         f->frequency = tea->freq;
152         return 0;
153 }
154
155 static int vidioc_s_frequency(struct file *file, void *priv,
156                                         struct v4l2_frequency *f)
157 {
158         struct snd_tea575x *tea = video_drvdata(file);
159
160         if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
161                 return -EINVAL;
162
163         tea->freq = f->frequency;
164
165         snd_tea575x_set_freq(tea);
166
167         return 0;
168 }
169
170 static int vidioc_g_audio(struct file *file, void *priv,
171                                         struct v4l2_audio *a)
172 {
173         if (a->index > 1)
174                 return -EINVAL;
175
176         strcpy(a->name, "Radio");
177         a->capability = V4L2_AUDCAP_STEREO;
178         return 0;
179 }
180
181 static int vidioc_s_audio(struct file *file, void *priv,
182                                         struct v4l2_audio *a)
183 {
184         if (a->index != 0)
185                 return -EINVAL;
186         return 0;
187 }
188
189 static int vidioc_queryctrl(struct file *file, void *priv,
190                                         struct v4l2_queryctrl *qc)
191 {
192         int i;
193
194         for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
195                 if (qc->id && qc->id == radio_qctrl[i].id) {
196                         memcpy(qc, &(radio_qctrl[i]),
197                                                 sizeof(*qc));
198                         return 0;
199                 }
200         }
201         return -EINVAL;
202 }
203
204 static int vidioc_g_ctrl(struct file *file, void *priv,
205                                         struct v4l2_control *ctrl)
206 {
207         struct snd_tea575x *tea = video_drvdata(file);
208
209         switch (ctrl->id) {
210         case V4L2_CID_AUDIO_MUTE:
211                 if (tea->ops->mute) {
212                         ctrl->value = tea->mute;
213                         return 0;
214                 }
215         }
216         return -EINVAL;
217 }
218
219 static int vidioc_s_ctrl(struct file *file, void *priv,
220                                         struct v4l2_control *ctrl)
221 {
222         struct snd_tea575x *tea = video_drvdata(file);
223
224         switch (ctrl->id) {
225         case V4L2_CID_AUDIO_MUTE:
226                 if (tea->ops->mute) {
227                         tea->ops->mute(tea, ctrl->value);
228                         tea->mute = ctrl->value;
229                         return 0;
230                 }
231         }
232         return -EINVAL;
233 }
234
235 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
236 {
237         *i = 0;
238         return 0;
239 }
240
241 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
242 {
243         if (i != 0)
244                 return -EINVAL;
245         return 0;
246 }
247
248 static int snd_tea575x_exclusive_open(struct file *file)
249 {
250         struct snd_tea575x *tea = video_drvdata(file);
251
252         return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0;
253 }
254
255 static int snd_tea575x_exclusive_release(struct file *file)
256 {
257         struct snd_tea575x *tea = video_drvdata(file);
258
259         clear_bit(0, &tea->in_use);
260         return 0;
261 }
262
263 static const struct v4l2_file_operations tea575x_fops = {
264         .owner          = THIS_MODULE,
265         .open           = snd_tea575x_exclusive_open,
266         .release        = snd_tea575x_exclusive_release,
267         .ioctl          = video_ioctl2,
268 };
269
270 static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
271         .vidioc_querycap    = vidioc_querycap,
272         .vidioc_g_tuner     = vidioc_g_tuner,
273         .vidioc_s_tuner     = vidioc_s_tuner,
274         .vidioc_g_audio     = vidioc_g_audio,
275         .vidioc_s_audio     = vidioc_s_audio,
276         .vidioc_g_input     = vidioc_g_input,
277         .vidioc_s_input     = vidioc_s_input,
278         .vidioc_g_frequency = vidioc_g_frequency,
279         .vidioc_s_frequency = vidioc_s_frequency,
280         .vidioc_queryctrl   = vidioc_queryctrl,
281         .vidioc_g_ctrl      = vidioc_g_ctrl,
282         .vidioc_s_ctrl      = vidioc_s_ctrl,
283 };
284
285 static struct video_device tea575x_radio = {
286         .name           = "tea575x-tuner",
287         .fops           = &tea575x_fops,
288         .ioctl_ops      = &tea575x_ioctl_ops,
289         .release        = video_device_release,
290 };
291
292 /*
293  * initialize all the tea575x chips
294  */
295 void snd_tea575x_init(struct snd_tea575x *tea)
296 {
297         int retval;
298         unsigned int val;
299         struct video_device *tea575x_radio_inst;
300
301         val = tea->ops->read(tea);
302         if (val == 0x1ffffff || val == 0) {
303                 snd_printk(KERN_ERR
304                            "tea575x-tuner: Cannot find TEA575x chip\n");
305                 return;
306         }
307
308         tea->in_use = 0;
309         tea->val = TEA575X_BIT_BAND_FM | TEA575X_BIT_SEARCH_10_40;
310         tea->freq = 90500 * 16;         /* 90.5Mhz default */
311
312         tea575x_radio_inst = video_device_alloc();
313         if (tea575x_radio_inst == NULL) {
314                 printk(KERN_ERR "tea575x-tuner: not enough memory\n");
315                 return;
316         }
317
318         memcpy(tea575x_radio_inst, &tea575x_radio, sizeof(tea575x_radio));
319
320         strcpy(tea575x_radio.name, tea->tea5759 ?
321                                    "TEA5759 radio" : "TEA5757 radio");
322
323         video_set_drvdata(tea575x_radio_inst, tea);
324
325         retval = video_register_device(tea575x_radio_inst,
326                                        VFL_TYPE_RADIO, radio_nr);
327         if (retval) {
328                 printk(KERN_ERR "tea575x-tuner: can't register video device!\n");
329                 kfree(tea575x_radio_inst);
330                 return;
331         }
332
333         snd_tea575x_set_freq(tea);
334
335         /* mute on init */
336         if (tea->ops->mute) {
337                 tea->ops->mute(tea, 1);
338                 tea->mute = 1;
339         }
340         tea->vd = tea575x_radio_inst;
341 }
342
343 void snd_tea575x_exit(struct snd_tea575x *tea)
344 {
345         if (tea->vd) {
346                 video_unregister_device(tea->vd);
347                 tea->vd = NULL;
348         }
349 }
350
351 static int __init alsa_tea575x_module_init(void)
352 {
353         return 0;
354 }
355
356 static void __exit alsa_tea575x_module_exit(void)
357 {
358 }
359
360 module_init(alsa_tea575x_module_init)
361 module_exit(alsa_tea575x_module_exit)
362
363 EXPORT_SYMBOL(snd_tea575x_init);
364 EXPORT_SYMBOL(snd_tea575x_exit);