sound/soc/codecs/es8328.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/es8328.c
Extension
.c
Size
25140 bytes
Lines
917
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 es8328_priv {
	struct regmap *regmap;
	struct clk *clk;
	int playback_fs;
	bool deemph;
	int mclkdiv2;
	const struct snd_pcm_hw_constraint_list *sysclk_constraints;
	const int *mclk_ratios;
	bool provider;
	struct regulator_bulk_data supplies[ES8328_SUPPLY_NUM];
};

/*
 * ES8328 Controls
 */

static const char * const adcpol_txt[] = {"Normal", "L Invert", "R Invert",
					  "L + R Invert"};
static SOC_ENUM_SINGLE_DECL(adcpol,
			    ES8328_ADCCONTROL6, 6, adcpol_txt);

static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0);
static const DECLARE_TLV_DB_SCALE(dac_adc_tlv, -9600, 50, 0);
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0);

static const struct {
	int rate;
	unsigned int val;
} deemph_settings[] = {
	{ 0,     ES8328_DACCONTROL6_DEEMPH_OFF },
	{ 32000, ES8328_DACCONTROL6_DEEMPH_32k },
	{ 44100, ES8328_DACCONTROL6_DEEMPH_44_1k },
	{ 48000, ES8328_DACCONTROL6_DEEMPH_48k },
};

static int es8328_set_deemph(struct snd_soc_component *component)
{
	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
	int val, i, best;

	/*
	 * If we're using deemphasis select the nearest available sample
	 * rate.
	 */
	if (es8328->deemph) {
		best = 0;
		for (i = 1; i < ARRAY_SIZE(deemph_settings); i++) {
			if (abs(deemph_settings[i].rate - es8328->playback_fs) <
			    abs(deemph_settings[best].rate - es8328->playback_fs))
				best = i;
		}

		val = deemph_settings[best].val;
	} else {
		val = ES8328_DACCONTROL6_DEEMPH_OFF;
	}

	dev_dbg(component->dev, "Set deemphasis %d\n", val);

	return snd_soc_component_update_bits(component, ES8328_DACCONTROL6,
			ES8328_DACCONTROL6_DEEMPH_MASK, val);
}

static int es8328_get_deemph(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);

	ucontrol->value.integer.value[0] = es8328->deemph;
	return 0;
}

static int es8328_put_deemph(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	struct es8328_priv *es8328 = snd_soc_component_get_drvdata(component);
	unsigned int deemph = ucontrol->value.integer.value[0];
	int ret;

	if (deemph > 1)
		return -EINVAL;

	if (es8328->deemph == deemph)
		return 0;

	es8328->deemph = deemph;
	ret = es8328_set_deemph(component);

Annotation

Implementation Notes