sound/aoa/soundbus/i2sbus/pcm.c
Source file repositories/reference/linux-study-clean/sound/aoa/soundbus/i2sbus/pcm.c
File Facts
- System
- Linux kernel
- Corpus path
sound/aoa/soundbus/i2sbus/pcm.c- Extension
.c- Size
- 27694 bytes
- Lines
- 1042
- Domain
- Driver Families
- Bucket
- sound/aoa
- 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.
- 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.
- 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/io.hlinux/delay.hlinux/slab.hsound/core.hasm/macio.hlinux/pci.hlinux/module.h../soundbus.hi2sbus.h
Detected Declarations
function get_pcm_infofunction clock_and_divisorsfunction i2sbus_pcm_openfunction i2sbus_pcm_preparefunction list_for_each_entry_reversefunction i2sbus_pcm_closefunction list_for_each_entryfunction i2sbus_wait_for_stopfunction i2sbus_wait_for_stop_bothfunction i2sbus_pcm_clear_activefunction i2sbus_hw_paramsfunction i2sbus_hw_freefunction i2sbus_playback_hw_paramsfunction i2sbus_playback_hw_freefunction i2sbus_record_hw_paramsfunction i2sbus_record_hw_freefunction i2sbus_pcm_preparefunction list_for_each_entryfunction in_le32function i2sbus_pcm_prepare_bothfunction i2sbus_pcm_triggerfunction i2sbus_pcm_pointerfunction handle_interruptfunction scoped_guardfunction i2sbus_tx_intrfunction i2sbus_rx_intrfunction i2sbus_playback_openfunction i2sbus_playback_closefunction i2sbus_playback_preparefunction i2sbus_playback_triggerfunction i2sbus_playback_pointerfunction i2sbus_record_openfunction i2sbus_record_closefunction i2sbus_record_preparefunction i2sbus_record_triggerfunction i2sbus_record_pointerfunction i2sbus_private_freefunction i2sbus_attach_codecfunction list_for_each_entryfunction i2sbus_detach_codecfunction list_for_each_entry
Annotated Snippet
if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) {
*out |= I2S_SF_CLOCK_SOURCE_18MHz;
return 0;
}
}
if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) {
if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) {
*out |= I2S_SF_CLOCK_SOURCE_45MHz;
return 0;
}
}
if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) {
if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) {
*out |= I2S_SF_CLOCK_SOURCE_49MHz;
return 0;
}
}
return -1;
}
#define CHECK_RATE(rate) \
do { if (rates & SNDRV_PCM_RATE_ ##rate) { \
int dummy; \
if (clock_and_divisors(sysclock_factor, \
bus_factor, rate, &dummy)) \
rates &= ~SNDRV_PCM_RATE_ ##rate; \
} } while (0)
static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
{
struct pcm_info *pi, *other;
struct soundbus_dev *sdev;
int masks_inited = 0, err;
struct codec_info_item *cii, *rev;
struct snd_pcm_hardware *hw;
u64 formats = 0;
unsigned int rates = 0;
struct transfer_info v;
int bus_factor = 0, sysclock_factor = 0;
int found_this;
guard(mutex)(&i2sdev->lock);
get_pcm_info(i2sdev, in, &pi, &other);
hw = &pi->substream->runtime->hw;
sdev = &i2sdev->sound;
if (pi->active) {
/* alsa messed up */
return -EBUSY;
}
/* we now need to assign the hw */
list_for_each_entry(cii, &sdev->codec_list, list) {
struct transfer_info *ti = cii->codec->transfers;
bus_factor = cii->codec->bus_factor;
sysclock_factor = cii->codec->sysclock_factor;
while (ti->formats && ti->rates) {
v = *ti;
if (ti->transfer_in == in
&& cii->codec->usable(cii, ti, &v)) {
if (masks_inited) {
formats &= v.formats;
rates &= v.rates;
} else {
formats = v.formats;
rates = v.rates;
masks_inited = 1;
}
}
ti++;
}
}
if (!masks_inited || !bus_factor || !sysclock_factor)
return -ENODEV;
/* bus dependent stuff */
hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_JOINT_DUPLEX;
CHECK_RATE(5512);
CHECK_RATE(8000);
CHECK_RATE(11025);
CHECK_RATE(16000);
CHECK_RATE(22050);
CHECK_RATE(32000);
CHECK_RATE(44100);
CHECK_RATE(48000);
CHECK_RATE(64000);
Annotation
- Immediate include surface: `linux/io.h`, `linux/delay.h`, `linux/slab.h`, `sound/core.h`, `asm/macio.h`, `linux/pci.h`, `linux/module.h`, `../soundbus.h`.
- Detected declarations: `function get_pcm_info`, `function clock_and_divisors`, `function i2sbus_pcm_open`, `function i2sbus_pcm_prepare`, `function list_for_each_entry_reverse`, `function i2sbus_pcm_close`, `function list_for_each_entry`, `function i2sbus_wait_for_stop`, `function i2sbus_wait_for_stop_both`, `function i2sbus_pcm_clear_active`.
- Atlas domain: Driver Families / sound/aoa.
- Implementation status: source 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.