sound/soc/codecs/nau8824.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/nau8824.c
Extension
.c
Size
65563 bytes
Lines
2059
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 (nau8824_is_jack_inserted(nau8824)) {
			nau8824_config_sysclk(nau8824,
				NAU8824_CLK_INTERNAL, 0);
		} else {
			nau8824_config_sysclk(nau8824, NAU8824_CLK_DIS, 0);
		}

		clk_disable_unprepare(nau8824->mclk);
	} else {
		dev_dbg(nau8824->dev, "system clock control : POWER ON\n");

		ret = clk_prepare_enable(nau8824->mclk);
		if (ret)
			return ret;

		/* Check the clock source setting is proper or not
		 * no matter the source is from FLL or MCLK.
		 */
		regmap_read(regmap, NAU8824_REG_FLL1, &value);
		clk_fll = value & NAU8824_FLL_RATIO_MASK;
		/* It's error to use internal clock when playback */
		regmap_read(regmap, NAU8824_REG_FLL6, &value);
		error = value & NAU8824_DCO_EN;
		if (!error) {
			/* Check error depending on source is FLL or MCLK. */
			regmap_read(regmap, NAU8824_REG_CLK_DIVIDER, &value);
			if (clk_fll)
				error = !(value & NAU8824_CLK_SRC_VCO);
			else
				error = value & NAU8824_CLK_SRC_VCO;
		}
		/* Recover the clock source setting if error. */
		if (error) {
			if (clk_fll) {
				regmap_update_bits(regmap,
					NAU8824_REG_FLL6, NAU8824_DCO_EN, 0);
				regmap_update_bits(regmap,
					NAU8824_REG_CLK_DIVIDER,
					NAU8824_CLK_SRC_MASK,
					NAU8824_CLK_SRC_VCO);
			} else {
				nau8824_config_sysclk(nau8824,
					NAU8824_CLK_MCLK, 0);
			}
		}
	}

	return 0;
}

static int dmic_clock_control(struct snd_soc_dapm_widget *w,
		struct snd_kcontrol *k, int  event)
{
	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
	struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
	int src;
	unsigned int freq;

	freq = clk_get_rate(nau8824->mclk);
	if (!freq)
		freq = nau8824->fs * 256;

	/* The DMIC clock is gotten from system clock (256fs) divided by
	 * DMIC_SRC (1, 2, 4, 8, 16, 32). The clock has to be equal or
	 * less than 3.072 MHz.
	 */
	for (src = 0; src < 5; src++) {
		if (freq / (0x1 << src) <= DMIC_CLK)
			break;
	}
	dev_dbg(nau8824->dev, "dmic src %d for mclk %d\n", src, freq);
	regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
		NAU8824_CLK_DMIC_SRC_MASK, (src << NAU8824_CLK_DMIC_SRC_SFT));

	return 0;
}

static const struct snd_kcontrol_new nau8824_adc_ch0_dmic =
	SOC_DAPM_SINGLE("Switch", NAU8824_REG_ENA_CTRL,
		NAU8824_ADC_CH0_DMIC_SFT, 1, 0);

static const struct snd_kcontrol_new nau8824_adc_ch1_dmic =
	SOC_DAPM_SINGLE("Switch", NAU8824_REG_ENA_CTRL,
		NAU8824_ADC_CH1_DMIC_SFT, 1, 0);

static const struct snd_kcontrol_new nau8824_adc_ch2_dmic =
	SOC_DAPM_SINGLE("Switch", NAU8824_REG_ENA_CTRL,
		NAU8824_ADC_CH2_DMIC_SFT, 1, 0);

static const struct snd_kcontrol_new nau8824_adc_ch3_dmic =

Annotation

Implementation Notes