sound/soc/codecs/rk3328_codec.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/rk3328_codec.c
Extension
.c
Size
13954 bytes
Lines
507
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 rk3328_codec_priv {
	struct regmap *regmap;
	struct gpio_desc *mute;
	struct clk *mclk;
	struct clk *pclk;
	unsigned int sclk;
	int spk_depop_time; /* msec */
};

static const struct reg_default rk3328_codec_reg_defaults[] = {
	{ CODEC_RESET, 0x03 },
	{ DAC_INIT_CTRL1, 0x00 },
	{ DAC_INIT_CTRL2, 0x50 },
	{ DAC_INIT_CTRL3, 0x0e },
	{ DAC_PRECHARGE_CTRL, 0x01 },
	{ DAC_PWR_CTRL, 0x00 },
	{ DAC_CLK_CTRL, 0x00 },
	{ HPMIX_CTRL, 0x00 },
	{ HPOUT_CTRL, 0x00 },
	{ HPOUTL_GAIN_CTRL, 0x00 },
	{ HPOUTR_GAIN_CTRL, 0x00 },
	{ HPOUT_POP_CTRL, 0x11 },
};

static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
{
	regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
	mdelay(10);
	regmap_write(rk3328->regmap, CODEC_RESET, 0x03);

	return 0;
}

static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
	struct rk3328_codec_priv *rk3328 =
		snd_soc_component_get_drvdata(dai->component);
	unsigned int val;

	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
	case SND_SOC_DAIFMT_CBC_CFC:
		val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
		break;
	case SND_SOC_DAIFMT_CBP_CFP:
		val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
		break;
	default:
		return -EINVAL;
	}

	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
			   PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);

	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_DSP_A:
	case SND_SOC_DAIFMT_DSP_B:
		val = DAC_MODE_PCM;
		break;
	case SND_SOC_DAIFMT_I2S:
		val = DAC_MODE_I2S;
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		val = DAC_MODE_RJM;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		val = DAC_MODE_LJM;
		break;
	default:
		return -EINVAL;
	}

	regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
			   DAC_MODE_MASK, val);

	return 0;
}

static int rk3328_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
{
	struct rk3328_codec_priv *rk3328 =
		snd_soc_component_get_drvdata(dai->component);
	unsigned int val;

	if (mute)
		val = HPOUTL_MUTE | HPOUTR_MUTE;
	else
		val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;

	regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
			   HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);

Annotation

Implementation Notes