1790 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)2//3// This file is provided under a dual BSD/GPLv2 license. When using or4// redistributing this file, you may do so under either license.5//6// Copyright(c) 2021, 2023 Advanced Micro Devices, Inc.7//8// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>9// Vijendar Mukunda <Vijendar.Mukunda@amd.com>10//11 12/*13 * Machine Driver Interface for ACP HW block14 */15 16#include <sound/core.h>17#include <sound/jack.h>18#include <sound/pcm_params.h>19#include <sound/soc-dapm.h>20#include <sound/soc.h>21#include <linux/input.h>22#include <linux/module.h>23 24#include "../../codecs/rt5682.h"25#include "../../codecs/rt1019.h"26#include "../../codecs/rt5682s.h"27#include "../../codecs/nau8825.h"28#include "../../codecs/nau8821.h"29#include "acp-mach.h"30 31#define PCO_PLAT_CLK 4800000032#define RT5682_PLL_FREQ (48000 * 512)33#define DUAL_CHANNEL 234#define FOUR_CHANNEL 435#define NAU8821_CODEC_DAI "nau8821-hifi"36#define NAU8821_BCLK 153600037#define NAU8821_FREQ_OUT 1228800038#define MAX98388_CODEC_DAI "max98388-aif1"39 40#define TDM_MODE_ENABLE 141 42const struct dmi_system_id acp_quirk_table[] = {43 {44 /* Google skyrim proto-0 */45 .matches = {46 DMI_EXACT_MATCH(DMI_PRODUCT_FAMILY, "Google_Skyrim"),47 },48 .driver_data = (void *)TDM_MODE_ENABLE,49 },50 {}51};52EXPORT_SYMBOL_GPL(acp_quirk_table);53 54static const unsigned int channels[] = {55 DUAL_CHANNEL,56};57 58static const unsigned int rates[] = {59 48000,60};61 62static const struct snd_pcm_hw_constraint_list constraints_rates = {63 .count = ARRAY_SIZE(rates),64 .list = rates,65 .mask = 0,66};67 68static const struct snd_pcm_hw_constraint_list constraints_channels = {69 .count = ARRAY_SIZE(channels),70 .list = channels,71 .mask = 0,72};73 74static int acp_clk_enable(struct acp_card_drvdata *drvdata,75 unsigned int srate, unsigned int bclk_ratio)76{77 clk_set_rate(drvdata->wclk, srate);78 clk_set_rate(drvdata->bclk, srate * bclk_ratio);79 80 return clk_prepare_enable(drvdata->wclk);81}82 83/* Declare RT5682 codec components */84SND_SOC_DAILINK_DEF(rt5682,85 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));86 87static struct snd_soc_jack rt5682_jack;88static struct snd_soc_jack_pin rt5682_jack_pins[] = {89 {90 .pin = "Headphone Jack",91 .mask = SND_JACK_HEADPHONE,92 },93 {94 .pin = "Headset Mic",95 .mask = SND_JACK_MICROPHONE,96 },97};98 99static const struct snd_kcontrol_new rt5682_controls[] = {100 SOC_DAPM_PIN_SWITCH("Headphone Jack"),101 SOC_DAPM_PIN_SWITCH("Headset Mic"),102};103 104static const struct snd_soc_dapm_widget rt5682_widgets[] = {105 SND_SOC_DAPM_HP("Headphone Jack", NULL),106 SND_SOC_DAPM_MIC("Headset Mic", NULL),107};108 109static const struct snd_soc_dapm_route rt5682_map[] = {110 { "Headphone Jack", NULL, "HPOL" },111 { "Headphone Jack", NULL, "HPOR" },112 { "IN1P", NULL, "Headset Mic" },113};114 115/* Define card ops for RT5682 CODEC */116static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)117{118 struct snd_soc_card *card = rtd->card;119 struct acp_card_drvdata *drvdata = card->drvdata;120 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);121 struct snd_soc_component *component = codec_dai->component;122 int ret;123 124 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);125 126 if (drvdata->hs_codec_id != RT5682)127 return -EINVAL;128 129 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");130 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");131 132 ret = snd_soc_dapm_new_controls(&card->dapm, rt5682_widgets,133 ARRAY_SIZE(rt5682_widgets));134 if (ret) {135 dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);136 return ret;137 }138 139 ret = snd_soc_add_card_controls(card, rt5682_controls,140 ARRAY_SIZE(rt5682_controls));141 if (ret) {142 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);143 return ret;144 }145 146 ret = snd_soc_card_jack_new_pins(card, "Headset Jack",147 SND_JACK_HEADSET | SND_JACK_LINEOUT |148 SND_JACK_BTN_0 | SND_JACK_BTN_1 |149 SND_JACK_BTN_2 | SND_JACK_BTN_3,150 &rt5682_jack,151 rt5682_jack_pins,152 ARRAY_SIZE(rt5682_jack_pins));153 if (ret) {154 dev_err(card->dev, "HP jack creation failed %d\n", ret);155 return ret;156 }157 158 snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);159 snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);160 snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);161 snd_jack_set_key(rt5682_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);162 163 ret = snd_soc_component_set_jack(component, &rt5682_jack, NULL);164 if (ret) {165 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);166 return ret;167 }168 169 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));170}171 172static int acp_card_hs_startup(struct snd_pcm_substream *substream)173{174 struct snd_pcm_runtime *runtime = substream->runtime;175 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);176 struct snd_soc_card *card = rtd->card;177 struct acp_card_drvdata *drvdata = card->drvdata;178 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);179 int ret;180 unsigned int fmt;181 182 if (drvdata->tdm_mode)183 fmt = SND_SOC_DAIFMT_DSP_A;184 else185 fmt = SND_SOC_DAIFMT_I2S;186 187 if (drvdata->soc_mclk)188 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;189 else190 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;191 192 ret = snd_soc_dai_set_fmt(codec_dai, fmt);193 if (ret < 0) {194 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);195 return ret;196 }197 198 runtime->hw.channels_max = DUAL_CHANNEL;199 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,200 &constraints_channels);201 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,202 &constraints_rates);203 204 return ret;205}206 207static void acp_card_shutdown(struct snd_pcm_substream *substream)208{209 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);210 struct snd_soc_card *card = rtd->card;211 struct acp_card_drvdata *drvdata = card->drvdata;212 213 if (!drvdata->soc_mclk)214 clk_disable_unprepare(drvdata->wclk);215}216 217static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream,218 struct snd_pcm_hw_params *params)219{220 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);221 struct snd_soc_card *card = rtd->card;222 struct acp_card_drvdata *drvdata = card->drvdata;223 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);224 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);225 int ret;226 unsigned int fmt, srate, ch, format;227 228 srate = params_rate(params);229 ch = params_channels(params);230 format = params_physical_width(params);231 232 if (drvdata->tdm_mode)233 fmt = SND_SOC_DAIFMT_DSP_A;234 else235 fmt = SND_SOC_DAIFMT_I2S;236 237 if (drvdata->soc_mclk)238 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;239 else240 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;241 242 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);243 if (ret && ret != -ENOTSUPP) {244 dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);245 return ret;246 }247 248 ret = snd_soc_dai_set_fmt(codec_dai, fmt);249 if (ret < 0) {250 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);251 return ret;252 }253 254 if (drvdata->tdm_mode) {255 /**256 * As codec supports slot 0 and slot 1 for playback and capture.257 */258 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 8, 16);259 if (ret && ret != -ENOTSUPP) {260 dev_err(rtd->dev, "set TDM slot err: %d\n", ret);261 return ret;262 }263 264 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 8, 16);265 if (ret < 0) {266 dev_warn(rtd->dev, "set TDM slot err:%d\n", ret);267 return ret;268 }269 }270 271 ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,272 PCO_PLAT_CLK, RT5682_PLL_FREQ);273 if (ret < 0) {274 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);275 return ret;276 }277 278 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,279 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);280 if (ret < 0) {281 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);282 return ret;283 }284 285 if (drvdata->tdm_mode) {286 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1,287 6144000, 49152000);288 if (ret < 0) {289 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);290 return ret;291 }292 293 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL1,294 49152000, SND_SOC_CLOCK_IN);295 if (ret < 0) {296 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);297 return ret;298 }299 }300 301 /* Set tdm/i2s1 master bclk ratio */302 ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format);303 if (ret < 0) {304 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);305 return ret;306 }307 308 if (!drvdata->soc_mclk) {309 ret = acp_clk_enable(drvdata, srate, ch * format);310 if (ret < 0) {311 dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);312 return ret;313 }314 }315 316 return 0;317}318 319static const struct snd_soc_ops acp_card_rt5682_ops = {320 .startup = acp_card_hs_startup,321 .shutdown = acp_card_shutdown,322 .hw_params = acp_card_rt5682_hw_params,323};324 325/* Define RT5682S CODEC component*/326SND_SOC_DAILINK_DEF(rt5682s,327 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));328 329static struct snd_soc_jack rt5682s_jack;330static struct snd_soc_jack_pin rt5682s_jack_pins[] = {331 {332 .pin = "Headphone Jack",333 .mask = SND_JACK_HEADPHONE,334 },335 {336 .pin = "Headset Mic",337 .mask = SND_JACK_MICROPHONE,338 },339};340 341static const struct snd_kcontrol_new rt5682s_controls[] = {342 SOC_DAPM_PIN_SWITCH("Headphone Jack"),343 SOC_DAPM_PIN_SWITCH("Headset Mic"),344};345 346static const struct snd_soc_dapm_widget rt5682s_widgets[] = {347 SND_SOC_DAPM_HP("Headphone Jack", NULL),348 SND_SOC_DAPM_MIC("Headset Mic", NULL),349};350 351static const struct snd_soc_dapm_route rt5682s_map[] = {352 { "Headphone Jack", NULL, "HPOL" },353 { "Headphone Jack", NULL, "HPOR" },354 { "IN1P", NULL, "Headset Mic" },355};356 357static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)358{359 struct snd_soc_card *card = rtd->card;360 struct acp_card_drvdata *drvdata = card->drvdata;361 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);362 struct snd_soc_component *component = codec_dai->component;363 int ret;364 365 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);366 367 if (drvdata->hs_codec_id != RT5682S)368 return -EINVAL;369 370 if (!drvdata->soc_mclk) {371 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");372 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");373 }374 375 ret = snd_soc_dapm_new_controls(&card->dapm, rt5682s_widgets,376 ARRAY_SIZE(rt5682s_widgets));377 if (ret) {378 dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);379 return ret;380 }381 382 ret = snd_soc_add_card_controls(card, rt5682s_controls,383 ARRAY_SIZE(rt5682s_controls));384 if (ret) {385 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);386 return ret;387 }388 389 ret = snd_soc_card_jack_new_pins(card, "Headset Jack",390 SND_JACK_HEADSET | SND_JACK_LINEOUT |391 SND_JACK_BTN_0 | SND_JACK_BTN_1 |392 SND_JACK_BTN_2 | SND_JACK_BTN_3,393 &rt5682s_jack,394 rt5682s_jack_pins,395 ARRAY_SIZE(rt5682s_jack_pins));396 if (ret) {397 dev_err(card->dev, "HP jack creation failed %d\n", ret);398 return ret;399 }400 401 snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);402 snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);403 snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);404 snd_jack_set_key(rt5682s_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);405 406 ret = snd_soc_component_set_jack(component, &rt5682s_jack, NULL);407 if (ret) {408 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);409 return ret;410 }411 412 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map));413}414 415static int acp_card_rt5682s_hw_params(struct snd_pcm_substream *substream,416 struct snd_pcm_hw_params *params)417{418 struct snd_soc_pcm_runtime *rtd = substream->private_data;419 struct snd_soc_card *card = rtd->card;420 struct acp_card_drvdata *drvdata = card->drvdata;421 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);422 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);423 int ret;424 unsigned int fmt, srate, ch, format;425 426 srate = params_rate(params);427 ch = params_channels(params);428 format = params_physical_width(params);429 430 if (drvdata->tdm_mode)431 fmt = SND_SOC_DAIFMT_DSP_A;432 else433 fmt = SND_SOC_DAIFMT_I2S;434 435 if (drvdata->soc_mclk)436 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;437 else438 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;439 440 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);441 if (ret && ret != -ENOTSUPP) {442 dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);443 return ret;444 }445 446 ret = snd_soc_dai_set_fmt(codec_dai, fmt);447 if (ret < 0) {448 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);449 return ret;450 }451 452 if (drvdata->tdm_mode) {453 /**454 * As codec supports slot 0 and slot 1 for playback and capture.455 */456 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 8, 16);457 if (ret && ret != -ENOTSUPP) {458 dev_err(rtd->dev, "set TDM slot err: %d\n", ret);459 return ret;460 }461 462 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 8, 16);463 if (ret < 0) {464 dev_warn(rtd->dev, "set TDM slot err:%d\n", ret);465 return ret;466 }467 }468 469 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,470 PCO_PLAT_CLK, RT5682_PLL_FREQ);471 if (ret < 0) {472 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);473 return ret;474 }475 476 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,477 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);478 if (ret < 0) {479 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);480 return ret;481 }482 483 if (drvdata->tdm_mode) {484 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1,485 6144000, 49152000);486 if (ret < 0) {487 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);488 return ret;489 }490 491 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL1,492 49152000, SND_SOC_CLOCK_IN);493 if (ret < 0) {494 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);495 return ret;496 }497 }498 499 /* Set tdm/i2s1 master bclk ratio */500 ret = snd_soc_dai_set_bclk_ratio(codec_dai, ch * format);501 if (ret < 0) {502 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);503 return ret;504 }505 506 clk_set_rate(drvdata->wclk, srate);507 clk_set_rate(drvdata->bclk, srate * ch * format);508 if (!drvdata->soc_mclk) {509 ret = acp_clk_enable(drvdata, srate, ch * format);510 if (ret < 0) {511 dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);512 return ret;513 }514 }515 516 return 0;517}518 519static const struct snd_soc_ops acp_card_rt5682s_ops = {520 .startup = acp_card_hs_startup,521 .hw_params = acp_card_rt5682s_hw_params,522};523 524static const unsigned int dmic_channels[] = {525 DUAL_CHANNEL, FOUR_CHANNEL,526};527 528static const struct snd_pcm_hw_constraint_list dmic_constraints_channels = {529 .count = ARRAY_SIZE(dmic_channels),530 .list = dmic_channels,531 .mask = 0,532};533 534static int acp_card_dmic_startup(struct snd_pcm_substream *substream)535{536 struct snd_pcm_runtime *runtime = substream->runtime;537 538 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,539 &dmic_constraints_channels);540 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,541 &constraints_rates);542 543 return 0;544}545 546static const struct snd_soc_ops acp_card_dmic_ops = {547 .startup = acp_card_dmic_startup,548};549 550/* Declare RT1019 codec components */551SND_SOC_DAILINK_DEF(rt1019,552 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"),553 COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));554 555static const struct snd_kcontrol_new rt1019_controls[] = {556 SOC_DAPM_PIN_SWITCH("Left Spk"),557 SOC_DAPM_PIN_SWITCH("Right Spk"),558};559 560static const struct snd_soc_dapm_widget rt1019_widgets[] = {561 SND_SOC_DAPM_SPK("Left Spk", NULL),562 SND_SOC_DAPM_SPK("Right Spk", NULL),563};564 565static const struct snd_soc_dapm_route rt1019_map_lr[] = {566 { "Left Spk", NULL, "Left SPO" },567 { "Right Spk", NULL, "Right SPO" },568};569 570static struct snd_soc_codec_conf rt1019_conf[] = {571 {572 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),573 .name_prefix = "Left",574 },575 {576 .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"),577 .name_prefix = "Right",578 },579};580 581static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)582{583 struct snd_soc_card *card = rtd->card;584 struct acp_card_drvdata *drvdata = card->drvdata;585 int ret;586 587 if (drvdata->amp_codec_id != RT1019)588 return -EINVAL;589 590 ret = snd_soc_dapm_new_controls(&card->dapm, rt1019_widgets,591 ARRAY_SIZE(rt1019_widgets));592 if (ret) {593 dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);594 return ret;595 }596 597 ret = snd_soc_add_card_controls(card, rt1019_controls,598 ARRAY_SIZE(rt1019_controls));599 if (ret) {600 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);601 return ret;602 }603 604 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,605 ARRAY_SIZE(rt1019_map_lr));606}607 608static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,609 struct snd_pcm_hw_params *params)610{611 struct snd_soc_pcm_runtime *rtd = substream->private_data;612 struct snd_soc_card *card = rtd->card;613 struct acp_card_drvdata *drvdata = card->drvdata;614 struct snd_soc_dai *codec_dai;615 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);616 int i, ret = 0;617 unsigned int fmt, srate, ch, format;618 619 srate = params_rate(params);620 ch = params_channels(params);621 format = params_physical_width(params);622 623 if (drvdata->amp_codec_id != RT1019)624 return -EINVAL;625 626 if (drvdata->tdm_mode)627 fmt = SND_SOC_DAIFMT_DSP_A;628 else629 fmt = SND_SOC_DAIFMT_I2S;630 631 if (drvdata->soc_mclk)632 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;633 else634 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;635 636 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);637 if (ret && ret != -ENOTSUPP) {638 dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);639 return ret;640 }641 642 if (drvdata->tdm_mode) {643 /**644 * As codec supports slot 2 and slot 3 for playback.645 */646 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16);647 if (ret && ret != -ENOTSUPP) {648 dev_err(rtd->dev, "set TDM slot err: %d\n", ret);649 return ret;650 }651 }652 653 for_each_rtd_codec_dais(rtd, i, codec_dai) {654 if (strcmp(codec_dai->name, "rt1019-aif"))655 continue;656 657 if (drvdata->tdm_mode)658 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,659 TDM_CHANNELS * format * srate, 256 * srate);660 else661 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,662 ch * format * srate, 256 * srate);663 664 if (ret < 0)665 return ret;666 667 ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,668 256 * srate, SND_SOC_CLOCK_IN);669 if (ret < 0)670 return ret;671 672 if (drvdata->tdm_mode) {673 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A674 | SND_SOC_DAIFMT_NB_NF);675 if (ret < 0) {676 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);677 return ret;678 }679 680 /**681 * As codec supports slot 2 for left channel playback.682 */683 if (!strcmp(codec_dai->component->name, "i2c-10EC1019:00")) {684 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x4, 8, 16);685 if (ret < 0)686 break;687 }688 689 /**690 * As codec supports slot 3 for right channel playback.691 */692 if (!strcmp(codec_dai->component->name, "i2c-10EC1019:01")) {693 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x8, 8, 16);694 if (ret < 0)695 break;696 }697 }698 }699 700 if (!drvdata->soc_mclk) {701 ret = acp_clk_enable(drvdata, srate, ch * format);702 if (ret < 0) {703 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);704 return ret;705 }706 }707 708 return 0;709}710 711static int acp_card_amp_startup(struct snd_pcm_substream *substream)712{713 struct snd_pcm_runtime *runtime = substream->runtime;714 715 runtime->hw.channels_max = DUAL_CHANNEL;716 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,717 &constraints_channels);718 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,719 &constraints_rates);720 721 return 0;722}723 724static const struct snd_soc_ops acp_card_rt1019_ops = {725 .startup = acp_card_amp_startup,726 .shutdown = acp_card_shutdown,727 .hw_params = acp_card_rt1019_hw_params,728};729 730/* Declare Maxim codec components */731SND_SOC_DAILINK_DEF(max98360a,732 DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));733 734static const struct snd_kcontrol_new max98360a_controls[] = {735 SOC_DAPM_PIN_SWITCH("Spk"),736};737 738static const struct snd_soc_dapm_widget max98360a_widgets[] = {739 SND_SOC_DAPM_SPK("Spk", NULL),740};741 742static const struct snd_soc_dapm_route max98360a_map[] = {743 {"Spk", NULL, "Speaker"},744};745 746static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)747{748 struct snd_soc_card *card = rtd->card;749 struct acp_card_drvdata *drvdata = card->drvdata;750 int ret;751 752 if (drvdata->amp_codec_id != MAX98360A)753 return -EINVAL;754 755 ret = snd_soc_dapm_new_controls(&card->dapm, max98360a_widgets,756 ARRAY_SIZE(max98360a_widgets));757 if (ret) {758 dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);759 return ret;760 }761 762 ret = snd_soc_add_card_controls(card, max98360a_controls,763 ARRAY_SIZE(max98360a_controls));764 if (ret) {765 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);766 return ret;767 }768 769 return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,770 ARRAY_SIZE(max98360a_map));771}772 773static int acp_card_maxim_hw_params(struct snd_pcm_substream *substream,774 struct snd_pcm_hw_params *params)775{776 struct snd_soc_pcm_runtime *rtd = substream->private_data;777 struct snd_soc_card *card = rtd->card;778 struct acp_card_drvdata *drvdata = card->drvdata;779 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);780 unsigned int fmt, srate, ch, format;781 int ret;782 783 srate = params_rate(params);784 ch = params_channels(params);785 format = params_physical_width(params);786 787 if (drvdata->tdm_mode)788 fmt = SND_SOC_DAIFMT_DSP_A;789 else790 fmt = SND_SOC_DAIFMT_I2S;791 792 if (drvdata->soc_mclk)793 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;794 else795 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;796 797 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);798 if (ret && ret != -ENOTSUPP) {799 dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);800 return ret;801 }802 803 if (drvdata->tdm_mode) {804 /**805 * As codec supports slot 2 and slot 3 for playback.806 */807 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xC, 0, 8, 16);808 if (ret && ret != -ENOTSUPP) {809 dev_err(rtd->dev, "set TDM slot err: %d\n", ret);810 return ret;811 }812 }813 814 if (!drvdata->soc_mclk) {815 ret = acp_clk_enable(drvdata, srate, ch * format);816 if (ret < 0) {817 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);818 return ret;819 }820 }821 return 0;822}823 824static const struct snd_soc_ops acp_card_maxim_ops = {825 .startup = acp_card_amp_startup,826 .shutdown = acp_card_shutdown,827 .hw_params = acp_card_maxim_hw_params,828};829 830SND_SOC_DAILINK_DEF(max98388,831 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ADS8388:00", MAX98388_CODEC_DAI),832 COMP_CODEC("i2c-ADS8388:01", MAX98388_CODEC_DAI)));833 834static const struct snd_kcontrol_new max98388_controls[] = {835 SOC_DAPM_PIN_SWITCH("Left Spk"),836 SOC_DAPM_PIN_SWITCH("Right Spk"),837};838 839static const struct snd_soc_dapm_widget max98388_widgets[] = {840 SND_SOC_DAPM_SPK("Left Spk", NULL),841 SND_SOC_DAPM_SPK("Right Spk", NULL),842};843 844static const struct snd_soc_dapm_route max98388_map[] = {845 { "Left Spk", NULL, "Left BE_OUT" },846 { "Right Spk", NULL, "Right BE_OUT" },847};848 849static struct snd_soc_codec_conf max98388_conf[] = {850 {851 .dlc = COMP_CODEC_CONF("i2c-ADS8388:00"),852 .name_prefix = "Left",853 },854 {855 .dlc = COMP_CODEC_CONF("i2c-ADS8388:01"),856 .name_prefix = "Right",857 },858};859 860static const unsigned int max98388_format[] = {16};861 862static struct snd_pcm_hw_constraint_list constraints_sample_bits_max = {863 .list = max98388_format,864 .count = ARRAY_SIZE(max98388_format),865};866 867static int acp_card_max98388_startup(struct snd_pcm_substream *substream)868{869 struct snd_pcm_runtime *runtime = substream->runtime;870 871 runtime->hw.channels_max = DUAL_CHANNEL;872 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,873 &constraints_channels);874 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,875 &constraints_rates);876 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,877 &constraints_sample_bits_max);878 879 return 0;880}881 882static int acp_card_max98388_init(struct snd_soc_pcm_runtime *rtd)883{884 struct snd_soc_card *card = rtd->card;885 struct acp_card_drvdata *drvdata = card->drvdata;886 int ret;887 888 if (drvdata->amp_codec_id != MAX98388)889 return -EINVAL;890 891 ret = snd_soc_dapm_new_controls(&card->dapm, max98388_widgets,892 ARRAY_SIZE(max98388_widgets));893 894 if (ret) {895 dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);896 /* Don't need to add routes if widget addition failed */897 return ret;898 }899 900 ret = snd_soc_add_card_controls(card, max98388_controls,901 ARRAY_SIZE(max98388_controls));902 if (ret) {903 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);904 return ret;905 }906 907 return snd_soc_dapm_add_routes(&rtd->card->dapm, max98388_map,908 ARRAY_SIZE(max98388_map));909}910 911static int acp_max98388_hw_params(struct snd_pcm_substream *substream,912 struct snd_pcm_hw_params *params)913{914 struct snd_soc_pcm_runtime *rtd = substream->private_data;915 struct snd_soc_card *card = rtd->card;916 struct snd_soc_dai *codec_dai =917 snd_soc_card_get_codec_dai(card,918 MAX98388_CODEC_DAI);919 int ret;920 921 ret = snd_soc_dai_set_fmt(codec_dai,922 SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S |923 SND_SOC_DAIFMT_NB_NF);924 if (ret < 0)925 return ret;926 927 return ret;928}929 930static const struct snd_soc_ops acp_max98388_ops = {931 .startup = acp_card_max98388_startup,932 .hw_params = acp_max98388_hw_params,933};934 935/* Declare nau8825 codec components */936SND_SOC_DAILINK_DEF(nau8825,937 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi")));938 939static struct snd_soc_jack nau8825_jack;940static struct snd_soc_jack_pin nau8825_jack_pins[] = {941 {942 .pin = "Headphone Jack",943 .mask = SND_JACK_HEADPHONE,944 },945 {946 .pin = "Headset Mic",947 .mask = SND_JACK_MICROPHONE,948 },949};950 951static const struct snd_kcontrol_new nau8825_controls[] = {952 SOC_DAPM_PIN_SWITCH("Headphone Jack"),953 SOC_DAPM_PIN_SWITCH("Headset Mic"),954};955 956static const struct snd_soc_dapm_widget nau8825_widgets[] = {957 SND_SOC_DAPM_HP("Headphone Jack", NULL),958 SND_SOC_DAPM_MIC("Headset Mic", NULL),959};960 961static const struct snd_soc_dapm_route nau8825_map[] = {962 { "Headphone Jack", NULL, "HPOL" },963 { "Headphone Jack", NULL, "HPOR" },964};965 966static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)967{968 struct snd_soc_card *card = rtd->card;969 struct acp_card_drvdata *drvdata = card->drvdata;970 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);971 struct snd_soc_component *component = codec_dai->component;972 int ret;973 974 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);975 976 if (drvdata->hs_codec_id != NAU8825)977 return -EINVAL;978 979 ret = snd_soc_dapm_new_controls(&card->dapm, nau8825_widgets,980 ARRAY_SIZE(nau8825_widgets));981 if (ret) {982 dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);983 return ret;984 }985 986 ret = snd_soc_add_card_controls(card, nau8825_controls,987 ARRAY_SIZE(nau8825_controls));988 if (ret) {989 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);990 return ret;991 }992 993 ret = snd_soc_card_jack_new_pins(card, "Headset Jack",994 SND_JACK_HEADSET | SND_JACK_LINEOUT |995 SND_JACK_BTN_0 | SND_JACK_BTN_1 |996 SND_JACK_BTN_2 | SND_JACK_BTN_3,997 &nau8825_jack,998 nau8825_jack_pins,999 ARRAY_SIZE(nau8825_jack_pins));1000 if (ret) {1001 dev_err(card->dev, "HP jack creation failed %d\n", ret);1002 return ret;1003 }1004 1005 snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);1006 snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);1007 snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);1008 snd_jack_set_key(nau8825_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);1009 1010 ret = snd_soc_component_set_jack(component, &nau8825_jack, NULL);1011 if (ret) {1012 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);1013 return ret;1014 }1015 1016 return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8825_map, ARRAY_SIZE(nau8825_map));1017}1018 1019static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,1020 struct snd_pcm_hw_params *params)1021{1022 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);1023 struct snd_soc_card *card = rtd->card;1024 struct acp_card_drvdata *drvdata = card->drvdata;1025 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);1026 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);1027 int ret;1028 unsigned int fmt;1029 1030 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS,1031 (48000 * 256), SND_SOC_CLOCK_IN);1032 if (ret < 0)1033 dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);1034 1035 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, params_rate(params),1036 params_rate(params) * 256);1037 if (ret < 0) {1038 dev_err(rtd->dev, "can't set FLL: %d\n", ret);1039 return ret;1040 }1041 1042 if (drvdata->tdm_mode)1043 fmt = SND_SOC_DAIFMT_DSP_A;1044 else1045 fmt = SND_SOC_DAIFMT_I2S;1046 1047 if (drvdata->soc_mclk)1048 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;1049 else1050 fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;1051 1052 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);1053 if (ret && ret != -ENOTSUPP) {1054 dev_err(rtd->dev, "Failed to set dai fmt: %d\n", ret);1055 return ret;1056 }1057 1058 ret = snd_soc_dai_set_fmt(codec_dai, fmt);1059 if (ret < 0) {1060 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);1061 return ret;1062 }1063 1064 if (drvdata->tdm_mode) {1065 /**1066 * As codec supports slot 4 and slot 5 for playback and slot 6 for capture.1067 */1068 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x30, 0xC0, 8, 16);1069 if (ret && ret != -ENOTSUPP) {1070 dev_err(rtd->dev, "set TDM slot err: %d\n", ret);1071 return ret;1072 }1073 1074 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x40, 0x30, 8, 16);1075 if (ret < 0) {1076 dev_warn(rtd->dev, "set TDM slot err:%d\n", ret);1077 return ret;1078 }1079 }1080 return ret;1081}1082 1083static int acp_nau8825_startup(struct snd_pcm_substream *substream)1084{1085 struct snd_pcm_runtime *runtime = substream->runtime;1086 1087 runtime->hw.channels_max = 2;1088 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,1089 &constraints_channels);1090 1091 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;1092 snd_pcm_hw_constraint_list(runtime, 0,1093 SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);1094 return 0;1095}1096 1097static const struct snd_soc_ops acp_card_nau8825_ops = {1098 .startup = acp_nau8825_startup,1099 .hw_params = acp_nau8825_hw_params,1100};1101 1102static int platform_clock_control(struct snd_soc_dapm_widget *w,1103 struct snd_kcontrol *k, int event)1104{1105 struct snd_soc_dapm_context *dapm = w->dapm;1106 struct snd_soc_card *card = dapm->card;1107 struct snd_soc_dai *codec_dai;1108 int ret = 0;1109 1110 codec_dai = snd_soc_card_get_codec_dai(card, NAU8821_CODEC_DAI);1111 if (!codec_dai) {1112 dev_err(card->dev, "Codec dai not found\n");1113 return -EIO;1114 }1115 1116 if (SND_SOC_DAPM_EVENT_OFF(event)) {1117 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_INTERNAL,1118 0, SND_SOC_CLOCK_IN);1119 if (ret < 0) {1120 dev_err(card->dev, "set sysclk err = %d\n", ret);1121 return -EIO;1122 }1123 } else {1124 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0,1125 SND_SOC_CLOCK_IN);1126 if (ret < 0)1127 dev_err(codec_dai->dev, "can't set FS clock %d\n", ret);1128 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, NAU8821_BCLK,1129 NAU8821_FREQ_OUT);1130 if (ret < 0)1131 dev_err(codec_dai->dev, "can't set FLL: %d\n", ret);1132 }1133 return ret;1134}1135 1136static struct snd_soc_jack nau8821_jack;1137static struct snd_soc_jack_pin nau8821_jack_pins[] = {1138 {1139 .pin = "Headphone Jack",1140 .mask = SND_JACK_HEADPHONE,1141 },1142 {1143 .pin = "Headset Mic",1144 .mask = SND_JACK_MICROPHONE,1145 },1146};1147 1148static const struct snd_kcontrol_new nau8821_controls[] = {1149 SOC_DAPM_PIN_SWITCH("Headphone Jack"),1150 SOC_DAPM_PIN_SWITCH("Headset Mic"),1151};1152 1153static const struct snd_soc_dapm_widget nau8821_widgets[] = {1154 SND_SOC_DAPM_HP("Headphone Jack", NULL),1155 SND_SOC_DAPM_MIC("Headset Mic", NULL),1156 SND_SOC_DAPM_MIC("Int Mic", NULL),1157 SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,1158 platform_clock_control, SND_SOC_DAPM_PRE_PMU |1159 SND_SOC_DAPM_POST_PMD),1160};1161 1162static const struct snd_soc_dapm_route nau8821_audio_route[] = {1163 /* HP jack connectors - unknown if we have jack detection */1164 { "Headphone Jack", NULL, "HPOL" },1165 { "Headphone Jack", NULL, "HPOR" },1166 { "MICL", NULL, "Headset Mic" },1167 { "MICR", NULL, "Headset Mic" },1168 { "DMIC", NULL, "Int Mic" },1169 { "Headphone Jack", NULL, "Platform Clock" },1170 { "Headset Mic", NULL, "Platform Clock" },1171 { "Int Mic", NULL, "Platform Clock" },1172};1173 1174static const unsigned int nau8821_format[] = {16};1175 1176static struct snd_pcm_hw_constraint_list constraints_sample_bits = {1177 .list = nau8821_format,1178 .count = ARRAY_SIZE(nau8821_format),1179};1180 1181static int acp_8821_init(struct snd_soc_pcm_runtime *rtd)1182{1183 struct snd_soc_card *card = rtd->card;1184 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);1185 struct snd_soc_component *component = codec_dai->component;1186 int ret;1187 1188 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);1189 1190 ret = snd_soc_dapm_new_controls(&card->dapm, nau8821_widgets,1191 ARRAY_SIZE(nau8821_widgets));1192 if (ret) {1193 dev_err(rtd->dev, "unable to add widget dapm controls, ret %d\n", ret);1194 // Don't need to add routes if widget addition failed1195 return ret;1196 }1197 1198 ret = snd_soc_add_card_controls(card, nau8821_controls,1199 ARRAY_SIZE(nau8821_controls));1200 if (ret) {1201 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);1202 return ret;1203 }1204 1205 ret = snd_soc_card_jack_new_pins(card, "Headset Jack",1206 SND_JACK_HEADSET | SND_JACK_LINEOUT |1207 SND_JACK_BTN_0 | SND_JACK_BTN_1 |1208 SND_JACK_BTN_2 | SND_JACK_BTN_3,1209 &nau8821_jack,1210 nau8821_jack_pins,1211 ARRAY_SIZE(nau8821_jack_pins));1212 if (ret) {1213 dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);1214 return ret;1215 }1216 1217 snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);1218 snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);1219 snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);1220 snd_jack_set_key(nau8821_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);1221 1222 nau8821_enable_jack_detect(component, &nau8821_jack);1223 1224 return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8821_audio_route,1225 ARRAY_SIZE(nau8821_audio_route));1226}1227 1228static int acp_8821_startup(struct snd_pcm_substream *substream)1229{1230 struct snd_pcm_runtime *runtime = substream->runtime;1231 1232 runtime->hw.channels_max = DUAL_CHANNEL;1233 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,1234 &constraints_channels);1235 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,1236 &constraints_rates);1237 snd_pcm_hw_constraint_list(substream->runtime, 0,1238 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,1239 &constraints_sample_bits);1240 return 0;1241}1242 1243static int acp_nau8821_hw_params(struct snd_pcm_substream *substream,1244 struct snd_pcm_hw_params *params)1245{1246 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);1247 struct snd_soc_card *card = rtd->card;1248 struct acp_card_drvdata *drvdata = card->drvdata;1249 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);1250 int ret;1251 unsigned int fmt;1252 1253 if (drvdata->soc_mclk)1254 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;1255 else1256 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;1257 1258 ret = snd_soc_dai_set_fmt(codec_dai, fmt);1259 if (ret < 0) {1260 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);1261 return ret;1262 }1263 1264 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8821_CLK_FLL_BLK, 0,1265 SND_SOC_CLOCK_IN);1266 if (ret < 0)1267 dev_err(card->dev, "can't set FS clock %d\n", ret);1268 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, snd_soc_params_to_bclk(params),1269 params_rate(params) * 256);1270 if (ret < 0)1271 dev_err(card->dev, "can't set FLL: %d\n", ret);1272 1273 return ret;1274}1275 1276static const struct snd_soc_ops acp_8821_ops = {1277 .startup = acp_8821_startup,1278 .hw_params = acp_nau8821_hw_params,1279};1280 1281SND_SOC_DAILINK_DEF(nau8821,1282 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-NVTN2020:00",1283 NAU8821_CODEC_DAI)));1284 1285/* Declare DMIC codec components */1286SND_SOC_DAILINK_DEF(dmic_codec,1287 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));1288 1289/* Declare ACP CPU components */1290static struct snd_soc_dai_link_component platform_component[] = {1291 {1292 .name = "acp_asoc_renoir.0",1293 }1294};1295 1296static struct snd_soc_dai_link_component platform_rmb_component[] = {1297 {1298 .name = "acp_asoc_rembrandt.0",1299 }1300};1301 1302static struct snd_soc_dai_link_component platform_acp63_component[] = {1303 {1304 .name = "acp_asoc_acp63.0",1305 }1306};1307 1308static struct snd_soc_dai_link_component platform_acp70_component[] = {1309 {1310 .name = "acp_asoc_acp70.0",1311 }1312};1313 1314static struct snd_soc_dai_link_component sof_component[] = {1315 {1316 .name = "0000:04:00.5",1317 }1318};1319 1320SND_SOC_DAILINK_DEF(i2s_sp,1321 DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));1322SND_SOC_DAILINK_DEF(i2s_hs,1323 DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-hs")));1324SND_SOC_DAILINK_DEF(sof_sp,1325 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));1326SND_SOC_DAILINK_DEF(sof_sp_virtual,1327 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp-virtual")));1328SND_SOC_DAILINK_DEF(sof_hs,1329 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs")));1330SND_SOC_DAILINK_DEF(sof_hs_virtual,1331 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs-virtual")));1332SND_SOC_DAILINK_DEF(sof_bt,1333 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-bt")));1334SND_SOC_DAILINK_DEF(sof_dmic,1335 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));1336SND_SOC_DAILINK_DEF(pdm_dmic,1337 DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));1338 1339static int acp_rtk_set_bias_level(struct snd_soc_card *card,1340 struct snd_soc_dapm_context *dapm,1341 enum snd_soc_bias_level level)1342{1343 struct snd_soc_component *component = dapm->component;1344 struct acp_card_drvdata *drvdata = card->drvdata;1345 int ret = 0;1346 1347 if (!component)1348 return 0;1349 1350 if (strncmp(component->name, "i2c-RTL5682", 11) &&1351 strncmp(component->name, "i2c-10EC1019", 12))1352 return 0;1353 1354 /*1355 * For Realtek's codec and amplifier components,1356 * the lrck and bclk must be enabled brfore their all dapms be powered on,1357 * and must be disabled after their all dapms be powered down1358 * to avoid any pop.1359 */1360 switch (level) {1361 case SND_SOC_BIAS_STANDBY:1362 if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) {1363 1364 /* Increase bclk's enable_count */1365 ret = clk_prepare_enable(drvdata->bclk);1366 if (ret < 0)1367 dev_err(component->dev, "Failed to enable bclk %d\n", ret);1368 } else {1369 /*1370 * Decrease bclk's enable_count.1371 * While the enable_count is 0, the bclk would be closed.1372 */1373 clk_disable_unprepare(drvdata->bclk);1374 }1375 break;1376 default:1377 break;1378 }1379 1380 return ret;1381}1382 1383int acp_sofdsp_dai_links_create(struct snd_soc_card *card)1384{1385 struct snd_soc_dai_link *links;1386 struct device *dev = card->dev;1387 struct acp_card_drvdata *drv_data = card->drvdata;1388 int i = 0, num_links = 0;1389 1390 if (drv_data->hs_cpu_id)1391 num_links++;1392 if (drv_data->bt_cpu_id)1393 num_links++;1394 if (drv_data->amp_cpu_id)1395 num_links++;1396 if (drv_data->dmic_cpu_id)1397 num_links++;1398 1399 links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);1400 if (!links)1401 return -ENOMEM;1402 1403 if (drv_data->hs_cpu_id == I2S_SP) {1404 links[i].name = "acp-headset-codec";1405 links[i].id = HEADSET_BE_ID;1406 links[i].cpus = sof_sp;1407 links[i].num_cpus = ARRAY_SIZE(sof_sp);1408 links[i].platforms = sof_component;1409 links[i].num_platforms = ARRAY_SIZE(sof_component);1410 links[i].dpcm_playback = 1;1411 links[i].dpcm_capture = 1;1412 links[i].nonatomic = true;1413 links[i].no_pcm = 1;1414 if (!drv_data->hs_codec_id) {1415 /* Use dummy codec if codec id not specified */1416 links[i].codecs = &snd_soc_dummy_dlc;1417 links[i].num_codecs = 1;1418 }1419 if (drv_data->hs_codec_id == RT5682) {1420 links[i].codecs = rt5682;1421 links[i].num_codecs = ARRAY_SIZE(rt5682);1422 links[i].init = acp_card_rt5682_init;1423 links[i].ops = &acp_card_rt5682_ops;1424 }1425 if (drv_data->hs_codec_id == RT5682S) {1426 links[i].codecs = rt5682s;1427 links[i].num_codecs = ARRAY_SIZE(rt5682s);1428 links[i].init = acp_card_rt5682s_init;1429 links[i].ops = &acp_card_rt5682s_ops;1430 }1431 if (drv_data->hs_codec_id == NAU8821) {1432 links[i].codecs = nau8821;1433 links[i].num_codecs = ARRAY_SIZE(nau8821);1434 links[i].init = acp_8821_init;1435 links[i].ops = &acp_8821_ops;1436 }1437 i++;1438 }1439 1440 if (drv_data->hs_cpu_id == I2S_HS) {1441 links[i].name = "acp-headset-codec";1442 links[i].id = HEADSET_BE_ID;1443 links[i].cpus = sof_hs;1444 links[i].num_cpus = ARRAY_SIZE(sof_hs);1445 links[i].platforms = sof_component;1446 links[i].num_platforms = ARRAY_SIZE(sof_component);1447 links[i].dpcm_playback = 1;1448 links[i].dpcm_capture = 1;1449 links[i].nonatomic = true;1450 links[i].no_pcm = 1;1451 if (!drv_data->hs_codec_id) {1452 /* Use dummy codec if codec id not specified */1453 links[i].codecs = &snd_soc_dummy_dlc;1454 links[i].num_codecs = 1;1455 }1456 if (drv_data->hs_codec_id == NAU8825) {1457 links[i].codecs = nau8825;1458 links[i].num_codecs = ARRAY_SIZE(nau8825);1459 links[i].init = acp_card_nau8825_init;1460 links[i].ops = &acp_card_nau8825_ops;1461 }1462 if (drv_data->hs_codec_id == RT5682S) {1463 links[i].codecs = rt5682s;1464 links[i].num_codecs = ARRAY_SIZE(rt5682s);1465 links[i].init = acp_card_rt5682s_init;1466 links[i].ops = &acp_card_rt5682s_ops;1467 }1468 i++;1469 }1470 1471 if (drv_data->amp_cpu_id == I2S_SP) {1472 links[i].name = "acp-amp-codec";1473 links[i].id = AMP_BE_ID;1474 if (drv_data->platform == RENOIR) {1475 links[i].cpus = sof_sp;1476 links[i].num_cpus = ARRAY_SIZE(sof_sp);1477 } else {1478 links[i].cpus = sof_sp_virtual;1479 links[i].num_cpus = ARRAY_SIZE(sof_sp_virtual);1480 }1481 links[i].platforms = sof_component;1482 links[i].num_platforms = ARRAY_SIZE(sof_component);1483 links[i].dpcm_playback = 1;1484 links[i].nonatomic = true;1485 links[i].no_pcm = 1;1486 if (!drv_data->amp_codec_id) {1487 /* Use dummy codec if codec id not specified */1488 links[i].codecs = &snd_soc_dummy_dlc;1489 links[i].num_codecs = 1;1490 }1491 if (drv_data->amp_codec_id == RT1019) {1492 links[i].codecs = rt1019;1493 links[i].num_codecs = ARRAY_SIZE(rt1019);1494 links[i].ops = &acp_card_rt1019_ops;1495 links[i].init = acp_card_rt1019_init;1496 card->codec_conf = rt1019_conf;1497 card->num_configs = ARRAY_SIZE(rt1019_conf);1498 }1499 if (drv_data->amp_codec_id == MAX98360A) {1500 links[i].codecs = max98360a;1501 links[i].num_codecs = ARRAY_SIZE(max98360a);1502 links[i].ops = &acp_card_maxim_ops;1503 links[i].init = acp_card_maxim_init;1504 }1505 i++;1506 }1507 1508 if (drv_data->amp_cpu_id == I2S_HS) {1509 links[i].name = "acp-amp-codec";1510 links[i].id = AMP_BE_ID;1511 links[i].cpus = sof_hs_virtual;1512 links[i].num_cpus = ARRAY_SIZE(sof_hs_virtual);1513 links[i].platforms = sof_component;1514 links[i].num_platforms = ARRAY_SIZE(sof_component);1515 links[i].dpcm_playback = 1;1516 links[i].nonatomic = true;1517 links[i].no_pcm = 1;1518 if (!drv_data->amp_codec_id) {1519 /* Use dummy codec if codec id not specified */1520 links[i].codecs = &snd_soc_dummy_dlc;1521 links[i].num_codecs = 1;1522 }1523 if (drv_data->amp_codec_id == MAX98360A) {1524 links[i].codecs = max98360a;1525 links[i].num_codecs = ARRAY_SIZE(max98360a);1526 links[i].ops = &acp_card_maxim_ops;1527 links[i].init = acp_card_maxim_init;1528 }1529 if (drv_data->amp_codec_id == MAX98388) {1530 links[i].dpcm_capture = 1;1531 links[i].codecs = max98388;1532 links[i].num_codecs = ARRAY_SIZE(max98388);1533 links[i].ops = &acp_max98388_ops;1534 links[i].init = acp_card_max98388_init;1535 card->codec_conf = max98388_conf;1536 card->num_configs = ARRAY_SIZE(max98388_conf);1537 }1538 if (drv_data->amp_codec_id == RT1019) {1539 links[i].codecs = rt1019;1540 links[i].num_codecs = ARRAY_SIZE(rt1019);1541 links[i].ops = &acp_card_rt1019_ops;1542 links[i].init = acp_card_rt1019_init;1543 card->codec_conf = rt1019_conf;1544 card->num_configs = ARRAY_SIZE(rt1019_conf);1545 }1546 i++;1547 }1548 1549 if (drv_data->bt_cpu_id == I2S_BT) {1550 links[i].name = "acp-bt-codec";1551 links[i].id = BT_BE_ID;1552 links[i].cpus = sof_bt;1553 links[i].num_cpus = ARRAY_SIZE(sof_bt);1554 links[i].platforms = sof_component;1555 links[i].num_platforms = ARRAY_SIZE(sof_component);1556 links[i].dpcm_playback = 1;1557 links[i].dpcm_capture = 1;1558 links[i].nonatomic = true;1559 links[i].no_pcm = 1;1560 if (!drv_data->bt_codec_id) {1561 /* Use dummy codec if codec id not specified */1562 links[i].codecs = &snd_soc_dummy_dlc;1563 links[i].num_codecs = 1;1564 }1565 i++;1566 }1567 1568 if (drv_data->dmic_cpu_id == DMIC) {1569 links[i].name = "acp-dmic-codec";1570 links[i].id = DMIC_BE_ID;1571 links[i].codecs = dmic_codec;1572 links[i].num_codecs = ARRAY_SIZE(dmic_codec);1573 links[i].cpus = sof_dmic;1574 links[i].num_cpus = ARRAY_SIZE(sof_dmic);1575 links[i].platforms = sof_component;1576 links[i].num_platforms = ARRAY_SIZE(sof_component);1577 links[i].dpcm_capture = 1;1578 links[i].nonatomic = true;1579 links[i].no_pcm = 1;1580 }1581 1582 card->dai_link = links;1583 card->num_links = num_links;1584 card->set_bias_level = acp_rtk_set_bias_level;1585 1586 return 0;1587}1588EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);1589 1590int acp_legacy_dai_links_create(struct snd_soc_card *card)1591{1592 struct snd_soc_dai_link *links;1593 struct device *dev = card->dev;1594 struct acp_card_drvdata *drv_data = card->drvdata;1595 int i = 0, num_links = 0;1596 int rc;1597 1598 if (drv_data->hs_cpu_id)1599 num_links++;1600 if (drv_data->amp_cpu_id)1601 num_links++;1602 if (drv_data->dmic_cpu_id)1603 num_links++;1604 1605 links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);1606 if (!links)1607 return -ENOMEM;1608 1609 if (drv_data->hs_cpu_id == I2S_SP) {1610 links[i].name = "acp-headset-codec";1611 links[i].id = HEADSET_BE_ID;1612 links[i].cpus = i2s_sp;1613 links[i].num_cpus = ARRAY_SIZE(i2s_sp);1614 links[i].platforms = platform_component;1615 links[i].num_platforms = ARRAY_SIZE(platform_component);1616 links[i].dpcm_playback = 1;1617 links[i].dpcm_capture = 1;1618 if (!drv_data->hs_codec_id) {1619 /* Use dummy codec if codec id not specified */1620 links[i].codecs = &snd_soc_dummy_dlc;1621 links[i].num_codecs = 1;1622 }1623 if (drv_data->hs_codec_id == RT5682) {1624 links[i].codecs = rt5682;1625 links[i].num_codecs = ARRAY_SIZE(rt5682);1626 links[i].init = acp_card_rt5682_init;1627 links[i].ops = &acp_card_rt5682_ops;1628 }1629 if (drv_data->hs_codec_id == RT5682S) {1630 links[i].codecs = rt5682s;1631 links[i].num_codecs = ARRAY_SIZE(rt5682s);1632 links[i].init = acp_card_rt5682s_init;1633 links[i].ops = &acp_card_rt5682s_ops;1634 }1635 if (drv_data->hs_codec_id == ES83XX) {1636 rc = acp_ops_configure_link(card, &links[i]);1637 if (rc != 0) {1638 dev_err(dev, "Failed to configure link for ES83XX: %d\n", rc);1639 return rc;1640 }1641 }1642 i++;1643 }1644 1645 if (drv_data->hs_cpu_id == I2S_HS) {1646 links[i].name = "acp-headset-codec";1647 links[i].id = HEADSET_BE_ID;1648 links[i].cpus = i2s_hs;1649 links[i].num_cpus = ARRAY_SIZE(i2s_hs);1650 if (drv_data->platform == REMBRANDT) {1651 links[i].platforms = platform_rmb_component;1652 links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);1653 } else if (drv_data->platform == ACP63) {1654 links[i].platforms = platform_acp63_component;1655 links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);1656 } else {1657 links[i].platforms = platform_component;1658 links[i].num_platforms = ARRAY_SIZE(platform_component);1659 }1660 links[i].dpcm_playback = 1;1661 links[i].dpcm_capture = 1;1662 if (!drv_data->hs_codec_id) {1663 /* Use dummy codec if codec id not specified */1664 links[i].codecs = &snd_soc_dummy_dlc;1665 links[i].num_codecs = 1;1666 }1667 if (drv_data->hs_codec_id == NAU8825) {1668 links[i].codecs = nau8825;1669 links[i].num_codecs = ARRAY_SIZE(nau8825);1670 links[i].init = acp_card_nau8825_init;1671 links[i].ops = &acp_card_nau8825_ops;1672 }1673 if (drv_data->hs_codec_id == RT5682S) {1674 links[i].codecs = rt5682s;1675 links[i].num_codecs = ARRAY_SIZE(rt5682s);1676 links[i].init = acp_card_rt5682s_init;1677 links[i].ops = &acp_card_rt5682s_ops;1678 }1679 i++;1680 }1681 1682 if (drv_data->amp_cpu_id == I2S_SP) {1683 links[i].name = "acp-amp-codec";1684 links[i].id = AMP_BE_ID;1685 links[i].cpus = i2s_sp;1686 links[i].num_cpus = ARRAY_SIZE(i2s_sp);1687 links[i].platforms = platform_component;1688 links[i].num_platforms = ARRAY_SIZE(platform_component);1689 links[i].dpcm_playback = 1;1690 if (!drv_data->amp_codec_id) {1691 /* Use dummy codec if codec id not specified */1692 links[i].codecs = &snd_soc_dummy_dlc;1693 links[i].num_codecs = 1;1694 }1695 if (drv_data->amp_codec_id == RT1019) {1696 links[i].codecs = rt1019;1697 links[i].num_codecs = ARRAY_SIZE(rt1019);1698 links[i].ops = &acp_card_rt1019_ops;1699 links[i].init = acp_card_rt1019_init;1700 card->codec_conf = rt1019_conf;1701 card->num_configs = ARRAY_SIZE(rt1019_conf);1702 }1703 if (drv_data->amp_codec_id == MAX98360A) {1704 links[i].codecs = max98360a;1705 links[i].num_codecs = ARRAY_SIZE(max98360a);1706 links[i].ops = &acp_card_maxim_ops;1707 links[i].init = acp_card_maxim_init;1708 }1709 i++;1710 }1711 1712 if (drv_data->amp_cpu_id == I2S_HS) {1713 links[i].name = "acp-amp-codec";1714 links[i].id = AMP_BE_ID;1715 links[i].cpus = i2s_hs;1716 links[i].num_cpus = ARRAY_SIZE(i2s_hs);1717 if (drv_data->platform == REMBRANDT) {1718 links[i].platforms = platform_rmb_component;1719 links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);1720 } else if (drv_data->platform == ACP63) {1721 links[i].platforms = platform_acp63_component;1722 links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);1723 } else {1724 links[i].platforms = platform_component;1725 links[i].num_platforms = ARRAY_SIZE(platform_component);1726 }1727 links[i].dpcm_playback = 1;1728 if (!drv_data->amp_codec_id) {1729 /* Use dummy codec if codec id not specified */1730 links[i].codecs = &snd_soc_dummy_dlc;1731 links[i].num_codecs = 1;1732 }1733 if (drv_data->amp_codec_id == MAX98360A) {1734 links[i].codecs = max98360a;1735 links[i].num_codecs = ARRAY_SIZE(max98360a);1736 links[i].ops = &acp_card_maxim_ops;1737 links[i].init = acp_card_maxim_init;1738 }1739 if (drv_data->amp_codec_id == RT1019) {1740 links[i].codecs = rt1019;1741 links[i].num_codecs = ARRAY_SIZE(rt1019);1742 links[i].ops = &acp_card_rt1019_ops;1743 links[i].init = acp_card_rt1019_init;1744 card->codec_conf = rt1019_conf;1745 card->num_configs = ARRAY_SIZE(rt1019_conf);1746 }1747 i++;1748 }1749 1750 if (drv_data->dmic_cpu_id == DMIC) {1751 links[i].name = "acp-dmic-codec";1752 links[i].id = DMIC_BE_ID;1753 if (drv_data->dmic_codec_id == DMIC) {1754 links[i].codecs = dmic_codec;1755 links[i].num_codecs = ARRAY_SIZE(dmic_codec);1756 } else {1757 /* Use dummy codec if codec id not specified */1758 links[i].codecs = &snd_soc_dummy_dlc;1759 links[i].num_codecs = 1;1760 }1761 links[i].cpus = pdm_dmic;1762 links[i].num_cpus = ARRAY_SIZE(pdm_dmic);1763 if (drv_data->platform == REMBRANDT) {1764 links[i].platforms = platform_rmb_component;1765 links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);1766 } else if (drv_data->platform == ACP63) {1767 links[i].platforms = platform_acp63_component;1768 links[i].num_platforms = ARRAY_SIZE(platform_acp63_component);1769 } else if ((drv_data->platform == ACP70) || (drv_data->platform == ACP71)) {1770 links[i].platforms = platform_acp70_component;1771 links[i].num_platforms = ARRAY_SIZE(platform_acp70_component);1772 } else {1773 links[i].platforms = platform_component;1774 links[i].num_platforms = ARRAY_SIZE(platform_component);1775 }1776 links[i].ops = &acp_card_dmic_ops;1777 links[i].dpcm_capture = 1;1778 }1779 1780 card->dai_link = links;1781 card->num_links = num_links;1782 card->set_bias_level = acp_rtk_set_bias_level;1783 1784 return 0;1785}1786EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);1787 1788MODULE_DESCRIPTION("AMD ACP Common Machine driver");1789MODULE_LICENSE("GPL v2");1790