diff options
Diffstat (limited to '')
-rw-r--r-- | sound/firewire/fireface/ff.c | 151 |
1 files changed, 80 insertions, 71 deletions
diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c index f5a016560eb8..7bf51d062021 100644 --- a/sound/firewire/fireface/ff.c +++ b/sound/firewire/fireface/ff.c @@ -16,12 +16,22 @@ MODULE_LICENSE("GPL v2"); static void name_card(struct snd_ff *ff) { struct fw_device *fw_dev = fw_parent_device(ff->unit); + const char *const names[] = { + [SND_FF_UNIT_VERSION_FF800] = "Fireface800", + [SND_FF_UNIT_VERSION_FF400] = "Fireface400", + [SND_FF_UNIT_VERSION_UFX] = "FirefaceUFX", + [SND_FF_UNIT_VERSION_UCX] = "FirefaceUCX", + [SND_FF_UNIT_VERSION_802] = "Fireface802", + }; + const char *name; + + name = names[ff->unit_version]; strcpy(ff->card->driver, "Fireface"); - strcpy(ff->card->shortname, ff->spec->name); - strcpy(ff->card->mixername, ff->spec->name); + strcpy(ff->card->shortname, name); + strcpy(ff->card->mixername, name); snprintf(ff->card->longname, sizeof(ff->card->longname), - "RME %s, GUID %08x%08x at %s, S%d", ff->spec->name, + "RME %s, GUID %08x%08x at %s, S%d", name, fw_dev->config_rom[3], fw_dev->config_rom[4], dev_name(&ff->unit->device), 100 << fw_dev->max_speed); } @@ -32,22 +42,33 @@ static void ff_card_free(struct snd_card *card) snd_ff_stream_destroy_duplex(ff); snd_ff_transaction_unregister(ff); + + mutex_destroy(&ff->mutex); + fw_unit_put(ff->unit); } -static void do_registration(struct work_struct *work) +static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry) { - struct snd_ff *ff = container_of(work, struct snd_ff, dwork.work); + struct snd_card *card; + struct snd_ff *ff; int err; - if (ff->registered) - return; - - err = snd_card_new(&ff->unit->device, -1, NULL, THIS_MODULE, 0, - &ff->card); + err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*ff), &card); if (err < 0) - return; - ff->card->private_free = ff_card_free; - ff->card->private_data = ff; + return err; + card->private_free = ff_card_free; + + ff = card->private_data; + ff->unit = fw_unit_get(unit); + dev_set_drvdata(&unit->device, ff); + ff->card = card; + + mutex_init(&ff->mutex); + spin_lock_init(&ff->lock); + init_waitqueue_head(&ff->hwdep_wait); + + ff->unit_version = entry->version; + ff->spec = (const struct snd_ff_spec *)entry->driver_data; err = snd_ff_transaction_register(ff); if (err < 0) @@ -73,79 +94,34 @@ static void do_registration(struct work_struct *work) if (err < 0) goto error; - err = snd_card_register(ff->card); + err = snd_card_register(card); if (err < 0) goto error; - ff->registered = true; - - return; -error: - snd_card_free(ff->card); - dev_info(&ff->unit->device, - "Sound card registration failed: %d\n", err); -} - -static int snd_ff_probe(struct fw_unit *unit, - const struct ieee1394_device_id *entry) -{ - struct snd_ff *ff; - - ff = devm_kzalloc(&unit->device, sizeof(struct snd_ff), GFP_KERNEL); - if (!ff) - return -ENOMEM; - ff->unit = fw_unit_get(unit); - dev_set_drvdata(&unit->device, ff); - - mutex_init(&ff->mutex); - spin_lock_init(&ff->lock); - init_waitqueue_head(&ff->hwdep_wait); - - ff->spec = (const struct snd_ff_spec *)entry->driver_data; - - /* Register this sound card later. */ - INIT_DEFERRABLE_WORK(&ff->dwork, do_registration); - snd_fw_schedule_registration(unit, &ff->dwork); - return 0; +error: + snd_card_free(card); + return err; } static void snd_ff_update(struct fw_unit *unit) { struct snd_ff *ff = dev_get_drvdata(&unit->device); - /* Postpone a workqueue for deferred registration. */ - if (!ff->registered) - snd_fw_schedule_registration(unit, &ff->dwork); - snd_ff_transaction_reregister(ff); - if (ff->registered) - snd_ff_stream_update_duplex(ff); + snd_ff_stream_update_duplex(ff); } static void snd_ff_remove(struct fw_unit *unit) { struct snd_ff *ff = dev_get_drvdata(&unit->device); - /* - * Confirm to stop the work for registration before the sound card is - * going to be released. The work is not scheduled again because bus - * reset handler is not called anymore. - */ - cancel_work_sync(&ff->dwork.work); - - if (ff->registered) { - // Block till all of ALSA character devices are released. - snd_card_free(ff->card); - } - - mutex_destroy(&ff->mutex); - fw_unit_put(ff->unit); + // Block till all of ALSA character devices are released. + snd_card_free(ff->card); } static const struct snd_ff_spec spec_ff800 = { - .name = "Fireface800", .pcm_capture_channels = {28, 20, 12}, .pcm_playback_channels = {28, 20, 12}, .midi_in_ports = 1, @@ -157,7 +133,6 @@ static const struct snd_ff_spec spec_ff800 = { }; static const struct snd_ff_spec spec_ff400 = { - .name = "Fireface400", .pcm_capture_channels = {18, 14, 10}, .pcm_playback_channels = {18, 14, 10}, .midi_in_ports = 2, @@ -169,7 +144,6 @@ static const struct snd_ff_spec spec_ff400 = { }; static const struct snd_ff_spec spec_ucx = { - .name = "FirefaceUCX", .pcm_capture_channels = {18, 14, 12}, .pcm_playback_channels = {18, 14, 12}, .midi_in_ports = 2, @@ -180,6 +154,17 @@ static const struct snd_ff_spec spec_ucx = { .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull}, }; +static const struct snd_ff_spec spec_ufx_802 = { + .pcm_capture_channels = {30, 22, 14}, + .pcm_playback_channels = {30, 22, 14}, + .midi_in_ports = 1, + .midi_out_ports = 1, + .protocol = &snd_ff_protocol_latter, + .midi_high_addr = 0xffff00000034ull, + .midi_addr_range = 0x80, + .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull}, +}; + static const struct ieee1394_device_id snd_ff_id_table[] = { /* Fireface 800 */ { @@ -189,7 +174,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { IEEE1394_MATCH_MODEL_ID, .vendor_id = OUI_RME, .specifier_id = OUI_RME, - .version = 0x000001, + .version = SND_FF_UNIT_VERSION_FF800, .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ff800, }, @@ -201,10 +186,22 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { IEEE1394_MATCH_MODEL_ID, .vendor_id = OUI_RME, .specifier_id = OUI_RME, - .version = 0x000002, + .version = SND_FF_UNIT_VERSION_FF400, .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ff400, }, + // Fireface UFX. + { + .match_flags = IEEE1394_MATCH_VENDOR_ID | + IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION | + IEEE1394_MATCH_MODEL_ID, + .vendor_id = OUI_RME, + .specifier_id = OUI_RME, + .version = SND_FF_UNIT_VERSION_UFX, + .model_id = 0x101800, + .driver_data = (kernel_ulong_t)&spec_ufx_802, + }, // Fireface UCX. { .match_flags = IEEE1394_MATCH_VENDOR_ID | @@ -213,10 +210,22 @@ static const struct ieee1394_device_id snd_ff_id_table[] = { IEEE1394_MATCH_MODEL_ID, .vendor_id = OUI_RME, .specifier_id = OUI_RME, - .version = 0x000004, + .version = SND_FF_UNIT_VERSION_UCX, .model_id = 0x101800, .driver_data = (kernel_ulong_t)&spec_ucx, }, + // Fireface 802. + { + .match_flags = IEEE1394_MATCH_VENDOR_ID | + IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION | + IEEE1394_MATCH_MODEL_ID, + .vendor_id = OUI_RME, + .specifier_id = OUI_RME, + .version = SND_FF_UNIT_VERSION_802, + .model_id = 0x101800, + .driver_data = (kernel_ulong_t)&spec_ufx_802, + }, {} }; MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table); @@ -224,7 +233,7 @@ MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table); static struct fw_driver ff_driver = { .driver = { .owner = THIS_MODULE, - .name = "snd-fireface", + .name = KBUILD_MODNAME, .bus = &fw_bus_type, }, .probe = snd_ff_probe, |