xref: /openbmc/linux/sound/firewire/tascam/tascam.c (revision e7253313)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * tascam.c - a part of driver for TASCAM FireWire series
4  *
5  * Copyright (c) 2015 Takashi Sakamoto
6  */
7 
8 #include "tascam.h"
9 
10 MODULE_DESCRIPTION("TASCAM FireWire series Driver");
11 MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
12 MODULE_LICENSE("GPL v2");
13 
14 static const struct snd_tscm_spec model_specs[] = {
15 	{
16 		.name = "FW-1884",
17 		.has_adat = true,
18 		.has_spdif = true,
19 		.pcm_capture_analog_channels = 8,
20 		.pcm_playback_analog_channels = 8,
21 		.midi_capture_ports = 4,
22 		.midi_playback_ports = 4,
23 	},
24 	{
25 		.name = "FW-1082",
26 		.has_adat = false,
27 		.has_spdif = true,
28 		.pcm_capture_analog_channels = 8,
29 		.pcm_playback_analog_channels = 2,
30 		.midi_capture_ports = 2,
31 		.midi_playback_ports = 2,
32 	},
33 	{
34 		.name = "FW-1804",
35 		.has_adat = true,
36 		.has_spdif = true,
37 		.pcm_capture_analog_channels = 8,
38 		.pcm_playback_analog_channels = 2,
39 		.midi_capture_ports = 2,
40 		.midi_playback_ports = 4,
41 	},
42 	// This kernel module doesn't support FE-8 because the most of features
43 	// can be implemented in userspace without any specific support of this
44 	// module.
45 };
46 
47 static int identify_model(struct snd_tscm *tscm)
48 {
49 	struct fw_device *fw_dev = fw_parent_device(tscm->unit);
50 	const u32 *config_rom = fw_dev->config_rom;
51 	char model[9];
52 	unsigned int i;
53 	u8 c;
54 
55 	if (fw_dev->config_rom_length < 30) {
56 		dev_err(&tscm->unit->device,
57 			"Configuration ROM is too short.\n");
58 		return -ENODEV;
59 	}
60 
61 	/* Pick up model name from certain addresses. */
62 	for (i = 0; i < 8; i++) {
63 		c = config_rom[28 + i / 4] >> (24 - 8 * (i % 4));
64 		if (c == '\0')
65 			break;
66 		model[i] = c;
67 	}
68 	model[i] = '\0';
69 
70 	for (i = 0; i < ARRAY_SIZE(model_specs); i++) {
71 		if (strcmp(model, model_specs[i].name) == 0) {
72 			tscm->spec = &model_specs[i];
73 			break;
74 		}
75 	}
76 	if (tscm->spec == NULL)
77 		return -ENODEV;
78 
79 	strcpy(tscm->card->driver, "FW-TASCAM");
80 	strcpy(tscm->card->shortname, model);
81 	strcpy(tscm->card->mixername, model);
82 	snprintf(tscm->card->longname, sizeof(tscm->card->longname),
83 		 "TASCAM %s, GUID %08x%08x at %s, S%d", model,
84 		 fw_dev->config_rom[3], fw_dev->config_rom[4],
85 		 dev_name(&tscm->unit->device), 100 << fw_dev->max_speed);
86 
87 	return 0;
88 }
89 
90 static void tscm_card_free(struct snd_card *card)
91 {
92 	struct snd_tscm *tscm = card->private_data;
93 
94 	snd_tscm_transaction_unregister(tscm);
95 	snd_tscm_stream_destroy_duplex(tscm);
96 }
97 
98 static void do_registration(struct work_struct *work)
99 {
100 	struct snd_tscm *tscm = container_of(work, struct snd_tscm, dwork.work);
101 	int err;
102 
103 	err = snd_card_new(&tscm->unit->device, -1, NULL, THIS_MODULE, 0,
104 			   &tscm->card);
105 	if (err < 0)
106 		return;
107 	tscm->card->private_free = tscm_card_free;
108 	tscm->card->private_data = tscm;
109 
110 	err = identify_model(tscm);
111 	if (err < 0)
112 		goto error;
113 
114 	err = snd_tscm_transaction_register(tscm);
115 	if (err < 0)
116 		goto error;
117 
118 	err = snd_tscm_stream_init_duplex(tscm);
119 	if (err < 0)
120 		goto error;
121 
122 	snd_tscm_proc_init(tscm);
123 
124 	err = snd_tscm_create_pcm_devices(tscm);
125 	if (err < 0)
126 		goto error;
127 
128 	err = snd_tscm_create_midi_devices(tscm);
129 	if (err < 0)
130 		goto error;
131 
132 	err = snd_tscm_create_hwdep_device(tscm);
133 	if (err < 0)
134 		goto error;
135 
136 	err = snd_card_register(tscm->card);
137 	if (err < 0)
138 		goto error;
139 
140 	tscm->registered = true;
141 
142 	return;
143 error:
144 	snd_card_free(tscm->card);
145 	dev_info(&tscm->unit->device,
146 		 "Sound card registration failed: %d\n", err);
147 }
148 
149 static int snd_tscm_probe(struct fw_unit *unit,
150 			   const struct ieee1394_device_id *entry)
151 {
152 	struct snd_tscm *tscm;
153 
154 	/* Allocate this independent of sound card instance. */
155 	tscm = devm_kzalloc(&unit->device, sizeof(struct snd_tscm), GFP_KERNEL);
156 	if (!tscm)
157 		return -ENOMEM;
158 	tscm->unit = fw_unit_get(unit);
159 	dev_set_drvdata(&unit->device, tscm);
160 
161 	mutex_init(&tscm->mutex);
162 	spin_lock_init(&tscm->lock);
163 	init_waitqueue_head(&tscm->hwdep_wait);
164 
165 	/* Allocate and register this sound card later. */
166 	INIT_DEFERRABLE_WORK(&tscm->dwork, do_registration);
167 	snd_fw_schedule_registration(unit, &tscm->dwork);
168 
169 	return 0;
170 }
171 
172 static void snd_tscm_update(struct fw_unit *unit)
173 {
174 	struct snd_tscm *tscm = dev_get_drvdata(&unit->device);
175 
176 	/* Postpone a workqueue for deferred registration. */
177 	if (!tscm->registered)
178 		snd_fw_schedule_registration(unit, &tscm->dwork);
179 
180 	snd_tscm_transaction_reregister(tscm);
181 
182 	/*
183 	 * After registration, userspace can start packet streaming, then this
184 	 * code block works fine.
185 	 */
186 	if (tscm->registered) {
187 		mutex_lock(&tscm->mutex);
188 		snd_tscm_stream_update_duplex(tscm);
189 		mutex_unlock(&tscm->mutex);
190 	}
191 }
192 
193 static void snd_tscm_remove(struct fw_unit *unit)
194 {
195 	struct snd_tscm *tscm = dev_get_drvdata(&unit->device);
196 
197 	/*
198 	 * Confirm to stop the work for registration before the sound card is
199 	 * going to be released. The work is not scheduled again because bus
200 	 * reset handler is not called anymore.
201 	 */
202 	cancel_delayed_work_sync(&tscm->dwork);
203 
204 	if (tscm->registered) {
205 		// Block till all of ALSA character devices are released.
206 		snd_card_free(tscm->card);
207 	}
208 
209 	mutex_destroy(&tscm->mutex);
210 	fw_unit_put(tscm->unit);
211 }
212 
213 static const struct ieee1394_device_id snd_tscm_id_table[] = {
214 	{
215 		.match_flags = IEEE1394_MATCH_VENDOR_ID |
216 			       IEEE1394_MATCH_SPECIFIER_ID,
217 		.vendor_id = 0x00022e,
218 		.specifier_id = 0x00022e,
219 	},
220 	{}
221 };
222 MODULE_DEVICE_TABLE(ieee1394, snd_tscm_id_table);
223 
224 static struct fw_driver tscm_driver = {
225 	.driver = {
226 		.owner = THIS_MODULE,
227 		.name = "snd-firewire-tascam",
228 		.bus = &fw_bus_type,
229 	},
230 	.probe    = snd_tscm_probe,
231 	.update   = snd_tscm_update,
232 	.remove   = snd_tscm_remove,
233 	.id_table = snd_tscm_id_table,
234 };
235 
236 static int __init snd_tscm_init(void)
237 {
238 	return driver_register(&tscm_driver.driver);
239 }
240 
241 static void __exit snd_tscm_exit(void)
242 {
243 	driver_unregister(&tscm_driver.driver);
244 }
245 
246 module_init(snd_tscm_init);
247 module_exit(snd_tscm_exit);
248