sound/firewire/fireworks/fireworks_stream.c

Source file repositories/reference/linux-study-clean/sound/firewire/fireworks/fireworks_stream.c

File Facts

System
Linux kernel
Corpus path
sound/firewire/fireworks/fireworks_stream.c
Extension
.c
Size
8954 bytes
Lines
369
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) {
			cmp_connection_release(&efw->in_conn);
			return err;
		}

		err = amdtp_domain_set_events_per_period(&efw->domain,
					frames_per_period, frames_per_buffer);
		if (err < 0) {
			cmp_connection_release(&efw->in_conn);
			cmp_connection_release(&efw->out_conn);
			return err;
		}
	}

	return 0;
}

int snd_efw_stream_start_duplex(struct snd_efw *efw)
{
	unsigned int rate;
	int err = 0;

	// Need no substreams.
	if (efw->substreams_counter == 0)
		return -EIO;

	if (amdtp_streaming_error(&efw->rx_stream) ||
	    amdtp_streaming_error(&efw->tx_stream)) {
		amdtp_domain_stop(&efw->domain);
		cmp_connection_break(&efw->out_conn);
		cmp_connection_break(&efw->in_conn);
	}

	err = snd_efw_command_get_sampling_rate(efw, &rate);
	if (err < 0)
		return err;

	if (!amdtp_stream_running(&efw->rx_stream)) {
		unsigned int tx_init_skip_cycles;

		// Audiofire 2/4 skip an isochronous cycle several thousands after starting
		// packet transmission.
		if (efw->is_fireworks3 && !efw->is_af9)
			tx_init_skip_cycles = 6000;
		else
			tx_init_skip_cycles = 0;

		err = start_stream(efw, &efw->rx_stream, rate);
		if (err < 0)
			goto error;

		err = start_stream(efw, &efw->tx_stream, rate);
		if (err < 0)
			goto error;

		// NOTE: The device ignores presentation time expressed by the value of syt field
		// of CIP header in received packets. The sequence of the number of data blocks per
		// packet is important for media clock recovery.
		err = amdtp_domain_start(&efw->domain, tx_init_skip_cycles, true, false);
		if (err < 0)
			goto error;

		if (!amdtp_domain_wait_ready(&efw->domain, READY_TIMEOUT_MS)) {
			err = -ETIMEDOUT;
			goto error;
		}
	}

	return 0;
error:
	amdtp_domain_stop(&efw->domain);

	cmp_connection_break(&efw->out_conn);
	cmp_connection_break(&efw->in_conn);

	return err;
}

void snd_efw_stream_stop_duplex(struct snd_efw *efw)
{
	if (efw->substreams_counter == 0) {
		amdtp_domain_stop(&efw->domain);

		cmp_connection_break(&efw->out_conn);
		cmp_connection_break(&efw->in_conn);

		cmp_connection_release(&efw->out_conn);
		cmp_connection_release(&efw->in_conn);
	}
}

Annotation

Implementation Notes