0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "motu.h"
0023
0024 #define MSG_FLAG_POS 4
0025 #define MSG_FLAG_TYPE_MASK 0xf8
0026 #define MSG_FLAG_MIDI_MASK 0x01
0027 #define MSG_FLAG_MODEL_SPECIFIC_MASK 0x06
0028 #define MSG_FLAG_8PRE 0x00
0029 #define MSG_FLAG_ULTRALITE 0x04
0030 #define MSG_FLAG_TRAVELER 0x04
0031 #define MSG_FLAG_828MK2 0x04
0032 #define MSG_FLAG_896HD 0x04
0033 #define MSG_FLAG_4PRE 0x05
0034 #define MSG_FLAG_AUDIOEXPRESS 0x05
0035 #define MSG_FLAG_TYPE_SHIFT 3
0036 #define MSG_VALUE_POS 5
0037 #define MSG_MIDI_BYTE_POS 6
0038 #define MSG_METER_IDX_POS 7
0039
0040
0041
0042 #define MSG_METER_IDX_POS_4PRE_AE 6
0043 #define MSG_MIDI_BYTE_POS_4PRE_AE 7
0044 #define MSG_FLAG_MIDI_POS_4PRE_AE 8
0045
0046 enum register_dsp_msg_type {
0047
0048 INVALID = 0x00,
0049 MIXER_SELECT = 0x01,
0050 MIXER_SRC_GAIN = 0x02,
0051 MIXER_SRC_PAN = 0x03,
0052 MIXER_SRC_FLAG = 0x04,
0053 MIXER_OUTPUT_PAIRED_VOLUME = 0x05,
0054 MIXER_OUTPUT_PAIRED_FLAG = 0x06,
0055 MAIN_OUTPUT_PAIRED_VOLUME = 0x07,
0056 HP_OUTPUT_PAIRED_VOLUME = 0x08,
0057 HP_OUTPUT_PAIRED_ASSIGNMENT = 0x09,
0058
0059 UNKNOWN_0 = 0x0a,
0060
0061 UNKNOWN_2 = 0x0c,
0062
0063 LINE_INPUT_BOOST = 0x0d,
0064
0065 LINE_INPUT_NOMINAL_LEVEL = 0x0e,
0066
0067 INPUT_GAIN_AND_INVERT = 0x15,
0068
0069 INPUT_FLAG = 0x16,
0070
0071 MIXER_SRC_PAIRED_BALANCE = 0x17,
0072
0073 MIXER_SRC_PAIRED_WIDTH = 0x18,
0074
0075
0076
0077
0078 METER = 0x1f,
0079 };
0080
0081 #define EVENT_QUEUE_SIZE 16
0082
0083 struct msg_parser {
0084 spinlock_t lock;
0085 struct snd_firewire_motu_register_dsp_meter meter;
0086 bool meter_pos_quirk;
0087
0088 struct snd_firewire_motu_register_dsp_parameter param;
0089 u8 prev_mixer_src_type;
0090 u8 mixer_ch;
0091 u8 mixer_src_ch;
0092
0093 u8 input_ch;
0094 u8 prev_msg_type;
0095
0096 u32 event_queue[EVENT_QUEUE_SIZE];
0097 unsigned int push_pos;
0098 unsigned int pull_pos;
0099 };
0100
0101 int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
0102 {
0103 struct msg_parser *parser;
0104 parser = devm_kzalloc(&motu->card->card_dev, sizeof(*parser), GFP_KERNEL);
0105 if (!parser)
0106 return -ENOMEM;
0107 spin_lock_init(&parser->lock);
0108 if (motu->spec == &snd_motu_spec_4pre || motu->spec == &snd_motu_spec_audio_express)
0109 parser->meter_pos_quirk = true;
0110 motu->message_parser = parser;
0111 return 0;
0112 }
0113
0114 int snd_motu_register_dsp_message_parser_init(struct snd_motu *motu)
0115 {
0116 struct msg_parser *parser = motu->message_parser;
0117
0118 parser->prev_mixer_src_type = INVALID;
0119 parser->mixer_ch = 0xff;
0120 parser->mixer_src_ch = 0xff;
0121 parser->prev_msg_type = INVALID;
0122
0123 return 0;
0124 }
0125
0126
0127 static void queue_event(struct snd_motu *motu, u8 msg_type, u8 identifier0, u8 identifier1, u8 val)
0128 {
0129 struct msg_parser *parser = motu->message_parser;
0130 unsigned int pos = parser->push_pos;
0131 u32 entry;
0132
0133 if (!motu->hwdep || motu->hwdep->used == 0)
0134 return;
0135
0136 entry = (msg_type << 24) | (identifier0 << 16) | (identifier1 << 8) | val;
0137 parser->event_queue[pos] = entry;
0138
0139 ++pos;
0140 if (pos >= EVENT_QUEUE_SIZE)
0141 pos = 0;
0142 parser->push_pos = pos;
0143 }
0144
0145 void snd_motu_register_dsp_message_parser_parse(struct snd_motu *motu, const struct pkt_desc *descs,
0146 unsigned int desc_count, unsigned int data_block_quadlets)
0147 {
0148 struct msg_parser *parser = motu->message_parser;
0149 bool meter_pos_quirk = parser->meter_pos_quirk;
0150 unsigned int pos = parser->push_pos;
0151 unsigned long flags;
0152 int i;
0153
0154 spin_lock_irqsave(&parser->lock, flags);
0155
0156 for (i = 0; i < desc_count; ++i) {
0157 const struct pkt_desc *desc = descs + i;
0158 __be32 *buffer = desc->ctx_payload;
0159 unsigned int data_blocks = desc->data_blocks;
0160 int j;
0161
0162 for (j = 0; j < data_blocks; ++j) {
0163 u8 *b = (u8 *)buffer;
0164 u8 msg_type = (b[MSG_FLAG_POS] & MSG_FLAG_TYPE_MASK) >> MSG_FLAG_TYPE_SHIFT;
0165 u8 val = b[MSG_VALUE_POS];
0166
0167 buffer += data_block_quadlets;
0168
0169 switch (msg_type) {
0170 case MIXER_SELECT:
0171 {
0172 u8 mixer_ch = val / 0x20;
0173 if (mixer_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_COUNT) {
0174 parser->mixer_src_ch = 0;
0175 parser->mixer_ch = mixer_ch;
0176 }
0177 break;
0178 }
0179 case MIXER_SRC_GAIN:
0180 case MIXER_SRC_PAN:
0181 case MIXER_SRC_FLAG:
0182 case MIXER_SRC_PAIRED_BALANCE:
0183 case MIXER_SRC_PAIRED_WIDTH:
0184 {
0185 struct snd_firewire_motu_register_dsp_parameter *param = &parser->param;
0186 u8 mixer_ch = parser->mixer_ch;
0187 u8 mixer_src_ch = parser->mixer_src_ch;
0188
0189 if (msg_type != parser->prev_mixer_src_type)
0190 mixer_src_ch = 0;
0191 else
0192 ++mixer_src_ch;
0193 parser->prev_mixer_src_type = msg_type;
0194
0195 if (mixer_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_COUNT &&
0196 mixer_src_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_SRC_COUNT) {
0197 u8 mixer_ch = parser->mixer_ch;
0198
0199 switch (msg_type) {
0200 case MIXER_SRC_GAIN:
0201 if (param->mixer.source[mixer_ch].gain[mixer_src_ch] != val) {
0202 queue_event(motu, msg_type, mixer_ch, mixer_src_ch, val);
0203 param->mixer.source[mixer_ch].gain[mixer_src_ch] = val;
0204 }
0205 break;
0206 case MIXER_SRC_PAN:
0207 if (param->mixer.source[mixer_ch].pan[mixer_src_ch] != val) {
0208 queue_event(motu, msg_type, mixer_ch, mixer_src_ch, val);
0209 param->mixer.source[mixer_ch].pan[mixer_src_ch] = val;
0210 }
0211 break;
0212 case MIXER_SRC_FLAG:
0213 if (param->mixer.source[mixer_ch].flag[mixer_src_ch] != val) {
0214 queue_event(motu, msg_type, mixer_ch, mixer_src_ch, val);
0215 param->mixer.source[mixer_ch].flag[mixer_src_ch] = val;
0216 }
0217 break;
0218 case MIXER_SRC_PAIRED_BALANCE:
0219 if (param->mixer.source[mixer_ch].paired_balance[mixer_src_ch] != val) {
0220 queue_event(motu, msg_type, mixer_ch, mixer_src_ch, val);
0221 param->mixer.source[mixer_ch].paired_balance[mixer_src_ch] = val;
0222 }
0223 break;
0224 case MIXER_SRC_PAIRED_WIDTH:
0225 if (param->mixer.source[mixer_ch].paired_width[mixer_src_ch] != val) {
0226 queue_event(motu, msg_type, mixer_ch, mixer_src_ch, val);
0227 param->mixer.source[mixer_ch].paired_width[mixer_src_ch] = val;
0228 }
0229 break;
0230 default:
0231 break;
0232 }
0233
0234 parser->mixer_src_ch = mixer_src_ch;
0235 }
0236 break;
0237 }
0238 case MIXER_OUTPUT_PAIRED_VOLUME:
0239 case MIXER_OUTPUT_PAIRED_FLAG:
0240 {
0241 struct snd_firewire_motu_register_dsp_parameter *param = &parser->param;
0242 u8 mixer_ch = parser->mixer_ch;
0243
0244 if (mixer_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_MIXER_COUNT) {
0245 switch (msg_type) {
0246 case MIXER_OUTPUT_PAIRED_VOLUME:
0247 if (param->mixer.output.paired_volume[mixer_ch] != val) {
0248 queue_event(motu, msg_type, mixer_ch, 0, val);
0249 param->mixer.output.paired_volume[mixer_ch] = val;
0250 }
0251 break;
0252 case MIXER_OUTPUT_PAIRED_FLAG:
0253 if (param->mixer.output.paired_flag[mixer_ch] != val) {
0254 queue_event(motu, msg_type, mixer_ch, 0, val);
0255 param->mixer.output.paired_flag[mixer_ch] = val;
0256 }
0257 break;
0258 default:
0259 break;
0260 }
0261 }
0262 break;
0263 }
0264 case MAIN_OUTPUT_PAIRED_VOLUME:
0265 if (parser->param.output.main_paired_volume != val) {
0266 queue_event(motu, msg_type, 0, 0, val);
0267 parser->param.output.main_paired_volume = val;
0268 }
0269 break;
0270 case HP_OUTPUT_PAIRED_VOLUME:
0271 if (parser->param.output.hp_paired_volume != val) {
0272 queue_event(motu, msg_type, 0, 0, val);
0273 parser->param.output.hp_paired_volume = val;
0274 }
0275 break;
0276 case HP_OUTPUT_PAIRED_ASSIGNMENT:
0277 if (parser->param.output.hp_paired_assignment != val) {
0278 queue_event(motu, msg_type, 0, 0, val);
0279 parser->param.output.hp_paired_assignment = val;
0280 }
0281 break;
0282 case LINE_INPUT_BOOST:
0283 if (parser->param.line_input.boost_flag != val) {
0284 queue_event(motu, msg_type, 0, 0, val);
0285 parser->param.line_input.boost_flag = val;
0286 }
0287 break;
0288 case LINE_INPUT_NOMINAL_LEVEL:
0289 if (parser->param.line_input.nominal_level_flag != val) {
0290 queue_event(motu, msg_type, 0, 0, val);
0291 parser->param.line_input.nominal_level_flag = val;
0292 }
0293 break;
0294 case INPUT_GAIN_AND_INVERT:
0295 case INPUT_FLAG:
0296 {
0297 struct snd_firewire_motu_register_dsp_parameter *param = &parser->param;
0298 u8 input_ch = parser->input_ch;
0299
0300 if (parser->prev_msg_type != msg_type)
0301 input_ch = 0;
0302 else
0303 ++input_ch;
0304
0305 if (input_ch < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_INPUT_COUNT) {
0306 switch (msg_type) {
0307 case INPUT_GAIN_AND_INVERT:
0308 if (param->input.gain_and_invert[input_ch] != val) {
0309 queue_event(motu, msg_type, input_ch, 0, val);
0310 param->input.gain_and_invert[input_ch] = val;
0311 }
0312 break;
0313 case INPUT_FLAG:
0314 if (param->input.flag[input_ch] != val) {
0315 queue_event(motu, msg_type, input_ch, 0, val);
0316 param->input.flag[input_ch] = val;
0317 }
0318 break;
0319 default:
0320 break;
0321 }
0322 parser->input_ch = input_ch;
0323 }
0324 break;
0325 }
0326 case UNKNOWN_0:
0327 case UNKNOWN_2:
0328 break;
0329 case METER:
0330 {
0331 u8 pos;
0332
0333 if (!meter_pos_quirk)
0334 pos = b[MSG_METER_IDX_POS];
0335 else
0336 pos = b[MSG_METER_IDX_POS_4PRE_AE];
0337
0338 if (pos < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_METER_INPUT_COUNT) {
0339 parser->meter.data[pos] = val;
0340 } else if (pos >= 0x80) {
0341 pos -= (0x80 - SNDRV_FIREWIRE_MOTU_REGISTER_DSP_METER_INPUT_COUNT);
0342
0343 if (pos < SNDRV_FIREWIRE_MOTU_REGISTER_DSP_METER_COUNT)
0344 parser->meter.data[pos] = val;
0345 }
0346
0347
0348
0349 fallthrough;
0350 }
0351 case INVALID:
0352 default:
0353
0354 continue;
0355 }
0356
0357 parser->prev_msg_type = msg_type;
0358 }
0359 }
0360
0361 if (pos != parser->push_pos)
0362 wake_up(&motu->hwdep_wait);
0363
0364 spin_unlock_irqrestore(&parser->lock, flags);
0365 }
0366
0367 void snd_motu_register_dsp_message_parser_copy_meter(struct snd_motu *motu,
0368 struct snd_firewire_motu_register_dsp_meter *meter)
0369 {
0370 struct msg_parser *parser = motu->message_parser;
0371 unsigned long flags;
0372
0373 spin_lock_irqsave(&parser->lock, flags);
0374 memcpy(meter, &parser->meter, sizeof(*meter));
0375 spin_unlock_irqrestore(&parser->lock, flags);
0376 }
0377
0378 void snd_motu_register_dsp_message_parser_copy_parameter(struct snd_motu *motu,
0379 struct snd_firewire_motu_register_dsp_parameter *param)
0380 {
0381 struct msg_parser *parser = motu->message_parser;
0382 unsigned long flags;
0383
0384 spin_lock_irqsave(&parser->lock, flags);
0385 memcpy(param, &parser->param, sizeof(*param));
0386 spin_unlock_irqrestore(&parser->lock, flags);
0387 }
0388
0389 unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *motu)
0390 {
0391 struct msg_parser *parser = motu->message_parser;
0392
0393 if (parser->pull_pos > parser->push_pos)
0394 return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
0395 else
0396 return parser->push_pos - parser->pull_pos;
0397 }
0398
0399 bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
0400 {
0401 struct msg_parser *parser = motu->message_parser;
0402 unsigned int pos = parser->pull_pos;
0403 unsigned long flags;
0404
0405 if (pos == parser->push_pos)
0406 return false;
0407
0408 spin_lock_irqsave(&parser->lock, flags);
0409
0410 *event = parser->event_queue[pos];
0411
0412 ++pos;
0413 if (pos >= EVENT_QUEUE_SIZE)
0414 pos = 0;
0415 parser->pull_pos = pos;
0416
0417 spin_unlock_irqrestore(&parser->lock, flags);
0418
0419 return true;
0420 }