Path: blob/master/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
26488 views
// SPDX-License-Identifier: GPL-2.01//2// mt8183-da7219-max98357.c3// -- MT8183-DA7219-MAX98357 ALSA SoC machine driver4//5// Copyright (c) 2018 MediaTek Inc.6// Author: Shunli Wang <[email protected]>78#include <linux/input.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/pinctrl/consumer.h>12#include <sound/jack.h>13#include <sound/pcm_params.h>14#include <sound/soc.h>1516#include "../../codecs/da7219.h"17#include "../../codecs/rt1015.h"18#include "../common/mtk-afe-platform-driver.h"19#include "mt8183-afe-common.h"2021#define DA7219_CODEC_DAI "da7219-hifi"22#define DA7219_DEV_NAME "da7219.5-001a"23#define RT1015_CODEC_DAI "rt1015-aif"24#define RT1015_DEV0_NAME "rt1015.6-0028"25#define RT1015_DEV1_NAME "rt1015.6-0029"2627struct mt8183_da7219_max98357_priv {28struct snd_soc_jack headset_jack, hdmi_jack;29};3031static struct snd_soc_jack_pin mt8183_da7219_max98357_jack_pins[] = {32{33.pin = "Headphones",34.mask = SND_JACK_HEADPHONE,35},36{37.pin = "Headset Mic",38.mask = SND_JACK_MICROPHONE,39},40{41.pin = "Line Out",42.mask = SND_JACK_LINEOUT,43},44};4546static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream,47struct snd_pcm_hw_params *params)48{49struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);50unsigned int rate = params_rate(params);51unsigned int mclk_fs_ratio = 128;52unsigned int mclk_fs = rate * mclk_fs_ratio;5354return snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0),550, mclk_fs, SND_SOC_CLOCK_OUT);56}5758static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {59.hw_params = mt8183_mt6358_i2s_hw_params,60};6162static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream,63struct snd_pcm_hw_params *params)64{65struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);66struct snd_soc_dai *codec_dai;67unsigned int rate = params_rate(params);68unsigned int mclk_fs_ratio = 256;69unsigned int mclk_fs = rate * mclk_fs_ratio;70unsigned int freq;71int ret = 0, j;7273ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0), 0,74mclk_fs, SND_SOC_CLOCK_OUT);75if (ret < 0)76dev_err(rtd->dev, "failed to set cpu dai sysclk\n");7778for_each_rtd_codec_dais(rtd, j, codec_dai) {79if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {80ret = snd_soc_dai_set_sysclk(codec_dai,81DA7219_CLKSRC_MCLK,82mclk_fs,83SND_SOC_CLOCK_IN);84if (ret < 0)85dev_err(rtd->dev, "failed to set sysclk\n");8687if ((rate % 8000) == 0)88freq = DA7219_PLL_FREQ_OUT_98304;89else90freq = DA7219_PLL_FREQ_OUT_90316;9192ret = snd_soc_dai_set_pll(codec_dai, 0,93DA7219_SYSCLK_PLL_SRM,940, freq);95if (ret)96dev_err(rtd->dev, "failed to start PLL: %d\n",97ret);98}99}100101return ret;102}103104static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream)105{106struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);107struct snd_soc_dai *codec_dai;108int ret = 0, j;109110for_each_rtd_codec_dais(rtd, j, codec_dai) {111if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {112ret = snd_soc_dai_set_pll(codec_dai,1130, DA7219_SYSCLK_MCLK, 0, 0);114if (ret < 0) {115dev_err(rtd->dev, "failed to stop PLL: %d\n",116ret);117break;118}119}120}121122return ret;123}124125static const struct snd_soc_ops mt8183_da7219_i2s_ops = {126.hw_params = mt8183_da7219_i2s_hw_params,127.hw_free = mt8183_da7219_hw_free,128};129130static int131mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,132struct snd_pcm_hw_params *params)133{134struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);135unsigned int rate = params_rate(params);136struct snd_soc_dai *codec_dai;137int ret = 0, i;138139for_each_rtd_codec_dais(rtd, i, codec_dai) {140if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) ||141!strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) {142ret = snd_soc_dai_set_pll(codec_dai, 0,143RT1015_PLL_S_BCLK,144rate * 64, rate * 256);145if (ret) {146dev_err(rtd->dev, "failed to set pll\n");147return ret;148}149150ret = snd_soc_dai_set_sysclk(codec_dai,151RT1015_SCLK_S_PLL,152rate * 256,153SND_SOC_CLOCK_IN);154if (ret) {155dev_err(rtd->dev, "failed to set sysclk\n");156return ret;157}158}159}160161return mt8183_da7219_i2s_hw_params(substream, params);162}163164static const struct snd_soc_ops mt8183_da7219_rt1015_i2s_ops = {165.hw_params = mt8183_da7219_rt1015_i2s_hw_params,166.hw_free = mt8183_da7219_hw_free,167};168169static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,170struct snd_pcm_hw_params *params)171{172/* fix BE i2s format to S32_LE, clean param mask first */173snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),1740, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);175176params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);177178return 0;179}180181static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,182struct snd_pcm_hw_params *params)183{184/* fix BE i2s format to S24_LE, clean param mask first */185snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),1860, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);187188params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);189190return 0;191}192193static int194mt8183_da7219_max98357_startup(195struct snd_pcm_substream *substream)196{197static const unsigned int rates[] = {19848000,199};200static const struct snd_pcm_hw_constraint_list constraints_rates = {201.count = ARRAY_SIZE(rates),202.list = rates,203.mask = 0,204};205static const unsigned int channels[] = {2062,207};208static const struct snd_pcm_hw_constraint_list constraints_channels = {209.count = ARRAY_SIZE(channels),210.list = channels,211.mask = 0,212};213214struct snd_pcm_runtime *runtime = substream->runtime;215216snd_pcm_hw_constraint_list(runtime, 0,217SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);218runtime->hw.channels_max = 2;219snd_pcm_hw_constraint_list(runtime, 0,220SNDRV_PCM_HW_PARAM_CHANNELS,221&constraints_channels);222223runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;224snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);225226return 0;227}228229static const struct snd_soc_ops mt8183_da7219_max98357_ops = {230.startup = mt8183_da7219_max98357_startup,231};232233static int234mt8183_da7219_max98357_bt_sco_startup(235struct snd_pcm_substream *substream)236{237static const unsigned int rates[] = {2388000, 16000239};240static const struct snd_pcm_hw_constraint_list constraints_rates = {241.count = ARRAY_SIZE(rates),242.list = rates,243.mask = 0,244};245static const unsigned int channels[] = {2461,247};248static const struct snd_pcm_hw_constraint_list constraints_channels = {249.count = ARRAY_SIZE(channels),250.list = channels,251.mask = 0,252};253254struct snd_pcm_runtime *runtime = substream->runtime;255256snd_pcm_hw_constraint_list(runtime, 0,257SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);258runtime->hw.channels_max = 1;259snd_pcm_hw_constraint_list(runtime, 0,260SNDRV_PCM_HW_PARAM_CHANNELS,261&constraints_channels);262263runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;264snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);265266return 0;267}268269static const struct snd_soc_ops mt8183_da7219_max98357_bt_sco_ops = {270.startup = mt8183_da7219_max98357_bt_sco_startup,271};272273/* FE */274SND_SOC_DAILINK_DEFS(playback1,275DAILINK_COMP_ARRAY(COMP_CPU("DL1")),276DAILINK_COMP_ARRAY(COMP_DUMMY()),277DAILINK_COMP_ARRAY(COMP_EMPTY()));278279SND_SOC_DAILINK_DEFS(playback2,280DAILINK_COMP_ARRAY(COMP_CPU("DL2")),281DAILINK_COMP_ARRAY(COMP_DUMMY()),282DAILINK_COMP_ARRAY(COMP_EMPTY()));283284SND_SOC_DAILINK_DEFS(playback3,285DAILINK_COMP_ARRAY(COMP_CPU("DL3")),286DAILINK_COMP_ARRAY(COMP_DUMMY()),287DAILINK_COMP_ARRAY(COMP_EMPTY()));288289SND_SOC_DAILINK_DEFS(capture1,290DAILINK_COMP_ARRAY(COMP_CPU("UL1")),291DAILINK_COMP_ARRAY(COMP_DUMMY()),292DAILINK_COMP_ARRAY(COMP_EMPTY()));293294SND_SOC_DAILINK_DEFS(capture2,295DAILINK_COMP_ARRAY(COMP_CPU("UL2")),296DAILINK_COMP_ARRAY(COMP_DUMMY()),297DAILINK_COMP_ARRAY(COMP_EMPTY()));298299SND_SOC_DAILINK_DEFS(capture3,300DAILINK_COMP_ARRAY(COMP_CPU("UL3")),301DAILINK_COMP_ARRAY(COMP_DUMMY()),302DAILINK_COMP_ARRAY(COMP_EMPTY()));303304SND_SOC_DAILINK_DEFS(capture_mono,305DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),306DAILINK_COMP_ARRAY(COMP_DUMMY()),307DAILINK_COMP_ARRAY(COMP_EMPTY()));308309SND_SOC_DAILINK_DEFS(playback_hdmi,310DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),311DAILINK_COMP_ARRAY(COMP_DUMMY()),312DAILINK_COMP_ARRAY(COMP_EMPTY()));313314/* BE */315SND_SOC_DAILINK_DEFS(primary_codec,316DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),317DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")),318DAILINK_COMP_ARRAY(COMP_EMPTY()));319320SND_SOC_DAILINK_DEFS(pcm1,321DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),322DAILINK_COMP_ARRAY(COMP_DUMMY()),323DAILINK_COMP_ARRAY(COMP_EMPTY()));324325SND_SOC_DAILINK_DEFS(pcm2,326DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),327DAILINK_COMP_ARRAY(COMP_DUMMY()),328DAILINK_COMP_ARRAY(COMP_EMPTY()));329330SND_SOC_DAILINK_DEFS(i2s0,331DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),332DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),333DAILINK_COMP_ARRAY(COMP_EMPTY()));334335SND_SOC_DAILINK_DEFS(i2s1,336DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),337DAILINK_COMP_ARRAY(COMP_DUMMY()),338DAILINK_COMP_ARRAY(COMP_EMPTY()));339340SND_SOC_DAILINK_DEFS(i2s2,341DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),342DAILINK_COMP_ARRAY(COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),343DAILINK_COMP_ARRAY(COMP_EMPTY()));344345SND_SOC_DAILINK_DEFS(i2s3_max98357a,346DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),347DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"),348COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),349DAILINK_COMP_ARRAY(COMP_EMPTY()));350351SND_SOC_DAILINK_DEFS(i2s3_rt1015,352DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),353DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI),354COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI),355COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),356DAILINK_COMP_ARRAY(COMP_EMPTY()));357358SND_SOC_DAILINK_DEFS(i2s3_rt1015p,359DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),360DAILINK_COMP_ARRAY(COMP_CODEC("rt1015p", "HiFi"),361COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),362DAILINK_COMP_ARRAY(COMP_EMPTY()));363364SND_SOC_DAILINK_DEFS(i2s5,365DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),366DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),367DAILINK_COMP_ARRAY(COMP_EMPTY()));368369SND_SOC_DAILINK_DEFS(tdm,370DAILINK_COMP_ARRAY(COMP_CPU("TDM")),371DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),372DAILINK_COMP_ARRAY(COMP_EMPTY()));373374static int mt8183_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)375{376struct mt8183_da7219_max98357_priv *priv =377snd_soc_card_get_drvdata(rtd->card);378int ret;379380ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,381&priv->hdmi_jack);382if (ret)383return ret;384385return snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component,386&priv->hdmi_jack, NULL);387}388389static int mt8183_bt_init(struct snd_soc_pcm_runtime *rtd)390{391struct snd_soc_component *cmpnt_afe =392snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);393struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);394int ret;395396ret = mt8183_dai_i2s_set_share(afe, "I2S5", "I2S0");397if (ret) {398dev_err(rtd->dev, "Failed to set up shared clocks\n");399return ret;400}401return 0;402}403404static int mt8183_da7219_init(struct snd_soc_pcm_runtime *rtd)405{406struct snd_soc_component *cmpnt_afe =407snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);408struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);409int ret;410411ret = mt8183_dai_i2s_set_share(afe, "I2S2", "I2S3");412if (ret) {413dev_err(rtd->dev, "Failed to set up shared clocks\n");414return ret;415}416return 0;417}418419static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {420/* FE */421{422.name = "Playback_1",423.stream_name = "Playback_1",424.trigger = {SND_SOC_DPCM_TRIGGER_PRE,425SND_SOC_DPCM_TRIGGER_PRE},426.dynamic = 1,427.playback_only = 1,428.ops = &mt8183_da7219_max98357_ops,429SND_SOC_DAILINK_REG(playback1),430},431{432.name = "Playback_2",433.stream_name = "Playback_2",434.trigger = {SND_SOC_DPCM_TRIGGER_PRE,435SND_SOC_DPCM_TRIGGER_PRE},436.dynamic = 1,437.playback_only = 1,438.ops = &mt8183_da7219_max98357_bt_sco_ops,439SND_SOC_DAILINK_REG(playback2),440},441{442.name = "Playback_3",443.stream_name = "Playback_3",444.trigger = {SND_SOC_DPCM_TRIGGER_PRE,445SND_SOC_DPCM_TRIGGER_PRE},446.dynamic = 1,447.playback_only = 1,448SND_SOC_DAILINK_REG(playback3),449},450{451.name = "Capture_1",452.stream_name = "Capture_1",453.trigger = {SND_SOC_DPCM_TRIGGER_PRE,454SND_SOC_DPCM_TRIGGER_PRE},455.dynamic = 1,456.capture_only = 1,457.ops = &mt8183_da7219_max98357_bt_sco_ops,458SND_SOC_DAILINK_REG(capture1),459},460{461.name = "Capture_2",462.stream_name = "Capture_2",463.trigger = {SND_SOC_DPCM_TRIGGER_PRE,464SND_SOC_DPCM_TRIGGER_PRE},465.dynamic = 1,466.capture_only = 1,467SND_SOC_DAILINK_REG(capture2),468},469{470.name = "Capture_3",471.stream_name = "Capture_3",472.trigger = {SND_SOC_DPCM_TRIGGER_PRE,473SND_SOC_DPCM_TRIGGER_PRE},474.dynamic = 1,475.capture_only = 1,476.ops = &mt8183_da7219_max98357_ops,477SND_SOC_DAILINK_REG(capture3),478},479{480.name = "Capture_Mono_1",481.stream_name = "Capture_Mono_1",482.trigger = {SND_SOC_DPCM_TRIGGER_PRE,483SND_SOC_DPCM_TRIGGER_PRE},484.dynamic = 1,485.capture_only = 1,486SND_SOC_DAILINK_REG(capture_mono),487},488{489.name = "Playback_HDMI",490.stream_name = "Playback_HDMI",491.trigger = {SND_SOC_DPCM_TRIGGER_PRE,492SND_SOC_DPCM_TRIGGER_PRE},493.dynamic = 1,494.playback_only = 1,495SND_SOC_DAILINK_REG(playback_hdmi),496},497/* BE */498{499.name = "Primary Codec",500.no_pcm = 1,501.ignore_suspend = 1,502SND_SOC_DAILINK_REG(primary_codec),503},504{505.name = "PCM 1",506.no_pcm = 1,507.ignore_suspend = 1,508SND_SOC_DAILINK_REG(pcm1),509},510{511.name = "PCM 2",512.no_pcm = 1,513.ignore_suspend = 1,514SND_SOC_DAILINK_REG(pcm2),515},516{517.name = "I2S0",518.no_pcm = 1,519.capture_only = 1,520.ignore_suspend = 1,521.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,522.ops = &mt8183_mt6358_i2s_ops,523SND_SOC_DAILINK_REG(i2s0),524},525{526.name = "I2S1",527.no_pcm = 1,528.playback_only = 1,529.ignore_suspend = 1,530.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,531.ops = &mt8183_mt6358_i2s_ops,532SND_SOC_DAILINK_REG(i2s1),533},534{535.name = "I2S2",536.no_pcm = 1,537.capture_only = 1,538.ignore_suspend = 1,539.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,540.ops = &mt8183_da7219_i2s_ops,541.init = &mt8183_da7219_init,542SND_SOC_DAILINK_REG(i2s2),543},544{545.name = "I2S3",546.no_pcm = 1,547.playback_only = 1,548.ignore_suspend = 1,549},550{551.name = "I2S5",552.no_pcm = 1,553.playback_only = 1,554.ignore_suspend = 1,555.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,556.ops = &mt8183_mt6358_i2s_ops,557.init = &mt8183_bt_init,558SND_SOC_DAILINK_REG(i2s5),559},560{561.name = "TDM",562.no_pcm = 1,563.dai_fmt = SND_SOC_DAIFMT_I2S |564SND_SOC_DAIFMT_IB_IF |565SND_SOC_DAIFMT_CBP_CFP,566.playback_only = 1,567.ignore_suspend = 1,568.be_hw_params_fixup = mt8183_i2s_hw_params_fixup,569.ignore = 1,570.init = mt8183_da7219_max98357_hdmi_init,571SND_SOC_DAILINK_REG(tdm),572},573};574575static int576mt8183_da7219_max98357_headset_init(struct snd_soc_component *component)577{578int ret;579struct mt8183_da7219_max98357_priv *priv =580snd_soc_card_get_drvdata(component->card);581582/* Enable Headset and 4 Buttons Jack detection */583ret = snd_soc_card_jack_new_pins(component->card,584"Headset Jack",585SND_JACK_HEADSET |586SND_JACK_BTN_0 | SND_JACK_BTN_1 |587SND_JACK_BTN_2 | SND_JACK_BTN_3 |588SND_JACK_LINEOUT,589&priv->headset_jack,590mt8183_da7219_max98357_jack_pins,591ARRAY_SIZE(mt8183_da7219_max98357_jack_pins));592if (ret)593return ret;594595snd_jack_set_key(596priv->headset_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);597snd_jack_set_key(598priv->headset_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);599snd_jack_set_key(600priv->headset_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);601snd_jack_set_key(602priv->headset_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);603604snd_soc_component_set_jack(component, &priv->headset_jack, NULL);605606return 0;607}608609static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = {610.dlc = COMP_EMPTY(),611.init = mt8183_da7219_max98357_headset_init,612};613614static struct snd_soc_codec_conf mt6358_codec_conf[] = {615{616.dlc = COMP_CODEC_CONF("mt6358-sound"),617.name_prefix = "Mt6358",618},619};620621static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = {622SOC_DAPM_PIN_SWITCH("Headphones"),623SOC_DAPM_PIN_SWITCH("Headset Mic"),624SOC_DAPM_PIN_SWITCH("Speakers"),625SOC_DAPM_PIN_SWITCH("Line Out"),626};627628static const629struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = {630SND_SOC_DAPM_HP("Headphones", NULL),631SND_SOC_DAPM_MIC("Headset Mic", NULL),632SND_SOC_DAPM_SPK("Speakers", NULL),633SND_SOC_DAPM_SPK("Line Out", NULL),634SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL",635"aud_tdm_out_on", "aud_tdm_out_off"),636};637638static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = {639{"Speakers", NULL, "Speaker"},640{"I2S Playback", NULL, "TDM_OUT_PINCTRL"},641};642643static struct snd_soc_card mt8183_da7219_max98357_card = {644.name = "mt8183_da7219_max98357",645.owner = THIS_MODULE,646.controls = mt8183_da7219_max98357_snd_controls,647.num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls),648.dapm_widgets = mt8183_da7219_max98357_dapm_widgets,649.num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets),650.dapm_routes = mt8183_da7219_max98357_dapm_routes,651.num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes),652.dai_link = mt8183_da7219_dai_links,653.num_links = ARRAY_SIZE(mt8183_da7219_dai_links),654.aux_dev = &mt8183_da7219_max98357_headset_dev,655.num_aux_devs = 1,656.codec_conf = mt6358_codec_conf,657.num_configs = ARRAY_SIZE(mt6358_codec_conf),658};659660static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = {661{662.dlc = COMP_CODEC_CONF("mt6358-sound"),663.name_prefix = "Mt6358",664},665{666.dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),667.name_prefix = "Left",668},669{670.dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),671.name_prefix = "Right",672},673};674675static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {676SOC_DAPM_PIN_SWITCH("Headphones"),677SOC_DAPM_PIN_SWITCH("Headset Mic"),678SOC_DAPM_PIN_SWITCH("Left Spk"),679SOC_DAPM_PIN_SWITCH("Right Spk"),680SOC_DAPM_PIN_SWITCH("Line Out"),681};682683static const684struct snd_soc_dapm_widget mt8183_da7219_rt1015_dapm_widgets[] = {685SND_SOC_DAPM_HP("Headphones", NULL),686SND_SOC_DAPM_MIC("Headset Mic", NULL),687SND_SOC_DAPM_SPK("Left Spk", NULL),688SND_SOC_DAPM_SPK("Right Spk", NULL),689SND_SOC_DAPM_LINE("Line Out", NULL),690SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL",691"aud_tdm_out_on", "aud_tdm_out_off"),692};693694static const struct snd_soc_dapm_route mt8183_da7219_rt1015_dapm_routes[] = {695{"Left Spk", NULL, "Left SPO"},696{"Right Spk", NULL, "Right SPO"},697{"I2S Playback", NULL, "TDM_OUT_PINCTRL"},698};699700static struct snd_soc_card mt8183_da7219_rt1015_card = {701.name = "mt8183_da7219_rt1015",702.owner = THIS_MODULE,703.controls = mt8183_da7219_rt1015_snd_controls,704.num_controls = ARRAY_SIZE(mt8183_da7219_rt1015_snd_controls),705.dapm_widgets = mt8183_da7219_rt1015_dapm_widgets,706.num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_widgets),707.dapm_routes = mt8183_da7219_rt1015_dapm_routes,708.num_dapm_routes = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_routes),709.dai_link = mt8183_da7219_dai_links,710.num_links = ARRAY_SIZE(mt8183_da7219_dai_links),711.aux_dev = &mt8183_da7219_max98357_headset_dev,712.num_aux_devs = 1,713.codec_conf = mt8183_da7219_rt1015_codec_conf,714.num_configs = ARRAY_SIZE(mt8183_da7219_rt1015_codec_conf),715};716717static struct snd_soc_card mt8183_da7219_rt1015p_card = {718.name = "mt8183_da7219_rt1015p",719.owner = THIS_MODULE,720.controls = mt8183_da7219_max98357_snd_controls,721.num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls),722.dapm_widgets = mt8183_da7219_max98357_dapm_widgets,723.num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets),724.dapm_routes = mt8183_da7219_max98357_dapm_routes,725.num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes),726.dai_link = mt8183_da7219_dai_links,727.num_links = ARRAY_SIZE(mt8183_da7219_dai_links),728.aux_dev = &mt8183_da7219_max98357_headset_dev,729.num_aux_devs = 1,730.codec_conf = mt6358_codec_conf,731.num_configs = ARRAY_SIZE(mt6358_codec_conf),732};733734static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)735{736struct snd_soc_card *card;737struct device_node *platform_node, *hdmi_codec;738struct snd_soc_dai_link *dai_link;739struct mt8183_da7219_max98357_priv *priv;740struct pinctrl *pinctrl;741int ret, i;742743platform_node = of_parse_phandle(pdev->dev.of_node,744"mediatek,platform", 0);745if (!platform_node) {746dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");747return -EINVAL;748}749750card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);751if (!card) {752ret = -EINVAL;753goto put_platform_node;754}755756card->dev = &pdev->dev;757758hdmi_codec = of_parse_phandle(pdev->dev.of_node,759"mediatek,hdmi-codec", 0);760761for_each_card_prelinks(card, i, dai_link) {762if (strcmp(dai_link->name, "I2S3") == 0) {763if (card == &mt8183_da7219_max98357_card) {764dai_link->be_hw_params_fixup =765mt8183_i2s_hw_params_fixup;766dai_link->ops = &mt8183_da7219_i2s_ops;767dai_link->cpus = i2s3_max98357a_cpus;768dai_link->num_cpus =769ARRAY_SIZE(i2s3_max98357a_cpus);770dai_link->codecs = i2s3_max98357a_codecs;771dai_link->num_codecs =772ARRAY_SIZE(i2s3_max98357a_codecs);773dai_link->platforms = i2s3_max98357a_platforms;774dai_link->num_platforms =775ARRAY_SIZE(i2s3_max98357a_platforms);776} else if (card == &mt8183_da7219_rt1015_card) {777dai_link->be_hw_params_fixup =778mt8183_rt1015_i2s_hw_params_fixup;779dai_link->ops = &mt8183_da7219_rt1015_i2s_ops;780dai_link->cpus = i2s3_rt1015_cpus;781dai_link->num_cpus =782ARRAY_SIZE(i2s3_rt1015_cpus);783dai_link->codecs = i2s3_rt1015_codecs;784dai_link->num_codecs =785ARRAY_SIZE(i2s3_rt1015_codecs);786dai_link->platforms = i2s3_rt1015_platforms;787dai_link->num_platforms =788ARRAY_SIZE(i2s3_rt1015_platforms);789} else if (card == &mt8183_da7219_rt1015p_card) {790dai_link->be_hw_params_fixup =791mt8183_rt1015_i2s_hw_params_fixup;792dai_link->ops = &mt8183_da7219_i2s_ops;793dai_link->cpus = i2s3_rt1015p_cpus;794dai_link->num_cpus =795ARRAY_SIZE(i2s3_rt1015p_cpus);796dai_link->codecs = i2s3_rt1015p_codecs;797dai_link->num_codecs =798ARRAY_SIZE(i2s3_rt1015p_codecs);799dai_link->platforms = i2s3_rt1015p_platforms;800dai_link->num_platforms =801ARRAY_SIZE(i2s3_rt1015p_platforms);802}803}804805if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) {806dai_link->codecs->of_node = hdmi_codec;807dai_link->ignore = 0;808}809810if (!dai_link->platforms->name)811dai_link->platforms->of_node = platform_node;812}813814mt8183_da7219_max98357_headset_dev.dlc.of_node =815of_parse_phandle(pdev->dev.of_node,816"mediatek,headset-codec", 0);817if (!mt8183_da7219_max98357_headset_dev.dlc.of_node) {818dev_err(&pdev->dev,819"Property 'mediatek,headset-codec' missing/invalid\n");820ret = -EINVAL;821goto put_hdmi_codec;822}823824priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);825if (!priv) {826ret = -ENOMEM;827goto put_hdmi_codec;828}829830snd_soc_card_set_drvdata(card, priv);831832pinctrl = devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT);833if (IS_ERR(pinctrl)) {834ret = PTR_ERR(pinctrl);835dev_err(&pdev->dev, "%s failed to select default state %d\n",836__func__, ret);837goto put_hdmi_codec;838}839840ret = devm_snd_soc_register_card(&pdev->dev, card);841842843put_hdmi_codec:844of_node_put(hdmi_codec);845put_platform_node:846of_node_put(platform_node);847return ret;848}849850#ifdef CONFIG_OF851static const struct of_device_id mt8183_da7219_max98357_dt_match[] = {852{853.compatible = "mediatek,mt8183_da7219_max98357",854.data = &mt8183_da7219_max98357_card,855},856{857.compatible = "mediatek,mt8183_da7219_rt1015",858.data = &mt8183_da7219_rt1015_card,859},860{861.compatible = "mediatek,mt8183_da7219_rt1015p",862.data = &mt8183_da7219_rt1015p_card,863},864{}865};866MODULE_DEVICE_TABLE(of, mt8183_da7219_max98357_dt_match);867#endif868869static struct platform_driver mt8183_da7219_max98357_driver = {870.driver = {871.name = "mt8183_da7219",872#ifdef CONFIG_OF873.of_match_table = mt8183_da7219_max98357_dt_match,874#endif875.pm = &snd_soc_pm_ops,876},877.probe = mt8183_da7219_max98357_dev_probe,878};879880module_platform_driver(mt8183_da7219_max98357_driver);881882/* Module information */883MODULE_DESCRIPTION("MT8183-DA7219-MAX98357 ALSA SoC machine driver");884MODULE_AUTHOR("Shunli Wang <[email protected]>");885MODULE_LICENSE("GPL v2");886MODULE_ALIAS("mt8183_da7219_max98357 soc card");887888889