cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

amdtp-ff.c (4411B)


      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
     11struct amdtp_ff {
     12	unsigned int pcm_channels;
     13};
     14
     15int 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
     30static 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
     60static 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
     90static 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
    103int 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
    115static 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
    139static 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
    161int 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_BLOCKING | CIP_UNAWARE_SYT | CIP_NO_HEADER, 0,
    172				 process_ctx_payloads, sizeof(struct amdtp_ff));
    173}