1 // SPDX-License-Identifier: GPL-2.0-only 1 // SPDX-License-Identifier: GPL-2.0-only 2 // 2 // 3 // motu-command-dsp-message-parser.c - a part 3 // motu-command-dsp-message-parser.c - a part of driver for MOTU FireWire series 4 // 4 // 5 // Copyright (c) 2021 Takashi Sakamoto <o-taka 5 // Copyright (c) 2021 Takashi Sakamoto <o-takashi@sakamocchi.jp> 6 6 7 // Below models allow software to configure th 7 // Below models allow software to configure their DSP function by command transferred in 8 // asynchronous transaction: 8 // asynchronous transaction: 9 // * 828 mk3 (FireWire only and Hybrid) 9 // * 828 mk3 (FireWire only and Hybrid) 10 // * 896 mk3 (FireWire only and Hybrid) 10 // * 896 mk3 (FireWire only and Hybrid) 11 // * Ultralite mk3 (FireWire only and Hybrid) 11 // * Ultralite mk3 (FireWire only and Hybrid) 12 // * Traveler mk3 12 // * Traveler mk3 13 // * Track 16 13 // * Track 16 14 // 14 // 15 // Isochronous packets from the above models i 15 // Isochronous packets from the above models includes messages to report state of hardware meter. 16 16 17 #include "motu.h" 17 #include "motu.h" 18 18 19 enum msg_parser_state { 19 enum msg_parser_state { 20 INITIALIZED, 20 INITIALIZED, 21 FRAGMENT_DETECTED, 21 FRAGMENT_DETECTED, 22 AVAILABLE, 22 AVAILABLE, 23 }; 23 }; 24 24 25 struct msg_parser { 25 struct msg_parser { 26 spinlock_t lock; 26 spinlock_t lock; 27 enum msg_parser_state state; 27 enum msg_parser_state state; 28 unsigned int interval; 28 unsigned int interval; 29 unsigned int message_count; 29 unsigned int message_count; 30 unsigned int fragment_pos; 30 unsigned int fragment_pos; 31 unsigned int value_index; 31 unsigned int value_index; 32 u64 value; 32 u64 value; 33 struct snd_firewire_motu_command_dsp_m 33 struct snd_firewire_motu_command_dsp_meter meter; 34 }; 34 }; 35 35 36 int snd_motu_command_dsp_message_parser_new(st 36 int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu) 37 { 37 { 38 struct msg_parser *parser; 38 struct msg_parser *parser; 39 39 40 parser = devm_kzalloc(&motu->card->car 40 parser = devm_kzalloc(&motu->card->card_dev, sizeof(*parser), GFP_KERNEL); 41 if (!parser) 41 if (!parser) 42 return -ENOMEM; 42 return -ENOMEM; 43 spin_lock_init(&parser->lock); 43 spin_lock_init(&parser->lock); 44 motu->message_parser = parser; 44 motu->message_parser = parser; 45 45 46 return 0; 46 return 0; 47 } 47 } 48 48 49 int snd_motu_command_dsp_message_parser_init(s 49 int snd_motu_command_dsp_message_parser_init(struct snd_motu *motu, enum cip_sfc sfc) 50 { 50 { 51 struct msg_parser *parser = motu->mess 51 struct msg_parser *parser = motu->message_parser; 52 52 53 parser->state = INITIALIZED; 53 parser->state = INITIALIZED; 54 54 55 // All of data blocks don't have messa 55 // All of data blocks don't have messages with meaningful information. 56 switch (sfc) { 56 switch (sfc) { 57 case CIP_SFC_176400: 57 case CIP_SFC_176400: 58 case CIP_SFC_192000: 58 case CIP_SFC_192000: 59 parser->interval = 4; 59 parser->interval = 4; 60 break; 60 break; 61 case CIP_SFC_88200: 61 case CIP_SFC_88200: 62 case CIP_SFC_96000: 62 case CIP_SFC_96000: 63 parser->interval = 2; 63 parser->interval = 2; 64 break; 64 break; 65 case CIP_SFC_32000: 65 case CIP_SFC_32000: 66 case CIP_SFC_44100: 66 case CIP_SFC_44100: 67 case CIP_SFC_48000: 67 case CIP_SFC_48000: 68 default: 68 default: 69 parser->interval = 1; 69 parser->interval = 1; 70 break; 70 break; 71 } 71 } 72 72 73 return 0; 73 return 0; 74 } 74 } 75 75 76 #define FRAGMENT_POS 6 76 #define FRAGMENT_POS 6 77 #define MIDI_BYTE_POS 7 77 #define MIDI_BYTE_POS 7 78 #define MIDI_FLAG_POS 8 78 #define MIDI_FLAG_POS 8 79 // One value of hardware meter consists of 4 m 79 // One value of hardware meter consists of 4 messages. 80 #define FRAGMENTS_PER_VALUE 4 80 #define FRAGMENTS_PER_VALUE 4 81 #define VALUES_AT_IMAGE_END 0xffff 81 #define VALUES_AT_IMAGE_END 0xffffffffffffffff 82 82 83 void snd_motu_command_dsp_message_parser_parse !! 83 void snd_motu_command_dsp_message_parser_parse(struct snd_motu *motu, const struct pkt_desc *descs, 84 const !! 84 unsigned int desc_count, unsigned int data_block_quadlets) 85 { 85 { 86 struct snd_motu *motu = container_of(s << 87 unsigned int data_block_quadlets = s-> << 88 struct msg_parser *parser = motu->mess 86 struct msg_parser *parser = motu->message_parser; 89 unsigned int interval = parser->interv 87 unsigned int interval = parser->interval; 90 unsigned long flags; 88 unsigned long flags; 91 int i; 89 int i; 92 90 93 spin_lock_irqsave(&parser->lock, flags 91 spin_lock_irqsave(&parser->lock, flags); 94 92 95 for (i = 0; i < count; ++i) { !! 93 for (i = 0; i < desc_count; ++i) { >> 94 const struct pkt_desc *desc = descs + i; 96 __be32 *buffer = desc->ctx_pay 95 __be32 *buffer = desc->ctx_payload; 97 unsigned int data_blocks = des 96 unsigned int data_blocks = desc->data_blocks; 98 int j; 97 int j; 99 << 100 desc = amdtp_stream_next_packe << 101 98 102 for (j = 0; j < data_blocks; + 99 for (j = 0; j < data_blocks; ++j) { 103 u8 *b = (u8 *)buffer; 100 u8 *b = (u8 *)buffer; 104 buffer += data_block_q 101 buffer += data_block_quadlets; 105 102 106 switch (parser->state) 103 switch (parser->state) { 107 case INITIALIZED: 104 case INITIALIZED: 108 { 105 { 109 u8 fragment = 106 u8 fragment = b[FRAGMENT_POS]; 110 107 111 if (fragment > 108 if (fragment > 0) { 112 parser 109 parser->value = fragment; 113 parser 110 parser->message_count = 1; 114 parser 111 parser->state = FRAGMENT_DETECTED; 115 } 112 } 116 break; 113 break; 117 } 114 } 118 case FRAGMENT_DETECTED 115 case FRAGMENT_DETECTED: 119 { 116 { 120 if (parser->me 117 if (parser->message_count % interval == 0) { 121 u8 fra 118 u8 fragment = b[FRAGMENT_POS]; 122 119 123 parser 120 parser->value >>= 8; 124 parser 121 parser->value |= (u64)fragment << 56; 125 122 126 if (pa 123 if (parser->value == VALUES_AT_IMAGE_END) { 127 124 parser->state = AVAILABLE; 128 125 parser->fragment_pos = 0; 129 126 parser->value_index = 0; 130 127 parser->message_count = 0; 131 } 128 } 132 } 129 } 133 ++parser->mess 130 ++parser->message_count; 134 break; 131 break; 135 } 132 } 136 case AVAILABLE: 133 case AVAILABLE: 137 default: 134 default: 138 { 135 { 139 if (parser->me 136 if (parser->message_count % interval == 0) { 140 u8 fra 137 u8 fragment = b[FRAGMENT_POS]; 141 138 142 parser 139 parser->value >>= 8; 143 parser 140 parser->value |= (u64)fragment << 56; 144 ++pars 141 ++parser->fragment_pos; 145 142 146 if (pa 143 if (parser->fragment_pos == 4) { 147 144 // Skip the last two quadlets since they could be 148 145 // invalid value (0xffffffff) as floating point 149 146 // number. 150 147 if (parser->value_index < 151 148 SNDRV_FIREWIRE_MOTU_COMMAND_DSP_METER_COUNT - 2) { 152 149 u32 val = (u32)(parser->value >> 32); 153 150 parser->meter.data[parser->value_index] = val; 154 151 } 155 152 ++parser->value_index; 156 153 parser->fragment_pos = 0; 157 } 154 } 158 155 159 if (pa 156 if (parser->value == VALUES_AT_IMAGE_END) { 160 157 parser->value_index = 0; 161 158 parser->fragment_pos = 0; 162 159 parser->message_count = 0; 163 } 160 } 164 } 161 } 165 ++parser->mess 162 ++parser->message_count; 166 break; 163 break; 167 } 164 } 168 } 165 } 169 } 166 } 170 } 167 } 171 168 172 spin_unlock_irqrestore(&parser->lock, 169 spin_unlock_irqrestore(&parser->lock, flags); 173 } 170 } 174 171 175 void snd_motu_command_dsp_message_parser_copy_ 172 void snd_motu_command_dsp_message_parser_copy_meter(struct snd_motu *motu, 176 struct 173 struct snd_firewire_motu_command_dsp_meter *meter) 177 { 174 { 178 struct msg_parser *parser = motu->mess 175 struct msg_parser *parser = motu->message_parser; 179 unsigned long flags; 176 unsigned long flags; 180 177 181 spin_lock_irqsave(&parser->lock, flags 178 spin_lock_irqsave(&parser->lock, flags); 182 memcpy(meter, &parser->meter, sizeof(* 179 memcpy(meter, &parser->meter, sizeof(*meter)); 183 spin_unlock_irqrestore(&parser->lock, 180 spin_unlock_irqrestore(&parser->lock, flags); 184 } 181 } 185 182
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.