linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC
@ 2021-06-29  1:47 Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 1/8] ASoC: mediatek: mt8195: update mediatek common driver Trevor Wu
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Trevor Wu @ 2021-06-29  1:47 UTC (permalink / raw)
  To: broonie, tiwai, robh+dt, matthias.bgg
  Cc: trevor.wu, alsa-devel, linux-mediatek, linux-arm-kernel,
	linux-kernel, devicetree, bicycle.tsai, jiaxin.yu, cychiang,
	aaronyu

This series of patches adds support for Mediatek AFE of MT8195 SoC.
Patches are based on broonie tree "for-next" branch.

Changes since v1:
  - fixed some problems related to dt-bindings
  - add some missing properties to dt-bindings
  - add depency declaration on dt-bindings
  - fixed some warnings found by kernel test robot

Trevor Wu (8):
  ASoC: mediatek: mt8195: update mediatek common driver
  ASoC: mediatek: mt8195: support etdm in platform driver
  ASoC: mediatek: mt8195: support adda in platform driver
  ASoC: mediatek: mt8195: support pcm in platform driver
  ASoC: mediatek: mt8195: add platform driver
  dt-bindings: mediatek: mt8195: add audio afe document
  ASoC: mediatek: mt8195: add machine driver with mt6359, rt1019 and
    rt5682
  dt-bindings: mediatek: mt8195: add mt8195-mt6359-rt1019-rt5682
    document

 .../bindings/sound/mt8195-afe-pcm.yaml        |  136 +
 .../sound/mt8195-mt6359-rt1019-rt5682.yaml    |   39 +
 sound/soc/mediatek/Kconfig                    |   23 +
 sound/soc/mediatek/Makefile                   |    1 +
 sound/soc/mediatek/common/mtk-afe-fe-dai.c    |   22 +-
 sound/soc/mediatek/common/mtk-base-afe.h      |   10 +-
 sound/soc/mediatek/mt8195/Makefile            |   14 +
 sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
 sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
 sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264 +++++++++++++++++
 sound/soc/mediatek/mt8195/mt8195-dai-adda.c   |  929 +++++
 sound/soc/mediatek/mt8195/mt8195-dai-etdm.c   | 2666 ++++++++++++++
 sound/soc/mediatek/mt8195/mt8195-dai-pcm.c    |  393 ++
 .../mt8195/mt8195-mt6359-rt1019-rt5682.c      |  977 +++++
 sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793 ++++++++++++++
 16 files changed, 12562 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
 create mode 100644 sound/soc/mediatek/mt8195/Makefile
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.c
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.h
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-common.h
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-dai-adda.c
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h

-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v2 1/8] ASoC: mediatek: mt8195: update mediatek common driver
  2021-06-29  1:47 [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC Trevor Wu
@ 2021-06-29  1:47 ` Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 3/8] ASoC: mediatek: mt8195: support adda in platform driver Trevor Wu
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Trevor Wu @ 2021-06-29  1:47 UTC (permalink / raw)
  To: broonie, tiwai, robh+dt, matthias.bgg
  Cc: trevor.wu, alsa-devel, linux-mediatek, linux-arm-kernel,
	linux-kernel, devicetree, bicycle.tsai, jiaxin.yu, cychiang,
	aaronyu

Update mediatek common driver to support MT8195

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
Reported-by: kernel test robot <lkp@intel.com>
---
 sound/soc/mediatek/common/mtk-afe-fe-dai.c | 22 +++++++++++++++++++---
 sound/soc/mediatek/common/mtk-base-afe.h   | 10 ++++++++--
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index 3cb2adf420bb..baaa5881b1d4 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -139,7 +139,7 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
 		substream->runtime->dma_area,
 		substream->runtime->dma_bytes);
 
-	memset_io(substream->runtime->dma_area, 0,
+	memset_io((void __force __iomem *)substream->runtime->dma_area, 0,
 		  substream->runtime->dma_bytes);
 
 	/* set addr */
@@ -433,11 +433,20 @@ int mtk_memif_set_addr(struct mtk_base_afe *afe, int id,
 				 phys_buf_addr_upper_32);
 	}
 
-	/* set MSB to 33-bit */
-	if (memif->data->msb_reg >= 0)
+	/*
+	 * set MSB to 33-bit, for memif address
+	 * only for memif base address, if msb_end_reg exists
+	 */
+	if (memif->data->msb_reg)
 		mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
 				       1, msb_at_bit33, memif->data->msb_shift);
 
+	/* set MSB to 33-bit, for memif end address */
+	if (memif->data->msb_end_reg)
+		mtk_regmap_update_bits(afe->regmap, memif->data->msb_end_reg,
+				       1, msb_at_bit33,
+				       memif->data->msb_end_shift);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(mtk_memif_set_addr);
@@ -464,6 +473,13 @@ int mtk_memif_set_channel(struct mtk_base_afe *afe,
 	else
 		mono = (channel == 1) ? 1 : 0;
 
+	/* for specific configuration of memif mono mode */
+	if (memif->data->int_odd_flag_reg)
+		mtk_regmap_update_bits(afe->regmap,
+				       memif->data->int_odd_flag_reg,
+				       1, mono,
+				       memif->data->int_odd_flag_shift);
+
 	return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
 				      1, mono, memif->data->mono_shift);
 }
diff --git a/sound/soc/mediatek/common/mtk-base-afe.h b/sound/soc/mediatek/common/mtk-base-afe.h
index a6f68c68581c..ef83e78c22a8 100644
--- a/sound/soc/mediatek/common/mtk-base-afe.h
+++ b/sound/soc/mediatek/common/mtk-base-afe.h
@@ -29,6 +29,8 @@ struct mtk_base_memif_data {
 	int quad_ch_reg;
 	int quad_ch_mask;
 	int quad_ch_shift;
+	int int_odd_flag_reg;
+	int int_odd_flag_shift;
 	int enable_reg;
 	int enable_shift;
 	int hd_reg;
@@ -37,10 +39,13 @@ struct mtk_base_memif_data {
 	int hd_align_mshift;
 	int msb_reg;
 	int msb_shift;
-	int msb2_reg;
-	int msb2_shift;
+	int msb_end_reg;
+	int msb_end_shift;
 	int agent_disable_reg;
 	int agent_disable_shift;
+	int ch_num_reg;
+	int ch_num_shift;
+	int ch_num_maskbit;
 	/* playback memif only */
 	int pbuf_reg;
 	int pbuf_mask;
@@ -62,6 +67,7 @@ struct mtk_base_irq_data {
 	int irq_en_shift;
 	int irq_clr_reg;
 	int irq_clr_shift;
+	int irq_status_shift;
 };
 
 struct device;
-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 3/8] ASoC: mediatek: mt8195: support adda in platform driver
  2021-06-29  1:47 [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 1/8] ASoC: mediatek: mt8195: update mediatek common driver Trevor Wu
@ 2021-06-29  1:47 ` Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 4/8] ASoC: mediatek: mt8195: support pcm " Trevor Wu
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Trevor Wu @ 2021-06-29  1:47 UTC (permalink / raw)
  To: broonie, tiwai, robh+dt, matthias.bgg
  Cc: trevor.wu, alsa-devel, linux-mediatek, linux-arm-kernel,
	linux-kernel, devicetree, bicycle.tsai, jiaxin.yu, cychiang,
	aaronyu

This patch adds mt8195 adda dai driver.

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
---
 sound/soc/mediatek/mt8195/mt8195-dai-adda.c | 929 ++++++++++++++++++++
 1 file changed, 929 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-dai-adda.c

diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c
new file mode 100644
index 000000000000..e6b3582b19e2
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c
@@ -0,0 +1,929 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI ADDA Control
+ *
+ * Copyright (c) 2021 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+#define ADDA_DL_GAIN_LOOPBACK 0x1800
+#define ADDA_HIRES_THRES 48000
+
+enum {
+	SUPPLY_SEQ_CLOCK_SEL,
+	SUPPLY_SEQ_CLOCK_ON,
+	SUPPLY_SEQ_ADDA_DL_ON,
+	SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+	SUPPLY_SEQ_ADDA_UL_ON,
+	SUPPLY_SEQ_ADDA_AFE_ON,
+};
+
+enum {
+	MTK_AFE_ADDA_DL_RATE_8K = 0,
+	MTK_AFE_ADDA_DL_RATE_11K = 1,
+	MTK_AFE_ADDA_DL_RATE_12K = 2,
+	MTK_AFE_ADDA_DL_RATE_16K = 3,
+	MTK_AFE_ADDA_DL_RATE_22K = 4,
+	MTK_AFE_ADDA_DL_RATE_24K = 5,
+	MTK_AFE_ADDA_DL_RATE_32K = 6,
+	MTK_AFE_ADDA_DL_RATE_44K = 7,
+	MTK_AFE_ADDA_DL_RATE_48K = 8,
+	MTK_AFE_ADDA_DL_RATE_96K = 9,
+	MTK_AFE_ADDA_DL_RATE_192K = 10,
+};
+
+enum {
+	MTK_AFE_ADDA_UL_RATE_8K = 0,
+	MTK_AFE_ADDA_UL_RATE_16K = 1,
+	MTK_AFE_ADDA_UL_RATE_32K = 2,
+	MTK_AFE_ADDA_UL_RATE_48K = 3,
+	MTK_AFE_ADDA_UL_RATE_96K = 4,
+	MTK_AFE_ADDA_UL_RATE_192K = 5,
+};
+
+enum {
+	DELAY_DATA_MISO1 = 0,
+	DELAY_DATA_MISO0 = 1,
+	DELAY_DATA_MISO2 = 1,
+};
+
+enum {
+	MTK_AFE_ADDA,
+	MTK_AFE_ADDA6,
+};
+
+struct mtk_dai_adda_priv {
+	bool hires_required;
+};
+
+static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe,
+					       unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_ADDA_DL_RATE_8K;
+	case 11025:
+		return MTK_AFE_ADDA_DL_RATE_11K;
+	case 12000:
+		return MTK_AFE_ADDA_DL_RATE_12K;
+	case 16000:
+		return MTK_AFE_ADDA_DL_RATE_16K;
+	case 22050:
+		return MTK_AFE_ADDA_DL_RATE_22K;
+	case 24000:
+		return MTK_AFE_ADDA_DL_RATE_24K;
+	case 32000:
+		return MTK_AFE_ADDA_DL_RATE_32K;
+	case 44100:
+		return MTK_AFE_ADDA_DL_RATE_44K;
+	case 48000:
+		return MTK_AFE_ADDA_DL_RATE_48K;
+	case 96000:
+		return MTK_AFE_ADDA_DL_RATE_96K;
+	case 192000:
+		return MTK_AFE_ADDA_DL_RATE_192K;
+	default:
+		dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+			 __func__, rate);
+		return MTK_AFE_ADDA_DL_RATE_48K;
+	}
+}
+
+static unsigned int afe_adda_ul_rate_transform(struct mtk_base_afe *afe,
+					       unsigned int rate)
+{
+	switch (rate) {
+	case 8000:
+		return MTK_AFE_ADDA_UL_RATE_8K;
+	case 16000:
+		return MTK_AFE_ADDA_UL_RATE_16K;
+	case 32000:
+		return MTK_AFE_ADDA_UL_RATE_32K;
+	case 48000:
+		return MTK_AFE_ADDA_UL_RATE_48K;
+	case 96000:
+		return MTK_AFE_ADDA_UL_RATE_96K;
+	case 192000:
+		return MTK_AFE_ADDA_UL_RATE_192K;
+	default:
+		dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n",
+			 __func__, rate);
+		return MTK_AFE_ADDA_UL_RATE_48K;
+	}
+}
+
+static int mt8195_adda_mtkaif_init(struct mtk_base_afe *afe)
+{
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+	int delay_data;
+	int delay_cycle;
+	unsigned int mask = 0;
+	unsigned int val = 0;
+
+	/* set rx protocol 2 & mtkaif_rxif_clkinv_adc inverse */
+	mask = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2);
+	val = (MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2);
+
+	regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0, mask, val);
+	regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_CFG0, mask, val);
+
+	mask = RG_RX_PROTOCOL2;
+	val = RG_RX_PROTOCOL2;
+	regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, mask, val);
+
+	if (!param->mtkaif_calibration_ok) {
+		dev_info(afe->dev, "%s(), calibration fail\n",  __func__);
+		return 0;
+	}
+
+	/* set delay for ch1, ch2 */
+	if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] >=
+	    param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) {
+		delay_data = DELAY_DATA_MISO1;
+		delay_cycle =
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] -
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1];
+	} else {
+		delay_data = DELAY_DATA_MISO0;
+		delay_cycle =
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] -
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0];
+	}
+
+	val = 0;
+	mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);
+	val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) &
+	       MTKAIF_RXIF_DELAY_CYCLE_MASK;
+	val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT;
+	regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG2, mask, val);
+
+	/* set delay between ch3 and ch2 */
+	if (param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] >=
+	    param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1]) {
+		delay_data = DELAY_DATA_MISO1;
+		delay_cycle =
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] -
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1];
+	} else {
+		delay_data = DELAY_DATA_MISO2;
+		delay_cycle =
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] -
+			param->mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2];
+	}
+
+	val = 0;
+	mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);
+	val |= MTKAIF_RXIF_DELAY_CYCLE(delay_cycle) &
+	       MTKAIF_RXIF_DELAY_CYCLE_MASK;
+	val |= delay_data << MTKAIF_RXIF_DELAY_DATA_SHIFT;
+	regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIF_RX_CFG2, mask, val);
+
+	return 0;
+}
+
+static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,
+				     struct snd_kcontrol *kcontrol,
+				     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8195_adda_mtkaif_init(afe);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(125, 135);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static void mtk_adda_ul_mictype(struct mtk_base_afe *afe, int adda, bool dmic)
+{
+	unsigned int reg = 0;
+	unsigned int mask = 0;
+	unsigned int val = 0;
+
+	switch (adda) {
+	case MTK_AFE_ADDA:
+		reg = AFE_ADDA_UL_SRC_CON0;
+		break;
+	case MTK_AFE_ADDA6:
+		reg = AFE_ADDA6_UL_SRC_CON0;
+		break;
+	default:
+		dev_info(afe->dev, "%s(), wrong parameter\n",  __func__);
+		return;
+	}
+
+	mask = (UL_SDM3_LEVEL_CTL | UL_MODE_3P25M_CH1_CTL |
+		UL_MODE_3P25M_CH2_CTL);
+
+	/* turn on dmic, ch1, ch2 */
+	if (dmic)
+		val = mask;
+
+	regmap_update_bits(afe->regmap, reg, mask, val);
+}
+
+static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol,
+			     int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mtk_adda_ul_mictype(afe, MTK_AFE_ADDA, param->mtkaif_dmic_on);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(125, 135);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_adda6_ul_event(struct snd_soc_dapm_widget *w,
+			      struct snd_kcontrol *kcontrol,
+			      int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+	unsigned int val;
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mtk_adda_ul_mictype(afe, MTK_AFE_ADDA6, param->mtkaif_dmic_on);
+
+		val = (param->mtkaif_adda6_only ?
+			ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE : 0);
+
+		regmap_update_bits(afe->regmap,
+				   AFE_ADDA_MTKAIF_SYNCWORD_CFG,
+				   ADDA6_MTKAIF_RX_SYNC_WORD2_DISABLE,
+				   val);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+		usleep_range(125, 135);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int mtk_audio_hires_event(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol,
+				 int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct clk *clk = afe_priv->clk[MT8195_CLK_TOP_AUDIO_H_SEL];
+	struct clk *clk_parent;
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		clk_parent = afe_priv->clk[MT8195_CLK_TOP_APLL1];
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		clk_parent = afe_priv->clk[MT8195_CLK_XTAL_26M];
+		break;
+	default:
+		return 0;
+	}
+	mt8195_afe_set_clk_parent(afe, clk, clk_parent);
+
+	return 0;
+}
+
+static int mtk_adda_hires_event(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol,
+				int event)
+{
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	int clk_id;
+
+	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
+		__func__, w->name, event);
+
+	if (strstr(w->name, "ADDA_UL"))
+		clk_id = MT8195_CLK_AUD_ADC_HIRES;
+	else if (strstr(w->name, "ADDA6_UL"))
+		clk_id = MT8195_CLK_AUD_ADDA6_ADC_HIRES;
+	else if (strstr(w->name, "ADDA_DL"))
+		clk_id = MT8195_CLK_AUD_DAC_HIRES;
+	else
+		return -EINVAL;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		mt8195_afe_enable_clk(afe, afe_priv->clk[clk_id]);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		mt8195_afe_disable_clk(afe, afe_priv->clk[clk_id]);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct mtk_dai_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,
+						       const char *name)
+{
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	int dai_id;
+
+	if (strstr(name, "ADDA_UL"))
+		dai_id = MT8195_AFE_IO_UL_SRC1;
+	else if (strstr(name, "ADDA6_UL"))
+		dai_id = MT8195_AFE_IO_UL_SRC2;
+	else if (strstr(name, "ADDA_DL"))
+		dai_id = MT8195_AFE_IO_DL_SRC;
+	else
+		return NULL;
+
+	return afe_priv->dai_priv[dai_id];
+}
+
+static int mtk_afe_adda_hires_connect(struct snd_soc_dapm_widget *source,
+				      struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_dapm_widget *w = source;
+	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mtk_dai_adda_priv *adda_priv;
+
+	adda_priv = get_adda_priv_by_name(afe, w->name);
+
+	if (!adda_priv) {
+		dev_info(afe->dev, "adda_priv == NULL");
+		return 0;
+	}
+
+	return (adda_priv->hires_required) ? 1 : 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_adda_o176_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN176, 0, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN176, 2, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN176, 20, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN176, 22, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN176_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_adda_o177_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN177, 1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN177, 3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN177, 21, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN177, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN177_2, 7, 1, 0),
+};
+
+static const char * const adda_dlgain_mux_map[] = {
+	"Bypass", "Connect",
+};
+
+static SOC_ENUM_SINGLE_DECL(adda_dlgain_mux_map_enum,
+			    SND_SOC_NOPM, 0,
+			    adda_dlgain_mux_map);
+
+static const struct snd_kcontrol_new adda_dlgain_mux_control =
+	SOC_DAPM_ENUM("DL_GAIN_MUX", adda_dlgain_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+	SND_SOC_DAPM_MIXER("I168", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I169", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I170", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I171", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("O176", SND_SOC_NOPM, 0, 0,
+			   mtk_dai_adda_o176_mix,
+			   ARRAY_SIZE(mtk_dai_adda_o176_mix)),
+	SND_SOC_DAPM_MIXER("O177", SND_SOC_NOPM, 0, 0,
+			   mtk_dai_adda_o177_mix,
+			   ARRAY_SIZE(mtk_dai_adda_o177_mix)),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
+			      AFE_ADDA_UL_DL_CON0,
+			      ADDA_AFE_ON_SHIFT, 0,
+			      NULL,
+			      0),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,
+			      AFE_ADDA_DL_SRC2_CON0,
+			      DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT, 0,
+			      mtk_adda_dl_event,
+			      SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+			      AFE_ADDA_UL_SRC_CON0,
+			      UL_SRC_ON_TMP_CTL_SHIFT, 0,
+			      mtk_adda_ul_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA6 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+			      AFE_ADDA6_UL_SRC_CON0,
+			      UL_SRC_ON_TMP_CTL_SHIFT, 0,
+			      mtk_adda6_ul_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA_UL_HIRES", SUPPLY_SEQ_CLOCK_ON,
+			      SND_SOC_NOPM,
+			      0, 0,
+			      mtk_adda_hires_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA6_UL_HIRES", SUPPLY_SEQ_CLOCK_ON,
+			      SND_SOC_NOPM,
+			      0, 0,
+			      mtk_adda_hires_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA_DL_HIRES", SUPPLY_SEQ_CLOCK_ON,
+			      SND_SOC_NOPM,
+			      0, 0,
+			      mtk_adda_hires_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("AUDIO_HIRES", SUPPLY_SEQ_CLOCK_SEL,
+			      SND_SOC_NOPM,
+			      0, 0,
+			      mtk_audio_hires_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,
+			      SND_SOC_NOPM,
+			      0, 0,
+			      mtk_adda_mtkaif_cfg_event,
+			      SND_SOC_DAPM_PRE_PMU),
+
+	SND_SOC_DAPM_MUX("DL_GAIN_MUX", SND_SOC_NOPM, 0, 0,
+			 &adda_dlgain_mux_control),
+
+	SND_SOC_DAPM_PGA("DL_GAIN", AFE_ADDA_DL_SRC2_CON0,
+			 DL_2_GAIN_ON_CTL_PRE_SHIFT, 0, NULL, 0),
+
+	SND_SOC_DAPM_INPUT("ADDA_INPUT"),
+	SND_SOC_DAPM_OUTPUT("ADDA_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+	{"ADDA Capture", NULL, "ADDA Enable"},
+	{"ADDA Capture", NULL, "ADDA Capture Enable"},
+	{"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},
+	{"ADDA Capture", NULL, "ADDA_UL_HIRES", mtk_afe_adda_hires_connect},
+	{"ADDA6 Capture", NULL, "ADDA Enable"},
+	{"ADDA6 Capture", NULL, "ADDA6 Capture Enable"},
+	{"ADDA6 Capture", NULL, "ADDA_MTKAIF_CFG"},
+	{"ADDA6 Capture", NULL, "ADDA6_UL_HIRES", mtk_afe_adda_hires_connect},
+
+	{"I168", NULL, "ADDA Capture"},
+	{"I169", NULL, "ADDA Capture"},
+	{"I170", NULL, "ADDA6 Capture"},
+	{"I171", NULL, "ADDA6 Capture"},
+
+	{"ADDA Playback", NULL, "ADDA Enable"},
+	{"ADDA Playback", NULL, "ADDA Playback Enable"},
+	{"ADDA Playback", NULL, "ADDA_DL_HIRES", mtk_afe_adda_hires_connect},
+
+	{"DL_GAIN", NULL, "O176"},
+	{"DL_GAIN", NULL, "O177"},
+
+	{"DL_GAIN_MUX", "Bypass", "O176"},
+	{"DL_GAIN_MUX", "Bypass", "O177"},
+	{"DL_GAIN_MUX", "Connect", "DL_GAIN"},
+
+	{"ADDA Playback", NULL, "DL_GAIN_MUX"},
+
+	{"O176", "I000 Switch", "I000"},
+	{"O177", "I001 Switch", "I001"},
+
+	{"O176", "I002 Switch", "I002"},
+	{"O177", "I003 Switch", "I003"},
+
+	{"O176", "I020 Switch", "I020"},
+	{"O177", "I021 Switch", "I021"},
+
+	{"O176", "I022 Switch", "I022"},
+	{"O177", "I023 Switch", "I023"},
+
+	{"O176", "I070 Switch", "I070"},
+	{"O177", "I071 Switch", "I071"},
+
+	{"ADDA_UL_HIRES", NULL, "AUDIO_HIRES"},
+	{"ADDA6_UL_HIRES", NULL, "AUDIO_HIRES"},
+	{"ADDA_DL_HIRES", NULL, "AUDIO_HIRES"},
+
+	{"ADDA Capture", NULL, "ADDA_INPUT"},
+	{"ADDA6 Capture", NULL, "ADDA_INPUT"},
+	{"ADDA_OUTPUT", NULL, "ADDA Playback"},
+};
+
+static int mt8195_adda_dl_gain_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+	unsigned int reg = AFE_ADDA_DL_SRC2_CON1;
+	unsigned int mask = DL_2_GAIN_CTL_PRE_MASK;
+	unsigned int value = (unsigned int)(ucontrol->value.integer.value[0]);
+
+	regmap_update_bits(afe->regmap, reg, mask, DL_2_GAIN_CTL_PRE(value));
+	return 0;
+}
+
+static int mt8195_adda_dl_gain_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+	unsigned int reg = AFE_ADDA_DL_SRC2_CON1;
+	unsigned int mask = DL_2_GAIN_CTL_PRE_MASK;
+	unsigned int value = 0;
+
+	regmap_read(afe->regmap, reg, &value);
+
+	ucontrol->value.integer.value[0] = ((value & mask) >>
+					    DL_2_GAIN_CTL_PRE_SHIFT);
+	return 0;
+}
+
+static int mt8195_adda6_only_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+	ucontrol->value.integer.value[0] = param->mtkaif_adda6_only;
+	return 0;
+}
+
+static int mt8195_adda6_only_set(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+	int mtkaif_adda6_only;
+
+	mtkaif_adda6_only = ucontrol->value.integer.value[0];
+
+	dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n",
+		 __func__, kcontrol->id.name, mtkaif_adda6_only);
+
+	param->mtkaif_adda6_only = mtkaif_adda6_only;
+
+	return 0;
+}
+
+static int mt8195_adda_dmic_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+
+	ucontrol->value.integer.value[0] = param->mtkaif_dmic_on;
+	return 0;
+}
+
+static int mt8195_adda_dmic_set(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+	int dmic_on;
+
+	dmic_on = ucontrol->value.integer.value[0];
+
+	dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
+		__func__, kcontrol->id.name, dmic_on);
+
+	param->mtkaif_dmic_on = dmic_on;
+	return 0;
+}
+
+static const struct snd_kcontrol_new mtk_dai_adda_controls[] = {
+	SOC_SINGLE_EXT("ADDA_DL_Gain", SND_SOC_NOPM, 0, 65535, 0,
+		       mt8195_adda_dl_gain_get, mt8195_adda_dl_gain_put),
+	SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC", 0,
+			    mt8195_adda_dmic_get, mt8195_adda_dmic_set),
+	SOC_SINGLE_BOOL_EXT("MTKAIF_ADDA6_ONLY", 0,
+			    mt8195_adda6_only_get,
+			    mt8195_adda6_only_set),
+};
+
+/* dai ops */
+static int mtk_dai_adda_startup(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	int clk_id;
+
+	dev_dbg(dai->dev, "%s id %d\n", __func__, dai->id);
+
+	clk_id = MT8195_CLK_INFRA_AO_AUDIO_26M_B;
+	mt8195_afe_enable_clk(afe, afe_priv->clk[clk_id]);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		clk_id = MT8195_CLK_AUD_DAC;
+	} else {
+		if (dai->id == MT8195_AFE_IO_UL_SRC1)
+			clk_id = MT8195_CLK_AUD_ADC;
+		else if (dai->id == MT8195_AFE_IO_UL_SRC2)
+			clk_id = MT8195_CLK_AUD_ADDA6_ADC;
+		else
+			clk_id = -1;
+	}
+	if (clk_id >= 0)
+		mt8195_afe_enable_clk(afe, afe_priv->clk[clk_id]);
+	return 0;
+}
+
+static void mtk_dai_adda_shutdown(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	int clk_id;
+
+	dev_dbg(dai->dev, "%s id %d\n", __func__, dai->id);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		clk_id = MT8195_CLK_AUD_DAC;
+	} else {
+		if (dai->id == MT8195_AFE_IO_UL_SRC1)
+			clk_id = MT8195_CLK_AUD_ADC;
+		else if (dai->id == MT8195_AFE_IO_UL_SRC2)
+			clk_id = MT8195_CLK_AUD_ADDA6_ADC;
+		else
+			clk_id = -1;
+	}
+
+	if (clk_id >= 0)
+		mt8195_afe_disable_clk(afe, afe_priv->clk[clk_id]);
+
+	clk_id = MT8195_CLK_INFRA_AO_AUDIO_26M_B;
+	mt8195_afe_disable_clk(afe, afe_priv->clk[clk_id]);
+}
+
+static int mtk_dai_da_configure(struct mtk_base_afe *afe,
+				unsigned int rate, int id)
+{
+	unsigned int val = 0;
+	unsigned int mask = 0;
+
+	/* set sampling rate */
+	mask |= DL_2_INPUT_MODE_CTL_MASK;
+	val |= DL_2_INPUT_MODE_CTL(afe_adda_dl_rate_transform(afe, rate));
+
+	/* turn off saturation */
+	mask |= DL_2_CH1_SATURATION_EN_CTL;
+	mask |= DL_2_CH2_SATURATION_EN_CTL;
+
+	/* turn off mute function */
+	mask |= DL_2_MUTE_CH1_OFF_CTL_PRE;
+	mask |= DL_2_MUTE_CH2_OFF_CTL_PRE;
+	val |= DL_2_MUTE_CH1_OFF_CTL_PRE;
+	val |= DL_2_MUTE_CH2_OFF_CTL_PRE;
+
+	/* set voice input data if input sample rate is 8k or 16k */
+	mask |= DL_2_VOICE_MODE_CTL_PRE;
+	if (rate == 8000 || rate == 16000)
+		val |= DL_2_VOICE_MODE_CTL_PRE;
+
+	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, mask, val);
+
+	mask = 0;
+	val = 0;
+
+	/* new 2nd sdm */
+	mask |= DL_USE_NEW_2ND_SDM;
+	val |= DL_USE_NEW_2ND_SDM;
+	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SDM_DCCOMP_CON, mask, val);
+
+	return 0;
+}
+
+static int mtk_dai_ad_configure(struct mtk_base_afe *afe,
+				unsigned int rate, int id)
+{
+	unsigned int val = 0;
+	unsigned int mask = 0;
+
+	mask |= UL_VOICE_MODE_CTL_MASK;
+	val |= UL_VOICE_MODE_CTL(afe_adda_ul_rate_transform(afe, rate));
+
+	switch (id) {
+	case MT8195_AFE_IO_UL_SRC1:
+		regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
+				   mask, val);
+		break;
+	case MT8195_AFE_IO_UL_SRC2:
+		regmap_update_bits(afe->regmap, AFE_ADDA6_UL_SRC_CON0,
+				   mask, val);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_dai_adda_priv *adda_priv = afe_priv->dai_priv[dai->id];
+	unsigned int rate = params_rate(params);
+	int id = dai->id;
+	int ret = 0;
+
+	dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
+		__func__, id, substream->stream, rate);
+
+	if (rate > ADDA_HIRES_THRES)
+		adda_priv->hires_required = 1;
+	else
+		adda_priv->hires_required = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		ret = mtk_dai_da_configure(afe, rate, id);
+	else
+		ret = mtk_dai_ad_configure(afe, rate, id);
+
+	return ret;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
+	.startup = mtk_dai_adda_startup,
+	.shutdown = mtk_dai_adda_shutdown,
+	.hw_params = mtk_dai_adda_hw_params,
+};
+
+/* dai driver */
+#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
+				 SNDRV_PCM_RATE_96000 |\
+				 SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
+				SNDRV_PCM_RATE_16000 |\
+				SNDRV_PCM_RATE_32000 |\
+				SNDRV_PCM_RATE_48000 |\
+				SNDRV_PCM_RATE_96000 |\
+				SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			  SNDRV_PCM_FMTBIT_S24_LE |\
+			  SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+	{
+		.name = "DL_SRC",
+		.id = MT8195_AFE_IO_DL_SRC,
+		.playback = {
+			.stream_name = "ADDA Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_PLAYBACK_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "UL_SRC1",
+		.id = MT8195_AFE_IO_UL_SRC1,
+		.capture = {
+			.stream_name = "ADDA Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+	{
+		.name = "UL_SRC2",
+		.id = MT8195_AFE_IO_UL_SRC2,
+		.capture = {
+			.stream_name = "ADDA6 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_ADDA_CAPTURE_RATES,
+			.formats = MTK_ADDA_FORMATS,
+		},
+		.ops = &mtk_dai_adda_ops,
+	},
+};
+
+static int init_adda_priv_data(struct mtk_base_afe *afe)
+{
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_dai_adda_priv *adda_priv;
+	int adda_dai_list[] = { MT8195_AFE_IO_DL_SRC,
+				MT8195_AFE_IO_UL_SRC1,
+				MT8195_AFE_IO_UL_SRC2};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) {
+		adda_priv = devm_kzalloc(afe->dev,
+					 sizeof(struct mtk_dai_adda_priv),
+					 GFP_KERNEL);
+		if (!adda_priv)
+			return -ENOMEM;
+
+		afe_priv->dai_priv[adda_dai_list[i]] = adda_priv;
+	}
+
+	return 0;
+}
+
+int mt8195_dai_adda_register(struct mtk_base_afe *afe)
+{
+	struct mtk_base_afe_dai *dai;
+
+	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+	if (!dai)
+		return -ENOMEM;
+
+	list_add(&dai->list, &afe->sub_dais);
+
+	dai->dai_drivers = mtk_dai_adda_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
+
+	dai->dapm_widgets = mtk_dai_adda_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
+	dai->dapm_routes = mtk_dai_adda_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
+	dai->controls = mtk_dai_adda_controls;
+	dai->num_controls = ARRAY_SIZE(mtk_dai_adda_controls);
+
+	return init_adda_priv_data(afe);
+}
-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 4/8] ASoC: mediatek: mt8195: support pcm in platform driver
  2021-06-29  1:47 [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 1/8] ASoC: mediatek: mt8195: update mediatek common driver Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 3/8] ASoC: mediatek: mt8195: support adda in platform driver Trevor Wu
@ 2021-06-29  1:47 ` Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 6/8] dt-bindings: mediatek: mt8195: add audio afe document Trevor Wu
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Trevor Wu @ 2021-06-29  1:47 UTC (permalink / raw)
  To: broonie, tiwai, robh+dt, matthias.bgg
  Cc: trevor.wu, alsa-devel, linux-mediatek, linux-arm-kernel,
	linux-kernel, devicetree, bicycle.tsai, jiaxin.yu, cychiang,
	aaronyu

This patch adds mt8195 pcm dai driver.

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
---
 sound/soc/mediatek/mt8195/mt8195-dai-pcm.c | 393 +++++++++++++++++++++
 1 file changed, 393 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-dai-pcm.c

diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
new file mode 100644
index 000000000000..bb0e2e4da14a
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-pcm.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI PCM I/F Control
+ *
+ * Copyright (c) 2020 MediaTek Inc.
+ * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
+ *         Trevor Wu <trevor.wu@mediatek.com>
+ */
+
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8195-afe-clk.h"
+#include "mt8195-afe-common.h"
+#include "mt8195-reg.h"
+
+enum {
+	MTK_DAI_PCM_FMT_I2S,
+	MTK_DAI_PCM_FMT_EIAJ,
+	MTK_DAI_PCM_FMT_MODEA,
+	MTK_DAI_PCM_FMT_MODEB,
+};
+
+enum {
+	MTK_DAI_PCM_CLK_A1SYS,
+	MTK_DAI_PCM_CLK_A2SYS,
+	MTK_DAI_PCM_CLK_26M_48K,
+	MTK_DAI_PCM_CLK_26M_441K,
+};
+
+struct mtk_dai_pcm_rate {
+	unsigned int rate;
+	unsigned int reg_value;
+};
+
+struct mtk_dai_pcmif_priv {
+	unsigned int slave_mode;
+	unsigned int lrck_inv;
+	unsigned int bck_inv;
+	unsigned int format;
+};
+
+static const struct mtk_dai_pcm_rate mtk_dai_pcm_rates[] = {
+	{ .rate = 8000, .reg_value = 0, },
+	{ .rate = 16000, .reg_value = 1, },
+	{ .rate = 32000, .reg_value = 2, },
+	{ .rate = 48000, .reg_value = 3, },
+	{ .rate = 11025, .reg_value = 1, },
+	{ .rate = 22050, .reg_value = 2, },
+	{ .rate = 44100, .reg_value = 3, },
+};
+
+static int mtk_dai_pcm_mode(unsigned int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mtk_dai_pcm_rates); i++)
+		if (mtk_dai_pcm_rates[i].rate == rate)
+			return mtk_dai_pcm_rates[i].reg_value;
+
+	return -EINVAL;
+}
+
+static const struct snd_kcontrol_new mtk_dai_pcm_o000_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN0, 0, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN0_2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_dai_pcm_o001_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN1, 1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN1_2, 7, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
+	SND_SOC_DAPM_MIXER("I002", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I003", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("O000", SND_SOC_NOPM, 0, 0,
+			   mtk_dai_pcm_o000_mix,
+			   ARRAY_SIZE(mtk_dai_pcm_o000_mix)),
+	SND_SOC_DAPM_MIXER("O001", SND_SOC_NOPM, 0, 0,
+			   mtk_dai_pcm_o001_mix,
+			   ARRAY_SIZE(mtk_dai_pcm_o001_mix)),
+
+	SND_SOC_DAPM_INPUT("PCM1_INPUT"),
+	SND_SOC_DAPM_OUTPUT("PCM1_OUTPUT"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
+	{"I002", NULL, "PCM1 Capture"},
+	{"I003", NULL, "PCM1 Capture"},
+
+	{"O000", "I000 Switch", "I000"},
+	{"O001", "I001 Switch", "I001"},
+
+	{"O000", "I070 Switch", "I070"},
+	{"O001", "I071 Switch", "I071"},
+
+	{"PCM1 Playback", NULL, "O000"},
+	{"PCM1 Playback", NULL, "O001"},
+
+	{"PCM1_OUTPUT", NULL, "PCM1 Playback"},
+	{"PCM1 Capture", NULL, "PCM1_INPUT"},
+};
+
+static void mtk_dai_pcm_enable(struct mtk_base_afe *afe)
+{
+	regmap_update_bits(afe->regmap, PCM_INTF_CON1,
+			   PCM_INTF_CON1_PCM_EN, PCM_INTF_CON1_PCM_EN);
+}
+
+static void mtk_dai_pcm_disable(struct mtk_base_afe *afe)
+{
+	regmap_update_bits(afe->regmap, PCM_INTF_CON1,
+			   PCM_INTF_CON1_PCM_EN, 0x0);
+}
+
+static int mtk_dai_pcm_configure(struct snd_pcm_substream *substream,
+				 struct snd_soc_dai *dai)
+{
+	struct snd_pcm_runtime * const runtime = substream->runtime;
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id];
+	unsigned int slave_mode = pcmif_priv->slave_mode;
+	unsigned int lrck_inv = pcmif_priv->lrck_inv;
+	unsigned int bck_inv = pcmif_priv->bck_inv;
+	unsigned int fmt = pcmif_priv->format;
+	unsigned int bit_width = dai->sample_bits;
+	unsigned int val = 0;
+	unsigned int mask = 0;
+	int fs = 0;
+	int mode = 0;
+
+	/* sync freq mode */
+	fs = mt8195_afe_fs_timing(runtime->rate);
+	if (fs < 0)
+		return -EINVAL;
+	val |= PCM_INTF_CON2_SYNC_FREQ_MODE(fs);
+	mask |= PCM_INTF_CON2_SYNC_FREQ_MODE_MASK;
+
+	/* clk domain sel */
+	if (runtime->rate % 8000)
+		val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_441K);
+	else
+		val |= PCM_INTF_CON2_CLK_DOMAIN_SEL(MTK_DAI_PCM_CLK_26M_48K);
+	mask |= PCM_INTF_CON2_CLK_DOMAIN_SEL_MASK;
+
+	regmap_update_bits(afe->regmap, PCM_INTF_CON2, mask, val);
+
+	val = 0;
+	mask = 0;
+
+	/* pcm mode */
+	mode = mtk_dai_pcm_mode(runtime->rate);
+	if (mode < 0)
+		return -EINVAL;
+	val |= PCM_INTF_CON1_PCM_MODE(mode);
+	mask |= PCM_INTF_CON1_PCM_MODE_MASK;
+
+	/* pcm format */
+	val |= PCM_INTF_CON1_PCM_FMT(fmt);
+	mask |= PCM_INTF_CON1_PCM_FMT_MASK;
+
+	/* pcm sync length */
+	if (fmt == MTK_DAI_PCM_FMT_MODEA ||
+	    fmt == MTK_DAI_PCM_FMT_MODEB)
+		val |= PCM_INTF_CON1_SYNC_LENGTH(1);
+	else
+		val |= PCM_INTF_CON1_SYNC_LENGTH(bit_width);
+	mask |= PCM_INTF_CON1_SYNC_LENGTH_MASK;
+
+	/* pcm bits, word length */
+	if (bit_width > 16) {
+		val |= PCM_INTF_CON1_PCM_24BIT;
+		val |= PCM_INTF_CON1_PCM_WLEN_64BCK;
+	} else {
+		val |= PCM_INTF_CON1_PCM_16BIT;
+		val |= PCM_INTF_CON1_PCM_WLEN_32BCK;
+	}
+	mask |= PCM_INTF_CON1_PCM_BIT_MASK;
+	mask |= PCM_INTF_CON1_PCM_WLEN_MASK;
+
+	/* master/slave */
+	if (!slave_mode) {
+		val |= PCM_INTF_CON1_PCM_MASTER;
+
+		if (lrck_inv)
+			val |= PCM_INTF_CON1_SYNC_OUT_INV;
+		if (bck_inv)
+			val |= PCM_INTF_CON1_BCLK_OUT_INV;
+		mask |= PCM_INTF_CON1_CLK_OUT_INV_MASK;
+	} else {
+		val |= PCM_INTF_CON1_PCM_SLAVE;
+
+		if (lrck_inv)
+			val |= PCM_INTF_CON1_SYNC_IN_INV;
+		if (bck_inv)
+			val |= PCM_INTF_CON1_BCLK_IN_INV;
+		mask |= PCM_INTF_CON1_CLK_IN_INV_MASK;
+
+		/* TODO: add asrc setting for slave mode */
+	}
+	mask |= PCM_INTF_CON1_PCM_M_S_MASK;
+
+	regmap_update_bits(afe->regmap, PCM_INTF_CON1, mask, val);
+
+	return 0;
+}
+
+/* dai ops */
+static int mtk_dai_pcm_startup(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+	if (dai->component->active)
+		return 0;
+
+	mt8195_afe_enable_main_clock(afe);
+
+	mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]);
+	mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]);
+	mt8195_afe_enable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]);
+
+	return 0;
+}
+
+static void mtk_dai_pcm_shutdown(struct snd_pcm_substream *substream,
+				 struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+
+	if (dai->component->active)
+		return;
+
+	mtk_dai_pcm_disable(afe);
+
+	mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_PCMIF]);
+	mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC12]);
+	mt8195_afe_disable_clk(afe, afe_priv->clk[MT8195_CLK_AUD_ASRC11]);
+
+	mt8195_afe_disable_main_clock(afe);
+}
+
+static int mtk_dai_pcm_prepare(struct snd_pcm_substream *substream,
+			       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	int ret = 0;
+
+	if (snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK) &&
+	    snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE))
+		return 0;
+
+	ret = mtk_dai_pcm_configure(substream, dai);
+	if (ret)
+		return ret;
+
+	mtk_dai_pcm_enable(afe);
+
+	return 0;
+}
+
+static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_dai_pcmif_priv *pcmif_priv = afe_priv->dai_priv[dai->id];
+
+	dev_dbg(dai->dev, "%s fmt 0x%x\n", __func__, fmt);
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		pcmif_priv->format = MTK_DAI_PCM_FMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		pcmif_priv->format = MTK_DAI_PCM_FMT_MODEA;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		pcmif_priv->format = MTK_DAI_PCM_FMT_MODEB;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		pcmif_priv->bck_inv = 0;
+		pcmif_priv->lrck_inv = 0;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		pcmif_priv->bck_inv = 0;
+		pcmif_priv->lrck_inv = 1;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		pcmif_priv->bck_inv = 1;
+		pcmif_priv->lrck_inv = 0;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		pcmif_priv->bck_inv = 1;
+		pcmif_priv->lrck_inv = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		pcmif_priv->slave_mode = 1;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		pcmif_priv->slave_mode = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
+	.startup	= mtk_dai_pcm_startup,
+	.shutdown	= mtk_dai_pcm_shutdown,
+	.prepare	= mtk_dai_pcm_prepare,
+	.set_fmt	= mtk_dai_pcm_set_fmt,
+};
+
+/* dai driver */
+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000)
+
+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			 SNDRV_PCM_FMTBIT_S24_LE |\
+			 SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
+	{
+		.name = "PCM1",
+		.id = MT8195_AFE_IO_PCM,
+		.playback = {
+			.stream_name = "PCM1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_PCM_RATES,
+			.formats = MTK_PCM_FORMATS,
+		},
+		.capture = {
+			.stream_name = "PCM1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = MTK_PCM_RATES,
+			.formats = MTK_PCM_FORMATS,
+		},
+		.ops = &mtk_dai_pcm_ops,
+		.symmetric_rate = 1,
+		.symmetric_sample_bits = 1,
+	},
+};
+
+static int init_pcmif_priv_data(struct mtk_base_afe *afe)
+{
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_dai_pcmif_priv *pcmif_priv;
+
+	pcmif_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_pcmif_priv),
+				  GFP_KERNEL);
+	if (!pcmif_priv)
+		return -ENOMEM;
+
+	afe_priv->dai_priv[MT8195_AFE_IO_PCM] = pcmif_priv;
+	return 0;
+}
+
+int mt8195_dai_pcm_register(struct mtk_base_afe *afe)
+{
+	struct mtk_base_afe_dai *dai;
+
+	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+	if (!dai)
+		return -ENOMEM;
+
+	list_add(&dai->list, &afe->sub_dais);
+
+	dai->dai_drivers = mtk_dai_pcm_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
+
+	dai->dapm_widgets = mtk_dai_pcm_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
+	dai->dapm_routes = mtk_dai_pcm_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
+
+	return init_pcmif_priv_data(afe);
+}
-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 6/8] dt-bindings: mediatek: mt8195: add audio afe document
  2021-06-29  1:47 [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC Trevor Wu
                   ` (2 preceding siblings ...)
  2021-06-29  1:47 ` [PATCH v2 4/8] ASoC: mediatek: mt8195: support pcm " Trevor Wu
@ 2021-06-29  1:47 ` Trevor Wu
  2021-07-01 20:18   ` Rob Herring
  2021-06-29  1:47 ` [PATCH v2 7/8] ASoC: mediatek: mt8195: add machine driver with mt6359, rt1019 and rt5682 Trevor Wu
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Trevor Wu @ 2021-06-29  1:47 UTC (permalink / raw)
  To: broonie, tiwai, robh+dt, matthias.bgg
  Cc: trevor.wu, alsa-devel, linux-mediatek, linux-arm-kernel,
	linux-kernel, devicetree, bicycle.tsai, jiaxin.yu, cychiang,
	aaronyu

This patch adds mt8195 audio afe document.

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
---
This patch depends on the following series that have not been accepted.

[1] Mediatek MT8195 clock support
https://patchwork.kernel.org/project/linux-mediatek/list/?series=501923
(dt-bindings/clock/mt8195-clk.h is included)

[2] Mediatek MT8195 power domain support
https://patchwork.kernel.org/project/linux-mediatek/list/?series=500709
(dt-bindings/power/mt8195-power.h is included)
---
 .../bindings/sound/mt8195-afe-pcm.yaml        | 136 ++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml

diff --git a/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
new file mode 100644
index 000000000000..a4fb5c7dd022
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-afe-pcm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek AFE PCM controller for mt8195
+
+maintainers:
+  - Trevor Wu <trevor.wu@mediatek.com>
+
+properties:
+  compatible:
+    const: mediatek,mt8195-audio
+
+  interrupts:
+    maxItems: 1
+
+  mediatek,topckgen:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of the mediatek topckgen controller
+
+  power-domains:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: audio 26M clock
+      - description: AFE clock
+      - description: audio infra sys clock
+      - description: audio infra 26M clock
+
+  clock-names:
+    items:
+      - const: clk26m
+      - const: aud_afe
+      - const: infra_ao_audio
+      - const: infra_ao_audio_26m_b
+
+  etdm-in1-chn-disabled:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    maxItems: 24
+    description: Specify which input channel should be disabled.
+
+  etdm-in2-chn-disabled:
+    $ref: /schemas/types.yaml#/definitions/uint8-array
+    maxItems: 16
+    description: Specify which input channel should be disabled.
+
+patternProperties:
+  "^etdm-in[1-2]-mclk-source$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Specify etdm in mclk source clock.
+    enum:
+      - 0 # xtal_26m_ck
+      - 1 # apll1_ck
+      - 2 # apll2_ck
+      - 3 # apll3_ck
+      - 4 # apll4_ck
+      - 5 # apll5_ck
+      - 6 # hdmirx_apll_ck
+
+  "^etdm-out[1-3]-mclk-source$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Specify etdm out mclk source clock.
+
+  "^etdm-in[1-2]-mclk-alwasys-on-rate$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Specify etdm in mclk output rate for always on case.
+
+  "^etdm-out[1-3]-mclk-alwasys-on-rate$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Specify etdm out mclk output rate for always on case.
+
+  "^etdm-in[1-2]-data-mode$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Specify etdm in data mode.
+    enum:
+      - 0 # one pin (TDM)
+      - 1 # multi pin (I2S)
+
+  "^etdm-out[1-3]-data-mode$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Specify etdm out data mode.
+
+  "^etdm-in[1-2]-cowork-source$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      etdm modules can share the same external clock pin. Specify
+      which etdm clock source is required by this etdm in moudule.
+    enum:
+      - 0 # etdm1_in
+      - 1 # etdm2_in
+      - 2 # etdm1_out
+      - 3 # etdm2_out
+      - 4 # etdm3_out
+
+  "^etdm-out[1-3]-cowork-source$":
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      etdm modules can share the same external clock pin. Specify
+      which etdm clock source is required by this etdm out moudule.
+
+required:
+  - compatible
+  - interrupts
+  - mediatek,topckgen
+  - power-domains
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/mt8195-clk.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/power/mt8195-power.h>
+
+    afe: mt8195-afe-pcm {
+        compatible = "mediatek,mt8195-audio";
+        interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
+        mediatek,topckgen = <&topckgen>;
+        power-domains = <&spm MT8195_POWER_DOMAIN_AUDIO>;
+        clocks = <&clk26m>,
+                 <&audsys CLK_AUD_AFE>,
+                 <&infracfg_ao CLK_INFRA_AO_AUDIO>,
+                 <&infracfg_ao CLK_INFRA_AO_AUDIO_26M_B>;
+        clock-names = "clk26m",
+                      "aud_afe",
+                      "infra_ao_audio",
+                      "infra_ao_audio_26m_b";
+    };
+
+...
-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 7/8] ASoC: mediatek: mt8195: add machine driver with mt6359, rt1019 and rt5682
  2021-06-29  1:47 [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC Trevor Wu
                   ` (3 preceding siblings ...)
  2021-06-29  1:47 ` [PATCH v2 6/8] dt-bindings: mediatek: mt8195: add audio afe document Trevor Wu
@ 2021-06-29  1:47 ` Trevor Wu
  2021-06-29  1:47 ` [PATCH v2 8/8] dt-bindings: mediatek: mt8195: add mt8195-mt6359-rt1019-rt5682 document Trevor Wu
       [not found] ` <20210629014736.31153-6-trevor.wu@mediatek.com>
  6 siblings, 0 replies; 18+ messages in thread
From: Trevor Wu @ 2021-06-29  1:47 UTC (permalink / raw)
  To: broonie, tiwai, robh+dt, matthias.bgg
  Cc: trevor.wu, alsa-devel, linux-mediatek, linux-arm-kernel,
	linux-kernel, devicetree, bicycle.tsai, jiaxin.yu, cychiang,
	aaronyu

This patch adds support for mt8195 board with mt6359, rt1019 and rt5682.

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
Reported-by: kernel test robot <lkp@intel.com>
---
 sound/soc/mediatek/Kconfig                    |  14 +
 sound/soc/mediatek/mt8195/Makefile            |   3 +
 .../mt8195/mt8195-mt6359-rt1019-rt5682.c      | 977 ++++++++++++++++++
 3 files changed, 994 insertions(+)
 create mode 100644 sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c

diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 3389f382be06..bfee954d0c7c 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -193,3 +193,17 @@ config SND_SOC_MT8195
 	  that can be used with other codecs.
 	  Select Y if you have such device.
 	  If unsure select "N".
+
+config SND_SOC_MT8195_MT6359_RT1019_RT5682
+	tristate "ASoC Audio driver for MT8195 with MT6359 RT1019 RT5682 codec"
+	depends on I2C
+	depends on SND_SOC_MT8195
+	select SND_SOC_MT6359
+	select SND_SOC_RT1015P
+	select SND_SOC_RT5682_I2C
+	select SND_SOC_DMIC
+	help
+	  This adds ASoC driver for Mediatek MT8195 boards
+	  with the MT6359 RT1019 RT5682 audio codec.
+	  Select Y if you have such device.
+	  If unsure select "N".
diff --git a/sound/soc/mediatek/mt8195/Makefile b/sound/soc/mediatek/mt8195/Makefile
index b2c9fd88f39e..883038c7dc3f 100644
--- a/sound/soc/mediatek/mt8195/Makefile
+++ b/sound/soc/mediatek/mt8195/Makefile
@@ -9,3 +9,6 @@ snd-soc-mt8195-afe-objs := \
 	mt8195-dai-pcm.o
 
 obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
+
+# machine driver
+obj-$(CONFIG_SND_SOC_MT8195_MT6359_RT1019_RT5682) += mt8195-mt6359-rt1019-rt5682.o
diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c
new file mode 100644
index 000000000000..58ed9799ca14
--- /dev/null
+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359-rt1019-rt5682.c
@@ -0,0 +1,977 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// mt8195-mt6359-rt1019-rt5682.c  --
+//	MT8195-MT6359-RT1019-RT6358 ALSA SoC machine driver
+//
+// Copyright (c) 2021 MediaTek Inc.
+// Author: Trevor Wu <trevor.wu@mediatek.com>
+//
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <sound/rt5682.h>
+#include <sound/soc.h>
+#include "../../codecs/mt6359.h"
+#include "../../codecs/rt5682.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "mt8195-afe-common.h"
+
+#define RT1019_CODEC_DAI	"HiFi"
+#define RT1019_DEV0_NAME	"rt1019p"
+
+#define RT5682_CODEC_DAI	"rt5682-aif1"
+#define RT5682_DEV0_NAME	"rt5682.2-001a"
+
+struct mt8195_mt6359_rt1019_rt5682_priv {
+	struct snd_soc_jack headset_jack;
+};
+
+static const struct snd_soc_dapm_widget
+	mt8195_mt6359_rt1019_rt5682_widgets[] = {
+	SND_SOC_DAPM_SPK("Speakers", NULL),
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route mt8195_mt6359_rt1019_rt5682_routes[] = {
+	/* speaker */
+	{ "Speakers", NULL, "Speaker" },
+	/* headset */
+	{ "Headphone Jack", NULL, "HPOL" },
+	{ "Headphone Jack", NULL, "HPOR" },
+	{ "IN1P", NULL, "Headset Mic" },
+};
+
+static const struct snd_kcontrol_new mt8195_mt6359_rt1019_rt5682_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Speakers"),
+	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+};
+
+static int mt8195_rt5682_etdm_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+	unsigned int rate = params_rate(params);
+	unsigned int mclk_fs_ratio = 128;
+	unsigned int mclk_fs = rate * mclk_fs_ratio;
+	int bitwidth;
+	int ret;
+
+	bitwidth = snd_pcm_format_width(params_format(params));
+	if (bitwidth < 0) {
+		dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
+		return bitwidth;
+	}
+
+	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
+	if (ret) {
+		dev_err(card->dev, "failed to set tdm slot\n");
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1,
+				  RT5682_PLL1_S_BCLK1,
+				  params_rate(params) * 64,
+				  params_rate(params) * 512);
+	if (ret) {
+		dev_err(card->dev, "failed to set pll\n");
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(codec_dai,
+				     RT5682_SCLK_S_PLL1,
+				     params_rate(params) * 512,
+				     SND_SOC_CLOCK_IN);
+	if (ret) {
+		dev_err(card->dev, "failed to set sysclk\n");
+		return ret;
+	}
+
+	return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8195_rt5682_etdm_ops = {
+	.hw_params = mt8195_rt5682_etdm_hw_params,
+};
+
+#define CKSYS_AUD_TOP_CFG 0x032c
+#define CKSYS_AUD_TOP_MON 0x0330
+
+static int mt8195_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *cmpnt_afe =
+		snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+	struct snd_soc_component *cmpnt_codec =
+		asoc_rtd_to_codec(rtd, 0)->component;
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
+	struct mt8195_afe_private *afe_priv = afe->platform_priv;
+	struct mtkaif_param *param = &afe_priv->mtkaif_params;
+	int phase;
+	unsigned int monitor;
+	int mtkaif_calibration_num_phase;
+	int test_done_1, test_done_2, test_done_3;
+	int cycle_1, cycle_2, cycle_3;
+	int prev_cycle_1, prev_cycle_2, prev_cycle_3;
+	int chosen_phase_1, chosen_phase_2, chosen_phase_3;
+	int counter;
+	bool mtkaif_calibration_ok;
+	int mtkaif_chosen_phase[MT8195_MTKAIF_MISO_NUM];
+	int mtkaif_phase_cycle[MT8195_MTKAIF_MISO_NUM];
+	int i;
+
+	dev_info(afe->dev, "%s(), start\n", __func__);
+
+	param->mtkaif_calibration_ok = false;
+	for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++) {
+		param->mtkaif_chosen_phase[i] = -1;
+		param->mtkaif_phase_cycle[i] = 0;
+		mtkaif_chosen_phase[i] = -1;
+		mtkaif_phase_cycle[i] = 0;
+	}
+
+	if (IS_ERR(afe_priv->topckgen)) {
+		dev_info(afe->dev, "%s() Cannot find topckgen controller\n",
+			 __func__);
+		return 0;
+	}
+
+	pm_runtime_get_sync(afe->dev);
+	mt6359_mtkaif_calibration_enable(cmpnt_codec);
+
+	/* set test type to synchronizer pulse */
+	regmap_update_bits(afe_priv->topckgen,
+			   CKSYS_AUD_TOP_CFG, 0xffff, 0x4);
+	mtkaif_calibration_num_phase = 42;	/* mt6359: 0 ~ 42 */
+	mtkaif_calibration_ok = true;
+
+	for (phase = 0;
+	     phase <= mtkaif_calibration_num_phase && mtkaif_calibration_ok;
+	     phase++) {
+		mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
+						    phase, phase, phase);
+
+		regmap_update_bits(afe_priv->topckgen,
+				   CKSYS_AUD_TOP_CFG, 0x1, 0x1);
+
+		test_done_1 = 0;
+		test_done_2 = 0;
+		test_done_3 = 0;
+		cycle_1 = -1;
+		cycle_2 = -1;
+		cycle_3 = -1;
+		counter = 0;
+		while (!(test_done_1 & test_done_2 & test_done_3)) {
+			regmap_read(afe_priv->topckgen,
+				    CKSYS_AUD_TOP_MON, &monitor);
+			test_done_1 = (monitor >> 28) & 0x1;
+			test_done_2 = (monitor >> 29) & 0x1;
+			test_done_3 = (monitor >> 30) & 0x1;
+			if (test_done_1 == 1)
+				cycle_1 = monitor & 0xf;
+
+			if (test_done_2 == 1)
+				cycle_2 = (monitor >> 4) & 0xf;
+
+			if (test_done_3 == 1)
+				cycle_3 = (monitor >> 8) & 0xf;
+
+			/* handle if never test done */
+			if (++counter > 10000) {
+				dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, cycle_3 %d, monitor 0x%x\n",
+					 __func__,
+					 cycle_1, cycle_2, cycle_3, monitor);
+				mtkaif_calibration_ok = false;
+				break;
+			}
+		}
+
+		if (phase == 0) {
+			prev_cycle_1 = cycle_1;
+			prev_cycle_2 = cycle_2;
+			prev_cycle_3 = cycle_3;
+		}
+
+		if (cycle_1 != prev_cycle_1 &&
+		    mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) {
+			mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = phase - 1;
+			mtkaif_phase_cycle[MT8195_MTKAIF_MISO_0] = prev_cycle_1;
+		}
+
+		if (cycle_2 != prev_cycle_2 &&
+		    mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) {
+			mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = phase - 1;
+			mtkaif_phase_cycle[MT8195_MTKAIF_MISO_1] = prev_cycle_2;
+		}
+
+		if (cycle_3 != prev_cycle_3 &&
+		    mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) {
+			mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = phase - 1;
+			mtkaif_phase_cycle[MT8195_MTKAIF_MISO_2] = prev_cycle_3;
+		}
+
+		regmap_update_bits(afe_priv->topckgen,
+				   CKSYS_AUD_TOP_CFG, 0x1, 0x0);
+
+		if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] >= 0 &&
+		    mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] >= 0 &&
+		    mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] >= 0)
+			break;
+	}
+
+	if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] < 0) {
+		mtkaif_calibration_ok = false;
+		chosen_phase_1 = 0;
+	} else {
+		chosen_phase_1 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0];
+	}
+
+	if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] < 0) {
+		mtkaif_calibration_ok = false;
+		chosen_phase_2 = 0;
+	} else {
+		chosen_phase_2 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1];
+	}
+
+	if (mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] < 0) {
+		mtkaif_calibration_ok = false;
+		chosen_phase_3 = 0;
+	} else {
+		chosen_phase_3 = mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2];
+	}
+
+	mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
+					    chosen_phase_1,
+					    chosen_phase_2,
+					    chosen_phase_3);
+
+	mt6359_mtkaif_calibration_disable(cmpnt_codec);
+	pm_runtime_put(afe->dev);
+
+	param->mtkaif_calibration_ok = mtkaif_calibration_ok;
+	param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_0] = chosen_phase_1;
+	param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_1] = chosen_phase_2;
+	param->mtkaif_chosen_phase[MT8195_MTKAIF_MISO_2] = chosen_phase_3;
+	for (i = 0; i < MT8195_MTKAIF_MISO_NUM; i++)
+		param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i];
+
+	dev_info(afe->dev, "%s(), end, calibration ok %d\n",
+		 __func__, param->mtkaif_calibration_ok);
+
+	return 0;
+}
+
+static int mt8195_mt6359_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *cmpnt_codec =
+		asoc_rtd_to_codec(rtd, 0)->component;
+
+	/* set mtkaif protocol */
+	mt6359_set_mtkaif_protocol(cmpnt_codec,
+				   MT6359_MTKAIF_PROTOCOL_2_CLK_P2);
+
+	/* mtkaif calibration */
+	mt8195_mt6359_mtkaif_calibration(rtd);
+
+	return 0;
+}
+
+static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *cmpnt_codec =
+		asoc_rtd_to_codec(rtd, 0)->component;
+	struct mt8195_mt6359_rt1019_rt5682_priv *priv =
+		snd_soc_card_get_drvdata(rtd->card);
+	struct snd_soc_jack *jack = &priv->headset_jack;
+	int ret;
+
+	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
+				    SND_JACK_HEADSET | SND_JACK_BTN_0 |
+				    SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+				    SND_JACK_BTN_3,
+				    jack, NULL, 0);
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+		return ret;
+	}
+
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+	ret = snd_soc_component_set_jack(cmpnt_codec, jack, NULL);
+	if (ret) {
+		dev_err(rtd->dev, "Headset Jack set failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+};
+
+static int mt8195_etdm_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				       struct snd_pcm_hw_params *params)
+{
+	/* fix BE i2s format to 32bit, clean param mask first */
+	snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+			     0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+	return 0;
+}
+
+static int mt8195_dptx_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+	unsigned int rate = params_rate(params);
+	unsigned int mclk_fs_ratio = 256;
+	unsigned int mclk_fs = rate * mclk_fs_ratio;
+
+	return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs,
+				      SND_SOC_CLOCK_OUT);
+}
+
+static struct snd_soc_ops mt8195_dptx_ops = {
+	.hw_params = mt8195_dptx_hw_params,
+};
+
+static int mt8195_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				       struct snd_pcm_hw_params *params)
+{
+	/* fix BE i2s format to 32bit, clean param mask first */
+	snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+			     0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+	params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+	return 0;
+}
+
+static int mt8195_playback_startup(struct snd_pcm_substream *substream)
+{
+	static const unsigned int rates[] = {
+		48000
+	};
+	static const unsigned int channels[] = {
+		2
+	};
+	static const struct snd_pcm_hw_constraint_list constraints_rates = {
+		.count = ARRAY_SIZE(rates),
+		.list  = rates,
+		.mask = 0,
+	};
+	static const struct snd_pcm_hw_constraint_list constraints_channels = {
+		.count = ARRAY_SIZE(channels),
+		.list  = channels,
+		.mask = 0,
+	};
+
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int ret;
+
+	ret = snd_pcm_hw_constraint_list(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_RATE,
+					 &constraints_rates);
+	if (ret < 0) {
+		dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+		return ret;
+	}
+
+	ret = snd_pcm_hw_constraint_list(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_CHANNELS,
+					 &constraints_channels);
+	if (ret < 0) {
+		dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_ops mt8195_playback_ops = {
+	.startup = mt8195_playback_startup,
+};
+
+static int mt8195_capture_startup(struct snd_pcm_substream *substream)
+{
+	static const unsigned int rates[] = {
+		48000
+	};
+	static const unsigned int channels[] = {
+		1, 2
+	};
+	static const struct snd_pcm_hw_constraint_list constraints_rates = {
+		.count = ARRAY_SIZE(rates),
+		.list  = rates,
+		.mask = 0,
+	};
+	static const struct snd_pcm_hw_constraint_list constraints_channels = {
+		.count = ARRAY_SIZE(channels),
+		.list  = channels,
+		.mask = 0,
+	};
+
+	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int ret;
+
+	ret = snd_pcm_hw_constraint_list(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_RATE,
+					 &constraints_rates);
+	if (ret < 0) {
+		dev_err(rtd->dev, "hw_constraint_list rate failed\n");
+		return ret;
+	}
+
+	ret = snd_pcm_hw_constraint_list(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_CHANNELS,
+					 &constraints_channels);
+	if (ret < 0) {
+		dev_err(rtd->dev, "hw_constraint_list channel failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct snd_soc_ops mt8195_capture_ops = {
+	.startup = mt8195_capture_startup,
+};
+
+enum {
+	DAI_LINK_DL2_FE,
+	DAI_LINK_DL3_FE,
+	DAI_LINK_DL6_FE,
+	DAI_LINK_DL7_FE,
+	DAI_LINK_DL8_FE,
+	DAI_LINK_DL10_FE,
+	DAI_LINK_DL11_FE,
+	DAI_LINK_UL1_FE,
+	DAI_LINK_UL2_FE,
+	DAI_LINK_UL3_FE,
+	DAI_LINK_UL4_FE,
+	DAI_LINK_UL5_FE,
+	DAI_LINK_UL6_FE,
+	DAI_LINK_UL8_FE,
+	DAI_LINK_UL9_FE,
+	DAI_LINK_UL10_FE,
+	DAI_LINK_DL_SRC_BE,
+	DAI_LINK_DPTX_BE,
+	DAI_LINK_ETDM1_IN_BE,
+	DAI_LINK_ETDM2_IN_BE,
+	DAI_LINK_ETDM1_OUT_BE,
+	DAI_LINK_ETDM2_OUT_BE,
+	DAI_LINK_ETDM3_OUT_BE,
+	DAI_LINK_PCM1_BE,
+	DAI_LINK_UL_SRC1_BE,
+	DAI_LINK_UL_SRC2_BE,
+};
+
+/* FE */
+SND_SOC_DAILINK_DEFS(DL2_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL3_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL6_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL7_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL8_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL10_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL10")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DL11_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL11")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL1_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL2_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL3_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL4_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL5_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL6_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL8_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL8")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL9_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL9")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL10_FE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL10")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* BE */
+SND_SOC_DAILINK_DEFS(DL_SRC_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+						   "mt6359-snd-codec-aif1")),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(DPTX_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DPTX")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM1_IN_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_IN")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM2_IN_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_IN")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
+						   RT5682_CODEC_DAI)),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM1_OUT_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME,
+						   RT5682_CODEC_DAI)),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM2_OUT_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_OUT")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC(RT1019_DEV0_NAME,
+						   RT1019_CODEC_DAI)),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(ETDM3_OUT_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM3_OUT")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(PCM1_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("PCM1")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL_SRC1_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC1")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+						   "mt6359-snd-codec-aif1"),
+					COMP_CODEC("dmic-codec",
+						   "dmic-hifi")),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(UL_SRC2_BE,
+		     DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC2")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
+						   "mt6359-snd-codec-aif2")),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link mt8195_mt6359_rt1019_rt5682_dai_links[] = {
+	/* FE */
+	[DAI_LINK_DL2_FE] = {
+		.name = "DL2_FE",
+		.stream_name = "DL2 Playback",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.ops = &mt8195_playback_ops,
+		SND_SOC_DAILINK_REG(DL2_FE),
+	},
+	[DAI_LINK_DL3_FE] = {
+		.name = "DL3_FE",
+		.stream_name = "DL3 Playback",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.ops = &mt8195_playback_ops,
+		SND_SOC_DAILINK_REG(DL3_FE),
+	},
+	[DAI_LINK_DL6_FE] = {
+		.name = "DL6_FE",
+		.stream_name = "DL6 Playback",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.ops = &mt8195_playback_ops,
+		SND_SOC_DAILINK_REG(DL6_FE),
+	},
+	[DAI_LINK_DL7_FE] = {
+		.name = "DL7_FE",
+		.stream_name = "DL7 Playback",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_PRE,
+			SND_SOC_DPCM_TRIGGER_PRE,
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		SND_SOC_DAILINK_REG(DL7_FE),
+	},
+	[DAI_LINK_DL8_FE] = {
+		.name = "DL8_FE",
+		.stream_name = "DL8 Playback",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.ops = &mt8195_playback_ops,
+		SND_SOC_DAILINK_REG(DL8_FE),
+	},
+	[DAI_LINK_DL10_FE] = {
+		.name = "DL10_FE",
+		.stream_name = "DL10 Playback",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		SND_SOC_DAILINK_REG(DL10_FE),
+	},
+	[DAI_LINK_DL11_FE] = {
+		.name = "DL11_FE",
+		.stream_name = "DL11 Playback",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.ops = &mt8195_playback_ops,
+		SND_SOC_DAILINK_REG(DL11_FE),
+	},
+	[DAI_LINK_UL1_FE] = {
+		.name = "UL1_FE",
+		.stream_name = "UL1 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_PRE,
+			SND_SOC_DPCM_TRIGGER_PRE,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(UL1_FE),
+	},
+	[DAI_LINK_UL2_FE] = {
+		.name = "UL2_FE",
+		.stream_name = "UL2 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8195_capture_ops,
+		SND_SOC_DAILINK_REG(UL2_FE),
+	},
+	[DAI_LINK_UL3_FE] = {
+		.name = "UL3_FE",
+		.stream_name = "UL3 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8195_capture_ops,
+		SND_SOC_DAILINK_REG(UL3_FE),
+	},
+	[DAI_LINK_UL4_FE] = {
+		.name = "UL4_FE",
+		.stream_name = "UL4 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8195_capture_ops,
+		SND_SOC_DAILINK_REG(UL4_FE),
+	},
+	[DAI_LINK_UL5_FE] = {
+		.name = "UL5_FE",
+		.stream_name = "UL5 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8195_capture_ops,
+		SND_SOC_DAILINK_REG(UL5_FE),
+	},
+	[DAI_LINK_UL6_FE] = {
+		.name = "UL6_FE",
+		.stream_name = "UL6 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_PRE,
+			SND_SOC_DPCM_TRIGGER_PRE,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(UL6_FE),
+	},
+	[DAI_LINK_UL8_FE] = {
+		.name = "UL8_FE",
+		.stream_name = "UL8 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8195_capture_ops,
+		SND_SOC_DAILINK_REG(UL8_FE),
+	},
+	[DAI_LINK_UL9_FE] = {
+		.name = "UL9_FE",
+		.stream_name = "UL9 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8195_capture_ops,
+		SND_SOC_DAILINK_REG(UL9_FE),
+	},
+	[DAI_LINK_UL10_FE] = {
+		.name = "UL10_FE",
+		.stream_name = "UL10 Capture",
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST,
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8195_capture_ops,
+		SND_SOC_DAILINK_REG(UL10_FE),
+	},
+	/* BE */
+	[DAI_LINK_DL_SRC_BE] = {
+		.name = "DL_SRC_BE",
+		.init = mt8195_mt6359_init,
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		SND_SOC_DAILINK_REG(DL_SRC_BE),
+	},
+	[DAI_LINK_DPTX_BE] = {
+		.name = "DPTX_BE",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.ops = &mt8195_dptx_ops,
+		.be_hw_params_fixup = mt8195_dptx_hw_params_fixup,
+		SND_SOC_DAILINK_REG(DPTX_BE),
+	},
+	[DAI_LINK_ETDM1_IN_BE] = {
+		.name = "ETDM1_IN_BE",
+		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(ETDM1_IN_BE),
+	},
+	[DAI_LINK_ETDM2_IN_BE] = {
+		.name = "ETDM2_IN_BE",
+		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+		.dpcm_capture = 1,
+		.init = mt8195_rt5682_init,
+		.ops = &mt8195_rt5682_etdm_ops,
+		.be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
+		SND_SOC_DAILINK_REG(ETDM2_IN_BE),
+	},
+	[DAI_LINK_ETDM1_OUT_BE] = {
+		.name = "ETDM1_OUT_BE",
+		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+		.dpcm_playback = 1,
+		.ops = &mt8195_rt5682_etdm_ops,
+		.be_hw_params_fixup = mt8195_etdm_hw_params_fixup,
+		SND_SOC_DAILINK_REG(ETDM1_OUT_BE),
+	},
+	[DAI_LINK_ETDM2_OUT_BE] = {
+		.name = "ETDM2_OUT_BE",
+		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+		.dpcm_playback = 1,
+		SND_SOC_DAILINK_REG(ETDM2_OUT_BE),
+	},
+	[DAI_LINK_ETDM3_OUT_BE] = {
+		.name = "ETDM3_OUT_BE",
+		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+		.dpcm_playback = 1,
+		SND_SOC_DAILINK_REG(ETDM3_OUT_BE),
+	},
+	[DAI_LINK_PCM1_BE] = {
+		.name = "PCM1_BE",
+		.no_pcm = 1,
+		.dai_fmt = SND_SOC_DAIFMT_I2S |
+			SND_SOC_DAIFMT_NB_NF |
+			SND_SOC_DAIFMT_CBS_CFS,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(PCM1_BE),
+	},
+	[DAI_LINK_UL_SRC1_BE] = {
+		.name = "UL_SRC1_BE",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(UL_SRC1_BE),
+	},
+	[DAI_LINK_UL_SRC2_BE] = {
+		.name = "UL_SRC2_BE",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(UL_SRC2_BE),
+	},
+};
+
+static struct snd_soc_card mt8195_mt6359_rt1019_rt5682_soc_card = {
+	.name = "mt8195_mt6359_rt1019_rt5682",
+	.owner = THIS_MODULE,
+	.dai_link = mt8195_mt6359_rt1019_rt5682_dai_links,
+	.num_links = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_dai_links),
+	.controls = mt8195_mt6359_rt1019_rt5682_controls,
+	.num_controls = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_controls),
+	.dapm_widgets = mt8195_mt6359_rt1019_rt5682_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_widgets),
+	.dapm_routes = mt8195_mt6359_rt1019_rt5682_routes,
+	.num_dapm_routes = ARRAY_SIZE(mt8195_mt6359_rt1019_rt5682_routes),
+};
+
+static int mt8195_mt6359_rt1019_rt5682_dev_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &mt8195_mt6359_rt1019_rt5682_soc_card;
+	struct device_node *platform_node;
+	struct snd_soc_dai_link *dai_link;
+	struct mt8195_mt6359_rt1019_rt5682_priv *priv = NULL;
+
+	int ret, i;
+
+	card->dev = &pdev->dev;
+
+	platform_node = of_parse_phandle(pdev->dev.of_node,
+					 "mediatek,platform", 0);
+	if (!platform_node) {
+		dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n");
+		return -EINVAL;
+	}
+
+	for_each_card_prelinks(card, i, dai_link) {
+		if (!dai_link->platforms->name)
+			dai_link->platforms->of_node = platform_node;
+	}
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	snd_soc_card_set_drvdata(card, priv);
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret)
+		dev_dbg(&pdev->dev, "%s snd_soc_register_card fail %d\n",
+			__func__, ret);
+	return ret;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id mt8195_mt6359_rt1019_rt5682_dt_match[] = {
+	{.compatible = "mediatek,mt8195_mt6359_rt1019_rt5682",},
+	{}
+};
+#endif
+
+static const struct dev_pm_ops mt8195_mt6359_rt1019_rt5682_pm_ops = {
+	.poweroff = snd_soc_poweroff,
+	.restore = snd_soc_resume,
+};
+
+static struct platform_driver mt8195_mt6359_rt1019_rt5682_driver = {
+	.driver = {
+		.name = "mt8195_mt6359_rt1019_rt5682",
+#ifdef CONFIG_OF
+		.of_match_table = mt8195_mt6359_rt1019_rt5682_dt_match,
+#endif
+		.pm = &mt8195_mt6359_rt1019_rt5682_pm_ops,
+	},
+	.probe = mt8195_mt6359_rt1019_rt5682_dev_probe,
+};
+
+module_platform_driver(mt8195_mt6359_rt1019_rt5682_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8195-MT6359-RT1019-RT5682 ALSA SoC machine driver");
+MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("mt8195_mt6359_rt1019_rt5682 soc card");
-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v2 8/8] dt-bindings: mediatek: mt8195: add mt8195-mt6359-rt1019-rt5682 document
  2021-06-29  1:47 [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC Trevor Wu
                   ` (4 preceding siblings ...)
  2021-06-29  1:47 ` [PATCH v2 7/8] ASoC: mediatek: mt8195: add machine driver with mt6359, rt1019 and rt5682 Trevor Wu
@ 2021-06-29  1:47 ` Trevor Wu
       [not found] ` <20210629014736.31153-6-trevor.wu@mediatek.com>
  6 siblings, 0 replies; 18+ messages in thread
From: Trevor Wu @ 2021-06-29  1:47 UTC (permalink / raw)
  To: broonie, tiwai, robh+dt, matthias.bgg
  Cc: trevor.wu, alsa-devel, linux-mediatek, linux-arm-kernel,
	linux-kernel, devicetree, bicycle.tsai, jiaxin.yu, cychiang,
	aaronyu

This patch adds document for mt8195 board with mt6359, rt1019 and rt5682

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
---
 .../sound/mt8195-mt6359-rt1019-rt5682.yaml    | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml

diff --git a/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
new file mode 100644
index 000000000000..246c0875e64e
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8195-mt6359-rt1019-rt5682.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mt8195-mt6359-rt1019-rt5682.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8195 with MT6359, RT1019 and RT5682 ASoC sound card driver
+
+maintainers:
+  - Trevor Wu <trevor.wu@mediatek.com>
+
+description:
+  This binding describes the MT8195 sound card.
+
+properties:
+  compatible:
+    const: mediatek,mt8195_mt6359_rt1019_rt5682
+
+  mediatek,platform:
+    $ref: "/schemas/types.yaml#/definitions/phandle"
+    description: The phandle of MT8195 ASoC platform.
+
+additionalProperties: false
+
+required:
+  - compatible
+  - mediatek,platform
+
+examples:
+  - |
+
+    sound: mt8195-sound {
+        compatible = "mediatek,mt8195_mt6359_rt1019_rt5682";
+        mediatek,platform = <&afe>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&aud_pins_default>;
+    };
+
+...
-- 
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 6/8] dt-bindings: mediatek: mt8195: add audio afe document
  2021-06-29  1:47 ` [PATCH v2 6/8] dt-bindings: mediatek: mt8195: add audio afe document Trevor Wu
@ 2021-07-01 20:18   ` Rob Herring
  2021-07-05  7:01     ` Trevor Wu
  0 siblings, 1 reply; 18+ messages in thread
From: Rob Herring @ 2021-07-01 20:18 UTC (permalink / raw)
  To: Trevor Wu
  Cc: broonie, tiwai, matthias.bgg, alsa-devel, linux-mediatek,
	linux-arm-kernel, linux-kernel, devicetree, bicycle.tsai,
	jiaxin.yu, cychiang, aaronyu

On Tue, Jun 29, 2021 at 09:47:34AM +0800, Trevor Wu wrote:
> This patch adds mt8195 audio afe document.
> 
> Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> ---
> This patch depends on the following series that have not been accepted.
> 
> [1] Mediatek MT8195 clock support
> https://patchwork.kernel.org/project/linux-mediatek/list/?series=501923
> (dt-bindings/clock/mt8195-clk.h is included)
> 
> [2] Mediatek MT8195 power domain support
> https://patchwork.kernel.org/project/linux-mediatek/list/?series=500709
> (dt-bindings/power/mt8195-power.h is included)
> ---
>  .../bindings/sound/mt8195-afe-pcm.yaml        | 136 ++++++++++++++++++
>  1 file changed, 136 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
> 
> diff --git a/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
> new file mode 100644
> index 000000000000..a4fb5c7dd022
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
> @@ -0,0 +1,136 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/mt8195-afe-pcm.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Mediatek AFE PCM controller for mt8195
> +
> +maintainers:
> +  - Trevor Wu <trevor.wu@mediatek.com>
> +
> +properties:
> +  compatible:
> +    const: mediatek,mt8195-audio
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  mediatek,topckgen:
> +    $ref: "/schemas/types.yaml#/definitions/phandle"
> +    description: The phandle of the mediatek topckgen controller
> +
> +  power-domains:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: audio 26M clock
> +      - description: AFE clock
> +      - description: audio infra sys clock
> +      - description: audio infra 26M clock
> +
> +  clock-names:
> +    items:
> +      - const: clk26m
> +      - const: aud_afe
> +      - const: infra_ao_audio
> +      - const: infra_ao_audio_26m_b
> +
> +  etdm-in1-chn-disabled:

Needs a vendor prefix.

> +    $ref: /schemas/types.yaml#/definitions/uint8-array
> +    maxItems: 24
> +    description: Specify which input channel should be disabled.
> +
> +  etdm-in2-chn-disabled:

Needs a vendor prefix.

> +    $ref: /schemas/types.yaml#/definitions/uint8-array
> +    maxItems: 16
> +    description: Specify which input channel should be disabled.
> +
> +patternProperties:
> +  "^etdm-in[1-2]-mclk-source$":

And all these need a vendor prefix.

> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Specify etdm in mclk source clock.
> +    enum:
> +      - 0 # xtal_26m_ck
> +      - 1 # apll1_ck
> +      - 2 # apll2_ck
> +      - 3 # apll3_ck
> +      - 4 # apll4_ck
> +      - 5 # apll5_ck
> +      - 6 # hdmirx_apll_ck
> +
> +  "^etdm-out[1-3]-mclk-source$":
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Specify etdm out mclk source clock.
> +
> +  "^etdm-in[1-2]-mclk-alwasys-on-rate$":
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Specify etdm in mclk output rate for always on case.

Hz? If so, '-hz' unit suffix and drop the type ref.

> +
> +  "^etdm-out[1-3]-mclk-alwasys-on-rate$":

typo: alwasys

> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Specify etdm out mclk output rate for always on case.

Hz?

> +
> +  "^etdm-in[1-2]-data-mode$":
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Specify etdm in data mode.
> +    enum:
> +      - 0 # one pin (TDM)
> +      - 1 # multi pin (I2S)

Can be boolean?

> +
> +  "^etdm-out[1-3]-data-mode$":
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Specify etdm out data mode.

Constraints on values?

> +
> +  "^etdm-in[1-2]-cowork-source$":
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      etdm modules can share the same external clock pin. Specify
> +      which etdm clock source is required by this etdm in moudule.
> +    enum:
> +      - 0 # etdm1_in
> +      - 1 # etdm2_in
> +      - 2 # etdm1_out
> +      - 3 # etdm2_out
> +      - 4 # etdm3_out
> +
> +  "^etdm-out[1-3]-cowork-source$":
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      etdm modules can share the same external clock pin. Specify
> +      which etdm clock source is required by this etdm out moudule.

Constraints?

> +
> +required:
> +  - compatible
> +  - interrupts
> +  - mediatek,topckgen
> +  - power-domains
> +  - clocks
> +  - clock-names
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/mt8195-clk.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/power/mt8195-power.h>
> +
> +    afe: mt8195-afe-pcm {
> +        compatible = "mediatek,mt8195-audio";
> +        interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
> +        mediatek,topckgen = <&topckgen>;
> +        power-domains = <&spm MT8195_POWER_DOMAIN_AUDIO>;
> +        clocks = <&clk26m>,
> +                 <&audsys CLK_AUD_AFE>,
> +                 <&infracfg_ao CLK_INFRA_AO_AUDIO>,
> +                 <&infracfg_ao CLK_INFRA_AO_AUDIO_26M_B>;
> +        clock-names = "clk26m",
> +                      "aud_afe",
> +                      "infra_ao_audio",
> +                      "infra_ao_audio_26m_b";
> +    };
> +
> +...
> -- 
> 2.18.0
> 
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 6/8] dt-bindings: mediatek: mt8195: add audio afe document
  2021-07-01 20:18   ` Rob Herring
@ 2021-07-05  7:01     ` Trevor Wu
  0 siblings, 0 replies; 18+ messages in thread
From: Trevor Wu @ 2021-07-05  7:01 UTC (permalink / raw)
  To: Rob Herring
  Cc: broonie, tiwai, matthias.bgg, alsa-devel, linux-mediatek,
	linux-arm-kernel, linux-kernel, devicetree, bicycle.tsai,
	jiaxin.yu, cychiang, aaronyu

On Thu, 2021-07-01 at 14:18 -0600, Rob Herring wrote:
> On Tue, Jun 29, 2021 at 09:47:34AM +0800, Trevor Wu wrote:
> > This patch adds mt8195 audio afe document.
> > 
> > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > ---
> > This patch depends on the following series that have not been
> > accepted.
> > 
> > [1] Mediatek MT8195 clock support
> > 
https://patchwork.kernel.org/project/linux-mediatek/list/?series=501923
> > (dt-bindings/clock/mt8195-clk.h is included)
> > 
> > [2] Mediatek MT8195 power domain support
> > 
https://patchwork.kernel.org/project/linux-mediatek/list/?series=500709
> > (dt-bindings/power/mt8195-power.h is included)
> > ---
> >  .../bindings/sound/mt8195-afe-pcm.yaml        | 136
> > ++++++++++++++++++
> >  1 file changed, 136 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/sound/mt8195-
> > afe-pcm.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/sound/mt8195-afe-
> > pcm.yaml b/Documentation/devicetree/bindings/sound/mt8195-afe-
> > pcm.yaml
> > new file mode 100644
> > index 000000000000..a4fb5c7dd022
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/mt8195-afe-pcm.yaml
> > @@ -0,0 +1,136 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/mt8195-afe-pcm.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Mediatek AFE PCM controller for mt8195
> > +
> > +maintainers:
> > +  - Trevor Wu <trevor.wu@mediatek.com>
> > +
> > +properties:
> > +  compatible:
> > +    const: mediatek,mt8195-audio
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  mediatek,topckgen:
> > +    $ref: "/schemas/types.yaml#/definitions/phandle"
> > +    description: The phandle of the mediatek topckgen controller
> > +
> > +  power-domains:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    items:
> > +      - description: audio 26M clock
> > +      - description: AFE clock
> > +      - description: audio infra sys clock
> > +      - description: audio infra 26M clock
> > +
> > +  clock-names:
> > +    items:
> > +      - const: clk26m
> > +      - const: aud_afe
> > +      - const: infra_ao_audio
> > +      - const: infra_ao_audio_26m_b
> > +
> > +  etdm-in1-chn-disabled:
> 
> Needs a vendor prefix.
> 
> > +    $ref: /schemas/types.yaml#/definitions/uint8-array
> > +    maxItems: 24
> > +    description: Specify which input channel should be disabled.
> > +
> > +  etdm-in2-chn-disabled:
> 
> Needs a vendor prefix.
> 
> > +    $ref: /schemas/types.yaml#/definitions/uint8-array
> > +    maxItems: 16
> > +    description: Specify which input channel should be disabled.
> > +
> > +patternProperties:
> > +  "^etdm-in[1-2]-mclk-source$":
> 
> And all these need a vendor prefix.
> 
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: Specify etdm in mclk source clock.
> > +    enum:
> > +      - 0 # xtal_26m_ck
> > +      - 1 # apll1_ck
> > +      - 2 # apll2_ck
> > +      - 3 # apll3_ck
> > +      - 4 # apll4_ck
> > +      - 5 # apll5_ck
> > +      - 6 # hdmirx_apll_ck
> > +
> > +  "^etdm-out[1-3]-mclk-source$":
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: Specify etdm out mclk source clock.
> > +
> > +  "^etdm-in[1-2]-mclk-alwasys-on-rate$":
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: Specify etdm in mclk output rate for always on
> > case.
> 
> Hz? If so, '-hz' unit suffix and drop the type ref.
> 

Yes, it's Hz.
I will add unit suffix and drop the type.

> > +
> > +  "^etdm-out[1-3]-mclk-alwasys-on-rate$":
> 
> typo: alwasys
> 
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: Specify etdm out mclk output rate for always on
> > case.
> 
> Hz?
> 
> > +
> > +  "^etdm-in[1-2]-data-mode$":
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: Specify etdm in data mode.
> > +    enum:
> > +      - 0 # one pin (TDM)
> > +      - 1 # multi pin (I2S)
> 
> Can be boolean?
> 
Yes, becasue only two options can be configured for data mode.
I will replace it with a bool property like "mediatek,etdm-in[1-2]-
multi-pin-mode".

> > +
> > +  "^etdm-out[1-3]-data-mode$":
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: Specify etdm out data mode.
> 
> Constraints on values?
> 
> > +
> > +  "^etdm-in[1-2]-cowork-source$":
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: |
> > +      etdm modules can share the same external clock pin. Specify
> > +      which etdm clock source is required by this etdm in moudule.
> > +    enum:
> > +      - 0 # etdm1_in
> > +      - 1 # etdm2_in
> > +      - 2 # etdm1_out
> > +      - 3 # etdm2_out
> > +      - 4 # etdm3_out
> > +
> > +  "^etdm-out[1-3]-cowork-source$":
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description: |
> > +      etdm modules can share the same external clock pin. Specify
> > +      which etdm clock source is required by this etdm out
> > moudule.
> 
> Constraints?
> 
> > +
> > +required:
> > +  - compatible
> > +  - interrupts
> > +  - mediatek,topckgen
> > +  - power-domains
> > +  - clocks
> > +  - clock-names
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/clock/mt8195-clk.h>
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +    #include <dt-bindings/interrupt-controller/irq.h>
> > +    #include <dt-bindings/power/mt8195-power.h>
> > +
> > +    afe: mt8195-afe-pcm {
> > +        compatible = "mediatek,mt8195-audio";
> > +        interrupts = <GIC_SPI 822 IRQ_TYPE_LEVEL_HIGH 0>;
> > +        mediatek,topckgen = <&topckgen>;
> > +        power-domains = <&spm MT8195_POWER_DOMAIN_AUDIO>;
> > +        clocks = <&clk26m>,
> > +                 <&audsys CLK_AUD_AFE>,
> > +                 <&infracfg_ao CLK_INFRA_AO_AUDIO>,
> > +                 <&infracfg_ao CLK_INFRA_AO_AUDIO_26M_B>;
> > +        clock-names = "clk26m",
> > +                      "aud_afe",
> > +                      "infra_ao_audio",
> > +                      "infra_ao_audio_26m_b";
> > +    };
> > +
> > +...
> > -- 
> > 2.18.0
> > 

Thanks for your reviewing.
I will correct all problems on v3.

Thanks,
Trevor
> > 
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
       [not found] ` <20210629014736.31153-6-trevor.wu@mediatek.com>
@ 2021-07-12  6:57   ` Chen-Yu Tsai
  2021-07-12 15:09     ` Trevor Wu
  0 siblings, 1 reply; 18+ messages in thread
From: Chen-Yu Tsai @ 2021-07-12  6:57 UTC (permalink / raw)
  To: Trevor Wu
  Cc: broonie, tiwai, Rob Herring, Matthias Brugger, alsa-devel,
	linux-mediatek, linux-arm-kernel, LKML, devicetree, bicycle.tsai,
	Jiaxin Yu, cychiang, aaronyu

 are all internal Hi,

On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <trevor.wu@mediatek.com> wrote:
>
> This patch adds mt8195 platform and affiliated driver.
>
> Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> ---
>  sound/soc/mediatek/Kconfig                     |    9 +
>  sound/soc/mediatek/Makefile                   |    1 +
>  sound/soc/mediatek/mt8195/Makefile            |   11 +
>  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
>  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
>  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
>  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264 +++++++++++++++++
>  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793 ++++++++++++++
>  8 files changed, 7378 insertions(+)
>  create mode 100644 sound/soc/mediatek/mt8195/Makefile
>  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.c
>  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.h
>  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-common.h
>  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
>  create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h
>
> diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
> index 74dae4332d17..3389f382be06 100644
> --- a/sound/soc/mediatek/Kconfig
> +++ b/sound/soc/mediatek/Kconfig
> @@ -184,3 +184,12 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
>           with the MT6359 RT1015 RT5682 audio codec.
>           Select Y if you have such device.
>           If unsure select "N".
> +
> +config SND_SOC_MT8195
> +       tristate "ASoC support for Mediatek MT8195 chip"
> +       select SND_SOC_MEDIATEK
> +       help
> +         This adds ASoC platform driver support for Mediatek MT8195 chip
> +         that can be used with other codecs.
> +         Select Y if you have such device.
> +         If unsure select "N".
> diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
> index f6cb6b8508e3..34778ca12106 100644
> --- a/sound/soc/mediatek/Makefile
> +++ b/sound/soc/mediatek/Makefile
> @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
>  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
>  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
>  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> diff --git a/sound/soc/mediatek/mt8195/Makefile b/sound/soc/mediatek/mt8195/Makefile
> new file mode 100644
> index 000000000000..b2c9fd88f39e
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8195/Makefile
> @@ -0,0 +1,11 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +# platform driver
> +snd-soc-mt8195-afe-objs := \
> +       mt8195-afe-clk.o \
> +       mt8195-afe-pcm.o \
> +       mt8195-dai-adda.o \
> +       mt8195-dai-etdm.o \
> +       mt8195-dai-pcm.o
> +
> +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> new file mode 100644
> index 000000000000..57aa799b4f41
> --- /dev/null
> +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> @@ -0,0 +1,899 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> + *
> + * Copyright (c) 2021 MediaTek Inc.
> + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> + *         Trevor Wu <trevor.wu@mediatek.com>
> + */
> +
> +#include <linux/clk.h>
> +
> +#include "mt8195-afe-common.h"
> +#include "mt8195-afe-clk.h"
> +#include "mt8195-reg.h"
> +
> +static const char *aud_clks[MT8195_CLK_NUM] = {

Most of these clocks are not described in the device tree binding. If
the driver needs to reference them, they should be described. We should
not be hard-coding clock names across different drivers.

The more important question is, why does the driver need to reference
all of them? Maybe we should take a step back and draw out a clock tree
diagram for the hardware?

> +       /* xtal */
> +       [MT8195_CLK_XTAL_26M] = "clk26m",
> +       /* pll */
> +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> +       [MT8195_CLK_APMIXED_HDMIRX_APLL] = "hdmirx_apll",
> +       /* divider */
> +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> +       [MT8195_CLK_TOP_HDMIRX_APLL] = "hdmirx_apll_ck",
> +       [MT8195_CLK_TOP_MAINPLL_D4_D4] = "mainpll_d4_d4",
> +       [MT8195_CLK_TOP_MAINPLL_D5_D2] = "mainpll_d5_d2",
> +       [MT8195_CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",
> +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> +       /* mux */
> +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
> +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] = "audio_local_bus_sel",
> +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> +       /* clock gate */
> +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] = "mphone_slave_b",
> +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] = "infra_ao_audio_26m_b",
> +       [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",


> +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] = "aud_spdifin_tuner_apll",
> +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] = "aud_spdifin_tuner_dbg",
> +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> +       [MT8195_CLK_AUD_APLL1_TUNER] = "aud_apll1_tuner",
> +       [MT8195_CLK_AUD_APLL2_TUNER] = "aud_apll2_tuner",
> +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> +       [MT8195_CLK_AUD_TML] = "aud_tml",
> +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] = "aud_afe_26m_dmic_tm",
> +       [MT8195_CLK_AUD_UL_TML_HIRES] = "aud_ul_tml_hires",
> +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
> +       [MT8195_CLK_AUD_LINEIN_TUNER] = "aud_linein_tuner",
> +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",

The MT8195_CLK_AUD_* clocks are all internal to the audio subsystem:
the bits that control these clock gates are in the same address space
as the audio parts. Would it be possible to model them as internal
ASoC SUPPLY widgets? The external ones could be modeled using ASoC
CLK_SUPPLY widgets, and the dependencies could be modeled with ASoC
routes. The ASoC core could then handle power sequencing, which the
driver currently does manually.

IMO this is better than having two drivers handling two aspects of
the same piece of hardware, while the two aspects are intertwined.


Regards
ChenYu

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-12  6:57   ` [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver Chen-Yu Tsai
@ 2021-07-12 15:09     ` Trevor Wu
  2021-07-13  6:00       ` Chen-Yu Tsai
  0 siblings, 1 reply; 18+ messages in thread
From: Trevor Wu @ 2021-07-12 15:09 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: broonie, tiwai, Rob Herring, Matthias Brugger, alsa-devel,
	linux-mediatek, linux-arm-kernel, LKML, devicetree, bicycle.tsai,
	Jiaxin Yu, cychiang, aaronyu

On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
>  are all internal Hi,
> 
> On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <trevor.wu@mediatek.com>
> wrote:
> > 
> > This patch adds mt8195 platform and affiliated driver.
> > 
> > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > ---
> >  sound/soc/mediatek/Kconfig                     |    9 +
> >  sound/soc/mediatek/Makefile                   |    1 +
> >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
> >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > +++++++++++++++++
> >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > ++++++++++++++
> >  8 files changed, 7378 insertions(+)
> >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.h
> >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-common.h
> >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
> >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h
> > 
> > diff --git a/sound/soc/mediatek/Kconfig
> > b/sound/soc/mediatek/Kconfig
> > index 74dae4332d17..3389f382be06 100644
> > --- a/sound/soc/mediatek/Kconfig
> > +++ b/sound/soc/mediatek/Kconfig
> > @@ -184,3 +184,12 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
> >           with the MT6359 RT1015 RT5682 audio codec.
> >           Select Y if you have such device.
> >           If unsure select "N".
> > +
> > +config SND_SOC_MT8195
> > +       tristate "ASoC support for Mediatek MT8195 chip"
> > +       select SND_SOC_MEDIATEK
> > +       help
> > +         This adds ASoC platform driver support for Mediatek
> > MT8195 chip
> > +         that can be used with other codecs.
> > +         Select Y if you have such device.
> > +         If unsure select "N".
> > diff --git a/sound/soc/mediatek/Makefile
> > b/sound/soc/mediatek/Makefile
> > index f6cb6b8508e3..34778ca12106 100644
> > --- a/sound/soc/mediatek/Makefile
> > +++ b/sound/soc/mediatek/Makefile
> > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > b/sound/soc/mediatek/mt8195/Makefile
> > new file mode 100644
> > index 000000000000..b2c9fd88f39e
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8195/Makefile
> > @@ -0,0 +1,11 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +# platform driver
> > +snd-soc-mt8195-afe-objs := \
> > +       mt8195-afe-clk.o \
> > +       mt8195-afe-pcm.o \
> > +       mt8195-dai-adda.o \
> > +       mt8195-dai-etdm.o \
> > +       mt8195-dai-pcm.o
> > +
> > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > new file mode 100644
> > index 000000000000..57aa799b4f41
> > --- /dev/null
> > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > @@ -0,0 +1,899 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > + *
> > + * Copyright (c) 2021 MediaTek Inc.
> > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > + *         Trevor Wu <trevor.wu@mediatek.com>
> > + */
> > +
> > +#include <linux/clk.h>
> > +
> > +#include "mt8195-afe-common.h"
> > +#include "mt8195-afe-clk.h"
> > +#include "mt8195-reg.h"
> > +
> > +static const char *aud_clks[MT8195_CLK_NUM] = {
> 
> Most of these clocks are not described in the device tree binding. If
> the driver needs to reference them, they should be described. We
> should
> not be hard-coding clock names across different drivers.
> 
Sorry, I didn't know I have to list all clocks in the dt-binding.
Originally, I thought these clocks will be described in the clock
binding, so I didn't add them to the binding of afe driver.
I will add these clocks to mt8195-afe-pcm.yaml.

> The more important question is, why does the driver need to reference
> all of them? Maybe we should take a step back and draw out a clock
> tree
> diagram for the hardware?
> 
The clock structure is PLL -> MUX -> GATE.
xtal, pll and divider are the possible clock inputs for MUX.
Because we select the clock input of audio module based on the use
case, we use clk_get to retrive all clocks which are possible to be
used.
Some of them are not used in this series, because some modules are
still developing. Should I only keep the clocks that have been used in
the series?

> > +       /* xtal */
> > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > +       /* pll */
> > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] = "hdmirx_apll",
> > +       /* divider */
> > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > +       [MT8195_CLK_TOP_HDMIRX_APLL] = "hdmirx_apll_ck",
> > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] = "mainpll_d4_d4",
> > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] = "mainpll_d5_d2",
> > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",
> > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > +       /* mux */
> > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
> > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > "audio_local_bus_sel",
> > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > +       /* clock gate */
> > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] = "mphone_slave_b",
> > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] = "infra_ao_audio_26m_b",
> > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",
> 
> 
> > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > "aud_spdifin_tuner_apll",
> > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > "aud_spdifin_tuner_dbg",
> > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > +       [MT8195_CLK_AUD_APLL1_TUNER] = "aud_apll1_tuner",
> > +       [MT8195_CLK_AUD_APLL2_TUNER] = "aud_apll2_tuner",
> > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] = "aud_afe_26m_dmic_tm",
> > +       [MT8195_CLK_AUD_UL_TML_HIRES] = "aud_ul_tml_hires",
> > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
> > +       [MT8195_CLK_AUD_LINEIN_TUNER] = "aud_linein_tuner",
> > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> 
> The MT8195_CLK_AUD_* clocks are all internal to the audio subsystem:
> the bits that control these clock gates are in the same address space
> as the audio parts. Would it be possible to model them as internal
> ASoC SUPPLY widgets? The external ones could be modeled using ASoC
> CLK_SUPPLY widgets, and the dependencies could be modeled with ASoC
> routes. The ASoC core could then handle power sequencing, which the
> driver currently does manually.
> 
> IMO this is better than having two drivers handling two aspects of
> the same piece of hardware, while the two aspects are intertwined.
> 

Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such clocks.
But those clocks are managed by CCF in the preceding SOCs like mt2701,
mt6779 and mt8183. Additionally, in some audio modules, clocks should
be enabled before configuring parameters(hw_params). As far as I know,
if we use CLK_SUPPLY or SUPPLY to model clocks, the power sequence is
controlled by DAPM. It seems to be impossible to fulfill all use cases.
That's why we just keep the manual control sequence and CCF seems to be
the best choice to model such clock gatess.

Thanks,
Trevor
> 
> Regards
> ChenYu
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-12 15:09     ` Trevor Wu
@ 2021-07-13  6:00       ` Chen-Yu Tsai
  2021-07-15 11:05         ` Trevor Wu
  0 siblings, 1 reply; 18+ messages in thread
From: Chen-Yu Tsai @ 2021-07-13  6:00 UTC (permalink / raw)
  To: Trevor Wu, Chun-Jie Chen
  Cc: broonie, tiwai, Rob Herring, Matthias Brugger, alsa-devel,
	linux-mediatek, linux-arm-kernel, LKML, devicetree, bicycle.tsai,
	Jiaxin Yu, Jimmy Cheng-Yi Chiang, Li-Yu Yu

On Mon, Jul 12, 2021 at 11:10 PM Trevor Wu <trevor.wu@mediatek.com> wrote:
>
> On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
> >  are all internal Hi,
> >
> > On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <trevor.wu@mediatek.com>
> > wrote:
> > >
> > > This patch adds mt8195 platform and affiliated driver.
> > >
> > > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > > ---
> > >  sound/soc/mediatek/Kconfig                     |    9 +
> > >  sound/soc/mediatek/Makefile                   |    1 +
> > >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
> > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> > >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> > >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > > +++++++++++++++++
> > >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > > ++++++++++++++
> > >  8 files changed, 7378 insertions(+)
> > >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.h
> > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-common.h
> > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
> > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h
> > >
> > > diff --git a/sound/soc/mediatek/Kconfig
> > > b/sound/soc/mediatek/Kconfig
> > > index 74dae4332d17..3389f382be06 100644
> > > --- a/sound/soc/mediatek/Kconfig
> > > +++ b/sound/soc/mediatek/Kconfig
> > > @@ -184,3 +184,12 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
> > >           with the MT6359 RT1015 RT5682 audio codec.
> > >           Select Y if you have such device.
> > >           If unsure select "N".
> > > +
> > > +config SND_SOC_MT8195
> > > +       tristate "ASoC support for Mediatek MT8195 chip"
> > > +       select SND_SOC_MEDIATEK
> > > +       help
> > > +         This adds ASoC platform driver support for Mediatek
> > > MT8195 chip
> > > +         that can be used with other codecs.
> > > +         Select Y if you have such device.
> > > +         If unsure select "N".
> > > diff --git a/sound/soc/mediatek/Makefile
> > > b/sound/soc/mediatek/Makefile
> > > index f6cb6b8508e3..34778ca12106 100644
> > > --- a/sound/soc/mediatek/Makefile
> > > +++ b/sound/soc/mediatek/Makefile
> > > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> > >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> > >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> > >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > > b/sound/soc/mediatek/mt8195/Makefile
> > > new file mode 100644
> > > index 000000000000..b2c9fd88f39e
> > > --- /dev/null
> > > +++ b/sound/soc/mediatek/mt8195/Makefile
> > > @@ -0,0 +1,11 @@
> > > +# SPDX-License-Identifier: GPL-2.0
> > > +
> > > +# platform driver
> > > +snd-soc-mt8195-afe-objs := \
> > > +       mt8195-afe-clk.o \
> > > +       mt8195-afe-pcm.o \
> > > +       mt8195-dai-adda.o \
> > > +       mt8195-dai-etdm.o \
> > > +       mt8195-dai-pcm.o
> > > +
> > > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > new file mode 100644
> > > index 000000000000..57aa799b4f41
> > > --- /dev/null
> > > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > @@ -0,0 +1,899 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > > + *
> > > + * Copyright (c) 2021 MediaTek Inc.
> > > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > > + *         Trevor Wu <trevor.wu@mediatek.com>
> > > + */
> > > +
> > > +#include <linux/clk.h>
> > > +
> > > +#include "mt8195-afe-common.h"
> > > +#include "mt8195-afe-clk.h"
> > > +#include "mt8195-reg.h"
> > > +
> > > +static const char *aud_clks[MT8195_CLK_NUM] = {
> >
> > Most of these clocks are not described in the device tree binding. If
> > the driver needs to reference them, they should be described. We
> > should
> > not be hard-coding clock names across different drivers.
> >
> Sorry, I didn't know I have to list all clocks in the dt-binding.
> Originally, I thought these clocks will be described in the clock
> binding, so I didn't add them to the binding of afe driver.
> I will add these clocks to mt8195-afe-pcm.yaml.

If the device consumes clocks, then the clocks that get consumed should
be listed in the device's bindings. This is not related to the clock
bindings, which is a clock provider.

> > The more important question is, why does the driver need to reference
> > all of them? Maybe we should take a step back and draw out a clock
> > tree
> > diagram for the hardware?
> >
> The clock structure is PLL -> MUX -> GATE.
> xtal, pll and divider are the possible clock inputs for MUX.
> Because we select the clock input of audio module based on the use
> case, we use clk_get to retrive all clocks which are possible to be
> used.

So I see a couple the driver is doing reparenting:

  a. Reparent audio_h to standard oscillator when ADDA is not used,
     presumably to let the APLL be turned off

Why not just turn off audio_h? It looks like audio_h feeds a couple clock
gates in the audio subsystem. Just a guess, but is this the AHB bus clock?
Why not just have it parented to "univpll_d7" all the time then?

Also, reparenting really should be done implicitly with clk_set_rate()
with the clock driver supporting reparenting on rate changes.

  b. Assignment of PLLs for I2S/PCM MCLK outputs

Is there a reason for explicit assignment, other than clock rate conflicts?
CCF supports requesting and locking the clock rate. And again, implicit
reparenting should be the norm. The clock driver's purpose is to fulfill
any and all clock rate requirements from its consumers. The consumer should
only need to ask for the clock rate, not a specific parent, unless there
are details that are not yet covered by the CCF.

A related question: the chip has five APLLs. How many MCLK combinations
does the application need to support? I assume this includes the standard
24.576 MHz and 22.5792 MHz clock rates.

> Some of them are not used in this series, because some modules are
> still developing. Should I only keep the clocks that have been used in
> the series?

Yes please. Only add the ones that are used. Things that aren't used
don't get tested and verified, and end up as dead code. If there are
plans to extend them in the future, and you can leave comments stating
that intent, and also mention it in the cover letter.

> > > +       /* xtal */
> > > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > > +       /* pll */
> > > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] = "hdmirx_apll",
> > > +       /* divider */
> > > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > > +       [MT8195_CLK_TOP_HDMIRX_APLL] = "hdmirx_apll_ck",
> > > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] = "mainpll_d4_d4",
> > > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] = "mainpll_d5_d2",
> > > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",
> > > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > > +       /* mux */
> > > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
> > > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > > "audio_local_bus_sel",
> > > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > > +       /* clock gate */
> > > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] = "mphone_slave_b",
> > > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] = "infra_ao_audio_26m_b",
> > > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",
> >
> >
> > > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > > "aud_spdifin_tuner_apll",
> > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > > "aud_spdifin_tuner_dbg",
> > > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > > +       [MT8195_CLK_AUD_APLL1_TUNER] = "aud_apll1_tuner",
> > > +       [MT8195_CLK_AUD_APLL2_TUNER] = "aud_apll2_tuner",
> > > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] = "aud_afe_26m_dmic_tm",
> > > +       [MT8195_CLK_AUD_UL_TML_HIRES] = "aud_ul_tml_hires",
> > > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires",
> > > +       [MT8195_CLK_AUD_LINEIN_TUNER] = "aud_linein_tuner",
> > > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> >
> > The MT8195_CLK_AUD_* clocks are all internal to the audio subsystem:
> > the bits that control these clock gates are in the same address space
> > as the audio parts. Would it be possible to model them as internal
> > ASoC SUPPLY widgets? The external ones could be modeled using ASoC
> > CLK_SUPPLY widgets, and the dependencies could be modeled with ASoC
> > routes. The ASoC core could then handle power sequencing, which the
> > driver currently does manually.
> >
> > IMO this is better than having two drivers handling two aspects of
> > the same piece of hardware, while the two aspects are intertwined.
> >
>
> Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such clocks.
> But those clocks are managed by CCF in the preceding SOCs like mt2701,
> mt6779 and mt8183. Additionally, in some audio modules, clocks should

This being a new driver, we have some more freedom to improve the design.

> be enabled before configuring parameters(hw_params). As far as I know,
> if we use CLK_SUPPLY or SUPPLY to model clocks, the power sequence is
> controlled by DAPM. It seems to be impossible to fulfill all use cases.
> That's why we just keep the manual control sequence and CCF seems to be
> the best choice to model such clock gatess.

I see. So yes, using CCF does give you reference counting, dependency
tracking and other advantages. And using DAPM supplies means you can't
enable the clock gates outside of DAPM without both pieces of code
fighting for control.

Can we at least move the audio clock gates into the audio driver though?
The arbitrary separation into two devices and drivers is fishy. And with
the move the external references to the audio clock gates can be removed.

And regarding the clock requirements for different modules, could we have
that information put in comments somewhere, so if someone were to revisit
it later, they would have the information needed to understand and possibly
improve it? Because right now there's just a bunch of clocks enabled and
disabled and nothing to explain why that's needed.


Regards
ChenYu

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-13  6:00       ` Chen-Yu Tsai
@ 2021-07-15 11:05         ` Trevor Wu
  2021-07-19 10:05           ` Chen-Yu Tsai
  0 siblings, 1 reply; 18+ messages in thread
From: Trevor Wu @ 2021-07-15 11:05 UTC (permalink / raw)
  To: Chen-Yu Tsai, Chun-Jie Chen
  Cc: broonie, tiwai, Rob Herring, Matthias Brugger, alsa-devel,
	linux-mediatek, linux-arm-kernel, LKML, devicetree, bicycle.tsai,
	Jiaxin Yu, Jimmy Cheng-Yi Chiang, Li-Yu Yu

On Tue, 2021-07-13 at 14:00 +0800, Chen-Yu Tsai wrote:
> On Mon, Jul 12, 2021 at 11:10 PM Trevor Wu <trevor.wu@mediatek.com>
> wrote:
> > 
> > On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
> > >  are all internal Hi,
> > > 
> > > On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <trevor.wu@mediatek.com
> > > >
> > > wrote:
> > > > 
> > > > This patch adds mt8195 platform and affiliated driver.
> > > > 
> > > > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > > > ---
> > > >  sound/soc/mediatek/Kconfig                     |    9 +
> > > >  sound/soc/mediatek/Makefile                   |    1 +
> > > >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
> > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> > > >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> > > >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > > > +++++++++++++++++
> > > >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > > > ++++++++++++++
> > > >  8 files changed, 7378 insertions(+)
> > > >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.h
> > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > common.h
> > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
> > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h
> > > > 
> > > > diff --git a/sound/soc/mediatek/Kconfig
> > > > b/sound/soc/mediatek/Kconfig
> > > > index 74dae4332d17..3389f382be06 100644
> > > > --- a/sound/soc/mediatek/Kconfig
> > > > +++ b/sound/soc/mediatek/Kconfig
> > > > @@ -184,3 +184,12 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
> > > >           with the MT6359 RT1015 RT5682 audio codec.
> > > >           Select Y if you have such device.
> > > >           If unsure select "N".
> > > > +
> > > > +config SND_SOC_MT8195
> > > > +       tristate "ASoC support for Mediatek MT8195 chip"
> > > > +       select SND_SOC_MEDIATEK
> > > > +       help
> > > > +         This adds ASoC platform driver support for Mediatek
> > > > MT8195 chip
> > > > +         that can be used with other codecs.
> > > > +         Select Y if you have such device.
> > > > +         If unsure select "N".
> > > > diff --git a/sound/soc/mediatek/Makefile
> > > > b/sound/soc/mediatek/Makefile
> > > > index f6cb6b8508e3..34778ca12106 100644
> > > > --- a/sound/soc/mediatek/Makefile
> > > > +++ b/sound/soc/mediatek/Makefile
> > > > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> > > >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> > > >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> > > >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > > > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > > > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > > > b/sound/soc/mediatek/mt8195/Makefile
> > > > new file mode 100644
> > > > index 000000000000..b2c9fd88f39e
> > > > --- /dev/null
> > > > +++ b/sound/soc/mediatek/mt8195/Makefile
> > > > @@ -0,0 +1,11 @@
> > > > +# SPDX-License-Identifier: GPL-2.0
> > > > +
> > > > +# platform driver
> > > > +snd-soc-mt8195-afe-objs := \
> > > > +       mt8195-afe-clk.o \
> > > > +       mt8195-afe-pcm.o \
> > > > +       mt8195-dai-adda.o \
> > > > +       mt8195-dai-etdm.o \
> > > > +       mt8195-dai-pcm.o
> > > > +
> > > > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > > > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > new file mode 100644
> > > > index 000000000000..57aa799b4f41
> > > > --- /dev/null
> > > > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > @@ -0,0 +1,899 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > > > + *
> > > > + * Copyright (c) 2021 MediaTek Inc.
> > > > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > > > + *         Trevor Wu <trevor.wu@mediatek.com>
> > > > + */
> > > > +
> > > > +#include <linux/clk.h>
> > > > +
> > > > +#include "mt8195-afe-common.h"
> > > > +#include "mt8195-afe-clk.h"
> > > > +#include "mt8195-reg.h"
> > > > +
> > > > +static const char *aud_clks[MT8195_CLK_NUM] = {
> > > 
> > > Most of these clocks are not described in the device tree
> > > binding. If
> > > the driver needs to reference them, they should be described. We
> > > should
> > > not be hard-coding clock names across different drivers.
> > > 
> > 
> > Sorry, I didn't know I have to list all clocks in the dt-binding.
> > Originally, I thought these clocks will be described in the clock
> > binding, so I didn't add them to the binding of afe driver.
> > I will add these clocks to mt8195-afe-pcm.yaml.
> 
> If the device consumes clocks, then the clocks that get consumed
> should
> be listed in the device's bindings. This is not related to the clock
> bindings, which is a clock provider.
> 
Got it. Thanks.

> > > The more important question is, why does the driver need to
> > > reference
> > > all of them? Maybe we should take a step back and draw out a
> > > clock
> > > tree
> > > diagram for the hardware?
> > > 
> > 
> > The clock structure is PLL -> MUX -> GATE.
> > xtal, pll and divider are the possible clock inputs for MUX.
> > Because we select the clock input of audio module based on the use
> > case, we use clk_get to retrive all clocks which are possible to be
> > used.
> 
> So I see a couple the driver is doing reparenting:
> 
>   a. Reparent audio_h to standard oscillator when ADDA is not used,
>      presumably to let the APLL be turned off
> 
> Why not just turn off audio_h? It looks like audio_h feeds a couple
> clock
> gates in the audio subsystem. Just a guess, but is this the AHB bus
> clock?
> Why not just have it parented to "univpll_d7" all the time then?
> 

Sorry, I am not sure if it is the AHB bus clock. 
I only know how audio module uses the clock.
audio_h feeds to some clock gate like aud_adc_hires, which is used when
sampling rate is higher than 48kHz, and hardware designer suggests us
use apll1_ck when AFE requrires the clock.

As I know, DSP also requires audio_h. 
When we disable the clock in AFE driver, the ref count in CCF is not
becoming zero if DSP still uses it.
But only AFE requires higher clock rate, so we reparent audio_h to 26M
when it's not required in adda module.

> Also, reparenting really should be done implicitly with
> clk_set_rate()
> with the clock driver supporting reparenting on rate changes.
> 
>   b. Assignment of PLLs for I2S/PCM MCLK outputs
> 
> Is there a reason for explicit assignment, other than clock rate
> conflicts?
> CCF supports requesting and locking the clock rate. And again,
> implicit
> reparenting should be the norm. The clock driver's purpose is to
> fulfill
> any and all clock rate requirements from its consumers. The consumer
> should
> only need to ask for the clock rate, not a specific parent, unless
> there
> are details that are not yet covered by the CCF.
> 

For MCLK output, we should configure divider to get the target rate,
and it can only divide the clock from current parent source.
So we should do reparent to divider's parent in case the parent rate is
not a multiple of target rate.


> A related question: the chip has five APLLs. How many MCLK
> combinations
> does the application need to support? I assume this includes the
> standard
> 24.576 MHz and 22.5792 MHz clock rates.
> 

APLL1 and APLL2 are used in most AFE modules, so their rate should be
fixed.
APLL1 is fixed to 196608000Hz.
APLL2 is fixed to 180633600Hz.
APLL is inputed to the divider(8bit), and MCLK is the output of
divider.
Other APLLs are reserved for some special usage which can't be
supported by APLL1 & APLL2.
But APLL3~APLL5 aren't used in the series, so I will remove them in v3.

> > Some of them are not used in this series, because some modules are
> > still developing. Should I only keep the clocks that have been used
> > in
> > the series?
> 
> Yes please. Only add the ones that are used. Things that aren't used
> don't get tested and verified, and end up as dead code. If there are
> plans to extend them in the future, and you can leave comments
> stating
> that intent, and also mention it in the cover letter.
> 
OK, I will remove the unused clock in v3.

> > > > +       /* xtal */
> > > > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > > > +       /* pll */
> > > > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > > > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > > > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > > > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > > > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > > > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] = "hdmirx_apll",
> > > > +       /* divider */
> > > > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > > > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > > > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > > > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > > > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > > > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > > > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > > > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > > > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > > > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > > > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > > > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > > > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > > > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > > > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > > > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > > > +       [MT8195_CLK_TOP_HDMIRX_APLL] = "hdmirx_apll_ck",
> > > > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] = "mainpll_d4_d4",
> > > > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] = "mainpll_d5_d2",
> > > > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",
> > > > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > > > +       /* mux */
> > > > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > > > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > > > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > > > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > > > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > > > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > > > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > > > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > > > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > > > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > > > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > > > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > > > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > > > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
> > > > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > > > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > > > "audio_local_bus_sel",
> > > > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > > > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > > > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > > > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > > > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > > > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > > > +       /* clock gate */
> > > > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] = "mphone_slave_b",
> > > > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > > > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > > > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] =
> > > > "infra_ao_audio_26m_b",
> > > > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",
> > > 
> > > 
> > > > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > > > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > > > "aud_spdifin_tuner_apll",
> > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > > > "aud_spdifin_tuner_dbg",
> > > > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > > > +       [MT8195_CLK_AUD_APLL1_TUNER] = "aud_apll1_tuner",
> > > > +       [MT8195_CLK_AUD_APLL2_TUNER] = "aud_apll2_tuner",
> > > > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > > > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > > > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > > > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > > > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > > > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > > > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > > > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > > > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > > > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > > > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > > > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > > > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > > > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] =
> > > > "aud_afe_26m_dmic_tm",
> > > > +       [MT8195_CLK_AUD_UL_TML_HIRES] = "aud_ul_tml_hires",
> > > > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > > > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > > > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] =
> > > > "aud_adda6_adc_hires",
> > > > +       [MT8195_CLK_AUD_LINEIN_TUNER] = "aud_linein_tuner",
> > > > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > > > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > > > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > > > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > > > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > > > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > > > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > > > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > > > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > > > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > > > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > > > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > > > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > > > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > > > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > > > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > > > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > > > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > > > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > > > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > > > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > > > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > > > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > > > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > > > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > > > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > > > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > > > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > > > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > > > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > > > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > > > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > > > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > > > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > > > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > > > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > > > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > > > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > > > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > > > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > > > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > > > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > > > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> > > 
> > > The MT8195_CLK_AUD_* clocks are all internal to the audio
> > > subsystem:
> > > the bits that control these clock gates are in the same address
> > > space
> > > as the audio parts. Would it be possible to model them as
> > > internal
> > > ASoC SUPPLY widgets? The external ones could be modeled using
> > > ASoC
> > > CLK_SUPPLY widgets, and the dependencies could be modeled with
> > > ASoC
> > > routes. The ASoC core could then handle power sequencing, which
> > > the
> > > driver currently does manually.
> > > 
> > > IMO this is better than having two drivers handling two aspects
> > > of
> > > the same piece of hardware, while the two aspects are
> > > intertwined.
> > > 
> > 
> > Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such clocks.
> > But those clocks are managed by CCF in the preceding SOCs like
> > mt2701,
> > mt6779 and mt8183. Additionally, in some audio modules, clocks
> > should
> 
> This being a new driver, we have some more freedom to improve the
> design.
> 
> > be enabled before configuring parameters(hw_params). As far as I
> > know,
> > if we use CLK_SUPPLY or SUPPLY to model clocks, the power sequence
> > is
> > controlled by DAPM. It seems to be impossible to fulfill all use
> > cases.
> > That's why we just keep the manual control sequence and CCF seems
> > to be
> > the best choice to model such clock gatess.
> 
> I see. So yes, using CCF does give you reference counting, dependency
> tracking and other advantages. And using DAPM supplies means you
> can't
> enable the clock gates outside of DAPM without both pieces of code
> fighting for control.
> 
> Can we at least move the audio clock gates into the audio driver
> though?
> The arbitrary separation into two devices and drivers is fishy. And
> with
> the move the external references to the audio clock gates can be
> removed.
> 
Because DAPM SUPPLY can't fit our control scenario. 
Did you suggest us implement the simple logic control(including ref
count, clock dependency) for clock gate(MT8195_CLK_AUD_*) in afe driver
instead of using CCF?

> And regarding the clock requirements for different modules, could we
> have
> that information put in comments somewhere, so if someone were to
> revisit
> it later, they would have the information needed to understand and
> possibly
> improve it? Because right now there's just a bunch of clocks enabled
> and
> disabled and nothing to explain why that's needed.
> 

For example,
MT8195_CLK_AUD_ADC(clock gate) is one of the clock feeding to ADDA
module.
Did you want me show the clock gate list feeding to ADDA?
On the other hand, I didn't know how to show the information properly
in comments. Could you kindly share me an example for reference? 

Thanks,
Trevor
> 
> Regards
> ChenYu
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-15 11:05         ` Trevor Wu
@ 2021-07-19 10:05           ` Chen-Yu Tsai
  2021-07-22  8:56             ` Trevor Wu
  0 siblings, 1 reply; 18+ messages in thread
From: Chen-Yu Tsai @ 2021-07-19 10:05 UTC (permalink / raw)
  To: Trevor Wu
  Cc: Chun-Jie Chen, broonie, tiwai, Rob Herring, Matthias Brugger,
	alsa-devel, linux-mediatek, linux-arm-kernel, LKML, devicetree,
	bicycle.tsai, Jiaxin Yu, Jimmy Cheng-Yi Chiang, Li-Yu Yu

Hi,

On Thu, Jul 15, 2021 at 7:05 PM Trevor Wu <trevor.wu@mediatek.com> wrote:
>
> On Tue, 2021-07-13 at 14:00 +0800, Chen-Yu Tsai wrote:
> > On Mon, Jul 12, 2021 at 11:10 PM Trevor Wu <trevor.wu@mediatek.com>
> > wrote:
> > >
> > > On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
> > > >  are all internal Hi,
> > > >
> > > > On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <trevor.wu@mediatek.com
> > > > >
> > > > wrote:
> > > > >
> > > > > This patch adds mt8195 platform and affiliated driver.
> > > > >
> > > > > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > > > > ---
> > > > >  sound/soc/mediatek/Kconfig                     |    9 +
> > > > >  sound/soc/mediatek/Makefile                   |    1 +
> > > > >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
> > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> > > > >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> > > > >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > > > > +++++++++++++++++
> > > > >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > > > > ++++++++++++++
> > > > >  8 files changed, 7378 insertions(+)
> > > > >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-clk.h
> > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > common.h
> > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
> > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h
> > > > >
> > > > > diff --git a/sound/soc/mediatek/Kconfig
> > > > > b/sound/soc/mediatek/Kconfig
> > > > > index 74dae4332d17..3389f382be06 100644
> > > > > --- a/sound/soc/mediatek/Kconfig
> > > > > +++ b/sound/soc/mediatek/Kconfig
> > > > > @@ -184,3 +184,12 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682
> > > > >           with the MT6359 RT1015 RT5682 audio codec.
> > > > >           Select Y if you have such device.
> > > > >           If unsure select "N".
> > > > > +
> > > > > +config SND_SOC_MT8195
> > > > > +       tristate "ASoC support for Mediatek MT8195 chip"
> > > > > +       select SND_SOC_MEDIATEK
> > > > > +       help
> > > > > +         This adds ASoC platform driver support for Mediatek
> > > > > MT8195 chip
> > > > > +         that can be used with other codecs.
> > > > > +         Select Y if you have such device.
> > > > > +         If unsure select "N".
> > > > > diff --git a/sound/soc/mediatek/Makefile
> > > > > b/sound/soc/mediatek/Makefile
> > > > > index f6cb6b8508e3..34778ca12106 100644
> > > > > --- a/sound/soc/mediatek/Makefile
> > > > > +++ b/sound/soc/mediatek/Makefile
> > > > > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> > > > >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> > > > >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> > > > >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > > > > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > > > > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > > > > b/sound/soc/mediatek/mt8195/Makefile
> > > > > new file mode 100644
> > > > > index 000000000000..b2c9fd88f39e
> > > > > --- /dev/null
> > > > > +++ b/sound/soc/mediatek/mt8195/Makefile
> > > > > @@ -0,0 +1,11 @@
> > > > > +# SPDX-License-Identifier: GPL-2.0
> > > > > +
> > > > > +# platform driver
> > > > > +snd-soc-mt8195-afe-objs := \
> > > > > +       mt8195-afe-clk.o \
> > > > > +       mt8195-afe-pcm.o \
> > > > > +       mt8195-dai-adda.o \
> > > > > +       mt8195-dai-etdm.o \
> > > > > +       mt8195-dai-pcm.o
> > > > > +
> > > > > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > > > > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > new file mode 100644
> > > > > index 000000000000..57aa799b4f41
> > > > > --- /dev/null
> > > > > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > @@ -0,0 +1,899 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > +/*
> > > > > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > > > > + *
> > > > > + * Copyright (c) 2021 MediaTek Inc.
> > > > > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > > > > + *         Trevor Wu <trevor.wu@mediatek.com>
> > > > > + */
> > > > > +
> > > > > +#include <linux/clk.h>
> > > > > +
> > > > > +#include "mt8195-afe-common.h"
> > > > > +#include "mt8195-afe-clk.h"
> > > > > +#include "mt8195-reg.h"
> > > > > +
> > > > > +static const char *aud_clks[MT8195_CLK_NUM] = {
> > > >
> > > > Most of these clocks are not described in the device tree
> > > > binding. If
> > > > the driver needs to reference them, they should be described. We
> > > > should
> > > > not be hard-coding clock names across different drivers.
> > > >
> > >
> > > Sorry, I didn't know I have to list all clocks in the dt-binding.
> > > Originally, I thought these clocks will be described in the clock
> > > binding, so I didn't add them to the binding of afe driver.
> > > I will add these clocks to mt8195-afe-pcm.yaml.
> >
> > If the device consumes clocks, then the clocks that get consumed
> > should
> > be listed in the device's bindings. This is not related to the clock
> > bindings, which is a clock provider.
> >
> Got it. Thanks.
>
> > > > The more important question is, why does the driver need to
> > > > reference
> > > > all of them? Maybe we should take a step back and draw out a
> > > > clock
> > > > tree
> > > > diagram for the hardware?
> > > >
> > >
> > > The clock structure is PLL -> MUX -> GATE.
> > > xtal, pll and divider are the possible clock inputs for MUX.
> > > Because we select the clock input of audio module based on the use
> > > case, we use clk_get to retrive all clocks which are possible to be
> > > used.
> >
> > So I see a couple the driver is doing reparenting:
> >
> >   a. Reparent audio_h to standard oscillator when ADDA is not used,
> >      presumably to let the APLL be turned off
> >
> > Why not just turn off audio_h? It looks like audio_h feeds a couple
> > clock
> > gates in the audio subsystem. Just a guess, but is this the AHB bus
> > clock?
> > Why not just have it parented to "univpll_d7" all the time then?
> >
>
> Sorry, I am not sure if it is the AHB bus clock.
> I only know how audio module uses the clock.
> audio_h feeds to some clock gate like aud_adc_hires, which is used when
> sampling rate is higher than 48kHz, and hardware designer suggests us
> use apll1_ck when AFE requrires the clock.

I see. So the simplified explanation is high clock rate for high res audio.
Would high clock rate work for standard sample rates?
Would using apll1 or univpll all the time work, instead of reparenting?
What's the gain if we do reparenting?

> As I know, DSP also requires audio_h.
> When we disable the clock in AFE driver, the ref count in CCF is not
> becoming zero if DSP still uses it.
> But only AFE requires higher clock rate, so we reparent audio_h to 26M
> when it's not required in adda module.

I see. Wouldn't reparenting the clock while it is in use by another module
cause glitches?

> > Also, reparenting really should be done implicitly with
> > clk_set_rate()
> > with the clock driver supporting reparenting on rate changes.
> >
> >   b. Assignment of PLLs for I2S/PCM MCLK outputs
> >
> > Is there a reason for explicit assignment, other than clock rate
> > conflicts?
> > CCF supports requesting and locking the clock rate. And again,
> > implicit
> > reparenting should be the norm. The clock driver's purpose is to
> > fulfill
> > any and all clock rate requirements from its consumers. The consumer
> > should
> > only need to ask for the clock rate, not a specific parent, unless
> > there
> > are details that are not yet covered by the CCF.
> >
>
> For MCLK output, we should configure divider to get the target rate,
> and it can only divide the clock from current parent source.
> So we should do reparent to divider's parent in case the parent rate is
> not a multiple of target rate.

Right. That is expected. What I'm saying is that the CCF provides the
framework for automatically reparenting based on the requested clock
rate. This is done in the clock driver's .determine_rate op.

When properly implemented, and also restricting or locking the clock rates
of the PLLs, then you can simply request a clock rate on the leaf clock,
in this case one of the MCLKs, and the CCF and clock driver would handle
everything else. The consumer should not be reparenting clocks manually
unless for a very good reason which cannot be satisfied by the CCF.

> > A related question: the chip has five APLLs. How many MCLK
> > combinations
> > does the application need to support? I assume this includes the
> > standard
> > 24.576 MHz and 22.5792 MHz clock rates.
> >
>
> APLL1 and APLL2 are used in most AFE modules, so their rate should be
> fixed.
> APLL1 is fixed to 196608000Hz.
> APLL2 is fixed to 180633600Hz.
> APLL is inputed to the divider(8bit), and MCLK is the output of
> divider.
> Other APLLs are reserved for some special usage which can't be
> supported by APLL1 & APLL2.
> But APLL3~APLL5 aren't used in the series, so I will remove them in v3.
>
> > > Some of them are not used in this series, because some modules are
> > > still developing. Should I only keep the clocks that have been used
> > > in
> > > the series?
> >
> > Yes please. Only add the ones that are used. Things that aren't used
> > don't get tested and verified, and end up as dead code. If there are
> > plans to extend them in the future, and you can leave comments
> > stating
> > that intent, and also mention it in the cover letter.
> >
> OK, I will remove the unused clock in v3.
>
> > > > > +       /* xtal */
> > > > > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > > > > +       /* pll */
> > > > > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > > > > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > > > > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > > > > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > > > > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > > > > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] = "hdmirx_apll",
> > > > > +       /* divider */
> > > > > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > > > > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > > > > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > > > > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > > > > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > > > > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > > > > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > > > > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > > > > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > > > > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > > > > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > > > > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > > > > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > > > > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > > > > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > > > > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > > > > +       [MT8195_CLK_TOP_HDMIRX_APLL] = "hdmirx_apll_ck",
> > > > > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] = "mainpll_d4_d4",
> > > > > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] = "mainpll_d5_d2",
> > > > > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",
> > > > > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > > > > +       /* mux */
> > > > > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > > > > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > > > > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > > > > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > > > > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > > > > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > > > > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > > > > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > > > > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > > > > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > > > > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > > > > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > > > > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > > > > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
> > > > > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > > > > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > > > > "audio_local_bus_sel",
> > > > > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > > > > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > > > > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > > > > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > > > > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > > > > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > > > > +       /* clock gate */
> > > > > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] = "mphone_slave_b",
> > > > > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > > > > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > > > > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] =
> > > > > "infra_ao_audio_26m_b",
> > > > > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] = "scp_adsp_audiodsp",
> > > >
> > > >
> > > > > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > > > > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > > > > "aud_spdifin_tuner_apll",
> > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > > > > "aud_spdifin_tuner_dbg",
> > > > > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > > > > +       [MT8195_CLK_AUD_APLL1_TUNER] = "aud_apll1_tuner",
> > > > > +       [MT8195_CLK_AUD_APLL2_TUNER] = "aud_apll2_tuner",
> > > > > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > > > > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > > > > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > > > > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > > > > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > > > > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > > > > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > > > > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > > > > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > > > > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > > > > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > > > > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > > > > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > > > > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] =
> > > > > "aud_afe_26m_dmic_tm",
> > > > > +       [MT8195_CLK_AUD_UL_TML_HIRES] = "aud_ul_tml_hires",
> > > > > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > > > > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > > > > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] =
> > > > > "aud_adda6_adc_hires",
> > > > > +       [MT8195_CLK_AUD_LINEIN_TUNER] = "aud_linein_tuner",
> > > > > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > > > > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > > > > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > > > > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > > > > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > > > > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > > > > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > > > > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > > > > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > > > > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > > > > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > > > > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > > > > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > > > > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > > > > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > > > > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > > > > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > > > > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > > > > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > > > > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > > > > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > > > > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > > > > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > > > > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > > > > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > > > > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > > > > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > > > > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > > > > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > > > > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > > > > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > > > > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > > > > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > > > > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > > > > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > > > > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > > > > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > > > > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > > > > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > > > > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > > > > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > > > > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > > > > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> > > >
> > > > The MT8195_CLK_AUD_* clocks are all internal to the audio
> > > > subsystem:
> > > > the bits that control these clock gates are in the same address
> > > > space
> > > > as the audio parts. Would it be possible to model them as
> > > > internal
> > > > ASoC SUPPLY widgets? The external ones could be modeled using
> > > > ASoC
> > > > CLK_SUPPLY widgets, and the dependencies could be modeled with
> > > > ASoC
> > > > routes. The ASoC core could then handle power sequencing, which
> > > > the
> > > > driver currently does manually.
> > > >
> > > > IMO this is better than having two drivers handling two aspects
> > > > of
> > > > the same piece of hardware, while the two aspects are
> > > > intertwined.
> > > >
> > >
> > > Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such clocks.
> > > But those clocks are managed by CCF in the preceding SOCs like
> > > mt2701,
> > > mt6779 and mt8183. Additionally, in some audio modules, clocks
> > > should
> >
> > This being a new driver, we have some more freedom to improve the
> > design.
> >
> > > be enabled before configuring parameters(hw_params). As far as I
> > > know,
> > > if we use CLK_SUPPLY or SUPPLY to model clocks, the power sequence
> > > is
> > > controlled by DAPM. It seems to be impossible to fulfill all use
> > > cases.
> > > That's why we just keep the manual control sequence and CCF seems
> > > to be
> > > the best choice to model such clock gatess.
> >
> > I see. So yes, using CCF does give you reference counting, dependency
> > tracking and other advantages. And using DAPM supplies means you
> > can't
> > enable the clock gates outside of DAPM without both pieces of code
> > fighting for control.
> >
> > Can we at least move the audio clock gates into the audio driver
> > though?
> > The arbitrary separation into two devices and drivers is fishy. And
> > with
> > the move the external references to the audio clock gates can be
> > removed.
> >
> Because DAPM SUPPLY can't fit our control scenario.
> Did you suggest us implement the simple logic control(including ref
> count, clock dependency) for clock gate(MT8195_CLK_AUD_*) in afe driver
> instead of using CCF?

I meant simply moving the CCF-based clk driver code (clk-mt8516-aud.c)
from `drivers/clk` and incorporating it into the audio driver, likely
in `mt8195-afe-clk.c` or maybe as a separate file. So the audio driver
would be a clock provider, and a clock consumer. It will directly use
the clocks it provides, internally, and you could remove all those
clock references from the device tree.

The goal is to have one hardware representation (device node) only, so
that it matches the hardware, which is one single unified block.

After the driver is completed, we can look for opportunities to improve
it, if resources are available.

> > And regarding the clock requirements for different modules, could we
> > have
> > that information put in comments somewhere, so if someone were to
> > revisit
> > it later, they would have the information needed to understand and
> > possibly
> > improve it? Because right now there's just a bunch of clocks enabled
> > and
> > disabled and nothing to explain why that's needed.
> >
>
> For example,
> MT8195_CLK_AUD_ADC(clock gate) is one of the clock feeding to ADDA
> module.
> Did you want me show the clock gate list feeding to ADDA?
> On the other hand, I didn't know how to show the information properly
> in comments. Could you kindly share me an example for reference?


For example, in `mt8195_afe_enable_reg_rw_clk()` in mt8195-afe-clk.c:

        unsigned int clk_array[] = {
                MT8195_CLK_SCP_ADSP_AUDIODSP,
                MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
                MT8195_CLK_TOP_CFG_26M_AUD,
                MT8195_CLK_INFRA_AO_AUDIO,
                MT8195_CLK_INFRA_AO_AUDIO_26M_B,
                MT8195_CLK_TOP_AUD_INTBUS_SEL,
                MT8195_CLK_TOP_A1SYS_HP_SEL,
                MT8195_CLK_AUD_A1SYS_HP,
                MT8195_CLK_AUD_A1SYS,
                MT8195_CLK_TOP_AUDIO_H_SEL,
        };

You could add a comment after each line stating why that clock needs to
be enabled. A simple note like "bus access clock" or "internal logic clock"
would suffice.

The above list also has some redundancies that could be eliminated.
MT8195_CLK_TOP_A1SYS_HP_SEL is parent to both MT8195_CLK_AUD_A1SYS_HP and
MT8195_CLK_AUD_A1SYS. When clocks are enabled, their parents are also
enabled by CCF, so there's no need to enable them explicitly, unless
that clock also directly feeds the clock consumer.


Another thing I wanted to bring up: is any of the code after

    struct mt8195_afe_tuner_cfg {

used? It looks like it is used to configure the five extra PLLs in the audio
subsystem, but the exposed (non-static) functions don't seem to be called
anywhere. Are they for modules not yet supported?


Regards
ChenYu

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-19 10:05           ` Chen-Yu Tsai
@ 2021-07-22  8:56             ` Trevor Wu
  2021-07-23  6:27               ` Chen-Yu Tsai
  0 siblings, 1 reply; 18+ messages in thread
From: Trevor Wu @ 2021-07-22  8:56 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Chun-Jie Chen, broonie, tiwai, Rob Herring, Matthias Brugger,
	alsa-devel, linux-mediatek, linux-arm-kernel, LKML, devicetree,
	bicycle.tsai, Jiaxin Yu, Jimmy Cheng-Yi Chiang, Li-Yu Yu

On Mon, 2021-07-19 at 18:05 +0800, Chen-Yu Tsai wrote:
> Hi,
> 
> On Thu, Jul 15, 2021 at 7:05 PM Trevor Wu <trevor.wu@mediatek.com>
> wrote:
> > 
> > On Tue, 2021-07-13 at 14:00 +0800, Chen-Yu Tsai wrote:
> > > On Mon, Jul 12, 2021 at 11:10 PM Trevor Wu <
> > > trevor.wu@mediatek.com>
> > > wrote:
> > > > 
> > > > On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
> > > > >  are all internal Hi,
> > > > > 
> > > > > On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <
> > > > > trevor.wu@mediatek.com
> > > > > > 
> > > > > 
> > > > > wrote:
> > > > > > 
> > > > > > This patch adds mt8195 platform and affiliated driver.
> > > > > > 
> > > > > > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > > > > > ---
> > > > > >  sound/soc/mediatek/Kconfig                     |    9 +
> > > > > >  sound/soc/mediatek/Makefile                   |    1 +
> > > > > >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
> > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > > > > > +++++++++++++++++
> > > > > >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > > > > > ++++++++++++++
> > > > > >  8 files changed, 7378 insertions(+)
> > > > > >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > clk.c
> > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > clk.h
> > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > common.h
> > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > pcm.c
> > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h
> > > > > > 
> > > > > > diff --git a/sound/soc/mediatek/Kconfig
> > > > > > b/sound/soc/mediatek/Kconfig
> > > > > > index 74dae4332d17..3389f382be06 100644
> > > > > > --- a/sound/soc/mediatek/Kconfig
> > > > > > +++ b/sound/soc/mediatek/Kconfig
> > > > > > @@ -184,3 +184,12 @@ config
> > > > > > SND_SOC_MT8192_MT6359_RT1015_RT5682
> > > > > >           with the MT6359 RT1015 RT5682 audio codec.
> > > > > >           Select Y if you have such device.
> > > > > >           If unsure select "N".
> > > > > > +
> > > > > > +config SND_SOC_MT8195
> > > > > > +       tristate "ASoC support for Mediatek MT8195 chip"
> > > > > > +       select SND_SOC_MEDIATEK
> > > > > > +       help
> > > > > > +         This adds ASoC platform driver support for
> > > > > > Mediatek
> > > > > > MT8195 chip
> > > > > > +         that can be used with other codecs.
> > > > > > +         Select Y if you have such device.
> > > > > > +         If unsure select "N".
> > > > > > diff --git a/sound/soc/mediatek/Makefile
> > > > > > b/sound/soc/mediatek/Makefile
> > > > > > index f6cb6b8508e3..34778ca12106 100644
> > > > > > --- a/sound/soc/mediatek/Makefile
> > > > > > +++ b/sound/soc/mediatek/Makefile
> > > > > > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> > > > > >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> > > > > >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> > > > > >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > > > > > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > > > > > b/sound/soc/mediatek/mt8195/Makefile
> > > > > > new file mode 100644
> > > > > > index 000000000000..b2c9fd88f39e
> > > > > > --- /dev/null
> > > > > > +++ b/sound/soc/mediatek/mt8195/Makefile
> > > > > > @@ -0,0 +1,11 @@
> > > > > > +# SPDX-License-Identifier: GPL-2.0
> > > > > > +
> > > > > > +# platform driver
> > > > > > +snd-soc-mt8195-afe-objs := \
> > > > > > +       mt8195-afe-clk.o \
> > > > > > +       mt8195-afe-pcm.o \
> > > > > > +       mt8195-dai-adda.o \
> > > > > > +       mt8195-dai-etdm.o \
> > > > > > +       mt8195-dai-pcm.o
> > > > > > +
> > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > > > > > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > new file mode 100644
> > > > > > index 000000000000..57aa799b4f41
> > > > > > --- /dev/null
> > > > > > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > @@ -0,0 +1,899 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > +/*
> > > > > > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > > > > > + *
> > > > > > + * Copyright (c) 2021 MediaTek Inc.
> > > > > > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > > > > > + *         Trevor Wu <trevor.wu@mediatek.com>
> > > > > > + */
> > > > > > +
> > > > > > +#include <linux/clk.h>
> > > > > > +
> > > > > > +#include "mt8195-afe-common.h"
> > > > > > +#include "mt8195-afe-clk.h"
> > > > > > +#include "mt8195-reg.h"
> > > > > > +
> > > > > > +static const char *aud_clks[MT8195_CLK_NUM] = {
> > > > > 
> > > > > Most of these clocks are not described in the device tree
> > > > > binding. If
> > > > > the driver needs to reference them, they should be described.
> > > > > We
> > > > > should
> > > > > not be hard-coding clock names across different drivers.
> > > > > 
> > > > 
> > > > Sorry, I didn't know I have to list all clocks in the dt-
> > > > binding.
> > > > Originally, I thought these clocks will be described in the
> > > > clock
> > > > binding, so I didn't add them to the binding of afe driver.
> > > > I will add these clocks to mt8195-afe-pcm.yaml.
> > > 
> > > If the device consumes clocks, then the clocks that get consumed
> > > should
> > > be listed in the device's bindings. This is not related to the
> > > clock
> > > bindings, which is a clock provider.
> > > 
> > 
> > Got it. Thanks.
> > 
> > > > > The more important question is, why does the driver need to
> > > > > reference
> > > > > all of them? Maybe we should take a step back and draw out a
> > > > > clock
> > > > > tree
> > > > > diagram for the hardware?
> > > > > 
> > > > 
> > > > The clock structure is PLL -> MUX -> GATE.
> > > > xtal, pll and divider are the possible clock inputs for MUX.
> > > > Because we select the clock input of audio module based on the
> > > > use
> > > > case, we use clk_get to retrive all clocks which are possible
> > > > to be
> > > > used.
> > > 
> > > So I see a couple the driver is doing reparenting:
> > > 
> > >   a. Reparent audio_h to standard oscillator when ADDA is not
> > > used,
> > >      presumably to let the APLL be turned off
> > > 
> > > Why not just turn off audio_h? It looks like audio_h feeds a
> > > couple
> > > clock
> > > gates in the audio subsystem. Just a guess, but is this the AHB
> > > bus
> > > clock?
> > > Why not just have it parented to "univpll_d7" all the time then?
> > > 
> > 
> > Sorry, I am not sure if it is the AHB bus clock.
> > I only know how audio module uses the clock.
> > audio_h feeds to some clock gate like aud_adc_hires, which is used
> > when
> > sampling rate is higher than 48kHz, and hardware designer suggests
> > us
> > use apll1_ck when AFE requrires the clock.
> 
> I see. So the simplified explanation is high clock rate for high res
> audio.
> Would high clock rate work for standard sample rates?

As far as I know, HW will switch clock to hires clock automatically
when the required rate is high,(ex: aud_adc and aud_adc_hires) so it
can't be controlled by driver.

> Would using apll1 or univpll all the time work, instead of
> reparenting?
> What's the gain if we do reparenting?
> 

As you said before, the gain is apll can be turned off when the clock
is not requrired by ADDA. That's why we didn't use apll all the time.

> > As I know, DSP also requires audio_h.
> > When we disable the clock in AFE driver, the ref count in CCF is
> > not
> > becoming zero if DSP still uses it.
> > But only AFE requires higher clock rate, so we reparent audio_h to
> > 26M
> > when it's not required in adda module.
> 
> I see. Wouldn't reparenting the clock while it is in use by another
> module
> cause glitches?

I checked with the DSP owner.
audio_h clock is required for DSP bus, but the clock rate is not
important.
The only thing it cares is audio_h should be powered on, so reparenting
is harmless for DSP.

> 
> > > Also, reparenting really should be done implicitly with
> > > clk_set_rate()
> > > with the clock driver supporting reparenting on rate changes.
> > > 
> > >   b. Assignment of PLLs for I2S/PCM MCLK outputs
> > > 
> > > Is there a reason for explicit assignment, other than clock rate
> > > conflicts?
> > > CCF supports requesting and locking the clock rate. And again,
> > > implicit
> > > reparenting should be the norm. The clock driver's purpose is to
> > > fulfill
> > > any and all clock rate requirements from its consumers. The
> > > consumer
> > > should
> > > only need to ask for the clock rate, not a specific parent,
> > > unless
> > > there
> > > are details that are not yet covered by the CCF.
> > > 
> > 
> > For MCLK output, we should configure divider to get the target
> > rate,
> > and it can only divide the clock from current parent source.
> > So we should do reparent to divider's parent in case the parent
> > rate is
> > not a multiple of target rate.
> 
> Right. That is expected. What I'm saying is that the CCF provides the
> framework for automatically reparenting based on the requested clock
> rate. This is done in the clock driver's .determine_rate op.
> 
> When properly implemented, and also restricting or locking the clock
> rates
> of the PLLs, then you can simply request a clock rate on the leaf
> clock,
> in this case one of the MCLKs, and the CCF and clock driver would
> handle
> everything else. The consumer should not be reparenting clocks
> manually
> unless for a very good reason which cannot be satisfied by the CCF.
> 

In some use cases, we really need to reparent clock manually.
For example, spdif in(slave) -> .... -> i2s out(master)

APLL3/APLL4 are reserved for slave input like earc in or spdif in,
which can refer to the external clock source.(APLL3 syncs with earc,
and APLL4 syncs with spdif in.)

When i2s out selects the clock source to APLL4, this makes sure that
spdif in and i2s out works in the same clock source.
If we just use APLL1/APLL2 on i2s out, there is little rate mismatch
between data input and output. Finally, it results in XRUN.

If we only use set_rate, it's possible that it can't switch to the
expected PLL source, because the rate of APLL3/APLL4 should be close to
APLL1/APLL2.

> > 
> > > A related question: the chip has five APLLs. How many MCLK
> > > combinations
> > > does the application need to support? I assume this includes the
> > > standard
> > > 24.576 MHz and 22.5792 MHz clock rates.
> > > 
> > 
> > APLL1 and APLL2 are used in most AFE modules, so their rate should
> > be
> > fixed.
> > APLL1 is fixed to 196608000Hz.
> > APLL2 is fixed to 180633600Hz.
> > APLL is inputed to the divider(8bit), and MCLK is the output of
> > divider.
> > Other APLLs are reserved for some special usage which can't be
> > supported by APLL1 & APLL2.
> > But APLL3~APLL5 aren't used in the series, so I will remove them in
> > v3.
> > 
> > > > Some of them are not used in this series, because some modules
> > > > are
> > > > still developing. Should I only keep the clocks that have been
> > > > used
> > > > in
> > > > the series?
> > > 
> > > Yes please. Only add the ones that are used. Things that aren't
> > > used
> > > don't get tested and verified, and end up as dead code. If there
> > > are
> > > plans to extend them in the future, and you can leave comments
> > > stating
> > > that intent, and also mention it in the cover letter.
> > > 
> > 
> > OK, I will remove the unused clock in v3.
> > 
> > > > > > +       /* xtal */
> > > > > > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > > > > > +       /* pll */
> > > > > > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > > > > > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > > > > > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > > > > > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > > > > > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > > > > > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] = "hdmirx_apll",
> > > > > > +       /* divider */
> > > > > > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > > > > > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > > > > > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > > > > > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > > > > > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > > > > > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > > > > > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > > > > > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > > > > > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > > > > > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > > > > > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > > > > > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > > > > > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > > > > > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > > > > > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > > > > > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > > > > > +       [MT8195_CLK_TOP_HDMIRX_APLL] = "hdmirx_apll_ck",
> > > > > > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] = "mainpll_d4_d4",
> > > > > > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] = "mainpll_d5_d2",
> > > > > > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",
> > > > > > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > > > > > +       /* mux */
> > > > > > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > > > > > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > > > > > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > > > > > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > > > > > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > > > > > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > > > > > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > > > > > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > > > > > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > > > > > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > > > > > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > > > > > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > > > > > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > > > > > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
> > > > > > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > > > > > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > > > > > "audio_local_bus_sel",
> > > > > > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > > > > > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > > > > > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > > > > > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > > > > > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > > > > > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > > > > > +       /* clock gate */
> > > > > > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] = "mphone_slave_b",
> > > > > > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] =
> > > > > > "infra_ao_audio_26m_b",
> > > > > > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] =
> > > > > > "scp_adsp_audiodsp",
> > > > > 
> > > > > 
> > > > > > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > > > > > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > > > > > "aud_spdifin_tuner_apll",
> > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > > > > > "aud_spdifin_tuner_dbg",
> > > > > > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > > > > > +       [MT8195_CLK_AUD_APLL1_TUNER] = "aud_apll1_tuner",
> > > > > > +       [MT8195_CLK_AUD_APLL2_TUNER] = "aud_apll2_tuner",
> > > > > > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > > > > > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > > > > > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > > > > > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > > > > > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > > > > > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > > > > > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > > > > > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > > > > > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > > > > > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > > > > > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > > > > > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > > > > > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > > > > > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] =
> > > > > > "aud_afe_26m_dmic_tm",
> > > > > > +       [MT8195_CLK_AUD_UL_TML_HIRES] = "aud_ul_tml_hires",
> > > > > > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] =
> > > > > > "aud_adda6_adc_hires",
> > > > > > +       [MT8195_CLK_AUD_LINEIN_TUNER] = "aud_linein_tuner",
> > > > > > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > > > > > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > > > > > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > > > > > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > > > > > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > > > > > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > > > > > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > > > > > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > > > > > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > > > > > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > > > > > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > > > > > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > > > > > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > > > > > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > > > > > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > > > > > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > > > > > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > > > > > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > > > > > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > > > > > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > > > > > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > > > > > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > > > > > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > > > > > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > > > > > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > > > > > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > > > > > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > > > > > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > > > > > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > > > > > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > > > > > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > > > > > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > > > > > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > > > > > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > > > > > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > > > > > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> > > > > 
> > > > > The MT8195_CLK_AUD_* clocks are all internal to the audio
> > > > > subsystem:
> > > > > the bits that control these clock gates are in the same
> > > > > address
> > > > > space
> > > > > as the audio parts. Would it be possible to model them as
> > > > > internal
> > > > > ASoC SUPPLY widgets? The external ones could be modeled using
> > > > > ASoC
> > > > > CLK_SUPPLY widgets, and the dependencies could be modeled
> > > > > with
> > > > > ASoC
> > > > > routes. The ASoC core could then handle power sequencing,
> > > > > which
> > > > > the
> > > > > driver currently does manually.
> > > > > 
> > > > > IMO this is better than having two drivers handling two
> > > > > aspects
> > > > > of
> > > > > the same piece of hardware, while the two aspects are
> > > > > intertwined.
> > > > > 
> > > > 
> > > > Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such
> > > > clocks.
> > > > But those clocks are managed by CCF in the preceding SOCs like
> > > > mt2701,
> > > > mt6779 and mt8183. Additionally, in some audio modules, clocks
> > > > should
> > > 
> > > This being a new driver, we have some more freedom to improve the
> > > design.
> > > 
> > > > be enabled before configuring parameters(hw_params). As far as
> > > > I
> > > > know,
> > > > if we use CLK_SUPPLY or SUPPLY to model clocks, the power
> > > > sequence
> > > > is
> > > > controlled by DAPM. It seems to be impossible to fulfill all
> > > > use
> > > > cases.
> > > > That's why we just keep the manual control sequence and CCF
> > > > seems
> > > > to be
> > > > the best choice to model such clock gatess.
> > > 
> > > I see. So yes, using CCF does give you reference counting,
> > > dependency
> > > tracking and other advantages. And using DAPM supplies means you
> > > can't
> > > enable the clock gates outside of DAPM without both pieces of
> > > code
> > > fighting for control.
> > > 
> > > Can we at least move the audio clock gates into the audio driver
> > > though?
> > > The arbitrary separation into two devices and drivers is fishy.
> > > And
> > > with
> > > the move the external references to the audio clock gates can be
> > > removed.
> > > 
> > 
> > Because DAPM SUPPLY can't fit our control scenario.
> > Did you suggest us implement the simple logic control(including ref
> > count, clock dependency) for clock gate(MT8195_CLK_AUD_*) in afe
> > driver
> > instead of using CCF?
> 
> I meant simply moving the CCF-based clk driver code (clk-mt8516-
> aud.c)
> from `drivers/clk` and incorporating it into the audio driver, likely
> in `mt8195-afe-clk.c` or maybe as a separate file. So the audio
> driver
> would be a clock provider, and a clock consumer. It will directly use
> the clocks it provides, internally, and you could remove all those
> clock references from the device tree.
> 
> The goal is to have one hardware representation (device node) only,
> so
> that it matches the hardware, which is one single unified block.
> 
> After the driver is completed, we can look for opportunities to
> improve
> it, if resources are available.

