sound/firewire/amdtp-am824.c

Source file repositories/reference/linux-study-clean/sound/firewire/amdtp-am824.c

File Facts

System
Linux kernel
Corpus path
sound/firewire/amdtp-am824.c
Extension
.c
Size
12023 bytes
Lines
421
Domain
Driver Families
Bucket
sound/firewire
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct amdtp_am824 {
	struct snd_rawmidi_substream *midi[AM824_MAX_CHANNELS_FOR_MIDI * 8];
	int midi_fifo_limit;
	int midi_fifo_used[AM824_MAX_CHANNELS_FOR_MIDI * 8];
	unsigned int pcm_channels;
	unsigned int midi_ports;

	u8 pcm_positions[AM824_MAX_CHANNELS_FOR_PCM];
	u8 midi_position;
};

/**
 * amdtp_am824_set_parameters - set stream parameters
 * @s: the AMDTP stream to configure
 * @rate: the sample rate
 * @pcm_channels: the number of PCM samples in each data block, to be encoded
 *                as AM824 multi-bit linear audio
 * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
 * @double_pcm_frames: one data block transfers two PCM frames
 *
 * The parameters must be set before the stream is started, and must not be
 * changed while the stream is running.
 */
int amdtp_am824_set_parameters(struct amdtp_stream *s, unsigned int rate,
			       unsigned int pcm_channels,
			       unsigned int midi_ports,
			       bool double_pcm_frames)
{
	struct amdtp_am824 *p = s->protocol;
	unsigned int midi_channels;
	unsigned int pcm_frame_multiplier;
	int i, err;

	if (amdtp_stream_running(s))
		return -EINVAL;

	if (pcm_channels > AM824_MAX_CHANNELS_FOR_PCM)
		return -EINVAL;

	midi_channels = DIV_ROUND_UP(midi_ports, 8);
	if (midi_channels > AM824_MAX_CHANNELS_FOR_MIDI)
		return -EINVAL;

	if (WARN_ON(amdtp_stream_running(s)) ||
	    WARN_ON(pcm_channels > AM824_MAX_CHANNELS_FOR_PCM) ||
	    WARN_ON(midi_channels > AM824_MAX_CHANNELS_FOR_MIDI))
		return -EINVAL;

	/*
	 * In IEC 61883-6, one data block represents one event. In ALSA, one
	 * event equals to one PCM frame. But Dice has a quirk at higher
	 * sampling rate to transfer two PCM frames in one data block.
	 */
	if (double_pcm_frames)
		pcm_frame_multiplier = 2;
	else
		pcm_frame_multiplier = 1;

	err = amdtp_stream_set_parameters(s, rate, pcm_channels + midi_channels,
					  pcm_frame_multiplier);
	if (err < 0)
		return err;

	if (s->direction == AMDTP_OUT_STREAM)
		s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;

	p->pcm_channels = pcm_channels;
	p->midi_ports = midi_ports;

	/* init the position map for PCM and MIDI channels */
	for (i = 0; i < pcm_channels; i++)
		p->pcm_positions[i] = i;
	p->midi_position = p->pcm_channels;

	/*
	 * We do not know the actual MIDI FIFO size of most devices.  Just
	 * assume two bytes, i.e., one byte can be received over the bus while
	 * the previous one is transmitted over MIDI.
	 * (The value here is adjusted for midi_ratelimit_per_packet().)
	 */
	p->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1;

	return 0;
}
EXPORT_SYMBOL_GPL(amdtp_am824_set_parameters);

/**
 * amdtp_am824_set_pcm_position - set an index of data channel for a channel
 *				  of PCM frame
 * @s: the AMDTP stream

Annotation

Implementation Notes