linux/sound/soc/intel/boards/sof_rt5682.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2// Copyright(c) 2019-2020 Intel Corporation.
   3
   4/*
   5 * Intel SOF Machine Driver with Realtek rt5682 Codec
   6 * and speaker codec MAX98357A or RT1015.
   7 */
   8#include <linux/i2c.h>
   9#include <linux/input.h>
  10#include <linux/module.h>
  11#include <linux/platform_device.h>
  12#include <linux/clk.h>
  13#include <linux/dmi.h>
  14#include <sound/core.h>
  15#include <sound/jack.h>
  16#include <sound/pcm.h>
  17#include <sound/pcm_params.h>
  18#include <sound/soc.h>
  19#include <sound/sof.h>
  20#include <sound/rt5682.h>
  21#include <sound/rt5682s.h>
  22#include <sound/soc-acpi.h>
  23#include "../../codecs/rt5682.h"
  24#include "../../codecs/rt5682s.h"
  25#include "../../codecs/hdac_hdmi.h"
  26#include "../common/soc-intel-quirks.h"
  27#include "hda_dsp_common.h"
  28#include "sof_maxim_common.h"
  29#include "sof_realtek_common.h"
  30
  31#define NAME_SIZE 32
  32
  33#define SOF_RT5682_SSP_CODEC(quirk)             ((quirk) & GENMASK(2, 0))
  34#define SOF_RT5682_SSP_CODEC_MASK                       (GENMASK(2, 0))
  35#define SOF_RT5682_MCLK_EN                      BIT(3)
  36#define SOF_RT5682_MCLK_24MHZ                   BIT(4)
  37#define SOF_SPEAKER_AMP_PRESENT         BIT(5)
  38#define SOF_RT5682_SSP_AMP_SHIFT                6
  39#define SOF_RT5682_SSP_AMP_MASK                 (GENMASK(8, 6))
  40#define SOF_RT5682_SSP_AMP(quirk)       \
  41        (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK)
  42#define SOF_RT5682_MCLK_BYTCHT_EN               BIT(9)
  43#define SOF_RT5682_NUM_HDMIDEV_SHIFT            10
  44#define SOF_RT5682_NUM_HDMIDEV_MASK             (GENMASK(12, 10))
  45#define SOF_RT5682_NUM_HDMIDEV(quirk)   \
  46        ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK)
  47#define SOF_RT1011_SPEAKER_AMP_PRESENT          BIT(13)
  48#define SOF_RT1015_SPEAKER_AMP_PRESENT          BIT(14)
  49#define SOF_RT1015_SPEAKER_AMP_100FS            BIT(15)
  50#define SOF_RT1015P_SPEAKER_AMP_PRESENT         BIT(16)
  51#define SOF_MAX98373_SPEAKER_AMP_PRESENT        BIT(17)
  52#define SOF_MAX98360A_SPEAKER_AMP_PRESENT       BIT(18)
  53
  54/* BT audio offload: reserve 3 bits for future */
  55#define SOF_BT_OFFLOAD_SSP_SHIFT                19
  56#define SOF_BT_OFFLOAD_SSP_MASK         (GENMASK(21, 19))
  57#define SOF_BT_OFFLOAD_SSP(quirk)       \
  58        (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
  59#define SOF_SSP_BT_OFFLOAD_PRESENT              BIT(22)
  60#define SOF_RT5682S_HEADPHONE_CODEC_PRESENT     BIT(23)
  61#define SOF_MAX98390_SPEAKER_AMP_PRESENT        BIT(24)
  62#define SOF_MAX98390_TWEETER_SPEAKER_PRESENT    BIT(25)
  63
  64
  65/* Default: MCLK on, MCLK 19.2M, SSP0  */
  66static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
  67                                        SOF_RT5682_SSP_CODEC(0);
  68
  69static int is_legacy_cpu;
  70
  71static struct snd_soc_jack sof_hdmi[3];
  72
  73struct sof_hdmi_pcm {
  74        struct list_head head;
  75        struct snd_soc_dai *codec_dai;
  76        int device;
  77};
  78
  79struct sof_card_private {
  80        struct clk *mclk;
  81        struct snd_soc_jack sof_headset;
  82        struct list_head hdmi_pcm_list;
  83        bool common_hdmi_codec_drv;
  84        bool idisp_codec;
  85};
  86
  87static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
  88{
  89        sof_rt5682_quirk = (unsigned long)id->driver_data;
  90        return 1;
  91}
  92
  93static const struct dmi_system_id sof_rt5682_quirk_table[] = {
  94        {
  95                .callback = sof_rt5682_quirk_cb,
  96                .matches = {
  97                        DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
  98                        DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
  99                },
 100                .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
 101        },
 102        {
 103                .callback = sof_rt5682_quirk_cb,
 104                .matches = {
 105                        DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
 106                        DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
 107                },
 108                .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
 109        },
 110        {
 111                .callback = sof_rt5682_quirk_cb,
 112                .matches = {
 113                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
 114                        DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
 115                },
 116                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 117                                        SOF_RT5682_MCLK_24MHZ |
 118                                        SOF_RT5682_SSP_CODEC(1)),
 119        },
 120        {
 121                /*
 122                 * Dooly is hatch family but using rt1015 amp so it
 123                 * requires a quirk before "Google_Hatch".
 124                 */
 125                .callback = sof_rt5682_quirk_cb,
 126                .matches = {
 127                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
 128                        DMI_MATCH(DMI_PRODUCT_NAME, "Dooly"),
 129                },
 130                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 131                                        SOF_RT5682_MCLK_24MHZ |
 132                                        SOF_RT5682_SSP_CODEC(0) |
 133                                        SOF_SPEAKER_AMP_PRESENT |
 134                                        SOF_RT1015_SPEAKER_AMP_PRESENT |
 135                                        SOF_RT1015_SPEAKER_AMP_100FS |
 136                                        SOF_RT5682_SSP_AMP(1)),
 137        },
 138        {
 139                .callback = sof_rt5682_quirk_cb,
 140                .matches = {
 141                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
 142                },
 143                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 144                                        SOF_RT5682_MCLK_24MHZ |
 145                                        SOF_RT5682_SSP_CODEC(0) |
 146                                        SOF_SPEAKER_AMP_PRESENT |
 147                                        SOF_RT5682_SSP_AMP(1)),
 148        },
 149        {
 150                .callback = sof_rt5682_quirk_cb,
 151                .matches = {
 152                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
 153                        DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
 154                },
 155                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 156                                        SOF_RT5682_SSP_CODEC(0)),
 157        },
 158        {
 159                .callback = sof_rt5682_quirk_cb,
 160                .matches = {
 161                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"),
 162                        DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"),
 163                },
 164                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 165                                        SOF_RT5682_SSP_CODEC(0) |
 166                                        SOF_SPEAKER_AMP_PRESENT |
 167                                        SOF_MAX98373_SPEAKER_AMP_PRESENT |
 168                                        SOF_RT5682_SSP_AMP(2) |
 169                                        SOF_RT5682_NUM_HDMIDEV(4)),
 170        },
 171        {
 172                .callback = sof_rt5682_quirk_cb,
 173                .matches = {
 174                        DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
 175                        DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
 176                        DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
 177                },
 178                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 179                                        SOF_RT5682_SSP_CODEC(0) |
 180                                        SOF_SPEAKER_AMP_PRESENT |
 181                                        SOF_MAX98373_SPEAKER_AMP_PRESENT |
 182                                        SOF_RT5682_SSP_AMP(2) |
 183                                        SOF_RT5682_NUM_HDMIDEV(4)),
 184        },
 185        {
 186                .callback = sof_rt5682_quirk_cb,
 187                .matches = {
 188                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
 189                        DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"),
 190                },
 191                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 192                                        SOF_RT5682_SSP_CODEC(0) |
 193                                        SOF_SPEAKER_AMP_PRESENT |
 194                                        SOF_MAX98390_SPEAKER_AMP_PRESENT |
 195                                        SOF_RT5682_SSP_AMP(2) |
 196                                        SOF_RT5682_NUM_HDMIDEV(4)),
 197        },
 198        {
 199                .callback = sof_rt5682_quirk_cb,
 200                .matches = {
 201                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
 202                        DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S_4SPK"),
 203                },
 204                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 205                                        SOF_RT5682_SSP_CODEC(0) |
 206                                        SOF_SPEAKER_AMP_PRESENT |
 207                                        SOF_MAX98390_SPEAKER_AMP_PRESENT |
 208                                        SOF_MAX98390_TWEETER_SPEAKER_PRESENT |
 209                                        SOF_RT5682_SSP_AMP(1) |
 210                                        SOF_RT5682_NUM_HDMIDEV(4) |
 211                                        SOF_BT_OFFLOAD_SSP(2) |
 212                                        SOF_SSP_BT_OFFLOAD_PRESENT),
 213
 214        },
 215        {
 216                .callback = sof_rt5682_quirk_cb,
 217                .matches = {
 218                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
 219                        DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"),
 220                },
 221                .driver_data = (void *)(SOF_RT5682_MCLK_EN |
 222                                        SOF_RT5682_SSP_CODEC(0) |
 223                                        SOF_SPEAKER_AMP_PRESENT |
 224                                        SOF_MAX98360A_SPEAKER_AMP_PRESENT |
 225                                        SOF_RT5682_SSP_AMP(2) |
 226                                        SOF_RT5682_NUM_HDMIDEV(4)),
 227        },
 228        {}
 229};
 230
 231static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
 232{
 233        struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
 234        struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
 235        struct sof_hdmi_pcm *pcm;
 236
 237        pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
 238        if (!pcm)
 239                return -ENOMEM;
 240
 241        /* dai_link id is 1:1 mapped to the PCM device */
 242        pcm->device = rtd->dai_link->id;
 243        pcm->codec_dai = dai;
 244
 245        list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
 246
 247        return 0;
 248}
 249
 250static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
 251{
 252        struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
 253        struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
 254        struct snd_soc_jack *jack;
 255        int ret;
 256
 257        /* need to enable ASRC function for 24MHz mclk rate */
 258        if ((sof_rt5682_quirk & SOF_RT5682_MCLK_EN) &&
 259            (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)) {
 260                if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
 261                        rt5682s_sel_asrc_clk_src(component,
 262                                                 RT5682S_DA_STEREO1_FILTER |
 263                                                 RT5682S_AD_STEREO1_FILTER,
 264                                                 RT5682S_CLK_SEL_I2S1_ASRC);
 265                else
 266                        rt5682_sel_asrc_clk_src(component,
 267                                                RT5682_DA_STEREO1_FILTER |
 268                                                RT5682_AD_STEREO1_FILTER,
 269                                                RT5682_CLK_SEL_I2S1_ASRC);
 270        }
 271
 272        if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
 273                /*
 274                 * The firmware might enable the clock at
 275                 * boot (this information may or may not
 276                 * be reflected in the enable clock register).
 277                 * To change the rate we must disable the clock
 278                 * first to cover these cases. Due to common
 279                 * clock framework restrictions that do not allow
 280                 * to disable a clock that has not been enabled,
 281                 * we need to enable the clock first.
 282                 */
 283                ret = clk_prepare_enable(ctx->mclk);
 284                if (!ret)
 285                        clk_disable_unprepare(ctx->mclk);
 286
 287                ret = clk_set_rate(ctx->mclk, 19200000);
 288
 289                if (ret)
 290                        dev_err(rtd->dev, "unable to set MCLK rate\n");
 291        }
 292
 293        /*
 294         * Headset buttons map to the google Reference headset.
 295         * These can be configured by userspace.
 296         */
 297        ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
 298                                    SND_JACK_HEADSET | SND_JACK_BTN_0 |
 299                                    SND_JACK_BTN_1 | SND_JACK_BTN_2 |
 300                                    SND_JACK_BTN_3,
 301                                    &ctx->sof_headset, NULL, 0);
 302        if (ret) {
 303                dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
 304                return ret;
 305        }
 306
 307        jack = &ctx->sof_headset;
 308
 309        snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
 310        snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
 311        snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
 312        snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
 313        ret = snd_soc_component_set_jack(component, jack, NULL);
 314
 315        if (ret) {
 316                dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
 317                return ret;
 318        }
 319
 320        return ret;
 321};
 322
 323static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
 324{
 325        struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
 326
 327        snd_soc_component_set_jack(component, NULL, NULL);
 328}
 329
 330static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
 331                                struct snd_pcm_hw_params *params)
 332{
 333        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 334        struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
 335        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 336        int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
 337
 338        if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
 339                if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
 340                        ret = clk_prepare_enable(ctx->mclk);
 341                        if (ret < 0) {
 342                                dev_err(rtd->dev,
 343                                        "could not configure MCLK state");
 344                                return ret;
 345                        }
 346                }
 347
 348                if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
 349                        pll_source = RT5682S_PLL_S_MCLK;
 350                else
 351                        pll_source = RT5682_PLL1_S_MCLK;
 352
 353                /* get the tplg configured mclk. */
 354                pll_in = sof_dai_get_mclk(rtd);
 355
 356                /* mclk from the quirk is the first choice */
 357                if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ) {
 358                        if (pll_in != 24000000)
 359                                dev_warn(rtd->dev, "configure wrong mclk in tplg, please use 24MHz.\n");
 360                        pll_in = 24000000;
 361                } else if (pll_in == 0) {
 362                        /* use default mclk if not specified correct in topology */
 363                        pll_in = 19200000;
 364                } else if (pll_in < 0) {
 365                        return pll_in;
 366                }
 367        } else {
 368                if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT)
 369                        pll_source = RT5682S_PLL_S_BCLK1;
 370                else
 371                        pll_source = RT5682_PLL1_S_BCLK1;
 372
 373                pll_in = params_rate(params) * 50;
 374        }
 375
 376        if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {
 377                pll_id = RT5682S_PLL2;
 378                clk_id = RT5682S_SCLK_S_PLL2;
 379        } else {
 380                pll_id = RT5682_PLL1;
 381                clk_id = RT5682_SCLK_S_PLL1;
 382        }
 383
 384        pll_out = params_rate(params) * 512;
 385
 386        /* when MCLK is 512FS, no need to set PLL configuration additionally. */
 387        if (pll_in == pll_out)
 388                clk_id = RT5682S_SCLK_S_MCLK;
 389        else {
 390                /* Configure pll for codec */
 391                ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in,
 392                                          pll_out);
 393                if (ret < 0)
 394                        dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
 395        }
 396
 397        /* Configure sysclk for codec */
 398        ret = snd_soc_dai_set_sysclk(codec_dai, clk_id,
 399                                     pll_out, SND_SOC_CLOCK_IN);
 400        if (ret < 0)
 401                dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
 402
 403        /*
 404         * slot_width should equal or large than data length, set them
 405         * be the same
 406         */
 407        ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
 408                                       params_width(params));
 409        if (ret < 0) {
 410                dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
 411                return ret;
 412        }
 413
 414        return ret;
 415}
 416
 417static struct snd_soc_ops sof_rt5682_ops = {
 418        .hw_params = sof_rt5682_hw_params,
 419};
 420
 421static struct snd_soc_dai_link_component platform_component[] = {
 422        {
 423                /* name might be overridden during probe */
 424                .name = "0000:00:1f.3"
 425        }
 426};
 427
 428static int sof_card_late_probe(struct snd_soc_card *card)
 429{
 430        struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
 431        struct snd_soc_component *component = NULL;
 432        struct snd_soc_dapm_context *dapm = &card->dapm;
 433        char jack_name[NAME_SIZE];
 434        struct sof_hdmi_pcm *pcm;
 435        int err;
 436        int i = 0;
 437
 438        /* HDMI is not supported by SOF on Baytrail/CherryTrail */
 439        if (is_legacy_cpu || !ctx->idisp_codec)
 440                return 0;
 441
 442        if (list_empty(&ctx->hdmi_pcm_list))
 443                return -EINVAL;
 444
 445        if (ctx->common_hdmi_codec_drv) {
 446                pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
 447                                       head);
 448                component = pcm->codec_dai->component;
 449                return hda_dsp_hdmi_build_controls(card, component);
 450        }
 451
 452        list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
 453                component = pcm->codec_dai->component;
 454                snprintf(jack_name, sizeof(jack_name),
 455                         "HDMI/DP, pcm=%d Jack", pcm->device);
 456                err = snd_soc_card_jack_new(card, jack_name,
 457                                            SND_JACK_AVOUT, &sof_hdmi[i],
 458                                            NULL, 0);
 459
 460                if (err)
 461                        return err;
 462
 463                err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
 464                                          &sof_hdmi[i]);
 465                if (err < 0)
 466                        return err;
 467
 468                i++;
 469        }
 470
 471        if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
 472                /* Disable Left and Right Spk pin after boot */
 473                snd_soc_dapm_disable_pin(dapm, "Left Spk");
 474                snd_soc_dapm_disable_pin(dapm, "Right Spk");
 475                err = snd_soc_dapm_sync(dapm);
 476                if (err < 0)
 477                        return err;
 478        }
 479
 480        return hdac_hdmi_jack_port_init(component, &card->dapm);
 481}
 482
 483static const struct snd_kcontrol_new sof_controls[] = {
 484        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
 485        SOC_DAPM_PIN_SWITCH("Headset Mic"),
 486        SOC_DAPM_PIN_SWITCH("Left Spk"),
 487        SOC_DAPM_PIN_SWITCH("Right Spk"),
 488
 489};
 490
 491static const struct snd_soc_dapm_widget sof_widgets[] = {
 492        SND_SOC_DAPM_HP("Headphone Jack", NULL),
 493        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 494        SND_SOC_DAPM_SPK("Left Spk", NULL),
 495        SND_SOC_DAPM_SPK("Right Spk", NULL),
 496};
 497
 498static const struct snd_soc_dapm_widget dmic_widgets[] = {
 499        SND_SOC_DAPM_MIC("SoC DMIC", NULL),
 500};
 501
 502static const struct snd_soc_dapm_route sof_map[] = {
 503        /* HP jack connectors - unknown if we have jack detection */
 504        { "Headphone Jack", NULL, "HPOL" },
 505        { "Headphone Jack", NULL, "HPOR" },
 506
 507        /* other jacks */
 508        { "IN1P", NULL, "Headset Mic" },
 509};
 510
 511static const struct snd_soc_dapm_route dmic_map[] = {
 512        /* digital mics */
 513        {"DMic", NULL, "SoC DMIC"},
 514};
 515
 516static int dmic_init(struct snd_soc_pcm_runtime *rtd)
 517{
 518        struct snd_soc_card *card = rtd->card;
 519        int ret;
 520
 521        ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
 522                                        ARRAY_SIZE(dmic_widgets));
 523        if (ret) {
 524                dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
 525                /* Don't need to add routes if widget addition failed */
 526                return ret;
 527        }
 528
 529        ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
 530                                      ARRAY_SIZE(dmic_map));
 531
 532        if (ret)
 533                dev_err(card->dev, "DMic map addition failed: %d\n", ret);
 534
 535        return ret;
 536}
 537
 538/* sof audio machine driver for rt5682 codec */
 539static struct snd_soc_card sof_audio_card_rt5682 = {
 540        .name = "rt5682", /* the sof- prefix is added by the core */
 541        .owner = THIS_MODULE,
 542        .controls = sof_controls,
 543        .num_controls = ARRAY_SIZE(sof_controls),
 544        .dapm_widgets = sof_widgets,
 545        .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
 546        .dapm_routes = sof_map,
 547        .num_dapm_routes = ARRAY_SIZE(sof_map),
 548        .fully_routed = true,
 549        .late_probe = sof_card_late_probe,
 550};
 551
 552static struct snd_soc_dai_link_component rt5682_component[] = {
 553        {
 554                .name = "i2c-10EC5682:00",
 555                .dai_name = "rt5682-aif1",
 556        }
 557};
 558
 559static struct snd_soc_dai_link_component rt5682s_component[] = {
 560        {
 561                .name = "i2c-RTL5682:00",
 562                .dai_name = "rt5682s-aif1",
 563        }
 564};
 565
 566static struct snd_soc_dai_link_component dmic_component[] = {
 567        {
 568                .name = "dmic-codec",
 569                .dai_name = "dmic-hifi",
 570        }
 571};
 572
 573static struct snd_soc_dai_link_component dummy_component[] = {
 574        {
 575                .name = "snd-soc-dummy",
 576                .dai_name = "snd-soc-dummy-dai",
 577        }
 578};
 579
 580#define IDISP_CODEC_MASK        0x4
 581
 582static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
 583                                                          int ssp_codec,
 584                                                          int ssp_amp,
 585                                                          int dmic_be_num,
 586                                                          int hdmi_num,
 587                                                          bool idisp_codec)
 588{
 589        struct snd_soc_dai_link_component *idisp_components;
 590        struct snd_soc_dai_link_component *cpus;
 591        struct snd_soc_dai_link *links;
 592        int i, id = 0;
 593
 594        links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
 595                             sof_audio_card_rt5682.num_links, GFP_KERNEL);
 596        cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
 597                             sof_audio_card_rt5682.num_links, GFP_KERNEL);
 598        if (!links || !cpus)
 599                goto devm_err;
 600
 601        /* codec SSP */
 602        links[id].name = devm_kasprintf(dev, GFP_KERNEL,
 603                                        "SSP%d-Codec", ssp_codec);
 604        if (!links[id].name)
 605                goto devm_err;
 606
 607        links[id].id = id;
 608        if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) {
 609                links[id].codecs = rt5682s_component;
 610                links[id].num_codecs = ARRAY_SIZE(rt5682s_component);
 611        } else {
 612                links[id].codecs = rt5682_component;
 613                links[id].num_codecs = ARRAY_SIZE(rt5682_component);
 614        }
 615        links[id].platforms = platform_component;
 616        links[id].num_platforms = ARRAY_SIZE(platform_component);
 617        links[id].init = sof_rt5682_codec_init;
 618        links[id].exit = sof_rt5682_codec_exit;
 619        links[id].ops = &sof_rt5682_ops;
 620        links[id].dpcm_playback = 1;
 621        links[id].dpcm_capture = 1;
 622        links[id].no_pcm = 1;
 623        links[id].cpus = &cpus[id];
 624        links[id].num_cpus = 1;
 625        if (is_legacy_cpu) {
 626                links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
 627                                                          "ssp%d-port",
 628                                                          ssp_codec);
 629                if (!links[id].cpus->dai_name)
 630                        goto devm_err;
 631        } else {
 632                /*
 633                 * Currently, On SKL+ platforms MCLK will be turned off in sof
 634                 * runtime suspended, and it will go into runtime suspended
 635                 * right after playback is stop. However, rt5682 will output
 636                 * static noise if sysclk turns off during playback. Set
 637                 * ignore_pmdown_time to power down rt5682 immediately and
 638                 * avoid the noise.
 639                 * It can be removed once we can control MCLK by driver.
 640                 */
 641                links[id].ignore_pmdown_time = 1;
 642                links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
 643                                                          "SSP%d Pin",
 644                                                          ssp_codec);
 645                if (!links[id].cpus->dai_name)
 646                        goto devm_err;
 647        }
 648        id++;
 649
 650        /* dmic */
 651        if (dmic_be_num > 0) {
 652                /* at least we have dmic01 */
 653                links[id].name = "dmic01";
 654                links[id].cpus = &cpus[id];
 655                links[id].cpus->dai_name = "DMIC01 Pin";
 656                links[id].init = dmic_init;
 657                if (dmic_be_num > 1) {
 658                        /* set up 2 BE links at most */
 659                        links[id + 1].name = "dmic16k";
 660                        links[id + 1].cpus = &cpus[id + 1];
 661                        links[id + 1].cpus->dai_name = "DMIC16k Pin";
 662                        dmic_be_num = 2;
 663                }
 664        }
 665
 666        for (i = 0; i < dmic_be_num; i++) {
 667                links[id].id = id;
 668                links[id].num_cpus = 1;
 669                links[id].codecs = dmic_component;
 670                links[id].num_codecs = ARRAY_SIZE(dmic_component);
 671                links[id].platforms = platform_component;
 672                links[id].num_platforms = ARRAY_SIZE(platform_component);
 673                links[id].ignore_suspend = 1;
 674                links[id].dpcm_capture = 1;
 675                links[id].no_pcm = 1;
 676                id++;
 677        }
 678
 679        /* HDMI */
 680        if (hdmi_num > 0) {
 681                idisp_components = devm_kzalloc(dev,
 682                                   sizeof(struct snd_soc_dai_link_component) *
 683                                   hdmi_num, GFP_KERNEL);
 684                if (!idisp_components)
 685                        goto devm_err;
 686        }
 687        for (i = 1; i <= hdmi_num; i++) {
 688                links[id].name = devm_kasprintf(dev, GFP_KERNEL,
 689                                                "iDisp%d", i);
 690                if (!links[id].name)
 691                        goto devm_err;
 692
 693                links[id].id = id;
 694                links[id].cpus = &cpus[id];
 695                links[id].num_cpus = 1;
 696                links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
 697                                                          "iDisp%d Pin", i);
 698                if (!links[id].cpus->dai_name)
 699                        goto devm_err;
 700
 701                if (idisp_codec) {
 702                        idisp_components[i - 1].name = "ehdaudio0D2";
 703                        idisp_components[i - 1].dai_name = devm_kasprintf(dev,
 704                                                                          GFP_KERNEL,
 705                                                                          "intel-hdmi-hifi%d",
 706                                                                          i);
 707                        if (!idisp_components[i - 1].dai_name)
 708                                goto devm_err;
 709                } else {
 710                        idisp_components[i - 1].name = "snd-soc-dummy";
 711                        idisp_components[i - 1].dai_name = "snd-soc-dummy-dai";
 712                }
 713
 714                links[id].codecs = &idisp_components[i - 1];
 715                links[id].num_codecs = 1;
 716                links[id].platforms = platform_component;
 717                links[id].num_platforms = ARRAY_SIZE(platform_component);
 718                links[id].init = sof_hdmi_init;
 719                links[id].dpcm_playback = 1;
 720                links[id].no_pcm = 1;
 721                id++;
 722        }
 723
 724        /* speaker amp */
 725        if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) {
 726                links[id].name = devm_kasprintf(dev, GFP_KERNEL,
 727                                                "SSP%d-Codec", ssp_amp);
 728                if (!links[id].name)
 729                        goto devm_err;
 730
 731                links[id].id = id;
 732                if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) {
 733                        sof_rt1015_dai_link(&links[id], (sof_rt5682_quirk &
 734                                        SOF_RT1015_SPEAKER_AMP_100FS) ? 100 : 64);
 735                } else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
 736                        sof_rt1015p_dai_link(&links[id]);
 737                } else if (sof_rt5682_quirk &
 738                                SOF_MAX98373_SPEAKER_AMP_PRESENT) {
 739                        links[id].codecs = max_98373_components;
 740                        links[id].num_codecs = ARRAY_SIZE(max_98373_components);
 741                        links[id].init = max_98373_spk_codec_init;
 742                        links[id].ops = &max_98373_ops;
 743                        /* feedback stream */
 744                        links[id].dpcm_capture = 1;
 745                } else if (sof_rt5682_quirk &
 746                                SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
 747                        max_98360a_dai_link(&links[id]);
 748                } else if (sof_rt5682_quirk &
 749                                SOF_RT1011_SPEAKER_AMP_PRESENT) {
 750                        sof_rt1011_dai_link(&links[id]);
 751                } else if (sof_rt5682_quirk &
 752                                SOF_MAX98390_SPEAKER_AMP_PRESENT) {
 753                        if (sof_rt5682_quirk &
 754                                SOF_MAX98390_TWEETER_SPEAKER_PRESENT) {
 755                                links[id].codecs = max_98390_4spk_components;
 756                                links[id].num_codecs = ARRAY_SIZE(max_98390_4spk_components);
 757                        } else {
 758                                links[id].codecs = max_98390_components;
 759                                links[id].num_codecs = ARRAY_SIZE(max_98390_components);
 760                        }
 761                        links[id].init = max_98390_spk_codec_init;
 762                        links[id].ops = &max_98390_ops;
 763                        links[id].dpcm_capture = 1;
 764
 765                } else {
 766                        max_98357a_dai_link(&links[id]);
 767                }
 768                links[id].platforms = platform_component;
 769                links[id].num_platforms = ARRAY_SIZE(platform_component);
 770                links[id].dpcm_playback = 1;
 771                links[id].no_pcm = 1;
 772                links[id].cpus = &cpus[id];
 773                links[id].num_cpus = 1;
 774                if (is_legacy_cpu) {
 775                        links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
 776                                                                  "ssp%d-port",
 777                                                                  ssp_amp);
 778                        if (!links[id].cpus->dai_name)
 779                                goto devm_err;
 780
 781                } else {
 782                        links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
 783                                                                  "SSP%d Pin",
 784                                                                  ssp_amp);
 785                        if (!links[id].cpus->dai_name)
 786                                goto devm_err;
 787                }
 788                id++;
 789        }
 790
 791        /* BT audio offload */
 792        if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
 793                int port = (sof_rt5682_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
 794                                SOF_BT_OFFLOAD_SSP_SHIFT;
 795
 796                links[id].id = id;
 797                links[id].cpus = &cpus[id];
 798                links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
 799                                                          "SSP%d Pin", port);
 800                if (!links[id].cpus->dai_name)
 801                        goto devm_err;
 802                links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
 803                if (!links[id].name)
 804                        goto devm_err;
 805                links[id].codecs = dummy_component;
 806                links[id].num_codecs = ARRAY_SIZE(dummy_component);
 807                links[id].platforms = platform_component;
 808                links[id].num_platforms = ARRAY_SIZE(platform_component);
 809                links[id].dpcm_playback = 1;
 810                links[id].dpcm_capture = 1;
 811                links[id].no_pcm = 1;
 812                links[id].num_cpus = 1;
 813        }
 814
 815        return links;
 816devm_err:
 817        return NULL;
 818}
 819
 820static int sof_audio_probe(struct platform_device *pdev)
 821{
 822        struct snd_soc_dai_link *dai_links;
 823        struct snd_soc_acpi_mach *mach;
 824        struct sof_card_private *ctx;
 825        int dmic_be_num, hdmi_num;
 826        int ret, ssp_amp, ssp_codec;
 827
 828        ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
 829        if (!ctx)
 830                return -ENOMEM;
 831
 832        if (pdev->id_entry && pdev->id_entry->driver_data)
 833                sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
 834
 835        dmi_check_system(sof_rt5682_quirk_table);
 836
 837        mach = pdev->dev.platform_data;
 838
 839        /* A speaker amp might not be present when the quirk claims one is.
 840         * Detect this via whether the machine driver match includes quirk_data.
 841         */
 842        if ((sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
 843                sof_rt5682_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
 844
 845        /* Detect the headset codec variant */
 846        if (acpi_dev_present("RTL5682", NULL, -1))
 847                sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT;
 848
 849        /* Detect the headset codec variant to support machines in DMI quirk */
 850        if (acpi_dev_present("RTL5682", NULL, -1))
 851                sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT;
 852
 853        if (soc_intel_is_byt() || soc_intel_is_cht()) {
 854                is_legacy_cpu = 1;
 855                dmic_be_num = 0;
 856                hdmi_num = 0;
 857                /* default quirk for legacy cpu */
 858                sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
 859                                                SOF_RT5682_MCLK_BYTCHT_EN |
 860                                                SOF_RT5682_SSP_CODEC(2);
 861        } else {
 862                dmic_be_num = 2;
 863                hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
 864                         SOF_RT5682_NUM_HDMIDEV_SHIFT;
 865                /* default number of HDMI DAI's */
 866                if (!hdmi_num)
 867                        hdmi_num = 3;
 868
 869                if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
 870                        ctx->idisp_codec = true;
 871        }
 872
 873        /* need to get main clock from pmc */
 874        if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
 875                ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
 876                if (IS_ERR(ctx->mclk)) {
 877                        ret = PTR_ERR(ctx->mclk);
 878
 879                        dev_err(&pdev->dev,
 880                                "Failed to get MCLK from pmc_plt_clk_3: %d\n",
 881                                ret);
 882                        return ret;
 883                }
 884
 885                ret = clk_prepare_enable(ctx->mclk);
 886                if (ret < 0) {
 887                        dev_err(&pdev->dev,
 888                                "could not configure MCLK state");
 889                        return ret;
 890                }
 891        }
 892
 893        dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
 894
 895        ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >>
 896                        SOF_RT5682_SSP_AMP_SHIFT;
 897
 898        ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK;
 899
 900        /* compute number of dai links */
 901        sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
 902
 903        if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
 904                sof_audio_card_rt5682.num_links++;
 905
 906        if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
 907                max_98373_set_codec_conf(&sof_audio_card_rt5682);
 908        else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT)
 909                sof_rt1011_codec_conf(&sof_audio_card_rt5682);
 910        else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
 911                sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
 912        else if (sof_rt5682_quirk & SOF_MAX98390_SPEAKER_AMP_PRESENT) {
 913                if (sof_rt5682_quirk & SOF_MAX98390_TWEETER_SPEAKER_PRESENT)
 914                        max_98390_set_codec_conf(&sof_audio_card_rt5682,
 915                                                 ARRAY_SIZE(max_98390_4spk_components));
 916                else
 917                        max_98390_set_codec_conf(&sof_audio_card_rt5682,
 918                                                 ARRAY_SIZE(max_98390_components));
 919        }
 920
 921        if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
 922                sof_audio_card_rt5682.num_links++;
 923
 924        dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
 925                                              dmic_be_num, hdmi_num, ctx->idisp_codec);
 926        if (!dai_links)
 927                return -ENOMEM;
 928
 929        sof_audio_card_rt5682.dai_link = dai_links;
 930
 931        if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT)
 932                sof_rt1015_codec_conf(&sof_audio_card_rt5682);
 933
 934        INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
 935
 936        sof_audio_card_rt5682.dev = &pdev->dev;
 937
 938        /* set platform name for each dailink */
 939        ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
 940                                                    mach->mach_params.platform);
 941        if (ret)
 942                return ret;
 943
 944        ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
 945
 946        snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
 947
 948        return devm_snd_soc_register_card(&pdev->dev,
 949                                          &sof_audio_card_rt5682);
 950}
 951
 952static const struct platform_device_id board_ids[] = {
 953        {
 954                .name = "sof_rt5682",
 955        },
 956        {
 957                .name = "tgl_mx98357_rt5682",
 958                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
 959                                        SOF_RT5682_SSP_CODEC(0) |
 960                                        SOF_SPEAKER_AMP_PRESENT |
 961                                        SOF_RT5682_SSP_AMP(1) |
 962                                        SOF_RT5682_NUM_HDMIDEV(4) |
 963                                        SOF_BT_OFFLOAD_SSP(2) |
 964                                        SOF_SSP_BT_OFFLOAD_PRESENT),
 965        },
 966        {
 967                .name = "jsl_rt5682_rt1015",
 968                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
 969                                        SOF_RT5682_MCLK_24MHZ |
 970                                        SOF_RT5682_SSP_CODEC(0) |
 971                                        SOF_SPEAKER_AMP_PRESENT |
 972                                        SOF_RT1015_SPEAKER_AMP_PRESENT |
 973                                        SOF_RT5682_SSP_AMP(1)),
 974        },
 975        {
 976                .name = "tgl_mx98373_rt5682",
 977                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
 978                                        SOF_RT5682_SSP_CODEC(0) |
 979                                        SOF_SPEAKER_AMP_PRESENT |
 980                                        SOF_MAX98373_SPEAKER_AMP_PRESENT |
 981                                        SOF_RT5682_SSP_AMP(1) |
 982                                        SOF_RT5682_NUM_HDMIDEV(4) |
 983                                        SOF_BT_OFFLOAD_SSP(2) |
 984                                        SOF_SSP_BT_OFFLOAD_PRESENT),
 985        },
 986        {
 987                .name = "jsl_rt5682_mx98360",
 988                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
 989                                        SOF_RT5682_MCLK_24MHZ |
 990                                        SOF_RT5682_SSP_CODEC(0) |
 991                                        SOF_SPEAKER_AMP_PRESENT |
 992                                        SOF_MAX98360A_SPEAKER_AMP_PRESENT |
 993                                        SOF_RT5682_SSP_AMP(1)),
 994        },
 995        {
 996                .name = "cml_rt1015_rt5682",
 997                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
 998                                        SOF_RT5682_MCLK_24MHZ |
 999                                        SOF_RT5682_SSP_CODEC(0) |
1000                                        SOF_SPEAKER_AMP_PRESENT |
1001                                        SOF_RT1015_SPEAKER_AMP_PRESENT |
1002                                        SOF_RT1015_SPEAKER_AMP_100FS |
1003                                        SOF_RT5682_SSP_AMP(1)),
1004        },
1005        {
1006                .name = "tgl_rt1011_rt5682",
1007                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1008                                        SOF_RT5682_SSP_CODEC(0) |
1009                                        SOF_SPEAKER_AMP_PRESENT |
1010                                        SOF_RT1011_SPEAKER_AMP_PRESENT |
1011                                        SOF_RT5682_SSP_AMP(1) |
1012                                        SOF_RT5682_NUM_HDMIDEV(4) |
1013                                        SOF_BT_OFFLOAD_SSP(2) |
1014                                        SOF_SSP_BT_OFFLOAD_PRESENT),
1015        },
1016        {
1017                .name = "jsl_rt5682_rt1015p",
1018                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1019                                        SOF_RT5682_MCLK_24MHZ |
1020                                        SOF_RT5682_SSP_CODEC(0) |
1021                                        SOF_SPEAKER_AMP_PRESENT |
1022                                        SOF_RT1015P_SPEAKER_AMP_PRESENT |
1023                                        SOF_RT5682_SSP_AMP(1)),
1024        },
1025        {
1026                .name = "adl_mx98373_rt5682",
1027                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1028                                        SOF_RT5682_SSP_CODEC(0) |
1029                                        SOF_SPEAKER_AMP_PRESENT |
1030                                        SOF_MAX98373_SPEAKER_AMP_PRESENT |
1031                                        SOF_RT5682_SSP_AMP(1) |
1032                                        SOF_RT5682_NUM_HDMIDEV(4) |
1033                                        SOF_BT_OFFLOAD_SSP(2) |
1034                                        SOF_SSP_BT_OFFLOAD_PRESENT),
1035        },
1036        {
1037                .name = "adl_mx98357_rt5682",
1038                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1039                                        SOF_RT5682_SSP_CODEC(0) |
1040                                        SOF_SPEAKER_AMP_PRESENT |
1041                                        SOF_RT5682_SSP_AMP(2) |
1042                                        SOF_RT5682_NUM_HDMIDEV(4)),
1043        },
1044        {
1045                .name = "adl_max98390_rt5682",
1046                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1047                                        SOF_RT5682_SSP_CODEC(0) |
1048                                        SOF_SPEAKER_AMP_PRESENT |
1049                                        SOF_MAX98390_SPEAKER_AMP_PRESENT |
1050                                        SOF_RT5682_SSP_AMP(1) |
1051                                        SOF_RT5682_NUM_HDMIDEV(4) |
1052                                        SOF_BT_OFFLOAD_SSP(2) |
1053                                        SOF_SSP_BT_OFFLOAD_PRESENT),
1054        },
1055        {
1056                .name = "adl_mx98360_rt5682",
1057                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1058                                        SOF_RT5682_SSP_CODEC(0) |
1059                                        SOF_SPEAKER_AMP_PRESENT |
1060                                        SOF_MAX98360A_SPEAKER_AMP_PRESENT |
1061                                        SOF_RT5682_SSP_AMP(1) |
1062                                        SOF_RT5682_NUM_HDMIDEV(4) |
1063                                        SOF_BT_OFFLOAD_SSP(2) |
1064                                        SOF_SSP_BT_OFFLOAD_PRESENT),
1065        },
1066        {
1067                .name = "adl_rt5682",
1068                .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
1069                                        SOF_RT5682_SSP_CODEC(0) |
1070                                        SOF_RT5682_NUM_HDMIDEV(4) |
1071                                        SOF_BT_OFFLOAD_SSP(2) |
1072                                        SOF_SSP_BT_OFFLOAD_PRESENT),
1073        },
1074        { }
1075};
1076MODULE_DEVICE_TABLE(platform, board_ids);
1077
1078static struct platform_driver sof_audio = {
1079        .probe = sof_audio_probe,
1080        .driver = {
1081                .name = "sof_rt5682",
1082                .pm = &snd_soc_pm_ops,
1083        },
1084        .id_table = board_ids,
1085};
1086module_platform_driver(sof_audio)
1087
1088/* Module information */
1089MODULE_DESCRIPTION("SOF Audio Machine driver");
1090MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
1091MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
1092MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
1093MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
1094MODULE_LICENSE("GPL v2");
1095MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
1096MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
1097MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
1098