cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sof_sdw.c (39081B)


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