.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * motu.c - a part of driver for MOTU FireWire series |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp> |
---|
5 | | - * |
---|
6 | | - * Licensed under the terms of the GNU General Public License, version 2. |
---|
7 | 6 | */ |
---|
8 | 7 | |
---|
9 | 8 | #include "motu.h" |
---|
.. | .. |
---|
52 | 51 | dev_name(&motu->unit->device), 100 << fw_dev->max_speed); |
---|
53 | 52 | } |
---|
54 | 53 | |
---|
55 | | -static void motu_free(struct snd_motu *motu) |
---|
56 | | -{ |
---|
57 | | - snd_motu_transaction_unregister(motu); |
---|
58 | | - |
---|
59 | | - snd_motu_stream_destroy_duplex(motu); |
---|
60 | | - fw_unit_put(motu->unit); |
---|
61 | | - |
---|
62 | | - mutex_destroy(&motu->mutex); |
---|
63 | | - kfree(motu); |
---|
64 | | -} |
---|
65 | | - |
---|
66 | | -/* |
---|
67 | | - * This module releases the FireWire unit data after all ALSA character devices |
---|
68 | | - * are released by applications. This is for releasing stream data or finishing |
---|
69 | | - * transactions safely. Thus at returning from .remove(), this module still keep |
---|
70 | | - * references for the unit. |
---|
71 | | - */ |
---|
72 | 54 | static void motu_card_free(struct snd_card *card) |
---|
73 | 55 | { |
---|
74 | | - motu_free(card->private_data); |
---|
| 56 | + struct snd_motu *motu = card->private_data; |
---|
| 57 | + |
---|
| 58 | + snd_motu_transaction_unregister(motu); |
---|
| 59 | + snd_motu_stream_destroy_duplex(motu); |
---|
75 | 60 | } |
---|
76 | 61 | |
---|
77 | 62 | static void do_registration(struct work_struct *work) |
---|
.. | .. |
---|
86 | 71 | &motu->card); |
---|
87 | 72 | if (err < 0) |
---|
88 | 73 | return; |
---|
| 74 | + motu->card->private_free = motu_card_free; |
---|
| 75 | + motu->card->private_data = motu; |
---|
89 | 76 | |
---|
90 | 77 | name_card(motu); |
---|
91 | 78 | |
---|
.. | .. |
---|
120 | 107 | if (err < 0) |
---|
121 | 108 | goto error; |
---|
122 | 109 | |
---|
123 | | - /* |
---|
124 | | - * After registered, motu instance can be released corresponding to |
---|
125 | | - * releasing the sound card instance. |
---|
126 | | - */ |
---|
127 | | - motu->card->private_free = motu_card_free; |
---|
128 | | - motu->card->private_data = motu; |
---|
129 | 110 | motu->registered = true; |
---|
130 | 111 | |
---|
131 | 112 | return; |
---|
132 | 113 | error: |
---|
133 | | - snd_motu_transaction_unregister(motu); |
---|
134 | | - snd_motu_stream_destroy_duplex(motu); |
---|
135 | 114 | snd_card_free(motu->card); |
---|
136 | 115 | dev_info(&motu->unit->device, |
---|
137 | 116 | "Sound card registration failed: %d\n", err); |
---|
.. | .. |
---|
143 | 122 | struct snd_motu *motu; |
---|
144 | 123 | |
---|
145 | 124 | /* Allocate this independently of sound card instance. */ |
---|
146 | | - motu = kzalloc(sizeof(struct snd_motu), GFP_KERNEL); |
---|
147 | | - if (motu == NULL) |
---|
| 125 | + motu = devm_kzalloc(&unit->device, sizeof(struct snd_motu), GFP_KERNEL); |
---|
| 126 | + if (!motu) |
---|
148 | 127 | return -ENOMEM; |
---|
149 | | - |
---|
150 | | - motu->spec = (const struct snd_motu_spec *)entry->driver_data; |
---|
151 | 128 | motu->unit = fw_unit_get(unit); |
---|
152 | 129 | dev_set_drvdata(&unit->device, motu); |
---|
153 | 130 | |
---|
| 131 | + motu->spec = (const struct snd_motu_spec *)entry->driver_data; |
---|
154 | 132 | mutex_init(&motu->mutex); |
---|
155 | 133 | spin_lock_init(&motu->lock); |
---|
156 | 134 | init_waitqueue_head(&motu->hwdep_wait); |
---|
.. | .. |
---|
174 | 152 | cancel_delayed_work_sync(&motu->dwork); |
---|
175 | 153 | |
---|
176 | 154 | if (motu->registered) { |
---|
177 | | - /* No need to wait for releasing card object in this context. */ |
---|
178 | | - snd_card_free_when_closed(motu->card); |
---|
179 | | - } else { |
---|
180 | | - /* Don't forget this case. */ |
---|
181 | | - motu_free(motu); |
---|
| 155 | + // Block till all of ALSA character devices are released. |
---|
| 156 | + snd_card_free(motu->card); |
---|
182 | 157 | } |
---|
| 158 | + |
---|
| 159 | + mutex_destroy(&motu->mutex); |
---|
| 160 | + fw_unit_put(motu->unit); |
---|
183 | 161 | } |
---|
184 | 162 | |
---|
185 | 163 | static void motu_bus_update(struct fw_unit *unit) |
---|
.. | .. |
---|
194 | 172 | snd_motu_transaction_reregister(motu); |
---|
195 | 173 | } |
---|
196 | 174 | |
---|
197 | | -static const struct snd_motu_spec motu_828mk2 = { |
---|
198 | | - .name = "828mk2", |
---|
199 | | - .protocol = &snd_motu_protocol_v2, |
---|
200 | | - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | |
---|
201 | | - SND_MOTU_SPEC_TX_MICINST_CHUNK | |
---|
202 | | - SND_MOTU_SPEC_TX_RETURN_CHUNK | |
---|
203 | | - SND_MOTU_SPEC_RX_SEPARETED_MAIN | |
---|
204 | | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | |
---|
205 | | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | |
---|
206 | | - SND_MOTU_SPEC_TX_MIDI_2ND_Q, |
---|
207 | | - |
---|
208 | | - .analog_in_ports = 8, |
---|
209 | | - .analog_out_ports = 8, |
---|
210 | | -}; |
---|
211 | | - |
---|
212 | | -const struct snd_motu_spec snd_motu_spec_traveler = { |
---|
213 | | - .name = "Traveler", |
---|
214 | | - .protocol = &snd_motu_protocol_v2, |
---|
215 | | - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | |
---|
216 | | - SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | |
---|
217 | | - SND_MOTU_SPEC_TX_RETURN_CHUNK | |
---|
218 | | - SND_MOTU_SPEC_HAS_AESEBU_IFACE | |
---|
219 | | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | |
---|
220 | | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | |
---|
221 | | - SND_MOTU_SPEC_TX_MIDI_2ND_Q, |
---|
222 | | - |
---|
223 | | - .analog_in_ports = 8, |
---|
224 | | - .analog_out_ports = 8, |
---|
225 | | -}; |
---|
226 | | - |
---|
227 | | -static const struct snd_motu_spec motu_828mk3 = { |
---|
228 | | - .name = "828mk3", |
---|
229 | | - .protocol = &snd_motu_protocol_v3, |
---|
230 | | - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | |
---|
231 | | - SND_MOTU_SPEC_SUPPORT_CLOCK_X4 | |
---|
232 | | - SND_MOTU_SPEC_TX_MICINST_CHUNK | |
---|
233 | | - SND_MOTU_SPEC_TX_RETURN_CHUNK | |
---|
234 | | - SND_MOTU_SPEC_TX_REVERB_CHUNK | |
---|
235 | | - SND_MOTU_SPEC_RX_SEPARETED_MAIN | |
---|
236 | | - SND_MOTU_SPEC_HAS_OPT_IFACE_A | |
---|
237 | | - SND_MOTU_SPEC_HAS_OPT_IFACE_B | |
---|
238 | | - SND_MOTU_SPEC_RX_MIDI_3RD_Q | |
---|
239 | | - SND_MOTU_SPEC_TX_MIDI_3RD_Q, |
---|
240 | | - |
---|
241 | | - .analog_in_ports = 8, |
---|
242 | | - .analog_out_ports = 8, |
---|
243 | | -}; |
---|
244 | | - |
---|
245 | | -static const struct snd_motu_spec motu_audio_express = { |
---|
246 | | - .name = "AudioExpress", |
---|
247 | | - .protocol = &snd_motu_protocol_v3, |
---|
248 | | - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | |
---|
249 | | - SND_MOTU_SPEC_TX_MICINST_CHUNK | |
---|
250 | | - SND_MOTU_SPEC_TX_RETURN_CHUNK | |
---|
251 | | - SND_MOTU_SPEC_RX_SEPARETED_MAIN | |
---|
252 | | - SND_MOTU_SPEC_RX_MIDI_2ND_Q | |
---|
253 | | - SND_MOTU_SPEC_TX_MIDI_3RD_Q, |
---|
254 | | - .analog_in_ports = 2, |
---|
255 | | - .analog_out_ports = 4, |
---|
256 | | -}; |
---|
257 | | - |
---|
258 | | -static const struct snd_motu_spec motu_4pre = { |
---|
259 | | - .name = "4pre", |
---|
260 | | - .protocol = &snd_motu_protocol_v3, |
---|
261 | | - .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 | |
---|
262 | | - SND_MOTU_SPEC_TX_MICINST_CHUNK | |
---|
263 | | - SND_MOTU_SPEC_TX_RETURN_CHUNK | |
---|
264 | | - SND_MOTU_SPEC_RX_SEPARETED_MAIN, |
---|
265 | | - .analog_in_ports = 2, |
---|
266 | | - .analog_out_ports = 2, |
---|
267 | | -}; |
---|
268 | | - |
---|
269 | 175 | #define SND_MOTU_DEV_ENTRY(model, data) \ |
---|
270 | 176 | { \ |
---|
271 | 177 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ |
---|
.. | .. |
---|
278 | 184 | } |
---|
279 | 185 | |
---|
280 | 186 | static const struct ieee1394_device_id motu_id_table[] = { |
---|
281 | | - SND_MOTU_DEV_ENTRY(0x000003, &motu_828mk2), |
---|
| 187 | + SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2), |
---|
282 | 188 | SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), |
---|
283 | | - SND_MOTU_DEV_ENTRY(0x000015, &motu_828mk3), /* FireWire only. */ |
---|
284 | | - SND_MOTU_DEV_ENTRY(0x000035, &motu_828mk3), /* Hybrid. */ |
---|
285 | | - SND_MOTU_DEV_ENTRY(0x000033, &motu_audio_express), |
---|
286 | | - SND_MOTU_DEV_ENTRY(0x000045, &motu_4pre), |
---|
| 189 | + SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite), |
---|
| 190 | + SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), |
---|
| 191 | + SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3), // FireWire only. |
---|
| 192 | + SND_MOTU_DEV_ENTRY(0x000019, &snd_motu_spec_ultralite_mk3), // FireWire only. |
---|
| 193 | + SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3), // Hybrid. |
---|
| 194 | + SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express), |
---|
| 195 | + SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre), |
---|
287 | 196 | { } |
---|
288 | 197 | }; |
---|
289 | 198 | MODULE_DEVICE_TABLE(ieee1394, motu_id_table); |
---|