radio-rtrack2.c revision 8bd7ef5ae615cce5cde2e8b40445cfe4a20c3c03
1/*
2 * RadioTrack II driver
3 * Copyright 1998 Ben Pfaff
4 *
5 * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
6 * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
7 * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
8 *
9 * Converted to the radio-isa framework by Hans Verkuil <hans.verkuil@cisco.com>
10 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
11 */
12
13#include <linux/module.h>	/* Modules 			*/
14#include <linux/init.h>		/* Initdata			*/
15#include <linux/ioport.h>	/* request_region		*/
16#include <linux/delay.h>	/* udelay			*/
17#include <linux/videodev2.h>	/* kernel radio structs		*/
18#include <linux/mutex.h>
19#include <linux/io.h>		/* outb, outb_p			*/
20#include <media/v4l2-device.h>
21#include <media/v4l2-ioctl.h>
22#include "radio-isa.h"
23
24MODULE_AUTHOR("Ben Pfaff");
25MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
26MODULE_LICENSE("GPL");
27MODULE_VERSION("0.1.99");
28
29#ifndef CONFIG_RADIO_RTRACK2_PORT
30#define CONFIG_RADIO_RTRACK2_PORT -1
31#endif
32
33#define RTRACK2_MAX 2
34
35static int io[RTRACK2_MAX] = { [0] = CONFIG_RADIO_RTRACK2_PORT,
36			      [1 ... (RTRACK2_MAX - 1)] = -1 };
37static int radio_nr[RTRACK2_MAX] = { [0 ... (RTRACK2_MAX - 1)] = -1 };
38
39module_param_array(io, int, NULL, 0444);
40MODULE_PARM_DESC(io, "I/O addresses of the RadioTrack card (0x20f or 0x30f)");
41module_param_array(radio_nr, int, NULL, 0444);
42MODULE_PARM_DESC(radio_nr, "Radio device numbers");
43
44static struct radio_isa_card *rtrack2_alloc(void)
45{
46	return kzalloc(sizeof(struct radio_isa_card), GFP_KERNEL);
47}
48
49static void zero(struct radio_isa_card *isa)
50{
51	outb_p(1, isa->io);
52	outb_p(3, isa->io);
53	outb_p(1, isa->io);
54}
55
56static void one(struct radio_isa_card *isa)
57{
58	outb_p(5, isa->io);
59	outb_p(7, isa->io);
60	outb_p(5, isa->io);
61}
62
63static int rtrack2_s_frequency(struct radio_isa_card *isa, u32 freq)
64{
65	int i;
66
67	freq = freq / 200 + 856;
68
69	outb_p(0xc8, isa->io);
70	outb_p(0xc9, isa->io);
71	outb_p(0xc9, isa->io);
72
73	for (i = 0; i < 10; i++)
74		zero(isa);
75
76	for (i = 14; i >= 0; i--)
77		if (freq & (1 << i))
78			one(isa);
79		else
80			zero(isa);
81
82	outb_p(0xc8, isa->io);
83	if (!v4l2_ctrl_g_ctrl(isa->mute))
84		outb_p(0, isa->io);
85	return 0;
86}
87
88static u32 rtrack2_g_signal(struct radio_isa_card *isa)
89{
90	/* bit set = no signal present	*/
91	return (inb(isa->io) & 2) ? 0 : 0xffff;
92}
93
94static int rtrack2_s_mute_volume(struct radio_isa_card *isa, bool mute, int vol)
95{
96	outb(mute, isa->io);
97	return 0;
98}
99
100static const struct radio_isa_ops rtrack2_ops = {
101	.alloc = rtrack2_alloc,
102	.s_mute_volume = rtrack2_s_mute_volume,
103	.s_frequency = rtrack2_s_frequency,
104	.g_signal = rtrack2_g_signal,
105};
106
107static const int rtrack2_ioports[] = { 0x20f, 0x30f };
108
109static struct radio_isa_driver rtrack2_driver = {
110	.driver = {
111		.match		= radio_isa_match,
112		.probe		= radio_isa_probe,
113		.remove		= radio_isa_remove,
114		.driver		= {
115			.name	= "radio-rtrack2",
116		},
117	},
118	.io_params = io,
119	.radio_nr_params = radio_nr,
120	.io_ports = rtrack2_ioports,
121	.num_of_io_ports = ARRAY_SIZE(rtrack2_ioports),
122	.region_size = 4,
123	.card = "AIMSlab RadioTrack II",
124	.ops = &rtrack2_ops,
125	.has_stereo = true,
126};
127
128static int __init rtrack2_init(void)
129{
130	return isa_register_driver(&rtrack2_driver.driver, RTRACK2_MAX);
131}
132
133static void __exit rtrack2_exit(void)
134{
135	isa_unregister_driver(&rtrack2_driver.driver);
136}
137
138module_init(rtrack2_init);
139module_exit(rtrack2_exit);
140