1da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2163ae6f3STakashi Sakamoto /* 3163ae6f3STakashi Sakamoto * amdtp-dot.c - a part of driver for Digidesign Digi 002/003 family 4163ae6f3STakashi Sakamoto * 5163ae6f3STakashi Sakamoto * Copyright (c) 2014-2015 Takashi Sakamoto 6163ae6f3STakashi Sakamoto * Copyright (C) 2012 Robin Gareus <robin@gareus.org> 7163ae6f3STakashi Sakamoto * Copyright (C) 2012 Damien Zammit <damien@zamaudio.com> 8163ae6f3STakashi Sakamoto */ 9163ae6f3STakashi Sakamoto 10163ae6f3STakashi Sakamoto #include <sound/pcm.h> 11163ae6f3STakashi Sakamoto #include "digi00x.h" 12163ae6f3STakashi Sakamoto 13163ae6f3STakashi Sakamoto #define CIP_FMT_AM 0x10 14163ae6f3STakashi Sakamoto 15163ae6f3STakashi Sakamoto /* 'Clock-based rate control mode' is just supported. */ 16163ae6f3STakashi Sakamoto #define AMDTP_FDF_AM824 0x00 17163ae6f3STakashi Sakamoto 18163ae6f3STakashi Sakamoto /* 199dc5d31cSTakashi Sakamoto * Nominally 3125 bytes/second, but the MIDI port's clock might be 209dc5d31cSTakashi Sakamoto * 1% too slow, and the bus clock 100 ppm too fast. 219dc5d31cSTakashi Sakamoto */ 229dc5d31cSTakashi Sakamoto #define MIDI_BYTES_PER_SECOND 3093 239dc5d31cSTakashi Sakamoto 249dc5d31cSTakashi Sakamoto /* 259dc5d31cSTakashi Sakamoto * Several devices look only at the first eight data blocks. 269dc5d31cSTakashi Sakamoto * In any case, this is more than enough for the MIDI data rate. 279dc5d31cSTakashi Sakamoto */ 289dc5d31cSTakashi Sakamoto #define MAX_MIDI_RX_BLOCKS 8 299dc5d31cSTakashi Sakamoto 308820a4cfSTakashi Sakamoto /* 3 = MAX(DOT_MIDI_IN_PORTS, DOT_MIDI_OUT_PORTS) + 1. */ 318820a4cfSTakashi Sakamoto #define MAX_MIDI_PORTS 3 328820a4cfSTakashi Sakamoto 339dc5d31cSTakashi Sakamoto /* 34163ae6f3STakashi Sakamoto * The double-oh-three algorithm was discovered by Robin Gareus and Damien 35163ae6f3STakashi Sakamoto * Zammit in 2012, with reverse-engineering for Digi 003 Rack. 36163ae6f3STakashi Sakamoto */ 37163ae6f3STakashi Sakamoto struct dot_state { 3817385a38STakashi Sakamoto u8 carry; 3917385a38STakashi Sakamoto u8 idx; 40163ae6f3STakashi Sakamoto unsigned int off; 41163ae6f3STakashi Sakamoto }; 42163ae6f3STakashi Sakamoto 43163ae6f3STakashi Sakamoto struct amdtp_dot { 44163ae6f3STakashi Sakamoto unsigned int pcm_channels; 45163ae6f3STakashi Sakamoto struct dot_state state; 46163ae6f3STakashi Sakamoto 478820a4cfSTakashi Sakamoto struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS]; 488820a4cfSTakashi Sakamoto int midi_fifo_used[MAX_MIDI_PORTS]; 499dc5d31cSTakashi Sakamoto int midi_fifo_limit; 50163ae6f3STakashi Sakamoto }; 51163ae6f3STakashi Sakamoto 52163ae6f3STakashi Sakamoto /* 53163ae6f3STakashi Sakamoto * double-oh-three look up table 54163ae6f3STakashi Sakamoto * 55163ae6f3STakashi Sakamoto * @param idx index byte (audio-sample data) 0x00..0xff 56163ae6f3STakashi Sakamoto * @param off channel offset shift 57163ae6f3STakashi Sakamoto * @return salt to XOR with given data 58163ae6f3STakashi Sakamoto */ 59163ae6f3STakashi Sakamoto #define BYTE_PER_SAMPLE (4) 60163ae6f3STakashi Sakamoto #define MAGIC_DOT_BYTE (2) 61163ae6f3STakashi Sakamoto #define MAGIC_BYTE_OFF(x) (((x) * BYTE_PER_SAMPLE) + MAGIC_DOT_BYTE) 62b8cb3750SGeert Uytterhoeven static u8 dot_scrt(const u8 idx, const unsigned int off) 63163ae6f3STakashi Sakamoto { 64163ae6f3STakashi Sakamoto /* 65163ae6f3STakashi Sakamoto * the length of the added pattern only depends on the lower nibble 66163ae6f3STakashi Sakamoto * of the last non-zero data 67163ae6f3STakashi Sakamoto */ 6817385a38STakashi Sakamoto static const u8 len[16] = {0, 1, 3, 5, 7, 9, 11, 13, 14, 69163ae6f3STakashi Sakamoto 12, 10, 8, 6, 4, 2, 0}; 70163ae6f3STakashi Sakamoto 71163ae6f3STakashi Sakamoto /* 72163ae6f3STakashi Sakamoto * the lower nibble of the salt. Interleaved sequence. 73163ae6f3STakashi Sakamoto * this is walked backwards according to len[] 74163ae6f3STakashi Sakamoto */ 7517385a38STakashi Sakamoto static const u8 nib[15] = {0x8, 0x7, 0x9, 0x6, 0xa, 0x5, 0xb, 0x4, 76163ae6f3STakashi Sakamoto 0xc, 0x3, 0xd, 0x2, 0xe, 0x1, 0xf}; 77163ae6f3STakashi Sakamoto 78163ae6f3STakashi Sakamoto /* circular list for the salt's hi nibble. */ 7917385a38STakashi Sakamoto static const u8 hir[15] = {0x0, 0x6, 0xf, 0x8, 0x7, 0x5, 0x3, 0x4, 80163ae6f3STakashi Sakamoto 0xc, 0xd, 0xe, 0x1, 0x2, 0xb, 0xa}; 81163ae6f3STakashi Sakamoto 82163ae6f3STakashi Sakamoto /* 83163ae6f3STakashi Sakamoto * start offset for upper nibble mapping. 84163ae6f3STakashi Sakamoto * note: 9 is /special/. In the case where the high nibble == 0x9, 85163ae6f3STakashi Sakamoto * hir[] is not used and - coincidentally - the salt's hi nibble is 86163ae6f3STakashi Sakamoto * 0x09 regardless of the offset. 87163ae6f3STakashi Sakamoto */ 8817385a38STakashi Sakamoto static const u8 hio[16] = {0, 11, 12, 6, 7, 5, 1, 4, 89163ae6f3STakashi Sakamoto 3, 0x00, 14, 13, 8, 9, 10, 2}; 90163ae6f3STakashi Sakamoto 9117385a38STakashi Sakamoto const u8 ln = idx & 0xf; 9217385a38STakashi Sakamoto const u8 hn = (idx >> 4) & 0xf; 9317385a38STakashi Sakamoto const u8 hr = (hn == 0x9) ? 0x9 : hir[(hio[hn] + off) % 15]; 94163ae6f3STakashi Sakamoto 95163ae6f3STakashi Sakamoto if (len[ln] < off) 96163ae6f3STakashi Sakamoto return 0x00; 97163ae6f3STakashi Sakamoto 98163ae6f3STakashi Sakamoto return ((nib[14 + off - len[ln]]) | (hr << 4)); 99163ae6f3STakashi Sakamoto } 100163ae6f3STakashi Sakamoto 101163ae6f3STakashi Sakamoto static void dot_encode_step(struct dot_state *state, __be32 *const buffer) 102163ae6f3STakashi Sakamoto { 10317385a38STakashi Sakamoto u8 * const data = (u8 *) buffer; 104163ae6f3STakashi Sakamoto 105163ae6f3STakashi Sakamoto if (data[MAGIC_DOT_BYTE] != 0x00) { 106163ae6f3STakashi Sakamoto state->off = 0; 107163ae6f3STakashi Sakamoto state->idx = data[MAGIC_DOT_BYTE] ^ state->carry; 108163ae6f3STakashi Sakamoto } 109163ae6f3STakashi Sakamoto data[MAGIC_DOT_BYTE] ^= state->carry; 110163ae6f3STakashi Sakamoto state->carry = dot_scrt(state->idx, ++(state->off)); 111163ae6f3STakashi Sakamoto } 112163ae6f3STakashi Sakamoto 113163ae6f3STakashi Sakamoto int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, 1149dc5d31cSTakashi Sakamoto unsigned int pcm_channels) 115163ae6f3STakashi Sakamoto { 116163ae6f3STakashi Sakamoto struct amdtp_dot *p = s->protocol; 117163ae6f3STakashi Sakamoto int err; 118163ae6f3STakashi Sakamoto 119163ae6f3STakashi Sakamoto if (amdtp_stream_running(s)) 120163ae6f3STakashi Sakamoto return -EBUSY; 121163ae6f3STakashi Sakamoto 122163ae6f3STakashi Sakamoto /* 1238820a4cfSTakashi Sakamoto * A first data channel is for MIDI messages, the rest is Multi Bit 1248820a4cfSTakashi Sakamoto * Linear Audio data channel. 125163ae6f3STakashi Sakamoto */ 126163ae6f3STakashi Sakamoto err = amdtp_stream_set_parameters(s, rate, pcm_channels + 1); 127163ae6f3STakashi Sakamoto if (err < 0) 128163ae6f3STakashi Sakamoto return err; 129163ae6f3STakashi Sakamoto 130d3d10a4aSTakashi Sakamoto s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc; 131163ae6f3STakashi Sakamoto 132163ae6f3STakashi Sakamoto p->pcm_channels = pcm_channels; 1339dc5d31cSTakashi Sakamoto 1349dc5d31cSTakashi Sakamoto /* 1359dc5d31cSTakashi Sakamoto * We do not know the actual MIDI FIFO size of most devices. Just 1369dc5d31cSTakashi Sakamoto * assume two bytes, i.e., one byte can be received over the bus while 1379dc5d31cSTakashi Sakamoto * the previous one is transmitted over MIDI. 1389dc5d31cSTakashi Sakamoto * (The value here is adjusted for midi_ratelimit_per_packet().) 1399dc5d31cSTakashi Sakamoto */ 1409dc5d31cSTakashi Sakamoto p->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1; 141163ae6f3STakashi Sakamoto 142163ae6f3STakashi Sakamoto return 0; 143163ae6f3STakashi Sakamoto } 144163ae6f3STakashi Sakamoto 145163ae6f3STakashi Sakamoto static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, 146163ae6f3STakashi Sakamoto __be32 *buffer, unsigned int frames) 147163ae6f3STakashi Sakamoto { 148163ae6f3STakashi Sakamoto struct amdtp_dot *p = s->protocol; 149163ae6f3STakashi Sakamoto struct snd_pcm_runtime *runtime = pcm->runtime; 150163ae6f3STakashi Sakamoto unsigned int channels, remaining_frames, i, c; 151163ae6f3STakashi Sakamoto const u32 *src; 152163ae6f3STakashi Sakamoto 153163ae6f3STakashi Sakamoto channels = p->pcm_channels; 154163ae6f3STakashi Sakamoto src = (void *)runtime->dma_area + 155163ae6f3STakashi Sakamoto frames_to_bytes(runtime, s->pcm_buffer_pointer); 156163ae6f3STakashi Sakamoto remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; 157163ae6f3STakashi Sakamoto 158163ae6f3STakashi Sakamoto buffer++; 159163ae6f3STakashi Sakamoto for (i = 0; i < frames; ++i) { 160163ae6f3STakashi Sakamoto for (c = 0; c < channels; ++c) { 161163ae6f3STakashi Sakamoto buffer[c] = cpu_to_be32((*src >> 8) | 0x40000000); 162163ae6f3STakashi Sakamoto dot_encode_step(&p->state, &buffer[c]); 163163ae6f3STakashi Sakamoto src++; 164163ae6f3STakashi Sakamoto } 165163ae6f3STakashi Sakamoto buffer += s->data_block_quadlets; 166163ae6f3STakashi Sakamoto if (--remaining_frames == 0) 167163ae6f3STakashi Sakamoto src = (void *)runtime->dma_area; 168163ae6f3STakashi Sakamoto } 169163ae6f3STakashi Sakamoto } 170163ae6f3STakashi Sakamoto 171163ae6f3STakashi Sakamoto static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, 172163ae6f3STakashi Sakamoto __be32 *buffer, unsigned int frames) 173163ae6f3STakashi Sakamoto { 174163ae6f3STakashi Sakamoto struct amdtp_dot *p = s->protocol; 175163ae6f3STakashi Sakamoto struct snd_pcm_runtime *runtime = pcm->runtime; 176163ae6f3STakashi Sakamoto unsigned int channels, remaining_frames, i, c; 177163ae6f3STakashi Sakamoto u32 *dst; 178163ae6f3STakashi Sakamoto 179163ae6f3STakashi Sakamoto channels = p->pcm_channels; 180163ae6f3STakashi Sakamoto dst = (void *)runtime->dma_area + 181163ae6f3STakashi Sakamoto frames_to_bytes(runtime, s->pcm_buffer_pointer); 182163ae6f3STakashi Sakamoto remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; 183163ae6f3STakashi Sakamoto 184163ae6f3STakashi Sakamoto buffer++; 185163ae6f3STakashi Sakamoto for (i = 0; i < frames; ++i) { 186163ae6f3STakashi Sakamoto for (c = 0; c < channels; ++c) { 187163ae6f3STakashi Sakamoto *dst = be32_to_cpu(buffer[c]) << 8; 188163ae6f3STakashi Sakamoto dst++; 189163ae6f3STakashi Sakamoto } 190163ae6f3STakashi Sakamoto buffer += s->data_block_quadlets; 191163ae6f3STakashi Sakamoto if (--remaining_frames == 0) 192163ae6f3STakashi Sakamoto dst = (void *)runtime->dma_area; 193163ae6f3STakashi Sakamoto } 194163ae6f3STakashi Sakamoto } 195163ae6f3STakashi Sakamoto 196163ae6f3STakashi Sakamoto static void write_pcm_silence(struct amdtp_stream *s, __be32 *buffer, 197163ae6f3STakashi Sakamoto unsigned int data_blocks) 198163ae6f3STakashi Sakamoto { 199163ae6f3STakashi Sakamoto struct amdtp_dot *p = s->protocol; 200163ae6f3STakashi Sakamoto unsigned int channels, i, c; 201163ae6f3STakashi Sakamoto 202163ae6f3STakashi Sakamoto channels = p->pcm_channels; 203163ae6f3STakashi Sakamoto 204163ae6f3STakashi Sakamoto buffer++; 205163ae6f3STakashi Sakamoto for (i = 0; i < data_blocks; ++i) { 206163ae6f3STakashi Sakamoto for (c = 0; c < channels; ++c) 207163ae6f3STakashi Sakamoto buffer[c] = cpu_to_be32(0x40000000); 208163ae6f3STakashi Sakamoto buffer += s->data_block_quadlets; 209163ae6f3STakashi Sakamoto } 210163ae6f3STakashi Sakamoto } 211163ae6f3STakashi Sakamoto 2129dc5d31cSTakashi Sakamoto static bool midi_ratelimit_per_packet(struct amdtp_stream *s, unsigned int port) 2139dc5d31cSTakashi Sakamoto { 2149dc5d31cSTakashi Sakamoto struct amdtp_dot *p = s->protocol; 2159dc5d31cSTakashi Sakamoto int used; 2169dc5d31cSTakashi Sakamoto 2179dc5d31cSTakashi Sakamoto used = p->midi_fifo_used[port]; 2189dc5d31cSTakashi Sakamoto if (used == 0) 2199dc5d31cSTakashi Sakamoto return true; 2209dc5d31cSTakashi Sakamoto 2219dc5d31cSTakashi Sakamoto used -= MIDI_BYTES_PER_SECOND * s->syt_interval; 2229dc5d31cSTakashi Sakamoto used = max(used, 0); 2239dc5d31cSTakashi Sakamoto p->midi_fifo_used[port] = used; 2249dc5d31cSTakashi Sakamoto 2259dc5d31cSTakashi Sakamoto return used < p->midi_fifo_limit; 2269dc5d31cSTakashi Sakamoto } 2279dc5d31cSTakashi Sakamoto 2289dc5d31cSTakashi Sakamoto static inline void midi_use_bytes(struct amdtp_stream *s, 2299dc5d31cSTakashi Sakamoto unsigned int port, unsigned int count) 2309dc5d31cSTakashi Sakamoto { 2319dc5d31cSTakashi Sakamoto struct amdtp_dot *p = s->protocol; 2329dc5d31cSTakashi Sakamoto 2339dc5d31cSTakashi Sakamoto p->midi_fifo_used[port] += amdtp_rate_table[s->sfc] * count; 2349dc5d31cSTakashi Sakamoto } 2359dc5d31cSTakashi Sakamoto 2369dc5d31cSTakashi Sakamoto static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer, 237ab754812STakashi Sakamoto unsigned int data_blocks, unsigned int data_block_counter) 2389dc5d31cSTakashi Sakamoto { 2399dc5d31cSTakashi Sakamoto struct amdtp_dot *p = s->protocol; 2409dc5d31cSTakashi Sakamoto unsigned int f, port; 2419dc5d31cSTakashi Sakamoto int len; 2429dc5d31cSTakashi Sakamoto u8 *b; 2439dc5d31cSTakashi Sakamoto 2449dc5d31cSTakashi Sakamoto for (f = 0; f < data_blocks; f++) { 245ab754812STakashi Sakamoto port = (data_block_counter + f) % 8; 2469dc5d31cSTakashi Sakamoto b = (u8 *)&buffer[0]; 2479dc5d31cSTakashi Sakamoto 2489dc5d31cSTakashi Sakamoto len = 0; 2498820a4cfSTakashi Sakamoto if (port < MAX_MIDI_PORTS && 2509dc5d31cSTakashi Sakamoto midi_ratelimit_per_packet(s, port) && 2519dc5d31cSTakashi Sakamoto p->midi[port] != NULL) 2529dc5d31cSTakashi Sakamoto len = snd_rawmidi_transmit(p->midi[port], b + 1, 2); 2539dc5d31cSTakashi Sakamoto 2549dc5d31cSTakashi Sakamoto if (len > 0) { 2558820a4cfSTakashi Sakamoto /* 2568820a4cfSTakashi Sakamoto * Upper 4 bits of LSB represent port number. 2578820a4cfSTakashi Sakamoto * - 0000b: physical MIDI port 1. 2588820a4cfSTakashi Sakamoto * - 0010b: physical MIDI port 2. 2598820a4cfSTakashi Sakamoto * - 1110b: console MIDI port. 2608820a4cfSTakashi Sakamoto */ 2618820a4cfSTakashi Sakamoto if (port == 2) 2628820a4cfSTakashi Sakamoto b[3] = 0xe0; 2638820a4cfSTakashi Sakamoto else if (port == 1) 2648820a4cfSTakashi Sakamoto b[3] = 0x20; 2658820a4cfSTakashi Sakamoto else 2668820a4cfSTakashi Sakamoto b[3] = 0x00; 2678820a4cfSTakashi Sakamoto b[3] |= len; 2689dc5d31cSTakashi Sakamoto midi_use_bytes(s, port, len); 2699dc5d31cSTakashi Sakamoto } else { 2709dc5d31cSTakashi Sakamoto b[1] = 0; 2719dc5d31cSTakashi Sakamoto b[2] = 0; 2729dc5d31cSTakashi Sakamoto b[3] = 0; 2739dc5d31cSTakashi Sakamoto } 2749dc5d31cSTakashi Sakamoto b[0] = 0x80; 2759dc5d31cSTakashi Sakamoto 2769dc5d31cSTakashi Sakamoto buffer += s->data_block_quadlets; 2779dc5d31cSTakashi Sakamoto } 2789dc5d31cSTakashi Sakamoto } 2799dc5d31cSTakashi Sakamoto 2809dc5d31cSTakashi Sakamoto static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer, 2819dc5d31cSTakashi Sakamoto unsigned int data_blocks) 2829dc5d31cSTakashi Sakamoto { 2839dc5d31cSTakashi Sakamoto struct amdtp_dot *p = s->protocol; 2849dc5d31cSTakashi Sakamoto unsigned int f, port, len; 2859dc5d31cSTakashi Sakamoto u8 *b; 2869dc5d31cSTakashi Sakamoto 2879dc5d31cSTakashi Sakamoto for (f = 0; f < data_blocks; f++) { 2889dc5d31cSTakashi Sakamoto b = (u8 *)&buffer[0]; 2899dc5d31cSTakashi Sakamoto 2908820a4cfSTakashi Sakamoto len = b[3] & 0x0f; 2918820a4cfSTakashi Sakamoto if (len > 0) { 2928820a4cfSTakashi Sakamoto /* 2938820a4cfSTakashi Sakamoto * Upper 4 bits of LSB represent port number. 2948820a4cfSTakashi Sakamoto * - 0000b: physical MIDI port 1. Use port 0. 2958820a4cfSTakashi Sakamoto * - 1110b: console MIDI port. Use port 2. 2968820a4cfSTakashi Sakamoto */ 2978820a4cfSTakashi Sakamoto if (b[3] >> 4 > 0) 2988820a4cfSTakashi Sakamoto port = 2; 2998820a4cfSTakashi Sakamoto else 3008820a4cfSTakashi Sakamoto port = 0; 3018820a4cfSTakashi Sakamoto 3028820a4cfSTakashi Sakamoto if (port < MAX_MIDI_PORTS && p->midi[port]) 3039dc5d31cSTakashi Sakamoto snd_rawmidi_receive(p->midi[port], b + 1, len); 3048820a4cfSTakashi Sakamoto } 3059dc5d31cSTakashi Sakamoto 3069dc5d31cSTakashi Sakamoto buffer += s->data_block_quadlets; 3079dc5d31cSTakashi Sakamoto } 3089dc5d31cSTakashi Sakamoto } 3099dc5d31cSTakashi Sakamoto 310163ae6f3STakashi Sakamoto int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s, 311163ae6f3STakashi Sakamoto struct snd_pcm_runtime *runtime) 312163ae6f3STakashi Sakamoto { 313163ae6f3STakashi Sakamoto int err; 314163ae6f3STakashi Sakamoto 315163ae6f3STakashi Sakamoto /* This protocol delivers 24 bit data in 32bit data channel. */ 316163ae6f3STakashi Sakamoto err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); 317163ae6f3STakashi Sakamoto if (err < 0) 318163ae6f3STakashi Sakamoto return err; 319163ae6f3STakashi Sakamoto 320163ae6f3STakashi Sakamoto return amdtp_stream_add_pcm_hw_constraints(s, runtime); 321163ae6f3STakashi Sakamoto } 322163ae6f3STakashi Sakamoto 3239dc5d31cSTakashi Sakamoto void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, 3249dc5d31cSTakashi Sakamoto struct snd_rawmidi_substream *midi) 3259dc5d31cSTakashi Sakamoto { 3269dc5d31cSTakashi Sakamoto struct amdtp_dot *p = s->protocol; 3279dc5d31cSTakashi Sakamoto 3288820a4cfSTakashi Sakamoto if (port < MAX_MIDI_PORTS) 3296aa7de05SMark Rutland WRITE_ONCE(p->midi[port], midi); 3309dc5d31cSTakashi Sakamoto } 3319dc5d31cSTakashi Sakamoto 332163ae6f3STakashi Sakamoto static unsigned int process_tx_data_blocks(struct amdtp_stream *s, 333ab754812STakashi Sakamoto __be32 *buffer, unsigned int data_blocks, 334ab754812STakashi Sakamoto unsigned int data_block_counter, unsigned int *syt) 335163ae6f3STakashi Sakamoto { 336163ae6f3STakashi Sakamoto struct snd_pcm_substream *pcm; 337163ae6f3STakashi Sakamoto unsigned int pcm_frames; 338163ae6f3STakashi Sakamoto 3396aa7de05SMark Rutland pcm = READ_ONCE(s->pcm); 340163ae6f3STakashi Sakamoto if (pcm) { 341a02cb8f8STakashi Sakamoto read_pcm_s32(s, pcm, buffer, data_blocks); 342163ae6f3STakashi Sakamoto pcm_frames = data_blocks; 343163ae6f3STakashi Sakamoto } else { 344163ae6f3STakashi Sakamoto pcm_frames = 0; 345163ae6f3STakashi Sakamoto } 346163ae6f3STakashi Sakamoto 3479dc5d31cSTakashi Sakamoto read_midi_messages(s, buffer, data_blocks); 348163ae6f3STakashi Sakamoto 349163ae6f3STakashi Sakamoto return pcm_frames; 350163ae6f3STakashi Sakamoto } 351163ae6f3STakashi Sakamoto 352163ae6f3STakashi Sakamoto static unsigned int process_rx_data_blocks(struct amdtp_stream *s, 353ab754812STakashi Sakamoto __be32 *buffer, unsigned int data_blocks, 354ab754812STakashi Sakamoto unsigned int data_block_counter, unsigned int *syt) 355163ae6f3STakashi Sakamoto { 356163ae6f3STakashi Sakamoto struct snd_pcm_substream *pcm; 357163ae6f3STakashi Sakamoto unsigned int pcm_frames; 358163ae6f3STakashi Sakamoto 3596aa7de05SMark Rutland pcm = READ_ONCE(s->pcm); 360163ae6f3STakashi Sakamoto if (pcm) { 361a02cb8f8STakashi Sakamoto write_pcm_s32(s, pcm, buffer, data_blocks); 362163ae6f3STakashi Sakamoto pcm_frames = data_blocks; 363163ae6f3STakashi Sakamoto } else { 364163ae6f3STakashi Sakamoto write_pcm_silence(s, buffer, data_blocks); 365163ae6f3STakashi Sakamoto pcm_frames = 0; 366163ae6f3STakashi Sakamoto } 367163ae6f3STakashi Sakamoto 368ab754812STakashi Sakamoto write_midi_messages(s, buffer, data_blocks, data_block_counter); 369163ae6f3STakashi Sakamoto 370163ae6f3STakashi Sakamoto return pcm_frames; 371163ae6f3STakashi Sakamoto } 372163ae6f3STakashi Sakamoto 373163ae6f3STakashi Sakamoto int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit, 374163ae6f3STakashi Sakamoto enum amdtp_stream_direction dir) 375163ae6f3STakashi Sakamoto { 376163ae6f3STakashi Sakamoto amdtp_stream_process_data_blocks_t process_data_blocks; 377163ae6f3STakashi Sakamoto enum cip_flags flags; 378163ae6f3STakashi Sakamoto 379163ae6f3STakashi Sakamoto /* Use different mode between incoming/outgoing. */ 380163ae6f3STakashi Sakamoto if (dir == AMDTP_IN_STREAM) { 38162f00e40STakashi Sakamoto flags = CIP_NONBLOCKING; 382163ae6f3STakashi Sakamoto process_data_blocks = process_tx_data_blocks; 383163ae6f3STakashi Sakamoto } else { 384163ae6f3STakashi Sakamoto flags = CIP_BLOCKING; 385163ae6f3STakashi Sakamoto process_data_blocks = process_rx_data_blocks; 386163ae6f3STakashi Sakamoto } 387163ae6f3STakashi Sakamoto 388163ae6f3STakashi Sakamoto return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM, 389163ae6f3STakashi Sakamoto process_data_blocks, sizeof(struct amdtp_dot)); 390163ae6f3STakashi Sakamoto } 391163ae6f3STakashi Sakamoto 392163ae6f3STakashi Sakamoto void amdtp_dot_reset(struct amdtp_stream *s) 393163ae6f3STakashi Sakamoto { 394163ae6f3STakashi Sakamoto struct amdtp_dot *p = s->protocol; 395163ae6f3STakashi Sakamoto 396163ae6f3STakashi Sakamoto p->state.carry = 0x00; 397163ae6f3STakashi Sakamoto p->state.idx = 0x00; 398163ae6f3STakashi Sakamoto p->state.off = 0; 399163ae6f3STakashi Sakamoto } 400