motu-command-dsp-message-parser.c 4.5 KB

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