1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2020 Intel Corporation 4 #include <linux/module.h> 5 #include <linux/string.h> 6 #include <sound/pcm.h> 7 #include <sound/pcm_params.h> 8 #include <sound/soc.h> 9 #include <sound/soc-acpi.h> 10 #include <sound/soc-dai.h> 11 #include <sound/soc-dapm.h> 12 #include <uapi/sound/asound.h> 13 #include "../common/soc-intel-quirks.h" 14 #include "sof_maxim_common.h" 15 16 /* 17 * Common structures and functions 18 */ 19 static const struct snd_kcontrol_new maxim_2spk_kcontrols[] = { 20 SOC_DAPM_PIN_SWITCH("Left Spk"), 21 SOC_DAPM_PIN_SWITCH("Right Spk"), 22 23 }; 24 25 static const struct snd_soc_dapm_widget maxim_2spk_widgets[] = { 26 SND_SOC_DAPM_SPK("Left Spk", NULL), 27 SND_SOC_DAPM_SPK("Right Spk", NULL), 28 }; 29 30 /* helper function to get the number of specific codec */ 31 static unsigned int get_num_codecs(const char *hid) 32 { 33 struct acpi_device *adev; 34 unsigned int dev_num = 0; 35 36 for_each_acpi_dev_match(adev, hid, NULL, -1) 37 dev_num++; 38 39 return dev_num; 40 } 41 42 #define MAX_98373_PIN_NAME 16 43 44 const struct snd_soc_dapm_route max_98373_dapm_routes[] = { 45 /* speaker */ 46 { "Left Spk", NULL, "Left BE_OUT" }, 47 { "Right Spk", NULL, "Right BE_OUT" }, 48 }; 49 EXPORT_SYMBOL_NS(max_98373_dapm_routes, SND_SOC_INTEL_SOF_MAXIM_COMMON); 50 51 static struct snd_soc_codec_conf max_98373_codec_conf[] = { 52 { 53 .dlc = COMP_CODEC_CONF(MAX_98373_DEV0_NAME), 54 .name_prefix = "Right", 55 }, 56 { 57 .dlc = COMP_CODEC_CONF(MAX_98373_DEV1_NAME), 58 .name_prefix = "Left", 59 }, 60 }; 61 62 struct snd_soc_dai_link_component max_98373_components[] = { 63 { /* For Right */ 64 .name = MAX_98373_DEV0_NAME, 65 .dai_name = MAX_98373_CODEC_DAI, 66 }, 67 { /* For Left */ 68 .name = MAX_98373_DEV1_NAME, 69 .dai_name = MAX_98373_CODEC_DAI, 70 }, 71 }; 72 EXPORT_SYMBOL_NS(max_98373_components, SND_SOC_INTEL_SOF_MAXIM_COMMON); 73 74 static int max_98373_hw_params(struct snd_pcm_substream *substream, 75 struct snd_pcm_hw_params *params) 76 { 77 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 78 struct snd_soc_dai *codec_dai; 79 int ret = 0; 80 int j; 81 82 for_each_rtd_codec_dais(rtd, j, codec_dai) { 83 if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) { 84 /* DEV0 tdm slot configuration */ 85 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x03, 3, 8, 32); 86 } else if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) { 87 /* DEV1 tdm slot configuration */ 88 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0C, 3, 8, 32); 89 } 90 if (ret < 0) { 91 dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", 92 ret); 93 return ret; 94 } 95 } 96 return 0; 97 } 98 99 int max_98373_trigger(struct snd_pcm_substream *substream, int cmd) 100 { 101 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 102 struct snd_soc_dai *codec_dai; 103 struct snd_soc_dai *cpu_dai; 104 int j; 105 int ret = 0; 106 107 /* set spk pin by playback only */ 108 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 109 return 0; 110 111 cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 112 for_each_rtd_codec_dais(rtd, j, codec_dai) { 113 struct snd_soc_dapm_context *dapm = 114 snd_soc_component_get_dapm(cpu_dai->component); 115 char pin_name[MAX_98373_PIN_NAME]; 116 117 snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk", 118 codec_dai->component->name_prefix); 119 120 switch (cmd) { 121 case SNDRV_PCM_TRIGGER_START: 122 case SNDRV_PCM_TRIGGER_RESUME: 123 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 124 ret = snd_soc_dapm_enable_pin(dapm, pin_name); 125 if (!ret) 126 snd_soc_dapm_sync(dapm); 127 break; 128 case SNDRV_PCM_TRIGGER_STOP: 129 case SNDRV_PCM_TRIGGER_SUSPEND: 130 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 131 ret = snd_soc_dapm_disable_pin(dapm, pin_name); 132 if (!ret) 133 snd_soc_dapm_sync(dapm); 134 break; 135 default: 136 break; 137 } 138 } 139 140 return ret; 141 } 142 EXPORT_SYMBOL_NS(max_98373_trigger, SND_SOC_INTEL_SOF_MAXIM_COMMON); 143 144 struct snd_soc_ops max_98373_ops = { 145 .hw_params = max_98373_hw_params, 146 .trigger = max_98373_trigger, 147 }; 148 EXPORT_SYMBOL_NS(max_98373_ops, SND_SOC_INTEL_SOF_MAXIM_COMMON); 149 150 int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) 151 { 152 struct snd_soc_card *card = rtd->card; 153 unsigned int num_codecs = get_num_codecs(MAX_98373_ACPI_HID); 154 int ret; 155 156 switch (num_codecs) { 157 case 2: 158 ret = snd_soc_dapm_new_controls(&card->dapm, maxim_2spk_widgets, 159 ARRAY_SIZE(maxim_2spk_widgets)); 160 if (ret) { 161 dev_err(rtd->dev, "fail to add max98373 widgets, ret %d\n", 162 ret); 163 return ret; 164 } 165 166 ret = snd_soc_add_card_controls(card, maxim_2spk_kcontrols, 167 ARRAY_SIZE(maxim_2spk_kcontrols)); 168 if (ret) { 169 dev_err(rtd->dev, "fail to add max98373 kcontrols, ret %d\n", 170 ret); 171 return ret; 172 } 173 174 ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, 175 ARRAY_SIZE(max_98373_dapm_routes)); 176 if (ret) { 177 dev_err(rtd->dev, "fail to add max98373 routes, ret %d\n", 178 ret); 179 return ret; 180 } 181 break; 182 default: 183 dev_err(rtd->dev, "max98373: invalid num_codecs %d\n", num_codecs); 184 return -EINVAL; 185 } 186 187 return ret; 188 } 189 EXPORT_SYMBOL_NS(max_98373_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON); 190 191 void max_98373_set_codec_conf(struct snd_soc_card *card) 192 { 193 card->codec_conf = max_98373_codec_conf; 194 card->num_configs = ARRAY_SIZE(max_98373_codec_conf); 195 } 196 EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON); 197 198 /* 199 * Maxim MAX98390 200 */ 201 static const struct snd_soc_dapm_route max_98390_dapm_routes[] = { 202 /* speaker */ 203 { "Left Spk", NULL, "Left BE_OUT" }, 204 { "Right Spk", NULL, "Right BE_OUT" }, 205 }; 206 207 static const struct snd_kcontrol_new max_98390_tt_kcontrols[] = { 208 SOC_DAPM_PIN_SWITCH("TL Spk"), 209 SOC_DAPM_PIN_SWITCH("TR Spk"), 210 }; 211 212 static const struct snd_soc_dapm_widget max_98390_tt_dapm_widgets[] = { 213 SND_SOC_DAPM_SPK("TL Spk", NULL), 214 SND_SOC_DAPM_SPK("TR Spk", NULL), 215 }; 216 217 static const struct snd_soc_dapm_route max_98390_tt_dapm_routes[] = { 218 /* Tweeter speaker */ 219 { "TL Spk", NULL, "Tweeter Left BE_OUT" }, 220 { "TR Spk", NULL, "Tweeter Right BE_OUT" }, 221 }; 222 223 static struct snd_soc_codec_conf max_98390_cml_codec_conf[] = { 224 { 225 .dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME), 226 .name_prefix = "Left", 227 }, 228 { 229 .dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME), 230 .name_prefix = "Right", 231 }, 232 }; 233 234 static struct snd_soc_codec_conf max_98390_codec_conf[] = { 235 { 236 .dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME), 237 .name_prefix = "Right", 238 }, 239 { 240 .dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME), 241 .name_prefix = "Left", 242 }, 243 { 244 .dlc = COMP_CODEC_CONF(MAX_98390_DEV2_NAME), 245 .name_prefix = "Tweeter Right", 246 }, 247 { 248 .dlc = COMP_CODEC_CONF(MAX_98390_DEV3_NAME), 249 .name_prefix = "Tweeter Left", 250 }, 251 }; 252 253 static struct snd_soc_dai_link_component max_98390_components[] = { 254 { 255 .name = MAX_98390_DEV0_NAME, 256 .dai_name = MAX_98390_CODEC_DAI, 257 }, 258 { 259 .name = MAX_98390_DEV1_NAME, 260 .dai_name = MAX_98390_CODEC_DAI, 261 }, 262 { 263 .name = MAX_98390_DEV2_NAME, 264 .dai_name = MAX_98390_CODEC_DAI, 265 }, 266 { 267 .name = MAX_98390_DEV3_NAME, 268 .dai_name = MAX_98390_CODEC_DAI, 269 }, 270 }; 271 272 static const struct { 273 unsigned int tx; 274 unsigned int rx; 275 } max_98390_tdm_mask[] = { 276 {.tx = 0x01, .rx = 0x3}, 277 {.tx = 0x02, .rx = 0x3}, 278 {.tx = 0x04, .rx = 0x3}, 279 {.tx = 0x08, .rx = 0x3}, 280 }; 281 282 static int max_98390_hw_params(struct snd_pcm_substream *substream, 283 struct snd_pcm_hw_params *params) 284 { 285 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 286 struct snd_soc_dai_link *dai_link = rtd->dai_link; 287 struct snd_soc_dai *codec_dai; 288 int i, ret; 289 290 for_each_rtd_codec_dais(rtd, i, codec_dai) { 291 if (i >= ARRAY_SIZE(max_98390_tdm_mask)) { 292 dev_err(codec_dai->dev, "invalid codec index %d\n", i); 293 return -ENODEV; 294 } 295 296 switch (dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 297 case SND_SOC_DAIFMT_DSP_A: 298 case SND_SOC_DAIFMT_DSP_B: 299 /* 4-slot TDM */ 300 ret = snd_soc_dai_set_tdm_slot(codec_dai, 301 max_98390_tdm_mask[i].tx, 302 max_98390_tdm_mask[i].rx, 303 4, 304 params_width(params)); 305 if (ret < 0) { 306 dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", 307 ret); 308 return ret; 309 } 310 break; 311 default: 312 dev_dbg(codec_dai->dev, "codec is in I2S mode\n"); 313 break; 314 } 315 } 316 return 0; 317 } 318 319 static int max_98390_init(struct snd_soc_pcm_runtime *rtd) 320 { 321 struct snd_soc_card *card = rtd->card; 322 unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID); 323 int ret; 324 325 switch (num_codecs) { 326 case 4: 327 /* add widgets/controls/dapm for tweeter speakers */ 328 ret = snd_soc_dapm_new_controls(&card->dapm, max_98390_tt_dapm_widgets, 329 ARRAY_SIZE(max_98390_tt_dapm_widgets)); 330 if (ret) { 331 dev_err(rtd->dev, "unable to add tweeter dapm widgets, ret %d\n", 332 ret); 333 /* Don't need to add routes if widget addition failed */ 334 return ret; 335 } 336 337 ret = snd_soc_add_card_controls(card, max_98390_tt_kcontrols, 338 ARRAY_SIZE(max_98390_tt_kcontrols)); 339 if (ret) { 340 dev_err(rtd->dev, "unable to add tweeter controls, ret %d\n", 341 ret); 342 return ret; 343 } 344 345 ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_tt_dapm_routes, 346 ARRAY_SIZE(max_98390_tt_dapm_routes)); 347 if (ret) { 348 dev_err(rtd->dev, "unable to add tweeter dapm routes, ret %d\n", 349 ret); 350 return ret; 351 } 352 353 fallthrough; 354 case 2: 355 /* add regular speakers dapm route */ 356 ret = snd_soc_dapm_new_controls(&card->dapm, maxim_2spk_widgets, 357 ARRAY_SIZE(maxim_2spk_widgets)); 358 if (ret) { 359 dev_err(rtd->dev, "fail to add max98390 woofer widgets, ret %d\n", 360 ret); 361 return ret; 362 } 363 364 ret = snd_soc_add_card_controls(card, maxim_2spk_kcontrols, 365 ARRAY_SIZE(maxim_2spk_kcontrols)); 366 if (ret) { 367 dev_err(rtd->dev, "fail to add max98390 woofer kcontrols, ret %d\n", 368 ret); 369 return ret; 370 } 371 372 ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_dapm_routes, 373 ARRAY_SIZE(max_98390_dapm_routes)); 374 if (ret) { 375 dev_err(rtd->dev, "unable to add dapm routes, ret %d\n", 376 ret); 377 return ret; 378 } 379 break; 380 default: 381 dev_err(rtd->dev, "invalid codec number %d\n", num_codecs); 382 return -EINVAL; 383 } 384 385 return ret; 386 } 387 388 static const struct snd_soc_ops max_98390_ops = { 389 .hw_params = max_98390_hw_params, 390 }; 391 392 void max_98390_dai_link(struct device *dev, struct snd_soc_dai_link *link) 393 { 394 unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID); 395 396 link->codecs = max_98390_components; 397 398 switch (num_codecs) { 399 case 2: 400 case 4: 401 link->num_codecs = num_codecs; 402 break; 403 default: 404 dev_err(dev, "invalid codec number %d for %s\n", num_codecs, 405 MAX_98390_ACPI_HID); 406 break; 407 } 408 409 link->init = max_98390_init; 410 link->ops = &max_98390_ops; 411 } 412 EXPORT_SYMBOL_NS(max_98390_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON); 413 414 void max_98390_set_codec_conf(struct device *dev, struct snd_soc_card *card) 415 { 416 unsigned int num_codecs = get_num_codecs(MAX_98390_ACPI_HID); 417 418 card->codec_conf = max_98390_codec_conf; 419 420 switch (num_codecs) { 421 case 2: 422 if (soc_intel_is_cml()) 423 card->codec_conf = max_98390_cml_codec_conf; 424 425 fallthrough; 426 case 4: 427 card->num_configs = num_codecs; 428 break; 429 default: 430 dev_err(dev, "invalid codec number %d for %s\n", num_codecs, 431 MAX_98390_ACPI_HID); 432 break; 433 } 434 } 435 EXPORT_SYMBOL_NS(max_98390_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON); 436 437 /* 438 * Maxim MAX98357A/MAX98360A 439 */ 440 static const struct snd_kcontrol_new max_98357a_kcontrols[] = { 441 SOC_DAPM_PIN_SWITCH("Spk"), 442 }; 443 444 static const struct snd_soc_dapm_widget max_98357a_dapm_widgets[] = { 445 SND_SOC_DAPM_SPK("Spk", NULL), 446 }; 447 448 static const struct snd_soc_dapm_route max_98357a_dapm_routes[] = { 449 /* speaker */ 450 {"Spk", NULL, "Speaker"}, 451 }; 452 453 static struct snd_soc_dai_link_component max_98357a_components[] = { 454 { 455 .name = MAX_98357A_DEV0_NAME, 456 .dai_name = MAX_98357A_CODEC_DAI, 457 } 458 }; 459 460 static struct snd_soc_dai_link_component max_98360a_components[] = { 461 { 462 .name = MAX_98360A_DEV0_NAME, 463 .dai_name = MAX_98357A_CODEC_DAI, 464 } 465 }; 466 467 static int max_98357a_init(struct snd_soc_pcm_runtime *rtd) 468 { 469 struct snd_soc_card *card = rtd->card; 470 int ret; 471 472 ret = snd_soc_dapm_new_controls(&card->dapm, max_98357a_dapm_widgets, 473 ARRAY_SIZE(max_98357a_dapm_widgets)); 474 if (ret) { 475 dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret); 476 /* Don't need to add routes if widget addition failed */ 477 return ret; 478 } 479 480 ret = snd_soc_add_card_controls(card, max_98357a_kcontrols, 481 ARRAY_SIZE(max_98357a_kcontrols)); 482 if (ret) { 483 dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret); 484 return ret; 485 } 486 487 ret = snd_soc_dapm_add_routes(&card->dapm, max_98357a_dapm_routes, 488 ARRAY_SIZE(max_98357a_dapm_routes)); 489 490 if (ret) 491 dev_err(rtd->dev, "unable to add dapm routes, ret %d\n", ret); 492 493 return ret; 494 } 495 496 void max_98357a_dai_link(struct snd_soc_dai_link *link) 497 { 498 link->codecs = max_98357a_components; 499 link->num_codecs = ARRAY_SIZE(max_98357a_components); 500 link->init = max_98357a_init; 501 } 502 EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON); 503 504 void max_98360a_dai_link(struct snd_soc_dai_link *link) 505 { 506 link->codecs = max_98360a_components; 507 link->num_codecs = ARRAY_SIZE(max_98360a_components); 508 link->init = max_98357a_init; 509 } 510 EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON); 511 512 MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers"); 513 MODULE_LICENSE("GPL"); 514