267 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ff.c - a part of driver for RME Fireface series4 *5 * Copyright (c) 2015-2017 Takashi Sakamoto6 */7 8#include "ff.h"9 10#define OUI_RME 0x000a3511 12MODULE_DESCRIPTION("RME Fireface series Driver");13MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");14MODULE_LICENSE("GPL");15 16static void name_card(struct snd_ff *ff)17{18 struct fw_device *fw_dev = fw_parent_device(ff->unit);19 static const char *const names[] = {20 [SND_FF_UNIT_VERSION_FF800] = "Fireface800",21 [SND_FF_UNIT_VERSION_FF400] = "Fireface400",22 [SND_FF_UNIT_VERSION_UFX] = "FirefaceUFX",23 [SND_FF_UNIT_VERSION_UCX] = "FirefaceUCX",24 [SND_FF_UNIT_VERSION_802] = "Fireface802",25 };26 const char *name;27 28 name = names[ff->unit_version];29 30 strcpy(ff->card->driver, "Fireface");31 strcpy(ff->card->shortname, name);32 strcpy(ff->card->mixername, name);33 snprintf(ff->card->longname, sizeof(ff->card->longname),34 "RME %s, GUID %08x%08x at %s, S%d", name,35 fw_dev->config_rom[3], fw_dev->config_rom[4],36 dev_name(&ff->unit->device), 100 << fw_dev->max_speed);37}38 39static void ff_card_free(struct snd_card *card)40{41 struct snd_ff *ff = card->private_data;42 43 snd_ff_stream_destroy_duplex(ff);44 snd_ff_transaction_unregister(ff);45 46 kfree(ff->msg_parser);47 48 mutex_destroy(&ff->mutex);49 fw_unit_put(ff->unit);50}51 52static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry)53{54 struct snd_card *card;55 struct snd_ff *ff;56 int err;57 58 err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*ff), &card);59 if (err < 0)60 return err;61 card->private_free = ff_card_free;62 63 ff = card->private_data;64 ff->unit = fw_unit_get(unit);65 dev_set_drvdata(&unit->device, ff);66 ff->card = card;67 68 mutex_init(&ff->mutex);69 spin_lock_init(&ff->lock);70 init_waitqueue_head(&ff->hwdep_wait);71 72 ff->unit_version = entry->version;73 ff->spec = (const struct snd_ff_spec *)entry->driver_data;74 75 err = snd_ff_transaction_register(ff);76 if (err < 0)77 goto error;78 79 name_card(ff);80 81 err = snd_ff_stream_init_duplex(ff);82 if (err < 0)83 goto error;84 85 snd_ff_proc_init(ff);86 87 err = snd_ff_create_midi_devices(ff);88 if (err < 0)89 goto error;90 91 err = snd_ff_create_pcm_devices(ff);92 if (err < 0)93 goto error;94 95 err = snd_ff_create_hwdep_devices(ff);96 if (err < 0)97 goto error;98 99 if (ff->spec->protocol->msg_parser_size > 0) {100 ff->msg_parser = kzalloc(ff->spec->protocol->msg_parser_size, GFP_KERNEL);101 if (!ff->msg_parser) {102 err = -ENOMEM;103 goto error;104 }105 }106 107 err = snd_card_register(card);108 if (err < 0)109 goto error;110 111 return 0;112error:113 snd_card_free(card);114 return err;115}116 117static void snd_ff_update(struct fw_unit *unit)118{119 struct snd_ff *ff = dev_get_drvdata(&unit->device);120 121 snd_ff_transaction_reregister(ff);122 123 snd_ff_stream_update_duplex(ff);124}125 126static void snd_ff_remove(struct fw_unit *unit)127{128 struct snd_ff *ff = dev_get_drvdata(&unit->device);129 130 // Block till all of ALSA character devices are released.131 snd_card_free(ff->card);132}133 134static const struct snd_ff_spec spec_ff800 = {135 .pcm_capture_channels = {28, 20, 12},136 .pcm_playback_channels = {28, 20, 12},137 .midi_in_ports = 1,138 .midi_out_ports = 1,139 .protocol = &snd_ff_protocol_ff800,140 .midi_high_addr = 0x000200000320ull,141 .midi_addr_range = 12,142 .midi_rx_addrs = {0x000080180000ull, 0},143};144 145static const struct snd_ff_spec spec_ff400 = {146 .pcm_capture_channels = {18, 14, 10},147 .pcm_playback_channels = {18, 14, 10},148 .midi_in_ports = 2,149 .midi_out_ports = 2,150 .protocol = &snd_ff_protocol_ff400,151 .midi_high_addr = 0x0000801003f4ull,152 .midi_addr_range = SND_FF_MAXIMIM_MIDI_QUADS * 4,153 .midi_rx_addrs = {0x000080180000ull, 0x000080190000ull},154};155 156static const struct snd_ff_spec spec_ucx = {157 .pcm_capture_channels = {18, 14, 12},158 .pcm_playback_channels = {18, 14, 12},159 .midi_in_ports = 2,160 .midi_out_ports = 2,161 .protocol = &snd_ff_protocol_latter,162 .midi_high_addr = 0xffff00000034ull,163 .midi_addr_range = 0x80,164 .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},165};166 167static const struct snd_ff_spec spec_ufx_802 = {168 .pcm_capture_channels = {30, 22, 14},169 .pcm_playback_channels = {30, 22, 14},170 .midi_in_ports = 1,171 .midi_out_ports = 1,172 .protocol = &snd_ff_protocol_latter,173 .midi_high_addr = 0xffff00000034ull,174 .midi_addr_range = 0x80,175 .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},176};177 178static const struct ieee1394_device_id snd_ff_id_table[] = {179 /* Fireface 800 */180 {181 .match_flags = IEEE1394_MATCH_VENDOR_ID |182 IEEE1394_MATCH_SPECIFIER_ID |183 IEEE1394_MATCH_VERSION |184 IEEE1394_MATCH_MODEL_ID,185 .vendor_id = OUI_RME,186 .specifier_id = OUI_RME,187 .version = SND_FF_UNIT_VERSION_FF800,188 .model_id = 0x101800,189 .driver_data = (kernel_ulong_t)&spec_ff800,190 },191 /* Fireface 400 */192 {193 .match_flags = IEEE1394_MATCH_VENDOR_ID |194 IEEE1394_MATCH_SPECIFIER_ID |195 IEEE1394_MATCH_VERSION |196 IEEE1394_MATCH_MODEL_ID,197 .vendor_id = OUI_RME,198 .specifier_id = OUI_RME,199 .version = SND_FF_UNIT_VERSION_FF400,200 .model_id = 0x101800,201 .driver_data = (kernel_ulong_t)&spec_ff400,202 },203 // Fireface UFX.204 {205 .match_flags = IEEE1394_MATCH_VENDOR_ID |206 IEEE1394_MATCH_SPECIFIER_ID |207 IEEE1394_MATCH_VERSION |208 IEEE1394_MATCH_MODEL_ID,209 .vendor_id = OUI_RME,210 .specifier_id = OUI_RME,211 .version = SND_FF_UNIT_VERSION_UFX,212 .model_id = 0x101800,213 .driver_data = (kernel_ulong_t)&spec_ufx_802,214 },215 // Fireface UCX.216 {217 .match_flags = IEEE1394_MATCH_VENDOR_ID |218 IEEE1394_MATCH_SPECIFIER_ID |219 IEEE1394_MATCH_VERSION |220 IEEE1394_MATCH_MODEL_ID,221 .vendor_id = OUI_RME,222 .specifier_id = OUI_RME,223 .version = SND_FF_UNIT_VERSION_UCX,224 .model_id = 0x101800,225 .driver_data = (kernel_ulong_t)&spec_ucx,226 },227 // Fireface 802.228 {229 .match_flags = IEEE1394_MATCH_VENDOR_ID |230 IEEE1394_MATCH_SPECIFIER_ID |231 IEEE1394_MATCH_VERSION |232 IEEE1394_MATCH_MODEL_ID,233 .vendor_id = OUI_RME,234 .specifier_id = OUI_RME,235 .version = SND_FF_UNIT_VERSION_802,236 .model_id = 0x101800,237 .driver_data = (kernel_ulong_t)&spec_ufx_802,238 },239 {}240};241MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table);242 243static struct fw_driver ff_driver = {244 .driver = {245 .owner = THIS_MODULE,246 .name = KBUILD_MODNAME,247 .bus = &fw_bus_type,248 },249 .probe = snd_ff_probe,250 .update = snd_ff_update,251 .remove = snd_ff_remove,252 .id_table = snd_ff_id_table,253};254 255static int __init snd_ff_init(void)256{257 return driver_register(&ff_driver.driver);258}259 260static void __exit snd_ff_exit(void)261{262 driver_unregister(&ff_driver.driver);263}264 265module_init(snd_ff_init);266module_exit(snd_ff_exit);267