brintos

brintos / linux-shallow public Read only

0
0
Text · 9.0 KiB · 78f3ad7 Raw
324 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// MediaTek ALSA SoC Audio DAI ADDA Control4//5// Copyright (c) 2018 MediaTek Inc.6// Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>7 8#include <linux/regmap.h>9#include <linux/delay.h>10#include "mt6797-afe-common.h"11#include "mt6797-interconnection.h"12#include "mt6797-reg.h"13#include "../common/mtk-dai-adda-common.h"14 15/* dai component */16static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {17	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3, I_DL1_CH1, 1, 0),18	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN3, I_DL2_CH1, 1, 0),19	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN3, I_DL3_CH1, 1, 0),20	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN3,21				    I_ADDA_UL_CH2, 1, 0),22	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN3,23				    I_ADDA_UL_CH1, 1, 0),24	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN3,25				    I_PCM_1_CAP_CH1, 1, 0),26	SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN3,27				    I_PCM_2_CAP_CH1, 1, 0),28};29 30static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {31	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN4, I_DL1_CH1, 1, 0),32	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN4, I_DL1_CH2, 1, 0),33	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN4, I_DL2_CH1, 1, 0),34	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN4, I_DL2_CH2, 1, 0),35	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN4, I_DL3_CH1, 1, 0),36	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN4, I_DL3_CH2, 1, 0),37	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN4,38				    I_ADDA_UL_CH2, 1, 0),39	SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN4,40				    I_ADDA_UL_CH1, 1, 0),41	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN4,42				    I_PCM_1_CAP_CH1, 1, 0),43	SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN4,44				    I_PCM_2_CAP_CH1, 1, 0),45	SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN4,46				    I_PCM_1_CAP_CH2, 1, 0),47	SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN4,48				    I_PCM_2_CAP_CH2, 1, 0),49};50 51static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,52			     struct snd_kcontrol *kcontrol,53			     int event)54{55	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);56	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);57 58	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",59		__func__, w->name, event);60 61	switch (event) {62	case SND_SOC_DAPM_POST_PMD:63		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */64		usleep_range(125, 135);65		break;66	default:67		break;68	}69 70	return 0;71}72 73enum {74	SUPPLY_SEQ_AUD_TOP_PDN,75	SUPPLY_SEQ_ADDA_AFE_ON,76	SUPPLY_SEQ_ADDA_DL_ON,77	SUPPLY_SEQ_ADDA_UL_ON,78};79 80static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {81	/* adda */82	SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,83			   mtk_adda_dl_ch1_mix,84			   ARRAY_SIZE(mtk_adda_dl_ch1_mix)),85	SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,86			   mtk_adda_dl_ch2_mix,87			   ARRAY_SIZE(mtk_adda_dl_ch2_mix)),88 89	SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,90			      AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0,91			      NULL, 0),92 93	SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,94			      AFE_ADDA_DL_SRC2_CON0,95			      DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0,96			      NULL, 0),97 98	SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,99			      AFE_ADDA_UL_SRC_CON0,100			      UL_SRC_ON_TMP_CTL_SFT, 0,101			      mtk_adda_ul_event,102			      SND_SOC_DAPM_POST_PMD),103 104	SND_SOC_DAPM_SUPPLY_S("aud_dac_clk", SUPPLY_SEQ_AUD_TOP_PDN,105			      AUDIO_TOP_CON0, PDN_DAC_SFT, 1,106			      NULL, 0),107	SND_SOC_DAPM_SUPPLY_S("aud_dac_predis_clk", SUPPLY_SEQ_AUD_TOP_PDN,108			      AUDIO_TOP_CON0, PDN_DAC_PREDIS_SFT, 1,109			      NULL, 0),110 111	SND_SOC_DAPM_SUPPLY_S("aud_adc_clk", SUPPLY_SEQ_AUD_TOP_PDN,112			      AUDIO_TOP_CON0, PDN_ADC_SFT, 1,113			      NULL, 0),114 115	SND_SOC_DAPM_CLOCK_SUPPLY("mtkaif_26m_clk"),116};117 118static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {119	/* playback */120	{"ADDA_DL_CH1", "DL1_CH1", "DL1"},121	{"ADDA_DL_CH2", "DL1_CH1", "DL1"},122	{"ADDA_DL_CH2", "DL1_CH2", "DL1"},123 124	{"ADDA_DL_CH1", "DL2_CH1", "DL2"},125	{"ADDA_DL_CH2", "DL2_CH1", "DL2"},126	{"ADDA_DL_CH2", "DL2_CH2", "DL2"},127 128	{"ADDA_DL_CH1", "DL3_CH1", "DL3"},129	{"ADDA_DL_CH2", "DL3_CH1", "DL3"},130	{"ADDA_DL_CH2", "DL3_CH2", "DL3"},131 132	{"ADDA Playback", NULL, "ADDA_DL_CH1"},133	{"ADDA Playback", NULL, "ADDA_DL_CH2"},134 135	/* adda enable */136	{"ADDA Playback", NULL, "ADDA Enable"},137	{"ADDA Playback", NULL, "ADDA Playback Enable"},138	{"ADDA Capture", NULL, "ADDA Enable"},139	{"ADDA Capture", NULL, "ADDA Capture Enable"},140 141	/* clk */142	{"ADDA Playback", NULL, "mtkaif_26m_clk"},143	{"ADDA Playback", NULL, "aud_dac_clk"},144	{"ADDA Playback", NULL, "aud_dac_predis_clk"},145 146	{"ADDA Capture", NULL, "mtkaif_26m_clk"},147	{"ADDA Capture", NULL, "aud_adc_clk"},148};149 150/* dai ops */151static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,152				  struct snd_pcm_hw_params *params,153				  struct snd_soc_dai *dai)154{155	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);156	unsigned int rate = params_rate(params);157 158	dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",159		__func__, dai->id, substream->stream, rate);160 161	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {162		unsigned int dl_src2_con0 = 0;163		unsigned int dl_src2_con1 = 0;164 165		/* clean predistortion */166		regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0);167		regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0);168 169		/* set input sampling rate */170		dl_src2_con0 = mtk_adda_dl_rate_transform(afe, rate) << 28;171 172		/* set output mode */173		switch (rate) {174		case 192000:175			dl_src2_con0 |= (0x1 << 24); /* UP_SAMPLING_RATE_X2 */176			dl_src2_con0 |= 1 << 14;177			break;178		case 96000:179			dl_src2_con0 |= (0x2 << 24); /* UP_SAMPLING_RATE_X4 */180			dl_src2_con0 |= 1 << 14;181			break;182		default:183			dl_src2_con0 |= (0x3 << 24); /* UP_SAMPLING_RATE_X8 */184			break;185		}186 187		/* turn off mute function */188		dl_src2_con0 |= (0x03 << 11);189 190		/* set voice input data if input sample rate is 8k or 16k */191		if (rate == 8000 || rate == 16000)192			dl_src2_con0 |= 0x01 << 5;193 194		if (rate < 96000) {195			/* SA suggest apply -0.3db to audio/speech path */196			dl_src2_con1 = 0xf74f0000;197		} else {198			/* SA suggest apply -0.3db to audio/speech path199			 * with DL gain set to half,200			 * 0xFFFF = 0dB -> 0x8000 = 0dB when 96k, 192k201			 */202			dl_src2_con1 = 0x7ba70000;203		}204 205		/* turn on down-link gain */206		dl_src2_con0 = dl_src2_con0 | (0x01 << 1);207 208		regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON0, dl_src2_con0);209		regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON1, dl_src2_con1);210	} else {211		unsigned int voice_mode = 0;212		unsigned int ul_src_con0 = 0;	/* default value */213 214		/* Using Internal ADC */215		regmap_update_bits(afe->regmap,216				   AFE_ADDA_TOP_CON0,217				   0x1 << 0,218				   0x0 << 0);219 220		voice_mode = mtk_adda_ul_rate_transform(afe, rate);221 222		ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);223 224		/* up8x txif sat on */225		regmap_write(afe->regmap, AFE_ADDA_NEWIF_CFG0, 0x03F87201);226 227		if (rate >= 96000) {	/* hires */228			/* use hires format [1 0 23] */229			regmap_update_bits(afe->regmap,230					   AFE_ADDA_NEWIF_CFG0,231					   0x1 << 5,232					   0x1 << 5);233 234			regmap_update_bits(afe->regmap,235					   AFE_ADDA_NEWIF_CFG2,236					   0xf << 28,237					   voice_mode << 28);238		} else {	/* normal 8~48k */239			/* use fixed 260k anc path */240			regmap_update_bits(afe->regmap,241					   AFE_ADDA_NEWIF_CFG2,242					   0xf << 28,243					   8 << 28);244 245			/* ul_use_cic_out */246			ul_src_con0 |= 0x1 << 20;247		}248 249		regmap_update_bits(afe->regmap,250				   AFE_ADDA_NEWIF_CFG2,251				   0xf << 28,252				   8 << 28);253 254		regmap_update_bits(afe->regmap,255				   AFE_ADDA_UL_SRC_CON0,256				   0xfffffffe,257				   ul_src_con0);258	}259 260	return 0;261}262 263static const struct snd_soc_dai_ops mtk_dai_adda_ops = {264	.hw_params = mtk_dai_adda_hw_params,265};266 267/* dai driver */268#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\269				 SNDRV_PCM_RATE_96000 |\270				 SNDRV_PCM_RATE_192000)271 272#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\273				SNDRV_PCM_RATE_16000 |\274				SNDRV_PCM_RATE_32000 |\275				SNDRV_PCM_RATE_48000 |\276				SNDRV_PCM_RATE_96000 |\277				SNDRV_PCM_RATE_192000)278 279#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\280			  SNDRV_PCM_FMTBIT_S24_LE |\281			  SNDRV_PCM_FMTBIT_S32_LE)282 283static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {284	{285		.name = "ADDA",286		.id = MT6797_DAI_ADDA,287		.playback = {288			.stream_name = "ADDA Playback",289			.channels_min = 1,290			.channels_max = 2,291			.rates = MTK_ADDA_PLAYBACK_RATES,292			.formats = MTK_ADDA_FORMATS,293		},294		.capture = {295			.stream_name = "ADDA Capture",296			.channels_min = 1,297			.channels_max = 2,298			.rates = MTK_ADDA_CAPTURE_RATES,299			.formats = MTK_ADDA_FORMATS,300		},301		.ops = &mtk_dai_adda_ops,302	},303};304 305int mt6797_dai_adda_register(struct mtk_base_afe *afe)306{307	struct mtk_base_afe_dai *dai;308 309	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);310	if (!dai)311		return -ENOMEM;312 313	list_add(&dai->list, &afe->sub_dais);314 315	dai->dai_drivers = mtk_dai_adda_driver;316	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);317 318	dai->dapm_widgets = mtk_dai_adda_widgets;319	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);320	dai->dapm_routes = mtk_dai_adda_routes;321	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);322	return 0;323}324