sound/hda/common/controller.c
Source file repositories/reference/linux-study-clean/sound/hda/common/controller.c
File Facts
- System
- Linux kernel
- Corpus path
sound/hda/common/controller.c- Extension
.c- Size
- 35168 bytes
- Lines
- 1309
- 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.
- 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clocksource.hlinux/delay.hlinux/interrupt.hlinux/kernel.hlinux/module.hlinux/pm_runtime.hlinux/slab.hasm/tsc.hsound/core.hsound/initval.hsound/pcm_params.hhda_controller.hhda_local.hcontroller_trace.h
Detected Declarations
function Copyrightfunction azx_release_devicefunction to_hda_pcm_streamfunction azx_adjust_codec_delayfunction azx_pcm_closefunction azx_pcm_hw_paramsfunction azx_pcm_hw_freefunction azx_pcm_preparefunction azx_pcm_triggerfunction snd_pcm_group_for_each_entryfunction scoped_guardfunction snd_pcm_group_for_each_entryfunction azx_get_pos_lpibfunction azx_get_pos_posbuffunction azx_get_positionfunction azx_pcm_pointerfunction afterfunction azx_get_sync_timefunction azx_get_sync_timefunction azx_get_crosststampfunction is_link_time_supportedfunction azx_get_time_infofunction azx_pcm_openfunction snd_BUG_ONfunction azx_pcm_freefunction snd_hda_attach_pcm_streamfunction list_for_each_entryfunction azx_command_addrfunction azx_rirb_get_responsefunction azx_single_wait_for_responsefunction azx_single_send_cmdfunction azx_single_get_responsefunction azx_send_cmdfunction azx_get_responsefunction codefunction snd_hda_codec_load_dsp_preparefunction snd_hda_codec_load_dsp_triggerfunction snd_hda_codec_load_dsp_cleanupfunction azx_init_chipfunction azx_stop_all_streamsfunction azx_stop_chipfunction stream_updatefunction azx_interruptfunction probe_codecfunction scoped_guardfunction snd_hda_bus_resetfunction azx_bus_initfunction azx_probe_codecs
Annotated Snippet
snd_pcm_group_for_each_entry(s, substream) {
if (s->pcm->card != substream->pcm->card)
continue;
azx_dev = get_azx_dev(s);
if (start) {
azx_dev->insufficient = 1;
snd_hdac_stream_start(azx_stream(azx_dev));
} else {
snd_hdac_stream_stop(azx_stream(azx_dev));
}
}
}
snd_hdac_stream_sync(hstr, start, sbits);
guard(spinlock)(&bus->reg_lock);
/* reset SYNC bits */
snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg);
snd_hdac_stream_timecounter_init(hstr, sbits, start);
return 0;
}
unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
{
return snd_hdac_stream_get_pos_lpib(azx_stream(azx_dev));
}
EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
{
return snd_hdac_stream_get_pos_posbuf(azx_stream(azx_dev));
}
EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
unsigned int azx_get_position(struct azx *chip,
struct azx_dev *azx_dev)
{
struct snd_pcm_substream *substream = azx_dev->core.substream;
unsigned int pos;
int stream = substream->stream;
int delay = 0;
if (chip->get_position[stream])
pos = chip->get_position[stream](chip, azx_dev);
else /* use the position buffer as default */
pos = azx_get_pos_posbuf(chip, azx_dev);
if (pos >= azx_dev->core.bufsize)
pos = 0;
if (substream->runtime) {
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
if (chip->get_delay[stream])
delay += chip->get_delay[stream](chip, azx_dev, pos);
if (hinfo->ops.get_delay)
delay += hinfo->ops.get_delay(hinfo, apcm->codec,
substream);
substream->runtime->delay = delay;
}
trace_azx_get_position(chip, azx_dev, pos, delay);
return pos;
}
EXPORT_SYMBOL_GPL(azx_get_position);
static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
return bytes_to_frames(substream->runtime,
azx_get_position(chip, azx_dev));
}
/*
* azx_scale64: Scale base by mult/div while not overflowing sanely
*
* Derived from scale64_check_overflow in kernel/time/timekeeping.c
*
* The tmestamps for a 48Khz stream can overflow after (2^64/10^9)/48K which
* is about 384307 ie ~4.5 days.
*
* This scales the calculation so that overflow will happen but after 2^64 /
* 48000 secs, which is pretty large!
*
* In caln below:
* base may overflow, but since there isn’t any additional division
* performed on base it’s OK
Annotation
- Immediate include surface: `linux/clocksource.h`, `linux/delay.h`, `linux/interrupt.h`, `linux/kernel.h`, `linux/module.h`, `linux/pm_runtime.h`, `linux/slab.h`, `asm/tsc.h`.
- Detected declarations: `function Copyright`, `function azx_release_device`, `function to_hda_pcm_stream`, `function azx_adjust_codec_delay`, `function azx_pcm_close`, `function azx_pcm_hw_params`, `function azx_pcm_hw_free`, `function azx_pcm_prepare`, `function azx_pcm_trigger`, `function snd_pcm_group_for_each_entry`.
- Atlas domain: Driver Families / sound/hda.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.