aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/radio-sf16fmr2.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-03-06 11:53:26 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:13 -0400
commitc32a9d7155307414bb6e120f4e6581a32ed708d3 (patch)
tree9defa21bbd429818daf9db6847c10383fae2e9be /drivers/media/radio/radio-sf16fmr2.c
parentc41269fd9275cce88b90af644969c6a5e2067657 (diff)
V4L/DVB (10889): radio-sf16fmr2: 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-sf16fmr2.c')
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c372
1 files changed, 175 insertions, 197 deletions
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 92f17a347fa7..19fb7fec4135 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -18,40 +18,29 @@
18#include <linux/init.h> /* Initdata */ 18#include <linux/init.h> /* Initdata */
19#include <linux/ioport.h> /* request_region */ 19#include <linux/ioport.h> /* request_region */
20#include <linux/delay.h> /* udelay */ 20#include <linux/delay.h> /* udelay */
21#include <asm/io.h> /* outb, outb_p */
22#include <asm/uaccess.h> /* copy to/from user */
23#include <linux/videodev2.h> /* kernel radio structs */ 21#include <linux/videodev2.h> /* kernel radio structs */
24#include <media/v4l2-common.h>
25#include <media/v4l2-ioctl.h>
26#include <linux/mutex.h> 22#include <linux/mutex.h>
23#include <linux/version.h> /* for KERNEL_VERSION MACRO */
24#include <linux/io.h> /* outb, outb_p */
25#include <linux/uaccess.h> /* copy to/from user */
26#include <media/v4l2-device.h>
27#include <media/v4l2-ioctl.h>
27 28
28static struct mutex lock; 29MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com");
30MODULE_DESCRIPTION("A driver for the SF16FMR2 radio.");
31MODULE_LICENSE("GPL");
32
33static int io = 0x384;
34static int radio_nr = -1;
35
36module_param(io, int, 0);
37MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)");
38module_param(radio_nr, int, 0);
29 39
30#include <linux/version.h> /* for KERNEL_VERSION MACRO */
31#define RADIO_VERSION KERNEL_VERSION(0,0,2) 40#define RADIO_VERSION KERNEL_VERSION(0,0,2)
32 41
33#define AUD_VOL_INDEX 1 42#define AUD_VOL_INDEX 1
34 43
35static struct v4l2_queryctrl radio_qctrl[] = {
36 {
37 .id = V4L2_CID_AUDIO_MUTE,
38 .name = "Mute",
39 .minimum = 0,
40 .maximum = 1,
41 .default_value = 1,
42 .type = V4L2_CTRL_TYPE_BOOLEAN,
43 },
44 [AUD_VOL_INDEX] = {
45 .id = V4L2_CID_AUDIO_VOLUME,
46 .name = "Volume",
47 .minimum = 0,
48 .maximum = 15,
49 .step = 1,
50 .default_value = 0,
51 .type = V4L2_CTRL_TYPE_INTEGER,
52 }
53};
54
55#undef DEBUG 44#undef DEBUG
56//#define DEBUG 1 45//#define DEBUG 1
57 46
@@ -62,156 +51,160 @@ static struct v4l2_queryctrl radio_qctrl[] = {
62#endif 51#endif
63 52
64/* this should be static vars for module size */ 53/* this should be static vars for module size */
65struct fmr2_device 54struct fmr2
66{ 55{
67 unsigned long in_use; 56 struct v4l2_device v4l2_dev;
68 int port; 57 struct video_device vdev;
58 struct mutex lock;
59 int io;
69 int curvol; /* 0-15 */ 60 int curvol; /* 0-15 */
70 int mute; 61 int mute;
71 int stereo; /* card is producing stereo audio */ 62 int stereo; /* card is producing stereo audio */
72 unsigned long curfreq; /* freq in kHz */ 63 unsigned long curfreq; /* freq in kHz */
73 int card_type; 64 int card_type;
74 __u32 flags; 65 u32 flags;
75}; 66};
76 67
77static int io = 0x384; 68static struct fmr2 fmr2_card;
78static int radio_nr = -1;
79 69
80/* hw precision is 12.5 kHz 70/* hw precision is 12.5 kHz
81 * It is only useful to give freq in intervall of 200 (=0.0125Mhz), 71 * It is only useful to give freq in intervall of 200 (=0.0125Mhz),
82 * other bits will be truncated 72 * other bits will be truncated
83 */ 73 */
84#define RSF16_ENCODE(x) ((x)/200+856) 74#define RSF16_ENCODE(x) ((x) / 200 + 856)
85#define RSF16_MINFREQ 87*16000 75#define RSF16_MINFREQ (87 * 16000)
86#define RSF16_MAXFREQ 108*16000 76#define RSF16_MAXFREQ (108 * 16000)
87 77
88static inline void wait(int n,int port) 78static inline void wait(int n, int io)
89{ 79{
90 for (;n;--n) inb(port); 80 for (; n; --n)
81 inb(io);
91} 82}
92 83
93static void outbits(int bits, unsigned int data, int nWait, int port) 84static void outbits(int bits, unsigned int data, int nWait, int io)
94{ 85{
95 int bit; 86 int bit;
96 for(;--bits>=0;) { 87
97 bit = (data>>bits) & 1; 88 for (; --bits >= 0;) {
98 outb(bit,port); 89 bit = (data >> bits) & 1;
99 wait(nWait,port); 90 outb(bit, io);
100 outb(bit|2,port); 91 wait(nWait, io);
101 wait(nWait,port); 92 outb(bit | 2, io);
102 outb(bit,port); 93 wait(nWait, io);
103 wait(nWait,port); 94 outb(bit, io);
95 wait(nWait, io);
104 } 96 }
105} 97}
106 98
107static inline void fmr2_mute(int port) 99static inline void fmr2_mute(int io)
108{ 100{
109 outb(0x00, port); 101 outb(0x00, io);
110 wait(4,port); 102 wait(4, io);
111} 103}
112 104
113static inline void fmr2_unmute(int port) 105static inline void fmr2_unmute(int io)
114{ 106{
115 outb(0x04, port); 107 outb(0x04, io);
116 wait(4,port); 108 wait(4, io);
117} 109}
118 110
119static inline int fmr2_stereo_mode(int port) 111static inline int fmr2_stereo_mode(int io)
120{ 112{
121 int n = inb(port); 113 int n = inb(io);
122 outb(6,port); 114
123 inb(port); 115 outb(6, io);
124 n = ((n>>3)&1)^1; 116 inb(io);
117 n = ((n >> 3) & 1) ^ 1;
125 debug_print((KERN_DEBUG "stereo: %d\n", n)); 118 debug_print((KERN_DEBUG "stereo: %d\n", n));
126 return n; 119 return n;
127} 120}
128 121
129static int fmr2_product_info(struct fmr2_device *dev) 122static int fmr2_product_info(struct fmr2 *dev)
130{ 123{
131 int n = inb(dev->port); 124 int n = inb(dev->io);
125
132 n &= 0xC1; 126 n &= 0xC1;
133 if (n == 0) 127 if (n == 0) {
134 {
135 /* this should support volume set */ 128 /* this should support volume set */
136 dev->card_type = 12; 129 dev->card_type = 12;
137 return 0; 130 return 0;
138 } 131 }
139 /* not volume (mine is 11) */ 132 /* not volume (mine is 11) */
140 dev->card_type = (n==128)?11:0; 133 dev->card_type = (n == 128) ? 11 : 0;
141 return n; 134 return n;
142} 135}
143 136
144static inline int fmr2_getsigstr(struct fmr2_device *dev) 137static inline int fmr2_getsigstr(struct fmr2 *dev)
145{ 138{
146 /* !!! work only if scanning freq */ 139 /* !!! works only if scanning freq */
147 int port = dev->port, res = 0xffff; 140 int res = 0xffff;
148 outb(5,port); 141
149 wait(4,port); 142 outb(5, dev->io);
150 if (!(inb(port)&1)) res = 0; 143 wait(4, dev->io);
144 if (!(inb(dev->io) & 1))
145 res = 0;
151 debug_print((KERN_DEBUG "signal: %d\n", res)); 146 debug_print((KERN_DEBUG "signal: %d\n", res));
152 return res; 147 return res;
153} 148}
154 149
155/* set frequency and unmute card */ 150/* set frequency and unmute card */
156static int fmr2_setfreq(struct fmr2_device *dev) 151static int fmr2_setfreq(struct fmr2 *dev)
157{ 152{
158 int port = dev->port;
159 unsigned long freq = dev->curfreq; 153 unsigned long freq = dev->curfreq;
160 154
161 fmr2_mute(port); 155 fmr2_mute(dev->io);
162 156
163 /* 0x42 for mono output 157 /* 0x42 for mono output
164 * 0x102 forward scanning 158 * 0x102 forward scanning
165 * 0x182 scansione avanti 159 * 0x182 scansione avanti
166 */ 160 */
167 outbits(9,0x2,3,port); 161 outbits(9, 0x2, 3, dev->io);
168 outbits(16,RSF16_ENCODE(freq),2,port); 162 outbits(16, RSF16_ENCODE(freq), 2, dev->io);
169 163
170 fmr2_unmute(port); 164 fmr2_unmute(dev->io);
171 165
172 /* wait 0.11 sec */ 166 /* wait 0.11 sec */
173 msleep(110); 167 msleep(110);
174 168
175 /* NOTE if mute this stop radio 169 /* NOTE if mute this stop radio
176 you must set freq on unmute */ 170 you must set freq on unmute */
177 dev->stereo = fmr2_stereo_mode(port); 171 dev->stereo = fmr2_stereo_mode(dev->io);
178 return 0; 172 return 0;
179} 173}
180 174
181/* !!! not tested, in my card this does't work !!! */ 175/* !!! not tested, in my card this does't work !!! */
182static int fmr2_setvolume(struct fmr2_device *dev) 176static int fmr2_setvolume(struct fmr2 *dev)
183{ 177{
184 int vol[16] = { 0x021, 0x084, 0x090, 0x104, 178 int vol[16] = { 0x021, 0x084, 0x090, 0x104,
185 0x110, 0x204, 0x210, 0x402, 179 0x110, 0x204, 0x210, 0x402,
186 0x404, 0x408, 0x410, 0x801, 180 0x404, 0x408, 0x410, 0x801,
187 0x802, 0x804, 0x808, 0x810 }; 181 0x802, 0x804, 0x808, 0x810 };
188 int i, a, port = dev->port; 182 int i, a;
189 int n = vol[dev->curvol & 0x0f]; 183 int n = vol[dev->curvol & 0x0f];
190 184
191 if (dev->card_type != 11) 185 if (dev->card_type != 11)
192 return 1; 186 return 1;
193 187
194 for (i = 12; --i >= 0; ) { 188 for (i = 12; --i >= 0; ) {
195 a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ 189 a = ((n >> i) & 1) << 6; /* if (a==0) a = 0; else a = 0x40; */
196 outb(a | 4, port); 190 outb(a | 4, dev->io);
197 wait(4, port); 191 wait(4, dev->io);
198 outb(a | 0x24, port); 192 outb(a | 0x24, dev->io);
199 wait(4, port); 193 wait(4, dev->io);
200 outb(a | 4, port); 194 outb(a | 4, dev->io);
201 wait(4, port); 195 wait(4, dev->io);
202 } 196 }
203 for (i = 6; --i >= 0; ) { 197 for (i = 6; --i >= 0; ) {
204 a = ((0x18 >> i) & 1) << 6; 198 a = ((0x18 >> i) & 1) << 6;
205 outb(a | 4, port); 199 outb(a | 4, dev->io);
206 wait(4,port); 200 wait(4, dev->io);
207 outb(a | 0x24, port); 201 outb(a | 0x24, dev->io);
208 wait(4,port); 202 wait(4, dev->io);
209 outb(a|4, port); 203 outb(a | 4, dev->io);
210 wait(4,port); 204 wait(4, dev->io);
211 } 205 }
212 wait(4, port); 206 wait(4, dev->io);
213 outb(0x14, port); 207 outb(0x14, dev->io);
214
215 return 0; 208 return 0;
216} 209}
217 210
@@ -220,9 +213,9 @@ static int vidioc_querycap(struct file *file, void *priv,
220{ 213{
221 strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver)); 214 strlcpy(v->driver, "radio-sf16fmr2", sizeof(v->driver));
222 strlcpy(v->card, "SF16-FMR2 radio", sizeof(v->card)); 215 strlcpy(v->card, "SF16-FMR2 radio", sizeof(v->card));
223 sprintf(v->bus_info, "ISA"); 216 strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
224 v->version = RADIO_VERSION; 217 v->version = RADIO_VERSION;
225 v->capabilities = V4L2_CAP_TUNER; 218 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
226 return 0; 219 return 0;
227} 220}
228 221
@@ -230,54 +223,52 @@ static int vidioc_g_tuner(struct file *file, void *priv,
230 struct v4l2_tuner *v) 223 struct v4l2_tuner *v)
231{ 224{
232 int mult; 225 int mult;
233 struct fmr2_device *fmr2 = video_drvdata(file); 226 struct fmr2 *fmr2 = video_drvdata(file);
234 227
235 if (v->index > 0) 228 if (v->index > 0)
236 return -EINVAL; 229 return -EINVAL;
237 230
238 strcpy(v->name, "FM"); 231 strlcpy(v->name, "FM", sizeof(v->name));
239 v->type = V4L2_TUNER_RADIO; 232 v->type = V4L2_TUNER_RADIO;
240 233
241 mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; 234 mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
242 v->rangelow = RSF16_MINFREQ/mult; 235 v->rangelow = RSF16_MINFREQ / mult;
243 v->rangehigh = RSF16_MAXFREQ/mult; 236 v->rangehigh = RSF16_MAXFREQ / mult;
244 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; 237 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
245 v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; 238 v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW;
246 v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: 239 v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO:
247 V4L2_TUNER_MODE_MONO; 240 V4L2_TUNER_MODE_MONO;
248 mutex_lock(&lock); 241 mutex_lock(&fmr2->lock);
249 v->signal = fmr2_getsigstr(fmr2); 242 v->signal = fmr2_getsigstr(fmr2);
250 mutex_unlock(&lock); 243 mutex_unlock(&fmr2->lock);
251 return 0; 244 return 0;
252} 245}
253 246
254static int vidioc_s_tuner(struct file *file, void *priv, 247static int vidioc_s_tuner(struct file *file, void *priv,
255 struct v4l2_tuner *v) 248 struct v4l2_tuner *v)
256{ 249{
257 if (v->index > 0) 250 return v->index ? -EINVAL : 0;
258 return -EINVAL;
259 return 0;
260} 251}
261 252
262static int vidioc_s_frequency(struct file *file, void *priv, 253static int vidioc_s_frequency(struct file *file, void *priv,
263 struct v4l2_frequency *f) 254 struct v4l2_frequency *f)
264{ 255{
265 struct fmr2_device *fmr2 = video_drvdata(file); 256 struct fmr2 *fmr2 = video_drvdata(file);
266 257
267 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) 258 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
268 f->frequency *= 1000; 259 f->frequency *= 1000;
269 if (f->frequency < RSF16_MINFREQ || 260 if (f->frequency < RSF16_MINFREQ ||
270 f->frequency > RSF16_MAXFREQ ) 261 f->frequency > RSF16_MAXFREQ)
271 return -EINVAL; 262 return -EINVAL;
272 /*rounding in steps of 200 to match th freq 263 /* rounding in steps of 200 to match the freq
273 that will be used */ 264 that will be used */
274 fmr2->curfreq = (f->frequency/200)*200; 265 fmr2->curfreq = (f->frequency / 200) * 200;
275 266
276 /* set card freq (if not muted) */ 267 /* set card freq (if not muted) */
277 if (fmr2->curvol && !fmr2->mute) { 268 if (fmr2->curvol && !fmr2->mute) {
278 mutex_lock(&lock); 269 mutex_lock(&fmr2->lock);
279 fmr2_setfreq(fmr2); 270 fmr2_setfreq(fmr2);
280 mutex_unlock(&lock); 271 mutex_unlock(&fmr2->lock);
281 } 272 }
282 return 0; 273 return 0;
283} 274}
@@ -285,7 +276,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
285static int vidioc_g_frequency(struct file *file, void *priv, 276static int vidioc_g_frequency(struct file *file, void *priv,
286 struct v4l2_frequency *f) 277 struct v4l2_frequency *f)
287{ 278{
288 struct fmr2_device *fmr2 = video_drvdata(file); 279 struct fmr2 *fmr2 = video_drvdata(file);
289 280
290 f->type = V4L2_TUNER_RADIO; 281 f->type = V4L2_TUNER_RADIO;
291 f->frequency = fmr2->curfreq; 282 f->frequency = fmr2->curfreq;
@@ -297,13 +288,16 @@ static int vidioc_g_frequency(struct file *file, void *priv,
297static int vidioc_queryctrl(struct file *file, void *priv, 288static int vidioc_queryctrl(struct file *file, void *priv,
298 struct v4l2_queryctrl *qc) 289 struct v4l2_queryctrl *qc)
299{ 290{
300 int i; 291 struct fmr2 *fmr2 = video_drvdata(file);
301 292
302 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { 293 switch (qc->id) {
303 if (qc->id && qc->id == radio_qctrl[i].id) { 294 case V4L2_CID_AUDIO_MUTE:
304 memcpy(qc, &radio_qctrl[i], sizeof(*qc)); 295 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
305 return 0; 296 case V4L2_CID_AUDIO_VOLUME:
306 } 297 /* Only card_type == 11 implements volume */
298 if (fmr2->card_type == 11)
299 return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0);
300 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
307 } 301 }
308 return -EINVAL; 302 return -EINVAL;
309} 303}
@@ -311,7 +305,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
311static int vidioc_g_ctrl(struct file *file, void *priv, 305static int vidioc_g_ctrl(struct file *file, void *priv,
312 struct v4l2_control *ctrl) 306 struct v4l2_control *ctrl)
313{ 307{
314 struct fmr2_device *fmr2 = video_drvdata(file); 308 struct fmr2 *fmr2 = video_drvdata(file);
315 309
316 switch (ctrl->id) { 310 switch (ctrl->id) {
317 case V4L2_CID_AUDIO_MUTE: 311 case V4L2_CID_AUDIO_MUTE:
@@ -327,18 +321,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
327static int vidioc_s_ctrl(struct file *file, void *priv, 321static int vidioc_s_ctrl(struct file *file, void *priv,
328 struct v4l2_control *ctrl) 322 struct v4l2_control *ctrl)
329{ 323{
330 struct fmr2_device *fmr2 = video_drvdata(file); 324 struct fmr2 *fmr2 = video_drvdata(file);
331 325
332 switch (ctrl->id) { 326 switch (ctrl->id) {
333 case V4L2_CID_AUDIO_MUTE: 327 case V4L2_CID_AUDIO_MUTE:
334 fmr2->mute = ctrl->value; 328 fmr2->mute = ctrl->value;
335 break; 329 break;
336 case V4L2_CID_AUDIO_VOLUME: 330 case V4L2_CID_AUDIO_VOLUME:
337 if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum) 331 fmr2->curvol = ctrl->value;
338 fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum;
339 else
340 fmr2->curvol = ctrl->value;
341
342 break; 332 break;
343 default: 333 default:
344 return -EINVAL; 334 return -EINVAL;
@@ -351,25 +341,14 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
351 printk(KERN_DEBUG "mute\n"); 341 printk(KERN_DEBUG "mute\n");
352#endif 342#endif
353 343
354 mutex_lock(&lock); 344 mutex_lock(&fmr2->lock);
355 if (fmr2->curvol && !fmr2->mute) { 345 if (fmr2->curvol && !fmr2->mute) {
356 fmr2_setvolume(fmr2); 346 fmr2_setvolume(fmr2);
357 /* Set frequency and unmute card */ 347 /* Set frequency and unmute card */
358 fmr2_setfreq(fmr2); 348 fmr2_setfreq(fmr2);
359 } else 349 } else
360 fmr2_mute(fmr2->port); 350 fmr2_mute(fmr2->io);
361 mutex_unlock(&lock); 351 mutex_unlock(&fmr2->lock);
362 return 0;
363}
364
365static int vidioc_g_audio(struct file *file, void *priv,
366 struct v4l2_audio *a)
367{
368 if (a->index > 1)
369 return -EINVAL;
370
371 strcpy(a->name, "Radio");
372 a->capability = V4L2_AUDCAP_STEREO;
373 return 0; 352 return 0;
374} 353}
375 354
@@ -381,36 +360,38 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
381 360
382static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 361static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
383{ 362{
384 if (i != 0) 363 return i ? -EINVAL : 0;
385 return -EINVAL;
386 return 0;
387} 364}
388 365
389static int vidioc_s_audio(struct file *file, void *priv, 366static int vidioc_g_audio(struct file *file, void *priv,
390 struct v4l2_audio *a) 367 struct v4l2_audio *a)
391{ 368{
392 if (a->index != 0) 369 a->index = 0;
393 return -EINVAL; 370 strlcpy(a->name, "Radio", sizeof(a->name));
371 a->capability = V4L2_AUDCAP_STEREO;
394 return 0; 372 return 0;
395} 373}
396 374
397static struct fmr2_device fmr2_unit; 375static int vidioc_s_audio(struct file *file, void *priv,
376 struct v4l2_audio *a)
377{
378 return a->index ? -EINVAL : 0;
379}
398 380
399static int fmr2_exclusive_open(struct file *file) 381static int fmr2_open(struct file *file)
400{ 382{
401 return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0; 383 return 0;
402} 384}
403 385
404static int fmr2_exclusive_release(struct file *file) 386static int fmr2_release(struct file *file)
405{ 387{
406 clear_bit(0, &fmr2_unit.in_use);
407 return 0; 388 return 0;
408} 389}
409 390
410static const struct v4l2_file_operations fmr2_fops = { 391static const struct v4l2_file_operations fmr2_fops = {
411 .owner = THIS_MODULE, 392 .owner = THIS_MODULE,
412 .open = fmr2_exclusive_open, 393 .open = fmr2_open,
413 .release = fmr2_exclusive_release, 394 .release = fmr2_release,
414 .ioctl = video_ioctl2, 395 .ioctl = video_ioctl2,
415}; 396};
416 397
@@ -429,67 +410,64 @@ static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
429 .vidioc_s_ctrl = vidioc_s_ctrl, 410 .vidioc_s_ctrl = vidioc_s_ctrl,
430}; 411};
431 412
432static struct video_device fmr2_radio = {
433 .name = "SF16FMR2 radio",
434 .fops = &fmr2_fops,
435 .ioctl_ops = &fmr2_ioctl_ops,
436 .release = video_device_release_empty,
437};
438
439static int __init fmr2_init(void) 413static int __init fmr2_init(void)
440{ 414{
441 fmr2_unit.port = io; 415 struct fmr2 *fmr2 = &fmr2_card;
442 fmr2_unit.curvol = 0; 416 struct v4l2_device *v4l2_dev = &fmr2->v4l2_dev;
443 fmr2_unit.mute = 0; 417 int res;
444 fmr2_unit.curfreq = 0; 418
445 fmr2_unit.stereo = 1; 419 strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name));
446 fmr2_unit.flags = V4L2_TUNER_CAP_LOW; 420 fmr2->io = io;
447 fmr2_unit.card_type = 0; 421 fmr2->stereo = 1;
448 video_set_drvdata(&fmr2_radio, &fmr2_unit); 422 fmr2->flags = V4L2_TUNER_CAP_LOW;
449 423 mutex_init(&fmr2->lock);
450 mutex_init(&lock); 424
451 425 if (!request_region(fmr2->io, 2, "sf16fmr2")) {
452 if (!request_region(io, 2, "sf16fmr2")) { 426 v4l2_err(v4l2_dev, "request_region failed!\n");
453 printk(KERN_ERR "radio-sf16fmr2: request_region failed!\n");
454 return -EBUSY; 427 return -EBUSY;
455 } 428 }
456 429
457 if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) { 430 res = v4l2_device_register(NULL, v4l2_dev);
458 release_region(io, 2); 431 if (res < 0) {
459 return -EINVAL; 432 release_region(fmr2->io, 2);
433 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
434 return res;
460 } 435 }
461 436
462 printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); 437 strlcpy(fmr2->vdev.name, v4l2_dev->name, sizeof(fmr2->vdev.name));
463 /* mute card - prevents noisy bootups */ 438 fmr2->vdev.v4l2_dev = v4l2_dev;
464 mutex_lock(&lock); 439 fmr2->vdev.fops = &fmr2_fops;
465 fmr2_mute(io); 440 fmr2->vdev.ioctl_ops = &fmr2_ioctl_ops;
466 fmr2_product_info(&fmr2_unit); 441 fmr2->vdev.release = video_device_release_empty;
467 mutex_unlock(&lock); 442 video_set_drvdata(&fmr2->vdev, fmr2);
468 debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
469 443
470 /* Only card_type == 11 implements volume */ 444 if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
471 if (fmr2_unit.card_type != 11) 445 v4l2_device_unregister(v4l2_dev);
472 radio_qctrl[AUD_VOL_INDEX].maximum = 1; 446 release_region(fmr2->io, 2);
447 return -EINVAL;
448 }
473 449
450 v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io);
451 /* mute card - prevents noisy bootups */
452 mutex_lock(&fmr2->lock);
453 fmr2_mute(fmr2->io);
454 fmr2_product_info(fmr2);
455 mutex_unlock(&fmr2->lock);
456 debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));
474 return 0; 457 return 0;
475} 458}
476 459
477MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); 460static void __exit fmr2_exit(void)
478MODULE_DESCRIPTION("A driver for the SF16FMR2 radio.");
479MODULE_LICENSE("GPL");
480
481module_param(io, int, 0);
482MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)");
483module_param(radio_nr, int, 0);
484
485static void __exit fmr2_cleanup_module(void)
486{ 461{
487 video_unregister_device(&fmr2_radio); 462 struct fmr2 *fmr2 = &fmr2_card;
488 release_region(io,2); 463
464 video_unregister_device(&fmr2->vdev);
465 v4l2_device_unregister(&fmr2->v4l2_dev);
466 release_region(fmr2->io, 2);
489} 467}
490 468
491module_init(fmr2_init); 469module_init(fmr2_init);
492module_exit(fmr2_cleanup_module); 470module_exit(fmr2_exit);
493 471
494#ifndef MODULE 472#ifndef MODULE
495 473