-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ALSA: firewire-motu: add message parser for meter information in comm…
…and DSP model Some of MOTU models allows software to configure their DSP parameters by command included in asynchronous transaction. The models multiplex messages for hardware meters into isochronous packet as well as PCM frames. For convenience, I call them as 'command DSP' model. This patch adds message parser for them to gather hardware meter information. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Link: https://lore.kernel.org/r/20211015080826.34847-3-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai <tiwai@suse.de>
- Loading branch information
Takashi Sakamoto
authored and
Takashi Iwai
committed
Oct 15, 2021
1 parent
bea36af
commit 90b28f3
Showing
8 changed files
with
216 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
// | ||
// motu-command-dsp-message-parser.c - a part of driver for MOTU FireWire series | ||
// | ||
// Copyright (c) 2021 Takashi Sakamoto <o-takashi@sakamocchi.jp> | ||
|
||
// Below models allow software to configure their DSP function by command transferred in | ||
// asynchronous transaction: | ||
// * 828 mk3 (FireWire only and Hybrid) | ||
// * 896 mk3 (FireWire only and Hybrid) | ||
// * Ultralite mk3 (FireWire only and Hybrid) | ||
// * Traveler mk3 | ||
// * Track 16 | ||
// | ||
// Isochronous packets from the above models includes messages to report state of hardware meter. | ||
|
||
#include "motu.h" | ||
|
||
enum msg_parser_state { | ||
INITIALIZED, | ||
FRAGMENT_DETECTED, | ||
AVAILABLE, | ||
}; | ||
|
||
struct msg_parser { | ||
enum msg_parser_state state; | ||
unsigned int interval; | ||
unsigned int message_count; | ||
unsigned int fragment_pos; | ||
unsigned int value_index; | ||
u64 value; | ||
struct snd_firewire_motu_command_dsp_meter meter; | ||
}; | ||
|
||
int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu) | ||
{ | ||
struct msg_parser *parser; | ||
|
||
parser = devm_kzalloc(&motu->card->card_dev, sizeof(*parser), GFP_KERNEL); | ||
if (!parser) | ||
return -ENOMEM; | ||
motu->message_parser = parser; | ||
|
||
return 0; | ||
} | ||
|
||
int snd_motu_command_dsp_message_parser_init(struct snd_motu *motu, enum cip_sfc sfc) | ||
{ | ||
struct msg_parser *parser = motu->message_parser; | ||
|
||
parser->state = INITIALIZED; | ||
|
||
// All of data blocks don't have messages with meaningful information. | ||
switch (sfc) { | ||
case CIP_SFC_176400: | ||
case CIP_SFC_192000: | ||
parser->interval = 4; | ||
break; | ||
case CIP_SFC_88200: | ||
case CIP_SFC_96000: | ||
parser->interval = 2; | ||
break; | ||
case CIP_SFC_32000: | ||
case CIP_SFC_44100: | ||
case CIP_SFC_48000: | ||
default: | ||
parser->interval = 1; | ||
break; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
#define FRAGMENT_POS 6 | ||
#define MIDI_BYTE_POS 7 | ||
#define MIDI_FLAG_POS 8 | ||
// One value of hardware meter consists of 4 messages. | ||
#define FRAGMENTS_PER_VALUE 4 | ||
#define VALUES_AT_IMAGE_END 0xffffffffffffffff | ||
|
||
void snd_motu_command_dsp_message_parser_parse(struct snd_motu *motu, const struct pkt_desc *descs, | ||
unsigned int desc_count, unsigned int data_block_quadlets) | ||
{ | ||
struct msg_parser *parser = motu->message_parser; | ||
unsigned int interval = parser->interval; | ||
int i; | ||
|
||
for (i = 0; i < desc_count; ++i) { | ||
const struct pkt_desc *desc = descs + i; | ||
__be32 *buffer = desc->ctx_payload; | ||
unsigned int data_blocks = desc->data_blocks; | ||
int j; | ||
|
||
for (j = 0; j < data_blocks; ++j) { | ||
u8 *b = (u8 *)buffer; | ||
buffer += data_block_quadlets; | ||
|
||
switch (parser->state) { | ||
case INITIALIZED: | ||
{ | ||
u8 fragment = b[FRAGMENT_POS]; | ||
|
||
if (fragment > 0) { | ||
parser->value = fragment; | ||
parser->message_count = 1; | ||
parser->state = FRAGMENT_DETECTED; | ||
} | ||
break; | ||
} | ||
case FRAGMENT_DETECTED: | ||
{ | ||
if (parser->message_count % interval == 0) { | ||
u8 fragment = b[FRAGMENT_POS]; | ||
|
||
parser->value >>= 8; | ||
parser->value |= (u64)fragment << 56; | ||
|
||
if (parser->value == VALUES_AT_IMAGE_END) { | ||
parser->state = AVAILABLE; | ||
parser->fragment_pos = 0; | ||
parser->value_index = 0; | ||
parser->message_count = 0; | ||
} | ||
} | ||
++parser->message_count; | ||
break; | ||
} | ||
case AVAILABLE: | ||
default: | ||
{ | ||
if (parser->message_count % interval == 0) { | ||
u8 fragment = b[FRAGMENT_POS]; | ||
|
||
parser->value >>= 8; | ||
parser->value |= (u64)fragment << 56; | ||
++parser->fragment_pos; | ||
|
||
if (parser->fragment_pos == 4) { | ||
if (parser->value_index < | ||
SNDRV_FIREWIRE_MOTU_COMMAND_DSP_METER_COUNT) { | ||
u32 val = (u32)(parser->value >> 32); | ||
parser->meter.data[parser->value_index] = val; | ||
++parser->value_index; | ||
} | ||
parser->fragment_pos = 0; | ||
} | ||
|
||
if (parser->value == VALUES_AT_IMAGE_END) { | ||
parser->value_index = 0; | ||
parser->fragment_pos = 0; | ||
parser->message_count = 0; | ||
} | ||
} | ||
++parser->message_count; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters