ASoC: mediatek: mt8186: add platform driver

Add mt8186 platform and affiliated driver.

Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20220718162204.26238-3-jiaxin.yu@mediatek.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Jiaxin Yu 2022-07-19 00:21:58 +08:00 committed by Mark Brown
parent 16824dffcf
commit 097e874ad3
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
8 changed files with 3485 additions and 2 deletions

View File

@ -152,6 +152,18 @@ config SND_SOC_MT8183_DA7219_MAX98357A
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MT8186
tristate "ASoC support for Mediatek MT8186 chip"
depends on ARCH_MEDIATEK || COMPILE_TEST
depends on COMMON_CLK
select SND_SOC_MEDIATEK
select MFD_SYSCON if SND_SOC_MT6358
help
This adds ASoC driver for Mediatek MT8186 boards
that can be used with other codecs.
Select Y if you have such device.
If unsure select "N".
config SND_SOC_MTK_BTCVSD
tristate "ALSA BT SCO CVSD/MSBC Driver"
help

View File

@ -4,5 +4,6 @@ obj-$(CONFIG_SND_SOC_MT2701) += mt2701/
obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
obj-$(CONFIG_SND_SOC_MT8186) += mt8186/
obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
obj-$(CONFIG_SND_SOC_MT8195) += mt8195/

View File

@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0
# platform driver
snd-soc-mt8186-afe-objs := \
mt8186-afe-pcm.o \
mt8186-audsys-clk.o \
mt8186-afe-clk.o \
mt8186-afe-gpio.o \
mt8186-dai-adda.o \
mt8186-afe-control.o \
mt8186-dai-i2s.o \
mt8186-dai-hw-gain.o \
mt8186-dai-pcm.o \
mt8186-dai-src.o \
mt8186-dai-hostless.o \
mt8186-dai-tdm.o \
mt8186-misc-control.o \
obj-$(CONFIG_SND_SOC_MT8186) += snd-soc-mt8186-afe.o

View File

@ -645,7 +645,8 @@ int mt8186_init_clock(struct mtk_base_afe *afe)
return 0;
}
void mt8186_deinit_clock(struct mtk_base_afe *afe)
void mt8186_deinit_clock(void *priv)
{
struct mtk_base_afe *afe = priv;
mt8186_audsys_clk_unregister(afe);
}

View File

@ -81,7 +81,7 @@ enum {
struct mtk_base_afe;
int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id);
int mt8186_init_clock(struct mtk_base_afe *afe);
void mt8186_deinit_clock(struct mtk_base_afe *afe);
void mt8186_deinit_clock(void *priv);
int mt8186_afe_enable_cgs(struct mtk_base_afe *afe);
void mt8186_afe_disable_cgs(struct mtk_base_afe *afe);
int mt8186_afe_enable_clock(struct mtk_base_afe *afe);

View File

@ -0,0 +1,195 @@
/* SPDX-License-Identifier: GPL-2.0
*
* mt8186-afe-common.h -- Mediatek 8186 audio driver definitions
*
* Copyright (c) 2022 MediaTek Inc.
* Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
*/
#ifndef _MT_8186_AFE_COMMON_H_
#define _MT_8186_AFE_COMMON_H_
#include <sound/soc.h>
#include <linux/list.h>
#include <linux/regmap.h>
#include "mt8186-reg.h"
#include "../common/mtk-base-afe.h"
enum {
MT8186_MEMIF_DL1,
MT8186_MEMIF_DL12,
MT8186_MEMIF_DL2,
MT8186_MEMIF_DL3,
MT8186_MEMIF_DL4,
MT8186_MEMIF_DL5,
MT8186_MEMIF_DL6,
MT8186_MEMIF_DL7,
MT8186_MEMIF_DL8,
MT8186_MEMIF_VUL12,
MT8186_MEMIF_VUL2,
MT8186_MEMIF_VUL3,
MT8186_MEMIF_VUL4,
MT8186_MEMIF_VUL5,
MT8186_MEMIF_VUL6,
MT8186_MEMIF_AWB,
MT8186_MEMIF_AWB2,
MT8186_MEMIF_NUM,
MT8186_DAI_ADDA = MT8186_MEMIF_NUM,
MT8186_DAI_AP_DMIC,
MT8186_DAI_CONNSYS_I2S,
MT8186_DAI_I2S_0,
MT8186_DAI_I2S_1,
MT8186_DAI_I2S_2,
MT8186_DAI_I2S_3,
MT8186_DAI_HW_GAIN_1,
MT8186_DAI_HW_GAIN_2,
MT8186_DAI_SRC_1,
MT8186_DAI_SRC_2,
MT8186_DAI_PCM,
MT8186_DAI_TDM_IN,
MT8186_DAI_HOSTLESS_LPBK,
MT8186_DAI_HOSTLESS_FM,
MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO,
MT8186_DAI_HOSTLESS_SRC_AAUDIO,
MT8186_DAI_HOSTLESS_SRC_1,
MT8186_DAI_HOSTLESS_SRC_BARGEIN,
MT8186_DAI_HOSTLESS_UL1,
MT8186_DAI_HOSTLESS_UL2,
MT8186_DAI_HOSTLESS_UL3,
MT8186_DAI_HOSTLESS_UL5,
MT8186_DAI_HOSTLESS_UL6,
MT8186_DAI_NUM,
};
#define MT8186_RECORD_MEMIF MT8186_MEMIF_VUL12
#define MT8186_ECHO_REF_MEMIF MT8186_MEMIF_AWB
#define MT8186_PRIMARY_MEMIF MT8186_MEMIF_DL1
#define MT8186_FAST_MEMIF MT8186_MEMIF_DL2
#define MT8186_DEEP_MEMIF MT8186_MEMIF_DL3
#define MT8186_VOIP_MEMIF MT8186_MEMIF_DL12
#define MT8186_MMAP_DL_MEMIF MT8186_MEMIF_DL5
#define MT8186_MMAP_UL_MEMIF MT8186_MEMIF_VUL5
#define MT8186_BARGEIN_MEMIF MT8186_MEMIF_AWB
enum {
MT8186_IRQ_0,
MT8186_IRQ_1,
MT8186_IRQ_2,
MT8186_IRQ_3,
MT8186_IRQ_4,
MT8186_IRQ_5,
MT8186_IRQ_6,
MT8186_IRQ_7,
MT8186_IRQ_8,
MT8186_IRQ_9,
MT8186_IRQ_10,
MT8186_IRQ_11,
MT8186_IRQ_12,
MT8186_IRQ_13,
MT8186_IRQ_14,
MT8186_IRQ_15,
MT8186_IRQ_16,
MT8186_IRQ_17,
MT8186_IRQ_18,
MT8186_IRQ_19,
MT8186_IRQ_20,
MT8186_IRQ_21,
MT8186_IRQ_22,
MT8186_IRQ_23,
MT8186_IRQ_24,
MT8186_IRQ_25,
MT8186_IRQ_26,
MT8186_IRQ_NUM,
};
enum {
MT8186_AFE_IRQ_DIR_MCU = 0,
MT8186_AFE_IRQ_DIR_DSP,
MT8186_AFE_IRQ_DIR_BOTH,
};
enum {
MTKAIF_PROTOCOL_1 = 0,
MTKAIF_PROTOCOL_2,
MTKAIF_PROTOCOL_2_CLK_P2,
};
enum {
MTK_AFE_ADDA_DL_GAIN_MUTE = 0,
MTK_AFE_ADDA_DL_GAIN_NORMAL = 0xf74f,
/* SA suggest apply -0.3db to audio/speech path */
};
#define MTK_SPK_I2S_0_STR "MTK_SPK_I2S_0"
#define MTK_SPK_I2S_1_STR "MTK_SPK_I2S_1"
#define MTK_SPK_I2S_2_STR "MTK_SPK_I2S_2"
#define MTK_SPK_I2S_3_STR "MTK_SPK_I2S_3"
/* MCLK */
enum {
MT8186_I2S0_MCK = 0,
MT8186_I2S1_MCK,
MT8186_I2S2_MCK,
MT8186_I2S4_MCK,
MT8186_TDM_MCK,
MT8186_MCK_NUM,
};
struct snd_pcm_substream;
struct mtk_base_irq_data;
struct clk;
struct mt8186_afe_private {
struct clk **clk;
struct clk_lookup **lookup;
struct regmap *topckgen;
struct regmap *apmixedsys;
struct regmap *infracfg;
int irq_cnt[MT8186_MEMIF_NUM];
int stf_positive_gain_db;
int pm_runtime_bypass_reg_ctl;
int sgen_mode;
int sgen_rate;
int sgen_amplitude;
/* xrun assert */
int xrun_assert[MT8186_MEMIF_NUM];
/* dai */
bool dai_on[MT8186_DAI_NUM];
void *dai_priv[MT8186_DAI_NUM];
/* adda */
bool mtkaif_calibration_ok;
int mtkaif_protocol;
int mtkaif_chosen_phase[4];
int mtkaif_phase_cycle[4];
int mtkaif_calibration_num_phase;
int mtkaif_dmic;
int mtkaif_looback0;
int mtkaif_looback1;
/* mck */
int mck_rate[MT8186_MCK_NUM];
};
int mt8186_dai_adda_register(struct mtk_base_afe *afe);
int mt8186_dai_i2s_register(struct mtk_base_afe *afe);
int mt8186_dai_tdm_register(struct mtk_base_afe *afe);
int mt8186_dai_hw_gain_register(struct mtk_base_afe *afe);
int mt8186_dai_src_register(struct mtk_base_afe *afe);
int mt8186_dai_pcm_register(struct mtk_base_afe *afe);
int mt8186_dai_hostless_register(struct mtk_base_afe *afe);
int mt8186_add_misc_control(struct snd_soc_component *component);
unsigned int mt8186_general_rate_transform(struct device *dev,
unsigned int rate);
unsigned int mt8186_rate_transform(struct device *dev,
unsigned int rate, int aud_blk);
unsigned int mt8186_tdm_relatch_rate_transform(struct device *dev,
unsigned int rate);
int mt8186_dai_set_priv(struct mtk_base_afe *afe, int id,
int priv_size, const void *priv_data);
#endif

View File

@ -0,0 +1,255 @@
// SPDX-License-Identifier: GPL-2.0
//
// MediaTek ALSA SoC Audio Control
//
// Copyright (c) 2022 MediaTek Inc.
// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
#include "mt8186-afe-common.h"
#include <linux/pm_runtime.h>
enum {
MTK_AFE_RATE_8K = 0,
MTK_AFE_RATE_11K,
MTK_AFE_RATE_12K,
MTK_AFE_RATE_384K,
MTK_AFE_RATE_16K,
MTK_AFE_RATE_22K,
MTK_AFE_RATE_24K,
MTK_AFE_RATE_352K,
MTK_AFE_RATE_32K,
MTK_AFE_RATE_44K,
MTK_AFE_RATE_48K,
MTK_AFE_RATE_88K,
MTK_AFE_RATE_96K,
MTK_AFE_RATE_176K,
MTK_AFE_RATE_192K,
MTK_AFE_RATE_260K,
};
enum {
MTK_AFE_PCM_RATE_8K = 0,
MTK_AFE_PCM_RATE_16K,
MTK_AFE_PCM_RATE_32K,
MTK_AFE_PCM_RATE_48K,
};
enum {
MTK_AFE_TDM_RATE_8K = 0,
MTK_AFE_TDM_RATE_12K,
MTK_AFE_TDM_RATE_16K,
MTK_AFE_TDM_RATE_24K,
MTK_AFE_TDM_RATE_32K,
MTK_AFE_TDM_RATE_48K,
MTK_AFE_TDM_RATE_64K,
MTK_AFE_TDM_RATE_96K,
MTK_AFE_TDM_RATE_128K,
MTK_AFE_TDM_RATE_192K,
MTK_AFE_TDM_RATE_256K,
MTK_AFE_TDM_RATE_384K,
MTK_AFE_TDM_RATE_11K,
MTK_AFE_TDM_RATE_22K,
MTK_AFE_TDM_RATE_44K,
MTK_AFE_TDM_RATE_88K,
MTK_AFE_TDM_RATE_176K,
MTK_AFE_TDM_RATE_352K,
};
enum {
MTK_AFE_TDM_RELATCH_RATE_8K = 0,
MTK_AFE_TDM_RELATCH_RATE_11K,
MTK_AFE_TDM_RELATCH_RATE_12K,
MTK_AFE_TDM_RELATCH_RATE_16K,
MTK_AFE_TDM_RELATCH_RATE_22K,
MTK_AFE_TDM_RELATCH_RATE_24K,
MTK_AFE_TDM_RELATCH_RATE_32K,
MTK_AFE_TDM_RELATCH_RATE_44K,
MTK_AFE_TDM_RELATCH_RATE_48K,
MTK_AFE_TDM_RELATCH_RATE_88K,
MTK_AFE_TDM_RELATCH_RATE_96K,
MTK_AFE_TDM_RELATCH_RATE_176K,
MTK_AFE_TDM_RELATCH_RATE_192K,
MTK_AFE_TDM_RELATCH_RATE_352K,
MTK_AFE_TDM_RELATCH_RATE_384K,
};
unsigned int mt8186_general_rate_transform(struct device *dev, unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_RATE_8K;
case 11025:
return MTK_AFE_RATE_11K;
case 12000:
return MTK_AFE_RATE_12K;
case 16000:
return MTK_AFE_RATE_16K;
case 22050:
return MTK_AFE_RATE_22K;
case 24000:
return MTK_AFE_RATE_24K;
case 32000:
return MTK_AFE_RATE_32K;
case 44100:
return MTK_AFE_RATE_44K;
case 48000:
return MTK_AFE_RATE_48K;
case 88200:
return MTK_AFE_RATE_88K;
case 96000:
return MTK_AFE_RATE_96K;
case 176400:
return MTK_AFE_RATE_176K;
case 192000:
return MTK_AFE_RATE_192K;
case 260000:
return MTK_AFE_RATE_260K;
case 352800:
return MTK_AFE_RATE_352K;
case 384000:
return MTK_AFE_RATE_384K;
default:
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
__func__, rate, MTK_AFE_RATE_48K);
}
return MTK_AFE_RATE_48K;
}
static unsigned int tdm_rate_transform(struct device *dev, unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_TDM_RATE_8K;
case 11025:
return MTK_AFE_TDM_RATE_11K;
case 12000:
return MTK_AFE_TDM_RATE_12K;
case 16000:
return MTK_AFE_TDM_RATE_16K;
case 22050:
return MTK_AFE_TDM_RATE_22K;
case 24000:
return MTK_AFE_TDM_RATE_24K;
case 32000:
return MTK_AFE_TDM_RATE_32K;
case 44100:
return MTK_AFE_TDM_RATE_44K;
case 48000:
return MTK_AFE_TDM_RATE_48K;
case 64000:
return MTK_AFE_TDM_RATE_64K;
case 88200:
return MTK_AFE_TDM_RATE_88K;
case 96000:
return MTK_AFE_TDM_RATE_96K;
case 128000:
return MTK_AFE_TDM_RATE_128K;
case 176400:
return MTK_AFE_TDM_RATE_176K;
case 192000:
return MTK_AFE_TDM_RATE_192K;
case 256000:
return MTK_AFE_TDM_RATE_256K;
case 352800:
return MTK_AFE_TDM_RATE_352K;
case 384000:
return MTK_AFE_TDM_RATE_384K;
default:
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
__func__, rate, MTK_AFE_TDM_RATE_48K);
}
return MTK_AFE_TDM_RATE_48K;
}
static unsigned int pcm_rate_transform(struct device *dev, unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_PCM_RATE_8K;
case 16000:
return MTK_AFE_PCM_RATE_16K;
case 32000:
return MTK_AFE_PCM_RATE_32K;
case 48000:
return MTK_AFE_PCM_RATE_48K;
default:
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
__func__, rate, MTK_AFE_PCM_RATE_48K);
}
return MTK_AFE_PCM_RATE_48K;
}
unsigned int mt8186_tdm_relatch_rate_transform(struct device *dev, unsigned int rate)
{
switch (rate) {
case 8000:
return MTK_AFE_TDM_RELATCH_RATE_8K;
case 11025:
return MTK_AFE_TDM_RELATCH_RATE_11K;
case 12000:
return MTK_AFE_TDM_RELATCH_RATE_12K;
case 16000:
return MTK_AFE_TDM_RELATCH_RATE_16K;
case 22050:
return MTK_AFE_TDM_RELATCH_RATE_22K;
case 24000:
return MTK_AFE_TDM_RELATCH_RATE_24K;
case 32000:
return MTK_AFE_TDM_RELATCH_RATE_32K;
case 44100:
return MTK_AFE_TDM_RELATCH_RATE_44K;
case 48000:
return MTK_AFE_TDM_RELATCH_RATE_48K;
case 88200:
return MTK_AFE_TDM_RELATCH_RATE_88K;
case 96000:
return MTK_AFE_TDM_RELATCH_RATE_96K;
case 176400:
return MTK_AFE_TDM_RELATCH_RATE_176K;
case 192000:
return MTK_AFE_TDM_RELATCH_RATE_192K;
case 352800:
return MTK_AFE_TDM_RELATCH_RATE_352K;
case 384000:
return MTK_AFE_TDM_RELATCH_RATE_384K;
default:
dev_err(dev, "%s(), rate %u invalid, use %d!!!\n",
__func__, rate, MTK_AFE_TDM_RELATCH_RATE_48K);
}
return MTK_AFE_TDM_RELATCH_RATE_48K;
}
unsigned int mt8186_rate_transform(struct device *dev, unsigned int rate, int aud_blk)
{
switch (aud_blk) {
case MT8186_DAI_PCM:
return pcm_rate_transform(dev, rate);
case MT8186_DAI_TDM_IN:
return tdm_rate_transform(dev, rate);
default:
return mt8186_general_rate_transform(dev, rate);
}
}
int mt8186_dai_set_priv(struct mtk_base_afe *afe, int id, int priv_size, const void *priv_data)
{
struct mt8186_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;
}

File diff suppressed because it is too large Load Diff