sound/hda/core/ext/stream.c

Source file repositories/reference/linux-study-clean/sound/hda/core/ext/stream.c

File Facts

System
Linux kernel
Corpus path
sound/hda/core/ext/stream.c
Extension
.c
Size
12664 bytes
Lines
449
Domain
Driver Families
Bucket
sound/hda
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

if (!hext_stream->link_locked) {
			res = hext_stream;
			break;
		}

	}
	if (res) {
		snd_hdac_ext_stream_decouple_locked(bus, res, true);
		res->link_locked = 1;
		res->link_substream = substream;
	}
	return res;
}

static struct hdac_ext_stream *
hdac_ext_host_dma_stream_assign(struct hdac_bus *bus,
				struct snd_pcm_substream *substream)
{
	struct hdac_ext_stream *res = NULL;
	struct hdac_stream *hstream = NULL;

	if (!bus->ppcap) {
		dev_err(bus->dev, "stream type not supported\n");
		return NULL;
	}

	guard(spinlock_irq)(&bus->reg_lock);
	list_for_each_entry(hstream, &bus->stream_list, list) {
		struct hdac_ext_stream *hext_stream = container_of(hstream,
								 struct hdac_ext_stream,
								 hstream);
		if (hstream->direction != substream->stream)
			continue;

		if (!hstream->opened) {
			res = hext_stream;
			break;
		}
	}
	if (res) {
		snd_hdac_ext_stream_decouple_locked(bus, res, true);
		res->hstream.opened = 1;
		res->hstream.running = 0;
		res->hstream.substream = substream;
	}

	return res;
}

/**
 * snd_hdac_ext_stream_assign - assign a stream for the PCM
 * @bus: HD-audio core bus
 * @substream: PCM substream to assign
 * @type: type of stream (coupled, host or link stream)
 *
 * This assigns the stream based on the type (coupled/host/link), for the
 * given PCM substream, assigns it and returns the stream object
 *
 * coupled: Looks for an unused stream
 * host: Looks for an unused decoupled host stream
 * link: Looks for an unused decoupled link stream
 *
 * If no stream is free, returns NULL. The function tries to keep using
 * the same stream object when it's used beforehand.  when a stream is
 * decoupled, it becomes a host stream and link stream.
 */
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
					   struct snd_pcm_substream *substream,
					   int type)
{
	struct hdac_ext_stream *hext_stream = NULL;
	struct hdac_stream *hstream = NULL;

	switch (type) {
	case HDAC_EXT_STREAM_TYPE_COUPLED:
		hstream = snd_hdac_stream_assign(bus, substream);
		if (hstream)
			hext_stream = container_of(hstream,
						   struct hdac_ext_stream,
						   hstream);
		return hext_stream;

	case HDAC_EXT_STREAM_TYPE_HOST:
		return hdac_ext_host_dma_stream_assign(bus, substream);

	case HDAC_EXT_STREAM_TYPE_LINK:
		return hdac_ext_link_dma_stream_assign(bus, substream);

	default:
		return NULL;

Annotation

Implementation Notes