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
  17unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1;
  18
  19#define INC_ID(BE, CPU, LINK)   do { (BE)++; (CPU)++; (LINK)++; } while (0)
  20
  21static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
  22{
  23        sof_sdw_quirk = (unsigned long)id->driver_data;
  24        return 1;
  25}
  26
  27static const struct dmi_system_id sof_sdw_quirk_table[] = {
  28        {
  29                .callback = sof_sdw_quirk_cb,
  30                .matches = {
  31                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  32                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6")
  33                },
  34                .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
  35                                        SOF_RT715_DAI_ID_FIX),
  36        },
  37        {
  38                /* early version of SKU 09C6 */
  39                .callback = sof_sdw_quirk_cb,
  40                .matches = {
  41                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  42                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983")
  43                },
  44                .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
  45                                        SOF_RT715_DAI_ID_FIX),
  46        },
  47        {
  48                .callback = sof_sdw_quirk_cb,
  49                .matches = {
  50                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  51                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"),
  52                },
  53                .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
  54                                        SOF_RT715_DAI_ID_FIX |
  55                                        SOF_SDW_FOUR_SPK),
  56        },
  57                {
  58                .callback = sof_sdw_quirk_cb,
  59                .matches = {
  60                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
  61                        DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"),
  62                },
  63                .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 |
  64                                        SOF_RT715_DAI_ID_FIX |
  65                                        SOF_SDW_FOUR_SPK),
  66        },
  67        {
  68                .callback = sof_sdw_quirk_cb,
  69                .matches = {
  70                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  71                        DMI_MATCH(DMI_PRODUCT_NAME,
  72                                  "Tiger Lake Client Platform"),
  73                },
  74                .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
  75                                SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
  76                                SOF_SSP_PORT(SOF_I2S_SSP2)),
  77        },
  78        {
  79                .callback = sof_sdw_quirk_cb,
  80                .matches = {
  81                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  82                        DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
  83                },
  84                .driver_data = (void *)SOF_SDW_PCH_DMIC,
  85        },
  86        {
  87                .callback = sof_sdw_quirk_cb,
  88                .matches = {
  89                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
  90                        DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
  91                },
  92                .driver_data = (void *)SOF_SDW_PCH_DMIC,
  93        },
  94        {
  95                .callback = sof_sdw_quirk_cb,
  96                .matches = {
  97                        DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  98                        DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
  99                },
 100                .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC),
 101        },
 102
 103        {}
 104};
 105
 106static struct snd_soc_codec_conf codec_conf[] = {
 107        {
 108                .dlc = COMP_CODEC_CONF("sdw:0:25d:711:0"),
 109                .name_prefix = "rt711",
 110        },
 111        /* rt1308 w/ I2S connection */
 112        {
 113                .dlc = COMP_CODEC_CONF("i2c-10EC1308:00"),
 114                .name_prefix = "rt1308-1",
 115        },
 116        /* rt1308 left on link 1 */
 117        {
 118                .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0"),
 119                .name_prefix = "rt1308-1",
 120        },
 121        /* two 1308s on link1 with different unique id */
 122        {
 123                .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:0"),
 124                .name_prefix = "rt1308-1",
 125        },
 126        {
 127                .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:2"),
 128                .name_prefix = "rt1308-2",
 129        },
 130        /* rt1308 right on link 2 */
 131        {
 132                .dlc = COMP_CODEC_CONF("sdw:2:25d:1308:0"),
 133                .name_prefix = "rt1308-2",
 134        },
 135        {
 136                .dlc = COMP_CODEC_CONF("sdw:3:25d:715:0"),
 137                .name_prefix = "rt715",
 138        },
 139        {
 140                .dlc = COMP_CODEC_CONF("sdw:0:25d:5682:0"),
 141                .name_prefix = "rt5682",
 142        },
 143};
 144
 145static struct snd_soc_dai_link_component dmic_component[] = {
 146        {
 147                .name = "dmic-codec",
 148                .dai_name = "dmic-hifi",
 149        }
 150};
 151
 152static struct snd_soc_dai_link_component platform_component[] = {
 153        {
 154                /* name might be overridden during probe */
 155                .name = "0000:00:1f.3"
 156        }
 157};
 158
 159/* these wrappers are only needed to avoid typecast compilation errors */
 160static int sdw_startup(struct snd_pcm_substream *substream)
 161{
 162        return sdw_startup_stream(substream);
 163}
 164
 165static void sdw_shutdown(struct snd_pcm_substream *substream)
 166{
 167        sdw_shutdown_stream(substream);
 168}
 169
 170static const struct snd_soc_ops sdw_ops = {
 171        .startup = sdw_startup,
 172        .shutdown = sdw_shutdown,
 173};
 174
 175static struct sof_sdw_codec_info codec_info_list[] = {
 176        {
 177                .id = 0x700,
 178                .direction = {true, true},
 179                .dai_name = "rt700-aif1",
 180                .init = sof_sdw_rt700_init,
 181        },
 182        {
 183                .id = 0x711,
 184                .direction = {true, true},
 185                .dai_name = "rt711-aif1",
 186                .init = sof_sdw_rt711_init,
 187        },
 188        {
 189                .id = 0x1308,
 190                .acpi_id = "10EC1308",
 191                .direction = {true, false},
 192                .dai_name = "rt1308-aif",
 193                .ops = &sof_sdw_rt1308_i2s_ops,
 194                .init = sof_sdw_rt1308_init,
 195        },
 196        {
 197                .id = 0x715,
 198                .direction = {false, true},
 199                .dai_name = "rt715-aif2",
 200                .init = sof_sdw_rt715_init,
 201        },
 202        {
 203                .id = 0x5682,
 204                .direction = {true, true},
 205                .dai_name = "rt5682-sdw",
 206                .init = sof_sdw_rt5682_init,
 207        },
 208};
 209
 210static inline int find_codec_info_part(unsigned int part_id)
 211{
 212        int i;
 213
 214        for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
 215                if (part_id == codec_info_list[i].id)
 216                        break;
 217
 218        if (i == ARRAY_SIZE(codec_info_list))
 219                return -EINVAL;
 220
 221        return i;
 222}
 223
 224static inline int find_codec_info_acpi(const u8 *acpi_id)
 225{
 226        int i;
 227
 228        if (!acpi_id[0])
 229                return -EINVAL;
 230
 231        for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
 232                if (!memcmp(codec_info_list[i].acpi_id, acpi_id,
 233                            ACPI_ID_LEN))
 234                        break;
 235
 236        if (i == ARRAY_SIZE(codec_info_list))
 237                return -EINVAL;
 238
 239        return i;
 240}
 241
 242/*
 243 * get BE dailink number and CPU DAI number based on sdw link adr.
 244 * Since some sdw slaves may be aggregated, the CPU DAI number
 245 * may be larger than the number of BE dailinks.
 246 */
 247static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
 248                                int *sdw_be_num, int *sdw_cpu_dai_num)
 249{
 250        const struct snd_soc_acpi_link_adr *link;
 251        bool group_visited[SDW_MAX_GROUPS];
 252        bool no_aggregation;
 253        int i;
 254
 255        no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
 256        *sdw_cpu_dai_num = 0;
 257        *sdw_be_num  = 0;
 258
 259        if (!links)
 260                return -EINVAL;
 261
 262        for (i = 0; i < SDW_MAX_GROUPS; i++)
 263                group_visited[i] = false;
 264
 265        for (link = links; link->num_adr; link++) {
 266                const struct snd_soc_acpi_endpoint *endpoint;
 267                int part_id, codec_index;
 268                int stream;
 269                u64 adr;
 270
 271                adr = link->adr_d->adr;
 272                part_id = SDW_PART_ID(adr);
 273                codec_index = find_codec_info_part(part_id);
 274                if (codec_index < 0)
 275                        return codec_index;
 276
 277                endpoint = link->adr_d->endpoints;
 278
 279                /* count DAI number for playback and capture */
 280                for_each_pcm_streams(stream) {
 281                        if (!codec_info_list[codec_index].direction[stream])
 282                                continue;
 283
 284                        (*sdw_cpu_dai_num)++;
 285
 286                        /* count BE for each non-aggregated slave or group */
 287                        if (!endpoint->aggregated || no_aggregation ||
 288                            !group_visited[endpoint->group_id])
 289                                (*sdw_be_num)++;
 290                }
 291
 292                if (endpoint->aggregated)
 293                        group_visited[endpoint->group_id] = true;
 294        }
 295
 296        return 0;
 297}
 298
 299static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id,
 300                          char *name, int playback, int capture,
 301                          struct snd_soc_dai_link_component *cpus,
 302                          int cpus_num,
 303                          struct snd_soc_dai_link_component *codecs,
 304                          int codecs_num,
 305                          int (*init)(struct snd_soc_pcm_runtime *rtd),
 306                          const struct snd_soc_ops *ops)
 307{
 308        dai_links->id = be_id;
 309        dai_links->name = name;
 310        dai_links->platforms = platform_component;
 311        dai_links->num_platforms = ARRAY_SIZE(platform_component);
 312        dai_links->nonatomic = true;
 313        dai_links->no_pcm = 1;
 314        dai_links->cpus = cpus;
 315        dai_links->num_cpus = cpus_num;
 316        dai_links->codecs = codecs;
 317        dai_links->num_codecs = codecs_num;
 318        dai_links->dpcm_playback = playback;
 319        dai_links->dpcm_capture = capture;
 320        dai_links->init = init;
 321        dai_links->ops = ops;
 322}
 323
 324static bool is_unique_device(const struct snd_soc_acpi_link_adr *link,
 325                             unsigned int sdw_version,
 326                             unsigned int mfg_id,
 327                             unsigned int part_id,
 328                             unsigned int class_id,
 329                             int index_in_link
 330                            )
 331{
 332        int i;
 333
 334        for (i = 0; i < link->num_adr; i++) {
 335                unsigned int sdw1_version, mfg1_id, part1_id, class1_id;
 336                u64 adr;
 337
 338                /* skip itself */
 339                if (i == index_in_link)
 340                        continue;
 341
 342                adr = link->adr_d[i].adr;
 343
 344                sdw1_version = SDW_VERSION(adr);
 345                mfg1_id = SDW_MFG_ID(adr);
 346                part1_id = SDW_PART_ID(adr);
 347                class1_id = SDW_CLASS_ID(adr);
 348
 349                if (sdw_version == sdw1_version &&
 350                    mfg_id == mfg1_id &&
 351                    part_id == part1_id &&
 352                    class_id == class1_id)
 353                        return false;
 354        }
 355
 356        return true;
 357}
 358
 359static int create_codec_dai_name(struct device *dev,
 360                                 const struct snd_soc_acpi_link_adr *link,
 361                                 struct snd_soc_dai_link_component *codec,
 362                                 int offset)
 363{
 364        int i;
 365
 366        for (i = 0; i < link->num_adr; i++) {
 367                unsigned int sdw_version, unique_id, mfg_id;
 368                unsigned int link_id, part_id, class_id;
 369                int codec_index, comp_index;
 370                char *codec_str;
 371                u64 adr;
 372
 373                adr = link->adr_d[i].adr;
 374
 375                sdw_version = SDW_VERSION(adr);
 376                link_id = SDW_DISCO_LINK_ID(adr);
 377                unique_id = SDW_UNIQUE_ID(adr);
 378                mfg_id = SDW_MFG_ID(adr);
 379                part_id = SDW_PART_ID(adr);
 380                class_id = SDW_CLASS_ID(adr);
 381
 382                comp_index = i + offset;
 383                if (is_unique_device(link, sdw_version, mfg_id, part_id,
 384                                     class_id, i)) {
 385                        codec_str = "sdw:%x:%x:%x:%x";
 386                        codec[comp_index].name =
 387                                devm_kasprintf(dev, GFP_KERNEL, codec_str,
 388                                               link_id, mfg_id, part_id,
 389                                               class_id);
 390                } else {
 391                        codec_str = "sdw:%x:%x:%x:%x:%x";
 392                        codec[comp_index].name =
 393                                devm_kasprintf(dev, GFP_KERNEL, codec_str,
 394                                               link_id, mfg_id, part_id,
 395                                               class_id, unique_id);
 396                }
 397
 398                if (!codec[comp_index].name)
 399                        return -ENOMEM;
 400
 401                codec_index = find_codec_info_part(part_id);
 402                if (codec_index < 0)
 403                        return codec_index;
 404
 405                codec[comp_index].dai_name =
 406                        codec_info_list[codec_index].dai_name;
 407        }
 408
 409        return 0;
 410}
 411
 412static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link,
 413                               struct snd_soc_dai_link *dai_links,
 414                               bool playback, int group_id)
 415{
 416        int i;
 417
 418        do {
 419                /*
 420                 * Initialize the codec. If codec is part of an aggregated
 421                 * group (group_id>0), initialize all codecs belonging to
 422                 * same group.
 423                 */
 424                for (i = 0; i < link->num_adr; i++) {
 425                        unsigned int part_id;
 426                        int codec_index;
 427
 428                        part_id = SDW_PART_ID(link->adr_d[i].adr);
 429                        codec_index = find_codec_info_part(part_id);
 430
 431                        if (codec_index < 0)
 432                                return codec_index;
 433                        /* The group_id is > 0 iff the codec is aggregated */
 434                        if (link->adr_d[i].endpoints->group_id != group_id)
 435                                continue;
 436                        if (codec_info_list[codec_index].init)
 437                                codec_info_list[codec_index].init(link,
 438                                                dai_links,
 439                                                &codec_info_list[codec_index],
 440                                                playback);
 441                }
 442                link++;
 443        } while (link->mask && group_id);
 444
 445        return 0;
 446}
 447
 448/*
 449 * check endpoint status in slaves and gather link ID for all slaves in
 450 * the same group to generate different CPU DAI. Now only support
 451 * one sdw link with all slaves set with only single group id.
 452 *
 453 * one slave on one sdw link with aggregated = 0
 454 * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI
 455 *
 456 * two or more slaves on one sdw link with aggregated = 0
 457 * one sdw BE DAI  <---> one-cpu DAI <---> multi-codec DAIs
 458 *
 459 * multiple links with multiple slaves with aggregated = 1
 460 * one sdw BE DAI  <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs
 461 */
 462static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link,
 463                          struct device *dev, int *cpu_dai_id, int *cpu_dai_num,
 464                          int *codec_num, int *group_id,
 465                          bool *group_generated)
 466{
 467        const struct snd_soc_acpi_adr_device *adr_d;
 468        const struct snd_soc_acpi_link_adr *adr_next;
 469        bool no_aggregation;
 470        int index = 0;
 471
 472        no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION;
 473        *codec_num = adr_link->num_adr;
 474        adr_d = adr_link->adr_d;
 475
 476        /* make sure the link mask has a single bit set */
 477        if (!is_power_of_2(adr_link->mask))
 478                return -EINVAL;
 479
 480        cpu_dai_id[index++] = ffs(adr_link->mask) - 1;
 481        if (!adr_d->endpoints->aggregated || no_aggregation) {
 482                *cpu_dai_num = 1;
 483                *group_id = 0;
 484                return 0;
 485        }
 486
 487        *group_id = adr_d->endpoints->group_id;
 488
 489        /* gather other link ID of slaves in the same group */
 490        for (adr_next = adr_link + 1; adr_next && adr_next->num_adr;
 491                adr_next++) {
 492                const struct snd_soc_acpi_endpoint *endpoint;
 493
 494                endpoint = adr_next->adr_d->endpoints;
 495                if (!endpoint->aggregated ||
 496                    endpoint->group_id != *group_id)
 497                        continue;
 498
 499                /* make sure the link mask has a single bit set */
 500                if (!is_power_of_2(adr_next->mask))
 501                        return -EINVAL;
 502
 503                if (index >= SDW_MAX_CPU_DAIS) {
 504                        dev_err(dev, " cpu_dai_id array overflows");
 505                        return -EINVAL;
 506                }
 507
 508                cpu_dai_id[index++] = ffs(adr_next->mask) - 1;
 509                *codec_num += adr_next->num_adr;
 510        }
 511
 512        /*
 513         * indicate CPU DAIs for this group have been generated
 514         * to avoid generating CPU DAIs for this group again.
 515         */
 516        group_generated[*group_id] = true;
 517        *cpu_dai_num = index;
 518
 519        return 0;
 520}
 521
 522static int create_sdw_dailink(struct device *dev, int *be_index,
 523                              struct snd_soc_dai_link *dai_links,
 524                              int sdw_be_num, int sdw_cpu_dai_num,
 525                              struct snd_soc_dai_link_component *cpus,
 526                              const struct snd_soc_acpi_link_adr *link,
 527                              int *cpu_id, bool *group_generated)
 528{
 529        const struct snd_soc_acpi_link_adr *link_next;
 530        struct snd_soc_dai_link_component *codecs;
 531        int cpu_dai_id[SDW_MAX_CPU_DAIS];
 532        int cpu_dai_num, cpu_dai_index;
 533        unsigned int part_id, group_id;
 534        int codec_idx = 0;
 535        int i = 0, j = 0;
 536        int codec_index;
 537        int codec_num;
 538        int stream;
 539        int ret;
 540        int k;
 541
 542        ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num,
 543                             &group_id, group_generated);
 544        if (ret)
 545                return ret;
 546
 547        codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL);
 548        if (!codecs)
 549                return -ENOMEM;
 550
 551        /* generate codec name on different links in the same group */
 552        for (link_next = link; link_next && link_next->num_adr &&
 553             i < cpu_dai_num; link_next++) {
 554                const struct snd_soc_acpi_endpoint *endpoints;
 555
 556                endpoints = link_next->adr_d->endpoints;
 557                if (group_id && (!endpoints->aggregated ||
 558                                 endpoints->group_id != group_id))
 559                        continue;
 560
 561                /* skip the link excluded by this processed group */
 562                if (cpu_dai_id[i] != ffs(link_next->mask) - 1)
 563                        continue;
 564
 565                ret = create_codec_dai_name(dev, link_next, codecs, codec_idx);
 566                if (ret < 0)
 567                        return ret;
 568
 569                /* check next link to create codec dai in the processed group */
 570                i++;
 571                codec_idx += link_next->num_adr;
 572        }
 573
 574        /* find codec info to create BE DAI */
 575        part_id = SDW_PART_ID(link->adr_d[0].adr);
 576        codec_index = find_codec_info_part(part_id);
 577        if (codec_index < 0)
 578                return codec_index;
 579
 580        cpu_dai_index = *cpu_id;
 581        for_each_pcm_streams(stream) {
 582                char *name, *cpu_name;
 583                int playback, capture;
 584                static const char * const sdw_stream_name[] = {
 585                        "SDW%d-Playback",
 586                        "SDW%d-Capture",
 587                };
 588
 589                if (!codec_info_list[codec_index].direction[stream])
 590                        continue;
 591
 592                /* create stream name according to first link id */
 593                name = devm_kasprintf(dev, GFP_KERNEL,
 594                                      sdw_stream_name[stream], cpu_dai_id[0]);
 595                if (!name)
 596                        return -ENOMEM;
 597
 598                /*
 599                 * generate CPU DAI name base on the sdw link ID and
 600                 * PIN ID with offset of 2 according to sdw dai driver.
 601                 */
 602                for (k = 0; k < cpu_dai_num; k++) {
 603                        cpu_name = devm_kasprintf(dev, GFP_KERNEL,
 604                                                  "SDW%d Pin%d", cpu_dai_id[k],
 605                                                  j + SDW_INTEL_BIDIR_PDI_BASE);
 606                        if (!cpu_name)
 607                                return -ENOMEM;
 608
 609                        if (cpu_dai_index >= sdw_cpu_dai_num) {
 610                                dev_err(dev, "invalid cpu dai index %d",
 611                                        cpu_dai_index);
 612                                return -EINVAL;
 613                        }
 614
 615                        cpus[cpu_dai_index++].dai_name = cpu_name;
 616                }
 617
 618                if (*be_index >= sdw_be_num) {
 619                        dev_err(dev, " invalid be dai index %d", *be_index);
 620                        return -EINVAL;
 621                }
 622
 623                if (*cpu_id >= sdw_cpu_dai_num) {
 624                        dev_err(dev, " invalid cpu dai index %d", *cpu_id);
 625                        return -EINVAL;
 626                }
 627
 628                playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
 629                capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
 630                init_dai_link(dai_links + *be_index, *be_index, name,
 631                              playback, capture,
 632                              cpus + *cpu_id, cpu_dai_num,
 633                              codecs, codec_num,
 634                              NULL, &sdw_ops);
 635
 636                ret = set_codec_init_func(link, dai_links + (*be_index)++,
 637                                          playback, group_id);
 638                if (ret < 0) {
 639                        dev_err(dev, "failed to init codec %d", codec_index);
 640                        return ret;
 641                }
 642
 643                *cpu_id += cpu_dai_num;
 644                j++;
 645        }
 646
 647        return 0;
 648}
 649
 650/*
 651 * DAI link ID of SSP & DMIC & HDMI are based on last
 652 * link ID used by sdw link. Since be_id may be changed
 653 * in init func of sdw codec, it is not equal to be_id
 654 */
 655static inline int get_next_be_id(struct snd_soc_dai_link *links,
 656                                 int be_id)
 657{
 658        return links[be_id - 1].id + 1;
 659}
 660
 661static int sof_card_dai_links_create(struct device *dev,
 662                                     struct snd_soc_acpi_mach *mach,
 663                                     struct snd_soc_card *card)
 664{
 665        int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num;
 666        struct snd_soc_dai_link_component *idisp_components;
 667        struct snd_soc_dai_link_component *ssp_components;
 668        struct snd_soc_acpi_mach_params *mach_params;
 669        const struct snd_soc_acpi_link_adr *adr_link;
 670        struct snd_soc_dai_link_component *cpus;
 671        bool group_generated[SDW_MAX_GROUPS];
 672        int ssp_codec_index, ssp_mask;
 673        struct snd_soc_dai_link *links;
 674        int num_links, link_id = 0;
 675        char *name, *cpu_name;
 676        int total_cpu_dai_num;
 677        int sdw_cpu_dai_num;
 678        int i, j, be_id = 0;
 679        int cpu_id = 0;
 680        int comp_num;
 681        int ret;
 682
 683        /* reset amp_num to ensure amp_num++ starts from 0 in each probe */
 684        for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
 685                codec_info_list[i].amp_num = 0;
 686
 687        hdmi_num = sof_sdw_quirk & SOF_SDW_TGL_HDMI ?
 688                                SOF_TGL_HDMI_COUNT : SOF_PRE_TGL_HDMI_COUNT;
 689
 690        ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk);
 691        /*
 692         * on generic tgl platform, I2S or sdw mode is supported
 693         * based on board rework. A ACPI device is registered in
 694         * system only when I2S mode is supported, not sdw mode.
 695         * Here check ACPI ID to confirm I2S is supported.
 696         */
 697        ssp_codec_index = find_codec_info_acpi(mach->id);
 698        ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0;
 699        comp_num = hdmi_num + ssp_num;
 700
 701        mach_params = &mach->mach_params;
 702        ret = get_sdw_dailink_info(mach_params->links,
 703                                   &sdw_be_num, &sdw_cpu_dai_num);
 704        if (ret < 0) {
 705                dev_err(dev, "failed to get sdw link info %d", ret);
 706                return ret;
 707        }
 708
 709        /* enable dmic01 & dmic16k */
 710        dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0;
 711        comp_num += dmic_num;
 712
 713        dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
 714                dmic_num, hdmi_num);
 715
 716        /* allocate BE dailinks */
 717        num_links = comp_num + sdw_be_num;
 718        links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL);
 719
 720        /* allocated CPU DAIs */
 721        total_cpu_dai_num = comp_num + sdw_cpu_dai_num;
 722        cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus),
 723                            GFP_KERNEL);
 724
 725        if (!links || !cpus)
 726                return -ENOMEM;
 727
 728        /* SDW */
 729        if (!sdw_be_num)
 730                goto SSP;
 731
 732        adr_link = mach_params->links;
 733        if (!adr_link)
 734                return -EINVAL;
 735
 736        /*
 737         * SoundWire Slaves aggregated in the same group may be
 738         * located on different hardware links. Clear array to indicate
 739         * CPU DAIs for this group have not been generated.
 740         */
 741        for (i = 0; i < SDW_MAX_GROUPS; i++)
 742                group_generated[i] = false;
 743
 744        /* generate DAI links by each sdw link */
 745        for (; adr_link->num_adr; adr_link++) {
 746                const struct snd_soc_acpi_endpoint *endpoint;
 747
 748                endpoint = adr_link->adr_d->endpoints;
 749                if (endpoint->aggregated && !endpoint->group_id) {
 750                        dev_err(dev, "invalid group id on link %x",
 751                                adr_link->mask);
 752                        continue;
 753                }
 754
 755                /* this group has been generated */
 756                if (endpoint->aggregated &&
 757                    group_generated[endpoint->group_id])
 758                        continue;
 759
 760                ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num,
 761                                         sdw_cpu_dai_num, cpus, adr_link,
 762                                         &cpu_id, group_generated);
 763                if (ret < 0) {
 764                        dev_err(dev, "failed to create dai link %d", be_id);
 765                        return -ENOMEM;
 766                }
 767        }
 768
 769        /* non-sdw DAI follows sdw DAI */
 770        link_id = be_id;
 771
 772        /* get BE ID for non-sdw DAI */
 773        be_id = get_next_be_id(links, be_id);
 774
 775SSP:
 776        /* SSP */
 777        if (!ssp_num)
 778                goto DMIC;
 779
 780        for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) {
 781                struct sof_sdw_codec_info *info;
 782                int playback, capture;
 783                char *codec_name;
 784
 785                if (!(ssp_mask & 0x1))
 786                        continue;
 787
 788                name = devm_kasprintf(dev, GFP_KERNEL,
 789                                      "SSP%d-Codec", i);
 790                if (!name)
 791                        return -ENOMEM;
 792
 793                cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i);
 794                if (!cpu_name)
 795                        return -ENOMEM;
 796
 797                ssp_components = devm_kzalloc(dev, sizeof(*ssp_components),
 798                                              GFP_KERNEL);
 799                if (!ssp_components)
 800                        return -ENOMEM;
 801
 802                info = &codec_info_list[ssp_codec_index];
 803                codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d",
 804                                            info->acpi_id, j++);
 805                if (!codec_name)
 806                        return -ENOMEM;
 807
 808                ssp_components->name = codec_name;
 809                ssp_components->dai_name = info->dai_name;
 810                cpus[cpu_id].dai_name = cpu_name;
 811
 812                playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
 813                capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
 814                init_dai_link(links + link_id, be_id, name,
 815                              playback, capture,
 816                              cpus + cpu_id, 1,
 817                              ssp_components, 1,
 818                              NULL, info->ops);
 819
 820                ret = info->init(NULL, links + link_id, info, 0);
 821                if (ret < 0)
 822                        return ret;
 823
 824                INC_ID(be_id, cpu_id, link_id);
 825        }
 826
 827DMIC:
 828        /* dmic */
 829        if (dmic_num > 0) {
 830                cpus[cpu_id].dai_name = "DMIC01 Pin";
 831                init_dai_link(links + link_id, be_id, "dmic01",
 832                              0, 1, // DMIC only supports capture
 833                              cpus + cpu_id, 1,
 834                              dmic_component, 1,
 835                              sof_sdw_dmic_init, NULL);
 836                INC_ID(be_id, cpu_id, link_id);
 837
 838                cpus[cpu_id].dai_name = "DMIC16k Pin";
 839                init_dai_link(links + link_id, be_id, "dmic16k",
 840                              0, 1, // DMIC only supports capture
 841                              cpus + cpu_id, 1,
 842                              dmic_component, 1,
 843                              /* don't call sof_sdw_dmic_init() twice */
 844                              NULL, NULL);
 845                INC_ID(be_id, cpu_id, link_id);
 846        }
 847
 848        /* HDMI */
 849        if (hdmi_num > 0) {
 850                idisp_components = devm_kcalloc(dev, hdmi_num,
 851                                                sizeof(*idisp_components),
 852                                                GFP_KERNEL);
 853                if (!idisp_components)
 854                        return -ENOMEM;
 855        }
 856
 857        for (i = 0; i < hdmi_num; i++) {
 858                name = devm_kasprintf(dev, GFP_KERNEL,
 859                                      "iDisp%d", i + 1);
 860                if (!name)
 861                        return -ENOMEM;
 862
 863                idisp_components[i].name = "ehdaudio0D2";
 864                idisp_components[i].dai_name = devm_kasprintf(dev,
 865                                                              GFP_KERNEL,
 866                                                              "intel-hdmi-hifi%d",
 867                                                              i + 1);
 868                if (!idisp_components[i].dai_name)
 869                        return -ENOMEM;
 870
 871                cpu_name = devm_kasprintf(dev, GFP_KERNEL,
 872                                          "iDisp%d Pin", i + 1);
 873                if (!cpu_name)
 874                        return -ENOMEM;
 875
 876                cpus[cpu_id].dai_name = cpu_name;
 877                init_dai_link(links + link_id, be_id, name,
 878                              1, 0, // HDMI only supports playback
 879                              cpus + cpu_id, 1,
 880                              idisp_components + i, 1,
 881                              sof_sdw_hdmi_init, NULL);
 882                INC_ID(be_id, cpu_id, link_id);
 883        }
 884
 885        card->dai_link = links;
 886        card->num_links = num_links;
 887
 888        return 0;
 889}
 890
 891/* SoC card */
 892static const char sdw_card_long_name[] = "Intel Soundwire SOF";
 893
 894static struct snd_soc_card card_sof_sdw = {
 895        .name = "soundwire",
 896        .late_probe = sof_sdw_hdmi_card_late_probe,
 897        .codec_conf = codec_conf,
 898        .num_configs = ARRAY_SIZE(codec_conf),
 899};
 900
 901static int mc_probe(struct platform_device *pdev)
 902{
 903        struct snd_soc_card *card = &card_sof_sdw;
 904        struct snd_soc_acpi_mach *mach;
 905        struct mc_private *ctx;
 906        int amp_num = 0, i;
 907        int ret;
 908
 909        dev_dbg(&pdev->dev, "Entry %s\n", __func__);
 910
 911        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
 912        if (!ctx)
 913                return -ENOMEM;
 914
 915        dmi_check_system(sof_sdw_quirk_table);
 916
 917        INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
 918
 919        card->dev = &pdev->dev;
 920
 921        mach = pdev->dev.platform_data;
 922        ret = sof_card_dai_links_create(&pdev->dev, mach,
 923                                        card);
 924        if (ret < 0)
 925                return ret;
 926
 927        ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
 928
 929        snd_soc_card_set_drvdata(card, ctx);
 930
 931        /*
 932         * the default amp_num is zero for each codec and
 933         * amp_num will only be increased for active amp
 934         * codecs on used platform
 935         */
 936        for (i = 0; i < ARRAY_SIZE(codec_info_list); i++)
 937                amp_num += codec_info_list[i].amp_num;
 938
 939        card->components = devm_kasprintf(card->dev, GFP_KERNEL,
 940                                          "cfg-spk:%d cfg-amp:%d",
 941                                          (sof_sdw_quirk & SOF_SDW_FOUR_SPK)
 942                                          ? 4 : 2, amp_num);
 943        if (!card->components)
 944                return -ENOMEM;
 945
 946        card->long_name = sdw_card_long_name;
 947
 948        /* Register the card */
 949        ret = devm_snd_soc_register_card(&pdev->dev, card);
 950        if (ret) {
 951                dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
 952                return ret;
 953        }
 954
 955        platform_set_drvdata(pdev, card);
 956
 957        return ret;
 958}
 959
 960static struct platform_driver sof_sdw_driver = {
 961        .driver = {
 962                .name = "sof_sdw",
 963                .pm = &snd_soc_pm_ops,
 964        },
 965        .probe = mc_probe,
 966};
 967
 968module_platform_driver(sof_sdw_driver);
 969
 970MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver");
 971MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
 972MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
 973MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
 974MODULE_LICENSE("GPL v2");
 975MODULE_ALIAS("platform:sof_sdw");
 976