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

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

File Facts

System
Linux kernel
Corpus path
sound/soc/mediatek/mt8186/mt8186-afe-clk.c
Extension
.c
Size
16987 bytes
Lines
590
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 mt8186_mck_div {
	u32 m_sel_id;
	u32 div_clk_id;
};

static const struct mt8186_mck_div mck_div[MT8186_MCK_NUM] = {
	[MT8186_I2S0_MCK] = {
		.m_sel_id = CLK_TOP_I2S0_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV0,
	},
	[MT8186_I2S1_MCK] = {
		.m_sel_id = CLK_TOP_I2S1_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV1,
	},
	[MT8186_I2S2_MCK] = {
		.m_sel_id = CLK_TOP_I2S2_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV2,
	},
	[MT8186_I2S4_MCK] = {
		.m_sel_id = CLK_TOP_I2S4_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV4,
	},
	[MT8186_TDM_MCK] = {
		.m_sel_id = CLK_TOP_TDM_M_SEL,
		.div_clk_id = CLK_TOP_APLL12_DIV_TDM,
	},
};

int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
{
	struct mt8186_afe_private *afe_priv = afe->platform_priv;
	int apll = mt8186_get_apll_by_rate(afe, rate);
	int apll_clk_id = apll == MT8186_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;

	/* 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);
			return ret;
		}
		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);
			return ret;
		}
	}

	/* 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);
		return ret;
	}
	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);
		return ret;
	}

	return 0;
}

void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id)
{
	struct mt8186_afe_private *afe_priv = afe->platform_priv;
	int m_sel_id = mck_div[mck_id].m_sel_id;
	int div_clk_id = mck_div[mck_id].div_clk_id;

	clk_disable_unprepare(afe_priv->clk[div_clk_id]);
	if (m_sel_id >= 0)
		clk_disable_unprepare(afe_priv->clk[m_sel_id]);
}

int mt8186_init_clock(struct mtk_base_afe *afe)
{
	struct mt8186_afe_private *afe_priv = afe->platform_priv;
	struct device_node *of_node = afe->dev->of_node;
	int i = 0;

Annotation

Implementation Notes