sound/soc/mediatek/mt8173/mt8173-afe-pcm.c

Source file repositories/reference/linux-study-clean/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c

File Facts

System
Linux kernel
Corpus path
sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
Extension
.c
Size
32392 bytes
Lines
1211
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 mt8173_afe_private {
	struct clk *clocks[MT8173_CLK_NUM];
};

static const struct snd_pcm_hardware mt8173_afe_hardware = {
	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
		 SNDRV_PCM_INFO_MMAP_VALID),
	.buffer_bytes_max = 256 * 1024,
	.period_bytes_min = 512,
	.period_bytes_max = 128 * 1024,
	.periods_min = 2,
	.periods_max = 256,
	.fifo_size = 0,
};

struct mt8173_afe_rate {
	unsigned int rate;
	unsigned int regvalue;
};

static const struct mt8173_afe_rate mt8173_afe_i2s_rates[] = {
	{ .rate = 8000, .regvalue = 0 },
	{ .rate = 11025, .regvalue = 1 },
	{ .rate = 12000, .regvalue = 2 },
	{ .rate = 16000, .regvalue = 4 },
	{ .rate = 22050, .regvalue = 5 },
	{ .rate = 24000, .regvalue = 6 },
	{ .rate = 32000, .regvalue = 8 },
	{ .rate = 44100, .regvalue = 9 },
	{ .rate = 48000, .regvalue = 10 },
	{ .rate = 88000, .regvalue = 11 },
	{ .rate = 96000, .regvalue = 12 },
	{ .rate = 174000, .regvalue = 13 },
	{ .rate = 192000, .regvalue = 14 },
};

static int mt8173_afe_i2s_fs(unsigned int sample_rate)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(mt8173_afe_i2s_rates); i++)
		if (mt8173_afe_i2s_rates[i].rate == sample_rate)
			return mt8173_afe_i2s_rates[i].regvalue;

	return -EINVAL;
}

static int mt8173_afe_set_i2s(struct mtk_base_afe *afe, unsigned int rate)
{
	unsigned int val;
	int fs = mt8173_afe_i2s_fs(rate);

	if (fs < 0)
		return -EINVAL;

	/* from external ADC */
	regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);
	regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1);

	/* set input */
	val = AFE_I2S_CON2_LOW_JITTER_CLK |
	      AFE_I2S_CON2_RATE(fs) |
	      AFE_I2S_CON2_FORMAT_I2S;

	regmap_update_bits(afe->regmap, AFE_I2S_CON2, ~AFE_I2S_CON2_EN, val);

	/* set output */
	val = AFE_I2S_CON1_LOW_JITTER_CLK |
	      AFE_I2S_CON1_RATE(fs) |
	      AFE_I2S_CON1_FORMAT_I2S;

	regmap_update_bits(afe->regmap, AFE_I2S_CON1, ~AFE_I2S_CON1_EN, val);
	return 0;
}

static void mt8173_afe_set_i2s_enable(struct mtk_base_afe *afe, bool enable)
{
	unsigned int val;

	regmap_read(afe->regmap, AFE_I2S_CON2, &val);
	if (!!(val & AFE_I2S_CON2_EN) == enable)
		return;

	/* input */
	regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable);

	/* output */
	regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable);
}

Annotation

Implementation Notes