kernel_samsung_a34x-permissive/sound/soc/mediatek/common_int/mtk-soc-machine.c
2024-04-28 15:49:01 +02:00

858 lines
23 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Michael Hsiao <michael.hsiao@mediatek.com>
*/
/*******************************************************************************
*
* Filename:
* ---------
* mt_soc_machine.c
*
* Project:
* --------
* Audio soc machine driver
*
* Description:
* ------------
* Audio machine driver
*
* Author:
* -------
* Chipeng Chang
*
*------------------------------------------------------------------------------
*
******************************************************************************
*/
/*****************************************************************************
* C O M P I L E R F L A G S
*****************************************************************************/
/*****************************************************************************
* E X T E R N A L R E F E R E N C E S
*****************************************************************************/
#include "mtk-auddrv-afe.h"
#include "mtk-auddrv-ana.h"
#include "mtk-auddrv-clk.h"
#include "mtk-auddrv-common.h"
#include "mtk-auddrv-def.h"
#include "mtk-auddrv-kernel.h"
#include "mtk-soc-afe-control.h"
#include <asm/div64.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <stdarg.h>
#include "mtk-soc-codec-63xx.h"
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include "mtk-soc-speaker-amp.h"
#if defined(CONFIG_SND_SOC_CS43130)
#include "mtk-cs43130-machine-ops.h"
#endif
#if defined(CONFIG_SND_SOC_CS35L35)
#include "mtk-cs35l35-machine-ops.h"
#endif
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
static struct dentry *mt_sco_audio_debugfs;
#define DEBUG_FS_NAME "mtksocaudio"
#define DEBUG_ANA_FS_NAME "mtksocanaaudio"
static int mt_soc_ana_debug_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t mt_soc_ana_debug_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
const int size = 8192;
/* char buffer[size]; */
char *buffer = NULL; /* for reduce kernel stack */
int n = 0;
int ret = 0;
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
kfree(buffer);
return -ENOMEM;
}
AudDrv_Clk_On();
audckbufEnable(true);
n = Ana_Debug_Read(buffer, size);
audckbufEnable(false);
AudDrv_Clk_Off();
ret = simple_read_from_buffer(buf, count, pos, buffer, n);
kfree(buffer);
return ret;
}
static int mt_soc_debug_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t mt_soc_debug_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
const int size = 12288;
/* char buffer[size]; */
char *buffer = NULL; /* for reduce kernel stack */
int n = 0;
int ret = 0;
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
kfree(buffer);
return -ENOMEM;
}
AudDrv_Clk_On();
n = AudDrv_Reg_Dump(buffer, size);
AudDrv_Clk_Off();
ret = simple_read_from_buffer(buf, count, pos, buffer, n);
kfree(buffer);
return ret;
}
static char const ParSetkeyAfe[] = "Setafereg";
static char const ParSetkeyAna[] = "Setanareg";
static char const PareGetkeyAfe[] = "Getafereg";
static char const PareGetkeyAna[] = "Getanareg";
static ssize_t mt_soc_debug_write(struct file *f, const char __user *buf,
size_t count, loff_t *offset)
{
#define MAX_DEBUG_WRITE_INPUT 256
int ret = 0;
char InputBuf[MAX_DEBUG_WRITE_INPUT];
char *token1 = NULL;
char *token2 = NULL;
char *token3 = NULL;
char *token4 = NULL;
char *token5 = NULL;
char *temp = NULL;
char *str_begin = NULL;
unsigned long regaddr = 0;
unsigned long regvalue = 0;
char delim[] = " ,";
if (!count) {
pr_debug("%s(), count is 0, return directly\n", __func__);
goto exit;
}
if (count > MAX_DEBUG_WRITE_INPUT)
count = MAX_DEBUG_WRITE_INPUT;
memset_io((void *)InputBuf, 0, MAX_DEBUG_WRITE_INPUT);
if (copy_from_user((InputBuf), buf, count)) {
pr_debug("%s(), copy_from_user fail, count = %zu\n",
__func__, count);
goto exit;
}
str_begin = kstrndup(InputBuf, MAX_DEBUG_WRITE_INPUT - 1,
GFP_KERNEL);
if (!str_begin) {
pr_warn("%s(), kstrdup fail\n", __func__);
goto exit;
}
temp = str_begin;
pr_debug(
"copy_from_user count = %zu, temp = %s, pointer = %p\n",
count, str_begin, str_begin);
token1 = strsep(&temp, delim);
token2 = strsep(&temp, delim);
token3 = strsep(&temp, delim);
token4 = strsep(&temp, delim);
token5 = strsep(&temp, delim);
pr_debug("token1 = %s token2 = %s token3 = %s token4 = %s token5 = %s\n",
token1, token2, token3, token4, token5);
AudDrv_Clk_On();
if (strcmp(token1, ParSetkeyAfe) == 0) {
if ((token3 != NULL) && (token5 != NULL)) {
ret = kstrtoul(token3, 16, &regaddr);
ret = kstrtoul(token5, 16, &regvalue);
pr_debug("%s, regaddr = 0x%x, regvalue = 0x%x\n",
ParSetkeyAfe, (unsigned int)regaddr,
(unsigned int)regvalue);
Afe_Set_Reg(regaddr, regvalue, 0xffffffff);
regvalue = Afe_Get_Reg(regaddr);
pr_debug("%s, regaddr = 0x%x, regvalue = 0x%x\n",
ParSetkeyAfe, (unsigned int)regaddr,
(unsigned int)regvalue);
} else {
pr_debug("token3 or token5 is NULL!\n");
}
}
if (strcmp(token1, ParSetkeyAna) == 0) {
if ((token3 != NULL) && (token5 != NULL)) {
ret = kstrtoul(token3, 16, &regaddr);
ret = kstrtoul(token5, 16, &regvalue);
pr_debug("%s, regaddr = 0x%x, regvalue = 0x%x\n",
ParSetkeyAna, (unsigned int)regaddr,
(unsigned int)regvalue);
audckbufEnable(true);
Ana_Set_Reg(regaddr, regvalue, 0xffffffff);
regvalue = Ana_Get_Reg(regaddr);
audckbufEnable(false);
pr_debug("%s, regaddr = 0x%x, regvalue = 0x%x\n",
ParSetkeyAna, (unsigned int)regaddr,
(unsigned int)regvalue);
} else {
pr_debug("token3 or token5 is NULL!\n");
}
}
if (strcmp(token1, PareGetkeyAfe) == 0) {
if (token3 != NULL) {
ret = kstrtoul(token3, 16, &regaddr);
regvalue = Afe_Get_Reg(regaddr);
pr_debug("%s, regaddr = 0x%x, regvalue = 0x%x\n",
PareGetkeyAfe, (unsigned int)regaddr,
(unsigned int)regvalue);
} else {
pr_debug("token3 is NULL!\n");
}
}
if (strcmp(token1, PareGetkeyAna) == 0) {
if (token3 != NULL) {
ret = kstrtoul(token3, 16, &regaddr);
regvalue = Ana_Get_Reg(regaddr);
pr_debug("%s, regaddr = 0x%x, regvalue = 0x%x\n",
PareGetkeyAna, (unsigned int)regaddr,
(unsigned int)regvalue);
} else {
pr_debug("token3 is NULL!\n");
}
}
AudDrv_Clk_Off();
kfree(str_begin);
exit:
return count;
}
static const struct file_operations mtaudio_debug_ops = {
.open = mt_soc_debug_open,
.read = mt_soc_debug_read,
.write = mt_soc_debug_write,
};
static const struct file_operations mtaudio_ana_debug_ops = {
.open = mt_soc_ana_debug_open, .read = mt_soc_ana_debug_read,
};
#endif
/* snd_soc_ops */
static int mt_machine_trigger(struct snd_pcm_substream *substream, int cmd)
{
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
EnableAfe(true);
return 0;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
EnableAfe(false);
return 0;
}
return -EINVAL;
}
static struct snd_soc_ops mt_machine_audio_ops = {
.trigger = mt_machine_trigger,
};
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link mt_soc_dai_common[] = {
/* FrontEnd DAI Links */
{
.name = "MultiMedia1",
.stream_name = MT_SOC_DL1_STREAM_NAME,
.cpu_dai_name = MT_SOC_DL1DAI_NAME,
.platform_name = MT_SOC_DL1_PCM,
.codec_dai_name = MT_SOC_CODEC_TXDAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "MultiMedia2",
.stream_name = MT_SOC_UL1_STREAM_NAME,
.cpu_dai_name = MT_SOC_UL1DAI_NAME,
.platform_name = MT_SOC_UL1_PCM,
.codec_dai_name = MT_SOC_CODEC_RXDAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "Voice_MD1",
.stream_name = MT_SOC_VOICE_MD1_STREAM_NAME,
.cpu_dai_name = MT_SOC_VOICE_MD1_NAME,
.platform_name = MT_SOC_VOICE_MD1,
.codec_dai_name = MT_SOC_CODEC_VOICE_MD1DAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
#ifdef CONFIG_MTK_HDMI_TDM
{
.name = "HDMI_OUT",
.stream_name = MT_SOC_HDMI_STREAM_NAME,
.cpu_dai_name = MT_SOC_HDMI_NAME,
.platform_name = MT_SOC_HDMI_PCM,
.codec_dai_name = MT_SOC_CODEC_HDMI_DUMMY_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
#endif
{
.name = "ULDLOOPBACK",
.stream_name = MT_SOC_ULDLLOOPBACK_STREAM_NAME,
.cpu_dai_name = MT_SOC_ULDLLOOPBACK_NAME,
.platform_name = MT_SOC_ULDLLOOPBACK_PCM,
.codec_dai_name = MT_SOC_CODEC_ULDLLOOPBACK_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "I2S0OUTPUT",
.stream_name = MT_SOC_I2S0_STREAM_NAME,
.cpu_dai_name = MT_SOC_I2S0_NAME,
.platform_name = MT_SOC_I2S0_PCM,
.codec_dai_name = MT_SOC_CODEC_I2S0_DUMMY_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "MRGRX",
.stream_name = MT_SOC_MRGRX_STREAM_NAME,
.cpu_dai_name = MT_SOC_MRGRX_NAME,
.platform_name = MT_SOC_MRGRX_PCM,
.codec_dai_name = MT_SOC_CODEC_MRGRX_DAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "MRGRXCAPTURE",
.stream_name = MT_SOC_MRGRX_CAPTURE_STREAM_NAME,
.cpu_dai_name = MT_SOC_MRGRX_NAME,
.platform_name = MT_SOC_MRGRX_AWB_PCM,
.codec_dai_name = MT_SOC_CODEC_MRGRX_DUMMY_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "I2S0DL1OUTPUT",
.stream_name = MT_SOC_I2SDL1_STREAM_NAME,
.cpu_dai_name = MT_SOC_I2S0DL1_NAME,
.platform_name = MT_SOC_I2S0DL1_PCM,
.codec_dai_name = MT_SOC_CODEC_I2S0TXDAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "DEEP_BUFFER_DL_OUTPUT",
.stream_name = MT_SOC_DEEP_BUFFER_DL_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = MT_SOC_DEEP_BUFFER_DL_PCM,
.codec_dai_name = MT_SOC_CODEC_DEEPBUFFER_TX_DAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "DL1AWBCAPTURE",
.stream_name = MT_SOC_DL1_AWB_RECORD_STREAM_NAME,
.cpu_dai_name = MT_SOC_DL1AWB_NAME,
.platform_name = MT_SOC_DL1_AWB_PCM,
.codec_dai_name = MT_SOC_CODEC_DL1AWBDAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "Voice_MD1_BT",
.stream_name = MT_SOC_VOICE_MD1_BT_STREAM_NAME,
.cpu_dai_name = MT_SOC_VOICE_MD1_BT_NAME,
.platform_name = MT_SOC_VOICE_MD1_BT,
.codec_dai_name = MT_SOC_CODEC_VOICE_MD1_BTDAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "VOIP_CALL_BT_PLAYBACK",
.stream_name = MT_SOC_VOIP_BT_OUT_STREAM_NAME,
.cpu_dai_name = MT_SOC_VOIP_CALL_BT_OUT_NAME,
.platform_name = MT_SOC_VOIP_BT_OUT,
.codec_dai_name = MT_SOC_CODEC_VOIPCALLBTOUTDAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "VOIP_CALL_BT_CAPTURE",
.stream_name = MT_SOC_VOIP_BT_IN_STREAM_NAME,
.cpu_dai_name = MT_SOC_VOIP_CALL_BT_IN_NAME,
.platform_name = MT_SOC_VOIP_BT_IN,
.codec_dai_name = MT_SOC_CODEC_VOIPCALLBTINDAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "TDM_Debug_CAPTURE",
.stream_name = MT_SOC_TDM_CAPTURE_STREAM_NAME,
.cpu_dai_name = MT_SOC_TDMRX_NAME,
.platform_name = MT_SOC_TDMRX_PCM,
.codec_dai_name = MT_SOC_CODEC_TDMRX_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "FM_MRG_TX",
.stream_name = MT_SOC_FM_MRGTX_STREAM_NAME,
.cpu_dai_name = MT_SOC_FM_MRGTX_NAME,
.platform_name = MT_SOC_FM_MRGTX_PCM,
.codec_dai_name = MT_SOC_CODEC_FMMRGTXDAI_DUMMY_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "MultiMedia3",
.stream_name = MT_SOC_UL1DATA2_STREAM_NAME,
.cpu_dai_name = MT_SOC_UL2DAI_NAME,
.platform_name = MT_SOC_UL2_PCM,
.codec_dai_name = MT_SOC_CODEC_RXDAI2_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "I2S0_AWB_CAPTURE",
.stream_name = MT_SOC_I2S0AWB_STREAM_NAME,
.cpu_dai_name = MT_SOC_I2S0AWBDAI_NAME,
.platform_name = MT_SOC_I2S0_AWB_PCM,
.codec_dai_name = MT_SOC_CODEC_I2S0AWB_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "Voice_MD2",
.stream_name = MT_SOC_VOICE_MD2_STREAM_NAME,
.cpu_dai_name = MT_SOC_VOICE_MD2_NAME,
.platform_name = MT_SOC_VOICE_MD2,
.codec_dai_name = MT_SOC_CODEC_VOICE_MD2DAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "PLATOFRM_CONTROL",
.stream_name = MT_SOC_ROUTING_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = MT_SOC_ROUTING_PCM,
.codec_dai_name = MT_SOC_CODEC_DUMMY_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "Voice_MD2_BT",
.stream_name = MT_SOC_VOICE_MD2_BT_STREAM_NAME,
.cpu_dai_name = MT_SOC_VOICE_MD2_BT_NAME,
.platform_name = MT_SOC_VOICE_MD2_BT,
.codec_dai_name = MT_SOC_CODEC_VOICE_MD2_BTDAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "HP_IMPEDANCE",
.stream_name = MT_SOC_HP_IMPEDANCE_STREAM_NAME,
.cpu_dai_name = MT_SOC_HP_IMPEDANCE_NAME,
.platform_name = MT_SOC_HP_IMPEDANCE_PCM,
.codec_dai_name = MT_SOC_CODEC_HP_IMPEDANCE_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "FM_I2S_RX_Playback",
.stream_name = MT_SOC_FM_I2S_PLAYBACK_STREAM_NAME,
.cpu_dai_name = MT_SOC_FM_I2S_NAME,
.platform_name = MT_SOC_FM_I2S_PCM,
.codec_dai_name = MT_SOC_CODEC_FM_I2S_DAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "FM_I2S_RX_Capture",
.stream_name = MT_SOC_FM_I2S_CAPTURE_STREAM_NAME,
.cpu_dai_name = MT_SOC_FM_I2S_NAME,
.platform_name = MT_SOC_FM_I2S_AWB_PCM,
.codec_dai_name = MT_SOC_CODEC_FM_I2S_DUMMY_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
{
.name = "MultiMedia_DL2",
.stream_name = MT_SOC_DL2_STREAM_NAME,
.cpu_dai_name = MT_SOC_DL2DAI_NAME,
.platform_name = MT_SOC_DL2_PCM,
.codec_dai_name = MT_SOC_CODEC_TXDAI2_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "MultiMedia_DL3",
.stream_name = MT_SOC_DL3_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = "snd-soc-dummy",
.codec_dai_name = MT_SOC_CODEC_OFFLOAD_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
#ifdef _NON_COMMON_FEATURE_READY
{
.name = "MOD_DAI_CAPTURE",
.stream_name = MT_SOC_MODDAI_STREAM_NAME,
.cpu_dai_name = MT_SOC_MOD_DAI_NAME,
.platform_name = MT_SOC_MOD_DAI_PCM,
.codec_dai_name = MT_SOC_CODEC_MOD_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
#endif
#ifdef CONFIG_SND_SOC_MTK_AUDIO_DSP
{
.name = "OFFLOAD",
.stream_name = MT_SOC_OFFLOAD_STREAM_NAME,
.cpu_dai_name = MT_SOC_OFFLOAD_PLAYBACK_DAI_NAME,
.platform_name = MT_SOC_PLAYBACK_OFFLOAD,
.codec_dai_name = MT_SOC_CODEC_OFFLOAD_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
#endif
#ifdef _NON_COMMON_FEATURE_READY
{
.name = "PCM_ANC",
.stream_name = MT_SOC_ANC_STREAM_NAME,
.cpu_dai_name = MT_SOC_ANC_NAME,
.platform_name = MT_SOC_ANC_PCM,
.codec_dai_name = MT_SOC_CODEC_ANC_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
#endif
{
.name = "ANC_RECORD",
.stream_name = MT_SOC_ANC_RECORD_STREAM_NAME,
.cpu_dai_name = MT_SOC_ANC_RECORD_DAI_NAME,
.platform_name = MT_SOC_I2S2_ADC2_PCM,
.codec_dai_name = MT_SOC_CODEC_DUMMY_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
.ops = &mt_machine_audio_ops,
},
#ifdef _NON_COMMON_FEATURE_READY
{
.name = "Voice_Ultrasound",
.stream_name = MT_SOC_VOICE_ULTRA_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = MT_SOC_VOICE_ULTRA,
.codec_dai_name = MT_SOC_CODEC_VOICE_ULTRADAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
#endif
{
.name = "Voice_USB",
.stream_name = MT_SOC_VOICE_USB_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = MT_SOC_VOICE_USB,
.codec_dai_name = MT_SOC_CODEC_VOICE_USBDAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "Voice_USB_ECHOREF",
.stream_name = MT_SOC_VOICE_USB_ECHOREF_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = MT_SOC_VOICE_USB_ECHOREF,
.codec_dai_name = MT_SOC_CODEC_VOICE_USB_ECHOREF_DAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
.playback_only = true,
},
#ifdef CONFIG_MTK_AUDIO_SCP_SPKPROTECT_SUPPORT
{
.name = "DL1SCPSPKOUTPUT",
.stream_name = MT_SOC_DL1SCPSPK_STREAM_NAME,
.cpu_dai_name = MT_SOC_DL1SCPSPK_NAME,
.platform_name = MT_SOC_DL1SCPSPK_PCM,
.codec_dai_name = MT_SOC_CODEC_SPKSCPTXDAI_NAME,
.codec_name = MT_SOC_CODEC_NAME,
},
{
.name = "VOICE_SCP",
.stream_name = MT_SOC_SCPVOICE_STREAM_NAME,
.cpu_dai_name = MT_SOC_SCPVOICE_NAME,
.platform_name = MT_SOC_SCP_VOICE_PCM,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
#endif
};
#ifdef CONFIG_SND_SOC_MTK_BTCVSD
static struct snd_soc_dai_link mt_soc_btcvsd_dai[] = {
{
.name = "BTCVSD",
.stream_name = "BTCVSD",
.cpu_dai_name = MT_SOC_BTCVSD_DAI_NAME,
.codec_dai_name = MT_SOC_CODEC_BTCVSD_DAI_NAME,
.codec_name = MT_SOC_CODEC_DUMMY_NAME,
},
};
#endif
static struct snd_soc_dai_link mt_soc_exthp_dai[] = {
{
.name = "ext_Headphone_Multimedia",
.stream_name = MT_SOC_HEADPHONE_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = "snd-soc-dummy",
#ifdef CONFIG_SND_SOC_CS43130
.codec_dai_name = "cs43130-hifi",
.codec_name = "cs43130.2-0030",
.ignore_suspend = 1,
.ignore_pmdown_time = true,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS |
SND_SOC_DAIFMT_NB_NF,
.ops = &cs43130_ops,
#else
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
#endif
},
};
static struct snd_soc_dai_link mt_soc_extspk_dai[] = {
{
.name = "ext_Speaker_Multimedia",
.stream_name = MT_SOC_SPEAKER_STREAM_NAME,
.cpu_dai_name = "snd-soc-dummy-dai",
.platform_name = "snd-soc-dummy",
#ifdef CONFIG_SND_SOC_MAX98926
.codec_dai_name = "max98926-aif1",
.codec_name = "MAX98926_MT",
#elif defined(CONFIG_SND_SOC_CS35L35)
.codec_dai_name = "cs35l35-pcm",
.codec_name = "cs35l35.2-0040",
.ignore_suspend = 1,
.ignore_pmdown_time = true,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS |
SND_SOC_DAIFMT_NB_NF,
.ops = &cs35l35_ops,
#else
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
#endif
},
{
.name = "I2S1_AWB_CAPTURE",
.stream_name = MT_SOC_I2S2ADC2_STREAM_NAME,
.cpu_dai_name = MT_SOC_I2S2ADC2DAI_NAME,
.platform_name = MT_SOC_I2S2_ADC2_PCM,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ops = &mt_machine_audio_ops,
},
};
static struct snd_soc_dai_link
mt_soc_dai_component[ARRAY_SIZE(mt_soc_dai_common) +
#ifdef CONFIG_SND_SOC_MTK_BTCVSD
ARRAY_SIZE(mt_soc_btcvsd_dai) +
#endif
ARRAY_SIZE(mt_soc_exthp_dai) +
ARRAY_SIZE(mt_soc_extspk_dai)];
#ifdef CONFIG_SND_SOC_MT6357_ACCDET
static struct snd_soc_aux_dev mtk_aux_devs = {
.name = "mtk-headset",
};
#endif
static struct snd_soc_card mt_snd_soc_card_mt = {
.name = "mt-snd-card",
.dai_link = mt_soc_dai_common,
.num_links = ARRAY_SIZE(mt_soc_dai_common),
#ifdef CONFIG_SND_SOC_MT6357_ACCDET
.aux_dev = &mtk_aux_devs,
.num_aux_devs = 1,
#endif
};
static int mt_soc_snd_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt_snd_soc_card_mt;
#ifdef CONFIG_SND_SOC_MTK_BTCVSD
struct device_node *btcvsd_node;
#endif
int ret;
int daiLinkNum = 0;
ret = mtk_spk_update_dai_link(mt_soc_extspk_dai, pdev);
if (ret) {
dev_err(&pdev->dev, "%s(), mtk_spk_update_dai_link error\n",
__func__);
return -EINVAL;
}
/* get_ext_dai_codec_name(); */
pr_debug("%s(), dai_link = %p\n",
__func__, mt_snd_soc_card_mt.dai_link);
/* DEAL WITH DAI LINK */
memcpy(mt_soc_dai_component, mt_soc_dai_common,
sizeof(mt_soc_dai_common));
daiLinkNum += ARRAY_SIZE(mt_soc_dai_common);
#ifdef CONFIG_SND_SOC_MTK_BTCVSD
/* assign btcvsd platform_node */
btcvsd_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,btcvsd_snd", 0);
if (!btcvsd_node) {
dev_err(&pdev->dev, "Property 'btcvsd_snd' missing or invalid\n");
return -EINVAL;
}
mt_soc_btcvsd_dai[0].platform_of_node = btcvsd_node;
memcpy(mt_soc_dai_component + daiLinkNum,
mt_soc_btcvsd_dai, sizeof(mt_soc_btcvsd_dai));
daiLinkNum += ARRAY_SIZE(mt_soc_btcvsd_dai);
#endif
memcpy(mt_soc_dai_component + daiLinkNum, mt_soc_exthp_dai,
sizeof(mt_soc_exthp_dai));
daiLinkNum += ARRAY_SIZE(mt_soc_exthp_dai);
memcpy(mt_soc_dai_component + daiLinkNum, mt_soc_extspk_dai,
sizeof(mt_soc_extspk_dai));
daiLinkNum += ARRAY_SIZE(mt_soc_extspk_dai);
mt_snd_soc_card_mt.dai_link = mt_soc_dai_component;
mt_snd_soc_card_mt.num_links = daiLinkNum;
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
#ifdef CONFIG_SND_SOC_MT6357_ACCDET
mtk_aux_devs.codec_of_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,headset-codec", 0);
if (!mtk_aux_devs.codec_of_node) {
dev_err(&pdev->dev, "Can't find controls for headset codec.\n");
return -EINVAL;
};
mtk_accdet_set_drvdata(card);
#endif
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
__func__, ret);
#ifdef CONFIG_DEBUG_FS
/* create debug file */
mt_sco_audio_debugfs =
debugfs_create_file(DEBUG_FS_NAME, S_IFREG | 0444, NULL,
(void *)DEBUG_FS_NAME, &mtaudio_debug_ops);
/* create analog debug file */
mt_sco_audio_debugfs = debugfs_create_file(
DEBUG_ANA_FS_NAME, S_IFREG | 0444, NULL,
(void *)DEBUG_ANA_FS_NAME, &mtaudio_ana_debug_ops);
#endif
return ret;
}
static int mt_soc_snd_remove(struct platform_device *pdev)
{
pr_debug("%s\n", __func__);
snd_soc_unregister_component(&pdev->dev);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id mt_audio_driver_dt_match[] = {
{
.compatible = "mediatek,audio",
},
{} };
#endif
static struct platform_driver mt_audio_driver = {
.driver = {
.name = "mtk-audio",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = mt_audio_driver_dt_match,
#endif
},
.probe = mt_soc_snd_probe,
.remove = mt_soc_snd_remove,
};
#ifndef CONFIG_OF
static struct platform_device *mtk_soc_snd_dev;
#endif
static int __init mt_soc_snd_init(void)
{
int ret;
pr_debug("%s\n", __func__);
#ifndef CONFIG_OF
mtk_soc_snd_dev = platform_device_alloc("mtk-audio", -1);
if (!mtk_soc_snd_dev)
return -ENOMEM;
ret = platform_device_add(mtk_soc_snd_dev);
if (ret != 0) {
platform_device_put(mtk_soc_snd_dev);
return ret;
}
#endif
ret = platform_driver_register(&mt_audio_driver);
pr_debug("-%s\n", __func__);
return ret;
}
module_init(mt_soc_snd_init);
static void __exit mt_soc_snd_exit(void)
{
platform_driver_unregister(&mt_audio_driver);
}
module_exit(mt_soc_snd_exit);
/* Module information */
MODULE_AUTHOR("ChiPeng <chipeng.chang@mediatek.com>");
MODULE_DESCRIPTION("ALSA SoC driver ");
MODULE_LICENSE("GPL");