sound/soc/codecs/pcm1681.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/pcm1681.c
Extension
.c
Size
8931 bytes
Lines
335
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 pcm1681_private {
	struct regmap *regmap;
	unsigned int format;
	/* Current deemphasis status */
	unsigned int deemph;
	/* Current rate for deemphasis control */
	unsigned int rate;
};

static const int pcm1681_deemph[] = { 44100, 48000, 32000 };

static int pcm1681_set_deemph(struct snd_soc_component *component)
{
	struct pcm1681_private *priv = snd_soc_component_get_drvdata(component);
	int i, val = -1, enable = 0;

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

	if (val != -1) {
		regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
				   PCM1681_DEEMPH_RATE_MASK, val << 3);
		enable = 1;
	} else {
		enable = 0;
	}

	/* enable/disable deemphasis functionality */
	return regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
					PCM1681_DEEMPH_MASK, enable);
}

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

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

	return 0;
}

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

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

	return pcm1681_set_deemph(component);
}

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

	/* The PCM1681 can only be consumer 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;
	}

	priv->format = format;

	return 0;
}

static int pcm1681_mute(struct snd_soc_dai *dai, int mute, int direction)
{
	struct snd_soc_component *component = dai->component;
	struct pcm1681_private *priv = snd_soc_component_get_drvdata(component);
	int val;

	if (mute)
		val = PCM1681_SOFT_MUTE_ALL;
	else
		val = 0;

	return regmap_write(priv->regmap, PCM1681_SOFT_MUTE, val);
}

Annotation

Implementation Notes