linux/sound/firewire/fireface/ff.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ff.c - a part of driver for RME Fireface series
   4 *
   5 * Copyright (c) 2015-2017 Takashi Sakamoto
   6 */
   7
   8#include "ff.h"
   9
  10#define OUI_RME 0x000a35
  11
  12MODULE_DESCRIPTION("RME Fireface series Driver");
  13MODULE_AUTHOR("Takashi Sakamoto <o-takashi@sakamocchi.jp>");
  14MODULE_LICENSE("GPL v2");
  15
  16static void name_card(struct snd_ff *ff)
  17{
  18        struct fw_device *fw_dev = fw_parent_device(ff->unit);
  19        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
  47static void do_registration(struct work_struct *work)
  48{
  49        struct snd_ff *ff = container_of(work, struct snd_ff, dwork.work);
  50        int err;
  51
  52        if (ff->registered)
  53                return;
  54
  55        err = snd_card_new(&ff->unit->device, -1, NULL, THIS_MODULE, 0,
  56                           &ff->card);
  57        if (err < 0)
  58                return;
  59        ff->card->private_free = ff_card_free;
  60        ff->card->private_data = ff;
  61
  62        err = snd_ff_transaction_register(ff);
  63        if (err < 0)
  64                goto error;
  65
  66        name_card(ff);
  67
  68        err = snd_ff_stream_init_duplex(ff);
  69        if (err < 0)
  70                goto error;
  71
  72        snd_ff_proc_init(ff);
  73
  74        err = snd_ff_create_midi_devices(ff);
  75        if (err < 0)
  76                goto error;
  77
  78        err = snd_ff_create_pcm_devices(ff);
  79        if (err < 0)
  80                goto error;
  81
  82        err = snd_ff_create_hwdep_devices(ff);
  83        if (err < 0)
  84                goto error;
  85
  86        err = snd_card_register(ff->card);
  87        if (err < 0)
  88                goto error;
  89
  90        ff->registered = true;
  91
  92        return;
  93error:
  94        snd_card_free(ff->card);
  95        dev_info(&ff->unit->device,
  96                 "Sound card registration failed: %d\n", err);
  97}
  98
  99static int snd_ff_probe(struct fw_unit *unit,
 100                           const struct ieee1394_device_id *entry)
 101{
 102        struct snd_ff *ff;
 103
 104        ff = devm_kzalloc(&unit->device, sizeof(struct snd_ff), GFP_KERNEL);
 105        if (!ff)
 106                return -ENOMEM;
 107        ff->unit = fw_unit_get(unit);
 108        dev_set_drvdata(&unit->device, ff);
 109
 110        mutex_init(&ff->mutex);
 111        spin_lock_init(&ff->lock);
 112        init_waitqueue_head(&ff->hwdep_wait);
 113
 114        ff->unit_version = entry->version;
 115        ff->spec = (const struct snd_ff_spec *)entry->driver_data;
 116
 117        /* Register this sound card later. */
 118        INIT_DEFERRABLE_WORK(&ff->dwork, do_registration);
 119        snd_fw_schedule_registration(unit, &ff->dwork);
 120
 121        return 0;
 122}
 123
 124static void snd_ff_update(struct fw_unit *unit)
 125{
 126        struct snd_ff *ff = dev_get_drvdata(&unit->device);
 127
 128        /* Postpone a workqueue for deferred registration. */
 129        if (!ff->registered)
 130                snd_fw_schedule_registration(unit, &ff->dwork);
 131
 132        snd_ff_transaction_reregister(ff);
 133
 134        if (ff->registered)
 135                snd_ff_stream_update_duplex(ff);
 136}
 137
 138static void snd_ff_remove(struct fw_unit *unit)
 139{
 140        struct snd_ff *ff = dev_get_drvdata(&unit->device);
 141
 142        /*
 143         * Confirm to stop the work for registration before the sound card is
 144         * going to be released. The work is not scheduled again because bus
 145         * reset handler is not called anymore.
 146         */
 147        cancel_work_sync(&ff->dwork.work);
 148
 149        if (ff->registered) {
 150                // Block till all of ALSA character devices are released.
 151                snd_card_free(ff->card);
 152        }
 153
 154        mutex_destroy(&ff->mutex);
 155        fw_unit_put(ff->unit);
 156}
 157
 158static const struct snd_ff_spec spec_ff800 = {
 159        .pcm_capture_channels = {28, 20, 12},
 160        .pcm_playback_channels = {28, 20, 12},
 161        .midi_in_ports = 1,
 162        .midi_out_ports = 1,
 163        .protocol = &snd_ff_protocol_ff800,
 164        .midi_high_addr = 0x000200000320ull,
 165        .midi_addr_range = 12,
 166        .midi_rx_addrs = {0x000080180000ull, 0},
 167};
 168
 169static const struct snd_ff_spec spec_ff400 = {
 170        .pcm_capture_channels = {18, 14, 10},
 171        .pcm_playback_channels = {18, 14, 10},
 172        .midi_in_ports = 2,
 173        .midi_out_ports = 2,
 174        .protocol = &snd_ff_protocol_ff400,
 175        .midi_high_addr = 0x0000801003f4ull,
 176        .midi_addr_range = SND_FF_MAXIMIM_MIDI_QUADS * 4,
 177        .midi_rx_addrs = {0x000080180000ull, 0x000080190000ull},
 178};
 179
 180static const struct snd_ff_spec spec_ucx = {
 181        .pcm_capture_channels = {18, 14, 12},
 182        .pcm_playback_channels = {18, 14, 12},
 183        .midi_in_ports = 2,
 184        .midi_out_ports = 2,
 185        .protocol = &snd_ff_protocol_latter,
 186        .midi_high_addr = 0xffff00000034ull,
 187        .midi_addr_range = 0x80,
 188        .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},
 189};
 190
 191static const struct snd_ff_spec spec_ufx_802 = {
 192        .pcm_capture_channels = {30, 22, 14},
 193        .pcm_playback_channels = {30, 22, 14},
 194        .midi_in_ports = 1,
 195        .midi_out_ports = 1,
 196        .protocol = &snd_ff_protocol_latter,
 197        .midi_high_addr = 0xffff00000034ull,
 198        .midi_addr_range = 0x80,
 199        .midi_rx_addrs = {0xffff00000030ull, 0xffff00000030ull},
 200};
 201
 202static const struct ieee1394_device_id snd_ff_id_table[] = {
 203        /* Fireface 800 */
 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_FF800,
 212                .model_id       = 0x101800,
 213                .driver_data    = (kernel_ulong_t)&spec_ff800,
 214        },
 215        /* Fireface 400 */
 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_FF400,
 224                .model_id       = 0x101800,
 225                .driver_data    = (kernel_ulong_t)&spec_ff400,
 226        },
 227        // Fireface UFX.
 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_UFX,
 236                .model_id       = 0x101800,
 237                .driver_data    = (kernel_ulong_t)&spec_ufx_802,
 238        },
 239        // Fireface UCX.
 240        {
 241                .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 242                                  IEEE1394_MATCH_SPECIFIER_ID |
 243                                  IEEE1394_MATCH_VERSION |
 244                                  IEEE1394_MATCH_MODEL_ID,
 245                .vendor_id      = OUI_RME,
 246                .specifier_id   = OUI_RME,
 247                .version        = SND_FF_UNIT_VERSION_UCX,
 248                .model_id       = 0x101800,
 249                .driver_data    = (kernel_ulong_t)&spec_ucx,
 250        },
 251        // Fireface 802.
 252        {
 253                .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 254                                  IEEE1394_MATCH_SPECIFIER_ID |
 255                                  IEEE1394_MATCH_VERSION |
 256                                  IEEE1394_MATCH_MODEL_ID,
 257                .vendor_id      = OUI_RME,
 258                .specifier_id   = OUI_RME,
 259                .version        = SND_FF_UNIT_VERSION_802,
 260                .model_id       = 0x101800,
 261                .driver_data    = (kernel_ulong_t)&spec_ufx_802,
 262        },
 263        {}
 264};
 265MODULE_DEVICE_TABLE(ieee1394, snd_ff_id_table);
 266
 267static struct fw_driver ff_driver = {
 268        .driver = {
 269                .owner  = THIS_MODULE,
 270                .name   = KBUILD_MODNAME,
 271                .bus    = &fw_bus_type,
 272        },
 273        .probe    = snd_ff_probe,
 274        .update   = snd_ff_update,
 275        .remove   = snd_ff_remove,
 276        .id_table = snd_ff_id_table,
 277};
 278
 279static int __init snd_ff_init(void)
 280{
 281        return driver_register(&ff_driver.driver);
 282}
 283
 284static void __exit snd_ff_exit(void)
 285{
 286        driver_unregister(&ff_driver.driver);
 287}
 288
 289module_init(snd_ff_init);
 290module_exit(snd_ff_exit);
 291