]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/radio/radio-gemtek.c
f959bb71c460b1081400625cc58a447872bc6b72
[linux-2.6-omap-h63xx.git] / drivers / media / radio / radio-gemtek.c
1 /* GemTek radio card driver for Linux (C) 1998 Jonas Munsin <jmunsin@iki.fi>
2  *
3  * GemTek hasn't released any specs on the card, so the protocol had to
4  * be reverse engineered with dosemu.
5  *
6  * Besides the protocol changes, this is mostly a copy of:
7  *
8  *    RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
9  *
10  *    Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
11  *    Converted to new API by Alan Cox <Alan.Cox@linux.org>
12  *    Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
13  *
14  * TODO: Allow for more than one of these foolish entities :-)
15  *
16  * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
17  */
18
19 #include <linux/module.h>       /* Modules                      */
20 #include <linux/init.h>         /* Initdata                     */
21 #include <linux/ioport.h>       /* request_region               */
22 #include <linux/delay.h>        /* udelay                       */
23 #include <asm/io.h>             /* outb, outb_p                 */
24 #include <asm/uaccess.h>        /* copy to/from user            */
25 #include <linux/videodev2.h>    /* kernel radio structs         */
26 #include <media/v4l2-common.h>
27 #include <linux/spinlock.h>
28
29 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
30 #define RADIO_VERSION KERNEL_VERSION(0,0,3)
31 #define RADIO_BANNER "GemTek Radio card driver: v0.0.3"
32
33 /*
34  * Module info.
35  */
36
37 MODULE_AUTHOR("Jonas Munsin, Pekka Seppänen <pexu@kapsi.fi>");
38 MODULE_DESCRIPTION("A driver for the GemTek Radio card.");
39 MODULE_LICENSE("GPL");
40
41 /*
42  * Module params.
43  */
44
45 #ifndef CONFIG_RADIO_GEMTEK_PORT
46 #define CONFIG_RADIO_GEMTEK_PORT -1
47 #endif
48 #ifndef CONFIG_RADIO_GEMTEK_PROBE
49 #define CONFIG_RADIO_GEMTEK_PROBE 1
50 #endif
51
52 static int io           = CONFIG_RADIO_GEMTEK_PORT;
53 static int probe        = CONFIG_RADIO_GEMTEK_PROBE;
54 static int hardmute;
55 static int shutdown     = 1;
56 static int keepmuted    = 1;
57 static int initmute     = 1;
58 static int radio_nr     = -1;
59
60 module_param(io, int, 0444);
61 MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic"
62          "probing is disabled or fails. The most common I/O ports are: 0x20c "
63          "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
64          " work for the combined sound/radiocard).");
65
66 module_param(probe, bool, 0444);
67 MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most "
68         "common I/O ports used by the card are probed.");
69
70 module_param(hardmute, bool, 0644);
71 MODULE_PARM_DESC(hardmute, "Enable `hard muting' by shutting down PLL, may "
72          "reduce static noise.");
73
74 module_param(shutdown, bool, 0644);
75 MODULE_PARM_DESC(shutdown, "Enable shutting down PLL and muting line when "
76          "module is unloaded.");
77
78 module_param(keepmuted, bool, 0644);
79 MODULE_PARM_DESC(keepmuted, "Keep card muted even when frequency is changed.");
80
81 module_param(initmute, bool, 0444);
82 MODULE_PARM_DESC(initmute, "Mute card when module is loaded.");
83
84 module_param(radio_nr, int, 0444);
85
86 /*
87  * Functions for controlling the card.
88  */
89 #define GEMTEK_LOWFREQ  (87*16000)
90 #define GEMTEK_HIGHFREQ (108*16000)
91
92 #define GEMTEK_CK               0x01    /* Clock signal                 */
93 #define GEMTEK_DA               0x02    /* Serial data                  */
94 #define GEMTEK_CE               0x04    /* Chip enable                  */
95 #define GEMTEK_NS               0x08    /* No signal                    */
96 #define GEMTEK_MT               0x10    /* Line mute                    */
97 #define GEMTEK_STDF_3_125_KHZ   0x01    /* Standard frequency 3.125 kHz */
98 #define GEMTEK_PLL_OFF          0x07    /* PLL off                      */
99
100 #define BU2614_BUS_SIZE 32      /* BU2614 / BU2614FS bus size           */
101 #define BU2614_NOPS     8       /* Number of supported operations       */
102
103 #define SHORT_DELAY 5           /* usec */
104 #define LONG_DELAY 75           /* usec */
105
106 struct gemtek_device {
107         unsigned long lastfreq;
108         int muted;
109         unsigned long bu2614data[BU2614_NOPS];
110 };
111
112 enum {
113         BU2614_VOID,
114         BU2614_FREQ,    /* D0..D15, Frequency data                      */
115         BU2614_PORT,    /* P0..P2, Output port control data             */
116         BU2614_FMES,    /* CT, Frequency measurement beginning data     */
117         BU2614_STDF,    /* R0..R2, Standard frequency data              */
118         BU2614_SWIN,    /* S, Switch between FMIN / AMIN                */
119         BU2614_SWAL,    /* PS, Swallow counter division (AMIN only)     */
120         BU2614_FMUN,    /* GT, Frequency measurement time and unlock    */
121         BU2614_TEST     /* TS, Test data is input                       */
122 };
123
124 struct bu2614_op {
125         int op;         /* Operation */
126         int size;       /* Data size */
127 };
128
129 static struct gemtek_device gemtek_unit;
130
131 static struct bu2614_op bu2614ops[] = {
132         {.op = BU2614_FREQ,
133          .size = 0x10},
134         {.op = BU2614_PORT,
135          .size = 0x03},
136         {.op = BU2614_VOID,
137          .size = 0x04},
138         {.op = BU2614_FMES,
139          .size = 0x01},
140         {.op = BU2614_STDF,
141          .size = 0x03},
142         {.op = BU2614_SWIN,
143          .size = 0x01},
144         {.op = BU2614_SWAL,
145          .size = 0x01},
146         {.op = BU2614_VOID,
147          .size = 0x01},
148         {.op = BU2614_FMUN,
149          .size = 0x01},
150         {.op = BU2614_TEST,
151          .size = 0x01}
152 };
153
154 static spinlock_t lock;
155
156 /*
157  * Set data which will be sent to BU2614FS.
158  */
159 static void gemtek_bu2614_set(struct gemtek_device *dev, int op,
160                               unsigned long data)
161 {
162         int i, q;
163
164         for (i = 0, q = 0; q < ARRAY_SIZE(dev->bu2614data); ++i) {
165                 if (bu2614ops[i].op == op) {
166                         dev->bu2614data[q] =
167                             data & ((1 << bu2614ops[i].size) - 1);
168                         return;
169                 }
170
171                 if (bu2614ops[i].op != BU2614_VOID)
172                         ++q;
173         }
174 }
175
176 /*
177  * Transmit settings to BU2614FS over GemTek IC.
178  */
179 static void gemtek_bu2614_transmit(struct gemtek_device *dev)
180 {
181         int i, bit, q, mute;
182
183         spin_lock(&lock);
184
185         mute = dev->muted ? GEMTEK_MT : 0x00;
186
187         outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
188         udelay(SHORT_DELAY);
189         outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
190         udelay(LONG_DELAY);
191
192         for (i = 0, q = 0; q < ARRAY_SIZE(dev->bu2614data); ++i) {
193                 for (bit = 0; bit < bu2614ops[i].size; ++bit) {
194                         if (bu2614ops[i].op != BU2614_VOID &&
195                             dev->bu2614data[q] & (1 << bit)) {
196                                 outb_p(mute | GEMTEK_CE | GEMTEK_DA, io);
197                                 udelay(SHORT_DELAY);
198                                 outb_p(mute | GEMTEK_CE | GEMTEK_DA |
199                                        GEMTEK_CK, io);
200                                 udelay(SHORT_DELAY);
201                         } else {
202                                 outb_p(mute | GEMTEK_CE, io);
203                                 udelay(SHORT_DELAY);
204                                 outb_p(mute | GEMTEK_CE | GEMTEK_CK, io);
205                                 udelay(SHORT_DELAY);
206                         }
207                 }
208
209                 if (bu2614ops[i].op != BU2614_VOID)
210                         ++q;
211         }
212
213         outb_p(mute | GEMTEK_DA | GEMTEK_CK, io);
214         udelay(SHORT_DELAY);
215         outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io);
216         udelay(LONG_DELAY);
217
218         spin_unlock(&lock);
219 }
220
221 /*
222  * Convert FM-frequency for BU2614FS (3.125 KHz STDF expected).
223  */
224 static inline void gemtek_convfreq(unsigned long *freq)
225 {
226         (*freq) /= 160;
227         (*freq) += 1052;        /* FMIN, 10.52 MHz              */
228         (*freq) *= 1565;        /* STDF, 1 / 156.5 = 0.00639    */
229         (*freq) /= 1000;
230 }
231
232 /*
233  * Set FM-frequency.
234  */
235 static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
236 {
237
238         if (keepmuted && hardmute && dev->muted)
239                 return;
240
241         if (freq < GEMTEK_LOWFREQ)
242                 freq = GEMTEK_LOWFREQ;
243         else if (freq > GEMTEK_HIGHFREQ)
244                 freq = GEMTEK_HIGHFREQ;
245
246         dev->lastfreq = freq;
247         dev->muted = 0;
248
249         gemtek_bu2614_set(dev, BU2614_PORT, 0);
250         gemtek_bu2614_set(dev, BU2614_FMES, 0);
251         gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode      */
252         gemtek_bu2614_set(dev, BU2614_SWAL, 0);
253         gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set   */
254         gemtek_bu2614_set(dev, BU2614_TEST, 0);
255
256         gemtek_convfreq(&freq);
257
258         gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
259         gemtek_bu2614_set(dev, BU2614_FREQ, freq);
260
261         gemtek_bu2614_transmit(dev);
262 }
263
264 /*
265  * Set mute flag.
266  */
267 static void gemtek_mute(struct gemtek_device *dev)
268 {
269         int i;
270         dev->muted = 1;
271
272         if (hardmute) {
273                 /* Turn off PLL, disable data output */
274                 gemtek_bu2614_set(dev, BU2614_PORT, 0);
275                 gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off   */
276                 gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode      */
277                 gemtek_bu2614_set(dev, BU2614_SWAL, 0);
278                 gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off   */
279                 gemtek_bu2614_set(dev, BU2614_TEST, 0);
280                 gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF);
281                 gemtek_bu2614_set(dev, BU2614_FREQ, 0);
282                 gemtek_bu2614_transmit(dev);
283         } else {
284                 spin_lock(&lock);
285
286                 /* Read bus contents (CE, CK and DA). */
287                 i = inb_p(io);
288                 /* Write it back with mute flag set. */
289                 outb_p((i >> 5) | GEMTEK_MT, io);
290                 udelay(SHORT_DELAY);
291
292                 spin_unlock(&lock);
293         }
294 }
295
296 /*
297  * Unset mute flag.
298  */
299 static void gemtek_unmute(struct gemtek_device *dev)
300 {
301         int i;
302         dev->muted = 0;
303
304         if (hardmute) {
305                 /* Turn PLL back on. */
306                 gemtek_setfreq(dev, dev->lastfreq);
307         } else {
308                 spin_lock(&lock);
309
310                 i = inb_p(io);
311                 outb_p(i >> 5, io);
312                 udelay(SHORT_DELAY);
313
314                 spin_unlock(&lock);
315         }
316 }
317
318 /*
319  * Get signal strength (= stereo status).
320  */
321 static inline int gemtek_getsigstr(void)
322 {
323         return inb_p(io) & GEMTEK_NS ? 0 : 1;
324 }
325
326 /*
327  * Check if requested card acts like GemTek Radio card.
328  */
329 static int gemtek_verify(int port)
330 {
331         static int verified = -1;
332         int i, q;
333
334         if (verified == port)
335                 return 1;
336
337         spin_lock(&lock);
338
339         q = inb_p(port);        /* Read bus contents before probing. */
340         /* Try to turn on CE, CK and DA respectively and check if card responds
341            properly. */
342         for (i = 0; i < 3; ++i) {
343                 outb_p(1 << i, port);
344                 udelay(SHORT_DELAY);
345
346                 if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) {
347                         spin_unlock(&lock);
348                         return 0;
349                 }
350         }
351         outb_p(q >> 5, port);   /* Write bus contents back. */
352         udelay(SHORT_DELAY);
353
354         spin_unlock(&lock);
355         verified = port;
356
357         return 1;
358 }
359
360 /*
361  * Automatic probing for card.
362  */
363 static int gemtek_probe(void)
364 {
365         int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
366         int i;
367
368         if (!probe) {
369                 printk(KERN_INFO "Automatic device probing disabled.\n");
370                 return -1;
371         }
372
373         printk(KERN_INFO "Automatic device probing enabled.\n");
374
375         for (i = 0; i < ARRAY_SIZE(ioports); ++i) {
376                 printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]);
377
378                 if (!request_region(ioports[i], 1, "gemtek-probe")) {
379                         printk(KERN_WARNING "I/O port 0x%x busy!\n",
380                                ioports[i]);
381                         continue;
382                 }
383
384                 if (gemtek_verify(ioports[i])) {
385                         printk(KERN_INFO "Card found from I/O port "
386                                "0x%x!\n", ioports[i]);
387
388                         release_region(ioports[i], 1);
389
390                         io = ioports[i];
391                         return io;
392                 }
393
394                 release_region(ioports[i], 1);
395         }
396
397         printk(KERN_ERR "Automatic probing failed!\n");
398
399         return -1;
400 }
401
402 /*
403  * Video 4 Linux stuff.
404  */
405
406 static struct v4l2_queryctrl radio_qctrl[] = {
407         {
408                 .id = V4L2_CID_AUDIO_MUTE,
409                 .name = "Mute",
410                 .minimum = 0,
411                 .maximum = 1,
412                 .default_value = 1,
413                 .type = V4L2_CTRL_TYPE_BOOLEAN,
414         }, {
415                 .id = V4L2_CID_AUDIO_VOLUME,
416                 .name = "Volume",
417                 .minimum = 0,
418                 .maximum = 65535,
419                 .step = 65535,
420                 .default_value = 0xff,
421                 .type = V4L2_CTRL_TYPE_INTEGER,
422         }
423 };
424
425 static struct file_operations gemtek_fops = {
426         .owner          = THIS_MODULE,
427         .open           = video_exclusive_open,
428         .release        = video_exclusive_release,
429         .ioctl          = video_ioctl2,
430         .compat_ioctl   = v4l_compat_ioctl32,
431         .llseek         = no_llseek
432 };
433
434 static int vidioc_querycap(struct file *file, void *priv,
435                            struct v4l2_capability *v)
436 {
437         strlcpy(v->driver, "radio-gemtek", sizeof(v->driver));
438         strlcpy(v->card, "GemTek", sizeof(v->card));
439         sprintf(v->bus_info, "ISA");
440         v->version = RADIO_VERSION;
441         v->capabilities = V4L2_CAP_TUNER;
442         return 0;
443 }
444
445 static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
446 {
447         if (v->index > 0)
448                 return -EINVAL;
449
450         strcpy(v->name, "FM");
451         v->type = V4L2_TUNER_RADIO;
452         v->rangelow = GEMTEK_LOWFREQ;
453         v->rangehigh = GEMTEK_HIGHFREQ;
454         v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
455         v->signal = 0xffff * gemtek_getsigstr();
456         if (v->signal) {
457                 v->audmode = V4L2_TUNER_MODE_STEREO;
458                 v->rxsubchans = V4L2_TUNER_SUB_STEREO;
459         } else {
460                 v->audmode = V4L2_TUNER_MODE_MONO;
461                 v->rxsubchans = V4L2_TUNER_SUB_MONO;
462         }
463
464         return 0;
465 }
466
467 static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
468 {
469         if (v->index > 0)
470                 return -EINVAL;
471         return 0;
472 }
473
474 static int vidioc_s_frequency(struct file *file, void *priv,
475                               struct v4l2_frequency *f)
476 {
477         struct video_device *dev = video_devdata(file);
478         struct gemtek_device *rt = dev->priv;
479
480         gemtek_setfreq(rt, f->frequency);
481
482         return 0;
483 }
484
485 static int vidioc_g_frequency(struct file *file, void *priv,
486                               struct v4l2_frequency *f)
487 {
488         struct video_device *dev = video_devdata(file);
489         struct gemtek_device *rt = dev->priv;
490
491         f->type = V4L2_TUNER_RADIO;
492         f->frequency = rt->lastfreq;
493         return 0;
494 }
495
496 static int vidioc_queryctrl(struct file *file, void *priv,
497                             struct v4l2_queryctrl *qc)
498 {
499         int i;
500
501         for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) {
502                 if (qc->id && qc->id == radio_qctrl[i].id) {
503                         memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
504                         return 0;
505                 }
506         }
507         return -EINVAL;
508 }
509
510 static int vidioc_g_ctrl(struct file *file, void *priv,
511                          struct v4l2_control *ctrl)
512 {
513         struct video_device *dev = video_devdata(file);
514         struct gemtek_device *rt = dev->priv;
515
516         switch (ctrl->id) {
517         case V4L2_CID_AUDIO_MUTE:
518                 ctrl->value = rt->muted;
519                 return 0;
520         case V4L2_CID_AUDIO_VOLUME:
521                 if (rt->muted)
522                         ctrl->value = 0;
523                 else
524                         ctrl->value = 65535;
525                 return 0;
526         }
527         return -EINVAL;
528 }
529
530 static int vidioc_s_ctrl(struct file *file, void *priv,
531                          struct v4l2_control *ctrl)
532 {
533         struct video_device *dev = video_devdata(file);
534         struct gemtek_device *rt = dev->priv;
535
536         switch (ctrl->id) {
537         case V4L2_CID_AUDIO_MUTE:
538                 if (ctrl->value)
539                         gemtek_mute(rt);
540                 else
541                         gemtek_unmute(rt);
542                 return 0;
543         case V4L2_CID_AUDIO_VOLUME:
544                 if (ctrl->value)
545                         gemtek_unmute(rt);
546                 else
547                         gemtek_mute(rt);
548                 return 0;
549         }
550         return -EINVAL;
551 }
552
553 static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
554 {
555         if (a->index > 1)
556                 return -EINVAL;
557
558         strcpy(a->name, "Radio");
559         a->capability = V4L2_AUDCAP_STEREO;
560         return 0;
561 }
562
563 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
564 {
565         *i = 0;
566         return 0;
567 }
568
569 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
570 {
571         if (i != 0)
572                 return -EINVAL;
573         return 0;
574 }
575
576 static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
577 {
578         if (a->index != 0)
579                 return -EINVAL;
580         return 0;
581 }
582
583 static struct video_device gemtek_radio = {
584         .owner                  = THIS_MODULE,
585         .name                   = "GemTek Radio card",
586         .type                   = VID_TYPE_TUNER,
587         .hardware               = VID_HARDWARE_GEMTEK,
588         .fops                   = &gemtek_fops,
589         .vidioc_querycap        = vidioc_querycap,
590         .vidioc_g_tuner         = vidioc_g_tuner,
591         .vidioc_s_tuner         = vidioc_s_tuner,
592         .vidioc_g_audio         = vidioc_g_audio,
593         .vidioc_s_audio         = vidioc_s_audio,
594         .vidioc_g_input         = vidioc_g_input,
595         .vidioc_s_input         = vidioc_s_input,
596         .vidioc_g_frequency     = vidioc_g_frequency,
597         .vidioc_s_frequency     = vidioc_s_frequency,
598         .vidioc_queryctrl       = vidioc_queryctrl,
599         .vidioc_g_ctrl          = vidioc_g_ctrl,
600         .vidioc_s_ctrl          = vidioc_s_ctrl
601 };
602
603 /*
604  * Initialization / cleanup related stuff.
605  */
606
607 /*
608  * Initilize card.
609  */
610 static int __init gemtek_init(void)
611 {
612         int i;
613
614         printk(KERN_INFO RADIO_BANNER "\n");
615
616         spin_lock_init(&lock);
617
618         gemtek_probe();
619         if (io) {
620                 if (!request_region(io, 1, "gemtek")) {
621                         printk(KERN_ERR "I/O port 0x%x already in use.\n", io);
622                         return -EBUSY;
623                 }
624
625                 if (!gemtek_verify(io))
626                         printk(KERN_WARNING "Card at I/O port 0x%x does not "
627                                "respond properly, check your "
628                                "configuration.\n", io);
629                 else
630                         printk(KERN_INFO "Using I/O port 0x%x.\n", io);
631         } else if (probe) {
632                 printk(KERN_ERR "Automatic probing failed and no "
633                        "fixed I/O port defined.\n");
634                 return -ENODEV;
635         } else {
636                 printk(KERN_ERR "Automatic probing disabled but no fixed "
637                        "I/O port defined.");
638                 return -EINVAL;
639         }
640
641         gemtek_radio.priv = &gemtek_unit;
642
643         if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO,
644                 radio_nr) == -1) {
645                 release_region(io, 1);
646                 return -EBUSY;
647         }
648
649         /* Set defaults */
650         gemtek_unit.lastfreq = GEMTEK_LOWFREQ;
651         for (i = 0; i < ARRAY_SIZE(gemtek_unit.bu2614data); ++i)
652                 gemtek_unit.bu2614data[i] = 0;
653
654         if (initmute)
655                 gemtek_mute(&gemtek_unit);
656
657         return 0;
658 }
659
660 /*
661  * Module cleanup
662  */
663 static void __exit gemtek_exit(void)
664 {
665         if (shutdown) {
666                 hardmute = 1;   /* Turn off PLL */
667                 gemtek_mute(&gemtek_unit);
668         } else {
669                 printk(KERN_INFO "Module unloaded but card not muted!\n");
670         }
671
672         video_unregister_device(&gemtek_radio);
673         release_region(io, 1);
674 }
675
676 module_init(gemtek_init);
677 module_exit(gemtek_exit);