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