Thanks for your detailed information.
I will try to move the CCF-based clk driver code to AFE driver.
If there are no other internal concerns and blocking problems, I will
include the changes in v3.

> > > And regarding the clock requirements for different modules, could
> > > we
> > > have
> > > that information put in comments somewhere, so if someone were to
> > > revisit
> > > it later, they would have the information needed to understand
> > > and
> > > possibly
> > > improve it? Because right now there's just a bunch of clocks
> > > enabled
> > > and
> > > disabled and nothing to explain why that's needed.
> > > 
> > 
> > For example,
> > MT8195_CLK_AUD_ADC(clock gate) is one of the clock feeding to ADDA
> > module.
> > Did you want me show the clock gate list feeding to ADDA?
> > On the other hand, I didn't know how to show the information
> > properly
> > in comments. Could you kindly share me an example for reference?
> 
> 
> For example, in `mt8195_afe_enable_reg_rw_clk()` in mt8195-afe-clk.c:
> 
>         unsigned int clk_array[] = {
>                 MT8195_CLK_SCP_ADSP_AUDIODSP,
>                 MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
>                 MT8195_CLK_TOP_CFG_26M_AUD,
>                 MT8195_CLK_INFRA_AO_AUDIO,
>                 MT8195_CLK_INFRA_AO_AUDIO_26M_B,
>                 MT8195_CLK_TOP_AUD_INTBUS_SEL,
>                 MT8195_CLK_TOP_A1SYS_HP_SEL,
>                 MT8195_CLK_AUD_A1SYS_HP,
>                 MT8195_CLK_AUD_A1SYS,
>                 MT8195_CLK_TOP_AUDIO_H_SEL,
>         };
> 
> You could add a comment after each line stating why that clock needs
> to
> be enabled. A simple note like "bus access clock" or "internal logic
> clock"
> would suffice.
> 
OK, I will add short notes to such clock lists.

> The above list also has some redundancies that could be eliminated.
> MT8195_CLK_TOP_A1SYS_HP_SEL is parent to both MT8195_CLK_AUD_A1SYS_HP
> and
> MT8195_CLK_AUD_A1SYS. When clocks are enabled, their parents are also
> enabled by CCF, so there's no need to enable them explicitly, unless
> that clock also directly feeds the clock consumer.
> 
OK, I will review all clock usages and remove the unnecessary clocks.

