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