sound/pci/oxygen/oxygen_lib.c
Source file repositories/reference/linux-study-clean/sound/pci/oxygen/oxygen_lib.c
File Facts
- System
- Linux kernel
- Corpus path
sound/pci/oxygen/oxygen_lib.c- Extension
.c- Size
- 24833 bytes
- Lines
- 798
- Domain
- Driver Families
- Bucket
- sound/pci
- 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/delay.hlinux/interrupt.hlinux/mutex.hlinux/pci.hlinux/slab.hlinux/module.hsound/ac97_codec.hsound/asoundef.hsound/core.hsound/info.hsound/mpu401.hsound/pcm.hoxygen.hcm9780.h
Detected Declarations
function oxygen_uart_input_readyfunction oxygen_read_uartfunction oxygen_interruptfunction scoped_guardfunction oxygen_spdif_input_bits_changedfunction oxygen_gpio_changedfunction oxygen_proc_readfunction oxygen_proc_initfunction oxygen_search_pci_idfunction oxygen_restore_eepromfunction configure_pcie_bridgefunction oxygen_initfunction oxygen_shutdownfunction oxygen_card_freefunction __oxygen_pci_probefunction scoped_guardfunction oxygen_pci_probefunction oxygen_pci_suspendfunction scoped_guardfunction is_bit_setfunction oxygen_restore_ac97function oxygen_pci_resumefunction oxygen_pci_shutdownexport oxygen_pci_probeexport oxygen_pci_shutdown
Annotated Snippet
if (clear) {
if (clear & OXYGEN_INT_SPDIF_IN_DETECT)
chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT;
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK,
chip->interrupt_mask & ~clear);
oxygen_write16(chip, OXYGEN_INTERRUPT_MASK,
chip->interrupt_mask);
}
elapsed_streams = status & chip->pcm_running;
}
for (i = 0; i < PCM_COUNT; ++i)
if ((elapsed_streams & (1 << i)) && chip->streams[i])
snd_pcm_period_elapsed(chip->streams[i]);
if (status & OXYGEN_INT_SPDIF_IN_DETECT) {
guard(spinlock)(&chip->reg_lock);
i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
if (i & (OXYGEN_SPDIF_SENSE_INT | OXYGEN_SPDIF_LOCK_INT |
OXYGEN_SPDIF_RATE_INT)) {
/* write the interrupt bit(s) to clear */
oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i);
schedule_work(&chip->spdif_input_bits_work);
}
}
if (status & OXYGEN_INT_GPIO)
schedule_work(&chip->gpio_work);
if (status & OXYGEN_INT_MIDI) {
if (chip->midi)
snd_mpu401_uart_interrupt(0, chip->midi->private_data);
else
oxygen_read_uart(chip);
}
if (status & OXYGEN_INT_AC97)
wake_up(&chip->ac97_waitqueue);
return IRQ_HANDLED;
}
static void oxygen_spdif_input_bits_changed(struct work_struct *work)
{
struct oxygen *chip = container_of(work, struct oxygen,
spdif_input_bits_work);
u32 reg;
/*
* This function gets called when there is new activity on the SPDIF
* input, or when we lose lock on the input signal, or when the rate
* changes.
*/
msleep(1);
scoped_guard(spinlock_irq, &chip->reg_lock) {
reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
if ((reg & (OXYGEN_SPDIF_SENSE_STATUS |
OXYGEN_SPDIF_LOCK_STATUS))
== OXYGEN_SPDIF_SENSE_STATUS) {
/*
* If we detect activity on the SPDIF input but cannot lock to
* a signal, the clock bit is likely to be wrong.
*/
reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK;
oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg);
spin_unlock_irq(&chip->reg_lock);
msleep(1);
spin_lock_irq(&chip->reg_lock);
reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL);
if ((reg & (OXYGEN_SPDIF_SENSE_STATUS |
OXYGEN_SPDIF_LOCK_STATUS))
== OXYGEN_SPDIF_SENSE_STATUS) {
/* nothing detected with either clock; give up */
if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK)
== OXYGEN_SPDIF_IN_CLOCK_192) {
/*
* Reset clock to <= 96 kHz because this is
* more likely to be received next time.
*/
reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK;
reg |= OXYGEN_SPDIF_IN_CLOCK_96;
oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg);
}
}
}
}
if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) {
scoped_guard(spinlock_irq, &chip->reg_lock) {
Annotation
- Immediate include surface: `linux/delay.h`, `linux/interrupt.h`, `linux/mutex.h`, `linux/pci.h`, `linux/slab.h`, `linux/module.h`, `sound/ac97_codec.h`, `sound/asoundef.h`.
- Detected declarations: `function oxygen_uart_input_ready`, `function oxygen_read_uart`, `function oxygen_interrupt`, `function scoped_guard`, `function oxygen_spdif_input_bits_changed`, `function oxygen_gpio_changed`, `function oxygen_proc_read`, `function oxygen_proc_init`, `function oxygen_search_pci_id`, `function oxygen_restore_eeprom`.
- Atlas domain: Driver Families / sound/pci.
- 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.