root/sound/firewire/tascam/amdtp-tascam.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. amdtp_tscm_set_parameters
  2. write_pcm_s32
  3. read_pcm_s32
  4. write_pcm_silence
  5. amdtp_tscm_add_pcm_hw_constraints
  6. read_status_messages
  7. process_ir_ctx_payloads
  8. process_it_ctx_payloads
  9. amdtp_tscm_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * amdtp-tascam.c - a part of driver for TASCAM FireWire series
   4  *
   5  * Copyright (c) 2015 Takashi Sakamoto
   6  */
   7 
   8 #include <sound/pcm.h>
   9 #include "tascam.h"
  10 
  11 #define AMDTP_FMT_TSCM_TX       0x1e
  12 #define AMDTP_FMT_TSCM_RX       0x3e
  13 
  14 struct amdtp_tscm {
  15         unsigned int pcm_channels;
  16 };
  17 
  18 int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate)
  19 {
  20         struct amdtp_tscm *p = s->protocol;
  21         unsigned int data_channels;
  22 
  23         if (amdtp_stream_running(s))
  24                 return -EBUSY;
  25 
  26         data_channels = p->pcm_channels;
  27 
  28         /* Packets in in-stream have extra 2 data channels. */
  29         if (s->direction == AMDTP_IN_STREAM)
  30                 data_channels += 2;
  31 
  32         return amdtp_stream_set_parameters(s, rate, data_channels);
  33 }
  34 
  35 static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
  36                           __be32 *buffer, unsigned int frames,
  37                           unsigned int pcm_frames)
  38 {
  39         struct amdtp_tscm *p = s->protocol;
  40         unsigned int channels = p->pcm_channels;
  41         struct snd_pcm_runtime *runtime = pcm->runtime;
  42         unsigned int pcm_buffer_pointer;
  43         int remaining_frames;
  44         const u32 *src;
  45         int i, c;
  46 
  47         pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
  48         pcm_buffer_pointer %= runtime->buffer_size;
  49 
  50         src = (void *)runtime->dma_area +
  51                                 frames_to_bytes(runtime, pcm_buffer_pointer);
  52         remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
  53 
  54         for (i = 0; i < frames; ++i) {
  55                 for (c = 0; c < channels; ++c) {
  56                         buffer[c] = cpu_to_be32(*src);
  57                         src++;
  58                 }
  59                 buffer += s->data_block_quadlets;
  60                 if (--remaining_frames == 0)
  61                         src = (void *)runtime->dma_area;
  62         }
  63 }
  64 
  65 static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
  66                          __be32 *buffer, unsigned int frames,
  67                          unsigned int pcm_frames)
  68 {
  69         struct amdtp_tscm *p = s->protocol;
  70         unsigned int channels = p->pcm_channels;
  71         struct snd_pcm_runtime *runtime = pcm->runtime;
  72         unsigned int pcm_buffer_pointer;
  73         int remaining_frames;
  74         u32 *dst;
  75         int i, c;
  76 
  77         pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
  78         pcm_buffer_pointer %= runtime->buffer_size;
  79 
  80         dst  = (void *)runtime->dma_area +
  81                                 frames_to_bytes(runtime, pcm_buffer_pointer);
  82         remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
  83 
  84         /* The first data channel is for event counter. */
  85         buffer += 1;
  86 
  87         for (i = 0; i < frames; ++i) {
  88                 for (c = 0; c < channels; ++c) {
  89                         *dst = be32_to_cpu(buffer[c]);
  90                         dst++;
  91                 }
  92                 buffer += s->data_block_quadlets;
  93                 if (--remaining_frames == 0)
  94                         dst = (void *)runtime->dma_area;
  95         }
  96 }
  97 
  98 static void write_pcm_silence(struct amdtp_stream *s, __be32 *buffer,
  99                               unsigned int data_blocks)
 100 {
 101         struct amdtp_tscm *p = s->protocol;
 102         unsigned int channels, i, c;
 103 
 104         channels = p->pcm_channels;
 105 
 106         for (i = 0; i < data_blocks; ++i) {
 107                 for (c = 0; c < channels; ++c)
 108                         buffer[c] = 0x00000000;
 109                 buffer += s->data_block_quadlets;
 110         }
 111 }
 112 
 113 int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s,
 114                                       struct snd_pcm_runtime *runtime)
 115 {
 116         int err;
 117 
 118         /*
 119          * Our implementation allows this protocol to deliver 24 bit sample in
 120          * 32bit data channel.
 121          */
 122         err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 123         if (err < 0)
 124                 return err;
 125 
 126         return amdtp_stream_add_pcm_hw_constraints(s, runtime);
 127 }
 128 
 129 static void read_status_messages(struct amdtp_stream *s,
 130                                  __be32 *buffer, unsigned int data_blocks)
 131 {
 132         struct snd_tscm *tscm = container_of(s, struct snd_tscm, tx_stream);
 133         bool used = READ_ONCE(tscm->hwdep->used);
 134         int i;
 135 
 136         for (i = 0; i < data_blocks; i++) {
 137                 unsigned int index;
 138                 __be32 before;
 139                 __be32 after;
 140 
 141                 index = be32_to_cpu(buffer[0]) % SNDRV_FIREWIRE_TASCAM_STATE_COUNT;
 142                 before = tscm->state[index];
 143                 after = buffer[s->data_block_quadlets - 1];
 144 
 145                 if (used && index > 4 && index < 16) {
 146                         __be32 mask;
 147 
 148                         if (index == 5)
 149                                 mask = cpu_to_be32(~0x0000ffff);
 150                         else if (index == 6)
 151                                 mask = cpu_to_be32(~0x0000ffff);
 152                         else if (index == 8)
 153                                 mask = cpu_to_be32(~0x000f0f00);
 154                         else
 155                                 mask = cpu_to_be32(~0x00000000);
 156 
 157                         if ((before ^ after) & mask) {
 158                                 struct snd_firewire_tascam_change *entry =
 159                                                 &tscm->queue[tscm->push_pos];
 160                                 unsigned long flag;
 161 
 162                                 spin_lock_irqsave(&tscm->lock, flag);
 163                                 entry->index = index;
 164                                 entry->before = before;
 165                                 entry->after = after;
 166                                 if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT)
 167                                         tscm->push_pos = 0;
 168                                 spin_unlock_irqrestore(&tscm->lock, flag);
 169 
 170                                 wake_up(&tscm->hwdep_wait);
 171                         }
 172                 }
 173 
 174                 tscm->state[index] = after;
 175                 buffer += s->data_block_quadlets;
 176         }
 177 }
 178 
 179 static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s,
 180                                             const struct pkt_desc *descs,
 181                                             unsigned int packets,
 182                                             struct snd_pcm_substream *pcm)
 183 {
 184         unsigned int pcm_frames = 0;
 185         int i;
 186 
 187         for (i = 0; i < packets; ++i) {
 188                 const struct pkt_desc *desc = descs + i;
 189                 __be32 *buf = desc->ctx_payload;
 190                 unsigned int data_blocks = desc->data_blocks;
 191 
 192                 if (pcm) {
 193                         read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
 194                         pcm_frames += data_blocks;
 195                 }
 196 
 197                 read_status_messages(s, buf, data_blocks);
 198         }
 199 
 200         return pcm_frames;
 201 }
 202 
 203 static unsigned int process_it_ctx_payloads(struct amdtp_stream *s,
 204                                             const struct pkt_desc *descs,
 205                                             unsigned int packets,
 206                                             struct snd_pcm_substream *pcm)
 207 {
 208         unsigned int pcm_frames = 0;
 209         int i;
 210 
 211         for (i = 0; i < packets; ++i) {
 212                 const struct pkt_desc *desc = descs + i;
 213                 __be32 *buf = desc->ctx_payload;
 214                 unsigned int data_blocks = desc->data_blocks;
 215 
 216                 if (pcm) {
 217                         write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
 218                         pcm_frames += data_blocks;
 219                 } else {
 220                         write_pcm_silence(s, buf, data_blocks);
 221                 }
 222         }
 223 
 224         return pcm_frames;
 225 }
 226 
 227 int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit,
 228                     enum amdtp_stream_direction dir, unsigned int pcm_channels)
 229 {
 230         amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
 231         struct amdtp_tscm *p;
 232         unsigned int fmt;
 233         int err;
 234 
 235         if (dir == AMDTP_IN_STREAM) {
 236                 fmt = AMDTP_FMT_TSCM_TX;
 237                 process_ctx_payloads = process_ir_ctx_payloads;
 238         } else {
 239                 fmt = AMDTP_FMT_TSCM_RX;
 240                 process_ctx_payloads = process_it_ctx_payloads;
 241         }
 242 
 243         err = amdtp_stream_init(s, unit, dir,
 244                         CIP_NONBLOCKING | CIP_SKIP_DBC_ZERO_CHECK, fmt,
 245                         process_ctx_payloads, sizeof(struct amdtp_tscm));
 246         if (err < 0)
 247                 return 0;
 248 
 249         if (dir == AMDTP_OUT_STREAM) {
 250                 // Use fixed value for FDF field.
 251                 s->ctx_data.rx.fdf = 0x00;
 252                 // Not used.
 253                 s->ctx_data.rx.syt_override = 0x0000;
 254         }
 255 
 256         /* This protocol uses fixed number of data channels for PCM samples. */
 257         p = s->protocol;
 258         p->pcm_channels = pcm_channels;
 259 
 260         return 0;
 261 }

/* [<][>][^][v][top][bottom][index][help] */