brintos

brintos / linux-shallow public Read only

0
0
Text · 7.9 KiB · f9945c2 Raw
311 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * MediaTek 8365 ALSA SoC Audio DAI DMIC Control4 *5 * Copyright (c) 2024 MediaTek Inc.6 * Authors: Jia Zeng <jia.zeng@mediatek.com>7 *          Alexandre Mergnat <amergnat@baylibre.com>8 */9 10#include <linux/bitops.h>11#include <linux/regmap.h>12#include <sound/pcm_params.h>13#include "mt8365-afe-clk.h"14#include "mt8365-afe-common.h"15 16struct mt8365_dmic_data {17	bool two_wire_mode;18	unsigned int clk_phase_sel_ch1;19	unsigned int clk_phase_sel_ch2;20	bool iir_on;21	unsigned int irr_mode;22	unsigned int dmic_mode;23	unsigned int dmic_channel;24};25 26static int get_chan_reg(unsigned int channel)27{28	switch (channel) {29	case 8:30		fallthrough;31	case 7:32		return AFE_DMIC3_UL_SRC_CON0;33	case 6:34		fallthrough;35	case 5:36		return AFE_DMIC2_UL_SRC_CON0;37	case 4:38		fallthrough;39	case 3:40		return AFE_DMIC1_UL_SRC_CON0;41	case 2:42		fallthrough;43	case 1:44		return AFE_DMIC0_UL_SRC_CON0;45	default:46		return -EINVAL;47	}48}49 50/* DAI Drivers */51 52static void audio_dmic_adda_enable(struct mtk_base_afe *afe)53{54	mt8365_dai_enable_adda_on(afe);55	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,56			   AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,57			   AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);58}59 60static void audio_dmic_adda_disable(struct mtk_base_afe *afe)61{62	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,63			   AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,64			   ~AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);65	mt8365_dai_disable_adda_on(afe);66}67 68static void mt8365_dai_enable_dmic(struct mtk_base_afe *afe,69				   struct snd_pcm_substream *substream,70				   struct snd_soc_dai *dai)71{72	struct mt8365_afe_private *afe_priv = afe->platform_priv;73	struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];74	unsigned int val_mask;75	int reg = get_chan_reg(dmic_data->dmic_channel);76 77	if (reg < 0)78		return;79 80	/* val and mask will be always same to enable */81	val_mask = DMIC_TOP_CON_CH1_ON |82		   DMIC_TOP_CON_CH2_ON |83		   DMIC_TOP_CON_SRC_ON;84 85	regmap_update_bits(afe->regmap, reg, val_mask, val_mask);86}87 88static void mt8365_dai_disable_dmic(struct mtk_base_afe *afe,89				    struct snd_pcm_substream *substream,90				    struct snd_soc_dai *dai)91{92	struct mt8365_afe_private *afe_priv = afe->platform_priv;93	struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];94	unsigned int mask;95	int reg = get_chan_reg(dmic_data->dmic_channel);96 97	if (reg < 0)98		return;99 100	dev_dbg(afe->dev, "%s dmic_channel %d\n", __func__, dmic_data->dmic_channel);101 102	mask = DMIC_TOP_CON_CH1_ON |103	       DMIC_TOP_CON_CH2_ON |104	       DMIC_TOP_CON_SRC_ON |105	       DMIC_TOP_CON_SDM3_LEVEL_MODE;106 107	/* Set all masked values to 0 */108	regmap_update_bits(afe->regmap, reg, mask, 0);109}110 111static int mt8365_dai_configure_dmic(struct mtk_base_afe *afe,112				     struct snd_pcm_substream *substream,113				     struct snd_soc_dai *dai)114{115	struct mt8365_afe_private *afe_priv = afe->platform_priv;116	struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];117	bool two_wire_mode = dmic_data->two_wire_mode;118	unsigned int clk_phase_sel_ch1 = dmic_data->clk_phase_sel_ch1;119	unsigned int clk_phase_sel_ch2 = dmic_data->clk_phase_sel_ch2;120	unsigned int val = 0;121	unsigned int rate = dai->rate;122	int reg = get_chan_reg(dai->channels);123 124	if (reg < 0)125		return -EINVAL;126 127	dmic_data->dmic_channel = dai->channels;128 129	val |= DMIC_TOP_CON_SDM3_LEVEL_MODE;130 131	if (two_wire_mode) {132		val |= DMIC_TOP_CON_TWO_WIRE_MODE;133	} else {134		val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH1,135				  clk_phase_sel_ch1);136		val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH2,137				  clk_phase_sel_ch2);138	}139 140	switch (rate) {141	case 48000:142		val |= DMIC_TOP_CON_VOICE_MODE_48K;143		break;144	case 32000:145		val |= DMIC_TOP_CON_VOICE_MODE_32K;146		break;147	case 16000:148		val |= DMIC_TOP_CON_VOICE_MODE_16K;149		break;150	case 8000:151		val |= DMIC_TOP_CON_VOICE_MODE_8K;152		break;153	default:154		return -EINVAL;155	}156 157	regmap_update_bits(afe->regmap, reg, DMIC_TOP_CON_CONFIG_MASK, val);158 159	return 0;160}161 162static int mt8365_dai_dmic_startup(struct snd_pcm_substream *substream,163				   struct snd_soc_dai *dai)164{165	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);166 167	mt8365_afe_enable_main_clk(afe);168 169	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);170	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);171	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);172	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);173 174	audio_dmic_adda_enable(afe);175 176	return 0;177}178 179static void mt8365_dai_dmic_shutdown(struct snd_pcm_substream *substream,180				     struct snd_soc_dai *dai)181{182	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);183 184	mt8365_dai_disable_dmic(afe, substream, dai);185	audio_dmic_adda_disable(afe);186	/* HW Request delay 125us before CG off */187	usleep_range(125, 300);188	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);189	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);190	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);191	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);192 193	mt8365_afe_disable_main_clk(afe);194}195 196static int mt8365_dai_dmic_prepare(struct snd_pcm_substream *substream,197				   struct snd_soc_dai *dai)198{199	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);200 201	mt8365_dai_configure_dmic(afe, substream, dai);202	mt8365_dai_enable_dmic(afe, substream, dai);203 204	return 0;205}206 207static const struct snd_soc_dai_ops mt8365_afe_dmic_ops = {208	.startup	= mt8365_dai_dmic_startup,209	.shutdown	= mt8365_dai_dmic_shutdown,210	.prepare	= mt8365_dai_dmic_prepare,211};212 213static struct snd_soc_dai_driver mtk_dai_dmic_driver[] = {214	{215		.name = "DMIC",216		.id = MT8365_AFE_IO_DMIC,217		.capture = {218			.stream_name = "DMIC Capture",219			.channels_min = 1,220			.channels_max = 8,221			.rates = SNDRV_PCM_RATE_16000 |222				 SNDRV_PCM_RATE_32000 |223				 SNDRV_PCM_RATE_48000,224			.formats = SNDRV_PCM_FMTBIT_S16_LE |225				   SNDRV_PCM_FMTBIT_S32_LE,226		},227		.ops = &mt8365_afe_dmic_ops,228	}229};230 231/* DAI Controls */232 233/* Values for 48kHz mode */234static const char * const iir_mode_src[] = {235	"SW custom", "5Hz", "10Hz", "25Hz", "50Hz", "65Hz"236};237 238static SOC_ENUM_SINGLE_DECL(iir_mode, AFE_DMIC0_UL_SRC_CON0, 7, iir_mode_src);239 240static const struct snd_kcontrol_new mtk_dai_dmic_controls[] = {241	SOC_SINGLE("DMIC IIR Switch", AFE_DMIC0_UL_SRC_CON0, DMIC_TOP_CON_IIR_ON, 1, 0),242	SOC_ENUM("DMIC IIR Mode", iir_mode),243};244 245/* DAI widget */246 247static const struct snd_soc_dapm_widget mtk_dai_dmic_widgets[] = {248	SND_SOC_DAPM_INPUT("DMIC In"),249};250 251/* DAI route */252 253static const struct snd_soc_dapm_route mtk_dai_dmic_routes[] = {254	{"I14", NULL, "DMIC Capture"},255	{"I15", NULL, "DMIC Capture"},256	{"I16", NULL, "DMIC Capture"},257	{"I17", NULL, "DMIC Capture"},258	{"I18", NULL, "DMIC Capture"},259	{"I19", NULL, "DMIC Capture"},260	{"I20", NULL, "DMIC Capture"},261	{"I21", NULL, "DMIC Capture"},262	{"DMIC Capture", NULL, "DMIC In"},263};264 265static int init_dmic_priv_data(struct mtk_base_afe *afe)266{267	struct mt8365_afe_private *afe_priv = afe->platform_priv;268	struct mt8365_dmic_data *dmic_priv;269	struct device_node *np = afe->dev->of_node;270	unsigned int temps[4];271	int ret;272 273	dmic_priv = devm_kzalloc(afe->dev, sizeof(*dmic_priv), GFP_KERNEL);274	if (!dmic_priv)275		return -ENOMEM;276 277	ret = of_property_read_u32_array(np, "mediatek,dmic-mode",278					 &temps[0],279					 1);280	if (ret == 0)281		dmic_priv->two_wire_mode = !!temps[0];282 283	if (!dmic_priv->two_wire_mode) {284		dmic_priv->clk_phase_sel_ch1 = 0;285		dmic_priv->clk_phase_sel_ch2 = 4;286	}287 288	afe_priv->dai_priv[MT8365_AFE_IO_DMIC] = dmic_priv;289	return 0;290}291 292int mt8365_dai_dmic_register(struct mtk_base_afe *afe)293{294	struct mtk_base_afe_dai *dai;295 296	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);297	if (!dai)298		return -ENOMEM;299 300	list_add(&dai->list, &afe->sub_dais);301	dai->dai_drivers = mtk_dai_dmic_driver;302	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_dmic_driver);303	dai->controls = mtk_dai_dmic_controls;304	dai->num_controls = ARRAY_SIZE(mtk_dai_dmic_controls);305	dai->dapm_widgets = mtk_dai_dmic_widgets;306	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_dmic_widgets);307	dai->dapm_routes = mtk_dai_dmic_routes;308	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_dmic_routes);309	return init_dmic_priv_data(afe);310}311