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