11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2a86d5057SHarsha Priya /* 3a86d5057SHarsha Priya * Intel Skylake I2S Machine Driver for NAU88L25+SSM4567 4a86d5057SHarsha Priya * 5a86d5057SHarsha Priya * Copyright (C) 2015, Intel Corporation. All rights reserved. 6a86d5057SHarsha Priya * 7a86d5057SHarsha Priya * Modified from: 8a86d5057SHarsha Priya * Intel Skylake I2S Machine Driver for NAU88L25 and SSM4567 9a86d5057SHarsha Priya * 10a86d5057SHarsha Priya * Copyright (C) 2015, Intel Corporation. All rights reserved. 11a86d5057SHarsha Priya */ 12a86d5057SHarsha Priya 13a86d5057SHarsha Priya #include <linux/module.h> 14a86d5057SHarsha Priya #include <linux/platform_device.h> 15a86d5057SHarsha Priya #include <sound/core.h> 16a86d5057SHarsha Priya #include <sound/pcm.h> 17a86d5057SHarsha Priya #include <sound/soc.h> 18b92826faSPierre-Louis Bossart #include <sound/soc-acpi.h> 19a86d5057SHarsha Priya #include <sound/jack.h> 20a86d5057SHarsha Priya #include <sound/pcm_params.h> 21a86d5057SHarsha Priya #include "../../codecs/nau8825.h" 22bc5f6ac9SJeeja KP #include "../../codecs/hdac_hdmi.h" 23a86d5057SHarsha Priya 24a86d5057SHarsha Priya #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" 25a86d5057SHarsha Priya #define SKL_SSM_CODEC_DAI "ssm4567-hifi" 26cfa12367SYong Zhi #define DMIC_CH(p) p->list[p->count-1] 27a86d5057SHarsha Priya 28a86d5057SHarsha Priya static struct snd_soc_jack skylake_headset; 29a86d5057SHarsha Priya static struct snd_soc_card skylake_audio_card; 30cfa12367SYong Zhi static const struct snd_pcm_hw_constraint_list *dmic_constraints; 319e4278cdSJeeja KP static struct snd_soc_jack skylake_hdmi[3]; 32a86d5057SHarsha Priya 3346ed1a27SSubhransu S. Prusty struct skl_hdmi_pcm { 3446ed1a27SSubhransu S. Prusty struct list_head head; 3546ed1a27SSubhransu S. Prusty struct snd_soc_dai *codec_dai; 3646ed1a27SSubhransu S. Prusty int device; 3746ed1a27SSubhransu S. Prusty }; 3846ed1a27SSubhransu S. Prusty 3946ed1a27SSubhransu S. Prusty struct skl_nau88125_private { 4046ed1a27SSubhransu S. Prusty struct list_head hdmi_pcm_list; 4146ed1a27SSubhransu S. Prusty }; 42bc5f6ac9SJeeja KP enum { 43bc5f6ac9SJeeja KP SKL_DPCM_AUDIO_PB = 0, 44bc5f6ac9SJeeja KP SKL_DPCM_AUDIO_CP, 45bc5f6ac9SJeeja KP SKL_DPCM_AUDIO_REF_CP, 46bc5f6ac9SJeeja KP SKL_DPCM_AUDIO_DMIC_CP, 47bc5f6ac9SJeeja KP SKL_DPCM_AUDIO_HDMI1_PB, 48bc5f6ac9SJeeja KP SKL_DPCM_AUDIO_HDMI2_PB, 49bc5f6ac9SJeeja KP SKL_DPCM_AUDIO_HDMI3_PB, 50bc5f6ac9SJeeja KP }; 51bc5f6ac9SJeeja KP 52a86d5057SHarsha Priya static const struct snd_kcontrol_new skylake_controls[] = { 53a86d5057SHarsha Priya SOC_DAPM_PIN_SWITCH("Headphone Jack"), 54a86d5057SHarsha Priya SOC_DAPM_PIN_SWITCH("Headset Mic"), 55a86d5057SHarsha Priya SOC_DAPM_PIN_SWITCH("Left Speaker"), 56a86d5057SHarsha Priya SOC_DAPM_PIN_SWITCH("Right Speaker"), 57a86d5057SHarsha Priya }; 58a86d5057SHarsha Priya 59a86d5057SHarsha Priya static int platform_clock_control(struct snd_soc_dapm_widget *w, 60a86d5057SHarsha Priya struct snd_kcontrol *k, int event) 61a86d5057SHarsha Priya { 62a86d5057SHarsha Priya struct snd_soc_dapm_context *dapm = w->dapm; 63a86d5057SHarsha Priya struct snd_soc_card *card = dapm->card; 64a86d5057SHarsha Priya struct snd_soc_dai *codec_dai; 65a86d5057SHarsha Priya int ret; 66a86d5057SHarsha Priya 67dfb6ec7aSPierre-Louis Bossart codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI); 68a86d5057SHarsha Priya if (!codec_dai) { 69a86d5057SHarsha Priya dev_err(card->dev, "Codec dai not found\n"); 70a86d5057SHarsha Priya return -EIO; 71a86d5057SHarsha Priya } 72a86d5057SHarsha Priya 73a86d5057SHarsha Priya if (SND_SOC_DAPM_EVENT_ON(event)) { 74a86d5057SHarsha Priya ret = snd_soc_dai_set_sysclk(codec_dai, 75a86d5057SHarsha Priya NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); 76a86d5057SHarsha Priya if (ret < 0) { 77a86d5057SHarsha Priya dev_err(card->dev, "set sysclk err = %d\n", ret); 78a86d5057SHarsha Priya return -EIO; 79a86d5057SHarsha Priya } 80a86d5057SHarsha Priya } else { 81a86d5057SHarsha Priya ret = snd_soc_dai_set_sysclk(codec_dai, 82a86d5057SHarsha Priya NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN); 83a86d5057SHarsha Priya if (ret < 0) { 84a86d5057SHarsha Priya dev_err(card->dev, "set sysclk err = %d\n", ret); 85a86d5057SHarsha Priya return -EIO; 86a86d5057SHarsha Priya } 87a86d5057SHarsha Priya } 88a86d5057SHarsha Priya return ret; 89a86d5057SHarsha Priya } 90a86d5057SHarsha Priya 91a86d5057SHarsha Priya static const struct snd_soc_dapm_widget skylake_widgets[] = { 92a86d5057SHarsha Priya SND_SOC_DAPM_HP("Headphone Jack", NULL), 93a86d5057SHarsha Priya SND_SOC_DAPM_MIC("Headset Mic", NULL), 94a86d5057SHarsha Priya SND_SOC_DAPM_SPK("Left Speaker", NULL), 95a86d5057SHarsha Priya SND_SOC_DAPM_SPK("Right Speaker", NULL), 96a86d5057SHarsha Priya SND_SOC_DAPM_MIC("SoC DMIC", NULL), 978d13640fSJeeja KP SND_SOC_DAPM_SPK("DP1", NULL), 988d13640fSJeeja KP SND_SOC_DAPM_SPK("DP2", NULL), 99a86d5057SHarsha Priya SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, 100a86d5057SHarsha Priya platform_clock_control, SND_SOC_DAPM_PRE_PMU | 101a86d5057SHarsha Priya SND_SOC_DAPM_POST_PMD), 102a86d5057SHarsha Priya }; 103a86d5057SHarsha Priya 104a86d5057SHarsha Priya static const struct snd_soc_dapm_route skylake_map[] = { 105a86d5057SHarsha Priya /* HP jack connectors - unknown if we have jack detection */ 106a86d5057SHarsha Priya {"Headphone Jack", NULL, "HPOL"}, 107a86d5057SHarsha Priya {"Headphone Jack", NULL, "HPOR"}, 108a86d5057SHarsha Priya 109a86d5057SHarsha Priya /* speaker */ 110a86d5057SHarsha Priya {"Left Speaker", NULL, "Left OUT"}, 111a86d5057SHarsha Priya {"Right Speaker", NULL, "Right OUT"}, 112a86d5057SHarsha Priya 113a86d5057SHarsha Priya /* other jacks */ 114a86d5057SHarsha Priya {"MIC", NULL, "Headset Mic"}, 1154c6ebc3eSFang, Yang A {"DMic", NULL, "SoC DMIC"}, 116a86d5057SHarsha Priya 117a86d5057SHarsha Priya /* CODEC BE connections */ 118a86d5057SHarsha Priya { "Left Playback", NULL, "ssp0 Tx"}, 119a86d5057SHarsha Priya { "Right Playback", NULL, "ssp0 Tx"}, 120a86d5057SHarsha Priya { "ssp0 Tx", NULL, "codec0_out"}, 121a86d5057SHarsha Priya 1225093f928SSathya Prakash M R /* IV feedback path */ 1235093f928SSathya Prakash M R { "codec0_lp_in", NULL, "ssp0 Rx"}, 1245188b95aSJeeja KP { "ssp0 Rx", NULL, "Left Capture Sense" }, 1255188b95aSJeeja KP { "ssp0 Rx", NULL, "Right Capture Sense" }, 1265093f928SSathya Prakash M R 1274c6ebc3eSFang, Yang A { "Playback", NULL, "ssp1 Tx"}, 128a86d5057SHarsha Priya { "ssp1 Tx", NULL, "codec1_out"}, 129a86d5057SHarsha Priya 130a86d5057SHarsha Priya { "codec0_in", NULL, "ssp1 Rx" }, 1314c6ebc3eSFang, Yang A { "ssp1 Rx", NULL, "Capture" }, 132a86d5057SHarsha Priya 133a86d5057SHarsha Priya /* DMIC */ 134a86d5057SHarsha Priya { "dmic01_hifi", NULL, "DMIC01 Rx" }, 1354c6ebc3eSFang, Yang A { "DMIC01 Rx", NULL, "DMIC AIF" }, 136bc5f6ac9SJeeja KP 137bc5f6ac9SJeeja KP { "hifi3", NULL, "iDisp3 Tx"}, 138bc5f6ac9SJeeja KP { "iDisp3 Tx", NULL, "iDisp3_out"}, 139bc5f6ac9SJeeja KP { "hifi2", NULL, "iDisp2 Tx"}, 140bc5f6ac9SJeeja KP { "iDisp2 Tx", NULL, "iDisp2_out"}, 141bc5f6ac9SJeeja KP { "hifi1", NULL, "iDisp1 Tx"}, 142bc5f6ac9SJeeja KP { "iDisp1 Tx", NULL, "iDisp1_out"}, 143bc5f6ac9SJeeja KP 144a86d5057SHarsha Priya { "Headphone Jack", NULL, "Platform Clock" }, 145a86d5057SHarsha Priya { "Headset Mic", NULL, "Platform Clock" }, 146a86d5057SHarsha Priya }; 147a86d5057SHarsha Priya 148a86d5057SHarsha Priya static struct snd_soc_codec_conf ssm4567_codec_conf[] = { 149a86d5057SHarsha Priya { 15003b70ef5SKuninori Morimoto .dlc = COMP_CODEC_CONF("i2c-INT343B:00"), 151a86d5057SHarsha Priya .name_prefix = "Left", 152a86d5057SHarsha Priya }, 153a86d5057SHarsha Priya { 15403b70ef5SKuninori Morimoto .dlc = COMP_CODEC_CONF("i2c-INT343B:01"), 155a86d5057SHarsha Priya .name_prefix = "Right", 156a86d5057SHarsha Priya }, 157a86d5057SHarsha Priya }; 158a86d5057SHarsha Priya 159a86d5057SHarsha Priya static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd) 160a86d5057SHarsha Priya { 161a86d5057SHarsha Priya int ret; 162a86d5057SHarsha Priya 163a86d5057SHarsha Priya /* Slot 1 for left */ 1640d1571c1SKuninori Morimoto ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0x01, 0x01, 2, 48); 165a86d5057SHarsha Priya if (ret < 0) 166a86d5057SHarsha Priya return ret; 167a86d5057SHarsha Priya 168a86d5057SHarsha Priya /* Slot 2 for right */ 1690d1571c1SKuninori Morimoto ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 1), 0x02, 0x02, 2, 48); 170a86d5057SHarsha Priya if (ret < 0) 171a86d5057SHarsha Priya return ret; 172a86d5057SHarsha Priya 173a86d5057SHarsha Priya return ret; 174a86d5057SHarsha Priya } 175a86d5057SHarsha Priya 176a86d5057SHarsha Priya static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) 177a86d5057SHarsha Priya { 178a86d5057SHarsha Priya int ret; 1790d1571c1SKuninori Morimoto struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 180a86d5057SHarsha Priya 181a86d5057SHarsha Priya /* 182a86d5057SHarsha Priya * 4 buttons here map to the google Reference headset 183a86d5057SHarsha Priya * The use of these buttons can be decided by the user space. 184a86d5057SHarsha Priya */ 185a86d5057SHarsha Priya ret = snd_soc_card_jack_new(&skylake_audio_card, "Headset Jack", 186a86d5057SHarsha Priya SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | 187a86d5057SHarsha Priya SND_JACK_BTN_2 | SND_JACK_BTN_3, &skylake_headset, 188a86d5057SHarsha Priya NULL, 0); 189a86d5057SHarsha Priya if (ret) { 190a86d5057SHarsha Priya dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret); 191a86d5057SHarsha Priya return ret; 192a86d5057SHarsha Priya } 193a86d5057SHarsha Priya 19445101122SKuninori Morimoto nau8825_enable_jack_detect(component, &skylake_headset); 195a86d5057SHarsha Priya 196941eee74SYong Zhi snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); 197941eee74SYong Zhi 198a86d5057SHarsha Priya return ret; 199a86d5057SHarsha Priya } 200a86d5057SHarsha Priya 201bc5f6ac9SJeeja KP static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) 202bc5f6ac9SJeeja KP { 20346ed1a27SSubhransu S. Prusty struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); 2040d1571c1SKuninori Morimoto struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); 20546ed1a27SSubhransu S. Prusty struct skl_hdmi_pcm *pcm; 206bc5f6ac9SJeeja KP 20746ed1a27SSubhransu S. Prusty pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 20846ed1a27SSubhransu S. Prusty if (!pcm) 20946ed1a27SSubhransu S. Prusty return -ENOMEM; 21046ed1a27SSubhransu S. Prusty 21146ed1a27SSubhransu S. Prusty pcm->device = SKL_DPCM_AUDIO_HDMI1_PB; 21246ed1a27SSubhransu S. Prusty pcm->codec_dai = dai; 21346ed1a27SSubhransu S. Prusty 21446ed1a27SSubhransu S. Prusty list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 21546ed1a27SSubhransu S. Prusty 21646ed1a27SSubhransu S. Prusty return 0; 217bc5f6ac9SJeeja KP } 218bc5f6ac9SJeeja KP 219bc5f6ac9SJeeja KP static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) 220bc5f6ac9SJeeja KP { 22146ed1a27SSubhransu S. Prusty struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); 2220d1571c1SKuninori Morimoto struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); 22346ed1a27SSubhransu S. Prusty struct skl_hdmi_pcm *pcm; 224bc5f6ac9SJeeja KP 22546ed1a27SSubhransu S. Prusty pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 22646ed1a27SSubhransu S. Prusty if (!pcm) 22746ed1a27SSubhransu S. Prusty return -ENOMEM; 22846ed1a27SSubhransu S. Prusty 22946ed1a27SSubhransu S. Prusty pcm->device = SKL_DPCM_AUDIO_HDMI2_PB; 23046ed1a27SSubhransu S. Prusty pcm->codec_dai = dai; 23146ed1a27SSubhransu S. Prusty 23246ed1a27SSubhransu S. Prusty list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 23346ed1a27SSubhransu S. Prusty 23446ed1a27SSubhransu S. Prusty return 0; 235bc5f6ac9SJeeja KP } 236bc5f6ac9SJeeja KP 237bc5f6ac9SJeeja KP 238bc5f6ac9SJeeja KP static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) 239bc5f6ac9SJeeja KP { 24046ed1a27SSubhransu S. Prusty struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); 2410d1571c1SKuninori Morimoto struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); 24246ed1a27SSubhransu S. Prusty struct skl_hdmi_pcm *pcm; 243bc5f6ac9SJeeja KP 24446ed1a27SSubhransu S. Prusty pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 24546ed1a27SSubhransu S. Prusty if (!pcm) 24646ed1a27SSubhransu S. Prusty return -ENOMEM; 24746ed1a27SSubhransu S. Prusty 24846ed1a27SSubhransu S. Prusty pcm->device = SKL_DPCM_AUDIO_HDMI3_PB; 24946ed1a27SSubhransu S. Prusty pcm->codec_dai = dai; 25046ed1a27SSubhransu S. Prusty 25146ed1a27SSubhransu S. Prusty list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 25246ed1a27SSubhransu S. Prusty 25346ed1a27SSubhransu S. Prusty return 0; 254bc5f6ac9SJeeja KP } 255bc5f6ac9SJeeja KP 2562616e27eSYong Zhi static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) 2572616e27eSYong Zhi { 2582616e27eSYong Zhi struct snd_soc_dapm_context *dapm; 2590d1571c1SKuninori Morimoto struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; 2602616e27eSYong Zhi 2612616e27eSYong Zhi dapm = snd_soc_component_get_dapm(component); 2622616e27eSYong Zhi snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); 2632616e27eSYong Zhi 2642616e27eSYong Zhi return 0; 2652616e27eSYong Zhi } 2662616e27eSYong Zhi 267617647aeSTakashi Iwai static const unsigned int rates[] = { 2682616e27eSYong Zhi 48000, 2692616e27eSYong Zhi }; 2702616e27eSYong Zhi 271617647aeSTakashi Iwai static const struct snd_pcm_hw_constraint_list constraints_rates = { 2722616e27eSYong Zhi .count = ARRAY_SIZE(rates), 2732616e27eSYong Zhi .list = rates, 2742616e27eSYong Zhi .mask = 0, 2752616e27eSYong Zhi }; 2762616e27eSYong Zhi 277617647aeSTakashi Iwai static const unsigned int channels[] = { 2782616e27eSYong Zhi 2, 2792616e27eSYong Zhi }; 2802616e27eSYong Zhi 281617647aeSTakashi Iwai static const struct snd_pcm_hw_constraint_list constraints_channels = { 2822616e27eSYong Zhi .count = ARRAY_SIZE(channels), 2832616e27eSYong Zhi .list = channels, 2842616e27eSYong Zhi .mask = 0, 2852616e27eSYong Zhi }; 2862616e27eSYong Zhi 2872616e27eSYong Zhi static int skl_fe_startup(struct snd_pcm_substream *substream) 2882616e27eSYong Zhi { 2892616e27eSYong Zhi struct snd_pcm_runtime *runtime = substream->runtime; 2902616e27eSYong Zhi 2912616e27eSYong Zhi /* 2922616e27eSYong Zhi * on this platform for PCM device we support, 2932616e27eSYong Zhi * 48Khz 2942616e27eSYong Zhi * stereo 2952616e27eSYong Zhi * 16 bit audio 2962616e27eSYong Zhi */ 2972616e27eSYong Zhi 2982616e27eSYong Zhi runtime->hw.channels_max = 2; 2992616e27eSYong Zhi snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 3002616e27eSYong Zhi &constraints_channels); 3012616e27eSYong Zhi 3022616e27eSYong Zhi runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 3032616e27eSYong Zhi snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 3042616e27eSYong Zhi 3052616e27eSYong Zhi snd_pcm_hw_constraint_list(runtime, 0, 3062616e27eSYong Zhi SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 3072616e27eSYong Zhi 3082616e27eSYong Zhi return 0; 3092616e27eSYong Zhi } 3102616e27eSYong Zhi 3112616e27eSYong Zhi static const struct snd_soc_ops skylake_nau8825_fe_ops = { 3122616e27eSYong Zhi .startup = skl_fe_startup, 3132616e27eSYong Zhi }; 3142616e27eSYong Zhi 315a86d5057SHarsha Priya static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, 316a86d5057SHarsha Priya struct snd_pcm_hw_params *params) 317a86d5057SHarsha Priya { 318a86d5057SHarsha Priya struct snd_interval *rate = hw_param_interval(params, 319a86d5057SHarsha Priya SNDRV_PCM_HW_PARAM_RATE); 320ddce36afSPierre-Louis Bossart struct snd_interval *chan = hw_param_interval(params, 321a86d5057SHarsha Priya SNDRV_PCM_HW_PARAM_CHANNELS); 322a86d5057SHarsha Priya struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 323a86d5057SHarsha Priya 324a86d5057SHarsha Priya /* The ADSP will covert the FE rate to 48k, stereo */ 325a86d5057SHarsha Priya rate->min = rate->max = 48000; 326ddce36afSPierre-Louis Bossart chan->min = chan->max = 2; 327a86d5057SHarsha Priya 328a86d5057SHarsha Priya /* set SSP0 to 24 bit */ 329a86d5057SHarsha Priya snd_mask_none(fmt); 330b5453e8cSTakashi Iwai snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); 331a86d5057SHarsha Priya return 0; 332a86d5057SHarsha Priya } 333a86d5057SHarsha Priya 3342616e27eSYong Zhi static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, 3352616e27eSYong Zhi struct snd_pcm_hw_params *params) 3362616e27eSYong Zhi { 337ddce36afSPierre-Louis Bossart struct snd_interval *chan = hw_param_interval(params, 3382616e27eSYong Zhi SNDRV_PCM_HW_PARAM_CHANNELS); 339cfa12367SYong Zhi if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2) 340ddce36afSPierre-Louis Bossart chan->min = chan->max = 2; 3412616e27eSYong Zhi else 342ddce36afSPierre-Louis Bossart chan->min = chan->max = 4; 3432616e27eSYong Zhi 3442616e27eSYong Zhi return 0; 3452616e27eSYong Zhi } 3462616e27eSYong Zhi 347a86d5057SHarsha Priya static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, 348a86d5057SHarsha Priya struct snd_pcm_hw_params *params) 349a86d5057SHarsha Priya { 3502207b93bSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3510d1571c1SKuninori Morimoto struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 352a86d5057SHarsha Priya int ret; 353a86d5057SHarsha Priya 354a86d5057SHarsha Priya ret = snd_soc_dai_set_sysclk(codec_dai, 355a86d5057SHarsha Priya NAU8825_CLK_MCLK, 24000000, SND_SOC_CLOCK_IN); 356a86d5057SHarsha Priya 357a86d5057SHarsha Priya if (ret < 0) 358a86d5057SHarsha Priya dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); 359a86d5057SHarsha Priya 360a86d5057SHarsha Priya return ret; 361a86d5057SHarsha Priya } 362a86d5057SHarsha Priya 3639b6fdef6SJulia Lawall static const struct snd_soc_ops skylake_nau8825_ops = { 364a86d5057SHarsha Priya .hw_params = skylake_nau8825_hw_params, 365a86d5057SHarsha Priya }; 366a86d5057SHarsha Priya 367617647aeSTakashi Iwai static const unsigned int channels_dmic[] = { 3682616e27eSYong Zhi 2, 4, 3692616e27eSYong Zhi }; 3702616e27eSYong Zhi 371617647aeSTakashi Iwai static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = { 3722616e27eSYong Zhi .count = ARRAY_SIZE(channels_dmic), 3732616e27eSYong Zhi .list = channels_dmic, 3742616e27eSYong Zhi .mask = 0, 3752616e27eSYong Zhi }; 3762616e27eSYong Zhi 377cfa12367SYong Zhi static const unsigned int dmic_2ch[] = { 378cfa12367SYong Zhi 2, 379cfa12367SYong Zhi }; 380cfa12367SYong Zhi 381cfa12367SYong Zhi static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = { 382cfa12367SYong Zhi .count = ARRAY_SIZE(dmic_2ch), 383cfa12367SYong Zhi .list = dmic_2ch, 384cfa12367SYong Zhi .mask = 0, 385cfa12367SYong Zhi }; 386cfa12367SYong Zhi 3872616e27eSYong Zhi static int skylake_dmic_startup(struct snd_pcm_substream *substream) 3882616e27eSYong Zhi { 3892616e27eSYong Zhi struct snd_pcm_runtime *runtime = substream->runtime; 3902616e27eSYong Zhi 391cfa12367SYong Zhi runtime->hw.channels_max = DMIC_CH(dmic_constraints); 3922616e27eSYong Zhi snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 393cfa12367SYong Zhi dmic_constraints); 3942616e27eSYong Zhi 3952616e27eSYong Zhi return snd_pcm_hw_constraint_list(substream->runtime, 0, 3962616e27eSYong Zhi SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 3972616e27eSYong Zhi } 3982616e27eSYong Zhi 3999b6fdef6SJulia Lawall static const struct snd_soc_ops skylake_dmic_ops = { 4002616e27eSYong Zhi .startup = skylake_dmic_startup, 4012616e27eSYong Zhi }; 4022616e27eSYong Zhi 403617647aeSTakashi Iwai static const unsigned int rates_16000[] = { 4042616e27eSYong Zhi 16000, 4052616e27eSYong Zhi }; 4062616e27eSYong Zhi 407617647aeSTakashi Iwai static const struct snd_pcm_hw_constraint_list constraints_16000 = { 4082616e27eSYong Zhi .count = ARRAY_SIZE(rates_16000), 4092616e27eSYong Zhi .list = rates_16000, 4102616e27eSYong Zhi }; 4112616e27eSYong Zhi 4120c7941a6SYong Zhi static const unsigned int ch_mono[] = { 4130c7941a6SYong Zhi 1, 4140c7941a6SYong Zhi }; 4150c7941a6SYong Zhi 4160c7941a6SYong Zhi static const struct snd_pcm_hw_constraint_list constraints_refcap = { 4170c7941a6SYong Zhi .count = ARRAY_SIZE(ch_mono), 4180c7941a6SYong Zhi .list = ch_mono, 4190c7941a6SYong Zhi }; 4200c7941a6SYong Zhi 4212616e27eSYong Zhi static int skylake_refcap_startup(struct snd_pcm_substream *substream) 4222616e27eSYong Zhi { 4230c7941a6SYong Zhi substream->runtime->hw.channels_max = 1; 4240c7941a6SYong Zhi snd_pcm_hw_constraint_list(substream->runtime, 0, 4250c7941a6SYong Zhi SNDRV_PCM_HW_PARAM_CHANNELS, 4260c7941a6SYong Zhi &constraints_refcap); 4270c7941a6SYong Zhi 4282616e27eSYong Zhi return snd_pcm_hw_constraint_list(substream->runtime, 0, 4292616e27eSYong Zhi SNDRV_PCM_HW_PARAM_RATE, 4302616e27eSYong Zhi &constraints_16000); 4312616e27eSYong Zhi } 4322616e27eSYong Zhi 43348bf41a2SPierre-Louis Bossart static const struct snd_soc_ops skylake_refcap_ops = { 4342616e27eSYong Zhi .startup = skylake_refcap_startup, 4352616e27eSYong Zhi }; 4362616e27eSYong Zhi 437502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(dummy, 438502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY())); 439502a522bSKuninori Morimoto 440502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(system, 441502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); 442502a522bSKuninori Morimoto 443502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(reference, 444502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); 445502a522bSKuninori Morimoto 446502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(dmic, 447502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); 448502a522bSKuninori Morimoto 449502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi1, 450502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); 451502a522bSKuninori Morimoto 452502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi2, 453502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); 454502a522bSKuninori Morimoto 455502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi3, 456502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); 457502a522bSKuninori Morimoto 458502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp0_pin, 459502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); 460502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp0_codec, 461502a522bSKuninori Morimoto DAILINK_COMP_ARRAY( 462502a522bSKuninori Morimoto /* Left */ COMP_CODEC("i2c-INT343B:00", SKL_SSM_CODEC_DAI), 463502a522bSKuninori Morimoto /* Right */ COMP_CODEC("i2c-INT343B:01", SKL_SSM_CODEC_DAI))); 464502a522bSKuninori Morimoto 465502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp1_pin, 466502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); 467502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(ssp1_codec, 468502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", SKL_NUVOTON_CODEC_DAI))); 469502a522bSKuninori Morimoto 470502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(dmic01_pin, 471502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); 472502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(dmic_codec, 473502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); 474502a522bSKuninori Morimoto 475502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp1_pin, 476502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); 477502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp1_codec, 478502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); 479502a522bSKuninori Morimoto 480502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp2_pin, 481502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); 482502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp2_codec, 483502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); 484502a522bSKuninori Morimoto 485502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp3_pin, 486502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); 487502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(idisp3_codec, 488502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); 489502a522bSKuninori Morimoto 490502a522bSKuninori Morimoto SND_SOC_DAILINK_DEF(platform, 491502a522bSKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); 492502a522bSKuninori Morimoto 493a86d5057SHarsha Priya /* skylake digital audio interface glue - connects codec <--> CPU */ 494a86d5057SHarsha Priya static struct snd_soc_dai_link skylake_dais[] = { 495a86d5057SHarsha Priya /* Front End DAI links */ 496bc5f6ac9SJeeja KP [SKL_DPCM_AUDIO_PB] = { 497a86d5057SHarsha Priya .name = "Skl Audio Port", 498a86d5057SHarsha Priya .stream_name = "Audio", 499a86d5057SHarsha Priya .dynamic = 1, 500a86d5057SHarsha Priya .nonatomic = 1, 5012616e27eSYong Zhi .init = skylake_nau8825_fe_init, 502a86d5057SHarsha Priya .trigger = { 503a86d5057SHarsha Priya SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 504a86d5057SHarsha Priya .dpcm_playback = 1, 5052616e27eSYong Zhi .ops = &skylake_nau8825_fe_ops, 506502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(system, dummy, platform), 507a86d5057SHarsha Priya }, 508bc5f6ac9SJeeja KP [SKL_DPCM_AUDIO_CP] = { 509a86d5057SHarsha Priya .name = "Skl Audio Capture Port", 510a86d5057SHarsha Priya .stream_name = "Audio Record", 511a86d5057SHarsha Priya .dynamic = 1, 512a86d5057SHarsha Priya .nonatomic = 1, 513a86d5057SHarsha Priya .trigger = { 514a86d5057SHarsha Priya SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 515a86d5057SHarsha Priya .dpcm_capture = 1, 5162616e27eSYong Zhi .ops = &skylake_nau8825_fe_ops, 517502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(system, dummy, platform), 518a86d5057SHarsha Priya }, 519bc5f6ac9SJeeja KP [SKL_DPCM_AUDIO_REF_CP] = { 520a86d5057SHarsha Priya .name = "Skl Audio Reference cap", 5212154be36SSathyanarayana Nujella .stream_name = "Wake on Voice", 522a86d5057SHarsha Priya .init = NULL, 523a86d5057SHarsha Priya .dpcm_capture = 1, 524a86d5057SHarsha Priya .nonatomic = 1, 525a86d5057SHarsha Priya .dynamic = 1, 52648bf41a2SPierre-Louis Bossart .ops = &skylake_refcap_ops, 527502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(reference, dummy, platform), 5282616e27eSYong Zhi }, 529bc5f6ac9SJeeja KP [SKL_DPCM_AUDIO_DMIC_CP] = { 5302616e27eSYong Zhi .name = "Skl Audio DMIC cap", 5312616e27eSYong Zhi .stream_name = "dmiccap", 5322616e27eSYong Zhi .init = NULL, 5332616e27eSYong Zhi .dpcm_capture = 1, 5342616e27eSYong Zhi .nonatomic = 1, 5352616e27eSYong Zhi .dynamic = 1, 5362616e27eSYong Zhi .ops = &skylake_dmic_ops, 537502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(dmic, dummy, platform), 538a86d5057SHarsha Priya }, 539bc5f6ac9SJeeja KP [SKL_DPCM_AUDIO_HDMI1_PB] = { 540bc5f6ac9SJeeja KP .name = "Skl HDMI Port1", 541bc5f6ac9SJeeja KP .stream_name = "Hdmi1", 542743ad80eSFang, Yang A .dpcm_playback = 1, 543743ad80eSFang, Yang A .init = NULL, 544bc5f6ac9SJeeja KP .trigger = { 545bc5f6ac9SJeeja KP SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 546bc5f6ac9SJeeja KP .nonatomic = 1, 547bc5f6ac9SJeeja KP .dynamic = 1, 548502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(hdmi1, dummy, platform), 549bc5f6ac9SJeeja KP }, 550bc5f6ac9SJeeja KP [SKL_DPCM_AUDIO_HDMI2_PB] = { 551bc5f6ac9SJeeja KP .name = "Skl HDMI Port2", 552bc5f6ac9SJeeja KP .stream_name = "Hdmi2", 553bc5f6ac9SJeeja KP .dpcm_playback = 1, 554bc5f6ac9SJeeja KP .init = NULL, 555bc5f6ac9SJeeja KP .trigger = { 556bc5f6ac9SJeeja KP SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 557bc5f6ac9SJeeja KP .nonatomic = 1, 558bc5f6ac9SJeeja KP .dynamic = 1, 559502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(hdmi2, dummy, platform), 560bc5f6ac9SJeeja KP }, 561bc5f6ac9SJeeja KP [SKL_DPCM_AUDIO_HDMI3_PB] = { 562bc5f6ac9SJeeja KP .name = "Skl HDMI Port3", 563bc5f6ac9SJeeja KP .stream_name = "Hdmi3", 564bc5f6ac9SJeeja KP .trigger = { 565bc5f6ac9SJeeja KP SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 566bc5f6ac9SJeeja KP .dpcm_playback = 1, 567bc5f6ac9SJeeja KP .init = NULL, 568743ad80eSFang, Yang A .nonatomic = 1, 569743ad80eSFang, Yang A .dynamic = 1, 570502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(hdmi3, dummy, platform), 571743ad80eSFang, Yang A }, 572743ad80eSFang, Yang A 573a86d5057SHarsha Priya /* Back End DAI links */ 574a86d5057SHarsha Priya { 575a86d5057SHarsha Priya /* SSP0 - Codec */ 576a86d5057SHarsha Priya .name = "SSP0-Codec", 5772f0ad491SMengdong Lin .id = 0, 578a86d5057SHarsha Priya .no_pcm = 1, 579a86d5057SHarsha Priya .dai_fmt = SND_SOC_DAIFMT_DSP_A | 580a86d5057SHarsha Priya SND_SOC_DAIFMT_IB_NF | 581*5374b921SPeter Ujfalusi SND_SOC_DAIFMT_CBC_CFC, 582a86d5057SHarsha Priya .init = skylake_ssm4567_codec_init, 583a86d5057SHarsha Priya .ignore_pmdown_time = 1, 584a86d5057SHarsha Priya .be_hw_params_fixup = skylake_ssp_fixup, 585a86d5057SHarsha Priya .dpcm_playback = 1, 5865188b95aSJeeja KP .dpcm_capture = 1, 587502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), 588a86d5057SHarsha Priya }, 589a86d5057SHarsha Priya { 590a86d5057SHarsha Priya /* SSP1 - Codec */ 591a86d5057SHarsha Priya .name = "SSP1-Codec", 5922f0ad491SMengdong Lin .id = 1, 593a86d5057SHarsha Priya .no_pcm = 1, 594a86d5057SHarsha Priya .init = skylake_nau8825_codec_init, 595a86d5057SHarsha Priya .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 596*5374b921SPeter Ujfalusi SND_SOC_DAIFMT_CBC_CFC, 597a86d5057SHarsha Priya .ignore_pmdown_time = 1, 598a86d5057SHarsha Priya .be_hw_params_fixup = skylake_ssp_fixup, 599a86d5057SHarsha Priya .ops = &skylake_nau8825_ops, 600a86d5057SHarsha Priya .dpcm_playback = 1, 601a86d5057SHarsha Priya .dpcm_capture = 1, 602502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), 603a86d5057SHarsha Priya }, 604a86d5057SHarsha Priya { 605a86d5057SHarsha Priya .name = "dmic01", 6062f0ad491SMengdong Lin .id = 2, 607a86d5057SHarsha Priya .ignore_suspend = 1, 6082616e27eSYong Zhi .be_hw_params_fixup = skylake_dmic_fixup, 609a86d5057SHarsha Priya .dpcm_capture = 1, 610a86d5057SHarsha Priya .no_pcm = 1, 611502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(dmic01_pin, dmic_codec, platform), 612a86d5057SHarsha Priya }, 613743ad80eSFang, Yang A { 614bc5f6ac9SJeeja KP .name = "iDisp1", 6152f0ad491SMengdong Lin .id = 3, 616743ad80eSFang, Yang A .dpcm_playback = 1, 617bc5f6ac9SJeeja KP .init = skylake_hdmi1_init, 618bc5f6ac9SJeeja KP .no_pcm = 1, 619502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), 620bc5f6ac9SJeeja KP }, 621bc5f6ac9SJeeja KP { 622bc5f6ac9SJeeja KP .name = "iDisp2", 6232f0ad491SMengdong Lin .id = 4, 624bc5f6ac9SJeeja KP .init = skylake_hdmi2_init, 625bc5f6ac9SJeeja KP .dpcm_playback = 1, 626bc5f6ac9SJeeja KP .no_pcm = 1, 627502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), 628bc5f6ac9SJeeja KP }, 629bc5f6ac9SJeeja KP { 630bc5f6ac9SJeeja KP .name = "iDisp3", 6312f0ad491SMengdong Lin .id = 5, 632bc5f6ac9SJeeja KP .init = skylake_hdmi3_init, 633bc5f6ac9SJeeja KP .dpcm_playback = 1, 634743ad80eSFang, Yang A .no_pcm = 1, 635502a522bSKuninori Morimoto SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), 636743ad80eSFang, Yang A }, 637a86d5057SHarsha Priya }; 638a86d5057SHarsha Priya 6399e4278cdSJeeja KP #define NAME_SIZE 32 64046ed1a27SSubhransu S. Prusty static int skylake_card_late_probe(struct snd_soc_card *card) 64146ed1a27SSubhransu S. Prusty { 64246ed1a27SSubhransu S. Prusty struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(card); 64346ed1a27SSubhransu S. Prusty struct skl_hdmi_pcm *pcm; 64445101122SKuninori Morimoto struct snd_soc_component *component = NULL; 6459e4278cdSJeeja KP int err, i = 0; 6469e4278cdSJeeja KP char jack_name[NAME_SIZE]; 64746ed1a27SSubhransu S. Prusty 64846ed1a27SSubhransu S. Prusty list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { 64945101122SKuninori Morimoto component = pcm->codec_dai->component; 6509e4278cdSJeeja KP snprintf(jack_name, sizeof(jack_name), 6519e4278cdSJeeja KP "HDMI/DP, pcm=%d Jack", pcm->device); 6529e4278cdSJeeja KP err = snd_soc_card_jack_new(card, jack_name, 6539e4278cdSJeeja KP SND_JACK_AVOUT, 6549e4278cdSJeeja KP &skylake_hdmi[i], 6559e4278cdSJeeja KP NULL, 0); 6569e4278cdSJeeja KP 6579e4278cdSJeeja KP if (err) 6589e4278cdSJeeja KP return err; 6599e4278cdSJeeja KP 6609e4278cdSJeeja KP err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, 6619e4278cdSJeeja KP &skylake_hdmi[i]); 66246ed1a27SSubhransu S. Prusty if (err < 0) 66346ed1a27SSubhransu S. Prusty return err; 6649e4278cdSJeeja KP 6659e4278cdSJeeja KP i++; 66646ed1a27SSubhransu S. Prusty } 66746ed1a27SSubhransu S. Prusty 66845101122SKuninori Morimoto if (!component) 66986b57031SJeeja KP return -EINVAL; 67086b57031SJeeja KP 67145101122SKuninori Morimoto return hdac_hdmi_jack_port_init(component, &card->dapm); 67246ed1a27SSubhransu S. Prusty } 67346ed1a27SSubhransu S. Prusty 674a86d5057SHarsha Priya /* skylake audio machine driver for SPT + NAU88L25 */ 675a86d5057SHarsha Priya static struct snd_soc_card skylake_audio_card = { 676a86d5057SHarsha Priya .name = "sklnau8825adi", 677a86d5057SHarsha Priya .owner = THIS_MODULE, 678a86d5057SHarsha Priya .dai_link = skylake_dais, 679a86d5057SHarsha Priya .num_links = ARRAY_SIZE(skylake_dais), 680a86d5057SHarsha Priya .controls = skylake_controls, 681a86d5057SHarsha Priya .num_controls = ARRAY_SIZE(skylake_controls), 682a86d5057SHarsha Priya .dapm_widgets = skylake_widgets, 683a86d5057SHarsha Priya .num_dapm_widgets = ARRAY_SIZE(skylake_widgets), 684a86d5057SHarsha Priya .dapm_routes = skylake_map, 685a86d5057SHarsha Priya .num_dapm_routes = ARRAY_SIZE(skylake_map), 686a86d5057SHarsha Priya .codec_conf = ssm4567_codec_conf, 687a86d5057SHarsha Priya .num_configs = ARRAY_SIZE(ssm4567_codec_conf), 6884c6ebc3eSFang, Yang A .fully_routed = true, 689c8061689SPierre-Louis Bossart .disable_route_checks = true, 69046ed1a27SSubhransu S. Prusty .late_probe = skylake_card_late_probe, 691a86d5057SHarsha Priya }; 692a86d5057SHarsha Priya 693a86d5057SHarsha Priya static int skylake_audio_probe(struct platform_device *pdev) 694a86d5057SHarsha Priya { 69546ed1a27SSubhransu S. Prusty struct skl_nau88125_private *ctx; 696b92826faSPierre-Louis Bossart struct snd_soc_acpi_mach *mach; 69746ed1a27SSubhransu S. Prusty 6988faef87eSJia-Ju Bai ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 69946ed1a27SSubhransu S. Prusty if (!ctx) 70046ed1a27SSubhransu S. Prusty return -ENOMEM; 70146ed1a27SSubhransu S. Prusty 70246ed1a27SSubhransu S. Prusty INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 70346ed1a27SSubhransu S. Prusty 704a86d5057SHarsha Priya skylake_audio_card.dev = &pdev->dev; 70546ed1a27SSubhransu S. Prusty snd_soc_card_set_drvdata(&skylake_audio_card, ctx); 706a86d5057SHarsha Priya 70742432196SGuennadi Liakhovetski mach = pdev->dev.platform_data; 708b92826faSPierre-Louis Bossart if (mach) 709b92826faSPierre-Louis Bossart dmic_constraints = mach->mach_params.dmic_num == 2 ? 710cfa12367SYong Zhi &constraints_dmic_2ch : &constraints_dmic_channels; 711cfa12367SYong Zhi 712a86d5057SHarsha Priya return devm_snd_soc_register_card(&pdev->dev, &skylake_audio_card); 713a86d5057SHarsha Priya } 714a86d5057SHarsha Priya 7159dc201cfSVinod Koul static const struct platform_device_id skl_board_ids[] = { 7169dc201cfSVinod Koul { .name = "skl_n88l25_s4567" }, 7179dc201cfSVinod Koul { .name = "kbl_n88l25_s4567" }, 7189dc201cfSVinod Koul { } 7199dc201cfSVinod Koul }; 72053b98536SPierre-Louis Bossart MODULE_DEVICE_TABLE(platform, skl_board_ids); 7219dc201cfSVinod Koul 722a86d5057SHarsha Priya static struct platform_driver skylake_audio = { 723a86d5057SHarsha Priya .probe = skylake_audio_probe, 724a86d5057SHarsha Priya .driver = { 725400ada0cSVinod Koul .name = "skl_n88l25_s4567", 726a86d5057SHarsha Priya .pm = &snd_soc_pm_ops, 727a86d5057SHarsha Priya }, 7289dc201cfSVinod Koul .id_table = skl_board_ids, 729a86d5057SHarsha Priya }; 730a86d5057SHarsha Priya 731a86d5057SHarsha Priya module_platform_driver(skylake_audio) 732a86d5057SHarsha Priya 733a86d5057SHarsha Priya /* Module information */ 734a86d5057SHarsha Priya MODULE_AUTHOR("Conrad Cooke <conrad.cooke@intel.com>"); 735a86d5057SHarsha Priya MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>"); 736a86d5057SHarsha Priya MODULE_AUTHOR("Naveen M <naveen.m@intel.com>"); 737a86d5057SHarsha Priya MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>"); 738a86d5057SHarsha Priya MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); 739a86d5057SHarsha Priya MODULE_DESCRIPTION("Intel Audio Machine driver for SKL with NAU88L25 and SSM4567 in I2S Mode"); 740a86d5057SHarsha Priya MODULE_LICENSE("GPL v2"); 741