xref: /openbmc/linux/sound/usb/hiface/chip.c (revision 6417f031)
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(&register_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(&register_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(&register_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