1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * motu.c - a part of driver for MOTU FireWire series |
4 | * |
5 | * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp> |
6 | */ |
7 | |
8 | #include "motu.h" |
9 | |
10 | #define OUI_MOTU 0x0001f2 |
11 | |
12 | MODULE_DESCRIPTION("MOTU FireWire driver" ); |
13 | MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>" ); |
14 | MODULE_LICENSE("GPL" ); |
15 | |
16 | const unsigned int snd_motu_clock_rates[SND_MOTU_CLOCK_RATE_COUNT] = { |
17 | /* mode 0 */ |
18 | [0] = 44100, |
19 | [1] = 48000, |
20 | /* mode 1 */ |
21 | [2] = 88200, |
22 | [3] = 96000, |
23 | /* mode 2 */ |
24 | [4] = 176400, |
25 | [5] = 192000, |
26 | }; |
27 | |
28 | static void name_card(struct snd_motu *motu) |
29 | { |
30 | struct fw_device *fw_dev = fw_parent_device(motu->unit); |
31 | struct fw_csr_iterator it; |
32 | int key, val; |
33 | u32 version = 0; |
34 | |
35 | fw_csr_iterator_init(ci: &it, p: motu->unit->directory); |
36 | while (fw_csr_iterator_next(ci: &it, key: &key, value: &val)) { |
37 | switch (key) { |
38 | case CSR_MODEL: |
39 | version = val; |
40 | break; |
41 | } |
42 | } |
43 | |
44 | strcpy(p: motu->card->driver, q: "FW-MOTU" ); |
45 | strcpy(p: motu->card->shortname, q: motu->spec->name); |
46 | strcpy(p: motu->card->mixername, q: motu->spec->name); |
47 | snprintf(buf: motu->card->longname, size: sizeof(motu->card->longname), |
48 | fmt: "MOTU %s (version:%06x), GUID %08x%08x at %s, S%d" , |
49 | motu->spec->name, version, |
50 | fw_dev->config_rom[3], fw_dev->config_rom[4], |
51 | dev_name(dev: &motu->unit->device), 100 << fw_dev->max_speed); |
52 | } |
53 | |
54 | static void motu_card_free(struct snd_card *card) |
55 | { |
56 | struct snd_motu *motu = card->private_data; |
57 | |
58 | snd_motu_transaction_unregister(motu); |
59 | snd_motu_stream_destroy_duplex(motu); |
60 | |
61 | mutex_destroy(lock: &motu->mutex); |
62 | fw_unit_put(unit: motu->unit); |
63 | } |
64 | |
65 | static int motu_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) |
66 | { |
67 | struct snd_card *card; |
68 | struct snd_motu *motu; |
69 | int err; |
70 | |
71 | err = snd_card_new(parent: &unit->device, idx: -1, NULL, THIS_MODULE, extra_size: sizeof(*motu), card_ret: &card); |
72 | if (err < 0) |
73 | return err; |
74 | card->private_free = motu_card_free; |
75 | |
76 | motu = card->private_data; |
77 | motu->unit = fw_unit_get(unit); |
78 | dev_set_drvdata(dev: &unit->device, data: motu); |
79 | motu->card = card; |
80 | |
81 | motu->spec = (const struct snd_motu_spec *)entry->driver_data; |
82 | mutex_init(&motu->mutex); |
83 | spin_lock_init(&motu->lock); |
84 | init_waitqueue_head(&motu->hwdep_wait); |
85 | |
86 | name_card(motu); |
87 | |
88 | err = snd_motu_transaction_register(motu); |
89 | if (err < 0) |
90 | goto error; |
91 | |
92 | err = snd_motu_stream_init_duplex(motu); |
93 | if (err < 0) |
94 | goto error; |
95 | |
96 | snd_motu_proc_init(motu); |
97 | |
98 | err = snd_motu_create_pcm_devices(motu); |
99 | if (err < 0) |
100 | goto error; |
101 | |
102 | if ((motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_2ND_Q) || |
103 | (motu->spec->flags & SND_MOTU_SPEC_RX_MIDI_3RD_Q) || |
104 | (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_2ND_Q) || |
105 | (motu->spec->flags & SND_MOTU_SPEC_TX_MIDI_3RD_Q)) { |
106 | err = snd_motu_create_midi_devices(motu); |
107 | if (err < 0) |
108 | goto error; |
109 | } |
110 | |
111 | err = snd_motu_create_hwdep_device(motu); |
112 | if (err < 0) |
113 | goto error; |
114 | |
115 | if (motu->spec->flags & SND_MOTU_SPEC_REGISTER_DSP) { |
116 | err = snd_motu_register_dsp_message_parser_new(motu); |
117 | if (err < 0) |
118 | goto error; |
119 | } else if (motu->spec->flags & SND_MOTU_SPEC_COMMAND_DSP) { |
120 | err = snd_motu_command_dsp_message_parser_new(motu); |
121 | if (err < 0) |
122 | goto error; |
123 | } |
124 | |
125 | err = snd_card_register(card); |
126 | if (err < 0) |
127 | goto error; |
128 | |
129 | return 0; |
130 | error: |
131 | snd_card_free(card); |
132 | return err; |
133 | } |
134 | |
135 | static void motu_remove(struct fw_unit *unit) |
136 | { |
137 | struct snd_motu *motu = dev_get_drvdata(dev: &unit->device); |
138 | |
139 | // Block till all of ALSA character devices are released. |
140 | snd_card_free(card: motu->card); |
141 | } |
142 | |
143 | static void motu_bus_update(struct fw_unit *unit) |
144 | { |
145 | struct snd_motu *motu = dev_get_drvdata(dev: &unit->device); |
146 | |
147 | /* The handler address register becomes initialized. */ |
148 | snd_motu_transaction_reregister(motu); |
149 | } |
150 | |
151 | #define SND_MOTU_DEV_ENTRY(model, data) \ |
152 | { \ |
153 | .match_flags = IEEE1394_MATCH_VENDOR_ID | \ |
154 | IEEE1394_MATCH_SPECIFIER_ID | \ |
155 | IEEE1394_MATCH_VERSION, \ |
156 | .vendor_id = OUI_MOTU, \ |
157 | .specifier_id = OUI_MOTU, \ |
158 | .version = model, \ |
159 | .driver_data = (kernel_ulong_t)data, \ |
160 | } |
161 | |
162 | static const struct ieee1394_device_id motu_id_table[] = { |
163 | SND_MOTU_DEV_ENTRY(0x000001, &snd_motu_spec_828), |
164 | SND_MOTU_DEV_ENTRY(0x000002, &snd_motu_spec_896), |
165 | SND_MOTU_DEV_ENTRY(0x000003, &snd_motu_spec_828mk2), |
166 | SND_MOTU_DEV_ENTRY(0x000005, &snd_motu_spec_896hd), |
167 | SND_MOTU_DEV_ENTRY(0x000009, &snd_motu_spec_traveler), |
168 | SND_MOTU_DEV_ENTRY(0x00000d, &snd_motu_spec_ultralite), |
169 | SND_MOTU_DEV_ENTRY(0x00000f, &snd_motu_spec_8pre), |
170 | SND_MOTU_DEV_ENTRY(0x000015, &snd_motu_spec_828mk3_fw), // FireWire only. |
171 | SND_MOTU_DEV_ENTRY(0x000017, &snd_motu_spec_896mk3), // FireWire only. |
172 | SND_MOTU_DEV_ENTRY(0x000019, &snd_motu_spec_ultralite_mk3), // FireWire only. |
173 | SND_MOTU_DEV_ENTRY(0x00001b, &snd_motu_spec_traveler_mk3), |
174 | SND_MOTU_DEV_ENTRY(0x000030, &snd_motu_spec_ultralite_mk3), // Hybrid. |
175 | SND_MOTU_DEV_ENTRY(0x000035, &snd_motu_spec_828mk3_hybrid), // Hybrid. |
176 | SND_MOTU_DEV_ENTRY(0x000037, &snd_motu_spec_896mk3), // Hybrid. |
177 | SND_MOTU_DEV_ENTRY(0x000033, &snd_motu_spec_audio_express), |
178 | SND_MOTU_DEV_ENTRY(0x000039, &snd_motu_spec_track16), |
179 | SND_MOTU_DEV_ENTRY(0x000045, &snd_motu_spec_4pre), |
180 | { } |
181 | }; |
182 | MODULE_DEVICE_TABLE(ieee1394, motu_id_table); |
183 | |
184 | static struct fw_driver motu_driver = { |
185 | .driver = { |
186 | .owner = THIS_MODULE, |
187 | .name = KBUILD_MODNAME, |
188 | .bus = &fw_bus_type, |
189 | }, |
190 | .probe = motu_probe, |
191 | .update = motu_bus_update, |
192 | .remove = motu_remove, |
193 | .id_table = motu_id_table, |
194 | }; |
195 | |
196 | static int __init alsa_motu_init(void) |
197 | { |
198 | return driver_register(drv: &motu_driver.driver); |
199 | } |
200 | |
201 | static void __exit alsa_motu_exit(void) |
202 | { |
203 | driver_unregister(drv: &motu_driver.driver); |
204 | } |
205 | |
206 | module_init(alsa_motu_init); |
207 | module_exit(alsa_motu_exit); |
208 | |