0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include "motu.h"
0018
0019 enum msg_parser_state {
0020 INITIALIZED,
0021 FRAGMENT_DETECTED,
0022 AVAILABLE,
0023 };
0024
0025 struct msg_parser {
0026 spinlock_t lock;
0027 enum msg_parser_state state;
0028 unsigned int interval;
0029 unsigned int message_count;
0030 unsigned int fragment_pos;
0031 unsigned int value_index;
0032 u64 value;
0033 struct snd_firewire_motu_command_dsp_meter meter;
0034 };
0035
0036 int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu)
0037 {
0038 struct msg_parser *parser;
0039
0040 parser = devm_kzalloc(&motu->card->card_dev, sizeof(*parser), GFP_KERNEL);
0041 if (!parser)
0042 return -ENOMEM;
0043 spin_lock_init(&parser->lock);
0044 motu->message_parser = parser;
0045
0046 return 0;
0047 }
0048
0049 int snd_motu_command_dsp_message_parser_init(struct snd_motu *motu, enum cip_sfc sfc)
0050 {
0051 struct msg_parser *parser = motu->message_parser;
0052
0053 parser->state = INITIALIZED;
0054
0055
0056 switch (sfc) {
0057 case CIP_SFC_176400:
0058 case CIP_SFC_192000:
0059 parser->interval = 4;
0060 break;
0061 case CIP_SFC_88200:
0062 case CIP_SFC_96000:
0063 parser->interval = 2;
0064 break;
0065 case CIP_SFC_32000:
0066 case CIP_SFC_44100:
0067 case CIP_SFC_48000:
0068 default:
0069 parser->interval = 1;
0070 break;
0071 }
0072
0073 return 0;
0074 }
0075
0076 #define FRAGMENT_POS 6
0077 #define MIDI_BYTE_POS 7
0078 #define MIDI_FLAG_POS 8
0079
0080 #define FRAGMENTS_PER_VALUE 4
0081 #define VALUES_AT_IMAGE_END 0xffffffffffffffff
0082
0083 void snd_motu_command_dsp_message_parser_parse(struct snd_motu *motu, const struct pkt_desc *descs,
0084 unsigned int desc_count, unsigned int data_block_quadlets)
0085 {
0086 struct msg_parser *parser = motu->message_parser;
0087 unsigned int interval = parser->interval;
0088 unsigned long flags;
0089 int i;
0090
0091 spin_lock_irqsave(&parser->lock, flags);
0092
0093 for (i = 0; i < desc_count; ++i) {
0094 const struct pkt_desc *desc = descs + i;
0095 __be32 *buffer = desc->ctx_payload;
0096 unsigned int data_blocks = desc->data_blocks;
0097 int j;
0098
0099 for (j = 0; j < data_blocks; ++j) {
0100 u8 *b = (u8 *)buffer;
0101 buffer += data_block_quadlets;
0102
0103 switch (parser->state) {
0104 case INITIALIZED:
0105 {
0106 u8 fragment = b[FRAGMENT_POS];
0107
0108 if (fragment > 0) {
0109 parser->value = fragment;
0110 parser->message_count = 1;
0111 parser->state = FRAGMENT_DETECTED;
0112 }
0113 break;
0114 }
0115 case FRAGMENT_DETECTED:
0116 {
0117 if (parser->message_count % interval == 0) {
0118 u8 fragment = b[FRAGMENT_POS];
0119
0120 parser->value >>= 8;
0121 parser->value |= (u64)fragment << 56;
0122
0123 if (parser->value == VALUES_AT_IMAGE_END) {
0124 parser->state = AVAILABLE;
0125 parser->fragment_pos = 0;
0126 parser->value_index = 0;
0127 parser->message_count = 0;
0128 }
0129 }
0130 ++parser->message_count;
0131 break;
0132 }
0133 case AVAILABLE:
0134 default:
0135 {
0136 if (parser->message_count % interval == 0) {
0137 u8 fragment = b[FRAGMENT_POS];
0138
0139 parser->value >>= 8;
0140 parser->value |= (u64)fragment << 56;
0141 ++parser->fragment_pos;
0142
0143 if (parser->fragment_pos == 4) {
0144
0145
0146
0147 if (parser->value_index <
0148 SNDRV_FIREWIRE_MOTU_COMMAND_DSP_METER_COUNT - 2) {
0149 u32 val = (u32)(parser->value >> 32);
0150 parser->meter.data[parser->value_index] = val;
0151 }
0152 ++parser->value_index;
0153 parser->fragment_pos = 0;
0154 }
0155
0156 if (parser->value == VALUES_AT_IMAGE_END) {
0157 parser->value_index = 0;
0158 parser->fragment_pos = 0;
0159 parser->message_count = 0;
0160 }
0161 }
0162 ++parser->message_count;
0163 break;
0164 }
0165 }
0166 }
0167 }
0168
0169 spin_unlock_irqrestore(&parser->lock, flags);
0170 }
0171
0172 void snd_motu_command_dsp_message_parser_copy_meter(struct snd_motu *motu,
0173 struct snd_firewire_motu_command_dsp_meter *meter)
0174 {
0175 struct msg_parser *parser = motu->message_parser;
0176 unsigned long flags;
0177
0178 spin_lock_irqsave(&parser->lock, flags);
0179 memcpy(meter, &parser->meter, sizeof(*meter));
0180 spin_unlock_irqrestore(&parser->lock, flags);
0181 }