xref: /openbmc/linux/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c (revision b181f7029bd71238ac2754ce7052dffd69432085)
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