summaryrefslogtreecommitdiff
path: root/sound/core/ump.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/ump.c')
-rw-r--r--sound/core/ump.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/sound/core/ump.c b/sound/core/ump.c
index d5d72473d999..cd192bec227a 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -984,7 +984,7 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
{
struct snd_ump_endpoint *ump = substream->rmidi->private_data;
int dir = substream->stream;
- int group = substream->number;
+ int group = ump->legacy_mapping[substream->number];
int err;
mutex_lock(&ump->open_mutex);
@@ -1016,7 +1016,7 @@ static int snd_ump_legacy_close(struct snd_rawmidi_substream *substream)
{
struct snd_ump_endpoint *ump = substream->rmidi->private_data;
int dir = substream->stream;
- int group = substream->number;
+ int group = ump->legacy_mapping[substream->number];
mutex_lock(&ump->open_mutex);
spin_lock_irq(&ump->legacy_locks[dir]);
@@ -1123,6 +1123,34 @@ static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
spin_unlock_irqrestore(&ump->legacy_locks[dir], flags);
}
+/* Fill ump->legacy_mapping[] for groups to be used for legacy rawmidi */
+static int fill_legacy_mapping(struct snd_ump_endpoint *ump)
+{
+ struct snd_ump_block *fb;
+ unsigned int group_maps = 0;
+ int i, num;
+
+ if (ump->info.flags & SNDRV_UMP_EP_INFO_STATIC_BLOCKS) {
+ list_for_each_entry(fb, &ump->block_list, list) {
+ for (i = 0; i < fb->info.num_groups; i++)
+ group_maps |= 1U << (fb->info.first_group + i);
+ }
+ if (!group_maps)
+ ump_info(ump, "No UMP Group is found in FB\n");
+ }
+
+ /* use all groups for non-static case */
+ if (!group_maps)
+ group_maps = (1U << SNDRV_UMP_MAX_GROUPS) - 1;
+
+ num = 0;
+ for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++)
+ if (group_maps & (1U << i))
+ ump->legacy_mapping[num++] = i;
+
+ return num;
+}
+
static void fill_substream_names(struct snd_ump_endpoint *ump,
struct snd_rawmidi *rmidi, int dir)
{
@@ -1130,7 +1158,7 @@ static void fill_substream_names(struct snd_ump_endpoint *ump,
list_for_each_entry(s, &rmidi->streams[dir].substreams, list)
snprintf(s->name, sizeof(s->name), "Group %d (%s)",
- s->number + 1, ump->info.name);
+ ump->legacy_mapping[s->number] + 1, ump->info.name);
}
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
@@ -1138,16 +1166,19 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
{
struct snd_rawmidi *rmidi;
bool input, output;
- int err;
+ int err, num;
- ump->out_cvts = kcalloc(16, sizeof(*ump->out_cvts), GFP_KERNEL);
+ ump->out_cvts = kcalloc(SNDRV_UMP_MAX_GROUPS,
+ sizeof(*ump->out_cvts), GFP_KERNEL);
if (!ump->out_cvts)
return -ENOMEM;
+ num = fill_legacy_mapping(ump);
+
input = ump->core.info_flags & SNDRV_RAWMIDI_INFO_INPUT;
output = ump->core.info_flags & SNDRV_RAWMIDI_INFO_OUTPUT;
err = snd_rawmidi_new(ump->core.card, id, device,
- output ? 16 : 0, input ? 16 : 0,
+ output ? num : 0, input ? num : 0,
&rmidi);
if (err < 0) {
kfree(ump->out_cvts);