sound/soc/codecs/cs47l92.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/cs47l92.c
Extension
.c
Size
75408 bytes
Lines
2104
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 cs47l92 {
	struct madera_priv core;
	struct madera_fll fll[2];
};

static const struct cs_dsp_region cs47l92_dsp1_regions[] = {
	{ .type = WMFW_ADSP2_PM, .base = 0x080000 },
	{ .type = WMFW_ADSP2_ZM, .base = 0x0e0000 },
	{ .type = WMFW_ADSP2_XM, .base = 0x0a0000 },
	{ .type = WMFW_ADSP2_YM, .base = 0x0c0000 },
};

static const char * const cs47l92_outdemux_texts[] = {
	"HPOUT3",
	"HPOUT4",
};

static int cs47l92_put_demux(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_component *component = snd_soc_dapm_kcontrol_to_component(kcontrol);
	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
	struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component);
	struct madera_priv *priv = &cs47l92->core;
	struct madera *madera = priv->madera;
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	unsigned int ep_sel, mux, change, cur;
	bool out_mono;
	int ret;

	if (ucontrol->value.enumerated.item[0] > e->items - 1)
		return -EINVAL;

	mux = ucontrol->value.enumerated.item[0];

	snd_soc_dapm_mutex_lock(dapm);

	ep_sel = mux << e->shift_l;

	change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1,
					     MADERA_EP_SEL_MASK,
					     ep_sel);
	if (!change)
		goto end;

	ret = regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &cur);
	if (ret != 0)
		dev_warn(madera->dev, "Failed to read outputs: %d\n", ret);

	/* EP_SEL should not be modified while HPOUT3 or 4 is enabled */
	ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
				 MADERA_OUT3L_ENA | MADERA_OUT3R_ENA, 0);
	if (ret)
		dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret);

	usleep_range(2000, 3000); /* wait for wseq to complete */

	ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
				 MADERA_EP_SEL, ep_sel);
	if (ret) {
		dev_err(madera->dev, "Failed to set OUT3 demux: %d\n", ret);
	} else {
		out_mono = madera->pdata.codec.out_mono[2 + mux];

		ret = madera_set_output_mode(component, 3, out_mono);
		if (ret < 0)
			dev_warn(madera->dev,
				 "Failed to set output mode: %d\n", ret);
	}

	ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
				 MADERA_OUT3L_ENA | MADERA_OUT3R_ENA, cur);
	if (ret) {
		dev_warn(madera->dev, "Failed to restore outputs: %d\n", ret);
	} else {
		/* wait for wseq */
		if (cur & (MADERA_OUT3L_ENA | MADERA_OUT3R_ENA))
			msleep(34); /* enable delay */
		else
			usleep_range(2000, 3000); /* disable delay */
	}

end:
	snd_soc_dapm_mutex_unlock(dapm);

	ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
	if (ret < 0) {
		dev_err(madera->dev, "Failed to update demux power state: %d\n", ret);
		return ret;
	}

Annotation

Implementation Notes