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