1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright(c) 2019 Intel Corporation. 3 4 /* 5 * Intel Cometlake I2S Machine driver for RT1011 + RT5682 codec 6 */ 7 8 #include <linux/input.h> 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/clk.h> 12 #include <linux/dmi.h> 13 #include <linux/slab.h> 14 #include <linux/acpi.h> 15 #include <sound/core.h> 16 #include <sound/jack.h> 17 #include <sound/pcm.h> 18 #include <sound/pcm_params.h> 19 #include <sound/soc.h> 20 #include <sound/rt5682.h> 21 #include <sound/soc-acpi.h> 22 #include "../../codecs/rt1011.h" 23 #include "../../codecs/rt5682.h" 24 #include "../../codecs/hdac_hdmi.h" 25 #include "hda_dsp_common.h" 26 27 /* The platform clock outputs 24Mhz clock to codec as I2S MCLK */ 28 #define CML_PLAT_CLK 24000000 29 #define CML_RT1011_CODEC_DAI "rt1011-aif" 30 #define CML_RT5682_CODEC_DAI "rt5682-aif1" 31 #define NAME_SIZE 32 32 33 static struct snd_soc_jack hdmi_jack[3]; 34 35 struct hdmi_pcm { 36 struct list_head head; 37 struct snd_soc_dai *codec_dai; 38 int device; 39 }; 40 41 struct card_private { 42 char codec_name[SND_ACPI_I2C_ID_LEN]; 43 struct snd_soc_jack headset; 44 struct list_head hdmi_pcm_list; 45 bool common_hdmi_codec_drv; 46 }; 47 48 static const struct snd_kcontrol_new cml_controls[] = { 49 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 50 SOC_DAPM_PIN_SWITCH("Headset Mic"), 51 SOC_DAPM_PIN_SWITCH("TL Ext Spk"), 52 SOC_DAPM_PIN_SWITCH("TR Ext Spk"), 53 SOC_DAPM_PIN_SWITCH("WL Ext Spk"), 54 SOC_DAPM_PIN_SWITCH("WR Ext Spk"), 55 }; 56 57 static const struct snd_soc_dapm_widget cml_rt1011_rt5682_widgets[] = { 58 SND_SOC_DAPM_SPK("TL Ext Spk", NULL), 59 SND_SOC_DAPM_SPK("TR Ext Spk", NULL), 60 SND_SOC_DAPM_SPK("WL Ext Spk", NULL), 61 SND_SOC_DAPM_SPK("WR Ext Spk", NULL), 62 SND_SOC_DAPM_HP("Headphone Jack", NULL), 63 SND_SOC_DAPM_MIC("Headset Mic", NULL), 64 SND_SOC_DAPM_MIC("SoC DMIC", NULL), 65 }; 66 67 static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = { 68 /*speaker*/ 69 {"TL Ext Spk", NULL, "TL SPO"}, 70 {"TR Ext Spk", NULL, "TR SPO"}, 71 {"WL Ext Spk", NULL, "WL SPO"}, 72 {"WR Ext Spk", NULL, "WR SPO"}, 73 74 /* HP jack connectors - unknown if we have jack detection */ 75 { "Headphone Jack", NULL, "HPOL" }, 76 { "Headphone Jack", NULL, "HPOR" }, 77 78 /* other jacks */ 79 { "IN1P", NULL, "Headset Mic" }, 80 81 /* DMIC */ 82 {"DMic", NULL, "SoC DMIC"}, 83 }; 84 85 static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) 86 { 87 struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 88 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 89 struct snd_soc_jack *jack; 90 int ret; 91 92 /* need to enable ASRC function for 24MHz mclk rate */ 93 rt5682_sel_asrc_clk_src(component, RT5682_DA_STEREO1_FILTER | 94 RT5682_AD_STEREO1_FILTER, 95 RT5682_CLK_SEL_I2S1_ASRC); 96 97 /* 98 * Headset buttons map to the google Reference headset. 99 * These can be configured by userspace. 100 */ 101 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", 102 SND_JACK_HEADSET | SND_JACK_BTN_0 | 103 SND_JACK_BTN_1 | SND_JACK_BTN_2 | 104 SND_JACK_BTN_3, 105 &ctx->headset, NULL, 0); 106 if (ret) { 107 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 108 return ret; 109 } 110 111 jack = &ctx->headset; 112 113 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 114 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 115 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 116 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 117 ret = snd_soc_component_set_jack(component, jack, NULL); 118 if (ret) 119 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 120 121 return ret; 122 }; 123 124 static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, 125 struct snd_pcm_hw_params *params) 126 { 127 struct snd_soc_pcm_runtime *rtd = substream->private_data; 128 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 129 int clk_id, clk_freq, pll_out, ret; 130 131 clk_id = RT5682_PLL1_S_MCLK; 132 clk_freq = CML_PLAT_CLK; 133 134 pll_out = params_rate(params) * 512; 135 136 ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); 137 if (ret < 0) 138 dev_warn(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret); 139 140 /* Configure sysclk for codec */ 141 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1, 142 pll_out, SND_SOC_CLOCK_IN); 143 if (ret < 0) 144 dev_warn(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); 145 146 /* 147 * slot_width should be equal or large than data length, set them 148 * be the same 149 */ 150 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2, 151 params_width(params)); 152 if (ret < 0) 153 dev_warn(rtd->dev, "set TDM slot err:%d\n", ret); 154 return ret; 155 } 156 157 static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, 158 struct snd_pcm_hw_params *params) 159 { 160 struct snd_soc_pcm_runtime *rtd = substream->private_data; 161 struct snd_soc_dai *codec_dai; 162 struct snd_soc_card *card = rtd->card; 163 int srate, i, ret = 0; 164 165 srate = params_rate(params); 166 167 for_each_rtd_codec_dais(rtd, i, codec_dai) { 168 169 /* 100 Fs to drive 24 bit data */ 170 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK, 171 100 * srate, 256 * srate); 172 if (ret < 0) { 173 dev_err(card->dev, "codec_dai clock not set\n"); 174 return ret; 175 } 176 177 ret = snd_soc_dai_set_sysclk(codec_dai, 178 RT1011_FS_SYS_PRE_S_PLL1, 179 256 * srate, SND_SOC_CLOCK_IN); 180 if (ret < 0) { 181 dev_err(card->dev, "codec_dai clock not set\n"); 182 return ret; 183 } 184 185 /* 186 * Codec TDM is configured as 24 bit capture/ playback. 187 * 2 CH PB is done over 4 codecs - 2 Woofers and 2 Tweeters. 188 * The Left woofer and tweeter plays the Left playback data 189 * and similar by the Right. 190 * Hence 2 codecs (1 T and 1 W pair) share same Rx slot. 191 * The feedback is captured for each codec individually. 192 * Hence all 4 codecs use 1 Tx slot each for feedback. 193 */ 194 if (!strcmp(codec_dai->component->name, "i2c-10EC1011:00")) { 195 ret = snd_soc_dai_set_tdm_slot(codec_dai, 196 0x4, 0x1, 4, 24); 197 if (ret < 0) 198 break; 199 } 200 if (!strcmp(codec_dai->component->name, "i2c-10EC1011:02")) { 201 ret = snd_soc_dai_set_tdm_slot(codec_dai, 202 0x1, 0x1, 4, 24); 203 if (ret < 0) 204 break; 205 } 206 /* TDM Rx slot 2 is used for Right Woofer & Tweeters pair */ 207 if (!strcmp(codec_dai->component->name, "i2c-10EC1011:01")) { 208 ret = snd_soc_dai_set_tdm_slot(codec_dai, 209 0x8, 0x2, 4, 24); 210 if (ret < 0) 211 break; 212 } 213 if (!strcmp(codec_dai->component->name, "i2c-10EC1011:03")) { 214 ret = snd_soc_dai_set_tdm_slot(codec_dai, 215 0x2, 0x2, 4, 24); 216 if (ret < 0) 217 break; 218 } 219 } 220 if (ret < 0) 221 dev_err(rtd->dev, 222 "set codec TDM slot for %s failed with error %d\n", 223 codec_dai->component->name, ret); 224 return ret; 225 } 226 227 static struct snd_soc_ops cml_rt5682_ops = { 228 .hw_params = cml_rt5682_hw_params, 229 }; 230 231 static const struct snd_soc_ops cml_rt1011_ops = { 232 .hw_params = cml_rt1011_hw_params, 233 }; 234 235 static int sof_card_late_probe(struct snd_soc_card *card) 236 { 237 struct card_private *ctx = snd_soc_card_get_drvdata(card); 238 struct snd_soc_component *component = NULL; 239 char jack_name[NAME_SIZE]; 240 struct hdmi_pcm *pcm; 241 int ret, i = 0; 242 243 if (list_empty(&ctx->hdmi_pcm_list)) 244 return -EINVAL; 245 246 if (ctx->common_hdmi_codec_drv) { 247 pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm, 248 head); 249 component = pcm->codec_dai->component; 250 return hda_dsp_hdmi_build_controls(card, component); 251 } 252 253 list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { 254 component = pcm->codec_dai->component; 255 snprintf(jack_name, sizeof(jack_name), 256 "HDMI/DP, pcm=%d Jack", pcm->device); 257 ret = snd_soc_card_jack_new(card, jack_name, 258 SND_JACK_AVOUT, &hdmi_jack[i], 259 NULL, 0); 260 if (ret) 261 return ret; 262 263 ret = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, 264 &hdmi_jack[i]); 265 if (ret < 0) 266 return ret; 267 268 i++; 269 } 270 271 return hdac_hdmi_jack_port_init(component, &card->dapm); 272 } 273 274 static int hdmi_init(struct snd_soc_pcm_runtime *rtd) 275 { 276 struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 277 struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); 278 struct hdmi_pcm *pcm; 279 280 pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); 281 if (!pcm) 282 return -ENOMEM; 283 284 pcm->device = dai->id; 285 pcm->codec_dai = dai; 286 287 list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); 288 289 return 0; 290 } 291 292 /* Cometlake digital audio interface glue - connects codec <--> CPU */ 293 294 SND_SOC_DAILINK_DEF(ssp0_pin, 295 DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); 296 SND_SOC_DAILINK_DEF(ssp0_codec, 297 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", 298 CML_RT5682_CODEC_DAI))); 299 300 SND_SOC_DAILINK_DEF(ssp1_pin, 301 DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); 302 SND_SOC_DAILINK_DEF(ssp1_codec, 303 DAILINK_COMP_ARRAY( 304 /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), 305 /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI), 306 /* TL */ COMP_CODEC("i2c-10EC1011:02", CML_RT1011_CODEC_DAI), 307 /* TR */ COMP_CODEC("i2c-10EC1011:03", CML_RT1011_CODEC_DAI))); 308 309 SND_SOC_DAILINK_DEF(dmic_pin, 310 DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); 311 312 SND_SOC_DAILINK_DEF(dmic16k_pin, 313 DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); 314 315 SND_SOC_DAILINK_DEF(dmic_codec, 316 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); 317 318 SND_SOC_DAILINK_DEF(idisp1_pin, 319 DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); 320 SND_SOC_DAILINK_DEF(idisp1_codec, 321 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); 322 323 SND_SOC_DAILINK_DEF(idisp2_pin, 324 DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); 325 SND_SOC_DAILINK_DEF(idisp2_codec, 326 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); 327 328 SND_SOC_DAILINK_DEF(idisp3_pin, 329 DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); 330 SND_SOC_DAILINK_DEF(idisp3_codec, 331 DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); 332 333 SND_SOC_DAILINK_DEF(platform, 334 DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); 335 336 static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { 337 /* Back End DAI links */ 338 { 339 /* SSP0 - Codec */ 340 .name = "SSP0-Codec", 341 .id = 0, 342 .init = cml_rt5682_codec_init, 343 .ignore_pmdown_time = 1, 344 .ops = &cml_rt5682_ops, 345 .dpcm_playback = 1, 346 .dpcm_capture = 1, 347 .no_pcm = 1, 348 SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), 349 }, 350 { 351 .name = "dmic01", 352 .id = 1, 353 .ignore_suspend = 1, 354 .dpcm_capture = 1, 355 .no_pcm = 1, 356 SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), 357 }, 358 { 359 .name = "dmic16k", 360 .id = 2, 361 .ignore_suspend = 1, 362 .dpcm_capture = 1, 363 .no_pcm = 1, 364 SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), 365 }, 366 { 367 .name = "iDisp1", 368 .id = 3, 369 .init = hdmi_init, 370 .dpcm_playback = 1, 371 .no_pcm = 1, 372 SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), 373 }, 374 { 375 .name = "iDisp2", 376 .id = 4, 377 .init = hdmi_init, 378 .dpcm_playback = 1, 379 .no_pcm = 1, 380 SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), 381 }, 382 { 383 .name = "iDisp3", 384 .id = 5, 385 .init = hdmi_init, 386 .dpcm_playback = 1, 387 .no_pcm = 1, 388 SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), 389 }, 390 { 391 /* 392 * SSP1 - Codec : added to end of list ensuring 393 * reuse of common topologies for other end points 394 * and changing only SSP1's codec 395 */ 396 .name = "SSP1-Codec", 397 .id = 6, 398 .dpcm_playback = 1, 399 .dpcm_capture = 1, /* Capture stream provides Feedback */ 400 .no_pcm = 1, 401 .ops = &cml_rt1011_ops, 402 SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), 403 }, 404 }; 405 406 static struct snd_soc_codec_conf rt1011_conf[] = { 407 { 408 .dlc = COMP_CODEC_CONF("i2c-10EC1011:00"), 409 .name_prefix = "WL", 410 }, 411 { 412 .dlc = COMP_CODEC_CONF("i2c-10EC1011:01"), 413 .name_prefix = "WR", 414 }, 415 { 416 .dlc = COMP_CODEC_CONF("i2c-10EC1011:02"), 417 .name_prefix = "TL", 418 }, 419 { 420 .dlc = COMP_CODEC_CONF("i2c-10EC1011:03"), 421 .name_prefix = "TR", 422 }, 423 }; 424 425 /* Cometlake audio machine driver for RT1011 and RT5682 */ 426 static struct snd_soc_card snd_soc_card_cml = { 427 .name = "cml_rt1011_rt5682", 428 .dai_link = cml_rt1011_rt5682_dailink, 429 .num_links = ARRAY_SIZE(cml_rt1011_rt5682_dailink), 430 .codec_conf = rt1011_conf, 431 .num_configs = ARRAY_SIZE(rt1011_conf), 432 .dapm_widgets = cml_rt1011_rt5682_widgets, 433 .num_dapm_widgets = ARRAY_SIZE(cml_rt1011_rt5682_widgets), 434 .dapm_routes = cml_rt1011_rt5682_map, 435 .num_dapm_routes = ARRAY_SIZE(cml_rt1011_rt5682_map), 436 .controls = cml_controls, 437 .num_controls = ARRAY_SIZE(cml_controls), 438 .fully_routed = true, 439 .late_probe = sof_card_late_probe, 440 }; 441 442 static int snd_cml_rt1011_probe(struct platform_device *pdev) 443 { 444 struct card_private *ctx; 445 struct snd_soc_acpi_mach *mach; 446 const char *platform_name; 447 int ret; 448 449 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 450 if (!ctx) 451 return -ENOMEM; 452 453 INIT_LIST_HEAD(&ctx->hdmi_pcm_list); 454 mach = pdev->dev.platform_data; 455 snd_soc_card_cml.dev = &pdev->dev; 456 platform_name = mach->mach_params.platform; 457 458 /* set platform name for each dailink */ 459 ret = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cml, 460 platform_name); 461 if (ret) 462 return ret; 463 464 ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; 465 466 snd_soc_card_set_drvdata(&snd_soc_card_cml, ctx); 467 468 return devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cml); 469 } 470 471 static struct platform_driver snd_cml_rt1011_rt5682_driver = { 472 .probe = snd_cml_rt1011_probe, 473 .driver = { 474 .name = "cml_rt1011_rt5682", 475 .pm = &snd_soc_pm_ops, 476 }, 477 }; 478 module_platform_driver(snd_cml_rt1011_rt5682_driver); 479 480 /* Module information */ 481 MODULE_DESCRIPTION("Cometlake Audio Machine driver - RT1011 and RT5682 in I2S mode"); 482 MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>"); 483 MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>"); 484 MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>"); 485 MODULE_LICENSE("GPL v2"); 486 MODULE_ALIAS("platform:cml_rt1011_rt5682"); 487