sound/soc/codecs/wm8580.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/wm8580.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/wm8580.c
Extension
.c
Size
28102 bytes
Lines
1058
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pll_state {
	unsigned int in;
	unsigned int out;
};

#define WM8580_NUM_SUPPLIES 3
static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
	"AVDD",
	"DVDD",
	"PVDD",
};

struct wm8580_driver_data {
	int num_dacs;
};

/* codec private data */
struct wm8580_priv {
	struct regmap *regmap;
	struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
	struct pll_state a;
	struct pll_state b;
	const struct wm8580_driver_data *drvdata;
	int sysclk[2];
};

static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);

static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
			 struct snd_ctl_elem_value *ucontrol)
{
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	struct wm8580_priv *wm8580 = snd_soc_component_get_drvdata(component);
	unsigned int reg = mc->reg;
	unsigned int reg2 = mc->rreg;
	int ret;

	/* Clear the register cache VU so we write without VU set */
	regcache_cache_only(wm8580->regmap, true);
	regmap_update_bits(wm8580->regmap, reg, 0x100, 0x000);
	regmap_update_bits(wm8580->regmap, reg2, 0x100, 0x000);
	regcache_cache_only(wm8580->regmap, false);

	ret = snd_soc_put_volsw(kcontrol, ucontrol);
	if (ret < 0)
		return ret;

	/* Now write again with the volume update bit set */
	snd_soc_component_update_bits(component, reg, 0x100, 0x100);
	snd_soc_component_update_bits(component, reg2, 0x100, 0x100);

	return 0;
}

static const struct snd_kcontrol_new wm8580_snd_controls[] = {
SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume",
		     WM8580_DIGITAL_ATTENUATION_DACL1,
		     WM8580_DIGITAL_ATTENUATION_DACR1,
		     0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume",
		     WM8580_DIGITAL_ATTENUATION_DACL2,
		     WM8580_DIGITAL_ATTENUATION_DACR2,
		     0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume",
		     WM8580_DIGITAL_ATTENUATION_DACL3,
		     WM8580_DIGITAL_ATTENUATION_DACR3,
		     0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),

SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),
SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),
SOC_SINGLE("DAC3 Deemphasis Switch", WM8580_DAC_CONTROL3, 2, 1, 0),

SOC_DOUBLE("DAC1 Invert Switch", WM8580_DAC_CONTROL4,  0, 1, 1, 0),
SOC_DOUBLE("DAC2 Invert Switch", WM8580_DAC_CONTROL4,  2, 3, 1, 0),
SOC_DOUBLE("DAC3 Invert Switch", WM8580_DAC_CONTROL4,  4, 5, 1, 0),

SOC_SINGLE("DAC ZC Switch", WM8580_DAC_CONTROL5, 5, 1, 0),
SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1),
SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1),
SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1),

SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1),
SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
};

static const struct snd_kcontrol_new wm8581_snd_controls[] = {
SOC_DOUBLE_R_EXT_TLV("DAC4 Playback Volume",
		     WM8581_DIGITAL_ATTENUATION_DACL4,

Annotation

Implementation Notes