2019-03-29 16:34:46 +08:00
// SPDX-License-Identifier: GPL-2.0
//
// mt8183-mt6358.c --
// MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver
//
// Copyright (c) 2018 MediaTek Inc.
// Author: Shunli Wang <shunli.wang@mediatek.com>
# include <linux/module.h>
2020-07-08 19:32:33 +08:00
# include <linux/of_device.h>
2020-07-08 19:32:31 +08:00
# include <linux/pinctrl/consumer.h>
# include <sound/jack.h>
2019-03-29 16:34:46 +08:00
# include <sound/pcm_params.h>
# include <sound/soc.h>
2020-07-08 19:32:33 +08:00
# include "../../codecs/rt1015.h"
2019-03-29 16:34:46 +08:00
# include "../../codecs/ts3a227e.h"
2020-07-08 19:32:31 +08:00
# include "mt8183-afe-common.h"
2019-03-29 16:34:46 +08:00
2020-07-08 19:32:33 +08:00
# define RT1015_CODEC_DAI "rt1015-aif"
# define RT1015_DEV0_NAME "rt1015.6-0028"
# define RT1015_DEV1_NAME "rt1015.6-0029"
2019-08-30 15:42:37 +08:00
enum PINCTRL_PIN_STATE {
PIN_STATE_DEFAULT = 0 ,
PIN_TDM_OUT_ON ,
PIN_TDM_OUT_OFF ,
2019-10-19 15:02:54 +08:00
PIN_WOV ,
2019-08-30 15:42:37 +08:00
PIN_STATE_MAX
} ;
static const char * const mt8183_pin_str [ PIN_STATE_MAX ] = {
2019-10-19 15:02:54 +08:00
" default " , " aud_tdm_out_on " , " aud_tdm_out_off " , " wov " ,
2019-08-30 15:42:37 +08:00
} ;
struct mt8183_mt6358_ts3a227_max98357_priv {
struct pinctrl * pinctrl ;
struct pinctrl_state * pin_states [ PIN_STATE_MAX ] ;
2020-07-10 13:25:02 +08:00
struct snd_soc_jack headset_jack , hdmi_jack ;
2019-08-30 15:42:37 +08:00
} ;
2019-03-29 16:34:46 +08:00
static int mt8183_mt6358_i2s_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
2020-07-20 10:18:48 +09:00
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd ( substream ) ;
2019-03-29 16:34:46 +08:00
unsigned int rate = params_rate ( params ) ;
unsigned int mclk_fs_ratio = 128 ;
unsigned int mclk_fs = rate * mclk_fs_ratio ;
2020-03-23 14:19:23 +09:00
return snd_soc_dai_set_sysclk ( asoc_rtd_to_cpu ( rtd , 0 ) ,
2019-03-29 16:34:46 +08:00
0 , mclk_fs , SND_SOC_CLOCK_OUT ) ;
}
static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {
. hw_params = mt8183_mt6358_i2s_hw_params ,
} ;
2020-07-08 19:32:33 +08:00
static int
mt8183_mt6358_rt1015_i2s_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
2020-07-20 10:18:48 +09:00
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd ( substream ) ;
2020-07-08 19:32:33 +08:00
unsigned int rate = params_rate ( params ) ;
unsigned int mclk_fs_ratio = 128 ;
unsigned int mclk_fs = rate * mclk_fs_ratio ;
struct snd_soc_card * card = rtd - > card ;
struct snd_soc_dai * codec_dai ;
int ret , i ;
for_each_rtd_codec_dais ( rtd , i , codec_dai ) {
ret = snd_soc_dai_set_pll ( codec_dai , 0 , RT1015_PLL_S_BCLK ,
rate * 64 , rate * 256 ) ;
if ( ret < 0 ) {
dev_err ( card - > dev , " failed to set pll \n " ) ;
return ret ;
}
ret = snd_soc_dai_set_sysclk ( codec_dai , RT1015_SCLK_S_PLL ,
rate * 256 , SND_SOC_CLOCK_IN ) ;
if ( ret < 0 ) {
dev_err ( card - > dev , " failed to set sysclk \n " ) ;
return ret ;
}
}
return snd_soc_dai_set_sysclk ( asoc_rtd_to_cpu ( rtd , 0 ) ,
0 , mclk_fs , SND_SOC_CLOCK_OUT ) ;
}
static const struct snd_soc_ops mt8183_mt6358_rt1015_i2s_ops = {
. hw_params = mt8183_mt6358_rt1015_i2s_hw_params ,
} ;
2019-03-29 16:34:46 +08:00
static int mt8183_i2s_hw_params_fixup ( struct snd_soc_pcm_runtime * rtd ,
struct snd_pcm_hw_params * params )
{
2021-12-09 15:32:24 +08:00
dev_dbg ( rtd - > dev , " %s(), fix format to S32_LE \n " , __func__ ) ;
2019-03-29 16:34:46 +08:00
2021-12-09 15:32:24 +08:00
/* fix BE i2s format to S32_LE, clean param mask first */
2019-03-29 16:34:46 +08:00
snd_mask_reset_range ( hw_param_mask ( params , SNDRV_PCM_HW_PARAM_FORMAT ) ,
2021-12-09 15:32:24 +08:00
0 , ( __force unsigned int ) SNDRV_PCM_FORMAT_LAST ) ;
2019-03-29 16:34:46 +08:00
params_set_format ( params , SNDRV_PCM_FORMAT_S32_LE ) ;
return 0 ;
}
2020-07-08 19:32:33 +08:00
static int mt8183_rt1015_i2s_hw_params_fixup ( struct snd_soc_pcm_runtime * rtd ,
struct snd_pcm_hw_params * params )
{
2021-12-09 15:32:24 +08:00
dev_dbg ( rtd - > dev , " %s(), fix format to S24_LE \n " , __func__ ) ;
2020-07-08 19:32:33 +08:00
2021-12-09 15:32:24 +08:00
/* fix BE i2s format to S24_LE, clean param mask first */
2020-07-08 19:32:33 +08:00
snd_mask_reset_range ( hw_param_mask ( params , SNDRV_PCM_HW_PARAM_FORMAT ) ,
2021-12-09 15:32:24 +08:00
0 , ( __force unsigned int ) SNDRV_PCM_FORMAT_LAST ) ;
2020-07-08 19:32:33 +08:00
params_set_format ( params , SNDRV_PCM_FORMAT_S24_LE ) ;
return 0 ;
}
2021-02-05 16:16:52 +08:00
static int
mt8183_mt6358_startup ( struct snd_pcm_substream * substream )
{
static const unsigned int rates [ ] = {
48000 ,
} ;
static const struct snd_pcm_hw_constraint_list constraints_rates = {
. count = ARRAY_SIZE ( rates ) ,
. list = rates ,
. mask = 0 ,
} ;
static const unsigned int channels [ ] = {
2 ,
} ;
static const struct snd_pcm_hw_constraint_list constraints_channels = {
. count = ARRAY_SIZE ( channels ) ,
. list = channels ,
. mask = 0 ,
} ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
snd_pcm_hw_constraint_list ( runtime , 0 ,
SNDRV_PCM_HW_PARAM_RATE , & constraints_rates ) ;
runtime - > hw . channels_max = 2 ;
snd_pcm_hw_constraint_list ( runtime , 0 ,
SNDRV_PCM_HW_PARAM_CHANNELS ,
& constraints_channels ) ;
runtime - > hw . formats = SNDRV_PCM_FMTBIT_S16_LE ;
snd_pcm_hw_constraint_msbits ( runtime , 0 , 16 , 16 ) ;
return 0 ;
}
static const struct snd_soc_ops mt8183_mt6358_ops = {
. startup = mt8183_mt6358_startup ,
} ;
2019-04-08 18:47:28 +08:00
static int
mt8183_mt6358_ts3a227_max98357_bt_sco_startup (
struct snd_pcm_substream * substream )
{
static const unsigned int rates [ ] = {
8000 , 16000
} ;
static const struct snd_pcm_hw_constraint_list constraints_rates = {
. count = ARRAY_SIZE ( rates ) ,
. list = rates ,
. mask = 0 ,
} ;
static const unsigned int channels [ ] = {
1 ,
} ;
static const struct snd_pcm_hw_constraint_list constraints_channels = {
. count = ARRAY_SIZE ( channels ) ,
. list = channels ,
. mask = 0 ,
} ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
snd_pcm_hw_constraint_list ( runtime , 0 ,
SNDRV_PCM_HW_PARAM_RATE , & constraints_rates ) ;
runtime - > hw . channels_max = 1 ;
snd_pcm_hw_constraint_list ( runtime , 0 ,
SNDRV_PCM_HW_PARAM_CHANNELS ,
& constraints_channels ) ;
runtime - > hw . formats = SNDRV_PCM_FMTBIT_S16_LE ;
snd_pcm_hw_constraint_msbits ( runtime , 0 , 16 , 16 ) ;
return 0 ;
}
static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_bt_sco_ops = {
. startup = mt8183_mt6358_ts3a227_max98357_bt_sco_startup ,
} ;
2019-06-06 13:08:49 +09:00
/* FE */
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 ( playback3 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " DL3 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( capture1 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " UL1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( capture2 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " UL2 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( capture3 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " UL3 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( capture_mono ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " UL_MONO_1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( playback_hdmi ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " HDMI " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2019-10-19 15:02:54 +08:00
SND_SOC_DAILINK_DEFS ( wake_on_voice ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2019-06-06 13:08:49 +09:00
/* BE */
SND_SOC_DAILINK_DEFS ( primary_codec ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " ADDA " ) ) ,
DAILINK_COMP_ARRAY ( COMP_CODEC ( " mt6358-sound " , " mt6358-snd-codec-aif1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( pcm1 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " PCM 1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( pcm2 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " PCM 2 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( i2s0 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " I2S0 " ) ) ,
2022-03-07 11:30:56 +08:00
DAILINK_COMP_ARRAY ( COMP_CODEC ( " bt-sco " , " bt-sco-pcm-wb " ) ) ,
2019-06-06 13:08:49 +09:00
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( i2s1 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " I2S1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( i2s2 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " I2S2 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_DUMMY ( ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2020-07-08 19:32:33 +08:00
SND_SOC_DAILINK_DEFS ( i2s3_max98357a ,
2019-06-06 13:08:49 +09:00
DAILINK_COMP_ARRAY ( COMP_CPU ( " I2S3 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_CODEC ( " max98357a " , " HiFi " ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2020-07-08 19:32:33 +08:00
SND_SOC_DAILINK_DEFS ( i2s3_rt1015 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " I2S3 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_CODEC ( RT1015_DEV0_NAME , RT1015_CODEC_DAI ) ,
COMP_CODEC ( RT1015_DEV1_NAME , RT1015_CODEC_DAI ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2021-03-11 11:31:51 +08:00
SND_SOC_DAILINK_DEFS ( i2s3_rt1015p ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " I2S3 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_CODEC ( " rt1015p " , " HiFi " ) ) ,
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_DEFS ( i2s5 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " I2S5 " ) ) ,
2022-03-07 11:30:56 +08:00
DAILINK_COMP_ARRAY ( COMP_CODEC ( " bt-sco " , " bt-sco-pcm-wb " ) ) ,
2019-06-06 13:08:49 +09:00
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
SND_SOC_DAILINK_DEFS ( tdm ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " TDM " ) ) ,
2020-07-10 13:25:01 +08:00
DAILINK_COMP_ARRAY ( COMP_CODEC ( NULL , " i2s-hifi " ) ) ,
2019-06-06 13:08:49 +09:00
DAILINK_COMP_ARRAY ( COMP_EMPTY ( ) ) ) ;
2019-08-22 20:51:00 +08:00
static int mt8183_mt6358_tdm_startup ( struct snd_pcm_substream * substream )
{
2020-07-20 10:18:48 +09:00
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd ( substream ) ;
2019-08-22 20:51:00 +08:00
struct mt8183_mt6358_ts3a227_max98357_priv * priv =
snd_soc_card_get_drvdata ( rtd - > card ) ;
int ret ;
if ( IS_ERR ( priv - > pin_states [ PIN_TDM_OUT_ON ] ) )
return PTR_ERR ( priv - > pin_states [ PIN_TDM_OUT_ON ] ) ;
ret = pinctrl_select_state ( priv - > pinctrl ,
priv - > pin_states [ PIN_TDM_OUT_ON ] ) ;
if ( ret )
dev_err ( rtd - > card - > dev , " %s failed to select state %d \n " ,
__func__ , ret ) ;
return ret ;
}
static void mt8183_mt6358_tdm_shutdown ( struct snd_pcm_substream * substream )
{
2020-07-20 10:18:48 +09:00
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd ( substream ) ;
2019-08-22 20:51:00 +08:00
struct mt8183_mt6358_ts3a227_max98357_priv * priv =
snd_soc_card_get_drvdata ( rtd - > card ) ;
int ret ;
if ( IS_ERR ( priv - > pin_states [ PIN_TDM_OUT_OFF ] ) )
return ;
ret = pinctrl_select_state ( priv - > pinctrl ,
priv - > pin_states [ PIN_TDM_OUT_OFF ] ) ;
if ( ret )
dev_err ( rtd - > card - > dev , " %s failed to select state %d \n " ,
__func__ , ret ) ;
}
2021-10-12 22:55:21 +02:00
static const struct snd_soc_ops mt8183_mt6358_tdm_ops = {
2019-08-22 20:51:00 +08:00
. startup = mt8183_mt6358_tdm_startup ,
. shutdown = mt8183_mt6358_tdm_shutdown ,
} ;
2019-10-19 15:02:54 +08:00
static int
mt8183_mt6358_ts3a227_max98357_wov_startup (
struct snd_pcm_substream * substream )
{
2020-07-20 10:18:48 +09:00
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd ( substream ) ;
2019-10-19 15:02:54 +08:00
struct snd_soc_card * card = rtd - > card ;
struct mt8183_mt6358_ts3a227_max98357_priv * priv =
snd_soc_card_get_drvdata ( card ) ;
return pinctrl_select_state ( priv - > pinctrl ,
priv - > pin_states [ PIN_WOV ] ) ;
}
static void
mt8183_mt6358_ts3a227_max98357_wov_shutdown (
struct snd_pcm_substream * substream )
{
2020-07-20 10:18:48 +09:00
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd ( substream ) ;
2019-10-19 15:02:54 +08:00
struct snd_soc_card * card = rtd - > card ;
struct mt8183_mt6358_ts3a227_max98357_priv * priv =
snd_soc_card_get_drvdata ( card ) ;
int ret ;
ret = pinctrl_select_state ( priv - > pinctrl ,
priv - > pin_states [ PIN_STATE_DEFAULT ] ) ;
if ( ret )
dev_err ( card - > dev , " %s failed to select state %d \n " ,
__func__ , ret ) ;
}
static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_wov_ops = {
. startup = mt8183_mt6358_ts3a227_max98357_wov_startup ,
. shutdown = mt8183_mt6358_ts3a227_max98357_wov_shutdown ,
} ;
2020-07-10 13:25:02 +08:00
static int
mt8183_mt6358_ts3a227_max98357_hdmi_init ( struct snd_soc_pcm_runtime * rtd )
{
struct mt8183_mt6358_ts3a227_max98357_priv * priv =
snd_soc_card_get_drvdata ( rtd - > card ) ;
int ret ;
ret = snd_soc_card_jack_new ( rtd - > card , " HDMI Jack " , SND_JACK_LINEOUT ,
2022-04-08 13:11:14 +09:00
& priv - > hdmi_jack ) ;
2020-07-10 13:25:02 +08:00
if ( ret )
return ret ;
2020-09-22 14:23:16 +08:00
return snd_soc_component_set_jack ( asoc_rtd_to_codec ( rtd , 0 ) - > component ,
& priv - > hdmi_jack , NULL ) ;
2020-07-10 13:25:02 +08:00
}
2020-07-08 19:32:33 +08:00
static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links [ ] = {
2019-03-29 16:34:46 +08:00
/* FE */
{
. name = " Playback_1 " ,
. stream_name = " Playback_1 " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_playback = 1 ,
2021-02-05 16:16:52 +08:00
. ops = & mt8183_mt6358_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( playback1 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " Playback_2 " ,
. stream_name = " Playback_2 " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_playback = 1 ,
2019-04-08 18:47:28 +08:00
. ops = & mt8183_mt6358_ts3a227_max98357_bt_sco_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( playback2 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " Playback_3 " ,
. stream_name = " Playback_3 " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_playback = 1 ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( playback3 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " Capture_1 " ,
. stream_name = " Capture_1 " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_capture = 1 ,
2019-04-08 18:47:28 +08:00
. ops = & mt8183_mt6358_ts3a227_max98357_bt_sco_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( capture1 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " Capture_2 " ,
. stream_name = " Capture_2 " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_capture = 1 ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( capture2 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " Capture_3 " ,
. stream_name = " Capture_3 " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_capture = 1 ,
2021-02-05 16:16:52 +08:00
. ops = & mt8183_mt6358_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( capture3 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " Capture_Mono_1 " ,
. stream_name = " Capture_Mono_1 " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_capture = 1 ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( capture_mono ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " Playback_HDMI " ,
. stream_name = " Playback_HDMI " ,
. trigger = { SND_SOC_DPCM_TRIGGER_PRE ,
SND_SOC_DPCM_TRIGGER_PRE } ,
. dynamic = 1 ,
. dpcm_playback = 1 ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( playback_hdmi ) ,
2019-03-29 16:34:46 +08:00
} ,
2019-10-19 15:02:54 +08:00
{
. name = " Wake on Voice " ,
. stream_name = " Wake on Voice " ,
. ignore_suspend = 1 ,
. ignore = 1 ,
SND_SOC_DAILINK_REG ( wake_on_voice ) ,
. ops = & mt8183_mt6358_ts3a227_max98357_wov_ops ,
} ,
2019-03-29 16:34:46 +08:00
/* BE */
{
. name = " Primary Codec " ,
. no_pcm = 1 ,
. dpcm_playback = 1 ,
. dpcm_capture = 1 ,
. ignore_suspend = 1 ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( primary_codec ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " PCM 1 " ,
. no_pcm = 1 ,
. dpcm_playback = 1 ,
. dpcm_capture = 1 ,
. ignore_suspend = 1 ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( pcm1 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " PCM 2 " ,
. no_pcm = 1 ,
. dpcm_playback = 1 ,
. dpcm_capture = 1 ,
. ignore_suspend = 1 ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( pcm2 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " I2S0 " ,
. no_pcm = 1 ,
. dpcm_capture = 1 ,
. ignore_suspend = 1 ,
. ops = & mt8183_mt6358_i2s_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( i2s0 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " I2S1 " ,
. no_pcm = 1 ,
. dpcm_playback = 1 ,
. ignore_suspend = 1 ,
. be_hw_params_fixup = mt8183_i2s_hw_params_fixup ,
. ops = & mt8183_mt6358_i2s_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( i2s1 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " I2S2 " ,
. no_pcm = 1 ,
. dpcm_capture = 1 ,
. ignore_suspend = 1 ,
. be_hw_params_fixup = mt8183_i2s_hw_params_fixup ,
. ops = & mt8183_mt6358_i2s_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( i2s2 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " I2S3 " ,
. no_pcm = 1 ,
. dpcm_playback = 1 ,
. ignore_suspend = 1 ,
} ,
{
. name = " I2S5 " ,
. no_pcm = 1 ,
. dpcm_playback = 1 ,
. ignore_suspend = 1 ,
. ops = & mt8183_mt6358_i2s_ops ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( i2s5 ) ,
2019-03-29 16:34:46 +08:00
} ,
{
. name = " TDM " ,
. no_pcm = 1 ,
2019-08-24 12:37:24 +08:00
. dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_IB_IF |
SND_SOC_DAIFMT_CBM_CFM ,
2019-03-29 16:34:46 +08:00
. dpcm_playback = 1 ,
. ignore_suspend = 1 ,
2019-08-22 20:51:00 +08:00
. be_hw_params_fixup = mt8183_i2s_hw_params_fixup ,
. ops = & mt8183_mt6358_tdm_ops ,
2021-01-20 17:22:36 +08:00
. ignore = 1 ,
2020-07-10 13:25:02 +08:00
. init = mt8183_mt6358_ts3a227_max98357_hdmi_init ,
2019-06-06 13:08:49 +09:00
SND_SOC_DAILINK_REG ( tdm ) ,
2019-03-29 16:34:46 +08:00
} ,
} ;
static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = {
. name = " mt8183_mt6358_ts3a227_max98357 " ,
. owner = THIS_MODULE ,
2020-07-08 19:32:33 +08:00
. dai_link = mt8183_mt6358_ts3a227_dai_links ,
. num_links = ARRAY_SIZE ( mt8183_mt6358_ts3a227_dai_links ) ,
} ;
2020-07-20 09:25:59 +08:00
static struct snd_soc_card mt8183_mt6358_ts3a227_max98357b_card = {
. name = " mt8183_mt6358_ts3a227_max98357b " ,
. owner = THIS_MODULE ,
. dai_link = mt8183_mt6358_ts3a227_dai_links ,
. num_links = ARRAY_SIZE ( mt8183_mt6358_ts3a227_dai_links ) ,
} ;
2020-07-08 19:32:33 +08:00
static struct snd_soc_codec_conf mt8183_mt6358_ts3a227_rt1015_amp_conf [ ] = {
{
. dlc = COMP_CODEC_CONF ( RT1015_DEV0_NAME ) ,
. name_prefix = " Left " ,
} ,
{
. dlc = COMP_CODEC_CONF ( RT1015_DEV1_NAME ) ,
. name_prefix = " Right " ,
} ,
} ;
static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015_card = {
. name = " mt8183_mt6358_ts3a227_rt1015 " ,
. owner = THIS_MODULE ,
. dai_link = mt8183_mt6358_ts3a227_dai_links ,
. num_links = ARRAY_SIZE ( mt8183_mt6358_ts3a227_dai_links ) ,
. codec_conf = mt8183_mt6358_ts3a227_rt1015_amp_conf ,
. num_configs = ARRAY_SIZE ( mt8183_mt6358_ts3a227_rt1015_amp_conf ) ,
2019-03-29 16:34:46 +08:00
} ;
2021-03-11 11:31:51 +08:00
static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015p_card = {
. name = " mt8183_mt6358_ts3a227_rt1015p " ,
. owner = THIS_MODULE ,
. dai_link = mt8183_mt6358_ts3a227_dai_links ,
. num_links = ARRAY_SIZE ( mt8183_mt6358_ts3a227_dai_links ) ,
} ;
2019-03-29 16:34:46 +08:00
static int
mt8183_mt6358_ts3a227_max98357_headset_init ( struct snd_soc_component * component )
{
int ret ;
2019-08-30 15:42:38 +08:00
struct mt8183_mt6358_ts3a227_max98357_priv * priv =
snd_soc_card_get_drvdata ( component - > card ) ;
2019-03-29 16:34:46 +08:00
/* Enable Headset and 4 Buttons Jack detection */
2020-07-08 19:32:33 +08:00
ret = snd_soc_card_jack_new ( component - > card ,
2019-03-29 16:34:46 +08:00
" Headset Jack " ,
SND_JACK_HEADSET |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3 ,
2022-04-08 13:11:14 +09:00
& priv - > headset_jack ) ;
2019-03-29 16:34:46 +08:00
if ( ret )
return ret ;
2019-08-30 15:42:38 +08:00
ret = ts3a227e_enable_jack_detect ( component , & priv - > headset_jack ) ;
2019-03-29 16:34:46 +08:00
return ret ;
}
2019-08-30 15:42:39 +08:00
static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = {
. dlc = COMP_EMPTY ( ) ,
. init = mt8183_mt6358_ts3a227_max98357_headset_init ,
} ;
2019-03-29 16:34:46 +08:00
static int
mt8183_mt6358_ts3a227_max98357_dev_probe ( struct platform_device * pdev )
{
2020-07-08 19:32:33 +08:00
struct snd_soc_card * card ;
2020-07-10 13:25:01 +08:00
struct device_node * platform_node , * ec_codec , * hdmi_codec ;
2019-03-29 16:34:46 +08:00
struct snd_soc_dai_link * dai_link ;
2019-08-22 20:51:00 +08:00
struct mt8183_mt6358_ts3a227_max98357_priv * priv ;
2020-07-08 19:32:33 +08:00
int ret , i ;
2019-03-29 16:34:46 +08:00
platform_node = of_parse_phandle ( pdev - > dev . of_node ,
" mediatek,platform " , 0 ) ;
if ( ! platform_node ) {
dev_err ( & pdev - > dev , " Property 'platform' missing or invalid \n " ) ;
return - EINVAL ;
}
2021-12-27 14:21:53 +08:00
card = ( struct snd_soc_card * ) of_device_get_match_data ( & pdev - > dev ) ;
if ( ! card )
2020-07-08 19:32:33 +08:00
return - EINVAL ;
card - > dev = & pdev - > dev ;
2019-10-19 15:02:54 +08:00
ec_codec = of_parse_phandle ( pdev - > dev . of_node , " mediatek,ec-codec " , 0 ) ;
2020-07-10 13:25:01 +08:00
hdmi_codec = of_parse_phandle ( pdev - > dev . of_node ,
" mediatek,hdmi-codec " , 0 ) ;
2019-10-19 15:02:54 +08:00
2019-03-29 16:34:46 +08:00
for_each_card_prelinks ( card , i , dai_link ) {
2019-10-19 15:02:54 +08:00
if ( ec_codec & & strcmp ( dai_link - > name , " Wake on Voice " ) = = 0 ) {
dai_link - > cpus [ 0 ] . name = NULL ;
dai_link - > cpus [ 0 ] . of_node = ec_codec ;
dai_link - > cpus [ 0 ] . dai_name = NULL ;
dai_link - > codecs [ 0 ] . name = NULL ;
dai_link - > codecs [ 0 ] . of_node = ec_codec ;
dai_link - > codecs [ 0 ] . dai_name = " Wake on Voice " ;
dai_link - > platforms [ 0 ] . of_node = ec_codec ;
dai_link - > ignore = 0 ;
}
2020-07-08 19:32:33 +08:00
if ( strcmp ( dai_link - > name , " I2S3 " ) = = 0 ) {
2020-07-20 09:25:59 +08:00
if ( card = = & mt8183_mt6358_ts3a227_max98357_card | |
card = = & mt8183_mt6358_ts3a227_max98357b_card ) {
2020-07-08 19:32:33 +08:00
dai_link - > be_hw_params_fixup =
mt8183_i2s_hw_params_fixup ;
dai_link - > ops = & mt8183_mt6358_i2s_ops ;
dai_link - > cpus = i2s3_max98357a_cpus ;
dai_link - > num_cpus =
ARRAY_SIZE ( i2s3_max98357a_cpus ) ;
dai_link - > codecs = i2s3_max98357a_codecs ;
dai_link - > num_codecs =
ARRAY_SIZE ( i2s3_max98357a_codecs ) ;
dai_link - > platforms = i2s3_max98357a_platforms ;
dai_link - > num_platforms =
ARRAY_SIZE ( i2s3_max98357a_platforms ) ;
} else if ( card = = & mt8183_mt6358_ts3a227_rt1015_card ) {
dai_link - > be_hw_params_fixup =
mt8183_rt1015_i2s_hw_params_fixup ;
dai_link - > ops = & mt8183_mt6358_rt1015_i2s_ops ;
dai_link - > cpus = i2s3_rt1015_cpus ;
dai_link - > num_cpus =
ARRAY_SIZE ( i2s3_rt1015_cpus ) ;
dai_link - > codecs = i2s3_rt1015_codecs ;
dai_link - > num_codecs =
ARRAY_SIZE ( i2s3_rt1015_codecs ) ;
dai_link - > platforms = i2s3_rt1015_platforms ;
dai_link - > num_platforms =
ARRAY_SIZE ( i2s3_rt1015_platforms ) ;
2021-03-11 11:31:51 +08:00
} else if ( card = = & mt8183_mt6358_ts3a227_rt1015p_card ) {
dai_link - > be_hw_params_fixup =
mt8183_rt1015_i2s_hw_params_fixup ;
dai_link - > ops = & mt8183_mt6358_i2s_ops ;
dai_link - > cpus = i2s3_rt1015p_cpus ;
dai_link - > num_cpus =
ARRAY_SIZE ( i2s3_rt1015p_cpus ) ;
dai_link - > codecs = i2s3_rt1015p_codecs ;
dai_link - > num_codecs =
ARRAY_SIZE ( i2s3_rt1015p_codecs ) ;
dai_link - > platforms = i2s3_rt1015p_platforms ;
dai_link - > num_platforms =
ARRAY_SIZE ( i2s3_rt1015p_platforms ) ;
2020-07-08 19:32:33 +08:00
}
}
2020-07-20 09:25:59 +08:00
if ( card = = & mt8183_mt6358_ts3a227_max98357b_card ) {
if ( strcmp ( dai_link - > name , " I2S2 " ) = = 0 | |
strcmp ( dai_link - > name , " I2S3 " ) = = 0 )
dai_link - > dai_fmt = SND_SOC_DAIFMT_LEFT_J |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ;
}
2021-01-20 17:22:36 +08:00
if ( hdmi_codec & & strcmp ( dai_link - > name , " TDM " ) = = 0 ) {
2020-07-10 13:25:01 +08:00
dai_link - > codecs - > of_node = hdmi_codec ;
2021-01-20 17:22:36 +08:00
dai_link - > ignore = 0 ;
}
2020-07-10 13:25:01 +08:00
2020-07-08 19:32:33 +08:00
if ( ! dai_link - > platforms - > name )
dai_link - > platforms - > of_node = platform_node ;
2019-03-29 16:34:46 +08:00
}
2019-08-08 14:53:52 +09:00
mt8183_mt6358_ts3a227_max98357_headset_dev . dlc . of_node =
2019-03-29 16:34:46 +08:00
of_parse_phandle ( pdev - > dev . of_node ,
" mediatek,headset-codec " , 0 ) ;
2019-08-08 14:53:52 +09:00
if ( mt8183_mt6358_ts3a227_max98357_headset_dev . dlc . of_node ) {
2019-07-16 11:24:17 +08:00
card - > aux_dev = & mt8183_mt6358_ts3a227_max98357_headset_dev ;
card - > num_aux_devs = 1 ;
2019-03-29 16:34:46 +08:00
}
2019-08-22 20:51:00 +08:00
priv = devm_kzalloc ( & pdev - > dev , sizeof ( * priv ) , GFP_KERNEL ) ;
if ( ! priv )
return - ENOMEM ;
snd_soc_card_set_drvdata ( card , priv ) ;
priv - > pinctrl = devm_pinctrl_get ( & pdev - > dev ) ;
if ( IS_ERR ( priv - > pinctrl ) ) {
dev_err ( & pdev - > dev , " %s devm_pinctrl_get failed \n " ,
2019-03-29 16:34:46 +08:00
__func__ ) ;
2019-08-22 20:51:00 +08:00
return PTR_ERR ( priv - > pinctrl ) ;
}
2019-08-30 15:42:40 +08:00
for ( i = 0 ; i < PIN_STATE_MAX ; i + + ) {
2019-08-22 20:51:00 +08:00
priv - > pin_states [ i ] = pinctrl_lookup_state ( priv - > pinctrl ,
mt8183_pin_str [ i ] ) ;
if ( IS_ERR ( priv - > pin_states [ i ] ) ) {
ret = PTR_ERR ( priv - > pin_states [ i ] ) ;
dev_info ( & pdev - > dev , " %s Can't find pin state %s %d \n " ,
__func__ , mt8183_pin_str [ i ] , ret ) ;
}
}
if ( ! IS_ERR ( priv - > pin_states [ PIN_TDM_OUT_OFF ] ) ) {
ret = pinctrl_select_state ( priv - > pinctrl ,
priv - > pin_states [ PIN_TDM_OUT_OFF ] ) ;
if ( ret )
dev_info ( & pdev - > dev ,
" %s failed to select state %d \n " ,
__func__ , ret ) ;
}
if ( ! IS_ERR ( priv - > pin_states [ PIN_STATE_DEFAULT ] ) ) {
ret = pinctrl_select_state ( priv - > pinctrl ,
priv - > pin_states [ PIN_STATE_DEFAULT ] ) ;
if ( ret )
dev_info ( & pdev - > dev ,
" %s failed to select state %d \n " ,
__func__ , ret ) ;
2019-03-29 16:34:46 +08:00
}
2021-12-24 14:47:17 +08:00
ret = devm_snd_soc_register_card ( & pdev - > dev , card ) ;
of_node_put ( platform_node ) ;
of_node_put ( ec_codec ) ;
of_node_put ( hdmi_codec ) ;
return ret ;
2019-03-29 16:34:46 +08:00
}
# ifdef CONFIG_OF
static const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match [ ] = {
2020-07-08 19:32:33 +08:00
{
. compatible = " mediatek,mt8183_mt6358_ts3a227_max98357 " ,
. data = & mt8183_mt6358_ts3a227_max98357_card ,
} ,
2020-07-20 09:25:59 +08:00
{
. compatible = " mediatek,mt8183_mt6358_ts3a227_max98357b " ,
. data = & mt8183_mt6358_ts3a227_max98357b_card ,
} ,
2020-07-08 19:32:33 +08:00
{
. compatible = " mediatek,mt8183_mt6358_ts3a227_rt1015 " ,
. data = & mt8183_mt6358_ts3a227_rt1015_card ,
} ,
2021-03-11 11:31:51 +08:00
{
. compatible = " mediatek,mt8183_mt6358_ts3a227_rt1015p " ,
. data = & mt8183_mt6358_ts3a227_rt1015p_card ,
} ,
2019-03-29 16:34:46 +08:00
{ }
} ;
# endif
static struct platform_driver mt8183_mt6358_ts3a227_max98357_driver = {
. driver = {
2020-07-08 19:32:33 +08:00
. name = " mt8183_mt6358_ts3a227 " ,
2019-03-29 16:34:46 +08:00
# ifdef CONFIG_OF
. of_match_table = mt8183_mt6358_ts3a227_max98357_dt_match ,
# endif
2020-12-11 13:13:34 +08:00
. pm = & snd_soc_pm_ops ,
2019-03-29 16:34:46 +08:00
} ,
. probe = mt8183_mt6358_ts3a227_max98357_dev_probe ,
} ;
module_platform_driver ( mt8183_mt6358_ts3a227_max98357_driver ) ;
/* Module information */
MODULE_DESCRIPTION ( " MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver " ) ;
MODULE_AUTHOR ( " Shunli Wang <shunli.wang@mediatek.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_ALIAS ( " mt8183_mt6358_ts3a227_max98357 soc card " ) ;