95385e90882c74199bcb3470dc2d16e100f60260
[releases.git] / chip.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Linux driver for M2Tech hiFace compatible devices
4  *
5  * Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V.
6  *
7  * Authors:  Michael Trimarchi <michael@amarulasolutions.com>
8  *           Antonio Ospite <ao2@amarulasolutions.com>
9  *
10  * The driver is based on the work done in TerraTec DMX 6Fire USB
11  */
12
13 #include <linux/module.h>
14 #include <linux/slab.h>
15 #include <sound/initval.h>
16
17 #include "chip.h"
18 #include "pcm.h"
19
20 MODULE_AUTHOR("Michael Trimarchi <michael@amarulasolutions.com>");
21 MODULE_AUTHOR("Antonio Ospite <ao2@amarulasolutions.com>");
22 MODULE_DESCRIPTION("M2Tech hiFace USB-SPDIF audio driver");
23 MODULE_LICENSE("GPL v2");
24
25 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
26 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
27 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
28
29 #define DRIVER_NAME "snd-usb-hiface"
30 #define CARD_NAME "hiFace"
31
32 module_param_array(index, int, NULL, 0444);
33 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
34 module_param_array(id, charp, NULL, 0444);
35 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
36 module_param_array(enable, bool, NULL, 0444);
37 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
38
39 static DEFINE_MUTEX(register_mutex);
40
41 struct hiface_vendor_quirk {
42         const char *device_name;
43         u8 extra_freq;
44 };
45
46 static int hiface_chip_create(struct usb_interface *intf,
47                               struct usb_device *device, int idx,
48                               const struct hiface_vendor_quirk *quirk,
49                               struct hiface_chip **rchip)
50 {
51         struct snd_card *card = NULL;
52         struct hiface_chip *chip;
53         int ret;
54         int len;
55
56         *rchip = NULL;
57
58         /* if we are here, card can be registered in alsa. */
59         ret = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,
60                            sizeof(*chip), &card);
61         if (ret < 0) {
62                 dev_err(&device->dev, "cannot create alsa card.\n");
63                 return ret;
64         }
65
66         strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
67
68         if (quirk && quirk->device_name)
69                 strscpy(card->shortname, quirk->device_name, sizeof(card->shortname));
70         else
71                 strscpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname));
72
73         strlcat(card->longname, card->shortname, sizeof(card->longname));
74         len = strlcat(card->longname, " at ", sizeof(card->longname));
75         if (len < sizeof(card->longname))
76                 usb_make_path(device, card->longname + len,
77                               sizeof(card->longname) - len);
78
79         chip = card->private_data;
80         chip->dev = device;
81         chip->card = card;
82
83         *rchip = chip;
84         return 0;
85 }
86
87 static int hiface_chip_probe(struct usb_interface *intf,
88                              const struct usb_device_id *usb_id)
89 {
90         const struct hiface_vendor_quirk *quirk = (struct hiface_vendor_quirk *)usb_id->driver_info;
91         int ret;
92         int i;
93         struct hiface_chip *chip;
94         struct usb_device *device = interface_to_usbdev(intf);
95
96         ret = usb_set_interface(device, 0, 0);
97         if (ret != 0) {
98                 dev_err(&device->dev, "can't set first interface for " CARD_NAME " device.\n");
99                 return -EIO;
100         }
101
102         /* check whether the card is already registered */
103         chip = NULL;
104         mutex_lock(&register_mutex);
105
106         for (i = 0; i < SNDRV_CARDS; i++)
107                 if (enable[i])
108                         break;
109
110         if (i >= SNDRV_CARDS) {
111                 dev_err(&device->dev, "no available " CARD_NAME " audio device\n");
112                 ret = -ENODEV;
113                 goto err;
114         }
115
116         ret = hiface_chip_create(intf, device, i, quirk, &chip);
117         if (ret < 0)
118                 goto err;
119
120         ret = hiface_pcm_init(chip, quirk ? quirk->extra_freq : 0);
121         if (ret < 0)
122                 goto err_chip_destroy;
123
124         ret = snd_card_register(chip->card);
125         if (ret < 0) {
126                 dev_err(&device->dev, "cannot register " CARD_NAME " card\n");
127                 goto err_chip_destroy;
128         }
129
130         mutex_unlock(&register_mutex);
131
132         usb_set_intfdata(intf, chip);
133         return 0;
134
135 err_chip_destroy:
136         snd_card_free(chip->card);
137 err:
138         mutex_unlock(&register_mutex);
139         return ret;
140 }
141
142 static void hiface_chip_disconnect(struct usb_interface *intf)
143 {
144         struct hiface_chip *chip;
145         struct snd_card *card;
146
147         chip = usb_get_intfdata(intf);
148         if (!chip)
149                 return;
150
151         card = chip->card;
152
153         /* Make sure that the userspace cannot create new request */
154         snd_card_disconnect(card);
155
156         hiface_pcm_abort(chip);
157         snd_card_free_when_closed(card);
158 }
159
160 static const struct usb_device_id device_table[] = {
161         {
162                 USB_DEVICE(0x04b4, 0x0384),
163                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
164                         .device_name = "Young",
165                         .extra_freq = 1,
166                 }
167         },
168         {
169                 USB_DEVICE(0x04b4, 0x930b),
170                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
171                         .device_name = "hiFace",
172                 }
173         },
174         {
175                 USB_DEVICE(0x04b4, 0x931b),
176                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
177                         .device_name = "North Star",
178                 }
179         },
180         {
181                 USB_DEVICE(0x04b4, 0x931c),
182                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
183                         .device_name = "W4S Young",
184                 }
185         },
186         {
187                 USB_DEVICE(0x04b4, 0x931d),
188                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
189                         .device_name = "Corrson",
190                 }
191         },
192         {
193                 USB_DEVICE(0x04b4, 0x931e),
194                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
195                         .device_name = "AUDIA",
196                 }
197         },
198         {
199                 USB_DEVICE(0x04b4, 0x931f),
200                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
201                         .device_name = "SL Audio",
202                 }
203         },
204         {
205                 USB_DEVICE(0x04b4, 0x9320),
206                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
207                         .device_name = "Empirical",
208                 }
209         },
210         {
211                 USB_DEVICE(0x04b4, 0x9321),
212                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
213                         .device_name = "Rockna",
214                 }
215         },
216         {
217                 USB_DEVICE(0x249c, 0x9001),
218                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
219                         .device_name = "Pathos",
220                 }
221         },
222         {
223                 USB_DEVICE(0x249c, 0x9002),
224                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
225                         .device_name = "Metronome",
226                 }
227         },
228         {
229                 USB_DEVICE(0x249c, 0x9006),
230                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
231                         .device_name = "CAD",
232                 }
233         },
234         {
235                 USB_DEVICE(0x249c, 0x9008),
236                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
237                         .device_name = "Audio Esclusive",
238                 }
239         },
240         {
241                 USB_DEVICE(0x249c, 0x931c),
242                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
243                         .device_name = "Rotel",
244                 }
245         },
246         {
247                 USB_DEVICE(0x249c, 0x932c),
248                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
249                         .device_name = "Eeaudio",
250                 }
251         },
252         {
253                 USB_DEVICE(0x245f, 0x931c),
254                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
255                         .device_name = "CHORD",
256                 }
257         },
258         {
259                 USB_DEVICE(0x25c6, 0x9002),
260                 .driver_info = (unsigned long)&(const struct hiface_vendor_quirk) {
261                         .device_name = "Vitus",
262                 }
263         },
264         {}
265 };
266
267 MODULE_DEVICE_TABLE(usb, device_table);
268
269 static struct usb_driver hiface_usb_driver = {
270         .name = DRIVER_NAME,
271         .probe = hiface_chip_probe,
272         .disconnect = hiface_chip_disconnect,
273         .id_table = device_table,
274 };
275
276 module_usb_driver(hiface_usb_driver);