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.

Dependency Surface

Detected Declarations

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

Implementation Notes