sound/soc/codecs/tas5086.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/tas5086.c
Extension
.c
Size
28630 bytes
Lines
992
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 tas5086_private {
	struct regmap	*regmap;
	unsigned int	mclk, sclk;
	unsigned int	format;
	bool		deemph;
	unsigned int	charge_period;
	unsigned int	pwm_start_mid_z;
	/* Current sample rate for de-emphasis control */
	int		rate;
	/* GPIO driving Reset pin, if any */
	struct gpio_desc *reset;
	struct		regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
};

static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };

static int tas5086_set_deemph(struct snd_soc_component *component)
{
	struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
	int i, val = 0;

	if (priv->deemph) {
		for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++) {
			if (tas5086_deemph[i] == priv->rate) {
				val = i;
				break;
			}
		}
	}

	return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1,
				  TAS5086_DEEMPH_MASK, val);
}

static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	struct tas5086_private *priv = snd_soc_component_get_drvdata(component);

	ucontrol->value.integer.value[0] = priv->deemph;

	return 0;
}

static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
	struct tas5086_private *priv = snd_soc_component_get_drvdata(component);

	priv->deemph = ucontrol->value.integer.value[0];

	return tas5086_set_deemph(component);
}


static int tas5086_set_dai_sysclk(struct snd_soc_dai *codec_dai,
				  int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_component *component = codec_dai->component;
	struct tas5086_private *priv = snd_soc_component_get_drvdata(component);

	switch (clk_id) {
	case TAS5086_CLK_IDX_MCLK:
		priv->mclk = freq;
		break;
	case TAS5086_CLK_IDX_SCLK:
		priv->sclk = freq;
		break;
	}

	return 0;
}

static int tas5086_set_dai_fmt(struct snd_soc_dai *codec_dai,
			       unsigned int format)
{
	struct snd_soc_component *component = codec_dai->component;
	struct tas5086_private *priv = snd_soc_component_get_drvdata(component);

	/* The TAS5086 can only be slave to all clocks */
	if ((format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) {
		dev_err(component->dev, "Invalid clocking mode\n");
		return -EINVAL;
	}

	/* we need to refer to the data format from hw_params() */
	priv->format = format;

Annotation

Implementation Notes