Commit 7cafc65b authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: dice: force to add two pcm devices for listed models

Some models reduce the number of available isochronous streams for higher
sampling transfer frequency. Such models bring an issue about how to add
PCM substreams. When at lower sampling transfer frequency, the
models reports whole available streams, thus this driver can add enough
number of PCM substreams at probing time. On the other hand, at higher
sampling transfer frequency, this driver can just add reduced number of
PCM substreams. After probed, even if the sampling transfer frequency is
changed to lower rate, fewer PCM substreams are actually available. This
is inconvenience.

For the reason, this commit adds a list so that this driver assume models
on the list to have two pairs of PCM substreams. This list keeps the name
of model in which the number of available streams differs depending on
sampling transfer frequency.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4bdc495c
...@@ -332,16 +332,22 @@ int snd_dice_create_pcm(struct snd_dice *dice) ...@@ -332,16 +332,22 @@ int snd_dice_create_pcm(struct snd_dice *dice)
int err; int err;
/* Check whether PCM substreams are required. */ /* Check whether PCM substreams are required. */
if (dice->force_two_pcms) {
max_capture = max_playback = 2;
} else {
max_capture = max_playback = 0; max_capture = max_playback = 0;
err = snd_dice_transaction_read_tx(dice, TX_NUMBER, &reg, sizeof(reg)); err = snd_dice_transaction_read_tx(dice, TX_NUMBER, &reg,
sizeof(reg));
if (err < 0) if (err < 0)
return err; return err;
max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
err = snd_dice_transaction_read_rx(dice, RX_NUMBER, &reg, sizeof(reg)); err = snd_dice_transaction_read_rx(dice, RX_NUMBER, &reg,
sizeof(reg));
if (err < 0) if (err < 0)
return err; return err;
max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS); max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
}
for (i = 0; i < MAX_STREAMS; i++) { for (i = 0; i < MAX_STREAMS; i++) {
capture = playback = 0; capture = playback = 0;
......
...@@ -13,6 +13,8 @@ MODULE_LICENSE("GPL v2"); ...@@ -13,6 +13,8 @@ MODULE_LICENSE("GPL v2");
#define OUI_WEISS 0x001c6a #define OUI_WEISS 0x001c6a
#define OUI_LOUD 0x000ff2 #define OUI_LOUD 0x000ff2
#define OUI_FOCUSRITE 0x00130e
#define OUI_TCELECTRONIC 0x001486
#define DICE_CATEGORY_ID 0x04 #define DICE_CATEGORY_ID 0x04
#define WEISS_CATEGORY_ID 0x00 #define WEISS_CATEGORY_ID 0x00
...@@ -20,6 +22,36 @@ MODULE_LICENSE("GPL v2"); ...@@ -20,6 +22,36 @@ MODULE_LICENSE("GPL v2");
#define PROBE_DELAY_MS (2 * MSEC_PER_SEC) #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) static int check_dice_category(struct fw_unit *unit)
{ {
struct fw_device *device = fw_parent_device(unit); struct fw_device *device = fw_parent_device(unit);
...@@ -44,6 +76,12 @@ static int check_dice_category(struct fw_unit *unit) ...@@ -44,6 +76,12 @@ static int check_dice_category(struct fw_unit *unit)
break; break;
} }
} }
if (vendor == OUI_FOCUSRITE || vendor == OUI_TCELECTRONIC) {
if (force_two_pcm_support(unit))
return 0;
}
if (vendor == OUI_WEISS) if (vendor == OUI_WEISS)
category = WEISS_CATEGORY_ID; category = WEISS_CATEGORY_ID;
else if (vendor == OUI_LOUD) else if (vendor == OUI_LOUD)
...@@ -150,6 +188,9 @@ static void do_registration(struct work_struct *work) ...@@ -150,6 +188,9 @@ static void do_registration(struct work_struct *work)
if (err < 0) if (err < 0)
return; return;
if (force_two_pcm_support(dice->unit))
dice->force_two_pcms = true;
err = snd_dice_transaction_init(dice); err = snd_dice_transaction_init(dice);
if (err < 0) if (err < 0)
goto error; goto error;
......
...@@ -97,6 +97,8 @@ struct snd_dice { ...@@ -97,6 +97,8 @@ struct snd_dice {
bool global_enabled; bool global_enabled;
struct completion clock_accepted; struct completion clock_accepted;
unsigned int substreams_counter; unsigned int substreams_counter;
bool force_two_pcms;
}; };
enum snd_dice_addr_type { enum snd_dice_addr_type {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment