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 { 101 int ret = 0; 102 struct snd_soc_pcm_runtime *rtd = substream->private_data; 103 104 /* 105 * Set wclk to 48000 because the rate constraint of this driver is 106 * 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is 107 * minimum of 64x the LRCLK sample rate." DA7219 is the only clk 108 * source so for all codecs we have to limit bclk to 64X lrclk. 109 */ 110 clk_set_rate(da7219_dai_wclk, 48000); 111 clk_set_rate(da7219_dai_bclk, 48000 * 64); 112 ret = clk_prepare_enable(da7219_dai_bclk); 113 if (ret < 0) { 114 dev_err(rtd->dev, "can't enable master clock %d\n", ret); 115 return ret; 116 } 117 118 return ret; 119 } 120 121 static void da7219_clk_disable(void) 122 { 123 clk_disable_unprepare(da7219_dai_bclk); 124 } 125 126 static const unsigned int channels[] = { 127 DUAL_CHANNEL, 128 }; 129 130 static const unsigned int rates[] = { 131 48000, 132 }; 133 134 static const struct snd_pcm_hw_constraint_list constraints_rates = { 135 .count = ARRAY_SIZE(rates), 136 .list = rates, 137 .mask = 0, 138 }; 139 140 static const struct snd_pcm_hw_constraint_list constraints_channels = { 141 .count = ARRAY_SIZE(channels), 142 .list = channels, 143 .mask = 0, 144 }; 145 146 static int cz_da7219_play_startup(struct snd_pcm_substream *substream) 147 { 148 struct snd_pcm_runtime *runtime = substream->runtime; 149 struct snd_soc_pcm_runtime *rtd = substream->private_data; 150 struct snd_soc_card *card = rtd->card; 151 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 152 153 /* 154 * On this platform for PCM device we support stereo 155 */ 156 157 runtime->hw.channels_max = DUAL_CHANNEL; 158 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 159 &constraints_channels); 160 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 161 &constraints_rates); 162 163 machine->play_i2s_instance = I2S_SP_INSTANCE; 164 return da7219_clk_enable(substream); 165 } 166 167 static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) 168 { 169 struct snd_pcm_runtime *runtime = substream->runtime; 170 struct snd_soc_pcm_runtime *rtd = substream->private_data; 171 struct snd_soc_card *card = rtd->card; 172 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 173 174 /* 175 * On this platform for PCM device we support stereo 176 */ 177 178 runtime->hw.channels_max = DUAL_CHANNEL; 179 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 180 &constraints_channels); 181 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 182 &constraints_rates); 183 184 machine->cap_i2s_instance = I2S_SP_INSTANCE; 185 machine->capture_channel = CAP_CHANNEL1; 186 return da7219_clk_enable(substream); 187 } 188 189 static int cz_max_startup(struct snd_pcm_substream *substream) 190 { 191 struct snd_pcm_runtime *runtime = substream->runtime; 192 struct snd_soc_pcm_runtime *rtd = substream->private_data; 193 struct snd_soc_card *card = rtd->card; 194 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 195 196 /* 197 * On this platform for PCM device we support stereo 198 */ 199 200 runtime->hw.channels_max = DUAL_CHANNEL; 201 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 202 &constraints_channels); 203 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 204 &constraints_rates); 205 206 machine->play_i2s_instance = I2S_BT_INSTANCE; 207 return da7219_clk_enable(substream); 208 } 209 210 static int cz_dmic0_startup(struct snd_pcm_substream *substream) 211 { 212 struct snd_pcm_runtime *runtime = substream->runtime; 213 struct snd_soc_pcm_runtime *rtd = substream->private_data; 214 struct snd_soc_card *card = rtd->card; 215 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 216 217 /* 218 * On this platform for PCM device we support stereo 219 */ 220 221 runtime->hw.channels_max = DUAL_CHANNEL; 222 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 223 &constraints_channels); 224 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 225 &constraints_rates); 226 227 machine->cap_i2s_instance = I2S_BT_INSTANCE; 228 return da7219_clk_enable(substream); 229 } 230 231 static int cz_dmic1_startup(struct snd_pcm_substream *substream) 232 { 233 struct snd_pcm_runtime *runtime = substream->runtime; 234 struct snd_soc_pcm_runtime *rtd = substream->private_data; 235 struct snd_soc_card *card = rtd->card; 236 struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); 237 238 /* 239 * On this platform for PCM device we support stereo 240 */ 241 242 runtime->hw.channels_max = DUAL_CHANNEL; 243 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 244 &constraints_channels); 245 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 246 &constraints_rates); 247 248 machine->cap_i2s_instance = I2S_SP_INSTANCE; 249 machine->capture_channel = CAP_CHANNEL0; 250 return da7219_clk_enable(substream); 251 } 252 253 static void cz_da7219_shutdown(struct snd_pcm_substream *substream) 254 { 255 da7219_clk_disable(); 256 } 257 258 static const struct snd_soc_ops cz_da7219_play_ops = { 259 .startup = cz_da7219_play_startup, 260 .shutdown = cz_da7219_shutdown, 261 }; 262 263 static const struct snd_soc_ops cz_da7219_cap_ops = { 264 .startup = cz_da7219_cap_startup, 265 .shutdown = cz_da7219_shutdown, 266 }; 267 268 static const struct snd_soc_ops cz_max_play_ops = { 269 .startup = cz_max_startup, 270 .shutdown = cz_da7219_shutdown, 271 }; 272 273 static const struct snd_soc_ops cz_dmic0_cap_ops = { 274 .startup = cz_dmic0_startup, 275 .shutdown = cz_da7219_shutdown, 276 }; 277 278 static const struct snd_soc_ops cz_dmic1_cap_ops = { 279 .startup = cz_dmic1_startup, 280 .shutdown = cz_da7219_shutdown, 281 }; 282 283 SND_SOC_DAILINK_DEF(designware1, 284 DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto"))); 285 SND_SOC_DAILINK_DEF(designware2, 286 DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.2.auto"))); 287 SND_SOC_DAILINK_DEF(designware3, 288 DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.3.auto"))); 289 290 SND_SOC_DAILINK_DEF(dlgs, 291 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", "da7219-hifi"))); 292 SND_SOC_DAILINK_DEF(mx, 293 DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); 294 SND_SOC_DAILINK_DEF(adau, 295 DAILINK_COMP_ARRAY(COMP_CODEC("ADAU7002:00", "adau7002-hifi"))); 296 297 SND_SOC_DAILINK_DEF(platform, 298 DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_audio_dma.0.auto"))); 299 300 static struct snd_soc_dai_link cz_dai_7219_98357[] = { 301 { 302 .name = "amd-da7219-play", 303 .stream_name = "Playback", 304 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 305 | SND_SOC_DAIFMT_CBM_CFM, 306 .init = cz_da7219_init, 307 .dpcm_playback = 1, 308 .ops = &cz_da7219_play_ops, 309 SND_SOC_DAILINK_REG(designware1, dlgs, platform), 310 }, 311 { 312 .name = "amd-da7219-cap", 313 .stream_name = "Capture", 314 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 315 | SND_SOC_DAIFMT_CBM_CFM, 316 .dpcm_capture = 1, 317 .ops = &cz_da7219_cap_ops, 318 SND_SOC_DAILINK_REG(designware2, dlgs, platform), 319 }, 320 { 321 .name = "amd-max98357-play", 322 .stream_name = "HiFi Playback", 323 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 324 | SND_SOC_DAIFMT_CBM_CFM, 325 .dpcm_playback = 1, 326 .ops = &cz_max_play_ops, 327 SND_SOC_DAILINK_REG(designware3, mx, platform), 328 }, 329 { 330 /* C panel DMIC */ 331 .name = "dmic0", 332 .stream_name = "DMIC0 Capture", 333 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 334 | SND_SOC_DAIFMT_CBM_CFM, 335 .dpcm_capture = 1, 336 .ops = &cz_dmic0_cap_ops, 337 SND_SOC_DAILINK_REG(designware3, adau, platform), 338 }, 339 { 340 /* A/B panel DMIC */ 341 .name = "dmic1", 342 .stream_name = "DMIC1 Capture", 343 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 344 | SND_SOC_DAIFMT_CBM_CFM, 345 .dpcm_capture = 1, 346 .ops = &cz_dmic1_cap_ops, 347 SND_SOC_DAILINK_REG(designware2, adau, platform), 348 }, 349 }; 350 351 static const struct snd_soc_dapm_widget cz_widgets[] = { 352 SND_SOC_DAPM_HP("Headphones", NULL), 353 SND_SOC_DAPM_SPK("Speakers", NULL), 354 SND_SOC_DAPM_MIC("Headset Mic", NULL), 355 SND_SOC_DAPM_MIC("Int Mic", NULL), 356 }; 357 358 static const struct snd_soc_dapm_route cz_audio_route[] = { 359 {"Headphones", NULL, "HPL"}, 360 {"Headphones", NULL, "HPR"}, 361 {"MIC", NULL, "Headset Mic"}, 362 {"Speakers", NULL, "Speaker"}, 363 {"PDM_DAT", NULL, "Int Mic"}, 364 }; 365 366 static const struct snd_kcontrol_new cz_mc_controls[] = { 367 SOC_DAPM_PIN_SWITCH("Headphones"), 368 SOC_DAPM_PIN_SWITCH("Speakers"), 369 SOC_DAPM_PIN_SWITCH("Headset Mic"), 370 SOC_DAPM_PIN_SWITCH("Int Mic"), 371 }; 372 373 static struct snd_soc_card cz_card = { 374 .name = "acpd7219m98357", 375 .owner = THIS_MODULE, 376 .dai_link = cz_dai_7219_98357, 377 .num_links = ARRAY_SIZE(cz_dai_7219_98357), 378 .dapm_widgets = cz_widgets, 379 .num_dapm_widgets = ARRAY_SIZE(cz_widgets), 380 .dapm_routes = cz_audio_route, 381 .num_dapm_routes = ARRAY_SIZE(cz_audio_route), 382 .controls = cz_mc_controls, 383 .num_controls = ARRAY_SIZE(cz_mc_controls), 384 }; 385 386 static struct regulator_consumer_supply acp_da7219_supplies[] = { 387 REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"), 388 REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"), 389 REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"), 390 REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"), 391 }; 392 393 static struct regulator_init_data acp_da7219_data = { 394 .constraints = { 395 .always_on = 1, 396 }, 397 .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies), 398 .consumer_supplies = acp_da7219_supplies, 399 }; 400 401 static struct regulator_config acp_da7219_cfg = { 402 .init_data = &acp_da7219_data, 403 }; 404 405 static struct regulator_ops acp_da7219_ops = { 406 }; 407 408 static const struct regulator_desc acp_da7219_desc = { 409 .name = "reg-fixed-1.8V", 410 .type = REGULATOR_VOLTAGE, 411 .owner = THIS_MODULE, 412 .ops = &acp_da7219_ops, 413 .fixed_uV = 1800000, /* 1.8V */ 414 .n_voltages = 1, 415 }; 416 417 static int cz_probe(struct platform_device *pdev) 418 { 419 int ret; 420 struct snd_soc_card *card; 421 struct acp_platform_info *machine; 422 struct regulator_dev *rdev; 423 424 acp_da7219_cfg.dev = &pdev->dev; 425 rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc, 426 &acp_da7219_cfg); 427 if (IS_ERR(rdev)) { 428 dev_err(&pdev->dev, "Failed to register regulator: %d\n", 429 (int)PTR_ERR(rdev)); 430 return -EINVAL; 431 } 432 433 machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info), 434 GFP_KERNEL); 435 if (!machine) 436 return -ENOMEM; 437 card = &cz_card; 438 cz_card.dev = &pdev->dev; 439 platform_set_drvdata(pdev, card); 440 snd_soc_card_set_drvdata(card, machine); 441 ret = devm_snd_soc_register_card(&pdev->dev, &cz_card); 442 if (ret) { 443 dev_err(&pdev->dev, 444 "devm_snd_soc_register_card(%s) failed: %d\n", 445 cz_card.name, ret); 446 return ret; 447 } 448 bt_uart_enable = !device_property_read_bool(&pdev->dev, 449 "bt-pad-enable"); 450 return 0; 451 } 452 453 static const struct acpi_device_id cz_audio_acpi_match[] = { 454 { "AMD7219", 0 }, 455 {}, 456 }; 457 MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); 458 459 static struct platform_driver cz_pcm_driver = { 460 .driver = { 461 .name = "cz-da7219-max98357a", 462 .acpi_match_table = ACPI_PTR(cz_audio_acpi_match), 463 .pm = &snd_soc_pm_ops, 464 }, 465 .probe = cz_probe, 466 }; 467 468 module_platform_driver(cz_pcm_driver); 469 470 MODULE_AUTHOR("akshu.agrawal@amd.com"); 471 MODULE_DESCRIPTION("DA7219 & MAX98357A audio support"); 472 MODULE_LICENSE("GPL v2"); 473