ALSA: bebob: Prepare for device specific operations

This commit is for some devices which have its own operations or quirks.

Many functionality should be implemented in user land. Then this commit adds
functionality related to stream such as sampling frequency or clock source. For
help to debug, this commit adds the functionality to get metering information
if it's available.

To help these functionalities, this commit adds some AV/C commands defined in
'AV/C Audio Subunit Specification (1394TA).

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Sakamoto
2014-04-25 22:45:21 +09:00
committed by Takashi Iwai
parent 618eabeae7
commit 1fc9522a08
7 changed files with 230 additions and 42 deletions

View File

@@ -68,6 +68,39 @@ end:
kfree(info);
}
static void
proc_read_meters(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_bebob *bebob = entry->private_data;
struct snd_bebob_meter_spec *spec = bebob->spec->meter;
u32 *buf;
unsigned int i, c, channels, size;
if (spec == NULL)
return;
channels = spec->num * 2;
size = channels * sizeof(u32);
buf = kmalloc(size, GFP_KERNEL);
if (buf == NULL)
return;
if (spec->get(bebob, buf, size) < 0)
goto end;
for (i = 0, c = 1; i < channels; i++) {
snd_iprintf(buffer, "%s %d:\t%d\n",
spec->labels[i / 2], c++, buf[i]);
if ((i + 1 < channels - 1) &&
(strcmp(spec->labels[i / 2],
spec->labels[(i + 1) / 2]) != 0))
c = 1;
}
end:
kfree(buf);
}
static void
proc_read_formation(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
@@ -100,16 +133,25 @@ proc_read_clock(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_bebob *bebob = entry->private_data;
unsigned int rate;
struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate;
struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock;
unsigned int rate, id;
bool internal;
if (snd_bebob_stream_get_rate(bebob, &rate) >= 0)
if (rate_spec->get(bebob, &rate) >= 0)
snd_iprintf(buffer, "Sampling rate: %d\n", rate);
if (snd_bebob_stream_check_internal_clock(bebob, &internal) >= 0)
snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)",
(internal) ? "Internal" : "External",
bebob->sync_input_plug);
if (clk_spec) {
if (clk_spec->get(bebob, &id) >= 0)
snd_iprintf(buffer, "Clock Source: %s\n",
clk_spec->labels[id]);
} else {
if (snd_bebob_stream_check_internal_clock(bebob,
&internal) >= 0)
snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n",
(internal) ? "Internal" : "External",
bebob->sync_input_plug);
}
}
static void
@@ -148,4 +190,7 @@ void snd_bebob_proc_init(struct snd_bebob *bebob)
add_node(bebob, root, "clock", proc_read_clock);
add_node(bebob, root, "firmware", proc_read_hw_info);
add_node(bebob, root, "formation", proc_read_formation);
if (bebob->spec->meter != NULL)
add_node(bebob, root, "meter", proc_read_meters);
}