sound/soc/codecs/rk817_codec.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/rk817_codec.c
Extension
.c
Size
17637 bytes
Lines
541
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 rk817_codec_priv {
	struct snd_soc_component *component;
	struct rk808 *rk808;
	struct clk *mclk;
	unsigned int stereo_sysclk;
	bool mic_in_differential;
};

/*
 * This sets the codec up with the values defined in the default implementation including the APLL
 * from the Rockchip vendor kernel. I do not know if these values are universal despite differing
 * from the default values defined above and taken from the datasheet, or implementation specific.
 * I don't have another implementation to compare from the Rockchip sources. Hard-coding for now.
 * Additionally, I do not know according to the documentation the units accepted for the clock
 * values, so for the moment those are left unvalidated.
 */

static int rk817_init(struct snd_soc_component *component)
{
	struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);

	snd_soc_component_write(component, RK817_CODEC_DDAC_POPD_DACST, 0x02);
	snd_soc_component_write(component, RK817_CODEC_DDAC_SR_LMT0, 0x02);
	snd_soc_component_write(component, RK817_CODEC_DADC_SR_ACL0, 0x02);
	snd_soc_component_write(component, RK817_CODEC_DTOP_VUCTIME, 0xf4);
	if (rk817->mic_in_differential) {
		snd_soc_component_update_bits(component, RK817_CODEC_AMIC_CFG0, MIC_DIFF_MASK,
			MIC_DIFF_EN);
	}

	return 0;
}

static int rk817_set_component_pll(struct snd_soc_component *component,
		int pll_id, int source, unsigned int freq_in,
		unsigned int freq_out)
{
	/* Set resistor value and charge pump current for PLL. */
	snd_soc_component_write(component, RK817_CODEC_APLL_CFG1, 0x58);
	/* Set the PLL feedback clock divide value (values not documented). */
	snd_soc_component_write(component, RK817_CODEC_APLL_CFG2, 0x2d);
	/* Set the PLL pre-divide value (values not documented). */
	snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, 0x0c);
	/* Set the PLL VCO output clock divide and PLL divided ratio of PLL High Clk (values not
	 * documented).
	 */
	snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5);

	return 0;
}

/*
 * DDAC/DADC L/R volume setting
 * 0db~-95db, 0.375db/step, for example:
 * 0x00: 0dB
 * 0xff: -95dB
 */

static const DECLARE_TLV_DB_MINMAX(rk817_vol_tlv, -9500, 0);

/*
 * PGA GAIN L/R volume setting
 * 27db~-18db, 3db/step, for example:
 * 0x0: -18dB
 * 0xf: 27dB
 */

static const DECLARE_TLV_DB_MINMAX(rk817_gain_tlv, -1800, 2700);

static const struct snd_kcontrol_new rk817_volume_controls[] = {
	SOC_DOUBLE_R_RANGE_TLV("Master Playback Volume", RK817_CODEC_DDAC_VOLL,
		RK817_CODEC_DDAC_VOLR, 0, 0x00, 0xff, 1, rk817_vol_tlv),
	SOC_DOUBLE_R_RANGE_TLV("Master Capture Volume", RK817_CODEC_DADC_VOLL,
		RK817_CODEC_DADC_VOLR, 0, 0x00, 0xff, 1, rk817_vol_tlv),
	SOC_DOUBLE_TLV("Mic Capture Gain", RK817_CODEC_DMIC_PGA_GAIN, 4, 0, 0xf, 0,
		rk817_gain_tlv),
};

/* Since the speaker output and L headphone pin are internally the same, make audio path mutually
 * exclusive with a mux.
 */

static const char *dac_mux_text[] = {
	"HP",
	"SPK",
};

static SOC_ENUM_SINGLE_VIRT_DECL(dac_enum, dac_mux_text);

static const struct snd_kcontrol_new dac_mux =

Annotation

Implementation Notes