sound/soc/mediatek/mt8183/mt8183-afe-clk.c

Source file repositories/reference/linux-study-clean/sound/soc/mediatek/mt8183/mt8183-afe-clk.c

File Facts

System
Linux kernel
Corpus path
sound/soc/mediatek/mt8183/mt8183-afe-clk.c
Extension
.c
Size
17301 bytes
Lines
615
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 mt8183_mck_div {
	int m_sel_id;
	int div_clk_id;
};

static const struct mt8183_mck_div mck_div[MT8183_MCK_NUM] = {
	[MT8183_I2S0_MCK] = {
		.m_sel_id = CLK_TOP_I2S0_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV0,
	},
	[MT8183_I2S1_MCK] = {
		.m_sel_id = CLK_TOP_I2S1_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV1,
	},
	[MT8183_I2S2_MCK] = {
		.m_sel_id = CLK_TOP_I2S2_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV2,
	},
	[MT8183_I2S3_MCK] = {
		.m_sel_id = CLK_TOP_I2S3_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV3,
	},
	[MT8183_I2S4_MCK] = {
		.m_sel_id = CLK_TOP_I2S4_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV4,
	},
	[MT8183_I2S4_BCK] = {
		.m_sel_id = -1,
		.div_clk_id = CLK_TOP_APLL12_DIVB,
	},
	[MT8183_I2S5_MCK] = {
		.m_sel_id = -1,
		.div_clk_id = -1,
	},
};

int mt8183_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
{
	struct mt8183_afe_private *afe_priv = afe->platform_priv;
	int apll = mt8183_get_apll_by_rate(afe, rate);
	int apll_clk_id = apll == MT8183_APLL1 ?
			  CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2;
	int m_sel_id = mck_div[mck_id].m_sel_id;
	int div_clk_id = mck_div[mck_id].div_clk_id;
	int ret;

	/* i2s5 mck not support */
	if (mck_id == MT8183_I2S5_MCK)
		return 0;

	/* select apll */
	if (m_sel_id >= 0) {
		ret = clk_prepare_enable(afe_priv->clk[m_sel_id]);
		if (ret) {
			dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
				__func__, aud_clks[m_sel_id], ret);
			goto ERR_ENABLE_MCLK;
		}
		ret = clk_set_parent(afe_priv->clk[m_sel_id],
				     afe_priv->clk[apll_clk_id]);
		if (ret) {
			dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n",
				__func__, aud_clks[m_sel_id],
				aud_clks[apll_clk_id], ret);
			goto ERR_SELECT_MCLK;
		}
	}

	/* enable div, set rate */
	ret = clk_prepare_enable(afe_priv->clk[div_clk_id]);
	if (ret) {
		dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
			__func__, aud_clks[div_clk_id], ret);
		goto ERR_ENABLE_MCLK_DIV;
	}
	ret = clk_set_rate(afe_priv->clk[div_clk_id], rate);
	if (ret) {
		dev_err(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n",
			__func__, aud_clks[div_clk_id],
			rate, ret);
		goto ERR_SET_MCLK_RATE;
	}

	return 0;

ERR_SET_MCLK_RATE:
	clk_disable_unprepare(afe_priv->clk[div_clk_id]);
ERR_ENABLE_MCLK_DIV:
ERR_SELECT_MCLK:
	if (m_sel_id >= 0)

Annotation

Implementation Notes