Path: blob/master/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c
26488 views
// SPDX-License-Identifier: GPL-2.01/*2* MediaTek 8365 ALSA SoC Audio DAI I2S Control3*4* Copyright (c) 2024 MediaTek Inc.5* Authors: Jia Zeng <[email protected]>6* Alexandre Mergnat <[email protected]>7*/89#include <linux/bitops.h>10#include <linux/regmap.h>11#include <sound/pcm_params.h>12#include "mt8365-afe-clk.h"13#include "mt8365-afe-common.h"1415#define IIR_RATIOVER 916#define IIR_INV_COEF 1017#define IIR_NO_NEED 111819struct mtk_afe_i2s_priv {20bool adda_link;21int i2s_out_on_ref_cnt;22int id;23int low_jitter_en;24int mclk_id;25int share_i2s_id;26unsigned int clk_id_in;27unsigned int clk_id_in_m_sel;28unsigned int clk_id_out;29unsigned int clk_id_out_m_sel;30unsigned int clk_in_mult;31unsigned int clk_out_mult;32unsigned int config_val_in;33unsigned int config_val_out;34unsigned int dynamic_bck;35unsigned int reg_off_in;36unsigned int reg_off_out;37};3839/* This enum is merely for mtk_afe_i2s_priv declare */40enum {41DAI_I2S0 = 0,42DAI_I2S3,43DAI_I2S_NUM,44};4546static const struct mtk_afe_i2s_priv mt8365_i2s_priv[DAI_I2S_NUM] = {47[DAI_I2S0] = {48.id = MT8365_AFE_IO_I2S,49.mclk_id = MT8365_I2S0_MCK,50.share_i2s_id = -1,51.clk_id_in = MT8365_CLK_AUD_I2S2_M,52.clk_id_out = MT8365_CLK_AUD_I2S1_M,53.clk_id_in_m_sel = MT8365_CLK_I2S2_M_SEL,54.clk_id_out_m_sel = MT8365_CLK_I2S1_M_SEL,55.clk_in_mult = 256,56.clk_out_mult = 256,57.adda_link = true,58.config_val_out = AFE_I2S_CON1_I2S2_TO_PAD,59.reg_off_in = AFE_I2S_CON2,60.reg_off_out = AFE_I2S_CON1,61},62[DAI_I2S3] = {63.id = MT8365_AFE_IO_2ND_I2S,64.mclk_id = MT8365_I2S3_MCK,65.share_i2s_id = -1,66.clk_id_in = MT8365_CLK_AUD_I2S0_M,67.clk_id_out = MT8365_CLK_AUD_I2S3_M,68.clk_id_in_m_sel = MT8365_CLK_I2S0_M_SEL,69.clk_id_out_m_sel = MT8365_CLK_I2S3_M_SEL,70.clk_in_mult = 256,71.clk_out_mult = 256,72.adda_link = false,73.config_val_in = AFE_I2S_CON_FROM_IO_MUX,74.reg_off_in = AFE_I2S_CON,75.reg_off_out = AFE_I2S_CON3,76},77};7879static const u32 *get_iir_coef(unsigned int input_fs,80unsigned int output_fs, unsigned int *count)81{82static const u32 IIR_COEF_48_TO_44p1[30] = {830x061fb0, 0x0bd256, 0x061fb0, 0xe3a3e6, 0xf0a300, 0x000003,840x0e416d, 0x1bb577, 0x0e416d, 0xe59178, 0xf23637, 0x000003,850x0c7d72, 0x189060, 0x0c7d72, 0xe96f09, 0xf505b2, 0x000003,860x126054, 0x249143, 0x126054, 0xe1fc0c, 0xf4b20a, 0x000002,870x000000, 0x323c85, 0x323c85, 0xf76d4e, 0x000000, 0x000002,88};8990static const u32 IIR_COEF_44p1_TO_32[42] = {910x0a6074, 0x0d237a, 0x0a6074, 0xdd8d6c, 0xe0b3f6, 0x000002,920x0e41f8, 0x128d48, 0x0e41f8, 0xefc14e, 0xf12d7a, 0x000003,930x0cfa60, 0x11e89c, 0x0cfa60, 0xf1b09e, 0xf27205, 0x000003,940x15b69c, 0x20e7e4, 0x15b69c, 0xea799a, 0xe9314a, 0x000002,950x0f79e2, 0x1a7064, 0x0f79e2, 0xf65e4a, 0xf03d8e, 0x000002,960x10c34f, 0x1ffe4b, 0x10c34f, 0x0bbecb, 0xf2bc4b, 0x000001,970x000000, 0x23b063, 0x23b063, 0x07335f, 0x000000, 0x000002,98};99100static const u32 IIR_COEF_48_TO_32[42] = {1010x0a2a9b, 0x0a2f05, 0x0a2a9b, 0xe73873, 0xe0c525, 0x000002,1020x0dd4ad, 0x0e765a, 0x0dd4ad, 0xf49808, 0xf14844, 0x000003,1030x18a8cd, 0x1c40d0, 0x18a8cd, 0xed2aab, 0xe542ec, 0x000002,1040x13e044, 0x1a47c4, 0x13e044, 0xf44aed, 0xe9acc7, 0x000002,1050x1abd9c, 0x2a5429, 0x1abd9c, 0xff3441, 0xe0fc5f, 0x000001,1060x0d86db, 0x193e2e, 0x0d86db, 0x1a6f15, 0xf14507, 0x000001,1070x000000, 0x1f820c, 0x1f820c, 0x0a1b1f, 0x000000, 0x000002,108};109110static const u32 IIR_COEF_32_TO_16[48] = {1110x122893, 0xffadd4, 0x122893, 0x0bc205, 0xc0ee1c, 0x000001,1120x1bab8a, 0x00750d, 0x1bab8a, 0x06a983, 0xe18a5c, 0x000002,1130x18f68e, 0x02706f, 0x18f68e, 0x0886a9, 0xe31bcb, 0x000002,1140x149c05, 0x054487, 0x149c05, 0x0bec31, 0xe5973e, 0x000002,1150x0ea303, 0x07f24a, 0x0ea303, 0x115ff9, 0xe967b6, 0x000002,1160x0823fd, 0x085531, 0x0823fd, 0x18d5b4, 0xee8d21, 0x000002,1170x06888e, 0x0acbbb, 0x06888e, 0x40b55c, 0xe76dce, 0x000001,1180x000000, 0x2d31a9, 0x2d31a9, 0x23ba4f, 0x000000, 0x000001,119};120121static const u32 IIR_COEF_96_TO_44p1[48] = {1220x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,1230x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,1240x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,1250x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,1260x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,1270x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,1280x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,1290x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,130};131132static const u32 IIR_COEF_44p1_TO_16[48] = {1330x0998fb, 0xf7f925, 0x0998fb, 0x1e54a0, 0xe06605, 0x000002,1340x0d828e, 0xf50f97, 0x0d828e, 0x0f41b5, 0xf0a999, 0x000003,1350x17ebeb, 0xee30d8, 0x17ebeb, 0x1f48ca, 0xe2ae88, 0x000002,1360x12fab5, 0xf46ddc, 0x12fab5, 0x20cc51, 0xe4d068, 0x000002,1370x0c7ac6, 0xfbd00e, 0x0c7ac6, 0x2337da, 0xe8028c, 0x000002,1380x060ddc, 0x015b3e, 0x060ddc, 0x266754, 0xec21b6, 0x000002,1390x0407b5, 0x04f827, 0x0407b5, 0x52e3d0, 0xe0149f, 0x000001,1400x000000, 0x1f9521, 0x1f9521, 0x2ac116, 0x000000, 0x000001,141};142143static const u32 IIR_COEF_48_TO_16[48] = {1440x0955ff, 0xf6544a, 0x0955ff, 0x2474e5, 0xe062e6, 0x000002,1450x0d4180, 0xf297f4, 0x0d4180, 0x12415b, 0xf0a3b0, 0x000003,1460x0ba079, 0xf4f0b0, 0x0ba079, 0x1285d3, 0xf1488b, 0x000003,1470x12247c, 0xf1033c, 0x12247c, 0x2625be, 0xe48e0d, 0x000002,1480x0b98e0, 0xf96d1a, 0x0b98e0, 0x27e79c, 0xe7798a, 0x000002,1490x055e3b, 0xffed09, 0x055e3b, 0x2a2e2d, 0xeb2854, 0x000002,1500x01a934, 0x01ca03, 0x01a934, 0x2c4fea, 0xee93ab, 0x000002,1510x000000, 0x1c46c5, 0x1c46c5, 0x2d37dc, 0x000000, 0x000001,152};153154static const u32 IIR_COEF_96_TO_16[48] = {1550x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,1560x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,1570x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,1580x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,1590x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,1600x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,1610x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,1620x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,163};164165static const struct {166const u32 *coef;167unsigned int cnt;168} iir_coef_tbl_list[8] = {169/* 0: 0.9188 */170{ IIR_COEF_48_TO_44p1, ARRAY_SIZE(IIR_COEF_48_TO_44p1) },171/* 1: 0.7256 */172{ IIR_COEF_44p1_TO_32, ARRAY_SIZE(IIR_COEF_44p1_TO_32) },173/* 2: 0.6667 */174{ IIR_COEF_48_TO_32, ARRAY_SIZE(IIR_COEF_48_TO_32) },175/* 3: 0.5 */176{ IIR_COEF_32_TO_16, ARRAY_SIZE(IIR_COEF_32_TO_16) },177/* 4: 0.4594 */178{ IIR_COEF_96_TO_44p1, ARRAY_SIZE(IIR_COEF_96_TO_44p1) },179/* 5: 0.3628 */180{ IIR_COEF_44p1_TO_16, ARRAY_SIZE(IIR_COEF_44p1_TO_16) },181/* 6: 0.3333 */182{ IIR_COEF_48_TO_16, ARRAY_SIZE(IIR_COEF_48_TO_16) },183/* 7: 0.1667 */184{ IIR_COEF_96_TO_16, ARRAY_SIZE(IIR_COEF_96_TO_16) },185};186187static const u32 freq_new_index[16] = {1880, 1, 2, 99, 3, 4, 5, 99, 6, 7, 8, 9, 10, 11, 12, 99189};190191static const u32 iir_coef_tbl_matrix[13][13] = {192{/*0*/193IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,194IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,195IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED196},197{/*1*/1981, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,199IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,200IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED201},202{/*2*/2032, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,204IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,205IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED206},207{/*3*/2083, IIR_INV_COEF, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED,209IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,210IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED211},212{/*4*/2135, 3, IIR_INV_COEF, 2, IIR_NO_NEED, IIR_NO_NEED,214IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,215IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED216},217{/*5*/2186, 4, 3, 2, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,219IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,220IIR_NO_NEED, IIR_NO_NEED221},222{/*6*/223IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 3, IIR_INV_COEF,224IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,225IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED226},227{/*7*/228IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 5, 3,229IIR_INV_COEF, 1, IIR_NO_NEED, IIR_NO_NEED,230IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED231},232{/*8*/2337, IIR_INV_COEF, IIR_INV_COEF, 6, 4, 3, 2, 0, IIR_NO_NEED,234IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED235},236{/*9*/237IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,238IIR_INV_COEF, IIR_INV_COEF, 5, 3, IIR_INV_COEF,239IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED240},241{/*10*/242IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,243IIR_INV_COEF, 6, 4, 3, 0,244IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED245},246{ /*11*/247IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,248IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,249IIR_INV_COEF, 3, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED250},251{/*12*/252IIR_RATIOVER, IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF,253IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,254IIR_INV_COEF, 4, 3, 0, IIR_NO_NEED255},256};257258const u32 *coef = NULL;259unsigned int cnt = 0;260u32 i = freq_new_index[input_fs];261u32 j = freq_new_index[output_fs];262263if (i < 13 && j < 13) {264u32 k = iir_coef_tbl_matrix[i][j];265266if (k >= IIR_NO_NEED) {267} else if (k == IIR_RATIOVER) {268} else if (k == IIR_INV_COEF) {269} else {270coef = iir_coef_tbl_list[k].coef;271cnt = iir_coef_tbl_list[k].cnt;272}273}274*count = cnt;275return coef;276}277278static int mt8365_dai_set_config(struct mtk_base_afe *afe,279struct mtk_afe_i2s_priv *i2s_data,280bool is_input, unsigned int rate,281int bit_width)282{283struct mt8365_afe_private *afe_priv = afe->platform_priv;284struct mt8365_be_dai_data *be =285&afe_priv->be_data[i2s_data->id - MT8365_AFE_BACKEND_BASE];286unsigned int val, reg_off;287int fs = mt8365_afe_fs_timing(rate);288289if (fs < 0)290return -EINVAL;291292val = AFE_I2S_CON_LOW_JITTER_CLK | AFE_I2S_CON_FORMAT_I2S;293val |= FIELD_PREP(AFE_I2S_CON_RATE_MASK, fs);294295if (is_input) {296reg_off = i2s_data->reg_off_in;297if (i2s_data->adda_link)298val |= i2s_data->config_val_in;299} else {300reg_off = i2s_data->reg_off_out;301val |= i2s_data->config_val_in;302}303304/* 1:bck=32lrck(16bit) or bck=64lrck(32bit) 0:fix bck=64lrck */305if (i2s_data->dynamic_bck) {306if (bit_width > 16)307val |= AFE_I2S_CON_WLEN_32BIT;308else309val &= ~(u32)AFE_I2S_CON_WLEN_32BIT;310} else {311val |= AFE_I2S_CON_WLEN_32BIT;312}313314if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==315SND_SOC_DAIFMT_CBP_CFP) {316val |= AFE_I2S_CON_SRC_SLAVE;317val &= ~(u32)AFE_I2S_CON_FROM_IO_MUX;//from consys318}319320regmap_update_bits(afe->regmap, reg_off, ~(u32)AFE_I2S_CON_EN, val);321322if (i2s_data->adda_link && is_input)323regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);324325return 0;326}327328int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe,329unsigned int rate, int bit_width)330{331struct mt8365_afe_private *afe_priv = afe->platform_priv;332struct mtk_afe_i2s_priv *i2s_data =333afe_priv->dai_priv[MT8365_AFE_IO_I2S];334335return mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);336}337338static int mt8365_afe_set_2nd_i2s_asrc(struct mtk_base_afe *afe,339unsigned int rate_in,340unsigned int rate_out,341unsigned int width,342unsigned int mono,343int o16bit, int tracking)344{345int ifs, ofs = 0;346unsigned int val = 0;347unsigned int mask = 0;348const u32 *coef;349u32 iir_stage;350unsigned int coef_count = 0;351352ifs = mt8365_afe_fs_timing(rate_in);353354if (ifs < 0)355return -EINVAL;356357ofs = mt8365_afe_fs_timing(rate_out);358359if (ofs < 0)360return -EINVAL;361362val = FIELD_PREP(O16BIT, o16bit) | FIELD_PREP(IS_MONO, mono);363regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,364O16BIT | IS_MONO, val);365366coef = get_iir_coef(ifs, ofs, &coef_count);367iir_stage = ((u32)coef_count / 6) - 1;368369if (coef) {370unsigned int i;371372/* CPU control IIR coeff SRAM */373regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,374COEFF_SRAM_CTRL, COEFF_SRAM_CTRL);375376/* set to 0, IIR coeff SRAM addr */377regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON13,3780xffffffff, 0x0);379380for (i = 0; i < coef_count; ++i)381regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON12,3820xffffffff, coef[i]);383384/* disable IIR coeff SRAM access */385regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,386COEFF_SRAM_CTRL,387~COEFF_SRAM_CTRL);388regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,389CLR_IIR_HISTORY | IIR_EN | IIR_STAGE_MASK,390CLR_IIR_HISTORY | IIR_EN |391FIELD_PREP(IIR_STAGE_MASK, iir_stage));392} else {393/* disable IIR */394regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,395IIR_EN, ~IIR_EN);396}397398/* CON3 setting (RX OFS) */399regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON3,4000x00FFFFFF, rx_frequency_palette(ofs));401/* CON4 setting (RX IFS) */402regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON4,4030x00FFFFFF, rx_frequency_palette(ifs));404405/* CON5 setting */406if (tracking) {407val = CALI_64_CYCLE |408CALI_AUTORST |409AUTO_TUNE_FREQ5 |410COMP_FREQ_RES |411CALI_BP_DGL |412CALI_AUTO_RESTART |413CALI_USE_FREQ_OUT |414CALI_SEL_01;415416mask = CALI_CYCLE_MASK |417CALI_AUTORST |418AUTO_TUNE_FREQ5 |419COMP_FREQ_RES |420CALI_SEL_MASK |421CALI_BP_DGL |422AUTO_TUNE_FREQ4 |423CALI_AUTO_RESTART |424CALI_USE_FREQ_OUT |425CALI_ON;426427regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,428mask, val);429regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,430CALI_ON, CALI_ON);431} else {432regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,4330xffffffff, 0x0);434}435/* CON6 setting fix 8125 */436regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON6,4370x0000ffff, 0x1FBD);438/* CON9 setting (RX IFS) */439regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON9,4400x000fffff, AutoRstThHi(ifs));441/* CON10 setting (RX IFS) */442regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON10,4430x000fffff, AutoRstThLo(ifs));444regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,445CHSET_STR_CLR, CHSET_STR_CLR);446447return 0;448}449450static int mt8365_afe_set_2nd_i2s_asrc_enable(struct mtk_base_afe *afe,451bool enable)452{453if (enable)454regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,455ASM_ON, ASM_ON);456else457regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,458ASM_ON, ~ASM_ON);459return 0;460}461462void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)463{464int i;465unsigned long flags;466struct mt8365_afe_private *afe_priv = afe->platform_priv;467struct mtk_afe_i2s_priv *i2s_data = NULL;468469for (i = 0; i < DAI_I2S_NUM; i++) {470if (mt8365_i2s_priv[i].adda_link)471i2s_data = afe_priv->dai_priv[mt8365_i2s_priv[i].id];472}473474if (!i2s_data)475return;476477spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);478479if (enable) {480i2s_data->i2s_out_on_ref_cnt++;481if (i2s_data->i2s_out_on_ref_cnt == 1)482regmap_update_bits(afe->regmap, AFE_I2S_CON1,4830x1, enable);484} else {485i2s_data->i2s_out_on_ref_cnt--;486if (i2s_data->i2s_out_on_ref_cnt == 0)487regmap_update_bits(afe->regmap, AFE_I2S_CON1,4880x1, enable);489else if (i2s_data->i2s_out_on_ref_cnt < 0)490i2s_data->i2s_out_on_ref_cnt = 0;491}492493spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);494}495496static void mt8365_dai_set_enable(struct mtk_base_afe *afe,497struct mtk_afe_i2s_priv *i2s_data,498bool is_input, bool enable)499{500unsigned int reg_off;501502if (is_input) {503reg_off = i2s_data->reg_off_in;504} else {505if (i2s_data->adda_link) {506mt8365_afe_set_i2s_out_enable(afe, enable);507return;508}509reg_off = i2s_data->reg_off_out;510}511regmap_update_bits(afe->regmap, reg_off,5120x1, enable);513}514515static int mt8365_dai_i2s_startup(struct snd_pcm_substream *substream,516struct snd_soc_dai *dai)517{518struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);519struct mt8365_afe_private *afe_priv = afe->platform_priv;520struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];521struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];522bool i2s_in_slave =523(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&524((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==525SND_SOC_DAIFMT_CBP_CFP);526527mt8365_afe_enable_main_clk(afe);528529if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)530clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_out]);531532if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !i2s_in_slave)533clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_in]);534535if (i2s_in_slave)536mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_I2S_IN);537538return 0;539}540541static void mt8365_dai_i2s_shutdown(struct snd_pcm_substream *substream,542struct snd_soc_dai *dai)543{544struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);545struct mt8365_afe_private *afe_priv = afe->platform_priv;546struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];547struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];548bool reset_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);549bool reset_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);550bool i2s_in_slave =551(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&552((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==553SND_SOC_DAIFMT_CBP_CFP);554555if (be->prepared[substream->stream]) {556if (reset_i2s_out_change)557mt8365_dai_set_enable(afe, i2s_data, false, false);558559if (reset_i2s_in_change)560mt8365_dai_set_enable(afe, i2s_data, true, false);561562if (substream->runtime->rate % 8000)563mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL1);564else565mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL2);566567if (reset_i2s_out_change)568be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = false;569570if (reset_i2s_in_change)571be->prepared[SNDRV_PCM_STREAM_CAPTURE] = false;572}573574if (reset_i2s_out_change)575mt8365_afe_disable_clk(afe,576afe_priv->clocks[i2s_data->clk_id_out]);577578if (reset_i2s_in_change && !i2s_in_slave)579mt8365_afe_disable_clk(afe,580afe_priv->clocks[i2s_data->clk_id_in]);581582if (i2s_in_slave)583mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_I2S_IN);584585mt8365_afe_disable_main_clk(afe);586}587588static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream,589struct snd_soc_dai *dai)590{591struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);592struct mt8365_afe_private *afe_priv = afe->platform_priv;593struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];594struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];595bool apply_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);596bool apply_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);597unsigned int rate = substream->runtime->rate;598int bit_width = snd_pcm_format_width(substream->runtime->format);599int ret;600601if (be->prepared[substream->stream]) {602dev_info(afe->dev, "%s '%s' prepared already\n",603__func__, snd_pcm_stream_str(substream));604return 0;605}606607if (apply_i2s_out_change) {608ret = mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);609if (ret)610return ret;611}612613if (apply_i2s_in_change) {614if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)615== SND_SOC_DAIFMT_CBP_CFP) {616ret = mt8365_afe_set_2nd_i2s_asrc(afe, 32000, rate,617(unsigned int)bit_width,6180, 0, 1);619if (ret < 0)620return ret;621}622ret = mt8365_dai_set_config(afe, i2s_data, true, rate, bit_width);623if (ret)624return ret;625}626627if (rate % 8000)628mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL1);629else630mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL2);631632if (apply_i2s_out_change) {633mt8365_afe_set_clk_parent(afe,634afe_priv->clocks[i2s_data->clk_id_out_m_sel],635((rate % 8000) ?636afe_priv->clocks[MT8365_CLK_AUD1] :637afe_priv->clocks[MT8365_CLK_AUD2]));638639mt8365_afe_set_clk_rate(afe,640afe_priv->clocks[i2s_data->clk_id_out],641rate * i2s_data->clk_out_mult);642643mt8365_dai_set_enable(afe, i2s_data, false, true);644be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = true;645}646647if (apply_i2s_in_change) {648mt8365_afe_set_clk_parent(afe,649afe_priv->clocks[i2s_data->clk_id_in_m_sel],650((rate % 8000) ?651afe_priv->clocks[MT8365_CLK_AUD1] :652afe_priv->clocks[MT8365_CLK_AUD2]));653654mt8365_afe_set_clk_rate(afe,655afe_priv->clocks[i2s_data->clk_id_in],656rate * i2s_data->clk_in_mult);657658mt8365_dai_set_enable(afe, i2s_data, true, true);659660if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)661== SND_SOC_DAIFMT_CBP_CFP)662mt8365_afe_set_2nd_i2s_asrc_enable(afe, true);663664be->prepared[SNDRV_PCM_STREAM_CAPTURE] = true;665}666return 0;667}668669static int mt8365_afe_2nd_i2s_hw_params(struct snd_pcm_substream *substream,670struct snd_pcm_hw_params *params,671struct snd_soc_dai *dai)672{673struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);674unsigned int width_val = params_width(params) > 16 ?675(AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01) : 0;676677if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)678regmap_update_bits(afe->regmap, AFE_CONN_24BIT,679AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01, width_val);680681return 0;682}683684static int mt8365_afe_2nd_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)685{686struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);687struct mt8365_afe_private *afe_priv = afe->platform_priv;688struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];689690be->fmt_mode = 0;691692switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {693case SND_SOC_DAIFMT_I2S:694be->fmt_mode |= SND_SOC_DAIFMT_I2S;695break;696case SND_SOC_DAIFMT_LEFT_J:697be->fmt_mode |= SND_SOC_DAIFMT_LEFT_J;698break;699default:700dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");701return -EINVAL;702}703704if (((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) &&705((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_IF) &&706((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_NF) &&707((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_IF)) {708dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");709return -EINVAL;710}711712be->fmt_mode |= (fmt & SND_SOC_DAIFMT_INV_MASK);713714if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBP_CFP))715be->fmt_mode |= (fmt & SND_SOC_DAIFMT_MASTER_MASK);716717return 0;718}719720static const struct snd_soc_dai_ops mt8365_afe_i2s_ops = {721.startup = mt8365_dai_i2s_startup,722.shutdown = mt8365_dai_i2s_shutdown,723.prepare = mt8365_dai_i2s_prepare,724};725726static const struct snd_soc_dai_ops mt8365_afe_2nd_i2s_ops = {727.startup = mt8365_dai_i2s_startup,728.shutdown = mt8365_dai_i2s_shutdown,729.hw_params = mt8365_afe_2nd_i2s_hw_params,730.prepare = mt8365_dai_i2s_prepare,731.set_fmt = mt8365_afe_2nd_i2s_set_fmt,732};733734static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {735{736.name = "I2S",737.id = MT8365_AFE_IO_I2S,738.playback = {739.stream_name = "I2S Playback",740.channels_min = 1,741.channels_max = 2,742.rates = SNDRV_PCM_RATE_8000_192000,743.formats = SNDRV_PCM_FMTBIT_S16_LE |744SNDRV_PCM_FMTBIT_S24_LE |745SNDRV_PCM_FMTBIT_S32_LE,746},747.capture = {748.stream_name = "I2S Capture",749.channels_min = 1,750.channels_max = 2,751.rates = SNDRV_PCM_RATE_8000_192000,752.formats = SNDRV_PCM_FMTBIT_S16_LE |753SNDRV_PCM_FMTBIT_S24_LE |754SNDRV_PCM_FMTBIT_S32_LE,755},756.ops = &mt8365_afe_i2s_ops,757}, {758.name = "2ND I2S",759.id = MT8365_AFE_IO_2ND_I2S,760.playback = {761.stream_name = "2ND I2S Playback",762.channels_min = 1,763.channels_max = 2,764.rates = SNDRV_PCM_RATE_8000_192000,765.formats = SNDRV_PCM_FMTBIT_S16_LE |766SNDRV_PCM_FMTBIT_S24_LE |767SNDRV_PCM_FMTBIT_S32_LE,768},769.capture = {770.stream_name = "2ND I2S Capture",771.channels_min = 1,772.channels_max = 2,773.rates = SNDRV_PCM_RATE_8000_192000,774.formats = SNDRV_PCM_FMTBIT_S16_LE |775SNDRV_PCM_FMTBIT_S24_LE |776SNDRV_PCM_FMTBIT_S32_LE,777},778.ops = &mt8365_afe_2nd_i2s_ops,779}780};781782static const char * const fmi2sin_text[] = {783"OPEN", "FM_2ND_I2S_IN"784};785786static SOC_ENUM_SINGLE_VIRT_DECL(fmi2sin_enum, fmi2sin_text);787788static const struct snd_kcontrol_new fmi2sin_mux =789SOC_DAPM_ENUM("FM 2ND I2S Source", fmi2sin_enum);790791static const struct snd_kcontrol_new i2s_o03_o04_enable_ctl =792SOC_DAPM_SINGLE_VIRT("Switch", 1);793794static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {795SND_SOC_DAPM_SWITCH("I2S O03_O04", SND_SOC_NOPM, 0, 0,796&i2s_o03_o04_enable_ctl),797SND_SOC_DAPM_MUX("FM 2ND I2S Mux", SND_SOC_NOPM, 0, 0, &fmi2sin_mux),798SND_SOC_DAPM_INPUT("2ND I2S In"),799};800801static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {802{"I2S O03_O04", "Switch", "O03"},803{"I2S O03_O04", "Switch", "O04"},804{"I2S Playback", NULL, "I2S O03_O04"},805{"2ND I2S Playback", NULL, "O00"},806{"2ND I2S Playback", NULL, "O01"},807{"2ND I2S Capture", NULL, "2ND I2S In"},808{"FM 2ND I2S Mux", "FM_2ND_I2S_IN", "2ND I2S Capture"},809};810811static int mt8365_dai_i2s_set_priv(struct mtk_base_afe *afe)812{813int i, ret;814815for (i = 0; i < DAI_I2S_NUM; i++) {816ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id,817sizeof(mt8365_i2s_priv[i]),818&mt8365_i2s_priv[i]);819if (ret)820return ret;821}822return 0;823}824825int mt8365_dai_i2s_register(struct mtk_base_afe *afe)826{827struct mtk_base_afe_dai *dai;828829dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);830if (!dai)831return -ENOMEM;832833list_add(&dai->list, &afe->sub_dais);834835dai->dai_drivers = mtk_dai_i2s_driver;836dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);837dai->dapm_widgets = mtk_dai_i2s_widgets;838dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);839dai->dapm_routes = mtk_dai_i2s_routes;840dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);841842/* set all dai i2s private data */843return mt8365_dai_i2s_set_priv(afe);844}845846847