root/sound/firewire/dice/dice.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_dice_category
  2. check_clock_caps
  3. dice_card_strings
  4. dice_card_free
  5. do_registration
  6. dice_probe
  7. dice_remove
  8. dice_bus_reset
  9. alsa_dice_init
  10. alsa_dice_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * TC Applied Technologies Digital Interface Communications Engine driver
   4  *
   5  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
   6  */
   7 
   8 #include "dice.h"
   9 
  10 MODULE_DESCRIPTION("DICE driver");
  11 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
  12 MODULE_LICENSE("GPL v2");
  13 
  14 #define OUI_WEISS               0x001c6a
  15 #define OUI_LOUD                0x000ff2
  16 #define OUI_FOCUSRITE           0x00130e
  17 #define OUI_TCELECTRONIC        0x000166
  18 #define OUI_ALESIS              0x000595
  19 #define OUI_MAUDIO              0x000d6c
  20 #define OUI_MYTEK               0x001ee8
  21 #define OUI_SSL                 0x0050c2        // Actually ID reserved by IEEE.
  22 #define OUI_PRESONUS            0x000a92
  23 
  24 #define DICE_CATEGORY_ID        0x04
  25 #define WEISS_CATEGORY_ID       0x00
  26 #define LOUD_CATEGORY_ID        0x10
  27 
  28 #define MODEL_ALESIS_IO_BOTH    0x000001
  29 
  30 static int check_dice_category(struct fw_unit *unit)
  31 {
  32         struct fw_device *device = fw_parent_device(unit);
  33         struct fw_csr_iterator it;
  34         int key, val, vendor = -1, model = -1;
  35         unsigned int category;
  36 
  37         /*
  38          * Check that GUID and unit directory are constructed according to DICE
  39          * rules, i.e., that the specifier ID is the GUID's OUI, and that the
  40          * GUID chip ID consists of the 8-bit category ID, the 10-bit product
  41          * ID, and a 22-bit serial number.
  42          */
  43         fw_csr_iterator_init(&it, unit->directory);
  44         while (fw_csr_iterator_next(&it, &key, &val)) {
  45                 switch (key) {
  46                 case CSR_SPECIFIER_ID:
  47                         vendor = val;
  48                         break;
  49                 case CSR_MODEL:
  50                         model = val;
  51                         break;
  52                 }
  53         }
  54 
  55         if (vendor == OUI_WEISS)
  56                 category = WEISS_CATEGORY_ID;
  57         else if (vendor == OUI_LOUD)
  58                 category = LOUD_CATEGORY_ID;
  59         else
  60                 category = DICE_CATEGORY_ID;
  61         if (device->config_rom[3] != ((vendor << 8) | category) ||
  62             device->config_rom[4] >> 22 != model)
  63                 return -ENODEV;
  64 
  65         return 0;
  66 }
  67 
  68 static int check_clock_caps(struct snd_dice *dice)
  69 {
  70         __be32 value;
  71         int err;
  72 
  73         /* some very old firmwares don't tell about their clock support */
  74         if (dice->clock_caps > 0) {
  75                 err = snd_dice_transaction_read_global(dice,
  76                                                 GLOBAL_CLOCK_CAPABILITIES,
  77                                                 &value, 4);
  78                 if (err < 0)
  79                         return err;
  80                 dice->clock_caps = be32_to_cpu(value);
  81         } else {
  82                 /* this should be supported by any device */
  83                 dice->clock_caps = CLOCK_CAP_RATE_44100 |
  84                                    CLOCK_CAP_RATE_48000 |
  85                                    CLOCK_CAP_SOURCE_ARX1 |
  86                                    CLOCK_CAP_SOURCE_INTERNAL;
  87         }
  88 
  89         return 0;
  90 }
  91 
  92 static void dice_card_strings(struct snd_dice *dice)
  93 {
  94         struct snd_card *card = dice->card;
  95         struct fw_device *dev = fw_parent_device(dice->unit);
  96         char vendor[32], model[32];
  97         unsigned int i;
  98         int err;
  99 
 100         strcpy(card->driver, "DICE");
 101 
 102         strcpy(card->shortname, "DICE");
 103         BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname));
 104         err = snd_dice_transaction_read_global(dice, GLOBAL_NICK_NAME,
 105                                                card->shortname,
 106                                                sizeof(card->shortname));
 107         if (err >= 0) {
 108                 /* DICE strings are returned in "always-wrong" endianness */
 109                 BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0);
 110                 for (i = 0; i < sizeof(card->shortname); i += 4)
 111                         swab32s((u32 *)&card->shortname[i]);
 112                 card->shortname[sizeof(card->shortname) - 1] = '\0';
 113         }
 114 
 115         strcpy(vendor, "?");
 116         fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor));
 117         strcpy(model, "?");
 118         fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model));
 119         snprintf(card->longname, sizeof(card->longname),
 120                  "%s %s (serial %u) at %s, S%d",
 121                  vendor, model, dev->config_rom[4] & 0x3fffff,
 122                  dev_name(&dice->unit->device), 100 << dev->max_speed);
 123 
 124         strcpy(card->mixername, "DICE");
 125 }
 126 
 127 static void dice_card_free(struct snd_card *card)
 128 {
 129         struct snd_dice *dice = card->private_data;
 130 
 131         snd_dice_stream_destroy_duplex(dice);
 132         snd_dice_transaction_destroy(dice);
 133 }
 134 
 135 static void do_registration(struct work_struct *work)
 136 {
 137         struct snd_dice *dice = container_of(work, struct snd_dice, dwork.work);
 138         int err;
 139 
 140         if (dice->registered)
 141                 return;
 142 
 143         err = snd_card_new(&dice->unit->device, -1, NULL, THIS_MODULE, 0,
 144                            &dice->card);
 145         if (err < 0)
 146                 return;
 147         dice->card->private_free = dice_card_free;
 148         dice->card->private_data = dice;
 149 
 150         err = snd_dice_transaction_init(dice);
 151         if (err < 0)
 152                 goto error;
 153 
 154         err = check_clock_caps(dice);
 155         if (err < 0)
 156                 goto error;
 157 
 158         dice_card_strings(dice);
 159 
 160         err = dice->detect_formats(dice);
 161         if (err < 0)
 162                 goto error;
 163 
 164         err = snd_dice_stream_init_duplex(dice);
 165         if (err < 0)
 166                 goto error;
 167 
 168         snd_dice_create_proc(dice);
 169 
 170         err = snd_dice_create_pcm(dice);
 171         if (err < 0)
 172                 goto error;
 173 
 174         err = snd_dice_create_midi(dice);
 175         if (err < 0)
 176                 goto error;
 177 
 178         err = snd_dice_create_hwdep(dice);
 179         if (err < 0)
 180                 goto error;
 181 
 182         err = snd_card_register(dice->card);
 183         if (err < 0)
 184                 goto error;
 185 
 186         dice->registered = true;
 187 
 188         return;
 189 error:
 190         snd_card_free(dice->card);
 191         dev_info(&dice->unit->device,
 192                  "Sound card registration failed: %d\n", err);
 193 }
 194 
 195 static int dice_probe(struct fw_unit *unit,
 196                       const struct ieee1394_device_id *entry)
 197 {
 198         struct snd_dice *dice;
 199         int err;
 200 
 201         if (!entry->driver_data && entry->vendor_id != OUI_SSL) {
 202                 err = check_dice_category(unit);
 203                 if (err < 0)
 204                         return -ENODEV;
 205         }
 206 
 207         /* Allocate this independent of sound card instance. */
 208         dice = devm_kzalloc(&unit->device, sizeof(struct snd_dice), GFP_KERNEL);
 209         if (!dice)
 210                 return -ENOMEM;
 211         dice->unit = fw_unit_get(unit);
 212         dev_set_drvdata(&unit->device, dice);
 213 
 214         if (!entry->driver_data) {
 215                 dice->detect_formats = snd_dice_stream_detect_current_formats;
 216         } else {
 217                 dice->detect_formats =
 218                                 (snd_dice_detect_formats_t)entry->driver_data;
 219         }
 220 
 221         spin_lock_init(&dice->lock);
 222         mutex_init(&dice->mutex);
 223         init_completion(&dice->clock_accepted);
 224         init_waitqueue_head(&dice->hwdep_wait);
 225 
 226         /* Allocate and register this sound card later. */
 227         INIT_DEFERRABLE_WORK(&dice->dwork, do_registration);
 228         snd_fw_schedule_registration(unit, &dice->dwork);
 229 
 230         return 0;
 231 }
 232 
 233 static void dice_remove(struct fw_unit *unit)
 234 {
 235         struct snd_dice *dice = dev_get_drvdata(&unit->device);
 236 
 237         /*
 238          * Confirm to stop the work for registration before the sound card is
 239          * going to be released. The work is not scheduled again because bus
 240          * reset handler is not called anymore.
 241          */
 242         cancel_delayed_work_sync(&dice->dwork);
 243 
 244         if (dice->registered) {
 245                 // Block till all of ALSA character devices are released.
 246                 snd_card_free(dice->card);
 247         }
 248 
 249         mutex_destroy(&dice->mutex);
 250         fw_unit_put(dice->unit);
 251 }
 252 
 253 static void dice_bus_reset(struct fw_unit *unit)
 254 {
 255         struct snd_dice *dice = dev_get_drvdata(&unit->device);
 256 
 257         /* Postpone a workqueue for deferred registration. */
 258         if (!dice->registered)
 259                 snd_fw_schedule_registration(unit, &dice->dwork);
 260 
 261         /* The handler address register becomes initialized. */
 262         snd_dice_transaction_reinit(dice);
 263 
 264         /*
 265          * After registration, userspace can start packet streaming, then this
 266          * code block works fine.
 267          */
 268         if (dice->registered) {
 269                 mutex_lock(&dice->mutex);
 270                 snd_dice_stream_update_duplex(dice);
 271                 mutex_unlock(&dice->mutex);
 272         }
 273 }
 274 
 275 #define DICE_INTERFACE  0x000001
 276 
 277 static const struct ieee1394_device_id dice_id_table[] = {
 278         /* M-Audio Profire 2626 has a different value in version field. */
 279         {
 280                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 281                                   IEEE1394_MATCH_MODEL_ID,
 282                 .vendor_id      = OUI_MAUDIO,
 283                 .model_id       = 0x000010,
 284                 .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
 285         },
 286         /* M-Audio Profire 610 has a different value in version field. */
 287         {
 288                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 289                                   IEEE1394_MATCH_MODEL_ID,
 290                 .vendor_id      = OUI_MAUDIO,
 291                 .model_id       = 0x000011,
 292                 .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
 293         },
 294         /* TC Electronic Konnekt 24D. */
 295         {
 296                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 297                                   IEEE1394_MATCH_MODEL_ID,
 298                 .vendor_id      = OUI_TCELECTRONIC,
 299                 .model_id       = 0x000020,
 300                 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
 301         },
 302         /* TC Electronic Konnekt 8. */
 303         {
 304                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 305                                   IEEE1394_MATCH_MODEL_ID,
 306                 .vendor_id      = OUI_TCELECTRONIC,
 307                 .model_id       = 0x000021,
 308                 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
 309         },
 310         /* TC Electronic Studio Konnekt 48. */
 311         {
 312                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 313                                   IEEE1394_MATCH_MODEL_ID,
 314                 .vendor_id      = OUI_TCELECTRONIC,
 315                 .model_id       = 0x000022,
 316                 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
 317         },
 318         /* TC Electronic Konnekt Live. */
 319         {
 320                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 321                                   IEEE1394_MATCH_MODEL_ID,
 322                 .vendor_id      = OUI_TCELECTRONIC,
 323                 .model_id       = 0x000023,
 324                 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
 325         },
 326         /* TC Electronic Desktop Konnekt 6. */
 327         {
 328                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 329                                   IEEE1394_MATCH_MODEL_ID,
 330                 .vendor_id      = OUI_TCELECTRONIC,
 331                 .model_id       = 0x000024,
 332                 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
 333         },
 334         /* TC Electronic Impact Twin. */
 335         {
 336                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 337                                   IEEE1394_MATCH_MODEL_ID,
 338                 .vendor_id      = OUI_TCELECTRONIC,
 339                 .model_id       = 0x000027,
 340                 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
 341         },
 342         /* TC Electronic Digital Konnekt x32. */
 343         {
 344                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 345                                   IEEE1394_MATCH_MODEL_ID,
 346                 .vendor_id      = OUI_TCELECTRONIC,
 347                 .model_id       = 0x000030,
 348                 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
 349         },
 350         /* Alesis iO14/iO26. */
 351         {
 352                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 353                                   IEEE1394_MATCH_MODEL_ID,
 354                 .vendor_id      = OUI_ALESIS,
 355                 .model_id       = MODEL_ALESIS_IO_BOTH,
 356                 .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats,
 357         },
 358         /* Mytek Stereo 192 DSD-DAC. */
 359         {
 360                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 361                                   IEEE1394_MATCH_MODEL_ID,
 362                 .vendor_id      = OUI_MYTEK,
 363                 .model_id       = 0x000002,
 364                 .driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats,
 365         },
 366         // Solid State Logic, Duende Classic and Mini.
 367         // NOTE: each field of GUID in config ROM is not compliant to standard
 368         // DICE scheme.
 369         {
 370                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 371                                   IEEE1394_MATCH_MODEL_ID,
 372                 .vendor_id      = OUI_SSL,
 373                 .model_id       = 0x000070,
 374         },
 375         // Presonus FireStudio.
 376         {
 377                 .match_flags    = IEEE1394_MATCH_VENDOR_ID |
 378                                   IEEE1394_MATCH_MODEL_ID,
 379                 .vendor_id      = OUI_PRESONUS,
 380                 .model_id       = 0x000008,
 381                 .driver_data    = (kernel_ulong_t)snd_dice_detect_presonus_formats,
 382         },
 383         {
 384                 .match_flags = IEEE1394_MATCH_VERSION,
 385                 .version     = DICE_INTERFACE,
 386         },
 387         { }
 388 };
 389 MODULE_DEVICE_TABLE(ieee1394, dice_id_table);
 390 
 391 static struct fw_driver dice_driver = {
 392         .driver   = {
 393                 .owner  = THIS_MODULE,
 394                 .name   = KBUILD_MODNAME,
 395                 .bus    = &fw_bus_type,
 396         },
 397         .probe    = dice_probe,
 398         .update   = dice_bus_reset,
 399         .remove   = dice_remove,
 400         .id_table = dice_id_table,
 401 };
 402 
 403 static int __init alsa_dice_init(void)
 404 {
 405         return driver_register(&dice_driver.driver);
 406 }
 407 
 408 static void __exit alsa_dice_exit(void)
 409 {
 410         driver_unregister(&dice_driver.driver);
 411 }
 412 
 413 module_init(alsa_dice_init);
 414 module_exit(alsa_dice_exit);

/* [<][>][^][v][top][bottom][index][help] */