~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/firewire/fireface/amdtp-ff.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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, 1);
 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 void process_it_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc,
116                                     unsigned int count, struct snd_pcm_substream *pcm)
117 {
118         unsigned int pcm_frames = 0;
119         int i;
120 
121         for (i = 0; i < count; ++i) {
122                 __le32 *buf = (__le32 *)desc->ctx_payload;
123                 unsigned int data_blocks = desc->data_blocks;
124 
125                 if (pcm) {
126                         write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
127                         pcm_frames += data_blocks;
128                 } else {
129                         write_pcm_silence(s, buf, data_blocks);
130                 }
131 
132                 desc = amdtp_stream_next_packet_desc(s, desc);
133         }
134 }
135 
136 static void process_ir_ctx_payloads(struct amdtp_stream *s, const struct pkt_desc *desc,
137                                     unsigned int count, struct snd_pcm_substream *pcm)
138 {
139         unsigned int pcm_frames = 0;
140         int i;
141 
142         for (i = 0; i < count; ++i) {
143                 __le32 *buf = (__le32 *)desc->ctx_payload;
144                 unsigned int data_blocks = desc->data_blocks;
145 
146                 if (pcm) {
147                         read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
148                         pcm_frames += data_blocks;
149                 }
150 
151                 desc = amdtp_stream_next_packet_desc(s, desc);
152         }
153 }
154 
155 int amdtp_ff_init(struct amdtp_stream *s, struct fw_unit *unit,
156                   enum amdtp_stream_direction dir)
157 {
158         amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
159 
160         if (dir == AMDTP_IN_STREAM)
161                 process_ctx_payloads = process_ir_ctx_payloads;
162         else
163                 process_ctx_payloads = process_it_ctx_payloads;
164 
165         return amdtp_stream_init(s, unit, dir, CIP_BLOCKING | CIP_UNAWARE_SYT | CIP_NO_HEADER, 0,
166                                  process_ctx_payloads, sizeof(struct amdtp_ff));
167 }
168 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php