Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] iommu/arm-smmu-v3: Retire disable_bypass parameter
From: Mostafa Saleh @ 2024-04-09 10:19 UTC (permalink / raw)
  To: Robin Murphy; +Cc: will, joro, iommu, linux-arm-kernel
In-Reply-To: <ea3ac4cd595a81b5511729601b2f7d4668178438.1712335927.git.robin.murphy@arm.com>

Hi Robin,

On Fri, Apr 05, 2024 at 05:52:07PM +0100, Robin Murphy wrote:
> The disable_bypass parameter has been mostly meaningless for a long time
> since the introduction of default domains. Its original intent is now
> fulfilled by the controls users have over the default domain type, and
> its remaining effect in the brief window between Stream Table
> initialisation and default domain creation hardly seems worth the
> complication. Furthermore, thanks to 2-level Stream Tables, disabling
> disable_bypass (there's another reason not to like it right there) has
> never guaranteed that any particular StreamID *will* bypass anyway - any
> device which might actually care about that wants RMRs - so there's not
> really much lost by taking away that option (which has already been
> non-default for nearing 6 years now).
> 
> As part of this, also remove the weird behaviour where we "successfully"
> probe and register a non-functional SMMU if the DT "#iommu-cells"
> property is wrong. I have no memory of what possessed me to think that
> was a good idea at the time, and by now I suspect it's likely to break
> things worse than simply failing probe would.
> 
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

Reviewed-by: Mostafa Saleh <smostafa@google.com>

> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 46 ++++++---------------
>  1 file changed, 13 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 41f93c3ab160..4eb74f0ad13b 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -30,11 +30,6 @@
>  #include "arm-smmu-v3.h"
>  #include "../../dma-iommu.h"
>  
> -static bool disable_bypass = true;
> -module_param(disable_bypass, bool, 0444);
> -MODULE_PARM_DESC(disable_bypass,
> -	"Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU.");
> -
>  static bool disable_msipolling;
>  module_param(disable_msipolling, bool, 0444);
>  MODULE_PARM_DESC(disable_msipolling,
> @@ -1567,17 +1562,13 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
>   * This can safely directly manipulate the STE memory without a sync sequence
>   * because the STE table has not been installed in the SMMU yet.
>   */
> -static void arm_smmu_init_initial_stes(struct arm_smmu_device *smmu,
> -				       struct arm_smmu_ste *strtab,
> +static void arm_smmu_init_initial_stes(struct arm_smmu_ste *strtab,
>  				       unsigned int nent)
>  {
>  	unsigned int i;
>  
>  	for (i = 0; i < nent; ++i) {
> -		if (disable_bypass)
> -			arm_smmu_make_abort_ste(strtab);
> -		else
> -			arm_smmu_make_bypass_ste(smmu, strtab);
> +		arm_smmu_make_abort_ste(strtab);
>  		strtab++;
>  	}
>  }
> @@ -1605,7 +1596,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
>  		return -ENOMEM;
>  	}
>  
> -	arm_smmu_init_initial_stes(smmu, desc->l2ptr, 1 << STRTAB_SPLIT);
> +	arm_smmu_init_initial_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
>  	arm_smmu_write_strtab_l1_desc(strtab, desc);
>  	return 0;
>  }
> @@ -2915,10 +2906,10 @@ static void arm_smmu_release_device(struct device *dev)
>  		iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
>  
>  	/* Put the STE back to what arm_smmu_init_strtab() sets */
> -	if (disable_bypass && !dev->iommu->require_direct)
> -		arm_smmu_attach_dev_blocked(&arm_smmu_blocked_domain, dev);
> -	else
> +	if (dev->iommu->require_direct)
>  		arm_smmu_attach_dev_identity(&arm_smmu_identity_domain, dev);
> +	else
> +		arm_smmu_attach_dev_blocked(&arm_smmu_blocked_domain, dev);
>  
>  	arm_smmu_disable_pasid(master);
>  	arm_smmu_remove_master(master);
> @@ -3273,7 +3264,7 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
>  	reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits);
>  	cfg->strtab_base_cfg = reg;
>  
> -	arm_smmu_init_initial_stes(smmu, strtab, cfg->num_l1_ents);
> +	arm_smmu_init_initial_stes(strtab, cfg->num_l1_ents);
>  	return 0;
>  }
>  
> @@ -3503,7 +3494,7 @@ static int arm_smmu_device_disable(struct arm_smmu_device *smmu)
>  	return ret;
>  }
>  
> -static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
> +static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
>  {
>  	int ret;
>  	u32 reg, enables;
> @@ -3513,7 +3504,6 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
>  	reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
>  	if (reg & CR0_SMMUEN) {
>  		dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
> -		WARN_ON(is_kdump_kernel() && !disable_bypass);
>  		arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
>  	}
>  
> @@ -3620,14 +3610,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
>  	if (is_kdump_kernel())
>  		enables &= ~(CR0_EVTQEN | CR0_PRIQEN);
>  
> -	/* Enable the SMMU interface, or ensure bypass */
> -	if (!bypass || disable_bypass) {
> -		enables |= CR0_SMMUEN;
> -	} else {
> -		ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
> -		if (ret)
> -			return ret;
> -	}
> +	/* Enable the SMMU interface */
> +	enables |= CR0_SMMUEN;
>  	ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
>  				      ARM_SMMU_CR0ACK);
>  	if (ret) {
> @@ -4019,7 +4003,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>  	resource_size_t ioaddr;
>  	struct arm_smmu_device *smmu;
>  	struct device *dev = &pdev->dev;
> -	bool bypass;
>  
>  	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
>  	if (!smmu)
> @@ -4030,12 +4013,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>  		ret = arm_smmu_device_dt_probe(pdev, smmu);
>  	} else {
>  		ret = arm_smmu_device_acpi_probe(pdev, smmu);
> -		if (ret == -ENODEV)
> -			return ret;
>  	}
> -
> -	/* Set bypass mode according to firmware probing result */
> -	bypass = !!ret;
> +	if (ret)
> +		return ret;
>  
>  	/* Base address */
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -4099,7 +4079,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>  	arm_smmu_rmr_install_bypass_ste(smmu);
>  
>  	/* Reset the device */
> -	ret = arm_smmu_device_reset(smmu, bypass);
> +	ret = arm_smmu_device_reset(smmu);
>  	if (ret)
>  		return ret;
>  
> -- 
> 2.39.2.101.g768bb238c484.dirty
> 
Thanks,
Mostafa

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

^ permalink raw reply

* [PATCH v2 14/18] ASoC: mediatek: Add MT8365 support
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

- Add specific config to enable:
  - MT8365 sound support
  - MT6357 audio codec support
- Add the mt8365 directory and all drivers under it.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/Kconfig         | 20 ++++++++++++++++++++
 sound/soc/mediatek/Makefile        |  1 +
 sound/soc/mediatek/mt8365/Makefile | 15 +++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 5a8476e1ecca..c1c86ecc0601 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -298,3 +298,23 @@ config SND_SOC_MT8195_MT6359
 	  boards with the MT6359 and other I2S audio codecs.
 	  Select Y if you have such device.
 	  If unsure select "N".
+
+config SND_SOC_MT8365
+	tristate "ASoC support for Mediatek MT8365 chip"
+	depends on ARCH_MEDIATEK
+	select SND_SOC_MEDIATEK
+	help
+	  This adds ASoC platform driver support for Mediatek MT8365 chip
+	  that can be used with other codecs.
+	  Select Y if you have such device.
+	  If unsure select "N".
+
+config SND_SOC_MT8365_MT6357
+	tristate "ASoC Audio driver for MT8365 with MT6357 codec"
+	depends on SND_SOC_MT8365 && MTK_PMIC_WRAP
+	select SND_SOC_MT6357
+	help
+	  This adds support for ASoC machine driver for Mediatek MT8365
+	  boards with the MT6357 codec.
+	  Select Y if you have such device.
+	  If unsure select "N".
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
index 3938e7f75c2e..4b55434f2168 100644
--- a/sound/soc/mediatek/Makefile
+++ b/sound/soc/mediatek/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_SND_SOC_MT8186) += mt8186/
 obj-$(CONFIG_SND_SOC_MT8188) += mt8188/
 obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
 obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
+obj-$(CONFIG_SND_SOC_MT8365) += mt8365/
diff --git a/sound/soc/mediatek/mt8365/Makefile b/sound/soc/mediatek/mt8365/Makefile
new file mode 100644
index 000000000000..52ba45a8498a
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/Makefile
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# MTK Platform driver
+snd-soc-mt8365-pcm-objs := \
+	mt8365-afe-clk.o \
+	mt8365-afe-pcm.o \
+	mt8365-dai-adda.o \
+	mt8365-dai-dmic.o \
+	mt8365-dai-i2s.o \
+	mt8365-dai-pcm.o
+
+obj-$(CONFIG_SND_SOC_MT8365) += snd-soc-mt8365-pcm.o
+
+# Machine driver
+obj-$(CONFIG_SND_SOC_MT8365_MT6357) += mt8365-mt6357.o

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 18/18] arm64: dts: mediatek: add audio support for mt8365-evk
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add the sound node which is linked to the MT8365 SoC AFE and
the MT6357 audio codec.

Update the file header.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 arch/arm64/boot/dts/mediatek/mt8365-evk.dts | 98 +++++++++++++++++++++++++++--
 1 file changed, 94 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
index 50cbaefa1a99..bf15d3c7a965 100644
--- a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts
@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2021-2022 BayLibre, SAS.
- * Authors:
- * Fabien Parent <fparent@baylibre.com>
- * Bernhard Rosenkränzer <bero@baylibre.com>
+ * Copyright (c) 2024 BayLibre, SAS.
+ * Authors: Fabien Parent <fparent@baylibre.com>
+ *	    Bernhard Rosenkränzer <bero@baylibre.com>
+ *	    Alexandre Mergnat <amergnat@baylibre.com>
  */
 
 /dts-v1/;
@@ -86,6 +86,29 @@ optee_reserved: optee@43200000 {
 			reg = <0 0x43200000 0 0x00c00000>;
 		};
 	};
+
+	sound: sound {
+		compatible = "mediatek,mt8365-mt6357";
+		pinctrl-names = "default",
+				"dmic",
+				"miso_off",
+				"miso_on",
+				"mosi_off",
+				"mosi_on";
+		pinctrl-0 = <&aud_default_pins>;
+		pinctrl-1 = <&aud_dmic_pins>;
+		pinctrl-2 = <&aud_miso_off_pins>;
+		pinctrl-3 = <&aud_miso_on_pins>;
+		pinctrl-4 = <&aud_mosi_off_pins>;
+		pinctrl-5 = <&aud_mosi_on_pins>;
+		mediatek,platform = <&afe>;
+		status = "okay";
+	};
+};
+
+&afe {
+	mediatek,dmic-mode = <1>;
+	status = "okay";
 };
 
 &cpu0 {
@@ -174,6 +197,12 @@ &mmc1 {
 	status = "okay";
 };
 
+&mt6357_codec {
+	vaud28-supply = <&mt6357_vaud28_reg>;
+	mediatek,micbias0-microvolt = <1900000>;
+	mediatek,micbias1-microvolt = <1700000>;
+};
+
 &mt6357_pmic {
 	interrupts-extended = <&pio 145 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-controller;
@@ -181,6 +210,67 @@ &mt6357_pmic {
 };
 
 &pio {
+	aud_default_pins: audiodefault-pins {
+		pins {
+		pinmux = <MT8365_PIN_72_CMDAT4__FUNC_I2S3_BCK>,
+			 <MT8365_PIN_73_CMDAT5__FUNC_I2S3_LRCK>,
+			 <MT8365_PIN_74_CMDAT6__FUNC_I2S3_MCK>,
+			 <MT8365_PIN_75_CMDAT7__FUNC_I2S3_DO>;
+		};
+	};
+
+	aud_dmic_pins: audiodmic-pins {
+		pins {
+		pinmux = <MT8365_PIN_117_DMIC0_CLK__FUNC_DMIC0_CLK>,
+			 <MT8365_PIN_118_DMIC0_DAT0__FUNC_DMIC0_DAT0>,
+			 <MT8365_PIN_119_DMIC0_DAT1__FUNC_DMIC0_DAT1>;
+		};
+	};
+
+	aud_miso_off_pins: misooff-pins {
+		pins {
+		pinmux = <MT8365_PIN_53_AUD_CLK_MISO__FUNC_GPIO53>,
+			 <MT8365_PIN_54_AUD_SYNC_MISO__FUNC_GPIO54>,
+			 <MT8365_PIN_55_AUD_DAT_MISO0__FUNC_GPIO55>,
+			 <MT8365_PIN_56_AUD_DAT_MISO1__FUNC_GPIO56>;
+		input-enable;
+		bias-pull-down;
+		drive-strength = <MTK_DRIVE_2mA>;
+		};
+	};
+
+	aud_miso_on_pins: misoon-pins {
+		pins {
+		pinmux = <MT8365_PIN_53_AUD_CLK_MISO__FUNC_AUD_CLK_MISO>,
+			 <MT8365_PIN_54_AUD_SYNC_MISO__FUNC_AUD_SYNC_MISO>,
+			 <MT8365_PIN_55_AUD_DAT_MISO0__FUNC_AUD_DAT_MISO0>,
+			 <MT8365_PIN_56_AUD_DAT_MISO1__FUNC_AUD_DAT_MISO1>;
+		drive-strength = <MTK_DRIVE_6mA>;
+		};
+	};
+
+	aud_mosi_off_pins: mosioff-pins {
+		pins {
+		pinmux = <MT8365_PIN_49_AUD_CLK_MOSI__FUNC_GPIO49>,
+			 <MT8365_PIN_50_AUD_SYNC_MOSI__FUNC_GPIO50>,
+			 <MT8365_PIN_51_AUD_DAT_MOSI0__FUNC_GPIO51>,
+			 <MT8365_PIN_52_AUD_DAT_MOSI1__FUNC_GPIO52>;
+		input-enable;
+		bias-pull-down;
+		drive-strength = <MTK_DRIVE_2mA>;
+		};
+	};
+
+	aud_mosi_on_pins: mosion-pins {
+		pins {
+		pinmux = <MT8365_PIN_49_AUD_CLK_MOSI__FUNC_AUD_CLK_MOSI>,
+			 <MT8365_PIN_50_AUD_SYNC_MOSI__FUNC_AUD_SYNC_MOSI>,
+			 <MT8365_PIN_51_AUD_DAT_MOSI0__FUNC_AUD_DAT_MOSI0>,
+			 <MT8365_PIN_52_AUD_DAT_MOSI1__FUNC_AUD_DAT_MOSI1>;
+		drive-strength = <MTK_DRIVE_6mA>;
+		};
+	};
+
 	ethernet_pins: ethernet-pins {
 		phy_reset_pins {
 			pinmux = <MT8365_PIN_133_TDM_TX_DATA1__FUNC_GPIO133>;

-- 
2.25.1


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

^ permalink raw reply related

* Re: [PATCH v2 0/4] Speed up boot with faster linear map creation
From: Itaru Kitayama @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Ryan Roberts
  Cc: Catalin Marinas, Will Deacon, Mark Rutland, Ard Biesheuvel,
	David Hildenbrand, Donald Dutile, Eric Chanudet, Linux ARM,
	linux-kernel@vger.kernel.org
In-Reply-To: <1d5abb48-08a8-4d83-a681-6915bc7b6907@arm.com>



> On Apr 9, 2024, at 19:04, Ryan Roberts <ryan.roberts@arm.com> wrote:
> 
> On 09/04/2024 01:10, Itaru Kitayama wrote:
>> Hi Ryan,
>> 
>>> On Apr 8, 2024, at 16:30, Ryan Roberts <ryan.roberts@arm.com> wrote:
>>> 
>>> On 06/04/2024 11:31, Itaru Kitayama wrote:
>>>> Hi Ryan,
>>>> 
>>>> On Sat, Apr 06, 2024 at 09:32:34AM +0100, Ryan Roberts wrote:
>>>>> Hi Itaru,
>>>>> 
>>>>> On 05/04/2024 08:39, Itaru Kitayama wrote:
>>>>>> On Thu, Apr 04, 2024 at 03:33:04PM +0100, Ryan Roberts wrote:
>>>>>>> Hi All,
>>>>>>> 
>>>>>>> It turns out that creating the linear map can take a significant proportion of
>>>>>>> the total boot time, especially when rodata=full. And most of the time is spent
>>>>>>> waiting on superfluous tlb invalidation and memory barriers. This series reworks
>>>>>>> the kernel pgtable generation code to significantly reduce the number of those
>>>>>>> TLBIs, ISBs and DSBs. See each patch for details.
>>>>>>> 
>>>>>>> The below shows the execution time of map_mem() across a couple of different
>>>>>>> systems with different RAM configurations. We measure after applying each patch
>>>>>>> and show the improvement relative to base (v6.9-rc2):
>>>>>>> 
>>>>>>>                | Apple M2 VM | Ampere Altra| Ampere Altra| Ampere Altra
>>>>>>>                | VM, 16G     | VM, 64G     | VM, 256G    | Metal, 512G
>>>>>>> ---------------|-------------|-------------|-------------|-------------
>>>>>>>                |   ms    (%) |   ms    (%) |   ms    (%) |    ms    (%)
>>>>>>> ---------------|-------------|-------------|-------------|-------------
>>>>>>> base           |  153   (0%) | 2227   (0%) | 8798   (0%) | 17442   (0%)
>>>>>>> no-cont-remap  |   77 (-49%) |  431 (-81%) | 1727 (-80%) |  3796 (-78%)
>>>>>>> batch-barriers |   13 (-92%) |  162 (-93%) |  655 (-93%) |  1656 (-91%)
>>>>>>> no-alloc-remap |   11 (-93%) |  109 (-95%) |  449 (-95%) |  1257 (-93%)
>>>>>>> lazy-unmap     |    6 (-96%) |   61 (-97%) |  257 (-97%) |   838 (-95%)
>>>>>>> 
>>>>>>> This series applies on top of v6.9-rc2. All mm selftests pass. I've compile and
>>>>>>> boot tested various PAGE_SIZE and VA size configs.
>>>>>>> 
>>>>>>> ---
>>>>>>> 
>>>>>>> Changes since v1 [1]
>>>>>>> ====================
>>>>>>> 
>>>>>>>   - Added Tested-by tags (thanks to Eric and Itaru)
>>>>>>>   - Renamed ___set_pte() -> __set_pte_nosync() (per Ard)
>>>>>>>   - Reordered patches (biggest impact & least controversial first)
>>>>>>>   - Reordered alloc/map/unmap functions in mmu.c to aid reader
>>>>>>>   - pte_clear() -> __pte_clear() in clear_fixmap_nosync()
>>>>>>>   - Reverted generic p4d_index() which caused x86 build error. Replaced with
>>>>>>>     unconditional p4d_index() define under arm64.
>>>>>>> 
>>>>>>> 
>>>>>>> [1] https://lore.kernel.org/linux-arm-kernel/20240326101448.3453626-1-ryan.roberts@arm.com/<https://lore.kernel.org/linux-arm-kernel/20240326101448.3453626-1-ryan.roberts@arm.com/>
>>>>>>> 
>>>>>>> Thanks,
>>>>>>> Ryan
>>>>>>> 
>>>>>>> 
>>>>>>> Ryan Roberts (4):
>>>>>>>   arm64: mm: Don't remap pgtables per-cont(pte|pmd) block
>>>>>>>   arm64: mm: Batch dsb and isb when populating pgtables
>>>>>>>   arm64: mm: Don't remap pgtables for allocate vs populate
>>>>>>>   arm64: mm: Lazily clear pte table mappings from fixmap
>>>>>>> 
>>>>>>> arch/arm64/include/asm/fixmap.h  |   5 +-
>>>>>>> arch/arm64/include/asm/mmu.h     |   8 +
>>>>>>> arch/arm64/include/asm/pgtable.h |  13 +-
>>>>>>> arch/arm64/kernel/cpufeature.c   |  10 +-
>>>>>>> arch/arm64/mm/fixmap.c           |  11 +
>>>>>>> arch/arm64/mm/mmu.c              | 377 +++++++++++++++++++++++--------
>>>>>>> 6 files changed, 319 insertions(+), 105 deletions(-)
>>>>>>> 
>>>>>>> --
>>>>>>> 2.25.1
>>>>>>> 
>>>>>> 
>>>>>> I've build and boot tested the v2 on FVP, base is taken from your
>>>>>> linux-rr repo. Running run_vmtests.sh on v2 left some gup longterm not oks, would you take a look at it? The mm ksefltests used is from your linux-rr repo too.
>>>>> 
>>>>> Thanks for taking a look at this.
>>>>> 
>>>>> I can't reproduce your issue unfortunately; steps as follows on Apple M2 VM:
>>>>> 
>>>>> Config: arm64 defconfig + the following:
>>>>> 
>>>>> # Squashfs for snaps, xfs for large file folios.
>>>>> ./scripts/config --enable CONFIG_SQUASHFS_LZ4
>>>>> ./scripts/config --enable CONFIG_SQUASHFS_LZO
>>>>> ./scripts/config --enable CONFIG_SQUASHFS_XZ
>>>>> ./scripts/config --enable CONFIG_SQUASHFS_ZSTD
>>>>> ./scripts/config --enable CONFIG_XFS_FS
>>>>> 
>>>>> # For general mm debug.
>>>>> ./scripts/config --enable CONFIG_DEBUG_VM
>>>>> ./scripts/config --enable CONFIG_DEBUG_VM_MAPLE_TREE
>>>>> ./scripts/config --enable CONFIG_DEBUG_VM_RB
>>>>> ./scripts/config --enable CONFIG_DEBUG_VM_PGFLAGS
>>>>> ./scripts/config --enable CONFIG_DEBUG_VM_PGTABLE
>>>>> ./scripts/config --enable CONFIG_PAGE_TABLE_CHECK
>>>>> 
>>>>> # For mm selftests.
>>>>> ./scripts/config --enable CONFIG_USERFAULTFD
>>>>> ./scripts/config --enable CONFIG_TEST_VMALLOC
>>>>> ./scripts/config --enable CONFIG_GUP_TEST
>>>>> 
>>>>> Running on VM with 12G memory, split across 2 (emulated) NUMA nodes (needed by
>>>>> some mm selftests), with kernel command line to reserve hugetlbs and other
>>>>> features required by some mm selftests:
>>>>> 
>>>>> "
>>>>> transparent_hugepage=madvise earlycon root=/dev/vda2 secretmem.enable
>>>>> hugepagesz=1G hugepages=0:2,1:2 hugepagesz=32M hugepages=0:2,1:2
>>>>> default_hugepagesz=2M hugepages=0:64,1:64 hugepagesz=64K hugepages=0:2,1:2
>>>>> "
>>>>> 
>>>>> Ubuntu userspace running off XFS rootfs. Build and run mm selftests from same
>>>>> git tree.
>>>>> 
>>>>> 
>>>>> Although I don't think any of this config should make a difference to gup_longterm.
>>>>> 
>>>>> Looks like your errors are all "ftruncate() failed". I've seen this problem on
>>>>> our CI system. There it is due to running the tests from NFS file system. What
>>>>> filesystem are you using? Perhaps you are sharing into the FVP using 9p? That
>>>>> might also be problematic.
>>>> 
>>>> That was it. This time I booted up the kernel including your series on
>>>> QEMU on my M1 and executed the gup_longterm program without the ftruncate
>>>> failures. When testing your kernel on FVP, I was executing the script from the FVP's host filesystem using 9p.
>>> 
>>> I'm not sure exactly what the root cause is. Perhaps there isn't enough space on
>>> the disk? It might be worth enhancing the error log to provide the errno in
>>> tools/testing/selftests/mm/gup_longterm.c.
>>> 
>> 
>> Attached is the strace’d gup_longterm executiong log on your
>> pgtable-boot-speedup-v2 kernel.
> 
> Sorry are you saying that it only fails with the pgtable-boot-speedup-v2 patch
> set applied? I thought we previously concluded that it was independent of that?
> I was under the impression that it was filesystem related and not something that
> I was planning to investigate.

No, irrespective of the kernel, if using 9p on FVP the test program fails.
It is indeed 9p filesystem related, as I switched to using NFS all the issues are gone.

Thanks,
Itaru.

> 
>> 
>> Thanks,
>> Itaru.
>> 
>>> Thanks,
>>> Ryan
>>> 
>>>> 
>>>> Thanks,
>>>> Itaru.
>>>> 
>>>>> 
>>>>> Does this problem reproduce with v6.9-rc2, without my patches? I except it
>>>>> probably does?
>>>>> 
>>>>> Thanks,
>>>>> Ryan
>>>>> 
>>>>>> 
>>>>>> Thanks,
>>>>>> Itaru.



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

^ permalink raw reply

* [PATCH v2 12/18] ASoC: mediatek: mt8365: Add platform driver
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add mt8365 platform driver.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/mt8365/mt8365-afe-pcm.c | 2275 ++++++++++++++++++++++++++++
 1 file changed, 2275 insertions(+)

diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
new file mode 100644
index 000000000000..ae99f8bdd251
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
@@ -0,0 +1,2275 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek 8365 ALSA SoC AFE platform driver
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include "mt8365-afe-common.h"
+#include "mt8365-afe-clk.h"
+#include "mt8365-reg.h"
+#include "../common/mtk-base-afe.h"
+#include "../common/mtk-afe-platform-driver.h"
+#include "../common/mtk-afe-fe-dai.h"
+
+#define AFE_BASE_END_OFFSET 8
+
+static unsigned int mCM2Input;
+
+static const unsigned int mt8365_afe_backup_list[] = {
+	AUDIO_TOP_CON0,
+	AFE_CONN0,
+	AFE_CONN1,
+	AFE_CONN3,
+	AFE_CONN4,
+	AFE_CONN5,
+	AFE_CONN6,
+	AFE_CONN7,
+	AFE_CONN8,
+	AFE_CONN9,
+	AFE_CONN10,
+	AFE_CONN11,
+	AFE_CONN12,
+	AFE_CONN13,
+	AFE_CONN14,
+	AFE_CONN15,
+	AFE_CONN16,
+	AFE_CONN17,
+	AFE_CONN18,
+	AFE_CONN19,
+	AFE_CONN20,
+	AFE_CONN21,
+	AFE_CONN26,
+	AFE_CONN27,
+	AFE_CONN28,
+	AFE_CONN29,
+	AFE_CONN30,
+	AFE_CONN31,
+	AFE_CONN32,
+	AFE_CONN33,
+	AFE_CONN34,
+	AFE_CONN35,
+	AFE_CONN36,
+	AFE_CONN_24BIT,
+	AFE_CONN_24BIT_1,
+	AFE_DAC_CON0,
+	AFE_DAC_CON1,
+	AFE_DL1_BASE,
+	AFE_DL1_END,
+	AFE_DL2_BASE,
+	AFE_DL2_END,
+	AFE_VUL_BASE,
+	AFE_VUL_END,
+	AFE_AWB_BASE,
+	AFE_AWB_END,
+	AFE_VUL3_BASE,
+	AFE_VUL3_END,
+	AFE_HDMI_OUT_BASE,
+	AFE_HDMI_OUT_END,
+	AFE_HDMI_IN_2CH_BASE,
+	AFE_HDMI_IN_2CH_END,
+	AFE_ADDA_UL_DL_CON0,
+	AFE_ADDA_DL_SRC2_CON0,
+	AFE_ADDA_DL_SRC2_CON1,
+	AFE_I2S_CON,
+	AFE_I2S_CON1,
+	AFE_I2S_CON2,
+	AFE_I2S_CON3,
+	AFE_ADDA_UL_SRC_CON0,
+	AFE_AUD_PAD_TOP,
+	AFE_HD_ENGEN_ENABLE,
+};
+
+static const struct snd_pcm_hardware mt8365_afe_hardware = {
+	.info = (SNDRV_PCM_INFO_MMAP |
+		 SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_MMAP_VALID),
+	.buffer_bytes_max = 256 * 1024,
+	.period_bytes_min = 512,
+	.period_bytes_max = 128 * 1024,
+	.periods_min = 2,
+	.periods_max = 256,
+	.fifo_size = 0,
+};
+
+struct mt8365_afe_rate {
+	unsigned int rate;
+	unsigned int reg_val;
+};
+
+static const struct mt8365_afe_rate mt8365_afe_fs_rates[] = {
+	{ .rate = 8000, .reg_val = MT8365_FS_8K },
+	{ .rate = 11025, .reg_val = MT8365_FS_11D025K },
+	{ .rate = 12000, .reg_val = MT8365_FS_12K },
+	{ .rate = 16000, .reg_val = MT8365_FS_16K },
+	{ .rate = 22050, .reg_val = MT8365_FS_22D05K },
+	{ .rate = 24000, .reg_val = MT8365_FS_24K },
+	{ .rate = 32000, .reg_val = MT8365_FS_32K },
+	{ .rate = 44100, .reg_val = MT8365_FS_44D1K },
+	{ .rate = 48000, .reg_val = MT8365_FS_48K },
+	{ .rate = 88200, .reg_val = MT8365_FS_88D2K },
+	{ .rate = 96000, .reg_val = MT8365_FS_96K },
+	{ .rate = 176400, .reg_val = MT8365_FS_176D4K },
+	{ .rate = 192000, .reg_val = MT8365_FS_192K },
+};
+
+int mt8365_afe_fs_timing(unsigned int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt8365_afe_fs_rates); i++)
+		if (mt8365_afe_fs_rates[i].rate == rate)
+			return mt8365_afe_fs_rates[i].reg_val;
+
+	return -EINVAL;
+}
+
+bool mt8365_afe_rate_supported(unsigned int rate, unsigned int id)
+{
+	switch (id) {
+	case MT8365_AFE_IO_TDM_IN:
+		if (rate >= 8000 && rate <= 192000)
+			return true;
+		break;
+	case MT8365_AFE_IO_DMIC:
+		if (rate >= 8000 && rate <= 48000)
+			return true;
+		break;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+bool mt8365_afe_channel_supported(unsigned int channel, unsigned int id)
+{
+	switch (id) {
+	case MT8365_AFE_IO_TDM_IN:
+		if (channel >= 1 && channel <= 8)
+			return true;
+		break;
+	case MT8365_AFE_IO_DMIC:
+		if (channel >= 1 && channel <= 8)
+			return true;
+		break;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+bool mt8365_afe_clk_group_44k(int sample_rate)
+{
+	if (sample_rate == 11025 ||
+	    sample_rate == 22050 ||
+	    sample_rate == 44100 ||
+	    sample_rate == 88200 ||
+	    sample_rate == 176400)
+		return true;
+	else
+		return false;
+}
+
+bool mt8365_afe_clk_group_48k(int sample_rate)
+{
+	return (!mt8365_afe_clk_group_44k(sample_rate));
+}
+
+int mt8365_dai_set_priv(struct mtk_base_afe *afe, int id,
+			int priv_size, const void *priv_data)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	void *temp_data;
+
+	temp_data = devm_kzalloc(afe->dev, priv_size, GFP_KERNEL);
+	if (!temp_data)
+		return -ENOMEM;
+
+	if (priv_data)
+		memcpy(temp_data, priv_data, priv_size);
+
+	afe_priv->dai_priv[id] = temp_data;
+
+	return 0;
+}
+
+static int mt8365_afe_irq_direction_enable(struct mtk_base_afe *afe,
+					   int irq_id, int direction)
+{
+	struct mtk_base_afe_irq *irq;
+
+	if (irq_id >= MT8365_AFE_IRQ_NUM)
+		return -1;
+
+	irq = &afe->irqs[irq_id];
+
+	if (direction == MT8365_AFE_IRQ_DIR_MCU) {
+		regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN,
+				   (1 << irq->irq_data->irq_clr_shift),
+				   0);
+		regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN,
+				   (1 << irq->irq_data->irq_clr_shift),
+				   (1 << irq->irq_data->irq_clr_shift));
+	} else if (direction == MT8365_AFE_IRQ_DIR_DSP) {
+		regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN,
+				   (1 << irq->irq_data->irq_clr_shift),
+				   (1 << irq->irq_data->irq_clr_shift));
+		regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN,
+				   (1 << irq->irq_data->irq_clr_shift),
+				   0);
+	} else {
+		regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN,
+				   (1 << irq->irq_data->irq_clr_shift),
+				   (1 << irq->irq_data->irq_clr_shift));
+		regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN,
+				   (1 << irq->irq_data->irq_clr_shift),
+				   (1 << irq->irq_data->irq_clr_shift));
+	}
+	return 0;
+}
+
+static int mt8365_memif_fs(struct snd_pcm_substream *substream,
+			   unsigned int rate)
+{
+	return mt8365_afe_fs_timing(rate);
+}
+
+static int mt8365_irq_fs(struct snd_pcm_substream *substream,
+			 unsigned int rate)
+{
+	return mt8365_memif_fs(substream, rate);
+}
+
+static const struct mt8365_cm_ctrl_reg cm_ctrl_reg[MT8365_CM_NUM] = {
+	[MT8365_CM1] = {
+		.con0 = AFE_CM1_CON0,
+		.con1 = AFE_CM1_CON1,
+		.con2 = AFE_CM1_CON2,
+		.con3 = AFE_CM1_CON3,
+		.con4 = AFE_CM1_CON4,
+	},
+	[MT8365_CM2] = {
+		.con0 = AFE_CM2_CON0,
+		.con1 = AFE_CM2_CON1,
+		.con2 = AFE_CM2_CON2,
+		.con3 = AFE_CM2_CON3,
+		.con4 = AFE_CM2_CON4,
+	}
+};
+
+static int mt8365_afe_cm2_mux_conn(struct mtk_base_afe *afe)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	unsigned int input = afe_priv->cm2_mux_input;
+
+	/* TDM_IN interconnect to CM2 */
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
+			   CM2_AFE_CM2_CONN_CFG1_MASK,
+			   CM2_AFE_CM2_CONN_CFG1(TDM_IN_CH0));
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
+			   CM2_AFE_CM2_CONN_CFG2_MASK,
+			   CM2_AFE_CM2_CONN_CFG2(TDM_IN_CH1));
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
+			   CM2_AFE_CM2_CONN_CFG3_MASK,
+			   CM2_AFE_CM2_CONN_CFG3(TDM_IN_CH2));
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
+			   CM2_AFE_CM2_CONN_CFG4_MASK,
+			   CM2_AFE_CM2_CONN_CFG4(TDM_IN_CH3));
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
+			   CM2_AFE_CM2_CONN_CFG5_MASK,
+			   CM2_AFE_CM2_CONN_CFG5(TDM_IN_CH4));
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN0,
+			   CM2_AFE_CM2_CONN_CFG6_MASK,
+			   CM2_AFE_CM2_CONN_CFG6(TDM_IN_CH5));
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+			   CM2_AFE_CM2_CONN_CFG7_MASK,
+			   CM2_AFE_CM2_CONN_CFG7(TDM_IN_CH6));
+	regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+			   CM2_AFE_CM2_CONN_CFG8_MASK,
+			   CM2_AFE_CM2_CONN_CFG8(TDM_IN_CH7));
+
+	/* ref data interconnect to CM2 */
+	if (input == MT8365_FROM_GASRC1) {
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG9_MASK,
+				   CM2_AFE_CM2_CONN_CFG9(GENERAL1_ASRC_OUT_LCH));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG10_MASK,
+				   CM2_AFE_CM2_CONN_CFG10(GENERAL1_ASRC_OUT_RCH));
+	} else if (input == MT8365_FROM_GASRC2) {
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG9_MASK,
+				   CM2_AFE_CM2_CONN_CFG9(GENERAL2_ASRC_OUT_LCH));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG10_MASK,
+				   CM2_AFE_CM2_CONN_CFG10(GENERAL2_ASRC_OUT_RCH));
+	} else if (input == MT8365_FROM_TDM_ASRC) {
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG9_MASK,
+				   CM2_AFE_CM2_CONN_CFG9(TDM_OUT_ASRC_CH0));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG10_MASK,
+				   CM2_AFE_CM2_CONN_CFG10(TDM_OUT_ASRC_CH1));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG11_MASK,
+				   CM2_AFE_CM2_CONN_CFG11(TDM_OUT_ASRC_CH2));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN1,
+				   CM2_AFE_CM2_CONN_CFG12_MASK,
+				   CM2_AFE_CM2_CONN_CFG12(TDM_OUT_ASRC_CH3));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
+				   CM2_AFE_CM2_CONN_CFG13_MASK,
+				   CM2_AFE_CM2_CONN_CFG13(TDM_OUT_ASRC_CH4));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
+				   CM2_AFE_CM2_CONN_CFG14_MASK,
+				   CM2_AFE_CM2_CONN_CFG14(TDM_OUT_ASRC_CH5));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
+				   CM2_AFE_CM2_CONN_CFG15_MASK,
+				   CM2_AFE_CM2_CONN_CFG15(TDM_OUT_ASRC_CH6));
+		regmap_update_bits(afe->regmap, AFE_CM2_CONN2,
+				   CM2_AFE_CM2_CONN_CFG16_MASK,
+				   CM2_AFE_CM2_CONN_CFG16(TDM_OUT_ASRC_CH7));
+	} else {
+		dev_err(afe->dev, "%s wrong CM2 input %d\n", __func__, input);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mt8365_afe_get_cm_update_cnt(struct mtk_base_afe *afe,
+					enum mt8365_cm_num cmNum,
+					unsigned int rate, unsigned int channel)
+{
+	unsigned int total_cnt, div_cnt, ch_pair, best_cnt;
+	unsigned int ch_update_cnt[MT8365_CM_UPDATA_CNT_SET];
+	int i;
+
+	/* calculate cm update cnt
+	 * total_cnt = clk / fs, clk is 26m or 24m or 22m
+	 * div_cnt = total_cnt / ch_pair, max ch 16ch ,2ch is a set
+	 * best_cnt < div_cnt ,we set best_cnt = div_cnt -10
+	 * ch01 = best_cnt, ch23 = 2* ch01_up_cnt
+	 * ch45 = 3* ch01_up_cnt ...ch1415 = 8* ch01_up_cnt
+	 */
+
+	if (cmNum == MT8365_CM1) {
+		total_cnt = MT8365_CLK_26M / rate;
+	} else if (cmNum == MT8365_CM2) {
+		if (mt8365_afe_clk_group_48k(rate))
+			total_cnt = MT8365_CLK_24M / rate;
+		else
+			total_cnt = MT8365_CLK_22M / rate;
+	} else {
+		return -1;
+	}
+
+	if (channel % 2)
+		ch_pair = (channel / 2) + 1;
+	else
+		ch_pair = channel / 2;
+
+	div_cnt =  total_cnt / ch_pair;
+	best_cnt = div_cnt - 10;
+
+	if (best_cnt <= 0)
+		return -1;
+
+	for (i = 0; i < ch_pair; i++)
+		ch_update_cnt[i] = (i + 1) * best_cnt;
+
+	switch (channel) {
+	case 16:
+		fallthrough;
+	case 15:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con4,
+				   CM_AFE_CM_UPDATE_CNT2_MASK,
+				   CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[7]));
+		fallthrough;
+	case 14:
+		fallthrough;
+	case 13:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con4,
+				   CM_AFE_CM_UPDATE_CNT1_MASK,
+				   CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[6]));
+		fallthrough;
+	case 12:
+		fallthrough;
+	case 11:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con3,
+				   CM_AFE_CM_UPDATE_CNT2_MASK,
+				   CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[5]));
+		fallthrough;
+	case 10:
+		fallthrough;
+	case 9:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con3,
+				   CM_AFE_CM_UPDATE_CNT1_MASK,
+				   CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[4]));
+		fallthrough;
+	case 8:
+		fallthrough;
+	case 7:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con2,
+				   CM_AFE_CM_UPDATE_CNT2_MASK,
+				   CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[3]));
+		fallthrough;
+	case 6:
+		fallthrough;
+	case 5:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con2,
+				   CM_AFE_CM_UPDATE_CNT1_MASK,
+				   CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[2]));
+		fallthrough;
+	case 4:
+		fallthrough;
+	case 3:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con1,
+				   CM_AFE_CM_UPDATE_CNT2_MASK,
+				   CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[1]));
+		fallthrough;
+	case 2:
+		fallthrough;
+	case 1:
+		regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con1,
+				   CM_AFE_CM_UPDATE_CNT1_MASK,
+				   CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[0]));
+		break;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mt8365_afe_configure_cm(struct mtk_base_afe *afe,
+				   enum mt8365_cm_num cmNum,
+				   unsigned int channels,
+				   unsigned int rate)
+{
+	unsigned int val, mask;
+	unsigned int fs = mt8365_afe_fs_timing(rate);
+
+	val = FIELD_PREP(CM_AFE_CM_CH_NUM_MASK, (channels - 1)) |
+	      FIELD_PREP(CM_AFE_CM_START_DATA_MASK, 0);
+
+	mask = CM_AFE_CM_CH_NUM_MASK |
+	       CM_AFE_CM_START_DATA_MASK;
+
+	if (cmNum == MT8365_CM1) {
+		val |= FIELD_PREP(CM_AFE_CM1_IN_MODE_MASK, fs);
+
+		mask |= CM_AFE_CM1_VUL_SEL |
+			CM_AFE_CM1_IN_MODE_MASK;
+	} else if (cmNum == MT8365_CM2) {
+		if (mt8365_afe_clk_group_48k(rate))
+			val |= FIELD_PREP(CM_AFE_CM2_CLK_SEL, 0);
+		else
+			val |= FIELD_PREP(CM_AFE_CM2_CLK_SEL, 1);
+
+		val |= FIELD_PREP(CM_AFE_CM2_TDM_SEL, 1);
+
+		mask |= CM_AFE_CM2_TDM_SEL |
+			CM_AFE_CM1_IN_MODE_MASK |
+			CM_AFE_CM2_CLK_SEL;
+
+		mt8365_afe_cm2_mux_conn(afe);
+	} else {
+		return -1;
+	}
+
+	regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con0, mask, val);
+
+	mt8365_afe_get_cm_update_cnt(afe, cmNum, rate, channels);
+
+	return 0;
+}
+
+int mt8365_afe_fe_startup(struct snd_pcm_substream *substream,
+			  struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int memif_num = snd_soc_rtd_to_cpu(rtd, 0)->id;
+	struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
+	int ret;
+
+	memif->substream = substream;
+
+	snd_pcm_hw_constraint_step(substream->runtime, 0,
+				   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
+
+	snd_soc_set_runtime_hwparams(substream, afe->mtk_afe_hardware);
+
+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
+
+	mt8365_afe_enable_main_clk(afe);
+	return ret;
+}
+
+static void mt8365_afe_fe_shutdown(struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	int memif_num = snd_soc_rtd_to_cpu(rtd, 0)->id;
+	struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
+
+	memif->substream = NULL;
+
+	mt8365_afe_disable_main_clk(afe);
+}
+
+static int mt8365_afe_fe_hw_params(struct snd_pcm_substream *substream,
+				   struct snd_pcm_hw_params *params,
+				   struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_control_data *ctrl_data = &afe_priv->ctrl_data;
+	int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
+	struct mtk_base_afe_memif *memif = &afe->memif[dai_id];
+	struct mt8365_fe_dai_data *fe_data = &afe_priv->fe_data[dai_id];
+	size_t request_size = params_buffer_bytes(params);
+	unsigned int channels = params_channels(params);
+	unsigned int rate = params_rate(params);
+	unsigned int base_end_offset = 8;
+	int ret, fs;
+
+	dev_info(afe->dev, "%s %s period = %d rate = %d channels = %d\n",
+		 __func__, memif->data->name, params_period_size(params),
+		 rate, channels);
+
+	if (dai_id == MT8365_AFE_MEMIF_VUL2) {
+		if (!ctrl_data->bypass_cm1)
+			/* configure cm1 */
+			mt8365_afe_configure_cm(afe, MT8365_CM1,
+						channels, rate);
+		else
+			regmap_update_bits(afe->regmap, AFE_CM1_CON0,
+					   CM_AFE_CM1_VUL_SEL,
+					   CM_AFE_CM1_VUL_SEL);
+	} else if (dai_id == MT8365_AFE_MEMIF_TDM_IN) {
+		if (!ctrl_data->bypass_cm2)
+			/* configure cm2 */
+			mt8365_afe_configure_cm(afe, MT8365_CM2,
+						channels, rate);
+		else
+			regmap_update_bits(afe->regmap, AFE_CM2_CON0,
+					   CM_AFE_CM2_TDM_SEL,
+					   ~CM_AFE_CM2_TDM_SEL);
+
+		base_end_offset = 4;
+	}
+
+	if (request_size > fe_data->sram_size) {
+		ret = snd_pcm_lib_malloc_pages(substream, request_size);
+		if (ret < 0) {
+			dev_err(afe->dev,
+				"%s %s malloc pages %zu bytes failed %d\n",
+				__func__, memif->data->name, request_size, ret);
+			return ret;
+		}
+
+		fe_data->use_sram = false;
+
+		mt8365_afe_emi_clk_on(afe);
+	} else {
+		struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+
+		dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
+		dma_buf->dev.dev = substream->pcm->card->dev;
+		dma_buf->area = (unsigned char *)fe_data->sram_vir_addr;
+		dma_buf->addr = fe_data->sram_phy_addr;
+		dma_buf->bytes = request_size;
+		snd_pcm_set_runtime_buffer(substream, dma_buf);
+
+		fe_data->use_sram = true;
+	}
+
+	memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr);
+	memif->buffer_size = substream->runtime->dma_bytes;
+
+	/* start */
+	regmap_write(afe->regmap, memif->data->reg_ofs_base,
+		     memif->phys_buf_addr);
+	/* end */
+	regmap_write(afe->regmap,
+		     memif->data->reg_ofs_base + base_end_offset,
+		     memif->phys_buf_addr + memif->buffer_size - 1);
+
+	/* set channel */
+	if (memif->data->mono_shift >= 0) {
+		unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
+
+		if (memif->data->mono_reg < 0)
+			dev_info(afe->dev, "%s mono_reg is NULL\n", __func__);
+		else
+			regmap_update_bits(afe->regmap, memif->data->mono_reg,
+					   1 << memif->data->mono_shift,
+					   mono << memif->data->mono_shift);
+	}
+
+	/* set rate */
+	if (memif->data->fs_shift < 0)
+		return 0;
+
+	fs = afe->memif_fs(substream, params_rate(params));
+
+	if (fs < 0)
+		return -EINVAL;
+
+	if (memif->data->fs_reg < 0)
+		dev_info(afe->dev, "%s fs_reg is NULL\n", __func__);
+	else
+		regmap_update_bits(afe->regmap, memif->data->fs_reg,
+				   memif->data->fs_maskbit << memif->data->fs_shift,
+				   fs << memif->data->fs_shift);
+
+	return 0;
+}
+
+static int mt8365_afe_fe_hw_free(struct snd_pcm_substream *substream,
+				 struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
+	struct mtk_base_afe_memif *memif = &afe->memif[dai_id];
+	struct mt8365_fe_dai_data *fe_data = &afe_priv->fe_data[dai_id];
+	int ret = 0;
+
+	if (fe_data->use_sram) {
+		snd_pcm_set_runtime_buffer(substream, NULL);
+	} else {
+		ret = snd_pcm_lib_free_pages(substream);
+
+		mt8365_afe_emi_clk_off(afe);
+	}
+
+	return ret;
+}
+
+static int mt8365_afe_fe_prepare(struct snd_pcm_substream *substream,
+				 struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
+	struct mtk_base_afe_memif *memif = &afe->memif[dai_id];
+
+	/* set format */
+	if (memif->data->hd_reg >= 0) {
+		switch (substream->runtime->format) {
+		case SNDRV_PCM_FORMAT_S16_LE:
+			regmap_update_bits(afe->regmap, memif->data->hd_reg,
+					   3 << memif->data->hd_shift,
+					   0 << memif->data->hd_shift);
+			break;
+		case SNDRV_PCM_FORMAT_S32_LE:
+			regmap_update_bits(afe->regmap, memif->data->hd_reg,
+					   3 << memif->data->hd_shift,
+					   3 << memif->data->hd_shift);
+
+			if (dai_id == MT8365_AFE_MEMIF_TDM_IN) {
+				regmap_update_bits(afe->regmap,
+						   memif->data->hd_reg,
+						   3 << memif->data->hd_shift,
+						   1 << memif->data->hd_shift);
+				regmap_update_bits(afe->regmap,
+						   memif->data->hd_reg,
+						   1 << memif->data->hd_align_mshift,
+						   1 << memif->data->hd_align_mshift);
+			}
+			break;
+		case SNDRV_PCM_FORMAT_S24_LE:
+			regmap_update_bits(afe->regmap, memif->data->hd_reg,
+					   3 << memif->data->hd_shift,
+					   1 << memif->data->hd_shift);
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	mt8365_afe_irq_direction_enable(afe, memif->irq_usage,
+					MT8365_AFE_IRQ_DIR_MCU);
+
+	return 0;
+}
+
+int mt8365_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
+			  struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id;
+	struct mt8365_control_data *ctrl_data = &afe_priv->ctrl_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		/* enable channel merge */
+		if (dai_id == MT8365_AFE_MEMIF_VUL2 &&
+		    !ctrl_data->bypass_cm1) {
+			regmap_update_bits(afe->regmap, AFE_CM1_CON0,
+					   CM_AFE_CM_ON, CM_AFE_CM_ON);
+		} else if (dai_id == MT8365_AFE_MEMIF_TDM_IN &&
+			   !ctrl_data->bypass_cm2) {
+			regmap_update_bits(afe->regmap, AFE_CM2_CON0,
+					   CM_AFE_CM_ON, CM_AFE_CM_ON);
+		}
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		/* disable channel merge */
+		if (dai_id == MT8365_AFE_MEMIF_VUL2 &&
+		    !ctrl_data->bypass_cm1) {
+			regmap_update_bits(afe->regmap, AFE_CM1_CON0,
+					   CM_AFE_CM_ON, ~CM_AFE_CM_ON);
+		} else if (dai_id == MT8365_AFE_MEMIF_TDM_IN &&
+			   !ctrl_data->bypass_cm2) {
+			regmap_update_bits(afe->regmap, AFE_CM2_CON0,
+					   CM_AFE_CM_ON, ~CM_AFE_CM_ON);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return mtk_afe_fe_trigger(substream, cmd, dai);
+}
+
+static int mt8365_afe_hw_gain1_startup(struct snd_pcm_substream *substream,
+				       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+
+	mt8365_afe_enable_main_clk(afe);
+	return 0;
+}
+
+static void mt8365_afe_hw_gain1_shutdown(struct snd_pcm_substream *substream,
+					 struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_be_dai_data *be =
+		&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+
+	if (be->prepared[substream->stream]) {
+		regmap_update_bits(afe->regmap, AFE_GAIN1_CON0,
+				   AFE_GAIN1_CON0_EN_MASK, 0);
+		be->prepared[substream->stream] = false;
+	}
+	mt8365_afe_disable_main_clk(afe);
+}
+
+static int mt8365_afe_hw_gain1_prepare(struct snd_pcm_substream *substream,
+				       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_be_dai_data *be =
+		&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+
+	int fs;
+	unsigned int val1 = 0, val2 = 0;
+
+	if (be->prepared[substream->stream]) {
+		dev_info(afe->dev, "%s prepared already\n", __func__);
+		return 0;
+	}
+
+	fs = mt8365_afe_fs_timing(substream->runtime->rate);
+	regmap_update_bits(afe->regmap, AFE_GAIN1_CON0,
+			   AFE_GAIN1_CON0_MODE_MASK, (unsigned int)fs << 4);
+
+	regmap_read(afe->regmap, AFE_GAIN1_CON1, &val1);
+	regmap_read(afe->regmap, AFE_GAIN1_CUR, &val2);
+	if ((val1 & AFE_GAIN1_CON1_MASK) != (val2 & AFE_GAIN1_CUR_MASK))
+		regmap_update_bits(afe->regmap, AFE_GAIN1_CUR,
+				   AFE_GAIN1_CUR_MASK, val1);
+
+	regmap_update_bits(afe->regmap, AFE_GAIN1_CON0,
+			   AFE_GAIN1_CON0_EN_MASK, 1);
+	be->prepared[substream->stream] = true;
+
+	return 0;
+}
+
+static const struct snd_pcm_hardware mt8365_hostless_hardware = {
+	.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+		 SNDRV_PCM_INFO_MMAP_VALID),
+	.period_bytes_min = 256,
+	.period_bytes_max = 4 * 48 * 1024,
+	.periods_min = 2,
+	.periods_max = 256,
+	.buffer_bytes_max = 8 * 48 * 1024,
+	.fifo_size = 0,
+};
+
+/* dai ops */
+static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int ret;
+
+	snd_soc_set_runtime_hwparams(substream, &mt8365_hostless_hardware);
+
+	ret = snd_pcm_hw_constraint_integer(runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
+	return ret;
+}
+
+/* FE DAIs */
+static const struct snd_soc_dai_ops mt8365_afe_fe_dai_ops = {
+	.startup	= mt8365_afe_fe_startup,
+	.shutdown	= mt8365_afe_fe_shutdown,
+	.hw_params	= mt8365_afe_fe_hw_params,
+	.hw_free	= mt8365_afe_fe_hw_free,
+	.prepare	= mt8365_afe_fe_prepare,
+	.trigger	= mt8365_afe_fe_trigger,
+};
+
+static const struct snd_soc_dai_ops mt8365_dai_hostless_ops = {
+	.startup = mtk_dai_hostless_startup,
+};
+
+static const struct snd_soc_dai_ops mt8365_afe_hw_gain1_ops = {
+	.startup	= mt8365_afe_hw_gain1_startup,
+	.shutdown	= mt8365_afe_hw_gain1_shutdown,
+	.prepare	= mt8365_afe_hw_gain1_prepare,
+};
+
+static struct snd_soc_dai_driver mt8365_memif_dai_driver[] = {
+	/* FE DAIs: memory intefaces to CPU */
+	{
+		.name = "DL1",
+		.id = MT8365_AFE_MEMIF_DL1,
+		.playback = {
+			.stream_name = "DL1",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "DL2",
+		.id = MT8365_AFE_MEMIF_DL2,
+		.playback = {
+			.stream_name = "DL2",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "TDM_OUT",
+		.id = MT8365_AFE_MEMIF_TDM_OUT,
+		.playback = {
+			.stream_name = "TDM_OUT",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "AWB",
+		.id = MT8365_AFE_MEMIF_AWB,
+		.capture = {
+			.stream_name = "AWB",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "VUL",
+		.id = MT8365_AFE_MEMIF_VUL,
+		.capture = {
+			.stream_name = "VUL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "VUL2",
+		.id = MT8365_AFE_MEMIF_VUL2,
+		.capture = {
+			.stream_name = "VUL2",
+			.channels_min = 1,
+			.channels_max = 16,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "VUL3",
+		.id = MT8365_AFE_MEMIF_VUL3,
+		.capture = {
+			.stream_name = "VUL3",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "TDM_IN",
+		.id = MT8365_AFE_MEMIF_TDM_IN,
+		.capture = {
+			.stream_name = "TDM_IN",
+			.channels_min = 1,
+			.channels_max = 16,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_fe_dai_ops,
+	}, {
+		.name = "Hostless FM DAI",
+		.id = MT8365_AFE_IO_VIRTUAL_FM,
+		.playback = {
+			.stream_name = "Hostless FM DL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+					  SNDRV_PCM_FMTBIT_S24_LE |
+					   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "Hostless FM UL",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+					  SNDRV_PCM_FMTBIT_S24_LE |
+					   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_dai_hostless_ops,
+	}, {
+		.name = "HW_GAIN1",
+		.id = MT8365_AFE_IO_HW_GAIN1,
+		.playback = {
+			.stream_name = "HW Gain 1 In",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "HW Gain 1 Out",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_hw_gain1_ops,
+		.symmetric_rate = 1,
+		.symmetric_channels = 1,
+		.symmetric_sample_bits = 1,
+	},
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o00_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN0, 5, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN0, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o01_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN1, 6, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN1, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o03_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN3, 5, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN3, 7, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN3, 0, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I10 Switch", AFE_CONN3, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o04_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN4, 6, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN4, 8, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN4, 1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I11 Switch", AFE_CONN4, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o05_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN5, 0, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN5, 3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN5, 5, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN5, 7, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN5, 9, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN5, 14, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN5, 16, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN5, 18, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN5, 20, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN5, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I10L Switch", AFE_CONN5, 10, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o06_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN6, 1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN6, 4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN6, 6, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN6, 8, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN6, 22, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN6, 15, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN6, 17, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN6, 19, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN6, 21, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN6, 24, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I11L Switch", AFE_CONN6, 11, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o07_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN7, 5, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN7, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o08_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN8, 6, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN8, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o09_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN9, 0, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN9, 3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN9, 9, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN9, 14, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN9, 16, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN9, 18, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN9, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o10_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN10, 1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN10, 4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN10, 22, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN10, 15, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN10, 17, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN10, 19, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN10, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o11_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN11, 0, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN11, 3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN11, 9, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN11, 14, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN11, 16, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN11, 18, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN11, 20, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o12_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN12, 1, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN12, 4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN12, 22, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN12, 15, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN12, 17, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN12, 19, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN12, 21, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o13_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN13, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o14_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN14, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o15_mix[] = {
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o16_mix[] = {
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o17_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN17, 3, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN17, 14, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o18_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN18, 4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN18, 15, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN18, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN18, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o19_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN19, 4, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN19, 16, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN19, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN19, 24, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN19, 25, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN19, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o20_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN20, 17, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN20, 24, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN20, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o21_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN21, 18, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN21, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN21, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o22_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN22, 24, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN22, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o23_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN23, 20, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN23, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN23, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o24_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN24, 21, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN24, 24, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN24, 26, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN24, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN24, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o25_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I27 Switch", AFE_CONN25, 27, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN25, 23, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN25, 25, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o26_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I28 Switch", AFE_CONN26, 28, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN26, 24, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN26, 26, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o27_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN27, 5, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN27, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o28_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN28, 6, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN28, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o29_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN29, 5, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN29, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o30_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN30, 6, 1, 0),
+	SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN30, 8, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o31_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I29 Switch", AFE_CONN31, 29, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o32_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I30 Switch", AFE_CONN32, 30, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o33_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I31 Switch", AFE_CONN33, 31, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o34_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I32 Switch", AFE_CONN34_1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o35_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I33 Switch", AFE_CONN35_1, 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mt8365_afe_o36_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("I34 Switch", AFE_CONN36_1, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_gain1_in_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN13,
+				    0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_hw_gain1_in_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN14,
+				    1, 1, 0),
+};
+
+static int mt8365_afe_cm2_io_input_mux_get(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = mCM2Input;
+
+	return 0;
+}
+
+static int mt8365_afe_cm2_io_input_mux_put(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_context *dapm =
+		snd_soc_dapm_kcontrol_dapm(kcontrol);
+	struct snd_soc_component *comp = snd_soc_dapm_to_component(dapm);
+	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(comp);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	int ret;
+
+	mCM2Input = ucontrol->value.enumerated.item[0];
+
+	afe_priv->cm2_mux_input = mCM2Input;
+	ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+	return ret;
+}
+
+static const char * const fmhwgain_text[] = {
+	"OPEN", "FM_HW_GAIN_IO"
+};
+
+static const char * const ain_text[] = {
+	"INT ADC", "EXT ADC",
+};
+
+static const char * const vul2_in_input_text[] = {
+	"VUL2_IN_FROM_O17O18", "VUL2_IN_FROM_CM1",
+};
+
+static const char * const mt8365_afe_cm2_mux_text[] = {
+	"OPEN", "FROM_GASRC1_OUT", "FROM_GASRC2_OUT", "FROM_TDM_ASRC_OUT",
+};
+
+static SOC_ENUM_SINGLE_VIRT_DECL(fmhwgain_enum, fmhwgain_text);
+static SOC_ENUM_SINGLE_DECL(ain_enum, AFE_ADDA_TOP_CON0, 0, ain_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(vul2_in_input_enum, vul2_in_input_text);
+static SOC_ENUM_SINGLE_VIRT_DECL(mt8365_afe_cm2_mux_input_enum,
+	mt8365_afe_cm2_mux_text);
+
+static const struct snd_kcontrol_new fmhwgain_mux =
+	SOC_DAPM_ENUM("FM HW Gain Source", fmhwgain_enum);
+
+static const struct snd_kcontrol_new ain_mux =
+	SOC_DAPM_ENUM("AIN Source", ain_enum);
+
+static const struct snd_kcontrol_new vul2_in_input_mux =
+	SOC_DAPM_ENUM("VUL2 Input", vul2_in_input_enum);
+
+static const struct snd_kcontrol_new mt8365_afe_cm2_mux_input_mux =
+	SOC_DAPM_ENUM_EXT("CM2_MUX Source", mt8365_afe_cm2_mux_input_enum,
+			  mt8365_afe_cm2_io_input_mux_get,
+			  mt8365_afe_cm2_io_input_mux_put);
+
+static const struct snd_soc_dapm_widget mt8365_memif_widgets[] = {
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I01", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I07", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I08", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I05L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I06L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I07L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I08L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I09", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I10", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I11", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I10L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I11L", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I12", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I13", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I14", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I15", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I16", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I19", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I20", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I21", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I22", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I23", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I24", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I25", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I26", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I27", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I28", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I29", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I30", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I31", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I32", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I33", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("I34", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("O00", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o00_mix, ARRAY_SIZE(mt8365_afe_o00_mix)),
+	SND_SOC_DAPM_MIXER("O01", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o01_mix, ARRAY_SIZE(mt8365_afe_o01_mix)),
+	SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o03_mix, ARRAY_SIZE(mt8365_afe_o03_mix)),
+	SND_SOC_DAPM_MIXER("O04", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o04_mix, ARRAY_SIZE(mt8365_afe_o04_mix)),
+	SND_SOC_DAPM_MIXER("O05", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o05_mix, ARRAY_SIZE(mt8365_afe_o05_mix)),
+	SND_SOC_DAPM_MIXER("O06", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o06_mix, ARRAY_SIZE(mt8365_afe_o06_mix)),
+	SND_SOC_DAPM_MIXER("O07", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o07_mix, ARRAY_SIZE(mt8365_afe_o07_mix)),
+	SND_SOC_DAPM_MIXER("O08", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o08_mix, ARRAY_SIZE(mt8365_afe_o08_mix)),
+	SND_SOC_DAPM_MIXER("O09", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o09_mix, ARRAY_SIZE(mt8365_afe_o09_mix)),
+	SND_SOC_DAPM_MIXER("O10", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o10_mix, ARRAY_SIZE(mt8365_afe_o10_mix)),
+	SND_SOC_DAPM_MIXER("O11", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o11_mix, ARRAY_SIZE(mt8365_afe_o11_mix)),
+	SND_SOC_DAPM_MIXER("O12", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o12_mix, ARRAY_SIZE(mt8365_afe_o12_mix)),
+	SND_SOC_DAPM_MIXER("O13", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o13_mix, ARRAY_SIZE(mt8365_afe_o13_mix)),
+	SND_SOC_DAPM_MIXER("O14", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o14_mix, ARRAY_SIZE(mt8365_afe_o14_mix)),
+	SND_SOC_DAPM_MIXER("O15", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o15_mix, ARRAY_SIZE(mt8365_afe_o15_mix)),
+	SND_SOC_DAPM_MIXER("O16", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o16_mix, ARRAY_SIZE(mt8365_afe_o16_mix)),
+	SND_SOC_DAPM_MIXER("O17", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o17_mix, ARRAY_SIZE(mt8365_afe_o17_mix)),
+	SND_SOC_DAPM_MIXER("O18", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o18_mix, ARRAY_SIZE(mt8365_afe_o18_mix)),
+	SND_SOC_DAPM_MIXER("O19", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o19_mix, ARRAY_SIZE(mt8365_afe_o19_mix)),
+	SND_SOC_DAPM_MIXER("O20", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o20_mix, ARRAY_SIZE(mt8365_afe_o20_mix)),
+	SND_SOC_DAPM_MIXER("O21", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o21_mix, ARRAY_SIZE(mt8365_afe_o21_mix)),
+	SND_SOC_DAPM_MIXER("O22", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o22_mix, ARRAY_SIZE(mt8365_afe_o22_mix)),
+	SND_SOC_DAPM_MIXER("O23", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o23_mix, ARRAY_SIZE(mt8365_afe_o23_mix)),
+	SND_SOC_DAPM_MIXER("O24", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o24_mix, ARRAY_SIZE(mt8365_afe_o24_mix)),
+	SND_SOC_DAPM_MIXER("O25", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o25_mix, ARRAY_SIZE(mt8365_afe_o25_mix)),
+	SND_SOC_DAPM_MIXER("O26", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o26_mix, ARRAY_SIZE(mt8365_afe_o26_mix)),
+	SND_SOC_DAPM_MIXER("O27", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o27_mix, ARRAY_SIZE(mt8365_afe_o27_mix)),
+	SND_SOC_DAPM_MIXER("O28", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o28_mix, ARRAY_SIZE(mt8365_afe_o28_mix)),
+	SND_SOC_DAPM_MIXER("O29", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o29_mix, ARRAY_SIZE(mt8365_afe_o29_mix)),
+	SND_SOC_DAPM_MIXER("O30", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o30_mix, ARRAY_SIZE(mt8365_afe_o30_mix)),
+	SND_SOC_DAPM_MIXER("O31", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o31_mix, ARRAY_SIZE(mt8365_afe_o31_mix)),
+	SND_SOC_DAPM_MIXER("O32", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o32_mix, ARRAY_SIZE(mt8365_afe_o32_mix)),
+	SND_SOC_DAPM_MIXER("O33", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o33_mix, ARRAY_SIZE(mt8365_afe_o33_mix)),
+	SND_SOC_DAPM_MIXER("O34", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o34_mix, ARRAY_SIZE(mt8365_afe_o34_mix)),
+	SND_SOC_DAPM_MIXER("O35", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o35_mix, ARRAY_SIZE(mt8365_afe_o35_mix)),
+	SND_SOC_DAPM_MIXER("O36", SND_SOC_NOPM, 0, 0,
+			   mt8365_afe_o36_mix, ARRAY_SIZE(mt8365_afe_o36_mix)),
+	SND_SOC_DAPM_MIXER("CM2_Mux IO", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("CM1_IO", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("O17O18", SND_SOC_NOPM, 0, 0, NULL, 0),
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_gain1_in_ch1_mix,
+			   ARRAY_SIZE(mtk_hw_gain1_in_ch1_mix)),
+	SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_hw_gain1_in_ch2_mix,
+			   ARRAY_SIZE(mtk_hw_gain1_in_ch2_mix)),
+
+	SND_SOC_DAPM_INPUT("DL Source"),
+
+	SND_SOC_DAPM_MUX("CM2_Mux_IO Input Mux", SND_SOC_NOPM, 0, 0,
+			 &mt8365_afe_cm2_mux_input_mux),
+
+	SND_SOC_DAPM_MUX("AIN Mux", SND_SOC_NOPM, 0, 0, &ain_mux),
+	SND_SOC_DAPM_MUX("VUL2 Input Mux", SND_SOC_NOPM, 0, 0,
+			 &vul2_in_input_mux),
+
+	SND_SOC_DAPM_MUX("FM HW Gain Mux", SND_SOC_NOPM, 0, 0, &fmhwgain_mux),
+
+	SND_SOC_DAPM_INPUT("HW Gain 1 Out Endpoint"),
+	SND_SOC_DAPM_OUTPUT("HW Gain 1 In Endpoint"),
+};
+
+static const struct snd_soc_dapm_route mt8365_memif_routes[] = {
+	/* downlink */
+	{"I00", NULL, "2ND I2S Capture"},
+	{"I01", NULL, "2ND I2S Capture"},
+	{"I05", NULL, "DL1"},
+	{"I06", NULL, "DL1"},
+	{"I07", NULL, "DL2"},
+	{"I08", NULL, "DL2"},
+
+	{"O03", "I05 Switch", "I05"},
+	{"O04", "I06 Switch", "I06"},
+	{"O00", "I05 Switch", "I05"},
+	{"O01", "I06 Switch", "I06"},
+	{"O07", "I05 Switch", "I05"},
+	{"O08", "I06 Switch", "I06"},
+	{"O27", "I05 Switch", "I05"},
+	{"O28", "I06 Switch", "I06"},
+	{"O29", "I05 Switch", "I05"},
+	{"O30", "I06 Switch", "I06"},
+
+	{"O03", "I07 Switch", "I07"},
+	{"O04", "I08 Switch", "I08"},
+	{"O00", "I07 Switch", "I07"},
+	{"O01", "I08 Switch", "I08"},
+	{"O07", "I07 Switch", "I07"},
+	{"O08", "I08 Switch", "I08"},
+
+	/* uplink */
+	{"AWB", NULL, "O05"},
+	{"AWB", NULL, "O06"},
+	{"VUL", NULL, "O09"},
+	{"VUL", NULL, "O10"},
+	{"VUL3", NULL, "O11"},
+	{"VUL3", NULL, "O12"},
+
+	{"AIN Mux", "EXT ADC", "I2S Capture"},
+	{"I03", NULL, "AIN Mux"},
+	{"I04", NULL, "AIN Mux"},
+
+	{"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1", "Hostless FM DL"},
+	{"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2", "Hostless FM DL"},
+
+	{"HW Gain 1 In Endpoint", NULL, "HW Gain 1 In"},
+	{"HW Gain 1 Out", NULL, "HW Gain 1 Out Endpoint"},
+	{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH1"},
+	{"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH2"},
+
+	{"FM HW Gain Mux", "FM_HW_GAIN_IO", "HW Gain 1 Out"},
+	{"Hostless FM UL", NULL, "FM HW Gain Mux"},
+	{"Hostless FM UL", NULL, "FM 2ND I2S Mux"},
+
+	{"O05", "I05 Switch", "I05L"},
+	{"O06", "I06 Switch", "I06L"},
+	{"O05", "I07 Switch", "I07L"},
+	{"O06", "I08 Switch", "I08L"},
+
+	{"O05", "I03 Switch", "I03"},
+	{"O06", "I04 Switch", "I04"},
+	{"O05", "I00 Switch", "I00"},
+	{"O06", "I01 Switch", "I01"},
+	{"O05", "I09 Switch", "I09"},
+	{"O06", "I22 Switch", "I22"},
+	{"O05", "I14 Switch", "I14"},
+	{"O06", "I15 Switch", "I15"},
+	{"O05", "I16 Switch", "I16"},
+	{"O06", "I17 Switch", "I17"},
+	{"O05", "I18 Switch", "I18"},
+	{"O06", "I19 Switch", "I19"},
+	{"O05", "I20 Switch", "I20"},
+	{"O06", "I21 Switch", "I21"},
+	{"O05", "I23 Switch", "I23"},
+	{"O06", "I24 Switch", "I24"},
+
+	{"O09", "I03 Switch", "I03"},
+	{"O10", "I04 Switch", "I04"},
+	{"O09", "I00 Switch", "I00"},
+	{"O10", "I01 Switch", "I01"},
+	{"O09", "I09 Switch", "I09"},
+	{"O10", "I22 Switch", "I22"},
+	{"O09", "I14 Switch", "I14"},
+	{"O10", "I15 Switch", "I15"},
+	{"O09", "I16 Switch", "I16"},
+	{"O10", "I17 Switch", "I17"},
+	{"O09", "I18 Switch", "I18"},
+	{"O10", "I19 Switch", "I19"},
+	{"O09", "I20 Switch", "I20"},
+	{"O10", "I21 Switch", "I21"},
+
+	{"O11", "I03 Switch", "I03"},
+	{"O12", "I04 Switch", "I04"},
+	{"O11", "I00 Switch", "I00"},
+	{"O12", "I01 Switch", "I01"},
+	{"O11", "I09 Switch", "I09"},
+	{"O12", "I22 Switch", "I22"},
+	{"O11", "I14 Switch", "I14"},
+	{"O12", "I15 Switch", "I15"},
+	{"O11", "I16 Switch", "I16"},
+	{"O12", "I17 Switch", "I17"},
+	{"O11", "I18 Switch", "I18"},
+	{"O12", "I19 Switch", "I19"},
+	{"O11", "I20 Switch", "I20"},
+	{"O12", "I21 Switch", "I21"},
+
+	/* CM2_Mux*/
+	{"CM2_Mux IO", NULL, "CM2_Mux_IO Input Mux"},
+
+	/* VUL2 */
+	{"VUL2", NULL, "VUL2 Input Mux"},
+	{"VUL2 Input Mux", "VUL2_IN_FROM_O17O18", "O17O18"},
+	{"VUL2 Input Mux", "VUL2_IN_FROM_CM1", "CM1_IO"},
+
+	{"O17O18", NULL, "O17"},
+	{"O17O18", NULL, "O18"},
+	{"CM1_IO", NULL, "O17"},
+	{"CM1_IO", NULL, "O18"},
+	{"CM1_IO", NULL, "O19"},
+	{"CM1_IO", NULL, "O20"},
+	{"CM1_IO", NULL, "O21"},
+	{"CM1_IO", NULL, "O22"},
+	{"CM1_IO", NULL, "O23"},
+	{"CM1_IO", NULL, "O24"},
+	{"CM1_IO", NULL, "O25"},
+	{"CM1_IO", NULL, "O26"},
+	{"CM1_IO", NULL, "O31"},
+	{"CM1_IO", NULL, "O32"},
+	{"CM1_IO", NULL, "O33"},
+	{"CM1_IO", NULL, "O34"},
+	{"CM1_IO", NULL, "O35"},
+	{"CM1_IO", NULL, "O36"},
+
+	{"O17", "I14 Switch", "I14"},
+	{"O18", "I15 Switch", "I15"},
+	{"O19", "I16 Switch", "I16"},
+	{"O20", "I17 Switch", "I17"},
+	{"O21", "I18 Switch", "I18"},
+	{"O22", "I19 Switch", "I19"},
+	{"O23", "I20 Switch", "I20"},
+	{"O24", "I21 Switch", "I21"},
+	{"O25", "I23 Switch", "I23"},
+	{"O26", "I24 Switch", "I24"},
+	{"O25", "I25 Switch", "I25"},
+	{"O26", "I26 Switch", "I26"},
+
+	{"O17", "I03 Switch", "I03"},
+	{"O18", "I04 Switch", "I04"},
+	{"O18", "I23 Switch", "I23"},
+	{"O18", "I25 Switch", "I25"},
+	{"O19", "I04 Switch", "I04"},
+	{"O19", "I23 Switch", "I23"},
+	{"O19", "I24 Switch", "I24"},
+	{"O19", "I25 Switch", "I25"},
+	{"O19", "I26 Switch", "I26"},
+	{"O20", "I24 Switch", "I24"},
+	{"O20", "I26 Switch", "I26"},
+	{"O21", "I23 Switch", "I23"},
+	{"O21", "I25 Switch", "I25"},
+	{"O22", "I24 Switch", "I24"},
+	{"O22", "I26 Switch", "I26"},
+
+	{"O23", "I23 Switch", "I23"},
+	{"O23", "I25 Switch", "I25"},
+	{"O24", "I24 Switch", "I24"},
+	{"O24", "I26 Switch", "I26"},
+	{"O24", "I23 Switch", "I23"},
+	{"O24", "I25 Switch", "I25"},
+	{"O13", "I00 Switch", "I00"},
+	{"O14", "I01 Switch", "I01"},
+	{"O03", "I10 Switch", "I10"},
+	{"O04", "I11 Switch", "I11"},
+};
+
+static const struct mtk_base_memif_data memif_data[MT8365_AFE_MEMIF_NUM] = {
+	{
+		.name = "DL1",
+		.id = MT8365_AFE_MEMIF_DL1,
+		.reg_ofs_base = AFE_DL1_BASE,
+		.reg_ofs_cur = AFE_DL1_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 0,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 21,
+		.hd_reg = AFE_MEMIF_PBUF_SIZE,
+		.hd_shift = 16,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 1,
+		.msb_reg = -1,
+		.msb_shift = -1,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	}, {
+		.name = "DL2",
+		.id = MT8365_AFE_MEMIF_DL2,
+		.reg_ofs_base = AFE_DL2_BASE,
+		.reg_ofs_cur = AFE_DL2_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 4,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 22,
+		.hd_reg = AFE_MEMIF_PBUF_SIZE,
+		.hd_shift = 18,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 2,
+		.msb_reg = -1,
+		.msb_shift = -1,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	}, {
+		.name = "TDM OUT",
+		.id = MT8365_AFE_MEMIF_TDM_OUT,
+		.reg_ofs_base = AFE_HDMI_OUT_BASE,
+		.reg_ofs_cur = AFE_HDMI_OUT_CUR,
+		.fs_reg = -1,
+		.fs_shift = -1,
+		.fs_maskbit = -1,
+		.mono_reg = -1,
+		.mono_shift = -1,
+		.hd_reg = AFE_MEMIF_PBUF_SIZE,
+		.hd_shift = 28,
+		.enable_reg = AFE_HDMI_OUT_CON0,
+		.enable_shift = 0,
+		.msb_reg = -1,
+		.msb_shift = -1,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	}, {
+		.name = "AWB",
+		.id = MT8365_AFE_MEMIF_AWB,
+		.reg_ofs_base = AFE_AWB_BASE,
+		.reg_ofs_cur = AFE_AWB_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 12,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 24,
+		.hd_reg = AFE_MEMIF_PBUF_SIZE,
+		.hd_shift = 20,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 6,
+		.msb_reg = AFE_MEMIF_MSB,
+		.msb_shift = 17,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	}, {
+		.name = "VUL",
+		.id = MT8365_AFE_MEMIF_VUL,
+		.reg_ofs_base = AFE_VUL_BASE,
+		.reg_ofs_cur = AFE_VUL_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 16,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON1,
+		.mono_shift = 27,
+		.hd_reg = AFE_MEMIF_PBUF_SIZE,
+		.hd_shift = 22,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 3,
+		.msb_reg = AFE_MEMIF_MSB,
+		.msb_shift = 20,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	}, {
+		.name = "VUL2",
+		.id = MT8365_AFE_MEMIF_VUL2,
+		.reg_ofs_base = AFE_VUL_D2_BASE,
+		.reg_ofs_cur = AFE_VUL_D2_CUR,
+		.fs_reg = AFE_DAC_CON0,
+		.fs_shift = 20,
+		.fs_maskbit = 0xf,
+		.mono_reg = -1,
+		.mono_shift = -1,
+		.hd_reg = AFE_MEMIF_PBUF_SIZE,
+		.hd_shift = 14,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 9,
+		.msb_reg = AFE_MEMIF_MSB,
+		.msb_shift = 21,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	}, {
+		.name = "VUL3",
+		.id = MT8365_AFE_MEMIF_VUL3,
+		.reg_ofs_base = AFE_VUL3_BASE,
+		.reg_ofs_cur = AFE_VUL3_CUR,
+		.fs_reg = AFE_DAC_CON1,
+		.fs_shift = 8,
+		.fs_maskbit = 0xf,
+		.mono_reg = AFE_DAC_CON0,
+		.mono_shift = 13,
+		.hd_reg = AFE_MEMIF_PBUF2_SIZE,
+		.hd_shift = 10,
+		.enable_reg = AFE_DAC_CON0,
+		.enable_shift = 12,
+		.msb_reg = AFE_MEMIF_MSB,
+		.msb_shift = 27,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	}, {
+		.name = "TDM IN",
+		.id = MT8365_AFE_MEMIF_TDM_IN,
+		.reg_ofs_base = AFE_HDMI_IN_2CH_BASE,
+		.reg_ofs_cur = AFE_HDMI_IN_2CH_CUR,
+		.fs_reg = -1,
+		.fs_shift = -1,
+		.fs_maskbit = -1,
+		.mono_reg = AFE_HDMI_IN_2CH_CON0,
+		.mono_shift = 1,
+		.hd_reg = AFE_MEMIF_PBUF2_SIZE,
+		.hd_shift = 8,
+		.hd_align_mshift = 5,
+		.enable_reg = AFE_HDMI_IN_2CH_CON0,
+		.enable_shift = 0,
+		.msb_reg = AFE_MEMIF_MSB,
+		.msb_shift = 28,
+		.agent_disable_reg = -1,
+		.agent_disable_shift = -1,
+	},
+};
+
+static const struct mtk_base_irq_data irq_data[MT8365_AFE_IRQ_NUM] = {
+	{
+		.id = MT8365_AFE_IRQ1,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT1,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 0,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 4,
+		.irq_fs_maskbit = 0xf,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 0,
+	}, {
+		.id = MT8365_AFE_IRQ2,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT2,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 1,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 8,
+		.irq_fs_maskbit = 0xf,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 1,
+	}, {
+		.id = MT8365_AFE_IRQ3,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT3,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 2,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 16,
+		.irq_fs_maskbit = 0xf,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 2,
+	}, {
+		.id = MT8365_AFE_IRQ4,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT4,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 3,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 20,
+		.irq_fs_maskbit = 0xf,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 3,
+	}, {
+		.id = MT8365_AFE_IRQ5,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT5,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON2,
+		.irq_en_shift = 3,
+		.irq_fs_reg = -1,
+		.irq_fs_shift = 0,
+		.irq_fs_maskbit = 0x0,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 4,
+	}, {
+		.id = MT8365_AFE_IRQ6,
+		.irq_cnt_reg = -1,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x0,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 13,
+		.irq_fs_reg = -1,
+		.irq_fs_shift = 0,
+		.irq_fs_maskbit = 0x0,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 5,
+	}, {
+		.id = MT8365_AFE_IRQ7,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT7,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 14,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 24,
+		.irq_fs_maskbit = 0xf,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 6,
+	}, {
+		.id = MT8365_AFE_IRQ8,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT8,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON,
+		.irq_en_shift = 15,
+		.irq_fs_reg = AFE_IRQ_MCU_CON,
+		.irq_fs_shift = 28,
+		.irq_fs_maskbit = 0xf,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 7,
+	}, {
+		.id = MT8365_AFE_IRQ9,
+		.irq_cnt_reg = -1,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x0,
+		.irq_en_reg = AFE_IRQ_MCU_CON2,
+		.irq_en_shift = 2,
+		.irq_fs_reg = -1,
+		.irq_fs_shift = 0,
+		.irq_fs_maskbit = 0x0,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 8,
+	}, {
+		.id = MT8365_AFE_IRQ10,
+		.irq_cnt_reg = AFE_IRQ_MCU_CNT10,
+		.irq_cnt_shift = 0,
+		.irq_cnt_maskbit = 0x3ffff,
+		.irq_en_reg = AFE_IRQ_MCU_CON2,
+		.irq_en_shift = 4,
+		.irq_fs_reg = -1,
+		.irq_fs_shift = 0,
+		.irq_fs_maskbit = 0x0,
+		.irq_clr_reg = AFE_IRQ_MCU_CLR,
+		.irq_clr_shift = 9,
+	},
+};
+
+static int memif_specified_irqs[MT8365_AFE_MEMIF_NUM] = {
+	[MT8365_AFE_MEMIF_DL1] = MT8365_AFE_IRQ1,
+	[MT8365_AFE_MEMIF_DL2] = MT8365_AFE_IRQ2,
+	[MT8365_AFE_MEMIF_TDM_OUT] = MT8365_AFE_IRQ5,
+	[MT8365_AFE_MEMIF_AWB] = MT8365_AFE_IRQ3,
+	[MT8365_AFE_MEMIF_VUL] = MT8365_AFE_IRQ4,
+	[MT8365_AFE_MEMIF_VUL2] = MT8365_AFE_IRQ7,
+	[MT8365_AFE_MEMIF_VUL3] = MT8365_AFE_IRQ8,
+	[MT8365_AFE_MEMIF_TDM_IN] = MT8365_AFE_IRQ10,
+};
+
+static const struct regmap_config mt8365_afe_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.max_register = MAX_REGISTER,
+	.cache_type = REGCACHE_NONE,
+};
+
+static irqreturn_t mt8365_afe_irq_handler(int irq, void *dev_id)
+{
+	struct mtk_base_afe *afe = dev_id;
+	unsigned int reg_value;
+	unsigned int mcu_irq_mask;
+	int i, ret;
+
+	ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &reg_value);
+	if (ret) {
+		dev_err_ratelimited(afe->dev, "%s irq status err\n", __func__);
+		reg_value = AFE_IRQ_STATUS_BITS;
+		goto err_irq;
+	}
+
+	ret = regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_irq_mask);
+	if (ret) {
+		dev_err_ratelimited(afe->dev, "%s irq mcu_en err\n", __func__);
+		reg_value = AFE_IRQ_STATUS_BITS;
+		goto err_irq;
+	}
+
+	/* only clr cpu irq */
+	reg_value &= mcu_irq_mask;
+
+	for (i = 0; i < MT8365_AFE_MEMIF_NUM; i++) {
+		struct mtk_base_afe_memif *memif = &afe->memif[i];
+		struct mtk_base_afe_irq *mcu_irq;
+
+		if (memif->irq_usage < 0)
+			continue;
+
+		mcu_irq = &afe->irqs[memif->irq_usage];
+
+		if (!(reg_value & (1 << mcu_irq->irq_data->irq_clr_shift)))
+			continue;
+
+		snd_pcm_period_elapsed(memif->substream);
+	}
+
+err_irq:
+	/* clear irq */
+	regmap_write(afe->regmap, AFE_IRQ_MCU_CLR,
+		     reg_value & AFE_IRQ_STATUS_BITS);
+
+	return IRQ_HANDLED;
+}
+
+static int __maybe_unused mt8365_afe_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int mt8365_afe_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+static int __maybe_unused mt8365_afe_suspend(struct device *dev)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dev);
+	struct regmap *regmap = afe->regmap;
+	int i;
+
+	mt8365_afe_enable_main_clk(afe);
+
+	if (!afe->reg_back_up)
+		afe->reg_back_up =
+			devm_kcalloc(dev, afe->reg_back_up_list_num,
+				     sizeof(unsigned int), GFP_KERNEL);
+
+	for (i = 0; i < afe->reg_back_up_list_num; i++)
+		regmap_read(regmap, afe->reg_back_up_list[i],
+			    &afe->reg_back_up[i]);
+
+	mt8365_afe_disable_main_clk(afe);
+
+	return 0;
+}
+
+static int __maybe_unused mt8365_afe_resume(struct device *dev)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dev);
+	struct regmap *regmap = afe->regmap;
+	int i = 0;
+
+	if (!afe->reg_back_up)
+		return 0;
+
+	mt8365_afe_enable_main_clk(afe);
+
+	for (i = 0; i < afe->reg_back_up_list_num; i++)
+		regmap_write(regmap, afe->reg_back_up_list[i],
+			     afe->reg_back_up[i]);
+
+	mt8365_afe_disable_main_clk(afe);
+
+	return 0;
+}
+
+static int __maybe_unused mt8365_afe_dev_runtime_suspend(struct device *dev)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dev);
+
+	if (pm_runtime_status_suspended(dev) || afe->suspended)
+		return 0;
+
+	mt8365_afe_suspend(dev);
+	afe->suspended = true;
+	return 0;
+}
+
+static int __maybe_unused mt8365_afe_dev_runtime_resume(struct device *dev)
+{
+	struct mtk_base_afe *afe = dev_get_drvdata(dev);
+
+	if (pm_runtime_status_suspended(dev) || !afe->suspended)
+		return 0;
+
+	mt8365_afe_resume(dev);
+	afe->suspended = false;
+	return 0;
+}
+
+static int mt8365_afe_init_registers(struct mtk_base_afe *afe)
+{
+	size_t i;
+
+	static struct {
+		unsigned int reg;
+		unsigned int mask;
+		unsigned int val;
+	} init_regs[] = {
+		{ AFE_CONN_24BIT, GENMASK(31, 0), GENMASK(31, 0) },
+		{ AFE_CONN_24BIT_1, GENMASK(21, 0), GENMASK(21, 0) },
+	};
+
+	mt8365_afe_enable_main_clk(afe);
+
+	for (i = 0; i < ARRAY_SIZE(init_regs); i++)
+		regmap_update_bits(afe->regmap, init_regs[i].reg,
+				   init_regs[i].mask, init_regs[i].val);
+
+	mt8365_afe_disable_main_clk(afe);
+
+	return 0;
+}
+
+static int mt8365_dai_memif_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 = mt8365_memif_dai_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mt8365_memif_dai_driver);
+
+	dai->dapm_widgets = mt8365_memif_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mt8365_memif_widgets);
+	dai->dapm_routes = mt8365_memif_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mt8365_memif_routes);
+	return 0;
+}
+
+typedef int (*dai_register_cb)(struct mtk_base_afe *);
+static const dai_register_cb dai_register_cbs[] = {
+	mt8365_dai_pcm_register,
+	mt8365_dai_i2s_register,
+	mt8365_dai_adda_register,
+	mt8365_dai_dmic_register,
+	mt8365_dai_memif_register,
+};
+
+static int mt8365_afe_pcm_dev_probe(struct platform_device *pdev)
+{
+	struct mtk_base_afe *afe;
+	struct mt8365_afe_private *afe_priv;
+	struct device *dev;
+	int ret, i, sel_irq;
+	unsigned int irq_id;
+	struct resource *res;
+
+	afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
+	if (!afe)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, afe);
+
+	afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
+					  GFP_KERNEL);
+	if (!afe->platform_priv)
+		return -ENOMEM;
+
+	afe_priv = afe->platform_priv;
+	afe->dev = &pdev->dev;
+	dev = afe->dev;
+
+	spin_lock_init(&afe_priv->afe_ctrl_lock);
+	mutex_init(&afe_priv->afe_clk_mutex);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(afe->base_addr))
+		return PTR_ERR(afe->base_addr);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res) {
+		afe_priv->afe_sram_vir_addr =
+			devm_ioremap_resource(&pdev->dev, res);
+		if (!IS_ERR(afe_priv->afe_sram_vir_addr)) {
+			afe_priv->afe_sram_phy_addr = res->start;
+			afe_priv->afe_sram_size = resource_size(res);
+		}
+	}
+
+	/* initial audio related clock */
+	ret = mt8365_afe_init_audio_clk(afe);
+	if (ret)
+		return dev_err_probe(afe->dev, ret, "mt8365_afe_init_audio_clk fail\n");
+
+	afe->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "top_audio_sel",
+						afe->base_addr,
+						&mt8365_afe_regmap_config);
+	if (IS_ERR(afe->regmap))
+		return PTR_ERR(afe->regmap);
+
+	/* memif % irq initialize*/
+	afe->memif_size = MT8365_AFE_MEMIF_NUM;
+	afe->memif = devm_kcalloc(afe->dev, afe->memif_size,
+				  sizeof(*afe->memif), GFP_KERNEL);
+	if (!afe->memif)
+		return -ENOMEM;
+
+	afe->irqs_size = MT8365_AFE_IRQ_NUM;
+	afe->irqs = devm_kcalloc(afe->dev, afe->irqs_size,
+				 sizeof(*afe->irqs), GFP_KERNEL);
+	if (!afe->irqs)
+		return -ENOMEM;
+
+	for (i = 0; i < afe->irqs_size; i++)
+		afe->irqs[i].irq_data = &irq_data[i];
+
+	irq_id = platform_get_irq(pdev, 0);
+	if (!irq_id) {
+		dev_err_probe(afe->dev, irq_id, "np %s no irq\n", afe->dev->of_node->name);
+		return -ENXIO;
+	}
+	ret = devm_request_irq(afe->dev, irq_id, mt8365_afe_irq_handler,
+			       0, "Afe_ISR_Handle", (void *)afe);
+	if (ret)
+		return dev_err_probe(afe->dev, ret, "could not request_irq\n");
+
+	/* init sub_dais */
+	INIT_LIST_HEAD(&afe->sub_dais);
+
+	for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
+		ret = dai_register_cbs[i](afe);
+		if (ret) {
+			dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
+				 i, ret);
+			return ret;
+		}
+	}
+
+	/* init dai_driver and component_driver */
+	ret = mtk_afe_combine_sub_dai(afe);
+	if (ret) {
+		dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
+			 ret);
+		return ret;
+	}
+
+	for (i = 0; i < afe->memif_size; i++) {
+		afe->memif[i].data = &memif_data[i];
+		sel_irq = memif_specified_irqs[i];
+		if (sel_irq >= 0) {
+			afe->memif[i].irq_usage = sel_irq;
+			afe->memif[i].const_irq = 1;
+			afe->irqs[sel_irq].irq_occupyed = true;
+		} else {
+			afe->memif[i].irq_usage = -1;
+		}
+	}
+
+	afe->mtk_afe_hardware = &mt8365_afe_hardware;
+	afe->memif_fs = mt8365_memif_fs;
+	afe->irq_fs = mt8365_irq_fs;
+
+	ret = devm_pm_runtime_enable(&pdev->dev);
+	if (ret)
+		return ret;
+
+	pm_runtime_get_sync(&pdev->dev);
+	afe->reg_back_up_list = mt8365_afe_backup_list;
+	afe->reg_back_up_list_num = ARRAY_SIZE(mt8365_afe_backup_list);
+	afe->runtime_resume = mt8365_afe_runtime_resume;
+	afe->runtime_suspend = mt8365_afe_runtime_suspend;
+
+	/* open afe pdn for dapm read/write audio register */
+	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_AFE);
+
+	/* Set 26m parent clk */
+	mt8365_afe_set_clk_parent(afe,
+				  afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL],
+				  afe_priv->clocks[MT8365_CLK_CLK26M]);
+
+	ret = devm_snd_soc_register_component(&pdev->dev,
+					      &mtk_afe_pcm_platform,
+					      afe->dai_drivers,
+					      afe->num_dai_drivers);
+	if (ret) {
+		dev_warn(dev, "err_platform\n");
+		return ret;
+	}
+
+	mt8365_afe_init_registers(afe);
+
+	return 0;
+}
+
+static void mt8365_afe_pcm_dev_remove(struct platform_device *pdev)
+{
+	struct mtk_base_afe *afe = platform_get_drvdata(pdev);
+
+	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_AFE);
+
+	pm_runtime_disable(&pdev->dev);
+	if (!pm_runtime_status_suspended(&pdev->dev))
+		mt8365_afe_runtime_suspend(&pdev->dev);
+}
+
+static const struct of_device_id mt8365_afe_pcm_dt_match[] = {
+	{ .compatible = "mediatek,mt8365-afe-pcm", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mt8365_afe_pcm_dt_match);
+
+static const struct dev_pm_ops mt8365_afe_pm_ops = {
+	SET_RUNTIME_PM_OPS(mt8365_afe_dev_runtime_suspend,
+			   mt8365_afe_dev_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(mt8365_afe_suspend,
+				mt8365_afe_resume)
+};
+
+static struct platform_driver mt8365_afe_pcm_driver = {
+	.driver = {
+		   .name = "mt8365-afe-pcm",
+		   .of_match_table = mt8365_afe_pcm_dt_match,
+		   .pm = &mt8365_afe_pm_ops,
+	},
+	.probe = mt8365_afe_pcm_dev_probe,
+	.remove_new = mt8365_afe_pcm_dev_remove,
+};
+
+module_platform_driver(mt8365_afe_pcm_driver);
+
+MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver");
+MODULE_AUTHOR("Jia Zeng <jia.zeng@mediatek.com>");
+MODULE_AUTHOR("Alexandre Mergnat <amergnat@baylibre.com>");
+MODULE_LICENSE("GPL");

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 11/18] ASoc: mediatek: mt8365: Add a specific soundcard for EVK
From: amergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat, Nicolas Belin
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

From: Nicolas Belin <nbelin@baylibre.com>

Add a specific soundcard for mt8365-evk. It supports audio jack
in/out, dmics, the amic and lineout.

Signed-off-by: Nicolas Belin <nbelin@baylibre.com>
Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/mt8365/mt8365-mt6357.c | 348 ++++++++++++++++++++++++++++++
 1 file changed, 348 insertions(+)

diff --git a/sound/soc/mediatek/mt8365/mt8365-mt6357.c b/sound/soc/mediatek/mt8365/mt8365-mt6357.c
new file mode 100644
index 000000000000..9f1be194fe34
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-mt6357.c
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek MT8365 Sound Card driver
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Nicolas Belin <nbelin@baylibre.com>
+ */
+
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include "mt8365-afe-common.h"
+#include <linux/pinctrl/consumer.h>
+#include "../common/mtk-soc-card.h"
+#include "../common/mtk-soundcard-driver.h"
+
+enum pinctrl_pin_state {
+	PIN_STATE_DEFAULT,
+	PIN_STATE_DMIC,
+	PIN_STATE_MISO_OFF,
+	PIN_STATE_MISO_ON,
+	PIN_STATE_MOSI_OFF,
+	PIN_STATE_MOSI_ON,
+	PIN_STATE_MAX
+};
+
+static const char * const mt8365_mt6357_pin_str[PIN_STATE_MAX] = {
+	"default",
+	"dmic",
+	"miso_off",
+	"miso_on",
+	"mosi_off",
+	"mosi_on",
+};
+
+struct mt8365_mt6357_priv {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pin_states[PIN_STATE_MAX];
+};
+
+enum {
+	/* FE */
+	DAI_LINK_DL1_PLAYBACK = 0,
+	DAI_LINK_DL2_PLAYBACK,
+	DAI_LINK_AWB_CAPTURE,
+	DAI_LINK_VUL_CAPTURE,
+	/* BE */
+	DAI_LINK_2ND_I2S_INTF,
+	DAI_LINK_DMIC,
+	DAI_LINK_INT_ADDA,
+	DAI_LINK_NUM
+};
+
+static const struct snd_soc_dapm_widget mt8365_mt6357_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("HDMI Out"),
+};
+
+static const struct snd_soc_dapm_route mt8365_mt6357_routes[] = {
+	{"HDMI Out", NULL, "2ND I2S Playback"},
+	{"DMIC In", NULL, "MICBIAS0"},
+};
+
+static int mt8365_mt6357_int_adda_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+	int ret = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_ON]))
+			return ret;
+
+		ret = pinctrl_select_state(priv->pinctrl,
+					   priv->pin_states[PIN_STATE_MOSI_ON]);
+		if (ret)
+			dev_err(rtd->card->dev, "%s failed to select state %d\n",
+				__func__, ret);
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (IS_ERR(priv->pin_states[PIN_STATE_MISO_ON]))
+			return ret;
+
+		ret = pinctrl_select_state(priv->pinctrl,
+					   priv->pin_states[PIN_STATE_MISO_ON]);
+		if (ret)
+			dev_err(rtd->card->dev, "%s failed to select state %d\n",
+				__func__, ret);
+	}
+
+	return 0;
+}
+
+static void mt8365_mt6357_int_adda_shutdown(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+	int ret = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_OFF]))
+			return;
+
+		ret = pinctrl_select_state(priv->pinctrl,
+					   priv->pin_states[PIN_STATE_MOSI_OFF]);
+		if (ret)
+			dev_err(rtd->card->dev, "%s failed to select state %d\n",
+				__func__, ret);
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (IS_ERR(priv->pin_states[PIN_STATE_MISO_OFF]))
+			return;
+
+		ret = pinctrl_select_state(priv->pinctrl,
+					   priv->pin_states[PIN_STATE_MISO_OFF]);
+		if (ret)
+			dev_err(rtd->card->dev, "%s failed to select state %d\n",
+				__func__, ret);
+	}
+}
+
+static const struct snd_soc_ops mt8365_mt6357_int_adda_ops = {
+	.startup = mt8365_mt6357_int_adda_startup,
+	.shutdown = mt8365_mt6357_int_adda_shutdown,
+};
+
+SND_SOC_DAILINK_DEFS(playback1,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(playback2,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(awb_capture,
+		     DAILINK_COMP_ARRAY(COMP_CPU("AWB")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(vul,
+		     DAILINK_COMP_ARRAY(COMP_CPU("VUL")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(i2s3,
+		     DAILINK_COMP_ARRAY(COMP_CPU("2ND I2S")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(dmic,
+		     DAILINK_COMP_ARRAY(COMP_CPU("DMIC")),
+		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(primary_codec,
+		     DAILINK_COMP_ARRAY(COMP_CPU("INT ADDA")),
+		     DAILINK_COMP_ARRAY(COMP_CODEC("mt6357-sound", "mt6357-snd-codec-aif1")),
+		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
+	/* Front End DAI links */
+	[DAI_LINK_DL1_PLAYBACK] = {
+		.name = "DL1_FE",
+		.stream_name = "MultiMedia1_PLayback",
+		.id = DAI_LINK_DL1_PLAYBACK,
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_merged_rate = 1,
+		SND_SOC_DAILINK_REG(playback1),
+	},
+	[DAI_LINK_DL2_PLAYBACK] = {
+		.name = "DL2_FE",
+		.stream_name = "MultiMedia2_PLayback",
+		.id = DAI_LINK_DL2_PLAYBACK,
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST
+		},
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_merged_rate = 1,
+		SND_SOC_DAILINK_REG(playback2),
+	},
+	[DAI_LINK_AWB_CAPTURE] = {
+		.name = "AWB_FE",
+		.stream_name = "DL1_AWB_Record",
+		.id = DAI_LINK_AWB_CAPTURE,
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.dpcm_merged_rate = 1,
+		SND_SOC_DAILINK_REG(awb_capture),
+	},
+	[DAI_LINK_VUL_CAPTURE] = {
+		.name = "VUL_FE",
+		.stream_name = "MultiMedia1_Capture",
+		.id = DAI_LINK_VUL_CAPTURE,
+		.trigger = {
+			SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST
+		},
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.dpcm_merged_rate = 1,
+		SND_SOC_DAILINK_REG(vul),
+	},
+	/* Back End DAI links */
+	[DAI_LINK_2ND_I2S_INTF] = {
+		.name = "2ND_I2S_BE",
+		.no_pcm = 1,
+		.id = DAI_LINK_2ND_I2S_INTF,
+		.dai_fmt = SND_SOC_DAIFMT_I2S |
+				SND_SOC_DAIFMT_NB_NF |
+				SND_SOC_DAIFMT_CBS_CFS,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(i2s3),
+	},
+	[DAI_LINK_DMIC] = {
+		.name = "DMIC_BE",
+		.no_pcm = 1,
+		.id = DAI_LINK_DMIC,
+		.dpcm_capture = 1,
+		SND_SOC_DAILINK_REG(dmic),
+	},
+	[DAI_LINK_INT_ADDA] = {
+		.name = "MTK_Codec",
+		.no_pcm = 1,
+		.id = DAI_LINK_INT_ADDA,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.ops = &mt8365_mt6357_int_adda_ops,
+		SND_SOC_DAILINK_REG(primary_codec),
+	},
+};
+
+static int mt8365_mt6357_gpio_probe(struct snd_soc_card *card)
+{
+	struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(card);
+	int ret, i;
+
+	priv->pinctrl = devm_pinctrl_get(card->dev);
+	if (IS_ERR(priv->pinctrl)) {
+		ret = PTR_ERR(priv->pinctrl);
+		return dev_err_probe(card->dev, ret,
+				     "Failed to get pinctrl\n");
+	}
+
+	for (i = PIN_STATE_DEFAULT ; i < PIN_STATE_MAX ; i++) {
+		priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl,
+							   mt8365_mt6357_pin_str[i]);
+		if (IS_ERR(priv->pin_states[i])) {
+			ret = PTR_ERR(priv->pin_states[i]);
+			dev_warn(card->dev, "No pin state for %s\n",
+				 mt8365_mt6357_pin_str[i]);
+		} else {
+			ret = pinctrl_select_state(priv->pinctrl,
+						   priv->pin_states[i]);
+			if (ret) {
+				dev_err_probe(card->dev, ret,
+					      "Failed to select pin state %s\n",
+					      mt8365_mt6357_pin_str[i]);
+				return ret;
+			}
+		}
+	}
+	return 0;
+}
+
+static struct snd_soc_card mt8365_mt6357_soc_card = {
+	.name = "mt8365-evk",
+	.owner = THIS_MODULE,
+	.dai_link = mt8365_mt6357_dais,
+	.num_links = ARRAY_SIZE(mt8365_mt6357_dais),
+	.dapm_widgets = mt8365_mt6357_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(mt8365_mt6357_widgets),
+	.dapm_routes = mt8365_mt6357_routes,
+	.num_dapm_routes = ARRAY_SIZE(mt8365_mt6357_routes),
+};
+
+static int mt8365_mt6357_dev_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
+{
+	struct mtk_platform_card_data *card_data = soc_card_data->card_data;
+	struct snd_soc_card *card = card_data->card;
+	struct device *dev = card->dev;
+	struct device_node *platform_node;
+	struct mt8365_mt6357_priv *mach_priv;
+	int i, ret;
+
+	card->dev = dev;
+	ret = parse_dai_link_info(card);
+	if (ret)
+		goto err;
+
+	mach_priv = devm_kzalloc(dev, sizeof(*mach_priv),
+				 GFP_KERNEL);
+	if (!mach_priv)
+		return -ENOMEM;
+	soc_card_data->mach_priv = mach_priv;
+	snd_soc_card_set_drvdata(card, soc_card_data);
+	mt8365_mt6357_gpio_probe(card);
+	return 0;
+
+err:
+	clean_card_reference(card);
+	return ret;
+}
+
+static const struct mtk_soundcard_pdata mt8365_mt6357_card = {
+	.card_name = "mt8365-mt6357",
+	.card_data = &(struct mtk_platform_card_data) {
+		.card = &mt8365_mt6357_soc_card,
+	},
+	.soc_probe = mt8365_mt6357_dev_probe
+};
+
+static const struct of_device_id mt8365_mt6357_dt_match[] = {
+	{
+		.compatible = "mediatek,mt8365-mt6357",
+		.data = &mt8365_mt6357_card,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mt8365_mt6357_dt_match);
+
+static struct platform_driver mt8365_mt6357_driver = {
+	.driver = {
+		   .name = "mt8365_mt6357",
+		   .of_match_table = mt8365_mt6357_dt_match,
+		   .pm = &snd_soc_pm_ops,
+	},
+	.probe = mtk_soundcard_common_probe,
+};
+
+module_platform_driver(mt8365_mt6357_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8365 EVK SoC machine driver");
+MODULE_AUTHOR("Nicolas Belin <nbelin@baylibre.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform: mt8365_mt6357");

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 08/18] ASoC: mediatek: mt8365: Add ADDA DAI support
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add ADDA Device Audio Interface support for MT8365 SoC.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/mt8365/mt8365-dai-adda.c | 315 ++++++++++++++++++++++++++++
 1 file changed, 315 insertions(+)

diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-adda.c b/sound/soc/mediatek/mt8365/mt8365-dai-adda.c
new file mode 100644
index 000000000000..65d45010ac90
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-dai-adda.c
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek 8365 ALSA SoC Audio DAI ADDA Control
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8365-afe-clk.h"
+#include "mt8365-afe-common.h"
+#include "../common/mtk-dai-adda-common.h"
+
+static int adda_afe_on_ref_cnt;
+
+/* DAI Drivers */
+
+static int mt8365_dai_set_adda_out(struct mtk_base_afe *afe, unsigned int rate)
+{
+	unsigned int val;
+
+	switch (rate) {
+	case 8000:
+		val = AFE_ADDA_DL_VOICE_DATA;
+		break;
+	case 16000:
+		val = AFE_ADDA_DL_VOICE_DATA;
+		break;
+	default:
+		val = 0;
+	}
+
+	val |= FIELD_PREP(AFE_ADDA_DL_SAMPLING_RATE,
+		mtk_adda_dl_rate_transform(afe, rate));
+	val |= AFE_ADDA_DL_8X_UPSAMPLE |
+	       AFE_ADDA_DL_MUTE_OFF_CH1 |
+	       AFE_ADDA_DL_MUTE_OFF_CH2 |
+	       AFE_ADDA_DL_DEGRADE_GAIN;
+
+	regmap_update_bits(afe->regmap, AFE_ADDA_PREDIS_CON0, 0xffffffff, 0);
+	regmap_update_bits(afe->regmap, AFE_ADDA_PREDIS_CON1, 0xffffffff, 0);
+	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 0xffffffff, val);
+	/* SA suggest apply -0.3db to audio/speech path */
+	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON1,
+			   0xffffffff, 0xf74f0000);
+	/* SA suggest use default value for sdm */
+	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SDM_DCCOMP_CON,
+			   0xffffffff, 0x0700701e);
+
+	return 0;
+}
+
+static int mt8365_dai_set_adda_in(struct mtk_base_afe *afe, unsigned int rate)
+{
+	unsigned int val;
+
+	val = FIELD_PREP(AFE_ADDA_UL_SAMPLING_RATE,
+			 mtk_adda_ul_rate_transform(afe, rate));
+	regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,
+			   AFE_ADDA_UL_SAMPLING_RATE, val);
+	/* Using Internal ADC */
+	regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x0);
+
+	return 0;
+}
+
+int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe)
+{
+	unsigned long flags;
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+
+	adda_afe_on_ref_cnt++;
+	if (adda_afe_on_ref_cnt == 1)
+		regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
+				   AFE_ADDA_UL_DL_ADDA_AFE_ON,
+				   AFE_ADDA_UL_DL_ADDA_AFE_ON);
+
+	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
+	return 0;
+}
+
+int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe)
+{
+	unsigned long flags;
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+
+	adda_afe_on_ref_cnt--;
+	if (adda_afe_on_ref_cnt == 0)
+		regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
+				   AFE_ADDA_UL_DL_ADDA_AFE_ON,
+				   ~AFE_ADDA_UL_DL_ADDA_AFE_ON);
+	else if (adda_afe_on_ref_cnt < 0)
+		adda_afe_on_ref_cnt = 0;
+
+	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
+	return 0;
+}
+
+static void mt8365_dai_set_adda_out_enable(struct mtk_base_afe *afe,
+					   bool enable)
+{
+	regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, 0x1, enable);
+
+	if (enable)
+		mt8365_dai_enable_adda_on(afe);
+	else
+		mt8365_dai_disable_adda_on(afe);
+}
+
+static void mt8365_dai_set_adda_in_enable(struct mtk_base_afe *afe, bool enable)
+{
+	if (enable) {
+		regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 0x1, 0x1);
+		mt8365_dai_enable_adda_on(afe);
+		/* enable aud_pad_top fifo */
+		regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP,
+				   0xffffffff, 0x31);
+	} else {
+		/* disable aud_pad_top fifo */
+		regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP,
+				   0xffffffff, 0x30);
+		regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, 0x1, 0x0);
+		/* de suggest disable ADDA_UL_SRC at least wait 125us */
+		usleep_range(150, 300);
+		mt8365_dai_disable_adda_on(afe);
+	}
+}
+
+static int mt8365_dai_int_adda_startup(struct snd_pcm_substream *substream,
+				       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	unsigned int stream = substream->stream;
+
+	mt8365_afe_enable_main_clk(afe);
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DAC);
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DAC_PREDIS);
+	} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_ADC);
+	}
+
+	return 0;
+}
+
+static void mt8365_dai_int_adda_shutdown(struct snd_pcm_substream *substream,
+					 struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_be_dai_data *be =
+		&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+	unsigned int stream = substream->stream;
+
+	if (be->prepared[stream]) {
+		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			mt8365_dai_set_adda_out_enable(afe, false);
+			mt8365_afe_set_i2s_out_enable(afe, false);
+		} else {
+			mt8365_dai_set_adda_in_enable(afe, false);
+		}
+		be->prepared[stream] = false;
+	}
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DAC_PREDIS);
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DAC);
+	} else if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_ADC);
+	}
+
+	mt8365_afe_disable_main_clk(afe);
+}
+
+static int mt8365_dai_int_adda_prepare(struct snd_pcm_substream *substream,
+				       struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_be_dai_data *be =
+		&afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+	unsigned int rate = substream->runtime->rate;
+	int bit_width = snd_pcm_format_width(substream->runtime->format);
+	int ret;
+
+	dev_info(afe->dev, "%s '%s' rate = %u\n", __func__,
+		 snd_pcm_stream_str(substream), rate);
+
+	if (be->prepared[substream->stream]) {
+		dev_info(afe->dev, "%s '%s' prepared already\n",
+			 __func__, snd_pcm_stream_str(substream));
+		return 0;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = mt8365_dai_set_adda_out(afe, rate);
+		if (ret)
+			return ret;
+
+		ret = mt8365_afe_set_i2s_out(afe, rate, bit_width);
+		if (ret)
+			return ret;
+
+		mt8365_dai_set_adda_out_enable(afe, true);
+		mt8365_afe_set_i2s_out_enable(afe, true);
+	} else {
+		ret = mt8365_dai_set_adda_in(afe, rate);
+		if (ret)
+			return ret;
+
+		mt8365_dai_set_adda_in_enable(afe, true);
+	}
+	be->prepared[substream->stream] = true;
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mt8365_afe_int_adda_ops = {
+	.startup	= mt8365_dai_int_adda_startup,
+	.shutdown	= mt8365_dai_int_adda_shutdown,
+	.prepare	= mt8365_dai_int_adda_prepare,
+};
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+	{
+		.name = "INT ADDA",
+		.id = MT8365_AFE_IO_INT_ADDA,
+		.playback = {
+			.stream_name = "INT ADDA Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.capture = {
+			.stream_name = "INT ADDA Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_16000 |
+				 SNDRV_PCM_RATE_32000 |
+				 SNDRV_PCM_RATE_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_int_adda_ops,
+	}
+};
+
+/* DAI Controls */
+
+static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN3,
+				    10, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {
+	SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN4,
+				    11, 1, 0),
+};
+
+static const struct snd_kcontrol_new int_adda_o03_o04_enable_ctl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+/* DAI widget */
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+	SND_SOC_DAPM_SWITCH("INT ADDA O03_O04", SND_SOC_NOPM, 0, 0,
+			    &int_adda_o03_o04_enable_ctl),
+	/* inter-connections */
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch1_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch1_mix)),
+	SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,
+			   mtk_adda_dl_ch2_mix,
+			   ARRAY_SIZE(mtk_adda_dl_ch2_mix)),
+};
+
+/* DAI route */
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+	{"INT ADDA O03_O04", "Switch", "O03"},
+	{"INT ADDA O03_O04", "Switch", "O04"},
+	{"INT ADDA Playback", NULL, "INT ADDA O03_O04"},
+	{"INT ADDA Playback", NULL, "ADDA_DL_CH1"},
+	{"INT ADDA Playback", NULL, "ADDA_DL_CH2"},
+	{"AIN Mux", "INT ADC", "INT ADDA Capture"},
+	{"ADDA_DL_CH1", "GAIN1_OUT_CH1", "Hostless FM DL"},
+	{"ADDA_DL_CH2", "GAIN1_OUT_CH2", "Hostless FM DL"},
+};
+
+int mt8365_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);
+	return 0;
+}

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 15/18] arm64: defconfig: enable mt8365 sound
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Enable the MediaTek MT8365-EVK sound support.

The audio feature is handled by the MT8365 SoC and
the MT6357 PMIC codec audio.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 2c30d617e180..40e88cdafa3a 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -939,6 +939,8 @@ CONFIG_SND_SOC_MT8192=m
 CONFIG_SND_SOC_MT8192_MT6359_RT1015_RT5682=m
 CONFIG_SND_SOC_MT8195=m
 CONFIG_SND_SOC_MT8195_MT6359=m
+CONFIG_SND_SOC_MT8365=m
+CONFIG_SND_SOC_MT8365_MT6357=m
 CONFIG_SND_MESON_AXG_SOUND_CARD=m
 CONFIG_SND_MESON_GX_SOUND_CARD=m
 CONFIG_SND_SOC_QCOM=m

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 07/18] ASoC: mediatek: mt8365: Add I2S DAI support
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add I2S Device Audio Interface support for MT8365 SoC.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/mt8365/mt8365-dai-i2s.c | 854 +++++++++++++++++++++++++++++
 1 file changed, 854 insertions(+)

diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c
new file mode 100644
index 000000000000..c12d75dfe215
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c
@@ -0,0 +1,854 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek 8365 ALSA SoC Audio DAI I2S Control
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8365-afe-clk.h"
+#include "mt8365-afe-common.h"
+
+struct mtk_afe_i2s_priv {
+	bool adda_link;
+	int i2s_out_on_ref_cnt;
+	int id;
+	int low_jitter_en;
+	int mclk_id;
+	int share_i2s_id;
+	unsigned int clk_id_in;
+	unsigned int clk_id_in_m_sel;
+	unsigned int clk_id_out;
+	unsigned int clk_id_out_m_sel;
+	unsigned int clk_in_mult;
+	unsigned int clk_out_mult;
+	unsigned int config_val_in;
+	unsigned int config_val_out;
+	unsigned int dynamic_bck;
+	unsigned int reg_off_in;
+	unsigned int reg_off_out;
+};
+
+/* This enum is merely for mtk_afe_i2s_priv declare */
+enum {
+	DAI_I2S0 = 0,
+	DAI_I2S3,
+	DAI_I2S_NUM,
+};
+
+static const struct mtk_afe_i2s_priv mt8365_i2s_priv[DAI_I2S_NUM] = {
+	[DAI_I2S0] = {
+		.id = MT8365_AFE_IO_I2S,
+		.mclk_id = MT8365_I2S0_MCK,
+		.share_i2s_id = -1,
+		.clk_id_in = MT8365_CLK_AUD_I2S2_M,
+		.clk_id_out = MT8365_CLK_AUD_I2S1_M,
+		.clk_id_in_m_sel = MT8365_CLK_I2S2_M_SEL,
+		.clk_id_out_m_sel = MT8365_CLK_I2S1_M_SEL,
+		.clk_in_mult = 256,
+		.clk_out_mult = 256,
+		.adda_link = true,
+		.config_val_out = AFE_I2S_CON1_I2S2_TO_PAD,
+		.reg_off_in = AFE_I2S_CON2,
+		.reg_off_out = AFE_I2S_CON1,
+	},
+	[DAI_I2S3] = {
+		.id = MT8365_AFE_IO_2ND_I2S,
+		.mclk_id = MT8365_I2S3_MCK,
+		.share_i2s_id = -1,
+		.clk_id_in = MT8365_CLK_AUD_I2S0_M,
+		.clk_id_out = MT8365_CLK_AUD_I2S3_M,
+		.clk_id_in_m_sel = MT8365_CLK_I2S0_M_SEL,
+		.clk_id_out_m_sel = MT8365_CLK_I2S3_M_SEL,
+		.clk_in_mult = 256,
+		.clk_out_mult = 256,
+		.adda_link = false,
+		.config_val_in = AFE_I2S_CON_FROM_IO_MUX,
+		.reg_off_in = AFE_I2S_CON,
+		.reg_off_out = AFE_I2S_CON3,
+	},
+};
+
+static const u32 *get_iir_coef(unsigned int input_fs,
+			       unsigned int output_fs, unsigned int *count)
+{
+#define RATIOVER 9
+#define INV_COEF 10
+#define NO_NEED 11
+
+	static const u32 IIR_COEF_48_TO_44p1[30] = {
+		0x061fb0, 0x0bd256, 0x061fb0, 0xe3a3e6, 0xf0a300, 0x000003,
+		0x0e416d, 0x1bb577, 0x0e416d, 0xe59178, 0xf23637, 0x000003,
+		0x0c7d72, 0x189060, 0x0c7d72, 0xe96f09, 0xf505b2, 0x000003,
+		0x126054, 0x249143, 0x126054, 0xe1fc0c, 0xf4b20a, 0x000002,
+		0x000000, 0x323c85, 0x323c85, 0xf76d4e, 0x000000, 0x000002,
+	};
+
+	static const u32 IIR_COEF_44p1_TO_32[42] = {
+		0x0a6074, 0x0d237a, 0x0a6074, 0xdd8d6c, 0xe0b3f6, 0x000002,
+		0x0e41f8, 0x128d48, 0x0e41f8, 0xefc14e, 0xf12d7a, 0x000003,
+		0x0cfa60, 0x11e89c, 0x0cfa60, 0xf1b09e, 0xf27205, 0x000003,
+		0x15b69c, 0x20e7e4, 0x15b69c, 0xea799a, 0xe9314a, 0x000002,
+		0x0f79e2, 0x1a7064, 0x0f79e2, 0xf65e4a, 0xf03d8e, 0x000002,
+		0x10c34f, 0x1ffe4b, 0x10c34f, 0x0bbecb, 0xf2bc4b, 0x000001,
+		0x000000, 0x23b063, 0x23b063, 0x07335f, 0x000000, 0x000002,
+	};
+
+	static const u32 IIR_COEF_48_TO_32[42] = {
+		0x0a2a9b, 0x0a2f05, 0x0a2a9b, 0xe73873, 0xe0c525, 0x000002,
+		0x0dd4ad, 0x0e765a, 0x0dd4ad, 0xf49808, 0xf14844, 0x000003,
+		0x18a8cd, 0x1c40d0, 0x18a8cd, 0xed2aab, 0xe542ec, 0x000002,
+		0x13e044, 0x1a47c4, 0x13e044, 0xf44aed, 0xe9acc7, 0x000002,
+		0x1abd9c, 0x2a5429, 0x1abd9c, 0xff3441, 0xe0fc5f, 0x000001,
+		0x0d86db, 0x193e2e, 0x0d86db, 0x1a6f15, 0xf14507, 0x000001,
+		0x000000, 0x1f820c, 0x1f820c, 0x0a1b1f, 0x000000, 0x000002,
+	};
+
+	static const u32 IIR_COEF_32_TO_16[48] = {
+		0x122893, 0xffadd4, 0x122893, 0x0bc205, 0xc0ee1c, 0x000001,
+		0x1bab8a, 0x00750d, 0x1bab8a, 0x06a983, 0xe18a5c, 0x000002,
+		0x18f68e, 0x02706f, 0x18f68e, 0x0886a9, 0xe31bcb, 0x000002,
+		0x149c05, 0x054487, 0x149c05, 0x0bec31, 0xe5973e, 0x000002,
+		0x0ea303, 0x07f24a, 0x0ea303, 0x115ff9, 0xe967b6, 0x000002,
+		0x0823fd, 0x085531, 0x0823fd, 0x18d5b4, 0xee8d21, 0x000002,
+		0x06888e, 0x0acbbb, 0x06888e, 0x40b55c, 0xe76dce, 0x000001,
+		0x000000, 0x2d31a9, 0x2d31a9, 0x23ba4f, 0x000000, 0x000001,
+	};
+
+	static const u32 IIR_COEF_96_TO_44p1[48] = {
+		0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
+		0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
+		0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
+		0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
+		0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
+		0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
+		0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
+		0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
+	};
+
+	static const u32 IIR_COEF_44p1_TO_16[48] = {
+		0x0998fb, 0xf7f925, 0x0998fb, 0x1e54a0, 0xe06605, 0x000002,
+		0x0d828e, 0xf50f97, 0x0d828e, 0x0f41b5, 0xf0a999, 0x000003,
+		0x17ebeb, 0xee30d8, 0x17ebeb, 0x1f48ca, 0xe2ae88, 0x000002,
+		0x12fab5, 0xf46ddc, 0x12fab5, 0x20cc51, 0xe4d068, 0x000002,
+		0x0c7ac6, 0xfbd00e, 0x0c7ac6, 0x2337da, 0xe8028c, 0x000002,
+		0x060ddc, 0x015b3e, 0x060ddc, 0x266754, 0xec21b6, 0x000002,
+		0x0407b5, 0x04f827, 0x0407b5, 0x52e3d0, 0xe0149f, 0x000001,
+		0x000000, 0x1f9521, 0x1f9521, 0x2ac116, 0x000000, 0x000001,
+	};
+
+	static const u32 IIR_COEF_48_TO_16[48] = {
+		0x0955ff, 0xf6544a, 0x0955ff, 0x2474e5, 0xe062e6, 0x000002,
+		0x0d4180, 0xf297f4, 0x0d4180, 0x12415b, 0xf0a3b0, 0x000003,
+		0x0ba079, 0xf4f0b0, 0x0ba079, 0x1285d3, 0xf1488b, 0x000003,
+		0x12247c, 0xf1033c, 0x12247c, 0x2625be, 0xe48e0d, 0x000002,
+		0x0b98e0, 0xf96d1a, 0x0b98e0, 0x27e79c, 0xe7798a, 0x000002,
+		0x055e3b, 0xffed09, 0x055e3b, 0x2a2e2d, 0xeb2854, 0x000002,
+		0x01a934, 0x01ca03, 0x01a934, 0x2c4fea, 0xee93ab, 0x000002,
+		0x000000, 0x1c46c5, 0x1c46c5, 0x2d37dc, 0x000000, 0x000001,
+	};
+
+	static const u32 IIR_COEF_96_TO_16[48] = {
+		0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
+		0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
+		0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
+		0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
+		0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
+		0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
+		0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
+		0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
+	};
+
+	static const struct {
+		const u32 *coef;
+		unsigned int cnt;
+	} iir_coef_tbl_list[8] = {
+		/* 0: 0.9188 */
+		{ IIR_COEF_48_TO_44p1, ARRAY_SIZE(IIR_COEF_48_TO_44p1) },
+		/* 1: 0.7256 */
+		{ IIR_COEF_44p1_TO_32, ARRAY_SIZE(IIR_COEF_44p1_TO_32) },
+		/* 2: 0.6667 */
+		{ IIR_COEF_48_TO_32, ARRAY_SIZE(IIR_COEF_48_TO_32) },
+		/* 3: 0.5 */
+		{ IIR_COEF_32_TO_16, ARRAY_SIZE(IIR_COEF_32_TO_16) },
+		/* 4: 0.4594 */
+		{ IIR_COEF_96_TO_44p1, ARRAY_SIZE(IIR_COEF_96_TO_44p1) },
+		/* 5: 0.3628 */
+		{ IIR_COEF_44p1_TO_16, ARRAY_SIZE(IIR_COEF_44p1_TO_16) },
+		/* 6: 0.3333 */
+		{ IIR_COEF_48_TO_16, ARRAY_SIZE(IIR_COEF_48_TO_16) },
+		/* 7: 0.1667 */
+		{ IIR_COEF_96_TO_16, ARRAY_SIZE(IIR_COEF_96_TO_16) },
+	};
+
+	static const u32 freq_new_index[16] = {
+		0, 1, 2, 99, 3, 4, 5, 99, 6, 7, 8, 9, 10, 11, 12, 99
+	};
+
+	static const u32 iir_coef_tbl_matrix[13][13] = {
+		{/*0*/
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*1*/
+			1, NO_NEED, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*2*/
+			2, 0, NO_NEED, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*3*/
+			3, INV_COEF, INV_COEF, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*4*/
+			5, 3, INV_COEF, 2, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*5*/
+			6, 4, 3, 2, 0, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED
+		},
+		{/*6*/
+			INV_COEF, INV_COEF, INV_COEF, 3, INV_COEF,
+			INV_COEF, NO_NEED, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*7*/
+			INV_COEF, INV_COEF, INV_COEF, 5, 3,
+			INV_COEF, 1, NO_NEED, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*8*/
+			7, INV_COEF, INV_COEF, 6, 4, 3, 2, 0, NO_NEED,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*9*/
+			INV_COEF, INV_COEF, INV_COEF, INV_COEF,
+			INV_COEF, INV_COEF, 5, 3, INV_COEF,
+			NO_NEED, NO_NEED, NO_NEED, NO_NEED
+		},
+		{/*10*/
+			INV_COEF, INV_COEF, INV_COEF, 7, INV_COEF,
+			INV_COEF, 6, 4, 3, 0,
+			NO_NEED, NO_NEED, NO_NEED
+		},
+		{ /*11*/
+			RATIOVER, INV_COEF, INV_COEF, INV_COEF,
+			INV_COEF, INV_COEF, INV_COEF, INV_COEF,
+			INV_COEF, 3, INV_COEF, NO_NEED, NO_NEED
+		},
+		{/*12*/
+			RATIOVER, RATIOVER, INV_COEF, INV_COEF,
+			INV_COEF, INV_COEF, 7, INV_COEF,
+			INV_COEF, 4, 3, 0, NO_NEED
+		},
+	};
+
+	const u32 *coef = NULL;
+	unsigned int cnt = 0;
+	u32 i = freq_new_index[input_fs];
+	u32 j = freq_new_index[output_fs];
+
+	if (i >= 13 || j >= 13) {
+	} else {
+		u32 k = iir_coef_tbl_matrix[i][j];
+
+		if (k >= NO_NEED) {
+		} else if (k == RATIOVER) {
+		} else if (k == INV_COEF) {
+		} else {
+			coef = iir_coef_tbl_list[k].coef;
+			cnt = iir_coef_tbl_list[k].cnt;
+		}
+	}
+	*count = cnt;
+	return coef;
+}
+
+static int mt8365_dai_set_config(struct mtk_base_afe *afe,
+				 struct mtk_afe_i2s_priv *i2s_data,
+				 bool is_input, unsigned int rate,
+				 int bit_width)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_be_dai_data *be =
+	&afe_priv->be_data[i2s_data->id - MT8365_AFE_BACKEND_BASE];
+	unsigned int val, reg_off;
+	int fs = mt8365_afe_fs_timing(rate);
+
+	if (fs < 0)
+		return -EINVAL;
+
+	val = AFE_I2S_CON_LOW_JITTER_CLK |
+	      FIELD_PREP(AFE_I2S_CON_RATE_MASK, fs) |
+	      AFE_I2S_CON_FORMAT_I2S;
+
+	if (is_input) {
+		reg_off = i2s_data->reg_off_in;
+		if (i2s_data->adda_link)
+			val |= i2s_data->config_val_in;
+	} else {
+		reg_off = i2s_data->reg_off_out;
+		val |= i2s_data->config_val_in;
+	}
+
+	/* 1:bck=32lrck(16bit) or bck=64lrck(32bit) 0:fix bck=64lrck */
+	if (i2s_data->dynamic_bck) {
+		if (bit_width > 16)
+			val |= AFE_I2S_CON_WLEN_32BIT;
+		else
+			val &= ~(u32)AFE_I2S_CON_WLEN_32BIT;
+	} else {
+		val |= AFE_I2S_CON_WLEN_32BIT;
+	}
+
+	if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
+	    SND_SOC_DAIFMT_CBM_CFM) {
+		val |= AFE_I2S_CON_SRC_SLAVE;
+		val &= ~(u32)AFE_I2S_CON_FROM_IO_MUX;//from consys
+	}
+
+	regmap_update_bits(afe->regmap, reg_off, ~(u32)AFE_I2S_CON_EN, val);
+
+	if (i2s_data->adda_link && is_input)
+		regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);
+
+	return 0;
+}
+
+int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe,
+			   unsigned int rate, int bit_width)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_i2s_priv *i2s_data =
+		afe_priv->dai_priv[MT8365_AFE_IO_I2S];
+
+	return mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
+}
+
+static int mt8365_afe_set_2nd_i2s_asrc(struct mtk_base_afe *afe,
+				       unsigned int rate_in,
+				       unsigned int rate_out,
+				       unsigned int width,
+				       unsigned int mono,
+				       int o16bit, int tracking)
+{
+	int ifs, ofs = 0;
+	unsigned int val = 0;
+	unsigned int mask = 0;
+	const u32 *coef;
+	u32 iir_stage;
+	unsigned int coef_count = 0;
+
+	ifs = mt8365_afe_fs_timing(rate_in);
+
+	if (ifs < 0)
+		return -EINVAL;
+
+	ofs = mt8365_afe_fs_timing(rate_out);
+
+	if (ofs < 0)
+		return -EINVAL;
+
+	val = FIELD_PREP(O16BIT, o16bit) | FIELD_PREP(IS_MONO, mono);
+	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
+			   O16BIT | IS_MONO, val);
+
+	coef = get_iir_coef(ifs, ofs, &coef_count);
+	iir_stage = ((u32)coef_count / 6) - 1;
+
+	if (coef) {
+		unsigned int i;
+
+		/* CPU control IIR coeff SRAM */
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
+				   COEFF_SRAM_CTRL, COEFF_SRAM_CTRL);
+
+		/* set to 0, IIR coeff SRAM addr */
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON13,
+				   0xffffffff, 0x0);
+
+		for (i = 0; i < coef_count; ++i)
+			regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON12,
+					   0xffffffff, coef[i]);
+
+		/* disable IIR coeff SRAM access */
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
+				   COEFF_SRAM_CTRL,
+				   (unsigned long)~COEFF_SRAM_CTRL);
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
+				   CLR_IIR_HISTORY | IIR_EN | IIR_STAGE_MASK,
+				   CLR_IIR_HISTORY | IIR_EN |
+				   FIELD_PREP(IIR_STAGE_MASK, iir_stage));
+	} else {
+		/* disable IIR */
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
+				   IIR_EN, (unsigned long)~IIR_EN);
+	}
+
+	/* CON3 setting (RX OFS) */
+	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON3,
+			   0x00FFFFFF, rx_frequency_palette(ofs));
+	/* CON4 setting (RX IFS) */
+	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON4,
+			   0x00FFFFFF, rx_frequency_palette(ifs));
+
+	/* CON5 setting */
+	if (tracking) {
+		val = CALI_64_CYCLE |
+		      CALI_AUTORST |
+		      AUTO_TUNE_FREQ5 |
+		      COMP_FREQ_RES |
+		      CALI_BP_DGL |
+		      CALI_AUTO_RESTART |
+		      CALI_USE_FREQ_OUT |
+		      CALI_SEL_01;
+
+		mask = CALI_CYCLE_MASK |
+		       CALI_AUTORST |
+		       AUTO_TUNE_FREQ5 |
+		       COMP_FREQ_RES |
+		       CALI_SEL_MASK |
+		       CALI_BP_DGL |
+		       AUTO_TUNE_FREQ4 |
+		       CALI_AUTO_RESTART |
+		       CALI_USE_FREQ_OUT |
+		       CALI_ON;
+
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
+				   mask, val);
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
+				   CALI_ON, CALI_ON);
+	} else {
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
+				   0xffffffff, 0x0);
+	}
+	/* CON6 setting fix 8125 */
+	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON6,
+			   0x0000ffff, 0x1FBD);
+	/* CON9 setting (RX IFS) */
+	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON9,
+			   0x000fffff, AutoRstThHi(ifs));
+	/* CON10 setting (RX IFS) */
+	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON10,
+			   0x000fffff, AutoRstThLo(ifs));
+	regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
+			   CHSET_STR_CLR, CHSET_STR_CLR);
+
+	return 0;
+}
+
+static int mt8365_afe_set_2nd_i2s_asrc_enable(struct mtk_base_afe *afe,
+					      bool enable)
+{
+	if (enable)
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
+				   ASM_ON, ASM_ON);
+	else
+		regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
+				   ASM_ON, (unsigned long)~ASM_ON);
+	return 0;
+}
+
+void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)
+{
+	int i;
+	unsigned long flags;
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_i2s_priv *i2s_data;
+
+	for (i = 0; i < DAI_I2S_NUM; i++) {
+		if (mt8365_i2s_priv[i].adda_link)
+			i2s_data = afe_priv->dai_priv[mt8365_i2s_priv[i].id];
+	}
+
+	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+
+	if (enable) {
+		i2s_data->i2s_out_on_ref_cnt++;
+		if (i2s_data->i2s_out_on_ref_cnt == 1)
+			regmap_update_bits(afe->regmap, AFE_I2S_CON1,
+					   0x1, enable);
+	} else {
+		i2s_data->i2s_out_on_ref_cnt--;
+		if (i2s_data->i2s_out_on_ref_cnt == 0)
+			regmap_update_bits(afe->regmap, AFE_I2S_CON1,
+					   0x1, enable);
+		else if (i2s_data->i2s_out_on_ref_cnt < 0)
+			i2s_data->i2s_out_on_ref_cnt = 0;
+	}
+
+	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+}
+
+static void mt8365_dai_set_enable(struct mtk_base_afe *afe,
+				  struct mtk_afe_i2s_priv *i2s_data,
+				  bool is_input, bool enable)
+{
+	unsigned int reg_off;
+
+	if (is_input) {
+		reg_off = i2s_data->reg_off_in;
+	} else {
+		if (i2s_data->adda_link) {
+			mt8365_afe_set_i2s_out_enable(afe, enable);
+			return;
+		}
+		reg_off = i2s_data->reg_off_out;
+	}
+	regmap_update_bits(afe->regmap, reg_off,
+			   0x1, enable);
+}
+
+static int mt8365_dai_i2s_startup(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
+	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+	bool i2s_in_slave =
+		(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
+		((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
+		SND_SOC_DAIFMT_CBM_CFM);
+
+	mt8365_afe_enable_main_clk(afe);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		mt8365_afe_enable_clk(afe,
+				      afe_priv->clocks[i2s_data->clk_id_out]);
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !i2s_in_slave)
+		mt8365_afe_enable_clk(afe,
+				      afe_priv->clocks[i2s_data->clk_id_in]);
+
+	if (i2s_in_slave)
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
+
+	return 0;
+}
+
+static void mt8365_dai_i2s_shutdown(struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
+	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+	bool reset_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+	bool reset_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+	bool i2s_in_slave =
+		(substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
+		((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
+		SND_SOC_DAIFMT_CBM_CFM);
+
+	if (be->prepared[substream->stream]) {
+		if (reset_i2s_out_change)
+			mt8365_dai_set_enable(afe, i2s_data, false, false);
+
+		if (reset_i2s_in_change)
+			mt8365_dai_set_enable(afe, i2s_data, true, false);
+
+		if (substream->runtime->rate % 8000)
+			mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
+		else
+			mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
+
+		if (reset_i2s_out_change)
+			be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = false;
+
+		if (reset_i2s_in_change)
+			be->prepared[SNDRV_PCM_STREAM_CAPTURE] = false;
+	}
+
+	if (reset_i2s_out_change)
+		mt8365_afe_disable_clk(afe,
+				       afe_priv->clocks[i2s_data->clk_id_out]);
+
+	if (reset_i2s_in_change && !i2s_in_slave)
+		mt8365_afe_disable_clk(afe,
+				       afe_priv->clocks[i2s_data->clk_id_in]);
+
+	if (i2s_in_slave)
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
+
+	mt8365_afe_disable_main_clk(afe);
+}
+
+static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream,
+				  struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
+	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+	bool apply_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+	bool apply_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+	unsigned int rate = substream->runtime->rate;
+	int bit_width = snd_pcm_format_width(substream->runtime->format);
+	int ret;
+
+	if (be->prepared[substream->stream]) {
+		dev_info(afe->dev, "%s '%s' prepared already\n",
+			 __func__, snd_pcm_stream_str(substream));
+		return 0;
+	}
+
+	if (apply_i2s_out_change) {
+		ret = mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
+		if (ret)
+			return ret;
+	}
+
+	if (apply_i2s_in_change) {
+		if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
+		    == SND_SOC_DAIFMT_CBM_CFM) {
+			ret = mt8365_afe_set_2nd_i2s_asrc(afe, 32000, rate,
+							  (unsigned int)bit_width,
+							  0, 0, 1);
+			if (ret < 0)
+				return ret;
+		}
+		ret = mt8365_dai_set_config(afe, i2s_data, true, rate, bit_width);
+		if (ret)
+			return ret;
+	}
+
+	if (rate % 8000)
+		mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
+	else
+		mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
+
+	if (apply_i2s_out_change) {
+		mt8365_afe_set_clk_parent(afe,
+					  afe_priv->clocks[i2s_data->clk_id_out_m_sel],
+					  ((rate % 8000) ?
+					  afe_priv->clocks[MT8365_CLK_AUD1] :
+					  afe_priv->clocks[MT8365_CLK_AUD2]));
+
+		mt8365_afe_set_clk_rate(afe,
+					afe_priv->clocks[i2s_data->clk_id_out],
+					rate * i2s_data->clk_out_mult);
+
+		mt8365_dai_set_enable(afe, i2s_data, false, true);
+		be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = true;
+	}
+
+	if (apply_i2s_in_change) {
+		mt8365_afe_set_clk_parent(afe,
+					  afe_priv->clocks[i2s_data->clk_id_in_m_sel],
+					  ((rate % 8000) ?
+					  afe_priv->clocks[MT8365_CLK_AUD1] :
+					  afe_priv->clocks[MT8365_CLK_AUD2]));
+
+		mt8365_afe_set_clk_rate(afe,
+					afe_priv->clocks[i2s_data->clk_id_in],
+					rate * i2s_data->clk_in_mult);
+
+		mt8365_dai_set_enable(afe, i2s_data, true, true);
+
+		if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
+		    == SND_SOC_DAIFMT_CBM_CFM)
+			mt8365_afe_set_2nd_i2s_asrc_enable(afe, true);
+
+		be->prepared[SNDRV_PCM_STREAM_CAPTURE] = true;
+	}
+	return 0;
+}
+
+static int mt8365_afe_2nd_i2s_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);
+	unsigned int width_val = params_width(params) > 16 ?
+		(AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01) : 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		regmap_update_bits(afe->regmap, AFE_CONN_24BIT,
+				   AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01, width_val);
+
+	return 0;
+}
+
+static int mt8365_afe_2nd_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
+
+	be->fmt_mode = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		be->fmt_mode |= SND_SOC_DAIFMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		be->fmt_mode |= SND_SOC_DAIFMT_LEFT_J;
+		break;
+	default:
+		dev_info(afe->dev, "invalid audio format for 2nd i2s!\n");
+		return -EINVAL;
+	}
+
+	if (((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) &&
+	    ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_IF) &&
+	    ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_NF) &&
+	    ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_IF)) {
+		dev_info(afe->dev, "invalid audio format for 2nd i2s!\n");
+		return -EINVAL;
+	}
+
+	be->fmt_mode |= (fmt & SND_SOC_DAIFMT_INV_MASK);
+
+	if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM))
+		be->fmt_mode |= (fmt & SND_SOC_DAIFMT_MASTER_MASK);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mt8365_afe_i2s_ops = {
+	.startup	= mt8365_dai_i2s_startup,
+	.shutdown	= mt8365_dai_i2s_shutdown,
+	.prepare	= mt8365_dai_i2s_prepare,
+};
+
+static const struct snd_soc_dai_ops mt8365_afe_2nd_i2s_ops = {
+	.startup	= mt8365_dai_i2s_startup,
+	.shutdown	= mt8365_dai_i2s_shutdown,
+	.hw_params	= mt8365_afe_2nd_i2s_hw_params,
+	.prepare	= mt8365_dai_i2s_prepare,
+	.set_fmt	= mt8365_afe_2nd_i2s_set_fmt,
+};
+
+static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
+	{
+		.name = "I2S",
+		.id = MT8365_AFE_IO_I2S,
+		.playback = {
+			.stream_name = "I2S Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "I2S Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_i2s_ops,
+	}, {
+		.name = "2ND I2S",
+		.id = MT8365_AFE_IO_2ND_I2S,
+		.playback = {
+			.stream_name = "2ND I2S Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.capture = {
+			.stream_name = "2ND I2S Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_192000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_2nd_i2s_ops,
+	}
+};
+
+/* low jitter control */
+static const char * const mt8365_i2s_hd_str[] = {
+	"Normal", "Low_Jitter"
+};
+
+static SOC_ENUM_SINGLE_EXT_DECL(mt8365_i2s_enum, mt8365_i2s_hd_str);
+
+static const char * const fmi2sin_text[] = {
+	"OPEN", "FM_2ND_I2S_IN"
+};
+
+static SOC_ENUM_SINGLE_VIRT_DECL(fmi2sin_enum, fmi2sin_text);
+
+static const struct snd_kcontrol_new fmi2sin_mux =
+	SOC_DAPM_ENUM("FM 2ND I2S Source", fmi2sin_enum);
+
+static const struct snd_kcontrol_new i2s_o03_o04_enable_ctl =
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
+
+static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
+	SND_SOC_DAPM_SWITCH("I2S O03_O04", SND_SOC_NOPM, 0, 0,
+			    &i2s_o03_o04_enable_ctl),
+	SND_SOC_DAPM_MUX("FM 2ND I2S Mux", SND_SOC_NOPM, 0, 0, &fmi2sin_mux),
+	SND_SOC_DAPM_INPUT("2ND I2S In"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
+	{"I2S O03_O04", "Switch", "O03"},
+	{"I2S O03_O04", "Switch", "O04"},
+	{"I2S Playback", NULL, "I2S O03_O04"},
+	{"2ND I2S Playback", NULL, "O00"},
+	{"2ND I2S Playback", NULL, "O01"},
+	{"2ND I2S Capture", NULL, "2ND I2S In"},
+	{"FM 2ND I2S Mux", "FM_2ND_I2S_IN", "2ND I2S Capture"},
+};
+
+static int mt8365_dai_i2s_set_priv(struct mtk_base_afe *afe)
+{
+	int i, ret;
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	for (i = 0; i < DAI_I2S_NUM; i++) {
+		ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id,
+					  sizeof(*afe_priv),
+					  &mt8365_i2s_priv[i]);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+int mt8365_dai_i2s_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_i2s_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
+	dai->dapm_widgets = mtk_dai_i2s_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
+	dai->dapm_routes = mtk_dai_i2s_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
+
+	/* set all dai i2s private data */
+	return mt8365_dai_i2s_set_priv(afe);
+}

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 09/18] ASoC: mediatek: mt8365: Add DMIC DAI support
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add Digital Micro Device Audio Interface support for MT8365 SoC.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/mt8365/mt8365-dai-dmic.c | 347 ++++++++++++++++++++++++++++
 1 file changed, 347 insertions(+)

diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c
new file mode 100644
index 000000000000..0dd606274d8e
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek 8365 ALSA SoC Audio DAI DMIC Control
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+#include "mt8365-afe-clk.h"
+#include "mt8365-afe-common.h"
+
+struct mt8365_dmic_data {
+	bool two_wire_mode;
+	unsigned int clk_phase_sel_ch1;
+	unsigned int clk_phase_sel_ch2;
+	bool iir_on;
+	unsigned int irr_mode;
+	unsigned int dmic_mode;
+	unsigned int dmic_channel;
+};
+
+static int get_chan_reg(unsigned int channel)
+{
+	switch (channel) {
+	case 8:
+		fallthrough;
+	case 7:
+		return AFE_DMIC3_UL_SRC_CON0;
+	case 6:
+		fallthrough;
+	case 5:
+		return AFE_DMIC2_UL_SRC_CON0;
+	case 4:
+		fallthrough;
+	case 3:
+		return AFE_DMIC1_UL_SRC_CON0;
+	case 2:
+		fallthrough;
+	case 1:
+		return AFE_DMIC0_UL_SRC_CON0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/* DAI Drivers */
+
+static void audio_dmic_adda_enable(struct mtk_base_afe *afe)
+{
+	mt8365_dai_enable_adda_on(afe);
+	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
+			   AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,
+			   AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);
+}
+
+static void audio_dmic_adda_disable(struct mtk_base_afe *afe)
+{
+	regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
+			   AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,
+			   ~AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);
+	mt8365_dai_disable_adda_on(afe);
+}
+
+static void mt8365_dai_enable_dmic(struct mtk_base_afe *afe,
+				   struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *dai)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
+	unsigned int val_mask;
+	int reg = get_chan_reg(dmic_data->dmic_channel);
+
+	if (reg < 0)
+		return;
+
+	/* val and mask will be always same to enable */
+	val_mask = DMIC_TOP_CON_CH1_ON |
+		   DMIC_TOP_CON_CH2_ON |
+		   DMIC_TOP_CON_SRC_ON;
+
+	regmap_update_bits(afe->regmap, reg, val_mask, val_mask);
+}
+
+static void mt8365_dai_disable_dmic(struct mtk_base_afe *afe,
+				    struct snd_pcm_substream *substream,
+				    struct snd_soc_dai *dai)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
+	unsigned int mask;
+	int reg = get_chan_reg(dmic_data->dmic_channel);
+
+	if (reg < 0)
+		return;
+
+	dev_info(afe->dev, "%s dmic_channel %d\n",
+		 __func__, dmic_data->dmic_channel);
+
+	mask = DMIC_TOP_CON_CH1_ON |
+	       DMIC_TOP_CON_CH2_ON |
+	       DMIC_TOP_CON_SRC_ON |
+	       DMIC_TOP_CON_SDM3_LEVEL_MODE;
+
+	/* Set all masked values to 0 */
+	regmap_update_bits(afe->regmap, reg, mask, 0);
+}
+
+static const struct reg_sequence mt8365_dmic_iir_coeff[] = {
+	{ AFE_DMIC0_IIR_COEF_02_01, 0x00000000 },
+	{ AFE_DMIC0_IIR_COEF_04_03, 0x00003FB8 },
+	{ AFE_DMIC0_IIR_COEF_06_05, 0x3FB80000 },
+	{ AFE_DMIC0_IIR_COEF_08_07, 0x3FB80000 },
+	{ AFE_DMIC0_IIR_COEF_10_09, 0x0000C048 },
+	{ AFE_DMIC1_IIR_COEF_02_01, 0x00000000 },
+	{ AFE_DMIC1_IIR_COEF_04_03, 0x00003FB8 },
+	{ AFE_DMIC1_IIR_COEF_06_05, 0x3FB80000 },
+	{ AFE_DMIC1_IIR_COEF_08_07, 0x3FB80000 },
+	{ AFE_DMIC1_IIR_COEF_10_09, 0x0000C048 },
+	{ AFE_DMIC2_IIR_COEF_02_01, 0x00000000 },
+	{ AFE_DMIC2_IIR_COEF_04_03, 0x00003FB8 },
+	{ AFE_DMIC2_IIR_COEF_06_05, 0x3FB80000 },
+	{ AFE_DMIC2_IIR_COEF_08_07, 0x3FB80000 },
+	{ AFE_DMIC2_IIR_COEF_10_09, 0x0000C048 },
+	{ AFE_DMIC3_IIR_COEF_02_01, 0x00000000 },
+	{ AFE_DMIC3_IIR_COEF_04_03, 0x00003FB8 },
+	{ AFE_DMIC3_IIR_COEF_06_05, 0x3FB80000 },
+	{ AFE_DMIC3_IIR_COEF_08_07, 0x3FB80000 },
+	{ AFE_DMIC3_IIR_COEF_10_09, 0x0000C048 },
+};
+
+static int mt8365_dai_load_dmic_iir_coeff_table(struct mtk_base_afe *afe)
+{
+	return regmap_multi_reg_write(afe->regmap,
+				      mt8365_dmic_iir_coeff,
+				      ARRAY_SIZE(mt8365_dmic_iir_coeff));
+}
+
+static int mt8365_dai_configure_dmic(struct mtk_base_afe *afe,
+				     struct snd_pcm_substream *substream,
+				     struct snd_soc_dai *dai)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
+	bool two_wire_mode = dmic_data->two_wire_mode;
+	unsigned int clk_phase_sel_ch1 = dmic_data->clk_phase_sel_ch1;
+	unsigned int clk_phase_sel_ch2 = dmic_data->clk_phase_sel_ch2;
+	unsigned int val = 0;
+	unsigned int mask = 0;
+	unsigned int rate = dai->rate;
+	int reg = get_chan_reg(dai->channels);
+
+	if (reg < 0)
+		return -EINVAL;
+
+	dmic_data->dmic_channel = dai->channels;
+
+	val |= DMIC_TOP_CON_SDM3_LEVEL_MODE;
+	mask |= DMIC_TOP_CON_SDM3_LEVEL_MODE;
+
+	if (two_wire_mode) {
+		val |= DMIC_TOP_CON_TWO_WIRE_MODE;
+		mask |= DMIC_TOP_CON_TWO_WIRE_MODE;
+	} else {
+		val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH1,
+				  clk_phase_sel_ch1);
+		val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH2,
+				  clk_phase_sel_ch2);
+		mask |= DMIC_TOP_CON_CK_PHASE_SEL_CH1;
+		mask |= DMIC_TOP_CON_CK_PHASE_SEL_CH2;
+	}
+
+	switch (rate) {
+	case 48000:
+		val |= DMIC_TOP_CON_VOICE_MODE_48K;
+		break;
+	case 32000:
+		val |= DMIC_TOP_CON_VOICE_MODE_32K;
+		break;
+	case 16000:
+		val |= DMIC_TOP_CON_VOICE_MODE_16K;
+		break;
+	case 8000:
+		val |= DMIC_TOP_CON_VOICE_MODE_8K;
+		break;
+	default:
+		return -EINVAL;
+	}
+	mask |= DMIC_TOP_CON_VOICE_MODE_MASK;
+
+	regmap_update_bits(afe->regmap, reg, DMIC_TOP_CON_CONFIG_MASK, val);
+
+	return 0;
+}
+
+static int mt8365_dai_dmic_startup(struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+
+	mt8365_afe_enable_main_clk(afe);
+
+	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);
+	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);
+	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);
+	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);
+
+	audio_dmic_adda_enable(afe);
+
+	return 0;
+}
+
+static void mt8365_dai_dmic_shutdown(struct snd_pcm_substream *substream,
+				     struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+
+	mt8365_dai_disable_dmic(afe, substream, dai);
+	audio_dmic_adda_disable(afe);
+	/* HW Request delay 125us before CG off */
+	usleep_range(125, 300);
+	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);
+	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);
+	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);
+	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);
+
+	mt8365_afe_disable_main_clk(afe);
+}
+
+static int mt8365_dai_dmic_prepare(struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *dai)
+{
+	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+
+	mt8365_dai_configure_dmic(afe, substream, dai);
+	mt8365_dai_enable_dmic(afe, substream, dai);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops mt8365_afe_dmic_ops = {
+	.startup	= mt8365_dai_dmic_startup,
+	.shutdown	= mt8365_dai_dmic_shutdown,
+	.prepare	= mt8365_dai_dmic_prepare,
+};
+
+static struct snd_soc_dai_driver mtk_dai_dmic_driver[] = {
+	{
+		.name = "DMIC",
+		.id = MT8365_AFE_IO_DMIC,
+		.capture = {
+			.stream_name = "DMIC Capture",
+			.channels_min = 1,
+			.channels_max = 8,
+			.rates = SNDRV_PCM_RATE_16000 |
+				 SNDRV_PCM_RATE_32000 |
+				 SNDRV_PCM_RATE_48000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE |
+				   SNDRV_PCM_FMTBIT_S32_LE,
+		},
+		.ops = &mt8365_afe_dmic_ops,
+	}
+};
+
+/* DAI Controls */
+
+/* Values for 48kHz mode */
+static const char * const iir_mode_src[] = {
+	"SW custom", "5Hz", "10Hz", "25Hz", "50Hz", "65Hz"
+};
+
+static SOC_ENUM_SINGLE_DECL(iir_mode, AFE_DMIC0_UL_SRC_CON0, 7, iir_mode_src);
+
+static const struct snd_kcontrol_new mtk_dai_dmic_controls[] = {
+	SOC_SINGLE("DMIC IIR Switch", AFE_DMIC0_UL_SRC_CON0, DMIC_TOP_CON_IIR_ON, 1, 0),
+	SOC_ENUM("DMIC IIR Mode", iir_mode),
+};
+
+/* DAI widget */
+
+static const struct snd_soc_dapm_widget mtk_dai_dmic_widgets[] = {
+	SND_SOC_DAPM_INPUT("DMIC In"),
+};
+
+/* DAI route */
+
+static const struct snd_soc_dapm_route mtk_dai_dmic_routes[] = {
+	{"I14", NULL, "DMIC Capture"},
+	{"I15", NULL, "DMIC Capture"},
+	{"I16", NULL, "DMIC Capture"},
+	{"I17", NULL, "DMIC Capture"},
+	{"I18", NULL, "DMIC Capture"},
+	{"I19", NULL, "DMIC Capture"},
+	{"I20", NULL, "DMIC Capture"},
+	{"I21", NULL, "DMIC Capture"},
+	{"DMIC Capture", NULL, "DMIC In"},
+};
+
+static int init_dmic_priv_data(struct mtk_base_afe *afe)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	struct mt8365_dmic_data *dmic_priv;
+	struct device_node *np = afe->dev->of_node;
+	unsigned int temps[4];
+	int ret;
+
+	dmic_priv = devm_kzalloc(afe->dev, sizeof(*dmic_priv), GFP_KERNEL);
+	if (!dmic_priv)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(np, "mediatek,dmic-mode",
+					 &temps[0],
+					 1);
+	if (ret == 0)
+		dmic_priv->two_wire_mode = !!temps[0];
+
+	if (!dmic_priv->two_wire_mode) {
+		dmic_priv->clk_phase_sel_ch1 = 0;
+		dmic_priv->clk_phase_sel_ch2 = 4;
+	}
+
+	afe_priv->dai_priv[MT8365_AFE_IO_DMIC] = dmic_priv;
+	return 0;
+}
+
+int mt8365_dai_dmic_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_dmic_driver;
+	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_dmic_driver);
+	dai->controls = mtk_dai_dmic_controls;
+	dai->num_controls = ARRAY_SIZE(mtk_dai_dmic_controls);
+	dai->dapm_widgets = mtk_dai_dmic_widgets;
+	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_dmic_widgets);
+	dai->dapm_routes = mtk_dai_dmic_routes;
+	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_dmic_routes);
+	return init_dmic_priv_data(afe);
+}

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 05/18] ASoC: mediatek: mt8365: Add common header
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add header files for register definition and structure.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/mt8365/mt8365-afe-common.h | 491 +++++++++++++
 sound/soc/mediatek/mt8365/mt8365-reg.h        | 991 ++++++++++++++++++++++++++
 2 files changed, 1482 insertions(+)

diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-common.h b/sound/soc/mediatek/mt8365/mt8365-afe-common.h
new file mode 100644
index 000000000000..4d8f8c4b19e3
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-common.h
@@ -0,0 +1,491 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Mediatek 8365 audio driver common definitions
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#ifndef _MT8365_AFE_COMMON_H_
+#define _MT8365_AFE_COMMON_H_
+
+#define COMMON_CLOCK_FRAMEWORK_API
+#define IDLE_TASK_DRIVER_API
+#define ENABLE_AFE_APLL_TUNER
+
+#include <linux/clk.h>
+#include <linux/list.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/asound.h>
+#include "../common/mtk-base-afe.h"
+#include "mt8365-reg.h"
+
+#define ENUM_TO_STR(enum) #enum
+
+#define snd_soc_dai_stream_active_playback(dai) \
+		snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK)
+#define snd_soc_dai_stream_active_capture(dai) \
+		snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)
+
+enum {
+	MT8365_AFE_MEMIF_DL1,
+	MT8365_AFE_MEMIF_DL2,
+	MT8365_AFE_MEMIF_TDM_OUT,
+	/*
+	 * MT8365_AFE_MEMIF_SPDIF_OUT,
+	 */
+	MT8365_AFE_MEMIF_AWB,
+	MT8365_AFE_MEMIF_VUL,
+	MT8365_AFE_MEMIF_VUL2,
+	MT8365_AFE_MEMIF_VUL3,
+	MT8365_AFE_MEMIF_TDM_IN,
+	/*
+	 * MT8365_AFE_MEMIF_SPDIF_IN,
+	 */
+	MT8365_AFE_MEMIF_NUM,
+	MT8365_AFE_BACKEND_BASE = MT8365_AFE_MEMIF_NUM,
+	MT8365_AFE_IO_TDM_OUT = MT8365_AFE_BACKEND_BASE,
+	MT8365_AFE_IO_TDM_IN,
+	MT8365_AFE_IO_I2S,
+	MT8365_AFE_IO_2ND_I2S,
+	MT8365_AFE_IO_PCM1,
+	MT8365_AFE_IO_VIRTUAL_DL_SRC,
+	MT8365_AFE_IO_VIRTUAL_TDM_OUT_SRC,
+	MT8365_AFE_IO_VIRTUAL_FM,
+	MT8365_AFE_IO_DMIC,
+	MT8365_AFE_IO_INT_ADDA,
+	MT8365_AFE_IO_GASRC1,
+	MT8365_AFE_IO_GASRC2,
+	MT8365_AFE_IO_TDM_ASRC,
+	MT8365_AFE_IO_HW_GAIN1,
+	MT8365_AFE_IO_HW_GAIN2,
+	MT8365_AFE_BACKEND_END,
+	MT8365_AFE_BACKEND_NUM = (MT8365_AFE_BACKEND_END -
+				  MT8365_AFE_BACKEND_BASE),
+};
+
+enum {
+	MT8365_AFE_IRQ1,
+	MT8365_AFE_IRQ2,
+	MT8365_AFE_IRQ3,
+	MT8365_AFE_IRQ4,
+	MT8365_AFE_IRQ5,
+	MT8365_AFE_IRQ6,
+	MT8365_AFE_IRQ7,
+	MT8365_AFE_IRQ8,
+	MT8365_AFE_IRQ9,
+	MT8365_AFE_IRQ10,
+	MT8365_AFE_IRQ_NUM,
+};
+
+enum {
+	MT8365_TOP_CG_AFE,
+	MT8365_TOP_CG_I2S_IN,
+	MT8365_TOP_CG_22M,
+	MT8365_TOP_CG_24M,
+	MT8365_TOP_CG_INTDIR_CK,
+	MT8365_TOP_CG_APLL2_TUNER,
+	MT8365_TOP_CG_APLL_TUNER,
+	MT8365_TOP_CG_SPDIF,
+	MT8365_TOP_CG_TDM_OUT,
+	MT8365_TOP_CG_TDM_IN,
+	MT8365_TOP_CG_ADC,
+	MT8365_TOP_CG_DAC,
+	MT8365_TOP_CG_DAC_PREDIS,
+	MT8365_TOP_CG_TML,
+	MT8365_TOP_CG_I2S1_BCLK,
+	MT8365_TOP_CG_I2S2_BCLK,
+	MT8365_TOP_CG_I2S3_BCLK,
+	MT8365_TOP_CG_I2S4_BCLK,
+	MT8365_TOP_CG_DMIC0_ADC,
+	MT8365_TOP_CG_DMIC1_ADC,
+	MT8365_TOP_CG_DMIC2_ADC,
+	MT8365_TOP_CG_DMIC3_ADC,
+	MT8365_TOP_CG_CONNSYS_I2S_ASRC,
+	MT8365_TOP_CG_GENERAL1_ASRC,
+	MT8365_TOP_CG_GENERAL2_ASRC,
+	MT8365_TOP_CG_TDM_ASRC,
+	MT8365_TOP_CG_NUM
+};
+
+enum {
+	MT8365_CLK_TOP_AUD_SEL,
+	MT8365_CLK_AUD_I2S0_M,
+	MT8365_CLK_AUD_I2S1_M,
+	MT8365_CLK_AUD_I2S2_M,
+	MT8365_CLK_AUD_I2S3_M,
+	MT8365_CLK_ENGEN1,
+	MT8365_CLK_ENGEN2,
+	MT8365_CLK_AUD1,
+	MT8365_CLK_AUD2,
+	MT8365_CLK_I2S0_M_SEL,
+	MT8365_CLK_I2S1_M_SEL,
+	MT8365_CLK_I2S2_M_SEL,
+	MT8365_CLK_I2S3_M_SEL,
+	MT8365_CLK_CLK26M,
+	MT8365_CLK_NUM
+};
+
+enum {
+	MT8365_AFE_APLL1 = 0,
+	MT8365_AFE_APLL2,
+	MT8365_AFE_APLL_NUM,
+};
+
+enum {
+	MT8365_AFE_1ST_I2S = 0,
+	MT8365_AFE_2ND_I2S,
+	MT8365_AFE_I2S_SETS,
+};
+
+enum {
+	MT8365_AFE_I2S_SEPARATE_CLOCK = 0,
+	MT8365_AFE_I2S_SHARED_CLOCK,
+};
+
+enum {
+	MT8365_AFE_TDM_OUT_I2S = 0,
+	MT8365_AFE_TDM_OUT_TDM,
+	MT8365_AFE_TDM_OUT_I2S_32BITS,
+};
+
+enum mt8365_afe_tdm_ch_start {
+	AFE_TDM_CH_START_O28_O29 = 0,
+	AFE_TDM_CH_START_O30_O31,
+	AFE_TDM_CH_START_O32_O33,
+	AFE_TDM_CH_START_O34_O35,
+	AFE_TDM_CH_ZERO,
+};
+
+enum {
+	MT8365_PCM_FORMAT_I2S = 0,
+	MT8365_PCM_FORMAT_EIAJ,
+	MT8365_PCM_FORMAT_PCMA,
+	MT8365_PCM_FORMAT_PCMB,
+};
+
+enum {
+	MT8365_FS_8K = 0,
+	MT8365_FS_11D025K,
+	MT8365_FS_12K,
+	MT8365_FS_384K,
+	MT8365_FS_16K,
+	MT8365_FS_22D05K,
+	MT8365_FS_24K,
+	MT8365_FS_130K,
+	MT8365_FS_32K,
+	MT8365_FS_44D1K,
+	MT8365_FS_48K,
+	MT8365_FS_88D2K,
+	MT8365_FS_96K,
+	MT8365_FS_176D4K,
+	MT8365_FS_192K,
+};
+
+enum {
+	FS_8000HZ  = 0, /* 0000b */
+	FS_11025HZ = 1, /* 0001b */
+	FS_12000HZ = 2, /* 0010b */
+	FS_384000HZ = 3, /* 0011b */
+	FS_16000HZ = 4, /* 0100b */
+	FS_22050HZ = 5, /* 0101b */
+	FS_24000HZ = 6, /* 0110b */
+	FS_130000HZ = 7, /* 0111b */
+	FS_32000HZ = 8, /* 1000b */
+	FS_44100HZ = 9, /* 1001b */
+	FS_48000HZ = 10, /* 1010b */
+	FS_88200HZ = 11, /* 1011b */
+	FS_96000HZ = 12, /* 1100b */
+	FS_176400HZ = 13, /* 1101b */
+	FS_192000HZ = 14, /* 1110b */
+	FS_260000HZ = 15, /* 1111b */
+};
+
+enum {
+	MT8365_AFE_DEBUGFS_AFE,
+	MT8365_AFE_DEBUGFS_MEMIF,
+	MT8365_AFE_DEBUGFS_IRQ,
+	MT8365_AFE_DEBUGFS_CONN,
+	MT8365_AFE_DEBUGFS_DBG,
+	MT8365_AFE_DEBUGFS_NUM,
+};
+
+enum {
+	MT8365_AFE_IRQ_DIR_MCU = 0,
+	MT8365_AFE_IRQ_DIR_DSP,
+	MT8365_AFE_IRQ_DIR_BOTH,
+};
+
+/* MCLK */
+enum {
+	MT8365_I2S0_MCK = 0,
+	MT8365_I2S3_MCK,
+	MT8365_MCK_NUM,
+};
+
+struct mt8365_fe_dai_data {
+	bool use_sram;
+	unsigned int sram_phy_addr;
+	void __iomem *sram_vir_addr;
+	unsigned int sram_size;
+};
+
+struct mt8365_be_dai_data {
+	bool prepared[SNDRV_PCM_STREAM_LAST + 1];
+	unsigned int fmt_mode;
+};
+
+#define MT8365_CLK_26M 26000000
+#define MT8365_CLK_24M 24000000
+#define MT8365_CLK_22M 22000000
+#define MT8365_CM_UPDATA_CNT_SET 8
+
+enum mt8365_cm_num {
+	MT8365_CM1 = 0,
+	MT8365_CM2,
+	MT8365_CM_NUM,
+};
+
+enum mt8365_cm2_mux_in {
+	MT8365_FROM_GASRC1 = 1,
+	MT8365_FROM_GASRC2,
+	MT8365_FROM_TDM_ASRC,
+	MT8365_CM_MUX_NUM,
+};
+
+enum cm2_mux_conn_in {
+	GENERAL2_ASRC_OUT_LCH = 0,
+	GENERAL2_ASRC_OUT_RCH = 1,
+	TDM_IN_CH0 = 2,
+	TDM_IN_CH1 = 3,
+	TDM_IN_CH2 = 4,
+	TDM_IN_CH3 = 5,
+	TDM_IN_CH4 = 6,
+	TDM_IN_CH5 = 7,
+	TDM_IN_CH6 = 8,
+	TDM_IN_CH7 = 9,
+	GENERAL1_ASRC_OUT_LCH = 10,
+	GENERAL1_ASRC_OUT_RCH = 11,
+	TDM_OUT_ASRC_CH0 = 12,
+	TDM_OUT_ASRC_CH1 = 13,
+	TDM_OUT_ASRC_CH2 = 14,
+	TDM_OUT_ASRC_CH3 = 15,
+	TDM_OUT_ASRC_CH4 = 16,
+	TDM_OUT_ASRC_CH5 = 17,
+	TDM_OUT_ASRC_CH6 = 18,
+	TDM_OUT_ASRC_CH7 = 19
+};
+
+struct mt8365_cm_ctrl_reg {
+	unsigned int con0;
+	unsigned int con1;
+	unsigned int con2;
+	unsigned int con3;
+	unsigned int con4;
+};
+
+struct mt8365_control_data {
+	bool bypass_cm1;
+	bool bypass_cm2;
+	unsigned int loopback_type;
+};
+
+enum dmic_input_mode {
+	DMIC_MODE_3P25M = 0,
+	DMIC_MODE_1P625M,
+	DMIC_MODE_812P5K,
+	DMIC_MODE_406P25K,
+};
+
+enum iir_mode {
+	IIR_MODE0 = 0,
+	IIR_MODE1,
+	IIR_MODE2,
+	IIR_MODE3,
+	IIR_MODE4,
+	IIR_MODE5,
+};
+
+enum {
+	MT8365_GASRC1 = 0,
+	MT8365_GASRC2,
+	MT8365_GASRC_NUM,
+	MT8365_TDM_ASRC1 = MT8365_GASRC_NUM,
+	MT8365_TDM_ASRC2,
+	MT8365_TDM_ASRC3,
+	MT8365_TDM_ASRC4,
+	MT8365_TDM_ASRC_NUM,
+};
+
+struct mt8365_gasrc_ctrl_reg {
+	unsigned int con0;
+	unsigned int con2;
+	unsigned int con3;
+	unsigned int con4;
+	unsigned int con5;
+	unsigned int con6;
+	unsigned int con9;
+	unsigned int con10;
+	unsigned int con12;
+	unsigned int con13;
+};
+
+struct mt8365_gasrc_data {
+	bool duplex;
+	bool tx_mode;
+	bool cali_on;
+	bool tdm_asrc_out_cm2;
+	bool iir_on;
+};
+
+#ifdef CONFIG_MTK_HIFIXDSP_SUPPORT
+struct mt8365_adsp_data {
+	/* information adsp supply */
+	bool adsp_on;
+	int (*hostless_active)(void);
+	/* information afe supply */
+	int (*set_afe_memif)(struct mtk_base_afe *afe,
+			     int memif_id,
+			     unsigned int rate,
+			     unsigned int channels,
+			     snd_pcm_format_t format);
+	int (*set_afe_memif_enable)(struct mtk_base_afe *afe,
+				    int memif_id,
+				    unsigned int rate,
+				    unsigned int period_size,
+				    int enable);
+	void (*get_afe_memif_sram)(struct mtk_base_afe *afe,
+				   int memif_id,
+				   unsigned int *paddr,
+				   unsigned int *size);
+	void (*set_afe_init)(struct mtk_base_afe *afe);
+	void (*set_afe_uninit)(struct mtk_base_afe *afe);
+};
+#endif
+
+struct mt8365_afe_private {
+	struct clk *clocks[MT8365_CLK_NUM];
+	struct regmap *topckgen;
+	struct mt8365_fe_dai_data fe_data[MT8365_AFE_MEMIF_NUM];
+	struct mt8365_be_dai_data be_data[MT8365_AFE_BACKEND_NUM];
+	struct mt8365_control_data ctrl_data;
+	struct mt8365_gasrc_data gasrc_data[MT8365_TDM_ASRC_NUM];
+#ifdef CONFIG_MTK_HIFIXDSP_SUPPORT
+	struct mt8365_adsp_data adsp_data;
+#endif
+	int afe_on_ref_cnt;
+	int top_cg_ref_cnt[MT8365_TOP_CG_NUM];
+	void __iomem *afe_sram_vir_addr;
+	unsigned int afe_sram_phy_addr;
+	unsigned int afe_sram_size;
+	/* locks */
+	spinlock_t afe_ctrl_lock;
+	struct mutex afe_clk_mutex;	/* Protect & sync APLL TUNER registers access*/
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_dentry[MT8365_AFE_DEBUGFS_NUM];
+#endif
+	int apll_tuner_ref_cnt[MT8365_AFE_APLL_NUM];
+	unsigned int tdm_out_mode;
+	unsigned int cm2_mux_input;
+
+	/* dai */
+	bool dai_on[MT8365_AFE_BACKEND_END];
+	void *dai_priv[MT8365_AFE_BACKEND_END];
+};
+
+static inline u32 rx_frequency_palette(unsigned int fs)
+{
+	/* *
+	 * A = (26M / fs) * 64
+	 * B = 8125 / A
+	 * return = DEC2HEX(B * 2^23)
+	 */
+	switch (fs) {
+	case FS_8000HZ:		return 0x050000;
+	case FS_11025HZ:	return 0x06E400;
+	case FS_12000HZ:	return 0x078000;
+	case FS_16000HZ:	return 0x0A0000;
+	case FS_22050HZ:	return 0x0DC800;
+	case FS_24000HZ:	return 0x0F0000;
+	case FS_32000HZ:	return 0x140000;
+	case FS_44100HZ:	return 0x1B9000;
+	case FS_48000HZ:	return 0x1E0000;
+	case FS_88200HZ:	return 0x372000;
+	case FS_96000HZ:	return 0x3C0000;
+	case FS_176400HZ:	return 0x6E4000;
+	case FS_192000HZ:	return 0x780000;
+	default:		return 0x0;
+	}
+}
+
+static inline u32 AutoRstThHi(unsigned int fs)
+{
+	switch (fs) {
+	case FS_8000HZ:		return 0x36000;
+	case FS_11025HZ:	return 0x27000;
+	case FS_12000HZ:	return 0x24000;
+	case FS_16000HZ:	return 0x1B000;
+	case FS_22050HZ:	return 0x14000;
+	case FS_24000HZ:	return 0x12000;
+	case FS_32000HZ:	return 0x0D800;
+	case FS_44100HZ:	return 0x09D00;
+	case FS_48000HZ:	return 0x08E00;
+	case FS_88200HZ:	return 0x04E00;
+	case FS_96000HZ:	return 0x04800;
+	case FS_176400HZ:	return 0x02700;
+	case FS_192000HZ:	return 0x02400;
+	default:		return 0x0;
+	}
+}
+
+static inline u32 AutoRstThLo(unsigned int fs)
+{
+	switch (fs) {
+	case FS_8000HZ:		return 0x30000;
+	case FS_11025HZ:	return 0x23000;
+	case FS_12000HZ:	return 0x20000;
+	case FS_16000HZ:	return 0x18000;
+	case FS_22050HZ:	return 0x11000;
+	case FS_24000HZ:	return 0x0FE00;
+	case FS_32000HZ:	return 0x0BE00;
+	case FS_44100HZ:	return 0x08A00;
+	case FS_48000HZ:	return 0x07F00;
+	case FS_88200HZ:	return 0x04500;
+	case FS_96000HZ:	return 0x04000;
+	case FS_176400HZ:	return 0x02300;
+	case FS_192000HZ:	return 0x02000;
+	default:		return 0x0;
+	}
+}
+
+bool mt8365_afe_clk_group_48k(int sample_rate);
+bool mt8365_afe_rate_supported(unsigned int rate, unsigned int id);
+bool mt8365_afe_channel_supported(unsigned int channel, unsigned int id);
+#ifdef CONFIG_MTK_HIFIXDSP_SUPPORT
+struct mtk_base_afe *mt8365_afe_pcm_get_info(void);
+#endif
+
+int mt8365_dai_i2s_register(struct mtk_base_afe *afe);
+int mt8365_dai_set_priv(struct mtk_base_afe *afe,
+			int id,
+			int priv_size,
+			const void *priv_data);
+
+int mt8365_afe_fs_timing(unsigned int rate);
+
+void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable);
+int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe, unsigned int rate,	int bit_width);
+
+int mt8365_dai_adda_register(struct mtk_base_afe *afe);
+int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe);
+int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe);
+
+int mt8365_dai_dmic_register(struct mtk_base_afe *afe);
+
+int mt8365_dai_pcm_register(struct mtk_base_afe *afe);
+
+int mt8365_dai_tdm_register(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8365/mt8365-reg.h b/sound/soc/mediatek/mt8365/mt8365-reg.h
new file mode 100644
index 000000000000..f79ae78b5c1e
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-reg.h
@@ -0,0 +1,991 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Mediatek 8365 audio driver reg definition
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#ifndef _MT8365_REG_H_
+#define _MT8365_REG_H_
+
+#define AUDIO_TOP_CON0			(0x0000)
+#define AUDIO_TOP_CON1			(0x0004)
+#define AUDIO_TOP_CON2			(0x0008)
+#define AUDIO_TOP_CON3			(0x000c)
+
+#define AFE_DAC_CON0			(0x0010)
+#define AFE_DAC_CON1			(0x0014)
+#define AFE_I2S_CON			(0x0018)
+#define AFE_CONN0			(0x0020)
+#define AFE_CONN1			(0x0024)
+#define AFE_CONN2			(0x0028)
+#define AFE_CONN3			(0x002c)
+#define AFE_CONN4			(0x0030)
+#define AFE_I2S_CON1			(0x0034)
+#define AFE_I2S_CON2			(0x0038)
+#define AFE_MRGIF_CON			(0x003c)
+#define AFE_DL1_BASE			(0x0040)
+#define AFE_DL1_CUR			(0x0044)
+#define AFE_DL1_END			(0x0048)
+#define AFE_I2S_CON3			(0x004c)
+#define AFE_DL2_BASE			(0x0050)
+#define AFE_DL2_CUR			(0x0054)
+#define AFE_DL2_END			(0x0058)
+#define AFE_CONN5			(0x005c)
+#define AFE_AWB_BASE			(0x0070)
+#define AFE_AWB_END			(0x0078)
+#define AFE_AWB_CUR			(0x007c)
+#define AFE_VUL_BASE			(0x0080)
+#define AFE_VUL_END			(0x0088)
+#define AFE_VUL_CUR			(0x008c)
+#define AFE_CONN6			(0x00bc)
+#define AFE_MEMIF_MSB			(0x00cc)
+#define AFE_MEMIF_MON0			(0x00d0)
+#define AFE_MEMIF_MON1			(0x00d4)
+#define AFE_MEMIF_MON2			(0x00d8)
+#define AFE_MEMIF_MON3			(0x00dc)
+#define AFE_MEMIF_MON4			(0x00e0)
+#define AFE_MEMIF_MON5			(0x00e4)
+#define AFE_MEMIF_MON6			(0x00e8)
+#define AFE_MEMIF_MON7			(0x00ec)
+#define AFE_MEMIF_MON8			(0x00f0)
+#define AFE_MEMIF_MON9			(0x00f4)
+#define AFE_MEMIF_MON10			(0x00f8)
+#define AFE_MEMIF_MON11			(0x00fc)
+#define AFE_ADDA_DL_SRC2_CON0		(0x0108)
+#define AFE_ADDA_DL_SRC2_CON1		(0x010c)
+#define AFE_ADDA_UL_SRC_CON0		(0x0114)
+#define AFE_ADDA_UL_SRC_CON1		(0x0118)
+#define AFE_ADDA_TOP_CON0		(0x0120)
+#define AFE_ADDA_UL_DL_CON0		(0x0124)
+#define AFE_ADDA_SRC_DEBUG		(0x012c)
+#define AFE_ADDA_SRC_DEBUG_MON0		(0x0130)
+#define AFE_ADDA_SRC_DEBUG_MON1		(0x0134)
+#define AFE_ADDA_UL_SRC_MON0		(0x0148)
+#define AFE_ADDA_UL_SRC_MON1		(0x014c)
+#define AFE_SRAM_BOUND			(0x0170)
+#define AFE_SECURE_CON			(0x0174)
+#define AFE_SECURE_CONN0		(0x0178)
+#define AFE_SIDETONE_DEBUG		(0x01d0)
+#define AFE_SIDETONE_MON		(0x01d4)
+#define AFE_SIDETONE_CON0		(0x01e0)
+#define AFE_SIDETONE_COEFF		(0x01e4)
+#define AFE_SIDETONE_CON1		(0x01e8)
+#define AFE_SIDETONE_GAIN		(0x01ec)
+#define AFE_SGEN_CON0			(0x01f0)
+#define AFE_SINEGEN_CON_TDM		(0x01f8)
+#define AFE_SINEGEN_CON_TDM_IN		(0x01fc)
+#define AFE_TOP_CON0			(0x0200)
+#define AFE_BUS_CFG			(0x0240)
+#define AFE_BUS_MON0			(0x0244)
+#define AFE_ADDA_PREDIS_CON0		(0x0260)
+#define AFE_ADDA_PREDIS_CON1		(0x0264)
+#define AFE_CONN_MON0			(0x0280)
+#define AFE_CONN_MON1			(0x0284)
+#define AFE_CONN_MON2			(0x0288)
+#define AFE_CONN_MON3			(0x028c)
+#define AFE_ADDA_IIR_COEF_02_01		(0x0290)
+#define AFE_ADDA_IIR_COEF_04_03		(0x0294)
+#define AFE_ADDA_IIR_COEF_06_05		(0x0298)
+#define AFE_ADDA_IIR_COEF_08_07		(0x029c)
+#define AFE_ADDA_IIR_COEF_10_09		(0x02a0)
+#define AFE_VUL_D2_BASE			(0x0350)
+#define AFE_VUL_D2_END			(0x0358)
+#define AFE_VUL_D2_CUR			(0x035c)
+#define AFE_HDMI_OUT_CON0		(0x0370)
+#define AFE_HDMI_OUT_BASE		(0x0374)
+#define AFE_HDMI_OUT_CUR		(0x0378)
+#define AFE_HDMI_OUT_END		(0x037c)
+#define AFE_SPDIF_OUT_CON0		(0x0380)
+#define AFE_SPDIF_OUT_BASE		(0x0384)
+#define AFE_SPDIF_OUT_CUR		(0x0388)
+#define AFE_SPDIF_OUT_END		(0x038c)
+#define AFE_HDMI_CONN0			(0x0390)
+#define AFE_HDMI_CONN1			(0x0398)
+#define AFE_CONN_TDMIN_CON		(0x039c)
+#define AFE_IRQ_MCU_CON			(0x03a0)
+#define AFE_IRQ_MCU_STATUS		(0x03a4)
+#define AFE_IRQ_MCU_CLR			(0x03a8)
+#define AFE_IRQ_MCU_CNT1		(0x03ac)
+#define AFE_IRQ_MCU_CNT2		(0x03b0)
+#define AFE_IRQ_MCU_EN			(0x03b4)
+#define AFE_IRQ_MCU_MON2		(0x03b8)
+#define AFE_IRQ_MCU_CNT5		(0x03bc)
+#define AFE_IRQ1_MCU_CNT_MON		(0x03c0)
+#define AFE_IRQ2_MCU_CNT_MON		(0x03c4)
+#define AFE_IRQ1_MCU_EN_CNT_MON		(0x03c8)
+#define AFE_IRQ5_MCU_CNT_MON		(0x03cc)
+#define AFE_MEMIF_MINLEN		(0x03d0)
+#define AFE_MEMIF_MAXLEN		(0x03d4)
+#define AFE_MEMIF_PBUF_SIZE		(0x03d8)
+#define AFE_IRQ_MCU_CNT7		(0x03dc)
+#define AFE_IRQ7_MCU_CNT_MON		(0x03e0)
+#define AFE_MEMIF_PBUF2_SIZE		(0x03ec)
+#define AFE_APLL_TUNER_CFG		(0x03f0)
+#define AFE_APLL_TUNER_CFG1		(0x03f4)
+#define AFE_IRQ_MCU_CON2		(0x03f8)
+#define IRQ13_MCU_CNT			(0x0408)
+#define IRQ13_MCU_CNT_MON		(0x040c)
+#define AFE_GAIN1_CON0			(0x0410)
+#define AFE_GAIN1_CON1			(0x0414)
+#define AFE_GAIN1_CON2			(0x0418)
+#define AFE_GAIN1_CON3			(0x041c)
+#define AFE_GAIN2_CON0			(0x0428)
+#define AFE_GAIN2_CON1			(0x042c)
+#define AFE_GAIN2_CON2			(0x0430)
+#define AFE_GAIN2_CON3			(0x0434)
+#define AFE_GAIN2_CUR			(0x043c)
+#define AFE_CONN11			(0x0448)
+#define AFE_CONN12			(0x044c)
+#define AFE_CONN13			(0x0450)
+#define AFE_CONN14			(0x0454)
+#define AFE_CONN15			(0x0458)
+#define AFE_CONN16			(0x045c)
+#define AFE_CONN7			(0x0460)
+#define AFE_CONN8			(0x0464)
+#define AFE_CONN9			(0x0468)
+#define AFE_CONN10			(0x046c)
+#define AFE_CONN21			(0x0470)
+#define AFE_CONN22			(0x0474)
+#define AFE_CONN23			(0x0478)
+#define AFE_CONN24			(0x047c)
+#define AFE_IEC_CFG			(0x0480)
+#define AFE_IEC_NSNUM			(0x0484)
+#define AFE_IEC_BURST_INFO		(0x0488)
+#define AFE_IEC_BURST_LEN		(0x048c)
+#define AFE_IEC_NSADR			(0x0490)
+#define AFE_CONN_RS			(0x0494)
+#define AFE_CONN_DI			(0x0498)
+#define AFE_IEC_CHL_STAT0		(0x04a0)
+#define AFE_IEC_CHL_STAT1		(0x04a4)
+#define AFE_IEC_CHR_STAT0		(0x04a8)
+#define AFE_IEC_CHR_STAT1		(0x04ac)
+#define AFE_CONN25			(0x04b0)
+#define AFE_CONN26			(0x04b4)
+#define FPGA_CFG2			(0x04b8)
+#define FPGA_CFG3			(0x04bc)
+#define FPGA_CFG0			(0x04c0)
+#define FPGA_CFG1			(0x04c4)
+#define AFE_SRAM_DELSEL_CON0		(0x04f0)
+#define AFE_SRAM_DELSEL_CON1		(0x04f4)
+#define AFE_SRAM_DELSEL_CON2		(0x04f8)
+#define FPGA_CFG4			(0x04fc)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON0	(0x0500)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON1	(0x0504)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON2	(0x0508)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON3	(0x050c)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON4	(0x0510)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON5	(0x0514)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON6	(0x0518)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON7	(0x051c)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON8	(0x0520)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON9	(0x0524)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON10	(0x0528)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON12	(0x0530)
+#define AFE_TDM_GASRC4_ASRC_2CH_CON13	(0x0534)
+#define PCM_INTF_CON2			(0x0538)
+#define PCM2_INTF_CON			(0x053c)
+#define AFE_APB_MON			(0x0540)
+#define AFE_CONN34			(0x0544)
+#define AFE_TDM_CON1			(0x0548)
+#define AFE_TDM_CON2			(0x054c)
+#define PCM_INTF_CON1			(0x0550)
+#define AFE_SECURE_MASK_CONN47_1	(0x0554)
+#define AFE_SECURE_MASK_CONN48_1	(0x0558)
+#define AFE_SECURE_MASK_CONN49_1	(0x055c)
+#define AFE_SECURE_MASK_CONN50_1	(0x0560)
+#define AFE_SECURE_MASK_CONN51_1	(0x0564)
+#define AFE_SECURE_MASK_CONN52_1	(0x0568)
+#define AFE_SECURE_MASK_CONN53_1	(0x056c)
+#define AFE_SE_SECURE_CON		(0x0570)
+#define AFE_TDM_IN_CON1			(0x0588)
+#define AFE_TDM_IN_CON2			(0x058c)
+#define AFE_TDM_IN_MON1			(0x0590)
+#define AFE_TDM_IN_MON2			(0x0594)
+#define AFE_TDM_IN_MON3			(0x0598)
+#define AFE_DMIC0_UL_SRC_CON0		(0x05b4)
+#define AFE_DMIC0_UL_SRC_CON1		(0x05b8)
+#define AFE_DMIC0_SRC_DEBUG		(0x05bc)
+#define AFE_DMIC0_SRC_DEBUG_MON0	(0x05c0)
+#define AFE_DMIC0_UL_SRC_MON0		(0x05c8)
+#define AFE_DMIC0_UL_SRC_MON1		(0x05cc)
+#define AFE_DMIC0_IIR_COEF_02_01	(0x05d0)
+#define AFE_DMIC0_IIR_COEF_04_03	(0x05d4)
+#define AFE_DMIC0_IIR_COEF_06_05	(0x05d8)
+#define AFE_DMIC0_IIR_COEF_08_07	(0x05dc)
+#define AFE_DMIC0_IIR_COEF_10_09	(0x05e0)
+#define AFE_DMIC1_UL_SRC_CON0		(0x0620)
+#define AFE_DMIC1_UL_SRC_CON1		(0x0624)
+#define AFE_DMIC1_SRC_DEBUG		(0x0628)
+#define AFE_DMIC1_SRC_DEBUG_MON0	(0x062c)
+#define AFE_DMIC1_UL_SRC_MON0		(0x0634)
+#define AFE_DMIC1_UL_SRC_MON1		(0x0638)
+#define AFE_DMIC1_IIR_COEF_02_01	(0x063c)
+#define AFE_DMIC1_IIR_COEF_04_03	(0x0640)
+#define AFE_DMIC1_IIR_COEF_06_05	(0x0644)
+#define AFE_DMIC1_IIR_COEF_08_07	(0x0648)
+#define AFE_DMIC1_IIR_COEF_10_09	(0x064c)
+#define AFE_SECURE_MASK_CONN39_1	(0x068c)
+#define AFE_SECURE_MASK_CONN40_1	(0x0690)
+#define AFE_SECURE_MASK_CONN41_1	(0x0694)
+#define AFE_SECURE_MASK_CONN42_1	(0x0698)
+#define AFE_SECURE_MASK_CONN43_1	(0x069c)
+#define AFE_SECURE_MASK_CONN44_1	(0x06a0)
+#define AFE_SECURE_MASK_CONN45_1	(0x06a4)
+#define AFE_SECURE_MASK_CONN46_1	(0x06a8)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON0	(0x06c0)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON1	(0x06c4)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON2	(0x06c8)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON3	(0x06cc)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON4	(0x06d0)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON5	(0x06d4)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON6	(0x06d8)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON7	(0x06dc)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON8	(0x06e0)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON9	(0x06e4)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON10	(0x06e8)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON12	(0x06f0)
+#define AFE_TDM_GASRC1_ASRC_2CH_CON13	(0x06f4)
+#define AFE_TDM_ASRC_CON0		(0x06f8)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON0	(0x0700)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON1	(0x0704)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON2	(0x0708)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON3	(0x070c)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON4	(0x0710)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON5	(0x0714)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON6	(0x0718)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON7	(0x071c)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON8	(0x0720)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON9	(0x0724)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON10	(0x0728)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON12	(0x0730)
+#define AFE_TDM_GASRC2_ASRC_2CH_CON13	(0x0734)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON0	(0x0740)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON1	(0x0744)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON2	(0x0748)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON3	(0x074c)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON4	(0x0750)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON5	(0x0754)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON6	(0x0758)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON7	(0x075c)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON8	(0x0760)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON9	(0x0764)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON10	(0x0768)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON12	(0x0770)
+#define AFE_TDM_GASRC3_ASRC_2CH_CON13	(0x0774)
+#define AFE_DMIC2_UL_SRC_CON0		(0x0780)
+#define AFE_DMIC2_UL_SRC_CON1		(0x0784)
+#define AFE_DMIC2_SRC_DEBUG		(0x0788)
+#define AFE_DMIC2_SRC_DEBUG_MON0	(0x078c)
+#define AFE_DMIC2_UL_SRC_MON0		(0x0794)
+#define AFE_DMIC2_UL_SRC_MON1		(0x0798)
+#define AFE_DMIC2_IIR_COEF_02_01	(0x079c)
+#define AFE_DMIC2_IIR_COEF_04_03	(0x07a0)
+#define AFE_DMIC2_IIR_COEF_06_05	(0x07a4)
+#define AFE_DMIC2_IIR_COEF_08_07	(0x07a8)
+#define AFE_DMIC2_IIR_COEF_10_09	(0x07ac)
+#define AFE_DMIC3_UL_SRC_CON0		(0x07ec)
+#define AFE_DMIC3_UL_SRC_CON1		(0x07f0)
+#define AFE_DMIC3_SRC_DEBUG		(0x07f4)
+#define AFE_DMIC3_SRC_DEBUG_MON0	(0x07f8)
+#define AFE_DMIC3_UL_SRC_MON0		(0x0800)
+#define AFE_DMIC3_UL_SRC_MON1		(0x0804)
+#define AFE_DMIC3_IIR_COEF_02_01	(0x0808)
+#define AFE_DMIC3_IIR_COEF_04_03	(0x080c)
+#define AFE_DMIC3_IIR_COEF_06_05	(0x0810)
+#define AFE_DMIC3_IIR_COEF_08_07	(0x0814)
+#define AFE_DMIC3_IIR_COEF_10_09	(0x0818)
+#define AFE_SECURE_MASK_CONN25_1	(0x0858)
+#define AFE_SECURE_MASK_CONN26_1	(0x085c)
+#define AFE_SECURE_MASK_CONN27_1	(0x0860)
+#define AFE_SECURE_MASK_CONN28_1	(0x0864)
+#define AFE_SECURE_MASK_CONN29_1	(0x0868)
+#define AFE_SECURE_MASK_CONN30_1	(0x086c)
+#define AFE_SECURE_MASK_CONN31_1	(0x0870)
+#define AFE_SECURE_MASK_CONN32_1	(0x0874)
+#define AFE_SECURE_MASK_CONN33_1	(0x0878)
+#define AFE_SECURE_MASK_CONN34_1	(0x087c)
+#define AFE_SECURE_MASK_CONN35_1	(0x0880)
+#define AFE_SECURE_MASK_CONN36_1	(0x0884)
+#define AFE_SECURE_MASK_CONN37_1	(0x0888)
+#define AFE_SECURE_MASK_CONN38_1	(0x088c)
+#define AFE_IRQ_MCU_SCP_EN		(0x0890)
+#define AFE_IRQ_MCU_DSP_EN		(0x0894)
+#define AFE_IRQ3_MCU_CNT_MON		(0x0898)
+#define AFE_IRQ4_MCU_CNT_MON		(0x089c)
+#define AFE_IRQ8_MCU_CNT_MON		(0x08a0)
+#define AFE_IRQ_MCU_CNT3		(0x08a4)
+#define AFE_IRQ_MCU_CNT4		(0x08a8)
+#define AFE_IRQ_MCU_CNT8		(0x08ac)
+#define AFE_IRQ_MCU_CNT11		(0x08b0)
+#define AFE_IRQ_MCU_CNT12		(0x08b4)
+#define AFE_IRQ11_MCU_CNT_MON		(0x08b8)
+#define AFE_IRQ12_MCU_CNT_MON		(0x08bc)
+#define AFE_VUL3_BASE			(0x08c0)
+#define AFE_VUL3_CUR			(0x08c4)
+#define AFE_VUL3_END			(0x08c8)
+#define AFE_VUL3_BASE_MSB		(0x08d0)
+#define AFE_VUL3_END_MSB		(0x08d4)
+#define AFE_IRQ10_MCU_CNT_MON		(0x08d8)
+#define AFE_IRQ_MCU_CNT10		(0x08dc)
+#define AFE_IRQ_ACC1_CNT		(0x08e0)
+#define AFE_IRQ_ACC2_CNT		(0x08e4)
+#define AFE_IRQ_ACC1_CNT_MON1		(0x08e8)
+#define AFE_IRQ_ACC2_CNT_MON		(0x08ec)
+#define AFE_TSF_CON			(0x08f0)
+#define AFE_TSF_MON			(0x08f4)
+#define AFE_IRQ_ACC1_CNT_MON2		(0x08f8)
+#define AFE_SPDIFIN_CFG0		(0x0900)
+#define AFE_SPDIFIN_CFG1		(0x0904)
+#define AFE_SPDIFIN_CHSTS1		(0x0908)
+#define AFE_SPDIFIN_CHSTS2		(0x090c)
+#define AFE_SPDIFIN_CHSTS3		(0x0910)
+#define AFE_SPDIFIN_CHSTS4		(0x0914)
+#define AFE_SPDIFIN_CHSTS5		(0x0918)
+#define AFE_SPDIFIN_CHSTS6		(0x091c)
+#define AFE_SPDIFIN_DEBUG1		(0x0920)
+#define AFE_SPDIFIN_DEBUG2		(0x0924)
+#define AFE_SPDIFIN_DEBUG3		(0x0928)
+#define AFE_SPDIFIN_DEBUG4		(0x092c)
+#define AFE_SPDIFIN_EC			(0x0930)
+#define AFE_SPDIFIN_CKLOCK_CFG		(0x0934)
+#define AFE_SPDIFIN_BR			(0x093c)
+#define AFE_SPDIFIN_BR_DBG1		(0x0940)
+#define AFE_SPDIFIN_INT_EXT		(0x0948)
+#define AFE_SPDIFIN_INT_EXT2		(0x094c)
+#define SPDIFIN_FREQ_INFO		(0x0950)
+#define SPDIFIN_FREQ_INFO_2		(0x0954)
+#define SPDIFIN_FREQ_INFO_3		(0x0958)
+#define SPDIFIN_FREQ_STATUS		(0x095c)
+#define SPDIFIN_USERCODE1		(0x0960)
+#define SPDIFIN_USERCODE2		(0x0964)
+#define SPDIFIN_USERCODE3		(0x0968)
+#define SPDIFIN_USERCODE4		(0x096c)
+#define SPDIFIN_USERCODE5		(0x0970)
+#define SPDIFIN_USERCODE6		(0x0974)
+#define SPDIFIN_USERCODE7		(0x0978)
+#define SPDIFIN_USERCODE8		(0x097c)
+#define SPDIFIN_USERCODE9		(0x0980)
+#define SPDIFIN_USERCODE10		(0x0984)
+#define SPDIFIN_USERCODE11		(0x0988)
+#define SPDIFIN_USERCODE12		(0x098c)
+#define SPDIFIN_MEMIF_CON0		(0x0990)
+#define SPDIFIN_BASE_ADR		(0x0994)
+#define SPDIFIN_END_ADR			(0x0998)
+#define SPDIFIN_APLL_TUNER_CFG		(0x09a0)
+#define SPDIFIN_APLL_TUNER_CFG1		(0x09a4)
+#define SPDIFIN_APLL2_TUNER_CFG		(0x09a8)
+#define SPDIFIN_APLL2_TUNER_CFG1	(0x09ac)
+#define SPDIFIN_TYPE_DET		(0x09b0)
+#define MPHONE_MULTI_CON0		(0x09b4)
+#define SPDIFIN_CUR_ADR			(0x09b8)
+#define AFE_SINEGEN_CON_SPDIFIN		(0x09bc)
+#define AFE_HDMI_IN_2CH_CON0		(0x09c0)
+#define AFE_HDMI_IN_2CH_BASE		(0x09c4)
+#define AFE_HDMI_IN_2CH_END		(0x09c8)
+#define AFE_HDMI_IN_2CH_CUR		(0x09cc)
+#define AFE_MEMIF_BUF_MON0		(0x09d0)
+#define AFE_MEMIF_BUF_MON1		(0x09d4)
+#define AFE_MEMIF_BUF_MON2		(0x09d8)
+#define AFE_MEMIF_BUF_MON3		(0x09dc)
+#define AFE_MEMIF_BUF_MON6		(0x09e8)
+#define AFE_MEMIF_BUF_MON7		(0x09ec)
+#define AFE_MEMIF_BUF_MON8		(0x09f0)
+#define AFE_MEMIF_BUF_MON10		(0x09f8)
+#define AFE_MEMIF_BUF_MON11		(0x09fc)
+#define SYSTOP_STC_CONFIG		(0x0a00)
+#define AUDIO_STC_STATUS		(0x0a04)
+#define SYSTOP_W_STC_H			(0x0a08)
+#define SYSTOP_W_STC_L			(0x0a0c)
+#define SYSTOP_R_STC_H			(0x0a10)
+#define SYSTOP_R_STC_L			(0x0a14)
+#define AUDIO_W_STC_H			(0x0a18)
+#define AUDIO_W_STC_L			(0x0a1c)
+#define AUDIO_R_STC_H			(0x0a20)
+#define AUDIO_R_STC_L			(0x0a24)
+#define SYSTOP_W_STC2_H			(0x0a28)
+#define SYSTOP_W_STC2_L			(0x0a2c)
+#define SYSTOP_R_STC2_H			(0x0a30)
+#define SYSTOP_R_STC2_L			(0x0a34)
+#define AUDIO_W_STC2_H			(0x0a38)
+#define AUDIO_W_STC2_L			(0x0a3c)
+#define AUDIO_R_STC2_H			(0x0a40)
+#define AUDIO_R_STC2_L			(0x0a44)
+
+#define AFE_CONN17			(0x0a48)
+#define AFE_CONN18			(0x0a4c)
+#define AFE_CONN19			(0x0a50)
+#define AFE_CONN20			(0x0a54)
+#define AFE_CONN27			(0x0a58)
+#define AFE_CONN28			(0x0a5c)
+#define AFE_CONN29			(0x0a60)
+#define AFE_CONN30			(0x0a64)
+#define AFE_CONN31			(0x0a68)
+#define AFE_CONN32			(0x0a6c)
+#define AFE_CONN33			(0x0a70)
+#define AFE_CONN35			(0x0a74)
+#define AFE_CONN36			(0x0a78)
+#define AFE_CONN37			(0x0a7c)
+#define AFE_CONN38			(0x0a80)
+#define AFE_CONN39			(0x0a84)
+#define AFE_CONN40			(0x0a88)
+#define AFE_CONN41			(0x0a8c)
+#define AFE_CONN42			(0x0a90)
+#define AFE_CONN44			(0x0a94)
+#define AFE_CONN45			(0x0a98)
+#define AFE_CONN46			(0x0a9c)
+#define AFE_CONN47			(0x0aa0)
+#define AFE_CONN_24BIT			(0x0aa4)
+#define AFE_CONN0_1			(0x0aa8)
+#define AFE_CONN1_1			(0x0aac)
+#define AFE_CONN2_1			(0x0ab0)
+#define AFE_CONN3_1			(0x0ab4)
+#define AFE_CONN4_1			(0x0ab8)
+#define AFE_CONN5_1			(0x0abc)
+#define AFE_CONN6_1			(0x0ac0)
+#define AFE_CONN7_1			(0x0ac4)
+#define AFE_CONN8_1			(0x0ac8)
+#define AFE_CONN9_1			(0x0acc)
+#define AFE_CONN10_1			(0x0ad0)
+#define AFE_CONN11_1			(0x0ad4)
+#define AFE_CONN12_1			(0x0ad8)
+#define AFE_CONN13_1			(0x0adc)
+#define AFE_CONN14_1			(0x0ae0)
+#define AFE_CONN15_1			(0x0ae4)
+#define AFE_CONN16_1			(0x0ae8)
+#define AFE_CONN17_1			(0x0aec)
+#define AFE_CONN18_1			(0x0af0)
+#define AFE_CONN19_1			(0x0af4)
+#define AFE_CONN43			(0x0af8)
+#define AFE_CONN43_1			(0x0afc)
+#define AFE_CONN21_1			(0x0b00)
+#define AFE_CONN22_1			(0x0b04)
+#define AFE_CONN23_1			(0x0b08)
+#define AFE_CONN24_1			(0x0b0c)
+#define AFE_CONN25_1			(0x0b10)
+#define AFE_CONN26_1			(0x0b14)
+#define AFE_CONN27_1			(0x0b18)
+#define AFE_CONN28_1			(0x0b1c)
+#define AFE_CONN29_1			(0x0b20)
+#define AFE_CONN30_1			(0x0b24)
+#define AFE_CONN31_1			(0x0b28)
+#define AFE_CONN32_1			(0x0b2c)
+#define AFE_CONN33_1			(0x0b30)
+#define AFE_CONN34_1			(0x0b34)
+#define AFE_CONN35_1			(0x0b38)
+#define AFE_CONN36_1			(0x0b3c)
+#define AFE_CONN37_1			(0x0b40)
+#define AFE_CONN38_1			(0x0b44)
+#define AFE_CONN39_1			(0x0b48)
+#define AFE_CONN40_1			(0x0b4c)
+#define AFE_CONN41_1			(0x0b50)
+#define AFE_CONN42_1			(0x0b54)
+#define AFE_CONN44_1			(0x0b58)
+#define AFE_CONN45_1			(0x0b5c)
+#define AFE_CONN46_1			(0x0b60)
+#define AFE_CONN47_1			(0x0b64)
+#define AFE_CONN_RS_1			(0x0b68)
+#define AFE_CONN_DI_1			(0x0b6c)
+#define AFE_CONN_24BIT_1		(0x0b70)
+#define AFE_GAIN1_CUR			(0x0b78)
+#define AFE_CONN20_1			(0x0b7c)
+#define AFE_DL1_BASE_MSB		(0x0b80)
+#define AFE_DL1_END_MSB			(0x0b84)
+#define AFE_DL2_BASE_MSB		(0x0b88)
+#define AFE_DL2_END_MSB			(0x0b8c)
+#define AFE_AWB_BASE_MSB		(0x0b90)
+#define AFE_AWB_END_MSB			(0x0b94)
+#define AFE_VUL_BASE_MSB		(0x0ba0)
+#define AFE_VUL_END_MSB			(0x0ba4)
+#define AFE_VUL_D2_BASE_MSB		(0x0ba8)
+#define AFE_VUL_D2_END_MSB		(0x0bac)
+#define AFE_HDMI_OUT_BASE_MSB		(0x0bb8)
+#define AFE_HDMI_OUT_END_MSB		(0x0bbc)
+#define AFE_HDMI_IN_2CH_BASE_MSB	(0x0bc0)
+#define AFE_HDMI_IN_2CH_END_MSB		(0x0bc4)
+#define AFE_SPDIF_OUT_BASE_MSB		(0x0bc8)
+#define AFE_SPDIF_OUT_END_MSB		(0x0bcc)
+#define SPDIFIN_BASE_MSB		(0x0bd0)
+#define SPDIFIN_END_MSB			(0x0bd4)
+#define AFE_DL1_CUR_MSB			(0x0bd8)
+#define AFE_DL2_CUR_MSB			(0x0bdc)
+#define AFE_AWB_CUR_MSB			(0x0be8)
+#define AFE_VUL_CUR_MSB			(0x0bf8)
+#define AFE_VUL_D2_CUR_MSB		(0x0c04)
+#define AFE_HDMI_OUT_CUR_MSB		(0x0c0c)
+#define AFE_HDMI_IN_2CH_CUR_MSB		(0x0c10)
+#define AFE_SPDIF_OUT_CUR_MSB		(0x0c14)
+#define SPDIFIN_CUR_MSB			(0x0c18)
+#define AFE_CONN_REG			(0x0c20)
+#define AFE_SECURE_MASK_CONN14_1	(0x0c24)
+#define AFE_SECURE_MASK_CONN15_1	(0x0c28)
+#define AFE_SECURE_MASK_CONN16_1	(0x0c2c)
+#define AFE_SECURE_MASK_CONN17_1	(0x0c30)
+#define AFE_SECURE_MASK_CONN18_1	(0x0c34)
+#define AFE_SECURE_MASK_CONN19_1	(0x0c38)
+#define AFE_SECURE_MASK_CONN20_1	(0x0c3c)
+#define AFE_SECURE_MASK_CONN21_1	(0x0c40)
+#define AFE_SECURE_MASK_CONN22_1	(0x0c44)
+#define AFE_SECURE_MASK_CONN23_1	(0x0c48)
+#define AFE_SECURE_MASK_CONN24_1	(0x0c4c)
+#define AFE_ADDA_DL_SDM_DCCOMP_CON	(0x0c50)
+#define AFE_ADDA_DL_SDM_TEST		(0x0c54)
+#define AFE_ADDA_DL_DC_COMP_CFG0	(0x0c58)
+#define AFE_ADDA_DL_DC_COMP_CFG1	(0x0c5c)
+#define AFE_ADDA_DL_SDM_FIFO_MON	(0x0c60)
+#define AFE_ADDA_DL_SRC_LCH_MON		(0x0c64)
+#define AFE_ADDA_DL_SRC_RCH_MON		(0x0c68)
+#define AFE_ADDA_DL_SDM_OUT_MON		(0x0c6c)
+#define AFE_ADDA_DL_SDM_DITHER_CON	(0x0c70)
+
+#define AFE_VUL3_CUR_MSB		(0x0c78)
+#define AFE_ASRC_2CH_CON0		(0x0c80)
+#define AFE_ASRC_2CH_CON1		(0x0c84)
+#define AFE_ASRC_2CH_CON2		(0x0c88)
+#define AFE_ASRC_2CH_CON3		(0x0c8c)
+#define AFE_ASRC_2CH_CON4		(0x0c90)
+#define AFE_ASRC_2CH_CON5		(0x0c94)
+#define AFE_ASRC_2CH_CON6		(0x0c98)
+#define AFE_ASRC_2CH_CON7		(0x0c9c)
+#define AFE_ASRC_2CH_CON8		(0x0ca0)
+#define AFE_ASRC_2CH_CON9		(0x0ca4)
+#define AFE_ASRC_2CH_CON10		(0x0ca8)
+#define AFE_ASRC_2CH_CON12		(0x0cb0)
+#define AFE_ASRC_2CH_CON13		(0x0cb4)
+
+#define AFE_PCM_TX_ASRC_2CH_CON0	(0x0cc0)
+#define AFE_PCM_TX_ASRC_2CH_CON1	(0x0cc4)
+#define AFE_PCM_TX_ASRC_2CH_CON2	(0x0cc8)
+#define AFE_PCM_TX_ASRC_2CH_CON3	(0x0ccc)
+#define AFE_PCM_TX_ASRC_2CH_CON4	(0x0cd0)
+#define AFE_PCM_TX_ASRC_2CH_CON5	(0x0cd4)
+#define AFE_PCM_TX_ASRC_2CH_CON6	(0x0cd8)
+#define AFE_PCM_TX_ASRC_2CH_CON7	(0x0cdc)
+#define AFE_PCM_TX_ASRC_2CH_CON8	(0x0ce0)
+#define AFE_PCM_TX_ASRC_2CH_CON9	(0x0ce4)
+#define AFE_PCM_TX_ASRC_2CH_CON10	(0x0ce8)
+#define AFE_PCM_TX_ASRC_2CH_CON12	(0x0cf0)
+#define AFE_PCM_TX_ASRC_2CH_CON13	(0x0cf4)
+#define AFE_PCM_RX_ASRC_2CH_CON0	(0x0d00)
+#define AFE_PCM_RX_ASRC_2CH_CON1	(0x0d04)
+#define AFE_PCM_RX_ASRC_2CH_CON2	(0x0d08)
+#define AFE_PCM_RX_ASRC_2CH_CON3	(0x0d0c)
+#define AFE_PCM_RX_ASRC_2CH_CON4	(0x0d10)
+#define AFE_PCM_RX_ASRC_2CH_CON5	(0x0d14)
+#define AFE_PCM_RX_ASRC_2CH_CON6	(0x0d18)
+#define AFE_PCM_RX_ASRC_2CH_CON7	(0x0d1c)
+#define AFE_PCM_RX_ASRC_2CH_CON8	(0x0d20)
+#define AFE_PCM_RX_ASRC_2CH_CON9	(0x0d24)
+#define AFE_PCM_RX_ASRC_2CH_CON10	(0x0d28)
+#define AFE_PCM_RX_ASRC_2CH_CON12	(0x0d30)
+#define AFE_PCM_RX_ASRC_2CH_CON13	(0x0d34)
+
+#define AFE_ADDA_PREDIS_CON2		(0x0d40)
+#define AFE_ADDA_PREDIS_CON3		(0x0d44)
+#define AFE_SECURE_MASK_CONN4_1		(0x0d48)
+#define AFE_SECURE_MASK_CONN5_1		(0x0d4c)
+#define AFE_SECURE_MASK_CONN6_1		(0x0d50)
+#define AFE_SECURE_MASK_CONN7_1		(0x0d54)
+#define AFE_SECURE_MASK_CONN8_1		(0x0d58)
+#define AFE_SECURE_MASK_CONN9_1		(0x0d5c)
+#define AFE_SECURE_MASK_CONN10_1	(0x0d60)
+#define AFE_SECURE_MASK_CONN11_1	(0x0d64)
+#define AFE_SECURE_MASK_CONN12_1	(0x0d68)
+#define AFE_SECURE_MASK_CONN13_1	(0x0d6c)
+#define AFE_MEMIF_MON12			(0x0d70)
+#define AFE_MEMIF_MON13			(0x0d74)
+#define AFE_MEMIF_MON14			(0x0d78)
+#define AFE_MEMIF_MON15			(0x0d7c)
+#define AFE_SECURE_MASK_CONN42		(0x0dbc)
+#define AFE_SECURE_MASK_CONN43		(0x0dc0)
+#define AFE_SECURE_MASK_CONN44		(0x0dc4)
+#define AFE_SECURE_MASK_CONN45		(0x0dc8)
+#define AFE_SECURE_MASK_CONN46		(0x0dcc)
+#define AFE_HD_ENGEN_ENABLE		(0x0dd0)
+#define AFE_SECURE_MASK_CONN47		(0x0dd4)
+#define AFE_SECURE_MASK_CONN48		(0x0dd8)
+#define AFE_SECURE_MASK_CONN49		(0x0ddc)
+#define AFE_SECURE_MASK_CONN50		(0x0de0)
+#define AFE_SECURE_MASK_CONN51		(0x0de4)
+#define AFE_SECURE_MASK_CONN52		(0x0de8)
+#define AFE_SECURE_MASK_CONN53		(0x0dec)
+#define AFE_SECURE_MASK_CONN0_1		(0x0df0)
+#define AFE_SECURE_MASK_CONN1_1		(0x0df4)
+#define AFE_SECURE_MASK_CONN2_1		(0x0df8)
+#define AFE_SECURE_MASK_CONN3_1		(0x0dfc)
+
+#define AFE_ADDA_MTKAIF_CFG0		(0x0e00)
+#define AFE_ADDA_MTKAIF_SYNCWORD_CFG	(0x0e14)
+#define AFE_ADDA_MTKAIF_RX_CFG0		(0x0e20)
+#define AFE_ADDA_MTKAIF_RX_CFG1		(0x0e24)
+#define AFE_ADDA_MTKAIF_RX_CFG2		(0x0e28)
+#define AFE_ADDA_MTKAIF_MON0		(0x0e34)
+#define AFE_ADDA_MTKAIF_MON1		(0x0e38)
+#define AFE_AUD_PAD_TOP			(0x0e40)
+
+#define AFE_CM1_CON4			(0x0e48)
+#define AFE_CM2_CON4			(0x0e4c)
+#define AFE_CM1_CON0			(0x0e50)
+#define AFE_CM1_CON1			(0x0e54)
+#define AFE_CM1_CON2			(0x0e58)
+#define AFE_CM1_CON3			(0x0e5c)
+#define AFE_CM2_CON0			(0x0e60)
+#define AFE_CM2_CON1			(0x0e64)
+#define AFE_CM2_CON2			(0x0e68)
+#define AFE_CM2_CON3			(0x0e6c)
+#define AFE_CM2_CONN0			(0x0e70)
+#define AFE_CM2_CONN1			(0x0e74)
+#define AFE_CM2_CONN2			(0x0e78)
+
+#define AFE_GENERAL1_ASRC_2CH_CON0	(0x0e80)
+#define AFE_GENERAL1_ASRC_2CH_CON1	(0x0e84)
+#define AFE_GENERAL1_ASRC_2CH_CON2	(0x0e88)
+#define AFE_GENERAL1_ASRC_2CH_CON3	(0x0e8c)
+#define AFE_GENERAL1_ASRC_2CH_CON4	(0x0e90)
+#define AFE_GENERAL1_ASRC_2CH_CON5	(0x0e94)
+#define AFE_GENERAL1_ASRC_2CH_CON6	(0x0e98)
+#define AFE_GENERAL1_ASRC_2CH_CON7	(0x0e9c)
+#define AFE_GENERAL1_ASRC_2CH_CON8	(0x0ea0)
+#define AFE_GENERAL1_ASRC_2CH_CON9	(0x0ea4)
+#define AFE_GENERAL1_ASRC_2CH_CON10	(0x0ea8)
+#define AFE_GENERAL1_ASRC_2CH_CON12	(0x0eb0)
+#define AFE_GENERAL1_ASRC_2CH_CON13	(0x0eb4)
+#define GENERAL_ASRC_MODE		(0x0eb8)
+#define GENERAL_ASRC_EN_ON		(0x0ebc)
+
+#define AFE_CONN48			(0x0ec0)
+#define AFE_CONN49			(0x0ec4)
+#define AFE_CONN50			(0x0ec8)
+#define AFE_CONN51			(0x0ecc)
+#define AFE_CONN52			(0x0ed0)
+#define AFE_CONN53			(0x0ed4)
+#define AFE_CONN48_1			(0x0ee0)
+#define AFE_CONN49_1			(0x0ee4)
+#define AFE_CONN50_1			(0x0ee8)
+#define AFE_CONN51_1			(0x0eec)
+#define AFE_CONN52_1			(0x0ef0)
+#define AFE_CONN53_1			(0x0ef4)
+
+#define AFE_GENERAL2_ASRC_2CH_CON0	(0x0f00)
+#define AFE_GENERAL2_ASRC_2CH_CON1	(0x0f04)
+#define AFE_GENERAL2_ASRC_2CH_CON2	(0x0f08)
+#define AFE_GENERAL2_ASRC_2CH_CON3	(0x0f0c)
+#define AFE_GENERAL2_ASRC_2CH_CON4	(0x0f10)
+#define AFE_GENERAL2_ASRC_2CH_CON5	(0x0f14)
+#define AFE_GENERAL2_ASRC_2CH_CON6	(0x0f18)
+#define AFE_GENERAL2_ASRC_2CH_CON7	(0x0f1c)
+#define AFE_GENERAL2_ASRC_2CH_CON8	(0x0f20)
+#define AFE_GENERAL2_ASRC_2CH_CON9	(0x0f24)
+#define AFE_GENERAL2_ASRC_2CH_CON10	(0x0f28)
+#define AFE_GENERAL2_ASRC_2CH_CON12	(0x0f30)
+#define AFE_GENERAL2_ASRC_2CH_CON13	(0x0f34)
+
+#define AFE_SECURE_MASK_CONN28		(0x0f48)
+#define AFE_SECURE_MASK_CONN29		(0x0f4c)
+#define AFE_SECURE_MASK_CONN30		(0x0f50)
+#define AFE_SECURE_MASK_CONN31		(0x0f54)
+#define AFE_SECURE_MASK_CONN32		(0x0f58)
+#define AFE_SECURE_MASK_CONN33		(0x0f5c)
+#define AFE_SECURE_MASK_CONN34		(0x0f60)
+#define AFE_SECURE_MASK_CONN35		(0x0f64)
+#define AFE_SECURE_MASK_CONN36		(0x0f68)
+#define AFE_SECURE_MASK_CONN37		(0x0f6c)
+#define AFE_SECURE_MASK_CONN38		(0x0f70)
+#define AFE_SECURE_MASK_CONN39		(0x0f74)
+#define AFE_SECURE_MASK_CONN40		(0x0f78)
+#define AFE_SECURE_MASK_CONN41		(0x0f7c)
+#define AFE_SIDEBAND0			(0x0f80)
+#define AFE_SIDEBAND1			(0x0f84)
+#define AFE_SECURE_SIDEBAND0		(0x0f88)
+#define AFE_SECURE_SIDEBAND1		(0x0f8c)
+#define AFE_SECURE_MASK_CONN0		(0x0f90)
+#define AFE_SECURE_MASK_CONN1		(0x0f94)
+#define AFE_SECURE_MASK_CONN2		(0x0f98)
+#define AFE_SECURE_MASK_CONN3		(0x0f9c)
+#define AFE_SECURE_MASK_CONN4		(0x0fa0)
+#define AFE_SECURE_MASK_CONN5		(0x0fa4)
+#define AFE_SECURE_MASK_CONN6		(0x0fa8)
+#define AFE_SECURE_MASK_CONN7		(0x0fac)
+#define AFE_SECURE_MASK_CONN8		(0x0fb0)
+#define AFE_SECURE_MASK_CONN9		(0x0fb4)
+#define AFE_SECURE_MASK_CONN10		(0x0fb8)
+#define AFE_SECURE_MASK_CONN11		(0x0fbc)
+#define AFE_SECURE_MASK_CONN12		(0x0fc0)
+#define AFE_SECURE_MASK_CONN13		(0x0fc4)
+#define AFE_SECURE_MASK_CONN14		(0x0fc8)
+#define AFE_SECURE_MASK_CONN15		(0x0fcc)
+#define AFE_SECURE_MASK_CONN16		(0x0fd0)
+#define AFE_SECURE_MASK_CONN17		(0x0fd4)
+#define AFE_SECURE_MASK_CONN18		(0x0fd8)
+#define AFE_SECURE_MASK_CONN19		(0x0fdc)
+#define AFE_SECURE_MASK_CONN20		(0x0fe0)
+#define AFE_SECURE_MASK_CONN21		(0x0fe4)
+#define AFE_SECURE_MASK_CONN22		(0x0fe8)
+#define AFE_SECURE_MASK_CONN23		(0x0fec)
+#define AFE_SECURE_MASK_CONN24		(0x0ff0)
+#define AFE_SECURE_MASK_CONN25		(0x0ff4)
+#define AFE_SECURE_MASK_CONN26		(0x0ff8)
+#define AFE_SECURE_MASK_CONN27		(0x0ffc)
+
+#define MAX_REGISTER			AFE_SECURE_MASK_CONN27
+
+#define AFE_IRQ_STATUS_BITS		0x3ff
+
+/* AUDIO_TOP_CON0 (0x0000) */
+#define AUD_TCON0_PDN_TML		BIT(27)
+#define AUD_TCON0_PDN_DAC_PREDIS	BIT(26)
+#define AUD_TCON0_PDN_DAC		BIT(25)
+#define AUD_TCON0_PDN_ADC		BIT(24)
+#define AUD_TCON0_PDN_TDM_IN		BIT(23)
+#define AUD_TCON0_PDN_TDM_OUT		BIT(22)
+#define AUD_TCON0_PDN_SPDIF		BIT(21)
+#define AUD_TCON0_PDN_APLL_TUNER	BIT(19)
+#define AUD_TCON0_PDN_APLL2_TUNER	BIT(18)
+#define AUD_TCON0_PDN_INTDIR		BIT(15)
+#define AUD_TCON0_PDN_24M		BIT(9)
+#define AUD_TCON0_PDN_22M		BIT(8)
+#define AUD_TCON0_PDN_I2S_IN		BIT(6)
+#define AUD_TCON0_PDN_AFE		BIT(2)
+
+/* AUDIO_TOP_CON1 (0x0004) */
+#define AUD_TCON1_PDN_TDM_ASRC		BIT(15)
+#define AUD_TCON1_PDN_GENERAL2_ASRC	BIT(14)
+#define AUD_TCON1_PDN_GENERAL1_ASRC	BIT(13)
+#define AUD_TCON1_PDN_CONNSYS_I2S_ASRC	BIT(12)
+#define AUD_TCON1_PDN_DMIC3_ADC		BIT(11)
+#define AUD_TCON1_PDN_DMIC2_ADC		BIT(10)
+#define AUD_TCON1_PDN_DMIC1_ADC		BIT(9)
+#define AUD_TCON1_PDN_DMIC0_ADC		BIT(8)
+#define AUD_TCON1_PDN_I2S4_BCLK		BIT(7)
+#define AUD_TCON1_PDN_I2S3_BCLK		BIT(6)
+#define AUD_TCON1_PDN_I2S2_BCLK		BIT(5)
+#define AUD_TCON1_PDN_I2S1_BCLK		BIT(4)
+
+/* AUDIO_TOP_CON3 (0x000C) */
+#define AUD_TCON3_HDMI_BCK_INV		BIT(3)
+
+/* AFE_I2S_CON (0x0018) */
+#define AFE_I2S_CON_PHASE_SHIFT_FIX	BIT(31)
+#define AFE_I2S_CON_FROM_IO_MUX		BIT(28)
+#define AFE_I2S_CON_LOW_JITTER_CLK	BIT(12)
+#define AFE_I2S_CON_RATE_MASK		GENMASK(11, 8)
+#define AFE_I2S_CON_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON_SRC_SLAVE		BIT(2)
+
+/* AFE_ASRC_2CH_CON0 */
+#define ONE_HEART	BIT(31)
+#define CHSET_STR_CLR	BIT(4)
+#define COEFF_SRAM_CTRL	BIT(1)
+#define ASM_ON		BIT(0)
+
+/* CON2 */
+#define O16BIT		BIT(19)
+#define CLR_IIR_HISTORY	BIT(17)
+#define IS_MONO		BIT(16)
+#define IIR_EN		BIT(11)
+#define IIR_STAGE_MASK	GENMASK(10, 8)
+
+/* CON5 */
+#define CALI_CYCLE_MASK	GENMASK(31, 16)
+#define CALI_64_CYCLE	FIELD_PREP(CALI_CYCLE_MASK, 0x3F)
+#define CALI_96_CYCLE	FIELD_PREP(CALI_CYCLE_MASK, 0x5F)
+#define CALI_441_CYCLE	FIELD_PREP(CALI_CYCLE_MASK, 0x1B8)
+
+#define CALI_AUTORST	BIT(15)
+#define AUTO_TUNE_FREQ5	BIT(12)
+#define COMP_FREQ_RES	BIT(11)
+
+#define CALI_SEL_MASK	GENMASK(9, 8)
+#define CALI_SEL_00	FIELD_PREP(CALI_SEL_MASK, 0)
+#define CALI_SEL_01	FIELD_PREP(CALI_SEL_MASK, 1)
+
+#define CALI_BP_DGL		BIT(7) /* Bypass the deglitch circuit */
+#define AUTO_TUNE_FREQ4		BIT(3)
+#define CALI_AUTO_RESTART	BIT(2)
+#define CALI_USE_FREQ_OUT	BIT(1)
+#define CALI_ON			BIT(0)
+
+#define AFE_I2S_CON_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON_EN			BIT(0)
+
+#define AFE_CONN3_I03_O03_S		BIT(3)
+#define AFE_CONN4_I04_O04_S		BIT(4)
+#define AFE_CONN4_I03_O04_S		BIT(3)
+
+/* AFE_I2S_CON1 (0x0034) */
+#define AFE_I2S_CON1_I2S2_TO_PAD	BIT(18)
+#define AFE_I2S_CON1_TDMOUT_TO_PAD	(0 << 18)
+#define AFE_I2S_CON1_RATE		GENMASK(11, 8)
+#define AFE_I2S_CON1_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON1_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON1_EN			BIT(0)
+
+/* AFE_I2S_CON2 (0x0038) */
+#define AFE_I2S_CON2_LOW_JITTER_CLK	BIT(12)
+#define AFE_I2S_CON2_RATE		GENMASK(11, 8)
+#define AFE_I2S_CON2_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON2_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON2_EN			BIT(0)
+
+/* AFE_I2S_CON3 (0x004C) */
+#define AFE_I2S_CON3_LOW_JITTER_CLK	BIT(12)
+#define AFE_I2S_CON3_RATE		GENMASK(11, 8)
+#define AFE_I2S_CON3_FORMAT_I2S		BIT(3)
+#define AFE_I2S_CON3_WLEN_32BIT		BIT(1)
+#define AFE_I2S_CON3_EN			BIT(0)
+
+/* AFE_ADDA_DL_SRC2_CON0 (0x0108) */
+#define AFE_ADDA_DL_SAMPLING_RATE	GENMASK(31, 28)
+#define AFE_ADDA_DL_8X_UPSAMPLE		GENMASK(25, 24)
+#define AFE_ADDA_DL_MUTE_OFF_CH1	BIT(12)
+#define AFE_ADDA_DL_MUTE_OFF_CH2	BIT(11)
+#define AFE_ADDA_DL_VOICE_DATA		BIT(5)
+#define AFE_ADDA_DL_DEGRADE_GAIN	BIT(1)
+
+/* AFE_ADDA_UL_SRC_CON0 (0x0114) */
+#define AFE_ADDA_UL_SAMPLING_RATE	GENMASK(19, 17)
+
+/* AFE_ADDA_UL_DL_CON0 */
+#define AFE_ADDA_UL_DL_ADDA_AFE_ON	BIT(0)
+#define AFE_ADDA_UL_DL_DMIC_CLKDIV_ON	BIT(1)
+
+/* AFE_APLL_TUNER_CFG (0x03f0) */
+#define AFE_APLL_TUNER_CFG_MASK		GENMASK(15, 1)
+#define AFE_APLL_TUNER_CFG_EN_MASK	BIT(0)
+
+/* AFE_APLL_TUNER_CFG1 (0x03f4) */
+#define AFE_APLL_TUNER_CFG1_MASK	GENMASK(15, 1)
+#define AFE_APLL_TUNER_CFG1_EN_MASK	BIT(0)
+
+/* PCM_INTF_CON1 (0x0550) */
+#define PCM_INTF_CON1_EXT_MODEM		BIT(17)
+#define PCM_INTF_CON1_16BIT		(0 << 16)
+#define PCM_INTF_CON1_24BIT		BIT(16)
+#define PCM_INTF_CON1_32BCK		(0 << 14)
+#define PCM_INTF_CON1_64BCK		BIT(14)
+#define PCM_INTF_CON1_MASTER_MODE	(0 << 5)
+#define PCM_INTF_CON1_SLAVE_MODE	BIT(5)
+#define PCM_INTF_CON1_FS_MASK		GENMASK(4, 3)
+#define PCM_INTF_CON1_FS_8K		FIELD_PREP(PCM_INTF_CON1_FS_MASK, 0)
+#define PCM_INTF_CON1_FS_16K		FIELD_PREP(PCM_INTF_CON1_FS_MASK, 1)
+#define PCM_INTF_CON1_FS_32K		FIELD_PREP(PCM_INTF_CON1_FS_MASK, 2)
+#define PCM_INTF_CON1_FS_48K		FIELD_PREP(PCM_INTF_CON1_FS_MASK, 3)
+#define PCM_INTF_CON1_SYNC_LEN_MASK	GENMASK(13, 9)
+#define PCM_INTF_CON1_SYNC_LEN(x)	FIELD_PREP(PCM_INTF_CON1_SYNC_LEN_MASK, ((x) - 1))
+#define PCM_INTF_CON1_FORMAT_MASK	GENMASK(2, 1)
+#define PCM_INTF_CON1_SYNC_OUT_INV	BIT(23)
+#define PCM_INTF_CON1_BCLK_OUT_INV	BIT(22)
+#define PCM_INTF_CON1_SYNC_IN_INV	BIT(21)
+#define PCM_INTF_CON1_BCLK_IN_INV	BIT(20)
+#define PCM_INTF_CON1_BYPASS_ASRC	BIT(6)
+#define PCM_INTF_CON1_EN		BIT(0)
+#define PCM_INTF_CON1_CONFIG_MASK	(0xf3fffe)
+
+/* AFE_DMIC0_UL_SRC_CON0 (0x05b4)
+ * AFE_DMIC1_UL_SRC_CON0 (0x0620)
+ * AFE_DMIC2_UL_SRC_CON0 (0x0780)
+ * AFE_DMIC3_UL_SRC_CON0 (0x07ec)
+ */
+#define DMIC_TOP_CON_CK_PHASE_SEL_CH1		GENMASK(29, 27)
+#define DMIC_TOP_CON_CK_PHASE_SEL_CH2		GENMASK(26, 24)
+#define DMIC_TOP_CON_TWO_WIRE_MODE		BIT(23)
+#define DMIC_TOP_CON_CH2_ON			BIT(22)
+#define DMIC_TOP_CON_CH1_ON			BIT(21)
+#define DMIC_TOP_CON_VOICE_MODE_MASK		GENMASK(19, 17)
+#define DMIC_TOP_CON_VOICE_MODE_8K		FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 0)
+#define DMIC_TOP_CON_VOICE_MODE_16K		FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 1)
+#define DMIC_TOP_CON_VOICE_MODE_32K		FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 2)
+#define DMIC_TOP_CON_VOICE_MODE_48K		FIELD_PREP(DMIC_TOP_CON_VOICE_MODE_MASK, 3)
+#define DMIC_TOP_CON_LOW_POWER_MODE_MASK	GENMASK(15, 14)
+#define DMIC_TOP_CON_LOW_POWER_MODE(x)		FIELD_PREP(DMIC_TOP_CON_LOW_POWER_MODE_MASK, (x))
+#define DMIC_TOP_CON_IIR_ON			BIT(10)
+#define DMIC_TOP_CON_IIR_MODE			GENMASK(9, 7)
+#define DMIC_TOP_CON_INPUT_MODE			BIT(5)
+#define DMIC_TOP_CON_SDM3_LEVEL_MODE		BIT(1)
+#define DMIC_TOP_CON_SRC_ON			BIT(0)
+#define DMIC_TOP_CON_SDM3_DE_SELECT		(0 << 1)
+#define DMIC_TOP_CON_CONFIG_MASK		(0x3f8ed7a6)
+
+/* AFE_CONN_24BIT (0x0AA4) */
+#define AFE_CONN_24BIT_O10		BIT(10)
+#define AFE_CONN_24BIT_O09		BIT(9)
+#define AFE_CONN_24BIT_O06		BIT(6)
+#define AFE_CONN_24BIT_O05		BIT(5)
+#define AFE_CONN_24BIT_O04		BIT(4)
+#define AFE_CONN_24BIT_O03		BIT(3)
+#define AFE_CONN_24BIT_O02		BIT(2)
+#define AFE_CONN_24BIT_O01		BIT(1)
+#define AFE_CONN_24BIT_O00		BIT(0)
+
+/* AFE_HD_ENGEN_ENABLE */
+#define AFE_22M_PLL_EN		BIT(0)
+#define AFE_24M_PLL_EN		BIT(1)
+
+/* AFE_GAIN1_CON0 (0x0410) */
+#define AFE_GAIN1_CON0_EN_MASK			GENMASK(0, 0)
+#define AFE_GAIN1_CON0_MODE_MASK		GENMASK(7, 4)
+#define AFE_GAIN1_CON0_SAMPLE_PER_STEP_MASK	GENMASK(15, 8)
+
+/* AFE_GAIN1_CON1 (0x0414) */
+#define AFE_GAIN1_CON1_MASK		GENMASK(19, 0)
+
+/* AFE_GAIN1_CUR (0x0B78) */
+#define AFE_GAIN1_CUR_MASK		GENMASK(19, 0)
+
+/* AFE_CM1_CON0 (0x0e50) */
+/* AFE_CM2_CON0 (0x0e60) */
+#define CM_AFE_CM_CH_NUM_MASK		GENMASK(3, 0)
+#define CM_AFE_CM_CH_NUM(x)		FIELD_PREP(CM_AFE_CM_CH_NUM_MASK, ((x) - 1))
+#define CM_AFE_CM_ON			BIT(4)
+#define CM_AFE_CM_START_DATA_MASK	GENMASK(11, 8)
+
+#define CM_AFE_CM1_VUL_SEL		BIT(12)
+#define CM_AFE_CM1_IN_MODE_MASK		GENMASK(19, 16)
+#define CM_AFE_CM2_TDM_SEL		BIT(12)
+#define CM_AFE_CM2_CLK_SEL		BIT(13)
+#define CM_AFE_CM2_GASRC1_OUT_SEL	BIT(17)
+#define CM_AFE_CM2_GASRC2_OUT_SEL	BIT(16)
+
+/* AFE_CM2_CONN* */
+#define CM2_AFE_CM2_CONN_CFG1(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG1_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG1_MASK	GENMASK(4, 0)
+#define CM2_AFE_CM2_CONN_CFG2(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG2_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG2_MASK	GENMASK(9, 5)
+#define CM2_AFE_CM2_CONN_CFG3(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG3_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG3_MASK	GENMASK(14, 10)
+#define CM2_AFE_CM2_CONN_CFG4(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG4_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG4_MASK	GENMASK(19, 15)
+#define CM2_AFE_CM2_CONN_CFG5(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG5_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG5_MASK	GENMASK(24, 20)
+#define CM2_AFE_CM2_CONN_CFG6(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG6_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG6_MASK	GENMASK(29, 25)
+#define CM2_AFE_CM2_CONN_CFG7(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG7_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG7_MASK	GENMASK(4, 0)
+#define CM2_AFE_CM2_CONN_CFG8(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG8_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG8_MASK	GENMASK(9, 5)
+#define CM2_AFE_CM2_CONN_CFG9(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG9_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG9_MASK	GENMASK(14, 10)
+#define CM2_AFE_CM2_CONN_CFG10(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG10_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG10_MASK	GENMASK(19, 15)
+#define CM2_AFE_CM2_CONN_CFG11(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG11_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG11_MASK	GENMASK(24, 20)
+#define CM2_AFE_CM2_CONN_CFG12(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG12_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG12_MASK	GENMASK(29, 25)
+#define CM2_AFE_CM2_CONN_CFG13(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG13_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG13_MASK	GENMASK(4, 0)
+#define CM2_AFE_CM2_CONN_CFG14(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG14_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG14_MASK	GENMASK(9, 5)
+#define CM2_AFE_CM2_CONN_CFG15(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG15_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG15_MASK	GENMASK(14, 10)
+#define CM2_AFE_CM2_CONN_CFG16(x)	FIELD_PREP(CM2_AFE_CM2_CONN_CFG16_MASK, (x))
+#define CM2_AFE_CM2_CONN_CFG16_MASK	GENMASK(19, 15)
+
+/* AFE_CM1_CON* */
+#define CM_AFE_CM_UPDATE_CNT1_MASK	GENMASK(15, 0)
+#define CM_AFE_CM_UPDATE_CNT1(x)	FIELD_PREP(CM_AFE_CM_UPDATE_CNT1_MASK, (x))
+#define CM_AFE_CM_UPDATE_CNT2_MASK	GENMASK(31, 16)
+#define CM_AFE_CM_UPDATE_CNT2(x)	FIELD_PREP(CM_AFE_CM_UPDATE_CNT2_MASK, (x))
+
+#endif

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 02/18] ASoC: dt-bindings: mediatek,mt8365-mt6357: Add audio sound card document
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add soundcard bindings for the MT8365 SoC with the MT6357 audio codec.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 .../bindings/sound/mediatek,mt8365-mt6357.yaml     | 99 ++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8365-mt6357.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8365-mt6357.yaml
new file mode 100644
index 000000000000..831c5b4665b8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8365-mt6357.yaml
@@ -0,0 +1,99 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt8365-mt6357.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Mediatek MT8365 ASoC sound card
+
+maintainers:
+  - Alexandre Mergnat <amergnat@baylibre.com>
+
+properties:
+  compatible:
+    const: mediatek,mt8365-mt6357
+
+  pinctrl-names:
+    minItems: 1
+    items:
+      - const: default
+      - const: dmic
+      - const: miso_off
+      - const: miso_on
+      - const: mosi_off
+      - const: mosi_on
+
+  mediatek,platform:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: The phandle of MT8365 ASoC platform.
+
+patternProperties:
+  "^dai-link-[0-9]+$":
+    type: object
+    description:
+      Container for dai-link level properties and CODEC sub-nodes.
+
+    properties:
+      codec:
+        type: object
+        description: Holds subnode which indicates codec dai.
+
+        properties:
+          sound-dai:
+            maxItems: 1
+            description: phandle of the codec DAI
+
+        additionalProperties: false
+
+      link-name:
+        description:
+          This property corresponds to the name of the BE dai-link to which
+          we are going to update parameters in this node.
+        items:
+          const: 2ND_I2S_BE
+
+      sound-dai:
+        maxItems: 1
+        description: phandle of the CPU DAI
+
+    required:
+      - link-name
+      - sound-dai
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - pinctrl-names
+  - mediatek,platform
+
+additionalProperties: false
+
+examples:
+  - |
+    sound {
+        compatible = "mediatek,mt8365-mt6357";
+        pinctrl-names = "default",
+                        "dmic",
+                        "miso_off",
+                        "miso_on",
+                        "mosi_off",
+                        "mosi_on";
+        pinctrl-0 = <&aud_default_pins>;
+        pinctrl-1 = <&aud_dmic_pins>;
+        pinctrl-2 = <&aud_miso_off_pins>;
+        pinctrl-3 = <&aud_miso_on_pins>;
+        pinctrl-4 = <&aud_mosi_off_pins>;
+        pinctrl-5 = <&aud_mosi_on_pins>;
+        mediatek,platform = <&afe>;
+
+        /* hdmi interface */
+        dai-link-0 {
+            link-name = "2ND_I2S_BE";
+            sound-dai = <&afe>;
+
+            codec {
+                sound-dai = <&it66121hdmitx>;
+            };
+        };
+    };

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 06/18] SoC: mediatek: mt8365: support audio clock control
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add audio clock wrapper and audio tuner control.

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 sound/soc/mediatek/mt8365/mt8365-afe-clk.c | 451 +++++++++++++++++++++++++++++
 sound/soc/mediatek/mt8365/mt8365-afe-clk.h |  49 ++++
 2 files changed, 500 insertions(+)

diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
new file mode 100644
index 000000000000..c87f8dd91978
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek 8365 AFE clock control
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#include "mt8365-afe-clk.h"
+#include "mt8365-afe-common.h"
+#include "mt8365-reg.h"
+#include "../common/mtk-base-afe.h"
+#include <linux/device.h>
+#include <linux/mfd/syscon.h>
+
+static const char *aud_clks[MT8365_CLK_NUM] = {
+	[MT8365_CLK_TOP_AUD_SEL] = "top_audio_sel",
+	[MT8365_CLK_AUD_I2S0_M] = "audio_i2s0_m",
+	[MT8365_CLK_AUD_I2S1_M] = "audio_i2s1_m",
+	[MT8365_CLK_AUD_I2S2_M] = "audio_i2s2_m",
+	[MT8365_CLK_AUD_I2S3_M] = "audio_i2s3_m",
+	[MT8365_CLK_ENGEN1] = "engen1",
+	[MT8365_CLK_ENGEN2] = "engen2",
+	[MT8365_CLK_AUD1] = "aud1",
+	[MT8365_CLK_AUD2] = "aud2",
+	[MT8365_CLK_I2S0_M_SEL] = "i2s0_m_sel",
+	[MT8365_CLK_I2S1_M_SEL] = "i2s1_m_sel",
+	[MT8365_CLK_I2S2_M_SEL] = "i2s2_m_sel",
+	[MT8365_CLK_I2S3_M_SEL] = "i2s3_m_sel",
+	[MT8365_CLK_CLK26M] = "top_clk26m_clk",
+};
+
+int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe)
+{
+	size_t i;
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
+		afe_priv->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]);
+		if (IS_ERR(afe_priv->clocks[i])) {
+			dev_err(afe->dev, "%s devm_clk_get %s fail\n",
+				__func__, aud_clks[i]);
+			return PTR_ERR(afe_priv->clocks[i]);
+		}
+	}
+	return 0;
+
+	afe_priv->topckgen = syscon_regmap_lookup_by_phandle(afe->dev->of_node,
+							     "mediatek,topckgen");
+	if (IS_ERR(afe_priv->topckgen)) {
+		dev_err(afe->dev, "%s() Cannot find topckgen controller: %ld\n",
+			__func__, PTR_ERR(afe_priv->topckgen));
+		return PTR_ERR(afe_priv->topckgen);
+	}
+}
+
+int mt8365_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+	int ret;
+
+	if (clk) {
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			dev_err(afe->dev, "Failed to enable clk\n");
+			return ret;
+		}
+	}
+	return 0;
+}
+
+void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+	if (clk)
+		clk_disable_unprepare(clk);
+}
+
+int mt8365_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
+			    unsigned int rate)
+{
+	int ret;
+
+	if (clk) {
+		ret = clk_set_rate(clk, rate);
+		if (ret) {
+			dev_err(afe->dev, "Failed to set rate\n");
+			return ret;
+		}
+	}
+	return 0;
+}
+
+int mt8365_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk,
+			      struct clk *parent)
+{
+	int ret;
+
+	if (clk && parent) {
+		ret = clk_set_parent(clk, parent);
+		if (ret) {
+			dev_err(afe->dev, "Failed to set parent\n");
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static unsigned int get_top_cg_reg(unsigned int cg_type)
+{
+	switch (cg_type) {
+	case MT8365_TOP_CG_AFE:
+	case MT8365_TOP_CG_I2S_IN:
+	case MT8365_TOP_CG_22M:
+	case MT8365_TOP_CG_24M:
+	case MT8365_TOP_CG_INTDIR_CK:
+	case MT8365_TOP_CG_APLL2_TUNER:
+	case MT8365_TOP_CG_APLL_TUNER:
+	case MT8365_TOP_CG_SPDIF:
+	case MT8365_TOP_CG_TDM_OUT:
+	case MT8365_TOP_CG_TDM_IN:
+	case MT8365_TOP_CG_ADC:
+	case MT8365_TOP_CG_DAC:
+	case MT8365_TOP_CG_DAC_PREDIS:
+	case MT8365_TOP_CG_TML:
+		return AUDIO_TOP_CON0;
+	case MT8365_TOP_CG_I2S1_BCLK:
+	case MT8365_TOP_CG_I2S2_BCLK:
+	case MT8365_TOP_CG_I2S3_BCLK:
+	case MT8365_TOP_CG_I2S4_BCLK:
+	case MT8365_TOP_CG_DMIC0_ADC:
+	case MT8365_TOP_CG_DMIC1_ADC:
+	case MT8365_TOP_CG_DMIC2_ADC:
+	case MT8365_TOP_CG_DMIC3_ADC:
+	case MT8365_TOP_CG_CONNSYS_I2S_ASRC:
+	case MT8365_TOP_CG_GENERAL1_ASRC:
+	case MT8365_TOP_CG_GENERAL2_ASRC:
+	case MT8365_TOP_CG_TDM_ASRC:
+		return AUDIO_TOP_CON1;
+	default:
+		return 0;
+	}
+}
+
+static unsigned int get_top_cg_mask(unsigned int cg_type)
+{
+	switch (cg_type) {
+	case MT8365_TOP_CG_AFE:
+		return AUD_TCON0_PDN_AFE;
+	case MT8365_TOP_CG_I2S_IN:
+		return AUD_TCON0_PDN_I2S_IN;
+	case MT8365_TOP_CG_22M:
+		return AUD_TCON0_PDN_22M;
+	case MT8365_TOP_CG_24M:
+		return AUD_TCON0_PDN_24M;
+	case MT8365_TOP_CG_INTDIR_CK:
+		return AUD_TCON0_PDN_INTDIR;
+	case MT8365_TOP_CG_APLL2_TUNER:
+		return AUD_TCON0_PDN_APLL2_TUNER;
+	case MT8365_TOP_CG_APLL_TUNER:
+		return AUD_TCON0_PDN_APLL_TUNER;
+	case MT8365_TOP_CG_SPDIF:
+		return AUD_TCON0_PDN_SPDIF;
+	case MT8365_TOP_CG_TDM_OUT:
+		return AUD_TCON0_PDN_TDM_OUT;
+	case MT8365_TOP_CG_TDM_IN:
+		return AUD_TCON0_PDN_TDM_IN;
+	case MT8365_TOP_CG_ADC:
+		return AUD_TCON0_PDN_ADC;
+	case MT8365_TOP_CG_DAC:
+		return AUD_TCON0_PDN_DAC;
+	case MT8365_TOP_CG_DAC_PREDIS:
+		return AUD_TCON0_PDN_DAC_PREDIS;
+	case MT8365_TOP_CG_TML:
+		return AUD_TCON0_PDN_TML;
+	case MT8365_TOP_CG_I2S1_BCLK:
+		return AUD_TCON1_PDN_I2S1_BCLK;
+	case MT8365_TOP_CG_I2S2_BCLK:
+		return AUD_TCON1_PDN_I2S2_BCLK;
+	case MT8365_TOP_CG_I2S3_BCLK:
+		return AUD_TCON1_PDN_I2S3_BCLK;
+	case MT8365_TOP_CG_I2S4_BCLK:
+		return AUD_TCON1_PDN_I2S4_BCLK;
+	case MT8365_TOP_CG_DMIC0_ADC:
+		return AUD_TCON1_PDN_DMIC0_ADC;
+	case MT8365_TOP_CG_DMIC1_ADC:
+		return AUD_TCON1_PDN_DMIC1_ADC;
+	case MT8365_TOP_CG_DMIC2_ADC:
+		return AUD_TCON1_PDN_DMIC2_ADC;
+	case MT8365_TOP_CG_DMIC3_ADC:
+		return AUD_TCON1_PDN_DMIC3_ADC;
+	case MT8365_TOP_CG_CONNSYS_I2S_ASRC:
+		return AUD_TCON1_PDN_CONNSYS_I2S_ASRC;
+	case MT8365_TOP_CG_GENERAL1_ASRC:
+		return AUD_TCON1_PDN_GENERAL1_ASRC;
+	case MT8365_TOP_CG_GENERAL2_ASRC:
+		return AUD_TCON1_PDN_GENERAL2_ASRC;
+	case MT8365_TOP_CG_TDM_ASRC:
+		return AUD_TCON1_PDN_TDM_ASRC;
+	default:
+		return 0;
+	}
+}
+
+static unsigned int get_top_cg_on_val(unsigned int cg_type)
+{
+	return 0;
+}
+
+static unsigned int get_top_cg_off_val(unsigned int cg_type)
+{
+	return get_top_cg_mask(cg_type);
+}
+
+int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	unsigned int reg = get_top_cg_reg(cg_type);
+	unsigned int mask = get_top_cg_mask(cg_type);
+	unsigned int val = get_top_cg_on_val(cg_type);
+	unsigned long flags;
+
+	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+
+	afe_priv->top_cg_ref_cnt[cg_type]++;
+	if (afe_priv->top_cg_ref_cnt[cg_type] == 1)
+		regmap_update_bits(afe->regmap, reg, mask, val);
+
+	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
+	return 0;
+}
+
+int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	unsigned int reg = get_top_cg_reg(cg_type);
+	unsigned int mask = get_top_cg_mask(cg_type);
+	unsigned int val = get_top_cg_off_val(cg_type);
+	unsigned long flags;
+
+	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+
+	afe_priv->top_cg_ref_cnt[cg_type]--;
+	if (afe_priv->top_cg_ref_cnt[cg_type] == 0)
+		regmap_update_bits(afe->regmap, reg, mask, val);
+	else if (afe_priv->top_cg_ref_cnt[cg_type] < 0)
+		afe_priv->top_cg_ref_cnt[cg_type] = 0;
+
+	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
+	return 0;
+}
+
+int mt8365_afe_enable_main_clk(struct mtk_base_afe *afe)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	mt8365_afe_enable_clk(afe, afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL]);
+	mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_AFE);
+	mt8365_afe_enable_afe_on(afe);
+
+	return 0;
+}
+
+int mt8365_afe_disable_main_clk(struct mtk_base_afe *afe)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	mt8365_afe_disable_afe_on(afe);
+	mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_AFE);
+	mt8365_afe_disable_clk(afe, afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL]);
+
+	return 0;
+}
+
+int mt8365_afe_emi_clk_on(struct mtk_base_afe *afe)
+{
+	return 0;
+}
+
+int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe)
+{
+	return 0;
+}
+
+int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+
+	afe_priv->afe_on_ref_cnt++;
+	if (afe_priv->afe_on_ref_cnt == 1)
+		regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
+
+	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
+	return 0;
+}
+
+int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+
+	afe_priv->afe_on_ref_cnt--;
+	if (afe_priv->afe_on_ref_cnt == 0)
+		regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0);
+	else if (afe_priv->afe_on_ref_cnt < 0)
+		afe_priv->afe_on_ref_cnt = 0;
+
+	spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
+	return 0;
+}
+
+int mt8365_afe_hd_engen_enable(struct mtk_base_afe *afe, bool apll1)
+{
+	if (apll1)
+		regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+				   AFE_22M_PLL_EN, AFE_22M_PLL_EN);
+	else
+		regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+				   AFE_24M_PLL_EN, AFE_24M_PLL_EN);
+
+	return 0;
+}
+
+int mt8365_afe_hd_engen_disable(struct mtk_base_afe *afe, bool apll1)
+{
+	if (apll1)
+		regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+				   AFE_22M_PLL_EN, ~AFE_22M_PLL_EN);
+	else
+		regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE,
+				   AFE_24M_PLL_EN, ~AFE_24M_PLL_EN);
+
+	return 0;
+}
+
+int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	mutex_lock(&afe_priv->afe_clk_mutex);
+
+	afe_priv->apll_tuner_ref_cnt[apll]++;
+	if (afe_priv->apll_tuner_ref_cnt[apll] != 1) {
+		mutex_unlock(&afe_priv->afe_clk_mutex);
+		return 0;
+	}
+
+	if (apll == MT8365_AFE_APLL1) {
+		regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG,
+				   AFE_APLL_TUNER_CFG_MASK, 0x432);
+		regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG,
+				   AFE_APLL_TUNER_CFG_EN_MASK, 0x1);
+	} else {
+		regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1,
+				   AFE_APLL_TUNER_CFG1_MASK, 0x434);
+		regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1,
+				   AFE_APLL_TUNER_CFG1_EN_MASK, 0x1);
+	}
+
+	mutex_unlock(&afe_priv->afe_clk_mutex);
+	return 0;
+}
+
+int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe,	unsigned int apll)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	mutex_lock(&afe_priv->afe_clk_mutex);
+
+	afe_priv->apll_tuner_ref_cnt[apll]--;
+	if (afe_priv->apll_tuner_ref_cnt[apll] == 0) {
+		if (apll == MT8365_AFE_APLL1)
+			regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG,
+					   AFE_APLL_TUNER_CFG_EN_MASK, 0x0);
+		else
+			regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1,
+					   AFE_APLL_TUNER_CFG1_EN_MASK, 0x0);
+
+	} else if (afe_priv->apll_tuner_ref_cnt[apll] < 0) {
+		afe_priv->apll_tuner_ref_cnt[apll] = 0;
+	}
+
+	mutex_unlock(&afe_priv->afe_clk_mutex);
+	return 0;
+}
+
+int mt8365_afe_enable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	if (apll == MT8365_AFE_APLL1) {
+		if (clk_prepare_enable(afe_priv->clocks[MT8365_CLK_ENGEN1])) {
+			dev_info(afe->dev, "%s Failed to enable ENGEN1 clk\n",
+				 __func__);
+			return 0;
+		}
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_22M);
+		mt8365_afe_hd_engen_enable(afe, true);
+#ifdef ENABLE_AFE_APLL_TUNER
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_APLL_TUNER);
+		mt8365_afe_enable_apll_tuner_cfg(afe, MT8365_AFE_APLL1);
+#endif
+	} else {
+		if (clk_prepare_enable(afe_priv->clocks[MT8365_CLK_ENGEN2])) {
+			dev_info(afe->dev, "%s Failed to enable ENGEN2 clk\n",
+				 __func__);
+			return 0;
+		}
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_24M);
+		mt8365_afe_hd_engen_enable(afe, false);
+#ifdef ENABLE_AFE_APLL_TUNER
+		mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_APLL2_TUNER);
+		mt8365_afe_enable_apll_tuner_cfg(afe, MT8365_AFE_APLL2);
+#endif
+	}
+
+	return 0;
+}
+
+int mt8365_afe_disable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll)
+{
+	struct mt8365_afe_private *afe_priv = afe->platform_priv;
+
+	if (apll == MT8365_AFE_APLL1) {
+#ifdef ENABLE_AFE_APLL_TUNER
+		mt8365_afe_disable_apll_tuner_cfg(afe, MT8365_AFE_APLL1);
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_APLL_TUNER);
+#endif
+		mt8365_afe_hd_engen_disable(afe, true);
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_22M);
+		clk_disable_unprepare(afe_priv->clocks[MT8365_CLK_ENGEN1]);
+	} else {
+#ifdef ENABLE_AFE_APLL_TUNER
+		mt8365_afe_disable_apll_tuner_cfg(afe, MT8365_AFE_APLL2);
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_APLL2_TUNER);
+#endif
+		mt8365_afe_hd_engen_disable(afe, false);
+		mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_24M);
+		clk_disable_unprepare(afe_priv->clocks[MT8365_CLK_ENGEN2]);
+	}
+
+	return 0;
+}
diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.h b/sound/soc/mediatek/mt8365/mt8365-afe-clk.h
new file mode 100644
index 000000000000..14fca6ae2641
--- /dev/null
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Mediatek 8365 AFE clock control definitions
+ *
+ * Copyright (c) 2024 MediaTek Inc.
+ * Authors: Jia Zeng <jia.zeng@mediatek.com>
+ *          Alexandre Mergnat <amergnat@baylibre.com>
+ */
+
+#ifndef _MT8365_AFE_UTILS_H_
+#define _MT8365_AFE_UTILS_H_
+
+struct mtk_base_afe;
+struct clk;
+
+int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe);
+
+int mt8365_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
+
+void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
+
+int mt8365_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, unsigned int rate);
+
+int mt8365_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk, struct clk *parent);
+
+int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type);
+
+int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type);
+
+int mt8365_afe_enable_main_clk(struct mtk_base_afe *afe);
+
+int mt8365_afe_disable_main_clk(struct mtk_base_afe *afe);
+
+int mt8365_afe_emi_clk_on(struct mtk_base_afe *afe);
+
+int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe);
+
+int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe);
+
+int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe);
+
+int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll);
+
+int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll);
+
+int mt8365_afe_enable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll);
+
+int mt8365_afe_disable_apll_associated_cfg(struct mtk_base_afe *afe, unsigned int apll);
+#endif

-- 
2.25.1


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

^ permalink raw reply related

* [PATCH v2 00/18] Add audio support for the MediaTek Genio 350-evk board
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat, Nicolas Belin

This serie aim to add the following audio support for the Genio 350-evk:
- Playback
  - 2ch Headset Jack (Earphone)
  - 1ch Line-out Jack (Speaker)
  - 8ch HDMI Tx
- Capture
  - 1ch DMIC (On-board Digital Microphone)
  - 1ch AMIC (On-board Analogic Microphone)
  - 1ch Headset Jack (External Analogic Microphone)

Of course, HDMI playback need the MT8365 display patches [1] and a DTS
change documented in "mediatek,mt8365-mt6357.yaml".

Rebase on top of sound/for-next branch and the
Angelo's serie "SoC: Cleanup MediaTek soundcard machine drivers" [2]
Work branch with all patches [5]

Applied patch:
- mfd: mt6397-core: register mt6357 sound codec

Test passed:
- mixer-test log: [3]
- pcm-test log: [4]

[1]: https://lore.kernel.org/all/20231023-display-support-v1-0-5c860ed5c33b@baylibre.com/
[2]: https://lore.kernel.org/all/20240313110147.1267793-1-angelogioacchino.delregno@collabora.com/
[3]: https://pastebin.com/pc43AVrT
[4]: https://pastebin.com/cCtGhDpg
[5]: https://gitlab.baylibre.com/baylibre/mediatek/bsp/linux/-/commits/sound/for-next/add-i350-audio-support

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
Changes in v2:
- Documentation fixed:
  - Remove spurious description.
  - Change property order to fit with dts coding style rules.
  - micbias property: use microvolt value instead of index.
  - mediatek,i2s-shared-clock property removed.
  - mediatek,dmic-iir-on property removed.
  - mediatek,dmic-irr-mode property removed.
  - Change dmic-two-wire-mode => dmic-mode to be aligned with another SoC
  - Remove the spurious 2nd reg of the afe.
- Manage IIR filter feature using audio controls.
- Fix audio controls to pass mixer-test and pcm-test.
- Refactor some const name according to feedbacks.
- Rework the codec to remove spurious driver data.
- Use the new common MTK probe functions for AFE PCM and sound card.
- Rework pinctrl probe in the soundcard driver.
- Remove spurious "const" variables in all files.
- Link to v1: https://lore.kernel.org/r/20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com

---
Alexandre Mergnat (16):
      ASoC: dt-bindings: mediatek,mt8365-afe: Add audio afe document
      ASoC: dt-bindings: mediatek,mt8365-mt6357: Add audio sound card document
      dt-bindings: mfd: mediatek: Add codec property for MT6357 PMIC
      ASoC: dt-bindings: mt6357: Add audio codec document
      ASoC: mediatek: mt8365: Add common header
      SoC: mediatek: mt8365: support audio clock control
      ASoC: mediatek: mt8365: Add I2S DAI support
      ASoC: mediatek: mt8365: Add ADDA DAI support
      ASoC: mediatek: mt8365: Add DMIC DAI support
      ASoC: mediatek: mt8365: Add PCM DAI support
      ASoC: mediatek: mt8365: Add platform driver
      ASoC: mediatek: Add MT8365 support
      arm64: defconfig: enable mt8365 sound
      arm64: dts: mediatek: add mt6357 audio codec support
      arm64: dts: mediatek: add afe support for mt8365 SoC
      arm64: dts: mediatek: add audio support for mt8365-evk

Nicolas Belin (2):
      ASoc: mediatek: mt8365: Add a specific soundcard for EVK
      ASoC: codecs: add MT6357 support

 .../devicetree/bindings/mfd/mediatek,mt6357.yaml   |    5 +
 .../bindings/sound/mediatek,mt8365-afe.yaml        |  136 ++
 .../bindings/sound/mediatek,mt8365-mt6357.yaml     |   99 +
 .../devicetree/bindings/sound/mt6357.yaml          |   54 +
 arch/arm64/boot/dts/mediatek/mt6357.dtsi           |    5 +-
 arch/arm64/boot/dts/mediatek/mt8365-evk.dts        |   98 +-
 arch/arm64/boot/dts/mediatek/mt8365.dtsi           |   46 +-
 arch/arm64/configs/defconfig                       |    2 +
 sound/soc/codecs/Kconfig                           |    7 +
 sound/soc/codecs/Makefile                          |    2 +
 sound/soc/codecs/mt6357.c                          | 1898 ++++++++++++++++
 sound/soc/codecs/mt6357.h                          |  662 ++++++
 sound/soc/mediatek/Kconfig                         |   20 +
 sound/soc/mediatek/Makefile                        |    1 +
 sound/soc/mediatek/mt8365/Makefile                 |   15 +
 sound/soc/mediatek/mt8365/mt8365-afe-clk.c         |  451 ++++
 sound/soc/mediatek/mt8365/mt8365-afe-clk.h         |   49 +
 sound/soc/mediatek/mt8365/mt8365-afe-common.h      |  491 +++++
 sound/soc/mediatek/mt8365/mt8365-afe-pcm.c         | 2275 ++++++++++++++++++++
 sound/soc/mediatek/mt8365/mt8365-dai-adda.c        |  315 +++
 sound/soc/mediatek/mt8365/mt8365-dai-dmic.c        |  347 +++
 sound/soc/mediatek/mt8365/mt8365-dai-i2s.c         |  854 ++++++++
 sound/soc/mediatek/mt8365/mt8365-dai-pcm.c         |  293 +++
 sound/soc/mediatek/mt8365/mt8365-mt6357.c          |  348 +++
 sound/soc/mediatek/mt8365/mt8365-reg.h             |  991 +++++++++
 25 files changed, 9456 insertions(+), 8 deletions(-)
---
base-commit: 6a3d4a830e4e9de8e8aefc233d790bef4a5c0037
change-id: 20240226-audio-i350-4e11da088e55

Best regards,
-- 
Alexandre Mergnat <amergnat@baylibre.com>


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

^ permalink raw reply

* [PATCH v2 01/18] ASoC: dt-bindings: mediatek,mt8365-afe: Add audio afe document
From: Alexandre Mergnat @ 2024-04-09 10:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	Lee Jones, Flora Fu, Jaroslav Kysela, Takashi Iwai, Sumit Semwal,
	Christian König, Catalin Marinas, Will Deacon, Rob Herring
  Cc: linux-sound, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-media, dri-devel, linaro-mm-sig,
	Alexandre Mergnat
In-Reply-To: <20240226-audio-i350-v2-0-3043d483de0d@baylibre.com>

Add MT8365 audio front-end bindings

Signed-off-by: Alexandre Mergnat <amergnat@baylibre.com>
---
 .../bindings/sound/mediatek,mt8365-afe.yaml        | 136 +++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8365-afe.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8365-afe.yaml
new file mode 100644
index 000000000000..d0759898b9c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt8365-afe.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/mediatek,mt8365-afe.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek AFE PCM controller for MT8365
+
+maintainers:
+  - Alexandre Mergnat <amergnat@baylibre.com>
+
+properties:
+  compatible:
+    const: mediatek,mt8365-afe-pcm
+
+  reg:
+    maxItems: 1
+
+  "#sound-dai-cells":
+    const: 0
+
+  clocks:
+    items:
+      - description: 26M clock
+      - description: mux for audio clock
+      - description: audio i2s0 mck
+      - description: audio i2s1 mck
+      - description: audio i2s2 mck
+      - description: audio i2s3 mck
+      - description: engen 1 clock
+      - description: engen 2 clock
+      - description: audio 1 clock
+      - description: audio 2 clock
+      - description: mux for i2s0
+      - description: mux for i2s1
+      - description: mux for i2s2
+      - description: mux for i2s3
+
+  clock-names:
+    items:
+      - const: top_clk26m_clk
+      - const: top_audio_sel
+      - const: audio_i2s0_m
+      - const: audio_i2s1_m
+      - const: audio_i2s2_m
+      - const: audio_i2s3_m
+      - const: engen1
+      - const: engen2
+      - const: aud1
+      - const: aud2
+      - const: i2s0_m_sel
+      - const: i2s1_m_sel
+      - const: i2s2_m_sel
+      - const: i2s3_m_sel
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  mediatek,dmic-mode:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Indicates how many data pins are used to transmit two channels of PDM
+      signal. 1 means two wires, 0 means one wire. Default value is 0.
+    enum:
+      - 0 # one wire
+      - 1 # two wires
+
+  mediatek,topckgen:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: The phandle of the mediatek topckgen controller
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - power-domains
+  - mediatek,topckgen
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/mediatek,mt8365-clk.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/power/mediatek,mt8365-power.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        afe@11220000 {
+            compatible = "mediatek,mt8365-afe-pcm";
+            reg = <0 0x11220000 0 0x1000>;
+            #sound-dai-cells = <0>;
+            clocks = <&clk26m>,
+                     <&topckgen CLK_TOP_AUDIO_SEL>,
+                     <&topckgen CLK_TOP_AUD_I2S0_M>,
+                     <&topckgen CLK_TOP_AUD_I2S1_M>,
+                     <&topckgen CLK_TOP_AUD_I2S2_M>,
+                     <&topckgen CLK_TOP_AUD_I2S3_M>,
+                     <&topckgen CLK_TOP_AUD_ENGEN1_SEL>,
+                     <&topckgen CLK_TOP_AUD_ENGEN2_SEL>,
+                     <&topckgen CLK_TOP_AUD_1_SEL>,
+                     <&topckgen CLK_TOP_AUD_2_SEL>,
+                     <&topckgen CLK_TOP_APLL_I2S0_SEL>,
+                     <&topckgen CLK_TOP_APLL_I2S1_SEL>,
+                     <&topckgen CLK_TOP_APLL_I2S2_SEL>,
+                     <&topckgen CLK_TOP_APLL_I2S3_SEL>;
+            clock-names = "top_clk26m_clk",
+                          "top_audio_sel",
+                          "audio_i2s0_m",
+                          "audio_i2s1_m",
+                          "audio_i2s2_m",
+                          "audio_i2s3_m",
+                          "engen1",
+                          "engen2",
+                          "aud1",
+                          "aud2",
+                          "i2s0_m_sel",
+                          "i2s1_m_sel",
+                          "i2s2_m_sel",
+                          "i2s3_m_sel";
+            interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>;
+            power-domains = <&spm MT8365_POWER_DOMAIN_AUDIO>;
+            mediatek,dmic-mode = <1>;
+            mediatek,topckgen = <&topckgen>;
+        };
+    };
+
+...

-- 
2.25.1


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

^ permalink raw reply related

* Re: [PATCH v3 2/2] ARM: dts: imx6: exchange fallback and specific compatible string
From: Fabio Estevam @ 2024-04-09 10:06 UTC (permalink / raw)
  To: Shengjiu Wang
  Cc: lgirdwood, broonie, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	shengjiu.wang, linux-sound, devicetree, linux-kernel, shawnguo,
	s.hauer, kernel, imx, linux-arm-kernel
In-Reply-To: <CAOMZO5Cku1kifsnWJOr0Zd-5+49j-KB67iHZDcvUsKwrhVPtLA@mail.gmail.com>

On Tue, Apr 9, 2024 at 7:02 AM Fabio Estevam <festevam@gmail.com> wrote:
>
> On Tue, Apr 9, 2024 at 6:08 AM Shengjiu Wang <shengjiu.wang@nxp.com> wrote:
> >
> > exchange fallback and specific compatible string for spdif sound card.
>
> Ok, but please explain the reason.

I mean, why can't these two .dts files be changed to

compatible =  "fsl,imx-audio-spdif";

, like all the others?

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

^ permalink raw reply

* Re: [PATCH v3 00/13] drm/display: Convert helpers Kconfig symbols to depends on
From: Jani Nikula @ 2024-04-09 10:04 UTC (permalink / raw)
  To: Geert Uytterhoeven, Maxime Ripard
  Cc: Maarten Lankhorst, Thomas Zimmermann, David Airlie, Daniel Vetter,
	dri-devel, Lucas De Marchi, kernel test robot, linux-renesas-soc,
	linux-arm-kernel
In-Reply-To: <a816fea-9974-d17f-bed6-69728e223@linux-m68k.org>

On Tue, 09 Apr 2024, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> The user should not need to know which helpers are needed for the driver
> he is interested in.  When a symbol selects another symbol, it should
> just make sure the dependencies of the target symbol are met.

It's really not "just make sure". This leads to perpetual illegal
configurations, and duct tape fixes. Select should not be used for
visible symbols or symbols with dependencies [1].

What we'd need for usability is not more abuse of select, but rather 1)
warnings for selecting symbols with dependencies, and 2) a way to enable
a kconfig option with all its dependencies, recursively. This is what we
lack.


BR,
Jani.


[1] Documentation/kbuild/kconfig-language.rst "reverse dependencies"


-- 
Jani Nikula, Intel

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

^ permalink raw reply

* Re: [PATCH v2 0/4] Speed up boot with faster linear map creation
From: Ryan Roberts @ 2024-04-09 10:04 UTC (permalink / raw)
  To: Itaru Kitayama
  Cc: Catalin Marinas, Will Deacon, Mark Rutland, Ard Biesheuvel,
	David Hildenbrand, Donald Dutile, Eric Chanudet, Linux ARM,
	linux-kernel@vger.kernel.org
In-Reply-To: <FCDCBCEE-7D97-4769-AB95-7294A9CE18E0@linux.dev>

On 09/04/2024 01:10, Itaru Kitayama wrote:
> Hi Ryan,
> 
>> On Apr 8, 2024, at 16:30, Ryan Roberts <ryan.roberts@arm.com> wrote:
>> 
>> On 06/04/2024 11:31, Itaru Kitayama wrote:
>>> Hi Ryan,
>>> 
>>> On Sat, Apr 06, 2024 at 09:32:34AM +0100, Ryan Roberts wrote:
>>>> Hi Itaru,
>>>> 
>>>> On 05/04/2024 08:39, Itaru Kitayama wrote:
>>>>> On Thu, Apr 04, 2024 at 03:33:04PM +0100, Ryan Roberts wrote:
>>>>>> Hi All,
>>>>>> 
>>>>>> It turns out that creating the linear map can take a significant proportion of
>>>>>> the total boot time, especially when rodata=full. And most of the time is spent
>>>>>> waiting on superfluous tlb invalidation and memory barriers. This series reworks
>>>>>> the kernel pgtable generation code to significantly reduce the number of those
>>>>>> TLBIs, ISBs and DSBs. See each patch for details.
>>>>>> 
>>>>>> The below shows the execution time of map_mem() across a couple of different
>>>>>> systems with different RAM configurations. We measure after applying each patch
>>>>>> and show the improvement relative to base (v6.9-rc2):
>>>>>> 
>>>>>>               | Apple M2 VM | Ampere Altra| Ampere Altra| Ampere Altra
>>>>>>               | VM, 16G     | VM, 64G     | VM, 256G    | Metal, 512G
>>>>>> ---------------|-------------|-------------|-------------|-------------
>>>>>>               |   ms    (%) |   ms    (%) |   ms    (%) |    ms    (%)
>>>>>> ---------------|-------------|-------------|-------------|-------------
>>>>>> base           |  153   (0%) | 2227   (0%) | 8798   (0%) | 17442   (0%)
>>>>>> no-cont-remap  |   77 (-49%) |  431 (-81%) | 1727 (-80%) |  3796 (-78%)
>>>>>> batch-barriers |   13 (-92%) |  162 (-93%) |  655 (-93%) |  1656 (-91%)
>>>>>> no-alloc-remap |   11 (-93%) |  109 (-95%) |  449 (-95%) |  1257 (-93%)
>>>>>> lazy-unmap     |    6 (-96%) |   61 (-97%) |  257 (-97%) |   838 (-95%)
>>>>>> 
>>>>>> This series applies on top of v6.9-rc2. All mm selftests pass. I've compile and
>>>>>> boot tested various PAGE_SIZE and VA size configs.
>>>>>> 
>>>>>> ---
>>>>>> 
>>>>>> Changes since v1 [1]
>>>>>> ====================
>>>>>> 
>>>>>>  - Added Tested-by tags (thanks to Eric and Itaru)
>>>>>>  - Renamed ___set_pte() -> __set_pte_nosync() (per Ard)
>>>>>>  - Reordered patches (biggest impact & least controversial first)
>>>>>>  - Reordered alloc/map/unmap functions in mmu.c to aid reader
>>>>>>  - pte_clear() -> __pte_clear() in clear_fixmap_nosync()
>>>>>>  - Reverted generic p4d_index() which caused x86 build error. Replaced with
>>>>>>    unconditional p4d_index() define under arm64.
>>>>>> 
>>>>>> 
>>>>>> [1] https://lore.kernel.org/linux-arm-kernel/20240326101448.3453626-1-ryan.roberts@arm.com/ <https://lore.kernel.org/linux-arm-kernel/20240326101448.3453626-1-ryan.roberts@arm.com/>
>>>>>> 
>>>>>> Thanks,
>>>>>> Ryan
>>>>>> 
>>>>>> 
>>>>>> Ryan Roberts (4):
>>>>>>  arm64: mm: Don't remap pgtables per-cont(pte|pmd) block
>>>>>>  arm64: mm: Batch dsb and isb when populating pgtables
>>>>>>  arm64: mm: Don't remap pgtables for allocate vs populate
>>>>>>  arm64: mm: Lazily clear pte table mappings from fixmap
>>>>>> 
>>>>>> arch/arm64/include/asm/fixmap.h  |   5 +-
>>>>>> arch/arm64/include/asm/mmu.h     |   8 +
>>>>>> arch/arm64/include/asm/pgtable.h |  13 +-
>>>>>> arch/arm64/kernel/cpufeature.c   |  10 +-
>>>>>> arch/arm64/mm/fixmap.c           |  11 +
>>>>>> arch/arm64/mm/mmu.c              | 377 +++++++++++++++++++++++--------
>>>>>> 6 files changed, 319 insertions(+), 105 deletions(-)
>>>>>> 
>>>>>> --
>>>>>> 2.25.1
>>>>>> 
>>>>> 
>>>>> I've build and boot tested the v2 on FVP, base is taken from your
>>>>> linux-rr repo. Running run_vmtests.sh on v2 left some gup longterm not oks, would you take a look at it? The mm ksefltests used is from your linux-rr repo too.
>>>> 
>>>> Thanks for taking a look at this.
>>>> 
>>>> I can't reproduce your issue unfortunately; steps as follows on Apple M2 VM:
>>>> 
>>>> Config: arm64 defconfig + the following:
>>>> 
>>>> # Squashfs for snaps, xfs for large file folios.
>>>> ./scripts/config --enable CONFIG_SQUASHFS_LZ4
>>>> ./scripts/config --enable CONFIG_SQUASHFS_LZO
>>>> ./scripts/config --enable CONFIG_SQUASHFS_XZ
>>>> ./scripts/config --enable CONFIG_SQUASHFS_ZSTD
>>>> ./scripts/config --enable CONFIG_XFS_FS
>>>> 
>>>> # For general mm debug.
>>>> ./scripts/config --enable CONFIG_DEBUG_VM
>>>> ./scripts/config --enable CONFIG_DEBUG_VM_MAPLE_TREE
>>>> ./scripts/config --enable CONFIG_DEBUG_VM_RB
>>>> ./scripts/config --enable CONFIG_DEBUG_VM_PGFLAGS
>>>> ./scripts/config --enable CONFIG_DEBUG_VM_PGTABLE
>>>> ./scripts/config --enable CONFIG_PAGE_TABLE_CHECK
>>>> 
>>>> # For mm selftests.
>>>> ./scripts/config --enable CONFIG_USERFAULTFD
>>>> ./scripts/config --enable CONFIG_TEST_VMALLOC
>>>> ./scripts/config --enable CONFIG_GUP_TEST
>>>> 
>>>> Running on VM with 12G memory, split across 2 (emulated) NUMA nodes (needed by
>>>> some mm selftests), with kernel command line to reserve hugetlbs and other
>>>> features required by some mm selftests:
>>>> 
>>>> "
>>>> transparent_hugepage=madvise earlycon root=/dev/vda2 secretmem.enable
>>>> hugepagesz=1G hugepages=0:2,1:2 hugepagesz=32M hugepages=0:2,1:2
>>>> default_hugepagesz=2M hugepages=0:64,1:64 hugepagesz=64K hugepages=0:2,1:2
>>>> "
>>>> 
>>>> Ubuntu userspace running off XFS rootfs. Build and run mm selftests from same
>>>> git tree.
>>>> 
>>>> 
>>>> Although I don't think any of this config should make a difference to gup_longterm.
>>>> 
>>>> Looks like your errors are all "ftruncate() failed". I've seen this problem on
>>>> our CI system. There it is due to running the tests from NFS file system. What
>>>> filesystem are you using? Perhaps you are sharing into the FVP using 9p? That
>>>> might also be problematic.
>>> 
>>> That was it. This time I booted up the kernel including your series on
>>> QEMU on my M1 and executed the gup_longterm program without the ftruncate
>>> failures. When testing your kernel on FVP, I was executing the script from the FVP's host filesystem using 9p.
>> 
>> I'm not sure exactly what the root cause is. Perhaps there isn't enough space on
>> the disk? It might be worth enhancing the error log to provide the errno in
>> tools/testing/selftests/mm/gup_longterm.c.
>> 
> 
> Attached is the strace’d gup_longterm executiong log on your
> pgtable-boot-speedup-v2 kernel.

Sorry are you saying that it only fails with the pgtable-boot-speedup-v2 patch
set applied? I thought we previously concluded that it was independent of that?
I was under the impression that it was filesystem related and not something that
I was planning to investigate.

> 
> Thanks,
> Itaru.
> 
>> Thanks,
>> Ryan
>> 
>>> 
>>> Thanks,
>>> Itaru.
>>> 
>>>> 
>>>> Does this problem reproduce with v6.9-rc2, without my patches? I except it
>>>> probably does?
>>>> 
>>>> Thanks,
>>>> Ryan
>>>> 
>>>>> 
>>>>> Thanks,
>>>>> Itaru.
> 
> 


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

^ permalink raw reply

* Re: [syzbot] [mm?] BUG: unable to handle kernel paging request in copy_from_kernel_nofault (2)
From: Puranjay Mohan @ 2024-04-09 10:03 UTC (permalink / raw)
  To: syzbot
  Cc: Andrii Nakryiko, Alexei Starovoitov, Mark Rutland, Andrew Morton,
	linux-arm-kernel, Russell King (Oracle), LKML, linux-mm,
	syzkaller-bugs, bpf
In-Reply-To: <ZhT5NRYnceirmAGz@shell.armlinux.org.uk>

"Russell King (Oracle)" <linux@armlinux.org.uk> writes:

> On Tue, Apr 09, 2024 at 07:45:54AM +0000, Puranjay Mohan wrote:
>> "Russell King (Oracle)" <linux@armlinux.org.uk> writes:
>> 
>> > On Fri, Apr 05, 2024 at 10:50:30AM -0700, Andrii Nakryiko wrote:
>> >> On Fri, Apr 5, 2024 at 9:30 AM Alexei Starovoitov
>> >> <alexei.starovoitov@gmail.com> wrote:
>> >> >
>> >> > On Fri, Apr 5, 2024 at 4:36 AM Russell King (Oracle)
>> >> > <linux@armlinux.org.uk> wrote:
>> >> > >
>> >> > > On Fri, Apr 05, 2024 at 12:02:36PM +0100, Mark Rutland wrote:
>> >> > > > On Thu, Apr 04, 2024 at 03:57:04PM -0700, Alexei Starovoitov wrote:
>> >> > > > > On Wed, Apr 3, 2024 at 6:56 PM Andrew Morton <akpm@linux-foundationorg> wrote:
>> >> > > > > >
>> >> > > > > > On Mon, 01 Apr 2024 22:19:25 -0700 syzbot <syzbot+186522670e6722692d86@syzkaller.appspotmail.com> wrote:
>> >> > > > > >
>> >> > > > > > > Hello,
>> >> > > > > >
>> >> > > > > > Thanks.  Cc: bpf@vger.kernel.org
>> >> > > > >
>> >> > > > > I suspect the issue is not on bpf side.
>> >> > > > > Looks like the bug is somewhere in arm32 bits.
>> >> > > > > copy_from_kernel_nofault() is called from lots of places.
>> >> > > > > bpf is just one user that is easy for syzbot to fuzz.
>> >> > > > > Interestingly arm defines copy_from_kernel_nofault_allowed()
>> >> > > > > that should have filtered out user addresses.
>> >> > > > > In this case ffffffe9 is probably a kernel address?
>> >> > > >
>> >> > > > It's at the end of the kernel range, and it's ERR_PTR(-EINVAL).
>> >> > > >
>> >> > > > 0xffffffe9 is -0x16, which is -22, which is -EINVAL.
>> >> > > >
>> >> > > > > But the kernel is doing a write?
>> >> > > > > Which makes no sense, since copy_from_kernel_nofault is probe reading.
>> >> > > >
>> >> > > > It makes perfect sense; the read from 'src' happened, then the kernel tries to
>> >> > > > write the result to 'dst', and that aligns with the disassembly in the report
>> >> > > > below, which I beleive is:
>> >> > > >
>> >> > > >      8: e4942000        ldr     r2, [r4], #0  <-- Read of 'src', fault fixup is elsewhere
>> >> > > >      c: e3530000        cmp     r3, #0
>> >> > > >   * 10: e5852000        str     r2, [r5]      <-- Write to 'dst'
>> >> > > >
>> >> > > > As above, it looks like 'dst' is ERR_PTR(-EINVAL).
>> >> > > >
>> >> > > > Are you certain that BPF is passing a sane value for 'dst'? Where does that
>> >> > > > come from in the first place?
>> >> > >
>> >> > > It looks to me like it gets passed in from the BPF program, and the
>> >> > > "type" for the argument is set to ARG_PTR_TO_UNINIT_MEM. What that
>> >> > > means for validation purposes, I've no idea, I'm not a BPF hacker.
>> >> > >
>> >> > > Obviously, if BPF is allowing copy_from_kernel_nofault() to be passed
>> >> > > an arbitary destination address, that would be a huge security hole.
>> >> >
>> >> > If that's the case that's indeed a giant security hole,
>> >> > but I doubt it. We would be crashing other archs as well.
>> >> > I cannot really tell whether arm32 JIT is on.
>> >> > If it is, it's likely a bug there.
>> >> > Puranjay,
>> >> > could you please take a look.
>> >> >
>> >> 
>> >> I dumped the BPF program that repro.c is loading, it works on x86-64
>> >> and there is nothing special there. We are probe-reading 5 bytes from
>> >> somewhere into the stack. Everything is unaligned here, but stays
>> >> within a well-defined memory slot.
>> >> 
>> >> Note the r3 = (s8)r1, that's a new-ish thing, maybe bug is somewhere
>> >> there (but then it would be JIT, not verifier itself)
>> >> 
>> >>    0: (7a) *(u64 *)(r10 -8) = 896542069
>> >>    1: (bf) r1 = r10
>> >>    2: (07) r1 += -7
>> >>    3: (b7) r2 = 5
>> >>    4: (bf) r3 = (s8)r1
>> >>    5: (85) call bpf_probe_read_kernel#-72390
>> >
>> 
>> I have started looking into this, the issue only reproduces when the JIT
>> is enabled. With the interpreter, it works fine.
>> 
>> I used GDB to dump the JITed BPF program:
>> 
>>    0xbf00012c:  push    {r4, r5, r6, r7, r8, r9, r11, lr}
>>    0xbf000130:  mov     r11, sp
>>    0xbf000134:  mov     r3, #0
>>    0xbf000138:  sub     r2, sp, #80     @ 0x50
>>    0xbf00013c:  sub     sp, sp, #88     @ 0x58
>>    0xbf000140:  strd    r2, [r11, #-64] @ 0xffffffc0
>>    0xbf000144:  mov     r2, #0
>>    0xbf000148:  strd    r2, [r11, #-72] @ 0xffffffb8
>>    0xbf00014c:  mov     r2, r0
>>    0xbf000150:  movw    r8, #9589       @ 0x2575
>>    0xbf000154:  movt    r8, #13680      @ 0x3570
>>    0xbf000158:  mov     r9, #0
>>    0xbf00015c:  ldr     r6, [r11, #-64] @ 0xffffffc0
>>    0xbf000160:  str     r8, [r6, #-8]
>>    0xbf000164:  str     r9, [r6, #-4]
>>    0xbf000168:  ldrd    r2, [r11, #-64] @ 0xffffffc0
>>    0xbf00016c:  movw    r8, #65529      @ 0xfff9
>>    0xbf000170:  movt    r8, #65535      @ 0xffff
>>    0xbf000174:  movw    r9, #65535      @ 0xffff
>>    0xbf000178:  movt    r9, #65535      @ 0xffff
>>    0xbf00017c:  adds    r2, r2, r8
>>    0xbf000180:  adc     r3, r3, r9
>>    0xbf000184:  mov     r6, #5
>>    0xbf000188:  mov     r7, #0
>>    0xbf00018c:  strd    r6, [r11, #-8]
>>    0xbf000190:  ldrd    r6, [r11, #-16]
>
> Up to this point, it looks correct. r2/r3 contain the stack pointer
> which corresponds to the instruction at "2:"
>
>>    0xbf000194:  lsl     r2, r2, #24
>>    0xbf000198:  asr     r2, r2, #24
>>    0xbf00019c:  str     r2, [r11, #-16]
>
> This then narrows the 64-bit pointer down to just 8!!! bits, but this
> is what the instruction at "4:" is asking for. However, it looks like
> it's happening to BPF's "r1" rather than "r3" and this is probably
> where the problem lies.
>
> I haven't got time to analyse this further this morning - I'm only
> around sporadically today. I'll try to look deeper at this later on.
>
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

I found the problem. The implementation of Sign extended move is broken,
it clobbers the source register. I have sent a patch to fix it and also
fixed another issue that I saw:
https://lore.kernel.org/bpf/20240409095038.26356-1-puranjay@kernel.org/

I have manually tested with the reproducer but let's try to rerun the
reproducer through syzbot:

#syz test: https://github.com/puranjaymohan/linux.git arm32_movsx_fix

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

^ permalink raw reply

* Re: [PATCH v3 2/2] ARM: dts: imx6: exchange fallback and specific compatible string
From: Fabio Estevam @ 2024-04-09 10:02 UTC (permalink / raw)
  To: Shengjiu Wang
  Cc: lgirdwood, broonie, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	shengjiu.wang, linux-sound, devicetree, linux-kernel, shawnguo,
	s.hauer, kernel, imx, linux-arm-kernel
In-Reply-To: <1712652644-28887-3-git-send-email-shengjiu.wang@nxp.com>

On Tue, Apr 9, 2024 at 6:08 AM Shengjiu Wang <shengjiu.wang@nxp.com> wrote:
>
> exchange fallback and specific compatible string for spdif sound card.

Ok, but please explain the reason.

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

^ permalink raw reply

* [PATCH v7 3/3] pinctrl: nuvoton: Add ma35d1 pinctrl and GPIO driver
From: Jacky Huang @ 2024-04-09  9:56 UTC (permalink / raw)
  To: linus.walleij, robh+dt, krzysztof.kozlowski+dt, conor+dt, p.zabel,
	j.neuschaefer
  Cc: linux-arm-kernel, linux-gpio, devicetree, linux-kernel, ychuang3,
	schung
In-Reply-To: <20240409095637.2135-1-ychuang570808@gmail.com>

From: Jacky Huang <ychuang3@nuvoton.com>

Add common pinctrl and GPIO driver for Nuvoton MA35 series SoC, and
add support for ma35d1 pinctrl.

Signed-off-by: Jacky Huang <ychuang3@nuvoton.com>
---
 drivers/pinctrl/nuvoton/Kconfig          |   19 +
 drivers/pinctrl/nuvoton/Makefile         |    2 +
 drivers/pinctrl/nuvoton/pinctrl-ma35.c   | 1233 +++++++++++++++
 drivers/pinctrl/nuvoton/pinctrl-ma35.h   |   51 +
 drivers/pinctrl/nuvoton/pinctrl-ma35d1.c | 1797 ++++++++++++++++++++++
 5 files changed, 3102 insertions(+)
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-ma35.c
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-ma35.h
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-ma35d1.c

diff --git a/drivers/pinctrl/nuvoton/Kconfig b/drivers/pinctrl/nuvoton/Kconfig
index 2abbfcec1fae..7eadaaf48d6e 100644
--- a/drivers/pinctrl/nuvoton/Kconfig
+++ b/drivers/pinctrl/nuvoton/Kconfig
@@ -45,3 +45,22 @@ config PINCTRL_NPCM8XX
 	  Say Y or M here to enable pin controller and GPIO support for
 	  the Nuvoton NPCM8XX SoC. This is strongly recommended when
 	  building a kernel that will run on this chip.
+
+config PINCTRL_MA35
+	bool
+	depends on (ARCH_MA35 || COMPILE_TEST) && OF
+	select GENERIC_PINCTRL_GROUPS
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select GPIO_GENERIC
+	select GPIOLIB_IRQCHIP
+	select MFD_SYSCON
+
+config PINCTRL_MA35D1
+	bool "Pinctrl and GPIO driver for Nuvoton MA35D1"
+	depends on (ARCH_MA35 || COMPILE_TEST) && OF
+	select PINCTRL_MA35
+	help
+	  Say Y here to enable pin controller and GPIO support
+	  for Nuvoton MA35D1 SoC.
diff --git a/drivers/pinctrl/nuvoton/Makefile b/drivers/pinctrl/nuvoton/Makefile
index 08031eab0af6..346c5082bc60 100644
--- a/drivers/pinctrl/nuvoton/Makefile
+++ b/drivers/pinctrl/nuvoton/Makefile
@@ -4,3 +4,5 @@
 obj-$(CONFIG_PINCTRL_WPCM450)	+= pinctrl-wpcm450.o
 obj-$(CONFIG_PINCTRL_NPCM7XX)	+= pinctrl-npcm7xx.o
 obj-$(CONFIG_PINCTRL_NPCM8XX)	+= pinctrl-npcm8xx.o
+obj-$(CONFIG_PINCTRL_MA35)	+= pinctrl-ma35.o
+obj-$(CONFIG_PINCTRL_MA35D1)	+= pinctrl-ma35d1.o
diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.c b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
new file mode 100644
index 000000000000..149d802c0c62
--- /dev/null
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.c
@@ -0,0 +1,1233 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ *
+ * Author: Shan-Chun Hung <schung@nuvoton.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "pinctrl-ma35.h"
+
+#define MA35_MFP_REG_BASE		0x80
+#define MA35_MFP_REG_SZ_PER_BANK	8
+#define MA35_MFP_BITS_PER_PORT		4
+
+#define MA35_GPIO_BANK_MAX		14
+#define MA35_GPIO_PORT_MAX		16
+
+/* GPIO control registers */
+#define MA35_GP_REG_MODE		0x00
+#define MA35_GP_REG_DINOFF		0x04
+#define MA35_GP_REG_DOUT		0x08
+#define MA35_GP_REG_DATMSK		0x0c
+#define MA35_GP_REG_PIN			0x10
+#define MA35_GP_REG_DBEN		0x14
+#define MA35_GP_REG_INTTYPE		0x18
+#define MA35_GP_REG_INTEN		0x1c
+#define MA35_GP_REG_INTSRC		0x20
+#define MA35_GP_REG_SMTEN		0x24
+#define MA35_GP_REG_SLEWCTL		0x28
+#define MA35_GP_REG_SPW			0x2c
+#define MA35_GP_REG_PUSEL		0x30
+#define MA35_GP_REG_DSL			0x38
+#define MA35_GP_REG_DSH			0x3c
+
+/* GPIO mode control */
+#define MA35_GP_MODE_INPUT		0x0
+#define MA35_GP_MODE_OUTPUT		0x1
+#define MA35_GP_MODE_OPEN_DRAIN		0x2
+#define MA35_GP_MODE_QUASI		0x3
+#define MA35_GP_MODE_MASK_WIDTH		2
+
+#define MA35_GP_SLEWCTL_MASK_WIDTH	2
+
+/* GPIO pull-up and pull-down selection control */
+#define MA35_GP_PUSEL_DISABLE		0x0
+#define MA35_GP_PUSEL_PULL_UP		0x1
+#define MA35_GP_PUSEL_PULL_DOWN		0x2
+#define MA35_GP_PUSEL_MASK_WIDTH	2
+
+/* Each pin data input/output is mapped by address mapping */
+#define MA35_PIN_MAP_BASE		0x800
+#define MA35_GP_DSH_BASE_PORT		8
+
+#define MVOLT_1800			0
+#define MVOLT_3300			1
+
+static const char * const gpio_group_name[] = {
+	"gpioa", "gpiob", "gpioc", "gpiod", "gpioe", "gpiof", "gpiog",
+	"gpioh", "gpioi", "gpioj", "gpiok", "gpiol", "gpiom", "gpion",
+};
+
+static const u32 ds_1800mv_tbl[] = {
+	2900, 4400, 5800, 7300, 8600, 10100, 11500, 13000,
+};
+
+static const u32 ds_3300mv_tbl[] = {
+	17100, 25600, 34100, 42800, 48000, 56000, 77000, 82000,
+};
+
+struct ma35_pin_func {
+	const char		*name;
+	const char		**groups;
+	u32			ngroups;
+};
+
+struct ma35_pin_setting {
+	u32			offset;
+	u32			shift;
+	u32			muxval;
+	unsigned long		*configs;
+	unsigned int		nconfigs;
+};
+
+struct ma35_pin_group {
+	const char		*name;
+	unsigned int		npins;
+	unsigned int		*pins;
+	struct ma35_pin_setting	*settings;
+};
+
+struct ma35_pin_bank {
+	void __iomem		*reg_base;
+	struct clk		*clk;
+	int			irq;
+	u8			nr_pins;
+	const char		*name;
+	u8			bank_num;
+	bool			valid;
+	struct device_node	*np;
+	struct gpio_chip	chip;
+	u32			irqtype;
+	u32			irqinten;
+	struct regmap		*regmap;
+	struct device		*dev;
+	spinlock_t		lock;
+};
+
+struct ma35_pin_ctrl {
+	struct ma35_pin_bank	*pin_banks;
+	u32			nr_banks;
+	u32			nr_pins;
+};
+
+struct ma35_pinctrl {
+	struct device		*dev;
+	struct ma35_pin_ctrl	*ctrl;
+	struct pinctrl_dev	*pctl;
+	const struct ma35_pinctrl_soc_info *info;
+	struct regmap		*regmap;
+	struct ma35_pin_group	*groups;
+	unsigned int		ngroups;
+	struct ma35_pin_func	*functions;
+	unsigned int		nfunctions;
+};
+
+static int ma35_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return npctl->ngroups;
+}
+
+static const char *ma35_get_group_name(struct pinctrl_dev *pctldev, unsigned int selector)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return npctl->groups[selector].name;
+}
+
+static int ma35_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
+			       const unsigned int **pins, unsigned int *npins)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+
+	if (selector >= npctl->ngroups)
+		return -EINVAL;
+
+	*pins = npctl->groups[selector].pins;
+	*npins = npctl->groups[selector].npins;
+
+	return 0;
+}
+
+static struct ma35_pin_group *ma35_pinctrl_find_group_by_name(
+			      const struct ma35_pinctrl *npctl, const char *name)
+{
+	int i;
+
+	for (i = 0; i < npctl->ngroups; i++) {
+		if (!strcmp(npctl->groups[i].name, name))
+			return &npctl->groups[i];
+	}
+	return NULL;
+}
+
+static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev,
+					    struct device_node *np,
+					    struct pinctrl_map **map,
+					    unsigned int *num_maps)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+	struct ma35_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = ma35_pinctrl_find_group_by_name(npctl, np->name);
+	if (!grp) {
+		dev_err(npctl->dev, "unable to find group for node %s\n", np->name);
+		return -EINVAL;
+	}
+
+	map_num += grp->npins;
+	new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map), GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		devm_kfree(pctldev->dev, new_map);
+		return -EINVAL;
+	}
+
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	new_map++;
+	for (i = 0; i < grp->npins; i++) {
+		new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[i].data.configs.group_or_pin = pin_get_name(pctldev, grp->pins[i]);
+		new_map[i].data.configs.configs = grp->settings[i].configs;
+		new_map[i].data.configs.num_configs = grp->settings[i].nconfigs;
+	}
+	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+	return 0;
+}
+
+static const struct pinctrl_ops ma35_pctrl_ops = {
+	.get_groups_count = ma35_get_groups_count,
+	.get_group_name = ma35_get_group_name,
+	.get_group_pins = ma35_get_group_pins,
+	.dt_node_to_map = ma35_pinctrl_dt_node_to_map_func,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int ma35_pinmux_get_func_count(struct pinctrl_dev *pctldev)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return npctl->nfunctions;
+}
+
+static const char *ma35_pinmux_get_func_name(struct pinctrl_dev *pctldev,
+					     unsigned int selector)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return npctl->functions[selector].name;
+}
+
+static int ma35_pinmux_get_func_groups(struct pinctrl_dev *pctldev,
+				       unsigned int function,
+				       const char *const **groups,
+				       unsigned int *const num_groups)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = npctl->functions[function].groups;
+	*num_groups = npctl->functions[function].ngroups;
+
+	return 0;
+}
+
+static int ma35_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
+			       unsigned int group)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+	struct ma35_pin_group *grp = &npctl->groups[group];
+	struct ma35_pin_setting *setting = grp->settings;
+	u32 i, regval;
+
+	dev_dbg(npctl->dev, "enable function %s group %s\n",
+		npctl->functions[selector].name, npctl->groups[group].name);
+
+	for (i = 0; i < grp->npins; i++) {
+		regmap_read(npctl->regmap, setting->offset, &regval);
+		regval &= ~GENMASK(setting->shift + MA35_MFP_BITS_PER_PORT - 1,
+				   setting->shift);
+		regval |= setting->muxval << setting->shift;
+		regmap_write(npctl->regmap, setting->offset, regval);
+		setting++;
+	}
+	return 0;
+}
+
+static const struct pinmux_ops ma35_pmx_ops = {
+	.get_functions_count = ma35_pinmux_get_func_count,
+	.get_function_name = ma35_pinmux_get_func_name,
+	.get_function_groups = ma35_pinmux_get_func_groups,
+	.set_mux = ma35_pinmux_set_mux,
+	.strict = true,
+};
+
+static void ma35_gpio_set_mode(void __iomem *reg_mode, unsigned int gpio, u32 mode)
+{
+	u32 regval = readl(reg_mode);
+
+	regval &= ~GENMASK(gpio * MA35_GP_MODE_MASK_WIDTH - 1,
+			   gpio * MA35_GP_MODE_MASK_WIDTH);
+	regval |= mode << gpio * MA35_GP_MODE_MASK_WIDTH;
+
+	writel(regval, reg_mode);
+}
+
+static u32 ma35_gpio_get_mode(void __iomem *reg_mode, unsigned int gpio)
+{
+	u32 regval = readl(reg_mode);
+
+	regval &= GENMASK(gpio * MA35_GP_MODE_MASK_WIDTH - 1,
+			  gpio * MA35_GP_MODE_MASK_WIDTH);
+
+	return regval >> gpio * MA35_GP_MODE_MASK_WIDTH;
+}
+
+static int ma35_gpio_core_direction_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(gc);
+	void __iomem *reg_mode = bank->reg_base + MA35_GP_REG_MODE;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bank->lock, flags);
+
+	ma35_gpio_set_mode(reg_mode, gpio, MA35_GP_MODE_INPUT);
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+
+	return 0;
+}
+
+static int ma35_gpio_core_direction_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(gc);
+	void __iomem *reg_dout = bank->reg_base + MA35_GP_REG_DOUT;
+	void __iomem *reg_mode = bank->reg_base + MA35_GP_REG_MODE;
+	unsigned long flags;
+	unsigned int regval;
+
+	spin_lock_irqsave(&bank->lock, flags);
+
+	regval = readl(reg_dout);
+	if (val)
+		writel(regval | BIT(gpio), reg_dout);
+	else
+		writel(regval & ~BIT(gpio), reg_dout);
+
+	ma35_gpio_set_mode(reg_mode, gpio, MA35_GP_MODE_OUTPUT);
+
+	spin_unlock_irqrestore(&bank->lock, flags);
+
+	return 0;
+}
+
+static int ma35_gpio_core_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(gc);
+
+	/* The MA35 PIN_MAP maps each GPIO pin to an independent 32-bit register. */
+	return readl(bank->reg_base + MA35_PIN_MAP_BASE + gpio * 4);
+}
+
+static void ma35_gpio_core_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(gc);
+
+	writel(val, bank->reg_base + MA35_PIN_MAP_BASE + gpio * 4);
+}
+
+static int ma35_gpio_core_to_request(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(gc);
+	u32 reg_offs, bit_offs, regval;
+
+	if (gpio < 8) {
+		/* The MFP low register controls port 0 ~ 7 */
+		reg_offs = bank->bank_num * MA35_MFP_REG_SZ_PER_BANK;
+		bit_offs = gpio * MA35_MFP_BITS_PER_PORT;
+	} else {
+		/* The MFP high register controls port 8 ~ 15 */
+		reg_offs = bank->bank_num * MA35_MFP_REG_SZ_PER_BANK + 4;
+		bit_offs = (gpio - 8) * MA35_MFP_BITS_PER_PORT;
+	}
+
+	regmap_read(bank->regmap, MA35_MFP_REG_BASE + reg_offs, &regval);
+	regval &= ~GENMASK(bit_offs + MA35_MFP_BITS_PER_PORT - 1, bit_offs);
+	regmap_write(bank->regmap, MA35_MFP_REG_BASE + reg_offs, regval);
+
+	return 0;
+}
+
+static void ma35_irq_gpio_ack(struct irq_data *d)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	void __iomem *reg_intsrc = bank->reg_base + MA35_GP_REG_INTSRC;
+	unsigned int num = (d->hwirq);
+
+	writel(1<<num, reg_intsrc);
+}
+
+static void ma35_irq_gpio_mask(struct irq_data *d)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	void __iomem *reg_ien = bank->reg_base + MA35_GP_REG_INTEN;
+	unsigned int num = (d->hwirq);
+	u32 regval;
+
+	regval = readl(reg_ien);
+
+	/*
+	 * The MA35_GP_REG_INTEN bits 0 ~ 15 control low-level or falling edge trigger,
+	 * while bits 16 ~ 31 control high-level or rising edge trigger.
+	 * We disable both type of interrupt.
+	 */
+	regval &= ~(BIT(num + 16) | BIT(num));
+
+	writel(regval, reg_ien);
+}
+
+static void ma35_irq_gpio_unmask(struct irq_data *d)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	void __iomem *reg_itype = bank->reg_base + MA35_GP_REG_INTTYPE;
+	void __iomem *reg_ien = bank->reg_base + MA35_GP_REG_INTEN;
+	unsigned int num = (d->hwirq);
+	u32 bval, regval;
+
+	bval = bank->irqtype & BIT(num);
+
+	regval = readl(reg_itype);
+	regval &= ~BIT(num);
+	writel(regval | bval, reg_itype);
+
+	bval = bank->irqinten & (BIT(num + 16) | BIT(num));
+
+	regval = readl(reg_ien);
+	regval &= ~(BIT(num + 16) | BIT(num));
+	writel(regval | bval, reg_ien);
+}
+
+static int ma35_irq_irqtype(struct irq_data *d, unsigned int type)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	unsigned int num = (d->hwirq);
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_BOTH:
+		irq_set_handler_locked(d, handle_edge_irq);
+		bank->irqtype &= ~(0x1 << num);
+		bank->irqinten |= (0x1 << num);
+		bank->irqinten |= (0x1 << (num + 16));
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		irq_set_handler_locked(d, handle_edge_irq);
+		bank->irqtype &= ~(0x1 << num);
+		bank->irqinten |= (0x1 << (num + 16));
+		bank->irqinten &= ~(0x1 << num);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_set_handler_locked(d, handle_edge_irq);
+		bank->irqtype &= ~(0x1 << num);
+		bank->irqinten |= (0x1 << num);
+		bank->irqinten &= ~(0x1 << (num + 16));
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_set_handler_locked(d, handle_level_irq);
+		bank->irqtype |= (0x1 << num);
+		bank->irqinten &= ~(0x1 << num);
+		bank->irqinten |= (0x1 << (num + 16));
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_set_handler_locked(d, handle_level_irq);
+		bank->irqtype |= (0x1 << num);
+		bank->irqinten &= ~(0x1 << (num + 16));
+		bank->irqinten |= (0x1 << num);
+		break;
+	default:
+		irq_set_handler_locked(d, handle_bad_irq);
+		return -EINVAL;
+	}
+
+	writel(bank->irqtype,	bank->reg_base + MA35_GP_REG_INTTYPE);
+	writel(bank->irqinten, bank->reg_base + MA35_GP_REG_INTEN);
+
+	return 0;
+}
+
+static struct irq_chip ma35_gpio_irqchip = {
+	.name = "MA35-GPIO-IRQ",
+	.irq_disable = ma35_irq_gpio_mask,
+	.irq_enable = ma35_irq_gpio_unmask,
+	.irq_ack = ma35_irq_gpio_ack,
+	.irq_mask = ma35_irq_gpio_mask,
+	.irq_unmask = ma35_irq_gpio_unmask,
+	.irq_set_type = ma35_irq_irqtype,
+	.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE,
+};
+
+static void ma35_irq_demux_intgroup(struct irq_desc *desc)
+{
+	struct ma35_pin_bank *bank = gpiochip_get_data(irq_desc_get_handler_data(desc));
+	struct irq_domain *irqdomain = bank->chip.irq.domain;
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	unsigned long isr;
+	int offset;
+
+	chained_irq_enter(irqchip, desc);
+
+	isr = readl(bank->reg_base + MA35_GP_REG_INTSRC);
+
+	if (isr)
+		for_each_set_bit(offset, &isr, bank->nr_pins)
+			generic_handle_irq(irq_find_mapping(irqdomain, offset));
+
+	chained_irq_exit(irqchip, desc);
+}
+
+static int ma35_gpiolib_register(struct platform_device *pdev, struct ma35_pinctrl *npctl)
+{
+	struct ma35_pin_ctrl *ctrl = npctl->ctrl;
+	struct ma35_pin_bank *bank = ctrl->pin_banks;
+	int ret;
+	int i;
+
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		if (!bank->valid) {
+			dev_warn(&pdev->dev, "bank %s is not valid\n",
+				 bank->np->name);
+			continue;
+		}
+		bank->irqtype = 0;
+		bank->irqinten = 0;
+		bank->chip.label = bank->name;
+		bank->chip.of_gpio_n_cells = 2;
+		bank->chip.parent = &pdev->dev;
+		bank->chip.request = ma35_gpio_core_to_request;
+		bank->chip.direction_input = ma35_gpio_core_direction_in;
+		bank->chip.direction_output = ma35_gpio_core_direction_out;
+		bank->chip.get = ma35_gpio_core_get;
+		bank->chip.set = ma35_gpio_core_set;
+		bank->chip.base = -1;
+		bank->chip.ngpio = bank->nr_pins;
+		bank->chip.can_sleep = false;
+		spin_lock_init(&bank->lock);
+
+		if (bank->irq > 0) {
+			struct gpio_irq_chip *girq;
+
+			girq = &bank->chip.irq;
+			gpio_irq_chip_set_chip(girq, &ma35_gpio_irqchip);
+			girq->parent_handler = ma35_irq_demux_intgroup;
+			girq->num_parents = 1;
+
+			girq->parents = devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents),
+						     GFP_KERNEL);
+			if (!girq->parents) {
+				ret = -ENOMEM;
+				goto fail;
+			}
+
+			girq->parents[0] = bank->irq;
+			girq->default_type = IRQ_TYPE_NONE;
+			girq->handler = handle_bad_irq;
+		}
+
+		ret = gpiochip_add_data(&bank->chip, bank);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
+				bank->chip.label, ret);
+			goto fail;
+		}
+	}
+	return 0;
+
+fail:
+	for (--i, --bank; i >= 0; --i, --bank) {
+		if (!bank->valid)
+			continue;
+		gpiochip_remove(&bank->chip);
+	}
+	return ret;
+}
+
+static int ma35_get_bank_data(struct ma35_pin_bank *bank, struct ma35_pinctrl *npctl)
+{
+	struct resource res;
+
+	if (of_address_to_resource(bank->np, 0, &res)) {
+		dev_err(npctl->dev, "cannot find IO resource for bank\n");
+		return -ENOENT;
+	}
+
+	bank->reg_base = devm_ioremap_resource(npctl->dev, &res);
+	if (IS_ERR(bank->reg_base)) {
+		dev_err(npctl->dev, "cannot ioremap resource for bank\n");
+		return PTR_ERR(bank->reg_base);
+	}
+
+	bank->irq = irq_of_parse_and_map(bank->np, 0);
+	bank->nr_pins = MA35_GPIO_PORT_MAX;
+
+	bank->clk = of_clk_get(bank->np, 0);
+	if (IS_ERR(bank->clk))
+		return PTR_ERR(bank->clk);
+
+	return clk_prepare_enable(bank->clk);
+}
+
+static int ma35_pinctrl_get_soc_data(struct ma35_pinctrl *pctl, struct platform_device *pdev)
+{
+	struct fwnode_handle *child;
+	struct ma35_pin_ctrl *ctrl;
+	struct ma35_pin_bank *bank;
+	int i, id = 0;
+
+	ctrl = pctl->ctrl;
+	ctrl->nr_banks = MA35_GPIO_BANK_MAX;
+
+	ctrl->pin_banks = devm_kcalloc(&pdev->dev, ctrl->nr_banks,
+				       sizeof(*ctrl->pin_banks), GFP_KERNEL);
+	if (!ctrl->pin_banks)
+		return -ENOMEM;
+
+	for (i = 0; i < ctrl->nr_banks; i++) {
+		ctrl->pin_banks[i].bank_num = i;
+		ctrl->pin_banks[i].name = gpio_group_name[i];
+	}
+
+	for_each_gpiochip_node(&pdev->dev, child) {
+		struct device_node *np = to_of_node(child);
+
+		bank = &ctrl->pin_banks[id];
+		bank->np = np;
+		bank->regmap = pctl->regmap;
+		bank->dev = &pdev->dev;
+		if (!ma35_get_bank_data(bank, pctl))
+			bank->valid = true;
+		id++;
+	}
+	return 0;
+}
+
+static void ma35_gpio_cla_port(unsigned int gpio_num, unsigned int *group,
+			       unsigned int *num)
+{
+	*group = gpio_num / MA35_GPIO_PORT_MAX;
+	*num = gpio_num % MA35_GPIO_PORT_MAX;
+}
+
+static int ma35_pinconf_set_pull(struct ma35_pinctrl *npctl, unsigned int pin,
+				 int pull_up)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_PUSEL);
+	regval &= ~GENMASK(port * MA35_GP_PUSEL_MASK_WIDTH - 1,
+			   port * MA35_GP_PUSEL_MASK_WIDTH);
+
+	switch (pull_up) {
+	case PIN_CONFIG_BIAS_PULL_UP:
+		regval |= MA35_GP_PUSEL_PULL_UP << port * MA35_GP_PUSEL_MASK_WIDTH;
+		break;
+
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		regval |= MA35_GP_PUSEL_PULL_DOWN << port * MA35_GP_PUSEL_MASK_WIDTH;
+		break;
+
+	case MA35_GP_PUSEL_DISABLE:
+		regval |= MA35_GP_PUSEL_DISABLE << port * MA35_GP_PUSEL_MASK_WIDTH;
+		break;
+
+	default:
+		regval |= MA35_GP_PUSEL_DISABLE << port * MA35_GP_PUSEL_MASK_WIDTH;
+		break;
+	}
+	writel(regval, base + MA35_GP_REG_PUSEL);
+
+	return 0;
+}
+
+static int ma35_pinconf_get_output(struct ma35_pinctrl *npctl, unsigned int pin)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 mode;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	mode = ma35_gpio_get_mode(base + MA35_GP_REG_MODE, port);
+	if (mode == MA35_GP_MODE_OUTPUT)
+		return 1;
+
+	return 0;
+}
+
+static int ma35_pinconf_get_pull(struct ma35_pinctrl *npctl, unsigned int pin)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_PUSEL);
+	regval &= GENMASK(port * MA35_GP_PUSEL_MASK_WIDTH - 1,
+			  port * MA35_GP_PUSEL_MASK_WIDTH);
+	regval >>= port * MA35_GP_PUSEL_MASK_WIDTH;
+
+	switch (regval) {
+	case MA35_GP_PUSEL_PULL_UP:
+		return PIN_CONFIG_BIAS_PULL_UP;
+
+	case MA35_GP_PUSEL_PULL_DOWN:
+		return PIN_CONFIG_BIAS_PULL_DOWN;
+
+	case MA35_GP_PUSEL_DISABLE:
+		return PIN_CONFIG_BIAS_DISABLE;
+	}
+
+	return PIN_CONFIG_BIAS_DISABLE;
+}
+
+static int ma35_pinconf_set_output(struct ma35_pinctrl *npctl, unsigned int pin, bool out)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	ma35_gpio_set_mode(base + MA35_GP_REG_MODE, port, MA35_GP_MODE_OUTPUT);
+
+	return 0;
+}
+
+static int ma35_pinconf_get_power_source(struct ma35_pinctrl *npctl, unsigned int pin)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_SPW);
+
+	if (regval & BIT(port))
+		return MVOLT_3300;
+	else
+		return MVOLT_1800;
+}
+
+static int ma35_pinconf_set_power_source(struct ma35_pinctrl *npctl,
+					 unsigned int pin, int arg)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	if ((arg != MVOLT_1800) && (arg != MVOLT_3300))
+		return -EINVAL;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_SPW);
+
+	if (arg == MVOLT_1800)
+		regval &= ~BIT(port);
+	else
+		regval |= BIT(port);
+
+	writel(regval, base + MA35_GP_REG_SPW);
+
+	return 0;
+}
+
+static int ma35_pinconf_get_drive_strength(struct ma35_pinctrl *npctl, unsigned int pin,
+					   u32 *strength)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval, ds_val;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	/*
+	 * The MA35_GP_REG_DSL register controls ports 0 to 7, while the MA35_GP_REG_DSH
+	 * register controls ports 8 to 15. Each port occupies a width of 4 bits, with 3
+	 * bits being effective.
+	 */
+	if (port < MA35_GP_DSH_BASE_PORT) {
+		regval = readl(base + MA35_GP_REG_DSL);
+		ds_val = (regval & GENMASK(port * 4 + 2, port * 4)) >> port * 4;
+	} else {
+		port -= MA35_GP_DSH_BASE_PORT;
+		regval = readl(base + MA35_GP_REG_DSH);
+		ds_val = (regval & GENMASK(port * 4 + 2, port * 4)) >> port * 4;
+	}
+
+	if (ma35_pinconf_get_power_source(npctl, pin) == MVOLT_1800)
+		*strength = ds_1800mv_tbl[ds_val];
+	else
+		*strength = ds_3300mv_tbl[ds_val];
+
+	return 0;
+}
+
+static int ma35_pinconf_set_drive_strength(struct ma35_pinctrl *npctl, unsigned int pin,
+					   int strength)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	int i, ds_val = -1;
+	u32 regval;
+
+	if (ma35_pinconf_get_power_source(npctl, pin) == MVOLT_1800) {
+		for (i = 0; i < ARRAY_SIZE(ds_1800mv_tbl); i++) {
+			if (ds_1800mv_tbl[i] == strength)
+				ds_val = i;
+		}
+	} else {
+		for (i = 0; i < ARRAY_SIZE(ds_3300mv_tbl); i++) {
+			if (ds_3300mv_tbl[i] == strength)
+				ds_val = i;
+		}
+	}
+	if (ds_val == -1)
+		return -EINVAL;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	if (port < MA35_GP_DSH_BASE_PORT) {
+		regval = readl(base + MA35_GP_REG_DSL);
+		regval &= ~GENMASK(port * 4 + 2, port * 4);
+		regval |= ds_val << port * 4;
+		writel(regval, base + MA35_GP_REG_DSL);
+	} else {
+		port -= MA35_GP_DSH_BASE_PORT;
+		regval = readl(base + MA35_GP_REG_DSH);
+		regval &= ~GENMASK(port * 4 + 2, port * 4);
+		regval |= ds_val << port * 4;
+		writel(regval, base + MA35_GP_REG_DSH);
+	}
+	return 0;
+}
+
+static int ma35_pinconf_get_schmitt_enable(struct ma35_pinctrl *npctl, unsigned int pin)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_SMTEN);
+
+	return !!(regval & BIT(port));
+}
+
+static int ma35_pinconf_set_schmitt(struct ma35_pinctrl *npctl, unsigned int pin, int enable)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_SMTEN);
+
+	if (enable)
+		regval |= BIT(port);
+	else
+		regval &= ~BIT(port);
+
+	writel(regval, base + MA35_GP_REG_SMTEN);
+
+	return 0;
+}
+
+static int ma35_pinconf_get_slew_rate(struct ma35_pinctrl *npctl, unsigned int pin)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_SLEWCTL);
+	regval &= GENMASK(port * MA35_GP_SLEWCTL_MASK_WIDTH - 1,
+			  port * MA35_GP_SLEWCTL_MASK_WIDTH);
+
+	return regval >> port * MA35_GP_SLEWCTL_MASK_WIDTH;
+}
+
+static int ma35_pinconf_set_slew_rate(struct ma35_pinctrl *npctl, unsigned int pin, int rate)
+{
+	unsigned int port, group_num;
+	void __iomem *base;
+	u32 regval;
+
+	ma35_gpio_cla_port(pin, &group_num, &port);
+	base = npctl->ctrl->pin_banks[group_num].reg_base;
+
+	regval = readl(base + MA35_GP_REG_SLEWCTL);
+	regval &= ~GENMASK(port * MA35_GP_SLEWCTL_MASK_WIDTH - 1,
+			   port * MA35_GP_SLEWCTL_MASK_WIDTH);
+	regval |= rate << port * MA35_GP_SLEWCTL_MASK_WIDTH;
+	writel(regval, base + MA35_GP_REG_SLEWCTL);
+
+	return 0;
+}
+
+static int ma35_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	u32 arg;
+	int ret;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (ma35_pinconf_get_pull(npctl, pin) == param)
+			arg = 1;
+		else
+			return -EINVAL;
+		break;
+
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		ret = ma35_pinconf_get_drive_strength(npctl, pin, &arg);
+		if (ret)
+			return ret;
+		break;
+
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		arg = ma35_pinconf_get_schmitt_enable(npctl, pin);
+		break;
+
+	case PIN_CONFIG_SLEW_RATE:
+		arg = ma35_pinconf_get_slew_rate(npctl, pin);
+		break;
+
+	case PIN_CONFIG_OUTPUT_ENABLE:
+		arg = ma35_pinconf_get_output(npctl, pin);
+		break;
+
+	case PIN_CONFIG_POWER_SOURCE:
+		arg = ma35_pinconf_get_power_source(npctl, pin);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	*config = pinconf_to_config_packed(param, arg);
+
+	return 0;
+}
+
+static int ma35_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			    unsigned long *configs, unsigned int num_configs)
+{
+	struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param;
+	unsigned int arg = 0;
+	int i, ret = 0;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+		case PIN_CONFIG_BIAS_PULL_UP:
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			ret = ma35_pinconf_set_pull(npctl, pin, param);
+			break;
+
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			ret = ma35_pinconf_set_drive_strength(npctl, pin, arg);
+			break;
+
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			ret = ma35_pinconf_set_schmitt(npctl, pin, 1);
+			break;
+
+		case PIN_CONFIG_INPUT_SCHMITT:
+			ret = ma35_pinconf_set_schmitt(npctl, pin, arg);
+			break;
+
+		case PIN_CONFIG_SLEW_RATE:
+			ret = ma35_pinconf_set_slew_rate(npctl, pin, arg);
+			break;
+
+		case PIN_CONFIG_OUTPUT_ENABLE:
+			ret = ma35_pinconf_set_output(npctl, pin, arg);
+			break;
+
+		case PIN_CONFIG_POWER_SOURCE:
+			ret = ma35_pinconf_set_power_source(npctl, pin, arg);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+	return ret;
+}
+
+static const struct pinconf_ops ma35_pinconf_ops = {
+	.pin_config_get = ma35_pinconf_get,
+	.pin_config_set = ma35_pinconf_set,
+	.is_generic = true,
+};
+
+static int ma35_pinctrl_parse_groups(struct device_node *np, struct ma35_pin_group *grp,
+				     struct ma35_pinctrl *npctl, u32 index)
+{
+	unsigned long *configs;
+	unsigned int nconfigs;
+	struct ma35_pin_setting *pin;
+	const __be32 *list;
+	int i, j, size, ret;
+
+	dev_dbg(npctl->dev, "group(%d): %s\n", index, np->name);
+
+	grp->name = np->name;
+
+	ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &nconfigs);
+	if (ret)
+		return ret;
+
+	/*
+	 * the binding format is nuvoton,pins = <bank pin-mfp pin-function>,
+	 * do sanity check and calculate pins number
+	 */
+	list = of_get_property(np, "nuvoton,pins", &size);
+	size /= sizeof(*list);
+	if (!size || size % 3) {
+		dev_err(npctl->dev, "wrong setting!\n");
+		return -EINVAL;
+	}
+	grp->npins = size / 3;
+
+	grp->pins = devm_kcalloc(npctl->dev, grp->npins, sizeof(*grp->pins), GFP_KERNEL);
+	if (!grp->pins)
+		return -ENOMEM;
+
+	grp->settings = devm_kcalloc(npctl->dev, grp->npins, sizeof(*grp->settings), GFP_KERNEL);
+	if (!grp->settings)
+		return -ENOMEM;
+
+	pin = grp->settings;
+
+	for (i = 0, j = 0; i < size; i += 3, j++) {
+		pin->offset = be32_to_cpu(*list++) * MA35_MFP_REG_SZ_PER_BANK + MA35_MFP_REG_BASE;
+		pin->shift = (be32_to_cpu(*list++) * MA35_MFP_BITS_PER_PORT) % 32;
+		pin->muxval = be32_to_cpu(*list++);
+		pin->configs = configs;
+		pin->nconfigs = nconfigs;
+		grp->pins[j] = npctl->info->get_pin_num(pin->offset, pin->shift);
+		pin++;
+	}
+	return 0;
+}
+
+static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinctrl *npctl,
+					u32 index)
+{
+	struct device_node *child;
+	struct ma35_pin_func *func;
+	struct ma35_pin_group *grp;
+	static u32 grp_index;
+	u32 ret, i = 0;
+
+	dev_dbg(npctl->dev, "parse function(%d): %s\n", index, np->name);
+
+	func = &npctl->functions[index];
+	func->name = np->name;
+	func->ngroups = of_get_child_count(np);
+
+	if (func->ngroups <= 0)
+		return 0;
+
+	func->groups = devm_kcalloc(npctl->dev, func->ngroups, sizeof(char *), GFP_KERNEL);
+	if (!func->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &npctl->groups[grp_index++];
+		ret = ma35_pinctrl_parse_groups(child, grp, npctl, i++);
+		if (ret) {
+			of_node_put(child);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int ma35_pinctrl_probe_dt(struct platform_device *pdev, struct ma35_pinctrl *npctl)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+	u32 idx = 0;
+	int ret;
+
+	if (!np)
+		return -ENODEV;
+
+	for_each_child_of_node(np, child) {
+		if (of_property_read_bool(child, "gpio-controller"))
+			continue;
+		npctl->nfunctions++;
+		npctl->ngroups += of_get_child_count(child);
+	}
+
+	npctl->functions = devm_kcalloc(&pdev->dev, npctl->nfunctions,
+					sizeof(*npctl->functions), GFP_KERNEL);
+	if (!npctl->functions)
+		return -ENOMEM;
+
+	npctl->groups = devm_kcalloc(&pdev->dev, npctl->ngroups,
+				     sizeof(*npctl->groups), GFP_KERNEL);
+	if (!npctl->groups)
+		return -ENOMEM;
+
+	dev_dbg(&pdev->dev, "nfunctions = %d\n", npctl->nfunctions);
+	dev_dbg(&pdev->dev, "ngroups = %d\n", npctl->ngroups);
+
+	for_each_child_of_node(np, child) {
+		if (of_property_read_bool(child, "gpio-controller"))
+			continue;
+
+		ret = ma35_pinctrl_parse_functions(child, npctl, idx++);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to parse function\n");
+			of_node_put(child);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+int ma35_pinctrl_probe(struct platform_device *pdev, const struct ma35_pinctrl_soc_info *info)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct pinctrl_desc *ma35_pinctrl_desc;
+	struct ma35_pinctrl *npctl;
+	int ret;
+
+	if (!info || !info->pins || !info->npins) {
+		dev_err(&pdev->dev, "wrong pinctrl info\n");
+		return -EINVAL;
+	}
+
+	npctl = devm_kzalloc(&pdev->dev, sizeof(*npctl), GFP_KERNEL);
+	if (!npctl)
+		return -ENOMEM;
+
+	ma35_pinctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*ma35_pinctrl_desc), GFP_KERNEL);
+	if (!ma35_pinctrl_desc)
+		return -ENOMEM;
+
+	npctl->ctrl = devm_kzalloc(&pdev->dev, sizeof(*npctl->ctrl), GFP_KERNEL);
+	if (!npctl->ctrl)
+		return -ENOMEM;
+
+	ma35_pinctrl_desc->name = dev_name(&pdev->dev);
+	ma35_pinctrl_desc->pins = info->pins;
+	ma35_pinctrl_desc->npins = info->npins;
+	ma35_pinctrl_desc->pctlops = &ma35_pctrl_ops;
+	ma35_pinctrl_desc->pmxops = &ma35_pmx_ops;
+	ma35_pinctrl_desc->confops = &ma35_pinconf_ops;
+	ma35_pinctrl_desc->owner = THIS_MODULE;
+
+	npctl->info = info;
+	npctl->dev = &pdev->dev;
+
+	npctl->regmap = syscon_regmap_lookup_by_phandle(np, "nuvoton,sys");
+	if (IS_ERR(npctl->regmap))
+		return dev_err_probe(&pdev->dev, PTR_ERR(npctl->regmap),
+				     "No syscfg phandle specified\n");
+
+	ma35_pinctrl_get_soc_data(npctl, pdev);
+
+	platform_set_drvdata(pdev, npctl);
+
+	ret = ma35_pinctrl_probe_dt(pdev, npctl);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "fail to probe MA35 pinctrl dt\n");
+
+	ret = devm_pinctrl_register_and_init(&pdev->dev, ma35_pinctrl_desc,
+					     npctl, &npctl->pctl);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "fail to register MA35 pinctrl\n");
+
+	ret = pinctrl_enable(npctl->pctl);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "fail to enable MA35 pinctrl\n");
+
+	return ma35_gpiolib_register(pdev, npctl);
+}
+
+int __maybe_unused ma35_pinctrl_suspend(struct device *dev)
+{
+	struct ma35_pinctrl *npctl = dev_get_drvdata(dev);
+
+	return pinctrl_force_sleep(npctl->pctl);
+}
+
+int __maybe_unused ma35_pinctrl_resume(struct device *dev)
+{
+	struct ma35_pinctrl *npctl = dev_get_drvdata(dev);
+
+	return pinctrl_force_default(npctl->pctl);
+}
diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35.h b/drivers/pinctrl/nuvoton/pinctrl-ma35.h
new file mode 100644
index 000000000000..281605e2c231
--- /dev/null
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ *
+ * Author: Shan-Chun Hung <schung@nuvoton.com>
+ */
+#ifndef __PINCTRL_MA35_H
+#define __PINCTRL_MA35_H
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+
+struct ma35_mux_desc {
+	const char *name;
+	u32 muxval;
+};
+
+struct ma35_pin_data {
+	u32 offset;
+	u32 shift;
+	struct ma35_mux_desc *muxes;
+};
+
+struct ma35_pinctrl_soc_info {
+	const struct pinctrl_pin_desc *pins;
+	unsigned int npins;
+	int (*get_pin_num)(int offset, int shift);
+};
+
+#define MA35_PIN(num, n, o, s, ...) {			\
+	.number = num,					\
+	.name = #n,					\
+	.drv_data = &(struct ma35_pin_data) {		\
+		.offset = o,				\
+		.shift = s,				\
+		.muxes = (struct ma35_mux_desc[]) {	\
+			 __VA_ARGS__, { } },		\
+	},						\
+}
+
+#define MA35_MUX(_val, _name) {				\
+	.name = _name,					\
+	.muxval = _val,					\
+}
+
+int ma35_pinctrl_probe(struct platform_device *pdev, const struct ma35_pinctrl_soc_info *info);
+int ma35_pinctrl_suspend(struct device *dev);
+int ma35_pinctrl_resume(struct device *dev);
+
+#endif /* __PINCTRL_MA35_H */
diff --git a/drivers/pinctrl/nuvoton/pinctrl-ma35d1.c b/drivers/pinctrl/nuvoton/pinctrl-ma35d1.c
new file mode 100644
index 000000000000..36510c0b0690
--- /dev/null
+++ b/drivers/pinctrl/nuvoton/pinctrl-ma35d1.c
@@ -0,0 +1,1797 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Nuvoton Technology Corp.
+ *
+ * Author: Shan-Chun Hung <schung@nuvoton.com>
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-ma35.h"
+
+static const struct pinctrl_pin_desc ma35d1_pins[] = {
+	MA35_PIN(0, PA0, 0x80, 0x0,
+		MA35_MUX(0x0, "GPA0"),
+		MA35_MUX(0x2, "UART1_nCTS"),
+		MA35_MUX(0x3, "UART16_RXD"),
+		MA35_MUX(0x6, "NAND_DATA0"),
+		MA35_MUX(0x7, "EBI_AD0"),
+		MA35_MUX(0x9, "EBI_ADR0")),
+	MA35_PIN(1, PA1, 0x80, 0x4,
+		MA35_MUX(0x0, "GPA1"),
+		MA35_MUX(0x2, "UART1_nRTS"),
+		MA35_MUX(0x3, "UART16_TXD"),
+		MA35_MUX(0x6, "NAND_DATA1"),
+		MA35_MUX(0x7, "EBI_AD1"),
+		MA35_MUX(0x9, "EBI_ADR1")),
+	MA35_PIN(2, PA2, 0x80, 0x8,
+		MA35_MUX(0x0, "GPA2"),
+		MA35_MUX(0x2, "UART1_RXD"),
+		MA35_MUX(0x6, "NAND_DATA2"),
+		MA35_MUX(0x7, "EBI_AD2"),
+		MA35_MUX(0x9, "EBI_ADR2")),
+	MA35_PIN(3, PA3, 0x80, 0xc,
+		MA35_MUX(0x0, "GPA3"),
+		MA35_MUX(0x2, "UART1_TXD"),
+		MA35_MUX(0x6, "NAND_DATA3"),
+		MA35_MUX(0x7, "EBI_AD3"),
+		MA35_MUX(0x9, "EBI_ADR3")),
+	MA35_PIN(4, PA4, 0x80, 0x10,
+		MA35_MUX(0x0, "GPA4"),
+		MA35_MUX(0x2, "UART3_nCTS"),
+		MA35_MUX(0x3, "UART2_RXD"),
+		MA35_MUX(0x6, "NAND_DATA4"),
+		MA35_MUX(0x7, "EBI_AD4"),
+		MA35_MUX(0x9, "EBI_ADR4")),
+	MA35_PIN(5, PA5, 0x80, 0x14,
+		MA35_MUX(0x0, "GPA5"),
+		MA35_MUX(0x2, "UART3_nRTS"),
+		MA35_MUX(0x3, "UART2_TXD"),
+		MA35_MUX(0x6, "NAND_DATA5"),
+		MA35_MUX(0x7, "EBI_AD5"),
+		MA35_MUX(0x9, "EBI_ADR5")),
+	MA35_PIN(6, PA6, 0x80, 0x18,
+		MA35_MUX(0x0, "GPA6"),
+		MA35_MUX(0x2, "UART3_RXD"),
+		MA35_MUX(0x6, "NAND_DATA6"),
+		MA35_MUX(0x7, "EBI_AD6"),
+		MA35_MUX(0x9, "EBI_ADR6")),
+	MA35_PIN(7, PA7, 0x80, 0x1c,
+		MA35_MUX(0x0, "GPA7"),
+		MA35_MUX(0x2, "UART3_TXD"),
+		MA35_MUX(0x6, "NAND_DATA7"),
+		MA35_MUX(0x7, "EBI_AD7"),
+		MA35_MUX(0x9, "EBI_ADR7")),
+	MA35_PIN(8, PA8, 0x84, 0x0,
+		MA35_MUX(0x0, "GPA8"),
+		MA35_MUX(0x2, "UART5_nCTS"),
+		MA35_MUX(0x3, "UART4_RXD"),
+		MA35_MUX(0x6, "NAND_RDY0"),
+		MA35_MUX(0x7, "EBI_AD8"),
+		MA35_MUX(0x9, "EBI_ADR8")),
+	MA35_PIN(9, PA9, 0x84, 0x4,
+		MA35_MUX(0x0, "GPA9"),
+		MA35_MUX(0x2, "UART5_nRTS"),
+		MA35_MUX(0x3, "UART4_TXD"),
+		MA35_MUX(0x6, "NAND_nRE"),
+		MA35_MUX(0x7, "EBI_AD9"),
+		MA35_MUX(0x9, "EBI_ADR9")),
+	MA35_PIN(10, PA10, 0x84, 0x8,
+		MA35_MUX(0x0, "GPA10"),
+		MA35_MUX(0x2, "UART5_RXD"),
+		MA35_MUX(0x6, "NAND_nWE"),
+		MA35_MUX(0x7, "EBI_AD10"),
+		MA35_MUX(0x9, "EBI_ADR10")),
+	MA35_PIN(11, PA11, 0x84, 0xc,
+		MA35_MUX(0x0, "GPA11"),
+		MA35_MUX(0x2, "UART5_TXD"),
+		MA35_MUX(0x6, "NAND_CLE"),
+		MA35_MUX(0x7, "EBI_AD11"),
+		MA35_MUX(0x9, "EBI_ADR11")),
+	MA35_PIN(12, PA12, 0x84, 0x10,
+		MA35_MUX(0x0, "GPA12"),
+		MA35_MUX(0x2, "UART7_nCTS"),
+		MA35_MUX(0x3, "UART8_RXD"),
+		MA35_MUX(0x6, "NAND_ALE"),
+		MA35_MUX(0x7, "EBI_AD12"),
+		MA35_MUX(0x9, "EBI_ADR12")),
+	MA35_PIN(13, PA13, 0x84, 0x14,
+		MA35_MUX(0x0, "GPA13"),
+		MA35_MUX(0x2, "UART7_nRTS"),
+		MA35_MUX(0x3, "UART8_TXD"),
+		MA35_MUX(0x6, "NAND_nCS0"),
+		MA35_MUX(0x7, "EBI_AD13"),
+		MA35_MUX(0x9, "EBI_ADR13")),
+	MA35_PIN(14, PA14, 0x84, 0x18,
+		MA35_MUX(0x0, "GPA14"),
+		MA35_MUX(0x2, "UART7_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x6, "NAND_nWP"),
+		MA35_MUX(0x7, "EBI_AD14"),
+		MA35_MUX(0x9, "EBI_ADR14")),
+	MA35_PIN(15, PA15, 0x84, 0x1c,
+		MA35_MUX(0x0, "GPA15"),
+		MA35_MUX(0x1, "EPWM0_CH2"),
+		MA35_MUX(0x2, "UART9_nCTS"),
+		MA35_MUX(0x3, "UART6_RXD"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x5, "CAN2_RXD"),
+		MA35_MUX(0x7, "EBI_ALE"),
+		MA35_MUX(0x9, "QEI0_A"),
+		MA35_MUX(0xb, "TM1"),
+		MA35_MUX(0xe, "RGMII0_PPS"),
+		MA35_MUX(0xf, "RMII0_PPS")),
+	MA35_PIN(16, PB0, 0x88, 0x0,
+		MA35_MUX(0x0, "GPB0"),
+		MA35_MUX(0x8, "EADC0_CH0")),
+	MA35_PIN(17, PB1, 0x88, 0x4,
+		MA35_MUX(0x0, "GPB1"),
+		MA35_MUX(0x8, "EADC0_CH1")),
+	MA35_PIN(18, PB2, 0x88, 0x8,
+		MA35_MUX(0x0, "GPB2"),
+		MA35_MUX(0x8, "EADC0_CH2")),
+	MA35_PIN(19, PB3, 0x88, 0xc,
+		MA35_MUX(0x0, "GPB3"),
+		MA35_MUX(0x8, "EADC0_CH3")),
+	MA35_PIN(20, PB4, 0x88, 0x10,
+		MA35_MUX(0x0, "GPB4"),
+		MA35_MUX(0x8, "EADC0_CH4")),
+	MA35_PIN(21, PB5, 0x88, 0x14,
+		MA35_MUX(0x0, "GPB5"),
+		MA35_MUX(0x8, "EADC0_CH5")),
+	MA35_PIN(22, PB6, 0x88, 0x18,
+		MA35_MUX(0x0, "GPB6"),
+		MA35_MUX(0x8, "EADC0_CH6")),
+	MA35_PIN(23, PB7, 0x88, 0x1c,
+		MA35_MUX(0x0, "GPB7"),
+		MA35_MUX(0x8, "EADC0_CH7")),
+	MA35_PIN(24, PB8, 0x8c, 0x0,
+		MA35_MUX(0x0, "GPB8"),
+		MA35_MUX(0x1, "EPWM2_BRAKE0"),
+		MA35_MUX(0x2, "UART2_nCTS"),
+		MA35_MUX(0x3, "UART1_RXD"),
+		MA35_MUX(0x4, "I2C2_SDA"),
+		MA35_MUX(0x5, "SPI0_SS1"),
+		MA35_MUX(0x6, "SPI0_I2SMCLK"),
+		MA35_MUX(0x8, "ADC0_CH0"),
+		MA35_MUX(0x9, "EBI_nCS0"),
+		MA35_MUX(0xb, "TM4"),
+		MA35_MUX(0xe, "QEI2_INDEX"),
+		MA35_MUX(0xf, "KPI_ROW6")),
+	MA35_PIN(25, PB9, 0x8c, 0x4,
+		MA35_MUX(0x0, "GPB9"),
+		MA35_MUX(0x1, "EPWM2_CH4"),
+		MA35_MUX(0x2, "UART2_nRTS"),
+		MA35_MUX(0x3, "UART1_TXD"),
+		MA35_MUX(0x4, "I2C2_SCL"),
+		MA35_MUX(0x5, "SPI0_CLK"),
+		MA35_MUX(0x6, "I2S0_MCLK"),
+		MA35_MUX(0x7, "CCAP1_HSYNC"),
+		MA35_MUX(0x8, "ADC0_CH1"),
+		MA35_MUX(0x9, "EBI_ALE"),
+		MA35_MUX(0xa, "EBI_AD13"),
+		MA35_MUX(0xb, "TM0_EXT"),
+		MA35_MUX(0xc, "I2S1_MCLK"),
+		MA35_MUX(0xd, "SC0_nCD"),
+		MA35_MUX(0xe, "QEI2_A"),
+		MA35_MUX(0xf, "KPI_ROW7")),
+	MA35_PIN(26, PB10, 0x8c, 0x8,
+		MA35_MUX(0x0, "GPB10"),
+		MA35_MUX(0x1, "EPWM2_CH5"),
+		MA35_MUX(0x2, "UART2_RXD"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x5, "SPI0_MOSI"),
+		MA35_MUX(0x6, "EBI_MCLK"),
+		MA35_MUX(0x7, "CCAP1_VSYNC"),
+		MA35_MUX(0x8, "ADC0_CH2"),
+		MA35_MUX(0x9, "EBI_ADR15"),
+		MA35_MUX(0xa, "EBI_AD14"),
+		MA35_MUX(0xb, "TM5"),
+		MA35_MUX(0xc, "I2C1_SDA"),
+		MA35_MUX(0xd, "INT1"),
+		MA35_MUX(0xe, "QEI2_B")),
+	MA35_PIN(27, PB11, 0x8c, 0xc,
+		MA35_MUX(0x0, "GPB11"),
+		MA35_MUX(0x1, "EPWM2_BRAKE1"),
+		MA35_MUX(0x2, "UART2_TXD"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x5, "SPI0_MISO"),
+		MA35_MUX(0x6, "I2S1_MCLK"),
+		MA35_MUX(0x7, "CCAP1_SFIELD"),
+		MA35_MUX(0x8, "ADC0_CH3"),
+		MA35_MUX(0x9, "EBI_nCS2"),
+		MA35_MUX(0xa, "EBI_ALE"),
+		MA35_MUX(0xb, "TM5_EXT"),
+		MA35_MUX(0xc, "I2C1_SCL"),
+		MA35_MUX(0xd, "INT2"),
+		MA35_MUX(0xe, "QEI2_INDEX")),
+	MA35_PIN(28, PB12, 0x8c, 0x10,
+		MA35_MUX(0x0, "GPB12"),
+		MA35_MUX(0x1, "EPWM2_CH0"),
+		MA35_MUX(0x2, "UART4_nCTS"),
+		MA35_MUX(0x3, "UART3_RXD"),
+		MA35_MUX(0x4, "I2C3_SDA"),
+		MA35_MUX(0x5, "CAN2_RXD"),
+		MA35_MUX(0x6, "I2S1_LRCK"),
+		MA35_MUX(0x8, "ADC0_CH4"),
+		MA35_MUX(0x9, "EBI_ADR16"),
+		MA35_MUX(0xe, "ECAP2_IC0")),
+	MA35_PIN(29, PB13, 0x8c, 0x14,
+		MA35_MUX(0x0, "GPB13"),
+		MA35_MUX(0x1, "EPWM2_CH1"),
+		MA35_MUX(0x2, "UART4_nRTS"),
+		MA35_MUX(0x3, "UART3_TXD"),
+		MA35_MUX(0x4, "I2C3_SCL"),
+		MA35_MUX(0x5, "CAN2_TXD"),
+		MA35_MUX(0x6, "I2S1_BCLK"),
+		MA35_MUX(0x8, "ADC0_CH5"),
+		MA35_MUX(0x9, "EBI_ADR17"),
+		MA35_MUX(0xe, "ECAP2_IC1")),
+	MA35_PIN(30, PB14, 0x8c, 0x18,
+		MA35_MUX(0x0, "GPB14"),
+		MA35_MUX(0x1, "EPWM2_CH2"),
+		MA35_MUX(0x2, "UART4_RXD"),
+		MA35_MUX(0x3, "CAN1_RXD"),
+		MA35_MUX(0x5, "I2C4_SDA"),
+		MA35_MUX(0x6, "I2S1_DI"),
+		MA35_MUX(0x8, "ADC0_CH6"),
+		MA35_MUX(0x9, "EBI_ADR18"),
+		MA35_MUX(0xe, "ECAP2_IC2")),
+	MA35_PIN(31, PB15, 0x8c, 0x1c,
+		MA35_MUX(0x0, "GPB15"),
+		MA35_MUX(0x1, "EPWM2_CH3"),
+		MA35_MUX(0x2, "UART4_TXD"),
+		MA35_MUX(0x3, "CAN1_TXD"),
+		MA35_MUX(0x5, "I2C4_SCL"),
+		MA35_MUX(0x6, "I2S1_DO"),
+		MA35_MUX(0x8, "ADC0_CH7"),
+		MA35_MUX(0x9, "EBI_ADR19")),
+	MA35_PIN(32, PC0, 0x90, 0x0,
+		MA35_MUX(0x0, "GPC0"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x6, "SD0_CMD/eMMC0_CMD")),
+	MA35_PIN(33, PC1, 0x90, 0x4,
+		MA35_MUX(0x0, "GPC1"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x6, "SD0_CLK/eMMC0_CLK")),
+	MA35_PIN(34, PC2, 0x90, 0x8,
+		MA35_MUX(0x0, "GPC2"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x6, "SD0_DAT0/eMMC0_DAT0")),
+	MA35_PIN(35, PC3, 0x90, 0xc,
+		MA35_MUX(0x0, "GPC3"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x6, "SD0_DAT1/eMMC0_DAT1")),
+	MA35_PIN(36, PC4, 0x90, 0x10,
+		MA35_MUX(0x0, "GPC4"),
+		MA35_MUX(0x4, "I2C5_SDA"),
+		MA35_MUX(0x6, "SD0_DAT2/eMMC0_DAT2")),
+	MA35_PIN(37, PC5, 0x90, 0x14,
+		MA35_MUX(0x0, "GPC5"),
+		MA35_MUX(0x4, "I2C5_SCL"),
+		MA35_MUX(0x6, "SD0_DAT3/eMMC0_DAT3")),
+	MA35_PIN(38, PC6, 0x90, 0x18,
+		MA35_MUX(0x0, "GPC6"),
+		MA35_MUX(0x3, "CAN1_RXD"),
+		MA35_MUX(0x6, "SD0_nCD")),
+	MA35_PIN(39, PC7, 0x90, 0x1c,
+		MA35_MUX(0x0, "GPC7"),
+		MA35_MUX(0x3, "CAN1_TXD"),
+		MA35_MUX(0x6, "SD0_WP")),
+	MA35_PIN(40, PC12, 0x94, 0x10,
+		MA35_MUX(0x0, "GPC12"),
+		MA35_MUX(0x2, "UART12_nCTS"),
+		MA35_MUX(0x3, "UART11_RXD"),
+		MA35_MUX(0x6, "LCM_DATA16")),
+	MA35_PIN(41, PC13, 0x94, 0x14,
+		MA35_MUX(0x0, "GPC13"),
+		MA35_MUX(0x2, "UART12_nRTS"),
+		MA35_MUX(0x3, "UART11_TXD"),
+		MA35_MUX(0x6, "LCM_DATA17")),
+	MA35_PIN(42, PC14, 0x94, 0x18,
+		MA35_MUX(0x0, "GPC14"),
+		MA35_MUX(0x2, "UART12_RXD"),
+		MA35_MUX(0x6, "LCM_DATA18")),
+	MA35_PIN(43, PC15, 0x94, 0x1c,
+		MA35_MUX(0x0, "GPC15"),
+		MA35_MUX(0x2, "UART12_TXD"),
+		MA35_MUX(0x6, "LCM_DATA19"),
+		MA35_MUX(0x7, "LCM_MPU_TE"),
+		MA35_MUX(0x8, "LCM_MPU_VSYNC")),
+	MA35_PIN(44, PD0, 0x98, 0x0,
+		MA35_MUX(0x0, "GPD0"),
+		MA35_MUX(0x2, "UART3_nCTS"),
+		MA35_MUX(0x3, "UART4_RXD"),
+		MA35_MUX(0x5, "QSPI0_SS0")),
+	MA35_PIN(45, PD1, 0x98, 0x4,
+		MA35_MUX(0x0, "GPD1"),
+		MA35_MUX(0x2, "UART3_nRTS"),
+		MA35_MUX(0x3, "UART4_TXD"),
+		MA35_MUX(0x5, "QSPI0_CLK")),
+	MA35_PIN(46, PD2, 0x98, 0x8,
+		MA35_MUX(0x0, "GPD2"),
+		MA35_MUX(0x2, "UART3_RXD"),
+		MA35_MUX(0x5, "QSPI0_MOSI0")),
+	MA35_PIN(47, PD3, 0x98, 0xc,
+		MA35_MUX(0x0, "GPD3"),
+		MA35_MUX(0x2, "UART3_TXD"),
+		MA35_MUX(0x5, "QSPI0_MISO0")),
+	MA35_PIN(48, PD4, 0x98, 0x10,
+		MA35_MUX(0x0, "GPD4"),
+		MA35_MUX(0x2, "UART1_nCTS"),
+		MA35_MUX(0x3, "UART2_RXD"),
+		MA35_MUX(0x4, "I2C2_SDA"),
+		MA35_MUX(0x5, "QSPI0_MOSI1")),
+	MA35_PIN(49, PD5, 0x98, 0x14,
+		MA35_MUX(0x0, "GPD5"),
+		MA35_MUX(0x2, "UART1_nRTS"),
+		MA35_MUX(0x3, "UART2_TXD"),
+		MA35_MUX(0x4, "I2C2_SCL"),
+		MA35_MUX(0x5, "QSPI0_MISO1")),
+	MA35_PIN(50, PD6, 0x98, 0x18,
+		MA35_MUX(0x0, "GPD6"),
+		MA35_MUX(0x1, "EPWM0_SYNC_IN"),
+		MA35_MUX(0x2, "UART1_RXD"),
+		MA35_MUX(0x5, "QSPI1_MOSI1"),
+		MA35_MUX(0x6, "I2C0_SDA"),
+		MA35_MUX(0x7, "I2S0_MCLK"),
+		MA35_MUX(0x8, "EPWM0_CH0"),
+		MA35_MUX(0x9, "EBI_AD5"),
+		MA35_MUX(0xa, "SPI3_SS1"),
+		MA35_MUX(0xb, "TRACE_CLK")),
+	MA35_PIN(51, PD7, 0x98, 0x1c,
+		MA35_MUX(0x0, "GPD7"),
+		MA35_MUX(0x1, "EPWM0_SYNC_OUT"),
+		MA35_MUX(0x2, "UART1_TXD"),
+		MA35_MUX(0x5, "QSPI1_MISO1"),
+		MA35_MUX(0x6, "I2C0_SCL"),
+		MA35_MUX(0x7, "I2S1_MCLK"),
+		MA35_MUX(0x8, "EPWM0_CH1"),
+		MA35_MUX(0x9, "EBI_AD6"),
+		MA35_MUX(0xa, "SC1_nCD"),
+		MA35_MUX(0xb, "EADC0_ST")),
+	MA35_PIN(52, PD8, 0x9c, 0x0,
+		MA35_MUX(0x0, "GPD8"),
+		MA35_MUX(0x1, "EPWM0_BRAKE0"),
+		MA35_MUX(0x2, "UART16_nCTS"),
+		MA35_MUX(0x3, "UART15_RXD"),
+		MA35_MUX(0x5, "QSPI1_SS0"),
+		MA35_MUX(0x7, "I2S1_LRCK"),
+		MA35_MUX(0x8, "EPWM0_CH2"),
+		MA35_MUX(0x9, "EBI_AD7"),
+		MA35_MUX(0xa, "SC1_CLK"),
+		MA35_MUX(0xb, "TM0")),
+	MA35_PIN(53, PD9, 0x9c, 0x4,
+		MA35_MUX(0x0, "GPD9"),
+		MA35_MUX(0x1, "EPWM0_BRAKE1"),
+		MA35_MUX(0x2, "UART16_nRTS"),
+		MA35_MUX(0x3, "UART15_TXD"),
+		MA35_MUX(0x5, "QSPI1_CLK"),
+		MA35_MUX(0x7, "I2S1_BCLK"),
+		MA35_MUX(0x8, "EPWM0_CH3"),
+		MA35_MUX(0x9, "EBI_AD8"),
+		MA35_MUX(0xa, "SC1_DAT"),
+		MA35_MUX(0xb, "TM0_EXT")),
+	MA35_PIN(54, PD10, 0x9c, 0x8,
+		MA35_MUX(0x0, "GPD10"),
+		MA35_MUX(0x1, "EPWM1_BRAKE0"),
+		MA35_MUX(0x2, "UART16_RXD"),
+		MA35_MUX(0x5, "QSPI1_MOSI0"),
+		MA35_MUX(0x7, "I2S1_DI"),
+		MA35_MUX(0x8, "EPWM0_CH4"),
+		MA35_MUX(0x9, "EBI_AD9"),
+		MA35_MUX(0xa, "SC1_RST"),
+		MA35_MUX(0xb, "TM2")),
+	MA35_PIN(55, PD11, 0x9c, 0xc,
+		MA35_MUX(0x0, "GPD11"),
+		MA35_MUX(0x1, "EPWM1_BRAKE1"),
+		MA35_MUX(0x2, "UART16_TXD"),
+		MA35_MUX(0x5, "QSPI1_MISO0"),
+		MA35_MUX(0x7, "I2S1_DO"),
+		MA35_MUX(0x8, "EPWM0_CH5"),
+		MA35_MUX(0x9, "EBI_AD10"),
+		MA35_MUX(0xa, "SC1_PWR"),
+		MA35_MUX(0xb, "TM2_EXT")),
+	MA35_PIN(56, PD12, 0x9c, 0x10,
+		MA35_MUX(0x0, "GPD12"),
+		MA35_MUX(0x1, "EPWM0_BRAKE0"),
+		MA35_MUX(0x2, "UART11_TXD"),
+		MA35_MUX(0x3, "UART10_RXD"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x6, "TRACE_DATA0"),
+		MA35_MUX(0x7, "EBI_nCS1"),
+		MA35_MUX(0x8, "EBI_AD4"),
+		MA35_MUX(0x9, "QEI0_INDEX"),
+		MA35_MUX(0xb, "TM5"),
+		MA35_MUX(0xc, "I2S1_LRCK"),
+		MA35_MUX(0xd, "INT1")),
+	MA35_PIN(57, PD13, 0x9c, 0x14,
+		MA35_MUX(0x0, "GPD13"),
+		MA35_MUX(0x1, "EPWM0_BRAKE1"),
+		MA35_MUX(0x2, "UART11_RXD"),
+		MA35_MUX(0x3, "UART10_TXD"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x6, "TRACE_DATA1"),
+		MA35_MUX(0x7, "EBI_nCS2"),
+		MA35_MUX(0x8, "EBI_AD5"),
+		MA35_MUX(0x9, "ECAP0_IC0"),
+		MA35_MUX(0xb, "TM5_EXT"),
+		MA35_MUX(0xc, "I2S1_BCLK")),
+	MA35_PIN(58, PD14, 0x9c, 0x18,
+		MA35_MUX(0x0, "GPD14"),
+		MA35_MUX(0x1, "EPWM0_SYNC_IN"),
+		MA35_MUX(0x2, "UART11_nCTS"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x6, "TRACE_DATA2"),
+		MA35_MUX(0x7, "EBI_MCLK"),
+		MA35_MUX(0x8, "EBI_AD6"),
+		MA35_MUX(0x9, "ECAP0_IC1"),
+		MA35_MUX(0xb, "TM6"),
+		MA35_MUX(0xc, "I2S1_DI"),
+		MA35_MUX(0xd, "INT3")),
+	MA35_PIN(59, PD15, 0x9c, 0x1c,
+		MA35_MUX(0x0, "GPD15"),
+		MA35_MUX(0x1, "EPWM0_SYNC_OUT"),
+		MA35_MUX(0x2, "UART11_nRTS"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x6, "TRACE_DATA3"),
+		MA35_MUX(0x7, "EBI_ALE"),
+		MA35_MUX(0x8, "EBI_AD7"),
+		MA35_MUX(0x9, "ECAP0_IC2"),
+		MA35_MUX(0xb, "TM6_EXT"),
+		MA35_MUX(0xc, "I2S1_DO")),
+	MA35_PIN(60, PE0, 0xa0, 0x0,
+		MA35_MUX(0x0, "GPE0"),
+		MA35_MUX(0x2, "UART9_nCTS"),
+		MA35_MUX(0x3, "UART8_RXD"),
+		MA35_MUX(0x7, "CCAP1_DATA0"),
+		MA35_MUX(0x8, "RGMII0_MDC"),
+		MA35_MUX(0x9, "RMII0_MDC")),
+	MA35_PIN(61, PE1, 0xa0, 0x4,
+		MA35_MUX(0x0, "GPE1"),
+		MA35_MUX(0x2, "UART9_nRTS"),
+		MA35_MUX(0x3, "UART8_TXD"),
+		MA35_MUX(0x7, "CCAP1_DATA1"),
+		MA35_MUX(0x8, "RGMII0_MDIO"),
+		MA35_MUX(0x9, "RMII0_MDIO")),
+	MA35_PIN(62, PE2, 0xa0, 0x8,
+		MA35_MUX(0x0, "GPE2"),
+		MA35_MUX(0x2, "UART9_RXD"),
+		MA35_MUX(0x7, "CCAP1_DATA2"),
+		MA35_MUX(0x8, "RGMII0_TXCTL"),
+		MA35_MUX(0x9, "RMII0_TXEN")),
+	MA35_PIN(63, PE3, 0xa0, 0xc,
+		MA35_MUX(0x0, "GPE3"),
+		MA35_MUX(0x2, "UART9_TXD"),
+		MA35_MUX(0x7, "CCAP1_DATA3"),
+		MA35_MUX(0x8, "RGMII0_TXD0"),
+		MA35_MUX(0x9, "RMII0_TXD0")),
+	MA35_PIN(64, PE4, 0xa0, 0x10,
+		MA35_MUX(0x0, "GPE4"),
+		MA35_MUX(0x2, "UART4_nCTS"),
+		MA35_MUX(0x3, "UART3_RXD"),
+		MA35_MUX(0x7, "CCAP1_DATA4"),
+		MA35_MUX(0x8, "RGMII0_TXD1"),
+		MA35_MUX(0x9, "RMII0_TXD1")),
+	MA35_PIN(65, PE5, 0xa0, 0x14,
+		MA35_MUX(0x0, "GPE5"),
+		MA35_MUX(0x2, "UART4_nRTS"),
+		MA35_MUX(0x3, "UART3_TXD"),
+		MA35_MUX(0x7, "CCAP1_DATA5"),
+		MA35_MUX(0x8, "RGMII0_RXCLK"),
+		MA35_MUX(0x9, "RMII0_REFCLK")),
+	MA35_PIN(66, PE6, 0xa0, 0x18,
+		MA35_MUX(0x0, "GPE6"),
+		MA35_MUX(0x2, "UART4_RXD"),
+		MA35_MUX(0x7, "CCAP1_DATA6"),
+		MA35_MUX(0x8, "RGMII0_RXCTL"),
+		MA35_MUX(0x9, "RMII0_CRSDV")),
+	MA35_PIN(67, PE7, 0xa0, 0x1c,
+		MA35_MUX(0x0, "GPE7"),
+		MA35_MUX(0x2, "UART4_TXD"),
+		MA35_MUX(0x7, "CCAP1_DATA7"),
+		MA35_MUX(0x8, "RGMII0_RXD0"),
+		MA35_MUX(0x9, "RMII0_RXD0")),
+	MA35_PIN(68, PE8, 0xa4, 0x0,
+		MA35_MUX(0x0, "GPE8"),
+		MA35_MUX(0x2, "UART13_nCTS"),
+		MA35_MUX(0x3, "UART12_RXD"),
+		MA35_MUX(0x7, "CCAP1_SCLK"),
+		MA35_MUX(0x8, "RGMII0_RXD1"),
+		MA35_MUX(0x9, "RMII0_RXD1")),
+	MA35_PIN(69, PE9, 0xa4, 0x4,
+		MA35_MUX(0x0, "GPE9"),
+		MA35_MUX(0x2, "UART13_nRTS"),
+		MA35_MUX(0x3, "UART12_TXD"),
+		MA35_MUX(0x7, "CCAP1_PIXCLK"),
+		MA35_MUX(0x8, "RGMII0_RXD2"),
+		MA35_MUX(0x9, "RMII0_RXERR")),
+	MA35_PIN(70, PE10, 0xa4, 0x8,
+		MA35_MUX(0x0, "GPE10"),
+		MA35_MUX(0x2, "UART15_nCTS"),
+		MA35_MUX(0x3, "UART14_RXD"),
+		MA35_MUX(0x5, "SPI1_SS0"),
+		MA35_MUX(0x7, "CCAP1_HSYNC"),
+		MA35_MUX(0x8, "RGMII0_RXD3")),
+	MA35_PIN(71, PE11, 0xa4, 0xc,
+		MA35_MUX(0x0, "GPE11"),
+		MA35_MUX(0x2, "UART15_nRTS"),
+		MA35_MUX(0x3, "UART14_TXD"),
+		MA35_MUX(0x5, "SPI1_CLK"),
+		MA35_MUX(0x7, "CCAP1_VSYNC"),
+		MA35_MUX(0x8, "RGMII0_TXCLK")),
+	MA35_PIN(72, PE12, 0xa4, 0x10,
+		MA35_MUX(0x0, "GPE12"),
+		MA35_MUX(0x2, "UART15_RXD"),
+		MA35_MUX(0x5, "SPI1_MOSI"),
+		MA35_MUX(0x7, "CCAP1_DATA8"),
+		MA35_MUX(0x8, "RGMII0_TXD2")),
+	MA35_PIN(73, PE13, 0xa4, 0x14,
+		MA35_MUX(0x0, "GPE13"),
+		MA35_MUX(0x2, "UART15_TXD"),
+		MA35_MUX(0x5, "SPI1_MISO"),
+		MA35_MUX(0x7, "CCAP1_DATA9"),
+		MA35_MUX(0x8, "RGMII0_TXD3")),
+	MA35_PIN(74, PE14, 0xa4, 0x18,
+		MA35_MUX(0x0, "GPE14"),
+		MA35_MUX(0x1, "UART0_TXD")),
+	MA35_PIN(75, PE15, 0xa4, 0x1c,
+		MA35_MUX(0x0, "GPE15"),
+		MA35_MUX(0x1, "UART0_RXD")),
+	MA35_PIN(76, PF0, 0xa8, 0x0,
+		MA35_MUX(0x0, "GPF0"),
+		MA35_MUX(0x2, "UART2_nCTS"),
+		MA35_MUX(0x3, "UART1_RXD"),
+		MA35_MUX(0x6, "RGMII0_RXD3"),
+		MA35_MUX(0x8, "RGMII1_MDC"),
+		MA35_MUX(0x9, "RMII1_MDC"),
+		MA35_MUX(0xe, "KPI_COL0")),
+	MA35_PIN(77, PF1, 0xa8, 0x4,
+		MA35_MUX(0x0, "GPF1"),
+		MA35_MUX(0x2, "UART2_nRTS"),
+		MA35_MUX(0x3, "UART1_TXD"),
+		MA35_MUX(0x6, "RGMII0_TXCLK"),
+		MA35_MUX(0x8, "RGMII1_MDIO"),
+		MA35_MUX(0x9, "RMII1_MDIO"),
+		MA35_MUX(0xe, "KPI_COL1")),
+	MA35_PIN(78, PF2, 0xa8, 0x8,
+		MA35_MUX(0x0, "GPF2"),
+		MA35_MUX(0x2, "UART2_RXD"),
+		MA35_MUX(0x6, "RGMII0_TXD2"),
+		MA35_MUX(0x8, "RGMII1_TXCTL"),
+		MA35_MUX(0x9, "RMII1_TXEN"),
+		MA35_MUX(0xe, "KPI_COL2")),
+	MA35_PIN(79, PF3, 0xa8, 0xc,
+		MA35_MUX(0x0, "GPF3"),
+		MA35_MUX(0x2, "UART2_TXD"),
+		MA35_MUX(0x6, "RGMII0_TXD3"),
+		MA35_MUX(0x8, "RGMII1_TXD0"),
+		MA35_MUX(0x9, "RMII1_TXD0"),
+		MA35_MUX(0xe, "KPI_COL3")),
+	MA35_PIN(80, PF4, 0xa8, 0x10,
+		MA35_MUX(0x0, "GPF4"),
+		MA35_MUX(0x2, "UART11_nCTS"),
+		MA35_MUX(0x3, "UART10_RXD"),
+		MA35_MUX(0x4, "I2S0_LRCK"),
+		MA35_MUX(0x5, "SPI1_SS0"),
+		MA35_MUX(0x8, "RGMII1_TXD1"),
+		MA35_MUX(0x9, "RMII1_TXD1"),
+		MA35_MUX(0xd, "CAN2_RXD"),
+		MA35_MUX(0xe, "KPI_ROW0")),
+	MA35_PIN(81, PF5, 0xa8, 0x14,
+		MA35_MUX(0x0, "GPF5"),
+		MA35_MUX(0x2, "UART11_nRTS"),
+		MA35_MUX(0x3, "UART10_TXD"),
+		MA35_MUX(0x4, "I2S0_BCLK"),
+		MA35_MUX(0x5, "SPI1_CLK"),
+		MA35_MUX(0x8, "RGMII1_RXCLK"),
+		MA35_MUX(0x9, "RMII1_REFCLK"),
+		MA35_MUX(0xd, "CAN2_TXD"),
+		MA35_MUX(0xe, "KPI_ROW1")),
+	MA35_PIN(82, PF6, 0xa8, 0x18,
+		MA35_MUX(0x0, "GPF6"),
+		MA35_MUX(0x2, "UART11_RXD"),
+		MA35_MUX(0x4, "I2S0_DI"),
+		MA35_MUX(0x5, "SPI1_MOSI"),
+		MA35_MUX(0x8, "RGMII1_RXCTL"),
+		MA35_MUX(0x9, "RMII1_CRSDV"),
+		MA35_MUX(0xa, "I2C4_SDA"),
+		MA35_MUX(0xd, "SC0_CLK"),
+		MA35_MUX(0xe, "KPI_ROW2")),
+	MA35_PIN(83, PF7, 0xa8, 0x1c,
+		MA35_MUX(0x0, "GPF7"),
+		MA35_MUX(0x2, "UART11_TXD"),
+		MA35_MUX(0x4, "I2S0_DO"),
+		MA35_MUX(0x5, "SPI1_MISO"),
+		MA35_MUX(0x8, "RGMII1_RXD0"),
+		MA35_MUX(0x9, "RMII1_RXD0"),
+		MA35_MUX(0xa, "I2C4_SCL"),
+		MA35_MUX(0xd, "SC0_DAT"),
+		MA35_MUX(0xe, "KPI_ROW3")),
+	MA35_PIN(84, PF8, 0xac, 0x0,
+		MA35_MUX(0x0, "GPF8"),
+		MA35_MUX(0x2, "UART13_RXD"),
+		MA35_MUX(0x4, "I2C5_SDA"),
+		MA35_MUX(0x5, "SPI0_SS0"),
+		MA35_MUX(0x8, "RGMII1_RXD1"),
+		MA35_MUX(0x9, "RMII1_RXD1"),
+		MA35_MUX(0xd, "SC0_RST"),
+		MA35_MUX(0xe, "KPI_COL4")),
+	MA35_PIN(85, PF9, 0xac, 0x4,
+		MA35_MUX(0x0, "GPF9"),
+		MA35_MUX(0x2, "UART13_TXD"),
+		MA35_MUX(0x4, "I2C5_SCL"),
+		MA35_MUX(0x5, "SPI0_SS1"),
+		MA35_MUX(0x8, "RGMII1_RXD2"),
+		MA35_MUX(0x9, "RMII1_RXERR"),
+		MA35_MUX(0xd, "SC0_PWR"),
+		MA35_MUX(0xe, "KPI_COL5")),
+	MA35_PIN(86, PF10, 0xac, 0x8,
+		MA35_MUX(0x0, "GPF10"),
+		MA35_MUX(0x2, "UART13_nCTS"),
+		MA35_MUX(0x5, "I2S0_LRCK"),
+		MA35_MUX(0x6, "SPI1_SS0"),
+		MA35_MUX(0x8, "RGMII1_RXD3"),
+		MA35_MUX(0x9, "SC0_CLK"),
+		MA35_MUX(0xe, "KPI_COL6")),
+	MA35_PIN(87, PF11, 0xac, 0xc,
+		MA35_MUX(0x0, "GPF11"),
+		MA35_MUX(0x2, "UART13_nRTS"),
+		MA35_MUX(0x5, "I2S0_BCLK"),
+		MA35_MUX(0x6, "SPI1_CLK"),
+		MA35_MUX(0x8, "RGMII1_TXCLK"),
+		MA35_MUX(0x9, "SC0_DAT"),
+		MA35_MUX(0xe, "KPI_COL7")),
+	MA35_PIN(88, PF12, 0xac, 0x10,
+		MA35_MUX(0x0, "GPF12"),
+		MA35_MUX(0x5, "I2S0_DI"),
+		MA35_MUX(0x6, "SPI1_MOSI"),
+		MA35_MUX(0x8, "RGMII1_TXD2"),
+		MA35_MUX(0x9, "SC0_RST"),
+		MA35_MUX(0xe, "KPI_ROW4")),
+	MA35_PIN(89, PF13, 0xac, 0x14,
+		MA35_MUX(0x0, "GPF13"),
+		MA35_MUX(0x5, "I2S0_DO"),
+		MA35_MUX(0x6, "SPI1_MISO"),
+		MA35_MUX(0x8, "RGMII1_TXD3"),
+		MA35_MUX(0x9, "SC0_PWR"),
+		MA35_MUX(0xe, "KPI_ROW5")),
+	MA35_PIN(90, PF14, 0xac, 0x18,
+		MA35_MUX(0x0, "GPF14"),
+		MA35_MUX(0x1, "EPWM2_BRAKE0"),
+		MA35_MUX(0x2, "EADC0_ST"),
+		MA35_MUX(0x3, "RGMII1_PPS"),
+		MA35_MUX(0x4, "RMII1_PPS"),
+		MA35_MUX(0x5, "SPI0_I2SMCLK"),
+		MA35_MUX(0x6, "SPI1_I2SMCLK"),
+		MA35_MUX(0x7, "CCAP1_SFIELD"),
+		MA35_MUX(0x8, "RGMII0_PPS"),
+		MA35_MUX(0x9, "RMII0_PPS"),
+		MA35_MUX(0xb, "TM0"),
+		MA35_MUX(0xc, "INT0"),
+		MA35_MUX(0xd, "SPI1_SS1"),
+		MA35_MUX(0xe, "QEI2_INDEX"),
+		MA35_MUX(0xf, "I2S0_MCLK")),
+	MA35_PIN(91, PF15, 0xac, 0x1c,
+		MA35_MUX(0x0, "GPF15"),
+		MA35_MUX(0x1, "HSUSB0_VBUSVLD")),
+	MA35_PIN(92, PG0, 0xb0, 0x0,
+		MA35_MUX(0x0, "GPG0"),
+		MA35_MUX(0x1, "EPWM0_CH0"),
+		MA35_MUX(0x2, "UART7_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x5, "SPI0_SS0"),
+		MA35_MUX(0x6, "EADC0_ST"),
+		MA35_MUX(0x7, "EBI_AD15"),
+		MA35_MUX(0x9, "I2S1_MCLK"),
+		MA35_MUX(0xa, "QEI0_INDEX"),
+		MA35_MUX(0xb, "TM1"),
+		MA35_MUX(0xc, "CLKO"),
+		MA35_MUX(0xd, "INT0"),
+		MA35_MUX(0xf, "EBI_ADR15")),
+	MA35_PIN(93, PG1, 0xb0, 0x4,
+		MA35_MUX(0x0, "GPG1"),
+		MA35_MUX(0x1, "EPWM0_CH3"),
+		MA35_MUX(0x2, "UART9_nRTS"),
+		MA35_MUX(0x3, "UART6_TXD"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x5, "CAN2_TXD"),
+		MA35_MUX(0x7, "EBI_nCS0"),
+		MA35_MUX(0x9, "QEI0_B"),
+		MA35_MUX(0xb, "TM1_EXT"),
+		MA35_MUX(0xe, "RGMII1_PPS"),
+		MA35_MUX(0xf, "RMII1_PPS")),
+	MA35_PIN(94, PG2, 0xb0, 0x8,
+		MA35_MUX(0x0, "GPG2"),
+		MA35_MUX(0x1, "EPWM0_CH4"),
+		MA35_MUX(0x2, "UART9_RXD"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x5, "SPI0_SS1"),
+		MA35_MUX(0x7, "EBI_ADR16"),
+		MA35_MUX(0x8, "EBI_nCS2"),
+		MA35_MUX(0xa, "QEI0_A"),
+		MA35_MUX(0xb, "TM3"),
+		MA35_MUX(0xd, "INT1")),
+	MA35_PIN(95, PG3, 0xb0, 0xc,
+		MA35_MUX(0x0, "GPG3"),
+		MA35_MUX(0x1, "EPWM0_CH5"),
+		MA35_MUX(0x2, "UART9_TXD"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x5, "SPI0_I2SMCLK"),
+		MA35_MUX(0x7, "EBI_ADR17"),
+		MA35_MUX(0x8, "EBI_nCS1"),
+		MA35_MUX(0x9, "EBI_MCLK"),
+		MA35_MUX(0xa, "QEI0_B"),
+		MA35_MUX(0xb, "TM3_EXT"),
+		MA35_MUX(0xc, "I2S1_MCLK")),
+	MA35_PIN(96, PG4, 0xb0, 0x10,
+		MA35_MUX(0x0, "GPG4"),
+		MA35_MUX(0x1, "EPWM1_CH0"),
+		MA35_MUX(0x2, "UART5_nCTS"),
+		MA35_MUX(0x3, "UART6_RXD"),
+		MA35_MUX(0x5, "SPI3_SS0"),
+		MA35_MUX(0x6, "QEI1_INDEX"),
+		MA35_MUX(0x7, "EBI_ADR18"),
+		MA35_MUX(0x8, "EBI_nCS0"),
+		MA35_MUX(0x9, "I2S1_DO"),
+		MA35_MUX(0xa, "SC1_CLK"),
+		MA35_MUX(0xb, "TM4"),
+		MA35_MUX(0xd, "INT2"),
+		MA35_MUX(0xe, "ECAP1_IC2")),
+	MA35_PIN(97, PG5, 0xb0, 0x14,
+		MA35_MUX(0x0, "GPG5"),
+		MA35_MUX(0x1, "EPWM1_CH1"),
+		MA35_MUX(0x2, "UART5_nRTS"),
+		MA35_MUX(0x3, "UART6_TXD"),
+		MA35_MUX(0x5, "SPI3_CLK"),
+		MA35_MUX(0x6, "ECAP0_IC0"),
+		MA35_MUX(0x7, "EBI_ADR19"),
+		MA35_MUX(0x8, "EBI_ALE"),
+		MA35_MUX(0x9, "I2S1_DI"),
+		MA35_MUX(0xa, "SC1_DAT"),
+		MA35_MUX(0xb, "TM4_EXT")),
+	MA35_PIN(98, PG6, 0xb0, 0x18,
+		MA35_MUX(0x0, "GPG6"),
+		MA35_MUX(0x1, "EPWM1_CH2"),
+		MA35_MUX(0x2, "UART5_RXD"),
+		MA35_MUX(0x3, "CAN1_RXD"),
+		MA35_MUX(0x5, "SPI3_MOSI"),
+		MA35_MUX(0x6, "ECAP0_IC1"),
+		MA35_MUX(0x7, "EBI_nRD"),
+		MA35_MUX(0x9, "I2S1_BCLK"),
+		MA35_MUX(0xa, "SC1_RST"),
+		MA35_MUX(0xb, "TM7"),
+		MA35_MUX(0xd, "INT3")),
+	MA35_PIN(99, PG7, 0xb0, 0x1c,
+		MA35_MUX(0x0, "GPG7"),
+		MA35_MUX(0x1, "EPWM1_CH3"),
+		MA35_MUX(0x2, "UART5_TXD"),
+		MA35_MUX(0x3, "CAN1_TXD"),
+		MA35_MUX(0x5, "SPI3_MISO"),
+		MA35_MUX(0x6, "ECAP0_IC2"),
+		MA35_MUX(0x7, "EBI_nWR"),
+		MA35_MUX(0x9, "I2S1_LRCK"),
+		MA35_MUX(0xa, "SC1_PWR"),
+		MA35_MUX(0xb, "TM7_EXT")),
+	MA35_PIN(100, PG8, 0xb4, 0x0,
+		MA35_MUX(0x0, "GPG8"),
+		MA35_MUX(0x1, "EPWM1_CH4"),
+		MA35_MUX(0x2, "UART12_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x5, "SPI2_SS0"),
+		MA35_MUX(0x6, "LCM_VSYNC"),
+		MA35_MUX(0x7, "I2C3_SDA"),
+		MA35_MUX(0xc, "EBI_AD7"),
+		MA35_MUX(0xd, "EBI_nCS0")),
+	MA35_PIN(101, PG9, 0xb4, 0x4,
+		MA35_MUX(0x0, "GPG9"),
+		MA35_MUX(0x1, "EPWM1_CH5"),
+		MA35_MUX(0x2, "UART12_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x5, "SPI2_CLK"),
+		MA35_MUX(0x6, "LCM_HSYNC"),
+		MA35_MUX(0x7, "I2C3_SCL"),
+		MA35_MUX(0xc, "EBI_AD8"),
+		MA35_MUX(0xd, "EBI_nCS1")),
+	MA35_PIN(102, PG10, 0xb4, 0x8,
+		MA35_MUX(0x0, "GPG10"),
+		MA35_MUX(0x2, "UART12_nRTS"),
+		MA35_MUX(0x3, "UART13_TXD"),
+		MA35_MUX(0x5, "SPI2_MOSI"),
+		MA35_MUX(0x6, "LCM_CLK"),
+		MA35_MUX(0xc, "EBI_AD9"),
+		MA35_MUX(0xd, "EBI_nWRH")),
+	MA35_PIN(103, PG11, 0xb4, 0xc,
+		MA35_MUX(0x0, "GPG11"),
+		MA35_MUX(0x3, "JTAG_TDO"),
+		MA35_MUX(0x5, "I2S0_MCLK"),
+		MA35_MUX(0x6, "NAND_RDY1"),
+		MA35_MUX(0x7, "EBI_nWRH"),
+		MA35_MUX(0x8, "EBI_nCS1"),
+		MA35_MUX(0xa, "EBI_AD0")),
+	MA35_PIN(104, PG12, 0xb4, 0x10,
+		MA35_MUX(0x0, "GPG12"),
+		MA35_MUX(0x3, "JTAG_TCK/SW_CLK"),
+		MA35_MUX(0x5, "I2S0_LRCK"),
+		MA35_MUX(0x7, "EBI_nWRL"),
+		MA35_MUX(0xa, "EBI_AD1")),
+	MA35_PIN(105, PG13, 0xb4, 0x14,
+		MA35_MUX(0x0, "GPG13"),
+		MA35_MUX(0x3, "JTAG_TMS/SW_DIO"),
+		MA35_MUX(0x5, "I2S0_BCLK"),
+		MA35_MUX(0x7, "EBI_MCLK"),
+		MA35_MUX(0xa, "EBI_AD2")),
+	MA35_PIN(106, PG14, 0xb4, 0x18,
+		MA35_MUX(0x0, "GPG14"),
+		MA35_MUX(0x3, "JTAG_TDI"),
+		MA35_MUX(0x5, "I2S0_DI"),
+		MA35_MUX(0x6, "NAND_nCS1"),
+		MA35_MUX(0x7, "EBI_ALE"),
+		MA35_MUX(0xa, "EBI_AD3")),
+	MA35_PIN(107, PG15, 0xb4, 0x1c,
+		MA35_MUX(0x0, "GPG15"),
+		MA35_MUX(0x3, "JTAG_nTRST"),
+		MA35_MUX(0x5, "I2S0_DO"),
+		MA35_MUX(0x7, "EBI_nCS0"),
+		MA35_MUX(0xa, "EBI_AD4")),
+	MA35_PIN(108, PH0, 0xb8, 0x0,
+		MA35_MUX(0x0, "GPH0"),
+		MA35_MUX(0x2, "UART8_nCTS"),
+		MA35_MUX(0x3, "UART7_RXD"),
+		MA35_MUX(0x6, "LCM_DATA8")),
+	MA35_PIN(109, PH1, 0xb8, 0x4,
+		MA35_MUX(0x0, "GPH1"),
+		MA35_MUX(0x2, "UART8_nRTS"),
+		MA35_MUX(0x3, "UART7_TXD"),
+		MA35_MUX(0x6, "LCM_DATA9")),
+	MA35_PIN(110, PH2, 0xb8, 0x8,
+		MA35_MUX(0x0, "GPH2"),
+		MA35_MUX(0x2, "UART8_RXD"),
+		MA35_MUX(0x6, "LCM_DATA10")),
+	MA35_PIN(111, PH3, 0xb8, 0xc,
+		MA35_MUX(0x0, "GPH3"),
+		MA35_MUX(0x2, "UART8_TXD"),
+		MA35_MUX(0x6, "LCM_DATA11")),
+	MA35_PIN(112, PH4, 0xb8, 0x10,
+		MA35_MUX(0x0, "GPH4"),
+		MA35_MUX(0x2, "UART10_nCTS"),
+		MA35_MUX(0x3, "UART9_RXD"),
+		MA35_MUX(0x6, "LCM_DATA12")),
+	MA35_PIN(113, PH5, 0xb8, 0x14,
+		MA35_MUX(0x0, "GPH5"),
+		MA35_MUX(0x2, "UART10_nRTS"),
+		MA35_MUX(0x3, "UART9_TXD"),
+		MA35_MUX(0x6, "LCM_DATA13")),
+	MA35_PIN(114, PH6, 0xb8, 0x18,
+		MA35_MUX(0x0, "GPH6"),
+		MA35_MUX(0x2, "UART10_RXD"),
+		MA35_MUX(0x6, "LCM_DATA14")),
+	MA35_PIN(115, PH7, 0xb8, 0x1c,
+		MA35_MUX(0x0, "GPH7"),
+		MA35_MUX(0x2, "UART10_TXD"),
+		MA35_MUX(0x6, "LCM_DATA15")),
+	MA35_PIN(116, PH8, 0xbc, 0x0,
+		MA35_MUX(0x0, "GPH8"),
+		MA35_MUX(0x6, "TAMPER0")),
+	MA35_PIN(117, PH9, 0xbc, 0x4,
+		MA35_MUX(0x0, "GPH9"),
+		MA35_MUX(0x4, "CLK_32KOUT"),
+		MA35_MUX(0x6, "TAMPER1")),
+	MA35_PIN(118, PH12, 0xbc, 0x10,
+		MA35_MUX(0x0, "GPH12"),
+		MA35_MUX(0x2, "UART14_nCTS"),
+		MA35_MUX(0x3, "UART13_RXD"),
+		MA35_MUX(0x6, "LCM_DATA20")),
+	MA35_PIN(119, PH13, 0xbc, 0x14,
+		MA35_MUX(0x0, "GPH13"),
+		MA35_MUX(0x2, "UART14_nRTS"),
+		MA35_MUX(0x3, "UART13_TXD"),
+		MA35_MUX(0x6, "LCM_DATA21")),
+	MA35_PIN(120, PH14, 0xbc, 0x18,
+		MA35_MUX(0x0, "GPH14"),
+		MA35_MUX(0x2, "UART14_RXD"),
+		MA35_MUX(0x6, "LCM_DATA22")),
+	MA35_PIN(121, PH15, 0xbc, 0x1c,
+		MA35_MUX(0x0, "GPH15"),
+		MA35_MUX(0x2, "UART14_TXD"),
+		MA35_MUX(0x6, "LCM_DATA23")),
+	MA35_PIN(122, PI0, 0xc0, 0x0,
+		MA35_MUX(0x0, "GPI0"),
+		MA35_MUX(0x1, "EPWM0_CH0"),
+		MA35_MUX(0x2, "UART12_nCTS"),
+		MA35_MUX(0x3, "UART11_RXD"),
+		MA35_MUX(0x4, "I2C2_SDA"),
+		MA35_MUX(0x5, "SPI3_SS0"),
+		MA35_MUX(0x7, "SC0_nCD"),
+		MA35_MUX(0x8, "EBI_ADR0"),
+		MA35_MUX(0xb, "TM0"),
+		MA35_MUX(0xc, "ECAP1_IC0")),
+	MA35_PIN(123, PI1, 0xc0, 0x4,
+		MA35_MUX(0x0, "GPI1"),
+		MA35_MUX(0x1, "EPWM0_CH1"),
+		MA35_MUX(0x2, "UART12_nRTS"),
+		MA35_MUX(0x3, "UART11_TXD"),
+		MA35_MUX(0x4, "I2C2_SCL"),
+		MA35_MUX(0x5, "SPI3_CLK"),
+		MA35_MUX(0x7, "SC0_CLK"),
+		MA35_MUX(0x8, "EBI_ADR1"),
+		MA35_MUX(0xb, "TM0_EXT"),
+		MA35_MUX(0xc, "ECAP1_IC1")),
+	MA35_PIN(124, PI2, 0xc0, 0x8,
+		MA35_MUX(0x0, "GPI2"),
+		MA35_MUX(0x1, "EPWM0_CH2"),
+		MA35_MUX(0x2, "UART12_RXD"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x5, "SPI3_MOSI"),
+		MA35_MUX(0x7, "SC0_DAT"),
+		MA35_MUX(0x8, "EBI_ADR2"),
+		MA35_MUX(0xb, "TM1"),
+		MA35_MUX(0xc, "ECAP1_IC2")),
+	MA35_PIN(125, PI3, 0xc0, 0xc,
+		MA35_MUX(0x0, "GPI3"),
+		MA35_MUX(0x1, "EPWM0_CH3"),
+		MA35_MUX(0x2, "UART12_TXD"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x5, "SPI3_MISO"),
+		MA35_MUX(0x7, "SC0_RST"),
+		MA35_MUX(0x8, "EBI_ADR3"),
+		MA35_MUX(0xb, "TM1_EXT")),
+	MA35_PIN(126, PI4, 0xc0, 0x10,
+		MA35_MUX(0x0, "GPI4"),
+		MA35_MUX(0x1, "EPWM0_CH4"),
+		MA35_MUX(0x2, "UART14_nCTS"),
+		MA35_MUX(0x3, "UART13_RXD"),
+		MA35_MUX(0x4, "I2C3_SDA"),
+		MA35_MUX(0x5, "SPI2_SS1"),
+		MA35_MUX(0x6, "I2S1_LRCK"),
+		MA35_MUX(0x8, "EBI_ADR4"),
+		MA35_MUX(0xd, "INT0")),
+	MA35_PIN(127, PI5, 0xc0, 0x14,
+		MA35_MUX(0x0, "GPI5"),
+		MA35_MUX(0x1, "EPWM0_CH5"),
+		MA35_MUX(0x2, "UART14_nRTS"),
+		MA35_MUX(0x3, "UART13_TXD"),
+		MA35_MUX(0x4, "I2C3_SCL"),
+		MA35_MUX(0x6, "I2S1_BCLK"),
+		MA35_MUX(0x8, "EBI_ADR5"),
+		MA35_MUX(0xd, "INT1")),
+	MA35_PIN(128, PI6, 0xc0, 0x18,
+		MA35_MUX(0x0, "GPI6"),
+		MA35_MUX(0x1, "EPWM0_BRAKE0"),
+		MA35_MUX(0x2, "UART14_RXD"),
+		MA35_MUX(0x3, "CAN1_RXD"),
+		MA35_MUX(0x6, "I2S1_DI"),
+		MA35_MUX(0x8, "EBI_ADR6"),
+		MA35_MUX(0xc, "QEI1_INDEX"),
+		MA35_MUX(0xd, "INT2")),
+	MA35_PIN(129, PI7, 0xc0, 0x1c,
+		MA35_MUX(0x0, "GPI7"),
+		MA35_MUX(0x1, "EPWM0_BRAKE1"),
+		MA35_MUX(0x2, "UART14_TXD"),
+		MA35_MUX(0x3, "CAN1_TXD"),
+		MA35_MUX(0x6, "I2S1_DO"),
+		MA35_MUX(0x8, "EBI_ADR7"),
+		MA35_MUX(0xc, "ECAP0_IC0"),
+		MA35_MUX(0xd, "INT3")),
+	MA35_PIN(130, PI8, 0xc4, 0x0,
+		MA35_MUX(0x0, "GPI8"),
+		MA35_MUX(0x2, "UART4_nCTS"),
+		MA35_MUX(0x3, "UART3_RXD"),
+		MA35_MUX(0x6, "LCM_DATA0"),
+		MA35_MUX(0xc, "EBI_AD11")),
+	MA35_PIN(131, PI9, 0xc4, 0x4,
+		MA35_MUX(0x0, "GPI9"),
+		MA35_MUX(0x2, "UART4_nRTS"),
+		MA35_MUX(0x3, "UART3_TXD"),
+		MA35_MUX(0x6, "LCM_DATA1"),
+		MA35_MUX(0xc, "EBI_AD12")),
+	MA35_PIN(132, PI10, 0xc4, 0x8,
+		MA35_MUX(0x0, "GPI10"),
+		MA35_MUX(0x2, "UART4_RXD"),
+		MA35_MUX(0x6, "LCM_DATA2"),
+		MA35_MUX(0xc, "EBI_AD13")),
+	MA35_PIN(133, PI11, 0xC4, 0xc,
+		MA35_MUX(0x0, "GPI11"),
+		MA35_MUX(0x2, "UART4_TXD"),
+		MA35_MUX(0x6, "LCM_DATA3"),
+		MA35_MUX(0xc, "EBI_AD14")),
+	MA35_PIN(134, PI12, 0xc4, 0x10,
+		MA35_MUX(0x0, "GPI12"),
+		MA35_MUX(0x2, "UART6_nCTS"),
+		MA35_MUX(0x3, "UART5_RXD"),
+		MA35_MUX(0x6, "LCM_DATA4")),
+	MA35_PIN(135, PI13, 0xc4, 0x14,
+		MA35_MUX(0x0, "GPI13"),
+		MA35_MUX(0x2, "UART6_nRTS"),
+		MA35_MUX(0x3, "UART5_TXD"),
+		MA35_MUX(0x6, "LCM_DATA5")),
+	MA35_PIN(136, PI14, 0xc4, 0x18,
+		MA35_MUX(0x0, "GPI14"),
+		MA35_MUX(0x2, "UART6_RXD"),
+		MA35_MUX(0x6, "LCM_DATA6")),
+	MA35_PIN(137, PI15, 0xc4, 0x1c,
+		MA35_MUX(0x0, "GPI15"),
+		MA35_MUX(0x2, "UART6_TXD"),
+		MA35_MUX(0x6, "LCM_DATA7")),
+	MA35_PIN(138, PJ0, 0xc8, 0x0,
+		MA35_MUX(0x0, "GPJ0"),
+		MA35_MUX(0x1, "EPWM1_BRAKE0"),
+		MA35_MUX(0x2, "UART8_nCTS"),
+		MA35_MUX(0x3, "UART7_RXD"),
+		MA35_MUX(0x4, "I2C2_SDA"),
+		MA35_MUX(0x5, "SPI2_SS0"),
+		MA35_MUX(0x6, "eMMC1_DAT4"),
+		MA35_MUX(0x7, "I2S0_LRCK"),
+		MA35_MUX(0x8, "SC0_CLK"),
+		MA35_MUX(0x9, "EBI_AD11"),
+		MA35_MUX(0xa, "EBI_ADR16"),
+		MA35_MUX(0xb, "EBI_nCS0"),
+		MA35_MUX(0xc, "EBI_AD7")),
+	MA35_PIN(139, PJ1, 0xc8, 0x4,
+		MA35_MUX(0x0, "GPJ1"),
+		MA35_MUX(0x1, "EPWM1_BRAKE1"),
+		MA35_MUX(0x2, "UART8_nRTS"),
+		MA35_MUX(0x3, "UART7_TXD"),
+		MA35_MUX(0x4, "I2C2_SCL"),
+		MA35_MUX(0x5, "SPI2_CLK"),
+		MA35_MUX(0x6, "eMMC1_DAT5"),
+		MA35_MUX(0x7, "I2S0_BCLK"),
+		MA35_MUX(0x8, "SC0_DAT"),
+		MA35_MUX(0x9, "EBI_AD12"),
+		MA35_MUX(0xa, "EBI_ADR17"),
+		MA35_MUX(0xb, "EBI_nCS1"),
+		MA35_MUX(0xc, "EBI_AD8")),
+	MA35_PIN(140, PJ2, 0xc8, 0x8,
+		MA35_MUX(0x0, "GPJ2"),
+		MA35_MUX(0x1, "EPWM1_CH4"),
+		MA35_MUX(0x2, "UART8_RXD"),
+		MA35_MUX(0x3, "CAN1_RXD"),
+		MA35_MUX(0x5, "SPI2_MOSI"),
+		MA35_MUX(0x6, "eMMC1_DAT6"),
+		MA35_MUX(0x7, "I2S0_DI"),
+		MA35_MUX(0x8, "SC0_RST"),
+		MA35_MUX(0x9, "EBI_AD13"),
+		MA35_MUX(0xa, "EBI_ADR18"),
+		MA35_MUX(0xb, "EBI_nWRH"),
+		MA35_MUX(0xc, "EBI_AD9")),
+	MA35_PIN(141, PJ3, 0xc8, 0xc,
+		MA35_MUX(0x0, "GPJ3"),
+		MA35_MUX(0x1, "EPWM1_CH5"),
+		MA35_MUX(0x2, "UART8_TXD"),
+		MA35_MUX(0x3, "CAN1_TXD"),
+		MA35_MUX(0x5, "SPI2_MISO"),
+		MA35_MUX(0x6, "eMMC1_DAT7"),
+		MA35_MUX(0x7, "I2S0_DO"),
+		MA35_MUX(0x8, "SC0_PWR"),
+		MA35_MUX(0x9, "EBI_AD14"),
+		MA35_MUX(0xa, "EBI_ADR19"),
+		MA35_MUX(0xb, "EBI_nWRL"),
+		MA35_MUX(0xc, "EBI_AD10")),
+	MA35_PIN(142, PJ4, 0xc8, 0x10,
+		MA35_MUX(0x0, "GPJ4"),
+		MA35_MUX(0x4, "I2C3_SDA"),
+		MA35_MUX(0x6, "SD1_WP")),
+	MA35_PIN(143, PJ5, 0xc8, 0x14,
+		MA35_MUX(0x0, "GPJ5"),
+		MA35_MUX(0x4, "I2C3_SCL"),
+		MA35_MUX(0x6, "SD1_nCD")),
+	MA35_PIN(144, PJ6, 0xc8, 0x18,
+		MA35_MUX(0x0, "GPJ6"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x6, "SD1_CMD/eMMC1_CMD")),
+	MA35_PIN(145, PJ7, 0xc8, 0x1c,
+		MA35_MUX(0x0, "GPJ7"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x6, "SD1_CLK/eMMC1_CLK")),
+	MA35_PIN(146, PJ8, 0xcc, 0x0,
+		MA35_MUX(0x0, "GPJ8"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x6, "SD1_DAT0/eMMC1_DAT0")),
+	MA35_PIN(147, PJ9, 0xcc, 0x4,
+		MA35_MUX(0x0, "GPJ9"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x6, "SD1_DAT1/eMMC1_DAT1")),
+	MA35_PIN(148, PJ10, 0xcc, 0x8,
+		MA35_MUX(0x0, "GPJ10"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x6, "SD1_DAT2/eMMC1_DAT2")),
+	MA35_PIN(149, PJ11, 0xcc, 0xc,
+		MA35_MUX(0x0, "GPJ11"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x6, "SD1_DAT3/eMMC1_DAT3")),
+	MA35_PIN(150, PJ12, 0xcc, 0x10,
+		MA35_MUX(0x0, "GPJ12"),
+		MA35_MUX(0x1, "EPWM1_CH2"),
+		MA35_MUX(0x2, "UART2_nCTS"),
+		MA35_MUX(0x3, "UART1_RXD"),
+		MA35_MUX(0x4, "I2C5_SDA"),
+		MA35_MUX(0x5, "SPI3_SS0"),
+		MA35_MUX(0x7, "SC1_CLK"),
+		MA35_MUX(0x8, "EBI_ADR12"),
+		MA35_MUX(0xb, "TM2"),
+		MA35_MUX(0xc, "QEI0_INDEX")),
+	MA35_PIN(151, PJ13, 0xcc, 0x14,
+		MA35_MUX(0x0, "GPJ13"),
+		MA35_MUX(0x1, "EPWM1_CH3"),
+		MA35_MUX(0x2, "UART2_nRTS"),
+		MA35_MUX(0x3, "UART1_TXD"),
+		MA35_MUX(0x4, "I2C5_SCL"),
+		MA35_MUX(0x5, "SPI3_MOSI"),
+		MA35_MUX(0x7, "SC1_DAT"),
+		MA35_MUX(0x8, "EBI_ADR13"),
+		MA35_MUX(0xb, "TM2_EXT")),
+	MA35_PIN(152, PJ14, 0xcc, 0x18,
+		MA35_MUX(0x0, "GPJ14"),
+		MA35_MUX(0x1, "EPWM1_CH4"),
+		MA35_MUX(0x2, "UART2_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x5, "SPI3_MISO"),
+		MA35_MUX(0x7, "SC1_RST"),
+		MA35_MUX(0x8, "EBI_ADR14"),
+		MA35_MUX(0xb, "TM3")),
+	MA35_PIN(153, PJ15, 0xcc, 0x1c,
+		MA35_MUX(0x0, "GPJ15"),
+		MA35_MUX(0x1, "EPWM1_CH5"),
+		MA35_MUX(0x2, "UART2_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x5, "SPI3_CLK"),
+		MA35_MUX(0x6, "EADC0_ST"),
+		MA35_MUX(0x7, "SC1_PWR"),
+		MA35_MUX(0x8, "EBI_ADR15"),
+		MA35_MUX(0xb, "TM3_EXT"),
+		MA35_MUX(0xd, "INT1")),
+	MA35_PIN(154, PK0, 0xd0, 0x0,
+		MA35_MUX(0x0, "GPK0"),
+		MA35_MUX(0x1, "EPWM0_SYNC_IN"),
+		MA35_MUX(0x2, "UART16_nCTS"),
+		MA35_MUX(0x3, "UART15_RXD"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x6, "I2S1_MCLK"),
+		MA35_MUX(0x8, "EBI_ADR8"),
+		MA35_MUX(0xb, "TM7"),
+		MA35_MUX(0xc, "ECAP0_IC1")),
+	MA35_PIN(155, PK1, 0xd0, 0x4,
+		MA35_MUX(0x0, "GPK1"),
+		MA35_MUX(0x1, "EPWM0_SYNC_OUT"),
+		MA35_MUX(0x2, "UART16_nRTS"),
+		MA35_MUX(0x3, "UART15_TXD"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x6, "EADC0_ST"),
+		MA35_MUX(0x8, "EBI_ADR9"),
+		MA35_MUX(0xb, "TM7_EXT"),
+		MA35_MUX(0xc, "ECAP0_IC2")),
+	MA35_PIN(156, PK2, 0xd0, 0x8,
+		MA35_MUX(0x0, "GPK2"),
+		MA35_MUX(0x1, "EPWM1_CH0"),
+		MA35_MUX(0x2, "UART16_RXD"),
+		MA35_MUX(0x3, "CAN2_RXD"),
+		MA35_MUX(0x5, "SPI3_I2SMCLK"),
+		MA35_MUX(0x7, "SC0_PWR"),
+		MA35_MUX(0x8, "EBI_ADR10"),
+		MA35_MUX(0xc, "QEI0_A")),
+	MA35_PIN(157, PK3, 0xd0, 0xc,
+		MA35_MUX(0x0, "GPK3"),
+		MA35_MUX(0x1, "EPWM1_CH1"),
+		MA35_MUX(0x2, "UART16_TXD"),
+		MA35_MUX(0x3, "CAN2_TXD"),
+		MA35_MUX(0x5, "SPI3_SS1"),
+		MA35_MUX(0x7, "SC1_nCD"),
+		MA35_MUX(0x8, "EBI_ADR11"),
+		MA35_MUX(0xc, "QEI0_B")),
+	MA35_PIN(158, PK4, 0xd0, 0x10,
+		MA35_MUX(0x0, "GPK4"),
+		MA35_MUX(0x2, "UART12_nCTS"),
+		MA35_MUX(0x3, "UART13_RXD"),
+		MA35_MUX(0x5, "SPI2_MISO"),
+		MA35_MUX(0x6, "LCM_DEN"),
+		MA35_MUX(0xc, "EBI_AD10"),
+		MA35_MUX(0xd, "EBI_nWRL")),
+	MA35_PIN(159, PK5, 0xd0, 0x14,
+		MA35_MUX(0x0, "GPK5"),
+		MA35_MUX(0x1, "EPWM1_CH1"),
+		MA35_MUX(0x2, "UART12_nRTS"),
+		MA35_MUX(0x3, "UART13_TXD"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x5, "SPI2_CLK"),
+		MA35_MUX(0x7, "I2S1_DI"),
+		MA35_MUX(0x8, "SC0_DAT"),
+		MA35_MUX(0x9, "EADC0_ST"),
+		MA35_MUX(0xb, "TM8_EXT"),
+		MA35_MUX(0xd, "INT1")),
+	MA35_PIN(160, PK6, 0xd0, 0x18,
+		MA35_MUX(0x0, "GPK6"),
+		MA35_MUX(0x1, "EPWM1_CH2"),
+		MA35_MUX(0x2, "UART12_RXD"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x5, "SPI2_MOSI"),
+		MA35_MUX(0x7, "I2S1_BCLK"),
+		MA35_MUX(0x8, "SC0_RST"),
+		MA35_MUX(0xb, "TM6"),
+		MA35_MUX(0xd, "INT2")),
+	MA35_PIN(161, PK7, 0xd0, 0x1c,
+		MA35_MUX(0x0, "GPK7"),
+		MA35_MUX(0x1, "EPWM1_CH3"),
+		MA35_MUX(0x2, "UART12_TXD"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x5, "SPI2_MISO"),
+		MA35_MUX(0x7, "I2S1_LRCK"),
+		MA35_MUX(0x8, "SC0_PWR"),
+		MA35_MUX(0x9, "CLKO"),
+		MA35_MUX(0xb, "TM6_EXT"),
+		MA35_MUX(0xd, "INT3")),
+	MA35_PIN(162, PK8, 0xd4, 0x0,
+		MA35_MUX(0x0, "GPK8"),
+		MA35_MUX(0x1, "EPWM1_CH0"),
+		MA35_MUX(0x4, "I2C3_SDA"),
+		MA35_MUX(0x5, "SPI3_CLK"),
+		MA35_MUX(0x7, "EADC0_ST"),
+		MA35_MUX(0x8, "EBI_AD15"),
+		MA35_MUX(0x9, "EBI_MCLK"),
+		MA35_MUX(0xa, "EBI_ADR15"),
+		MA35_MUX(0xb, "TM8"),
+		MA35_MUX(0xc, "QEI1_INDEX")),
+	MA35_PIN(163, PK9, 0xd4, 0x4,
+		MA35_MUX(0x0, "GPK9"),
+		MA35_MUX(0x4, "I2C3_SCL"),
+		MA35_MUX(0x6, "CCAP0_SCLK"),
+		MA35_MUX(0x8, "EBI_AD0"),
+		MA35_MUX(0xa, "EBI_ADR0")),
+	MA35_PIN(164, PK10, 0xd4, 0x8,
+		MA35_MUX(0x0, "GPK10"),
+		MA35_MUX(0x3, "CAN1_RXD"),
+		MA35_MUX(0x6, "CCAP0_PIXCLK"),
+		MA35_MUX(0x8, "EBI_AD1"),
+		MA35_MUX(0xa, "EBI_ADR1")),
+	MA35_PIN(165, PK11, 0xd4, 0xc,
+		MA35_MUX(0x0, "GPK11"),
+		MA35_MUX(0x3, "CAN1_TXD"),
+		MA35_MUX(0x6, "CCAP0_HSYNC"),
+		MA35_MUX(0x8, "EBI_AD2"),
+		MA35_MUX(0xa, "EBI_ADR2")),
+	MA35_PIN(166, PK12, 0xd4, 0x10,
+		MA35_MUX(0x0, "GPK12"),
+		MA35_MUX(0x1, "EPWM2_CH0"),
+		MA35_MUX(0x2, "UART1_nCTS"),
+		MA35_MUX(0x3, "UART13_RXD"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x5, "I2S0_LRCK"),
+		MA35_MUX(0x6, "SPI1_SS0"),
+		MA35_MUX(0x8, "SC0_CLK"),
+		MA35_MUX(0xb, "TM10"),
+		MA35_MUX(0xd, "INT2")),
+	MA35_PIN(167, PK13, 0xd4, 0x14,
+		MA35_MUX(0x0, "GPK13"),
+		MA35_MUX(0x1, "EPWM2_CH1"),
+		MA35_MUX(0x2, "UART1_nRTS"),
+		MA35_MUX(0x3, "UART13_TXD"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x5, "I2S0_BCLK"),
+		MA35_MUX(0x6, "SPI1_CLK"),
+		MA35_MUX(0x8, "SC0_DAT"),
+		MA35_MUX(0xb, "TM10_EXT")),
+	MA35_PIN(168, PK14, 0xd4, 0x18,
+		MA35_MUX(0x0, "GPK14"),
+		MA35_MUX(0x1, "EPWM2_CH2"),
+		MA35_MUX(0x2, "UART1_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x5, "I2S0_DI"),
+		MA35_MUX(0x6, "SPI1_MOSI"),
+		MA35_MUX(0x8, "SC0_RST"),
+		MA35_MUX(0xa, "I2C5_SDA"),
+		MA35_MUX(0xb, "TM11"),
+		MA35_MUX(0xd, "INT3")),
+	MA35_PIN(169, PK15, 0xd4, 0x1c,
+		MA35_MUX(0x0, "GPK15"),
+		MA35_MUX(0x1, "EPWM2_CH3"),
+		MA35_MUX(0x2, "UART1_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x5, "I2S0_DO"),
+		MA35_MUX(0x6, "SPI1_MISO"),
+		MA35_MUX(0x8, "SC0_PWR"),
+		MA35_MUX(0xa, "I2C5_SCL"),
+		MA35_MUX(0xb, "TM11_EXT")),
+	MA35_PIN(170, PL0, 0xd8, 0x0,
+		MA35_MUX(0x0, "GPL0"),
+		MA35_MUX(0x1, "EPWM1_CH0"),
+		MA35_MUX(0x2, "UART11_nCTS"),
+		MA35_MUX(0x3, "UART10_RXD"),
+		MA35_MUX(0x4, "I2C3_SDA"),
+		MA35_MUX(0x5, "SPI2_MOSI"),
+		MA35_MUX(0x6, "QSPI1_MOSI1"),
+		MA35_MUX(0x7, "I2S0_LRCK"),
+		MA35_MUX(0x8, "EBI_AD11"),
+		MA35_MUX(0x9, "SC1_CLK"),
+		MA35_MUX(0xb, "TM5"),
+		MA35_MUX(0xc, "QEI1_A")),
+	MA35_PIN(171, PL1, 0xd8, 0x4,
+		MA35_MUX(0x0, "GPL1"),
+		MA35_MUX(0x1, "EPWM1_CH1"),
+		MA35_MUX(0x2, "UART11_nRTS"),
+		MA35_MUX(0x3, "UART10_TXD"),
+		MA35_MUX(0x4, "I2C3_SCL"),
+		MA35_MUX(0x5, "SPI2_MISO"),
+		MA35_MUX(0x6, "QSPI1_MISO1"),
+		MA35_MUX(0x7, "I2S0_BCLK"),
+		MA35_MUX(0x8, "EBI_AD12"),
+		MA35_MUX(0x9, "SC1_DAT"),
+		MA35_MUX(0xb, "TM5_EXT"),
+		MA35_MUX(0xc, "QEI1_B")),
+	MA35_PIN(172, PL2, 0xd8, 0x8,
+		MA35_MUX(0x0, "GPL2"),
+		MA35_MUX(0x1, "EPWM1_CH2"),
+		MA35_MUX(0x2, "UART11_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x5, "SPI2_SS0"),
+		MA35_MUX(0x6, "QSPI1_SS1"),
+		MA35_MUX(0x7, "I2S0_DI"),
+		MA35_MUX(0x8, "EBI_AD13"),
+		MA35_MUX(0x9, "SC1_RST"),
+		MA35_MUX(0xb, "TM7"),
+		MA35_MUX(0xc, "QEI1_INDEX")),
+	MA35_PIN(173, PL3, 0xd8, 0xc,
+		MA35_MUX(0x0, "GPL3"),
+		MA35_MUX(0x1, "EPWM1_CH3"),
+		MA35_MUX(0x2, "UART11_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x5, "SPI2_CLK"),
+		MA35_MUX(0x6, "QSPI1_CLK"),
+		MA35_MUX(0x7, "I2S0_DO"),
+		MA35_MUX(0x8, "EBI_AD14"),
+		MA35_MUX(0x9, "SC1_PWR"),
+		MA35_MUX(0xb, "TM7_EXT"),
+		MA35_MUX(0xc, "ECAP0_IC0")),
+	MA35_PIN(174, PL4, 0xd8, 0x10,
+		MA35_MUX(0x0, "GPL4"),
+		MA35_MUX(0x1, "EPWM1_CH4"),
+		MA35_MUX(0x2, "UART2_nCTS"),
+		MA35_MUX(0x3, "UART1_RXD"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x5, "SPI3_MOSI"),
+		MA35_MUX(0x6, "QSPI1_MOSI0"),
+		MA35_MUX(0x7, "I2S0_MCLK"),
+		MA35_MUX(0x8, "EBI_nRD"),
+		MA35_MUX(0x9, "SC1_nCD"),
+		MA35_MUX(0xb, "TM9"),
+		MA35_MUX(0xc, "ECAP0_IC1")),
+	MA35_PIN(175, PL5, 0xd8, 0x14,
+		MA35_MUX(0x0, "GPL5"),
+		MA35_MUX(0x1, "EPWM1_CH5"),
+		MA35_MUX(0x2, "UART2_nRTS"),
+		MA35_MUX(0x3, "UART1_TXD"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x5, "SPI3_MISO"),
+		MA35_MUX(0x6, "QSPI1_MISO0"),
+		MA35_MUX(0x7, "I2S1_MCLK"),
+		MA35_MUX(0x8, "EBI_nWR"),
+		MA35_MUX(0x9, "SC0_nCD"),
+		MA35_MUX(0xb, "TM9_EXT"),
+		MA35_MUX(0xc, "ECAP0_IC2")),
+	MA35_PIN(176, PL6, 0xd8, 0x18,
+		MA35_MUX(0x0, "GPL6"),
+		MA35_MUX(0x1, "EPWM0_CH0"),
+		MA35_MUX(0x2, "UART2_RXD"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x6, "QSPI1_MOSI1"),
+		MA35_MUX(0x7, "TRACE_CLK"),
+		MA35_MUX(0x8, "EBI_AD5"),
+		MA35_MUX(0xb, "TM3"),
+		MA35_MUX(0xc, "ECAP1_IC0"),
+		MA35_MUX(0xd, "INT0")),
+	MA35_PIN(177, PL7, 0xd8, 0x1c,
+		MA35_MUX(0x0, "GPL7"),
+		MA35_MUX(0x1, "EPWM0_CH1"),
+		MA35_MUX(0x2, "UART2_TXD"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x6, "QSPI1_MISO1"),
+		MA35_MUX(0x8, "EBI_AD6"),
+		MA35_MUX(0xb, "TM3_EXT"),
+		MA35_MUX(0xc, "ECAP1_IC1"),
+		MA35_MUX(0xd, "INT1")),
+	MA35_PIN(178, PL8, 0xdc, 0x0,
+		MA35_MUX(0x0, "GPL8"),
+		MA35_MUX(0x1, "EPWM0_CH2"),
+		MA35_MUX(0x2, "UART14_nCTS"),
+		MA35_MUX(0x3, "UART13_RXD"),
+		MA35_MUX(0x4, "I2C5_SDA"),
+		MA35_MUX(0x5, "SPI3_SS0"),
+		MA35_MUX(0x6, "EPWM0_CH4"),
+		MA35_MUX(0x7, "I2S1_LRCK"),
+		MA35_MUX(0x8, "EBI_AD7"),
+		MA35_MUX(0x9, "SC0_CLK"),
+		MA35_MUX(0xb, "TM4"),
+		MA35_MUX(0xc, "ECAP1_IC2"),
+		MA35_MUX(0xd, "INT2")),
+	MA35_PIN(179, PL9, 0xdc, 0x4,
+		MA35_MUX(0x0, "GPL9"),
+		MA35_MUX(0x1, "EPWM0_CH3"),
+		MA35_MUX(0x2, "UART14_nRTS"),
+		MA35_MUX(0x3, "UART13_TXD"),
+		MA35_MUX(0x4, "I2C5_SCL"),
+		MA35_MUX(0x5, "SPI3_CLK"),
+		MA35_MUX(0x6, "EPWM1_CH4"),
+		MA35_MUX(0x7, "I2S1_BCLK"),
+		MA35_MUX(0x8, "EBI_AD8"),
+		MA35_MUX(0x9, "SC0_DAT"),
+		MA35_MUX(0xb, "TM4_EXT"),
+		MA35_MUX(0xc, "QEI0_A"),
+		MA35_MUX(0xd, "INT3")),
+	MA35_PIN(180, PL10, 0xdc, 0x8,
+		MA35_MUX(0x0, "GPL10"),
+		MA35_MUX(0x1, "EPWM0_CH4"),
+		MA35_MUX(0x2, "UART14_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x5, "SPI3_MOSI"),
+		MA35_MUX(0x6, "EPWM0_CH5"),
+		MA35_MUX(0x7, "I2S1_DI"),
+		MA35_MUX(0x8, "EBI_AD9"),
+		MA35_MUX(0x9, "SC0_RST"),
+		MA35_MUX(0xb, "EBI_nWRH"),
+		MA35_MUX(0xc, "QEI0_B")),
+	MA35_PIN(181, PL11, 0xdc, 0xc,
+		MA35_MUX(0x0, "GPL11"),
+		MA35_MUX(0x1, "EPWM0_CH5"),
+		MA35_MUX(0x2, "UART14_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x5, "SPI3_MISO"),
+		MA35_MUX(0x6, "EPWM1_CH5"),
+		MA35_MUX(0x7, "I2S1_DO"),
+		MA35_MUX(0x8, "EBI_AD10"),
+		MA35_MUX(0x9, "SC0_PWR"),
+		MA35_MUX(0xb, "EBI_nWRL"),
+		MA35_MUX(0xc, "QEI0_INDEX")),
+	MA35_PIN(182, PL12, 0xdc, 0x10,
+		MA35_MUX(0x0, "GPL12"),
+		MA35_MUX(0x1, "EPWM0_SYNC_IN"),
+		MA35_MUX(0x2, "UART7_nCTS"),
+		MA35_MUX(0x3, "ECAP1_IC0"),
+		MA35_MUX(0x4, "UART14_RXD"),
+		MA35_MUX(0x5, "SPI0_SS0"),
+		MA35_MUX(0x6, "I2S1_LRCK"),
+		MA35_MUX(0x7, "SC1_CLK"),
+		MA35_MUX(0x8, "EBI_AD0"),
+		MA35_MUX(0x9, "HSUSBH_PWREN"),
+		MA35_MUX(0xa, "I2C2_SDA"),
+		MA35_MUX(0xb, "TM0"),
+		MA35_MUX(0xc, "EPWM0_CH2"),
+		MA35_MUX(0xd, "EBI_AD11"),
+		MA35_MUX(0xe, "RGMII0_PPS"),
+		MA35_MUX(0xf, "RMII0_PPS")),
+	MA35_PIN(183, PL13, 0xdc, 0x14,
+		MA35_MUX(0x0, "GPL13"),
+		MA35_MUX(0x1, "EPWM0_SYNC_OUT"),
+		MA35_MUX(0x2, "UART7_nRTS"),
+		MA35_MUX(0x3, "ECAP1_IC1"),
+		MA35_MUX(0x4, "UART14_TXD"),
+		MA35_MUX(0x5, "SPI0_CLK"),
+		MA35_MUX(0x6, "I2S1_BCLK"),
+		MA35_MUX(0x7, "SC1_DAT"),
+		MA35_MUX(0x8, "EBI_AD1"),
+		MA35_MUX(0x9, "HSUSBH_OVC"),
+		MA35_MUX(0xa, "I2C2_SCL"),
+		MA35_MUX(0xb, "TM0_EXT"),
+		MA35_MUX(0xc, "EPWM0_CH3"),
+		MA35_MUX(0xd, "EBI_AD12"),
+		MA35_MUX(0xe, "RGMII1_PPS"),
+		MA35_MUX(0xf, "RMII1_PPS")),
+	MA35_PIN(184, PL14, 0xdc, 0x18,
+		MA35_MUX(0x0, "GPL14"),
+		MA35_MUX(0x1, "EPWM0_CH2"),
+		MA35_MUX(0x2, "UART7_RXD"),
+		MA35_MUX(0x4, "CAN1_RXD"),
+		MA35_MUX(0x5, "SPI0_MOSI"),
+		MA35_MUX(0x6, "I2S1_DI"),
+		MA35_MUX(0x7, "SC1_RST"),
+		MA35_MUX(0x8, "EBI_AD2"),
+		MA35_MUX(0xb, "TM2"),
+		MA35_MUX(0xc, "INT0"),
+		MA35_MUX(0xd, "EBI_AD13")),
+	MA35_PIN(185, PL15, 0xdc, 0x1c,
+		MA35_MUX(0x0, "GPL15"),
+		MA35_MUX(0x1, "EPWM0_CH1"),
+		MA35_MUX(0x2, "UART7_TXD"),
+		MA35_MUX(0x3, "TRACE_CLK"),
+		MA35_MUX(0x4, "CAN1_TXD"),
+		MA35_MUX(0x5, "SPI0_MISO"),
+		MA35_MUX(0x6, "I2S1_DO"),
+		MA35_MUX(0x7, "SC1_PWR"),
+		MA35_MUX(0x8, "EBI_AD3"),
+		MA35_MUX(0xb, "TM2_EXT"),
+		MA35_MUX(0xc, "INT2"),
+		MA35_MUX(0xd, "EBI_AD14")),
+	MA35_PIN(186, PM0, 0xe0, 0x0,
+		MA35_MUX(0x0, "GPM0"),
+		MA35_MUX(0x4, "I2C4_SDA"),
+		MA35_MUX(0x6, "CCAP0_VSYNC"),
+		MA35_MUX(0x8, "EBI_AD3"),
+		MA35_MUX(0xa, "EBI_ADR3")),
+	MA35_PIN(187, PM1, 0xe0, 0x4,
+		MA35_MUX(0x0, "GPM1"),
+		MA35_MUX(0x4, "I2C4_SCL"),
+		MA35_MUX(0x5, "SPI3_I2SMCLK"),
+		MA35_MUX(0x6, "CCAP0_SFIELD"),
+		MA35_MUX(0x8, "EBI_AD4"),
+		MA35_MUX(0xa, "EBI_ADR4")),
+	MA35_PIN(188, PM2, 0xe0, 0x8,
+		MA35_MUX(0x0, "GPM2"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x6, "CCAP0_DATA0"),
+		MA35_MUX(0x8, "EBI_AD5"),
+		MA35_MUX(0xa, "EBI_ADR5")),
+	MA35_PIN(189, PM3, 0xe0, 0xc,
+		MA35_MUX(0x0, "GPM3"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x6, "CCAP0_DATA1"),
+		MA35_MUX(0x8, "EBI_AD6"),
+		MA35_MUX(0xa, "EBI_ADR6")),
+	MA35_PIN(190, PM4, 0xe0, 0x10,
+		MA35_MUX(0x0, "GPM4"),
+		MA35_MUX(0x4, "I2C5_SDA"),
+		MA35_MUX(0x6, "CCAP0_DATA2"),
+		MA35_MUX(0x8, "EBI_AD7"),
+		MA35_MUX(0xa, "EBI_ADR7")),
+	MA35_PIN(191, PM5, 0xe0, 0x14,
+		MA35_MUX(0x0, "GPM5"),
+		MA35_MUX(0x4, "I2C5_SCL"),
+		MA35_MUX(0x6, "CCAP0_DATA3"),
+		MA35_MUX(0x8, "EBI_AD8"),
+		MA35_MUX(0xa, "EBI_ADR8")),
+	MA35_PIN(192, PM6, 0xe0, 0x18,
+		MA35_MUX(0x0, "GPM6"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x6, "CCAP0_DATA4"),
+		MA35_MUX(0x8, "EBI_AD9"),
+		MA35_MUX(0xa, "EBI_ADR9")),
+	MA35_PIN(193, PM7, 0xe0, 0x1c,
+		MA35_MUX(0x0, "GPM7"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x6, "CCAP0_DATA5"),
+		MA35_MUX(0x8, "EBI_AD10"),
+		MA35_MUX(0xa, "EBI_ADR10")),
+	MA35_PIN(194, PM8, 0xe4, 0x0,
+		MA35_MUX(0x0, "GPM8"),
+		MA35_MUX(0x4, "I2C0_SDA"),
+		MA35_MUX(0x6, "CCAP0_DATA6"),
+		MA35_MUX(0x8, "EBI_AD11"),
+		MA35_MUX(0xa, "EBI_ADR11")),
+	MA35_PIN(195, PM9, 0xe4, 0x4,
+		MA35_MUX(0x0, "GPM9"),
+		MA35_MUX(0x4, "I2C0_SCL"),
+		MA35_MUX(0x6, "CCAP0_DATA7"),
+		MA35_MUX(0x8, "EBI_AD12"),
+		MA35_MUX(0xa, "EBI_ADR12")),
+	MA35_PIN(196, PM10, 0xe4, 0x8,
+		MA35_MUX(0x0, "GPM10"),
+		MA35_MUX(0x1, "EPWM1_CH2"),
+		MA35_MUX(0x3, "CAN2_RXD"),
+		MA35_MUX(0x5, "SPI3_SS0"),
+		MA35_MUX(0x6, "CCAP0_DATA8"),
+		MA35_MUX(0x7, "SPI2_I2SMCLK"),
+		MA35_MUX(0x8, "EBI_AD13"),
+		MA35_MUX(0xa, "EBI_ADR13")),
+	MA35_PIN(197, PM11, 0xe4, 0xc,
+		MA35_MUX(0x0, "GPM11"),
+		MA35_MUX(0x1, "EPWM1_CH3"),
+		MA35_MUX(0x3, "CAN2_TXD"),
+		MA35_MUX(0x5, "SPI3_SS1"),
+		MA35_MUX(0x6, "CCAP0_DATA9"),
+		MA35_MUX(0x7, "SPI2_SS1"),
+		MA35_MUX(0x8, "EBI_AD14"),
+		MA35_MUX(0xa, "EBI_ADR14")),
+	MA35_PIN(198, PM12, 0xe4, 0x10,
+		MA35_MUX(0x0, "GPM12"),
+		MA35_MUX(0x1, "EPWM1_CH4"),
+		MA35_MUX(0x2, "UART10_nCTS"),
+		MA35_MUX(0x3, "TRACE_DATA0"),
+		MA35_MUX(0x4, "UART11_RXD"),
+		MA35_MUX(0x5, "I2C2_SDA"),
+		MA35_MUX(0x7, "SC1_nCD"),
+		MA35_MUX(0x8, "EBI_AD8"),
+		MA35_MUX(0x9, "I2S1_MCLK"),
+		MA35_MUX(0xb, "TM8")),
+	MA35_PIN(199, PM13, 0xe4, 0x14,
+		MA35_MUX(0x0, "GPM13"),
+		MA35_MUX(0x1, "EPWM1_CH5"),
+		MA35_MUX(0x2, "UART10_nRTS"),
+		MA35_MUX(0x3, "TRACE_DATA1"),
+		MA35_MUX(0x4, "UART11_TXD"),
+		MA35_MUX(0x5, "I2C2_SCL"),
+		MA35_MUX(0x8, "EBI_AD9"),
+		MA35_MUX(0x9, "ECAP1_IC0"),
+		MA35_MUX(0xb, "TM8_EXT")),
+	MA35_PIN(200, PM14, 0xe4, 0x18,
+		MA35_MUX(0x0, "GPM14"),
+		MA35_MUX(0x1, "EPWM1_BRAKE0"),
+		MA35_MUX(0x2, "UART10_RXD"),
+		MA35_MUX(0x3, "TRACE_DATA2"),
+		MA35_MUX(0x4, "CAN2_RXD"),
+		MA35_MUX(0x6, "I2C3_SDA"),
+		MA35_MUX(0x8, "EBI_AD10"),
+		MA35_MUX(0x9, "ECAP1_IC1"),
+		MA35_MUX(0xb, "TM10"),
+		MA35_MUX(0xd, "INT1")),
+	MA35_PIN(201, PM15, 0xe4, 0x1c,
+		MA35_MUX(0x0, "GPM15"),
+		MA35_MUX(0x1, "EPWM1_BRAKE1"),
+		MA35_MUX(0x2, "UART10_TXD"),
+		MA35_MUX(0x3, "TRACE_DATA3"),
+		MA35_MUX(0x4, "CAN2_TXD"),
+		MA35_MUX(0x6, "I2C3_SCL"),
+		MA35_MUX(0x8, "EBI_AD11"),
+		MA35_MUX(0x9, "ECAP1_IC2"),
+		MA35_MUX(0xb, "TM10_EXT"),
+		MA35_MUX(0xd, "INT2")),
+	MA35_PIN(202, PN0, 0xe8, 0x0,
+		MA35_MUX(0x0, "GPN0"),
+		MA35_MUX(0x4, "I2C2_SDA"),
+		MA35_MUX(0x6, "CCAP1_DATA0")),
+	MA35_PIN(203, PN1, 0xe8, 0x4,
+		MA35_MUX(0x0, "GPN1"),
+		MA35_MUX(0x4, "I2C2_SCL"),
+		MA35_MUX(0x6, "CCAP1_DATA1")),
+	MA35_PIN(204, PN2, 0xe8, 0x8,
+		MA35_MUX(0x0, "GPN2"),
+		MA35_MUX(0x3, "CAN0_RXD"),
+		MA35_MUX(0x6, "CCAP1_DATA2")),
+	MA35_PIN(205, PN3, 0xe8, 0xc,
+		MA35_MUX(0x0, "GPN3"),
+		MA35_MUX(0x3, "CAN0_TXD"),
+		MA35_MUX(0x6, "CCAP1_DATA3")),
+	MA35_PIN(206, PN4, 0xe8, 0x10,
+		MA35_MUX(0x0, "GPN4"),
+		MA35_MUX(0x4, "I2C1_SDA"),
+		MA35_MUX(0x6, "CCAP1_DATA4")),
+	MA35_PIN(207, PN5, 0xe8, 0x14,
+		MA35_MUX(0x0, "GPN5"),
+		MA35_MUX(0x4, "I2C1_SCL"),
+		MA35_MUX(0x6, "CCAP1_DATA5")),
+	MA35_PIN(208, PN6, 0xe8, 0x18,
+		MA35_MUX(0x0, "GPN6"),
+		MA35_MUX(0x3, "CAN1_RXD"),
+		MA35_MUX(0x6, "CCAP1_DATA6")),
+	MA35_PIN(209, PN7, 0xe8, 0x1c,
+		MA35_MUX(0x0, "GPN7"),
+		MA35_MUX(0x3, "CAN1_TXD"),
+		MA35_MUX(0x6, "CCAP1_DATA7")),
+	MA35_PIN(210, PN10, 0xec, 0x8,
+		MA35_MUX(0x0, "GPN10"),
+		MA35_MUX(0x3, "CAN2_RXD"),
+		MA35_MUX(0x6, "CCAP1_SCLK")),
+	MA35_PIN(211, PN11, 0xec, 0xc,
+		MA35_MUX(0x0, "GPN11"),
+		MA35_MUX(0x3, "CAN2_TXD"),
+		MA35_MUX(0x6, "CCAP1_PIXCLK")),
+	MA35_PIN(212, PN12, 0xec, 0x10,
+		MA35_MUX(0x0, "GPN12"),
+		MA35_MUX(0x2, "UART6_nCTS"),
+		MA35_MUX(0x3, "UART12_RXD"),
+		MA35_MUX(0x4, "I2C5_SDA"),
+		MA35_MUX(0x6, "CCAP1_HSYNC")),
+	MA35_PIN(213, PN13, 0xec, 0x14,
+		MA35_MUX(0x0, "GPN13"),
+		MA35_MUX(0x2, "UART6_nRTS"),
+		MA35_MUX(0x3, "UART12_TXD"),
+		MA35_MUX(0x4, "I2C5_SCL"),
+		MA35_MUX(0x6, "CCAP1_VSYNC")),
+	MA35_PIN(214, PN14, 0xec, 0x18,
+		MA35_MUX(0x0, "GPN14"),
+		MA35_MUX(0x2, "UART6_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x5, "SPI1_SS1"),
+		MA35_MUX(0x6, "CCAP1_SFIELD"),
+		MA35_MUX(0x7, "SPI1_I2SMCLK")),
+	MA35_PIN(215, PN15, 0xec, 0x1c,
+		MA35_MUX(0x0, "GPN15"),
+		MA35_MUX(0x1, "EPWM2_CH4"),
+		MA35_MUX(0x2, "UART6_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x5, "I2S0_MCLK"),
+		MA35_MUX(0x6, "SPI1_SS1"),
+		MA35_MUX(0x7, "SPI1_I2SMCLK"),
+		MA35_MUX(0x8, "SC0_nCD"),
+		MA35_MUX(0x9, "EADC0_ST"),
+		MA35_MUX(0xa, "CLKO"),
+		MA35_MUX(0xb, "TM6")),
+	MA35_PIN(216, PN8, 0xec, 0x0,
+		MA35_MUX(0x0, "GPN8"),
+		MA35_MUX(0x1, "EPWM2_CH4"),
+		MA35_MUX(0x4, "I2C0_SDA"),
+		MA35_MUX(0x5, "SPI2_I2SMCLK"),
+		MA35_MUX(0x6, "CCAP1_DATA8")),
+	MA35_PIN(217, PN9, 0xec, 0x4,
+		MA35_MUX(0x0, "GPN9"),
+		MA35_MUX(0x1, "EPWM2_CH5"),
+		MA35_MUX(0x4, "I2C0_SCL"),
+		MA35_MUX(0x5, "SPI1_I2SMCLK"),
+		MA35_MUX(0x6, "CCAP1_DATA9")),
+	MA35_PIN(218, PN10, 0xec, 0x8,
+		MA35_MUX(0x0, "GPN10"),
+		MA35_MUX(0x3, "CAN2_RXD"),
+		MA35_MUX(0x4, "USBHL2_DM"),
+		MA35_MUX(0x6, "CCAP1_SCLK")),
+	MA35_PIN(219, PN11, 0xec, 0xc,
+		MA35_MUX(0x0, "GPN11"),
+		MA35_MUX(0x3, "CAN2_TXD"),
+		MA35_MUX(0x4, "USBHL2_DP"),
+		MA35_MUX(0x6, "CCAP1_PIXCLK")),
+	MA35_PIN(220, PN12, 0xec, 0x10,
+		MA35_MUX(0x0, "GPN12"),
+		MA35_MUX(0x2, "UART6_nCTS"),
+		MA35_MUX(0x3, "UART12_RXD"),
+		MA35_MUX(0x4, "I2C5_SDA"),
+		MA35_MUX(0x6, "CCAP1_HSYNC")),
+	MA35_PIN(221, PN13, 0xec, 0x14,
+		MA35_MUX(0x0, "GPN13"),
+		MA35_MUX(0x2, "UART6_nRTS"),
+		MA35_MUX(0x3, "UART12_TXD"),
+		MA35_MUX(0x4, "I2C5_SCL"),
+		MA35_MUX(0x6, "CCAP1_VSYNC")),
+	MA35_PIN(222, PN14, 0xec, 0x18,
+		MA35_MUX(0x0, "GPN14"),
+		MA35_MUX(0x2, "UART6_RXD"),
+		MA35_MUX(0x3, "CAN3_RXD"),
+		MA35_MUX(0x4, "USBHL3_DM"),
+		MA35_MUX(0x5, "SPI1_SS1"),
+		MA35_MUX(0x6, "CCAP1_SFIELD"),
+		MA35_MUX(0x7, "SPI1_I2SMCLK")),
+	MA35_PIN(223, PN15, 0xec, 0x1c,
+		MA35_MUX(0x0, "GPN15"),
+		MA35_MUX(0x1, "EPWM2_CH4"),
+		MA35_MUX(0x2, "UART6_TXD"),
+		MA35_MUX(0x3, "CAN3_TXD"),
+		MA35_MUX(0x4, "USBHL3_DP"),
+		MA35_MUX(0x5, "I2S0_MCLK"),
+		MA35_MUX(0x6, "SPI1_SS1"),
+		MA35_MUX(0x7, "SPI1_I2SMCLK"),
+		MA35_MUX(0x8, "SC0_nCD"),
+		MA35_MUX(0x9, "EADC0_ST"),
+		MA35_MUX(0xa, "CLKO"),
+		MA35_MUX(0xb, "TM6")),
+};
+
+static int ma35d1_get_pin_num(int offset, int shift)
+{
+	return (offset - 0x80) * 2 + shift / 4;
+}
+
+static struct ma35_pinctrl_soc_info ma35d1_pinctrl_info = {
+	.pins = ma35d1_pins,
+	.npins = ARRAY_SIZE(ma35d1_pins),
+	.get_pin_num = ma35d1_get_pin_num,
+};
+
+static const struct dev_pm_ops ma35d1_pinctrl_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(ma35_pinctrl_suspend, ma35_pinctrl_resume)
+};
+
+static int ma35d1_pinctrl_probe(struct platform_device *pdev)
+{
+	return ma35_pinctrl_probe(pdev, &ma35d1_pinctrl_info);
+}
+
+static const struct of_device_id ma35d1_pinctrl_of_match[] = {
+	{ .compatible = "nuvoton,ma35d1-pinctrl", },
+	{ },
+};
+
+static struct platform_driver ma35d1_pinctrl_driver = {
+	.probe = ma35d1_pinctrl_probe,
+	.driver = {
+		.name = "ma35d1-pinctrl",
+		.pm = &ma35d1_pinctrl_pm_ops,
+		.of_match_table = ma35d1_pinctrl_of_match,
+	},
+};
+
+static int __init ma35d1_pinctrl_init(void)
+{
+	return platform_driver_register(&ma35d1_pinctrl_driver);
+}
+arch_initcall(ma35d1_pinctrl_init);
+
+MODULE_AUTHOR("schung@nuvoton.com");
+MODULE_DESCRIPTION("Nuvoton MA35D1 pinctrl driver");
+MODULE_LICENSE("GPL");
-- 
2.34.1


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

^ permalink raw reply related

* [PATCH v7 1/3] dt-bindings: reset: Add syscon to nuvoton ma35d1 system-management node
From: Jacky Huang @ 2024-04-09  9:56 UTC (permalink / raw)
  To: linus.walleij, robh+dt, krzysztof.kozlowski+dt, conor+dt, p.zabel,
	j.neuschaefer
  Cc: linux-arm-kernel, linux-gpio, devicetree, linux-kernel, ychuang3,
	schung, Krzysztof Kozlowski
In-Reply-To: <20240409095637.2135-1-ychuang570808@gmail.com>

From: Jacky Huang <ychuang3@nuvoton.com>

Add a compatible 'syscon' to the system management node since the system
control registers are mapped by this driver. The other driver must access
the system control registers through 'regmap' using a phandle that
references this node.

Signed-off-by: Jacky Huang <ychuang3@nuvoton.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
---
 .../devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml        | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml b/Documentation/devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml
index 34c5c1c08ec1..3ce7dcecd87a 100644
--- a/Documentation/devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml
+++ b/Documentation/devicetree/bindings/reset/nuvoton,ma35d1-reset.yaml
@@ -18,6 +18,7 @@ properties:
   compatible:
     items:
       - const: nuvoton,ma35d1-reset
+      - const: syscon
 
   reg:
     maxItems: 1
@@ -37,7 +38,7 @@ examples:
   - |
 
     system-management@40460000 {
-        compatible = "nuvoton,ma35d1-reset";
+        compatible = "nuvoton,ma35d1-reset", "syscon";
         reg = <0x40460000 0x200>;
         #reset-cells = <1>;
     };
-- 
2.34.1


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

^ permalink raw reply related

* [PATCH v7 0/3] Add support for nuvoton ma35d1 pin control
From: Jacky Huang @ 2024-04-09  9:56 UTC (permalink / raw)
  To: linus.walleij, robh+dt, krzysztof.kozlowski+dt, conor+dt, p.zabel,
	j.neuschaefer
  Cc: linux-arm-kernel, linux-gpio, devicetree, linux-kernel, ychuang3,
	schung

From: Jacky Huang <ychuang3@nuvoton.com>

This patch series adds the pin control and GPIO driver for the nuvoton ma35d1
ARMv8 SoC. It includes DT binding documentation and the ma35d1 pin control driver.

This pin control driver has been tested on the ma35d1 som board with Linux 6.9.0.

v7:
  - Replace the magic numbers appearing in the driver with defined constants, or
    provide comments to explain them.
  - Update the ma35_irq_irqtype()
    - irq_set_handler_locked(d, handle_edge_irq) and
      irq_set_handler_locked(d, handle_level_irq)
    - add case IRQ_TYPE_EDGE_BOTH
  - Use handle_bad_irq for girq->handler, instead of handle_level_irq

v6:
  - Remove DTS from this patchset. The DTS will be submitted in another patchset.

v5:
  - Update the pinctrl driver header file pinctrl-ma35.h
    - Include platform_device.h to fix compile issues.

v4:
  - Update the pinctrl driver Kconfig
    - Add depends to CONFIG_PINCTRL_MA35D1 to prevent compilation errors.
  - Update the pinctrl driver
    - Utilize devm_kcalloc() instead of devm_kzalloc().
    - Employ ARRAY_SIZE() instead of sizeof()/sizeof().

v3:
  - Update DTS and YAML files
    - Corrected the unit address of nodes gpioa ~ gpion.
    - Removed the invalid "pin-default" node.
    - Removed the phandle entry from "nuvoton,pins".
  - Update pinctrl driver
    - Fixed the Kconfig by using "depend on" instead of "if".
    - Removed unused #include of header files.
    - Utilized immutable irq_chip instead of dynamic irq_chip.
    - Replaced ma35_dt_free_map() with pinconf_generic_dt_free_map().
    - Implemented other minor fixes as suggested by the reviewer.

v2:
  - Update nuvoton,ma35d1-pinctrl.yaml
    - Update the 'nuvoton,pins' to follow the style of rockchip pinctrl approch.
    - Use power-source to indicate the pin voltage selection which follow the
      realtek pinctrl approch.
    - Instead of integer, use drive-strength-microamp to specify the real driving
      strength capability of IO pins.
  - Update ma35d1 pinctrl driver
    - Add I/O drive strength lookup table for translating device tree setting
      into control register.
  - Remove ma35d1-pinfunc.h which is unused after update definition of 'nuvoton,pins'.


Jacky Huang (3):
  dt-bindings: reset: Add syscon to nuvoton ma35d1 system-management
    node
  dt-bindings: pinctrl: Document nuvoton ma35d1 pin control
  pinctrl: nuvoton: Add ma35d1 pinctrl and GPIO driver

 .../pinctrl/nuvoton,ma35d1-pinctrl.yaml       |  163 ++
 .../bindings/reset/nuvoton,ma35d1-reset.yaml  |    3 +-
 drivers/pinctrl/nuvoton/Kconfig               |   19 +
 drivers/pinctrl/nuvoton/Makefile              |    2 +
 drivers/pinctrl/nuvoton/pinctrl-ma35.c        | 1233 +++++++++++
 drivers/pinctrl/nuvoton/pinctrl-ma35.h        |   51 +
 drivers/pinctrl/nuvoton/pinctrl-ma35d1.c      | 1797 +++++++++++++++++
 7 files changed, 3267 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,ma35d1-pinctrl.yaml
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-ma35.c
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-ma35.h
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-ma35d1.c

-- 
2.34.1


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

^ permalink raw reply

* [PATCH v7 2/3] dt-bindings: pinctrl: Document nuvoton ma35d1 pin control
From: Jacky Huang @ 2024-04-09  9:56 UTC (permalink / raw)
  To: linus.walleij, robh+dt, krzysztof.kozlowski+dt, conor+dt, p.zabel,
	j.neuschaefer
  Cc: linux-arm-kernel, linux-gpio, devicetree, linux-kernel, ychuang3,
	schung, Krzysztof Kozlowski
In-Reply-To: <20240409095637.2135-1-ychuang570808@gmail.com>

From: Jacky Huang <ychuang3@nuvoton.com>

Add documentation to describe nuvoton ma35d1 pin control and GPIO.

Signed-off-by: Jacky Huang <ychuang3@nuvoton.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 .../pinctrl/nuvoton,ma35d1-pinctrl.yaml       | 163 ++++++++++++++++++
 1 file changed, 163 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,ma35d1-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/nuvoton,ma35d1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nuvoton,ma35d1-pinctrl.yaml
new file mode 100644
index 000000000000..8b9ec263213f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nuvoton,ma35d1-pinctrl.yaml
@@ -0,0 +1,163 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nuvoton,ma35d1-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton MA35D1 pin control and GPIO
+
+maintainers:
+  - Shan-Chun Hung <schung@nuvoton.com>
+  - Jacky Huang <ychuang3@nuvoton.com>
+
+allOf:
+  - $ref: pinctrl.yaml#
+
+properties:
+  compatible:
+    enum:
+      - nuvoton,ma35d1-pinctrl
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 1
+
+  nuvoton,sys:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle of the system-management node.
+
+  ranges: true
+
+patternProperties:
+  "^gpio@[0-9a-f]+$":
+    type: object
+    additionalProperties: false
+    properties:
+      gpio-controller: true
+
+      '#gpio-cells':
+        const: 2
+
+      reg:
+        maxItems: 1
+
+      clocks:
+        maxItems: 1
+
+      interrupt-controller: true
+
+      '#interrupt-cells':
+        const: 2
+
+      interrupts:
+        description:
+          The interrupt outputs to sysirq.
+        maxItems: 1
+
+    required:
+      - gpio-controller
+      - '#gpio-cells'
+      - reg
+      - clocks
+      - interrupt-controller
+      - '#interrupt-cells'
+      - interrupts
+
+  "^pin-[a-z0-9]+$":
+    type: object
+    description:
+      A pinctrl node should contain at least one subnodes representing the
+      pinctrl groups available on the machine. Each subnode will list the
+      pins it needs, and how they should be configured, with regard to muxer
+      configuration, pullups, drive strength, input enable/disable and input
+      schmitt.
+
+    $ref: pincfg-node.yaml#
+
+    properties:
+      power-source:
+        description: |
+          Valid arguments are described as below:
+          0: power supply of 1.8V
+          1: power supply of 3.3V
+        enum: [0, 1]
+
+      drive-strength-microamp:
+        oneOf:
+          - enum: [ 2900, 4400, 5800, 7300, 8600, 10100, 11500, 13000 ]
+            description: 1.8V I/O driving strength
+          - enum: [ 17100, 25600, 34100, 42800, 48000, 56000, 77000, 82000 ]
+            description: 3.3V I/O driving strength
+
+    unevaluatedProperties: false
+
+  "-grp$":
+    type: object
+    description:
+      Pinctrl node's client devices use subnodes for desired pin configuration.
+      Client device subnodes use below standard properties.
+    properties:
+      nuvoton,pins:
+        description:
+          Each entry consists of 4 parameters and represents the mux and config
+          setting for one pin.
+        $ref: /schemas/types.yaml#/definitions/uint32-matrix
+        minItems: 1
+        items:
+          items:
+            - minimum: 0
+              maximum: 13
+              description:
+                Pin bank.
+            - minimum: 0
+              maximum: 15
+              description:
+                Pin bank index.
+            - minimum: 0
+              maximum: 15
+              description:
+                Mux 0 means GPIO and mux 1 to 15 means the specific device function.
+
+required:
+  - compatible
+  - nuvoton,sys
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
+
+    pinctrl@40040000 {
+        compatible = "nuvoton,ma35d1-pinctrl";
+        #address-cells = <1>;
+        #size-cells = <1>;
+        nuvoton,sys = <&sys>;
+        ranges = <0 0x40040000 0xc00>;
+
+        gpio@0 {
+            reg = <0x0 0x40>;
+            interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+            clocks = <&clk GPA_GATE>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+        };
+
+        uart-grp {
+            uart11-pins {
+                nuvoton,pins = <11 0 2>,
+                               <11 1 2>,
+                               <11 2 2>,
+                               <11 3 2>;
+                bias-disable;
+                power-source = <1>;
+            };
+        };
+    };
-- 
2.34.1


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

^ permalink raw reply related

* [PATCH RFC] arm64: dts: mediatek: mt8183-kodama: Split into base and overlays
From: Chen-Yu Tsai @ 2024-04-09  9:52 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno
  Cc: dianders, Chen-Yu Tsai, devicetree, linux-kernel,
	linux-arm-kernel, linux-mediatek

All the SKUs of Kodama share much of their .dts, as evident of the
inclusion of a common .dtsi file. However this scheme builds each
.dtb file as a complete device tree.

To deduplicate this, make the common .dtsi file a .dts file, and the
SKU specific .dts files into .dtso overlay source files. Have the build
system assemble the SKU specific .dtb files from these components.

The final composite .dtb files increase in size by around 54 kB, or 22.5%,
due to the inclusion of symbols and fixup tables, and extra phandle
properties. This could be slightly reduced by dropping the symbol and
fixup tables after the overlays are fully applied if desired.

However if the bootloader can assemble the end .dtb using the base .dtb
and overlays, and only those are counted, then the combined size
decreases by around 165 kB, or 68.7%.

Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Hi,

This is part of the work I'm looking into and will present at EOSS 2024
in Seattle [1].

The idea is to reorganize device trees so that devices within a common
family, instead of having a common .dtsi file, will share a base DTB
and apply one or more overlays on top. This allows an upstream [2] or
downstream [3] bundling script to be able to deduplicate the base DTB
and get some space savings, however minor they are compared to the
kernel binary executable.

This patch gives a simple conversion, but we could even look into
converting the entire MT8183 Kukui family, which are all based on the
"Kukui" hardware reference design.

There are some issues, hence the RFC:

1. The base .dtb doesn't have a valid board compatible string sequence
   yet. Suppose we used the sequence

     "google,kodama", "mediatek,mt8183"

   for the base .dtb in this conversion, would that be acceptable? The
   base .dtb would act like a fallback.

2. The composite .dtb files grow in size substantially, due to the base
   .dtb file being built with overlay support. The symbols and fixup
   tables could be trimmed out with `fdtput`, but there will still be
   extra phandles, and also nodes with /omit-if-no-ref/ that would
   have been removed.
   For this I could maybe come up with a program to minify the DTB. That
   would also work for existing composite .dtb files in-tree.

3. Such a scheme would require more awareness on the maintainer's part,
   and of the .dtbo authors. The maintainer needs to be aware of how
   the composite .dtb files are assembled. The authors need to know that
   certain constructs, such as /delete-property/ or /delete-node/, won't
   work.

[1] https://eoss24.sched.com/event/1aBGe/second-source-component-probing-on-device-tree-platforms-chen-yu-tsai-google-llc
[2] https://lore.kernel.org/linux-arm-kernel/20240329032836.141899-1-sjg@chromium.org/
[3] https://crrev.com/c/5412876

 arch/arm64/boot/dts/mediatek/Makefile                       | 6 ++++++
 ...ukui-kodama-sku16.dts => mt8183-kukui-kodama-sku16.dtso} | 4 ++--
 ...ui-kodama-sku272.dts => mt8183-kukui-kodama-sku272.dtso} | 4 ++--
 ...ui-kodama-sku288.dts => mt8183-kukui-kodama-sku288.dtso} | 4 ++--
 ...ukui-kodama-sku32.dts => mt8183-kukui-kodama-sku32.dtso} | 4 ++--
 .../{mt8183-kukui-kodama.dtsi => mt8183-kukui-kodama.dts}   | 0
 6 files changed, 14 insertions(+), 8 deletions(-)
 rename arch/arm64/boot/dts/mediatek/{mt8183-kukui-kodama-sku16.dts => mt8183-kukui-kodama-sku16.dtso} (90%)
 rename arch/arm64/boot/dts/mediatek/{mt8183-kukui-kodama-sku272.dts => mt8183-kukui-kodama-sku272.dtso} (90%)
 rename arch/arm64/boot/dts/mediatek/{mt8183-kukui-kodama-sku288.dts => mt8183-kukui-kodama-sku288.dtso} (90%)
 rename arch/arm64/boot/dts/mediatek/{mt8183-kukui-kodama-sku32.dts => mt8183-kukui-kodama-sku32.dtso} (90%)
 rename arch/arm64/boot/dts/mediatek/{mt8183-kukui-kodama.dtsi => mt8183-kukui-kodama.dts} (100%)

diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 9234dadfe1ad..6986d7a2efaa 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -46,6 +46,12 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu-sku22.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku32.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku38.dtb
+
+mt8183-kukui-kodama-sku16-dtbs := mt8183-kukui-kodama.dtb mt8183-kukui-kodama-sku16.dtbo
+mt8183-kukui-kodama-sku272-dtbs := mt8183-kukui-kodama.dtb mt8183-kukui-kodama-sku272.dtbo
+mt8183-kukui-kodama-sku288-dtbs := mt8183-kukui-kodama.dtb mt8183-kukui-kodama-sku288.dtbo
+mt8183-kukui-kodama-sku32-dtbs := mt8183-kukui-kodama.dtb mt8183-kukui-kodama-sku32.dtbo
+
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku16.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku272.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku288.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dtso
similarity index 90%
rename from arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts
rename to arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dtso
index 7213cdcca612..20675de68823 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dtso
@@ -8,9 +8,9 @@
  */
 
 /dts-v1/;
-#include "mt8183-kukui-kodama.dtsi"
+/plugin/;
 
-/ {
+&{/} {
 	model = "MediaTek kodama sku16 board";
 	chassis-type = "tablet";
 	compatible = "google,kodama-sku16", "google,kodama", "mediatek,mt8183";
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dtso
similarity index 90%
rename from arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts
rename to arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dtso
index bbf0cd1aa66d..46ab97a18003 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dtso
@@ -8,9 +8,9 @@
  */
 
 /dts-v1/;
-#include "mt8183-kukui-kodama.dtsi"
+/plugin/;
 
-/ {
+&{/} {
 	model = "MediaTek kodama sku272 board";
 	chassis-type = "tablet";
 	compatible = "google,kodama-sku272", "google,kodama", "mediatek,mt8183";
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dtso
similarity index 90%
rename from arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts
rename to arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dtso
index a429ffeac3bd..e27b56f1826d 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dtso
@@ -8,9 +8,9 @@
  */
 
 /dts-v1/;
-#include "mt8183-kukui-kodama.dtsi"
+/plugin/;
 
-/ {
+&{/} {
 	model = "MediaTek kodama sku288 board";
 	chassis-type = "tablet";
 	compatible = "google,kodama-sku288", "google,kodama", "mediatek,mt8183";
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dtso
similarity index 90%
rename from arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts
rename to arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dtso
index 5a416143b4a0..d9a13ff7abf2 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dts
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dtso
@@ -8,9 +8,9 @@
  */
 
 /dts-v1/;
-#include "mt8183-kukui-kodama.dtsi"
+/plugin/;
 
-/ {
+&{/} {
 	model = "MediaTek kodama sku32 board";
 	chassis-type = "tablet";
 	compatible = "google,kodama-sku32", "google,kodama", "mediatek,mt8183";
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dts
similarity index 100%
rename from arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
rename to arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dts
-- 
2.44.0.478.gd926399ef9-goog


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

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox