Path: blob/master/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c
26488 views
// SPDX-License-Identifier: GPL-2.01//2// MediaTek ALSA SoC Audio DAI I2S Control3//4// Copyright (c) 2022 MediaTek Inc.5// Author: Jiaxin Yu <[email protected]>67#include <linux/bitops.h>8#include <linux/regmap.h>9#include <sound/pcm_params.h>10#include "mt8186-afe-clk.h"11#include "mt8186-afe-common.h"12#include "mt8186-afe-gpio.h"13#include "mt8186-interconnection.h"1415enum {16I2S_FMT_EIAJ = 0,17I2S_FMT_I2S = 1,18};1920enum {21I2S_WLEN_16_BIT = 0,22I2S_WLEN_32_BIT = 1,23};2425enum {26I2S_HD_NORMAL = 0,27I2S_HD_LOW_JITTER = 1,28};2930enum {31I2S1_SEL_O28_O29 = 0,32I2S1_SEL_O03_O04 = 1,33};3435enum {36I2S_IN_PAD_CONNSYS = 0,37I2S_IN_PAD_IO_MUX = 1,38};3940struct mtk_afe_i2s_priv {41int id;42int rate; /* for determine which apll to use */43int low_jitter_en;44int master; /* only i2s0 has slave mode*/4546int share_i2s_id;4748int mclk_id;49int mclk_rate;50int mclk_apll;51};5253static unsigned int get_i2s_wlen(snd_pcm_format_t format)54{55return snd_pcm_format_physical_width(format) <= 16 ?56I2S_WLEN_16_BIT : I2S_WLEN_32_BIT;57}5859#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux"60#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux"61#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux"62#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux"63#define MTK_AFE_I2S0_SRC_KCONTROL_NAME "I2S0_SRC_Mux"6465#define I2S0_HD_EN_W_NAME "I2S0_HD_EN"66#define I2S1_HD_EN_W_NAME "I2S1_HD_EN"67#define I2S2_HD_EN_W_NAME "I2S2_HD_EN"68#define I2S3_HD_EN_W_NAME "I2S3_HD_EN"6970#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN"71#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN"72#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN"73#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN"7475static int get_i2s_id_by_name(struct mtk_base_afe *afe,76const char *name)77{78if (strncmp(name, "I2S0", 4) == 0)79return MT8186_DAI_I2S_0;80else if (strncmp(name, "I2S1", 4) == 0)81return MT8186_DAI_I2S_1;82else if (strncmp(name, "I2S2", 4) == 0)83return MT8186_DAI_I2S_2;84else if (strncmp(name, "I2S3", 4) == 0)85return MT8186_DAI_I2S_3;8687return -EINVAL;88}8990static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe,91const char *name)92{93struct mt8186_afe_private *afe_priv = afe->platform_priv;94int dai_id = get_i2s_id_by_name(afe, name);9596if (dai_id < 0)97return NULL;9899return afe_priv->dai_priv[dai_id];100}101102/* low jitter control */103static const char * const mt8186_i2s_hd_str[] = {104"Normal", "Low_Jitter"105};106107static const struct soc_enum mt8186_i2s_enum[] = {108SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_hd_str),109mt8186_i2s_hd_str),110};111112static int mt8186_i2s_hd_get(struct snd_kcontrol *kcontrol,113struct snd_ctl_elem_value *ucontrol)114{115struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);116struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);117struct mtk_afe_i2s_priv *i2s_priv;118119i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);120ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;121122return 0;123}124125static int mt8186_i2s_hd_set(struct snd_kcontrol *kcontrol,126struct snd_ctl_elem_value *ucontrol)127{128struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);129struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);130struct mtk_afe_i2s_priv *i2s_priv;131struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;132int hd_en;133134if (ucontrol->value.enumerated.item[0] >= e->items)135return -EINVAL;136137hd_en = ucontrol->value.integer.value[0];138139dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",140__func__, kcontrol->id.name, hd_en);141142i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);143if (i2s_priv->low_jitter_en == hd_en)144return 0;145146i2s_priv->low_jitter_en = hd_en;147148return 1;149}150151static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = {152SOC_ENUM_EXT(MTK_AFE_I2S0_KCONTROL_NAME, mt8186_i2s_enum[0],153mt8186_i2s_hd_get, mt8186_i2s_hd_set),154SOC_ENUM_EXT(MTK_AFE_I2S1_KCONTROL_NAME, mt8186_i2s_enum[0],155mt8186_i2s_hd_get, mt8186_i2s_hd_set),156SOC_ENUM_EXT(MTK_AFE_I2S2_KCONTROL_NAME, mt8186_i2s_enum[0],157mt8186_i2s_hd_get, mt8186_i2s_hd_set),158SOC_ENUM_EXT(MTK_AFE_I2S3_KCONTROL_NAME, mt8186_i2s_enum[0],159mt8186_i2s_hd_get, mt8186_i2s_hd_set),160};161162/* dai component */163/* i2s virtual mux to output widget */164static const char * const i2s_mux_map[] = {165"Normal", "Dummy_Widget",166};167168static int i2s_mux_map_value[] = {1690, 1,170};171172static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s_mux_map_enum,173SND_SOC_NOPM,1740,1751,176i2s_mux_map,177i2s_mux_map_value);178179static const struct snd_kcontrol_new i2s0_in_mux_control =180SOC_DAPM_ENUM("I2S0 In Select", i2s_mux_map_enum);181182static const struct snd_kcontrol_new i2s1_out_mux_control =183SOC_DAPM_ENUM("I2S1 Out Select", i2s_mux_map_enum);184185static const struct snd_kcontrol_new i2s2_in_mux_control =186SOC_DAPM_ENUM("I2S2 In Select", i2s_mux_map_enum);187188static const struct snd_kcontrol_new i2s3_out_mux_control =189SOC_DAPM_ENUM("I2S3 Out Select", i2s_mux_map_enum);190191/* i2s in lpbk */192static const char * const i2s_lpbk_mux_map[] = {193"Normal", "Lpbk",194};195196static int i2s_lpbk_mux_map_value[] = {1970, 1,198};199200static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s0_lpbk_mux_map_enum,201AFE_I2S_CON,202I2S_LOOPBACK_SFT,2031,204i2s_lpbk_mux_map,205i2s_lpbk_mux_map_value);206207static const struct snd_kcontrol_new i2s0_lpbk_mux_control =208SOC_DAPM_ENUM("I2S Lpbk Select", i2s0_lpbk_mux_map_enum);209210static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s2_lpbk_mux_map_enum,211AFE_I2S_CON2,212I2S3_LOOPBACK_SFT,2131,214i2s_lpbk_mux_map,215i2s_lpbk_mux_map_value);216217static const struct snd_kcontrol_new i2s2_lpbk_mux_control =218SOC_DAPM_ENUM("I2S Lpbk Select", i2s2_lpbk_mux_map_enum);219220/* interconnection */221static const struct snd_kcontrol_new mtk_i2s3_ch1_mix[] = {222SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN0,223I_DL1_CH1, 1, 0),224SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN0,225I_DL2_CH1, 1, 0),226SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN0,227I_DL3_CH1, 1, 0),228SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN0,229I_DL12_CH1, 1, 0),230SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN0,231I_DL12_CH3, 1, 0),232SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN0_1,233I_DL6_CH1, 1, 0),234SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN0_1,235I_DL4_CH1, 1, 0),236SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN0_1,237I_DL5_CH1, 1, 0),238SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN0_1,239I_DL8_CH1, 1, 0),240SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN0,241I_GAIN1_OUT_CH1, 1, 0),242SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN0,243I_ADDA_UL_CH1, 1, 0),244SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN0,245I_ADDA_UL_CH2, 1, 0),246SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN0,247I_ADDA_UL_CH3, 1, 0),248SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN0,249I_PCM_1_CAP_CH1, 1, 0),250SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN0_1,251I_SRC_1_OUT_CH1, 1, 0),252};253254static const struct snd_kcontrol_new mtk_i2s3_ch2_mix[] = {255SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN1,256I_DL1_CH2, 1, 0),257SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN1,258I_DL2_CH2, 1, 0),259SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN1,260I_DL3_CH2, 1, 0),261SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN1,262I_DL12_CH2, 1, 0),263SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN1,264I_DL12_CH4, 1, 0),265SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN1_1,266I_DL6_CH2, 1, 0),267SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN1_1,268I_DL4_CH2, 1, 0),269SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN1_1,270I_DL5_CH2, 1, 0),271SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN1_1,272I_DL8_CH2, 1, 0),273SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN1,274I_GAIN1_OUT_CH2, 1, 0),275SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN1,276I_ADDA_UL_CH1, 1, 0),277SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN1,278I_ADDA_UL_CH2, 1, 0),279SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN1,280I_ADDA_UL_CH3, 1, 0),281SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN1,282I_PCM_1_CAP_CH2, 1, 0),283SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN1,284I_PCM_2_CAP_CH2, 1, 0),285SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN1_1,286I_SRC_1_OUT_CH2, 1, 0),287};288289static const struct snd_kcontrol_new mtk_i2s1_ch1_mix[] = {290SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN28,291I_DL1_CH1, 1, 0),292SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN28,293I_DL2_CH1, 1, 0),294SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN28,295I_DL3_CH1, 1, 0),296SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN28,297I_DL12_CH1, 1, 0),298SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN28,299I_DL12_CH3, 1, 0),300SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN28_1,301I_DL6_CH1, 1, 0),302SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN28_1,303I_DL4_CH1, 1, 0),304SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN28_1,305I_DL5_CH1, 1, 0),306SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN28_1,307I_DL8_CH1, 1, 0),308SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN28,309I_GAIN1_OUT_CH1, 1, 0),310SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN28,311I_ADDA_UL_CH1, 1, 0),312SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN28,313I_PCM_1_CAP_CH1, 1, 0),314SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN28_1,315I_SRC_1_OUT_CH1, 1, 0),316};317318static const struct snd_kcontrol_new mtk_i2s1_ch2_mix[] = {319SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN29,320I_DL1_CH2, 1, 0),321SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN29,322I_DL2_CH2, 1, 0),323SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN29,324I_DL3_CH2, 1, 0),325SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN29,326I_DL12_CH2, 1, 0),327SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN29,328I_DL12_CH4, 1, 0),329SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN29_1,330I_DL6_CH2, 1, 0),331SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN29_1,332I_DL4_CH2, 1, 0),333SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN29_1,334I_DL5_CH2, 1, 0),335SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN29_1,336I_DL8_CH2, 1, 0),337SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN29,338I_GAIN1_OUT_CH2, 1, 0),339SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN29,340I_ADDA_UL_CH2, 1, 0),341SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN29,342I_PCM_1_CAP_CH2, 1, 0),343SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN29,344I_PCM_2_CAP_CH2, 1, 0),345SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN29_1,346I_SRC_1_OUT_CH2, 1, 0),347};348349enum {350SUPPLY_SEQ_APLL,351SUPPLY_SEQ_I2S_MCLK_EN,352SUPPLY_SEQ_I2S_HD_EN,353SUPPLY_SEQ_I2S_EN,354};355356static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w,357struct snd_kcontrol *kcontrol,358int event)359{360struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);361struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);362struct mtk_afe_i2s_priv *i2s_priv;363364i2s_priv = get_i2s_priv_by_name(afe, w->name);365366dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",367__func__, w->name, event);368369switch (event) {370case SND_SOC_DAPM_PRE_PMU:371mt8186_afe_gpio_request(afe->dev, true, i2s_priv->id, 0);372break;373case SND_SOC_DAPM_POST_PMD:374mt8186_afe_gpio_request(afe->dev, false, i2s_priv->id, 0);375break;376default:377break;378}379380return 0;381}382383static int mtk_apll_event(struct snd_soc_dapm_widget *w,384struct snd_kcontrol *kcontrol,385int event)386{387struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);388struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);389390dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",391__func__, w->name, event);392393switch (event) {394case SND_SOC_DAPM_PRE_PMU:395if (snd_soc_dapm_widget_name_cmp(w, APLL1_W_NAME) == 0)396mt8186_apll1_enable(afe);397else398mt8186_apll2_enable(afe);399break;400case SND_SOC_DAPM_POST_PMD:401if (snd_soc_dapm_widget_name_cmp(w, APLL1_W_NAME) == 0)402mt8186_apll1_disable(afe);403else404mt8186_apll2_disable(afe);405break;406default:407break;408}409410return 0;411}412413static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,414struct snd_kcontrol *kcontrol,415int event)416{417struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);418struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);419struct mtk_afe_i2s_priv *i2s_priv;420421dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",422__func__, w->name, event);423424i2s_priv = get_i2s_priv_by_name(afe, w->name);425426switch (event) {427case SND_SOC_DAPM_PRE_PMU:428mt8186_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);429break;430case SND_SOC_DAPM_POST_PMD:431i2s_priv->mclk_rate = 0;432mt8186_mck_disable(afe, i2s_priv->mclk_id);433break;434default:435break;436}437438return 0;439}440441static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {442SND_SOC_DAPM_INPUT("CONNSYS"),443444SND_SOC_DAPM_MIXER("I2S1_CH1", SND_SOC_NOPM, 0, 0,445mtk_i2s1_ch1_mix,446ARRAY_SIZE(mtk_i2s1_ch1_mix)),447SND_SOC_DAPM_MIXER("I2S1_CH2", SND_SOC_NOPM, 0, 0,448mtk_i2s1_ch2_mix,449ARRAY_SIZE(mtk_i2s1_ch2_mix)),450451SND_SOC_DAPM_MIXER("I2S3_CH1", SND_SOC_NOPM, 0, 0,452mtk_i2s3_ch1_mix,453ARRAY_SIZE(mtk_i2s3_ch1_mix)),454SND_SOC_DAPM_MIXER("I2S3_CH2", SND_SOC_NOPM, 0, 0,455mtk_i2s3_ch2_mix,456ARRAY_SIZE(mtk_i2s3_ch2_mix)),457458/* i2s en*/459SND_SOC_DAPM_SUPPLY_S("I2S0_EN", SUPPLY_SEQ_I2S_EN,460AFE_I2S_CON, I2S_EN_SFT, 0,461mtk_i2s_en_event,462SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),463SND_SOC_DAPM_SUPPLY_S("I2S1_EN", SUPPLY_SEQ_I2S_EN,464AFE_I2S_CON1, I2S_EN_SFT, 0,465mtk_i2s_en_event,466SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),467SND_SOC_DAPM_SUPPLY_S("I2S2_EN", SUPPLY_SEQ_I2S_EN,468AFE_I2S_CON2, I2S_EN_SFT, 0,469mtk_i2s_en_event,470SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),471SND_SOC_DAPM_SUPPLY_S("I2S3_EN", SUPPLY_SEQ_I2S_EN,472AFE_I2S_CON3, I2S_EN_SFT, 0,473mtk_i2s_en_event,474SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),475/* i2s hd en */476SND_SOC_DAPM_SUPPLY_S(I2S0_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,477AFE_I2S_CON, I2S1_HD_EN_SFT, 0, NULL,478SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),479SND_SOC_DAPM_SUPPLY_S(I2S1_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,480AFE_I2S_CON1, I2S2_HD_EN_SFT, 0, NULL,481SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),482SND_SOC_DAPM_SUPPLY_S(I2S2_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,483AFE_I2S_CON2, I2S3_HD_EN_SFT, 0, NULL,484SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),485SND_SOC_DAPM_SUPPLY_S(I2S3_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,486AFE_I2S_CON3, I2S4_HD_EN_SFT, 0, NULL,487SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),488489/* i2s mclk en */490SND_SOC_DAPM_SUPPLY_S(I2S0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,491SND_SOC_NOPM, 0, 0,492mtk_mclk_en_event,493SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),494SND_SOC_DAPM_SUPPLY_S(I2S1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,495SND_SOC_NOPM, 0, 0,496mtk_mclk_en_event,497SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),498SND_SOC_DAPM_SUPPLY_S(I2S2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,499SND_SOC_NOPM, 0, 0,500mtk_mclk_en_event,501SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),502SND_SOC_DAPM_SUPPLY_S(I2S3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,503SND_SOC_NOPM, 0, 0,504mtk_mclk_en_event,505SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),506507/* apll */508SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL,509SND_SOC_NOPM, 0, 0,510mtk_apll_event,511SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),512SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL,513SND_SOC_NOPM, 0, 0,514mtk_apll_event,515SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),516517/* allow i2s on without codec on */518SND_SOC_DAPM_OUTPUT("I2S_DUMMY_OUT"),519SND_SOC_DAPM_MUX("I2S1_Out_Mux",520SND_SOC_NOPM, 0, 0, &i2s1_out_mux_control),521SND_SOC_DAPM_MUX("I2S3_Out_Mux",522SND_SOC_NOPM, 0, 0, &i2s3_out_mux_control),523SND_SOC_DAPM_INPUT("I2S_DUMMY_IN"),524SND_SOC_DAPM_MUX("I2S0_In_Mux",525SND_SOC_NOPM, 0, 0, &i2s0_in_mux_control),526SND_SOC_DAPM_MUX("I2S2_In_Mux",527SND_SOC_NOPM, 0, 0, &i2s2_in_mux_control),528529/* i2s in lpbk */530SND_SOC_DAPM_MUX("I2S0_Lpbk_Mux",531SND_SOC_NOPM, 0, 0, &i2s0_lpbk_mux_control),532SND_SOC_DAPM_MUX("I2S2_Lpbk_Mux",533SND_SOC_NOPM, 0, 0, &i2s2_lpbk_mux_control),534};535536static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,537struct snd_soc_dapm_widget *sink)538{539struct snd_soc_dapm_widget *w = sink;540struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);541struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);542struct mtk_afe_i2s_priv *i2s_priv;543544i2s_priv = get_i2s_priv_by_name(afe, sink->name);545if (i2s_priv->share_i2s_id < 0)546return 0;547548return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name);549}550551static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,552struct snd_soc_dapm_widget *sink)553{554struct snd_soc_dapm_widget *w = sink;555struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);556struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);557struct mtk_afe_i2s_priv *i2s_priv;558559i2s_priv = get_i2s_priv_by_name(afe, sink->name);560if (get_i2s_id_by_name(afe, sink->name) ==561get_i2s_id_by_name(afe, source->name))562return i2s_priv->low_jitter_en;563564/* check if share i2s need hd en */565if (i2s_priv->share_i2s_id < 0)566return 0;567568if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))569return i2s_priv->low_jitter_en;570571return 0;572}573574static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,575struct snd_soc_dapm_widget *sink)576{577struct snd_soc_dapm_widget *w = sink;578struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);579struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);580struct mtk_afe_i2s_priv *i2s_priv;581int cur_apll;582int i2s_need_apll;583584i2s_priv = get_i2s_priv_by_name(afe, w->name);585/* which apll */586cur_apll = mt8186_get_apll_by_name(afe, source->name);587/* choose APLL from i2s rate */588i2s_need_apll = mt8186_get_apll_by_rate(afe, i2s_priv->rate);589590return (i2s_need_apll == cur_apll) ? 1 : 0;591}592593static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,594struct snd_soc_dapm_widget *sink)595{596struct snd_soc_dapm_widget *w = sink;597struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);598struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);599struct mtk_afe_i2s_priv *i2s_priv;600601i2s_priv = get_i2s_priv_by_name(afe, sink->name);602if (get_i2s_id_by_name(afe, sink->name) ==603get_i2s_id_by_name(afe, source->name))604return (i2s_priv->mclk_rate > 0) ? 1 : 0;605606/* check if share i2s need mclk */607if (i2s_priv->share_i2s_id < 0)608return 0;609610if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))611return (i2s_priv->mclk_rate > 0) ? 1 : 0;612613return 0;614}615616static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,617struct snd_soc_dapm_widget *sink)618{619struct snd_soc_dapm_widget *w = sink;620struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);621struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);622struct mtk_afe_i2s_priv *i2s_priv;623int cur_apll;624625i2s_priv = get_i2s_priv_by_name(afe, w->name);626/* which apll */627cur_apll = mt8186_get_apll_by_name(afe, source->name);628629return (i2s_priv->mclk_apll == cur_apll) ? 1 : 0;630}631632static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {633{"Connsys I2S", NULL, "CONNSYS"},634635/* i2s0 */636{"I2S0", NULL, "I2S0_EN"},637{"I2S0", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},638{"I2S0", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},639{"I2S0", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},640641{"I2S0", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},642{"I2S0", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},643{"I2S0", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},644{"I2S0", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},645{I2S0_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},646{I2S0_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},647648{"I2S0", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},649{"I2S0", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},650{"I2S0", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},651{"I2S0", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},652{I2S0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},653{I2S0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},654655/* i2s1 */656{"I2S1_CH1", "DL1_CH1 Switch", "DL1"},657{"I2S1_CH2", "DL1_CH2 Switch", "DL1"},658659{"I2S1_CH1", "DL1_CH1 Switch", "DSP_DL1_VIRT"},660{"I2S1_CH2", "DL1_CH2 Switch", "DSP_DL1_VIRT"},661662{"I2S1_CH1", "DL2_CH1 Switch", "DL2"},663{"I2S1_CH2", "DL2_CH2 Switch", "DL2"},664665{"I2S1_CH1", "DL2_CH1 Switch", "DSP_DL2_VIRT"},666{"I2S1_CH2", "DL2_CH2 Switch", "DSP_DL2_VIRT"},667668{"I2S1_CH1", "DL3_CH1 Switch", "DL3"},669{"I2S1_CH2", "DL3_CH2 Switch", "DL3"},670671{"I2S1_CH1", "DL12_CH1 Switch", "DL12"},672{"I2S1_CH2", "DL12_CH2 Switch", "DL12"},673674{"I2S1_CH1", "DL12_CH3 Switch", "DL12"},675{"I2S1_CH2", "DL12_CH4 Switch", "DL12"},676677{"I2S1_CH1", "DL6_CH1 Switch", "DL6"},678{"I2S1_CH2", "DL6_CH2 Switch", "DL6"},679680{"I2S1_CH1", "DL4_CH1 Switch", "DL4"},681{"I2S1_CH2", "DL4_CH2 Switch", "DL4"},682683{"I2S1_CH1", "DL5_CH1 Switch", "DL5"},684{"I2S1_CH2", "DL5_CH2 Switch", "DL5"},685686{"I2S1_CH1", "DL8_CH1 Switch", "DL8"},687{"I2S1_CH2", "DL8_CH2 Switch", "DL8"},688689{"I2S1", NULL, "I2S1_CH1"},690{"I2S1", NULL, "I2S1_CH2"},691692{"I2S1", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},693{"I2S1", NULL, "I2S1_EN"},694{"I2S1", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},695{"I2S1", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},696697{"I2S1", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},698{"I2S1", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},699{"I2S1", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},700{"I2S1", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},701{I2S1_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},702{I2S1_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},703704{"I2S1", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},705{"I2S1", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},706{"I2S1", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},707{"I2S1", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},708{I2S1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},709{I2S1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},710711/* i2s2 */712{"I2S2", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},713{"I2S2", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},714{"I2S2", NULL, "I2S2_EN"},715{"I2S2", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},716717{"I2S2", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},718{"I2S2", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},719{"I2S2", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},720{"I2S2", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},721{I2S2_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},722{I2S2_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},723724{"I2S2", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},725{"I2S2", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},726{"I2S2", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},727{"I2S2", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},728{I2S2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},729{I2S2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},730731/* i2s3 */732{"I2S3_CH1", "DL1_CH1 Switch", "DL1"},733{"I2S3_CH2", "DL1_CH2 Switch", "DL1"},734735{"I2S3_CH1", "DL1_CH1 Switch", "DSP_DL1_VIRT"},736{"I2S3_CH2", "DL1_CH2 Switch", "DSP_DL1_VIRT"},737738{"I2S3_CH1", "DL2_CH1 Switch", "DL2"},739{"I2S3_CH2", "DL2_CH2 Switch", "DL2"},740741{"I2S3_CH1", "DL2_CH1 Switch", "DSP_DL2_VIRT"},742{"I2S3_CH2", "DL2_CH2 Switch", "DSP_DL2_VIRT"},743744{"I2S3_CH1", "DL3_CH1 Switch", "DL3"},745{"I2S3_CH2", "DL3_CH2 Switch", "DL3"},746747{"I2S3_CH1", "DL12_CH1 Switch", "DL12"},748{"I2S3_CH2", "DL12_CH2 Switch", "DL12"},749750{"I2S3_CH1", "DL12_CH3 Switch", "DL12"},751{"I2S3_CH2", "DL12_CH4 Switch", "DL12"},752753{"I2S3_CH1", "DL6_CH1 Switch", "DL6"},754{"I2S3_CH2", "DL6_CH2 Switch", "DL6"},755756{"I2S3_CH1", "DL4_CH1 Switch", "DL4"},757{"I2S3_CH2", "DL4_CH2 Switch", "DL4"},758759{"I2S3_CH1", "DL5_CH1 Switch", "DL5"},760{"I2S3_CH2", "DL5_CH2 Switch", "DL5"},761762{"I2S3_CH1", "DL8_CH1 Switch", "DL8"},763{"I2S3_CH2", "DL8_CH2 Switch", "DL8"},764765{"I2S3", NULL, "I2S3_CH1"},766{"I2S3", NULL, "I2S3_CH2"},767768{"I2S3", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},769{"I2S3", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},770{"I2S3", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},771{"I2S3", NULL, "I2S3_EN"},772773{"I2S3", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},774{"I2S3", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},775{"I2S3", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},776{"I2S3", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},777{I2S3_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},778{I2S3_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},779780{"I2S3", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},781{"I2S3", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},782{"I2S3", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},783{"I2S3", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},784{I2S3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},785{I2S3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},786787/* allow i2s on without codec on */788{"I2S0", NULL, "I2S0_In_Mux"},789{"I2S0_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},790791{"I2S1_Out_Mux", "Dummy_Widget", "I2S1"},792{"I2S_DUMMY_OUT", NULL, "I2S1_Out_Mux"},793794{"I2S2", NULL, "I2S2_In_Mux"},795{"I2S2_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"},796797{"I2S3_Out_Mux", "Dummy_Widget", "I2S3"},798{"I2S_DUMMY_OUT", NULL, "I2S3_Out_Mux"},799800/* i2s in lpbk */801{"I2S0_Lpbk_Mux", "Lpbk", "I2S3"},802{"I2S2_Lpbk_Mux", "Lpbk", "I2S1"},803{"I2S0", NULL, "I2S0_Lpbk_Mux"},804{"I2S2", NULL, "I2S2_Lpbk_Mux"},805};806807/* dai ops */808static int mtk_dai_connsys_i2s_hw_params(struct snd_pcm_substream *substream,809struct snd_pcm_hw_params *params,810struct snd_soc_dai *dai)811{812struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);813unsigned int rate = params_rate(params);814unsigned int rate_reg = mt8186_rate_transform(afe->dev,815rate, dai->id);816unsigned int i2s_con = 0;817818dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",819__func__, dai->id, substream->stream, rate);820821/* non-inverse, i2s mode, slave, 16bits, from connsys */822i2s_con |= 0 << INV_PAD_CTRL_SFT;823i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;824i2s_con |= 1 << I2S_SRC_SFT;825i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) << I2S_WLEN_SFT;826i2s_con |= 0 << I2SIN_PAD_SEL_SFT;827regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con);828829/* use asrc */830regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,831I2S_BYPSRC_MASK_SFT, 0);832833/* slave mode, set i2s for asrc */834regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,835I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT);836837if (rate == 44100)838regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1b9000);839else if (rate == 32000)840regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000);841else842regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1e0000);843844/* Calibration setting */845regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x140000);846regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x36000);847regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x2fc00);848regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x7ef4);849regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0xff5986);850851/* 0:Stereo 1:Mono */852regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,853CHSET_IS_MONO_MASK_SFT, 0);854855return 0;856}857858static int mtk_dai_connsys_i2s_trigger(struct snd_pcm_substream *substream,859int cmd, struct snd_soc_dai *dai)860{861struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);862struct mt8186_afe_private *afe_priv = afe->platform_priv;863864dev_dbg(afe->dev, "%s(), cmd %d, stream %d\n",865__func__, cmd, substream->stream);866867switch (cmd) {868case SNDRV_PCM_TRIGGER_START:869case SNDRV_PCM_TRIGGER_RESUME:870/* i2s enable */871regmap_update_bits(afe->regmap,872AFE_CONNSYS_I2S_CON,873I2S_EN_MASK_SFT,874BIT(I2S_EN_SFT));875876/* calibrator enable */877regmap_update_bits(afe->regmap,878AFE_ASRC_2CH_CON5,879CALI_EN_MASK_SFT,880BIT(CALI_EN_SFT));881882/* asrc enable */883regmap_update_bits(afe->regmap,884AFE_ASRC_2CH_CON0,885CON0_CHSET_STR_CLR_MASK_SFT,886BIT(CON0_CHSET_STR_CLR_SFT));887regmap_update_bits(afe->regmap,888AFE_ASRC_2CH_CON0,889CON0_ASM_ON_MASK_SFT,890BIT(CON0_ASM_ON_SFT));891892afe_priv->dai_on[dai->id] = true;893return 0;894case SNDRV_PCM_TRIGGER_STOP:895case SNDRV_PCM_TRIGGER_SUSPEND:896regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,897CON0_ASM_ON_MASK_SFT, 0);898regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,899CALI_EN_MASK_SFT, 0);900901/* i2s disable */902regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,903I2S_EN_MASK_SFT, 0);904905/* bypass asrc */906regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,907I2S_BYPSRC_MASK_SFT, BIT(I2S_BYPSRC_SFT));908909afe_priv->dai_on[dai->id] = false;910return 0;911default:912return -EINVAL;913}914return 0;915}916917static const struct snd_soc_dai_ops mtk_dai_connsys_i2s_ops = {918.hw_params = mtk_dai_connsys_i2s_hw_params,919.trigger = mtk_dai_connsys_i2s_trigger,920};921922/* i2s */923static int mtk_dai_i2s_config(struct mtk_base_afe *afe,924struct snd_pcm_hw_params *params,925int i2s_id)926{927struct mt8186_afe_private *afe_priv = afe->platform_priv;928struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id];929930unsigned int rate = params_rate(params);931unsigned int rate_reg = mt8186_rate_transform(afe->dev,932rate, i2s_id);933snd_pcm_format_t format = params_format(params);934unsigned int i2s_con = 0;935int ret;936937dev_dbg(afe->dev, "%s(), id %d, rate %d, format %d\n",938__func__, i2s_id, rate, format);939940i2s_priv->rate = rate;941942switch (i2s_id) {943case MT8186_DAI_I2S_0:944i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;945i2s_con |= rate_reg << I2S_OUT_MODE_SFT;946i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;947i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;948regmap_update_bits(afe->regmap, AFE_I2S_CON,9490xffffeffa, i2s_con);950break;951case MT8186_DAI_I2S_1:952i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT;953i2s_con |= rate_reg << I2S2_OUT_MODE_SFT;954i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT;955i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT;956regmap_update_bits(afe->regmap, AFE_I2S_CON1,9570xffffeffa, i2s_con);958break;959case MT8186_DAI_I2S_2:960i2s_con = 8 << I2S3_UPDATE_WORD_SFT;961i2s_con |= rate_reg << I2S3_OUT_MODE_SFT;962i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT;963i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT;964regmap_update_bits(afe->regmap, AFE_I2S_CON2,9650xffffeffa, i2s_con);966break;967case MT8186_DAI_I2S_3:968i2s_con = rate_reg << I2S4_OUT_MODE_SFT;969i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT;970i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT;971regmap_update_bits(afe->regmap, AFE_I2S_CON3,9720xffffeffa, i2s_con);973break;974default:975dev_err(afe->dev, "%s(), id %d not support\n",976__func__, i2s_id);977return -EINVAL;978}979980/* set share i2s */981if (i2s_priv->share_i2s_id >= 0) {982ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);983if (ret)984return ret;985}986987return 0;988}989990static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream,991struct snd_pcm_hw_params *params,992struct snd_soc_dai *dai)993{994struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);995996return mtk_dai_i2s_config(afe, params, dai->id);997}998999static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,1000int clk_id, unsigned int freq, int dir)1001{1002struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);1003struct mt8186_afe_private *afe_priv = afe->platform_priv;1004struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id];1005int apll;1006int apll_rate;10071008if (dir != SND_SOC_CLOCK_OUT) {1009dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);1010return -EINVAL;1011}10121013dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);10141015apll = mt8186_get_apll_by_rate(afe, freq);1016apll_rate = mt8186_get_apll_rate(afe, apll);10171018if (freq > apll_rate) {1019dev_err(afe->dev, "%s(), freq > apll rate", __func__);1020return -EINVAL;1021}10221023if (apll_rate % freq != 0) {1024dev_err(afe->dev, "%s(), APLL cannot generate freq Hz", __func__);1025return -EINVAL;1026}10271028i2s_priv->mclk_rate = freq;1029i2s_priv->mclk_apll = apll;10301031if (i2s_priv->share_i2s_id > 0) {1032struct mtk_afe_i2s_priv *share_i2s_priv;10331034share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];1035if (!share_i2s_priv) {1036dev_err(afe->dev, "%s(), share_i2s_priv == NULL", __func__);1037return -EINVAL;1038}10391040share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;1041share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;1042}10431044return 0;1045}10461047static const struct snd_soc_dai_ops mtk_dai_i2s_ops = {1048.hw_params = mtk_dai_i2s_hw_params,1049.set_sysclk = mtk_dai_i2s_set_sysclk,1050};10511052/* dai driver */1053#define MTK_CONNSYS_I2S_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)10541055#define MTK_I2S_RATES (SNDRV_PCM_RATE_8000_48000 |\1056SNDRV_PCM_RATE_88200 |\1057SNDRV_PCM_RATE_96000 |\1058SNDRV_PCM_RATE_176400 |\1059SNDRV_PCM_RATE_192000)10601061#define MTK_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\1062SNDRV_PCM_FMTBIT_S24_LE |\1063SNDRV_PCM_FMTBIT_S32_LE)10641065static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {1066{1067.name = "CONNSYS_I2S",1068.id = MT8186_DAI_CONNSYS_I2S,1069.capture = {1070.stream_name = "Connsys I2S",1071.channels_min = 1,1072.channels_max = 2,1073.rates = MTK_CONNSYS_I2S_RATES,1074.formats = MTK_I2S_FORMATS,1075},1076.ops = &mtk_dai_connsys_i2s_ops,1077},1078{1079.name = "I2S0",1080.id = MT8186_DAI_I2S_0,1081.capture = {1082.stream_name = "I2S0",1083.channels_min = 1,1084.channels_max = 2,1085.rates = MTK_I2S_RATES,1086.formats = MTK_I2S_FORMATS,1087},1088.ops = &mtk_dai_i2s_ops,1089},1090{1091.name = "I2S1",1092.id = MT8186_DAI_I2S_1,1093.playback = {1094.stream_name = "I2S1",1095.channels_min = 1,1096.channels_max = 2,1097.rates = MTK_I2S_RATES,1098.formats = MTK_I2S_FORMATS,1099},1100.ops = &mtk_dai_i2s_ops,1101},1102{1103.name = "I2S2",1104.id = MT8186_DAI_I2S_2,1105.capture = {1106.stream_name = "I2S2",1107.channels_min = 1,1108.channels_max = 2,1109.rates = MTK_I2S_RATES,1110.formats = MTK_I2S_FORMATS,1111},1112.ops = &mtk_dai_i2s_ops,1113},1114{1115.name = "I2S3",1116.id = MT8186_DAI_I2S_3,1117.playback = {1118.stream_name = "I2S3",1119.channels_min = 1,1120.channels_max = 2,1121.rates = MTK_I2S_RATES,1122.formats = MTK_I2S_FORMATS,1123},1124.ops = &mtk_dai_i2s_ops,1125}1126};11271128/* this enum is merely for mtk_afe_i2s_priv declare */1129enum {1130DAI_I2S0 = 0,1131DAI_I2S1,1132DAI_I2S2,1133DAI_I2S3,1134DAI_I2S_NUM,1135};11361137static const struct mtk_afe_i2s_priv mt8186_i2s_priv[DAI_I2S_NUM] = {1138[DAI_I2S0] = {1139.id = MT8186_DAI_I2S_0,1140.mclk_id = MT8186_I2S0_MCK,1141.share_i2s_id = -1,1142},1143[DAI_I2S1] = {1144.id = MT8186_DAI_I2S_1,1145.mclk_id = MT8186_I2S1_MCK,1146.share_i2s_id = -1,1147},1148[DAI_I2S2] = {1149.id = MT8186_DAI_I2S_2,1150.mclk_id = MT8186_I2S2_MCK,1151.share_i2s_id = -1,1152},1153[DAI_I2S3] = {1154.id = MT8186_DAI_I2S_3,1155/* clock gate naming is hf_faud_i2s4_m_ck*/1156.mclk_id = MT8186_I2S4_MCK,1157.share_i2s_id = -1,1158}1159};11601161/**1162* mt8186_dai_i2s_set_share() - Set up I2S ports to share a single clock.1163* @afe: Pointer to &struct mtk_base_afe1164* @main_i2s_name: The name of the I2S port that will provide the clock1165* @secondary_i2s_name: The name of the I2S port that will use this clock1166*/1167int mt8186_dai_i2s_set_share(struct mtk_base_afe *afe, const char *main_i2s_name,1168const char *secondary_i2s_name)1169{1170struct mtk_afe_i2s_priv *secondary_i2s_priv;1171int main_i2s_id;11721173secondary_i2s_priv = get_i2s_priv_by_name(afe, secondary_i2s_name);1174if (!secondary_i2s_priv)1175return -EINVAL;11761177main_i2s_id = get_i2s_id_by_name(afe, main_i2s_name);1178if (main_i2s_id < 0)1179return main_i2s_id;11801181secondary_i2s_priv->share_i2s_id = main_i2s_id;11821183return 0;1184}1185EXPORT_SYMBOL_GPL(mt8186_dai_i2s_set_share);11861187static int mt8186_dai_i2s_set_priv(struct mtk_base_afe *afe)1188{1189int i;1190int ret;11911192for (i = 0; i < DAI_I2S_NUM; i++) {1193ret = mt8186_dai_set_priv(afe, mt8186_i2s_priv[i].id,1194sizeof(struct mtk_afe_i2s_priv),1195&mt8186_i2s_priv[i]);1196if (ret)1197return ret;1198}11991200return 0;1201}12021203int mt8186_dai_i2s_register(struct mtk_base_afe *afe)1204{1205struct mtk_base_afe_dai *dai;1206int ret;12071208dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);1209if (!dai)1210return -ENOMEM;12111212list_add(&dai->list, &afe->sub_dais);12131214dai->dai_drivers = mtk_dai_i2s_driver;1215dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);12161217dai->controls = mtk_dai_i2s_controls;1218dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls);1219dai->dapm_widgets = mtk_dai_i2s_widgets;1220dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);1221dai->dapm_routes = mtk_dai_i2s_routes;1222dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);12231224/* set all dai i2s private data */1225ret = mt8186_dai_i2s_set_priv(afe);1226if (ret)1227return ret;12281229return 0;1230}123112321233