sound/soc/codecs/wm8990.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/wm8990.c
Extension
.c
Size
39571 bytes
Lines
1262
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 wm8990_priv {
	struct regmap *regmap;
	unsigned int sysclk;
	unsigned int pcmclk;
};

#define wm8990_reset(c) snd_soc_component_write(c, WM8990_RESET, 0)

static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1650, 3000, 0);

static const DECLARE_TLV_DB_SCALE(out_mix_tlv, 0, -2100, 0);

static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -7300, 600, 0);

static const DECLARE_TLV_DB_SCALE(out_dac_tlv, -7163, 0, 0);

static const DECLARE_TLV_DB_SCALE(in_adc_tlv, -7163, 1763, 0);

static const DECLARE_TLV_DB_SCALE(out_sidetone_tlv, -3600, 0, 0);

static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
	struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	struct soc_mixer_control *mc =
		(struct soc_mixer_control *)kcontrol->private_value;
	int reg = mc->reg;
	int ret;
	u16 val;

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

	/* now hit the volume update bits (always bit 8) */
	val = snd_soc_component_read(component, reg);
	return snd_soc_component_write(component, reg, val | 0x0100);
}

#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
	tlv_array) \
	SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \
		snd_soc_get_volsw, wm899x_outpga_put_volsw_vu, tlv_array)


static const char *wm8990_digital_sidetone[] =
	{"None", "Left ADC", "Right ADC", "Reserved"};

static SOC_ENUM_SINGLE_DECL(wm8990_left_digital_sidetone_enum,
			    WM8990_DIGITAL_SIDE_TONE,
			    WM8990_ADC_TO_DACL_SHIFT,
			    wm8990_digital_sidetone);

static SOC_ENUM_SINGLE_DECL(wm8990_right_digital_sidetone_enum,
			    WM8990_DIGITAL_SIDE_TONE,
			    WM8990_ADC_TO_DACR_SHIFT,
			    wm8990_digital_sidetone);

static const char *wm8990_adcmode[] =
	{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};

static SOC_ENUM_SINGLE_DECL(wm8990_right_adcmode_enum,
			    WM8990_ADC_CTRL,
			    WM8990_ADC_HPF_CUT_SHIFT,
			    wm8990_adcmode);

static const struct snd_kcontrol_new wm8990_snd_controls[] = {
/* INMIXL */
SOC_SINGLE("LIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L12MNBST_BIT, 1, 0),
SOC_SINGLE("LIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L34MNBST_BIT, 1, 0),
/* INMIXR */
SOC_SINGLE("RIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R12MNBST_BIT, 1, 0),
SOC_SINGLE("RIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R34MNBST_BIT, 1, 0),

/* LOMIX */
SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER3,
	WM8990_LLI3LOVOL_SHIFT, WM8990_LLI3LOVOL_MASK, 1, out_mix_tlv),
SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
	WM8990_LR12LOVOL_SHIFT, WM8990_LR12LOVOL_MASK, 1, out_mix_tlv),
SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
	WM8990_LL12LOVOL_SHIFT, WM8990_LL12LOVOL_MASK, 1, out_mix_tlv),
SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER5,
	WM8990_LRI3LOVOL_SHIFT, WM8990_LRI3LOVOL_MASK, 1, out_mix_tlv),
SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
	WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),
SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
	WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),

/* ROMIX */
SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER4,

Annotation

Implementation Notes