11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22a18483aSHarsha Priya N /*
32a18483aSHarsha Priya N * Intel Kabylake I2S Machine Driver with MAXIM98927
42a18483aSHarsha Priya N * RT5514 and RT5663 Codecs
52a18483aSHarsha Priya N *
62a18483aSHarsha Priya N * Copyright (C) 2017, Intel Corporation. All rights reserved.
72a18483aSHarsha Priya N *
82a18483aSHarsha Priya N * Modified from:
92a18483aSHarsha Priya N * Intel Kabylake I2S Machine driver supporting MAXIM98927 and
102a18483aSHarsha Priya N * RT5663 codecs
112a18483aSHarsha Priya N */
122a18483aSHarsha Priya N
1380b64903SHarsha Priya N #include <linux/input.h>
142a18483aSHarsha Priya N #include <linux/module.h>
152a18483aSHarsha Priya N #include <linux/platform_device.h>
162a18483aSHarsha Priya N #include <sound/core.h>
172a18483aSHarsha Priya N #include <sound/jack.h>
182a18483aSHarsha Priya N #include <sound/pcm.h>
192a18483aSHarsha Priya N #include <sound/pcm_params.h>
202a18483aSHarsha Priya N #include <sound/soc.h>
21b92826faSPierre-Louis Bossart #include <sound/soc-acpi.h>
222a18483aSHarsha Priya N #include "../../codecs/rt5514.h"
232a18483aSHarsha Priya N #include "../../codecs/rt5663.h"
242a18483aSHarsha Priya N #include "../../codecs/hdac_hdmi.h"
2547cbea21SNaveen M #include <linux/clk.h>
2647cbea21SNaveen M #include <linux/clk-provider.h>
2747cbea21SNaveen M #include <linux/clkdev.h>
282a18483aSHarsha Priya N
292a18483aSHarsha Priya N #define KBL_REALTEK_CODEC_DAI "rt5663-aif"
302a18483aSHarsha Priya N #define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1"
312a18483aSHarsha Priya N #define KBL_MAXIM_CODEC_DAI "max98927-aif1"
322a18483aSHarsha Priya N #define MAXIM_DEV0_NAME "i2c-MX98927:00"
332a18483aSHarsha Priya N #define MAXIM_DEV1_NAME "i2c-MX98927:01"
342a18483aSHarsha Priya N #define RT5514_DEV_NAME "i2c-10EC5514:00"
352a18483aSHarsha Priya N #define RT5663_DEV_NAME "i2c-10EC5663:00"
362a18483aSHarsha Priya N #define RT5514_AIF1_BCLK_FREQ (48000 * 8 * 16)
372a18483aSHarsha Priya N #define RT5514_AIF1_SYSCLK_FREQ 12288000
382a18483aSHarsha Priya N #define NAME_SIZE 32
392a18483aSHarsha Priya N
402a18483aSHarsha Priya N #define DMIC_CH(p) p->list[p->count-1]
412a18483aSHarsha Priya N
422a18483aSHarsha Priya N
432a18483aSHarsha Priya N static struct snd_soc_card kabylake_audio_card;
442a18483aSHarsha Priya N static const struct snd_pcm_hw_constraint_list *dmic_constraints;
452a18483aSHarsha Priya N
462a18483aSHarsha Priya N struct kbl_hdmi_pcm {
472a18483aSHarsha Priya N struct list_head head;
482a18483aSHarsha Priya N struct snd_soc_dai *codec_dai;
492a18483aSHarsha Priya N int device;
502a18483aSHarsha Priya N };
512a18483aSHarsha Priya N
522a18483aSHarsha Priya N struct kbl_codec_private {
532a18483aSHarsha Priya N struct snd_soc_jack kabylake_headset;
542a18483aSHarsha Priya N struct list_head hdmi_pcm_list;
552a18483aSHarsha Priya N struct snd_soc_jack kabylake_hdmi[2];
5647cbea21SNaveen M struct clk *mclk;
5747cbea21SNaveen M struct clk *sclk;
582a18483aSHarsha Priya N };
592a18483aSHarsha Priya N
602a18483aSHarsha Priya N enum {
612a18483aSHarsha Priya N KBL_DPCM_AUDIO_PB = 0,
622a18483aSHarsha Priya N KBL_DPCM_AUDIO_CP,
63b32ee384SNaveen Manohar KBL_DPCM_AUDIO_HS_PB,
64b32ee384SNaveen Manohar KBL_DPCM_AUDIO_ECHO_REF_CP,
652a18483aSHarsha Priya N KBL_DPCM_AUDIO_DMIC_CP,
66393a829bSHarsha Priya N KBL_DPCM_AUDIO_RT5514_DSP,
672a18483aSHarsha Priya N KBL_DPCM_AUDIO_HDMI1_PB,
682a18483aSHarsha Priya N KBL_DPCM_AUDIO_HDMI2_PB,
692a18483aSHarsha Priya N };
702a18483aSHarsha Priya N
712a18483aSHarsha Priya N static const struct snd_kcontrol_new kabylake_controls[] = {
722a18483aSHarsha Priya N SOC_DAPM_PIN_SWITCH("Headphone Jack"),
732a18483aSHarsha Priya N SOC_DAPM_PIN_SWITCH("Headset Mic"),
742a18483aSHarsha Priya N SOC_DAPM_PIN_SWITCH("Left Spk"),
752a18483aSHarsha Priya N SOC_DAPM_PIN_SWITCH("Right Spk"),
762a18483aSHarsha Priya N SOC_DAPM_PIN_SWITCH("DMIC"),
772a18483aSHarsha Priya N };
782a18483aSHarsha Priya N
platform_clock_control(struct snd_soc_dapm_widget * w,struct snd_kcontrol * k,int event)7947cbea21SNaveen M static int platform_clock_control(struct snd_soc_dapm_widget *w,
8047cbea21SNaveen M struct snd_kcontrol *k, int event)
8147cbea21SNaveen M {
8247cbea21SNaveen M struct snd_soc_dapm_context *dapm = w->dapm;
8347cbea21SNaveen M struct snd_soc_card *card = dapm->card;
8447cbea21SNaveen M struct kbl_codec_private *priv = snd_soc_card_get_drvdata(card);
8547cbea21SNaveen M int ret = 0;
8647cbea21SNaveen M
8747cbea21SNaveen M /*
8847cbea21SNaveen M * MCLK/SCLK need to be ON early for a successful synchronization of
8947cbea21SNaveen M * codec internal clock. And the clocks are turned off during
9047cbea21SNaveen M * POST_PMD after the stream is stopped.
9147cbea21SNaveen M */
9247cbea21SNaveen M switch (event) {
9347cbea21SNaveen M case SND_SOC_DAPM_PRE_PMU:
9447cbea21SNaveen M /* Enable MCLK */
9547cbea21SNaveen M ret = clk_set_rate(priv->mclk, 24000000);
9647cbea21SNaveen M if (ret < 0) {
9747cbea21SNaveen M dev_err(card->dev, "Can't set rate for mclk, err: %d\n",
9847cbea21SNaveen M ret);
9947cbea21SNaveen M return ret;
10047cbea21SNaveen M }
10147cbea21SNaveen M
10247cbea21SNaveen M ret = clk_prepare_enable(priv->mclk);
10347cbea21SNaveen M if (ret < 0) {
10447cbea21SNaveen M dev_err(card->dev, "Can't enable mclk, err: %d\n", ret);
10547cbea21SNaveen M return ret;
10647cbea21SNaveen M }
10747cbea21SNaveen M
10847cbea21SNaveen M /* Enable SCLK */
10947cbea21SNaveen M ret = clk_set_rate(priv->sclk, 3072000);
11047cbea21SNaveen M if (ret < 0) {
11147cbea21SNaveen M dev_err(card->dev, "Can't set rate for sclk, err: %d\n",
11247cbea21SNaveen M ret);
11347cbea21SNaveen M clk_disable_unprepare(priv->mclk);
11447cbea21SNaveen M return ret;
11547cbea21SNaveen M }
11647cbea21SNaveen M
11747cbea21SNaveen M ret = clk_prepare_enable(priv->sclk);
11847cbea21SNaveen M if (ret < 0) {
11947cbea21SNaveen M dev_err(card->dev, "Can't enable sclk, err: %d\n", ret);
12047cbea21SNaveen M clk_disable_unprepare(priv->mclk);
12147cbea21SNaveen M }
12247cbea21SNaveen M break;
12347cbea21SNaveen M case SND_SOC_DAPM_POST_PMD:
12447cbea21SNaveen M clk_disable_unprepare(priv->mclk);
12547cbea21SNaveen M clk_disable_unprepare(priv->sclk);
12647cbea21SNaveen M break;
12747cbea21SNaveen M default:
12847cbea21SNaveen M return 0;
12947cbea21SNaveen M }
13047cbea21SNaveen M
13147cbea21SNaveen M return 0;
13247cbea21SNaveen M }
13347cbea21SNaveen M
1342a18483aSHarsha Priya N static const struct snd_soc_dapm_widget kabylake_widgets[] = {
1352a18483aSHarsha Priya N SND_SOC_DAPM_HP("Headphone Jack", NULL),
1362a18483aSHarsha Priya N SND_SOC_DAPM_MIC("Headset Mic", NULL),
1372a18483aSHarsha Priya N SND_SOC_DAPM_SPK("Left Spk", NULL),
1382a18483aSHarsha Priya N SND_SOC_DAPM_SPK("Right Spk", NULL),
1392a18483aSHarsha Priya N SND_SOC_DAPM_MIC("DMIC", NULL),
140c20252cfSNaveen M SND_SOC_DAPM_SPK("HDMI1", NULL),
141c20252cfSNaveen M SND_SOC_DAPM_SPK("HDMI2", NULL),
14247cbea21SNaveen M SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
14347cbea21SNaveen M platform_clock_control, SND_SOC_DAPM_PRE_PMU |
14447cbea21SNaveen M SND_SOC_DAPM_POST_PMD),
1452a18483aSHarsha Priya N
1462a18483aSHarsha Priya N };
1472a18483aSHarsha Priya N
148c0703be9SPierre-Louis Bossart static struct snd_soc_jack_pin jack_pins[] = {
149c0703be9SPierre-Louis Bossart {
150c0703be9SPierre-Louis Bossart .pin = "Headphone Jack",
151c0703be9SPierre-Louis Bossart .mask = SND_JACK_HEADPHONE,
152c0703be9SPierre-Louis Bossart },
153c0703be9SPierre-Louis Bossart {
154c0703be9SPierre-Louis Bossart .pin = "Headset Mic",
155c0703be9SPierre-Louis Bossart .mask = SND_JACK_MICROPHONE,
156c0703be9SPierre-Louis Bossart },
157c0703be9SPierre-Louis Bossart };
158c0703be9SPierre-Louis Bossart
1592a18483aSHarsha Priya N static const struct snd_soc_dapm_route kabylake_map[] = {
1602a18483aSHarsha Priya N /* Headphones */
16147cbea21SNaveen M { "Headphone Jack", NULL, "Platform Clock" },
1622a18483aSHarsha Priya N { "Headphone Jack", NULL, "HPOL" },
1632a18483aSHarsha Priya N { "Headphone Jack", NULL, "HPOR" },
1642a18483aSHarsha Priya N
1652a18483aSHarsha Priya N /* speaker */
1662a18483aSHarsha Priya N { "Left Spk", NULL, "Left BE_OUT" },
1672a18483aSHarsha Priya N { "Right Spk", NULL, "Right BE_OUT" },
1682a18483aSHarsha Priya N
1692a18483aSHarsha Priya N /* other jacks */
17047cbea21SNaveen M { "Headset Mic", NULL, "Platform Clock" },
1712a18483aSHarsha Priya N { "IN1P", NULL, "Headset Mic" },
1722a18483aSHarsha Priya N { "IN1N", NULL, "Headset Mic" },
1732a18483aSHarsha Priya N
1742a18483aSHarsha Priya N /* CODEC BE connections */
1752a18483aSHarsha Priya N { "Left HiFi Playback", NULL, "ssp0 Tx" },
1762a18483aSHarsha Priya N { "Right HiFi Playback", NULL, "ssp0 Tx" },
1770b06122fSNaveen Manohar { "ssp0 Tx", NULL, "spk_out" },
1782a18483aSHarsha Priya N
1792a18483aSHarsha Priya N { "AIF Playback", NULL, "ssp1 Tx" },
1804c761ebfSNaveen Manohar { "ssp1 Tx", NULL, "codec1_out" },
1812a18483aSHarsha Priya N
1820b06122fSNaveen Manohar { "hs_in", NULL, "ssp1 Rx" },
1832a18483aSHarsha Priya N { "ssp1 Rx", NULL, "AIF Capture" },
1842a18483aSHarsha Priya N
1852a18483aSHarsha Priya N { "codec1_in", NULL, "ssp0 Rx" },
1862a18483aSHarsha Priya N { "ssp0 Rx", NULL, "AIF1 Capture" },
1872a18483aSHarsha Priya N
18864220b9dSNaveen Manohar /* IV feedback path */
18964220b9dSNaveen Manohar { "codec0_fb_in", NULL, "ssp0 Rx"},
19064220b9dSNaveen Manohar { "ssp0 Rx", NULL, "Left HiFi Capture" },
19164220b9dSNaveen Manohar { "ssp0 Rx", NULL, "Right HiFi Capture" },
19264220b9dSNaveen Manohar
1932a18483aSHarsha Priya N /* DMIC */
1942a18483aSHarsha Priya N { "DMIC1L", NULL, "DMIC" },
1952a18483aSHarsha Priya N { "DMIC1R", NULL, "DMIC" },
1962a18483aSHarsha Priya N { "DMIC2L", NULL, "DMIC" },
1972a18483aSHarsha Priya N { "DMIC2R", NULL, "DMIC" },
1982a18483aSHarsha Priya N
1992a18483aSHarsha Priya N { "hifi2", NULL, "iDisp2 Tx" },
2002a18483aSHarsha Priya N { "iDisp2 Tx", NULL, "iDisp2_out" },
2012a18483aSHarsha Priya N { "hifi1", NULL, "iDisp1 Tx" },
2022a18483aSHarsha Priya N { "iDisp1 Tx", NULL, "iDisp1_out" },
2032a18483aSHarsha Priya N };
2042a18483aSHarsha Priya N
2052a18483aSHarsha Priya N static struct snd_soc_codec_conf max98927_codec_conf[] = {
2062a18483aSHarsha Priya N {
2075a349330SKuninori Morimoto .dlc = COMP_CODEC_CONF(MAXIM_DEV0_NAME),
2082a18483aSHarsha Priya N .name_prefix = "Right",
2092a18483aSHarsha Priya N },
2102a18483aSHarsha Priya N {
2115a349330SKuninori Morimoto .dlc = COMP_CODEC_CONF(MAXIM_DEV1_NAME),
2122a18483aSHarsha Priya N .name_prefix = "Left",
2132a18483aSHarsha Priya N },
2142a18483aSHarsha Priya N };
2152a18483aSHarsha Priya N
2162a18483aSHarsha Priya N
kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime * rtd)2172a18483aSHarsha Priya N static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd)
2182a18483aSHarsha Priya N {
2192a18483aSHarsha Priya N struct snd_soc_dapm_context *dapm;
2200d1571c1SKuninori Morimoto struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component;
2212a18483aSHarsha Priya N int ret;
2222a18483aSHarsha Priya N
2232a18483aSHarsha Priya N dapm = snd_soc_component_get_dapm(component);
2242a18483aSHarsha Priya N ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
2252a18483aSHarsha Priya N if (ret)
2262a18483aSHarsha Priya N dev_err(rtd->dev, "Ref Cap -Ignore suspend failed = %d\n", ret);
2272a18483aSHarsha Priya N
2282a18483aSHarsha Priya N return ret;
2292a18483aSHarsha Priya N }
2302a18483aSHarsha Priya N
kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime * rtd)2312a18483aSHarsha Priya N static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
2322a18483aSHarsha Priya N {
2332a18483aSHarsha Priya N int ret;
2342a18483aSHarsha Priya N struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
2350d1571c1SKuninori Morimoto struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
23680b64903SHarsha Priya N struct snd_soc_jack *jack;
2372a18483aSHarsha Priya N
2382a18483aSHarsha Priya N /*
2392a18483aSHarsha Priya N * Headset buttons map to the google Reference headset.
2402a18483aSHarsha Priya N * These can be configured by userspace.
2412a18483aSHarsha Priya N */
242c0703be9SPierre-Louis Bossart ret = snd_soc_card_jack_new_pins(&kabylake_audio_card, "Headset Jack",
2432a18483aSHarsha Priya N SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
24419aed2d6SAkihiko Odaki SND_JACK_BTN_2 | SND_JACK_BTN_3,
245c0703be9SPierre-Louis Bossart &ctx->kabylake_headset,
246c0703be9SPierre-Louis Bossart jack_pins,
247c0703be9SPierre-Louis Bossart ARRAY_SIZE(jack_pins));
2482a18483aSHarsha Priya N if (ret) {
2492a18483aSHarsha Priya N dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
2502a18483aSHarsha Priya N return ret;
2512a18483aSHarsha Priya N }
2522a18483aSHarsha Priya N
25380b64903SHarsha Priya N jack = &ctx->kabylake_headset;
2548ee64928SBenson Leung snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
25580b64903SHarsha Priya N snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
25680b64903SHarsha Priya N snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
25780b64903SHarsha Priya N snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
25880b64903SHarsha Priya N
25937a04911SOder Chiou snd_soc_component_set_jack(component, &ctx->kabylake_headset, NULL);
2602a18483aSHarsha Priya N
2612a18483aSHarsha Priya N ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC");
2622a18483aSHarsha Priya N if (ret)
2632a18483aSHarsha Priya N dev_err(rtd->dev, "DMIC - Ignore suspend failed = %d\n", ret);
2642a18483aSHarsha Priya N
2652a18483aSHarsha Priya N return ret;
2662a18483aSHarsha Priya N }
2672a18483aSHarsha Priya N
kabylake_hdmi_init(struct snd_soc_pcm_runtime * rtd,int device)2682a18483aSHarsha Priya N static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device)
2692a18483aSHarsha Priya N {
2702a18483aSHarsha Priya N struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
2710d1571c1SKuninori Morimoto struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
2722a18483aSHarsha Priya N struct kbl_hdmi_pcm *pcm;
2732a18483aSHarsha Priya N
2742a18483aSHarsha Priya N pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
2752a18483aSHarsha Priya N if (!pcm)
2762a18483aSHarsha Priya N return -ENOMEM;
2772a18483aSHarsha Priya N
2782a18483aSHarsha Priya N pcm->device = device;
2792a18483aSHarsha Priya N pcm->codec_dai = dai;
2802a18483aSHarsha Priya N
2812a18483aSHarsha Priya N list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
2822a18483aSHarsha Priya N
2832a18483aSHarsha Priya N return 0;
2842a18483aSHarsha Priya N }
2852a18483aSHarsha Priya N
kabylake_hdmi1_init(struct snd_soc_pcm_runtime * rtd)2862a18483aSHarsha Priya N static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
2872a18483aSHarsha Priya N {
2882a18483aSHarsha Priya N return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB);
2892a18483aSHarsha Priya N }
2902a18483aSHarsha Priya N
kabylake_hdmi2_init(struct snd_soc_pcm_runtime * rtd)2912a18483aSHarsha Priya N static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
2922a18483aSHarsha Priya N {
2932a18483aSHarsha Priya N return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB);
2942a18483aSHarsha Priya N }
2952a18483aSHarsha Priya N
2962a18483aSHarsha Priya N static const unsigned int rates[] = {
2972a18483aSHarsha Priya N 48000,
2982a18483aSHarsha Priya N };
2992a18483aSHarsha Priya N
3002a18483aSHarsha Priya N static const struct snd_pcm_hw_constraint_list constraints_rates = {
3012a18483aSHarsha Priya N .count = ARRAY_SIZE(rates),
3022a18483aSHarsha Priya N .list = rates,
3032a18483aSHarsha Priya N .mask = 0,
3042a18483aSHarsha Priya N };
3052a18483aSHarsha Priya N
3062a18483aSHarsha Priya N static const unsigned int channels[] = {
3072a18483aSHarsha Priya N 2,
3082a18483aSHarsha Priya N };
3092a18483aSHarsha Priya N
3102a18483aSHarsha Priya N static const struct snd_pcm_hw_constraint_list constraints_channels = {
3112a18483aSHarsha Priya N .count = ARRAY_SIZE(channels),
3122a18483aSHarsha Priya N .list = channels,
3132a18483aSHarsha Priya N .mask = 0,
3142a18483aSHarsha Priya N };
3152a18483aSHarsha Priya N
kbl_fe_startup(struct snd_pcm_substream * substream)3162a18483aSHarsha Priya N static int kbl_fe_startup(struct snd_pcm_substream *substream)
3172a18483aSHarsha Priya N {
3182a18483aSHarsha Priya N struct snd_pcm_runtime *runtime = substream->runtime;
3192a18483aSHarsha Priya N
3202a18483aSHarsha Priya N /*
3212a18483aSHarsha Priya N * On this platform for PCM device we support,
3222a18483aSHarsha Priya N * 48Khz
3232a18483aSHarsha Priya N * stereo
3242a18483aSHarsha Priya N * 16 bit audio
3252a18483aSHarsha Priya N */
3262a18483aSHarsha Priya N
3272a18483aSHarsha Priya N runtime->hw.channels_max = 2;
3282a18483aSHarsha Priya N snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
3292a18483aSHarsha Priya N &constraints_channels);
3302a18483aSHarsha Priya N
3312a18483aSHarsha Priya N runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
3322a18483aSHarsha Priya N snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
3332a18483aSHarsha Priya N
3342a18483aSHarsha Priya N snd_pcm_hw_constraint_list(runtime, 0,
3352a18483aSHarsha Priya N SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
3362a18483aSHarsha Priya N
3372a18483aSHarsha Priya N return 0;
3382a18483aSHarsha Priya N }
3392a18483aSHarsha Priya N
3402a18483aSHarsha Priya N static const struct snd_soc_ops kabylake_rt5663_fe_ops = {
3412a18483aSHarsha Priya N .startup = kbl_fe_startup,
3422a18483aSHarsha Priya N };
3432a18483aSHarsha Priya N
kabylake_ssp_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)3442a18483aSHarsha Priya N static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
3452a18483aSHarsha Priya N struct snd_pcm_hw_params *params)
3462a18483aSHarsha Priya N {
3472a18483aSHarsha Priya N struct snd_interval *rate = hw_param_interval(params,
3482a18483aSHarsha Priya N SNDRV_PCM_HW_PARAM_RATE);
34911576138SPierre-Louis Bossart struct snd_interval *chan = hw_param_interval(params,
3502a18483aSHarsha Priya N SNDRV_PCM_HW_PARAM_CHANNELS);
3512a18483aSHarsha Priya N struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
3525c5f1baeSHarsha Priya struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL;
3535c5f1baeSHarsha Priya
3545c5f1baeSHarsha Priya /*
3555c5f1baeSHarsha Priya * The following loop will be called only for playback stream
3565c5f1baeSHarsha Priya * In this platform, there is only one playback device on every SSP
3575c5f1baeSHarsha Priya */
3585c5f1baeSHarsha Priya for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) {
3595c5f1baeSHarsha Priya rtd_dpcm = dpcm;
3605c5f1baeSHarsha Priya break;
3615c5f1baeSHarsha Priya }
3625c5f1baeSHarsha Priya
3635c5f1baeSHarsha Priya /*
3645c5f1baeSHarsha Priya * This following loop will be called only for capture stream
3655c5f1baeSHarsha Priya * In this platform, there is only one capture device on every SSP
3665c5f1baeSHarsha Priya */
3675c5f1baeSHarsha Priya for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) {
3685c5f1baeSHarsha Priya rtd_dpcm = dpcm;
3695c5f1baeSHarsha Priya break;
3705c5f1baeSHarsha Priya }
3715c5f1baeSHarsha Priya
3725c5f1baeSHarsha Priya if (!rtd_dpcm)
3735c5f1baeSHarsha Priya return -EINVAL;
3745c5f1baeSHarsha Priya
3755c5f1baeSHarsha Priya /*
3765c5f1baeSHarsha Priya * The above 2 loops are mutually exclusive based on the stream direction,
3775c5f1baeSHarsha Priya * thus rtd_dpcm variable will never be overwritten
3785c5f1baeSHarsha Priya */
3792a18483aSHarsha Priya N
3802a18483aSHarsha Priya N /*
3812a18483aSHarsha Priya N * The ADSP will convert the FE rate to 48k, stereo, 24 bit
3822a18483aSHarsha Priya N */
3835c5f1baeSHarsha Priya if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") ||
3845c5f1baeSHarsha Priya !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") ||
3855c5f1baeSHarsha Priya !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) {
3862a18483aSHarsha Priya N rate->min = rate->max = 48000;
38711576138SPierre-Louis Bossart chan->min = chan->max = 2;
3882a18483aSHarsha Priya N snd_mask_none(fmt);
389b5453e8cSTakashi Iwai snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
3905c5f1baeSHarsha Priya } else if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio DMIC cap")) {
3912a18483aSHarsha Priya N if (params_channels(params) == 2 ||
3922a18483aSHarsha Priya N DMIC_CH(dmic_constraints) == 2)
39311576138SPierre-Louis Bossart chan->min = chan->max = 2;
3942a18483aSHarsha Priya N else
39511576138SPierre-Louis Bossart chan->min = chan->max = 4;
3962a18483aSHarsha Priya N }
3972a18483aSHarsha Priya N /*
3982a18483aSHarsha Priya N * The speaker on the SSP0 supports S16_LE and not S24_LE.
3992a18483aSHarsha Priya N * thus changing the mask here
4002a18483aSHarsha Priya N */
4015c5f1baeSHarsha Priya if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec"))
402b5453e8cSTakashi Iwai snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
4032a18483aSHarsha Priya N
4042a18483aSHarsha Priya N return 0;
4052a18483aSHarsha Priya N }
4062a18483aSHarsha Priya N
kabylake_rt5663_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)4072a18483aSHarsha Priya N static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream,
4082a18483aSHarsha Priya N struct snd_pcm_hw_params *params)
4092a18483aSHarsha Priya N {
4102207b93bSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
4110d1571c1SKuninori Morimoto struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
4122a18483aSHarsha Priya N int ret;
4132a18483aSHarsha Priya N
4142a18483aSHarsha Priya N /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */
41545101122SKuninori Morimoto rt5663_sel_asrc_clk_src(codec_dai->component,
416349d63c3SHarsha Priya N RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER,
417349d63c3SHarsha Priya N RT5663_CLK_SEL_I2S1_ASRC);
4182a18483aSHarsha Priya N
4192a18483aSHarsha Priya N ret = snd_soc_dai_set_sysclk(codec_dai,
4202a18483aSHarsha Priya N RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN);
4212a18483aSHarsha Priya N if (ret < 0)
4222a18483aSHarsha Priya N dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
4232a18483aSHarsha Priya N
4242a18483aSHarsha Priya N return ret;
4252a18483aSHarsha Priya N }
4262a18483aSHarsha Priya N
4272a18483aSHarsha Priya N static struct snd_soc_ops kabylake_rt5663_ops = {
4282a18483aSHarsha Priya N .hw_params = kabylake_rt5663_hw_params,
4292a18483aSHarsha Priya N };
4302a18483aSHarsha Priya N
kabylake_ssp0_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)4312a18483aSHarsha Priya N static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
4322a18483aSHarsha Priya N struct snd_pcm_hw_params *params)
4332a18483aSHarsha Priya N {
4342207b93bSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
4350b7990e3SKuninori Morimoto struct snd_soc_dai *codec_dai;
4362a18483aSHarsha Priya N int ret = 0, j;
4372a18483aSHarsha Priya N
4385dd1677cSKuninori Morimoto for_each_rtd_codec_dais(rtd, j, codec_dai) {
4392a18483aSHarsha Priya N if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) {
4402a18483aSHarsha Priya N ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16);
4412a18483aSHarsha Priya N if (ret < 0) {
4422a18483aSHarsha Priya N dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
4432a18483aSHarsha Priya N return ret;
4442a18483aSHarsha Priya N }
4452a18483aSHarsha Priya N
4462a18483aSHarsha Priya N ret = snd_soc_dai_set_sysclk(codec_dai,
4476512dd4dSHarsha Priya N RT5514_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN);
4482a18483aSHarsha Priya N if (ret < 0) {
4496512dd4dSHarsha Priya N dev_err(rtd->dev, "set sysclk err: %d\n", ret);
4502a18483aSHarsha Priya N return ret;
4512a18483aSHarsha Priya N }
4522a18483aSHarsha Priya N }
453cc4db0e2SHarsha Priya N if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) {
454cc4db0e2SHarsha Priya N ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16);
4552a18483aSHarsha Priya N if (ret < 0) {
456cc4db0e2SHarsha Priya N dev_err(rtd->dev, "DEV0 TDM slot err:%d\n", ret);
457cc4db0e2SHarsha Priya N return ret;
458cc4db0e2SHarsha Priya N }
459cc4db0e2SHarsha Priya N }
460cc4db0e2SHarsha Priya N
461cc4db0e2SHarsha Priya N if (!strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
462cc4db0e2SHarsha Priya N ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16);
463cc4db0e2SHarsha Priya N if (ret < 0) {
464cc4db0e2SHarsha Priya N dev_err(rtd->dev, "DEV1 TDM slot err:%d\n", ret);
4652a18483aSHarsha Priya N return ret;
4662a18483aSHarsha Priya N }
4672a18483aSHarsha Priya N }
4682a18483aSHarsha Priya N }
4692a18483aSHarsha Priya N return ret;
4702a18483aSHarsha Priya N }
4712a18483aSHarsha Priya N
4722a18483aSHarsha Priya N static struct snd_soc_ops kabylake_ssp0_ops = {
4732a18483aSHarsha Priya N .hw_params = kabylake_ssp0_hw_params,
4742a18483aSHarsha Priya N };
4752a18483aSHarsha Priya N
4762a18483aSHarsha Priya N static const unsigned int channels_dmic[] = {
4772a18483aSHarsha Priya N 4,
4782a18483aSHarsha Priya N };
4792a18483aSHarsha Priya N
4802a18483aSHarsha Priya N static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
4812a18483aSHarsha Priya N .count = ARRAY_SIZE(channels_dmic),
4822a18483aSHarsha Priya N .list = channels_dmic,
4832a18483aSHarsha Priya N .mask = 0,
4842a18483aSHarsha Priya N };
4852a18483aSHarsha Priya N
4862a18483aSHarsha Priya N static const unsigned int dmic_2ch[] = {
487d6ba3f81STzung-Bi Shih 2,
4882a18483aSHarsha Priya N };
4892a18483aSHarsha Priya N
4902a18483aSHarsha Priya N static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = {
4912a18483aSHarsha Priya N .count = ARRAY_SIZE(dmic_2ch),
4922a18483aSHarsha Priya N .list = dmic_2ch,
4932a18483aSHarsha Priya N .mask = 0,
4942a18483aSHarsha Priya N };
4952a18483aSHarsha Priya N
kabylake_dmic_startup(struct snd_pcm_substream * substream)4962a18483aSHarsha Priya N static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
4972a18483aSHarsha Priya N {
4982a18483aSHarsha Priya N struct snd_pcm_runtime *runtime = substream->runtime;
4992a18483aSHarsha Priya N
5002a18483aSHarsha Priya N runtime->hw.channels_max = DMIC_CH(dmic_constraints);
5012a18483aSHarsha Priya N snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
5022a18483aSHarsha Priya N dmic_constraints);
5032a18483aSHarsha Priya N
504e2db787bSYu-Hsuan Hsu runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
505e2db787bSYu-Hsuan Hsu snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
506e2db787bSYu-Hsuan Hsu
5072a18483aSHarsha Priya N return snd_pcm_hw_constraint_list(substream->runtime, 0,
5082a18483aSHarsha Priya N SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
5092a18483aSHarsha Priya N }
5102a18483aSHarsha Priya N
5112a18483aSHarsha Priya N static struct snd_soc_ops kabylake_dmic_ops = {
5122a18483aSHarsha Priya N .startup = kabylake_dmic_startup,
5132a18483aSHarsha Priya N };
5142a18483aSHarsha Priya N
51542ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(dummy,
51642ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()));
51742ac21b9SKuninori Morimoto
51842ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(system,
51942ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("System Pin")));
52042ac21b9SKuninori Morimoto
52142ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(system2,
52242ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("System Pin2")));
52342ac21b9SKuninori Morimoto
52442ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(echoref,
52542ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin")));
52642ac21b9SKuninori Morimoto
52742ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(spi_cpu,
52842ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("spi-PRP0001:00")));
52942ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(spi_platform,
53042ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("spi-PRP0001:00")));
53142ac21b9SKuninori Morimoto
53242ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(dmic,
53342ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin")));
53442ac21b9SKuninori Morimoto
53542ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi1,
53642ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin")));
53742ac21b9SKuninori Morimoto
53842ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(hdmi2,
53942ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin")));
54042ac21b9SKuninori Morimoto
54142ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(ssp0_pin,
54242ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin")));
54342ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(ssp0_codec,
54442ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(
54542ac21b9SKuninori Morimoto /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, KBL_MAXIM_CODEC_DAI),
54642ac21b9SKuninori Morimoto /* Right */COMP_CODEC(MAXIM_DEV1_NAME, KBL_MAXIM_CODEC_DAI),
54742ac21b9SKuninori Morimoto /* dmic */ COMP_CODEC(RT5514_DEV_NAME, KBL_REALTEK_DMIC_CODEC_DAI)));
54842ac21b9SKuninori Morimoto
54942ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(ssp1_pin,
55042ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin")));
55142ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(ssp1_codec,
55242ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC(RT5663_DEV_NAME, KBL_REALTEK_CODEC_DAI)));
55342ac21b9SKuninori Morimoto
55442ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(idisp1_pin,
55542ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
55642ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(idisp1_codec,
55742ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
55842ac21b9SKuninori Morimoto
55942ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(idisp2_pin,
56042ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
56142ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(idisp2_codec,
56242ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
56342ac21b9SKuninori Morimoto
56442ac21b9SKuninori Morimoto SND_SOC_DAILINK_DEF(platform,
56542ac21b9SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
56642ac21b9SKuninori Morimoto
5672a18483aSHarsha Priya N /* kabylake digital audio interface glue - connects codec <--> CPU */
5682a18483aSHarsha Priya N static struct snd_soc_dai_link kabylake_dais[] = {
5692a18483aSHarsha Priya N /* Front End DAI links */
5702a18483aSHarsha Priya N [KBL_DPCM_AUDIO_PB] = {
5712a18483aSHarsha Priya N .name = "Kbl Audio Port",
5722a18483aSHarsha Priya N .stream_name = "Audio",
5732a18483aSHarsha Priya N .dynamic = 1,
5742a18483aSHarsha Priya N .nonatomic = 1,
5752a18483aSHarsha Priya N .init = kabylake_rt5663_fe_init,
5762a18483aSHarsha Priya N .trigger = {
5772a18483aSHarsha Priya N SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
5782a18483aSHarsha Priya N .dpcm_playback = 1,
5792a18483aSHarsha Priya N .ops = &kabylake_rt5663_fe_ops,
58042ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(system, dummy, platform),
5812a18483aSHarsha Priya N },
5822a18483aSHarsha Priya N [KBL_DPCM_AUDIO_CP] = {
5832a18483aSHarsha Priya N .name = "Kbl Audio Capture Port",
5842a18483aSHarsha Priya N .stream_name = "Audio Record",
5852a18483aSHarsha Priya N .dynamic = 1,
5862a18483aSHarsha Priya N .nonatomic = 1,
5872a18483aSHarsha Priya N .trigger = {
5882a18483aSHarsha Priya N SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
5892a18483aSHarsha Priya N .dpcm_capture = 1,
5902a18483aSHarsha Priya N .ops = &kabylake_rt5663_fe_ops,
59142ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(system, dummy, platform),
5922a18483aSHarsha Priya N },
593b32ee384SNaveen Manohar [KBL_DPCM_AUDIO_HS_PB] = {
594b32ee384SNaveen Manohar .name = "Kbl Audio Headset Playback",
595b32ee384SNaveen Manohar .stream_name = "Headset Audio",
596b32ee384SNaveen Manohar .dpcm_playback = 1,
597b32ee384SNaveen Manohar .nonatomic = 1,
598b32ee384SNaveen Manohar .dynamic = 1,
59942ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(system2, dummy, platform),
600b32ee384SNaveen Manohar },
601b32ee384SNaveen Manohar [KBL_DPCM_AUDIO_ECHO_REF_CP] = {
602b32ee384SNaveen Manohar .name = "Kbl Audio Echo Reference cap",
603b32ee384SNaveen Manohar .stream_name = "Echoreference Capture",
604b32ee384SNaveen Manohar .init = NULL,
605dc261875SPierre-Louis Bossart .dpcm_capture = 1,
606b32ee384SNaveen Manohar .nonatomic = 1,
60742ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(echoref, dummy, platform),
608b32ee384SNaveen Manohar },
609393a829bSHarsha Priya N [KBL_DPCM_AUDIO_RT5514_DSP] = {
610393a829bSHarsha Priya N .name = "rt5514 dsp",
611393a829bSHarsha Priya N .stream_name = "Wake on Voice",
61242ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(spi_cpu, dummy, spi_platform),
613393a829bSHarsha Priya N },
6142a18483aSHarsha Priya N [KBL_DPCM_AUDIO_DMIC_CP] = {
6152a18483aSHarsha Priya N .name = "Kbl Audio DMIC cap",
6162a18483aSHarsha Priya N .stream_name = "dmiccap",
6172a18483aSHarsha Priya N .init = NULL,
6182a18483aSHarsha Priya N .dpcm_capture = 1,
6192a18483aSHarsha Priya N .nonatomic = 1,
6202a18483aSHarsha Priya N .dynamic = 1,
6212a18483aSHarsha Priya N .ops = &kabylake_dmic_ops,
62242ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(dmic, dummy, platform),
6232a18483aSHarsha Priya N },
6242a18483aSHarsha Priya N [KBL_DPCM_AUDIO_HDMI1_PB] = {
6252a18483aSHarsha Priya N .name = "Kbl HDMI Port1",
6262a18483aSHarsha Priya N .stream_name = "Hdmi1",
6272a18483aSHarsha Priya N .dpcm_playback = 1,
6282a18483aSHarsha Priya N .init = NULL,
6292a18483aSHarsha Priya N .trigger = {
6302a18483aSHarsha Priya N SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
6312a18483aSHarsha Priya N .nonatomic = 1,
6322a18483aSHarsha Priya N .dynamic = 1,
63342ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(hdmi1, dummy, platform),
6342a18483aSHarsha Priya N },
6352a18483aSHarsha Priya N [KBL_DPCM_AUDIO_HDMI2_PB] = {
6362a18483aSHarsha Priya N .name = "Kbl HDMI Port2",
6372a18483aSHarsha Priya N .stream_name = "Hdmi2",
6382a18483aSHarsha Priya N .dpcm_playback = 1,
6392a18483aSHarsha Priya N .init = NULL,
6402a18483aSHarsha Priya N .trigger = {
6412a18483aSHarsha Priya N SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
6422a18483aSHarsha Priya N .nonatomic = 1,
6432a18483aSHarsha Priya N .dynamic = 1,
64442ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(hdmi2, dummy, platform),
6452a18483aSHarsha Priya N },
6462a18483aSHarsha Priya N /* Back End DAI links */
6472a18483aSHarsha Priya N /* single Back end dai for both max speakers and dmic */
6482a18483aSHarsha Priya N {
6492a18483aSHarsha Priya N /* SSP0 - Codec */
6502a18483aSHarsha Priya N .name = "SSP0-Codec",
6512a18483aSHarsha Priya N .id = 0,
6522a18483aSHarsha Priya N .no_pcm = 1,
6532a18483aSHarsha Priya N .dai_fmt = SND_SOC_DAIFMT_DSP_B |
6542a18483aSHarsha Priya N SND_SOC_DAIFMT_NB_NF |
6555374b921SPeter Ujfalusi SND_SOC_DAIFMT_CBC_CFC,
6562a18483aSHarsha Priya N .ignore_pmdown_time = 1,
6572a18483aSHarsha Priya N .be_hw_params_fixup = kabylake_ssp_fixup,
6582a18483aSHarsha Priya N .dpcm_playback = 1,
6592a18483aSHarsha Priya N .dpcm_capture = 1,
6602a18483aSHarsha Priya N .ops = &kabylake_ssp0_ops,
66142ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform),
6622a18483aSHarsha Priya N },
6632a18483aSHarsha Priya N {
6642a18483aSHarsha Priya N .name = "SSP1-Codec",
6652a18483aSHarsha Priya N .id = 1,
6662a18483aSHarsha Priya N .no_pcm = 1,
6672a18483aSHarsha Priya N .init = kabylake_rt5663_codec_init,
6682a18483aSHarsha Priya N .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
6695374b921SPeter Ujfalusi SND_SOC_DAIFMT_CBC_CFC,
6702a18483aSHarsha Priya N .ignore_pmdown_time = 1,
6712a18483aSHarsha Priya N .be_hw_params_fixup = kabylake_ssp_fixup,
6722a18483aSHarsha Priya N .ops = &kabylake_rt5663_ops,
6732a18483aSHarsha Priya N .dpcm_playback = 1,
6742a18483aSHarsha Priya N .dpcm_capture = 1,
67542ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform),
6762a18483aSHarsha Priya N },
6772a18483aSHarsha Priya N {
6782a18483aSHarsha Priya N .name = "iDisp1",
6792a18483aSHarsha Priya N .id = 3,
6802a18483aSHarsha Priya N .dpcm_playback = 1,
6812a18483aSHarsha Priya N .init = kabylake_hdmi1_init,
6822a18483aSHarsha Priya N .no_pcm = 1,
68342ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform),
6842a18483aSHarsha Priya N },
6852a18483aSHarsha Priya N {
6862a18483aSHarsha Priya N .name = "iDisp2",
6872a18483aSHarsha Priya N .id = 4,
6882a18483aSHarsha Priya N .init = kabylake_hdmi2_init,
6892a18483aSHarsha Priya N .dpcm_playback = 1,
6902a18483aSHarsha Priya N .no_pcm = 1,
69142ac21b9SKuninori Morimoto SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform),
6922a18483aSHarsha Priya N },
6932a18483aSHarsha Priya N };
6942a18483aSHarsha Priya N
kabylake_set_bias_level(struct snd_soc_card * card,struct snd_soc_dapm_context * dapm,enum snd_soc_bias_level level)69515747a80SBrent Lu static int kabylake_set_bias_level(struct snd_soc_card *card,
69615747a80SBrent Lu struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
69715747a80SBrent Lu {
69815747a80SBrent Lu struct snd_soc_component *component = dapm->component;
69915747a80SBrent Lu struct kbl_codec_private *priv = snd_soc_card_get_drvdata(card);
70015747a80SBrent Lu int ret = 0;
70115747a80SBrent Lu
70215747a80SBrent Lu if (!component || strcmp(component->name, RT5514_DEV_NAME))
70315747a80SBrent Lu return 0;
70415747a80SBrent Lu
70515747a80SBrent Lu if (IS_ERR(priv->mclk))
70615747a80SBrent Lu return 0;
70715747a80SBrent Lu
70815747a80SBrent Lu /*
70915747a80SBrent Lu * It's required to control mclk directly in the set_bias_level
71015747a80SBrent Lu * function for rt5514 codec or the recording function could
71115747a80SBrent Lu * break.
71215747a80SBrent Lu */
71315747a80SBrent Lu switch (level) {
71415747a80SBrent Lu case SND_SOC_BIAS_PREPARE:
71515747a80SBrent Lu if (dapm->bias_level == SND_SOC_BIAS_ON) {
716879ee8b6SGuenter Roeck if (!__clk_is_enabled(priv->mclk))
717879ee8b6SGuenter Roeck return 0;
71815747a80SBrent Lu dev_dbg(card->dev, "Disable mclk");
71915747a80SBrent Lu clk_disable_unprepare(priv->mclk);
72015747a80SBrent Lu } else {
72115747a80SBrent Lu dev_dbg(card->dev, "Enable mclk");
72215747a80SBrent Lu ret = clk_set_rate(priv->mclk, 24000000);
72315747a80SBrent Lu if (ret) {
72415747a80SBrent Lu dev_err(card->dev, "Can't set rate for mclk, err: %d\n",
72515747a80SBrent Lu ret);
72615747a80SBrent Lu return ret;
72715747a80SBrent Lu }
72815747a80SBrent Lu
72915747a80SBrent Lu ret = clk_prepare_enable(priv->mclk);
73015747a80SBrent Lu if (ret) {
73115747a80SBrent Lu dev_err(card->dev, "Can't enable mclk, err: %d\n",
73215747a80SBrent Lu ret);
73315747a80SBrent Lu
73415747a80SBrent Lu /* mclk is already enabled in FW */
73515747a80SBrent Lu ret = 0;
73615747a80SBrent Lu }
73715747a80SBrent Lu }
73815747a80SBrent Lu break;
73915747a80SBrent Lu default:
74015747a80SBrent Lu break;
74115747a80SBrent Lu }
74215747a80SBrent Lu
74315747a80SBrent Lu return ret;
74415747a80SBrent Lu }
74515747a80SBrent Lu
kabylake_card_late_probe(struct snd_soc_card * card)7462a18483aSHarsha Priya N static int kabylake_card_late_probe(struct snd_soc_card *card)
7472a18483aSHarsha Priya N {
7482a18483aSHarsha Priya N struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card);
7492a18483aSHarsha Priya N struct kbl_hdmi_pcm *pcm;
75045101122SKuninori Morimoto struct snd_soc_component *component = NULL;
7512a18483aSHarsha Priya N int err, i = 0;
7522a18483aSHarsha Priya N char jack_name[NAME_SIZE];
7532a18483aSHarsha Priya N
7542a18483aSHarsha Priya N list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
75545101122SKuninori Morimoto component = pcm->codec_dai->component;
756d1c4cb44SChintan Patel snprintf(jack_name, sizeof(jack_name),
757d1c4cb44SChintan Patel "HDMI/DP,pcm=%d Jack", pcm->device);
7582a18483aSHarsha Priya N err = snd_soc_card_jack_new(card, jack_name,
75919aed2d6SAkihiko Odaki SND_JACK_AVOUT, &ctx->kabylake_hdmi[i]);
7602a18483aSHarsha Priya N
7612a18483aSHarsha Priya N if (err)
7622a18483aSHarsha Priya N return err;
7632a18483aSHarsha Priya N err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
7642a18483aSHarsha Priya N &ctx->kabylake_hdmi[i]);
7652a18483aSHarsha Priya N if (err < 0)
7662a18483aSHarsha Priya N return err;
7672a18483aSHarsha Priya N i++;
7682a18483aSHarsha Priya N }
7692a18483aSHarsha Priya N
77045101122SKuninori Morimoto if (!component)
7713a13347fSNaveen M return -EINVAL;
7723a13347fSNaveen M
77345101122SKuninori Morimoto return hdac_hdmi_jack_port_init(component, &card->dapm);
7742a18483aSHarsha Priya N }
7752a18483aSHarsha Priya N
7762a18483aSHarsha Priya N /*
7772a18483aSHarsha Priya N * kabylake audio machine driver for MAX98927 + RT5514 + RT5663
7782a18483aSHarsha Priya N */
7792a18483aSHarsha Priya N static struct snd_soc_card kabylake_audio_card = {
780d745cc1aSJaroslav Kysela .name = "kbl-r5514-5663-max",
7812a18483aSHarsha Priya N .owner = THIS_MODULE,
7822a18483aSHarsha Priya N .dai_link = kabylake_dais,
7832a18483aSHarsha Priya N .num_links = ARRAY_SIZE(kabylake_dais),
78415747a80SBrent Lu .set_bias_level = kabylake_set_bias_level,
7852a18483aSHarsha Priya N .controls = kabylake_controls,
7862a18483aSHarsha Priya N .num_controls = ARRAY_SIZE(kabylake_controls),
7872a18483aSHarsha Priya N .dapm_widgets = kabylake_widgets,
7882a18483aSHarsha Priya N .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets),
7892a18483aSHarsha Priya N .dapm_routes = kabylake_map,
7902a18483aSHarsha Priya N .num_dapm_routes = ARRAY_SIZE(kabylake_map),
7912a18483aSHarsha Priya N .codec_conf = max98927_codec_conf,
7922a18483aSHarsha Priya N .num_configs = ARRAY_SIZE(max98927_codec_conf),
7932a18483aSHarsha Priya N .fully_routed = true,
794*48f3fe13SCezary Rojewski .disable_route_checks = true,
7952a18483aSHarsha Priya N .late_probe = kabylake_card_late_probe,
7962a18483aSHarsha Priya N };
7972a18483aSHarsha Priya N
kabylake_audio_probe(struct platform_device * pdev)7982a18483aSHarsha Priya N static int kabylake_audio_probe(struct platform_device *pdev)
7992a18483aSHarsha Priya N {
8002a18483aSHarsha Priya N struct kbl_codec_private *ctx;
801b92826faSPierre-Louis Bossart struct snd_soc_acpi_mach *mach;
80238e58021SPierre-Louis Bossart int ret;
8032a18483aSHarsha Priya N
80446c33133SVinod Koul ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
8052a18483aSHarsha Priya N if (!ctx)
8062a18483aSHarsha Priya N return -ENOMEM;
8072a18483aSHarsha Priya N
8082a18483aSHarsha Priya N INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
8092a18483aSHarsha Priya N
8102a18483aSHarsha Priya N kabylake_audio_card.dev = &pdev->dev;
8112a18483aSHarsha Priya N snd_soc_card_set_drvdata(&kabylake_audio_card, ctx);
8122a18483aSHarsha Priya N
81342432196SGuennadi Liakhovetski mach = pdev->dev.platform_data;
814b92826faSPierre-Louis Bossart if (mach)
815b92826faSPierre-Louis Bossart dmic_constraints = mach->mach_params.dmic_num == 2 ?
8162a18483aSHarsha Priya N &constraints_dmic_2ch : &constraints_dmic_channels;
8172a18483aSHarsha Priya N
81847cbea21SNaveen M ctx->mclk = devm_clk_get(&pdev->dev, "ssp1_mclk");
81947cbea21SNaveen M if (IS_ERR(ctx->mclk)) {
82047cbea21SNaveen M ret = PTR_ERR(ctx->mclk);
82147cbea21SNaveen M if (ret == -ENOENT) {
82247cbea21SNaveen M dev_info(&pdev->dev,
82347cbea21SNaveen M "Failed to get ssp1_mclk, defer probe\n");
82447cbea21SNaveen M return -EPROBE_DEFER;
82547cbea21SNaveen M }
82647cbea21SNaveen M
82747cbea21SNaveen M dev_err(&pdev->dev, "Failed to get ssp1_mclk with err:%d\n",
82847cbea21SNaveen M ret);
82947cbea21SNaveen M return ret;
83047cbea21SNaveen M }
83147cbea21SNaveen M
83247cbea21SNaveen M ctx->sclk = devm_clk_get(&pdev->dev, "ssp1_sclk");
83347cbea21SNaveen M if (IS_ERR(ctx->sclk)) {
83447cbea21SNaveen M ret = PTR_ERR(ctx->sclk);
83547cbea21SNaveen M if (ret == -ENOENT) {
83647cbea21SNaveen M dev_info(&pdev->dev,
83747cbea21SNaveen M "Failed to get ssp1_sclk, defer probe\n");
83847cbea21SNaveen M return -EPROBE_DEFER;
83947cbea21SNaveen M }
84047cbea21SNaveen M
84147cbea21SNaveen M dev_err(&pdev->dev, "Failed to get ssp1_sclk with err:%d\n",
84247cbea21SNaveen M ret);
84347cbea21SNaveen M return ret;
84447cbea21SNaveen M }
84547cbea21SNaveen M
8462a18483aSHarsha Priya N return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card);
8472a18483aSHarsha Priya N }
8482a18483aSHarsha Priya N
8492a18483aSHarsha Priya N static const struct platform_device_id kbl_board_ids[] = {
8502a18483aSHarsha Priya N { .name = "kbl_r5514_5663_max" },
8512a18483aSHarsha Priya N { }
8522a18483aSHarsha Priya N };
85353b98536SPierre-Louis Bossart MODULE_DEVICE_TABLE(platform, kbl_board_ids);
8542a18483aSHarsha Priya N
8552a18483aSHarsha Priya N static struct platform_driver kabylake_audio = {
8562a18483aSHarsha Priya N .probe = kabylake_audio_probe,
8572a18483aSHarsha Priya N .driver = {
8582a18483aSHarsha Priya N .name = "kbl_r5514_5663_max",
8592a18483aSHarsha Priya N .pm = &snd_soc_pm_ops,
8602a18483aSHarsha Priya N },
8612a18483aSHarsha Priya N .id_table = kbl_board_ids,
8622a18483aSHarsha Priya N };
8632a18483aSHarsha Priya N
8642a18483aSHarsha Priya N module_platform_driver(kabylake_audio)
8652a18483aSHarsha Priya N
8662a18483aSHarsha Priya N /* Module information */
8672a18483aSHarsha Priya N MODULE_DESCRIPTION("Audio Machine driver-RT5663 RT5514 & MAX98927");
8682a18483aSHarsha Priya N MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
8692a18483aSHarsha Priya N MODULE_LICENSE("GPL v2");
870