| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * TC Applied Technologies Digital Interface Communications Engine driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
|---|
| 5 | | - * Licensed under the terms of the GNU General Public License, version 2. |
|---|
| 6 | 6 | */ |
|---|
| 7 | 7 | |
|---|
| 8 | 8 | #include "dice.h" |
|---|
| .. | .. |
|---|
| 19 | 19 | #define OUI_MAUDIO 0x000d6c |
|---|
| 20 | 20 | #define OUI_MYTEK 0x001ee8 |
|---|
| 21 | 21 | #define OUI_SSL 0x0050c2 // Actually ID reserved by IEEE. |
|---|
| 22 | +#define OUI_PRESONUS 0x000a92 |
|---|
| 22 | 23 | |
|---|
| 23 | 24 | #define DICE_CATEGORY_ID 0x04 |
|---|
| 24 | 25 | #define WEISS_CATEGORY_ID 0x00 |
|---|
| .. | .. |
|---|
| 123 | 124 | strcpy(card->mixername, "DICE"); |
|---|
| 124 | 125 | } |
|---|
| 125 | 126 | |
|---|
| 126 | | -static void dice_free(struct snd_dice *dice) |
|---|
| 127 | | -{ |
|---|
| 128 | | - snd_dice_stream_destroy_duplex(dice); |
|---|
| 129 | | - snd_dice_transaction_destroy(dice); |
|---|
| 130 | | - fw_unit_put(dice->unit); |
|---|
| 131 | | - |
|---|
| 132 | | - mutex_destroy(&dice->mutex); |
|---|
| 133 | | - kfree(dice); |
|---|
| 134 | | -} |
|---|
| 135 | | - |
|---|
| 136 | | -/* |
|---|
| 137 | | - * This module releases the FireWire unit data after all ALSA character devices |
|---|
| 138 | | - * are released by applications. This is for releasing stream data or finishing |
|---|
| 139 | | - * transactions safely. Thus at returning from .remove(), this module still keep |
|---|
| 140 | | - * references for the unit. |
|---|
| 141 | | - */ |
|---|
| 142 | 127 | static void dice_card_free(struct snd_card *card) |
|---|
| 143 | 128 | { |
|---|
| 144 | | - dice_free(card->private_data); |
|---|
| 129 | + struct snd_dice *dice = card->private_data; |
|---|
| 130 | + |
|---|
| 131 | + snd_dice_stream_destroy_duplex(dice); |
|---|
| 132 | + snd_dice_transaction_destroy(dice); |
|---|
| 145 | 133 | } |
|---|
| 146 | 134 | |
|---|
| 147 | 135 | static void do_registration(struct work_struct *work) |
|---|
| .. | .. |
|---|
| 156 | 144 | &dice->card); |
|---|
| 157 | 145 | if (err < 0) |
|---|
| 158 | 146 | return; |
|---|
| 147 | + dice->card->private_free = dice_card_free; |
|---|
| 148 | + dice->card->private_data = dice; |
|---|
| 159 | 149 | |
|---|
| 160 | 150 | err = snd_dice_transaction_init(dice); |
|---|
| 161 | 151 | if (err < 0) |
|---|
| .. | .. |
|---|
| 193 | 183 | if (err < 0) |
|---|
| 194 | 184 | goto error; |
|---|
| 195 | 185 | |
|---|
| 196 | | - /* |
|---|
| 197 | | - * After registered, dice instance can be released corresponding to |
|---|
| 198 | | - * releasing the sound card instance. |
|---|
| 199 | | - */ |
|---|
| 200 | | - dice->card->private_free = dice_card_free; |
|---|
| 201 | | - dice->card->private_data = dice; |
|---|
| 202 | 186 | dice->registered = true; |
|---|
| 203 | 187 | |
|---|
| 204 | 188 | return; |
|---|
| 205 | 189 | error: |
|---|
| 206 | | - snd_dice_stream_destroy_duplex(dice); |
|---|
| 207 | | - snd_dice_transaction_destroy(dice); |
|---|
| 208 | | - snd_dice_stream_destroy_duplex(dice); |
|---|
| 209 | 190 | snd_card_free(dice->card); |
|---|
| 210 | 191 | dev_info(&dice->unit->device, |
|---|
| 211 | 192 | "Sound card registration failed: %d\n", err); |
|---|
| .. | .. |
|---|
| 224 | 205 | } |
|---|
| 225 | 206 | |
|---|
| 226 | 207 | /* Allocate this independent of sound card instance. */ |
|---|
| 227 | | - dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL); |
|---|
| 228 | | - if (dice == NULL) |
|---|
| 208 | + dice = devm_kzalloc(&unit->device, sizeof(struct snd_dice), GFP_KERNEL); |
|---|
| 209 | + if (!dice) |
|---|
| 229 | 210 | return -ENOMEM; |
|---|
| 230 | | - |
|---|
| 231 | 211 | dice->unit = fw_unit_get(unit); |
|---|
| 232 | 212 | dev_set_drvdata(&unit->device, dice); |
|---|
| 233 | 213 | |
|---|
| .. | .. |
|---|
| 262 | 242 | cancel_delayed_work_sync(&dice->dwork); |
|---|
| 263 | 243 | |
|---|
| 264 | 244 | if (dice->registered) { |
|---|
| 265 | | - /* No need to wait for releasing card object in this context. */ |
|---|
| 266 | | - snd_card_free_when_closed(dice->card); |
|---|
| 267 | | - } else { |
|---|
| 268 | | - /* Don't forget this case. */ |
|---|
| 269 | | - dice_free(dice); |
|---|
| 245 | + // Block till all of ALSA character devices are released. |
|---|
| 246 | + snd_card_free(dice->card); |
|---|
| 270 | 247 | } |
|---|
| 248 | + |
|---|
| 249 | + mutex_destroy(&dice->mutex); |
|---|
| 250 | + fw_unit_put(dice->unit); |
|---|
| 271 | 251 | } |
|---|
| 272 | 252 | |
|---|
| 273 | 253 | static void dice_bus_reset(struct fw_unit *unit) |
|---|
| .. | .. |
|---|
| 375 | 355 | .model_id = MODEL_ALESIS_IO_BOTH, |
|---|
| 376 | 356 | .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats, |
|---|
| 377 | 357 | }, |
|---|
| 358 | + // Alesis MasterControl. |
|---|
| 359 | + { |
|---|
| 360 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | |
|---|
| 361 | + IEEE1394_MATCH_MODEL_ID, |
|---|
| 362 | + .vendor_id = OUI_ALESIS, |
|---|
| 363 | + .model_id = 0x000002, |
|---|
| 364 | + .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_mastercontrol_formats, |
|---|
| 365 | + }, |
|---|
| 378 | 366 | /* Mytek Stereo 192 DSD-DAC. */ |
|---|
| 379 | 367 | { |
|---|
| 380 | 368 | .match_flags = IEEE1394_MATCH_VENDOR_ID | |
|---|
| .. | .. |
|---|
| 392 | 380 | .vendor_id = OUI_SSL, |
|---|
| 393 | 381 | .model_id = 0x000070, |
|---|
| 394 | 382 | }, |
|---|
| 383 | + // Presonus FireStudio. |
|---|
| 384 | + { |
|---|
| 385 | + .match_flags = IEEE1394_MATCH_VENDOR_ID | |
|---|
| 386 | + IEEE1394_MATCH_MODEL_ID, |
|---|
| 387 | + .vendor_id = OUI_PRESONUS, |
|---|
| 388 | + .model_id = 0x000008, |
|---|
| 389 | + .driver_data = (kernel_ulong_t)snd_dice_detect_presonus_formats, |
|---|
| 390 | + }, |
|---|
| 395 | 391 | { |
|---|
| 396 | 392 | .match_flags = IEEE1394_MATCH_VERSION, |
|---|
| 397 | 393 | .version = DICE_INTERFACE, |
|---|