brintos

brintos / linux-shallow public Read only

0
0
Text · 8.0 KiB · ae62089 Raw
299 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * mt2701-afe-clock-ctrl.c  --  Mediatek 2701 afe clock ctrl4 *5 * Copyright (c) 2016 MediaTek Inc.6 * Author: Garlic Tseng <garlic.tseng@mediatek.com>7 *	   Ryder Lee <ryder.lee@mediatek.com>8 */9 10#include "mt2701-afe-common.h"11#include "mt2701-afe-clock-ctrl.h"12 13static const char *const base_clks[] = {14	[MT2701_INFRA_SYS_AUDIO] = "infra_sys_audio_clk",15	[MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",16	[MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",17	[MT2701_TOP_AUD_A1SYS] = "top_audio_a1sys_hp",18	[MT2701_TOP_AUD_A2SYS] = "top_audio_a2sys_hp",19	[MT2701_AUDSYS_AFE] = "audio_afe_pd",20	[MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd",21	[MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd",22	[MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd",23};24 25int mt2701_init_clock(struct mtk_base_afe *afe)26{27	struct mt2701_afe_private *afe_priv = afe->platform_priv;28	int i;29 30	for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {31		afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]);32		if (IS_ERR(afe_priv->base_ck[i])) {33			dev_err(afe->dev, "failed to get %s\n", base_clks[i]);34			return PTR_ERR(afe_priv->base_ck[i]);35		}36	}37 38	/* Get I2S related clocks */39	for (i = 0; i < afe_priv->soc->i2s_num; i++) {40		struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];41		struct clk *i2s_ck;42		char name[13];43 44		snprintf(name, sizeof(name), "i2s%d_src_sel", i);45		i2s_path->sel_ck = devm_clk_get(afe->dev, name);46		if (IS_ERR(i2s_path->sel_ck)) {47			dev_err(afe->dev, "failed to get %s\n", name);48			return PTR_ERR(i2s_path->sel_ck);49		}50 51		snprintf(name, sizeof(name), "i2s%d_src_div", i);52		i2s_path->div_ck = devm_clk_get(afe->dev, name);53		if (IS_ERR(i2s_path->div_ck)) {54			dev_err(afe->dev, "failed to get %s\n", name);55			return PTR_ERR(i2s_path->div_ck);56		}57 58		snprintf(name, sizeof(name), "i2s%d_mclk_en", i);59		i2s_path->mclk_ck = devm_clk_get(afe->dev, name);60		if (IS_ERR(i2s_path->mclk_ck)) {61			dev_err(afe->dev, "failed to get %s\n", name);62			return PTR_ERR(i2s_path->mclk_ck);63		}64 65		snprintf(name, sizeof(name), "i2so%d_hop_ck", i);66		i2s_ck = devm_clk_get(afe->dev, name);67		if (IS_ERR(i2s_ck)) {68			dev_err(afe->dev, "failed to get %s\n", name);69			return PTR_ERR(i2s_ck);70		}71		i2s_path->hop_ck[SNDRV_PCM_STREAM_PLAYBACK] = i2s_ck;72 73		snprintf(name, sizeof(name), "i2si%d_hop_ck", i);74		i2s_ck = devm_clk_get(afe->dev, name);75		if (IS_ERR(i2s_ck)) {76			dev_err(afe->dev, "failed to get %s\n", name);77			return PTR_ERR(i2s_ck);78		}79		i2s_path->hop_ck[SNDRV_PCM_STREAM_CAPTURE] = i2s_ck;80 81		snprintf(name, sizeof(name), "asrc%d_out_ck", i);82		i2s_path->asrco_ck = devm_clk_get(afe->dev, name);83		if (IS_ERR(i2s_path->asrco_ck)) {84			dev_err(afe->dev, "failed to get %s\n", name);85			return PTR_ERR(i2s_path->asrco_ck);86		}87	}88 89	/* Some platforms may support BT path */90	afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd");91	if (IS_ERR(afe_priv->mrgif_ck)) {92		if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER)93			return -EPROBE_DEFER;94 95		afe_priv->mrgif_ck = NULL;96	}97 98	return 0;99}100 101int mt2701_afe_enable_i2s(struct mtk_base_afe *afe,102			  struct mt2701_i2s_path *i2s_path,103			  int dir)104{105	int ret;106 107	ret = clk_prepare_enable(i2s_path->asrco_ck);108	if (ret) {109		dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret);110		return ret;111	}112 113	ret = clk_prepare_enable(i2s_path->hop_ck[dir]);114	if (ret) {115		dev_err(afe->dev, "failed to enable I2S clock %d\n", ret);116		goto err_hop_ck;117	}118 119	return 0;120 121err_hop_ck:122	clk_disable_unprepare(i2s_path->asrco_ck);123 124	return ret;125}126 127void mt2701_afe_disable_i2s(struct mtk_base_afe *afe,128			    struct mt2701_i2s_path *i2s_path,129			    int dir)130{131	clk_disable_unprepare(i2s_path->hop_ck[dir]);132	clk_disable_unprepare(i2s_path->asrco_ck);133}134 135int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id)136{137	struct mt2701_afe_private *afe_priv = afe->platform_priv;138	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];139 140	return clk_prepare_enable(i2s_path->mclk_ck);141}142 143void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id)144{145	struct mt2701_afe_private *afe_priv = afe->platform_priv;146	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];147 148	clk_disable_unprepare(i2s_path->mclk_ck);149}150 151int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe)152{153	struct mt2701_afe_private *afe_priv = afe->platform_priv;154 155	return clk_prepare_enable(afe_priv->mrgif_ck);156}157 158void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe)159{160	struct mt2701_afe_private *afe_priv = afe->platform_priv;161 162	clk_disable_unprepare(afe_priv->mrgif_ck);163}164 165static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe)166{167	struct mt2701_afe_private *afe_priv = afe->platform_priv;168	int ret;169 170	/* Enable infra clock gate */171	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);172	if (ret)173		return ret;174 175	/* Enable top a1sys clock gate */176	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);177	if (ret)178		goto err_a1sys;179 180	/* Enable top a2sys clock gate */181	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);182	if (ret)183		goto err_a2sys;184 185	/* Internal clock gates */186	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]);187	if (ret)188		goto err_afe;189 190	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);191	if (ret)192		goto err_audio_a1sys;193 194	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);195	if (ret)196		goto err_audio_a2sys;197 198	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);199	if (ret)200		goto err_afe_conn;201 202	return 0;203 204err_afe_conn:205	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);206err_audio_a2sys:207	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);208err_audio_a1sys:209	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);210err_afe:211	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);212err_a2sys:213	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);214err_a1sys:215	clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);216 217	return ret;218}219 220static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe)221{222	struct mt2701_afe_private *afe_priv = afe->platform_priv;223 224	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);225	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);226	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);227	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);228	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A1SYS]);229	clk_disable_unprepare(afe_priv->base_ck[MT2701_TOP_AUD_A2SYS]);230	clk_disable_unprepare(afe_priv->base_ck[MT2701_INFRA_SYS_AUDIO]);231}232 233int mt2701_afe_enable_clock(struct mtk_base_afe *afe)234{235	int ret;236 237	/* Enable audio system */238	ret = mt2701_afe_enable_audsys(afe);239	if (ret) {240		dev_err(afe->dev, "failed to enable audio system %d\n", ret);241		return ret;242	}243 244	regmap_update_bits(afe->regmap, ASYS_TOP_CON,245			   ASYS_TOP_CON_ASYS_TIMING_ON,246			   ASYS_TOP_CON_ASYS_TIMING_ON);247	regmap_update_bits(afe->regmap, AFE_DAC_CON0,248			   AFE_DAC_CON0_AFE_ON,249			   AFE_DAC_CON0_AFE_ON);250 251	/* Configure ASRC */252	regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL);253	regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL);254 255	return 0;256}257 258int mt2701_afe_disable_clock(struct mtk_base_afe *afe)259{260	regmap_update_bits(afe->regmap, ASYS_TOP_CON,261			   ASYS_TOP_CON_ASYS_TIMING_ON, 0);262	regmap_update_bits(afe->regmap, AFE_DAC_CON0,263			   AFE_DAC_CON0_AFE_ON, 0);264 265	mt2701_afe_disable_audsys(afe);266 267	return 0;268}269 270int mt2701_mclk_configuration(struct mtk_base_afe *afe, int id)271 272{273	struct mt2701_afe_private *priv = afe->platform_priv;274	struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];275	int ret = -EINVAL;276 277	/* Set mclk source */278	if (!(MT2701_PLL_DOMAIN_0_RATE % i2s_path->mclk_rate))279		ret = clk_set_parent(i2s_path->sel_ck,280				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);281	else if (!(MT2701_PLL_DOMAIN_1_RATE % i2s_path->mclk_rate))282		ret = clk_set_parent(i2s_path->sel_ck,283				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);284 285	if (ret) {286		dev_err(afe->dev, "failed to set mclk source\n");287		return ret;288	}289 290	/* Set mclk divider */291	ret = clk_set_rate(i2s_path->div_ck, i2s_path->mclk_rate);292	if (ret) {293		dev_err(afe->dev, "failed to set mclk divider %d\n", ret);294		return ret;295	}296 297	return 0;298}299