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 <sound/tea575x-tuner.h> 46 #include <media/v4l2-device.h> 47 #include <media/v4l2-ioctl.h> 48 #include <media/v4l2-fh.h> 49 #include <media/v4l2-ctrls.h> 50 #include <media/v4l2-event.h> 51 52 MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net"); 53 MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000."); 54 MODULE_LICENSE("GPL"); 55 MODULE_VERSION("1.0.0"); 56 57 static int radio_nr = -1; 58 module_param(radio_nr, int, 0644); 59 MODULE_PARM_DESC(radio_nr, "Radio device number"); 60 61 /* TEA5757 pin mappings */ 62 static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16; 63 64 static atomic_t maxiradio_instance = ATOMIC_INIT(0); 65 66 #define PCI_VENDOR_ID_GUILLEMOT 0x5046 67 #define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001 68 69 struct maxiradio 70 { 71 struct snd_tea575x tea; 72 struct v4l2_device v4l2_dev; 73 struct pci_dev *pdev; 74 75 u16 io; /* base of radio io */ 76 }; 77 78 static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev) 79 { 80 return container_of(v4l2_dev, struct maxiradio, v4l2_dev); 81 } 82 83 static void maxiradio_tea575x_set_pins(struct snd_tea575x *tea, u8 pins) 84 { 85 struct maxiradio *dev = tea->private_data; 86 u8 bits = 0; 87 88 bits |= (pins & TEA575X_DATA) ? data : 0; 89 bits |= (pins & TEA575X_CLK) ? clk : 0; 90 bits |= (pins & TEA575X_WREN) ? wren : 0; 91 bits |= power; 92 93 outb(bits, dev->io); 94 } 95 96 /* Note: this card cannot read out the data of the shift registers, 97 only the mono/stereo pin works. */ 98 static u8 maxiradio_tea575x_get_pins(struct snd_tea575x *tea) 99 { 100 struct maxiradio *dev = tea->private_data; 101 u8 bits = inb(dev->io); 102 103 return ((bits & data) ? TEA575X_DATA : 0) | 104 ((bits & mo_st) ? TEA575X_MOST : 0); 105 } 106 107 static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output) 108 { 109 } 110 111 static struct snd_tea575x_ops maxiradio_tea_ops = { 112 .set_pins = maxiradio_tea575x_set_pins, 113 .get_pins = maxiradio_tea575x_get_pins, 114 .set_direction = maxiradio_tea575x_set_direction, 115 }; 116 117 static int __devinit maxiradio_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 118 { 119 struct maxiradio *dev; 120 struct v4l2_device *v4l2_dev; 121 int retval = -ENOMEM; 122 123 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 124 if (dev == NULL) { 125 dev_err(&pdev->dev, "not enough memory\n"); 126 return -ENOMEM; 127 } 128 129 v4l2_dev = &dev->v4l2_dev; 130 v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance); 131 132 retval = v4l2_device_register(&pdev->dev, v4l2_dev); 133 if (retval < 0) { 134 v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); 135 goto errfr; 136 } 137 dev->tea.private_data = dev; 138 dev->tea.ops = &maxiradio_tea_ops; 139 /* The data pin cannot be read. This may be a hardware limitation, or 140 we just don't know how to read it. */ 141 dev->tea.cannot_read_data = true; 142 dev->tea.v4l2_dev = v4l2_dev; 143 dev->tea.radio_nr = radio_nr; 144 strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card)); 145 snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info), 146 "PCI:%s", pci_name(pdev)); 147 148 retval = -ENODEV; 149 150 if (!request_region(pci_resource_start(pdev, 0), 151 pci_resource_len(pdev, 0), v4l2_dev->name)) { 152 dev_err(&pdev->dev, "can't reserve I/O ports\n"); 153 goto err_hdl; 154 } 155 156 if (pci_enable_device(pdev)) 157 goto err_out_free_region; 158 159 dev->io = pci_resource_start(pdev, 0); 160 if (snd_tea575x_init(&dev->tea, THIS_MODULE)) { 161 printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n"); 162 goto err_out_free_region; 163 } 164 return 0; 165 166 err_out_free_region: 167 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 168 err_hdl: 169 v4l2_device_unregister(v4l2_dev); 170 errfr: 171 kfree(dev); 172 return retval; 173 } 174 175 static void __devexit maxiradio_remove(struct pci_dev *pdev) 176 { 177 struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); 178 struct maxiradio *dev = to_maxiradio(v4l2_dev); 179 180 snd_tea575x_exit(&dev->tea); 181 /* Turn off power */ 182 outb(0, dev->io); 183 v4l2_device_unregister(v4l2_dev); 184 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 185 } 186 187 static struct pci_device_id maxiradio_pci_tbl[] = { 188 { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO, 189 PCI_ANY_ID, PCI_ANY_ID, }, 190 { 0 } 191 }; 192 193 MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl); 194 195 static struct pci_driver maxiradio_driver = { 196 .name = "radio-maxiradio", 197 .id_table = maxiradio_pci_tbl, 198 .probe = maxiradio_probe, 199 .remove = __devexit_p(maxiradio_remove), 200 }; 201 202 static int __init maxiradio_init(void) 203 { 204 return pci_register_driver(&maxiradio_driver); 205 } 206 207 static void __exit maxiradio_exit(void) 208 { 209 pci_unregister_driver(&maxiradio_driver); 210 } 211 212 module_init(maxiradio_init); 213 module_exit(maxiradio_exit); 214