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->frequency < RSF16_MINFREQ || 255 f->frequency > RSF16_MAXFREQ) 256 return -EINVAL; 257 /* rounding in steps of 200 to match the freq 258 that will be used */ 259 fmr2->curfreq = (f->frequency / 200) * 200; 260 261 /* set card freq (if not muted) */ 262 if (fmr2->curvol && !fmr2->mute) { 263 mutex_lock(&fmr2->lock); 264 fmr2_setfreq(fmr2); 265 mutex_unlock(&fmr2->lock); 266 } 267 return 0; 268 } 269 270 static int vidioc_g_frequency(struct file *file, void *priv, 271 struct v4l2_frequency *f) 272 { 273 struct fmr2 *fmr2 = video_drvdata(file); 274 275 f->type = V4L2_TUNER_RADIO; 276 f->frequency = fmr2->curfreq; 277 return 0; 278 } 279 280 static int vidioc_queryctrl(struct file *file, void *priv, 281 struct v4l2_queryctrl *qc) 282 { 283 struct fmr2 *fmr2 = video_drvdata(file); 284 285 switch (qc->id) { 286 case V4L2_CID_AUDIO_MUTE: 287 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); 288 case V4L2_CID_AUDIO_VOLUME: 289 /* Only card_type == 11 implements volume */ 290 if (fmr2->card_type == 11) 291 return v4l2_ctrl_query_fill(qc, 0, 15, 1, 0); 292 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0); 293 } 294 return -EINVAL; 295 } 296 297 static int vidioc_g_ctrl(struct file *file, void *priv, 298 struct v4l2_control *ctrl) 299 { 300 struct fmr2 *fmr2 = video_drvdata(file); 301 302 switch (ctrl->id) { 303 case V4L2_CID_AUDIO_MUTE: 304 ctrl->value = fmr2->mute; 305 return 0; 306 case V4L2_CID_AUDIO_VOLUME: 307 ctrl->value = fmr2->curvol; 308 return 0; 309 } 310 return -EINVAL; 311 } 312 313 static int vidioc_s_ctrl(struct file *file, void *priv, 314 struct v4l2_control *ctrl) 315 { 316 struct fmr2 *fmr2 = video_drvdata(file); 317 318 switch (ctrl->id) { 319 case V4L2_CID_AUDIO_MUTE: 320 fmr2->mute = ctrl->value; 321 break; 322 case V4L2_CID_AUDIO_VOLUME: 323 fmr2->curvol = ctrl->value; 324 break; 325 default: 326 return -EINVAL; 327 } 328 329 #ifdef DEBUG 330 if (fmr2->curvol && !fmr2->mute) 331 printk(KERN_DEBUG "unmute\n"); 332 else 333 printk(KERN_DEBUG "mute\n"); 334 #endif 335 336 mutex_lock(&fmr2->lock); 337 if (fmr2->curvol && !fmr2->mute) { 338 fmr2_setvolume(fmr2); 339 /* Set frequency and unmute card */ 340 fmr2_setfreq(fmr2); 341 } else 342 fmr2_mute(fmr2->io); 343 mutex_unlock(&fmr2->lock); 344 return 0; 345 } 346 347 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 348 { 349 *i = 0; 350 return 0; 351 } 352 353 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 354 { 355 return i ? -EINVAL : 0; 356 } 357 358 static int vidioc_g_audio(struct file *file, void *priv, 359 struct v4l2_audio *a) 360 { 361 a->index = 0; 362 strlcpy(a->name, "Radio", sizeof(a->name)); 363 a->capability = V4L2_AUDCAP_STEREO; 364 return 0; 365 } 366 367 static int vidioc_s_audio(struct file *file, void *priv, 368 struct v4l2_audio *a) 369 { 370 return a->index ? -EINVAL : 0; 371 } 372 373 static const struct v4l2_file_operations fmr2_fops = { 374 .owner = THIS_MODULE, 375 .ioctl = video_ioctl2, 376 }; 377 378 static const struct v4l2_ioctl_ops fmr2_ioctl_ops = { 379 .vidioc_querycap = vidioc_querycap, 380 .vidioc_g_tuner = vidioc_g_tuner, 381 .vidioc_s_tuner = vidioc_s_tuner, 382 .vidioc_g_audio = vidioc_g_audio, 383 .vidioc_s_audio = vidioc_s_audio, 384 .vidioc_g_input = vidioc_g_input, 385 .vidioc_s_input = vidioc_s_input, 386 .vidioc_g_frequency = vidioc_g_frequency, 387 .vidioc_s_frequency = vidioc_s_frequency, 388 .vidioc_queryctrl = vidioc_queryctrl, 389 .vidioc_g_ctrl = vidioc_g_ctrl, 390 .vidioc_s_ctrl = vidioc_s_ctrl, 391 }; 392 393 static int __init fmr2_init(void) 394 { 395 struct fmr2 *fmr2 = &fmr2_card; 396 struct v4l2_device *v4l2_dev = &fmr2->v4l2_dev; 397 int res; 398 399 strlcpy(v4l2_dev->name, "sf16fmr2", sizeof(v4l2_dev->name)); 400 fmr2->io = io; 401 fmr2->stereo = 1; 402 mutex_init(&fmr2->lock); 403 404 if (!request_region(fmr2->io, 2, "sf16fmr2")) { 405 v4l2_err(v4l2_dev, "request_region failed!\n"); 406 return -EBUSY; 407 } 408 409 res = v4l2_device_register(NULL, v4l2_dev); 410 if (res < 0) { 411 release_region(fmr2->io, 2); 412 v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); 413 return res; 414 } 415 416 strlcpy(fmr2->vdev.name, v4l2_dev->name, sizeof(fmr2->vdev.name)); 417 fmr2->vdev.v4l2_dev = v4l2_dev; 418 fmr2->vdev.fops = &fmr2_fops; 419 fmr2->vdev.ioctl_ops = &fmr2_ioctl_ops; 420 fmr2->vdev.release = video_device_release_empty; 421 video_set_drvdata(&fmr2->vdev, fmr2); 422 423 if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { 424 v4l2_device_unregister(v4l2_dev); 425 release_region(fmr2->io, 2); 426 return -EINVAL; 427 } 428 429 v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io); 430 /* mute card - prevents noisy bootups */ 431 mutex_lock(&fmr2->lock); 432 fmr2_mute(fmr2->io); 433 fmr2_product_info(fmr2); 434 mutex_unlock(&fmr2->lock); 435 debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type)); 436 return 0; 437 } 438 439 static void __exit fmr2_exit(void) 440 { 441 struct fmr2 *fmr2 = &fmr2_card; 442 443 video_unregister_device(&fmr2->vdev); 444 v4l2_device_unregister(&fmr2->v4l2_dev); 445 release_region(fmr2->io, 2); 446 } 447 448 module_init(fmr2_init); 449 module_exit(fmr2_exit); 450 451 #ifndef MODULE 452 453 static int __init fmr2_setup_io(char *str) 454 { 455 get_option(&str, &io); 456 return 1; 457 } 458 459 __setup("sf16fmr2=", fmr2_setup_io); 460 461 #endif 462