Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
   1// SPDX-License-Identifier: GPL-2.0-only
   2// Copyright (c) 2020 Intel Corporation
   3
   4/*
   5 *  sof_sdw - ASOC Machine driver for Intel SoundWire platforms
   6 */
   7
   8#include <linux/device.h>
   9#include <linux/dmi.h>
  10#include <linux/module.h>
  11#include <linux/soundwire/sdw.h>
  12#include <linux/soundwire/sdw_type.h>
  13#include <sound/soc.h>
  14#include <sound/soc-acpi.h>
  15#include "sof_sdw_common.h"
  16#include "../../codecs/rt711.h"
  17
  18unsigned long sof_sdw_quirk = RT711_JD1;
  19static int quirk_override = -1;
  20module_param_named(quirk, quirk_override, int, 0444);
  21MODULE_PARM_DESC(quirk, "Board-specific quirk override");
  22
  23#define INC_ID(BE, CPU, LINK)	do { (BE)++; (CPU)++; (LINK)++; } while (0)
  24
  25static void log_quirks(struct device *dev)
  26{
  27	if (SOF_RT711_JDSRC(sof_sdw_quirk))
  28		dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n",
  29			SOF_RT711_JDSRC(sof_sdw_quirk));
  30	if (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
  31		dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n");
  32	if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
  33		dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n");
  34	if (sof_sdw_quirk & SOF_SDW_PCH_DMIC)
  35		dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n");
  36	if (SOF_SSP_GET_PORT(sof_sdw_quirk))
  37		dev_dbg(dev, "SSP port %ld\n",
  38			SOF_SSP_GET_PORT(sof_sdw_quirk));
  39	if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION)
  40		dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n");
  41}
  42
  43static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
  44{
  45	sof_sdw_quirk = (unsigned long)id->driver_data;
  46	return 1;
  47}
  48
  49static const struct dmi_system_id sof_sdw_quirk_table[] = {
  50	/* CometLake devices */
  51	{
  52		.callback = sof_sdw_quirk_cb,
  53		.matches = {
  54			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  55			DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
  56		},
  57		.driver_data = (void *)SOF_SDW_PCH_DMIC,
  58	},
  59	{
  60		.callback = sof_sdw_quirk_cb,
  61		.matches = {
  62			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  63			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
  64		},
  65		.driver_data = (void *)RT711_JD2,
  66	},
  67	{
  68		/* early version of SKU 09C6 */
  69		.callback = sof_sdw_quirk_cb,
  70		.matches = {
  71			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  72			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
  73		},
  74		.driver_data = (void *)RT711_JD2,
  75	},
  76	{
  77		.callback = sof_sdw_quirk_cb,
  78		.matches = {
  79			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  80			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
  81		},
  82		.driver_data = (void *)(RT711_JD2 |
  83					SOF_SDW_FOUR_SPK),
  84	},
  85	{
  86		.callback = sof_sdw_quirk_cb,
  87		.matches = {
  88			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  89			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
  90		},
  91		.driver_data = (void *)(RT711_JD2 |
  92					SOF_SDW_FOUR_SPK),
  93	},
  94	/* IceLake devices */
  95	{
  96		.callback = sof_sdw_quirk_cb,
  97		.matches = {
  98			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  99			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
 100		},
 101		.driver_data = (void *)SOF_SDW_PCH_DMIC,
 102	},
 103	/* TigerLake devices */
 104	{
 105		.callback = sof_sdw_quirk_cb,
 106		.matches = {
 107			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
 108			DMI_MATCH(DMI_PRODUCT_NAME,
 109				  "Tiger Lake Client Platform"),
 110		},
 111		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 112					RT711_JD1 |
 113					SOF_SDW_PCH_DMIC |
 114					SOF_SSP_PORT(SOF_I2S_SSP2)),
 115	},
 116	{
 117		.callback = sof_sdw_quirk_cb,
 118		.matches = {
 119			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 120			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
 121		},
 122		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 123					RT711_JD2),
 124	},
 125	{
 126		/* another SKU of Dell Latitude 9520 */
 127		.callback = sof_sdw_quirk_cb,
 128		.matches = {
 129			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 130			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3F")
 131		},
 132		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 133					RT711_JD2),
 134	},
 135	{
 136		/* Dell XPS 9710 */
 137		.callback = sof_sdw_quirk_cb,
 138		.matches = {
 139			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 140			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D")
 141		},
 142		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 143					RT711_JD2 |
 144					SOF_SDW_FOUR_SPK),
 145	},
 146	{
 147		.callback = sof_sdw_quirk_cb,
 148		.matches = {
 149			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 150			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
 151		},
 152		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 153					RT711_JD2 |
 154					SOF_SDW_FOUR_SPK),
 155	},
 156	{
 157		.callback = sof_sdw_quirk_cb,
 158		.matches = {
 159			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
 160			DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
 161		},
 162		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 163					SOF_SDW_PCH_DMIC |
 164					SOF_SDW_FOUR_SPK |
 165					SOF_BT_OFFLOAD_SSP(2) |
 166					SOF_SSP_BT_OFFLOAD_PRESENT),
 167	},
 168	{
 169		.callback = sof_sdw_quirk_cb,
 170		.matches = {
 171			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
 172			DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
 173		},
 174		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 175					SOF_SDW_PCH_DMIC |
 176					SOF_SDW_FOUR_SPK),
 177	},
 178	{
 179		/*
 180		 * this entry covers multiple HP SKUs. The family name
 181		 * does not seem robust enough, so we use a partial
 182		 * match that ignores the product name suffix
 183		 * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
 184		 */
 185		.callback = sof_sdw_quirk_cb,
 186		.matches = {
 187			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
 188			DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
 189		},
 190		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 191					SOF_SDW_PCH_DMIC |
 192					RT711_JD1),
 193	},
 194	{
 195		/* NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
 196		.callback = sof_sdw_quirk_cb,
 197		.matches = {
 198			DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
 199			DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
 200		},
 201		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 202					SOF_SDW_PCH_DMIC |
 203					RT711_JD1),
 204	},
 205	{
 206		/* NUC15 LAPBC710 skews */
 207		.callback = sof_sdw_quirk_cb,
 208		.matches = {
 209			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
 210			DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
 211		},
 212		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 213					SOF_SDW_PCH_DMIC |
 214					RT711_JD1),
 215	},
 216	/* TigerLake-SDCA devices */
 217	{
 218		.callback = sof_sdw_quirk_cb,
 219		.matches = {
 220			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 221			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
 222		},
 223		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 224					RT711_JD2 |
 225					SOF_SDW_FOUR_SPK),
 226	},
 227	{
 228		.callback = sof_sdw_quirk_cb,
 229		.matches = {
 230			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 231			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A45")
 232		},
 233		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 234					RT711_JD2),
 235	},
 236	/* AlderLake devices */
 237	{
 238		.callback = sof_sdw_quirk_cb,
 239		.matches = {
 240			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
 241			DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
 242		},
 243		.driver_data = (void *)(RT711_JD2_100K |
 244					SOF_SDW_TGL_HDMI |
 245					SOF_BT_OFFLOAD_SSP(2) |
 246					SOF_SSP_BT_OFFLOAD_PRESENT),
 247	},
 248	{
 249		.callback = sof_sdw_quirk_cb,
 250		.matches = {
 251			DMI_MATCH(DMI_SYS_VENDOR, "Google"),
 252			DMI_MATCH(DMI_PRODUCT_NAME, "Brya"),
 253		},
 254		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 255					SOF_SDW_PCH_DMIC |
 256					SOF_SDW_FOUR_SPK |
 257					SOF_BT_OFFLOAD_SSP(2) |
 258					SOF_SSP_BT_OFFLOAD_PRESENT),
 259	},
 260	{
 261		.callback = sof_sdw_quirk_cb,
 262		.matches = {
 263			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 264			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0")
 265		},
 266		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 267					RT711_JD2 |
 268					SOF_SDW_FOUR_SPK),
 269	},
 270	{
 271		.callback = sof_sdw_quirk_cb,
 272		.matches = {
 273			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 274			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"),
 275		},
 276		/* No Jack */
 277		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 278					SOF_SDW_FOUR_SPK),
 279	},
 280	{
 281		.callback = sof_sdw_quirk_cb,
 282		.matches = {
 283			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 284			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF")
 285		},
 286		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 287					RT711_JD2 |
 288					SOF_SDW_FOUR_SPK),
 289	},
 290	{
 291		.callback = sof_sdw_quirk_cb,
 292		.matches = {
 293			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 294			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00")
 295		},
 296		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 297					RT711_JD2 |
 298					SOF_SDW_FOUR_SPK),
 299	},
 300	{
 301		.callback = sof_sdw_quirk_cb,
 302		.matches = {
 303			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 304			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01")
 305		},
 306		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 307					RT711_JD2 |
 308					SOF_SDW_FOUR_SPK),
 309	},
 310	{
 311		.callback = sof_sdw_quirk_cb,
 312		.matches = {
 313			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 314			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11")
 315		},
 316		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 317					RT711_JD2 |
 318					SOF_SDW_FOUR_SPK),
 319	},
 320	{
 321		.callback = sof_sdw_quirk_cb,
 322		.matches = {
 323			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 324			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12")
 325		},
 326		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 327					RT711_JD2 |
 328					SOF_SDW_FOUR_SPK),
 329	},
 330	{
 331		.callback = sof_sdw_quirk_cb,
 332		.matches = {
 333			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 334			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B13"),
 335		},
 336		/* No Jack */
 337		.driver_data = (void *)SOF_SDW_TGL_HDMI,
 338	},
 339	{
 340		.callback = sof_sdw_quirk_cb,
 341		.matches = {
 342			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 343			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"),
 344		},
 345		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 346					RT711_JD2 |
 347					SOF_SDW_FOUR_SPK),
 348	},
 349	{
 350		.callback = sof_sdw_quirk_cb,
 351		.matches = {
 352			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
 353			DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-k0xxx"),
 354		},
 355		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 356					RT711_JD2),
 357	},
 358	/* RaptorLake devices */
 359	{
 360		.callback = sof_sdw_quirk_cb,
 361		.matches = {
 362			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 363			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"),
 364		},
 365		/* No Jack */
 366		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 367					SOF_SDW_FOUR_SPK),
 368	},
 369	{
 370		.callback = sof_sdw_quirk_cb,
 371		.matches = {
 372			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 373			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11")
 374		},
 375		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 376					RT711_JD2 |
 377					SOF_SDW_FOUR_SPK),
 378	},
 379	{
 380		.callback = sof_sdw_quirk_cb,
 381		.matches = {
 382			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 383			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40")
 384		},
 385		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 386					RT711_JD2 |
 387					SOF_SDW_FOUR_SPK),
 388	},
 389	{
 390		.callback = sof_sdw_quirk_cb,
 391		.matches = {
 392			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
 393			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F")
 394		},
 395		.driver_data = (void *)(SOF_SDW_TGL_HDMI |
 396					RT711_JD2 |
 397					SOF_SDW_FOUR_SPK),
 398	},
 399	/* MeteorLake devices */
 400	{
 401		.callback = sof_sdw_quirk_cb,
 402		.matches = {
 403			DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_mtlrvp"),
 404		},
 405		.driver_data = (void *)(RT711_JD1 | SOF_SDW_TGL_HDMI),
 406	},
 407	{}
 408};
 409
 410static struct snd_soc_dai_link_component dmic_component[] = {
 411	{
 412		.name = "dmic-codec",
 413		.dai_name = "dmic-hifi",
 414	}
 415};
 416
 417static struct snd_soc_dai_link_component platform_component[] = {
 418	{
 419		/* name might be overridden during probe */
 420		.name = "0000:00:1f.3"
 421	}
 422};
 423
 424/* these wrappers are only needed to avoid typecast compilation errors */
 425int sdw_startup(struct snd_pcm_substream *substream)
 426{
 427	return sdw_startup_stream(substream);
 428}
 429
 430int sdw_prepare(struct snd_pcm_substream *substream)
 431{
 432	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 433	struct sdw_stream_runtime *sdw_stream;
 434	struct snd_soc_dai *dai;
 435
 436	/* Find stream from first CPU DAI */
 437	dai = asoc_rtd_to_cpu(rtd, 0);
 438
 439	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
 440
 441	if (IS_ERR(sdw_stream)) {
 442		dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
 443		return PTR_ERR(sdw_stream);
 444	}
 445
 446	return sdw_prepare_stream(sdw_stream);
 447}
 448
 449int sdw_trigger(struct snd_pcm_substream *substream, int cmd)
 450{
 451	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 452	struct sdw_stream_runtime *sdw_stream;
 453	struct snd_soc_dai *dai;
 454	int ret;
 455
 456	/* Find stream from first CPU DAI */
 457	dai = asoc_rtd_to_cpu(rtd, 0);
 458
 459	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
 460
 461	if (IS_ERR(sdw_stream)) {
 462		dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
 463		return PTR_ERR(sdw_stream);
 464	}
 465
 466	switch (cmd) {
 467	case SNDRV_PCM_TRIGGER_START:
 468	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 469	case SNDRV_PCM_TRIGGER_RESUME:
 470		ret = sdw_enable_stream(sdw_stream);
 471		break;
 472
 473	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 474	case SNDRV_PCM_TRIGGER_SUSPEND:
 475	case SNDRV_PCM_TRIGGER_STOP:
 476		ret = sdw_disable_stream(sdw_stream);
 477		break;
 478	default:
 479		ret = -EINVAL;
 480		break;
 481	}
 482
 483	if (ret)
 484		dev_err(rtd->dev, "%s trigger %d failed: %d", __func__, cmd, ret);
 485
 486	return ret;
 487}
 488
 489int sdw_hw_free(struct snd_pcm_substream *substream)
 490{
 491	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 492	struct sdw_stream_runtime *sdw_stream;
 493	struct snd_soc_dai *dai;
 494
 495	/* Find stream from first CPU DAI */
 496	dai = asoc_rtd_to_cpu(rtd, 0);
 497
 498	sdw_stream = snd_soc_dai_get_stream(dai, substream->stream);
 499
 500	if (IS_ERR(sdw_stream)) {
 501		dev_err(rtd->dev, "no stream found for DAI %s", dai->name);
 502		return PTR_ERR(sdw_stream);
 503	}
 504
 505	return sdw_deprepare_stream(sdw_stream);
 506}
 507
 508void sdw_shutdown(struct snd_pcm_substream *substream)
 509{
 510	sdw_shutdown_stream(substream);
 511}
 512
 513static const struct snd_soc_ops sdw_ops = {
 514	.startup = sdw_startup,
 515	.prepare = sdw_prepare,
 516	.trigger = sdw_trigger,
 517	.hw_free = sdw_hw_free,
 518	.shutdown = sdw_shutdown,
 519};
 520
 521static struct sof_sdw_codec_info codec_info_list[] = {
 522	{
 523		.part_id = 0x700,
 524		.direction = {true, true},
 525		.dai_name = "rt700-aif1",
 526		.init = sof_sdw_rt700_init,
 527		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
 528	},
 529	{
 530		.part_id = 0x711,
 531		.version_id = 3,
 532		.direction = {true, true},
 533		.dai_name = "rt711-sdca-aif1",
 534		.init = sof_sdw_rt711_sdca_init,
 535		.exit = sof_sdw_rt711_sdca_exit,
 536		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
 537	},
 538	{
 539		.part_id = 0x711,
 540		.version_id = 2,
 541		.direction = {true, true},
 542		.dai_name = "rt711-aif1",
 543		.init = sof_sdw_rt711_init,
 544		.exit = sof_sdw_rt711_exit,
 545		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
 546	},
 547	{
 548		.part_id = 0x1308,
 549		.acpi_id = "10EC1308",
 550		.direction = {true, false},
 551		.dai_name = "rt1308-aif",
 552		.ops = &sof_sdw_rt1308_i2s_ops,
 553		.init = sof_sdw_rt_amp_init,
 554		.exit = sof_sdw_rt_amp_exit,
 555		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
 556	},
 557	{
 558		.part_id = 0x1316,
 559		.direction = {true, true},
 560		.dai_name = "rt1316-aif",
 561		.init = sof_sdw_rt_amp_init,
 562		.exit = sof_sdw_rt_amp_exit,
 563		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
 564	},
 565	{
 566		.part_id = 0x1318,
 567		.direction = {true, true},
 568		.dai_name = "rt1318-aif",
 569		.init = sof_sdw_rt_amp_init,
 570		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
 571	},
 572	{
 573		.part_id = 0x714,
 574		.version_id = 3,
 575		.direction = {false, true},
 576		.ignore_pch_dmic = true,
 577		.dai_name = "rt715-aif2",
 578		.init = sof_sdw_rt715_sdca_init,
 579		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
 580	},
 581	{
 582		.part_id = 0x715,
 583		.version_id = 3,
 584		.direction = {false, true},
 585		.ignore_pch_dmic = true,
 586		.dai_name = "rt715-aif2",
 587		.init = sof_sdw_rt715_sdca_init,
 588		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
 589	},
 590	{
 591		.part_id = 0x714,
 592		.version_id = 2,
 593		.direction = {false, true},
 594		.ignore_pch_dmic = true,
 595		.dai_name = "rt715-aif2",
 596		.init = sof_sdw_rt715_init,
 597		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
 598	},
 599	{
 600		.part_id = 0x715,
 601		.version_id = 2,
 602		.direction = {false, true},
 603		.ignore_pch_dmic = true,
 604		.dai_name = "rt715-aif2",
 605		.init = sof_sdw_rt715_init,
 606		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
 607	},
 608	{
 609		.part_id = 0x8373,
 610		.direction = {true, true},
 611		.dai_name = "max98373-aif1",
 612		.init = sof_sdw_mx8373_init,
 613		.codec_card_late_probe = sof_sdw_mx8373_late_probe,
 614		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
 615	},
 616	{
 617		.part_id = 0x5682,
 618		.direction = {true, true},
 619		.dai_name = "rt5682-sdw",
 620		.init = sof_sdw_rt5682_init,
 621		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
 622	},
 623	{
 624		.part_id = 0xaaaa, /* generic codec mockup */
 625		.version_id = 0,
 626		.direction = {true, true},
 627		.dai_name = "sdw-mockup-aif1",
 628		.init = NULL,
 629		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
 630	},
 631	{
 632		.part_id = 0xaa55, /* headset codec mockup */
 633		.version_id = 0,
 634		.direction = {true, true},
 635		.dai_name = "sdw-mockup-aif1",
 636		.init = NULL,
 637		.codec_type = SOF_SDW_CODEC_TYPE_JACK,
 638	},
 639	{
 640		.part_id = 0x55aa, /* amplifier mockup */
 641		.version_id = 0,
 642		.direction = {true, false},
 643		.dai_name = "sdw-mockup-aif1",
 644		.init = NULL,
 645		.codec_type = SOF_SDW_CODEC_TYPE_AMP,
 646	},
 647	{
 648		.part_id = 0x5555,
 649		.version_id = 0,
 650		.direction = {false, true},
 651		.dai_name = "sdw-mockup-aif1",
 652		.codec_type = SOF_SDW_CODEC_TYPE_MIC,
 653	},
 654};
 655
 656static inline int find_codec_info_part(u64 adr)
 657{
 658	unsigned int part_id, sdw_version;
 659	int i;
 660
 661	part_id = SDW_PART_ID(adr);
 662	sdw_version = SDW_VERSION(adr);
 663	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
 664		/*
 665		 * A codec info is for all sdw version with the part id if
 666		 * version_id is not specified in the codec info.
 667		 */
 668		if (part_id == codec_info_list[i].part_id &&
 669		    (!codec_info_list[i].version_id ||
 670		     sdw_version == codec_info_list[i].version_id))
 671			return i;
 672
 673	return -EINVAL;
 674
 675}
 676
 677static inline int find_codec_info_acpi(const u8 *acpi_id)
 678{
 679	int i;
 680
 681	if (!acpi_id[0])
 682		return -EINVAL;
 683
 684	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
 685		if (!memcmp(codec_info_list[i].acpi_id, acpi_id,
 686			    ACPI_ID_LEN))
 687			break;
 688
 689	if (i == ARRAY_SIZE(codec_info_list))
 690		return -EINVAL;
 691
 692	return i;
 693}
 694
 695/*
 696 * get BE dailink number and CPU DAI number based on sdw link adr.
 697 * Since some sdw slaves may be aggregated, the CPU DAI number
 698 * may be larger than the number of BE dailinks.
 699 */
 700static int get_sdw_dailink_info(struct device *dev, const struct snd_soc_acpi_link_adr *links,
 701				int *sdw_be_num, int *sdw_cpu_dai_num)
 702{
 703	const struct snd_soc_acpi_link_adr *link;
 704	int _codec_type = SOF_SDW_CODEC_TYPE_JACK;
 705	bool group_visited[SDW_MAX_GROUPS];
 706	bool no_aggregation;
 707	int i;
 708
 709	no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
 710	*sdw_cpu_dai_num = 0;
 711	*sdw_be_num  = 0;
 712
 713	if (!links)
 714		return -EINVAL;
 715
 716	for (i = 0; i < SDW_MAX_GROUPS; i++)
 717		group_visited[i] = false;
 718
 719	for (link = links; link->num_adr; link++) {
 720		const struct snd_soc_acpi_endpoint *endpoint;
 721		int codec_index;
 722		int stream;
 723		u64 adr;
 724
 725		adr = link->adr_d->adr;
 726		codec_index = find_codec_info_part(adr);
 727		if (codec_index < 0)
 728			return codec_index;
 729
 730		if (codec_info_list[codec_index].codec_type < _codec_type)
 731			dev_warn(dev,
 732				 "Unexpected address table ordering. Expected order: jack -> amp -> mic\n");
 733
 734		_codec_type = codec_info_list[codec_index].codec_type;
 735
 736		endpoint = link->adr_d->endpoints;
 737
 738		/* count DAI number for playback and capture */
 739		for_each_pcm_streams(stream) {
 740			if (!codec_info_list[codec_index].direction[stream])
 741				continue;
 742
 743			(*sdw_cpu_dai_num)++;
 744
 745			/* count BE for each non-aggregated slave or group */
 746			if (!endpoint->aggregated || no_aggregation ||
 747			    !group_visited[endpoint->group_id])
 748				(*sdw_be_num)++;
 749		}
 750
 751		if (endpoint->aggregated)
 752			group_visited[endpoint->group_id] = true;
 753	}
 754
 755	return 0;
 756}
 757
 758static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
 759			  int be_id, char *name, int playback, int capture,
 760			  struct snd_soc_dai_link_component *cpus, int cpus_num,
 761			  struct snd_soc_dai_link_component *codecs, int codecs_num,
 762			  int (*init)(struct snd_soc_pcm_runtime *rtd),
 763			  const struct snd_soc_ops *ops)
 764{
 765	dev_dbg(dev, "create dai link %s, id %d\n", name, be_id);
 766	dai_links->id = be_id;
 767	dai_links->name = name;
 768	dai_links->platforms = platform_component;
 769	dai_links->num_platforms = ARRAY_SIZE(platform_component);
 770	dai_links->no_pcm = 1;
 771	dai_links->cpus = cpus;
 772	dai_links->num_cpus = cpus_num;
 773	dai_links->codecs = codecs;
 774	dai_links->num_codecs = codecs_num;
 775	dai_links->dpcm_playback = playback;
 776	dai_links->dpcm_capture = capture;
 777	dai_links->init = init;
 778	dai_links->ops = ops;
 779}
 780
 781static bool is_unique_device(const struct snd_soc_acpi_link_adr *link,
 782			     unsigned int sdw_version,
 783			     unsigned int mfg_id,
 784			     unsigned int part_id,
 785			     unsigned int class_id,
 786			     int index_in_link
 787			    )
 788{
 789	int i;
 790
 791	for (i = 0; i < link->num_adr; i++) {
 792		unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
 793		u64 adr;
 794
 795		/* skip itself */
 796		if (i == index_in_link)
 797			continue;
 798
 799		adr = link->adr_d[i].adr;
 800
 801		sdw1_version = SDW_VERSION(adr);
 802		mfg1_id = SDW_MFG_ID(adr);
 803		part1_id = SDW_PART_ID(adr);
 804		class1_id = SDW_CLASS_ID(adr);
 805
 806		if (sdw_version == sdw1_version &&
 807		    mfg_id == mfg1_id &&
 808		    part_id == part1_id &&
 809		    class_id == class1_id)
 810			return false;
 811	}
 812
 813	return true;
 814}
 815
 816static int create_codec_dai_name(struct device *dev,
 817				 const struct snd_soc_acpi_link_adr *link,
 818				 struct snd_soc_dai_link_component *codec,
 819				 int offset,
 820				 struct snd_soc_codec_conf *codec_conf,
 821				 int codec_count,
 822				 int *codec_conf_index)
 823{
 824	int i;
 825
 826	/* sanity check */
 827	if (*codec_conf_index + link->num_adr > codec_count) {
 828		dev_err(dev, "codec_conf: out-of-bounds access requested\n");
 829		return -EINVAL;
 830	}
 831
 832	for (i = 0; i < link->num_adr; i++) {
 833		unsigned int sdw_version, unique_id, mfg_id;
 834		unsigned int link_id, part_id, class_id;
 835		int codec_index, comp_index;
 836		char *codec_str;
 837		u64 adr;
 838
 839		adr = link->adr_d[i].adr;
 840
 841		sdw_version = SDW_VERSION(adr);
 842		link_id = SDW_DISCO_LINK_ID(adr);
 843		unique_id = SDW_UNIQUE_ID(adr);
 844		mfg_id = SDW_MFG_ID(adr);
 845		part_id = SDW_PART_ID(adr);
 846		class_id = SDW_CLASS_ID(adr);
 847
 848		comp_index = i + offset;
 849		if (is_unique_device(link, sdw_version, mfg_id, part_id,
 850				     class_id, i)) {
 851			codec_str = "sdw:%01x:%04x:%04x:%02x";
 852			codec[comp_index].name =
 853				devm_kasprintf(dev, GFP_KERNEL, codec_str,
 854					       link_id, mfg_id, part_id,
 855					       class_id);
 856		} else {
 857			codec_str = "sdw:%01x:%04x:%04x:%02x:%01x";
 858			codec[comp_index].name =
 859				devm_kasprintf(dev, GFP_KERNEL, codec_str,
 860					       link_id, mfg_id, part_id,
 861					       class_id, unique_id);
 862		}
 863
 864		if (!codec[comp_index].name)
 865			return -ENOMEM;
 866
 867		codec_index = find_codec_info_part(adr);
 868		if (codec_index < 0)
 869			return codec_index;
 870
 871		codec[comp_index].dai_name =
 872			codec_info_list[codec_index].dai_name;
 873
 874		codec_conf[*codec_conf_index].dlc = codec[comp_index];
 875		codec_conf[*codec_conf_index].name_prefix = link->adr_d[i].name_prefix;
 876
 877		++*codec_conf_index;
 878	}
 879
 880	return 0;
 881}
 882
 883static int set_codec_init_func(struct snd_soc_card *card,
 884			       const struct snd_soc_acpi_link_adr *link,
 885			       struct snd_soc_dai_link *dai_links,
 886			       bool playback, int group_id)
 887{
 888	int i;
 889
 890	do {
 891		/*
 892		 * Initialize the codec. If codec is part of an aggregated
 893		 * group (group_id>0), initialize all codecs belonging to
 894		 * same group.
 895		 */
 896		for (i = 0; i < link->num_adr; i++) {
 897			int codec_index;
 898
 899			codec_index = find_codec_info_part(link->adr_d[i].adr);
 900
 901			if (codec_index < 0)
 902				return codec_index;
 903			/* The group_id is > 0 iff the codec is aggregated */
 904			if (link->adr_d[i].endpoints->group_id != group_id)
 905				continue;
 906			if (codec_info_list[codec_index].init)
 907				codec_info_list[codec_index].init(card,
 908						link,
 909						dai_links,
 910						&codec_info_list[codec_index],
 911						playback);
 912		}
 913		link++;
 914	} while (link->mask && group_id);
 915
 916	return 0;
 917}
 918
 919/*
 920 * check endpoint status in slaves and gather link ID for all slaves in
 921 * the same group to generate different CPU DAI. Now only support
 922 * one sdw link with all slaves set with only single group id.
 923 *
 924 * one slave on one sdw link with aggregated = 0
 925 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI
 926 *
 927 * two or more slaves on one sdw link with aggregated = 0
 928 * one sdw BE DAI  <---> one-cpu DAI <---> multi-codec DAIs
 929 *
 930 * multiple links with multiple slaves with aggregated = 1
 931 * one sdw BE DAI  <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs
 932 */
 933static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
 934			  struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
 935			  int *codec_num, unsigned int *group_id,
 936			  bool *group_generated)
 937{
 938	const struct snd_soc_acpi_adr_device *adr_d;
 939	const struct snd_soc_acpi_link_adr *adr_next;
 940	bool no_aggregation;
 941	int index = 0;
 942
 943	no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
 944	*codec_num = adr_link->num_adr;
 945	adr_d = adr_link->adr_d;
 946
 947	/* make sure the link mask has a single bit set */
 948	if (!is_power_of_2(adr_link->mask))
 949		return -EINVAL;
 950
 951	cpu_dai_id[index++] = ffs(adr_link->mask) - 1;
 952	if (!adr_d->endpoints->aggregated || no_aggregation) {
 953		*cpu_dai_num = 1;
 954		*group_id = 0;
 955		return 0;
 956	}
 957
 958	*group_id = adr_d->endpoints->group_id;
 959
 960	/* gather other link ID of slaves in the same group */
 961	for (adr_next = adr_link + 1; adr_next && adr_next->num_adr;
 962		adr_next++) {
 963		const struct snd_soc_acpi_endpoint *endpoint;
 964
 965		endpoint = adr_next->adr_d->endpoints;
 966		if (!endpoint->aggregated ||
 967		    endpoint->group_id != *group_id)
 968			continue;
 969
 970		/* make sure the link mask has a single bit set */
 971		if (!is_power_of_2(adr_next->mask))
 972			return -EINVAL;
 973
 974		if (index >= SDW_MAX_CPU_DAIS) {
 975			dev_err(dev, " cpu_dai_id array overflows");
 976			return -EINVAL;
 977		}
 978
 979		cpu_dai_id[index++] = ffs(adr_next->mask) - 1;
 980		*codec_num += adr_next->num_adr;
 981	}
 982
 983	/*
 984	 * indicate CPU DAIs for this group have been generated
 985	 * to avoid generating CPU DAIs for this group again.
 986	 */
 987	group_generated[*group_id] = true;
 988	*cpu_dai_num = index;
 989
 990	return 0;
 991}
 992
 993static int create_sdw_dailink(struct snd_soc_card *card,
 994			      struct device *dev, int *link_index,
 995			      struct snd_soc_dai_link *dai_links,
 996			      int sdw_be_num, int sdw_cpu_dai_num,
 997			      struct snd_soc_dai_link_component *cpus,
 998			      const struct snd_soc_acpi_link_adr *link,
 999			      int *cpu_id, bool *group_generated,
1000			      struct snd_soc_codec_conf *codec_conf,
1001			      int codec_count, int *link_id,
1002			      int *codec_conf_index,
1003			      bool *ignore_pch_dmic)
1004{
1005	const struct snd_soc_acpi_link_adr *link_next;
1006	struct snd_soc_dai_link_component *codecs;
1007	int cpu_dai_id[SDW_MAX_CPU_DAIS];
1008	int cpu_dai_num, cpu_dai_index;
1009	unsigned int group_id;
1010	int codec_idx = 0;
1011	int i = 0, j = 0;
1012	int codec_index;
1013	int codec_num;
1014	int stream;
1015	int ret;
1016	int k;
1017
1018	ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
1019			     &group_id, group_generated);
1020	if (ret)
1021		return ret;
1022
1023	codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
1024	if (!codecs)
1025		return -ENOMEM;
1026
1027	/* generate codec name on different links in the same group */
1028	for (link_next = link; link_next && link_next->num_adr &&
1029	     i < cpu_dai_num; link_next++) {
1030		const struct snd_soc_acpi_endpoint *endpoints;
1031
1032		endpoints = link_next->adr_d->endpoints;
1033		if (group_id && (!endpoints->aggregated ||
1034				 endpoints->group_id != group_id))
1035			continue;
1036
1037		/* skip the link excluded by this processed group */
1038		if (cpu_dai_id[i] != ffs(link_next->mask) - 1)
1039			continue;
1040
1041		ret = create_codec_dai_name(dev, link_next, codecs, codec_idx,
1042					    codec_conf, codec_count, codec_conf_index);
1043		if (ret < 0)
1044			return ret;
1045
1046		/* check next link to create codec dai in the processed group */
1047		i++;
1048		codec_idx += link_next->num_adr;
1049	}
1050
1051	/* find codec info to create BE DAI */
1052	codec_index = find_codec_info_part(link->adr_d[0].adr);
1053	if (codec_index < 0)
1054		return codec_index;
1055
1056	if (codec_info_list[codec_index].ignore_pch_dmic)
1057		*ignore_pch_dmic = true;
1058
1059	/* Shift the first amplifier's *link_id to SDW_AMP_DAI_ID */
1060	if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_AMP &&
1061	    *link_id < SDW_AMP_DAI_ID)
1062		*link_id = SDW_AMP_DAI_ID;
1063
1064	/*
1065	 * DAI ID is fixed at SDW_DMIC_DAI_ID for MICs to
1066	 * keep sdw DMIC and HDMI setting static in UCM
1067	 */
1068	if (codec_info_list[codec_index].codec_type == SOF_SDW_CODEC_TYPE_MIC &&
1069	    *link_id < SDW_DMIC_DAI_ID)
1070		*link_id = SDW_DMIC_DAI_ID;
1071
1072	cpu_dai_index = *cpu_id;
1073	for_each_pcm_streams(stream) {
1074		char *name, *cpu_name;
1075		int playback, capture;
1076		static const char * const sdw_stream_name[] = {
1077			"SDW%d-Playback",
1078			"SDW%d-Capture",
1079		};
1080
1081		if (!codec_info_list[codec_index].direction[stream])
1082			continue;
1083
1084		/* create stream name according to first link id */
1085		name = devm_kasprintf(dev, GFP_KERNEL,
1086				      sdw_stream_name[stream], cpu_dai_id[0]);
1087		if (!name)
1088			return -ENOMEM;
1089
1090		/*
1091		 * generate CPU DAI name base on the sdw link ID and
1092		 * PIN ID with offset of 2 according to sdw dai driver.
1093		 */
1094		for (k = 0; k < cpu_dai_num; k++) {
1095			cpu_name = devm_kasprintf(dev, GFP_KERNEL,
1096						  "SDW%d Pin%d", cpu_dai_id[k],
1097						  j + SDW_INTEL_BIDIR_PDI_BASE);
1098			if (!cpu_name)
1099				return -ENOMEM;
1100
1101			if (cpu_dai_index >= sdw_cpu_dai_num) {
1102				dev_err(dev, "invalid cpu dai index %d",
1103					cpu_dai_index);
1104				return -EINVAL;
1105			}
1106
1107			cpus[cpu_dai_index++].dai_name = cpu_name;
1108		}
1109
1110		/*
1111		 * We create sdw dai links at first stage, so link index should
1112		 * not be larger than sdw_be_num
1113		 */
1114		if (*link_index >= sdw_be_num) {
1115			dev_err(dev, "invalid dai link index %d", *link_index);
1116			return -EINVAL;
1117		}
1118
1119		if (*cpu_id >= sdw_cpu_dai_num) {
1120			dev_err(dev, " invalid cpu dai index %d", *cpu_id);
1121			return -EINVAL;
1122		}
1123
1124		playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
1125		capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
1126		init_dai_link(dev, dai_links + *link_index, (*link_id)++, name,
1127			      playback, capture,
1128			      cpus + *cpu_id, cpu_dai_num,
1129			      codecs, codec_num,
1130			      NULL, &sdw_ops);
1131
1132		/*
1133		 * SoundWire DAILINKs use 'stream' functions and Bank Switch operations
1134		 * based on wait_for_completion(), tag them as 'nonatomic'.
1135		 */
1136		dai_links[*link_index].nonatomic = true;
1137
1138		ret = set_codec_init_func(card, link, dai_links + (*link_index)++,
1139					  playback, group_id);
1140		if (ret < 0) {
1141			dev_err(dev, "failed to init codec %d", codec_index);
1142			return ret;
1143		}
1144
1145		*cpu_id += cpu_dai_num;
1146		j++;
1147	}
1148
1149	return 0;
1150}
1151
1152#define IDISP_CODEC_MASK	0x4
1153
1154static int sof_card_codec_conf_alloc(struct device *dev,
1155				     struct snd_soc_acpi_mach_params *mach_params,
1156				     struct snd_soc_codec_conf **codec_conf,
1157				     int *codec_conf_count)
1158{
1159	const struct snd_soc_acpi_link_adr *adr_link;
1160	struct snd_soc_codec_conf *c_conf;
1161	int num_codecs = 0;
1162	int i;
1163
1164	adr_link = mach_params->links;
1165	if (!adr_link)
1166		return -EINVAL;
1167
1168	/* generate DAI links by each sdw link */
1169	for (; adr_link->num_adr; adr_link++) {
1170		for (i = 0; i < adr_link->num_adr; i++) {
1171			if (!adr_link->adr_d[i].name_prefix) {
1172				dev_err(dev, "codec 0x%llx does not have a name prefix\n",
1173					adr_link->adr_d[i].adr);
1174				return -EINVAL;
1175			}
1176		}
1177		num_codecs += adr_link->num_adr;
1178	}
1179
1180	c_conf = devm_kzalloc(dev, num_codecs * sizeof(*c_conf), GFP_KERNEL);
1181	if (!c_conf)
1182		return -ENOMEM;
1183
1184	*codec_conf = c_conf;
1185	*codec_conf_count = num_codecs;
1186
1187	return 0;
1188}
1189
1190static int sof_card_dai_links_create(struct device *dev,
1191				     struct snd_soc_acpi_mach *mach,
1192				     struct snd_soc_card *card)
1193{
1194	int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num;
1195	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
1196	struct snd_soc_dai_link_component *idisp_components;
1197	struct snd_soc_dai_link_component *ssp_components;
1198	struct snd_soc_acpi_mach_params *mach_params;
1199	const struct snd_soc_acpi_link_adr *adr_link;
1200	struct snd_soc_dai_link_component *cpus;
1201	struct snd_soc_codec_conf *codec_conf;
1202	bool ignore_pch_dmic = false;
1203	int codec_conf_count;
1204	int codec_conf_index = 0;
1205	bool group_generated[SDW_MAX_GROUPS];
1206	int ssp_codec_index, ssp_mask;
1207	struct snd_soc_dai_link *links;
1208	int num_links, link_index = 0;
1209	char *name, *cpu_name;
1210	int total_cpu_dai_num;
1211	int sdw_cpu_dai_num;
1212	int i, j, be_id = 0;
1213	int cpu_id = 0;
1214	int comp_num;
1215	int ret;
1216
1217	mach_params = &mach->mach_params;
1218
1219	/* allocate codec conf, will be populated when dailinks are created */
1220	ret = sof_card_codec_conf_alloc(dev, mach_params, &codec_conf, &codec_conf_count);
1221	if (ret < 0)
1222		return ret;
1223
1224	/* reset amp_num to ensure amp_num++ starts from 0 in each probe */
1225	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1226		codec_info_list[i].amp_num = 0;
1227
1228	if (mach_params->codec_mask & IDISP_CODEC_MASK) {
1229		ctx->idisp_codec = true;
1230
1231		if (sof_sdw_quirk & SOF_SDW_TGL_HDMI)
1232			hdmi_num = SOF_TGL_HDMI_COUNT;
1233		else
1234			hdmi_num = SOF_PRE_TGL_HDMI_COUNT;
1235	}
1236
1237	ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
1238	/*
1239	 * on generic tgl platform, I2S or sdw mode is supported
1240	 * based on board rework. A ACPI device is registered in
1241	 * system only when I2S mode is supported, not sdw mode.
1242	 * Here check ACPI ID to confirm I2S is supported.
1243	 */
1244	ssp_codec_index = find_codec_info_acpi(mach->id);
1245	ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0;
1246	comp_num = hdmi_num + ssp_num;
1247
1248	ret = get_sdw_dailink_info(dev, mach_params->links,
1249				   &sdw_be_num, &sdw_cpu_dai_num);
1250	if (ret < 0) {
1251		dev_err(dev, "failed to get sdw link info %d", ret);
1252		return ret;
1253	}
1254
1255	/* enable dmic01 & dmic16k */
1256	dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0;
1257	comp_num += dmic_num;
1258
1259	if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
1260		comp_num++;
1261
1262	dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
1263		dmic_num, ctx->idisp_codec ? hdmi_num : 0);
1264
1265	/* allocate BE dailinks */
1266	num_links = comp_num + sdw_be_num;
1267	links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL);
1268
1269	/* allocated CPU DAIs */
1270	total_cpu_dai_num = comp_num + sdw_cpu_dai_num;
1271	cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus),
1272			    GFP_KERNEL);
1273
1274	if (!links || !cpus)
1275		return -ENOMEM;
1276
1277	/* SDW */
1278	if (!sdw_be_num)
1279		goto SSP;
1280
1281	adr_link = mach_params->links;
1282	if (!adr_link)
1283		return -EINVAL;
1284
1285	/*
1286	 * SoundWire Slaves aggregated in the same group may be
1287	 * located on different hardware links. Clear array to indicate
1288	 * CPU DAIs for this group have not been generated.
1289	 */
1290	for (i = 0; i < SDW_MAX_GROUPS; i++)
1291		group_generated[i] = false;
1292
1293	/* generate DAI links by each sdw link */
1294	for (; adr_link->num_adr; adr_link++) {
1295		const struct snd_soc_acpi_endpoint *endpoint;
1296
1297		endpoint = adr_link->adr_d->endpoints;
1298		if (endpoint->aggregated && !endpoint->group_id) {
1299			dev_err(dev, "invalid group id on link %x",
1300				adr_link->mask);
1301			continue;
1302		}
1303
1304		/* this group has been generated */
1305		if (endpoint->aggregated &&
1306		    group_generated[endpoint->group_id])
1307			continue;
1308
1309		ret = create_sdw_dailink(card, dev, &link_index, links, sdw_be_num,
1310					 sdw_cpu_dai_num, cpus, adr_link,
1311					 &cpu_id, group_generated,
1312					 codec_conf, codec_conf_count,
1313					 &be_id, &codec_conf_index,
1314					 &ignore_pch_dmic);
1315		if (ret < 0) {
1316			dev_err(dev, "failed to create dai link %d", link_index);
1317			return ret;
1318		}
1319	}
1320
1321SSP:
1322	/* SSP */
1323	if (!ssp_num)
1324		goto DMIC;
1325
1326	for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) {
1327		struct sof_sdw_codec_info *info;
1328		int playback, capture;
1329		char *codec_name;
1330
1331		if (!(ssp_mask & 0x1))
1332			continue;
1333
1334		name = devm_kasprintf(dev, GFP_KERNEL,
1335				      "SSP%d-Codec", i);
1336		if (!name)
1337			return -ENOMEM;
1338
1339		cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
1340		if (!cpu_name)
1341			return -ENOMEM;
1342
1343		ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
1344					      GFP_KERNEL);
1345		if (!ssp_components)
1346			return -ENOMEM;
1347
1348		info = &codec_info_list[ssp_codec_index];
1349		codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
1350					    info->acpi_id, j++);
1351		if (!codec_name)
1352			return -ENOMEM;
1353
1354		ssp_components->name = codec_name;
1355		ssp_components->dai_name = info->dai_name;
1356		cpus[cpu_id].dai_name = cpu_name;
1357
1358		playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
1359		capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
1360		init_dai_link(dev, links + link_index, be_id, name,
1361			      playback, capture,
1362			      cpus + cpu_id, 1,
1363			      ssp_components, 1,
1364			      NULL, info->ops);
1365
1366		ret = info->init(card, NULL, links + link_index, info, 0);
1367		if (ret < 0)
1368			return ret;
1369
1370		INC_ID(be_id, cpu_id, link_index);
1371	}
1372
1373DMIC:
1374	/* dmic */
1375	if (dmic_num > 0) {
1376		if (ignore_pch_dmic) {
1377			dev_warn(dev, "Ignoring PCH DMIC\n");
1378			goto HDMI;
1379		}
1380		cpus[cpu_id].dai_name = "DMIC01 Pin";
1381		init_dai_link(dev, links + link_index, be_id, "dmic01",
1382			      0, 1, // DMIC only supports capture
1383			      cpus + cpu_id, 1,
1384			      dmic_component, 1,
1385			      sof_sdw_dmic_init, NULL);
1386		INC_ID(be_id, cpu_id, link_index);
1387
1388		cpus[cpu_id].dai_name = "DMIC16k Pin";
1389		init_dai_link(dev, links + link_index, be_id, "dmic16k",
1390			      0, 1, // DMIC only supports capture
1391			      cpus + cpu_id, 1,
1392			      dmic_component, 1,
1393			      /* don't call sof_sdw_dmic_init() twice */
1394			      NULL, NULL);
1395		INC_ID(be_id, cpu_id, link_index);
1396	}
1397
1398HDMI:
1399	/* HDMI */
1400	if (hdmi_num > 0) {
1401		idisp_components = devm_kcalloc(dev, hdmi_num,
1402						sizeof(*idisp_components),
1403						GFP_KERNEL);
1404		if (!idisp_components)
1405			return -ENOMEM;
1406	}
1407
1408	for (i = 0; i < hdmi_num; i++) {
1409		name = devm_kasprintf(dev, GFP_KERNEL,
1410				      "iDisp%d", i + 1);
1411		if (!name)
1412			return -ENOMEM;
1413
1414		if (ctx->idisp_codec) {
1415			idisp_components[i].name = "ehdaudio0D2";
1416			idisp_components[i].dai_name = devm_kasprintf(dev,
1417								      GFP_KERNEL,
1418								      "intel-hdmi-hifi%d",
1419								      i + 1);
1420			if (!idisp_components[i].dai_name)
1421				return -ENOMEM;
1422		} else {
1423			idisp_components[i].name = "snd-soc-dummy";
1424			idisp_components[i].dai_name = "snd-soc-dummy-dai";
1425		}
1426
1427		cpu_name = devm_kasprintf(dev, GFP_KERNEL,
1428					  "iDisp%d Pin", i + 1);
1429		if (!cpu_name)
1430			return -ENOMEM;
1431
1432		cpus[cpu_id].dai_name = cpu_name;
1433		init_dai_link(dev, links + link_index, be_id, name,
1434			      1, 0, // HDMI only supports playback
1435			      cpus + cpu_id, 1,
1436			      idisp_components + i, 1,
1437			      sof_sdw_hdmi_init, NULL);
1438		INC_ID(be_id, cpu_id, link_index);
1439	}
1440
1441	if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
1442		int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
1443				SOF_BT_OFFLOAD_SSP_SHIFT;
1444
1445		name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
1446		if (!name)
1447			return -ENOMEM;
1448
1449		ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
1450						GFP_KERNEL);
1451		if (!ssp_components)
1452			return -ENOMEM;
1453
1454		ssp_components->name = "snd-soc-dummy";
1455		ssp_components->dai_name = "snd-soc-dummy-dai";
1456
1457		cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port);
1458		if (!cpu_name)
1459			return -ENOMEM;
1460
1461		cpus[cpu_id].dai_name = cpu_name;
1462		init_dai_link(dev, links + link_index, be_id, name, 1, 1,
1463				cpus + cpu_id, 1, ssp_components, 1, NULL, NULL);
1464	}
1465
1466	card->dai_link = links;
1467	card->num_links = num_links;
1468
1469	card->codec_conf = codec_conf;
1470	card->num_configs = codec_conf_count;
1471
1472	return 0;
1473}
1474
1475static int sof_sdw_card_late_probe(struct snd_soc_card *card)
1476{
1477	struct mc_private *ctx = snd_soc_card_get_drvdata(card);
1478	int ret = 0;
1479	int i;
1480
1481	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1482		if (!codec_info_list[i].late_probe)
1483			continue;
1484
1485		ret = codec_info_list[i].codec_card_late_probe(card);
1486		if (ret < 0)
1487			return ret;
1488	}
1489
1490	if (ctx->idisp_codec)
1491		ret = sof_sdw_hdmi_card_late_probe(card);
1492
1493	return ret;
1494}
1495
1496/* SoC card */
1497static const char sdw_card_long_name[] = "Intel Soundwire SOF";
1498
1499static struct snd_soc_card card_sof_sdw = {
1500	.name = "soundwire",
1501	.owner = THIS_MODULE,
1502	.late_probe = sof_sdw_card_late_probe,
1503};
1504
1505static void mc_dailink_exit_loop(struct snd_soc_card *card)
1506{
1507	struct snd_soc_dai_link *link;
1508	int ret;
1509	int i, j;
1510
1511	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1512		if (!codec_info_list[i].exit)
1513			continue;
1514		/*
1515		 * We don't need to call .exit function if there is no matched
1516		 * dai link found.
1517		 */
1518		for_each_card_prelinks(card, j, link) {
1519			if (!strcmp(link->codecs[0].dai_name,
1520				    codec_info_list[i].dai_name)) {
1521				ret = codec_info_list[i].exit(card, link);
1522				if (ret)
1523					dev_warn(card->dev,
1524						 "codec exit failed %d\n",
1525						 ret);
1526				break;
1527			}
1528		}
1529	}
1530}
1531
1532static int mc_probe(struct platform_device *pdev)
1533{
1534	struct snd_soc_card *card = &card_sof_sdw;
1535	struct snd_soc_acpi_mach *mach;
1536	struct mc_private *ctx;
1537	int amp_num = 0, i;
1538	int ret;
1539
1540	dev_dbg(&pdev->dev, "Entry\n");
1541
1542	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1543	if (!ctx)
1544		return -ENOMEM;
1545
1546	dmi_check_system(sof_sdw_quirk_table);
1547
1548	if (quirk_override != -1) {
1549		dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
1550			 sof_sdw_quirk, quirk_override);
1551		sof_sdw_quirk = quirk_override;
1552	}
1553	log_quirks(&pdev->dev);
1554
1555	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
1556
1557	card->dev = &pdev->dev;
1558	snd_soc_card_set_drvdata(card, ctx);
1559
1560	mach = pdev->dev.platform_data;
1561	ret = sof_card_dai_links_create(&pdev->dev, mach,
1562					card);
1563	if (ret < 0)
1564		return ret;
1565
1566	/*
1567	 * the default amp_num is zero for each codec and
1568	 * amp_num will only be increased for active amp
1569	 * codecs on used platform
1570	 */
1571	for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1572		amp_num += codec_info_list[i].amp_num;
1573
1574	card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1575					  "cfg-spk:%d cfg-amp:%d",
1576					  (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
1577					  ? 4 : 2, amp_num);
1578	if (!card->components)
1579		return -ENOMEM;
1580
1581	if (mach->mach_params.dmic_num) {
1582		card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1583						  "%s mic:dmic cfg-mics:%d",
1584						  card->components,
1585						  mach->mach_params.dmic_num);
1586		if (!card->components)
1587			return -ENOMEM;
1588	}
1589
1590	card->long_name = sdw_card_long_name;
1591
1592	/* Register the card */
1593	ret = devm_snd_soc_register_card(&pdev->dev, card);
1594	if (ret) {
1595		dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
1596		mc_dailink_exit_loop(card);
1597		return ret;
1598	}
1599
1600	platform_set_drvdata(pdev, card);
1601
1602	return ret;
1603}
1604
1605static int mc_remove(struct platform_device *pdev)
1606{
1607	struct snd_soc_card *card = platform_get_drvdata(pdev);
1608
1609	mc_dailink_exit_loop(card);
1610
1611	return 0;
1612}
1613
1614static struct platform_driver sof_sdw_driver = {
1615	.driver = {
1616		.name = "sof_sdw",
1617		.pm = &snd_soc_pm_ops,
1618	},
1619	.probe = mc_probe,
1620	.remove = mc_remove,
1621};
1622
1623module_platform_driver(sof_sdw_driver);
1624
1625MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
1626MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1627MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
1628MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1629MODULE_LICENSE("GPL v2");
1630MODULE_ALIAS("platform:sof_sdw");
1631MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
1632MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);