1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2020 Intel Corporation. All rights reserved. 4 5 #include <linux/device.h> 6 #include <linux/kernel.h> 7 #include <sound/pcm.h> 8 #include <sound/pcm_params.h> 9 #include <sound/soc.h> 10 #include <sound/soc-acpi.h> 11 #include <sound/soc-dai.h> 12 #include <sound/soc-dapm.h> 13 #include <sound/sof.h> 14 #include <uapi/sound/asound.h> 15 #include "../../codecs/rt1011.h" 16 #include "../../codecs/rt1015.h" 17 #include "../../codecs/rt1308.h" 18 #include "sof_realtek_common.h" 19 20 /* 21 * Current only 2-amp configuration is supported for rt1011 22 */ 23 static const struct snd_soc_dapm_route speaker_map_lr[] = { 24 /* speaker */ 25 { "Left Spk", NULL, "Left SPO" }, 26 { "Right Spk", NULL, "Right SPO" }, 27 }; 28 29 /* 30 * Make sure device's Unique ID follows this configuration: 31 * 32 * Two speakers: 33 * 0: left, 1: right 34 * Four speakers: 35 * 0: Woofer left, 1: Woofer right 36 * 2: Tweeter left, 3: Tweeter right 37 */ 38 static struct snd_soc_codec_conf rt1011_codec_confs[] = { 39 { 40 .dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME), 41 .name_prefix = "Left", 42 }, 43 { 44 .dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME), 45 .name_prefix = "Right", 46 }, 47 }; 48 49 static struct snd_soc_dai_link_component rt1011_dai_link_components[] = { 50 { 51 .name = RT1011_DEV0_NAME, 52 .dai_name = RT1011_CODEC_DAI, 53 }, 54 { 55 .name = RT1011_DEV1_NAME, 56 .dai_name = RT1011_CODEC_DAI, 57 }, 58 }; 59 60 static const struct { 61 unsigned int tx; 62 unsigned int rx; 63 } rt1011_tdm_mask[] = { 64 {.tx = 0x4, .rx = 0x1}, 65 {.tx = 0x8, .rx = 0x2}, 66 }; 67 68 static int rt1011_hw_params(struct snd_pcm_substream *substream, 69 struct snd_pcm_hw_params *params) 70 { 71 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 72 struct snd_soc_dai *codec_dai; 73 int srate, i, ret = 0; 74 75 srate = params_rate(params); 76 77 for_each_rtd_codec_dais(rtd, i, codec_dai) { 78 /* 100 Fs to drive 24 bit data */ 79 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK, 80 100 * srate, 256 * srate); 81 if (ret < 0) { 82 dev_err(codec_dai->dev, "fail to set pll, ret %d\n", 83 ret); 84 return ret; 85 } 86 87 ret = snd_soc_dai_set_sysclk(codec_dai, RT1011_FS_SYS_PRE_S_PLL1, 88 256 * srate, SND_SOC_CLOCK_IN); 89 if (ret < 0) { 90 dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n", 91 ret); 92 return ret; 93 } 94 95 if (i >= ARRAY_SIZE(rt1011_tdm_mask)) { 96 dev_err(codec_dai->dev, "invalid codec index %d\n", 97 i); 98 return -ENODEV; 99 } 100 101 ret = snd_soc_dai_set_tdm_slot(codec_dai, rt1011_tdm_mask[i].tx, 102 rt1011_tdm_mask[i].rx, 4, 103 params_width(params)); 104 if (ret < 0) { 105 dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", 106 ret); 107 return ret; 108 } 109 } 110 111 return 0; 112 } 113 114 static const struct snd_soc_ops rt1011_ops = { 115 .hw_params = rt1011_hw_params, 116 }; 117 118 static int rt1011_init(struct snd_soc_pcm_runtime *rtd) 119 { 120 struct snd_soc_card *card = rtd->card; 121 int ret; 122 123 ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr, 124 ARRAY_SIZE(speaker_map_lr)); 125 if (ret) 126 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); 127 return ret; 128 } 129 130 void sof_rt1011_dai_link(struct snd_soc_dai_link *link) 131 { 132 link->codecs = rt1011_dai_link_components; 133 link->num_codecs = ARRAY_SIZE(rt1011_dai_link_components); 134 link->init = rt1011_init; 135 link->ops = &rt1011_ops; 136 } 137 EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); 138 139 void sof_rt1011_codec_conf(struct snd_soc_card *card) 140 { 141 card->codec_conf = rt1011_codec_confs; 142 card->num_configs = ARRAY_SIZE(rt1011_codec_confs); 143 } 144 EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); 145 146 /* 147 * rt1015: i2c mode driver for ALC1015 and ALC1015Q 148 * rt1015p: auto-mode driver for ALC1015, ALC1015Q, and ALC1015Q-VB 149 * 150 * For stereo output, there are always two amplifiers on the board. 151 * However, the ACPI implements only one device instance (UID=0) if they 152 * are sharing the same enable pin. The code will detect the number of 153 * device instance and use corresponding DAPM structures for 154 * initialization. 155 */ 156 static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = { 157 /* speaker */ 158 { "Left Spk", NULL, "Speaker" }, 159 { "Right Spk", NULL, "Speaker" }, 160 }; 161 162 static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = { 163 /* speaker */ 164 { "Left Spk", NULL, "Left Speaker" }, 165 { "Right Spk", NULL, "Right Speaker" }, 166 }; 167 168 static struct snd_soc_codec_conf rt1015p_codec_confs[] = { 169 { 170 .dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME), 171 .name_prefix = "Left", 172 }, 173 { 174 .dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME), 175 .name_prefix = "Right", 176 }, 177 }; 178 179 static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = { 180 { 181 .name = RT1015P_DEV0_NAME, 182 .dai_name = RT1015P_CODEC_DAI, 183 }, 184 { 185 .name = RT1015P_DEV1_NAME, 186 .dai_name = RT1015P_CODEC_DAI, 187 }, 188 }; 189 190 static int rt1015p_get_num_codecs(void) 191 { 192 static int dev_num; 193 194 if (dev_num) 195 return dev_num; 196 197 if (!acpi_dev_present("RTL1015", "1", -1)) 198 dev_num = 1; 199 else 200 dev_num = 2; 201 202 return dev_num; 203 } 204 205 static int rt1015p_hw_params(struct snd_pcm_substream *substream, 206 struct snd_pcm_hw_params *params) 207 { 208 /* reserved for debugging purpose */ 209 210 return 0; 211 } 212 213 static const struct snd_soc_ops rt1015p_ops = { 214 .hw_params = rt1015p_hw_params, 215 }; 216 217 static int rt1015p_init(struct snd_soc_pcm_runtime *rtd) 218 { 219 struct snd_soc_card *card = rtd->card; 220 int ret; 221 222 if (rt1015p_get_num_codecs() == 1) 223 ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes, 224 ARRAY_SIZE(rt1015p_1dev_dapm_routes)); 225 else 226 ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes, 227 ARRAY_SIZE(rt1015p_2dev_dapm_routes)); 228 if (ret) 229 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); 230 return ret; 231 } 232 233 void sof_rt1015p_dai_link(struct snd_soc_dai_link *link) 234 { 235 link->codecs = rt1015p_dai_link_components; 236 link->num_codecs = rt1015p_get_num_codecs(); 237 link->init = rt1015p_init; 238 link->ops = &rt1015p_ops; 239 } 240 EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); 241 242 void sof_rt1015p_codec_conf(struct snd_soc_card *card) 243 { 244 if (rt1015p_get_num_codecs() == 1) 245 return; 246 247 card->codec_conf = rt1015p_codec_confs; 248 card->num_configs = ARRAY_SIZE(rt1015p_codec_confs); 249 } 250 EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); 251 252 /* 253 * RT1015 audio amplifier 254 */ 255 256 static const struct { 257 unsigned int tx; 258 unsigned int rx; 259 } rt1015_tdm_mask[] = { 260 {.tx = 0x0, .rx = 0x1}, 261 {.tx = 0x0, .rx = 0x2}, 262 }; 263 264 static int rt1015_hw_params(struct snd_pcm_substream *substream, 265 struct snd_pcm_hw_params *params) 266 { 267 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 268 struct snd_soc_dai_link *dai_link = rtd->dai_link; 269 struct snd_soc_dai *codec_dai; 270 int i, clk_freq; 271 int ret = 0; 272 273 clk_freq = sof_dai_get_bclk(rtd); 274 275 if (clk_freq <= 0) { 276 dev_err(rtd->dev, "fail to get bclk freq, ret %d\n", clk_freq); 277 return -EINVAL; 278 } 279 280 for_each_rtd_codec_dais(rtd, i, codec_dai) { 281 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, 282 clk_freq, 283 params_rate(params) * 256); 284 if (ret) { 285 dev_err(codec_dai->dev, "fail to set pll, ret %d\n", 286 ret); 287 return ret; 288 } 289 290 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, 291 params_rate(params) * 256, 292 SND_SOC_CLOCK_IN); 293 if (ret) { 294 dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n", 295 ret); 296 return ret; 297 } 298 299 switch (dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 300 case SND_SOC_DAIFMT_DSP_A: 301 case SND_SOC_DAIFMT_DSP_B: 302 /* 4-slot TDM */ 303 ret = snd_soc_dai_set_tdm_slot(codec_dai, 304 rt1015_tdm_mask[i].tx, 305 rt1015_tdm_mask[i].rx, 306 4, 307 params_width(params)); 308 if (ret < 0) { 309 dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", 310 ret); 311 return ret; 312 } 313 break; 314 default: 315 dev_dbg(codec_dai->dev, "codec is in I2S mode\n"); 316 break; 317 } 318 } 319 320 return ret; 321 } 322 323 static struct snd_soc_ops rt1015_ops = { 324 .hw_params = rt1015_hw_params, 325 }; 326 327 static struct snd_soc_codec_conf rt1015_amp_conf[] = { 328 { 329 .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), 330 .name_prefix = "Left", 331 }, 332 { 333 .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), 334 .name_prefix = "Right", 335 }, 336 }; 337 338 static struct snd_soc_dai_link_component rt1015_components[] = { 339 { 340 .name = RT1015_DEV0_NAME, 341 .dai_name = RT1015_CODEC_DAI, 342 }, 343 { 344 .name = RT1015_DEV1_NAME, 345 .dai_name = RT1015_CODEC_DAI, 346 }, 347 }; 348 349 static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd) 350 { 351 return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr, 352 ARRAY_SIZE(speaker_map_lr)); 353 } 354 355 void sof_rt1015_codec_conf(struct snd_soc_card *card) 356 { 357 card->codec_conf = rt1015_amp_conf; 358 card->num_configs = ARRAY_SIZE(rt1015_amp_conf); 359 } 360 EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); 361 362 void sof_rt1015_dai_link(struct snd_soc_dai_link *link) 363 { 364 link->codecs = rt1015_components; 365 link->num_codecs = ARRAY_SIZE(rt1015_components); 366 link->init = speaker_codec_init_lr; 367 link->ops = &rt1015_ops; 368 } 369 EXPORT_SYMBOL_NS(sof_rt1015_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); 370 371 /* 372 * RT1308 audio amplifier 373 */ 374 static const struct snd_kcontrol_new rt1308_kcontrols[] = { 375 SOC_DAPM_PIN_SWITCH("Speakers"), 376 }; 377 378 static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = { 379 SND_SOC_DAPM_SPK("Speakers", NULL), 380 }; 381 382 static const struct snd_soc_dapm_route rt1308_dapm_routes[] = { 383 /* speaker */ 384 {"Speakers", NULL, "SPOL"}, 385 {"Speakers", NULL, "SPOR"}, 386 }; 387 388 static struct snd_soc_dai_link_component rt1308_components[] = { 389 { 390 .name = RT1308_DEV0_NAME, 391 .dai_name = RT1308_CODEC_DAI, 392 } 393 }; 394 395 static int rt1308_init(struct snd_soc_pcm_runtime *rtd) 396 { 397 struct snd_soc_card *card = rtd->card; 398 int ret; 399 400 ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_dapm_widgets, 401 ARRAY_SIZE(rt1308_dapm_widgets)); 402 if (ret) { 403 dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret); 404 return ret; 405 } 406 407 ret = snd_soc_add_card_controls(card, rt1308_kcontrols, 408 ARRAY_SIZE(rt1308_kcontrols)); 409 if (ret) { 410 dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret); 411 return ret; 412 } 413 414 ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_dapm_routes, 415 ARRAY_SIZE(rt1308_dapm_routes)); 416 417 if (ret) 418 dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret); 419 420 return ret; 421 } 422 423 static int rt1308_hw_params(struct snd_pcm_substream *substream, 424 struct snd_pcm_hw_params *params) 425 { 426 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 427 struct snd_soc_card *card = rtd->card; 428 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 429 int clk_id, clk_freq, pll_out; 430 int ret; 431 432 clk_id = RT1308_PLL_S_MCLK; 433 /* get the tplg configured mclk. */ 434 clk_freq = sof_dai_get_mclk(rtd); 435 436 pll_out = params_rate(params) * 512; 437 438 /* Set rt1308 pll */ 439 ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); 440 if (ret < 0) { 441 dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", ret); 442 return ret; 443 } 444 445 /* Set rt1308 sysclk */ 446 ret = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out, 447 SND_SOC_CLOCK_IN); 448 if (ret < 0) 449 dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", ret); 450 451 return ret; 452 } 453 454 static const struct snd_soc_ops rt1308_ops = { 455 .hw_params = rt1308_hw_params, 456 }; 457 458 void sof_rt1308_dai_link(struct snd_soc_dai_link *link) 459 { 460 link->codecs = rt1308_components; 461 link->num_codecs = ARRAY_SIZE(rt1308_components); 462 link->init = rt1308_init; 463 link->ops = &rt1308_ops; 464 } 465 EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); 466 467 /* 468 * 2-amp Configuration for RT1019 469 */ 470 471 static const struct snd_soc_dapm_route rt1019p_dapm_routes[] = { 472 /* speaker */ 473 { "Left Spk", NULL, "Speaker" }, 474 { "Right Spk", NULL, "Speaker" }, 475 }; 476 477 static struct snd_soc_dai_link_component rt1019p_components[] = { 478 { 479 .name = RT1019P_DEV0_NAME, 480 .dai_name = RT1019P_CODEC_DAI, 481 }, 482 }; 483 484 static int rt1019p_init(struct snd_soc_pcm_runtime *rtd) 485 { 486 struct snd_soc_card *card = rtd->card; 487 int ret; 488 489 ret = snd_soc_dapm_add_routes(&card->dapm, rt1019p_dapm_routes, 490 ARRAY_SIZE(rt1019p_dapm_routes)); 491 if (ret) { 492 dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); 493 return ret; 494 } 495 return ret; 496 } 497 498 void sof_rt1019p_dai_link(struct snd_soc_dai_link *link) 499 { 500 link->codecs = rt1019p_components; 501 link->num_codecs = ARRAY_SIZE(rt1019p_components); 502 link->init = rt1019p_init; 503 } 504 EXPORT_SYMBOL_NS(sof_rt1019p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); 505 506 MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers"); 507 MODULE_LICENSE("GPL"); 508