1 /* SF16FMR2 radio driver for Linux radio support 2 * heavily based on fmi driver... 3 * (c) 2000-2002 Ziglio Frediano, freddy77@angelfire.com 4 * 5 * Notes on the hardware 6 * 7 * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); 8 * No volume control - only mute/unmute - you have to use line volume 9 * 10 * For read stereo/mono you must wait 0.1 sec after set frequency and 11 * card unmuted so I set frequency on unmute 12 * Signal handling seem to work only on autoscanning (not implemented) 13 * 14 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org> 15 */ 16 17 #include <linux/module.h> /* Modules */ 18 #include <linux/init.h> /* Initdata */ 19 #include <linux/ioport.h> /* request_region */ 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 */ 24 #include <media/v4l2-common.h> 25 #include <linux/mutex.h> 26 27 #define RADIO_VERSION KERNEL_VERSION(0,0,2) 28 29 static struct v4l2_queryctrl radio_qctrl[] = { 30 { 31 .id = V4L2_CID_AUDIO_MUTE, 32 .name = "Mute", 33 .minimum = 0, 34 .maximum = 1, 35 .default_value = 1, 36 .type = V4L2_CTRL_TYPE_BOOLEAN, 37 },{ 38 .id = V4L2_CID_AUDIO_VOLUME, 39 .name = "Volume", 40 .minimum = 0, 41 .maximum = 65535, 42 .step = 1<<12, 43 .default_value = 0xff, 44 .type = V4L2_CTRL_TYPE_INTEGER, 45 } 46 }; 47 48 static struct mutex lock; 49 50 #undef DEBUG 51 //#define DEBUG 1 52 53 #ifdef DEBUG 54 # define debug_print(s) printk s 55 #else 56 # define debug_print(s) 57 #endif 58 59 /* this should be static vars for module size */ 60 struct fmr2_device 61 { 62 int port; 63 int curvol; /* 0-65535, if not volume 0 or 65535 */ 64 int mute; 65 int stereo; /* card is producing stereo audio */ 66 unsigned long curfreq; /* freq in kHz */ 67 int card_type; 68 __u32 flags; 69 }; 70 71 static int io = 0x384; 72 static int radio_nr = -1; 73 74 /* hw precision is 12.5 kHz 75 * It is only useful to give freq in intervall of 200 (=0.0125Mhz), 76 * other bits will be truncated 77 */ 78 #define RSF16_ENCODE(x) ((x)/200+856) 79 #define RSF16_MINFREQ 87*16000 80 #define RSF16_MAXFREQ 108*16000 81 82 static inline void wait(int n,int port) 83 { 84 for (;n;--n) inb(port); 85 } 86 87 static void outbits(int bits, unsigned int data, int nWait, int port) 88 { 89 int bit; 90 for(;--bits>=0;) { 91 bit = (data>>bits) & 1; 92 outb(bit,port); 93 wait(nWait,port); 94 outb(bit|2,port); 95 wait(nWait,port); 96 outb(bit,port); 97 wait(nWait,port); 98 } 99 } 100 101 static inline void fmr2_mute(int port) 102 { 103 outb(0x00, port); 104 wait(4,port); 105 } 106 107 static inline void fmr2_unmute(int port) 108 { 109 outb(0x04, port); 110 wait(4,port); 111 } 112 113 static inline int fmr2_stereo_mode(int port) 114 { 115 int n = inb(port); 116 outb(6,port); 117 inb(port); 118 n = ((n>>3)&1)^1; 119 debug_print((KERN_DEBUG "stereo: %d\n", n)); 120 return n; 121 } 122 123 static int fmr2_product_info(struct fmr2_device *dev) 124 { 125 int n = inb(dev->port); 126 n &= 0xC1; 127 if (n == 0) 128 { 129 /* this should support volume set */ 130 dev->card_type = 12; 131 return 0; 132 } 133 /* not volume (mine is 11) */ 134 dev->card_type = (n==128)?11:0; 135 return n; 136 } 137 138 static inline int fmr2_getsigstr(struct fmr2_device *dev) 139 { 140 /* !!! work only if scanning freq */ 141 int port = dev->port, res = 0xffff; 142 outb(5,port); 143 wait(4,port); 144 if (!(inb(port)&1)) res = 0; 145 debug_print((KERN_DEBUG "signal: %d\n", res)); 146 return res; 147 } 148 149 /* set frequency and unmute card */ 150 static int fmr2_setfreq(struct fmr2_device *dev) 151 { 152 int port = dev->port; 153 unsigned long freq = dev->curfreq; 154 155 fmr2_mute(port); 156 157 /* 0x42 for mono output 158 * 0x102 forward scanning 159 * 0x182 scansione avanti 160 */ 161 outbits(9,0x2,3,port); 162 outbits(16,RSF16_ENCODE(freq),2,port); 163 164 fmr2_unmute(port); 165 166 /* wait 0.11 sec */ 167 msleep(110); 168 169 /* NOTE if mute this stop radio 170 you must set freq on unmute */ 171 dev->stereo = fmr2_stereo_mode(port); 172 return 0; 173 } 174 175 /* !!! not tested, in my card this does't work !!! */ 176 static int fmr2_setvolume(struct fmr2_device *dev) 177 { 178 int i,a,n, port = dev->port; 179 180 if (dev->card_type != 11) return 1; 181 182 switch( (dev->curvol+(1<<11)) >> 12 ) 183 { 184 case 0: case 1: n = 0x21; break; 185 case 2: n = 0x84; break; 186 case 3: n = 0x90; break; 187 case 4: n = 0x104; break; 188 case 5: n = 0x110; break; 189 case 6: n = 0x204; break; 190 case 7: n = 0x210; break; 191 case 8: n = 0x402; break; 192 case 9: n = 0x404; break; 193 default: 194 case 10: n = 0x408; break; 195 case 11: n = 0x410; break; 196 case 12: n = 0x801; break; 197 case 13: n = 0x802; break; 198 case 14: n = 0x804; break; 199 case 15: n = 0x808; break; 200 case 16: n = 0x810; break; 201 } 202 for(i=12;--i>=0;) 203 { 204 a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ 205 outb(a|4, port); 206 wait(4,port); 207 outb(a|0x24, port); 208 wait(4,port); 209 outb(a|4, port); 210 wait(4,port); 211 } 212 for(i=6;--i>=0;) 213 { 214 a = ((0x18 >> i) & 1) << 6; 215 outb(a|4, port); 216 wait(4,port); 217 outb(a|0x24, port); 218 wait(4,port); 219 outb(a|4, port); 220 wait(4,port); 221 } 222 wait(4,port); 223 outb(0x14, port); 224 225 return 0; 226 } 227 228 static int fmr2_do_ioctl(struct inode *inode, struct file *file, 229 unsigned int cmd, void *arg) 230 { 231 struct video_device *dev = video_devdata(file); 232 struct fmr2_device *fmr2 = dev->priv; 233 debug_print((KERN_DEBUG "freq %ld flags %d vol %d mute %d " 234 "stereo %d type %d\n", 235 fmr2->curfreq, fmr2->flags, fmr2->curvol, fmr2->mute, 236 fmr2->stereo, fmr2->card_type)); 237 238 switch(cmd) 239 { 240 case VIDIOC_QUERYCAP: 241 { 242 struct v4l2_capability *v = arg; 243 memset(v,0,sizeof(*v)); 244 strlcpy(v->driver, "radio-sf16fmr2", sizeof (v->driver)); 245 strlcpy(v->card, "SF16-FMR2 radio", sizeof (v->card)); 246 sprintf(v->bus_info,"ISA"); 247 v->version = RADIO_VERSION; 248 v->capabilities = V4L2_CAP_TUNER; 249 250 return 0; 251 } 252 case VIDIOC_G_TUNER: 253 { 254 struct v4l2_tuner *v = arg; 255 int mult; 256 257 if (v->index > 0) 258 return -EINVAL; 259 260 memset(v,0,sizeof(*v)); 261 strcpy(v->name, "FM"); 262 v->type = V4L2_TUNER_RADIO; 263 264 mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; 265 v->rangelow = RSF16_MINFREQ/mult; 266 v->rangehigh = RSF16_MAXFREQ/mult; 267 v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; 268 v->capability=fmr2->flags&V4L2_TUNER_CAP_LOW; 269 270 v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: 271 V4L2_TUNER_MODE_MONO; 272 mutex_lock(&lock); 273 v->signal = fmr2_getsigstr(fmr2); 274 mutex_unlock(&lock); 275 276 return 0; 277 } 278 case VIDIOC_S_TUNER: 279 { 280 struct v4l2_tuner *v = arg; 281 282 if (v->index > 0) 283 return -EINVAL; 284 285 return 0; 286 } 287 case VIDIOC_S_FREQUENCY: 288 { 289 struct v4l2_frequency *f = arg; 290 291 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) 292 f->frequency *= 1000; 293 if (f->frequency < RSF16_MINFREQ || 294 f->frequency > RSF16_MAXFREQ ) 295 return -EINVAL; 296 /*rounding in steps of 200 to match th freq 297 that will be used */ 298 fmr2->curfreq = (f->frequency/200)*200; 299 300 /* set card freq (if not muted) */ 301 if (fmr2->curvol && !fmr2->mute) 302 { 303 mutex_lock(&lock); 304 fmr2_setfreq(fmr2); 305 mutex_unlock(&lock); 306 } 307 308 return 0; 309 } 310 case VIDIOC_G_FREQUENCY: 311 { 312 struct v4l2_frequency *f = arg; 313 314 f->type = V4L2_TUNER_RADIO; 315 f->frequency = fmr2->curfreq; 316 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) 317 f->frequency /= 1000; 318 319 return 0; 320 } 321 case VIDIOC_QUERYCTRL: 322 { 323 struct v4l2_queryctrl *qc = arg; 324 int i; 325 326 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { 327 if ((fmr2->card_type != 11) 328 && V4L2_CID_AUDIO_VOLUME) 329 radio_qctrl[i].step=65535; 330 if (qc->id && qc->id == radio_qctrl[i].id) { 331 memcpy(qc, &(radio_qctrl[i]), 332 sizeof(*qc)); 333 return (0); 334 } 335 } 336 return -EINVAL; 337 } 338 case VIDIOC_G_CTRL: 339 { 340 struct v4l2_control *ctrl= arg; 341 342 switch (ctrl->id) { 343 case V4L2_CID_AUDIO_MUTE: 344 ctrl->value=fmr2->mute; 345 return (0); 346 case V4L2_CID_AUDIO_VOLUME: 347 ctrl->value=fmr2->curvol; 348 return (0); 349 } 350 return -EINVAL; 351 } 352 case VIDIOC_S_CTRL: 353 { 354 struct v4l2_control *ctrl= arg; 355 356 switch (ctrl->id) { 357 case V4L2_CID_AUDIO_MUTE: 358 fmr2->mute=ctrl->value; 359 if (fmr2->card_type != 11) { 360 if (!fmr2->mute) { 361 fmr2->curvol = 65535; 362 } else { 363 fmr2->curvol = 0; 364 } 365 } 366 break; 367 case V4L2_CID_AUDIO_VOLUME: 368 fmr2->curvol = ctrl->value; 369 if (fmr2->card_type != 11) { 370 if (fmr2->curvol) { 371 fmr2->curvol = 65535; 372 fmr2->mute = 0; 373 } else { 374 fmr2->curvol = 0; 375 fmr2->mute = 1; 376 } 377 } 378 break; 379 default: 380 return -EINVAL; 381 } 382 #ifdef DEBUG 383 if (fmr2->curvol && !fmr2->mute) 384 printk(KERN_DEBUG "unmute\n"); 385 else 386 printk(KERN_DEBUG "mute\n"); 387 #endif 388 mutex_lock(&lock); 389 if (fmr2->curvol && !fmr2->mute) { 390 fmr2_setvolume(fmr2); 391 fmr2_setfreq(fmr2); 392 } else 393 fmr2_mute(fmr2->port); 394 mutex_unlock(&lock); 395 return (0); 396 } 397 default: 398 return v4l_compat_translate_ioctl(inode,file,cmd,arg, 399 az_do_ioctl); 400 401 } 402 } 403 404 static int fmr2_ioctl(struct inode *inode, struct file *file, 405 unsigned int cmd, unsigned long arg) 406 { 407 return video_usercopy(inode, file, cmd, arg, fmr2_do_ioctl); 408 } 409 410 static struct fmr2_device fmr2_unit; 411 412 static struct file_operations fmr2_fops = { 413 .owner = THIS_MODULE, 414 .open = video_exclusive_open, 415 .release = video_exclusive_release, 416 .ioctl = fmr2_ioctl, 417 .compat_ioctl = v4l_compat_ioctl32, 418 .llseek = no_llseek, 419 }; 420 421 static struct video_device fmr2_radio= 422 { 423 .owner = THIS_MODULE, 424 .name = "SF16FMR2 radio", 425 . type = VID_TYPE_TUNER, 426 .hardware = 0, 427 .fops = &fmr2_fops, 428 }; 429 430 static int __init fmr2_init(void) 431 { 432 fmr2_unit.port = io; 433 fmr2_unit.curvol = 0; 434 fmr2_unit.mute = 0; 435 fmr2_unit.curfreq = 0; 436 fmr2_unit.stereo = 1; 437 fmr2_unit.flags = V4L2_TUNER_CAP_LOW; 438 fmr2_unit.card_type = 0; 439 fmr2_radio.priv = &fmr2_unit; 440 441 mutex_init(&lock); 442 443 if (request_region(io, 2, "sf16fmr2")) 444 { 445 printk(KERN_ERR "fmr2: port 0x%x already in use\n", io); 446 return -EBUSY; 447 } 448 449 if(video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr)==-1) 450 { 451 release_region(io, 2); 452 return -EINVAL; 453 } 454 455 printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); 456 /* mute card - prevents noisy bootups */ 457 mutex_lock(&lock); 458 fmr2_mute(io); 459 fmr2_product_info(&fmr2_unit); 460 mutex_unlock(&lock); 461 debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); 462 return 0; 463 } 464 465 MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); 466 MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); 467 MODULE_LICENSE("GPL"); 468 469 module_param(io, int, 0); 470 MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); 471 module_param(radio_nr, int, 0); 472 473 static void __exit fmr2_cleanup_module(void) 474 { 475 video_unregister_device(&fmr2_radio); 476 release_region(io,2); 477 } 478 479 module_init(fmr2_init); 480 module_exit(fmr2_cleanup_module); 481 482 #ifndef MODULE 483 484 static int __init fmr2_setup_io(char *str) 485 { 486 get_option(&str, &io); 487 return 1; 488 } 489 490 __setup("sf16fmr2=", fmr2_setup_io); 491 492 #endif 493