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 maxiradio_probe(struct pci_dev *pdev, 118 const struct pci_device_id *ent) 119 { 120 struct maxiradio *dev; 121 struct v4l2_device *v4l2_dev; 122 int retval = -ENOMEM; 123 124 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 125 if (dev == NULL) { 126 dev_err(&pdev->dev, "not enough memory\n"); 127 return -ENOMEM; 128 } 129 130 v4l2_dev = &dev->v4l2_dev; 131 v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance); 132 133 retval = v4l2_device_register(&pdev->dev, v4l2_dev); 134 if (retval < 0) { 135 v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); 136 goto errfr; 137 } 138 dev->tea.private_data = dev; 139 dev->tea.ops = &maxiradio_tea_ops; 140 /* The data pin cannot be read. This may be a hardware limitation, or 141 we just don't know how to read it. */ 142 dev->tea.cannot_read_data = true; 143 dev->tea.v4l2_dev = v4l2_dev; 144 dev->tea.radio_nr = radio_nr; 145 strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card)); 146 snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info), 147 "PCI:%s", pci_name(pdev)); 148 149 retval = -ENODEV; 150 151 if (!request_region(pci_resource_start(pdev, 0), 152 pci_resource_len(pdev, 0), v4l2_dev->name)) { 153 dev_err(&pdev->dev, "can't reserve I/O ports\n"); 154 goto err_hdl; 155 } 156 157 if (pci_enable_device(pdev)) 158 goto err_out_free_region; 159 160 dev->io = pci_resource_start(pdev, 0); 161 if (snd_tea575x_init(&dev->tea, THIS_MODULE)) { 162 printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n"); 163 goto err_out_free_region; 164 } 165 return 0; 166 167 err_out_free_region: 168 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 169 err_hdl: 170 v4l2_device_unregister(v4l2_dev); 171 errfr: 172 kfree(dev); 173 return retval; 174 } 175 176 static void maxiradio_remove(struct pci_dev *pdev) 177 { 178 struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); 179 struct maxiradio *dev = to_maxiradio(v4l2_dev); 180 181 snd_tea575x_exit(&dev->tea); 182 /* Turn off power */ 183 outb(0, dev->io); 184 v4l2_device_unregister(v4l2_dev); 185 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 186 } 187 188 static struct pci_device_id maxiradio_pci_tbl[] = { 189 { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO, 190 PCI_ANY_ID, PCI_ANY_ID, }, 191 { 0 } 192 }; 193 194 MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl); 195 196 static struct pci_driver maxiradio_driver = { 197 .name = "radio-maxiradio", 198 .id_table = maxiradio_pci_tbl, 199 .probe = maxiradio_probe, 200 .remove = maxiradio_remove, 201 }; 202 203 static int __init maxiradio_init(void) 204 { 205 return pci_register_driver(&maxiradio_driver); 206 } 207 208 static void __exit maxiradio_exit(void) 209 { 210 pci_unregister_driver(&maxiradio_driver); 211 } 212 213 module_init(maxiradio_init); 214 module_exit(maxiradio_exit); 215