sound/soc/codecs/cs42l43.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/cs42l43.c
Extension
.c
Size
99282 bytes
Lines
2967
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 cs42l43_pll_config {
	unsigned int freq;

	unsigned int div;
	unsigned int mode;
	unsigned int cal;
};

static const struct cs42l43_pll_config cs42l43_pll_configs[] = {
	{ 2400000, 0x50000000, 0x1, 0xA4 },
	{ 3000000, 0x40000000, 0x1, 0x83 },
	{ 3072000, 0x40000000, 0x3, 0x80 },
};

static int cs42l43_set_pll(struct cs42l43_codec *priv, unsigned int src,
			   unsigned int freq)
{
	struct cs42l43 *cs42l43 = priv->core;

	lockdep_assert_held(&cs42l43->pll_lock);

	if (priv->refclk_src == src && priv->refclk_freq == freq)
		return 0;

	if (regmap_test_bits(cs42l43->regmap, CS42L43_CTRL_REG, CS42L43_PLL_EN_MASK)) {
		dev_err(priv->dev, "PLL active, can't change configuration\n");
		return -EBUSY;
	}

	switch (src) {
	case CS42L43_SYSCLK_MCLK:
	case CS42L43_SYSCLK_SDW:
		dev_dbg(priv->dev, "Source PLL from %s at %uHz\n",
			src ? "SoundWire" : "MCLK", freq);

		priv->refclk_src = src;
		priv->refclk_freq = freq;

		return 0;
	default:
		dev_err(priv->dev, "Invalid PLL source: 0x%x\n", src);
		return -EINVAL;
	}
}

static int cs42l43_enable_pll(struct cs42l43_codec *priv)
{
	static const struct reg_sequence enable_seq[] = {
		{ CS42L43_OSC_DIV_SEL, 0x0, },
		{ CS42L43_MCLK_SRC_SEL, CS42L43_OSC_PLL_MCLK_SEL_MASK, 5, },
	};
	struct cs42l43 *cs42l43 = priv->core;
	const struct cs42l43_pll_config *config = NULL;
	unsigned int div = 0;
	unsigned int freq = priv->refclk_freq;
	unsigned long time_left;

	lockdep_assert_held(&cs42l43->pll_lock);

	if (priv->refclk_src == CS42L43_SYSCLK_SDW) {
		if (!freq)
			freq = cs42l43->sdw_freq;
		else if (!cs42l43->sdw_freq)
			cs42l43->sdw_freq = freq;
	}

	dev_dbg(priv->dev, "Enabling PLL at %uHz\n", freq);

	div = fls(freq) -
	      fls(cs42l43_pll_configs[ARRAY_SIZE(cs42l43_pll_configs) - 1].freq);
	freq >>= div;

	if (div <= CS42L43_PLL_REFCLK_DIV_MASK) {
		int i;

		for (i = 0; i < ARRAY_SIZE(cs42l43_pll_configs); i++) {
			if (freq == cs42l43_pll_configs[i].freq) {
				config = &cs42l43_pll_configs[i];
				break;
			}
		}
	}

	if (!config) {
		dev_err(priv->dev, "No suitable PLL config: 0x%x, %uHz\n", div, freq);
		return -EINVAL;
	}

	regmap_update_bits(cs42l43->regmap, CS42L43_PLL_CONTROL,
			   CS42L43_PLL_REFCLK_DIV_MASK | CS42L43_PLL_REFCLK_SRC_MASK,

Annotation

Implementation Notes