sound/firewire/motu/motu-stream.c

Source file repositories/reference/linux-study-clean/sound/firewire/motu/motu-stream.c

File Facts

System
Linux kernel
Corpus path
sound/firewire/motu/motu-stream.c
Extension
.c
Size
11088 bytes
Lines
430
Domain
Driver Families
Bucket
sound/firewire
Inferred role
Driver Families: implementation source
Status
source 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

if (err < 0) {
			dev_err(&motu->unit->device,
				"fail to set sampling rate: %d\n", err);
			return err;
		}

		err = snd_motu_stream_cache_packet_formats(motu);
		if (err < 0)
			return err;

		err = keep_resources(motu, rate, &motu->tx_stream);
		if (err < 0)
			return err;

		err = keep_resources(motu, rate, &motu->rx_stream);
		if (err < 0) {
			fw_iso_resources_free(&motu->tx_resources);
			return err;
		}

		err = amdtp_domain_set_events_per_period(&motu->domain,
					frames_per_period, frames_per_buffer);
		if (err < 0) {
			fw_iso_resources_free(&motu->tx_resources);
			fw_iso_resources_free(&motu->rx_resources);
			return err;
		}

		motu->cache.size = motu->tx_stream.syt_interval * frames_per_buffer;
		motu->cache.event_offsets = kcalloc(motu->cache.size, sizeof(*motu->cache.event_offsets),
						  GFP_KERNEL);
		if (!motu->cache.event_offsets) {
			fw_iso_resources_free(&motu->tx_resources);
			fw_iso_resources_free(&motu->rx_resources);
			return -ENOMEM;
		}
	}

	return 0;
}

static int ensure_packet_formats(struct snd_motu *motu)
{
	__be32 reg;
	u32 data;
	int err;

	err = snd_motu_transaction_read(motu, PACKET_FORMAT_OFFSET, &reg,
					sizeof(reg));
	if (err < 0)
		return err;
	data = be32_to_cpu(reg);

	data &= ~(TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS |
		  RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS|
		  TX_PACKET_TRANSMISSION_SPEED_MASK);
	if (motu->spec->tx_fixed_pcm_chunks[0] == motu->tx_packet_formats.pcm_chunks[0])
		data |= TX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
	if (motu->spec->rx_fixed_pcm_chunks[0] == motu->rx_packet_formats.pcm_chunks[0])
		data |= RX_PACKET_EXCLUDE_DIFFERED_DATA_CHUNKS;
	data |= fw_parent_device(motu->unit)->max_speed;

	reg = cpu_to_be32(data);
	return snd_motu_transaction_write(motu, PACKET_FORMAT_OFFSET, &reg,
					  sizeof(reg));
}

int snd_motu_stream_start_duplex(struct snd_motu *motu)
{
	unsigned int generation = motu->rx_resources.generation;
	int err = 0;

	if (motu->substreams_counter == 0)
		return 0;

	if (amdtp_streaming_error(&motu->rx_stream) ||
	    amdtp_streaming_error(&motu->tx_stream)) {
		amdtp_domain_stop(&motu->domain);
		finish_session(motu);
	}

	if (generation != fw_parent_device(motu->unit)->card->generation) {
		err = fw_iso_resources_update(&motu->rx_resources);
		if (err < 0)
			return err;

		err = fw_iso_resources_update(&motu->tx_resources);
		if (err < 0)
			return err;
	}

Annotation

Implementation Notes