diff mbox series

[04/11] ALSA: firewire-motu: parse messages for mixer source parameters in register-DSP model

Message ID 20211015080826.34847-5-o-takashi@sakamocchi.jp (mailing list archive)
State New, archived
Headers show
Series ALSA: firewire-motu: add ioctl commands to retrieve information in messages delivered by isoc packet | expand

Commit Message

Takashi Sakamoto Oct. 15, 2021, 8:08 a.m. UTC
In register DSP models, current parameters of DSP are always reported by
messages in isochronous packet. When user operates hardware component such
as rotary knob, corresponding message is changed.

This commit parses the message and cache current parameters of mixer
source function, commonly available for all of register DSP models.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 include/uapi/sound/firewire.h                 | 28 ++++++++
 .../motu/motu-register-dsp-message-parser.c   | 64 +++++++++++++++++++
 2 files changed, 92 insertions(+)
diff mbox series

Patch

diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h
index a8df8fb03b52..bb5ecff73896 100644
--- a/include/uapi/sound/firewire.h
+++ b/include/uapi/sound/firewire.h
@@ -145,6 +145,34 @@  struct snd_firewire_motu_register_dsp_meter {
 	__u8 data[SNDRV_FIREWIRE_MOTU_REGISTER_DSP_METER_COUNT];
 };
 
+#define SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_COUNT		4
+#define SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT	20
+
+/**
+ * snd_firewire_motu_register_dsp_parameter - the container for parameters of DSP controlled
+ *					      by register access.
+ * @mixer.source.gain: The gain of source to mixer.
+ * @mixer.source.pan: The L/R balance of source to mixer.
+ * @mixer.source.flag: The flag of source to mixer, including mute, solo.
+ * @mixer.source.paired_balance: The L/R balance of paired source to mixer, only for 4 pre and
+ *				 Audio Express.
+ * @mixer.source.paired_width: The width of paired source to mixer, only for 4 pre and
+ *			       Audio Express.
+ *
+ * The structure expresses the set of parameters for DSP controlled by register access.
+ */
+struct snd_firewire_motu_register_dsp_parameter {
+	struct {
+		struct {
+			__u8 gain[SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT];
+			__u8 pan[SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT];
+			__u8 flag[SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT];
+			__u8 paired_balance[SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT];
+			__u8 paired_width[SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT];
+		} source[SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_COUNT];
+	} mixer;
+};
+
 // In below MOTU models, software is allowed to control their DSP by command in frame of
 // asynchronous transaction to 0x'ffff'0001'0000:
 //
diff --git a/sound/firewire/motu/motu-register-dsp-message-parser.c b/sound/firewire/motu/motu-register-dsp-message-parser.c
index fe804615294c..6df40e5ee9db 100644
--- a/sound/firewire/motu/motu-register-dsp-message-parser.c
+++ b/sound/firewire/motu/motu-register-dsp-message-parser.c
@@ -82,6 +82,11 @@  struct msg_parser {
 	spinlock_t lock;
 	struct snd_firewire_motu_register_dsp_meter meter;
 	bool meter_pos_quirk;
+
+	struct snd_firewire_motu_register_dsp_parameter param;
+	u8 prev_mixer_src_type;
+	u8 mixer_ch;
+	u8 mixer_src_ch;
 };
 
 int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
@@ -99,6 +104,12 @@  int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
 
 int snd_motu_register_dsp_message_parser_init(struct snd_motu *motu)
 {
+	struct msg_parser *parser = motu->message_parser;
+
+	parser->prev_mixer_src_type = INVALID;
+	parser->mixer_ch = 0xff;
+	parser->mixer_src_ch = 0xff;
+
 	return 0;
 }
 
@@ -126,6 +137,59 @@  void snd_motu_register_dsp_message_parser_parse(struct snd_motu *motu, const str
 			buffer += data_block_quadlets;
 
 			switch (msg_type) {
+			case MIXER_SELECT:
+			{
+				u8 mixer_ch = val / 0x20;
+				if (mixer_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_COUNT) {
+					parser->mixer_src_ch = 0;
+					parser->mixer_ch = mixer_ch;
+				}
+				break;
+			}
+			case MIXER_SRC_GAIN:
+			case MIXER_SRC_PAN:
+			case MIXER_SRC_FLAG:
+			case MIXER_SRC_PAIRED_BALANCE:
+			case MIXER_SRC_PAIRED_WIDTH:
+			{
+				struct snd_firewire_motu_register_dsp_parameter *param = &parser->param;
+				u8 mixer_ch = parser->mixer_ch;
+				u8 mixer_src_ch = parser->mixer_src_ch;
+
+				if (msg_type != parser->prev_mixer_src_type)
+					mixer_src_ch = 0;
+				else
+					++mixer_src_ch;
+				parser->prev_mixer_src_type = msg_type;
+
+				if (mixer_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_COUNT &&
+				    mixer_src_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT) {
+					u8 mixer_ch = parser->mixer_ch;
+
+					switch (msg_type) {
+					case MIXER_SRC_GAIN:
+						param->mixer.source[mixer_ch].gain[mixer_src_ch] = val;
+						break;
+					case MIXER_SRC_PAN:
+						param->mixer.source[mixer_ch].pan[mixer_src_ch] = val;
+						break;
+					case MIXER_SRC_FLAG:
+						param->mixer.source[mixer_ch].flag[mixer_src_ch] = val;
+						break;
+					case MIXER_SRC_PAIRED_BALANCE:
+						param->mixer.source[mixer_ch].paired_balance[mixer_src_ch] = val;
+						break;
+					case MIXER_SRC_PAIRED_WIDTH:
+						param->mixer.source[mixer_ch].paired_width[mixer_src_ch] = val;
+						break;
+					default:
+						break;
+					}
+
+					parser->mixer_src_ch = mixer_src_ch;
+				}
+				break;
+			}
 			case METER:
 			{
 				u8 pos;