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 int rt1015_hw_params(struct snd_pcm_substream *substream, 257 struct snd_pcm_hw_params *params) 258 { 259 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 260 struct snd_soc_dai *codec_dai; 261 int i, fs = 64, ret; 262 263 for_each_rtd_codec_dais(rtd, i, codec_dai) { 264 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, 265 params_rate(params) * fs, 266 params_rate(params) * 256); 267 if (ret) 268 return ret; 269 270 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, 271 params_rate(params) * 256, 272 SND_SOC_CLOCK_IN); 273 if (ret) 274 return ret; 275 } 276 277 return 0; 278 } 279 280 static int rt1015_hw_params_pll_and_tdm(struct snd_pcm_substream *substream, 281 struct snd_pcm_hw_params *params) 282 { 283 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 284 struct snd_soc_dai *codec_dai; 285 int i, fs = 100, ret; 286 287 for_each_rtd_codec_dais(rtd, i, codec_dai) { 288 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, 289 params_rate(params) * fs, 290 params_rate(params) * 256); 291 if (ret) 292 return ret; 293 294 ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, 295 params_rate(params) * 256, 296 SND_SOC_CLOCK_IN); 297 if (ret) 298 return ret; 299 } 300 /* rx slot 1 for RT1015_DEV0_NAME */ 301 ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 302 0x0, 0x1, 4, 24); 303 if (ret) 304 return ret; 305 306 /* rx slot 2 for RT1015_DEV1_NAME */ 307 ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 1), 308 0x0, 0x2, 4, 24); 309 if (ret) 310 return ret; 311 312 return 0; 313 } 314 315 static struct snd_soc_ops rt1015_ops = { 316 .hw_params = rt1015_hw_params, 317 }; 318 319 static struct snd_soc_codec_conf rt1015_amp_conf[] = { 320 { 321 .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), 322 .name_prefix = "Left", 323 }, 324 { 325 .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), 326 .name_prefix = "Right", 327 }, 328 }; 329 330 static struct snd_soc_dai_link_component rt1015_components[] = { 331 { 332 .name = RT1015_DEV0_NAME, 333 .dai_name = RT1015_CODEC_DAI, 334 }, 335 { 336 .name = RT1015_DEV1_NAME, 337 .dai_name = RT1015_CODEC_DAI, 338 }, 339 }; 340 341 static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd) 342 { 343 return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr, 344 ARRAY_SIZE(speaker_map_lr)); 345 } 346 347 void sof_rt1015_codec_conf(struct snd_soc_card *card) 348 { 349 card->codec_conf = rt1015_amp_conf; 350 card->num_configs = ARRAY_SIZE(rt1015_amp_conf); 351 } 352 EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); 353 354 void sof_rt1015_dai_link(struct snd_soc_dai_link *link, unsigned int fs) 355 { 356 link->codecs = rt1015_components; 357 link->num_codecs = ARRAY_SIZE(rt1015_components); 358 link->init = speaker_codec_init_lr; 359 link->ops = &rt1015_ops; 360 361 if (fs == 100) 362 rt1015_ops.hw_params = rt1015_hw_params_pll_and_tdm; 363 } 364 EXPORT_SYMBOL_NS(sof_rt1015_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); 365 366 /* 367 * RT1308 audio amplifier 368 */ 369 static const struct snd_kcontrol_new rt1308_kcontrols[] = { 370 SOC_DAPM_PIN_SWITCH("Speakers"), 371 }; 372 373 static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = { 374 SND_SOC_DAPM_SPK("Speakers", NULL), 375 }; 376 377 static const struct snd_soc_dapm_route rt1308_dapm_routes[] = { 378 /* speaker */ 379 {"Speakers", NULL, "SPOL"}, 380 {"Speakers", NULL, "SPOR"}, 381 }; 382 383 static struct snd_soc_dai_link_component rt1308_components[] = { 384 { 385 .name = RT1308_DEV0_NAME, 386 .dai_name = RT1308_CODEC_DAI, 387 } 388 }; 389 390 static int rt1308_init(struct snd_soc_pcm_runtime *rtd) 391 { 392 struct snd_soc_card *card = rtd->card; 393 int ret; 394 395 ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_dapm_widgets, 396 ARRAY_SIZE(rt1308_dapm_widgets)); 397 if (ret) { 398 dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret); 399 return ret; 400 } 401 402 ret = snd_soc_add_card_controls(card, rt1308_kcontrols, 403 ARRAY_SIZE(rt1308_kcontrols)); 404 if (ret) { 405 dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret); 406 return ret; 407 } 408 409 ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_dapm_routes, 410 ARRAY_SIZE(rt1308_dapm_routes)); 411 412 if (ret) 413 dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret); 414 415 return ret; 416 } 417 418 static int rt1308_hw_params(struct snd_pcm_substream *substream, 419 struct snd_pcm_hw_params *params) 420 { 421 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 422 struct snd_soc_card *card = rtd->card; 423 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 424 int clk_id, clk_freq, pll_out; 425 int ret; 426 427 clk_id = RT1308_PLL_S_MCLK; 428 /* get the tplg configured mclk. */ 429 clk_freq = sof_dai_get_mclk(rtd); 430 431 pll_out = params_rate(params) * 512; 432 433 /* Set rt1308 pll */ 434 ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); 435 if (ret < 0) { 436 dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", ret); 437 return ret; 438 } 439 440 /* Set rt1308 sysclk */ 441 ret = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out, 442 SND_SOC_CLOCK_IN); 443 if (ret < 0) 444 dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", ret); 445 446 return ret; 447 } 448 449 static const struct snd_soc_ops rt1308_ops = { 450 .hw_params = rt1308_hw_params, 451 }; 452 453 void sof_rt1308_dai_link(struct snd_soc_dai_link *link) 454 { 455 link->codecs = rt1308_components; 456 link->num_codecs = ARRAY_SIZE(rt1308_components); 457 link->init = rt1308_init; 458 link->ops = &rt1308_ops; 459 } 460 EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); 461 462 MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers"); 463 MODULE_LICENSE("GPL"); 464