File Index
Files and directories
Sign in
FILE

mt8365-dai-i2s.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * MediaTek 8365 ALSA SoC Audio DAI I2S Control
  4 *
  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
 16#define IIR_RATIOVER 9
 17#define IIR_INV_COEF 10
 18#define IIR_NO_NEED 11
 19
 20struct mtk_afe_i2s_priv {
 21	bool adda_link;
 22	int i2s_out_on_ref_cnt;
 23	int id;
 24	int low_jitter_en;
 25	int mclk_id;
 26	int share_i2s_id;
 27	unsigned int clk_id_in;
 28	unsigned int clk_id_in_m_sel;
 29	unsigned int clk_id_out;
 30	unsigned int clk_id_out_m_sel;
 31	unsigned int clk_in_mult;
 32	unsigned int clk_out_mult;
 33	unsigned int config_val_in;
 34	unsigned int config_val_out;
 35	unsigned int dynamic_bck;
 36	unsigned int reg_off_in;
 37	unsigned int reg_off_out;
 38};
 39
 40/* This enum is merely for mtk_afe_i2s_priv declare */
 41enum {
 42	DAI_I2S0 = 0,
 43	DAI_I2S3,
 44	DAI_I2S_NUM,
 45};
 46
 47static const struct mtk_afe_i2s_priv mt8365_i2s_priv[DAI_I2S_NUM] = {
 48	[DAI_I2S0] = {
 49		.id = MT8365_AFE_IO_I2S,
 50		.mclk_id = MT8365_I2S0_MCK,
 51		.share_i2s_id = -1,
 52		.clk_id_in = MT8365_CLK_AUD_I2S2_M,
 53		.clk_id_out = MT8365_CLK_AUD_I2S1_M,
 54		.clk_id_in_m_sel = MT8365_CLK_I2S2_M_SEL,
 55		.clk_id_out_m_sel = MT8365_CLK_I2S1_M_SEL,
 56		.clk_in_mult = 256,
 57		.clk_out_mult = 256,
 58		.adda_link = true,
 59		.config_val_out = AFE_I2S_CON1_I2S2_TO_PAD,
 60		.reg_off_in = AFE_I2S_CON2,
 61		.reg_off_out = AFE_I2S_CON1,
 62	},
 63	[DAI_I2S3] = {
 64		.id = MT8365_AFE_IO_2ND_I2S,
 65		.mclk_id = MT8365_I2S3_MCK,
 66		.share_i2s_id = -1,
 67		.clk_id_in = MT8365_CLK_AUD_I2S0_M,
 68		.clk_id_out = MT8365_CLK_AUD_I2S3_M,
 69		.clk_id_in_m_sel = MT8365_CLK_I2S0_M_SEL,
 70		.clk_id_out_m_sel = MT8365_CLK_I2S3_M_SEL,
 71		.clk_in_mult = 256,
 72		.clk_out_mult = 256,
 73		.adda_link = false,
 74		.config_val_in = AFE_I2S_CON_FROM_IO_MUX,
 75		.reg_off_in = AFE_I2S_CON,
 76		.reg_off_out = AFE_I2S_CON3,
 77	},
 78};
 79
 80static const u32 *get_iir_coef(unsigned int input_fs,
 81			       unsigned int output_fs, unsigned int *count)
 82{
 83	static const u32 IIR_COEF_48_TO_44p1[30] = {
 84		0x061fb0, 0x0bd256, 0x061fb0, 0xe3a3e6, 0xf0a300, 0x000003,
 85		0x0e416d, 0x1bb577, 0x0e416d, 0xe59178, 0xf23637, 0x000003,
 86		0x0c7d72, 0x189060, 0x0c7d72, 0xe96f09, 0xf505b2, 0x000003,
 87		0x126054, 0x249143, 0x126054, 0xe1fc0c, 0xf4b20a, 0x000002,
 88		0x000000, 0x323c85, 0x323c85, 0xf76d4e, 0x000000, 0x000002,
 89	};
 90
 91	static const u32 IIR_COEF_44p1_TO_32[42] = {
 92		0x0a6074, 0x0d237a, 0x0a6074, 0xdd8d6c, 0xe0b3f6, 0x000002,
 93		0x0e41f8, 0x128d48, 0x0e41f8, 0xefc14e, 0xf12d7a, 0x000003,
 94		0x0cfa60, 0x11e89c, 0x0cfa60, 0xf1b09e, 0xf27205, 0x000003,
 95		0x15b69c, 0x20e7e4, 0x15b69c, 0xea799a, 0xe9314a, 0x000002,
 96		0x0f79e2, 0x1a7064, 0x0f79e2, 0xf65e4a, 0xf03d8e, 0x000002,
 97		0x10c34f, 0x1ffe4b, 0x10c34f, 0x0bbecb, 0xf2bc4b, 0x000001,
 98		0x000000, 0x23b063, 0x23b063, 0x07335f, 0x000000, 0x000002,
 99	};
100
101	static const u32 IIR_COEF_48_TO_32[42] = {
102		0x0a2a9b, 0x0a2f05, 0x0a2a9b, 0xe73873, 0xe0c525, 0x000002,
103		0x0dd4ad, 0x0e765a, 0x0dd4ad, 0xf49808, 0xf14844, 0x000003,
104		0x18a8cd, 0x1c40d0, 0x18a8cd, 0xed2aab, 0xe542ec, 0x000002,
105		0x13e044, 0x1a47c4, 0x13e044, 0xf44aed, 0xe9acc7, 0x000002,
106		0x1abd9c, 0x2a5429, 0x1abd9c, 0xff3441, 0xe0fc5f, 0x000001,
107		0x0d86db, 0x193e2e, 0x0d86db, 0x1a6f15, 0xf14507, 0x000001,
108		0x000000, 0x1f820c, 0x1f820c, 0x0a1b1f, 0x000000, 0x000002,
109	};
110
111	static const u32 IIR_COEF_32_TO_16[48] = {
112		0x122893, 0xffadd4, 0x122893, 0x0bc205, 0xc0ee1c, 0x000001,
113		0x1bab8a, 0x00750d, 0x1bab8a, 0x06a983, 0xe18a5c, 0x000002,
114		0x18f68e, 0x02706f, 0x18f68e, 0x0886a9, 0xe31bcb, 0x000002,
115		0x149c05, 0x054487, 0x149c05, 0x0bec31, 0xe5973e, 0x000002,
116		0x0ea303, 0x07f24a, 0x0ea303, 0x115ff9, 0xe967b6, 0x000002,
117		0x0823fd, 0x085531, 0x0823fd, 0x18d5b4, 0xee8d21, 0x000002,
118		0x06888e, 0x0acbbb, 0x06888e, 0x40b55c, 0xe76dce, 0x000001,
119		0x000000, 0x2d31a9, 0x2d31a9, 0x23ba4f, 0x000000, 0x000001,
120	};
121
122	static const u32 IIR_COEF_96_TO_44p1[48] = {
123		0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
124		0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
125		0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
126		0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
127		0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
128		0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
129		0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
130		0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
131	};
132
133	static const u32 IIR_COEF_44p1_TO_16[48] = {
134		0x0998fb, 0xf7f925, 0x0998fb, 0x1e54a0, 0xe06605, 0x000002,
135		0x0d828e, 0xf50f97, 0x0d828e, 0x0f41b5, 0xf0a999, 0x000003,
136		0x17ebeb, 0xee30d8, 0x17ebeb, 0x1f48ca, 0xe2ae88, 0x000002,
137		0x12fab5, 0xf46ddc, 0x12fab5, 0x20cc51, 0xe4d068, 0x000002,
138		0x0c7ac6, 0xfbd00e, 0x0c7ac6, 0x2337da, 0xe8028c, 0x000002,
139		0x060ddc, 0x015b3e, 0x060ddc, 0x266754, 0xec21b6, 0x000002,
140		0x0407b5, 0x04f827, 0x0407b5, 0x52e3d0, 0xe0149f, 0x000001,
141		0x000000, 0x1f9521, 0x1f9521, 0x2ac116, 0x000000, 0x000001,
142	};
143
144	static const u32 IIR_COEF_48_TO_16[48] = {
145		0x0955ff, 0xf6544a, 0x0955ff, 0x2474e5, 0xe062e6, 0x000002,
146		0x0d4180, 0xf297f4, 0x0d4180, 0x12415b, 0xf0a3b0, 0x000003,
147		0x0ba079, 0xf4f0b0, 0x0ba079, 0x1285d3, 0xf1488b, 0x000003,
148		0x12247c, 0xf1033c, 0x12247c, 0x2625be, 0xe48e0d, 0x000002,
149		0x0b98e0, 0xf96d1a, 0x0b98e0, 0x27e79c, 0xe7798a, 0x000002,
150		0x055e3b, 0xffed09, 0x055e3b, 0x2a2e2d, 0xeb2854, 0x000002,
151		0x01a934, 0x01ca03, 0x01a934, 0x2c4fea, 0xee93ab, 0x000002,
152		0x000000, 0x1c46c5, 0x1c46c5, 0x2d37dc, 0x000000, 0x000001,
153	};
154
155	static const u32 IIR_COEF_96_TO_16[48] = {
156		0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
157		0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
158		0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
159		0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
160		0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
161		0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
162		0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
163		0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
164	};
165
166	static const struct {
167		const u32 *coef;
168		unsigned int cnt;
169	} iir_coef_tbl_list[8] = {
170		/* 0: 0.9188 */
171		{ IIR_COEF_48_TO_44p1, ARRAY_SIZE(IIR_COEF_48_TO_44p1) },
172		/* 1: 0.7256 */
173		{ IIR_COEF_44p1_TO_32, ARRAY_SIZE(IIR_COEF_44p1_TO_32) },
174		/* 2: 0.6667 */
175		{ IIR_COEF_48_TO_32, ARRAY_SIZE(IIR_COEF_48_TO_32) },
176		/* 3: 0.5 */
177		{ IIR_COEF_32_TO_16, ARRAY_SIZE(IIR_COEF_32_TO_16) },
178		/* 4: 0.4594 */
179		{ IIR_COEF_96_TO_44p1, ARRAY_SIZE(IIR_COEF_96_TO_44p1) },
180		/* 5: 0.3628 */
181		{ IIR_COEF_44p1_TO_16, ARRAY_SIZE(IIR_COEF_44p1_TO_16) },
182		/* 6: 0.3333 */
183		{ IIR_COEF_48_TO_16, ARRAY_SIZE(IIR_COEF_48_TO_16) },
184		/* 7: 0.1667 */
185		{ IIR_COEF_96_TO_16, ARRAY_SIZE(IIR_COEF_96_TO_16) },
186	};
187
188	static const u32 freq_new_index[16] = {
189		0, 1, 2, 99, 3, 4, 5, 99, 6, 7, 8, 9, 10, 11, 12, 99
190	};
191
192	static const u32 iir_coef_tbl_matrix[13][13] = {
193		{/*0*/
194			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
195			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
196			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
197		},
198		{/*1*/
199			1, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
200			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
201			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
202		},
203		{/*2*/
204			2, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
205			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
206			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
207		},
208		{/*3*/
209			3, IIR_INV_COEF, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED,
210			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
211			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
212		},
213		{/*4*/
214			5, 3, IIR_INV_COEF, 2, IIR_NO_NEED, IIR_NO_NEED,
215			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
216			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
217		},
218		{/*5*/
219			6, 4, 3, 2, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
220			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
221			IIR_NO_NEED, IIR_NO_NEED
222		},
223		{/*6*/
224			IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 3, IIR_INV_COEF,
225			IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
226			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
227		},
228		{/*7*/
229			IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 5, 3,
230			IIR_INV_COEF, 1, IIR_NO_NEED, IIR_NO_NEED,
231			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
232		},
233		{/*8*/
234			7, IIR_INV_COEF, IIR_INV_COEF, 6, 4, 3, 2, 0, IIR_NO_NEED,
235			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
236		},
237		{/*9*/
238			IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
239			IIR_INV_COEF, IIR_INV_COEF, 5, 3, IIR_INV_COEF,
240			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
241		},
242		{/*10*/
243			IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,
244			IIR_INV_COEF, 6, 4, 3, 0,
245			IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
246		},
247		{ /*11*/
248			IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
249			IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
250			IIR_INV_COEF, 3, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED
251		},
252		{/*12*/
253			IIR_RATIOVER, IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF,
254			IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,
255			IIR_INV_COEF, 4, 3, 0, IIR_NO_NEED
256		},
257	};
258
259	const u32 *coef = NULL;
260	unsigned int cnt = 0;
261	u32 i = freq_new_index[input_fs];
262	u32 j = freq_new_index[output_fs];
263
264	if (i < 13 && j < 13) {
265		u32 k = iir_coef_tbl_matrix[i][j];
266
267		if (k >= IIR_NO_NEED) {
268		} else if (k == IIR_RATIOVER) {
269		} else if (k == IIR_INV_COEF) {
270		} else {
271			coef = iir_coef_tbl_list[k].coef;
272			cnt = iir_coef_tbl_list[k].cnt;
273		}
274	}
275	*count = cnt;
276	return coef;
277}
278
279static int mt8365_dai_set_config(struct mtk_base_afe *afe,
280				 struct mtk_afe_i2s_priv *i2s_data,
281				 bool is_input, unsigned int rate,
282				 int bit_width)
283{
284	struct mt8365_afe_private *afe_priv = afe->platform_priv;
285	struct mt8365_be_dai_data *be =
286	&afe_priv->be_data[i2s_data->id - MT8365_AFE_BACKEND_BASE];
287	unsigned int val, reg_off;
288	int fs = mt8365_afe_fs_timing(rate);
289
290	if (fs < 0)
291		return -EINVAL;
292
293	val = AFE_I2S_CON_LOW_JITTER_CLK | AFE_I2S_CON_FORMAT_I2S;
294	val |= FIELD_PREP(AFE_I2S_CON_RATE_MASK, fs);
295
296	if (is_input) {
297		reg_off = i2s_data->reg_off_in;
298		if (i2s_data->adda_link)
299			val |= i2s_data->config_val_in;
300	} else {
301		reg_off = i2s_data->reg_off_out;
302		val |= i2s_data->config_val_in;
303	}
304
305	/* 1:bck=32lrck(16bit) or bck=64lrck(32bit) 0:fix bck=64lrck */
306	if (i2s_data->dynamic_bck) {
307		if (bit_width > 16)
308			val |= AFE_I2S_CON_WLEN_32BIT;
309		else
310			val &= ~(u32)AFE_I2S_CON_WLEN_32BIT;
311	} else {
312		val |= AFE_I2S_CON_WLEN_32BIT;
313	}
314
315	if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
316	    SND_SOC_DAIFMT_CBP_CFP) {
317		val |= AFE_I2S_CON_SRC_SLAVE;
318		val &= ~(u32)AFE_I2S_CON_FROM_IO_MUX;//from consys
319	}
320
321	regmap_update_bits(afe->regmap, reg_off, ~(u32)AFE_I2S_CON_EN, val);
322
323	if (i2s_data->adda_link && is_input)
324		regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);
325
326	return 0;
327}
328
329int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe,
330			   unsigned int rate, int bit_width)
331{
332	struct mt8365_afe_private *afe_priv = afe->platform_priv;
333	struct mtk_afe_i2s_priv *i2s_data =
334		afe_priv->dai_priv[MT8365_AFE_IO_I2S];
335
336	return mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
337}
338
339static int mt8365_afe_set_2nd_i2s_asrc(struct mtk_base_afe *afe,
340				       unsigned int rate_in,
341				       unsigned int rate_out,
342				       unsigned int width,
343				       unsigned int mono,
344				       int o16bit, int tracking)
345{
346	int ifs, ofs = 0;
347	unsigned int val = 0;
348	unsigned int mask = 0;
349	const u32 *coef;
350	u32 iir_stage;
351	unsigned int coef_count = 0;
352
353	ifs = mt8365_afe_fs_timing(rate_in);
354
355	if (ifs < 0)
356		return -EINVAL;
357
358	ofs = mt8365_afe_fs_timing(rate_out);
359
360	if (ofs < 0)
361		return -EINVAL;
362
363	val = FIELD_PREP(O16BIT, o16bit) | FIELD_PREP(IS_MONO, mono);
364	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
365			   O16BIT | IS_MONO, val);
366
367	coef = get_iir_coef(ifs, ofs, &coef_count);
368	iir_stage = ((u32)coef_count / 6) - 1;
369
370	if (coef) {
371		unsigned int i;
372
373		/* CPU control IIR coeff SRAM */
374		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
375				   COEFF_SRAM_CTRL, COEFF_SRAM_CTRL);
376
377		/* set to 0, IIR coeff SRAM addr */
378		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON13,
379				   0xffffffff, 0x0);
380
381		for (i = 0; i < coef_count; ++i)
382			regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON12,
383					   0xffffffff, coef[i]);
384
385		/* disable IIR coeff SRAM access */
386		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
387				   COEFF_SRAM_CTRL,
388				   ~COEFF_SRAM_CTRL);
389		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
390				   CLR_IIR_HISTORY | IIR_EN | IIR_STAGE_MASK,
391				   CLR_IIR_HISTORY | IIR_EN |
392				   FIELD_PREP(IIR_STAGE_MASK, iir_stage));
393	} else {
394		/* disable IIR */
395		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
396				   IIR_EN, ~IIR_EN);
397	}
398
399	/* CON3 setting (RX OFS) */
400	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON3,
401			   0x00FFFFFF, rx_frequency_palette(ofs));
402	/* CON4 setting (RX IFS) */
403	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON4,
404			   0x00FFFFFF, rx_frequency_palette(ifs));
405
406	/* CON5 setting */
407	if (tracking) {
408		val = CALI_64_CYCLE |
409		      CALI_AUTORST |
410		      AUTO_TUNE_FREQ5 |
411		      COMP_FREQ_RES |
412		      CALI_BP_DGL |
413		      CALI_AUTO_RESTART |
414		      CALI_USE_FREQ_OUT |
415		      CALI_SEL_01;
416
417		mask = CALI_CYCLE_MASK |
418		       CALI_AUTORST |
419		       AUTO_TUNE_FREQ5 |
420		       COMP_FREQ_RES |
421		       CALI_SEL_MASK |
422		       CALI_BP_DGL |
423		       AUTO_TUNE_FREQ4 |
424		       CALI_AUTO_RESTART |
425		       CALI_USE_FREQ_OUT |
426		       CALI_ON;
427
428		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
429				   mask, val);
430		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
431				   CALI_ON, CALI_ON);
432	} else {
433		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
434				   0xffffffff, 0x0);
435	}
436	/* CON6 setting fix 8125 */
437	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON6,
438			   0x0000ffff, 0x1FBD);
439	/* CON9 setting (RX IFS) */
440	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON9,
441			   0x000fffff, AutoRstThHi(ifs));
442	/* CON10 setting (RX IFS) */
443	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON10,
444			   0x000fffff, AutoRstThLo(ifs));
445	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
446			   CHSET_STR_CLR, CHSET_STR_CLR);
447
448	return 0;
449}
450
451static int mt8365_afe_set_2nd_i2s_asrc_enable(struct mtk_base_afe *afe,
452					      bool enable)
453{
454	if (enable)
455		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
456				   ASM_ON, ASM_ON);
457	else
458		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
459				   ASM_ON, ~ASM_ON);
460	return 0;
461}
462
463void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)
464{
465	int i;
466	unsigned long flags;
467	struct mt8365_afe_private *afe_priv = afe->platform_priv;
468	struct mtk_afe_i2s_priv *i2s_data = NULL;
469
470	for (i = 0; i < DAI_I2S_NUM; i++) {
471		if (mt8365_i2s_priv[i].adda_link)
472			i2s_data = afe_priv->dai_priv[mt8365_i2s_priv[i].id];
473	}
474
475	if (!i2s_data)
476		return;
477
478	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
479
480	if (enable) {
481		i2s_data->i2s_out_on_ref_cnt++;
482		if (i2s_data->i2s_out_on_ref_cnt == 1)
483			regmap_update_bits(afe->regmap, AFE_I2S_CON1,
484					   0x1, enable);
485	} else {
486		i2s_data->i2s_out_on_ref_cnt--;
487		if (i2s_data->i2s_out_on_ref_cnt == 0)
488			regmap_update_bits(afe->regmap, AFE_I2S_CON1,
489					   0x1, enable);
490		else if (i2s_data->i2s_out_on_ref_cnt < 0)
491			i2s_data->i2s_out_on_ref_cnt = 0;
492	}
493
494	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
495}
496
497static void mt8365_dai_set_enable(struct mtk_base_afe *afe,
498				  struct mtk_afe_i2s_priv *i2s_data,
499				  bool is_input, bool enable)
500{
501	unsigned int reg_off;
502
503	if (is_input) {
504		reg_off = i2s_data->reg_off_in;
505	} else {
506		if (i2s_data->adda_link) {
507			mt8365_afe_set_i2s_out_enable(afe, enable);
508			return;
509		}
510		reg_off = i2s_data->reg_off_out;
511	}
512	regmap_update_bits(afe->regmap, reg_off,
513			   0x1, enable);
514}
515
516static int mt8365_dai_i2s_startup(struct snd_pcm_substream *substream,
517				  struct snd_soc_dai *dai)
518{
519	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
520	struct mt8365_afe_private *afe_priv = afe->platform_priv;
521	struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
522	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
523	bool i2s_in_slave =
524		(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
525		((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
526		SND_SOC_DAIFMT_CBP_CFP);
527
528	mt8365_afe_enable_main_clk(afe);
529
530	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
531		clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_out]);
532
533	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !i2s_in_slave)
534		clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_in]);
535
536	if (i2s_in_slave)
537		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
538
539	return 0;
540}
541
542static void mt8365_dai_i2s_shutdown(struct snd_pcm_substream *substream,
543				    struct snd_soc_dai *dai)
544{
545	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
546	struct mt8365_afe_private *afe_priv = afe->platform_priv;
547	struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
548	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
549	bool reset_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
550	bool reset_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
551	bool i2s_in_slave =
552		(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
553		((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
554		SND_SOC_DAIFMT_CBP_CFP);
555
556	if (be->prepared[substream->stream]) {
557		if (reset_i2s_out_change)
558			mt8365_dai_set_enable(afe, i2s_data, false, false);
559
560		if (reset_i2s_in_change)
561			mt8365_dai_set_enable(afe, i2s_data, true, false);
562
563		if (substream->runtime->rate % 8000)
564			mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
565		else
566			mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
567
568		if (reset_i2s_out_change)
569			be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = false;
570
571		if (reset_i2s_in_change)
572			be->prepared[SNDRV_PCM_STREAM_CAPTURE] = false;
573	}
574
575	if (reset_i2s_out_change)
576		mt8365_afe_disable_clk(afe,
577				       afe_priv->clocks[i2s_data->clk_id_out]);
578
579	if (reset_i2s_in_change && !i2s_in_slave)
580		mt8365_afe_disable_clk(afe,
581				       afe_priv->clocks[i2s_data->clk_id_in]);
582
583	if (i2s_in_slave)
584		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
585
586	mt8365_afe_disable_main_clk(afe);
587}
588
589static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream,
590				  struct snd_soc_dai *dai)
591{
592	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
593	struct mt8365_afe_private *afe_priv = afe->platform_priv;
594	struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
595	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
596	bool apply_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
597	bool apply_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
598	unsigned int rate = substream->runtime->rate;
599	int bit_width = snd_pcm_format_width(substream->runtime->format);
600	int ret;
601
602	if (be->prepared[substream->stream]) {
603		dev_info(afe->dev, "%s '%s' prepared already\n",
604			 __func__, snd_pcm_stream_str(substream));
605		return 0;
606	}
607
608	if (apply_i2s_out_change) {
609		ret = mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
610		if (ret)
611			return ret;
612	}
613
614	if (apply_i2s_in_change) {
615		if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
616		    == SND_SOC_DAIFMT_CBP_CFP) {
617			ret = mt8365_afe_set_2nd_i2s_asrc(afe, 32000, rate,
618							  (unsigned int)bit_width,
619							  0, 0, 1);
620			if (ret < 0)
621				return ret;
622		}
623		ret = mt8365_dai_set_config(afe, i2s_data, true, rate, bit_width);
624		if (ret)
625			return ret;
626	}
627
628	if (rate % 8000)
629		mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
630	else
631		mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
632
633	if (apply_i2s_out_change) {
634		mt8365_afe_set_clk_parent(afe,
635					  afe_priv->clocks[i2s_data->clk_id_out_m_sel],
636					  ((rate % 8000) ?
637					  afe_priv->clocks[MT8365_CLK_AUD1] :
638					  afe_priv->clocks[MT8365_CLK_AUD2]));
639
640		mt8365_afe_set_clk_rate(afe,
641					afe_priv->clocks[i2s_data->clk_id_out],
642					rate * i2s_data->clk_out_mult);
643
644		mt8365_dai_set_enable(afe, i2s_data, false, true);
645		be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = true;
646	}
647
648	if (apply_i2s_in_change) {
649		mt8365_afe_set_clk_parent(afe,
650					  afe_priv->clocks[i2s_data->clk_id_in_m_sel],
651					  ((rate % 8000) ?
652					  afe_priv->clocks[MT8365_CLK_AUD1] :
653					  afe_priv->clocks[MT8365_CLK_AUD2]));
654
655		mt8365_afe_set_clk_rate(afe,
656					afe_priv->clocks[i2s_data->clk_id_in],
657					rate * i2s_data->clk_in_mult);
658
659		mt8365_dai_set_enable(afe, i2s_data, true, true);
660
661		if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
662		    == SND_SOC_DAIFMT_CBP_CFP)
663			mt8365_afe_set_2nd_i2s_asrc_enable(afe, true);
664
665		be->prepared[SNDRV_PCM_STREAM_CAPTURE] = true;
666	}
667	return 0;
668}
669
670static int mt8365_afe_2nd_i2s_hw_params(struct snd_pcm_substream *substream,
671					struct snd_pcm_hw_params *params,
672					struct snd_soc_dai *dai)
673{
674	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
675	unsigned int width_val = params_width(params) > 16 ?
676		(AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01) : 0;
677
678	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
679		regmap_update_bits(afe->regmap, AFE_CONN_24BIT,
680				   AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01, width_val);
681
682	return 0;
683}
684
685static int mt8365_afe_2nd_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
686{
687	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
688	struct mt8365_afe_private *afe_priv = afe->platform_priv;
689	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
690
691	be->fmt_mode = 0;
692
693	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
694	case SND_SOC_DAIFMT_I2S:
695		be->fmt_mode |= SND_SOC_DAIFMT_I2S;
696		break;
697	case SND_SOC_DAIFMT_LEFT_J:
698		be->fmt_mode |= SND_SOC_DAIFMT_LEFT_J;
699		break;
700	default:
701		dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");
702		return -EINVAL;
703	}
704
705	if (((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) &&
706	    ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_IF) &&
707	    ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_NF) &&
708	    ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_IF)) {
709		dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");
710		return -EINVAL;
711	}
712
713	be->fmt_mode |= (fmt & SND_SOC_DAIFMT_INV_MASK);
714
715	if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBP_CFP))
716		be->fmt_mode |= (fmt & SND_SOC_DAIFMT_MASTER_MASK);
717
718	return 0;
719}
720
721static const struct snd_soc_dai_ops mt8365_afe_i2s_ops = {
722	.startup	= mt8365_dai_i2s_startup,
723	.shutdown	= mt8365_dai_i2s_shutdown,
724	.prepare	= mt8365_dai_i2s_prepare,
725};
726
727static const struct snd_soc_dai_ops mt8365_afe_2nd_i2s_ops = {
728	.startup	= mt8365_dai_i2s_startup,
729	.shutdown	= mt8365_dai_i2s_shutdown,
730	.hw_params	= mt8365_afe_2nd_i2s_hw_params,
731	.prepare	= mt8365_dai_i2s_prepare,
732	.set_fmt	= mt8365_afe_2nd_i2s_set_fmt,
733};
734
735static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
736	{
737		.name = "I2S",
738		.id = MT8365_AFE_IO_I2S,
739		.playback = {
740			.stream_name = "I2S Playback",
741			.channels_min = 1,
742			.channels_max = 2,
743			.rates = SNDRV_PCM_RATE_8000_192000,
744			.formats = SNDRV_PCM_FMTBIT_S16_LE |
745				   SNDRV_PCM_FMTBIT_S24_LE |
746				   SNDRV_PCM_FMTBIT_S32_LE,
747		},
748		.capture = {
749			.stream_name = "I2S Capture",
750			.channels_min = 1,
751			.channels_max = 2,
752			.rates = SNDRV_PCM_RATE_8000_192000,
753			.formats = SNDRV_PCM_FMTBIT_S16_LE |
754				   SNDRV_PCM_FMTBIT_S24_LE |
755				   SNDRV_PCM_FMTBIT_S32_LE,
756		},
757		.ops = &mt8365_afe_i2s_ops,
758	}, {
759		.name = "2ND I2S",
760		.id = MT8365_AFE_IO_2ND_I2S,
761		.playback = {
762			.stream_name = "2ND I2S Playback",
763			.channels_min = 1,
764			.channels_max = 2,
765			.rates = SNDRV_PCM_RATE_8000_192000,
766			.formats = SNDRV_PCM_FMTBIT_S16_LE |
767				   SNDRV_PCM_FMTBIT_S24_LE |
768				   SNDRV_PCM_FMTBIT_S32_LE,
769		},
770		.capture = {
771			.stream_name = "2ND I2S Capture",
772			.channels_min = 1,
773			.channels_max = 2,
774			.rates = SNDRV_PCM_RATE_8000_192000,
775			.formats = SNDRV_PCM_FMTBIT_S16_LE |
776				   SNDRV_PCM_FMTBIT_S24_LE |
777				   SNDRV_PCM_FMTBIT_S32_LE,
778		},
779		.ops = &mt8365_afe_2nd_i2s_ops,
780	}
781};
782
783static const char * const fmi2sin_text[] = {
784	"OPEN", "FM_2ND_I2S_IN"
785};
786
787static SOC_ENUM_SINGLE_VIRT_DECL(fmi2sin_enum, fmi2sin_text);
788
789static const struct snd_kcontrol_new fmi2sin_mux =
790	SOC_DAPM_ENUM("FM 2ND I2S Source", fmi2sin_enum);
791
792static const struct snd_kcontrol_new i2s_o03_o04_enable_ctl =
793	SOC_DAPM_SINGLE_VIRT("Switch", 1);
794
795static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
796	SND_SOC_DAPM_SWITCH("I2S O03_O04", SND_SOC_NOPM, 0, 0,
797			    &i2s_o03_o04_enable_ctl),
798	SND_SOC_DAPM_MUX("FM 2ND I2S Mux", SND_SOC_NOPM, 0, 0, &fmi2sin_mux),
799	SND_SOC_DAPM_INPUT("2ND I2S In"),
800};
801
802static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
803	{"I2S O03_O04", "Switch", "O03"},
804	{"I2S O03_O04", "Switch", "O04"},
805	{"I2S Playback", NULL, "I2S O03_O04"},
806	{"2ND I2S Playback", NULL, "O00"},
807	{"2ND I2S Playback", NULL, "O01"},
808	{"2ND I2S Capture", NULL, "2ND I2S In"},
809	{"FM 2ND I2S Mux", "FM_2ND_I2S_IN", "2ND I2S Capture"},
810};
811
812static int mt8365_dai_i2s_set_priv(struct mtk_base_afe *afe)
813{
814	int i, ret;
815
816	for (i = 0; i < DAI_I2S_NUM; i++) {
817		ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id,
818					  sizeof(mt8365_i2s_priv[i]),
819					  &mt8365_i2s_priv[i]);
820		if (ret)
821			return ret;
822	}
823	return 0;
824}
825
826int mt8365_dai_i2s_register(struct mtk_base_afe *afe)
827{
828	struct mtk_base_afe_dai *dai;
829
830	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
831	if (!dai)
832		return -ENOMEM;
833
834	list_add(&dai->list, &afe->sub_dais);
835
836	dai->dai_drivers = mtk_dai_i2s_driver;
837	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
838	dai->dapm_widgets = mtk_dai_i2s_widgets;
839	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
840	dai->dapm_routes = mtk_dai_i2s_routes;
841	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
842
843	/* set all dai i2s private data */
844	return mt8365_dai_i2s_set_priv(afe);
845}
~/ Read-only file preview.