diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 05e2e18b4c30..4aa0249826fd 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -332,16 +332,22 @@ int snd_dice_create_pcm(struct snd_dice *dice) int err; /* Check whether PCM substreams are required. */ - max_capture = max_playback = 0; - err = snd_dice_transaction_read_tx(dice, TX_NUMBER, ®, sizeof(reg)); - if (err < 0) - return err; - max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); + if (dice->force_two_pcms) { + max_capture = max_playback = 2; + } else { + max_capture = max_playback = 0; + err = snd_dice_transaction_read_tx(dice, TX_NUMBER, ®, + sizeof(reg)); + if (err < 0) + return err; + max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); - err = snd_dice_transaction_read_rx(dice, RX_NUMBER, ®, sizeof(reg)); - if (err < 0) - return err; - max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); + err = snd_dice_transaction_read_rx(dice, RX_NUMBER, ®, + sizeof(reg)); + if (err < 0) + return err; + max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); + } for (i = 0; i < MAX_STREAMS; i++) { capture = playback = 0; diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index f7303a650ac2..8b64aef31a86 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c @@ -13,6 +13,8 @@ MODULE_LICENSE("GPL v2"); #define OUI_WEISS 0x001c6a #define OUI_LOUD 0x000ff2 +#define OUI_FOCUSRITE 0x00130e +#define OUI_TCELECTRONIC 0x001486 #define DICE_CATEGORY_ID 0x04 #define WEISS_CATEGORY_ID 0x00 @@ -20,6 +22,36 @@ MODULE_LICENSE("GPL v2"); #define PROBE_DELAY_MS (2 * MSEC_PER_SEC) +/* + * Some models support several isochronous channels, while these streams are not + * always available. In this case, add the model name to this list. + */ +static bool force_two_pcm_support(struct fw_unit *unit) +{ + const char *const models[] = { + /* TC Electronic models. */ + "StudioKonnekt48", + /* Focusrite models. */ + "SAFFIRE_PRO_40", + "LIQUID_SAFFIRE_56", + "SAFFIRE_PRO_40_1", + }; + char model[32]; + unsigned int i; + int err; + + err = fw_csr_string(unit->directory, CSR_MODEL, model, sizeof(model)); + if (err < 0) + return false; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + if (strcmp(models[i], model) == 0) + break; + } + + return i < ARRAY_SIZE(models); +} + static int check_dice_category(struct fw_unit *unit) { struct fw_device *device = fw_parent_device(unit); @@ -44,6 +76,12 @@ static int check_dice_category(struct fw_unit *unit) break; } } + + if (vendor == OUI_FOCUSRITE || vendor == OUI_TCELECTRONIC) { + if (force_two_pcm_support(unit)) + return 0; + } + if (vendor == OUI_WEISS) category = WEISS_CATEGORY_ID; else if (vendor == OUI_LOUD) @@ -150,6 +188,9 @@ static void do_registration(struct work_struct *work) if (err < 0) return; + if (force_two_pcm_support(dice->unit)) + dice->force_two_pcms = true; + err = snd_dice_transaction_init(dice); if (err < 0) goto error; diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h index 8fba87d83810..e6c07857f475 100644 --- a/sound/firewire/dice/dice.h +++ b/sound/firewire/dice/dice.h @@ -97,6 +97,8 @@ struct snd_dice { bool global_enabled; struct completion clock_accepted; unsigned int substreams_counter; + + bool force_two_pcms; }; enum snd_dice_addr_type {