1 /* 2 * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux 3 * (C) 2001 Dimitromanolakis Apostolos <apdim@grecian.net> 4 * 5 * Based in the radio Maestro PCI driver. Actually it uses the same chip 6 * for radio but different pci controller. 7 * 8 * I didn't have any specs I reversed engineered the protocol from 9 * the windows driver (radio.dll). 10 * 11 * The card uses the TEA5757 chip that includes a search function but it 12 * is useless as I haven't found any way to read back the frequency. If 13 * anybody does please mail me. 14 * 15 * For the pdf file see: 16 * http://www.nxp.com/acrobat_download2/expired_datasheets/TEA5757_5759_3.pdf 17 * 18 * 19 * CHANGES: 20 * 0.75b 21 * - better pci interface thanks to Francois Romieu <romieu@cogenit.fr> 22 * 23 * 0.75 Sun Feb 4 22:51:27 EET 2001 24 * - tiding up 25 * - removed support for multiple devices as it didn't work anyway 26 * 27 * BUGS: 28 * - card unmutes if you change frequency 29 * 30 * (c) 2006, 2007 by Mauro Carvalho Chehab <mchehab@infradead.org>: 31 * - Conversion to V4L2 API 32 * - Uses video_ioctl2 for parsing and to add debug support 33 */ 34 35 36 #include <linux/module.h> 37 #include <linux/init.h> 38 #include <linux/ioport.h> 39 #include <linux/delay.h> 40 #include <linux/mutex.h> 41 #include <linux/pci.h> 42 #include <linux/videodev2.h> 43 #include <linux/io.h> 44 #include <linux/slab.h> 45 #include <media/v4l2-device.h> 46 #include <media/v4l2-ioctl.h> 47 48 #define DRIVER_VERSION "0.7.8" 49 50 51 MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); 52 MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000 radio."); 53 MODULE_LICENSE("GPL"); 54 MODULE_VERSION(DRIVER_VERSION); 55 56 static int radio_nr = -1; 57 module_param(radio_nr, int, 0); 58 59 static int debug; 60 61 module_param(debug, int, 0644); 62 MODULE_PARM_DESC(debug, "activates debug info"); 63 64 #define dprintk(dev, num, fmt, arg...) \ 65 v4l2_dbg(num, debug, &dev->v4l2_dev, fmt, ## arg) 66 67 #ifndef PCI_VENDOR_ID_GUILLEMOT 68 #define PCI_VENDOR_ID_GUILLEMOT 0x5046 69 #endif 70 71 #ifndef PCI_DEVICE_ID_GUILLEMOT 72 #define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 73 #endif 74 75 76 /* TEA5757 pin mappings */ 77 static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; 78 79 #define FREQ_LO (87 * 16000) 80 #define FREQ_HI (108 * 16000) 81 82 #define FREQ_IF 171200 /* 10.7*16000 */ 83 #define FREQ_STEP 200 /* 12.5*16 */ 84 85 /* (x==fmhz*16*1000) -> bits */ 86 #define FREQ2BITS(x) \ 87 ((((unsigned int)(x) + FREQ_IF + (FREQ_STEP << 1)) / (FREQ_STEP << 2)) << 2) 88 89 #define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF) 90 91 92 struct maxiradio 93 { 94 struct v4l2_device v4l2_dev; 95 struct video_device vdev; 96 struct pci_dev *pdev; 97 98 u16 io; /* base of radio io */ 99 u16 muted; /* VIDEO_AUDIO_MUTE */ 100 u16 stereo; /* VIDEO_TUNER_STEREO_ON */ 101 u16 tuned; /* signal strength (0 or 0xffff) */ 102 103 unsigned long freq; 104 105 struct mutex lock; 106 }; 107 108 static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) 109 { 110 return container_of(v4l2_dev, struct maxiradio, v4l2_dev); 111 } 112 113 static void outbit(unsigned long bit, u16 io) 114 { 115 int val = power | wren | (bit ? data : 0); 116 117 outb(val, io); 118 udelay(4); 119 outb(val | clk, io); 120 udelay(4); 121 outb(val, io); 122 udelay(4); 123 } 124 125 static void turn_power(struct maxiradio *dev, int p) 126 { 127 if (p != 0) { 128 dprintk(dev, 1, "Radio powered on\n"); 129 outb(power, dev->io); 130 } else { 131 dprintk(dev, 1, "Radio powered off\n"); 132 outb(0, dev->io); 133 } 134 } 135 136 static void set_freq(struct maxiradio *dev, u32 freq) 137 { 138 unsigned long int si; 139 int bl; 140 int io = dev->io; 141 int val = FREQ2BITS(freq); 142 143 /* TEA5757 shift register bits (see pdf) */ 144 145 outbit(0, io); /* 24 search */ 146 outbit(1, io); /* 23 search up/down */ 147 148 outbit(0, io); /* 22 stereo/mono */ 149 150 outbit(0, io); /* 21 band */ 151 outbit(0, io); /* 20 band (only 00=FM works I think) */ 152 153 outbit(0, io); /* 19 port ? */ 154 outbit(0, io); /* 18 port ? */ 155 156 outbit(0, io); /* 17 search level */ 157 outbit(0, io); /* 16 search level */ 158 159 si = 0x8000; 160 for (bl = 1; bl <= 16; bl++) { 161 outbit(val & si, io); 162 si >>= 1; 163 } 164 165 dprintk(dev, 1, "Radio freq set to %d.%02d MHz\n", 166 freq / 16000, 167 freq % 16000 * 100 / 16000); 168 169 turn_power(dev, 1); 170 } 171 172 static int get_stereo(u16 io) 173 { 174 outb(power,io); 175 udelay(4); 176 177 return !(inb(io) & mo_st); 178 } 179 180 static int get_tune(u16 io) 181 { 182 outb(power+clk,io); 183 udelay(4); 184 185 return !(inb(io) & mo_st); 186 } 187 188 189 static int vidioc_querycap(struct file *file, void *priv, 190 struct v4l2_capability *v) 191 { 192 struct maxiradio *dev = video_drvdata(file); 193 194 strlcpy(v->driver, "radio-maxiradio", sizeof(v->driver)); 195 strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof(v->card)); 196 snprintf(v->bus_info, sizeof(v->bus_info), "PCI:%s", pci_name(dev->pdev)); 197 v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; 198 return 0; 199 } 200 201 static int vidioc_g_tuner(struct file *file, void *priv, 202 struct v4l2_tuner *v) 203 { 204 struct maxiradio *dev = video_drvdata(file); 205 206 if (v->index > 0) 207 return -EINVAL; 208 209 mutex_lock(&dev->lock); 210 strlcpy(v->name, "FM", sizeof(v->name)); 211 v->type = V4L2_TUNER_RADIO; 212 v->rangelow = FREQ_LO; 213 v->rangehigh = FREQ_HI; 214 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 215 v->capability = V4L2_TUNER_CAP_LOW; 216 if (get_stereo(dev->io)) 217 v->audmode = V4L2_TUNER_MODE_STEREO; 218 else 219 v->audmode = V4L2_TUNER_MODE_MONO; 220 v->signal = 0xffff * get_tune(dev->io); 221 mutex_unlock(&dev->lock); 222 223 return 0; 224 } 225 226 static int vidioc_s_tuner(struct file *file, void *priv, 227 struct v4l2_tuner *v) 228 { 229 return v->index ? -EINVAL : 0; 230 } 231 232 static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) 233 { 234 *i = 0; 235 return 0; 236 } 237 238 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) 239 { 240 return i ? -EINVAL : 0; 241 } 242 243 static int vidioc_g_audio(struct file *file, void *priv, 244 struct v4l2_audio *a) 245 { 246 a->index = 0; 247 strlcpy(a->name, "Radio", sizeof(a->name)); 248 a->capability = V4L2_AUDCAP_STEREO; 249 return 0; 250 } 251 252 253 static int vidioc_s_audio(struct file *file, void *priv, 254 struct v4l2_audio *a) 255 { 256 return a->index ? -EINVAL : 0; 257 } 258 259 static int vidioc_s_frequency(struct file *file, void *priv, 260 struct v4l2_frequency *f) 261 { 262 struct maxiradio *dev = video_drvdata(file); 263 264 if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) 265 return -EINVAL; 266 if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) { 267 dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n", 268 f->frequency / 16000, 269 f->frequency % 16000 * 100 / 16000, 270 FREQ_LO / 16000, FREQ_HI / 16000); 271 272 return -EINVAL; 273 } 274 275 mutex_lock(&dev->lock); 276 dev->freq = f->frequency; 277 set_freq(dev, dev->freq); 278 msleep(125); 279 mutex_unlock(&dev->lock); 280 281 return 0; 282 } 283 284 static int vidioc_g_frequency(struct file *file, void *priv, 285 struct v4l2_frequency *f) 286 { 287 struct maxiradio *dev = video_drvdata(file); 288 289 if (f->tuner != 0) 290 return -EINVAL; 291 f->type = V4L2_TUNER_RADIO; 292 f->frequency = dev->freq; 293 294 dprintk(dev, 4, "radio freq is %d.%02d MHz", 295 f->frequency / 16000, 296 f->frequency % 16000 * 100 / 16000); 297 298 return 0; 299 } 300 301 static int vidioc_queryctrl(struct file *file, void *priv, 302 struct v4l2_queryctrl *qc) 303 { 304 switch (qc->id) { 305 case V4L2_CID_AUDIO_MUTE: 306 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); 307 } 308 return -EINVAL; 309 } 310 311 static int vidioc_g_ctrl(struct file *file, void *priv, 312 struct v4l2_control *ctrl) 313 { 314 struct maxiradio *dev = video_drvdata(file); 315 316 switch (ctrl->id) { 317 case V4L2_CID_AUDIO_MUTE: 318 ctrl->value = dev->muted; 319 return 0; 320 } 321 322 return -EINVAL; 323 } 324 325 static int vidioc_s_ctrl(struct file *file, void *priv, 326 struct v4l2_control *ctrl) 327 { 328 struct maxiradio *dev = video_drvdata(file); 329 330 switch (ctrl->id) { 331 case V4L2_CID_AUDIO_MUTE: 332 mutex_lock(&dev->lock); 333 dev->muted = ctrl->value; 334 if (dev->muted) 335 turn_power(dev, 0); 336 else 337 set_freq(dev, dev->freq); 338 mutex_unlock(&dev->lock); 339 return 0; 340 } 341 342 return -EINVAL; 343 } 344 345 static const struct v4l2_file_operations maxiradio_fops = { 346 .owner = THIS_MODULE, 347 .unlocked_ioctl = video_ioctl2, 348 }; 349 350 static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = { 351 .vidioc_querycap = vidioc_querycap, 352 .vidioc_g_tuner = vidioc_g_tuner, 353 .vidioc_s_tuner = vidioc_s_tuner, 354 .vidioc_g_audio = vidioc_g_audio, 355 .vidioc_s_audio = vidioc_s_audio, 356 .vidioc_g_input = vidioc_g_input, 357 .vidioc_s_input = vidioc_s_input, 358 .vidioc_g_frequency = vidioc_g_frequency, 359 .vidioc_s_frequency = vidioc_s_frequency, 360 .vidioc_queryctrl = vidioc_queryctrl, 361 .vidioc_g_ctrl = vidioc_g_ctrl, 362 .vidioc_s_ctrl = vidioc_s_ctrl, 363 }; 364 365 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 366 { 367 struct maxiradio *dev; 368 struct v4l2_device *v4l2_dev; 369 int retval = -ENOMEM; 370 371 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 372 if (dev == NULL) { 373 dev_err(&pdev->dev, "not enough memory\n"); 374 return -ENOMEM; 375 } 376 377 v4l2_dev = &dev->v4l2_dev; 378 mutex_init(&dev->lock); 379 dev->pdev = pdev; 380 dev->muted = 1; 381 dev->freq = FREQ_LO; 382 383 strlcpy(v4l2_dev->name, "maxiradio", sizeof(v4l2_dev->name)); 384 385 retval = v4l2_device_register(&pdev->dev, v4l2_dev); 386 if (retval < 0) { 387 v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); 388 goto errfr; 389 } 390 391 if (!request_region(pci_resource_start(pdev, 0), 392 pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) { 393 v4l2_err(v4l2_dev, "can't reserve I/O ports\n"); 394 goto err_out; 395 } 396 397 if (pci_enable_device(pdev)) 398 goto err_out_free_region; 399 400 dev->io = pci_resource_start(pdev, 0); 401 strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); 402 dev->vdev.v4l2_dev = v4l2_dev; 403 dev->vdev.fops = &maxiradio_fops; 404 dev->vdev.ioctl_ops = &maxiradio_ioctl_ops; 405 dev->vdev.release = video_device_release_empty; 406 video_set_drvdata(&dev->vdev, dev); 407 408 if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { 409 v4l2_err(v4l2_dev, "can't register device!"); 410 goto err_out_free_region; 411 } 412 413 v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n"); 414 415 v4l2_info(v4l2_dev, "found Guillemot MAXI Radio device (io = 0x%x)\n", 416 dev->io); 417 return 0; 418 419 err_out_free_region: 420 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 421 err_out: 422 v4l2_device_unregister(v4l2_dev); 423 errfr: 424 kfree(dev); 425 return -ENODEV; 426 } 427 428 static void __devexit maxiradio_remove_one(struct pci_dev *pdev) 429 { 430 struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); 431 struct maxiradio *dev = to_maxiradio(v4l2_dev); 432 433 video_unregister_device(&dev->vdev); 434 v4l2_device_unregister(&dev->v4l2_dev); 435 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 436 } 437 438 static struct pci_device_id maxiradio_pci_tbl[] = { 439 { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO, 440 PCI_ANY_ID, PCI_ANY_ID, }, 441 { 0 } 442 }; 443 444 MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl); 445 446 static struct pci_driver maxiradio_driver = { 447 .name = "radio-maxiradio", 448 .id_table = maxiradio_pci_tbl, 449 .probe = maxiradio_init_one, 450 .remove = __devexit_p(maxiradio_remove_one), 451 }; 452 453 static int __init maxiradio_radio_init(void) 454 { 455 return pci_register_driver(&maxiradio_driver); 456 } 457 458 static void __exit maxiradio_radio_exit(void) 459 { 460 pci_unregister_driver(&maxiradio_driver); 461 } 462 463 module_init(maxiradio_radio_init); 464 module_exit(maxiradio_radio_exit); 465