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