0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <linux/module.h>
0038 #include <linux/init.h>
0039 #include <linux/ioport.h>
0040 #include <linux/delay.h>
0041 #include <linux/mutex.h>
0042 #include <linux/pci.h>
0043 #include <linux/videodev2.h>
0044 #include <linux/io.h>
0045 #include <linux/slab.h>
0046 #include <media/drv-intf/tea575x.h>
0047 #include <media/v4l2-device.h>
0048 #include <media/v4l2-ioctl.h>
0049 #include <media/v4l2-fh.h>
0050 #include <media/v4l2-ctrls.h>
0051 #include <media/v4l2-event.h>
0052
0053 MODULE_AUTHOR("Dimitromanolakis Apostolos, apdim@grecian.net");
0054 MODULE_DESCRIPTION("Radio driver for the Guillemot Maxi Radio FM2000.");
0055 MODULE_LICENSE("GPL");
0056 MODULE_VERSION("1.0.0");
0057
0058 static int radio_nr = -1;
0059 module_param(radio_nr, int, 0644);
0060 MODULE_PARM_DESC(radio_nr, "Radio device number");
0061
0062
0063 static const int clk = 1, data = 2, wren = 4, mo_st = 8, power = 16;
0064
0065 static atomic_t maxiradio_instance = ATOMIC_INIT(0);
0066
0067 #define PCI_VENDOR_ID_GUILLEMOT 0x5046
0068 #define PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO 0x1001
0069
0070 struct maxiradio
0071 {
0072 struct snd_tea575x tea;
0073 struct v4l2_device v4l2_dev;
0074 struct pci_dev *pdev;
0075
0076 u16 io;
0077 };
0078
0079 static inline struct maxiradio *to_maxiradio(struct v4l2_device *v4l2_dev)
0080 {
0081 return container_of(v4l2_dev, struct maxiradio, v4l2_dev);
0082 }
0083
0084 static void maxiradio_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
0085 {
0086 struct maxiradio *dev = tea->private_data;
0087 u8 bits = 0;
0088
0089 bits |= (pins & TEA575X_DATA) ? data : 0;
0090 bits |= (pins & TEA575X_CLK) ? clk : 0;
0091 bits |= (pins & TEA575X_WREN) ? wren : 0;
0092 bits |= power;
0093
0094 outb(bits, dev->io);
0095 }
0096
0097
0098
0099 static u8 maxiradio_tea575x_get_pins(struct snd_tea575x *tea)
0100 {
0101 struct maxiradio *dev = tea->private_data;
0102 u8 bits = inb(dev->io);
0103
0104 return ((bits & data) ? TEA575X_DATA : 0) |
0105 ((bits & mo_st) ? TEA575X_MOST : 0);
0106 }
0107
0108 static void maxiradio_tea575x_set_direction(struct snd_tea575x *tea, bool output)
0109 {
0110 }
0111
0112 static const struct snd_tea575x_ops maxiradio_tea_ops = {
0113 .set_pins = maxiradio_tea575x_set_pins,
0114 .get_pins = maxiradio_tea575x_get_pins,
0115 .set_direction = maxiradio_tea575x_set_direction,
0116 };
0117
0118 static int maxiradio_probe(struct pci_dev *pdev,
0119 const struct pci_device_id *ent)
0120 {
0121 struct maxiradio *dev;
0122 struct v4l2_device *v4l2_dev;
0123 int retval = -ENOMEM;
0124
0125 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0126 if (dev == NULL) {
0127 dev_err(&pdev->dev, "not enough memory\n");
0128 return -ENOMEM;
0129 }
0130
0131 v4l2_dev = &dev->v4l2_dev;
0132 v4l2_device_set_name(v4l2_dev, "maxiradio", &maxiradio_instance);
0133
0134 retval = v4l2_device_register(&pdev->dev, v4l2_dev);
0135 if (retval < 0) {
0136 v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
0137 goto errfr;
0138 }
0139 dev->tea.private_data = dev;
0140 dev->tea.ops = &maxiradio_tea_ops;
0141
0142
0143 dev->tea.cannot_read_data = true;
0144 dev->tea.v4l2_dev = v4l2_dev;
0145 dev->tea.radio_nr = radio_nr;
0146 strscpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card));
0147
0148 retval = -ENODEV;
0149
0150 if (!request_region(pci_resource_start(pdev, 0),
0151 pci_resource_len(pdev, 0), v4l2_dev->name)) {
0152 dev_err(&pdev->dev, "can't reserve I/O ports\n");
0153 goto err_hdl;
0154 }
0155
0156 if (pci_enable_device(pdev))
0157 goto err_out_free_region;
0158
0159 dev->io = pci_resource_start(pdev, 0);
0160 if (snd_tea575x_init(&dev->tea, THIS_MODULE)) {
0161 printk(KERN_ERR "radio-maxiradio: Unable to detect TEA575x tuner\n");
0162 goto err_out_free_region;
0163 }
0164 return 0;
0165
0166 err_out_free_region:
0167 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
0168 err_hdl:
0169 v4l2_device_unregister(v4l2_dev);
0170 errfr:
0171 kfree(dev);
0172 return retval;
0173 }
0174
0175 static void maxiradio_remove(struct pci_dev *pdev)
0176 {
0177 struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
0178 struct maxiradio *dev = to_maxiradio(v4l2_dev);
0179
0180 snd_tea575x_exit(&dev->tea);
0181
0182 outb(0, dev->io);
0183 v4l2_device_unregister(v4l2_dev);
0184 release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
0185 kfree(dev);
0186 }
0187
0188 static const struct pci_device_id maxiradio_pci_tbl[] = {
0189 { PCI_VENDOR_ID_GUILLEMOT, PCI_DEVICE_ID_GUILLEMOT_MAXIRADIO,
0190 PCI_ANY_ID, PCI_ANY_ID, },
0191 { 0 }
0192 };
0193
0194 MODULE_DEVICE_TABLE(pci, maxiradio_pci_tbl);
0195
0196 static struct pci_driver maxiradio_driver = {
0197 .name = "radio-maxiradio",
0198 .id_table = maxiradio_pci_tbl,
0199 .probe = maxiradio_probe,
0200 .remove = maxiradio_remove,
0201 };
0202
0203 module_pci_driver(maxiradio_driver);