1e149ca29SPierre-Louis Bossart // SPDX-License-Identifier: GPL-2.0-only
235dc19adSYong Zhi // Copyright(c) 2019 Intel Corporation.
335dc19adSYong Zhi
435dc19adSYong Zhi /*
53f32e596SYong Zhi * Intel SOF Machine driver for DA7219 + MAX98373/MAX98360A codec
635dc19adSYong Zhi */
735dc19adSYong Zhi
835dc19adSYong Zhi #include <linux/input.h>
935dc19adSYong Zhi #include <linux/module.h>
109a1fe79dSCezary Rojewski #include <sound/jack.h>
1135dc19adSYong Zhi #include <sound/pcm.h>
1235dc19adSYong Zhi #include <sound/pcm_params.h>
1335dc19adSYong Zhi #include <linux/platform_device.h>
1435dc19adSYong Zhi #include <sound/soc.h>
1535dc19adSYong Zhi #include <sound/soc-acpi.h>
1635dc19adSYong Zhi #include "../../codecs/da7219.h"
1735dc19adSYong Zhi #include "hda_dsp_common.h"
1835dc19adSYong Zhi
1935dc19adSYong Zhi #define DIALOG_CODEC_DAI "da7219-hifi"
2035dc19adSYong Zhi #define MAX98373_CODEC_DAI "max98373-aif1"
2135dc19adSYong Zhi #define MAXIM_DEV0_NAME "i2c-MX98373:00"
2235dc19adSYong Zhi #define MAXIM_DEV1_NAME "i2c-MX98373:01"
2335dc19adSYong Zhi
2435dc19adSYong Zhi struct hdmi_pcm {
2535dc19adSYong Zhi struct list_head head;
2635dc19adSYong Zhi struct snd_soc_dai *codec_dai;
2735dc19adSYong Zhi int device;
2835dc19adSYong Zhi };
2935dc19adSYong Zhi
3035dc19adSYong Zhi struct card_private {
3135dc19adSYong Zhi struct snd_soc_jack headset;
3235dc19adSYong Zhi struct list_head hdmi_pcm_list;
3335dc19adSYong Zhi struct snd_soc_jack hdmi[3];
3435dc19adSYong Zhi };
3535dc19adSYong Zhi
platform_clock_control(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)3635dc19adSYong Zhi static int platform_clock_control(struct snd_soc_dapm_widget *w,
3735dc19adSYong Zhi struct snd_kcontrol *k, int event)
3835dc19adSYong Zhi {
3935dc19adSYong Zhi struct snd_soc_dapm_context *dapm = w->dapm;
4035dc19adSYong Zhi struct snd_soc_card *card = dapm->card;
4135dc19adSYong Zhi struct snd_soc_dai *codec_dai;
4235dc19adSYong Zhi int ret = 0;
4335dc19adSYong Zhi
4435dc19adSYong Zhi codec_dai = snd_soc_card_get_codec_dai(card, DIALOG_CODEC_DAI);
4535dc19adSYong Zhi if (!codec_dai) {
4635dc19adSYong Zhi dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
4735dc19adSYong Zhi return -EIO;
4835dc19adSYong Zhi }
4935dc19adSYong Zhi
5035dc19adSYong Zhi if (SND_SOC_DAPM_EVENT_OFF(event)) {
5135dc19adSYong Zhi ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK,
5235dc19adSYong Zhi 0, 0);
5335dc19adSYong Zhi if (ret)
5435dc19adSYong Zhi dev_err(card->dev, "failed to stop PLL: %d\n", ret);
5535dc19adSYong Zhi } else if (SND_SOC_DAPM_EVENT_ON(event)) {
5635dc19adSYong Zhi ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM,
5735dc19adSYong Zhi 0, DA7219_PLL_FREQ_OUT_98304);
5835dc19adSYong Zhi if (ret)
5935dc19adSYong Zhi dev_err(card->dev, "failed to start PLL: %d\n", ret);
6035dc19adSYong Zhi }
6135dc19adSYong Zhi
6235dc19adSYong Zhi return ret;
6335dc19adSYong Zhi }
6435dc19adSYong Zhi
6535dc19adSYong Zhi static const struct snd_kcontrol_new controls[] = {
6635dc19adSYong Zhi SOC_DAPM_PIN_SWITCH("Headphone Jack"),
6735dc19adSYong Zhi SOC_DAPM_PIN_SWITCH("Headset Mic"),
68*7265089aSAlper Nebi Yasak SOC_DAPM_PIN_SWITCH("Line Out"),
6935dc19adSYong Zhi SOC_DAPM_PIN_SWITCH("Left Spk"),
7035dc19adSYong Zhi SOC_DAPM_PIN_SWITCH("Right Spk"),
7135dc19adSYong Zhi };
7235dc19adSYong Zhi
733f32e596SYong Zhi static const struct snd_kcontrol_new m98360a_controls[] = {
743f32e596SYong Zhi SOC_DAPM_PIN_SWITCH("Headphone Jack"),
753f32e596SYong Zhi SOC_DAPM_PIN_SWITCH("Headset Mic"),
76*7265089aSAlper Nebi Yasak SOC_DAPM_PIN_SWITCH("Line Out"),
7790c49d6aSYong Zhi SOC_DAPM_PIN_SWITCH("Spk"),
783f32e596SYong Zhi };
793f32e596SYong Zhi
8090c49d6aSYong Zhi /* For MAX98373 amp */
8135dc19adSYong Zhi static const struct snd_soc_dapm_widget widgets[] = {
8235dc19adSYong Zhi SND_SOC_DAPM_HP("Headphone Jack", NULL),
8335dc19adSYong Zhi SND_SOC_DAPM_MIC("Headset Mic", NULL),
84*7265089aSAlper Nebi Yasak SND_SOC_DAPM_LINE("Line Out", NULL),
8590c49d6aSYong Zhi
8690c49d6aSYong Zhi SND_SOC_DAPM_SPK("Left Spk", NULL),
8790c49d6aSYong Zhi SND_SOC_DAPM_SPK("Right Spk", NULL),
8890c49d6aSYong Zhi
8935dc19adSYong Zhi SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
9035dc19adSYong Zhi platform_clock_control, SND_SOC_DAPM_POST_PMD |
9135dc19adSYong Zhi SND_SOC_DAPM_PRE_PMU),
9235e648ccSKeyon Jie
9335e648ccSKeyon Jie SND_SOC_DAPM_MIC("SoC DMIC", NULL),
9435dc19adSYong Zhi };
9535dc19adSYong Zhi
9635dc19adSYong Zhi static const struct snd_soc_dapm_route audio_map[] = {
9735dc19adSYong Zhi { "Headphone Jack", NULL, "HPL" },
9835dc19adSYong Zhi { "Headphone Jack", NULL, "HPR" },
9935dc19adSYong Zhi
10035dc19adSYong Zhi { "MIC", NULL, "Headset Mic" },
10135dc19adSYong Zhi
10235dc19adSYong Zhi { "Headphone Jack", NULL, "Platform Clock" },
10335dc19adSYong Zhi { "Headset Mic", NULL, "Platform Clock" },
104*7265089aSAlper Nebi Yasak { "Line Out", NULL, "Platform Clock" },
10535dc19adSYong Zhi
1063f32e596SYong Zhi { "Left Spk", NULL, "Left BE_OUT" },
1073f32e596SYong Zhi { "Right Spk", NULL, "Right BE_OUT" },
10835e648ccSKeyon Jie
10935e648ccSKeyon Jie /* digital mics */
11035e648ccSKeyon Jie {"DMic", NULL, "SoC DMIC"},
1113f32e596SYong Zhi };
1123f32e596SYong Zhi
11390c49d6aSYong Zhi /* For MAX98360A amp */
11490c49d6aSYong Zhi static const struct snd_soc_dapm_widget max98360a_widgets[] = {
11590c49d6aSYong Zhi SND_SOC_DAPM_HP("Headphone Jack", NULL),
11690c49d6aSYong Zhi SND_SOC_DAPM_MIC("Headset Mic", NULL),
117*7265089aSAlper Nebi Yasak SND_SOC_DAPM_LINE("Line Out", NULL),
11890c49d6aSYong Zhi
11990c49d6aSYong Zhi SND_SOC_DAPM_SPK("Spk", NULL),
12090c49d6aSYong Zhi
12190c49d6aSYong Zhi SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
12290c49d6aSYong Zhi platform_clock_control, SND_SOC_DAPM_POST_PMD |
12390c49d6aSYong Zhi SND_SOC_DAPM_PRE_PMU),
12435e648ccSKeyon Jie
12535e648ccSKeyon Jie SND_SOC_DAPM_MIC("SoC DMIC", NULL),
12690c49d6aSYong Zhi };
12790c49d6aSYong Zhi
12890c49d6aSYong Zhi static const struct snd_soc_dapm_route max98360a_map[] = {
12990c49d6aSYong Zhi { "Headphone Jack", NULL, "HPL" },
13090c49d6aSYong Zhi { "Headphone Jack", NULL, "HPR" },
13190c49d6aSYong Zhi
13290c49d6aSYong Zhi { "MIC", NULL, "Headset Mic" },
13390c49d6aSYong Zhi
13490c49d6aSYong Zhi { "Headphone Jack", NULL, "Platform Clock" },
13590c49d6aSYong Zhi { "Headset Mic", NULL, "Platform Clock" },
136*7265089aSAlper Nebi Yasak { "Line Out", NULL, "Platform Clock" },
13790c49d6aSYong Zhi
13890c49d6aSYong Zhi {"Spk", NULL, "Speaker"},
13935e648ccSKeyon Jie
14035e648ccSKeyon Jie /* digital mics */
14135e648ccSKeyon Jie {"DMic", NULL, "SoC DMIC"},
14290c49d6aSYong Zhi };
14390c49d6aSYong Zhi
1442913bb1fSPierre-Louis Bossart static struct snd_soc_jack_pin jack_pins[] = {
1452913bb1fSPierre-Louis Bossart {
1462913bb1fSPierre-Louis Bossart .pin = "Headphone Jack",
1472913bb1fSPierre-Louis Bossart .mask = SND_JACK_HEADPHONE,
1482913bb1fSPierre-Louis Bossart },
1492913bb1fSPierre-Louis Bossart {
1502913bb1fSPierre-Louis Bossart .pin = "Headset Mic",
1512913bb1fSPierre-Louis Bossart .mask = SND_JACK_MICROPHONE,
1522913bb1fSPierre-Louis Bossart },
153*7265089aSAlper Nebi Yasak {
154*7265089aSAlper Nebi Yasak .pin = "Line Out",
155*7265089aSAlper Nebi Yasak .mask = SND_JACK_LINEOUT,
156*7265089aSAlper Nebi Yasak },
1572913bb1fSPierre-Louis Bossart };
1582913bb1fSPierre-Louis Bossart
15935dc19adSYong Zhi static struct snd_soc_jack headset;
16035dc19adSYong Zhi
da7219_codec_init(struct snd_soc_pcm_runtime * rtd)16135dc19adSYong Zhi static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd)
16235dc19adSYong Zhi {
1630d1571c1SKuninori Morimoto struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
1640d1571c1SKuninori Morimoto struct snd_soc_component *component = codec_dai->component;
16535dc19adSYong Zhi struct snd_soc_jack *jack;
16635dc19adSYong Zhi int ret;
16735dc19adSYong Zhi
16835dc19adSYong Zhi /* Configure sysclk for codec */
16935dc19adSYong Zhi ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 24000000,
17035dc19adSYong Zhi SND_SOC_CLOCK_IN);
17135dc19adSYong Zhi if (ret) {
17235dc19adSYong Zhi dev_err(rtd->dev, "can't set codec sysclk configuration\n");
17335dc19adSYong Zhi return ret;
17435dc19adSYong Zhi }
17535dc19adSYong Zhi
17635dc19adSYong Zhi /*
17735dc19adSYong Zhi * Headset buttons map to the google Reference headset.
17835dc19adSYong Zhi * These can be configured by userspace.
17935dc19adSYong Zhi */
1802913bb1fSPierre-Louis Bossart ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
18135dc19adSYong Zhi SND_JACK_HEADSET | SND_JACK_BTN_0 |
18235dc19adSYong Zhi SND_JACK_BTN_1 | SND_JACK_BTN_2 |
18335dc19adSYong Zhi SND_JACK_BTN_3 | SND_JACK_LINEOUT,
1842913bb1fSPierre-Louis Bossart &headset,
1852913bb1fSPierre-Louis Bossart jack_pins,
1862913bb1fSPierre-Louis Bossart ARRAY_SIZE(jack_pins));
18735dc19adSYong Zhi if (ret) {
18835dc19adSYong Zhi dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
18935dc19adSYong Zhi return ret;
19035dc19adSYong Zhi }
19135dc19adSYong Zhi
19235dc19adSYong Zhi jack = &headset;
19335dc19adSYong Zhi snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
19435dc19adSYong Zhi snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
19535dc19adSYong Zhi snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
19635dc19adSYong Zhi snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
1979a1fe79dSCezary Rojewski snd_soc_component_set_jack(component, jack, NULL);
19835dc19adSYong Zhi
19935dc19adSYong Zhi return ret;
20035dc19adSYong Zhi }
20135dc19adSYong Zhi
ssp1_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)20235dc19adSYong Zhi static int ssp1_hw_params(struct snd_pcm_substream *substream,
20335dc19adSYong Zhi struct snd_pcm_hw_params *params)
20435dc19adSYong Zhi {
2052207b93bSKuninori Morimoto struct snd_soc_pcm_runtime *runtime = asoc_substream_to_rtd(substream);
20635dc19adSYong Zhi int ret, j;
20735dc19adSYong Zhi
2080402cca4SNathan Chancellor for (j = 0; j < runtime->dai_link->num_codecs; j++) {
2090d1571c1SKuninori Morimoto struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, j);
21035dc19adSYong Zhi
21135dc19adSYong Zhi if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) {
21235dc19adSYong Zhi /* vmon_slot_no = 0 imon_slot_no = 1 for TX slots */
21335dc19adSYong Zhi ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 3, 4, 16);
21435dc19adSYong Zhi if (ret < 0) {
21535dc19adSYong Zhi dev_err(runtime->dev, "DEV0 TDM slot err:%d\n", ret);
21635dc19adSYong Zhi return ret;
21735dc19adSYong Zhi }
21835dc19adSYong Zhi }
21935dc19adSYong Zhi if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
22035dc19adSYong Zhi /* vmon_slot_no = 2 imon_slot_no = 3 for TX slots */
22135dc19adSYong Zhi ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC, 3, 4, 16);
22235dc19adSYong Zhi if (ret < 0) {
22335dc19adSYong Zhi dev_err(runtime->dev, "DEV1 TDM slot err:%d\n", ret);
22435dc19adSYong Zhi return ret;
22535dc19adSYong Zhi }
22635dc19adSYong Zhi }
22735dc19adSYong Zhi }
22835dc19adSYong Zhi
22935dc19adSYong Zhi return 0;
23035dc19adSYong Zhi }
23135dc19adSYong Zhi
23235dc19adSYong Zhi static struct snd_soc_ops ssp1_ops = {
23335dc19adSYong Zhi .hw_params = ssp1_hw_params,
23435dc19adSYong Zhi };
23535dc19adSYong Zhi
23635dc19adSYong Zhi static struct snd_soc_codec_conf max98373_codec_conf[] = {
23735dc19adSYong Zhi {
23835dc19adSYong Zhi .dlc = COMP_CODEC_CONF(MAXIM_DEV0_NAME),
23935dc19adSYong Zhi .name_prefix = "Right",
24035dc19adSYong Zhi },
24135dc19adSYong Zhi {
24235dc19adSYong Zhi .dlc = COMP_CODEC_CONF(MAXIM_DEV1_NAME),
24335dc19adSYong Zhi .name_prefix = "Left",
24435dc19adSYong Zhi },
24535dc19adSYong Zhi };
24635dc19adSYong Zhi
hdmi_init(struct snd_soc_pcm_runtime * rtd)24735dc19adSYong Zhi static int hdmi_init(struct snd_soc_pcm_runtime *rtd)
24835dc19adSYong Zhi {
24935dc19adSYong Zhi struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
2500d1571c1SKuninori Morimoto struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
25135dc19adSYong Zhi struct hdmi_pcm *pcm;
25235dc19adSYong Zhi
25335dc19adSYong Zhi pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
25435dc19adSYong Zhi if (!pcm)
25535dc19adSYong Zhi return -ENOMEM;
25635dc19adSYong Zhi
25735dc19adSYong Zhi pcm->device = dai->id;
25835dc19adSYong Zhi pcm->codec_dai = dai;
25935dc19adSYong Zhi
26035dc19adSYong Zhi list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
26135dc19adSYong Zhi
26235dc19adSYong Zhi return 0;
26335dc19adSYong Zhi }
26435dc19adSYong Zhi
card_late_probe(struct snd_soc_card * card)26535dc19adSYong Zhi static int card_late_probe(struct snd_soc_card *card)
26635dc19adSYong Zhi {
26735dc19adSYong Zhi struct card_private *ctx = snd_soc_card_get_drvdata(card);
26835dc19adSYong Zhi struct snd_soc_acpi_mach *mach = (card->dev)->platform_data;
26935dc19adSYong Zhi struct hdmi_pcm *pcm;
27035dc19adSYong Zhi
27135dc19adSYong Zhi if (mach->mach_params.common_hdmi_codec_drv) {
27235dc19adSYong Zhi pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm,
27335dc19adSYong Zhi head);
27435dc19adSYong Zhi return hda_dsp_hdmi_build_controls(card,
27535dc19adSYong Zhi pcm->codec_dai->component);
27635dc19adSYong Zhi }
27735dc19adSYong Zhi
27835dc19adSYong Zhi return -EINVAL;
27935dc19adSYong Zhi }
28035dc19adSYong Zhi
28135dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp0_pin,
28235dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
28335dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp0_codec,
28435dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", DIALOG_CODEC_DAI)));
28535dc19adSYong Zhi
28635dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp1_pin,
28735dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
28835dc19adSYong Zhi SND_SOC_DAILINK_DEF(ssp1_amps,
28935dc19adSYong Zhi DAILINK_COMP_ARRAY(
29035dc19adSYong Zhi /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, MAX98373_CODEC_DAI),
29135dc19adSYong Zhi /* Right */ COMP_CODEC(MAXIM_DEV1_NAME, MAX98373_CODEC_DAI)));
29290c49d6aSYong Zhi
29390c49d6aSYong Zhi SND_SOC_DAILINK_DEF(ssp1_m98360a,
29490c49d6aSYong Zhi DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
29535dc19adSYong Zhi
29635dc19adSYong Zhi SND_SOC_DAILINK_DEF(dmic_pin,
29735dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin")));
29835dc19adSYong Zhi SND_SOC_DAILINK_DEF(dmic_codec,
29935dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
30035dc19adSYong Zhi
301a8bb72f1SYong Zhi SND_SOC_DAILINK_DEF(dmic16k_pin,
302a8bb72f1SYong Zhi DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
303a8bb72f1SYong Zhi
30435dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp1_pin,
30535dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
30635dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp1_codec,
30735dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
30835dc19adSYong Zhi
30935dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp2_pin,
31035dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
31135dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp2_codec,
31235dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
31335dc19adSYong Zhi
31435dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp3_pin,
31535dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
31635dc19adSYong Zhi SND_SOC_DAILINK_DEF(idisp3_codec,
31735dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
31835dc19adSYong Zhi
31935dc19adSYong Zhi SND_SOC_DAILINK_DEF(platform, /* subject to be overridden during probe */
32035dc19adSYong Zhi DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
32135dc19adSYong Zhi
32235dc19adSYong Zhi static struct snd_soc_dai_link dais[] = {
32335dc19adSYong Zhi /* Back End DAI links */
32435dc19adSYong Zhi {
32535dc19adSYong Zhi .name = "SSP1-Codec",
32635dc19adSYong Zhi .id = 0,
32735dc19adSYong Zhi .ignore_pmdown_time = 1,
32835dc19adSYong Zhi .no_pcm = 1,
32935dc19adSYong Zhi .dpcm_playback = 1,
33035dc19adSYong Zhi .dpcm_capture = 1, /* IV feedback */
33135dc19adSYong Zhi .ops = &ssp1_ops,
33235dc19adSYong Zhi SND_SOC_DAILINK_REG(ssp1_pin, ssp1_amps, platform),
33335dc19adSYong Zhi },
33435dc19adSYong Zhi {
33535dc19adSYong Zhi .name = "SSP0-Codec",
33635dc19adSYong Zhi .id = 1,
33735dc19adSYong Zhi .no_pcm = 1,
33835dc19adSYong Zhi .init = da7219_codec_init,
33935dc19adSYong Zhi .ignore_pmdown_time = 1,
34035dc19adSYong Zhi .dpcm_playback = 1,
34135dc19adSYong Zhi .dpcm_capture = 1,
34235dc19adSYong Zhi SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
34335dc19adSYong Zhi },
34435dc19adSYong Zhi {
34535dc19adSYong Zhi .name = "dmic01",
34635dc19adSYong Zhi .id = 2,
34735dc19adSYong Zhi .ignore_suspend = 1,
34835dc19adSYong Zhi .dpcm_capture = 1,
34935dc19adSYong Zhi .no_pcm = 1,
35035dc19adSYong Zhi SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform),
35135dc19adSYong Zhi },
35235dc19adSYong Zhi {
35335dc19adSYong Zhi .name = "iDisp1",
35435dc19adSYong Zhi .id = 3,
35535dc19adSYong Zhi .init = hdmi_init,
35635dc19adSYong Zhi .dpcm_playback = 1,
35735dc19adSYong Zhi .no_pcm = 1,
35835dc19adSYong Zhi SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
35935dc19adSYong Zhi },
36035dc19adSYong Zhi {
36135dc19adSYong Zhi .name = "iDisp2",
36235dc19adSYong Zhi .id = 4,
36335dc19adSYong Zhi .init = hdmi_init,
36435dc19adSYong Zhi .dpcm_playback = 1,
36535dc19adSYong Zhi .no_pcm = 1,
36635dc19adSYong Zhi SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
36735dc19adSYong Zhi },
36835dc19adSYong Zhi {
36935dc19adSYong Zhi .name = "iDisp3",
37035dc19adSYong Zhi .id = 5,
37135dc19adSYong Zhi .init = hdmi_init,
37235dc19adSYong Zhi .dpcm_playback = 1,
37335dc19adSYong Zhi .no_pcm = 1,
37435dc19adSYong Zhi SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform),
37535dc19adSYong Zhi },
376a8bb72f1SYong Zhi {
377a8bb72f1SYong Zhi .name = "dmic16k",
378a8bb72f1SYong Zhi .id = 6,
379a8bb72f1SYong Zhi .ignore_suspend = 1,
380a8bb72f1SYong Zhi .dpcm_capture = 1,
381a8bb72f1SYong Zhi .no_pcm = 1,
382a8bb72f1SYong Zhi SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform),
383a8bb72f1SYong Zhi }
38435dc19adSYong Zhi };
38535dc19adSYong Zhi
38635dc19adSYong Zhi static struct snd_soc_card card_da7219_m98373 = {
38735dc19adSYong Zhi .name = "da7219max",
38835dc19adSYong Zhi .owner = THIS_MODULE,
38935dc19adSYong Zhi .dai_link = dais,
39035dc19adSYong Zhi .num_links = ARRAY_SIZE(dais),
39135dc19adSYong Zhi .controls = controls,
39235dc19adSYong Zhi .num_controls = ARRAY_SIZE(controls),
39335dc19adSYong Zhi .dapm_widgets = widgets,
39435dc19adSYong Zhi .num_dapm_widgets = ARRAY_SIZE(widgets),
39535dc19adSYong Zhi .dapm_routes = audio_map,
39635dc19adSYong Zhi .num_dapm_routes = ARRAY_SIZE(audio_map),
39735dc19adSYong Zhi .codec_conf = max98373_codec_conf,
39835dc19adSYong Zhi .num_configs = ARRAY_SIZE(max98373_codec_conf),
39935dc19adSYong Zhi .fully_routed = true,
40035dc19adSYong Zhi .late_probe = card_late_probe,
40135dc19adSYong Zhi };
40235dc19adSYong Zhi
4033f32e596SYong Zhi static struct snd_soc_card card_da7219_m98360a = {
4043f32e596SYong Zhi .name = "da7219max98360a",
4053f32e596SYong Zhi .owner = THIS_MODULE,
4063f32e596SYong Zhi .dai_link = dais,
4073f32e596SYong Zhi .num_links = ARRAY_SIZE(dais),
4083f32e596SYong Zhi .controls = m98360a_controls,
4093f32e596SYong Zhi .num_controls = ARRAY_SIZE(m98360a_controls),
41090c49d6aSYong Zhi .dapm_widgets = max98360a_widgets,
41190c49d6aSYong Zhi .num_dapm_widgets = ARRAY_SIZE(max98360a_widgets),
41290c49d6aSYong Zhi .dapm_routes = max98360a_map,
41390c49d6aSYong Zhi .num_dapm_routes = ARRAY_SIZE(max98360a_map),
4143f32e596SYong Zhi .fully_routed = true,
4153f32e596SYong Zhi .late_probe = card_late_probe,
4163f32e596SYong Zhi };
4173f32e596SYong Zhi
audio_probe(struct platform_device * pdev)41835dc19adSYong Zhi static int audio_probe(struct platform_device *pdev)
41935dc19adSYong Zhi {
42035dc19adSYong Zhi static struct snd_soc_card *card;
42135dc19adSYong Zhi struct snd_soc_acpi_mach *mach;
42235dc19adSYong Zhi struct card_private *ctx;
42335dc19adSYong Zhi int ret;
42435dc19adSYong Zhi
4252e6529a5SPierre-Louis Bossart ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
42635dc19adSYong Zhi if (!ctx)
42735dc19adSYong Zhi return -ENOMEM;
42835dc19adSYong Zhi
4293f32e596SYong Zhi /* By default dais[0] is configured for max98373 */
4300f32d9ebSBrent Lu if (!strcmp(pdev->name, "sof_da7219_mx98360a")) {
4313f32e596SYong Zhi dais[0] = (struct snd_soc_dai_link) {
4323f32e596SYong Zhi .name = "SSP1-Codec",
4333f32e596SYong Zhi .id = 0,
4343f32e596SYong Zhi .no_pcm = 1,
4353f32e596SYong Zhi .dpcm_playback = 1,
4363f32e596SYong Zhi .ignore_pmdown_time = 1,
43790c49d6aSYong Zhi SND_SOC_DAILINK_REG(ssp1_pin, ssp1_m98360a, platform) };
4383f32e596SYong Zhi }
4393f32e596SYong Zhi
44035dc19adSYong Zhi INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
44135dc19adSYong Zhi card = (struct snd_soc_card *)pdev->id_entry->driver_data;
44235dc19adSYong Zhi card->dev = &pdev->dev;
44335dc19adSYong Zhi
44442432196SGuennadi Liakhovetski mach = pdev->dev.platform_data;
44535dc19adSYong Zhi ret = snd_soc_fixup_dai_links_platform_name(card,
44635dc19adSYong Zhi mach->mach_params.platform);
44735dc19adSYong Zhi if (ret)
44835dc19adSYong Zhi return ret;
44935dc19adSYong Zhi
45035dc19adSYong Zhi snd_soc_card_set_drvdata(card, ctx);
45135dc19adSYong Zhi
45235dc19adSYong Zhi return devm_snd_soc_register_card(&pdev->dev, card);
45335dc19adSYong Zhi }
45435dc19adSYong Zhi
45535dc19adSYong Zhi static const struct platform_device_id board_ids[] = {
45635dc19adSYong Zhi {
4571cc04d19SPierre-Louis Bossart .name = "sof_da7219_mx98373",
45835dc19adSYong Zhi .driver_data = (kernel_ulong_t)&card_da7219_m98373,
45935dc19adSYong Zhi },
4603f32e596SYong Zhi {
4611cc04d19SPierre-Louis Bossart .name = "sof_da7219_mx98360a",
4623f32e596SYong Zhi .driver_data = (kernel_ulong_t)&card_da7219_m98360a,
4633f32e596SYong Zhi },
46435dc19adSYong Zhi { }
46535dc19adSYong Zhi };
466a75e5cdfSZou Wei MODULE_DEVICE_TABLE(platform, board_ids);
46735dc19adSYong Zhi
46835dc19adSYong Zhi static struct platform_driver audio = {
46935dc19adSYong Zhi .probe = audio_probe,
47035dc19adSYong Zhi .driver = {
4713f32e596SYong Zhi .name = "sof_da7219_max98_360a_373",
47235dc19adSYong Zhi .pm = &snd_soc_pm_ops,
47335dc19adSYong Zhi },
47435dc19adSYong Zhi .id_table = board_ids,
47535dc19adSYong Zhi };
47635dc19adSYong Zhi module_platform_driver(audio)
47735dc19adSYong Zhi
47835dc19adSYong Zhi /* Module information */
47935dc19adSYong Zhi MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver");
48035dc19adSYong Zhi MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
48135dc19adSYong Zhi MODULE_LICENSE("GPL v2");
482f6081af6SPierre-Louis Bossart MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
483