summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Marangi2025-12-04 22:13:12 +0000
committerChristian Marangi2026-05-14 18:18:33 +0000
commit6f66bee6ba189d014c9fb5f7834161d157037491 (patch)
tree8d0bf4839f63c89366e1dcefa807f695032de57d
parent530d3329f4d070162c6cd53d6775edb42183f19e (diff)
downloadopenwrt-6f66bee6ba189d014c9fb5f7834161d157037491.tar.gz
airoha: replace I2S patch with upstream pending version
Replace I2S sound patch with upstream pending version. This adds ETDM support and fix various bug in the downstream implementation. (cherry picked from commit 8f1914053b24f56c101057390a0a83707864cf71) [ fix conflict error ] Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
-rw-r--r--target/linux/airoha/patches-6.6/123-01-ASoC-mediatek-move-some-header-to-global-include.patch410
-rw-r--r--target/linux/airoha/patches-6.6/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch876
2 files changed, 721 insertions, 565 deletions
diff --git a/target/linux/airoha/patches-6.6/123-01-ASoC-mediatek-move-some-header-to-global-include.patch b/target/linux/airoha/patches-6.6/123-01-ASoC-mediatek-move-some-header-to-global-include.patch
deleted file mode 100644
index 5016ed7503..0000000000
--- a/target/linux/airoha/patches-6.6/123-01-ASoC-mediatek-move-some-header-to-global-include.patch
+++ /dev/null
@@ -1,410 +0,0 @@
-From 527123b53739a2f73ca924b9c6e2f63dc66739a5 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth@gmail.com>
-Date: Fri, 1 Aug 2025 11:06:56 +0200
-Subject: [PATCH 1/3] ASoC: mediatek: move some header to global include
-
-In preparation for support of Airoha SoC sound system based on Mediatek
-AFE, move some header to global include to prevent having to use complex
-redirection for inclusion.
-
-Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
----
- .../common => include/sound/mediatek}/mtk-afe-fe-dai.h | 0
- .../sound/mediatek}/mtk-afe-platform-driver.h | 0
- sound/soc/mediatek/common/mtk-afe-fe-dai.c | 4 ++--
- sound/soc/mediatek/common/mtk-afe-platform-driver.c | 2 +-
- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 2 +-
- sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 2 +-
- sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt8186/mt8186-misc-control.c | 4 ++--
- sound/soc/mediatek/mt8186/mt8186-mt6366-common.c | 2 +-
- sound/soc/mediatek/mt8186/mt8186-mt6366.c | 2 +-
- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt8188/mt8188-mt6359.c | 2 +-
- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 2 +-
- sound/soc/mediatek/mt8195/mt8195-afe-pcm.c | 4 ++--
- sound/soc/mediatek/mt8195/mt8195-mt6359.c | 2 +-
- sound/soc/mediatek/mt8365/mt8365-afe-pcm.c | 4 ++--
- 22 files changed, 32 insertions(+), 32 deletions(-)
- rename {sound/soc/mediatek/common => include/sound/mediatek}/mtk-afe-fe-dai.h (100%)
- rename {sound/soc/mediatek/common => include/sound/mediatek}/mtk-afe-platform-driver.h (100%)
-
---- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
-+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
-@@ -11,9 +11,9 @@
- #include <linux/pm_runtime.h>
- #include <linux/regmap.h>
- #include <sound/soc.h>
--#include "mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
- #include <sound/pcm_params.h>
--#include "mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
- #include "mtk-base-afe.h"
-
- #define AFE_BASE_END_OFFSET 8
---- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c
-+++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
-@@ -10,7 +10,7 @@
- #include <linux/dma-mapping.h>
- #include <sound/soc.h>
-
--#include "mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
- #include "mtk-base-afe.h"
-
- int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe)
---- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
-+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
-@@ -18,8 +18,8 @@
-
- #include "mt2701-afe-common.h"
- #include "mt2701-afe-clock-ctrl.h"
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- static const struct snd_pcm_hardware mt2701_afe_hardware = {
- .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED
---- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c
-+++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c
-@@ -16,8 +16,8 @@
- #include "mt6797-afe-clk.h"
- #include "mt6797-interconnection.h"
- #include "mt6797-reg.h"
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- enum {
- MTK_AFE_RATE_8K = 0,
---- a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c
-+++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c
-@@ -16,8 +16,8 @@
-
- #include "mt7986-afe-common.h"
- #include "mt7986-reg.h"
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- enum {
- MTK_AFE_RATE_8K = 0,
---- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
-+++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
-@@ -19,8 +19,8 @@
- #include <sound/soc.h>
- #include "mt8173-afe-common.h"
- #include "../common/mtk-base-afe.h"
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- /*****************************************************************************
- * R E G I S T E R D E F I N I T I O N
---- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
-+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
-@@ -18,8 +18,8 @@
- #include "mt8183-afe-clk.h"
- #include "mt8183-interconnection.h"
- #include "mt8183-reg.h"
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- enum {
- MTK_AFE_RATE_8K = 0,
---- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
-+++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
-@@ -16,7 +16,7 @@
-
- #include "../../codecs/da7219.h"
- #include "../../codecs/rt1015.h"
--#include "../common/mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
- #include "mt8183-afe-common.h"
-
- #define DA7219_CODEC_DAI "da7219-hifi"
---- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
-+++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
-@@ -15,7 +15,7 @@
-
- #include "../../codecs/rt1015.h"
- #include "../../codecs/ts3a227e.h"
--#include "../common/mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
- #include "mt8183-afe-common.h"
-
- #define RT1015_CODEC_DAI "rt1015-aif"
---- a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
-+++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c
-@@ -15,8 +15,8 @@
- #include <linux/reset.h>
- #include <sound/soc.h>
-
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- #include "mt8186-afe-common.h"
- #include "mt8186-afe-clk.h"
---- a/sound/soc/mediatek/mt8186/mt8186-misc-control.c
-+++ b/sound/soc/mediatek/mt8186/mt8186-misc-control.c
-@@ -11,8 +11,8 @@
- #include <linux/regmap.h>
- #include <sound/soc.h>
-
--#include "../common/mtk-afe-fe-dai.h"
--#include "../common/mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
- #include "mt8186-afe-common.h"
-
- static const char * const mt8186_sgen_mode_str[] = {
---- a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
-+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
-@@ -9,7 +9,7 @@
- #include <sound/soc.h>
-
- #include "../../codecs/mt6358.h"
--#include "../common/mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
- #include "mt8186-afe-common.h"
- #include "mt8186-mt6366-common.h"
-
---- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
-+++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c
-@@ -24,8 +24,8 @@
- #include "mt8188-afe-common.h"
- #include "mt8188-afe-clk.h"
- #include "mt8188-reg.h"
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- #define MT8188_MEMIF_BUFFER_BYTES_ALIGN (0x40)
- #define MT8188_MEMIF_DL7_MAX_PERIOD_SIZE (0x3fff)
---- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
-+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
-@@ -17,8 +17,8 @@
- #include <linux/reset.h>
- #include <sound/soc.h>
-
--#include "../common/mtk-afe-fe-dai.h"
--#include "../common/mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-
- #include "mt8192-afe-common.h"
- #include "mt8192-afe-clk.h"
---- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
-+++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c
-@@ -20,8 +20,8 @@
- #include "mt8195-afe-common.h"
- #include "mt8195-afe-clk.h"
- #include "mt8195-reg.h"
--#include "../common/mtk-afe-platform-driver.h"
--#include "../common/mtk-afe-fe-dai.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
-
- #define MT8195_MEMIF_BUFFER_BYTES_ALIGN (0x40)
- #define MT8195_MEMIF_DL7_MAX_PERIOD_SIZE (0x3fff)
---- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c
-+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c
-@@ -19,7 +19,7 @@
- #include "../../codecs/mt6359.h"
- #include "../../codecs/rt1011.h"
- #include "../../codecs/rt5682.h"
--#include "../common/mtk-afe-platform-driver.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
- #include "../common/mtk-dsp-sof-common.h"
- #include "../common/mtk-soc-card.h"
- #include "mt8195-afe-clk.h"
---- /dev/null
-+++ b/include/sound/mediatek/mtk-afe-fe-dai.h
-@@ -0,0 +1,53 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * mtk-afe-fe-dais.h -- Mediatek afe fe dai operator definition
-+ *
-+ * Copyright (c) 2016 MediaTek Inc.
-+ * Author: Garlic Tseng <garlic.tseng@mediatek.com>
-+ */
-+
-+#ifndef _MTK_AFE_FE_DAI_H_
-+#define _MTK_AFE_FE_DAI_H_
-+
-+struct snd_soc_dai_ops;
-+struct mtk_base_afe;
-+struct mtk_base_afe_memif;
-+
-+int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
-+ struct snd_soc_dai *dai);
-+void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream,
-+ struct snd_soc_dai *dai);
-+int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params,
-+ struct snd_soc_dai *dai);
-+int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream,
-+ struct snd_soc_dai *dai);
-+int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
-+ struct snd_soc_dai *dai);
-+int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
-+ struct snd_soc_dai *dai);
-+
-+extern const struct snd_soc_dai_ops mtk_afe_fe_ops;
-+
-+int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe);
-+int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id);
-+int mtk_afe_suspend(struct snd_soc_component *component);
-+int mtk_afe_resume(struct snd_soc_component *component);
-+
-+int mtk_memif_set_enable(struct mtk_base_afe *afe, int id);
-+int mtk_memif_set_disable(struct mtk_base_afe *afe, int id);
-+int mtk_memif_set_addr(struct mtk_base_afe *afe, int id,
-+ unsigned char *dma_area,
-+ dma_addr_t dma_addr,
-+ size_t dma_bytes);
-+int mtk_memif_set_channel(struct mtk_base_afe *afe,
-+ int id, unsigned int channel);
-+int mtk_memif_set_rate(struct mtk_base_afe *afe,
-+ int id, unsigned int rate);
-+int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream,
-+ int id, unsigned int rate);
-+int mtk_memif_set_format(struct mtk_base_afe *afe,
-+ int id, snd_pcm_format_t format);
-+int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe,
-+ int id, int pbuf_size);
-+#endif
---- /dev/null
-+++ b/include/sound/mediatek/mtk-afe-platform-driver.h
-@@ -0,0 +1,28 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * mtk-afe-platform-driver.h -- Mediatek afe platform driver definition
-+ *
-+ * Copyright (c) 2016 MediaTek Inc.
-+ * Author: Garlic Tseng <garlic.tseng@mediatek.com>
-+ */
-+
-+#ifndef _MTK_AFE_PLATFORM_DRIVER_H_
-+#define _MTK_AFE_PLATFORM_DRIVER_H_
-+
-+#define AFE_PCM_NAME "mtk-afe-pcm"
-+extern const struct snd_soc_component_driver mtk_afe_pcm_platform;
-+
-+struct mtk_base_afe;
-+struct snd_pcm;
-+struct snd_soc_component;
-+struct snd_soc_pcm_runtime;
-+
-+snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
-+ struct snd_pcm_substream *substream);
-+int mtk_afe_pcm_new(struct snd_soc_component *component,
-+ struct snd_soc_pcm_runtime *rtd);
-+
-+int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe);
-+int mtk_afe_add_sub_dai_control(struct snd_soc_component *component);
-+#endif
-+
---- a/sound/soc/mediatek/common/mtk-afe-fe-dai.h
-+++ /dev/null
-@@ -1,53 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * mtk-afe-fe-dais.h -- Mediatek afe fe dai operator definition
-- *
-- * Copyright (c) 2016 MediaTek Inc.
-- * Author: Garlic Tseng <garlic.tseng@mediatek.com>
-- */
--
--#ifndef _MTK_AFE_FE_DAI_H_
--#define _MTK_AFE_FE_DAI_H_
--
--struct snd_soc_dai_ops;
--struct mtk_base_afe;
--struct mtk_base_afe_memif;
--
--int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
-- struct snd_soc_dai *dai);
--void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream,
-- struct snd_soc_dai *dai);
--int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
-- struct snd_pcm_hw_params *params,
-- struct snd_soc_dai *dai);
--int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream,
-- struct snd_soc_dai *dai);
--int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
-- struct snd_soc_dai *dai);
--int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
-- struct snd_soc_dai *dai);
--
--extern const struct snd_soc_dai_ops mtk_afe_fe_ops;
--
--int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe);
--int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id);
--int mtk_afe_suspend(struct snd_soc_component *component);
--int mtk_afe_resume(struct snd_soc_component *component);
--
--int mtk_memif_set_enable(struct mtk_base_afe *afe, int id);
--int mtk_memif_set_disable(struct mtk_base_afe *afe, int id);
--int mtk_memif_set_addr(struct mtk_base_afe *afe, int id,
-- unsigned char *dma_area,
-- dma_addr_t dma_addr,
-- size_t dma_bytes);
--int mtk_memif_set_channel(struct mtk_base_afe *afe,
-- int id, unsigned int channel);
--int mtk_memif_set_rate(struct mtk_base_afe *afe,
-- int id, unsigned int rate);
--int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream,
-- int id, unsigned int rate);
--int mtk_memif_set_format(struct mtk_base_afe *afe,
-- int id, snd_pcm_format_t format);
--int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe,
-- int id, int pbuf_size);
--#endif
---- a/sound/soc/mediatek/common/mtk-afe-platform-driver.h
-+++ /dev/null
-@@ -1,28 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * mtk-afe-platform-driver.h -- Mediatek afe platform driver definition
-- *
-- * Copyright (c) 2016 MediaTek Inc.
-- * Author: Garlic Tseng <garlic.tseng@mediatek.com>
-- */
--
--#ifndef _MTK_AFE_PLATFORM_DRIVER_H_
--#define _MTK_AFE_PLATFORM_DRIVER_H_
--
--#define AFE_PCM_NAME "mtk-afe-pcm"
--extern const struct snd_soc_component_driver mtk_afe_pcm_platform;
--
--struct mtk_base_afe;
--struct snd_pcm;
--struct snd_soc_component;
--struct snd_soc_pcm_runtime;
--
--snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
-- struct snd_pcm_substream *substream);
--int mtk_afe_pcm_new(struct snd_soc_component *component,
-- struct snd_soc_pcm_runtime *rtd);
--
--int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe);
--int mtk_afe_add_sub_dai_control(struct snd_soc_component *component);
--#endif
--
diff --git a/target/linux/airoha/patches-6.6/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch b/target/linux/airoha/patches-6.6/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch
index 93d2baf5c3..c30791a500 100644
--- a/target/linux/airoha/patches-6.6/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch
+++ b/target/linux/airoha/patches-6.6/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch
@@ -1,94 +1,85 @@
-From 9989af6ed0dba86f57ac4aa1574f9ce9b1e640af Mon Sep 17 00:00:00 2001
+From 131f599fd0464f8e685610d9e24dadd8fbb4ba76 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 31 Jul 2025 15:32:32 +0200
-Subject: [PATCH 2/3] ASoC: airoha: Add AFE and I2S driver for Airoha AN7581
+Subject: [PATCH] ASoC: airoha: Add AFE and machine driver for Airoha AN7581
Add support for the Sound system present on Airoha AN7581 SoC. This is
based on the mediatek AFE drivers.
-Also add the I2S driver to create an actual sound card for the AFE.
+Also add the machine driver to create an actual sound card for the AFE.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
- sound/soc/Kconfig | 1 +
- sound/soc/Makefile | 1 +
- sound/soc/airoha/Kconfig | 19 +
- sound/soc/airoha/Makefile | 2 +
- sound/soc/airoha/an7581/Makefile | 8 +
- sound/soc/airoha/an7581/an7581-afe-common.h | 35 ++
- sound/soc/airoha/an7581/an7581-afe-pcm.c | 455 ++++++++++++++++++++
- sound/soc/airoha/an7581/an7581-i2s.c | 110 +++++
- sound/soc/airoha/an7581/an7581-reg.h | 29 ++
- 9 files changed, 660 insertions(+)
- create mode 100644 sound/soc/airoha/Kconfig
- create mode 100644 sound/soc/airoha/Makefile
- create mode 100644 sound/soc/airoha/an7581/Makefile
- create mode 100644 sound/soc/airoha/an7581/an7581-afe-common.h
- create mode 100644 sound/soc/airoha/an7581/an7581-afe-pcm.c
- create mode 100644 sound/soc/airoha/an7581/an7581-i2s.c
- create mode 100644 sound/soc/airoha/an7581/an7581-reg.h
+ MAINTAINERS | 8 +
+ sound/soc/mediatek/Kconfig | 20 +
+ sound/soc/mediatek/Makefile | 1 +
+ sound/soc/mediatek/an7581/Makefile | 9 +
+ sound/soc/mediatek/an7581/an7581-afe-common.h | 39 ++
+ sound/soc/mediatek/an7581/an7581-afe-pcm.c | 497 ++++++++++++++++++
+ sound/soc/mediatek/an7581/an7581-dai-etdm.c | 407 ++++++++++++++
+ sound/soc/mediatek/an7581/an7581-reg.h | 88 ++++
+ sound/soc/mediatek/an7581/an7581-wm8960.c | 170 ++++++
+ 9 files changed, 1239 insertions(+)
+ create mode 100644 sound/soc/mediatek/an7581/Makefile
+ create mode 100644 sound/soc/mediatek/an7581/an7581-afe-common.h
+ create mode 100644 sound/soc/mediatek/an7581/an7581-afe-pcm.c
+ create mode 100644 sound/soc/mediatek/an7581/an7581-dai-etdm.c
+ create mode 100644 sound/soc/mediatek/an7581/an7581-reg.h
+ create mode 100644 sound/soc/mediatek/an7581/an7581-wm8960.c
---- a/sound/soc/Kconfig
-+++ b/sound/soc/Kconfig
-@@ -78,6 +78,7 @@ config SND_SOC_ACPI
+--- a/sound/soc/mediatek/Kconfig
++++ b/sound/soc/mediatek/Kconfig
+@@ -3,6 +3,26 @@ config SND_SOC_MEDIATEK
+ tristate
+ select REGMAP_MMIO
- # All the supported SoCs
- source "sound/soc/adi/Kconfig"
-+source "sound/soc/airoha/Kconfig"
- source "sound/soc/amd/Kconfig"
- source "sound/soc/apple/Kconfig"
- source "sound/soc/atmel/Kconfig"
---- a/sound/soc/Makefile
-+++ b/sound/soc/Makefile
-@@ -36,6 +36,7 @@ obj-$(CONFIG_SND_SOC) += codecs/
- obj-$(CONFIG_SND_SOC) += generic/
- obj-$(CONFIG_SND_SOC) += apple/
- obj-$(CONFIG_SND_SOC) += adi/
-+obj-$(CONFIG_SND_SOC) += airoha/
- obj-$(CONFIG_SND_SOC) += amd/
- obj-$(CONFIG_SND_SOC) += atmel/
- obj-$(CONFIG_SND_SOC) += au1x/
---- /dev/null
-+++ b/sound/soc/airoha/Kconfig
-@@ -0,0 +1,19 @@
-+# SPDX-License-Identifier: GPL-2.0-only
+config SND_SOC_AN7581
+ tristate "ASoC support for Airoha AN7581 chip"
+ depends on ARCH_AIROHA || COMPILE_TEST
+ select SND_SOC_MEDIATEK
+ help
-+ This adds ASoC driver for Airoha AN7581 boards
++ This adds ASoC platform driver support for Airoha AN7581 chip
+ that can be used with other codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
-+config SND_SOC_AN7581_I2S
-+ tristate "I2S support for Airoha AN7581 chip"
-+ depends on SND_SOC_AN7581
++config SND_SOC_AN7581_WM8960
++ tristate "ASoc Audio driver for Airoha AN7581 with WM8960 codec"
++ depends on SND_SOC_AN7581 && I2C
++ select SND_SOC_WM8960
+ help
-+ This adds I2S driver for Airoha AN7581 boards
-+ that can be used with other codecs.
++ This adds support for ASoC machine driver for Airoha AN7581
++ boards with the WM8960 codecs.
+ Select Y if you have such device.
+ If unsure select "N".
---- /dev/null
-+++ b/sound/soc/airoha/Makefile
-@@ -0,0 +1,2 @@
-+# SPDX-License-Identifier: GPL-2.0
++
+ config SND_SOC_MT2701
+ tristate "ASoC support for Mediatek MT2701 chip"
+ depends on ARCH_MEDIATEK
+--- a/sound/soc/mediatek/Makefile
++++ b/sound/soc/mediatek/Makefile
+@@ -1,5 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-$(CONFIG_SND_SOC_MEDIATEK) += common/
+obj-$(CONFIG_SND_SOC_AN7581) += an7581/
+ obj-$(CONFIG_SND_SOC_MT2701) += mt2701/
+ obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
+ obj-$(CONFIG_SND_SOC_MT7986) += mt7986/
--- /dev/null
-+++ b/sound/soc/airoha/an7581/Makefile
-@@ -0,0 +1,8 @@
++++ b/sound/soc/mediatek/an7581/Makefile
+@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# platform driver
+snd-soc-an7581-afe-y := \
-+ an7581-afe-pcm.o
++ an7581-afe-pcm.o \
++ an7581-dai-etdm.o
+
+obj-$(CONFIG_SND_SOC_AN7581) += snd-soc-an7581-afe.o
-+obj-$(CONFIG_SND_SOC_AN7581_I2S) += an7581-i2s.o
++obj-$(CONFIG_SND_SOC_AN7581_WM8960) += an7581-wm8960.o
--- /dev/null
-+++ b/sound/soc/airoha/an7581/an7581-afe-common.h
-@@ -0,0 +1,35 @@
++++ b/sound/soc/mediatek/an7581/an7581-afe-common.h
+@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * an7581-afe-common.h -- Airoha AN7581 audio driver definitions
@@ -106,7 +97,8 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ AN7581_MEMIF_DL1,
+ AN7581_MEMIF_UL1,
+ AN7581_MEMIF_NUM,
-+ AN7581_DAI_NUM = AN7581_MEMIF_NUM,
++ AN7581_DAI_ETDM = AN7581_MEMIF_NUM,
++ AN7581_DAI_NUM,
+};
+
+enum {
@@ -123,10 +115,13 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+unsigned int an7581_afe_rate_transform(struct device *dev,
+ unsigned int rate);
+
++/* dai register */
++int an7581_dai_etdm_register(struct mtk_base_afe *afe);
++
+#endif
--- /dev/null
-+++ b/sound/soc/airoha/an7581/an7581-afe-pcm.c
-@@ -0,0 +1,455 @@
++++ b/sound/soc/mediatek/an7581/an7581-afe-pcm.c
+@@ -0,0 +1,497 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Airoha ALSA SoC AFE platform driver for AN7581
@@ -139,31 +134,32 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
++#include <linux/reset.h>
+
+#include "an7581-afe-common.h"
+#include "an7581-reg.h"
-+#include <sound/mediatek/mtk-afe-platform-driver.h>
-+#include <sound/mediatek/mtk-afe-fe-dai.h>
++#include "../common/mtk-afe-platform-driver.h"
++#include "../common/mtk-afe-fe-dai.h"
+
+enum {
-+ ARH_AFE_RATE_7K = 16,
+ ARH_AFE_RATE_8K = 0,
-+ ARH_AFE_RATE_11K = 17,
+ ARH_AFE_RATE_12K = 1,
-+ ARH_AFE_RATE_14K = 18,
+ ARH_AFE_RATE_16K = 2,
-+ ARH_AFE_RATE_22K = 19,
+ ARH_AFE_RATE_24K = 3,
-+ ARH_AFE_RATE_29K = 20,
+ ARH_AFE_RATE_32K = 4,
-+ ARH_AFE_RATE_44K = 21,
+ ARH_AFE_RATE_48K = 5,
-+ ARH_AFE_RATE_88K = 22,
+ ARH_AFE_RATE_96K = 6,
-+ ARH_AFE_RATE_176K = 23,
+ ARH_AFE_RATE_192K = 7,
-+ ARH_AFE_RATE_352K = 24,
+ ARH_AFE_RATE_384K = 8,
++ ARH_AFE_RATE_7K = 16,
++ ARH_AFE_RATE_11K = 17,
++ ARH_AFE_RATE_14K = 18,
++ ARH_AFE_RATE_22K = 19,
++ ARH_AFE_RATE_29K = 20,
++ ARH_AFE_RATE_44K = 21,
++ ARH_AFE_RATE_88K = 22,
++ ARH_AFE_RATE_176K = 23,
++ ARH_AFE_RATE_352K = 24,
+};
+
+unsigned int an7581_afe_rate_transform(struct device *dev, unsigned int rate)
@@ -275,7 +271,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ .capture = {
+ .stream_name = "UL1",
+ .channels_min = 1,
-+ .channels_max = 2,
++ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = ARH_PCM_FORMATS,
+ },
@@ -283,6 +279,25 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ },
+};
+
++static const struct snd_soc_dapm_widget an7581_memif_widgets[] = {
++ /* DL */
++ SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0),
++ SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0),
++
++ /* UL */
++ SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0, NULL, 0),
++ SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0, NULL, 0),
++};
++
++static const struct snd_soc_dapm_route an7581_memif_routes[] = {
++ {"I032", NULL, "DL1"},
++ {"I033", NULL, "DL1"},
++ {"UL1", NULL, "O018"},
++ {"UL1", NULL, "O019"},
++ {"O018", NULL, "I150"},
++ {"O019", NULL, "I151"},
++};
++
+static const struct snd_soc_component_driver an7581_afe_pcm_dai_component = {
+ .name = "an7581-afe-pcm-dai",
+};
@@ -299,14 +314,20 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ .fs_maskbit = -1,
+ .mono_reg = -1,
+ .mono_shift = -1,
-+ .hd_reg = -1,
-+ .hd_shift = -1,
++ .hd_reg = AFE_DL1_CON0,
++ .hd_shift = AFE_HD_SHIFT,
+ .enable_reg = AFE_DAC_CON0,
-+ .enable_shift = 17,
++ .enable_shift = AFE_DL1_ENABLE_SHIFT,
+ .msb_reg = -1,
+ .msb_shift = -1,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
++ .pbuf_reg = AFE_DL1_CON0,
++ .pbuf_mask = AFE_PBUF_SIZE_MASK,
++ .pbuf_shift = AFE_PBUF_SIZE_SHIFT,
++ .minlen_reg = AFE_DL1_CON0,
++ .minlen_mask = AFE_MINLEN_MASK,
++ .minlen_shift = AFE_MINLEN_SHIFT,
+ },
+ [AN7581_MEMIF_UL1] = {
+ .name = "UL1",
@@ -319,12 +340,12 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ .fs_maskbit = -1,
+ .mono_reg = -1,
+ .mono_shift = -1,
-+ .hd_reg = -1,
-+ .hd_shift = -1,
++ .hd_reg = AFE_UL1_CON0,
++ .hd_shift = AFE_HD_SHIFT,
+ .enable_reg = AFE_DAC_CON0,
-+ .enable_shift = 1,
-+ .msb_reg = -1,
-+ .msb_shift = -1,
++ .enable_shift = AFE_UL1_ENABLE_SHIFT,
++ .msb_reg = AFE_UL1_CON0,
++ .msb_shift = AFE_MSB_SHIFT,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = -1,
+ },
@@ -333,29 +354,29 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+static const struct mtk_base_irq_data irq_data[AN7581_IRQ_NUM] = {
+ [AN7581_IRQ_0] = {
+ .id = AN7581_IRQ_0,
-+ .irq_cnt_reg = -1,
-+ .irq_cnt_shift = -1,
-+ .irq_cnt_maskbit = -1,
-+ .irq_en_reg = AFE_IRQ1_CON0,
-+ .irq_en_shift = 4,
++ .irq_cnt_reg = AFE_IRQ_CNT,
++ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
++ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
++ .irq_en_reg = AFE_IRQ_CON0,
++ .irq_en_shift = AFE_IRQ_ON_SHIFT,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = -1,
+ .irq_fs_maskbit = -1,
-+ .irq_clr_reg = AFE_IRQ1_CON0,
-+ .irq_clr_shift = 0,
++ .irq_clr_reg = AFE_IRQ_CON0,
++ .irq_clr_shift = AFE_IRQ_CLR_SHIFT,
+ },
+ [AN7581_IRQ_1] = {
+ .id = AN7581_IRQ_1,
-+ .irq_cnt_reg = -1,
-+ .irq_cnt_shift = -1,
-+ .irq_cnt_maskbit = -1,
-+ .irq_en_reg = AFE_IRQ0_CON0,
-+ .irq_en_shift = 4,
++ .irq_cnt_reg = AFE_IRQ1_CNT,
++ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
++ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
++ .irq_en_reg = AFE_IRQ1_CON0,
++ .irq_en_shift = AFE_IRQ_ON_SHIFT,
+ .irq_fs_reg = -1,
+ .irq_fs_shift = -1,
+ .irq_fs_maskbit = -1,
-+ .irq_clr_reg = AFE_IRQ0_CON0,
-+ .irq_clr_shift = 1,
++ .irq_clr_reg = AFE_IRQ1_CON0,
++ .irq_clr_shift = AFE_IRQ_CLR_SHIFT,
+ },
+};
+
@@ -378,9 +399,9 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ regmap_read(afe->regmap, AFE_IRQ_STS, &status);
+
+ if (status & AFE_IRQ_STS_RECORD)
-+ reg = AFE_IRQ0_CON0;
-+ else
+ reg = AFE_IRQ1_CON0;
++ else
++ reg = AFE_IRQ_CON0;
+
+ regmap_set_bits(afe->regmap, reg, BIT(2));
+ regmap_clear_bits(afe->regmap, reg, BIT(2));
@@ -429,18 +450,25 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ dai->dai_drivers = an7581_memif_dai_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(an7581_memif_dai_driver);
+
++ dai->dapm_widgets = an7581_memif_widgets;
++ dai->num_dapm_widgets = ARRAY_SIZE(an7581_memif_widgets);
++ dai->dapm_routes = an7581_memif_routes;
++ dai->num_dapm_routes = ARRAY_SIZE(an7581_memif_routes);
++
+ return 0;
+}
+
+typedef int (*dai_register_cb)(struct mtk_base_afe *);
+static const dai_register_cb dai_register_cbs[] = {
++ an7581_dai_etdm_register,
+ an7581_dai_memif_register,
+};
+
+static int an7581_afe_pcm_dev_probe(struct platform_device *pdev)
+{
-+ struct mtk_base_afe *afe;
+ struct an7581_afe_private *afe_priv;
++ struct reset_control *reset;
++ struct mtk_base_afe *afe;
+ struct device *dev;
+ int i, irq_id, ret;
+
@@ -454,6 +482,15 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ if (!afe->platform_priv)
+ return -ENOMEM;
+
++ reset = devm_reset_control_get_exclusive(dev, NULL);
++ if (IS_ERR(reset))
++ return PTR_ERR(reset);
++
++ /* Global reset I2S */
++ reset_control_assert(reset);
++ usleep_range(10, 20);
++ reset_control_deassert(reset);
++
+ afe_priv = afe->platform_priv;
+ afe->dev = &pdev->dev;
+ dev = afe->dev;
@@ -576,15 +613,516 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ .pm = pm_ptr(&an7581_afe_pm_ops),
+ },
+ .probe = an7581_afe_pcm_dev_probe,
-+ .remove_new = an7581_afe_pcm_dev_remove,
++ .remove = an7581_afe_pcm_dev_remove,
+};
+module_platform_driver(an7581_afe_pcm_driver);
+
+MODULE_DESCRIPTION("Airoha SoC AFE platform driver for ALSA AN7581");
+MODULE_LICENSE("GPL");
--- /dev/null
-+++ b/sound/soc/airoha/an7581/an7581-i2s.c
-@@ -0,0 +1,110 @@
++++ b/sound/soc/mediatek/an7581/an7581-dai-etdm.c
+@@ -0,0 +1,407 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Airoha ALSA SoC Audio DAI eTDM Control
++ *
++ */
++
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++#include <linux/regmap.h>
++#include <sound/pcm_params.h>
++#include "an7581-afe-common.h"
++#include "an7581-reg.h"
++
++#define HOPPING_CLK 0
++#define APLL_CLK 1
++#define MTK_DAI_ETDM_FORMAT_I2S 0
++#define MTK_DAI_ETDM_FORMAT_DSPA 4
++#define MTK_DAI_ETDM_FORMAT_DSPB 5
++
++enum {
++ MTK_ETDM_RATE_8K = 0,
++ MTK_ETDM_RATE_12K = 1,
++ MTK_ETDM_RATE_16K = 2,
++ MTK_ETDM_RATE_24K = 3,
++ MTK_ETDM_RATE_32K = 4,
++ MTK_ETDM_RATE_48K = 5,
++ MTK_ETDM_RATE_96K = 6,
++ MTK_ETDM_RATE_192K = 7,
++ MTK_ETDM_RATE_384K = 8,
++ MTK_ETDM_RATE_7K = 16,
++ MTK_ETDM_RATE_11K = 17,
++ MTK_ETDM_RATE_14K = 18,
++ MTK_ETDM_RATE_22K = 19,
++ MTK_ETDM_RATE_29K = 20,
++ MTK_ETDM_RATE_44K = 21,
++ MTK_ETDM_RATE_88K = 22,
++ MTK_ETDM_RATE_176K = 23,
++ MTK_ETDM_RATE_352K = 24,
++};
++
++struct mtk_dai_etdm_priv {
++ bool bck_inv;
++ bool lrck_inv;
++ bool slave_mode;
++ unsigned int format;
++};
++
++static unsigned int an7581_etdm_rate_transform(struct device *dev, unsigned int rate)
++{
++ switch (rate) {
++ case 7350:
++ return MTK_ETDM_RATE_7K;
++ case 8000:
++ return MTK_ETDM_RATE_8K;
++ case 11025:
++ return MTK_ETDM_RATE_11K;
++ case 12000:
++ return MTK_ETDM_RATE_12K;
++ case 14700:
++ return MTK_ETDM_RATE_14K;
++ case 16000:
++ return MTK_ETDM_RATE_16K;
++ case 22050:
++ return MTK_ETDM_RATE_22K;
++ case 24000:
++ return MTK_ETDM_RATE_24K;
++ case 29400:
++ return MTK_ETDM_RATE_29K;
++ case 32000:
++ return MTK_ETDM_RATE_32K;
++ case 44100:
++ return MTK_ETDM_RATE_44K;
++ case 48000:
++ return MTK_ETDM_RATE_48K;
++ case 88200:
++ return MTK_ETDM_RATE_88K;
++ case 96000:
++ return MTK_ETDM_RATE_96K;
++ case 176400:
++ return MTK_ETDM_RATE_176K;
++ case 192000:
++ return MTK_ETDM_RATE_192K;
++ case 352800:
++ return MTK_ETDM_RATE_352K;
++ case 384000:
++ return MTK_ETDM_RATE_384K;
++ default:
++ dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n",
++ __func__, rate, MTK_ETDM_RATE_48K);
++ return MTK_ETDM_RATE_48K;
++ }
++}
++
++static int get_etdm_wlen(unsigned int bitwidth)
++{
++ return bitwidth <= 16 ? 16 : 32;
++}
++
++static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = {
++ /* DL */
++ SND_SOC_DAPM_MIXER("I150", SND_SOC_NOPM, 0, 0, NULL, 0),
++ SND_SOC_DAPM_MIXER("I151", SND_SOC_NOPM, 0, 0, NULL, 0),
++
++ /* UL */
++ SND_SOC_DAPM_MIXER("O124", SND_SOC_NOPM, 0, 0, NULL, 0),
++ SND_SOC_DAPM_MIXER("O125", SND_SOC_NOPM, 0, 0, NULL, 0),
++};
++
++static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = {
++ {"I150", NULL, "ETDM Capture"},
++ {"I151", NULL, "ETDM Capture"},
++ {"ETDM Playback", NULL, "O124"},
++ {"ETDM Playback", NULL, "O125"},
++ {"O124", NULL, "I032"},
++ {"O125", NULL, "I033"},
++};
++
++/* dai ops */
++static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream,
++ struct snd_soc_dai *dai)
++{
++ return 0;
++}
++
++static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream,
++ struct snd_soc_dai *dai)
++{
++}
++
++static unsigned int get_etdm_ch_fixup(unsigned int channels)
++{
++ if (channels > 16)
++ return 24;
++ else if (channels > 8)
++ return 16;
++ else if (channels > 4)
++ return 8;
++ else if (channels > 2)
++ return 4;
++ else
++ return 2;
++}
++
++static int mtk_dai_etdm_config(struct mtk_base_afe *afe,
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai,
++ int stream)
++{
++ struct an7581_afe_private *afe_priv = afe->platform_priv;
++ struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
++ unsigned int rate = params_rate(params);
++ unsigned int etdm_rate = an7581_etdm_rate_transform(afe->dev, rate);
++ unsigned int channels = params_channels(params);
++ unsigned int bit_width = params_width(params);
++ unsigned int wlen = get_etdm_wlen(bit_width);
++ unsigned int val = 0;
++ unsigned int mask = 0;
++
++ dev_dbg(afe->dev, "%s(), stream %d, rate %u, bitwidth %u\n",
++ __func__, stream, rate, bit_width);
++
++ /* CON0 */
++ mask |= ETDM_BIT_LEN;
++ val |= FIELD_PREP(ETDM_BIT_LEN, bit_width - 1);
++ mask |= ETDM_WRD_LEN;
++ val |= FIELD_PREP(ETDM_WRD_LEN, wlen - 1);
++ mask |= ETDM_FMT;
++ val |= FIELD_PREP(ETDM_FMT, etdm_data->format);
++ mask |= ETDM_CH_NUM;
++ val |= FIELD_PREP(ETDM_CH_NUM, get_etdm_ch_fixup(channels) - 1);
++ mask |= ETDM_MODE;
++ val |= ETDM_MODE;
++
++ switch (stream) {
++ case SNDRV_PCM_STREAM_PLAYBACK:
++ /* set ETDM_OUT1_CON0 */
++ regmap_update_bits(afe->regmap, ETDM_OUT1_CON0, mask, val);
++
++ /* set ETDM_OUT1_CON1 */
++ regmap_update_bits(afe->regmap, ETDM_OUT1_CON1,
++ EDTM_DIRECT_INPUT_MASTER_BCK |
++ EDTM_LRCK_AUTO_MODE |
++ EDTM_CKEN_SEL | EDTM_LRCK_AUTO_OFF |
++ EDTM_INITIAL_POINT | EDTM_INITIAL_COUNT,
++ EDTM_DIRECT_INPUT_MASTER_BCK |
++ EDTM_LRCK_AUTO_MODE |
++ EDTM_CKEN_SEL | EDTM_LRCK_AUTO_OFF |
++ FIELD_PREP(EDTM_INITIAL_POINT, 14) |
++ FIELD_PREP(EDTM_INITIAL_COUNT, 14));
++
++ /* set ETDM_OUT1_CON4 */
++ regmap_update_bits(afe->regmap, ETDM_OUT1_CON4, OUT_SEL_FS,
++ FIELD_PREP(OUT_SEL_FS, etdm_rate));
++ break;
++ case SNDRV_PCM_STREAM_CAPTURE:
++ /* set ETDM_IN1_CON0 */
++ regmap_update_bits(afe->regmap, ETDM_IN1_CON0, mask, val);
++ regmap_set_bits(afe->regmap, ETDM_IN1_CON0, ETDM_SYNC);
++
++ /* set ETDM_IN1_CON1 */
++ regmap_update_bits(afe->regmap, ETDM_IN1_CON1,
++ EDTM_LRCK_AUTO_MODE |
++ EDTM_CKEN_SEL | EDTM_LRCK_AUTO_OFF |
++ EDTM_INITIAL_POINT | EDTM_INITIAL_COUNT,
++ EDTM_LRCK_AUTO_MODE |
++ EDTM_CKEN_SEL | EDTM_LRCK_AUTO_OFF |
++ FIELD_PREP(EDTM_INITIAL_POINT, 14) |
++ FIELD_PREP(EDTM_INITIAL_COUNT, 14));
++
++ /* set ETDM_IN1_CON3 */
++ regmap_update_bits(afe->regmap, ETDM_IN1_CON3, IN_SEL_FS,
++ FIELD_PREP(IN_SEL_FS, etdm_rate));
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai)
++{
++ unsigned int rate = params_rate(params);
++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
++
++ regmap_update_bits(afe->regmap, ETDM_COWORK_CON0,
++ EDTM_IN1_SLAVE_SEL, FIELD_PREP(EDTM_IN1_SLAVE_SEL, 1));
++ regmap_update_bits(afe->regmap, ETDM_COWORK_CON0,
++ EDTM_OUT1_SLAVE_SEL, FIELD_PREP(EDTM_OUT1_SLAVE_SEL, 1));
++ regmap_update_bits(afe->regmap, ETDM_COWORK_CON1,
++ EDTM_IN1_SDATA0_SEL, FIELD_PREP(EDTM_IN1_SDATA0_SEL, 0));
++
++ switch (rate) {
++ case 8000:
++ case 12000:
++ case 16000:
++ case 24000:
++ case 32000:
++ case 48000:
++ case 96000:
++ case 192000:
++ mtk_dai_etdm_config(afe, params, dai, substream->stream);
++ return 0;
++ default:
++ dev_err(afe->dev,
++ "Sample rate %d invalid. Supported rates: 8/12/16/24/32/48/96/192 kHz\n",
++ rate);
++ return -EINVAL;
++ }
++}
++
++static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd,
++ struct snd_soc_dai *dai)
++{
++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
++
++ dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id);
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ regmap_set_bits(afe->regmap, ETDM_IN1_CON0, ETDM_EN);
++ regmap_set_bits(afe->regmap, ETDM_OUT1_CON0, ETDM_EN);
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ regmap_clear_bits(afe->regmap, ETDM_IN1_CON0, ETDM_EN);
++ regmap_clear_bits(afe->regmap, ETDM_OUT1_CON0, ETDM_EN);
++ break;
++ default:
++ break;
++ }
++
++ return 0;
++}
++
++static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
++{
++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
++ struct an7581_afe_private *afe_priv = afe->platform_priv;
++ struct mtk_dai_etdm_priv *etdm_data;
++ void *priv_data;
++
++ switch (dai->id) {
++ case AN7581_DAI_ETDM:
++ break;
++ default:
++ dev_warn(afe->dev, "%s(), id %d not support\n",
++ __func__, dai->id);
++ return -EINVAL;
++ }
++
++ priv_data = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_etdm_priv),
++ GFP_KERNEL);
++ if (!priv_data)
++ return -ENOMEM;
++
++ afe_priv->dai_priv[dai->id] = priv_data;
++ etdm_data = afe_priv->dai_priv[dai->id];
++
++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++ case SND_SOC_DAIFMT_I2S:
++ etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S;
++ break;
++ case SND_SOC_DAIFMT_DSP_A:
++ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA;
++ break;
++ case SND_SOC_DAIFMT_DSP_B:
++ etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
++ case SND_SOC_DAIFMT_NB_NF:
++ etdm_data->bck_inv = false;
++ etdm_data->lrck_inv = false;
++ break;
++ case SND_SOC_DAIFMT_NB_IF:
++ etdm_data->bck_inv = false;
++ etdm_data->lrck_inv = true;
++ break;
++ case SND_SOC_DAIFMT_IB_NF:
++ etdm_data->bck_inv = true;
++ etdm_data->lrck_inv = false;
++ break;
++ case SND_SOC_DAIFMT_IB_IF:
++ etdm_data->bck_inv = true;
++ etdm_data->lrck_inv = true;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++ case SND_SOC_DAIFMT_CBP_CFP:
++ etdm_data->slave_mode = true;
++ break;
++ case SND_SOC_DAIFMT_CBC_CFC:
++ etdm_data->slave_mode = false;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static const struct snd_soc_dai_ops mtk_dai_etdm_ops = {
++ .startup = mtk_dai_etdm_startup,
++ .shutdown = mtk_dai_etdm_shutdown,
++ .hw_params = mtk_dai_etdm_hw_params,
++ .trigger = mtk_dai_etdm_trigger,
++ .set_fmt = mtk_dai_etdm_set_fmt,
++};
++
++/* dai driver */
++#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
++ SNDRV_PCM_FMTBIT_S24_LE |\
++ SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = {
++ {
++ .name = "ETDM",
++ .id = AN7581_DAI_ETDM,
++ .capture = {
++ .stream_name = "ETDM Capture",
++ .channels_min = 1,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_8000_192000,
++ .formats = MTK_ETDM_FORMATS,
++ },
++ .playback = {
++ .stream_name = "ETDM Playback",
++ .channels_min = 1,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_8000_192000,
++ .formats = MTK_ETDM_FORMATS,
++ },
++ .ops = &mtk_dai_etdm_ops,
++ .symmetric_rate = 1,
++ .symmetric_sample_bits = 1,
++ },
++};
++
++int an7581_dai_etdm_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_etdm_driver;
++ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver);
++
++ dai->dapm_widgets = mtk_dai_etdm_widgets;
++ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets);
++ dai->dapm_routes = mtk_dai_etdm_routes;
++ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes);
++
++ return 0;
++}
+--- /dev/null
++++ b/sound/soc/mediatek/an7581/an7581-reg.h
+@@ -0,0 +1,88 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * an7581-reg.h -- Airoha AN7581 audio driver reg definition
++ */
++
++#ifndef _AN7581_REG_H_
++#define _AN7581_REG_H_
++
++#define AFE_DAC_CON0 0x0
++#define AFE_DL1_ENABLE_SHIFT 17
++#define AFE_UL1_ENABLE_SHIFT 1
++
++#define ETDM_COWORK_CON0 0x4c
++#define EDTM_IN1_SLAVE_SEL GENMASK(27, 24)
++#define EDTM_OUT1_SLAVE_SEL GENMASK(11, 8)
++#define ETDM_COWORK_CON1 0x50
++#define EDTM_IN1_SDATA0_SEL GENMASK(3, 0)
++#define ETDM_IN1_CON0 0x5c
++#define EDTM_LRCK_AUTO_MODE BIT(29)
++#define ETDM_CH_NUM GENMASK(27, 23)
++#define ETDM_WRD_LEN GENMASK(20, 16)
++#define ETDM_BIT_LEN GENMASK(15, 11)
++#define ETDM_FMT GENMASK(8, 6)
++#define ETDM_MODE BIT(5)
++#define ETDM_SYNC BIT(1)
++#define ETDM_EN BIT(0)
++#define ETDM_IN1_CON1 0x60
++#define ETDM_IN1_CON2 0x64
++#define IN_CLK_SRC GENMASK(12, 10)
++#define ETDM_IN1_CON3 0x68
++#define IN_SEL_FS GENMASK(30, 26)
++#define ETDM_IN1_CON4 0x6c
++#define IN_RELATCH GENMASK(24, 20)
++#define IN_CLK_INV BIT(18)
++#define ETDM_IN1_CON5 0x70
++#define ETDM_IN1_CON6 0x74
++#define ETDM_OUT1_CON0 0x7c
++#define ETDM_OUT1_CON1 0x80
++#define EDTM_DIRECT_INPUT_MASTER_BCK BIT(30)
++#define EDTM_CKEN_SEL BIT(12)
++#define EDTM_LRCK_AUTO_OFF BIT(10)
++#define EDTM_INITIAL_POINT GENMASK(9, 5)
++#define EDTM_INITIAL_COUNT GENMASK(4, 0)
++#define ETDM_OUT1_CON2 0x84
++#define ETDM_OUT1_CON3 0x88
++#define ETDM_OUT1_CON4 0x8c
++#define OUT_RELATCH GENMASK(28, 24)
++#define OUT_CLK_SRC GENMASK(8, 6)
++#define OUT_SEL_FS GENMASK(4, 0)
++#define ETDM_OUT1_CON5 0x90
++#define ETDM_CLK_DIV BIT(12)
++#define OUT_CLK_INV BIT(9)
++#define ETDM_OUT1_CON6 0x94
++#define ETDM_OUT1_CON7 0x98
++
++#define AFE_DL1_BASE 0xa8
++#define AFE_DL1_END 0xb0
++#define AFE_DL1_CUR 0xac
++#define AFE_DL1_CON0 0xb4
++#define AFE_PBUF_SIZE_SHIFT 16
++#define AFE_PBUF_SIZE_MASK GENMASK(1, 0)
++#define AFE_MINLEN_SHIFT 8
++#define AFE_MINLEN_MASK GENMASK(3, 0)
++#define AFE_HD_SHIFT 5
++
++#define AFE_UL1_BASE 0xc4
++#define AFE_UL1_END 0xc8
++#define AFE_UL1_CUR 0xcc
++#define AFE_UL1_CON0 0xd0
++#define AFE_MSB_SHIFT 6
++
++#define AFE_IRQ_CON0 0xe4
++#define AFE_IRQ_ON_SHIFT 0
++#define AFE_IRQ_CLR_SHIFT 1
++#define AFE_IRQ_CNT 0xe8
++#define AFE_IRQ_CNT_SHIFT 0
++#define AFE_IRQ_CNT_MASK GENMASK(31, 0)
++
++#define AFE_IRQ_STS 0xf8
++#define AFE_IRQ_STS_PLAY BIT(1)
++#define AFE_IRQ_STS_RECORD BIT(0)
++
++#define AFE_IRQ1_CON0 0x100
++#define AFE_IRQ1_CNT 0x104
++
++#define AFE_MAX_REGISTER AFE_IRQ1_CON0
++
++#endif
+--- /dev/null
++++ b/sound/soc/mediatek/an7581/an7581-wm8960.c
+@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Airoha ALSA SoC I2S platform driver for AN7581
@@ -596,6 +1134,16 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+
+#include "an7581-afe-common.h"
+
++static const struct snd_soc_dapm_widget an7581_wm8960_widgets[] = {
++ SND_SOC_DAPM_HP("Headphone", NULL),
++ SND_SOC_DAPM_MIC("AMIC", NULL),
++};
++
++static const struct snd_kcontrol_new an7581_wm8960_controls[] = {
++ SOC_DAPM_PIN_SWITCH("Headphone"),
++ SOC_DAPM_PIN_SWITCH("AMIC"),
++};
++
+SND_SOC_DAILINK_DEFS(playback,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
@@ -606,10 +1154,16 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
-+static struct snd_soc_dai_link an7581_i2s_dai_links[] = {
++SND_SOC_DAILINK_DEFS(codec,
++ DAILINK_COMP_ARRAY(COMP_CPU("ETDM")),
++ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8960-hifi")),
++ DAILINK_COMP_ARRAY(COMP_EMPTY()));
++
++static struct snd_soc_dai_link an7581_wm8960_dai_links[] = {
++ /* FE */
+ {
-+ .name = "an7581-i2s-playback",
-+ .stream_name = "an7581-i2s-playback",
++ .name = "wm8960-playback",
++ .stream_name = "wm8960-playback",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .dynamic = 0,
@@ -617,29 +1171,43 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ SND_SOC_DAILINK_REG(playback),
+ },
+ {
-+ .name = "an7581-i2s-capture",
-+ .stream_name = "an7581-i2s-capture",
++ .name = "wm8960-capture",
++ .stream_name = "wm8960-capture",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .dynamic = 0,
+ .capture_only = 1,
+ SND_SOC_DAILINK_REG(capture),
+ },
++ /* BE */
++ {
++ .name = "wm8960-codec",
++ .no_pcm = 1,
++ .dai_fmt = SND_SOC_DAIFMT_I2S |
++ SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBC_CFC |
++ SND_SOC_DAIFMT_GATED,
++ SND_SOC_DAILINK_REG(codec),
++ },
+};
+
-+static struct snd_soc_card an7581_i2s_card = {
-+ .name = "an7581-i2s",
++static struct snd_soc_card an7581_wm8960_card = {
++ .name = "an7581-wm8960",
+ .owner = THIS_MODULE,
-+ .dai_link = an7581_i2s_dai_links,
-+ .num_links = ARRAY_SIZE(an7581_i2s_dai_links),
++ .dai_link = an7581_wm8960_dai_links,
++ .num_links = ARRAY_SIZE(an7581_wm8960_dai_links),
++ .controls = an7581_wm8960_controls,
++ .num_controls = ARRAY_SIZE(an7581_wm8960_controls),
++ .dapm_widgets = an7581_wm8960_widgets,
++ .num_dapm_widgets = ARRAY_SIZE(an7581_wm8960_widgets),
+};
+
-+static int an7581_i2s_machine_probe(struct platform_device *pdev)
++static int an7581_wm8960_machine_probe(struct platform_device *pdev)
+{
-+ struct snd_soc_card *card = &an7581_i2s_card;
-+ struct device_node *platform_dai_node;
++ struct device_node *platform_dai_node, *codec_dai_node;
++ struct snd_soc_card *card = &an7581_wm8960_card;
++ struct device_node *platform, *codec;
+ struct snd_soc_dai_link *dai_link;
-+ struct device_node *platform;
+ int ret, i;
+
+ card->dev = &pdev->dev;
@@ -665,6 +1233,35 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+ dai_link->platforms->of_node = platform_dai_node;
+ }
+
++ codec = of_get_child_by_name(pdev->dev.of_node, "codec");
++
++ if (codec) {
++ codec_dai_node = of_parse_phandle(codec, "sound-dai", 0);
++ of_node_put(codec);
++
++ if (!codec_dai_node) {
++ of_node_put(platform_dai_node);
++ dev_err(&pdev->dev, "Failed to parse codec/sound-dai property\n");
++ return -EINVAL;
++ }
++ } else {
++ of_node_put(platform_dai_node);
++ dev_err(&pdev->dev, "Property 'codec' missing or invalid\n");
++ return -EINVAL;
++ }
++
++ for_each_card_prelinks(card, i, dai_link) {
++ if (dai_link->codecs->name)
++ continue;
++ dai_link->codecs->of_node = codec_dai_node;
++ }
++
++ ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
++ if (ret) {
++ dev_err(&pdev->dev, "Failed to parse audio-routing: %d\n", ret);
++ goto err_of_node_put;
++ }
++
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
@@ -675,55 +1272,24 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+
+err_of_node_put:
+ of_node_put(platform_dai_node);
++ of_node_put(codec_dai_node);
+ return ret;
+}
+
-+static const struct of_device_id an7581_i2s_machine_dt_match[] = {
-+ { .compatible = "airoha,an7581-i2s" },
++static const struct of_device_id an7581_wm8960_machine_dt_match[] = {
++ { .compatible = "airoha,an7581-wm8960-sound" },
+ { /* sentinel */ }
+};
-+MODULE_DEVICE_TABLE(of, an7581_i2s_machine_dt_match);
++MODULE_DEVICE_TABLE(of, an7581_wm8960_machine_dt_match);
+
-+static struct platform_driver an7581_i2s_driver = {
++static struct platform_driver an7581_wm8960_driver = {
+ .driver = {
-+ .name = "an7581-i2s",
-+ .of_match_table = an7581_i2s_machine_dt_match,
++ .name = "an7581-wm8960",
++ .of_match_table = an7581_wm8960_machine_dt_match,
+ },
-+ .probe = an7581_i2s_machine_probe,
++ .probe = an7581_wm8960_machine_probe,
+};
-+module_platform_driver(an7581_i2s_driver);
++module_platform_driver(an7581_wm8960_driver);
+
+MODULE_DESCRIPTION("Airoha SoC I2S platform driver for ALSA AN7581");
+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/sound/soc/airoha/an7581/an7581-reg.h
-@@ -0,0 +1,29 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * an7581-reg.h -- Airoha AN7581 audio driver reg definition
-+ */
-+
-+#ifndef _AN7581_REG_H_
-+#define _AN7581_REG_H_
-+
-+#define AFE_DAC_CON0 0x0
-+
-+#define AFE_DL1_BASE 0xa8
-+#define AFE_DL1_END 0xac
-+#define AFE_DL1_CUR 0xb0
-+
-+#define AFE_UL1_BASE 0xc4
-+#define AFE_UL1_END 0xc8
-+#define AFE_UL1_CUR 0xcc
-+
-+#define AFE_IRQ0_CON0 0xe4
-+
-+#define AFE_IRQ_STS 0xf8
-+#define AFE_IRQ_STS_PLAY BIT(1)
-+#define AFE_IRQ_STS_RECORD BIT(0)
-+
-+#define AFE_IRQ1_CON0 0x100
-+
-+#define AFE_MAX_REGISTER AFE_IRQ1_CON0
-+
-+#endif