[alsa-devel] [PATCH 04/13] bebob: Add functionality to change sampling rate and control interface
Takashi Sakamoto
o-takashi at sakamocchi.jp
Sat Nov 23 07:09:16 CET 2013
This commit adds the functionality to change sampling rate. To debug this,
this commit also adds control interface. I plan to extend this control
interface for the other functionality.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
sound/firewire/bebob/Makefile | 2 +-
sound/firewire/bebob/bebob.c | 4 +
sound/firewire/bebob/bebob.h | 4 +
sound/firewire/bebob/bebob_control.c | 148 +++++++++++++++++++++++++++++++++++
sound/firewire/bebob/bebob_stream.c | 2 +
5 files changed, 159 insertions(+), 1 deletion(-)
create mode 100644 sound/firewire/bebob/bebob_control.c
diff --git a/sound/firewire/bebob/Makefile b/sound/firewire/bebob/Makefile
index 6e44fa0..bec01cd 100644
--- a/sound/firewire/bebob/Makefile
+++ b/sound/firewire/bebob/Makefile
@@ -1,3 +1,3 @@
-snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o \
+snd-bebob-objs := bebob_command.o bebob_stream.o bebob_proc.o bebob_control.o \
bebob.o
obj-m += snd-bebob.o
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index e5aa96e..71a3896 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -177,6 +177,10 @@ snd_bebob_probe(struct fw_unit *unit,
if (err < 0)
goto error;
+ err = snd_bebob_create_control_devices(bebob);
+ if (err < 0)
+ goto error;
+
snd_bebob_proc_init(bebob);
err = snd_bebob_stream_discover(bebob);
diff --git a/sound/firewire/bebob/bebob.h b/sound/firewire/bebob/bebob.h
index 2d60165..d87999e 100644
--- a/sound/firewire/bebob/bebob.h
+++ b/sound/firewire/bebob/bebob.h
@@ -30,6 +30,7 @@
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/info.h>
+#include <sound/control.h>
#include "../packets-buffer.h"
#include "../iso-resources.h"
@@ -74,6 +75,7 @@ struct snd_bebob {
struct snd_bebob_stream_formation
rx_stream_formations[SND_BEBOB_STRM_FMT_ENTRIES];
+ struct snd_ctl_elem_id *ctl_id_freq;
};
static inline int
@@ -149,6 +151,8 @@ void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob);
void snd_bebob_proc_init(struct snd_bebob *bebob);
+int snd_bebob_create_control_devices(struct snd_bebob *bebob);
+
#define SND_BEBOB_DEV_ENTRY(vendor, model) \
{ \
.match_flags = IEEE1394_MATCH_VENDOR_ID | \
diff --git a/sound/firewire/bebob/bebob_control.c b/sound/firewire/bebob/bebob_control.c
new file mode 100644
index 0000000..f9a9229
--- /dev/null
+++ b/sound/firewire/bebob/bebob_control.c
@@ -0,0 +1,148 @@
+/*
+ * bebob_control.c - a part of driver for BeBoB based devices
+ *
+ * Copyright (c) 2013 Takashi Sakamoto
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "bebob.h"
+
+
+/*
+ * Global Control: Sampling Rate Control
+ *
+ * refer to snd_bebob_rate_table.
+ */
+static int
+control_sampling_rate_info(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *einf)
+{
+ struct snd_bebob *bebob = snd_kcontrol_chip(kctl);
+ unsigned int i, value;
+
+ /* maximum value for user */
+ einf->value.enumerated.items = 0;
+ for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++)
+ if ((bebob->tx_stream_formations[i].pcm > 0) &&
+ (bebob->rx_stream_formations[i].pcm > 0))
+ einf->value.enumerated.items++;
+
+ einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ einf->count = 1;
+
+ if (einf->value.enumerated.item >= einf->value.enumerated.items)
+ einf->value.enumerated.item = einf->value.enumerated.items - 1;
+
+ /* skip unsupported sampling rates */
+ value = einf->value.enumerated.item;
+ for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) {
+ if ((bebob->tx_stream_formations[i].pcm == 0) ||
+ (bebob->rx_stream_formations[i].pcm == 0))
+ continue;
+ else if (value == 0)
+ break;
+ else
+ value--;
+ }
+
+ sprintf(einf->value.enumerated.name, "%dHz", snd_bebob_rate_table[i]);
+
+ return 0;
+}
+static int
+control_sampling_rate_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uval)
+{
+ struct snd_bebob *bebob = snd_kcontrol_chip(kctl);
+ unsigned int i, sampling_rate, index;
+ int err;
+
+ mutex_lock(&bebob->mutex);
+
+ err = snd_bebob_stream_get_rate(bebob, &sampling_rate);
+ if (err < 0)
+ goto end;
+
+ for (index = 0; index < ARRAY_SIZE(snd_bebob_rate_table); index++)
+ if (snd_bebob_rate_table[index] == sampling_rate)
+ break;
+
+ uval->value.enumerated.item[0] = 0;
+ for (i = 0; i < index; i++)
+ if ((bebob->tx_stream_formations[i].pcm != 0) ||
+ (bebob->rx_stream_formations[i].pcm != 0))
+ uval->value.enumerated.item[0]++;
+
+end:
+ mutex_unlock(&bebob->mutex);
+ return err;
+}
+static int
+control_sampling_rate_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uval)
+{
+ struct snd_bebob *bebob = snd_kcontrol_chip(kctl);
+ unsigned int index, sampling_rate;
+ int value, changed = 0;
+
+ /* get index from user value*/
+ value = uval->value.enumerated.item[0];
+ for (index = 0; index < ARRAY_SIZE(snd_bebob_rate_table); index++) {
+ if ((bebob->tx_stream_formations[index].pcm == 0) ||
+ (bebob->rx_stream_formations[index].pcm == 0))
+ continue;
+ else if (value == 0)
+ break;
+ else
+ value--;
+ }
+
+ sampling_rate = snd_bebob_rate_table[index];
+
+ mutex_lock(&bebob->mutex);
+ if (snd_bebob_stream_set_rate(bebob, sampling_rate) < 0)
+ goto end;
+
+ /* prevent from failure of getting command just after setting */
+ msleep(100);
+ changed = 1;
+
+ snd_ctl_notify(bebob->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ bebob->ctl_id_freq);
+end:
+ mutex_unlock(&bebob->mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new global_sampling_rate_control = {
+ .name = "Sampling Rate",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = control_sampling_rate_info,
+ .get = control_sampling_rate_get,
+ .put = control_sampling_rate_put
+};
+
+int snd_bebob_create_control_devices(struct snd_bebob *bebob)
+{
+ int err = 0;
+ struct snd_kcontrol *kctl;
+
+ kctl = snd_ctl_new1(&global_sampling_rate_control, bebob);
+ err = snd_ctl_add(bebob->card, kctl);
+ if (err < 0)
+ goto end;
+ bebob->ctl_id_freq = &kctl->id;
+end:
+ return err;
+}
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index 6852945..773dffb 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -368,6 +368,8 @@ int snd_bebob_stream_start_duplex(struct snd_bebob *bebob,
err = snd_bebob_stream_set_rate(bebob, rate);
if (err < 0)
goto end;
+ snd_ctl_notify(bebob->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ bebob->ctl_id_freq);
err = make_both_connections(bebob, rate);
if (err < 0)
--
1.8.3.2
More information about the Alsa-devel
mailing list