aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-rtrack2.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-03-06 11:52:06 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:12 -0400
commit922c78e9f6900ade073da1a92d43c56d77cf790f (patch)
treee46f7ee11fe53296bf9f963169b8b9f7c49461c4 /drivers/media/radio/radio-rtrack2.c
parent2710e6aa3f15cb008577ce31fc469e8af7466075 (diff)
V4L/DVB (10887): radio-rtrack2: convert to v4l2_device.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio/radio-rtrack2.c')
-rw-r--r--drivers/media/radio/radio-rtrack2.c278
1 files changed, 129 insertions, 149 deletions
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 2587227214bf..08bd8d9dc4f1 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -13,34 +13,17 @@
13#include <linux/init.h> /* Initdata */ 13#include <linux/init.h> /* Initdata */
14#include <linux/ioport.h> /* request_region */ 14#include <linux/ioport.h> /* request_region */
15#include <linux/delay.h> /* udelay */ 15#include <linux/delay.h> /* udelay */
16#include <asm/io.h> /* outb, outb_p */
17#include <asm/uaccess.h> /* copy to/from user */
18#include <linux/videodev2.h> /* kernel radio structs */ 16#include <linux/videodev2.h> /* kernel radio structs */
19#include <media/v4l2-common.h> 17#include <linux/mutex.h>
18#include <linux/version.h> /* for KERNEL_VERSION MACRO */
19#include <linux/io.h> /* outb, outb_p */
20#include <linux/uaccess.h> /* copy to/from user */
21#include <media/v4l2-device.h>
20#include <media/v4l2-ioctl.h> 22#include <media/v4l2-ioctl.h>
21#include <linux/spinlock.h>
22 23
23#include <linux/version.h> /* for KERNEL_VERSION MACRO */ 24MODULE_AUTHOR("Ben Pfaff");
24#define RADIO_VERSION KERNEL_VERSION(0,0,2) 25MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
25 26MODULE_LICENSE("GPL");
26static struct v4l2_queryctrl radio_qctrl[] = {
27 {
28 .id = V4L2_CID_AUDIO_MUTE,
29 .name = "Mute",
30 .minimum = 0,
31 .maximum = 1,
32 .default_value = 1,
33 .type = V4L2_CTRL_TYPE_BOOLEAN,
34 },{
35 .id = V4L2_CID_AUDIO_VOLUME,
36 .name = "Volume",
37 .minimum = 0,
38 .maximum = 65535,
39 .step = 65535,
40 .default_value = 0xff,
41 .type = V4L2_CTRL_TYPE_INTEGER,
42 }
43};
44 27
45#ifndef CONFIG_RADIO_RTRACK2_PORT 28#ifndef CONFIG_RADIO_RTRACK2_PORT
46#define CONFIG_RADIO_RTRACK2_PORT -1 29#define CONFIG_RADIO_RTRACK2_PORT -1
@@ -48,79 +31,89 @@ static struct v4l2_queryctrl radio_qctrl[] = {
48 31
49static int io = CONFIG_RADIO_RTRACK2_PORT; 32static int io = CONFIG_RADIO_RTRACK2_PORT;
50static int radio_nr = -1; 33static int radio_nr = -1;
51static spinlock_t lock;
52 34
53struct rt_device 35module_param(io, int, 0);
36MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
37module_param(radio_nr, int, 0);
38
39#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
40
41struct rtrack2
54{ 42{
55 unsigned long in_use; 43 struct v4l2_device v4l2_dev;
56 int port; 44 struct video_device vdev;
45 int io;
57 unsigned long curfreq; 46 unsigned long curfreq;
58 int muted; 47 int muted;
48 struct mutex lock;
59}; 49};
60 50
51static struct rtrack2 rtrack2_card;
52
61 53
62/* local things */ 54/* local things */
63 55
64static void rt_mute(struct rt_device *dev) 56static void rt_mute(struct rtrack2 *dev)
65{ 57{
66 if(dev->muted) 58 if (dev->muted)
67 return; 59 return;
68 spin_lock(&lock); 60 mutex_lock(&dev->lock);
69 outb(1, io); 61 outb(1, dev->io);
70 spin_unlock(&lock); 62 mutex_unlock(&dev->lock);
63 mutex_unlock(&dev->lock);
71 dev->muted = 1; 64 dev->muted = 1;
72} 65}
73 66
74static void rt_unmute(struct rt_device *dev) 67static void rt_unmute(struct rtrack2 *dev)
75{ 68{
76 if(dev->muted == 0) 69 if(dev->muted == 0)
77 return; 70 return;
78 spin_lock(&lock); 71 mutex_lock(&dev->lock);
79 outb(0, io); 72 outb(0, dev->io);
80 spin_unlock(&lock); 73 mutex_unlock(&dev->lock);
81 dev->muted = 0; 74 dev->muted = 0;
82} 75}
83 76
84static void zero(void) 77static void zero(struct rtrack2 *dev)
85{ 78{
86 outb_p(1, io); 79 outb_p(1, dev->io);
87 outb_p(3, io); 80 outb_p(3, dev->io);
88 outb_p(1, io); 81 outb_p(1, dev->io);
89} 82}
90 83
91static void one(void) 84static void one(struct rtrack2 *dev)
92{ 85{
93 outb_p(5, io); 86 outb_p(5, dev->io);
94 outb_p(7, io); 87 outb_p(7, dev->io);
95 outb_p(5, io); 88 outb_p(5, dev->io);
96} 89}
97 90
98static int rt_setfreq(struct rt_device *dev, unsigned long freq) 91static int rt_setfreq(struct rtrack2 *dev, unsigned long freq)
99{ 92{
100 int i; 93 int i;
101 94
95 mutex_lock(&dev->lock);
96 dev->curfreq = freq;
102 freq = freq / 200 + 856; 97 freq = freq / 200 + 856;
103 98
104 spin_lock(&lock); 99 outb_p(0xc8, dev->io);
105 100 outb_p(0xc9, dev->io);
106 outb_p(0xc8, io); 101 outb_p(0xc9, dev->io);
107 outb_p(0xc9, io);
108 outb_p(0xc9, io);
109 102
110 for (i = 0; i < 10; i++) 103 for (i = 0; i < 10; i++)
111 zero (); 104 zero(dev);
112 105
113 for (i = 14; i >= 0; i--) 106 for (i = 14; i >= 0; i--)
114 if (freq & (1 << i)) 107 if (freq & (1 << i))
115 one (); 108 one(dev);
116 else 109 else
117 zero (); 110 zero(dev);
118 111
119 outb_p(0xc8, io); 112 outb_p(0xc8, dev->io);
120 if (!dev->muted) 113 if (!dev->muted)
121 outb_p(0, io); 114 outb_p(0, dev->io);
122 115
123 spin_unlock(&lock); 116 mutex_unlock(&dev->lock);
124 return 0; 117 return 0;
125} 118}
126 119
@@ -129,61 +122,61 @@ static int vidioc_querycap(struct file *file, void *priv,
129{ 122{
130 strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver)); 123 strlcpy(v->driver, "radio-rtrack2", sizeof(v->driver));
131 strlcpy(v->card, "RadioTrack II", sizeof(v->card)); 124 strlcpy(v->card, "RadioTrack II", sizeof(v->card));
132 sprintf(v->bus_info, "ISA"); 125 strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
133 v->version = RADIO_VERSION; 126 v->version = RADIO_VERSION;
134 v->capabilities = V4L2_CAP_TUNER; 127 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
135 return 0; 128 return 0;
136} 129}
137 130
138static int vidioc_s_tuner(struct file *file, void *priv, 131static int vidioc_s_tuner(struct file *file, void *priv,
139 struct v4l2_tuner *v) 132 struct v4l2_tuner *v)
140{ 133{
141 if (v->index > 0) 134 return v->index ? -EINVAL : 0;
142 return -EINVAL;
143
144 return 0;
145} 135}
146 136
147static int rt_getsigstr(struct rt_device *dev) 137static int rt_getsigstr(struct rtrack2 *dev)
148{ 138{
149 if (inb(io) & 2) /* bit set = no signal present */ 139 int sig = 1;
150 return 0; 140
151 return 1; /* signal present */ 141 mutex_lock(&dev->lock);
142 if (inb(dev->io) & 2) /* bit set = no signal present */
143 sig = 0;
144 mutex_unlock(&dev->lock);
145 return sig;
152} 146}
153 147
154static int vidioc_g_tuner(struct file *file, void *priv, 148static int vidioc_g_tuner(struct file *file, void *priv,
155 struct v4l2_tuner *v) 149 struct v4l2_tuner *v)
156{ 150{
157 struct rt_device *rt = video_drvdata(file); 151 struct rtrack2 *rt = video_drvdata(file);
158 152
159 if (v->index > 0) 153 if (v->index > 0)
160 return -EINVAL; 154 return -EINVAL;
161 155
162 strcpy(v->name, "FM"); 156 strlcpy(v->name, "FM", sizeof(v->name));
163 v->type = V4L2_TUNER_RADIO; 157 v->type = V4L2_TUNER_RADIO;
164 v->rangelow = (88*16000); 158 v->rangelow = 88 * 16000;
165 v->rangehigh = (108*16000); 159 v->rangehigh = 108 * 16000;
166 v->rxsubchans = V4L2_TUNER_SUB_MONO; 160 v->rxsubchans = V4L2_TUNER_SUB_MONO;
167 v->capability = V4L2_TUNER_CAP_LOW; 161 v->capability = V4L2_TUNER_CAP_LOW;
168 v->audmode = V4L2_TUNER_MODE_MONO; 162 v->audmode = V4L2_TUNER_MODE_MONO;
169 v->signal = 0xFFFF*rt_getsigstr(rt); 163 v->signal = 0xFFFF * rt_getsigstr(rt);
170 return 0; 164 return 0;
171} 165}
172 166
173static int vidioc_s_frequency(struct file *file, void *priv, 167static int vidioc_s_frequency(struct file *file, void *priv,
174 struct v4l2_frequency *f) 168 struct v4l2_frequency *f)
175{ 169{
176 struct rt_device *rt = video_drvdata(file); 170 struct rtrack2 *rt = video_drvdata(file);
177 171
178 rt->curfreq = f->frequency; 172 rt_setfreq(rt, f->frequency);
179 rt_setfreq(rt, rt->curfreq);
180 return 0; 173 return 0;
181} 174}
182 175
183static int vidioc_g_frequency(struct file *file, void *priv, 176static int vidioc_g_frequency(struct file *file, void *priv,
184 struct v4l2_frequency *f) 177 struct v4l2_frequency *f)
185{ 178{
186 struct rt_device *rt = video_drvdata(file); 179 struct rtrack2 *rt = video_drvdata(file);
187 180
188 f->type = V4L2_TUNER_RADIO; 181 f->type = V4L2_TUNER_RADIO;
189 f->frequency = rt->curfreq; 182 f->frequency = rt->curfreq;
@@ -193,14 +186,11 @@ static int vidioc_g_frequency(struct file *file, void *priv,
193static int vidioc_queryctrl(struct file *file, void *priv, 186static int vidioc_queryctrl(struct file *file, void *priv,
194 struct v4l2_queryctrl *qc) 187 struct v4l2_queryctrl *qc)
195{ 188{
196 int i; 189 switch (qc->id) {
197 190 case V4L2_CID_AUDIO_MUTE:
198 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { 191 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
199 if (qc->id && qc->id == radio_qctrl[i].id) { 192 case V4L2_CID_AUDIO_VOLUME:
200 memcpy(qc, &(radio_qctrl[i]), 193 return v4l2_ctrl_query_fill(qc, 0, 65535, 65535, 65535);
201 sizeof(*qc));
202 return 0;
203 }
204 } 194 }
205 return -EINVAL; 195 return -EINVAL;
206} 196}
@@ -208,7 +198,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
208static int vidioc_g_ctrl(struct file *file, void *priv, 198static int vidioc_g_ctrl(struct file *file, void *priv,
209 struct v4l2_control *ctrl) 199 struct v4l2_control *ctrl)
210{ 200{
211 struct rt_device *rt = video_drvdata(file); 201 struct rtrack2 *rt = video_drvdata(file);
212 202
213 switch (ctrl->id) { 203 switch (ctrl->id) {
214 case V4L2_CID_AUDIO_MUTE: 204 case V4L2_CID_AUDIO_MUTE:
@@ -227,7 +217,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
227static int vidioc_s_ctrl(struct file *file, void *priv, 217static int vidioc_s_ctrl(struct file *file, void *priv,
228 struct v4l2_control *ctrl) 218 struct v4l2_control *ctrl)
229{ 219{
230 struct rt_device *rt = video_drvdata(file); 220 struct rtrack2 *rt = video_drvdata(file);
231 221
232 switch (ctrl->id) { 222 switch (ctrl->id) {
233 case V4L2_CID_AUDIO_MUTE: 223 case V4L2_CID_AUDIO_MUTE:
@@ -246,17 +236,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
246 return -EINVAL; 236 return -EINVAL;
247} 237}
248 238
249static int vidioc_g_audio(struct file *file, void *priv,
250 struct v4l2_audio *a)
251{
252 if (a->index > 1)
253 return -EINVAL;
254
255 strcpy(a->name, "Radio");
256 a->capability = V4L2_AUDCAP_STEREO;
257 return 0;
258}
259
260static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 239static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
261{ 240{
262 *i = 0; 241 *i = 0;
@@ -265,36 +244,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
265 244
266static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 245static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
267{ 246{
268 if (i != 0) 247 return i ? -EINVAL : 0;
269 return -EINVAL;
270 return 0;
271} 248}
272 249
273static int vidioc_s_audio(struct file *file, void *priv, 250static int vidioc_g_audio(struct file *file, void *priv,
274 struct v4l2_audio *a) 251 struct v4l2_audio *a)
275{ 252{
276 if (a->index != 0) 253 a->index = 0;
277 return -EINVAL; 254 strlcpy(a->name, "Radio", sizeof(a->name));
255 a->capability = V4L2_AUDCAP_STEREO;
278 return 0; 256 return 0;
279} 257}
280 258
281static struct rt_device rtrack2_unit; 259static int vidioc_s_audio(struct file *file, void *priv,
260 struct v4l2_audio *a)
261{
262 return a->index ? -EINVAL : 0;
263}
282 264
283static int rtrack2_exclusive_open(struct file *file) 265static int rtrack2_open(struct file *file)
284{ 266{
285 return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0; 267 return 0;
286} 268}
287 269
288static int rtrack2_exclusive_release(struct file *file) 270static int rtrack2_release(struct file *file)
289{ 271{
290 clear_bit(0, &rtrack2_unit.in_use);
291 return 0; 272 return 0;
292} 273}
293 274
294static const struct v4l2_file_operations rtrack2_fops = { 275static const struct v4l2_file_operations rtrack2_fops = {
295 .owner = THIS_MODULE, 276 .owner = THIS_MODULE,
296 .open = rtrack2_exclusive_open, 277 .open = rtrack2_open,
297 .release = rtrack2_exclusive_release, 278 .release = rtrack2_release,
298 .ioctl = video_ioctl2, 279 .ioctl = video_ioctl2,
299}; 280};
300 281
@@ -313,62 +294,61 @@ static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
313 .vidioc_s_input = vidioc_s_input, 294 .vidioc_s_input = vidioc_s_input,
314}; 295};
315 296
316static struct video_device rtrack2_radio = {
317 .name = "RadioTrack II radio",
318 .fops = &rtrack2_fops,
319 .ioctl_ops = &rtrack2_ioctl_ops,
320 .release = video_device_release_empty,
321};
322
323static int __init rtrack2_init(void) 297static int __init rtrack2_init(void)
324{ 298{
325 if(io==-1) 299 struct rtrack2 *dev = &rtrack2_card;
326 { 300 struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
327 printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); 301 int res;
302
303 strlcpy(v4l2_dev->name, "rtrack2", sizeof(v4l2_dev->name));
304 dev->io = io;
305 if (dev->io == -1) {
306 v4l2_err(v4l2_dev, "You must set an I/O address with io=0x20c or io=0x30c\n");
328 return -EINVAL; 307 return -EINVAL;
329 } 308 }
330 if (!request_region(io, 4, "rtrack2")) 309 if (!request_region(dev->io, 4, "rtrack2")) {
331 { 310 v4l2_err(v4l2_dev, "port 0x%x already in use\n", dev->io);
332 printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
333 return -EBUSY; 311 return -EBUSY;
334 } 312 }
335 313
336 video_set_drvdata(&rtrack2_radio, &rtrack2_unit); 314 res = v4l2_device_register(NULL, v4l2_dev);
315 if (res < 0) {
316 release_region(dev->io, 4);
317 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
318 return res;
319 }
337 320
338 spin_lock_init(&lock); 321 strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
339 if (video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { 322 dev->vdev.v4l2_dev = v4l2_dev;
340 release_region(io, 4); 323 dev->vdev.fops = &rtrack2_fops;
324 dev->vdev.ioctl_ops = &rtrack2_ioctl_ops;
325 dev->vdev.release = video_device_release_empty;
326 video_set_drvdata(&dev->vdev, dev);
327
328 mutex_init(&dev->lock);
329 if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
330 v4l2_device_unregister(v4l2_dev);
331 release_region(dev->io, 4);
341 return -EINVAL; 332 return -EINVAL;
342 } 333 }
343 334
344 printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); 335 v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n");
345 336
346 /* mute card - prevents noisy bootups */ 337 /* mute card - prevents noisy bootups */
347 outb(1, io); 338 outb(1, dev->io);
348 rtrack2_unit.muted = 1; 339 dev->muted = 1;
349 340
350 return 0; 341 return 0;
351} 342}
352 343
353MODULE_AUTHOR("Ben Pfaff"); 344static void __exit rtrack2_exit(void)
354MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
355MODULE_LICENSE("GPL");
356
357module_param(io, int, 0);
358MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
359module_param(radio_nr, int, 0);
360
361static void __exit rtrack2_cleanup_module(void)
362{ 345{
363 video_unregister_device(&rtrack2_radio); 346 struct rtrack2 *dev = &rtrack2_card;
364 release_region(io,4); 347
348 video_unregister_device(&dev->vdev);
349 v4l2_device_unregister(&dev->v4l2_dev);
350 release_region(dev->io, 4);
365} 351}
366 352
367module_init(rtrack2_init); 353module_init(rtrack2_init);
368module_exit(rtrack2_cleanup_module); 354module_exit(rtrack2_exit);
369
370/*
371 Local variables:
372 compile-command: "mmake"
373 End:
374*/