> 
> Another thing I wanted to bring up: is any of the code after
> 
>     struct mt8195_afe_tuner_cfg {
> 
> used? It looks like it is used to configure the five extra PLLs in
> the audio
> subsystem, but the exposed (non-static) functions don't seem to be
> called
> anywhere. Are they for modules not yet supported?
> 

Yes, tuners are not supported now.
I will remove the code and add them back when tuners are required in
the future.


Thanks,
Trevor

> 
> Regards
> ChenYu
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-22  8:56             ` Trevor Wu
@ 2021-07-23  6:27               ` Chen-Yu Tsai
  2021-07-26 14:31                 ` Trevor Wu
  0 siblings, 1 reply; 18+ messages in thread
From: Chen-Yu Tsai @ 2021-07-23  6:27 UTC (permalink / raw)
  To: Trevor Wu
  Cc: Chun-Jie Chen, broonie, tiwai, Rob Herring, Matthias Brugger,
	alsa-devel, linux-mediatek, linux-arm-kernel, LKML, devicetree,
	bicycle.tsai, Jiaxin Yu, Jimmy Cheng-Yi Chiang, Li-Yu Yu

On Thu, Jul 22, 2021 at 4:56 PM Trevor Wu <trevor.wu@mediatek.com> wrote:
>
> On Mon, 2021-07-19 at 18:05 +0800, Chen-Yu Tsai wrote:
> > Hi,
> >
> > On Thu, Jul 15, 2021 at 7:05 PM Trevor Wu <trevor.wu@mediatek.com>
> > wrote:
> > >
> > > On Tue, 2021-07-13 at 14:00 +0800, Chen-Yu Tsai wrote:
> > > > On Mon, Jul 12, 2021 at 11:10 PM Trevor Wu <
> > > > trevor.wu@mediatek.com>
> > > > wrote:
> > > > >
> > > > > On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
> > > > > >  are all internal Hi,
> > > > > >
> > > > > > On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <
> > > > > > trevor.wu@mediatek.com
> > > > > > >
> > > > > >
> > > > > > wrote:
> > > > > > >
> > > > > > > This patch adds mt8195 platform and affiliated driver.
> > > > > > >
> > > > > > > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > > > > > > ---
> > > > > > >  sound/soc/mediatek/Kconfig                     |    9 +
> > > > > > >  sound/soc/mediatek/Makefile                   |    1 +
> > > > > > >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899 +++++
> > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > > > > > > +++++++++++++++++
> > > > > > >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > > > > > > ++++++++++++++
> > > > > > >  8 files changed, 7378 insertions(+)
> > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > > clk.c
> > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > > clk.h
> > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > > common.h
> > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-afe-
> > > > > > > pcm.c
> > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-reg.h
> > > > > > >
> > > > > > > diff --git a/sound/soc/mediatek/Kconfig
> > > > > > > b/sound/soc/mediatek/Kconfig
> > > > > > > index 74dae4332d17..3389f382be06 100644
> > > > > > > --- a/sound/soc/mediatek/Kconfig
> > > > > > > +++ b/sound/soc/mediatek/Kconfig
> > > > > > > @@ -184,3 +184,12 @@ config
> > > > > > > SND_SOC_MT8192_MT6359_RT1015_RT5682
> > > > > > >           with the MT6359 RT1015 RT5682 audio codec.
> > > > > > >           Select Y if you have such device.
> > > > > > >           If unsure select "N".
> > > > > > > +
> > > > > > > +config SND_SOC_MT8195
> > > > > > > +       tristate "ASoC support for Mediatek MT8195 chip"
> > > > > > > +       select SND_SOC_MEDIATEK
> > > > > > > +       help
> > > > > > > +         This adds ASoC platform driver support for
> > > > > > > Mediatek
> > > > > > > MT8195 chip
> > > > > > > +         that can be used with other codecs.
> > > > > > > +         Select Y if you have such device.
> > > > > > > +         If unsure select "N".
> > > > > > > diff --git a/sound/soc/mediatek/Makefile
> > > > > > > b/sound/soc/mediatek/Makefile
> > > > > > > index f6cb6b8508e3..34778ca12106 100644
> > > > > > > --- a/sound/soc/mediatek/Makefile
> > > > > > > +++ b/sound/soc/mediatek/Makefile
> > > > > > > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> > > > > > >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> > > > > > >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> > > > > > >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > > > > > > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > > > > > > b/sound/soc/mediatek/mt8195/Makefile
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..b2c9fd88f39e
> > > > > > > --- /dev/null
> > > > > > > +++ b/sound/soc/mediatek/mt8195/Makefile
> > > > > > > @@ -0,0 +1,11 @@
> > > > > > > +# SPDX-License-Identifier: GPL-2.0
> > > > > > > +
> > > > > > > +# platform driver
> > > > > > > +snd-soc-mt8195-afe-objs := \
> > > > > > > +       mt8195-afe-clk.o \
> > > > > > > +       mt8195-afe-pcm.o \
> > > > > > > +       mt8195-dai-adda.o \
> > > > > > > +       mt8195-dai-etdm.o \
> > > > > > > +       mt8195-dai-pcm.o
> > > > > > > +
> > > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > > > > > > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > new file mode 100644
> > > > > > > index 000000000000..57aa799b4f41
> > > > > > > --- /dev/null
> > > > > > > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > @@ -0,0 +1,899 @@
> > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > +/*
> > > > > > > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > > > > > > + *
> > > > > > > + * Copyright (c) 2021 MediaTek Inc.
> > > > > > > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > > > > > > + *         Trevor Wu <trevor.wu@mediatek.com>
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <linux/clk.h>
> > > > > > > +
> > > > > > > +#include "mt8195-afe-common.h"
> > > > > > > +#include "mt8195-afe-clk.h"
> > > > > > > +#include "mt8195-reg.h"
> > > > > > > +
> > > > > > > +static const char *aud_clks[MT8195_CLK_NUM] = {
> > > > > >
> > > > > > Most of these clocks are not described in the device tree
> > > > > > binding. If
> > > > > > the driver needs to reference them, they should be described.
> > > > > > We
> > > > > > should
> > > > > > not be hard-coding clock names across different drivers.
> > > > > >
> > > > >
> > > > > Sorry, I didn't know I have to list all clocks in the dt-
> > > > > binding.
> > > > > Originally, I thought these clocks will be described in the
> > > > > clock
> > > > > binding, so I didn't add them to the binding of afe driver.
> > > > > I will add these clocks to mt8195-afe-pcm.yaml.
> > > >
> > > > If the device consumes clocks, then the clocks that get consumed
> > > > should
> > > > be listed in the device's bindings. This is not related to the
> > > > clock
> > > > bindings, which is a clock provider.
> > > >
> > >
> > > Got it. Thanks.
> > >
> > > > > > The more important question is, why does the driver need to
> > > > > > reference
> > > > > > all of them? Maybe we should take a step back and draw out a
> > > > > > clock
> > > > > > tree
> > > > > > diagram for the hardware?
> > > > > >
> > > > >
> > > > > The clock structure is PLL -> MUX -> GATE.
> > > > > xtal, pll and divider are the possible clock inputs for MUX.
> > > > > Because we select the clock input of audio module based on the
> > > > > use
> > > > > case, we use clk_get to retrive all clocks which are possible
> > > > > to be
> > > > > used.
> > > >
> > > > So I see a couple the driver is doing reparenting:
> > > >
> > > >   a. Reparent audio_h to standard oscillator when ADDA is not
> > > > used,
> > > >      presumably to let the APLL be turned off
> > > >
> > > > Why not just turn off audio_h? It looks like audio_h feeds a
> > > > couple
> > > > clock
> > > > gates in the audio subsystem. Just a guess, but is this the AHB
> > > > bus
> > > > clock?
> > > > Why not just have it parented to "univpll_d7" all the time then?
> > > >
> > >
> > > Sorry, I am not sure if it is the AHB bus clock.
> > > I only know how audio module uses the clock.
> > > audio_h feeds to some clock gate like aud_adc_hires, which is used
> > > when
> > > sampling rate is higher than 48kHz, and hardware designer suggests
> > > us
> > > use apll1_ck when AFE requrires the clock.
> >
> > I see. So the simplified explanation is high clock rate for high res
> > audio.
> > Would high clock rate work for standard sample rates?
>
> As far as I know, HW will switch clock to hires clock automatically
> when the required rate is high,(ex: aud_adc and aud_adc_hires) so it
> can't be controlled by driver.

I see. That might not be so friendly to the Linux clk driver.

> > Would using apll1 or univpll all the time work, instead of
> > reparenting?
> > What's the gain if we do reparenting?
> >
>
> As you said before, the gain is apll can be turned off when the clock
> is not requrired by ADDA. That's why we didn't use apll all the time.

Right, and what's the gain from turning it off? Lower power consumption?

> > > As I know, DSP also requires audio_h.
> > > When we disable the clock in AFE driver, the ref count in CCF is
> > > not
> > > becoming zero if DSP still uses it.
> > > But only AFE requires higher clock rate, so we reparent audio_h to
> > > 26M
> > > when it's not required in adda module.
> >
> > I see. Wouldn't reparenting the clock while it is in use by another
> > module
> > cause glitches?
>
> I checked with the DSP owner.
> audio_h clock is required for DSP bus, but the clock rate is not
> important.
> The only thing it cares is audio_h should be powered on, so reparenting
> is harmless for DSP.

OK.

> > > > Also, reparenting really should be done implicitly with
> > > > clk_set_rate()
> > > > with the clock driver supporting reparenting on rate changes.
> > > >
> > > >   b. Assignment of PLLs for I2S/PCM MCLK outputs
> > > >
> > > > Is there a reason for explicit assignment, other than clock rate
> > > > conflicts?
> > > > CCF supports requesting and locking the clock rate. And again,
> > > > implicit
> > > > reparenting should be the norm. The clock driver's purpose is to
> > > > fulfill
> > > > any and all clock rate requirements from its consumers. The
> > > > consumer
> > > > should
> > > > only need to ask for the clock rate, not a specific parent,
> > > > unless
> > > > there
> > > > are details that are not yet covered by the CCF.
> > > >
> > >
> > > For MCLK output, we should configure divider to get the target
> > > rate,
> > > and it can only divide the clock from current parent source.
> > > So we should do reparent to divider's parent in case the parent
> > > rate is
> > > not a multiple of target rate.
> >
> > Right. That is expected. What I'm saying is that the CCF provides the
> > framework for automatically reparenting based on the requested clock
> > rate. This is done in the clock driver's .determine_rate op.
> >
> > When properly implemented, and also restricting or locking the clock
> > rates
> > of the PLLs, then you can simply request a clock rate on the leaf
> > clock,
> > in this case one of the MCLKs, and the CCF and clock driver would
> > handle
> > everything else. The consumer should not be reparenting clocks
> > manually
> > unless for a very good reason which cannot be satisfied by the CCF.
> >
>
> In some use cases, we really need to reparent clock manually.
> For example, spdif in(slave) -> .... -> i2s out(master)
>
> APLL3/APLL4 are reserved for slave input like earc in or spdif in,
> which can refer to the external clock source.(APLL3 syncs with earc,
> and APLL4 syncs with spdif in.)
>
> When i2s out selects the clock source to APLL4, this makes sure that
> spdif in and i2s out works in the same clock source.
> If we just use APLL1/APLL2 on i2s out, there is little rate mismatch
> between data input and output. Finally, it results in XRUN.

I see, that makes more sense.

> If we only use set_rate, it's possible that it can't switch to the
> expected PLL source, because the rate of APLL3/APLL4 should be close to
> APLL1/APLL2.

Well, in theory the CCF should choose the one with the closest rate.
And if APLL3/APLL4 is already tracking the external clock source, its
clock rate should match.

If it's a static requirement, maybe we could replace the *-mclk-source
DT properties with standard assigned-clocks and assigned-clock-parents?
This would get handled by CCF directly, and then the only thing the
clk driver has to do is make sure it doesn't get reparented again.

Or is there a need to do reparenting at runtime?

> > > > A related question: the chip has five APLLs. How many MCLK
> > > > combinations
> > > > does the application need to support? I assume this includes the
> > > > standard
> > > > 24.576 MHz and 22.5792 MHz clock rates.
> > > >
> > >
> > > APLL1 and APLL2 are used in most AFE modules, so their rate should
> > > be
> > > fixed.
> > > APLL1 is fixed to 196608000Hz.
> > > APLL2 is fixed to 180633600Hz.
> > > APLL is inputed to the divider(8bit), and MCLK is the output of
> > > divider.
> > > Other APLLs are reserved for some special usage which can't be
> > > supported by APLL1 & APLL2.
> > > But APLL3~APLL5 aren't used in the series, so I will remove them in
> > > v3.
> > >
> > > > > Some of them are not used in this series, because some modules
> > > > > are
> > > > > still developing. Should I only keep the clocks that have been
> > > > > used
> > > > > in
> > > > > the series?
> > > >
> > > > Yes please. Only add the ones that are used. Things that aren't
> > > > used
> > > > don't get tested and verified, and end up as dead code. If there
> > > > are
> > > > plans to extend them in the future, and you can leave comments
> > > > stating
> > > > that intent, and also mention it in the cover letter.
> > > >
> > >
> > > OK, I will remove the unused clock in v3.
> > >
> > > > > > > +       /* xtal */
> > > > > > > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > > > > > > +       /* pll */
> > > > > > > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > > > > > > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > > > > > > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > > > > > > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > > > > > > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > > > > > > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] = "hdmirx_apll",
> > > > > > > +       /* divider */
> > > > > > > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > > > > > > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > > > > > > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > > > > > > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > > > > > > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > > > > > > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > > > > > > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > > > > > > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > > > > > > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > > > > > > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > > > > > > +       [MT8195_CLK_TOP_HDMIRX_APLL] = "hdmirx_apll_ck",
> > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] = "mainpll_d4_d4",
> > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] = "mainpll_d5_d2",
> > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] = "mainpll_d7_d2",
> > > > > > > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > > > > > > +       /* mux */
> > > > > > > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > > > > > > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > > > > > > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > > > > > > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > > > > > > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > > > > > > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > > > > > > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > > > > > > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > > > > > > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > > > > > > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > > > > > > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > > > > > > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > > > > > > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > > > > > > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] = "aud_intbus_sel",
> > > > > > > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > > > > > > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > > > > > > "audio_local_bus_sel",
> > > > > > > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > > > > > > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > > > > > > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > > > > > > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > > > > > > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > > > > > > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > > > > > > +       /* clock gate */
> > > > > > > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] = "mphone_slave_b",
> > > > > > > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] =
> > > > > > > "infra_ao_audio_26m_b",
> > > > > > > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] =
> > > > > > > "scp_adsp_audiodsp",
> > > > > >
> > > > > >
> > > > > > > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > > > > > > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > > > > > > "aud_spdifin_tuner_apll",
> > > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > > > > > > "aud_spdifin_tuner_dbg",
> > > > > > > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > > > > > > +       [MT8195_CLK_AUD_APLL1_TUNER] = "aud_apll1_tuner",
> > > > > > > +       [MT8195_CLK_AUD_APLL2_TUNER] = "aud_apll2_tuner",
> > > > > > > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > > > > > > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > > > > > > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > > > > > > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > > > > > > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > > > > > > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > > > > > > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > > > > > > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > > > > > > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > > > > > > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] =
> > > > > > > "aud_afe_26m_dmic_tm",
> > > > > > > +       [MT8195_CLK_AUD_UL_TML_HIRES] = "aud_ul_tml_hires",
> > > > > > > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] =
> > > > > > > "aud_adda6_adc_hires",
> > > > > > > +       [MT8195_CLK_AUD_LINEIN_TUNER] = "aud_linein_tuner",
> > > > > > > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > > > > > > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > > > > > > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > > > > > > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > > > > > > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > > > > > > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > > > > > > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > > > > > > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > > > > > > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > > > > > > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > > > > > > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > > > > > > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > > > > > > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > > > > > > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > > > > > > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > > > > > > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > > > > > > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > > > > > > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > > > > > > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > > > > > > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > > > > > > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > > > > > > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > > > > > > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > > > > > > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > > > > > > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > > > > > > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > > > > > > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > > > > > > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > > > > > > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > > > > > > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > > > > > > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > > > > > > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > > > > > > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > > > > > > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > > > > > > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> > > > > >
> > > > > > The MT8195_CLK_AUD_* clocks are all internal to the audio
> > > > > > subsystem:
> > > > > > the bits that control these clock gates are in the same
> > > > > > address
> > > > > > space
> > > > > > as the audio parts. Would it be possible to model them as
> > > > > > internal
> > > > > > ASoC SUPPLY widgets? The external ones could be modeled using
> > > > > > ASoC
> > > > > > CLK_SUPPLY widgets, and the dependencies could be modeled
> > > > > > with
> > > > > > ASoC
> > > > > > routes. The ASoC core could then handle power sequencing,
> > > > > > which
> > > > > > the
> > > > > > driver currently does manually.
> > > > > >
> > > > > > IMO this is better than having two drivers handling two
> > > > > > aspects
> > > > > > of
> > > > > > the same piece of hardware, while the two aspects are
> > > > > > intertwined.
> > > > > >
> > > > >
> > > > > Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such
> > > > > clocks.
> > > > > But those clocks are managed by CCF in the preceding SOCs like
> > > > > mt2701,
> > > > > mt6779 and mt8183. Additionally, in some audio modules, clocks
> > > > > should
> > > >
> > > > This being a new driver, we have some more freedom to improve the
> > > > design.
> > > >
> > > > > be enabled before configuring parameters(hw_params). As far as
> > > > > I
> > > > > know,
> > > > > if we use CLK_SUPPLY or SUPPLY to model clocks, the power
> > > > > sequence
> > > > > is
> > > > > controlled by DAPM. It seems to be impossible to fulfill all
> > > > > use
> > > > > cases.
> > > > > That's why we just keep the manual control sequence and CCF
> > > > > seems
> > > > > to be
> > > > > the best choice to model such clock gatess.
> > > >
> > > > I see. So yes, using CCF does give you reference counting,
> > > > dependency
> > > > tracking and other advantages. And using DAPM supplies means you
> > > > can't
> > > > enable the clock gates outside of DAPM without both pieces of
> > > > code
> > > > fighting for control.
> > > >
> > > > Can we at least move the audio clock gates into the audio driver
> > > > though?
> > > > The arbitrary separation into two devices and drivers is fishy.
> > > > And
> > > > with
> > > > the move the external references to the audio clock gates can be
> > > > removed.
> > > >
> > >
> > > Because DAPM SUPPLY can't fit our control scenario.
> > > Did you suggest us implement the simple logic control(including ref
> > > count, clock dependency) for clock gate(MT8195_CLK_AUD_*) in afe
> > > driver
> > > instead of using CCF?
> >
> > I meant simply moving the CCF-based clk driver code (clk-mt8516-
> > aud.c)
> > from `drivers/clk` and incorporating it into the audio driver, likely
> > in `mt8195-afe-clk.c` or maybe as a separate file. So the audio
> > driver
> > would be a clock provider, and a clock consumer. It will directly use
> > the clocks it provides, internally, and you could remove all those
> > clock references from the device tree.
> >
> > The goal is to have one hardware representation (device node) only,
> > so
> > that it matches the hardware, which is one single unified block.
> >
> > After the driver is completed, we can look for opportunities to
> > improve
> > it, if resources are available.
>
> Thanks for your detailed information.
> I will try to move the CCF-based clk driver code to AFE driver.
> If there are no other internal concerns and blocking problems, I will
> include the changes in v3.

Great.

> > > > And regarding the clock requirements for different modules, could
> > > > we
> > > > have
> > > > that information put in comments somewhere, so if someone were to
> > > > revisit
> > > > it later, they would have the information needed to understand
> > > > and
> > > > possibly
> > > > improve it? Because right now there's just a bunch of clocks
> > > > enabled
> > > > and
> > > > disabled and nothing to explain why that's needed.
> > > >
> > >
> > > For example,
> > > MT8195_CLK_AUD_ADC(clock gate) is one of the clock feeding to ADDA
> > > module.
> > > Did you want me show the clock gate list feeding to ADDA?
> > > On the other hand, I didn't know how to show the information
> > > properly
> > > in comments. Could you kindly share me an example for reference?
> >
> >
> > For example, in `mt8195_afe_enable_reg_rw_clk()` in mt8195-afe-clk.c:
> >
> >         unsigned int clk_array[] = {
> >                 MT8195_CLK_SCP_ADSP_AUDIODSP,
> >                 MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
> >                 MT8195_CLK_TOP_CFG_26M_AUD,
> >                 MT8195_CLK_INFRA_AO_AUDIO,
> >                 MT8195_CLK_INFRA_AO_AUDIO_26M_B,
> >                 MT8195_CLK_TOP_AUD_INTBUS_SEL,
> >                 MT8195_CLK_TOP_A1SYS_HP_SEL,
> >                 MT8195_CLK_AUD_A1SYS_HP,
> >                 MT8195_CLK_AUD_A1SYS,
> >                 MT8195_CLK_TOP_AUDIO_H_SEL,
> >         };
> >
> > You could add a comment after each line stating why that clock needs
> > to
> > be enabled. A simple note like "bus access clock" or "internal logic
> > clock"
> > would suffice.
> >
> OK, I will add short notes to such clock lists.
>
> > The above list also has some redundancies that could be eliminated.
> > MT8195_CLK_TOP_A1SYS_HP_SEL is parent to both MT8195_CLK_AUD_A1SYS_HP
> > and
> > MT8195_CLK_AUD_A1SYS. When clocks are enabled, their parents are also
> > enabled by CCF, so there's no need to enable them explicitly, unless
> > that clock also directly feeds the clock consumer.
> >
> OK, I will review all clock usages and remove the unnecessary clocks.
>
> >
> > Another thing I wanted to bring up: is any of the code after
> >
> >     struct mt8195_afe_tuner_cfg {
> >
> > used? It looks like it is used to configure the five extra PLLs in
> > the audio
> > subsystem, but the exposed (non-static) functions don't seem to be
> > called
> > anywhere. Are they for modules not yet supported?
> >
>
> Yes, tuners are not supported now.
> I will remove the code and add them back when tuners are required in
> the future.

Thanks.


ChenYu

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-23  6:27               ` Chen-Yu Tsai
@ 2021-07-26 14:31                 ` Trevor Wu
  2021-08-02 10:21                   ` Chen-Yu Tsai
  0 siblings, 1 reply; 18+ messages in thread
From: Trevor Wu @ 2021-07-26 14:31 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Chun-Jie Chen, broonie, tiwai, Rob Herring, Matthias Brugger,
	alsa-devel, linux-mediatek, linux-arm-kernel, LKML, devicetree,
	bicycle.tsai, Jiaxin Yu, Jimmy Cheng-Yi Chiang, Li-Yu Yu

On Fri, 2021-07-23 at 14:27 +0800, Chen-Yu Tsai wrote:
> On Thu, Jul 22, 2021 at 4:56 PM Trevor Wu <trevor.wu@mediatek.com>
> wrote:
> > 
> > On Mon, 2021-07-19 at 18:05 +0800, Chen-Yu Tsai wrote:
> > > Hi,
> > > 
> > > On Thu, Jul 15, 2021 at 7:05 PM Trevor Wu <trevor.wu@mediatek.com
> > > >
> > > wrote:
> > > > 
> > > > On Tue, 2021-07-13 at 14:00 +0800, Chen-Yu Tsai wrote:
> > > > > On Mon, Jul 12, 2021 at 11:10 PM Trevor Wu <
> > > > > trevor.wu@mediatek.com>
> > > > > wrote:
> > > > > > 
> > > > > > On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
> > > > > > >  are all internal Hi,
> > > > > > > 
> > > > > > > On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <
> > > > > > > trevor.wu@mediatek.com
> > > > > > > > 
> > > > > > > 
> > > > > > > wrote:
> > > > > > > > 
> > > > > > > > This patch adds mt8195 platform and affiliated driver.
> > > > > > > > 
> > > > > > > > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > > > > > > > ---
> > > > > > > >  sound/soc/mediatek/Kconfig                     |    9
> > > > > > > > +
> > > > > > > >  sound/soc/mediatek/Makefile                   |    1 +
> > > > > > > >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899
> > > > > > > > +++++
> > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > > > > > > > +++++++++++++++++
> > > > > > > >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > > > > > > > ++++++++++++++
> > > > > > > >  8 files changed, 7378 insertions(+)
> > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > afe-
> > > > > > > > clk.c
> > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > afe-
> > > > > > > > clk.h
> > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > afe-
> > > > > > > > common.h
> > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > afe-
> > > > > > > > pcm.c
> > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > reg.h
> > > > > > > > 
> > > > > > > > diff --git a/sound/soc/mediatek/Kconfig
> > > > > > > > b/sound/soc/mediatek/Kconfig
> > > > > > > > index 74dae4332d17..3389f382be06 100644
> > > > > > > > --- a/sound/soc/mediatek/Kconfig
> > > > > > > > +++ b/sound/soc/mediatek/Kconfig
> > > > > > > > @@ -184,3 +184,12 @@ config
> > > > > > > > SND_SOC_MT8192_MT6359_RT1015_RT5682
> > > > > > > >           with the MT6359 RT1015 RT5682 audio codec.
> > > > > > > >           Select Y if you have such device.
> > > > > > > >           If unsure select "N".
> > > > > > > > +
> > > > > > > > +config SND_SOC_MT8195
> > > > > > > > +       tristate "ASoC support for Mediatek MT8195
> > > > > > > > chip"
> > > > > > > > +       select SND_SOC_MEDIATEK
> > > > > > > > +       help
> > > > > > > > +         This adds ASoC platform driver support for
> > > > > > > > Mediatek
> > > > > > > > MT8195 chip
> > > > > > > > +         that can be used with other codecs.
> > > > > > > > +         Select Y if you have such device.
> > > > > > > > +         If unsure select "N".
> > > > > > > > diff --git a/sound/soc/mediatek/Makefile
> > > > > > > > b/sound/soc/mediatek/Makefile
> > > > > > > > index f6cb6b8508e3..34778ca12106 100644
> > > > > > > > --- a/sound/soc/mediatek/Makefile
> > > > > > > > +++ b/sound/soc/mediatek/Makefile
> > > > > > > > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> > > > > > > >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> > > > > > > >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> > > > > > > >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > > > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > > > > > > > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > > > > > > > b/sound/soc/mediatek/mt8195/Makefile
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..b2c9fd88f39e
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/sound/soc/mediatek/mt8195/Makefile
> > > > > > > > @@ -0,0 +1,11 @@
> > > > > > > > +# SPDX-License-Identifier: GPL-2.0
> > > > > > > > +
> > > > > > > > +# platform driver
> > > > > > > > +snd-soc-mt8195-afe-objs := \
> > > > > > > > +       mt8195-afe-clk.o \
> > > > > > > > +       mt8195-afe-pcm.o \
> > > > > > > > +       mt8195-dai-adda.o \
> > > > > > > > +       mt8195-dai-etdm.o \
> > > > > > > > +       mt8195-dai-pcm.o
> > > > > > > > +
> > > > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > > > > > > > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > > new file mode 100644
> > > > > > > > index 000000000000..57aa799b4f41
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > > @@ -0,0 +1,899 @@
> > > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > > +/*
> > > > > > > > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > > > > > > > + *
> > > > > > > > + * Copyright (c) 2021 MediaTek Inc.
> > > > > > > > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > > > > > > > + *         Trevor Wu <trevor.wu@mediatek.com>
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <linux/clk.h>
> > > > > > > > +
> > > > > > > > +#include "mt8195-afe-common.h"
> > > > > > > > +#include "mt8195-afe-clk.h"
> > > > > > > > +#include "mt8195-reg.h"
> > > > > > > > +
> > > > > > > > +static const char *aud_clks[MT8195_CLK_NUM] = {
> > > > > > > 
> > > > > > > Most of these clocks are not described in the device tree
> > > > > > > binding. If
> > > > > > > the driver needs to reference them, they should be
> > > > > > > described.
> > > > > > > We
> > > > > > > should
> > > > > > > not be hard-coding clock names across different drivers.
> > > > > > > 
> > > > > > 
> > > > > > Sorry, I didn't know I have to list all clocks in the dt-
> > > > > > binding.
> > > > > > Originally, I thought these clocks will be described in the
> > > > > > clock
> > > > > > binding, so I didn't add them to the binding of afe driver.
> > > > > > I will add these clocks to mt8195-afe-pcm.yaml.
> > > > > 
> > > > > If the device consumes clocks, then the clocks that get
> > > > > consumed
> > > > > should
> > > > > be listed in the device's bindings. This is not related to
> > > > > the
> > > > > clock
> > > > > bindings, which is a clock provider.
> > > > > 
> > > > 
> > > > Got it. Thanks.
> > > > 
> > > > > > > The more important question is, why does the driver need
> > > > > > > to
> > > > > > > reference
> > > > > > > all of them? Maybe we should take a step back and draw
> > > > > > > out a
> > > > > > > clock
> > > > > > > tree
> > > > > > > diagram for the hardware?
> > > > > > > 
> > > > > > 
> > > > > > The clock structure is PLL -> MUX -> GATE.
> > > > > > xtal, pll and divider are the possible clock inputs for
> > > > > > MUX.
> > > > > > Because we select the clock input of audio module based on
> > > > > > the
> > > > > > use
> > > > > > case, we use clk_get to retrive all clocks which are
> > > > > > possible
> > > > > > to be
> > > > > > used.
> > > > > 
> > > > > So I see a couple the driver is doing reparenting:
> > > > > 
> > > > >   a. Reparent audio_h to standard oscillator when ADDA is not
> > > > > used,
> > > > >      presumably to let the APLL be turned off
> > > > > 
> > > > > Why not just turn off audio_h? It looks like audio_h feeds a
> > > > > couple
> > > > > clock
> > > > > gates in the audio subsystem. Just a guess, but is this the
> > > > > AHB
> > > > > bus
> > > > > clock?
> > > > > Why not just have it parented to "univpll_d7" all the time
> > > > > then?
> > > > > 
> > > > 
> > > > Sorry, I am not sure if it is the AHB bus clock.
> > > > I only know how audio module uses the clock.
> > > > audio_h feeds to some clock gate like aud_adc_hires, which is
> > > > used
> > > > when
> > > > sampling rate is higher than 48kHz, and hardware designer
> > > > suggests
> > > > us
> > > > use apll1_ck when AFE requrires the clock.
> > > 
> > > I see. So the simplified explanation is high clock rate for high
> > > res
> > > audio.
> > > Would high clock rate work for standard sample rates?
> > 
> > As far as I know, HW will switch clock to hires clock automatically
> > when the required rate is high,(ex: aud_adc and aud_adc_hires) so
> > it
> > can't be controlled by driver.
> 
> I see. That might not be so friendly to the Linux clk driver.
> 
> > > Would using apll1 or univpll all the time work, instead of
> > > reparenting?
> > > What's the gain if we do reparenting?
> > > 
> > 
> > As you said before, the gain is apll can be turned off when the
> > clock
> > is not requrired by ADDA. That's why we didn't use apll all the
> > time.
> 
> Right, and what's the gain from turning it off? Lower power
> consumption?
> 

Yes. Xtal_26m is supplied to most modules, but APLL1 is mainly used by
afe. When audio feature is not used, we hope APLL1 can be turned off to
lower power consumption.

> > > > As I know, DSP also requires audio_h.
> > > > When we disable the clock in AFE driver, the ref count in CCF
> > > > is
> > > > not
> > > > becoming zero if DSP still uses it.
> > > > But only AFE requires higher clock rate, so we reparent audio_h
> > > > to
> > > > 26M
> > > > when it's not required in adda module.
> > > 
> > > I see. Wouldn't reparenting the clock while it is in use by
> > > another
> > > module
> > > cause glitches?
> > 
> > I checked with the DSP owner.
> > audio_h clock is required for DSP bus, but the clock rate is not
> > important.
> > The only thing it cares is audio_h should be powered on, so
> > reparenting
> > is harmless for DSP.
> 
> OK.
> 
> > > > > Also, reparenting really should be done implicitly with
> > > > > clk_set_rate()
> > > > > with the clock driver supporting reparenting on rate changes.
> > > > > 
> > > > >   b. Assignment of PLLs for I2S/PCM MCLK outputs
> > > > > 
> > > > > Is there a reason for explicit assignment, other than clock
> > > > > rate
> > > > > conflicts?
> > > > > CCF supports requesting and locking the clock rate. And
> > > > > again,
> > > > > implicit
> > > > > reparenting should be the norm. The clock driver's purpose is
> > > > > to
> > > > > fulfill
> > > > > any and all clock rate requirements from its consumers. The
> > > > > consumer
> > > > > should
> > > > > only need to ask for the clock rate, not a specific parent,
> > > > > unless
> > > > > there
> > > > > are details that are not yet covered by the CCF.
> > > > > 
> > > > 
> > > > For MCLK output, we should configure divider to get the target
> > > > rate,
> > > > and it can only divide the clock from current parent source.
> > > > So we should do reparent to divider's parent in case the parent
> > > > rate is
> > > > not a multiple of target rate.
> > > 
> > > Right. That is expected. What I'm saying is that the CCF provides
> > > the
> > > framework for automatically reparenting based on the requested
> > > clock
> > > rate. This is done in the clock driver's .determine_rate op.
> > > 
> > > When properly implemented, and also restricting or locking the
> > > clock
> > > rates
> > > of the PLLs, then you can simply request a clock rate on the leaf
> > > clock,
> > > in this case one of the MCLKs, and the CCF and clock driver would
> > > handle
> > > everything else. The consumer should not be reparenting clocks
> > > manually
> > > unless for a very good reason which cannot be satisfied by the
> > > CCF.
> > > 
> > 
> > In some use cases, we really need to reparent clock manually.
> > For example, spdif in(slave) -> .... -> i2s out(master)
> > 
> > APLL3/APLL4 are reserved for slave input like earc in or spdif in,
> > which can refer to the external clock source.(APLL3 syncs with
> > earc,
> > and APLL4 syncs with spdif in.)
> > 
> > When i2s out selects the clock source to APLL4, this makes sure
> > that
> > spdif in and i2s out works in the same clock source.
> > If we just use APLL1/APLL2 on i2s out, there is little rate
> > mismatch
> > between data input and output. Finally, it results in XRUN.
> 
> I see, that makes more sense.
> 
> > If we only use set_rate, it's possible that it can't switch to the
> > expected PLL source, because the rate of APLL3/APLL4 should be
> > close to
> > APLL1/APLL2.
> 
> Well, in theory the CCF should choose the one with the closest rate.
> And if APLL3/APLL4 is already tracking the external clock source, its
> clock rate should match.
> 
> If it's a static requirement, maybe we could replace the *-mclk-
> source
> DT properties with standard assigned-clocks and assigned-clock-
> parents?
> This would get handled by CCF directly, and then the only thing the
> clk driver has to do is make sure it doesn't get reparented again.
> 
> Or is there a need to do reparenting at runtime?
> 

For the use case of APLL3/APLL4, static assignment should be ok.

But I checked with CCF owner, we can't just use clk_set_rate(divider,
rate) to get expected MCLK output, because reparenting MUX
automatically is not supported now. (PLL -> MUX -> divider)

We still have to call clk_set_parent() before clk_set_rate(). Which
means some information should be got from DTS to check whether the PLL
source can be switched or not, so *-mclk-source should be keeped to
identify the case.

Thanks,
Trevor

> > > > > A related question: the chip has five APLLs. How many MCLK
> > > > > combinations
> > > > > does the application need to support? I assume this includes
> > > > > the
> > > > > standard
> > > > > 24.576 MHz and 22.5792 MHz clock rates.
> > > > > 
> > > > 
> > > > APLL1 and APLL2 are used in most AFE modules, so their rate
> > > > should
> > > > be
> > > > fixed.
> > > > APLL1 is fixed to 196608000Hz.
> > > > APLL2 is fixed to 180633600Hz.
> > > > APLL is inputed to the divider(8bit), and MCLK is the output of
> > > > divider.
> > > > Other APLLs are reserved for some special usage which can't be
> > > > supported by APLL1 & APLL2.
> > > > But APLL3~APLL5 aren't used in the series, so I will remove
> > > > them in
> > > > v3.
> > > > 
> > > > > > Some of them are not used in this series, because some
> > > > > > modules
> > > > > > are
> > > > > > still developing. Should I only keep the clocks that have
> > > > > > been
> > > > > > used
> > > > > > in
> > > > > > the series?
> > > > > 
> > > > > Yes please. Only add the ones that are used. Things that
> > > > > aren't
> > > > > used
> > > > > don't get tested and verified, and end up as dead code. If
> > > > > there
> > > > > are
> > > > > plans to extend them in the future, and you can leave
> > > > > comments
> > > > > stating
> > > > > that intent, and also mention it in the cover letter.
> > > > > 
> > > > 
> > > > OK, I will remove the unused clock in v3.
> > > > 
> > > > > > > > +       /* xtal */
> > > > > > > > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > > > > > > > +       /* pll */
> > > > > > > > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > > > > > > > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > > > > > > > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > > > > > > > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > > > > > > > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > > > > > > > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] =
> > > > > > > > "hdmirx_apll",
> > > > > > > > +       /* divider */
> > > > > > > > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > > > > > > > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > > > > > > > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > > > > > > > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > > > > > > > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > > > > > > > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > > > > > > > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > > > > > > > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > > > > > > > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > > > > > > > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > > > > > > > +       [MT8195_CLK_TOP_HDMIRX_APLL] =
> > > > > > > > "hdmirx_apll_ck",
> > > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] =
> > > > > > > > "mainpll_d4_d4",
> > > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] =
> > > > > > > > "mainpll_d5_d2",
> > > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] =
> > > > > > > > "mainpll_d7_d2",
> > > > > > > > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > > > > > > > +       /* mux */
> > > > > > > > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > > > > > > > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > > > > > > > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > > > > > > > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > > > > > > > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > > > > > > > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > > > > > > > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > > > > > > > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > > > > > > > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > > > > > > > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > > > > > > > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > > > > > > > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > > > > > > > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > > > > > > > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] =
> > > > > > > > "aud_intbus_sel",
> > > > > > > > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > > > > > > > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > > > > > > > "audio_local_bus_sel",
> > > > > > > > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > > > > > > > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > > > > > > > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > > > > > > > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > > > > > > > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > > > > > > > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > > > > > > > +       /* clock gate */
> > > > > > > > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] =
> > > > > > > > "mphone_slave_b",
> > > > > > > > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > > > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > > > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] =
> > > > > > > > "infra_ao_audio_26m_b",
> > > > > > > > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] =
> > > > > > > > "scp_adsp_audiodsp",
> > > > > > > 
> > > > > > > 
> > > > > > > > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > > > > > > > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > > > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > > > > > > > "aud_spdifin_tuner_apll",
> > > > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > > > > > > > "aud_spdifin_tuner_dbg",
> > > > > > > > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > > > > > > > +       [MT8195_CLK_AUD_APLL1_TUNER] =
> > > > > > > > "aud_apll1_tuner",
> > > > > > > > +       [MT8195_CLK_AUD_APLL2_TUNER] =
> > > > > > > > "aud_apll2_tuner",
> > > > > > > > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > > > > > > > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > > > > > > > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > > > > > > > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > > > > > > > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > > > > > > > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > > > > > > > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > > > > > > > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > > > > > > > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > > > > > > > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] =
> > > > > > > > "aud_afe_26m_dmic_tm",
> > > > > > > > +       [MT8195_CLK_AUD_UL_TML_HIRES] =
> > > > > > > > "aud_ul_tml_hires",
> > > > > > > > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > > > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > > > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] =
> > > > > > > > "aud_adda6_adc_hires",
> > > > > > > > +       [MT8195_CLK_AUD_LINEIN_TUNER] =
> > > > > > > > "aud_linein_tuner",
> > > > > > > > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > > > > > > > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > > > > > > > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > > > > > > > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > > > > > > > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > > > > > > > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > > > > > > > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > > > > > > > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > > > > > > > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > > > > > > > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > > > > > > > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > > > > > > > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > > > > > > > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > > > > > > > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > > > > > > > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > > > > > > > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> > > > > > > 
> > > > > > > The MT8195_CLK_AUD_* clocks are all internal to the audio
> > > > > > > subsystem:
> > > > > > > the bits that control these clock gates are in the same
> > > > > > > address
> > > > > > > space
> > > > > > > as the audio parts. Would it be possible to model them as
> > > > > > > internal
> > > > > > > ASoC SUPPLY widgets? The external ones could be modeled
> > > > > > > using
> > > > > > > ASoC
> > > > > > > CLK_SUPPLY widgets, and the dependencies could be modeled
> > > > > > > with
> > > > > > > ASoC
> > > > > > > routes. The ASoC core could then handle power sequencing,
> > > > > > > which
> > > > > > > the
> > > > > > > driver currently does manually.
> > > > > > > 
> > > > > > > IMO this is better than having two drivers handling two
> > > > > > > aspects
> > > > > > > of
> > > > > > > the same piece of hardware, while the two aspects are
> > > > > > > intertwined.
> > > > > > > 
> > > > > > 
> > > > > > Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such
> > > > > > clocks.
> > > > > > But those clocks are managed by CCF in the preceding SOCs
> > > > > > like
> > > > > > mt2701,
> > > > > > mt6779 and mt8183. Additionally, in some audio modules,
> > > > > > clocks
> > > > > > should
> > > > > 
> > > > > This being a new driver, we have some more freedom to improve
> > > > > the
> > > > > design.
> > > > > 
> > > > > > be enabled before configuring parameters(hw_params). As far
> > > > > > as
> > > > > > I
> > > > > > know,
> > > > > > if we use CLK_SUPPLY or SUPPLY to model clocks, the power
> > > > > > sequence
> > > > > > is
> > > > > > controlled by DAPM. It seems to be impossible to fulfill
> > > > > > all
> > > > > > use
> > > > > > cases.
> > > > > > That's why we just keep the manual control sequence and CCF
> > > > > > seems
> > > > > > to be
> > > > > > the best choice to model such clock gatess.
> > > > > 
> > > > > I see. So yes, using CCF does give you reference counting,
> > > > > dependency
> > > > > tracking and other advantages. And using DAPM supplies means
> > > > > you
> > > > > can't
> > > > > enable the clock gates outside of DAPM without both pieces of
> > > > > code
> > > > > fighting for control.
> > > > > 
> > > > > Can we at least move the audio clock gates into the audio
> > > > > driver
> > > > > though?
> > > > > The arbitrary separation into two devices and drivers is
> > > > > fishy.
> > > > > And
> > > > > with
> > > > > the move the external references to the audio clock gates can
> > > > > be
> > > > > removed.
> > > > > 
> > > > 
> > > > Because DAPM SUPPLY can't fit our control scenario.
> > > > Did you suggest us implement the simple logic control(including
> > > > ref
> > > > count, clock dependency) for clock gate(MT8195_CLK_AUD_*) in
> > > > afe
> > > > driver
> > > > instead of using CCF?
> > > 
> > > I meant simply moving the CCF-based clk driver code (clk-mt8516-
> > > aud.c)
> > > from `drivers/clk` and incorporating it into the audio driver,
> > > likely
> > > in `mt8195-afe-clk.c` or maybe as a separate file. So the audio
> > > driver
> > > would be a clock provider, and a clock consumer. It will directly
> > > use
> > > the clocks it provides, internally, and you could remove all
> > > those
> > > clock references from the device tree.
> > > 
> > > The goal is to have one hardware representation (device node)
> > > only,
> > > so
> > > that it matches the hardware, which is one single unified block.
> > > 
> > > After the driver is completed, we can look for opportunities to
> > > improve
> > > it, if resources are available.
> > 
> > Thanks for your detailed information.
> > I will try to move the CCF-based clk driver code to AFE driver.
> > If there are no other internal concerns and blocking problems, I
> > will
> > include the changes in v3.
> 
> Great.
> 
> > > > > And regarding the clock requirements for different modules,
> > > > > could
> > > > > we
> > > > > have
> > > > > that information put in comments somewhere, so if someone
> > > > > were to
> > > > > revisit
> > > > > it later, they would have the information needed to
> > > > > understand
> > > > > and
> > > > > possibly
> > > > > improve it? Because right now there's just a bunch of clocks
> > > > > enabled
> > > > > and
> > > > > disabled and nothing to explain why that's needed.
> > > > > 
> > > > 
> > > > For example,
> > > > MT8195_CLK_AUD_ADC(clock gate) is one of the clock feeding to
> > > > ADDA
> > > > module.
> > > > Did you want me show the clock gate list feeding to ADDA?
> > > > On the other hand, I didn't know how to show the information
> > > > properly
> > > > in comments. Could you kindly share me an example for
> > > > reference?
> > > 
> > > 
> > > For example, in `mt8195_afe_enable_reg_rw_clk()` in mt8195-afe-
> > > clk.c:
> > > 
> > >         unsigned int clk_array[] = {
> > >                 MT8195_CLK_SCP_ADSP_AUDIODSP,
> > >                 MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
> > >                 MT8195_CLK_TOP_CFG_26M_AUD,
> > >                 MT8195_CLK_INFRA_AO_AUDIO,
> > >                 MT8195_CLK_INFRA_AO_AUDIO_26M_B,
> > >                 MT8195_CLK_TOP_AUD_INTBUS_SEL,
> > >                 MT8195_CLK_TOP_A1SYS_HP_SEL,
> > >                 MT8195_CLK_AUD_A1SYS_HP,
> > >                 MT8195_CLK_AUD_A1SYS,
> > >                 MT8195_CLK_TOP_AUDIO_H_SEL,
> > >         };
> > > 
> > > You could add a comment after each line stating why that clock
> > > needs
> > > to
> > > be enabled. A simple note like "bus access clock" or "internal
> > > logic
> > > clock"
> > > would suffice.
> > > 
> > 
> > OK, I will add short notes to such clock lists.
> > 
> > > The above list also has some redundancies that could be
> > > eliminated.
> > > MT8195_CLK_TOP_A1SYS_HP_SEL is parent to both
> > > MT8195_CLK_AUD_A1SYS_HP
> > > and
> > > MT8195_CLK_AUD_A1SYS. When clocks are enabled, their parents are
> > > also
> > > enabled by CCF, so there's no need to enable them explicitly,
> > > unless
> > > that clock also directly feeds the clock consumer.
> > > 
> > 
> > OK, I will review all clock usages and remove the unnecessary
> > clocks.
> > 
> > > 
> > > Another thing I wanted to bring up: is any of the code after
> > > 
> > >     struct mt8195_afe_tuner_cfg {
> > > 
> > > used? It looks like it is used to configure the five extra PLLs
> > > in
> > > the audio
> > > subsystem, but the exposed (non-static) functions don't seem to
> > > be
> > > called
> > > anywhere. Are they for modules not yet supported?
> > > 
> > 
> > Yes, tuners are not supported now.
> > I will remove the code and add them back when tuners are required
> > in
> > the future.
> 
> Thanks.
> 
> 
> ChenYu
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver
  2021-07-26 14:31                 ` Trevor Wu
@ 2021-08-02 10:21                   ` Chen-Yu Tsai
  0 siblings, 0 replies; 18+ messages in thread
From: Chen-Yu Tsai @ 2021-08-02 10:21 UTC (permalink / raw)
  To: Trevor Wu
  Cc: Chun-Jie Chen, broonie, tiwai, Rob Herring, Matthias Brugger,
	alsa-devel, moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE, LKML,
	Devicetree List, bicycle.tsai, Jiaxin Yu, Jimmy Cheng-Yi Chiang,
	Li-Yu Yu

On Mon, Jul 26, 2021 at 10:31 PM Trevor Wu <trevor.wu@mediatek.com> wrote:
>
> On Fri, 2021-07-23 at 14:27 +0800, Chen-Yu Tsai wrote:
> > On Thu, Jul 22, 2021 at 4:56 PM Trevor Wu <trevor.wu@mediatek.com>
> > wrote:
> > >
> > > On Mon, 2021-07-19 at 18:05 +0800, Chen-Yu Tsai wrote:
> > > > Hi,
> > > >
> > > > On Thu, Jul 15, 2021 at 7:05 PM Trevor Wu <trevor.wu@mediatek.com
> > > > >
> > > > wrote:
> > > > >
> > > > > On Tue, 2021-07-13 at 14:00 +0800, Chen-Yu Tsai wrote:
> > > > > > On Mon, Jul 12, 2021 at 11:10 PM Trevor Wu <
> > > > > > trevor.wu@mediatek.com>
> > > > > > wrote:
> > > > > > >
> > > > > > > On Mon, 2021-07-12 at 14:57 +0800, Chen-Yu Tsai wrote:
> > > > > > > >  are all internal Hi,
> > > > > > > >
> > > > > > > > On Tue, Jun 29, 2021 at 9:49 AM Trevor Wu <
> > > > > > > > trevor.wu@mediatek.com
> > > > > > > > >
> > > > > > > >
> > > > > > > > wrote:
> > > > > > > > >
> > > > > > > > > This patch adds mt8195 platform and affiliated driver.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
> > > > > > > > > ---
> > > > > > > > >  sound/soc/mediatek/Kconfig                     |    9
> > > > > > > > > +
> > > > > > > > >  sound/soc/mediatek/Makefile                   |    1 +
> > > > > > > > >  sound/soc/mediatek/mt8195/Makefile            |   11 +
> > > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.c    |  899
> > > > > > > > > +++++
> > > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-clk.h    |  201 +
> > > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-common.h |  200 +
> > > > > > > > >  sound/soc/mediatek/mt8195/mt8195-afe-pcm.c    | 3264
> > > > > > > > > +++++++++++++++++
> > > > > > > > >  sound/soc/mediatek/mt8195/mt8195-reg.h        | 2793
> > > > > > > > > ++++++++++++++
> > > > > > > > >  8 files changed, 7378 insertions(+)
> > > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/Makefile
> > > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > > afe-
> > > > > > > > > clk.c
> > > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > > afe-
> > > > > > > > > clk.h
> > > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > > afe-
> > > > > > > > > common.h
> > > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > > afe-
> > > > > > > > > pcm.c
> > > > > > > > >  create mode 100644 sound/soc/mediatek/mt8195/mt8195-
> > > > > > > > > reg.h
> > > > > > > > >
> > > > > > > > > diff --git a/sound/soc/mediatek/Kconfig
> > > > > > > > > b/sound/soc/mediatek/Kconfig
> > > > > > > > > index 74dae4332d17..3389f382be06 100644
> > > > > > > > > --- a/sound/soc/mediatek/Kconfig
> > > > > > > > > +++ b/sound/soc/mediatek/Kconfig
> > > > > > > > > @@ -184,3 +184,12 @@ config
> > > > > > > > > SND_SOC_MT8192_MT6359_RT1015_RT5682
> > > > > > > > >           with the MT6359 RT1015 RT5682 audio codec.
> > > > > > > > >           Select Y if you have such device.
> > > > > > > > >           If unsure select "N".
> > > > > > > > > +
> > > > > > > > > +config SND_SOC_MT8195
> > > > > > > > > +       tristate "ASoC support for Mediatek MT8195
> > > > > > > > > chip"
> > > > > > > > > +       select SND_SOC_MEDIATEK
> > > > > > > > > +       help
> > > > > > > > > +         This adds ASoC platform driver support for
> > > > > > > > > Mediatek
> > > > > > > > > MT8195 chip
> > > > > > > > > +         that can be used with other codecs.
> > > > > > > > > +         Select Y if you have such device.
> > > > > > > > > +         If unsure select "N".
> > > > > > > > > diff --git a/sound/soc/mediatek/Makefile
> > > > > > > > > b/sound/soc/mediatek/Makefile
> > > > > > > > > index f6cb6b8508e3..34778ca12106 100644
> > > > > > > > > --- a/sound/soc/mediatek/Makefile
> > > > > > > > > +++ b/sound/soc/mediatek/Makefile
> > > > > > > > > @@ -5,3 +5,4 @@ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
> > > > > > > > >  obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
> > > > > > > > >  obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
> > > > > > > > >  obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
> > > > > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
> > > > > > > > > diff --git a/sound/soc/mediatek/mt8195/Makefile
> > > > > > > > > b/sound/soc/mediatek/mt8195/Makefile
> > > > > > > > > new file mode 100644
> > > > > > > > > index 000000000000..b2c9fd88f39e
> > > > > > > > > --- /dev/null
> > > > > > > > > +++ b/sound/soc/mediatek/mt8195/Makefile
> > > > > > > > > @@ -0,0 +1,11 @@
> > > > > > > > > +# SPDX-License-Identifier: GPL-2.0
> > > > > > > > > +
> > > > > > > > > +# platform driver
> > > > > > > > > +snd-soc-mt8195-afe-objs := \
> > > > > > > > > +       mt8195-afe-clk.o \
> > > > > > > > > +       mt8195-afe-pcm.o \
> > > > > > > > > +       mt8195-dai-adda.o \
> > > > > > > > > +       mt8195-dai-etdm.o \
> > > > > > > > > +       mt8195-dai-pcm.o
> > > > > > > > > +
> > > > > > > > > +obj-$(CONFIG_SND_SOC_MT8195) += snd-soc-mt8195-afe.o
> > > > > > > > > diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > > > b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > > > new file mode 100644
> > > > > > > > > index 000000000000..57aa799b4f41
> > > > > > > > > --- /dev/null
> > > > > > > > > +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
> > > > > > > > > @@ -0,0 +1,899 @@
> > > > > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > > > > +/*
> > > > > > > > > + * mt8195-afe-clk.c  --  Mediatek 8195 afe clock ctrl
> > > > > > > > > + *
> > > > > > > > > + * Copyright (c) 2021 MediaTek Inc.
> > > > > > > > > + * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
> > > > > > > > > + *         Trevor Wu <trevor.wu@mediatek.com>
> > > > > > > > > + */
> > > > > > > > > +
> > > > > > > > > +#include <linux/clk.h>
> > > > > > > > > +
> > > > > > > > > +#include "mt8195-afe-common.h"
> > > > > > > > > +#include "mt8195-afe-clk.h"
> > > > > > > > > +#include "mt8195-reg.h"
> > > > > > > > > +
> > > > > > > > > +static const char *aud_clks[MT8195_CLK_NUM] = {
> > > > > > > >
> > > > > > > > Most of these clocks are not described in the device tree
> > > > > > > > binding. If
> > > > > > > > the driver needs to reference them, they should be
> > > > > > > > described.
> > > > > > > > We
> > > > > > > > should
> > > > > > > > not be hard-coding clock names across different drivers.
> > > > > > > >
> > > > > > >
> > > > > > > Sorry, I didn't know I have to list all clocks in the dt-
> > > > > > > binding.
> > > > > > > Originally, I thought these clocks will be described in the
> > > > > > > clock
> > > > > > > binding, so I didn't add them to the binding of afe driver.
> > > > > > > I will add these clocks to mt8195-afe-pcm.yaml.
> > > > > >
> > > > > > If the device consumes clocks, then the clocks that get
> > > > > > consumed
> > > > > > should
> > > > > > be listed in the device's bindings. This is not related to
> > > > > > the
> > > > > > clock
> > > > > > bindings, which is a clock provider.
> > > > > >
> > > > >
> > > > > Got it. Thanks.
> > > > >
> > > > > > > > The more important question is, why does the driver need
> > > > > > > > to
> > > > > > > > reference
> > > > > > > > all of them? Maybe we should take a step back and draw
> > > > > > > > out a
> > > > > > > > clock
> > > > > > > > tree
> > > > > > > > diagram for the hardware?
> > > > > > > >
> > > > > > >
> > > > > > > The clock structure is PLL -> MUX -> GATE.
> > > > > > > xtal, pll and divider are the possible clock inputs for
> > > > > > > MUX.
> > > > > > > Because we select the clock input of audio module based on
> > > > > > > the
> > > > > > > use
> > > > > > > case, we use clk_get to retrive all clocks which are
> > > > > > > possible
> > > > > > > to be
> > > > > > > used.
> > > > > >
> > > > > > So I see a couple the driver is doing reparenting:
> > > > > >
> > > > > >   a. Reparent audio_h to standard oscillator when ADDA is not
> > > > > > used,
> > > > > >      presumably to let the APLL be turned off
> > > > > >
> > > > > > Why not just turn off audio_h? It looks like audio_h feeds a
> > > > > > couple
> > > > > > clock
> > > > > > gates in the audio subsystem. Just a guess, but is this the
> > > > > > AHB
> > > > > > bus
> > > > > > clock?
> > > > > > Why not just have it parented to "univpll_d7" all the time
> > > > > > then?
> > > > > >
> > > > >
> > > > > Sorry, I am not sure if it is the AHB bus clock.
> > > > > I only know how audio module uses the clock.
> > > > > audio_h feeds to some clock gate like aud_adc_hires, which is
> > > > > used
> > > > > when
> > > > > sampling rate is higher than 48kHz, and hardware designer
> > > > > suggests
> > > > > us
> > > > > use apll1_ck when AFE requrires the clock.
> > > >
> > > > I see. So the simplified explanation is high clock rate for high
> > > > res
> > > > audio.
> > > > Would high clock rate work for standard sample rates?
> > >
> > > As far as I know, HW will switch clock to hires clock automatically
> > > when the required rate is high,(ex: aud_adc and aud_adc_hires) so
> > > it
> > > can't be controlled by driver.
> >
> > I see. That might not be so friendly to the Linux clk driver.
> >
> > > > Would using apll1 or univpll all the time work, instead of
> > > > reparenting?
> > > > What's the gain if we do reparenting?
> > > >
> > >
> > > As you said before, the gain is apll can be turned off when the
> > > clock
> > > is not requrired by ADDA. That's why we didn't use apll all the
> > > time.
> >
> > Right, and what's the gain from turning it off? Lower power
> > consumption?
> >
>
> Yes. Xtal_26m is supplied to most modules, but APLL1 is mainly used by
> afe. When audio feature is not used, we hope APLL1 can be turned off to
> lower power consumption.
>
> > > > > As I know, DSP also requires audio_h.
> > > > > When we disable the clock in AFE driver, the ref count in CCF
> > > > > is
> > > > > not
> > > > > becoming zero if DSP still uses it.
> > > > > But only AFE requires higher clock rate, so we reparent audio_h
> > > > > to
> > > > > 26M
> > > > > when it's not required in adda module.
> > > >
> > > > I see. Wouldn't reparenting the clock while it is in use by
> > > > another
> > > > module
> > > > cause glitches?
> > >
> > > I checked with the DSP owner.
> > > audio_h clock is required for DSP bus, but the clock rate is not
> > > important.
> > > The only thing it cares is audio_h should be powered on, so
> > > reparenting
> > > is harmless for DSP.
> >
> > OK.
> >
> > > > > > Also, reparenting really should be done implicitly with
> > > > > > clk_set_rate()
> > > > > > with the clock driver supporting reparenting on rate changes.
> > > > > >
> > > > > >   b. Assignment of PLLs for I2S/PCM MCLK outputs
> > > > > >
> > > > > > Is there a reason for explicit assignment, other than clock
> > > > > > rate
> > > > > > conflicts?
> > > > > > CCF supports requesting and locking the clock rate. And
> > > > > > again,
> > > > > > implicit
> > > > > > reparenting should be the norm. The clock driver's purpose is
> > > > > > to
> > > > > > fulfill
> > > > > > any and all clock rate requirements from its consumers. The
> > > > > > consumer
> > > > > > should
> > > > > > only need to ask for the clock rate, not a specific parent,
> > > > > > unless
> > > > > > there
> > > > > > are details that are not yet covered by the CCF.
> > > > > >
> > > > >
> > > > > For MCLK output, we should configure divider to get the target
> > > > > rate,
> > > > > and it can only divide the clock from current parent source.
> > > > > So we should do reparent to divider's parent in case the parent
> > > > > rate is
> > > > > not a multiple of target rate.
> > > >
> > > > Right. That is expected. What I'm saying is that the CCF provides
> > > > the
> > > > framework for automatically reparenting based on the requested
> > > > clock
> > > > rate. This is done in the clock driver's .determine_rate op.
> > > >
> > > > When properly implemented, and also restricting or locking the
> > > > clock
> > > > rates
> > > > of the PLLs, then you can simply request a clock rate on the leaf
> > > > clock,
> > > > in this case one of the MCLKs, and the CCF and clock driver would
> > > > handle
> > > > everything else. The consumer should not be reparenting clocks
> > > > manually
> > > > unless for a very good reason which cannot be satisfied by the
> > > > CCF.
> > > >
> > >
> > > In some use cases, we really need to reparent clock manually.
> > > For example, spdif in(slave) -> .... -> i2s out(master)
> > >
> > > APLL3/APLL4 are reserved for slave input like earc in or spdif in,
> > > which can refer to the external clock source.(APLL3 syncs with
> > > earc,
> > > and APLL4 syncs with spdif in.)
> > >
> > > When i2s out selects the clock source to APLL4, this makes sure
> > > that
> > > spdif in and i2s out works in the same clock source.
> > > If we just use APLL1/APLL2 on i2s out, there is little rate
> > > mismatch
> > > between data input and output. Finally, it results in XRUN.
> >
> > I see, that makes more sense.
> >
> > > If we only use set_rate, it's possible that it can't switch to the
> > > expected PLL source, because the rate of APLL3/APLL4 should be
> > > close to
> > > APLL1/APLL2.
> >
> > Well, in theory the CCF should choose the one with the closest rate.
> > And if APLL3/APLL4 is already tracking the external clock source, its
> > clock rate should match.
> >
> > If it's a static requirement, maybe we could replace the *-mclk-
> > source
> > DT properties with standard assigned-clocks and assigned-clock-
> > parents?
> > This would get handled by CCF directly, and then the only thing the
> > clk driver has to do is make sure it doesn't get reparented again.
> >
> > Or is there a need to do reparenting at runtime?
> >
>
> For the use case of APLL3/APLL4, static assignment should be ok.
>
> But I checked with CCF owner, we can't just use clk_set_rate(divider,
> rate) to get expected MCLK output, because reparenting MUX
> automatically is not supported now. (PLL -> MUX -> divider)
>
> We still have to call clk_set_parent() before clk_set_rate(). Which
> means some information should be got from DTS to check whether the PLL
> source can be switched or not, so *-mclk-source should be keeped to
> identify the case.

So for the clk stuff I already provided a proof of concept [1] offline.

I would like to see a device tree description that follows the design
of the hardware, such as only listing the clocks that actually do feed
into the audio subsystem, and not including all their parents (and
grand parents).

The driver should follow that description.


ChenYu

[1] https://crrev.com/c/3060172

> > > > > > A related question: the chip has five APLLs. How many MCLK
> > > > > > combinations
> > > > > > does the application need to support? I assume this includes
> > > > > > the
> > > > > > standard
> > > > > > 24.576 MHz and 22.5792 MHz clock rates.
> > > > > >
> > > > >
> > > > > APLL1 and APLL2 are used in most AFE modules, so their rate
> > > > > should
> > > > > be
> > > > > fixed.
> > > > > APLL1 is fixed to 196608000Hz.
> > > > > APLL2 is fixed to 180633600Hz.
> > > > > APLL is inputed to the divider(8bit), and MCLK is the output of
> > > > > divider.
> > > > > Other APLLs are reserved for some special usage which can't be
> > > > > supported by APLL1 & APLL2.
> > > > > But APLL3~APLL5 aren't used in the series, so I will remove
> > > > > them in
> > > > > v3.
> > > > >
> > > > > > > Some of them are not used in this series, because some
> > > > > > > modules
> > > > > > > are
> > > > > > > still developing. Should I only keep the clocks that have
> > > > > > > been
> > > > > > > used
> > > > > > > in
> > > > > > > the series?
> > > > > >
> > > > > > Yes please. Only add the ones that are used. Things that
> > > > > > aren't
> > > > > > used
> > > > > > don't get tested and verified, and end up as dead code. If
> > > > > > there
> > > > > > are
> > > > > > plans to extend them in the future, and you can leave
> > > > > > comments
> > > > > > stating
> > > > > > that intent, and also mention it in the cover letter.
> > > > > >
> > > > >
> > > > > OK, I will remove the unused clock in v3.
> > > > >
> > > > > > > > > +       /* xtal */
> > > > > > > > > +       [MT8195_CLK_XTAL_26M] = "clk26m",
> > > > > > > > > +       /* pll */
> > > > > > > > > +       [MT8195_CLK_APMIXED_APLL1] = "apll1",
> > > > > > > > > +       [MT8195_CLK_APMIXED_APLL2] = "apll2",
> > > > > > > > > +       [MT8195_CLK_APMIXED_APLL3] = "apll3",
> > > > > > > > > +       [MT8195_CLK_APMIXED_APLL4] = "apll4",
> > > > > > > > > +       [MT8195_CLK_APMIXED_APLL5] = "apll5",
> > > > > > > > > +       [MT8195_CLK_APMIXED_HDMIRX_APLL] =
> > > > > > > > > "hdmirx_apll",
> > > > > > > > > +       /* divider */
> > > > > > > > > +       [MT8195_CLK_TOP_APLL1] = "apll1_ck",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL1_D4] = "apll1_d4",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL2] = "apll2_ck",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL2_D4] = "apll2_d4",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL3] = "apll3_ck",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL3_D4] = "apll3_d4",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL4] = "apll4_ck",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL4_D4] = "apll4_d4",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL5] = "apll5_ck",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL5_D4] = "apll5_d4",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV0] = "apll12_div0",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV1] = "apll12_div1",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV2] = "apll12_div2",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV3] = "apll12_div3",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV4] = "apll12_div4",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL12_DIV9] = "apll12_div9",
> > > > > > > > > +       [MT8195_CLK_TOP_HDMIRX_APLL] =
> > > > > > > > > "hdmirx_apll_ck",
> > > > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D4_D4] =
> > > > > > > > > "mainpll_d4_d4",
> > > > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D5_D2] =
> > > > > > > > > "mainpll_d5_d2",
> > > > > > > > > +       [MT8195_CLK_TOP_MAINPLL_D7_D2] =
> > > > > > > > > "mainpll_d7_d2",
> > > > > > > > > +       [MT8195_CLK_TOP_UNIVPLL_D4] = "univpll_d4",
> > > > > > > > > +       /* mux */
> > > > > > > > > +       [MT8195_CLK_TOP_APLL1_SEL] = "apll1_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL2_SEL] = "apll2_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL3_SEL] = "apll3_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL4_SEL] = "apll4_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_APLL5_SEL] = "apll5_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_A1SYS_HP_SEL] = "a1sys_hp_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_A2SYS_SEL] = "a2sys_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_A3SYS_SEL] = "a3sys_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_A4SYS_SEL] = "a4sys_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_ASM_H_SEL] = "asm_h_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_ASM_M_SEL] = "asm_m_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_ASM_L_SEL] = "asm_l_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_AUD_IEC_SEL] = "aud_iec_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_AUD_INTBUS_SEL] =
> > > > > > > > > "aud_intbus_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_AUDIO_H_SEL] = "audio_h_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL] =
> > > > > > > > > "audio_local_bus_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_DPTX_M_SEL] = "dptx_m_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_INTDIR_SEL] = "intdir_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_I2SO1_M_SEL] = "i2so1_m_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_I2SO2_M_SEL] = "i2so2_m_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_I2SI1_M_SEL] = "i2si1_m_sel",
> > > > > > > > > +       [MT8195_CLK_TOP_I2SI2_M_SEL] = "i2si2_m_sel",
> > > > > > > > > +       /* clock gate */
> > > > > > > > > +       [MT8195_CLK_TOP_MPHONE_SLAVE_B] =
> > > > > > > > > "mphone_slave_b",
> > > > > > > > > +       [MT8195_CLK_TOP_CFG_26M_AUD] = "cfg_26m_aud",
> > > > > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO] = "infra_ao_audio",
> > > > > > > > > +       [MT8195_CLK_INFRA_AO_AUDIO_26M_B] =
> > > > > > > > > "infra_ao_audio_26m_b",
> > > > > > > > > +       [MT8195_CLK_SCP_ADSP_AUDIODSP] =
> > > > > > > > > "scp_adsp_audiodsp",
> > > > > > > >
> > > > > > > >
> > > > > > > > > +       [MT8195_CLK_AUD_AFE] = "aud_afe",
> > > > > > > > > +       [MT8195_CLK_AUD_LRCK_CNT] = "aud_lrck_cnt",
> > > > > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_APLL] =
> > > > > > > > > "aud_spdifin_tuner_apll",
> > > > > > > > > +       [MT8195_CLK_AUD_SPDIFIN_TUNER_DBG] =
> > > > > > > > > "aud_spdifin_tuner_dbg",
> > > > > > > > > +       [MT8195_CLK_AUD_UL_TML] = "aud_ul_tml",
> > > > > > > > > +       [MT8195_CLK_AUD_APLL1_TUNER] =
> > > > > > > > > "aud_apll1_tuner",
> > > > > > > > > +       [MT8195_CLK_AUD_APLL2_TUNER] =
> > > > > > > > > "aud_apll2_tuner",
> > > > > > > > > +       [MT8195_CLK_AUD_TOP0_SPDF] = "aud_top0_spdf",
> > > > > > > > > +       [MT8195_CLK_AUD_APLL] = "aud_apll",
> > > > > > > > > +       [MT8195_CLK_AUD_APLL2] = "aud_apll2",
> > > > > > > > > +       [MT8195_CLK_AUD_DAC] = "aud_dac",
> > > > > > > > > +       [MT8195_CLK_AUD_DAC_PREDIS] = "aud_dac_predis",
> > > > > > > > > +       [MT8195_CLK_AUD_TML] = "aud_tml",
> > > > > > > > > +       [MT8195_CLK_AUD_ADC] = "aud_adc",
> > > > > > > > > +       [MT8195_CLK_AUD_DAC_HIRES] = "aud_dac_hires",
> > > > > > > > > +       [MT8195_CLK_AUD_A1SYS_HP] = "aud_a1sys_hp",
> > > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC1] = "aud_afe_dmic1",
> > > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC2] = "aud_afe_dmic2",
> > > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC3] = "aud_afe_dmic3",
> > > > > > > > > +       [MT8195_CLK_AUD_AFE_DMIC4] = "aud_afe_dmic4",
> > > > > > > > > +       [MT8195_CLK_AUD_AFE_26M_DMIC_TM] =
> > > > > > > > > "aud_afe_26m_dmic_tm",
> > > > > > > > > +       [MT8195_CLK_AUD_UL_TML_HIRES] =
> > > > > > > > > "aud_ul_tml_hires",
> > > > > > > > > +       [MT8195_CLK_AUD_ADC_HIRES] = "aud_adc_hires",
> > > > > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC] = "aud_adda6_adc",
> > > > > > > > > +       [MT8195_CLK_AUD_ADDA6_ADC_HIRES] =
> > > > > > > > > "aud_adda6_adc_hires",
> > > > > > > > > +       [MT8195_CLK_AUD_LINEIN_TUNER] =
> > > > > > > > > "aud_linein_tuner",
> > > > > > > > > +       [MT8195_CLK_AUD_EARC_TUNER] = "aud_earc_tuner",
> > > > > > > > > +       [MT8195_CLK_AUD_I2SIN] = "aud_i2sin",
> > > > > > > > > +       [MT8195_CLK_AUD_TDM_IN] = "aud_tdm_in",
> > > > > > > > > +       [MT8195_CLK_AUD_I2S_OUT] = "aud_i2s_out",
> > > > > > > > > +       [MT8195_CLK_AUD_TDM_OUT] = "aud_tdm_out",
> > > > > > > > > +       [MT8195_CLK_AUD_HDMI_OUT] = "aud_hdmi_out",
> > > > > > > > > +       [MT8195_CLK_AUD_ASRC11] = "aud_asrc11",
> > > > > > > > > +       [MT8195_CLK_AUD_ASRC12] = "aud_asrc12",
> > > > > > > > > +       [MT8195_CLK_AUD_MULTI_IN] = "aud_multi_in",
> > > > > > > > > +       [MT8195_CLK_AUD_INTDIR] = "aud_intdir",
> > > > > > > > > +       [MT8195_CLK_AUD_A1SYS] = "aud_a1sys",
> > > > > > > > > +       [MT8195_CLK_AUD_A2SYS] = "aud_a2sys",
> > > > > > > > > +       [MT8195_CLK_AUD_PCMIF] = "aud_pcmif",
> > > > > > > > > +       [MT8195_CLK_AUD_A3SYS] = "aud_a3sys",
> > > > > > > > > +       [MT8195_CLK_AUD_A4SYS] = "aud_a4sys",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL1] = "aud_memif_ul1",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL2] = "aud_memif_ul2",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL3] = "aud_memif_ul3",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL4] = "aud_memif_ul4",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL5] = "aud_memif_ul5",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL6] = "aud_memif_ul6",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL8] = "aud_memif_ul8",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL9] = "aud_memif_ul9",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_UL10] = "aud_memif_ul10",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL2] = "aud_memif_dl2",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL3] = "aud_memif_dl3",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL6] = "aud_memif_dl6",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL7] = "aud_memif_dl7",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL8] = "aud_memif_dl8",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL10] = "aud_memif_dl10",
> > > > > > > > > +       [MT8195_CLK_AUD_MEMIF_DL11] = "aud_memif_dl11",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC0] = "aud_gasrc0",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC1] = "aud_gasrc1",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC2] = "aud_gasrc2",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC3] = "aud_gasrc3",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC4] = "aud_gasrc4",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC5] = "aud_gasrc5",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC6] = "aud_gasrc6",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC7] = "aud_gasrc7",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC8] = "aud_gasrc8",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC9] = "aud_gasrc9",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC10] = "aud_gasrc10",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC11] = "aud_gasrc11",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC12] = "aud_gasrc12",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC13] = "aud_gasrc13",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC14] = "aud_gasrc14",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC15] = "aud_gasrc15",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC16] = "aud_gasrc16",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC17] = "aud_gasrc17",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC18] = "aud_gasrc18",
> > > > > > > > > +       [MT8195_CLK_AUD_GASRC19] = "aud_gasrc19",
> > > > > > > >
> > > > > > > > The MT8195_CLK_AUD_* clocks are all internal to the audio
> > > > > > > > subsystem:
> > > > > > > > the bits that control these clock gates are in the same
> > > > > > > > address
> > > > > > > > space
> > > > > > > > as the audio parts. Would it be possible to model them as
> > > > > > > > internal
> > > > > > > > ASoC SUPPLY widgets? The external ones could be modeled
> > > > > > > > using
> > > > > > > > ASoC
> > > > > > > > CLK_SUPPLY widgets, and the dependencies could be modeled
> > > > > > > > with
> > > > > > > > ASoC
> > > > > > > > routes. The ASoC core could then handle power sequencing,
> > > > > > > > which
> > > > > > > > the
> > > > > > > > driver currently does manually.
> > > > > > > >
> > > > > > > > IMO this is better than having two drivers handling two
> > > > > > > > aspects
> > > > > > > > of
> > > > > > > > the same piece of hardware, while the two aspects are
> > > > > > > > intertwined.
> > > > > > > >
> > > > > > >
> > > > > > > Yes, it's ok to use the CLK_SUPPLY and SUPPLY to model such
> > > > > > > clocks.
> > > > > > > But those clocks are managed by CCF in the preceding SOCs
> > > > > > > like
> > > > > > > mt2701,
> > > > > > > mt6779 and mt8183. Additionally, in some audio modules,
> > > > > > > clocks
> > > > > > > should
> > > > > >
> > > > > > This being a new driver, we have some more freedom to improve
> > > > > > the
> > > > > > design.
> > > > > >
> > > > > > > be enabled before configuring parameters(hw_params). As far
> > > > > > > as
> > > > > > > I
> > > > > > > know,
> > > > > > > if we use CLK_SUPPLY or SUPPLY to model clocks, the power
> > > > > > > sequence
> > > > > > > is
> > > > > > > controlled by DAPM. It seems to be impossible to fulfill
> > > > > > > all
> > > > > > > use
> > > > > > > cases.
> > > > > > > That's why we just keep the manual control sequence and CCF
> > > > > > > seems
> > > > > > > to be
> > > > > > > the best choice to model such clock gatess.
> > > > > >
> > > > > > I see. So yes, using CCF does give you reference counting,
> > > > > > dependency
> > > > > > tracking and other advantages. And using DAPM supplies means
> > > > > > you
> > > > > > can't
> > > > > > enable the clock gates outside of DAPM without both pieces of
> > > > > > code
> > > > > > fighting for control.
> > > > > >
> > > > > > Can we at least move the audio clock gates into the audio
> > > > > > driver
> > > > > > though?
> > > > > > The arbitrary separation into two devices and drivers is
> > > > > > fishy.
> > > > > > And
> > > > > > with
> > > > > > the move the external references to the audio clock gates can
> > > > > > be
> > > > > > removed.
> > > > > >
> > > > >
> > > > > Because DAPM SUPPLY can't fit our control scenario.
> > > > > Did you suggest us implement the simple logic control(including
> > > > > ref
> > > > > count, clock dependency) for clock gate(MT8195_CLK_AUD_*) in
> > > > > afe
> > > > > driver
> > > > > instead of using CCF?
> > > >
> > > > I meant simply moving the CCF-based clk driver code (clk-mt8516-
> > > > aud.c)
> > > > from `drivers/clk` and incorporating it into the audio driver,
> > > > likely
> > > > in `mt8195-afe-clk.c` or maybe as a separate file. So the audio
> > > > driver
> > > > would be a clock provider, and a clock consumer. It will directly
> > > > use
> > > > the clocks it provides, internally, and you could remove all
> > > > those
> > > > clock references from the device tree.
> > > >
> > > > The goal is to have one hardware representation (device node)
> > > > only,
> > > > so
> > > > that it matches the hardware, which is one single unified block.
> > > >
> > > > After the driver is completed, we can look for opportunities to
> > > > improve
> > > > it, if resources are available.
> > >
> > > Thanks for your detailed information.
> > > I will try to move the CCF-based clk driver code to AFE driver.
> > > If there are no other internal concerns and blocking problems, I
> > > will
> > > include the changes in v3.
> >
> > Great.
> >
> > > > > > And regarding the clock requirements for different modules,
> > > > > > could
> > > > > > we
> > > > > > have
> > > > > > that information put in comments somewhere, so if someone
> > > > > > were to
> > > > > > revisit
> > > > > > it later, they would have the information needed to
> > > > > > understand
> > > > > > and
> > > > > > possibly
> > > > > > improve it? Because right now there's just a bunch of clocks
> > > > > > enabled
> > > > > > and
> > > > > > disabled and nothing to explain why that's needed.
> > > > > >
> > > > >
> > > > > For example,
> > > > > MT8195_CLK_AUD_ADC(clock gate) is one of the clock feeding to
> > > > > ADDA
> > > > > module.
> > > > > Did you want me show the clock gate list feeding to ADDA?
> > > > > On the other hand, I didn't know how to show the information
> > > > > properly
> > > > > in comments. Could you kindly share me an example for
> > > > > reference?
> > > >
> > > >
> > > > For example, in `mt8195_afe_enable_reg_rw_clk()` in mt8195-afe-
> > > > clk.c:
> > > >
> > > >         unsigned int clk_array[] = {
> > > >                 MT8195_CLK_SCP_ADSP_AUDIODSP,
> > > >                 MT8195_CLK_TOP_AUDIO_LOCAL_BUS_SEL,
> > > >                 MT8195_CLK_TOP_CFG_26M_AUD,
> > > >                 MT8195_CLK_INFRA_AO_AUDIO,
> > > >                 MT8195_CLK_INFRA_AO_AUDIO_26M_B,
> > > >                 MT8195_CLK_TOP_AUD_INTBUS_SEL,
> > > >                 MT8195_CLK_TOP_A1SYS_HP_SEL,
> > > >                 MT8195_CLK_AUD_A1SYS_HP,
> > > >                 MT8195_CLK_AUD_A1SYS,
> > > >                 MT8195_CLK_TOP_AUDIO_H_SEL,
> > > >         };
> > > >
> > > > You could add a comment after each line stating why that clock
> > > > needs
> > > > to
> > > > be enabled. A simple note like "bus access clock" or "internal
> > > > logic
> > > > clock"
> > > > would suffice.
> > > >
> > >
> > > OK, I will add short notes to such clock lists.
> > >
> > > > The above list also has some redundancies that could be
> > > > eliminated.
> > > > MT8195_CLK_TOP_A1SYS_HP_SEL is parent to both
> > > > MT8195_CLK_AUD_A1SYS_HP
> > > > and
> > > > MT8195_CLK_AUD_A1SYS. When clocks are enabled, their parents are
> > > > also
> > > > enabled by CCF, so there's no need to enable them explicitly,
> > > > unless
> > > > that clock also directly feeds the clock consumer.
> > > >
> > >
> > > OK, I will review all clock usages and remove the unnecessary
> > > clocks.
> > >
> > > >
> > > > Another thing I wanted to bring up: is any of the code after
> > > >
> > > >     struct mt8195_afe_tuner_cfg {
> > > >
> > > > used? It looks like it is used to configure the five extra PLLs
> > > > in
> > > > the audio
> > > > subsystem, but the exposed (non-static) functions don't seem to
> > > > be
> > > > called
> > > > anywhere. Are they for modules not yet supported?
> > > >
> > >
> > > Yes, tuners are not supported now.
> > > I will remove the code and add them back when tuners are required
> > > in
> > > the future.
> >
> > Thanks.
> >
> >
> > ChenYu

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2021-08-02 10:23 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-29  1:47 [PATCH v2 0/8] ASoC: mediatek: Add support for MT8195 SoC Trevor Wu
2021-06-29  1:47 ` [PATCH v2 1/8] ASoC: mediatek: mt8195: update mediatek common driver Trevor Wu
2021-06-29  1:47 ` [PATCH v2 3/8] ASoC: mediatek: mt8195: support adda in platform driver Trevor Wu
2021-06-29  1:47 ` [PATCH v2 4/8] ASoC: mediatek: mt8195: support pcm " Trevor Wu
2021-06-29  1:47 ` [PATCH v2 6/8] dt-bindings: mediatek: mt8195: add audio afe document Trevor Wu
2021-07-01 20:18   ` Rob Herring
2021-07-05  7:01     ` Trevor Wu
2021-06-29  1:47 ` [PATCH v2 7/8] ASoC: mediatek: mt8195: add machine driver with mt6359, rt1019 and rt5682 Trevor Wu
2021-06-29  1:47 ` [PATCH v2 8/8] dt-bindings: mediatek: mt8195: add mt8195-mt6359-rt1019-rt5682 document Trevor Wu
     [not found] ` <20210629014736.31153-6-trevor.wu@mediatek.com>
2021-07-12  6:57   ` [PATCH v2 5/8] ASoC: mediatek: mt8195: add platform driver Chen-Yu Tsai
2021-07-12 15:09     ` Trevor Wu
2021-07-13  6:00       ` Chen-Yu Tsai
2021-07-15 11:05         ` Trevor Wu
2021-07-19 10:05           ` Chen-Yu Tsai
2021-07-22  8:56             ` Trevor Wu
2021-07-23  6:27               ` Chen-Yu Tsai
2021-07-26 14:31                 ` Trevor Wu
2021-08-02 10:21                   ` Chen-Yu Tsai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).