sound/soc/codecs/cs35l56.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/cs35l56.c
Extension
.c
Size
62993 bytes
Lines
2160
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

if (slots == 0) {
			slots = params_channels(params);

			/* I2S always has an even number of slots */
			if (!cs35l56->tdm_mode)
				slots = round_up(slots, 2);
		}

		bclk_freq = asp_width * slots * rate;
		freq_id = cs35l56_get_bclk_freq_id(bclk_freq);
		if (freq_id < 0) {
			dev_err(cs35l56->base.dev, "%s: Invalid BCLK %u\n", __func__, bclk_freq);
			return -EINVAL;
		}

		regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1,
				   CS35L56_ASP_BCLK_FREQ_MASK,
				   freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT);
	}

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2,
				   CS35L56_ASP_RX_WIDTH_MASK, asp_width <<
				   CS35L56_ASP_RX_WIDTH_SHIFT);
		regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL5,
				   CS35L56_ASP_RX_WL_MASK, asp_wl);
	} else {
		regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL2,
				   CS35L56_ASP_TX_WIDTH_MASK, asp_width <<
				   CS35L56_ASP_TX_WIDTH_SHIFT);
		regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_DATA_CONTROL1,
				   CS35L56_ASP_TX_WL_MASK, asp_wl);
	}

	return 0;
}

static int cs35l56_asp_dai_set_sysclk(struct snd_soc_dai *dai,
				      int clk_id, unsigned int freq, int dir)
{
	struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);
	int freq_id;

	if (freq == 0) {
		cs35l56->sysclk_set = false;
		return 0;
	}

	freq_id = cs35l56_get_bclk_freq_id(freq);
	if (freq_id < 0)
		return freq_id;

	regmap_update_bits(cs35l56->base.regmap, CS35L56_ASP1_CONTROL1,
			   CS35L56_ASP_BCLK_FREQ_MASK,
			   freq_id << CS35L56_ASP_BCLK_FREQ_SHIFT);
	cs35l56->sysclk_set = true;

	return 0;
}

static const struct snd_soc_dai_ops cs35l56_ops = {
	.probe = cs35l56_asp_dai_probe,
	.set_fmt = cs35l56_asp_dai_set_fmt,
	.set_tdm_slot = cs35l56_asp_dai_set_tdm_slot,
	.hw_params = cs35l56_asp_dai_hw_params,
	.set_sysclk = cs35l56_asp_dai_set_sysclk,
};

static void cs35l56_sdw_dai_shutdown(struct snd_pcm_substream *substream,
				     struct snd_soc_dai *dai)
{
	snd_soc_dai_set_dma_data(dai, substream, NULL);
}

static int cs35l56_sdw_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
					unsigned int rx_mask, int slots, int slot_width)
{
	struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(dai->component);

	/* rx/tx are from point of view of the CPU end so opposite to our rx/tx */
	cs35l56->rx_mask = tx_mask;
	cs35l56->tx_mask = rx_mask;

	return 0;
}

static int cs35l56_sdw_dai_hw_params(struct snd_pcm_substream *substream,
				     struct snd_pcm_hw_params *params,
				     struct snd_soc_dai *dai)
{

Annotation

Implementation Notes