linux/sound/soc/intel/boards/sof_sdw.c
<<
>>
Prefs
   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 int mc_probe(struct platform_device *pdev)
1402{
1403        struct snd_soc_card *card = &card_sof_sdw;
1404        struct snd_soc_acpi_mach *mach;
1405        struct mc_private *ctx;
1406        int amp_num = 0, i;
1407        int ret;
1408
1409        dev_dbg(&pdev->dev, "Entry %s\n", __func__);
1410
1411        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
1412        if (!ctx)
1413                return -ENOMEM;
1414
1415        dmi_check_system(sof_sdw_quirk_table);
1416
1417        if (quirk_override != -1) {
1418                dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
1419                         sof_sdw_quirk, quirk_override);
1420                sof_sdw_quirk = quirk_override;
1421        }
1422        log_quirks(&pdev->dev);
1423
1424        INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
1425
1426        card->dev = &pdev->dev;
1427        snd_soc_card_set_drvdata(card, ctx);
1428
1429        mach = pdev->dev.platform_data;
1430        ret = sof_card_dai_links_create(&pdev->dev, mach,
1431                                        card);
1432        if (ret < 0)
1433                return ret;
1434
1435        /*
1436         * the default amp_num is zero for each codec and
1437         * amp_num will only be increased for active amp
1438         * codecs on used platform
1439         */
1440        for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
1441                amp_num += codec_info_list[i].amp_num;
1442
1443        card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1444                                          "cfg-spk:%d cfg-amp:%d",
1445                                          (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
1446                                          ? 4 : 2, amp_num);
1447        if (!card->components)
1448                return -ENOMEM;
1449
1450        if (mach->mach_params.dmic_num) {
1451                card->components = devm_kasprintf(card->dev, GFP_KERNEL,
1452                                                  "%s mic:dmic cfg-mics:%d",
1453                                                  card->components,
1454                                                  mach->mach_params.dmic_num);
1455                if (!card->components)
1456                        return -ENOMEM;
1457        }
1458
1459        card->long_name = sdw_card_long_name;
1460
1461        /* Register the card */
1462        ret = devm_snd_soc_register_card(&pdev->dev, card);
1463        if (ret) {
1464                dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
1465                return ret;
1466        }
1467
1468        platform_set_drvdata(pdev, card);
1469
1470        return ret;
1471}
1472
1473static int mc_remove(struct platform_device *pdev)
1474{
1475        struct snd_soc_card *card = platform_get_drvdata(pdev);
1476        struct snd_soc_dai_link *link;
1477        int ret;
1478        int i, j;
1479
1480        for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
1481                if (!codec_info_list[i].exit)
1482                        continue;
1483                /*
1484                 * We don't need to call .exit function if there is no matched
1485                 * dai link found.
1486                 */
1487                for_each_card_prelinks(card, j, link) {
1488                        if (!strcmp(link->codecs[0].dai_name,
1489                                    codec_info_list[i].dai_name)) {
1490                                ret = codec_info_list[i].exit(card, link);
1491                                if (ret)
1492                                        dev_warn(&pdev->dev,
1493                                                 "codec exit failed %d\n",
1494                                                 ret);
1495                                break;
1496                        }
1497                }
1498        }
1499
1500        return 0;
1501}
1502
1503static struct platform_driver sof_sdw_driver = {
1504        .driver = {
1505                .name = "sof_sdw",
1506                .pm = &snd_soc_pm_ops,
1507        },
1508        .probe = mc_probe,
1509        .remove = mc_remove,
1510};
1511
1512module_platform_driver(sof_sdw_driver);
1513
1514MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
1515MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
1516MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
1517MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
1518MODULE_LICENSE("GPL v2");
1519MODULE_ALIAS("platform:sof_sdw");
1520MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
1521MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
1522