1 /* 2 * Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec 3 * 4 * Copyright 2017 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26 #include <sound/core.h> 27 #include <sound/soc.h> 28 #include <sound/pcm.h> 29 #include <sound/pcm_params.h> 30 #include <sound/soc-dapm.h> 31 #include <sound/jack.h> 32 #include <linux/clk.h> 33 #include <linux/gpio.h> 34 #include <linux/module.h> 35 #include <linux/regulator/machine.h> 36 #include <linux/regulator/driver.h> 37 #include <linux/i2c.h> 38 #include <linux/input.h> 39 #include <linux/acpi.h> 40 41 #include "acp.h" 42 #include "../codecs/da7219.h" 43 #include "../codecs/da7219-aad.h" 44 45 #define CZ_PLAT_CLK 48000000 46 #define DUAL_CHANNEL 2 47 48 static struct snd_soc_jack cz_jack; 49 static struct clk *da7219_dai_wclk; 50 static struct clk *da7219_dai_bclk; 51 extern bool bt_uart_enable; 52 53 static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) 54 { 55 int ret; 56 struct snd_soc_card *card = rtd->card; 57 struct snd_soc_dai *codec_dai = rtd->codec_dai; 58 struct snd_soc_component *component = codec_dai->component; 59 60 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); 61 62 ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, 63 CZ_PLAT_CLK, SND_SOC_CLOCK_IN); 64 if (ret < 0) { 65 dev_err(rtd->dev, "can't set codec sysclk: %d\n", ret); 66 return ret; 67 } 68 69 ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL, 70 CZ_PLAT_CLK, DA7219_PLL_FREQ_OUT_98304); 71 if (ret < 0) { 72 dev_err(rtd->dev, "can't set codec pll: %d\n", ret); 73 return ret; 74 } 75 76 da7219_dai_wclk = clk_get(component->dev, "da7219-dai-wclk"); 77 da7219_dai_bclk = clk_get(component->dev, "da7219-dai-bclk"); 78 79 ret = snd_soc_card_jack_new(card, "Headset Jack", 80 SND_JACK_HEADSET | SND_JACK_LINEOUT | 81 SND_JACK_BTN_0 | SND_JACK_BTN_1 | 82 SND_JACK_BTN_2 | SND_JACK_BTN_3, 83 &cz_jack, NULL, 0); 84 if (ret) { 85 dev_err(card->dev, "HP jack creation failed %d\n", ret); 86 return ret; 87 } 88 89 snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 90 snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); 91 snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); 92 snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); 93 94 da7219_aad_jack_det(component, &cz_jack); 95 96 return 0; 97 } 98 99 static int da7219_clk_enable(struct snd_pcm_substream *substream, 100 int wclk_rate, int bclk_rate) 101 { 102 int ret = 0; 103 struct snd_soc_pcm_runtime *rtd = substream->private_data; 104 105 clk_set_rate(da7219_dai_wclk, wclk_rate); 106 clk_set_rate(da7219_dai_bclk, bclk_rate); 107 ret = clk_prepare_enable(da7219_dai_bclk); 108 if (ret < 0) { 109 dev_err(rtd->dev, "can't enable master clock %d\n", ret); 110 return ret; 111 } 112 113 return ret; 114 } 115 116 static void da7219_clk_disable(void) 117 { 118 clk_disable_unprepare(da7219_dai_bclk); 119 } 120 121 static const unsigned int channels[] = { 122 DUAL_CHANNEL, 123 }; 124 125 static const unsigned int rates[] = { 126 48000, 127 }; 128 129 static const struct snd_pcm_hw_constraint_list constraints_rates = { 130 .count = ARRAY_SIZE(rates), 131 .list = rates, 132 .mask = 0, 133 }; 134 135 static const struct snd_pcm_hw_constraint_list constraints_channels = { 136 .count = ARRAY_SIZE(channels), 137 .list = channels, 138 .mask = 0, 139 }; 140 141 static int cz_da7219_play_startup(struct snd_pcm_substream *substream) 142 { 143 struct snd_pcm_runtime *runtime = substream->runtime; 144 struct snd_soc_pcm_runtime *rtd = substream->private_data; 145 struct snd_soc_card *card = rtd->card; 146 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 147 148 /* 149 * On this platform for PCM device we support stereo 150 */ 151 152 runtime->hw.channels_max = DUAL_CHANNEL; 153 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 154 &constraints_channels); 155 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 156 &constraints_rates); 157 158 machine->play_i2s_instance = I2S_SP_INSTANCE; 159 return 0; 160 } 161 162 static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) 163 { 164 struct snd_pcm_runtime *runtime = substream->runtime; 165 struct snd_soc_pcm_runtime *rtd = substream->private_data; 166 struct snd_soc_card *card = rtd->card; 167 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 168 169 /* 170 * On this platform for PCM device we support stereo 171 */ 172 173 runtime->hw.channels_max = DUAL_CHANNEL; 174 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 175 &constraints_channels); 176 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 177 &constraints_rates); 178 179 machine->cap_i2s_instance = I2S_SP_INSTANCE; 180 machine->capture_channel = CAP_CHANNEL1; 181 return 0; 182 } 183 184 static int cz_max_startup(struct snd_pcm_substream *substream) 185 { 186 struct snd_pcm_runtime *runtime = substream->runtime; 187 struct snd_soc_pcm_runtime *rtd = substream->private_data; 188 struct snd_soc_card *card = rtd->card; 189 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 190 191 /* 192 * On this platform for PCM device we support stereo 193 */ 194 195 runtime->hw.channels_max = DUAL_CHANNEL; 196 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 197 &constraints_channels); 198 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 199 &constraints_rates); 200 201 machine->play_i2s_instance = I2S_BT_INSTANCE; 202 return 0; 203 } 204 205 static int cz_dmic0_startup(struct snd_pcm_substream *substream) 206 { 207 struct snd_pcm_runtime *runtime = substream->runtime; 208 struct snd_soc_pcm_runtime *rtd = substream->private_data; 209 struct snd_soc_card *card = rtd->card; 210 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 211 212 /* 213 * On this platform for PCM device we support stereo 214 */ 215 216 runtime->hw.channels_max = DUAL_CHANNEL; 217 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 218 &constraints_channels); 219 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 220 &constraints_rates); 221 222 machine->cap_i2s_instance = I2S_BT_INSTANCE; 223 return 0; 224 } 225 226 static int cz_dmic1_startup(struct snd_pcm_substream *substream) 227 { 228 struct snd_pcm_runtime *runtime = substream->runtime; 229 struct snd_soc_pcm_runtime *rtd = substream->private_data; 230 struct snd_soc_card *card = rtd->card; 231 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 232 233 /* 234 * On this platform for PCM device we support stereo 235 */ 236 237 runtime->hw.channels_max = DUAL_CHANNEL; 238 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 239 &constraints_channels); 240 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 241 &constraints_rates); 242 243 machine->cap_i2s_instance = I2S_SP_INSTANCE; 244 machine->capture_channel = CAP_CHANNEL0; 245 return 0; 246 } 247 248 static int cz_da7219_params(struct snd_pcm_substream *substream, 249 struct snd_pcm_hw_params *params) 250 { 251 int wclk, bclk; 252 253 wclk = params_rate(params); 254 bclk = wclk * params_channels(params) * 255 snd_pcm_format_width(params_format(params)); 256 /* ADAU7002 spec: "The ADAU7002 requires a BCLK rate 257 * that is minimum of 64x the LRCLK sample rate." 258 * DA7219 is the only clk source so for all codecs 259 * we have to limit bclk to 64X lrclk. 260 */ 261 if (bclk < (wclk * 64)) 262 bclk = wclk * 64; 263 return da7219_clk_enable(substream, wclk, bclk); 264 } 265 266 static void cz_da7219_shutdown(struct snd_pcm_substream *substream) 267 { 268 da7219_clk_disable(); 269 } 270 271 static const struct snd_soc_ops cz_da7219_play_ops = { 272 .startup = cz_da7219_play_startup, 273 .shutdown = cz_da7219_shutdown, 274 .hw_params = cz_da7219_params, 275 }; 276 277 static const struct snd_soc_ops cz_da7219_cap_ops = { 278 .startup = cz_da7219_cap_startup, 279 .shutdown = cz_da7219_shutdown, 280 .hw_params = cz_da7219_params, 281 }; 282 283 static const struct snd_soc_ops cz_max_play_ops = { 284 .startup = cz_max_startup, 285 .shutdown = cz_da7219_shutdown, 286 .hw_params = cz_da7219_params, 287 }; 288 289 static const struct snd_soc_ops cz_dmic0_cap_ops = { 290 .startup = cz_dmic0_startup, 291 .shutdown = cz_da7219_shutdown, 292 .hw_params = cz_da7219_params, 293 }; 294 295 static const struct snd_soc_ops cz_dmic1_cap_ops = { 296 .startup = cz_dmic1_startup, 297 .shutdown = cz_da7219_shutdown, 298 .hw_params = cz_da7219_params, 299 }; 300 301 static struct snd_soc_dai_link cz_dai_7219_98357[] = { 302 { 303 .name = "amd-da7219-play", 304 .stream_name = "Playback", 305 .platform_name = "acp_audio_dma.0.auto", 306 .cpu_dai_name = "designware-i2s.1.auto", 307 .codec_dai_name = "da7219-hifi", 308 .codec_name = "i2c-DLGS7219:00", 309 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 310 | SND_SOC_DAIFMT_CBM_CFM, 311 .init = cz_da7219_init, 312 .dpcm_playback = 1, 313 .ops = &cz_da7219_play_ops, 314 }, 315 { 316 .name = "amd-da7219-cap", 317 .stream_name = "Capture", 318 .platform_name = "acp_audio_dma.0.auto", 319 .cpu_dai_name = "designware-i2s.2.auto", 320 .codec_dai_name = "da7219-hifi", 321 .codec_name = "i2c-DLGS7219:00", 322 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 323 | SND_SOC_DAIFMT_CBM_CFM, 324 .dpcm_capture = 1, 325 .ops = &cz_da7219_cap_ops, 326 }, 327 { 328 .name = "amd-max98357-play", 329 .stream_name = "HiFi Playback", 330 .platform_name = "acp_audio_dma.0.auto", 331 .cpu_dai_name = "designware-i2s.3.auto", 332 .codec_dai_name = "HiFi", 333 .codec_name = "MX98357A:00", 334 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 335 | SND_SOC_DAIFMT_CBM_CFM, 336 .dpcm_playback = 1, 337 .ops = &cz_max_play_ops, 338 }, 339 { 340 /* C panel DMIC */ 341 .name = "dmic0", 342 .stream_name = "DMIC0 Capture", 343 .platform_name = "acp_audio_dma.0.auto", 344 .cpu_dai_name = "designware-i2s.3.auto", 345 .codec_dai_name = "adau7002-hifi", 346 .codec_name = "ADAU7002:00", 347 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 348 | SND_SOC_DAIFMT_CBM_CFM, 349 .dpcm_capture = 1, 350 .ops = &cz_dmic0_cap_ops, 351 }, 352 { 353 /* A/B panel DMIC */ 354 .name = "dmic1", 355 .stream_name = "DMIC1 Capture", 356 .platform_name = "acp_audio_dma.0.auto", 357 .cpu_dai_name = "designware-i2s.2.auto", 358 .codec_dai_name = "adau7002-hifi", 359 .codec_name = "ADAU7002:00", 360 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 361 | SND_SOC_DAIFMT_CBM_CFM, 362 .dpcm_capture = 1, 363 .ops = &cz_dmic1_cap_ops, 364 }, 365 }; 366 367 static const struct snd_soc_dapm_widget cz_widgets[] = { 368 SND_SOC_DAPM_HP("Headphones", NULL), 369 SND_SOC_DAPM_SPK("Speakers", NULL), 370 SND_SOC_DAPM_MIC("Headset Mic", NULL), 371 SND_SOC_DAPM_MIC("Int Mic", NULL), 372 }; 373 374 static const struct snd_soc_dapm_route cz_audio_route[] = { 375 {"Headphones", NULL, "HPL"}, 376 {"Headphones", NULL, "HPR"}, 377 {"MIC", NULL, "Headset Mic"}, 378 {"Speakers", NULL, "Speaker"}, 379 {"PDM_DAT", NULL, "Int Mic"}, 380 }; 381 382 static const struct snd_kcontrol_new cz_mc_controls[] = { 383 SOC_DAPM_PIN_SWITCH("Headphones"), 384 SOC_DAPM_PIN_SWITCH("Speakers"), 385 SOC_DAPM_PIN_SWITCH("Headset Mic"), 386 SOC_DAPM_PIN_SWITCH("Int Mic"), 387 }; 388 389 static struct snd_soc_card cz_card = { 390 .name = "acpd7219m98357", 391 .owner = THIS_MODULE, 392 .dai_link = cz_dai_7219_98357, 393 .num_links = ARRAY_SIZE(cz_dai_7219_98357), 394 .dapm_widgets = cz_widgets, 395 .num_dapm_widgets = ARRAY_SIZE(cz_widgets), 396 .dapm_routes = cz_audio_route, 397 .num_dapm_routes = ARRAY_SIZE(cz_audio_route), 398 .controls = cz_mc_controls, 399 .num_controls = ARRAY_SIZE(cz_mc_controls), 400 }; 401 402 static struct regulator_consumer_supply acp_da7219_supplies[] = { 403 REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"), 404 REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"), 405 REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"), 406 REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"), 407 }; 408 409 static struct regulator_init_data acp_da7219_data = { 410 .constraints = { 411 .always_on = 1, 412 }, 413 .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies), 414 .consumer_supplies = acp_da7219_supplies, 415 }; 416 417 static struct regulator_config acp_da7219_cfg = { 418 .init_data = &acp_da7219_data, 419 }; 420 421 static struct regulator_ops acp_da7219_ops = { 422 }; 423 424 static const struct regulator_desc acp_da7219_desc = { 425 .name = "reg-fixed-1.8V", 426 .type = REGULATOR_VOLTAGE, 427 .owner = THIS_MODULE, 428 .ops = &acp_da7219_ops, 429 .fixed_uV = 1800000, /* 1.8V */ 430 .n_voltages = 1, 431 }; 432 433 static int cz_probe(struct platform_device *pdev) 434 { 435 int ret; 436 struct snd_soc_card *card; 437 struct acp_platform_info *machine; 438 struct regulator_dev *rdev; 439 440 acp_da7219_cfg.dev = &pdev->dev; 441 rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc, 442 &acp_da7219_cfg); 443 if (IS_ERR(rdev)) { 444 dev_err(&pdev->dev, "Failed to register regulator: %d\n", 445 (int)PTR_ERR(rdev)); 446 return -EINVAL; 447 } 448 449 machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info), 450 GFP_KERNEL); 451 if (!machine) 452 return -ENOMEM; 453 card = &cz_card; 454 cz_card.dev = &pdev->dev; 455 platform_set_drvdata(pdev, card); 456 snd_soc_card_set_drvdata(card, machine); 457 ret = devm_snd_soc_register_card(&pdev->dev, &cz_card); 458 if (ret) { 459 dev_err(&pdev->dev, 460 "devm_snd_soc_register_card(%s) failed: %d\n", 461 cz_card.name, ret); 462 return ret; 463 } 464 bt_uart_enable = !device_property_read_bool(&pdev->dev, 465 "bt-pad-enable"); 466 return 0; 467 } 468 469 static const struct acpi_device_id cz_audio_acpi_match[] = { 470 { "AMD7219", 0 }, 471 {}, 472 }; 473 MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); 474 475 static struct platform_driver cz_pcm_driver = { 476 .driver = { 477 .name = "cz-da7219-max98357a", 478 .acpi_match_table = ACPI_PTR(cz_audio_acpi_match), 479 .pm = &snd_soc_pm_ops, 480 }, 481 .probe = cz_probe, 482 }; 483 484 module_platform_driver(cz_pcm_driver); 485 486 MODULE_AUTHOR("akshu.agrawal@amd.com"); 487 MODULE_DESCRIPTION("DA7219 & MAX98357A audio support"); 488 MODULE_LICENSE("GPL v2"); 489