18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright 2017 Advanced Micro Devices, Inc.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci */
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include <sound/core.h>
278c2ecf20Sopenharmony_ci#include <sound/soc.h>
288c2ecf20Sopenharmony_ci#include <sound/pcm.h>
298c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
308c2ecf20Sopenharmony_ci#include <sound/soc-dapm.h>
318c2ecf20Sopenharmony_ci#include <sound/jack.h>
328c2ecf20Sopenharmony_ci#include <linux/clk.h>
338c2ecf20Sopenharmony_ci#include <linux/gpio.h>
348c2ecf20Sopenharmony_ci#include <linux/module.h>
358c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h>
368c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h>
378c2ecf20Sopenharmony_ci#include <linux/i2c.h>
388c2ecf20Sopenharmony_ci#include <linux/input.h>
398c2ecf20Sopenharmony_ci#include <linux/acpi.h>
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#include "acp.h"
428c2ecf20Sopenharmony_ci#include "../codecs/da7219.h"
438c2ecf20Sopenharmony_ci#include "../codecs/da7219-aad.h"
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define CZ_PLAT_CLK 48000000
468c2ecf20Sopenharmony_ci#define DUAL_CHANNEL		2
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic struct snd_soc_jack cz_jack;
498c2ecf20Sopenharmony_cistatic struct clk *da7219_dai_wclk;
508c2ecf20Sopenharmony_cistatic struct clk *da7219_dai_bclk;
518c2ecf20Sopenharmony_ciextern bool bt_uart_enable;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	int ret;
568c2ecf20Sopenharmony_ci	struct snd_soc_card *card = rtd->card;
578c2ecf20Sopenharmony_ci	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
588c2ecf20Sopenharmony_ci	struct snd_soc_component *component = codec_dai->component;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK,
638c2ecf20Sopenharmony_ci				     CZ_PLAT_CLK, SND_SOC_CLOCK_IN);
648c2ecf20Sopenharmony_ci	if (ret < 0) {
658c2ecf20Sopenharmony_ci		dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret);
668c2ecf20Sopenharmony_ci		return ret;
678c2ecf20Sopenharmony_ci	}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL,
708c2ecf20Sopenharmony_ci				  CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304);
718c2ecf20Sopenharmony_ci	if (ret < 0) {
728c2ecf20Sopenharmony_ci		dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
738c2ecf20Sopenharmony_ci		return ret;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	da7219_dai_wclk = devm_clk_get(component->dev, "da7219-dai-wclk");
778c2ecf20Sopenharmony_ci	if (IS_ERR(da7219_dai_wclk))
788c2ecf20Sopenharmony_ci		return PTR_ERR(da7219_dai_wclk);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	da7219_dai_bclk = devm_clk_get(component->dev, "da7219-dai-bclk");
818c2ecf20Sopenharmony_ci	if (IS_ERR(da7219_dai_bclk))
828c2ecf20Sopenharmony_ci		return PTR_ERR(da7219_dai_bclk);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	ret = snd_soc_card_jack_new(card, "Headset Jack",
858c2ecf20Sopenharmony_ci				SND_JACK_HEADSET | SND_JACK_LINEOUT |
868c2ecf20Sopenharmony_ci				SND_JACK_BTN_0 | SND_JACK_BTN_1 |
878c2ecf20Sopenharmony_ci				SND_JACK_BTN_2 | SND_JACK_BTN_3,
888c2ecf20Sopenharmony_ci				&cz_jack, NULL, 0);
898c2ecf20Sopenharmony_ci	if (ret) {
908c2ecf20Sopenharmony_ci		dev_err(card->dev, "HP jack creation failed %d\n", ret);
918c2ecf20Sopenharmony_ci		return ret;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
958c2ecf20Sopenharmony_ci	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
968c2ecf20Sopenharmony_ci	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
978c2ecf20Sopenharmony_ci	snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	da7219_aad_jack_det(component, &cz_jack);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	return 0;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic int da7219_clk_enable(struct snd_pcm_substream *substream)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	int ret = 0;
1078c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	/*
1108c2ecf20Sopenharmony_ci	 * Set wclk to 48000 because the rate constraint of this driver is
1118c2ecf20Sopenharmony_ci	 * 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is
1128c2ecf20Sopenharmony_ci	 * minimum of 64x the LRCLK sample rate." DA7219 is the only clk
1138c2ecf20Sopenharmony_ci	 * source so for all codecs we have to limit bclk to 64X lrclk.
1148c2ecf20Sopenharmony_ci	 */
1158c2ecf20Sopenharmony_ci	clk_set_rate(da7219_dai_wclk, 48000);
1168c2ecf20Sopenharmony_ci	clk_set_rate(da7219_dai_bclk, 48000 * 64);
1178c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(da7219_dai_bclk);
1188c2ecf20Sopenharmony_ci	if (ret < 0) {
1198c2ecf20Sopenharmony_ci		dev_err(rtd->dev, "can't enable master clock %d\n", ret);
1208c2ecf20Sopenharmony_ci		return ret;
1218c2ecf20Sopenharmony_ci	}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	return ret;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic void da7219_clk_disable(void)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	clk_disable_unprepare(da7219_dai_bclk);
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic const unsigned int channels[] = {
1328c2ecf20Sopenharmony_ci	DUAL_CHANNEL,
1338c2ecf20Sopenharmony_ci};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic const unsigned int rates[] = {
1368c2ecf20Sopenharmony_ci	48000,
1378c2ecf20Sopenharmony_ci};
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list constraints_rates = {
1408c2ecf20Sopenharmony_ci	.count = ARRAY_SIZE(rates),
1418c2ecf20Sopenharmony_ci	.list  = rates,
1428c2ecf20Sopenharmony_ci	.mask = 0,
1438c2ecf20Sopenharmony_ci};
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list constraints_channels = {
1468c2ecf20Sopenharmony_ci	.count = ARRAY_SIZE(channels),
1478c2ecf20Sopenharmony_ci	.list = channels,
1488c2ecf20Sopenharmony_ci	.mask = 0,
1498c2ecf20Sopenharmony_ci};
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistatic int cz_da7219_play_startup(struct snd_pcm_substream *substream)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
1548c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1558c2ecf20Sopenharmony_ci	struct snd_soc_card *card = rtd->card;
1568c2ecf20Sopenharmony_ci	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	/*
1598c2ecf20Sopenharmony_ci	 * On this platform for PCM device we support stereo
1608c2ecf20Sopenharmony_ci	 */
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	runtime->hw.channels_max = DUAL_CHANNEL;
1638c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
1648c2ecf20Sopenharmony_ci				   &constraints_channels);
1658c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1668c2ecf20Sopenharmony_ci				   &constraints_rates);
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	machine->play_i2s_instance = I2S_SP_INSTANCE;
1698c2ecf20Sopenharmony_ci	return da7219_clk_enable(substream);
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_cistatic int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
1758c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1768c2ecf20Sopenharmony_ci	struct snd_soc_card *card = rtd->card;
1778c2ecf20Sopenharmony_ci	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	/*
1808c2ecf20Sopenharmony_ci	 * On this platform for PCM device we support stereo
1818c2ecf20Sopenharmony_ci	 */
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	runtime->hw.channels_max = DUAL_CHANNEL;
1848c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
1858c2ecf20Sopenharmony_ci				   &constraints_channels);
1868c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1878c2ecf20Sopenharmony_ci				   &constraints_rates);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	machine->cap_i2s_instance = I2S_SP_INSTANCE;
1908c2ecf20Sopenharmony_ci	machine->capture_channel = CAP_CHANNEL1;
1918c2ecf20Sopenharmony_ci	return da7219_clk_enable(substream);
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic int cz_max_startup(struct snd_pcm_substream *substream)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
1978c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1988c2ecf20Sopenharmony_ci	struct snd_soc_card *card = rtd->card;
1998c2ecf20Sopenharmony_ci	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	/*
2028c2ecf20Sopenharmony_ci	 * On this platform for PCM device we support stereo
2038c2ecf20Sopenharmony_ci	 */
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	runtime->hw.channels_max = DUAL_CHANNEL;
2068c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
2078c2ecf20Sopenharmony_ci				   &constraints_channels);
2088c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
2098c2ecf20Sopenharmony_ci				   &constraints_rates);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	machine->play_i2s_instance = I2S_BT_INSTANCE;
2128c2ecf20Sopenharmony_ci	return da7219_clk_enable(substream);
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistatic int cz_dmic0_startup(struct snd_pcm_substream *substream)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
2188c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
2198c2ecf20Sopenharmony_ci	struct snd_soc_card *card = rtd->card;
2208c2ecf20Sopenharmony_ci	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	/*
2238c2ecf20Sopenharmony_ci	 * On this platform for PCM device we support stereo
2248c2ecf20Sopenharmony_ci	 */
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	runtime->hw.channels_max = DUAL_CHANNEL;
2278c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
2288c2ecf20Sopenharmony_ci				   &constraints_channels);
2298c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
2308c2ecf20Sopenharmony_ci				   &constraints_rates);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	machine->cap_i2s_instance = I2S_BT_INSTANCE;
2338c2ecf20Sopenharmony_ci	return da7219_clk_enable(substream);
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic int cz_dmic1_startup(struct snd_pcm_substream *substream)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
2398c2ecf20Sopenharmony_ci	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
2408c2ecf20Sopenharmony_ci	struct snd_soc_card *card = rtd->card;
2418c2ecf20Sopenharmony_ci	struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	/*
2448c2ecf20Sopenharmony_ci	 * On this platform for PCM device we support stereo
2458c2ecf20Sopenharmony_ci	 */
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	runtime->hw.channels_max = DUAL_CHANNEL;
2488c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
2498c2ecf20Sopenharmony_ci				   &constraints_channels);
2508c2ecf20Sopenharmony_ci	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
2518c2ecf20Sopenharmony_ci				   &constraints_rates);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	machine->cap_i2s_instance = I2S_SP_INSTANCE;
2548c2ecf20Sopenharmony_ci	machine->capture_channel = CAP_CHANNEL0;
2558c2ecf20Sopenharmony_ci	return da7219_clk_enable(substream);
2568c2ecf20Sopenharmony_ci}
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_cistatic void cz_da7219_shutdown(struct snd_pcm_substream *substream)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	da7219_clk_disable();
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_cistatic const struct snd_soc_ops cz_da7219_play_ops = {
2648c2ecf20Sopenharmony_ci	.startup = cz_da7219_play_startup,
2658c2ecf20Sopenharmony_ci	.shutdown = cz_da7219_shutdown,
2668c2ecf20Sopenharmony_ci};
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic const struct snd_soc_ops cz_da7219_cap_ops = {
2698c2ecf20Sopenharmony_ci	.startup = cz_da7219_cap_startup,
2708c2ecf20Sopenharmony_ci	.shutdown = cz_da7219_shutdown,
2718c2ecf20Sopenharmony_ci};
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic const struct snd_soc_ops cz_max_play_ops = {
2748c2ecf20Sopenharmony_ci	.startup = cz_max_startup,
2758c2ecf20Sopenharmony_ci	.shutdown = cz_da7219_shutdown,
2768c2ecf20Sopenharmony_ci};
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_cistatic const struct snd_soc_ops cz_dmic0_cap_ops = {
2798c2ecf20Sopenharmony_ci	.startup = cz_dmic0_startup,
2808c2ecf20Sopenharmony_ci	.shutdown = cz_da7219_shutdown,
2818c2ecf20Sopenharmony_ci};
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_cistatic const struct snd_soc_ops cz_dmic1_cap_ops = {
2848c2ecf20Sopenharmony_ci	.startup = cz_dmic1_startup,
2858c2ecf20Sopenharmony_ci	.shutdown = cz_da7219_shutdown,
2868c2ecf20Sopenharmony_ci};
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(designware1,
2898c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto")));
2908c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(designware2,
2918c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto")));
2928c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(designware3,
2938c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.3.auto")));
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(dlgs,
2968c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", "da7219-hifi")));
2978c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(mx,
2988c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi")));
2998c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(adau,
3008c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_CODEC("ADAU7002:00", "adau7002-hifi")));
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEF(platform,
3038c2ecf20Sopenharmony_ci	DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0.auto")));
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic struct snd_soc_dai_link cz_dai_7219_98357[] = {
3068c2ecf20Sopenharmony_ci	{
3078c2ecf20Sopenharmony_ci		.name = "amd-da7219-play",
3088c2ecf20Sopenharmony_ci		.stream_name = "Playback",
3098c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3108c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3118c2ecf20Sopenharmony_ci		.init = cz_da7219_init,
3128c2ecf20Sopenharmony_ci		.dpcm_playback = 1,
3138c2ecf20Sopenharmony_ci		.ops = &cz_da7219_play_ops,
3148c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(designware1, dlgs, platform),
3158c2ecf20Sopenharmony_ci	},
3168c2ecf20Sopenharmony_ci	{
3178c2ecf20Sopenharmony_ci		.name = "amd-da7219-cap",
3188c2ecf20Sopenharmony_ci		.stream_name = "Capture",
3198c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3208c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3218c2ecf20Sopenharmony_ci		.dpcm_capture = 1,
3228c2ecf20Sopenharmony_ci		.ops = &cz_da7219_cap_ops,
3238c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(designware2, dlgs, platform),
3248c2ecf20Sopenharmony_ci	},
3258c2ecf20Sopenharmony_ci	{
3268c2ecf20Sopenharmony_ci		.name = "amd-max98357-play",
3278c2ecf20Sopenharmony_ci		.stream_name = "HiFi Playback",
3288c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3298c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3308c2ecf20Sopenharmony_ci		.dpcm_playback = 1,
3318c2ecf20Sopenharmony_ci		.ops = &cz_max_play_ops,
3328c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(designware3, mx, platform),
3338c2ecf20Sopenharmony_ci	},
3348c2ecf20Sopenharmony_ci	{
3358c2ecf20Sopenharmony_ci		/* C panel DMIC */
3368c2ecf20Sopenharmony_ci		.name = "dmic0",
3378c2ecf20Sopenharmony_ci		.stream_name = "DMIC0 Capture",
3388c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3398c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3408c2ecf20Sopenharmony_ci		.dpcm_capture = 1,
3418c2ecf20Sopenharmony_ci		.ops = &cz_dmic0_cap_ops,
3428c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(designware3, adau, platform),
3438c2ecf20Sopenharmony_ci	},
3448c2ecf20Sopenharmony_ci	{
3458c2ecf20Sopenharmony_ci		/* A/B panel DMIC */
3468c2ecf20Sopenharmony_ci		.name = "dmic1",
3478c2ecf20Sopenharmony_ci		.stream_name = "DMIC1 Capture",
3488c2ecf20Sopenharmony_ci		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
3498c2ecf20Sopenharmony_ci				| SND_SOC_DAIFMT_CBM_CFM,
3508c2ecf20Sopenharmony_ci		.dpcm_capture = 1,
3518c2ecf20Sopenharmony_ci		.ops = &cz_dmic1_cap_ops,
3528c2ecf20Sopenharmony_ci		SND_SOC_DAILINK_REG(designware2, adau, platform),
3538c2ecf20Sopenharmony_ci	},
3548c2ecf20Sopenharmony_ci};
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget cz_widgets[] = {
3578c2ecf20Sopenharmony_ci	SND_SOC_DAPM_HP("Headphones", NULL),
3588c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SPK("Speakers", NULL),
3598c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MIC("Headset Mic", NULL),
3608c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MIC("Int Mic", NULL),
3618c2ecf20Sopenharmony_ci};
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route cz_audio_route[] = {
3648c2ecf20Sopenharmony_ci	{"Headphones", NULL, "HPL"},
3658c2ecf20Sopenharmony_ci	{"Headphones", NULL, "HPR"},
3668c2ecf20Sopenharmony_ci	{"MIC", NULL, "Headset Mic"},
3678c2ecf20Sopenharmony_ci	{"Speakers", NULL, "Speaker"},
3688c2ecf20Sopenharmony_ci	{"PDM_DAT", NULL, "Int Mic"},
3698c2ecf20Sopenharmony_ci};
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new cz_mc_controls[] = {
3728c2ecf20Sopenharmony_ci	SOC_DAPM_PIN_SWITCH("Headphones"),
3738c2ecf20Sopenharmony_ci	SOC_DAPM_PIN_SWITCH("Speakers"),
3748c2ecf20Sopenharmony_ci	SOC_DAPM_PIN_SWITCH("Headset Mic"),
3758c2ecf20Sopenharmony_ci	SOC_DAPM_PIN_SWITCH("Int Mic"),
3768c2ecf20Sopenharmony_ci};
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_cistatic struct snd_soc_card cz_card = {
3798c2ecf20Sopenharmony_ci	.name = "acpd7219m98357",
3808c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
3818c2ecf20Sopenharmony_ci	.dai_link = cz_dai_7219_98357,
3828c2ecf20Sopenharmony_ci	.num_links = ARRAY_SIZE(cz_dai_7219_98357),
3838c2ecf20Sopenharmony_ci	.dapm_widgets = cz_widgets,
3848c2ecf20Sopenharmony_ci	.num_dapm_widgets = ARRAY_SIZE(cz_widgets),
3858c2ecf20Sopenharmony_ci	.dapm_routes = cz_audio_route,
3868c2ecf20Sopenharmony_ci	.num_dapm_routes = ARRAY_SIZE(cz_audio_route),
3878c2ecf20Sopenharmony_ci	.controls = cz_mc_controls,
3888c2ecf20Sopenharmony_ci	.num_controls = ARRAY_SIZE(cz_mc_controls),
3898c2ecf20Sopenharmony_ci};
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_cistatic struct regulator_consumer_supply acp_da7219_supplies[] = {
3928c2ecf20Sopenharmony_ci	REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
3938c2ecf20Sopenharmony_ci	REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
3948c2ecf20Sopenharmony_ci	REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
3958c2ecf20Sopenharmony_ci	REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
3968c2ecf20Sopenharmony_ci};
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic struct regulator_init_data acp_da7219_data = {
3998c2ecf20Sopenharmony_ci	.constraints = {
4008c2ecf20Sopenharmony_ci		.always_on = 1,
4018c2ecf20Sopenharmony_ci	},
4028c2ecf20Sopenharmony_ci	.num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
4038c2ecf20Sopenharmony_ci	.consumer_supplies = acp_da7219_supplies,
4048c2ecf20Sopenharmony_ci};
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cistatic struct regulator_config acp_da7219_cfg = {
4078c2ecf20Sopenharmony_ci	.init_data = &acp_da7219_data,
4088c2ecf20Sopenharmony_ci};
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic struct regulator_ops acp_da7219_ops = {
4118c2ecf20Sopenharmony_ci};
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic const struct regulator_desc acp_da7219_desc = {
4148c2ecf20Sopenharmony_ci	.name = "reg-fixed-1.8V",
4158c2ecf20Sopenharmony_ci	.type = REGULATOR_VOLTAGE,
4168c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
4178c2ecf20Sopenharmony_ci	.ops = &acp_da7219_ops,
4188c2ecf20Sopenharmony_ci	.fixed_uV = 1800000, /* 1.8V */
4198c2ecf20Sopenharmony_ci	.n_voltages = 1,
4208c2ecf20Sopenharmony_ci};
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_cistatic int cz_probe(struct platform_device *pdev)
4238c2ecf20Sopenharmony_ci{
4248c2ecf20Sopenharmony_ci	int ret;
4258c2ecf20Sopenharmony_ci	struct snd_soc_card *card;
4268c2ecf20Sopenharmony_ci	struct acp_platform_info *machine;
4278c2ecf20Sopenharmony_ci	struct regulator_dev *rdev;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	acp_da7219_cfg.dev = &pdev->dev;
4308c2ecf20Sopenharmony_ci	rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc,
4318c2ecf20Sopenharmony_ci				       &acp_da7219_cfg);
4328c2ecf20Sopenharmony_ci	if (IS_ERR(rdev)) {
4338c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to register regulator: %d\n",
4348c2ecf20Sopenharmony_ci			(int)PTR_ERR(rdev));
4358c2ecf20Sopenharmony_ci		return -EINVAL;
4368c2ecf20Sopenharmony_ci	}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info),
4398c2ecf20Sopenharmony_ci			       GFP_KERNEL);
4408c2ecf20Sopenharmony_ci	if (!machine)
4418c2ecf20Sopenharmony_ci		return -ENOMEM;
4428c2ecf20Sopenharmony_ci	card = &cz_card;
4438c2ecf20Sopenharmony_ci	cz_card.dev = &pdev->dev;
4448c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, card);
4458c2ecf20Sopenharmony_ci	snd_soc_card_set_drvdata(card, machine);
4468c2ecf20Sopenharmony_ci	ret = devm_snd_soc_register_card(&pdev->dev, &cz_card);
4478c2ecf20Sopenharmony_ci	if (ret) {
4488c2ecf20Sopenharmony_ci		dev_err(&pdev->dev,
4498c2ecf20Sopenharmony_ci				"devm_snd_soc_register_card(%s) failed: %d\n",
4508c2ecf20Sopenharmony_ci				cz_card.name, ret);
4518c2ecf20Sopenharmony_ci		return ret;
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci	bt_uart_enable = !device_property_read_bool(&pdev->dev,
4548c2ecf20Sopenharmony_ci						    "bt-pad-enable");
4558c2ecf20Sopenharmony_ci	return 0;
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
4598c2ecf20Sopenharmony_cistatic const struct acpi_device_id cz_audio_acpi_match[] = {
4608c2ecf20Sopenharmony_ci	{ "AMD7219", 0 },
4618c2ecf20Sopenharmony_ci	{},
4628c2ecf20Sopenharmony_ci};
4638c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match);
4648c2ecf20Sopenharmony_ci#endif
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_cistatic struct platform_driver cz_pcm_driver = {
4678c2ecf20Sopenharmony_ci	.driver = {
4688c2ecf20Sopenharmony_ci		.name = "cz-da7219-max98357a",
4698c2ecf20Sopenharmony_ci		.acpi_match_table = ACPI_PTR(cz_audio_acpi_match),
4708c2ecf20Sopenharmony_ci		.pm = &snd_soc_pm_ops,
4718c2ecf20Sopenharmony_ci	},
4728c2ecf20Sopenharmony_ci	.probe = cz_probe,
4738c2ecf20Sopenharmony_ci};
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_cimodule_platform_driver(cz_pcm_driver);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ciMODULE_AUTHOR("akshu.agrawal@amd.com");
4788c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DA7219 & MAX98357A audio support");
4798c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
480