aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio')
-rw-r--r--drivers/media/radio/radio-gemtek.c397
1 files changed, 187 insertions, 210 deletions
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 2b68be773f13..91448c47b0cf 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -20,16 +20,15 @@
20#include <linux/init.h> /* Initdata */ 20#include <linux/init.h> /* Initdata */
21#include <linux/ioport.h> /* request_region */ 21#include <linux/ioport.h> /* request_region */
22#include <linux/delay.h> /* udelay */ 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 */ 23#include <linux/videodev2.h> /* kernel radio structs */
24#include <linux/version.h> /* for KERNEL_VERSION MACRO */
25#include <linux/mutex.h>
26#include <linux/io.h> /* outb, outb_p */
27#include <linux/uaccess.h> /* copy to/from user */
26#include <media/v4l2-ioctl.h> 28#include <media/v4l2-ioctl.h>
27#include <media/v4l2-common.h> 29#include <media/v4l2-device.h>
28#include <linux/spinlock.h>
29 30
30#include <linux/version.h> /* for KERNEL_VERSION MACRO */ 31#define RADIO_VERSION KERNEL_VERSION(0, 0, 3)
31#define RADIO_VERSION KERNEL_VERSION(0,0,3)
32#define RADIO_BANNER "GemTek Radio card driver: v0.0.3"
33 32
34/* 33/*
35 * Module info. 34 * Module info.
@@ -57,7 +56,6 @@ static int shutdown = 1;
57static int keepmuted = 1; 56static int keepmuted = 1;
58static int initmute = 1; 57static int initmute = 1;
59static int radio_nr = -1; 58static int radio_nr = -1;
60static unsigned long in_use;
61 59
62module_param(io, int, 0444); 60module_param(io, int, 0444);
63MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic " 61MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
@@ -112,12 +110,19 @@ module_param(radio_nr, int, 0444);
112#define SHORT_DELAY 5 /* usec */ 110#define SHORT_DELAY 5 /* usec */
113#define LONG_DELAY 75 /* usec */ 111#define LONG_DELAY 75 /* usec */
114 112
115struct gemtek_device { 113struct gemtek {
114 struct v4l2_device v4l2_dev;
115 struct video_device vdev;
116 struct mutex lock;
116 unsigned long lastfreq; 117 unsigned long lastfreq;
117 int muted; 118 int muted;
119 int verified;
120 int io;
118 u32 bu2614data; 121 u32 bu2614data;
119}; 122};
120 123
124static struct gemtek gemtek_card;
125
121#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */ 126#define BU2614_FREQ_BITS 16 /* D0..D15, Frequency data */
122#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */ 127#define BU2614_PORT_BITS 3 /* P0..P2, Output port control data */
123#define BU2614_VOID_BITS 4 /* unused */ 128#define BU2614_VOID_BITS 4 /* unused */
@@ -153,10 +158,6 @@ struct gemtek_device {
153#define BU2614_FMUN_MASK MKMASK(FMUN) 158#define BU2614_FMUN_MASK MKMASK(FMUN)
154#define BU2614_TEST_MASK MKMASK(TEST) 159#define BU2614_TEST_MASK MKMASK(TEST)
155 160
156static struct gemtek_device gemtek_unit;
157
158static spinlock_t lock;
159
160/* 161/*
161 * Set data which will be sent to BU2614FS. 162 * Set data which will be sent to BU2614FS.
162 */ 163 */
@@ -166,33 +167,33 @@ static spinlock_t lock;
166/* 167/*
167 * Transmit settings to BU2614FS over GemTek IC. 168 * Transmit settings to BU2614FS over GemTek IC.
168 */ 169 */
169static void gemtek_bu2614_transmit(struct gemtek_device *dev) 170static void gemtek_bu2614_transmit(struct gemtek *gt)
170{ 171{
171 int i, bit, q, mute; 172 int i, bit, q, mute;
172 173
173 spin_lock(&lock); 174 mutex_lock(&gt->lock);
174 175
175 mute = dev->muted ? GEMTEK_MT : 0x00; 176 mute = gt->muted ? GEMTEK_MT : 0x00;
176 177
177 outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); 178 outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io);
178 udelay(SHORT_DELAY); 179 udelay(SHORT_DELAY);
179 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); 180 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
180 udelay(LONG_DELAY); 181 udelay(LONG_DELAY);
181 182
182 for (i = 0, q = dev->bu2614data; i < 32; i++, q >>= 1) { 183 for (i = 0, q = gt->bu2614data; i < 32; i++, q >>= 1) {
183 bit = (q & 1) ? GEMTEK_DA : 0; 184 bit = (q & 1) ? GEMTEK_DA : 0;
184 outb_p(mute | GEMTEK_CE | bit, io); 185 outb_p(mute | GEMTEK_CE | bit, gt->io);
185 udelay(SHORT_DELAY); 186 udelay(SHORT_DELAY);
186 outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, io); 187 outb_p(mute | GEMTEK_CE | bit | GEMTEK_CK, gt->io);
187 udelay(SHORT_DELAY); 188 udelay(SHORT_DELAY);
188 } 189 }
189 190
190 outb_p(mute | GEMTEK_DA | GEMTEK_CK, io); 191 outb_p(mute | GEMTEK_DA | GEMTEK_CK, gt->io);
191 udelay(SHORT_DELAY); 192 udelay(SHORT_DELAY);
192 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, io); 193 outb_p(mute | GEMTEK_CE | GEMTEK_DA | GEMTEK_CK, gt->io);
193 udelay(LONG_DELAY); 194 udelay(LONG_DELAY);
194 195
195 spin_unlock(&lock); 196 mutex_unlock(&gt->lock);
196} 197}
197 198
198/* 199/*
@@ -206,107 +207,109 @@ static unsigned long gemtek_convfreq(unsigned long freq)
206/* 207/*
207 * Set FM-frequency. 208 * Set FM-frequency.
208 */ 209 */
209static void gemtek_setfreq(struct gemtek_device *dev, unsigned long freq) 210static void gemtek_setfreq(struct gemtek *gt, unsigned long freq)
210{ 211{
211 212 if (keepmuted && hardmute && gt->muted)
212 if (keepmuted && hardmute && dev->muted)
213 return; 213 return;
214 214
215 if (freq < GEMTEK_LOWFREQ) 215 freq = clamp_val(freq, GEMTEK_LOWFREQ, GEMTEK_HIGHFREQ);
216 freq = GEMTEK_LOWFREQ;
217 else if (freq > GEMTEK_HIGHFREQ)
218 freq = GEMTEK_HIGHFREQ;
219 216
220 dev->lastfreq = freq; 217 gt->lastfreq = freq;
221 dev->muted = 0; 218 gt->muted = 0;
222 219
223 gemtek_bu2614_set(dev, BU2614_PORT, 0); 220 gemtek_bu2614_set(gt, BU2614_PORT, 0);
224 gemtek_bu2614_set(dev, BU2614_FMES, 0); 221 gemtek_bu2614_set(gt, BU2614_FMES, 0);
225 gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ 222 gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */
226 gemtek_bu2614_set(dev, BU2614_SWAL, 0); 223 gemtek_bu2614_set(gt, BU2614_SWAL, 0);
227 gemtek_bu2614_set(dev, BU2614_FMUN, 1); /* GT bit set */ 224 gemtek_bu2614_set(gt, BU2614_FMUN, 1); /* GT bit set */
228 gemtek_bu2614_set(dev, BU2614_TEST, 0); 225 gemtek_bu2614_set(gt, BU2614_TEST, 0);
229 226
230 gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_STDF_3_125_KHZ); 227 gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_STDF_3_125_KHZ);
231 gemtek_bu2614_set(dev, BU2614_FREQ, gemtek_convfreq(freq)); 228 gemtek_bu2614_set(gt, BU2614_FREQ, gemtek_convfreq(freq));
232 229
233 gemtek_bu2614_transmit(dev); 230 gemtek_bu2614_transmit(gt);
234} 231}
235 232
236/* 233/*
237 * Set mute flag. 234 * Set mute flag.
238 */ 235 */
239static void gemtek_mute(struct gemtek_device *dev) 236static void gemtek_mute(struct gemtek *gt)
240{ 237{
241 int i; 238 int i;
242 dev->muted = 1; 239
240 gt->muted = 1;
243 241
244 if (hardmute) { 242 if (hardmute) {
245 /* Turn off PLL, disable data output */ 243 /* Turn off PLL, disable data output */
246 gemtek_bu2614_set(dev, BU2614_PORT, 0); 244 gemtek_bu2614_set(gt, BU2614_PORT, 0);
247 gemtek_bu2614_set(dev, BU2614_FMES, 0); /* CT bit off */ 245 gemtek_bu2614_set(gt, BU2614_FMES, 0); /* CT bit off */
248 gemtek_bu2614_set(dev, BU2614_SWIN, 0); /* FM-mode */ 246 gemtek_bu2614_set(gt, BU2614_SWIN, 0); /* FM-mode */
249 gemtek_bu2614_set(dev, BU2614_SWAL, 0); 247 gemtek_bu2614_set(gt, BU2614_SWAL, 0);
250 gemtek_bu2614_set(dev, BU2614_FMUN, 0); /* GT bit off */ 248 gemtek_bu2614_set(gt, BU2614_FMUN, 0); /* GT bit off */
251 gemtek_bu2614_set(dev, BU2614_TEST, 0); 249 gemtek_bu2614_set(gt, BU2614_TEST, 0);
252 gemtek_bu2614_set(dev, BU2614_STDF, GEMTEK_PLL_OFF); 250 gemtek_bu2614_set(gt, BU2614_STDF, GEMTEK_PLL_OFF);
253 gemtek_bu2614_set(dev, BU2614_FREQ, 0); 251 gemtek_bu2614_set(gt, BU2614_FREQ, 0);
254 gemtek_bu2614_transmit(dev); 252 gemtek_bu2614_transmit(gt);
255 } else { 253 return;
256 spin_lock(&lock); 254 }
257 255
258 /* Read bus contents (CE, CK and DA). */ 256 mutex_lock(&gt->lock);
259 i = inb_p(io);
260 /* Write it back with mute flag set. */
261 outb_p((i >> 5) | GEMTEK_MT, io);
262 udelay(SHORT_DELAY);
263 257
264 spin_unlock(&lock); 258 /* Read bus contents (CE, CK and DA). */
265 } 259 i = inb_p(gt->io);
260 /* Write it back with mute flag set. */
261 outb_p((i >> 5) | GEMTEK_MT, gt->io);
262 udelay(SHORT_DELAY);
263
264 mutex_unlock(&gt->lock);
266} 265}
267 266
268/* 267/*
269 * Unset mute flag. 268 * Unset mute flag.
270 */ 269 */
271static void gemtek_unmute(struct gemtek_device *dev) 270static void gemtek_unmute(struct gemtek *gt)
272{ 271{
273 int i; 272 int i;
274 dev->muted = 0;
275 273
274 gt->muted = 0;
276 if (hardmute) { 275 if (hardmute) {
277 /* Turn PLL back on. */ 276 /* Turn PLL back on. */
278 gemtek_setfreq(dev, dev->lastfreq); 277 gemtek_setfreq(gt, gt->lastfreq);
279 } else { 278 return;
280 spin_lock(&lock); 279 }
280 mutex_lock(&gt->lock);
281 281
282 i = inb_p(io); 282 i = inb_p(gt->io);
283 outb_p(i >> 5, io); 283 outb_p(i >> 5, gt->io);
284 udelay(SHORT_DELAY); 284 udelay(SHORT_DELAY);
285 285
286 spin_unlock(&lock); 286 mutex_unlock(&gt->lock);
287 }
288} 287}
289 288
290/* 289/*
291 * Get signal strength (= stereo status). 290 * Get signal strength (= stereo status).
292 */ 291 */
293static inline int gemtek_getsigstr(void) 292static inline int gemtek_getsigstr(struct gemtek *gt)
294{ 293{
295 return inb_p(io) & GEMTEK_NS ? 0 : 1; 294 int sig;
295
296 mutex_lock(&gt->lock);
297 sig = inb_p(gt->io) & GEMTEK_NS ? 0 : 1;
298 mutex_unlock(&gt->lock);
299 return sig;
296} 300}
297 301
298/* 302/*
299 * Check if requested card acts like GemTek Radio card. 303 * Check if requested card acts like GemTek Radio card.
300 */ 304 */
301static int gemtek_verify(int port) 305static int gemtek_verify(struct gemtek *gt, int port)
302{ 306{
303 static int verified = -1;
304 int i, q; 307 int i, q;
305 308
306 if (verified == port) 309 if (gt->verified == port)
307 return 1; 310 return 1;
308 311
309 spin_lock(&lock); 312 mutex_lock(&gt->lock);
310 313
311 q = inb_p(port); /* Read bus contents before probing. */ 314 q = inb_p(port); /* Read bus contents before probing. */
312 /* Try to turn on CE, CK and DA respectively and check if card responds 315 /* Try to turn on CE, CK and DA respectively and check if card responds
@@ -316,15 +319,15 @@ static int gemtek_verify(int port)
316 udelay(SHORT_DELAY); 319 udelay(SHORT_DELAY);
317 320
318 if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) { 321 if ((inb_p(port) & (~GEMTEK_NS)) != (0x17 | (1 << (i + 5)))) {
319 spin_unlock(&lock); 322 mutex_unlock(&gt->lock);
320 return 0; 323 return 0;
321 } 324 }
322 } 325 }
323 outb_p(q >> 5, port); /* Write bus contents back. */ 326 outb_p(q >> 5, port); /* Write bus contents back. */
324 udelay(SHORT_DELAY); 327 udelay(SHORT_DELAY);
325 328
326 spin_unlock(&lock); 329 mutex_unlock(&gt->lock);
327 verified = port; 330 gt->verified = port;
328 331
329 return 1; 332 return 1;
330} 333}
@@ -332,83 +335,61 @@ static int gemtek_verify(int port)
332/* 335/*
333 * Automatic probing for card. 336 * Automatic probing for card.
334 */ 337 */
335static int gemtek_probe(void) 338static int gemtek_probe(struct gemtek *gt)
336{ 339{
340 struct v4l2_device *v4l2_dev = &gt->v4l2_dev;
337 int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; 341 int ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c };
338 int i; 342 int i;
339 343
340 if (!probe) { 344 if (!probe) {
341 printk(KERN_INFO "Automatic device probing disabled.\n"); 345 v4l2_info(v4l2_dev, "Automatic device probing disabled.\n");
342 return -1; 346 return -1;
343 } 347 }
344 348
345 printk(KERN_INFO "Automatic device probing enabled.\n"); 349 v4l2_info(v4l2_dev, "Automatic device probing enabled.\n");
346 350
347 for (i = 0; i < ARRAY_SIZE(ioports); ++i) { 351 for (i = 0; i < ARRAY_SIZE(ioports); ++i) {
348 printk(KERN_INFO "Trying I/O port 0x%x...\n", ioports[i]); 352 v4l2_info(v4l2_dev, "Trying I/O port 0x%x...\n", ioports[i]);
349 353
350 if (!request_region(ioports[i], 1, "gemtek-probe")) { 354 if (!request_region(ioports[i], 1, "gemtek-probe")) {
351 printk(KERN_WARNING "I/O port 0x%x busy!\n", 355 v4l2_warn(v4l2_dev, "I/O port 0x%x busy!\n",
352 ioports[i]); 356 ioports[i]);
353 continue; 357 continue;
354 } 358 }
355 359
356 if (gemtek_verify(ioports[i])) { 360 if (gemtek_verify(gt, ioports[i])) {
357 printk(KERN_INFO "Card found from I/O port " 361 v4l2_info(v4l2_dev, "Card found from I/O port "
358 "0x%x!\n", ioports[i]); 362 "0x%x!\n", ioports[i]);
359 363
360 release_region(ioports[i], 1); 364 release_region(ioports[i], 1);
361 365 gt->io = ioports[i];
362 io = ioports[i]; 366 return gt->io;
363 return io;
364 } 367 }
365 368
366 release_region(ioports[i], 1); 369 release_region(ioports[i], 1);
367 } 370 }
368 371
369 printk(KERN_ERR "Automatic probing failed!\n"); 372 v4l2_err(v4l2_dev, "Automatic probing failed!\n");
370
371 return -1; 373 return -1;
372} 374}
373 375
374/* 376/*
375 * Video 4 Linux stuff. 377 * Video 4 Linux stuff.
376 */ 378 */
377 379static int gemtek_open(struct file *file)
378static struct v4l2_queryctrl radio_qctrl[] = {
379 {
380 .id = V4L2_CID_AUDIO_MUTE,
381 .name = "Mute",
382 .minimum = 0,
383 .maximum = 1,
384 .default_value = 1,
385 .type = V4L2_CTRL_TYPE_BOOLEAN,
386 }, {
387 .id = V4L2_CID_AUDIO_VOLUME,
388 .name = "Volume",
389 .minimum = 0,
390 .maximum = 65535,
391 .step = 65535,
392 .default_value = 0xff,
393 .type = V4L2_CTRL_TYPE_INTEGER,
394 }
395};
396
397static int gemtek_exclusive_open(struct file *file)
398{ 380{
399 return test_and_set_bit(0, &in_use) ? -EBUSY : 0; 381 return 0;
400} 382}
401 383
402static int gemtek_exclusive_release(struct file *file) 384static int gemtek_release(struct file *file)
403{ 385{
404 clear_bit(0, &in_use);
405 return 0; 386 return 0;
406} 387}
407 388
408static const struct v4l2_file_operations gemtek_fops = { 389static const struct v4l2_file_operations gemtek_fops = {
409 .owner = THIS_MODULE, 390 .owner = THIS_MODULE,
410 .open = gemtek_exclusive_open, 391 .open = gemtek_open,
411 .release = gemtek_exclusive_release, 392 .release = gemtek_release,
412 .ioctl = video_ioctl2, 393 .ioctl = video_ioctl2,
413}; 394};
414 395
@@ -417,23 +398,25 @@ static int vidioc_querycap(struct file *file, void *priv,
417{ 398{
418 strlcpy(v->driver, "radio-gemtek", sizeof(v->driver)); 399 strlcpy(v->driver, "radio-gemtek", sizeof(v->driver));
419 strlcpy(v->card, "GemTek", sizeof(v->card)); 400 strlcpy(v->card, "GemTek", sizeof(v->card));
420 sprintf(v->bus_info, "ISA"); 401 strlcpy(v->bus_info, "ISA", sizeof(v->bus_info));
421 v->version = RADIO_VERSION; 402 v->version = RADIO_VERSION;
422 v->capabilities = V4L2_CAP_TUNER; 403 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
423 return 0; 404 return 0;
424} 405}
425 406
426static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) 407static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
427{ 408{
409 struct gemtek *gt = video_drvdata(file);
410
428 if (v->index > 0) 411 if (v->index > 0)
429 return -EINVAL; 412 return -EINVAL;
430 413
431 strcpy(v->name, "FM"); 414 strlcpy(v->name, "FM", sizeof(v->name));
432 v->type = V4L2_TUNER_RADIO; 415 v->type = V4L2_TUNER_RADIO;
433 v->rangelow = GEMTEK_LOWFREQ; 416 v->rangelow = GEMTEK_LOWFREQ;
434 v->rangehigh = GEMTEK_HIGHFREQ; 417 v->rangehigh = GEMTEK_HIGHFREQ;
435 v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; 418 v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
436 v->signal = 0xffff * gemtek_getsigstr(); 419 v->signal = 0xffff * gemtek_getsigstr(gt);
437 if (v->signal) { 420 if (v->signal) {
438 v->audmode = V4L2_TUNER_MODE_STEREO; 421 v->audmode = V4L2_TUNER_MODE_STEREO;
439 v->rxsubchans = V4L2_TUNER_SUB_STEREO; 422 v->rxsubchans = V4L2_TUNER_SUB_STEREO;
@@ -441,65 +424,56 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
441 v->audmode = V4L2_TUNER_MODE_MONO; 424 v->audmode = V4L2_TUNER_MODE_MONO;
442 v->rxsubchans = V4L2_TUNER_SUB_MONO; 425 v->rxsubchans = V4L2_TUNER_SUB_MONO;
443 } 426 }
444
445 return 0; 427 return 0;
446} 428}
447 429
448static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) 430static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
449{ 431{
450 if (v->index > 0) 432 return (v->index != 0) ? -EINVAL : 0;
451 return -EINVAL;
452 return 0;
453} 433}
454 434
455static int vidioc_s_frequency(struct file *file, void *priv, 435static int vidioc_g_frequency(struct file *file, void *priv,
456 struct v4l2_frequency *f) 436 struct v4l2_frequency *f)
457{ 437{
458 struct gemtek_device *rt = video_drvdata(file); 438 struct gemtek *gt = video_drvdata(file);
459
460 gemtek_setfreq(rt, f->frequency);
461 439
440 if (f->tuner != 0)
441 return -EINVAL;
442 f->type = V4L2_TUNER_RADIO;
443 f->frequency = gt->lastfreq;
462 return 0; 444 return 0;
463} 445}
464 446
465static int vidioc_g_frequency(struct file *file, void *priv, 447static int vidioc_s_frequency(struct file *file, void *priv,
466 struct v4l2_frequency *f) 448 struct v4l2_frequency *f)
467{ 449{
468 struct gemtek_device *rt = video_drvdata(file); 450 struct gemtek *gt = video_drvdata(file);
469 451
470 f->type = V4L2_TUNER_RADIO; 452 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
471 f->frequency = rt->lastfreq; 453 return -EINVAL;
454 gemtek_setfreq(gt, f->frequency);
472 return 0; 455 return 0;
473} 456}
474 457
475static int vidioc_queryctrl(struct file *file, void *priv, 458static int vidioc_queryctrl(struct file *file, void *priv,
476 struct v4l2_queryctrl *qc) 459 struct v4l2_queryctrl *qc)
477{ 460{
478 int i; 461 switch (qc->id) {
479 462 case V4L2_CID_AUDIO_MUTE:
480 for (i = 0; i < ARRAY_SIZE(radio_qctrl); ++i) { 463 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
481 if (qc->id && qc->id == radio_qctrl[i].id) { 464 default:
482 memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); 465 return -EINVAL;
483 return 0;
484 }
485 } 466 }
486 return -EINVAL;
487} 467}
488 468
489static int vidioc_g_ctrl(struct file *file, void *priv, 469static int vidioc_g_ctrl(struct file *file, void *priv,
490 struct v4l2_control *ctrl) 470 struct v4l2_control *ctrl)
491{ 471{
492 struct gemtek_device *rt = video_drvdata(file); 472 struct gemtek *gt = video_drvdata(file);
493 473
494 switch (ctrl->id) { 474 switch (ctrl->id) {
495 case V4L2_CID_AUDIO_MUTE: 475 case V4L2_CID_AUDIO_MUTE:
496 ctrl->value = rt->muted; 476 ctrl->value = gt->muted;
497 return 0;
498 case V4L2_CID_AUDIO_VOLUME:
499 if (rt->muted)
500 ctrl->value = 0;
501 else
502 ctrl->value = 65535;
503 return 0; 477 return 0;
504 } 478 }
505 return -EINVAL; 479 return -EINVAL;
@@ -508,35 +482,19 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
508static int vidioc_s_ctrl(struct file *file, void *priv, 482static int vidioc_s_ctrl(struct file *file, void *priv,
509 struct v4l2_control *ctrl) 483 struct v4l2_control *ctrl)
510{ 484{
511 struct gemtek_device *rt = video_drvdata(file); 485 struct gemtek *gt = video_drvdata(file);
512 486
513 switch (ctrl->id) { 487 switch (ctrl->id) {
514 case V4L2_CID_AUDIO_MUTE: 488 case V4L2_CID_AUDIO_MUTE:
515 if (ctrl->value) 489 if (ctrl->value)
516 gemtek_mute(rt); 490 gemtek_mute(gt);
517 else
518 gemtek_unmute(rt);
519 return 0;
520 case V4L2_CID_AUDIO_VOLUME:
521 if (ctrl->value)
522 gemtek_unmute(rt);
523 else 491 else
524 gemtek_mute(rt); 492 gemtek_unmute(gt);
525 return 0; 493 return 0;
526 } 494 }
527 return -EINVAL; 495 return -EINVAL;
528} 496}
529 497
530static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
531{
532 if (a->index > 1)
533 return -EINVAL;
534
535 strcpy(a->name, "Radio");
536 a->capability = V4L2_AUDCAP_STEREO;
537 return 0;
538}
539
540static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 498static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
541{ 499{
542 *i = 0; 500 *i = 0;
@@ -545,16 +503,20 @@ static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
545 503
546static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 504static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
547{ 505{
548 if (i != 0) 506 return (i != 0) ? -EINVAL : 0;
549 return -EINVAL; 507}
508
509static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
510{
511 a->index = 0;
512 strlcpy(a->name, "Radio", sizeof(a->name));
513 a->capability = V4L2_AUDCAP_STEREO;
550 return 0; 514 return 0;
551} 515}
552 516
553static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) 517static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
554{ 518{
555 if (a->index != 0) 519 return (a->index != 0) ? -EINVAL : 0;
556 return -EINVAL;
557 return 0;
558} 520}
559 521
560static const struct v4l2_ioctl_ops gemtek_ioctl_ops = { 522static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
@@ -572,62 +534,73 @@ static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
572 .vidioc_s_ctrl = vidioc_s_ctrl 534 .vidioc_s_ctrl = vidioc_s_ctrl
573}; 535};
574 536
575static struct video_device gemtek_radio = {
576 .name = "GemTek Radio card",
577 .fops = &gemtek_fops,
578 .ioctl_ops = &gemtek_ioctl_ops,
579 .release = video_device_release_empty,
580};
581
582/* 537/*
583 * Initialization / cleanup related stuff. 538 * Initialization / cleanup related stuff.
584 */ 539 */
585 540
586/*
587 * Initilize card.
588 */
589static int __init gemtek_init(void) 541static int __init gemtek_init(void)
590{ 542{
591 printk(KERN_INFO RADIO_BANNER "\n"); 543 struct gemtek *gt = &gemtek_card;
544 struct v4l2_device *v4l2_dev = &gt->v4l2_dev;
545 int res;
592 546
593 spin_lock_init(&lock); 547 strlcpy(v4l2_dev->name, "gemtek", sizeof(v4l2_dev->name));
594 548
595 gemtek_probe(); 549 v4l2_info(v4l2_dev, "GemTek Radio card driver: v0.0.3\n");
596 if (io) { 550
597 if (!request_region(io, 1, "gemtek")) { 551 mutex_init(&gt->lock);
598 printk(KERN_ERR "I/O port 0x%x already in use.\n", io); 552
553 gt->verified = -1;
554 gt->io = io;
555 gemtek_probe(gt);
556 if (gt->io) {
557 if (!request_region(gt->io, 1, "gemtek")) {
558 v4l2_err(v4l2_dev, "I/O port 0x%x already in use.\n", gt->io);
599 return -EBUSY; 559 return -EBUSY;
600 } 560 }
601 561
602 if (!gemtek_verify(io)) 562 if (!gemtek_verify(gt, gt->io))
603 printk(KERN_WARNING "Card at I/O port 0x%x does not " 563 v4l2_warn(v4l2_dev, "Card at I/O port 0x%x does not "
604 "respond properly, check your " 564 "respond properly, check your "
605 "configuration.\n", io); 565 "configuration.\n", gt->io);
606 else 566 else
607 printk(KERN_INFO "Using I/O port 0x%x.\n", io); 567 v4l2_info(v4l2_dev, "Using I/O port 0x%x.\n", gt->io);
608 } else if (probe) { 568 } else if (probe) {
609 printk(KERN_ERR "Automatic probing failed and no " 569 v4l2_err(v4l2_dev, "Automatic probing failed and no "
610 "fixed I/O port defined.\n"); 570 "fixed I/O port defined.\n");
611 return -ENODEV; 571 return -ENODEV;
612 } else { 572 } else {
613 printk(KERN_ERR "Automatic probing disabled but no fixed " 573 v4l2_err(v4l2_dev, "Automatic probing disabled but no fixed "
614 "I/O port defined."); 574 "I/O port defined.");
615 return -EINVAL; 575 return -EINVAL;
616 } 576 }
617 577
618 video_set_drvdata(&gemtek_radio, &gemtek_unit); 578 res = v4l2_device_register(NULL, v4l2_dev);
579 if (res < 0) {
580 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
581 release_region(gt->io, 1);
582 return res;
583 }
619 584
620 if (video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr) < 0) { 585 strlcpy(gt->vdev.name, v4l2_dev->name, sizeof(gt->vdev.name));
621 release_region(io, 1); 586 gt->vdev.v4l2_dev = v4l2_dev;
587 gt->vdev.fops = &gemtek_fops;
588 gt->vdev.ioctl_ops = &gemtek_ioctl_ops;
589 gt->vdev.release = video_device_release_empty;
590 video_set_drvdata(&gt->vdev, gt);
591
592 if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
593 v4l2_device_unregister(v4l2_dev);
594 release_region(gt->io, 1);
622 return -EBUSY; 595 return -EBUSY;
623 } 596 }
624 597
625 /* Set defaults */ 598 /* Set defaults */
626 gemtek_unit.lastfreq = GEMTEK_LOWFREQ; 599 gt->lastfreq = GEMTEK_LOWFREQ;
627 gemtek_unit.bu2614data = 0; 600 gt->bu2614data = 0;
628 601
629 if (initmute) 602 if (initmute)
630 gemtek_mute(&gemtek_unit); 603 gemtek_mute(gt);
631 604
632 return 0; 605 return 0;
633} 606}
@@ -637,15 +610,19 @@ static int __init gemtek_init(void)
637 */ 610 */
638static void __exit gemtek_exit(void) 611static void __exit gemtek_exit(void)
639{ 612{
613 struct gemtek *gt = &gemtek_card;
614 struct v4l2_device *v4l2_dev = &gt->v4l2_dev;
615
640 if (shutdown) { 616 if (shutdown) {
641 hardmute = 1; /* Turn off PLL */ 617 hardmute = 1; /* Turn off PLL */
642 gemtek_mute(&gemtek_unit); 618 gemtek_mute(gt);
643 } else { 619 } else {
644 printk(KERN_INFO "Module unloaded but card not muted!\n"); 620 v4l2_info(v4l2_dev, "Module unloaded but card not muted!\n");
645 } 621 }
646 622
647 video_unregister_device(&gemtek_radio); 623 video_unregister_device(&gt->vdev);
648 release_region(io, 1); 624 v4l2_device_unregister(&gt->v4l2_dev);
625 release_region(gt->io, 1);
649} 626}
650 627
651module_init(gemtek_init); 628module_init(gemtek_init);