1 // SPDX-License-Identifier: GPL-2.0-only
3 * amdtp-ff.c - a part of driver for RME Fireface series
5 * Copyright (c) 2015-2017 Takashi Sakamoto
12 unsigned int pcm_channels
;
15 int amdtp_ff_set_parameters(struct amdtp_stream
*s
, unsigned int rate
,
16 unsigned int pcm_channels
)
18 struct amdtp_ff
*p
= s
->protocol
;
19 unsigned int data_channels
;
21 if (amdtp_stream_running(s
))
24 p
->pcm_channels
= pcm_channels
;
25 data_channels
= pcm_channels
;
27 return amdtp_stream_set_parameters(s
, rate
, data_channels
);
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
)
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
;
42 pcm_buffer_pointer
= s
->pcm_buffer_pointer
+ pcm_frames
;
43 pcm_buffer_pointer
%= runtime
->buffer_size
;
45 src
= (void *)runtime
->dma_area
+
46 frames_to_bytes(runtime
, pcm_buffer_pointer
);
47 remaining_frames
= runtime
->buffer_size
- pcm_buffer_pointer
;
49 for (i
= 0; i
< frames
; ++i
) {
50 for (c
= 0; c
< channels
; ++c
) {
51 buffer
[c
] = cpu_to_le32(*src
);
54 buffer
+= s
->data_block_quadlets
;
55 if (--remaining_frames
== 0)
56 src
= (void *)runtime
->dma_area
;
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
)
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
;
72 pcm_buffer_pointer
= s
->pcm_buffer_pointer
+ pcm_frames
;
73 pcm_buffer_pointer
%= runtime
->buffer_size
;
75 dst
= (void *)runtime
->dma_area
+
76 frames_to_bytes(runtime
, pcm_buffer_pointer
);
77 remaining_frames
= runtime
->buffer_size
- pcm_buffer_pointer
;
79 for (i
= 0; i
< frames
; ++i
) {
80 for (c
= 0; c
< channels
; ++c
) {
81 *dst
= le32_to_cpu(buffer
[c
]) & 0xffffff00;
84 buffer
+= s
->data_block_quadlets
;
85 if (--remaining_frames
== 0)
86 dst
= (void *)runtime
->dma_area
;
90 static void write_pcm_silence(struct amdtp_stream
*s
,
91 __le32
*buffer
, unsigned int frames
)
93 struct amdtp_ff
*p
= s
->protocol
;
94 unsigned int i
, c
, channels
= p
->pcm_channels
;
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
;
103 int amdtp_ff_add_pcm_hw_constraints(struct amdtp_stream
*s
,
104 struct snd_pcm_runtime
*runtime
)
108 err
= snd_pcm_hw_constraint_msbits(runtime
, 0, 32, 24);
112 return amdtp_stream_add_pcm_hw_constraints(s
, runtime
);
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
)
120 unsigned int pcm_frames
= 0;
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
;
129 write_pcm_s32(s
, pcm
, buf
, data_blocks
, pcm_frames
);
130 pcm_frames
+= data_blocks
;
132 write_pcm_silence(s
, buf
, data_blocks
);
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
)
144 unsigned int pcm_frames
= 0;
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
;
153 read_pcm_s32(s
, pcm
, buf
, data_blocks
, pcm_frames
);
154 pcm_frames
+= data_blocks
;
161 int amdtp_ff_init(struct amdtp_stream
*s
, struct fw_unit
*unit
,
162 enum amdtp_stream_direction dir
)
164 amdtp_stream_process_ctx_payloads_t process_ctx_payloads
;
166 if (dir
== AMDTP_IN_STREAM
)
167 process_ctx_payloads
= process_ir_ctx_payloads
;
169 process_ctx_payloads
= process_it_ctx_payloads
;
171 return amdtp_stream_init(s
, unit
, dir
, CIP_NO_HEADER
, 0,
172 process_ctx_payloads
, sizeof(struct amdtp_ff
));