sound/soc/codecs/wm8960.c
Source file repositories/reference/linux-study-clean/sound/soc/codecs/wm8960.c
File Facts
- System
- Linux kernel
- Corpus path
sound/soc/codecs/wm8960.c- Extension
.c- Size
- 44618 bytes
- Lines
- 1592
- Domain
- Driver Families
- Bucket
- sound/soc
- 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.
- 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/module.hlinux/moduleparam.hlinux/init.hlinux/delay.hlinux/pm.hlinux/clk.hlinux/i2c.hlinux/acpi.hlinux/slab.hsound/core.hsound/pcm.hsound/pcm_params.hsound/soc.hsound/initval.hsound/tlv.hsound/wm8960.hwm8960.h
Detected Declarations
struct wm8960_privstruct _pll_divfunction wm8960_volatilefunction wm8960_set_deemphfunction wm8960_get_deemphfunction wm8960_put_deemphfunction wm8960_add_widgetsfunction wm8960_set_dai_fmtfunction wm8960_configure_sysclkfunction wm8960_configure_clockingfunction wm8960_hw_paramsfunction wm8960_hw_freefunction wm8960_mutefunction wm8960_set_bias_level_out3function wm8960_set_bias_level_caplessfunction is_pll_freq_availablefunction pll_factorsfunction wm8960_set_pllfunction wm8960_set_dai_pllfunction wm8960_set_dai_clkdivfunction wm8960_set_bias_levelfunction wm8960_set_dai_sysclkfunction wm8960_probefunction wm8960_set_pdata_from_offunction wm8960_i2c_probefunction wm8960_i2c_remove
Annotated Snippet
struct wm8960_priv {
struct clk *mclk;
struct regmap *regmap;
int (*set_bias_level)(struct snd_soc_component *,
enum snd_soc_bias_level level);
struct snd_soc_dapm_widget *lout1;
struct snd_soc_dapm_widget *rout1;
struct snd_soc_dapm_widget *out3;
bool deemph;
int lrclk;
int bclk;
int sysclk;
int clk_id;
int freq_in;
bool is_stream_in_use[2];
struct wm8960_data pdata;
ktime_t dsch_start;
struct regulator_bulk_data supplies[WM8960_NUM_SUPPLIES];
};
#define wm8960_reset(c) regmap_write(c, WM8960_RESET, 0)
/* enumerated controls */
static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",
"Right Inverted", "Stereo Inversion"};
static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};
static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};
static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};
static const char *wm8960_alcmode[] = {"ALC", "Limiter"};
static const char *wm8960_adc_data_output_sel[] = {
"Left Data = Left ADC; Right Data = Right ADC",
"Left Data = Left ADC; Right Data = Left ADC",
"Left Data = Right ADC; Right Data = Right ADC",
"Left Data = Right ADC; Right Data = Left ADC",
};
static const char *wm8960_dmonomix[] = {"Stereo", "Mono"};
static const char *wm8960_dacslope[] = {"Normal", "Sloping"};
static const struct soc_enum wm8960_enum[] = {
SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),
SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),
SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),
SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),
SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),
SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),
SOC_ENUM_SINGLE(WM8960_ADDCTL1, 2, 4, wm8960_adc_data_output_sel),
SOC_ENUM_SINGLE(WM8960_ADDCTL1, 4, 2, wm8960_dmonomix),
SOC_ENUM_SINGLE(WM8960_DACCTL2, 1, 2, wm8960_dacslope),
};
static const int deemph_settings[] = { 0, 32000, 44100, 48000 };
static int wm8960_set_deemph(struct snd_soc_component *component)
{
struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);
int val, i, best;
/* If we're using deemphasis select the nearest available sample
* rate.
*/
if (wm8960->deemph) {
best = 1;
for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) {
if (abs(deemph_settings[i] - wm8960->lrclk) <
abs(deemph_settings[best] - wm8960->lrclk))
best = i;
}
val = best << 1;
} else {
val = 0;
}
dev_dbg(component->dev, "Set deemphasis %d\n", val);
return snd_soc_component_update_bits(component, WM8960_DACCTL1,
0x6, val);
}
static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = wm8960->deemph;
return 0;
}
static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
Annotation
- Immediate include surface: `linux/module.h`, `linux/moduleparam.h`, `linux/init.h`, `linux/delay.h`, `linux/pm.h`, `linux/clk.h`, `linux/i2c.h`, `linux/acpi.h`.
- Detected declarations: `struct wm8960_priv`, `struct _pll_div`, `function wm8960_volatile`, `function wm8960_set_deemph`, `function wm8960_get_deemph`, `function wm8960_put_deemph`, `function wm8960_add_widgets`, `function wm8960_set_dai_fmt`, `function wm8960_configure_sysclk`, `function wm8960_configure_clocking`.
- Atlas domain: Driver Families / sound/soc.
- 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.