sound/pci/ice1712/wm8766.c
Source file repositories/reference/linux-study-clean/sound/pci/ice1712/wm8766.c
File Facts
- System
- Linux kernel
- Corpus path
sound/pci/ice1712/wm8766.c- Extension
.c- Size
- 9098 bytes
- Lines
- 333
- Domain
- Driver Families
- Bucket
- sound/pci
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/delay.hsound/core.hsound/control.hsound/tlv.hwm8766.h
Detected Declarations
function Copyrightfunction snd_wm8766_initfunction snd_wm8766_resumefunction snd_wm8766_set_iffunction snd_wm8766_volume_restorefunction snd_wm8766_volume_infofunction snd_wm8766_enum_infofunction snd_wm8766_ctl_getfunction snd_wm8766_ctl_putfunction snd_wm8766_add_controlfunction snd_wm8766_build_controls
Annotated Snippet
if (wm->ctl[n].flags & WM8766_FLAG_STEREO) {
val2 = wm->regs[wm->ctl[n].reg2] & wm->ctl[n].mask2;
val2 >>= __ffs(wm->ctl[n].mask2);
if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
val2 &= ~WM8766_VOL_UPDATE;
}
}
if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
if (wm->ctl[n].flags & WM8766_FLAG_STEREO)
val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
}
ucontrol->value.integer.value[0] = val1;
if (wm->ctl[n].flags & WM8766_FLAG_STEREO)
ucontrol->value.integer.value[1] = val2;
return 0;
}
static int snd_wm8766_ctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_wm8766 *wm = snd_kcontrol_chip(kcontrol);
int n = kcontrol->private_value;
u16 val, regval1, regval2;
/* this also works for enum because value is a union */
regval1 = ucontrol->value.integer.value[0];
regval2 = ucontrol->value.integer.value[1];
if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
regval1 = wm->ctl[n].max - (regval1 - wm->ctl[n].min);
regval2 = wm->ctl[n].max - (regval2 - wm->ctl[n].min);
}
if (wm->ctl[n].set)
wm->ctl[n].set(wm, regval1, regval2);
else {
val = wm->regs[wm->ctl[n].reg1] & ~wm->ctl[n].mask1;
val |= regval1 << __ffs(wm->ctl[n].mask1);
/* both stereo controls in one register */
if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
wm->ctl[n].reg1 == wm->ctl[n].reg2) {
val &= ~wm->ctl[n].mask2;
val |= regval2 << __ffs(wm->ctl[n].mask2);
}
snd_wm8766_write(wm, wm->ctl[n].reg1, val);
/* stereo controls in different registers */
if (wm->ctl[n].flags & WM8766_FLAG_STEREO &&
wm->ctl[n].reg1 != wm->ctl[n].reg2) {
val = wm->regs[wm->ctl[n].reg2] & ~wm->ctl[n].mask2;
val |= regval2 << __ffs(wm->ctl[n].mask2);
if (wm->ctl[n].flags & WM8766_FLAG_VOL_UPDATE)
val |= WM8766_VOL_UPDATE;
snd_wm8766_write(wm, wm->ctl[n].reg2, val);
}
}
return 0;
}
static int snd_wm8766_add_control(struct snd_wm8766 *wm, int num)
{
struct snd_kcontrol_new cont;
struct snd_kcontrol *ctl;
memset(&cont, 0, sizeof(cont));
cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
cont.private_value = num;
cont.name = wm->ctl[num].name;
cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
if (wm->ctl[num].flags & WM8766_FLAG_LIM ||
wm->ctl[num].flags & WM8766_FLAG_ALC)
cont.access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
cont.tlv.p = NULL;
cont.get = snd_wm8766_ctl_get;
cont.put = snd_wm8766_ctl_put;
switch (wm->ctl[num].type) {
case SNDRV_CTL_ELEM_TYPE_INTEGER:
cont.info = snd_wm8766_volume_info;
cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
cont.tlv.p = wm->ctl[num].tlv;
break;
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
wm->ctl[num].max = 1;
if (wm->ctl[num].flags & WM8766_FLAG_STEREO)
cont.info = snd_ctl_boolean_stereo_info;
else
cont.info = snd_ctl_boolean_mono_info;
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
Annotation
- Immediate include surface: `linux/delay.h`, `sound/core.h`, `sound/control.h`, `sound/tlv.h`, `wm8766.h`.
- Detected declarations: `function Copyright`, `function snd_wm8766_init`, `function snd_wm8766_resume`, `function snd_wm8766_set_if`, `function snd_wm8766_volume_restore`, `function snd_wm8766_volume_info`, `function snd_wm8766_enum_info`, `function snd_wm8766_ctl_get`, `function snd_wm8766_ctl_put`, `function snd_wm8766_add_control`.
- Atlas domain: Driver Families / sound/pci.
- Implementation status: source implementation candidate.
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.