root/sound/firewire/fireface/amdtp-ff.c

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

DEFINITIONS

This source file includes following definitions.
  1. amdtp_ff_set_parameters
  2. write_pcm_s32
  3. read_pcm_s32
  4. write_pcm_silence
  5. amdtp_ff_add_pcm_hw_constraints
  6. process_it_ctx_payloads
  7. process_ir_ctx_payloads
  8. amdtp_ff_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * amdtp-ff.c - a part of driver for RME Fireface series
   4  *
   5  * Copyright (c) 2015-2017 Takashi Sakamoto
   6  */
   7 
   8 #include <sound/pcm.h>
   9 #include "ff.h"
  10 
  11 struct amdtp_ff {
  12         unsigned int pcm_channels;
  13 };
  14 
  15 int amdtp_ff_set_parameters(struct amdtp_stream *s, unsigned int rate,
  16                             unsigned int pcm_channels)
  17 {
  18         struct amdtp_ff *p = s->protocol;
  19         unsigned int data_channels;
  20 
  21         if (amdtp_stream_running(s))
  22                 return -EBUSY;
  23 
  24         p->pcm_channels = pcm_channels;
  25         data_channels = pcm_channels;
  26 
  27         return amdtp_stream_set_parameters(s, rate, data_channels);
  28 }
  29 
  30 static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
  31                           __le32 *buffer, unsigned int frames,
  32                           unsigned int pcm_frames)
  33 {
  34         struct amdtp_ff *p = s->protocol;
  35         unsigned int channels = p->pcm_channels;
  36         struct snd_pcm_runtime *runtime = pcm->runtime;
  37         unsigned int pcm_buffer_pointer;
  38         int remaining_frames;
  39         const u32 *src;
  40         int i, c;
  41 
  42         pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
  43         pcm_buffer_pointer %= runtime->buffer_size;
  44 
  45         src = (void *)runtime->dma_area +
  46                                 frames_to_bytes(runtime, pcm_buffer_pointer);
  47         remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
  48 
  49         for (i = 0; i < frames; ++i) {
  50                 for (c = 0; c < channels; ++c) {
  51                         buffer[c] = cpu_to_le32(*src);
  52                         src++;
  53                 }
  54                 buffer += s->data_block_quadlets;
  55                 if (--remaining_frames == 0)
  56                         src = (void *)runtime->dma_area;
  57         }
  58 }
  59 
  60 static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
  61                          __le32 *buffer, unsigned int frames,
  62                          unsigned int pcm_frames)
  63 {
  64         struct amdtp_ff *p = s->protocol;
  65         unsigned int channels = p->pcm_channels;
  66         struct snd_pcm_runtime *runtime = pcm->runtime;
  67         unsigned int pcm_buffer_pointer;
  68         int remaining_frames;
  69         u32 *dst;
  70         int i, c;
  71 
  72         pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
  73         pcm_buffer_pointer %= runtime->buffer_size;
  74 
  75         dst  = (void *)runtime->dma_area +
  76                                 frames_to_bytes(runtime, pcm_buffer_pointer);
  77         remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
  78 
  79         for (i = 0; i < frames; ++i) {
  80                 for (c = 0; c < channels; ++c) {
  81                         *dst = le32_to_cpu(buffer[c]) & 0xffffff00;
  82                         dst++;
  83                 }
  84                 buffer += s->data_block_quadlets;
  85                 if (--remaining_frames == 0)
  86                         dst = (void *)runtime->dma_area;
  87         }
  88 }
  89 
  90 static void write_pcm_silence(struct amdtp_stream *s,
  91                               __le32 *buffer, unsigned int frames)
  92 {
  93         struct amdtp_ff *p = s->protocol;
  94         unsigned int i, c, channels = p->pcm_channels;
  95 
  96         for (i = 0; i < frames; ++i) {
  97                 for (c = 0; c < channels; ++c)
  98                         buffer[c] = cpu_to_le32(0x00000000);
  99                 buffer += s->data_block_quadlets;
 100         }
 101 }
 102 
 103 int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream *s,
 104                                     struct snd_pcm_runtime *runtime)
 105 {
 106         int err;
 107 
 108         err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 109         if (err < 0)
 110                 return err;
 111 
 112         return amdtp_stream_add_pcm_hw_constraints(s, runtime);
 113 }
 114 
 115 static unsigned int process_it_ctx_payloads(struct amdtp_stream *s,
 116                                            const struct pkt_desc *descs,
 117                                            unsigned int packets,
 118                                            struct snd_pcm_substream *pcm)
 119 {
 120         unsigned int pcm_frames = 0;
 121         int i;
 122 
 123         for (i = 0; i < packets; ++i) {
 124                 const struct pkt_desc *desc = descs + i;
 125                 __le32 *buf = (__le32 *)desc->ctx_payload;
 126                 unsigned int data_blocks = desc->data_blocks;
 127 
 128                 if (pcm) {
 129                         write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
 130                         pcm_frames += data_blocks;
 131                 } else {
 132                         write_pcm_silence(s, buf, data_blocks);
 133                 }
 134         }
 135 
 136         return pcm_frames;
 137 }
 138 
 139 static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s,
 140                                             const struct pkt_desc *descs,
 141                                             unsigned int packets,
 142                                             struct snd_pcm_substream *pcm)
 143 {
 144         unsigned int pcm_frames = 0;
 145         int i;
 146 
 147         for (i = 0; i < packets; ++i) {
 148                 const struct pkt_desc *desc = descs + i;
 149                 __le32 *buf = (__le32 *)desc->ctx_payload;
 150                 unsigned int data_blocks = desc->data_blocks;
 151 
 152                 if (pcm) {
 153                         read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
 154                         pcm_frames += data_blocks;
 155                 }
 156         }
 157 
 158         return pcm_frames;
 159 }
 160 
 161 int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit,
 162                   enum amdtp_stream_direction dir)
 163 {
 164         amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
 165 
 166         if (dir == AMDTP_IN_STREAM)
 167                 process_ctx_payloads = process_ir_ctx_payloads;
 168         else
 169                 process_ctx_payloads = process_it_ctx_payloads;
 170 
 171         return amdtp_stream_init(s, unit, dir, CIP_NO_HEADER, 0,
 172                                  process_ctx_payloads, sizeof(struct amdtp_ff));
 173 }

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