linux/sound/soc/intel/boards/bytcr_rt5640.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  byt_cr_dpcm_rt5640.c - ASoc Machine driver for Intel Byt CR platform
   4 *
   5 *  Copyright (C) 2014 Intel Corp
   6 *  Author: Subhransu S. Prusty <subhransu.s.prusty@intel.com>
   7 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   8 *
   9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10 */
  11
  12#include <linux/i2c.h>
  13#include <linux/init.h>
  14#include <linux/module.h>
  15#include <linux/moduleparam.h>
  16#include <linux/platform_device.h>
  17#include <linux/acpi.h>
  18#include <linux/clk.h>
  19#include <linux/device.h>
  20#include <linux/dmi.h>
  21#include <linux/input.h>
  22#include <linux/slab.h>
  23#include <sound/pcm.h>
  24#include <sound/pcm_params.h>
  25#include <sound/soc.h>
  26#include <sound/jack.h>
  27#include <sound/soc-acpi.h>
  28#include <dt-bindings/sound/rt5640.h>
  29#include "../../codecs/rt5640.h"
  30#include "../atom/sst-atom-controls.h"
  31#include "../common/soc-intel-quirks.h"
  32
  33enum {
  34        BYT_RT5640_DMIC1_MAP,
  35        BYT_RT5640_DMIC2_MAP,
  36        BYT_RT5640_IN1_MAP,
  37        BYT_RT5640_IN3_MAP,
  38        BYT_RT5640_NO_INTERNAL_MIC_MAP,
  39};
  40
  41enum {
  42        BYT_RT5640_JD_SRC_GPIO1         = (RT5640_JD_SRC_GPIO1 << 4),
  43        BYT_RT5640_JD_SRC_JD1_IN4P      = (RT5640_JD_SRC_JD1_IN4P << 4),
  44        BYT_RT5640_JD_SRC_JD2_IN4N      = (RT5640_JD_SRC_JD2_IN4N << 4),
  45        BYT_RT5640_JD_SRC_GPIO2         = (RT5640_JD_SRC_GPIO2 << 4),
  46        BYT_RT5640_JD_SRC_GPIO3         = (RT5640_JD_SRC_GPIO3 << 4),
  47        BYT_RT5640_JD_SRC_GPIO4         = (RT5640_JD_SRC_GPIO4 << 4),
  48};
  49
  50enum {
  51        BYT_RT5640_OVCD_TH_600UA        = (6 << 8),
  52        BYT_RT5640_OVCD_TH_1500UA       = (15 << 8),
  53        BYT_RT5640_OVCD_TH_2000UA       = (20 << 8),
  54};
  55
  56enum {
  57        BYT_RT5640_OVCD_SF_0P5          = (RT5640_OVCD_SF_0P5 << 13),
  58        BYT_RT5640_OVCD_SF_0P75         = (RT5640_OVCD_SF_0P75 << 13),
  59        BYT_RT5640_OVCD_SF_1P0          = (RT5640_OVCD_SF_1P0 << 13),
  60        BYT_RT5640_OVCD_SF_1P5          = (RT5640_OVCD_SF_1P5 << 13),
  61};
  62
  63#define BYT_RT5640_MAP(quirk)           ((quirk) &  GENMASK(3, 0))
  64#define BYT_RT5640_JDSRC(quirk)         (((quirk) & GENMASK(7, 4)) >> 4)
  65#define BYT_RT5640_OVCD_TH(quirk)       (((quirk) & GENMASK(12, 8)) >> 8)
  66#define BYT_RT5640_OVCD_SF(quirk)       (((quirk) & GENMASK(14, 13)) >> 13)
  67#define BYT_RT5640_JD_NOT_INV           BIT(16)
  68#define BYT_RT5640_MONO_SPEAKER         BIT(17)
  69#define BYT_RT5640_DIFF_MIC             BIT(18) /* default is single-ended */
  70#define BYT_RT5640_SSP2_AIF2            BIT(19) /* default is using AIF1  */
  71#define BYT_RT5640_SSP0_AIF1            BIT(20)
  72#define BYT_RT5640_SSP0_AIF2            BIT(21)
  73#define BYT_RT5640_MCLK_EN              BIT(22)
  74#define BYT_RT5640_MCLK_25MHZ           BIT(23)
  75#define BYT_RT5640_NO_SPEAKERS          BIT(24)
  76
  77#define BYTCR_INPUT_DEFAULTS                            \
  78        (BYT_RT5640_IN3_MAP |                           \
  79         BYT_RT5640_JD_SRC_JD1_IN4P |                   \
  80         BYT_RT5640_OVCD_TH_2000UA |                    \
  81         BYT_RT5640_OVCD_SF_0P75 |                      \
  82         BYT_RT5640_DIFF_MIC)
  83
  84/* in-diff or dmic-pin + jdsrc + ovcd-th + -sf + jd-inv + terminating entry */
  85#define MAX_NO_PROPS 6
  86
  87struct byt_rt5640_private {
  88        struct snd_soc_jack jack;
  89        struct clk *mclk;
  90};
  91static bool is_bytcr;
  92
  93static unsigned long byt_rt5640_quirk = BYT_RT5640_MCLK_EN;
  94static int quirk_override = -1;
  95module_param_named(quirk, quirk_override, int, 0444);
  96MODULE_PARM_DESC(quirk, "Board-specific quirk override");
  97
  98static void log_quirks(struct device *dev)
  99{
 100        int map;
 101        bool has_mclk = false;
 102        bool has_ssp0 = false;
 103        bool has_ssp0_aif1 = false;
 104        bool has_ssp0_aif2 = false;
 105        bool has_ssp2_aif2 = false;
 106
 107        map = BYT_RT5640_MAP(byt_rt5640_quirk);
 108        switch (map) {
 109        case BYT_RT5640_DMIC1_MAP:
 110                dev_info(dev, "quirk DMIC1_MAP enabled\n");
 111                break;
 112        case BYT_RT5640_DMIC2_MAP:
 113                dev_info(dev, "quirk DMIC2_MAP enabled\n");
 114                break;
 115        case BYT_RT5640_IN1_MAP:
 116                dev_info(dev, "quirk IN1_MAP enabled\n");
 117                break;
 118        case BYT_RT5640_IN3_MAP:
 119                dev_info(dev, "quirk IN3_MAP enabled\n");
 120                break;
 121        case BYT_RT5640_NO_INTERNAL_MIC_MAP:
 122                dev_info(dev, "quirk NO_INTERNAL_MIC_MAP enabled\n");
 123                break;
 124        default:
 125                dev_err(dev, "quirk map 0x%x is not supported, microphone input will not work\n", map);
 126                break;
 127        }
 128        if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
 129                dev_info(dev, "quirk realtek,jack-detect-source %ld\n",
 130                         BYT_RT5640_JDSRC(byt_rt5640_quirk));
 131                dev_info(dev, "quirk realtek,over-current-threshold-microamp %ld\n",
 132                         BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);
 133                dev_info(dev, "quirk realtek,over-current-scale-factor %ld\n",
 134                         BYT_RT5640_OVCD_SF(byt_rt5640_quirk));
 135        }
 136        if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
 137                dev_info(dev, "quirk JD_NOT_INV enabled\n");
 138        if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER)
 139                dev_info(dev, "quirk MONO_SPEAKER enabled\n");
 140        if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)
 141                dev_info(dev, "quirk NO_SPEAKERS enabled\n");
 142        if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
 143                dev_info(dev, "quirk DIFF_MIC enabled\n");
 144        if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
 145                dev_info(dev, "quirk SSP0_AIF1 enabled\n");
 146                has_ssp0 = true;
 147                has_ssp0_aif1 = true;
 148        }
 149        if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
 150                dev_info(dev, "quirk SSP0_AIF2 enabled\n");
 151                has_ssp0 = true;
 152                has_ssp0_aif2 = true;
 153        }
 154        if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
 155                dev_info(dev, "quirk SSP2_AIF2 enabled\n");
 156                has_ssp2_aif2 = true;
 157        }
 158        if (is_bytcr && !has_ssp0)
 159                dev_err(dev, "Invalid routing, bytcr detected but no SSP0-based quirk, audio cannot work with SSP2 on bytcr\n");
 160        if (has_ssp0_aif1 && has_ssp0_aif2)
 161                dev_err(dev, "Invalid routing, SSP0 cannot be connected to both AIF1 and AIF2\n");
 162        if (has_ssp0 && has_ssp2_aif2)
 163                dev_err(dev, "Invalid routing, cannot have both SSP0 and SSP2 connected to codec\n");
 164
 165        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
 166                dev_info(dev, "quirk MCLK_EN enabled\n");
 167                has_mclk = true;
 168        }
 169        if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {
 170                if (has_mclk)
 171                        dev_info(dev, "quirk MCLK_25MHZ enabled\n");
 172                else
 173                        dev_err(dev, "quirk MCLK_25MHZ enabled but quirk MCLK not selected, will be ignored\n");
 174        }
 175}
 176
 177static int byt_rt5640_prepare_and_enable_pll1(struct snd_soc_dai *codec_dai,
 178                                              int rate)
 179{
 180        int ret;
 181
 182        /* Configure the PLL before selecting it */
 183        if (!(byt_rt5640_quirk & BYT_RT5640_MCLK_EN)) {
 184                /* use bitclock as PLL input */
 185                if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
 186                    (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
 187                        /* 2x16 bit slots on SSP0 */
 188                        ret = snd_soc_dai_set_pll(codec_dai, 0,
 189                                                  RT5640_PLL1_S_BCLK1,
 190                                                  rate * 32, rate * 512);
 191                } else {
 192                        /* 2x15 bit slots on SSP2 */
 193                        ret = snd_soc_dai_set_pll(codec_dai, 0,
 194                                                  RT5640_PLL1_S_BCLK1,
 195                                                  rate * 50, rate * 512);
 196                }
 197        } else {
 198                if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ) {
 199                        ret = snd_soc_dai_set_pll(codec_dai, 0,
 200                                                  RT5640_PLL1_S_MCLK,
 201                                                  25000000, rate * 512);
 202                } else {
 203                        ret = snd_soc_dai_set_pll(codec_dai, 0,
 204                                                  RT5640_PLL1_S_MCLK,
 205                                                  19200000, rate * 512);
 206                }
 207        }
 208
 209        if (ret < 0) {
 210                dev_err(codec_dai->component->dev, "can't set pll: %d\n", ret);
 211                return ret;
 212        }
 213
 214        ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1,
 215                                     rate * 512, SND_SOC_CLOCK_IN);
 216        if (ret < 0) {
 217                dev_err(codec_dai->component->dev, "can't set clock %d\n", ret);
 218                return ret;
 219        }
 220
 221        return 0;
 222}
 223
 224#define BYT_CODEC_DAI1  "rt5640-aif1"
 225#define BYT_CODEC_DAI2  "rt5640-aif2"
 226
 227static int platform_clock_control(struct snd_soc_dapm_widget *w,
 228                                  struct snd_kcontrol *k, int  event)
 229{
 230        struct snd_soc_dapm_context *dapm = w->dapm;
 231        struct snd_soc_card *card = dapm->card;
 232        struct snd_soc_dai *codec_dai;
 233        struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
 234        int ret;
 235
 236        codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
 237        if (!codec_dai)
 238                codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI2);
 239
 240        if (!codec_dai) {
 241                dev_err(card->dev,
 242                        "Codec dai not found; Unable to set platform clock\n");
 243                return -EIO;
 244        }
 245
 246        if (SND_SOC_DAPM_EVENT_ON(event)) {
 247                if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
 248                        ret = clk_prepare_enable(priv->mclk);
 249                        if (ret < 0) {
 250                                dev_err(card->dev,
 251                                        "could not configure MCLK state\n");
 252                                return ret;
 253                        }
 254                }
 255                ret = byt_rt5640_prepare_and_enable_pll1(codec_dai, 48000);
 256        } else {
 257                /*
 258                 * Set codec clock source to internal clock before
 259                 * turning off the platform clock. Codec needs clock
 260                 * for Jack detection and button press
 261                 */
 262                ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK,
 263                                             48000 * 512,
 264                                             SND_SOC_CLOCK_IN);
 265                if (!ret) {
 266                        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
 267                                clk_disable_unprepare(priv->mclk);
 268                }
 269        }
 270
 271        if (ret < 0) {
 272                dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
 273                return ret;
 274        }
 275
 276        return 0;
 277}
 278
 279static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
 280        SND_SOC_DAPM_HP("Headphone", NULL),
 281        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 282        SND_SOC_DAPM_MIC("Internal Mic", NULL),
 283        SND_SOC_DAPM_SPK("Speaker", NULL),
 284        SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
 285                            platform_clock_control, SND_SOC_DAPM_PRE_PMU |
 286                            SND_SOC_DAPM_POST_PMD),
 287
 288};
 289
 290static const struct snd_soc_dapm_route byt_rt5640_audio_map[] = {
 291        {"Headphone", NULL, "Platform Clock"},
 292        {"Headset Mic", NULL, "Platform Clock"},
 293        {"Internal Mic", NULL, "Platform Clock"},
 294        {"Speaker", NULL, "Platform Clock"},
 295
 296        {"Headset Mic", NULL, "MICBIAS1"},
 297        {"IN2P", NULL, "Headset Mic"},
 298        {"Headphone", NULL, "HPOL"},
 299        {"Headphone", NULL, "HPOR"},
 300};
 301
 302static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic1_map[] = {
 303        {"DMIC1", NULL, "Internal Mic"},
 304};
 305
 306static const struct snd_soc_dapm_route byt_rt5640_intmic_dmic2_map[] = {
 307        {"DMIC2", NULL, "Internal Mic"},
 308};
 309
 310static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
 311        {"Internal Mic", NULL, "MICBIAS1"},
 312        {"IN1P", NULL, "Internal Mic"},
 313};
 314
 315static const struct snd_soc_dapm_route byt_rt5640_intmic_in3_map[] = {
 316        {"Internal Mic", NULL, "MICBIAS1"},
 317        {"IN3P", NULL, "Internal Mic"},
 318};
 319
 320static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif1_map[] = {
 321        {"ssp2 Tx", NULL, "codec_out0"},
 322        {"ssp2 Tx", NULL, "codec_out1"},
 323        {"codec_in0", NULL, "ssp2 Rx"},
 324        {"codec_in1", NULL, "ssp2 Rx"},
 325
 326        {"AIF1 Playback", NULL, "ssp2 Tx"},
 327        {"ssp2 Rx", NULL, "AIF1 Capture"},
 328};
 329
 330static const struct snd_soc_dapm_route byt_rt5640_ssp2_aif2_map[] = {
 331        {"ssp2 Tx", NULL, "codec_out0"},
 332        {"ssp2 Tx", NULL, "codec_out1"},
 333        {"codec_in0", NULL, "ssp2 Rx"},
 334        {"codec_in1", NULL, "ssp2 Rx"},
 335
 336        {"AIF2 Playback", NULL, "ssp2 Tx"},
 337        {"ssp2 Rx", NULL, "AIF2 Capture"},
 338};
 339
 340static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif1_map[] = {
 341        {"ssp0 Tx", NULL, "modem_out"},
 342        {"modem_in", NULL, "ssp0 Rx"},
 343
 344        {"AIF1 Playback", NULL, "ssp0 Tx"},
 345        {"ssp0 Rx", NULL, "AIF1 Capture"},
 346};
 347
 348static const struct snd_soc_dapm_route byt_rt5640_ssp0_aif2_map[] = {
 349        {"ssp0 Tx", NULL, "modem_out"},
 350        {"modem_in", NULL, "ssp0 Rx"},
 351
 352        {"AIF2 Playback", NULL, "ssp0 Tx"},
 353        {"ssp0 Rx", NULL, "AIF2 Capture"},
 354};
 355
 356static const struct snd_soc_dapm_route byt_rt5640_stereo_spk_map[] = {
 357        {"Speaker", NULL, "SPOLP"},
 358        {"Speaker", NULL, "SPOLN"},
 359        {"Speaker", NULL, "SPORP"},
 360        {"Speaker", NULL, "SPORN"},
 361};
 362
 363static const struct snd_soc_dapm_route byt_rt5640_mono_spk_map[] = {
 364        {"Speaker", NULL, "SPOLP"},
 365        {"Speaker", NULL, "SPOLN"},
 366};
 367
 368static const struct snd_kcontrol_new byt_rt5640_controls[] = {
 369        SOC_DAPM_PIN_SWITCH("Headphone"),
 370        SOC_DAPM_PIN_SWITCH("Headset Mic"),
 371        SOC_DAPM_PIN_SWITCH("Internal Mic"),
 372        SOC_DAPM_PIN_SWITCH("Speaker"),
 373};
 374
 375static struct snd_soc_jack_pin rt5640_pins[] = {
 376        {
 377                .pin    = "Headphone",
 378                .mask   = SND_JACK_HEADPHONE,
 379        },
 380        {
 381                .pin    = "Headset Mic",
 382                .mask   = SND_JACK_MICROPHONE,
 383        },
 384};
 385
 386static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
 387                                        struct snd_pcm_hw_params *params)
 388{
 389        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 390        struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
 391
 392        return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params));
 393}
 394
 395/* Please keep this list alphabetically sorted */
 396static const struct dmi_system_id byt_rt5640_quirk_table[] = {
 397        {       /* Acer Iconia Tab 8 W1-810 */
 398                .matches = {
 399                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
 400                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Iconia W1-810"),
 401                },
 402                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 403                                        BYT_RT5640_JD_SRC_JD1_IN4P |
 404                                        BYT_RT5640_OVCD_TH_1500UA |
 405                                        BYT_RT5640_OVCD_SF_0P75 |
 406                                        BYT_RT5640_SSP0_AIF1 |
 407                                        BYT_RT5640_MCLK_EN),
 408        },
 409        {       /* Acer One 10 S1002 */
 410                .matches = {
 411                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 412                        DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"),
 413                },
 414                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 415                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 416                                        BYT_RT5640_OVCD_TH_2000UA |
 417                                        BYT_RT5640_OVCD_SF_0P75 |
 418                                        BYT_RT5640_DIFF_MIC |
 419                                        BYT_RT5640_SSP0_AIF2 |
 420                                        BYT_RT5640_MCLK_EN),
 421        },
 422        {
 423                .matches = {
 424                        DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 425                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
 426                },
 427                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 428                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 429                                        BYT_RT5640_OVCD_TH_2000UA |
 430                                        BYT_RT5640_OVCD_SF_0P75 |
 431                                        BYT_RT5640_SSP0_AIF1 |
 432                                        BYT_RT5640_MCLK_EN),
 433        },
 434        {
 435                .matches = {
 436                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
 437                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 80 Cesium"),
 438                },
 439                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 440                                        BYT_RT5640_MONO_SPEAKER |
 441                                        BYT_RT5640_SSP0_AIF1 |
 442                                        BYT_RT5640_MCLK_EN),
 443        },
 444        {
 445                .matches = {
 446                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
 447                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"),
 448                },
 449                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 450                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 451                                        BYT_RT5640_OVCD_TH_2000UA |
 452                                        BYT_RT5640_OVCD_SF_0P75 |
 453                                        BYT_RT5640_SSP0_AIF1 |
 454                                        BYT_RT5640_MCLK_EN),
 455        },
 456        {
 457                .matches = {
 458                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 459                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
 460                },
 461                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 462                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 463                                        BYT_RT5640_OVCD_TH_2000UA |
 464                                        BYT_RT5640_OVCD_SF_0P75 |
 465                                        BYT_RT5640_SSP0_AIF1 |
 466                                        BYT_RT5640_MCLK_EN),
 467        },
 468        {
 469                .matches = {
 470                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 471                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
 472                },
 473                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 474                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 475                                        BYT_RT5640_OVCD_TH_2000UA |
 476                                        BYT_RT5640_OVCD_SF_0P75 |
 477                                        BYT_RT5640_MCLK_EN),
 478        },
 479        {
 480                .matches = {
 481                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 482                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
 483                },
 484                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 485                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 486                                        BYT_RT5640_OVCD_TH_2000UA |
 487                                        BYT_RT5640_OVCD_SF_0P75 |
 488                                        BYT_RT5640_MONO_SPEAKER |
 489                                        BYT_RT5640_DIFF_MIC |
 490                                        BYT_RT5640_SSP0_AIF2 |
 491                                        BYT_RT5640_MCLK_EN),
 492        },
 493        {       /* Chuwi Vi8 (CWI506) */
 494                .matches = {
 495                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
 496                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),
 497                        /* The above are too generic, also match BIOS info */
 498                        DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
 499                },
 500                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 501                                        BYT_RT5640_MONO_SPEAKER |
 502                                        BYT_RT5640_SSP0_AIF1 |
 503                                        BYT_RT5640_MCLK_EN),
 504        },
 505        {
 506                /* Chuwi Vi10 (CWI505) */
 507                .matches = {
 508                        DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
 509                        DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"),
 510                        DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
 511                        DMI_MATCH(DMI_PRODUCT_NAME, "S165"),
 512                },
 513                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 514                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 515                                        BYT_RT5640_OVCD_TH_2000UA |
 516                                        BYT_RT5640_OVCD_SF_0P75 |
 517                                        BYT_RT5640_DIFF_MIC |
 518                                        BYT_RT5640_SSP0_AIF1 |
 519                                        BYT_RT5640_MCLK_EN),
 520        },
 521        {
 522                /* Chuwi Hi8 (CWI509) */
 523                .matches = {
 524                        DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
 525                        DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),
 526                        DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
 527                        DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
 528                },
 529                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 530                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 531                                        BYT_RT5640_OVCD_TH_2000UA |
 532                                        BYT_RT5640_OVCD_SF_0P75 |
 533                                        BYT_RT5640_MONO_SPEAKER |
 534                                        BYT_RT5640_DIFF_MIC |
 535                                        BYT_RT5640_SSP0_AIF1 |
 536                                        BYT_RT5640_MCLK_EN),
 537        },
 538        {
 539                .matches = {
 540                        DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
 541                        DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
 542                },
 543                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP),
 544        },
 545        {       /* Connect Tablet 9 */
 546                .matches = {
 547                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Connect"),
 548                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Tablet 9"),
 549                },
 550                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 551                                        BYT_RT5640_MONO_SPEAKER |
 552                                        BYT_RT5640_SSP0_AIF1 |
 553                                        BYT_RT5640_MCLK_EN),
 554        },
 555        {
 556                .matches = {
 557                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 558                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),
 559                },
 560                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 561                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 562                                        BYT_RT5640_OVCD_TH_2000UA |
 563                                        BYT_RT5640_OVCD_SF_0P75 |
 564                                        BYT_RT5640_MONO_SPEAKER |
 565                                        BYT_RT5640_MCLK_EN),
 566        },
 567        {       /* Estar Beauty HD MID 7316R */
 568                .matches = {
 569                        DMI_MATCH(DMI_SYS_VENDOR, "Estar"),
 570                        DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
 571                },
 572                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 573                                        BYT_RT5640_MONO_SPEAKER |
 574                                        BYT_RT5640_SSP0_AIF1 |
 575                                        BYT_RT5640_MCLK_EN),
 576        },
 577        {       /* Glavey TM800A550L */
 578                .matches = {
 579                        DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 580                        DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 581                        /* Above strings are too generic, also match on BIOS version */
 582                        DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
 583                },
 584                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 585                                        BYT_RT5640_SSP0_AIF1 |
 586                                        BYT_RT5640_MCLK_EN),
 587        },
 588        {
 589                .matches = {
 590                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 591                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
 592                },
 593                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 594                                        BYT_RT5640_MCLK_EN),
 595        },
 596        {       /* HP Pavilion x2 10-k0XX, 10-n0XX */
 597                .matches = {
 598                        DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 599                        DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
 600                },
 601                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 602                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 603                                        BYT_RT5640_OVCD_TH_1500UA |
 604                                        BYT_RT5640_OVCD_SF_0P75 |
 605                                        BYT_RT5640_SSP0_AIF1 |
 606                                        BYT_RT5640_MCLK_EN),
 607        },
 608        {       /* HP Pavilion x2 10-p0XX */
 609                .matches = {
 610                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
 611                        DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
 612                },
 613                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 614                                        BYT_RT5640_JD_SRC_JD1_IN4P |
 615                                        BYT_RT5640_OVCD_TH_2000UA |
 616                                        BYT_RT5640_OVCD_SF_0P75 |
 617                                        BYT_RT5640_MCLK_EN),
 618        },
 619        {       /* HP Stream 7 */
 620                .matches = {
 621                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 622                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"),
 623                },
 624                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 625                                        BYT_RT5640_MONO_SPEAKER |
 626                                        BYT_RT5640_JD_NOT_INV |
 627                                        BYT_RT5640_SSP0_AIF1 |
 628                                        BYT_RT5640_MCLK_EN),
 629        },
 630        {       /* I.T.Works TW891 */
 631                .matches = {
 632                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
 633                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),
 634                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
 635                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
 636                },
 637                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 638                                        BYT_RT5640_MONO_SPEAKER |
 639                                        BYT_RT5640_SSP0_AIF1 |
 640                                        BYT_RT5640_MCLK_EN),
 641        },
 642        {       /* Lamina I8270 / T701BR.SE */
 643                .matches = {
 644                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"),
 645                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"),
 646                },
 647                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 648                                        BYT_RT5640_MONO_SPEAKER |
 649                                        BYT_RT5640_JD_NOT_INV |
 650                                        BYT_RT5640_SSP0_AIF1 |
 651                                        BYT_RT5640_MCLK_EN),
 652        },
 653        {       /* Lenovo Miix 2 8 */
 654                .matches = {
 655                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 656                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "20326"),
 657                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Hiking"),
 658                },
 659                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 660                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 661                                        BYT_RT5640_OVCD_TH_2000UA |
 662                                        BYT_RT5640_OVCD_SF_0P75 |
 663                                        BYT_RT5640_MONO_SPEAKER |
 664                                        BYT_RT5640_MCLK_EN),
 665        },
 666        {       /* Lenovo Miix 3-830 */
 667                .matches = {
 668                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 669                        DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 3-830"),
 670                },
 671                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 672                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 673                                        BYT_RT5640_OVCD_TH_2000UA |
 674                                        BYT_RT5640_OVCD_SF_0P75 |
 675                                        BYT_RT5640_MONO_SPEAKER |
 676                                        BYT_RT5640_DIFF_MIC |
 677                                        BYT_RT5640_SSP0_AIF1 |
 678                                        BYT_RT5640_MCLK_EN),
 679        },
 680        {       /* Linx Linx7 tablet */
 681                .matches = {
 682                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"),
 683                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"),
 684                },
 685                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 686                                        BYT_RT5640_MONO_SPEAKER |
 687                                        BYT_RT5640_JD_NOT_INV |
 688                                        BYT_RT5640_SSP0_AIF1 |
 689                                        BYT_RT5640_MCLK_EN),
 690        },
 691        {       /* Mele PCG03 Mini PC */
 692                .matches = {
 693                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),
 694                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"),
 695                },
 696                .driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP |
 697                                        BYT_RT5640_NO_SPEAKERS |
 698                                        BYT_RT5640_SSP0_AIF1),
 699        },
 700        {       /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
 701                .matches = {
 702                        DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
 703                        DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),
 704                },
 705                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 706                                        BYT_RT5640_MONO_SPEAKER |
 707                                        BYT_RT5640_SSP0_AIF1 |
 708                                        BYT_RT5640_MCLK_EN),
 709        },
 710        {
 711                /* MPMAN MPWIN895CL */
 712                .matches = {
 713                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MPMAN"),
 714                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MPWIN8900CL"),
 715                },
 716                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 717                                        BYT_RT5640_MONO_SPEAKER |
 718                                        BYT_RT5640_SSP0_AIF1 |
 719                                        BYT_RT5640_MCLK_EN),
 720        },
 721        {       /* MSI S100 tablet */
 722                .matches = {
 723                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
 724                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"),
 725                },
 726                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 727                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 728                                        BYT_RT5640_OVCD_TH_2000UA |
 729                                        BYT_RT5640_OVCD_SF_0P75 |
 730                                        BYT_RT5640_MONO_SPEAKER |
 731                                        BYT_RT5640_DIFF_MIC |
 732                                        BYT_RT5640_MCLK_EN),
 733        },
 734        {       /* Nuvison/TMax TM800W560 */
 735                .matches = {
 736                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TMAX"),
 737                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TM800W560L"),
 738                },
 739                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 740                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 741                                        BYT_RT5640_OVCD_TH_2000UA |
 742                                        BYT_RT5640_OVCD_SF_0P75 |
 743                                        BYT_RT5640_JD_NOT_INV |
 744                                        BYT_RT5640_DIFF_MIC |
 745                                        BYT_RT5640_SSP0_AIF1 |
 746                                        BYT_RT5640_MCLK_EN),
 747        },
 748        {       /* Onda v975w */
 749                .matches = {
 750                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 751                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 752                        /* The above are too generic, also match BIOS info */
 753                        DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"),
 754                        DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"),
 755                },
 756                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 757                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 758                                        BYT_RT5640_OVCD_TH_2000UA |
 759                                        BYT_RT5640_OVCD_SF_0P75 |
 760                                        BYT_RT5640_DIFF_MIC |
 761                                        BYT_RT5640_MCLK_EN),
 762        },
 763        {       /* Pipo W4 */
 764                .matches = {
 765                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 766                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 767                        /* The above are too generic, also match BIOS info */
 768                        DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"),
 769                },
 770                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 771                                        BYT_RT5640_MONO_SPEAKER |
 772                                        BYT_RT5640_SSP0_AIF1 |
 773                                        BYT_RT5640_MCLK_EN),
 774        },
 775        {       /* Point of View Mobii TAB-P800W (V2.0) */
 776                .matches = {
 777                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 778                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 779                        /* The above are too generic, also match BIOS info */
 780                        DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
 781                        DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"),
 782                },
 783                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 784                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 785                                        BYT_RT5640_OVCD_TH_2000UA |
 786                                        BYT_RT5640_OVCD_SF_0P75 |
 787                                        BYT_RT5640_MONO_SPEAKER |
 788                                        BYT_RT5640_DIFF_MIC |
 789                                        BYT_RT5640_SSP0_AIF2 |
 790                                        BYT_RT5640_MCLK_EN),
 791        },
 792        {       /* Point of View Mobii TAB-P800W (V2.1) */
 793                .matches = {
 794                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 795                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 796                        /* The above are too generic, also match BIOS info */
 797                        DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
 798                        DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"),
 799                },
 800                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 801                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 802                                        BYT_RT5640_OVCD_TH_2000UA |
 803                                        BYT_RT5640_OVCD_SF_0P75 |
 804                                        BYT_RT5640_MONO_SPEAKER |
 805                                        BYT_RT5640_DIFF_MIC |
 806                                        BYT_RT5640_SSP0_AIF2 |
 807                                        BYT_RT5640_MCLK_EN),
 808        },
 809        {       /* Point of View Mobii TAB-P1005W-232 (V2.0) */
 810                .matches = {
 811                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"),
 812                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"),
 813                },
 814                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 815                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 816                                        BYT_RT5640_OVCD_TH_2000UA |
 817                                        BYT_RT5640_OVCD_SF_0P75 |
 818                                        BYT_RT5640_DIFF_MIC |
 819                                        BYT_RT5640_SSP0_AIF1 |
 820                                        BYT_RT5640_MCLK_EN),
 821        },
 822        {
 823                /* Prowise PT301 */
 824                .matches = {
 825                        DMI_MATCH(DMI_SYS_VENDOR, "Prowise"),
 826                        DMI_MATCH(DMI_PRODUCT_NAME, "PT301"),
 827                },
 828                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 829                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 830                                        BYT_RT5640_OVCD_TH_2000UA |
 831                                        BYT_RT5640_OVCD_SF_0P75 |
 832                                        BYT_RT5640_DIFF_MIC |
 833                                        BYT_RT5640_SSP0_AIF1 |
 834                                        BYT_RT5640_MCLK_EN),
 835        },
 836        {
 837                /* Teclast X89 */
 838                .matches = {
 839                        DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
 840                        DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
 841                },
 842                .driver_data = (void *)(BYT_RT5640_IN3_MAP |
 843                                        BYT_RT5640_JD_SRC_JD1_IN4P |
 844                                        BYT_RT5640_OVCD_TH_2000UA |
 845                                        BYT_RT5640_OVCD_SF_1P0 |
 846                                        BYT_RT5640_SSP0_AIF1 |
 847                                        BYT_RT5640_MCLK_EN),
 848        },
 849        {       /* Toshiba Satellite Click Mini L9W-B */
 850                .matches = {
 851                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 852                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"),
 853                },
 854                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 855                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 856                                        BYT_RT5640_OVCD_TH_1500UA |
 857                                        BYT_RT5640_OVCD_SF_0P75 |
 858                                        BYT_RT5640_SSP0_AIF1 |
 859                                        BYT_RT5640_MCLK_EN),
 860        },
 861        {       /* Toshiba Encore WT8-A */
 862                .matches = {
 863                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 864                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"),
 865                },
 866                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 867                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 868                                        BYT_RT5640_OVCD_TH_2000UA |
 869                                        BYT_RT5640_OVCD_SF_0P75 |
 870                                        BYT_RT5640_JD_NOT_INV |
 871                                        BYT_RT5640_MCLK_EN),
 872        },
 873        {       /* Toshiba Encore WT10-A */
 874                .matches = {
 875                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 876                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT10-A-103"),
 877                },
 878                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 879                                        BYT_RT5640_JD_SRC_JD1_IN4P |
 880                                        BYT_RT5640_OVCD_TH_2000UA |
 881                                        BYT_RT5640_OVCD_SF_0P75 |
 882                                        BYT_RT5640_SSP0_AIF2 |
 883                                        BYT_RT5640_MCLK_EN),
 884        },
 885        {       /* Voyo Winpad A15 */
 886                .matches = {
 887                        DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 888                        DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 889                        /* Above strings are too generic, also match on BIOS date */
 890                        DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"),
 891                },
 892                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 893                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 894                                        BYT_RT5640_OVCD_TH_2000UA |
 895                                        BYT_RT5640_OVCD_SF_0P75 |
 896                                        BYT_RT5640_DIFF_MIC |
 897                                        BYT_RT5640_MCLK_EN),
 898        },
 899        {       /* Catch-all for generic Insyde tablets, must be last */
 900                .matches = {
 901                        DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
 902                },
 903                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 904                                        BYT_RT5640_MCLK_EN |
 905                                        BYT_RT5640_SSP0_AIF1),
 906
 907        },
 908        {}
 909};
 910
 911/*
 912 * Note this MUST be called before snd_soc_register_card(), so that the props
 913 * are in place before the codec component driver's probe function parses them.
 914 */
 915static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
 916{
 917        struct property_entry props[MAX_NO_PROPS] = {};
 918        struct device *i2c_dev;
 919        int ret, cnt = 0;
 920
 921        i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
 922        if (!i2c_dev)
 923                return -EPROBE_DEFER;
 924
 925        switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
 926        case BYT_RT5640_DMIC1_MAP:
 927                props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin",
 928                                                  RT5640_DMIC1_DATA_PIN_IN1P);
 929                break;
 930        case BYT_RT5640_DMIC2_MAP:
 931                props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin",
 932                                                  RT5640_DMIC2_DATA_PIN_IN1N);
 933                break;
 934        case BYT_RT5640_IN1_MAP:
 935                if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
 936                        props[cnt++] =
 937                                PROPERTY_ENTRY_BOOL("realtek,in1-differential");
 938                break;
 939        case BYT_RT5640_IN3_MAP:
 940                if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
 941                        props[cnt++] =
 942                                PROPERTY_ENTRY_BOOL("realtek,in3-differential");
 943                break;
 944        }
 945
 946        if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
 947                props[cnt++] = PROPERTY_ENTRY_U32(
 948                                    "realtek,jack-detect-source",
 949                                    BYT_RT5640_JDSRC(byt_rt5640_quirk));
 950
 951                props[cnt++] = PROPERTY_ENTRY_U32(
 952                                    "realtek,over-current-threshold-microamp",
 953                                    BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);
 954
 955                props[cnt++] = PROPERTY_ENTRY_U32(
 956                                    "realtek,over-current-scale-factor",
 957                                    BYT_RT5640_OVCD_SF(byt_rt5640_quirk));
 958        }
 959
 960        if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
 961                props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
 962
 963        ret = device_add_properties(i2c_dev, props);
 964        put_device(i2c_dev);
 965
 966        return ret;
 967}
 968
 969static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
 970{
 971        struct snd_soc_card *card = runtime->card;
 972        struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
 973        struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component;
 974        const struct snd_soc_dapm_route *custom_map = NULL;
 975        int num_routes = 0;
 976        int ret;
 977
 978        card->dapm.idle_bias_off = true;
 979
 980        /* Start with RC clk for jack-detect (we disable MCLK below) */
 981        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
 982                snd_soc_component_update_bits(component, RT5640_GLB_CLK,
 983                        RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);
 984
 985        rt5640_sel_asrc_clk_src(component,
 986                                RT5640_DA_STEREO_FILTER |
 987                                RT5640_DA_MONO_L_FILTER |
 988                                RT5640_DA_MONO_R_FILTER |
 989                                RT5640_AD_STEREO_FILTER |
 990                                RT5640_AD_MONO_L_FILTER |
 991                                RT5640_AD_MONO_R_FILTER,
 992                                RT5640_CLK_SEL_ASRC);
 993
 994        ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
 995                                        ARRAY_SIZE(byt_rt5640_controls));
 996        if (ret) {
 997                dev_err(card->dev, "unable to add card controls\n");
 998                return ret;
 999        }
1000
1001        switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
1002        case BYT_RT5640_IN1_MAP:
1003                custom_map = byt_rt5640_intmic_in1_map;
1004                num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);
1005                break;
1006        case BYT_RT5640_IN3_MAP:
1007                custom_map = byt_rt5640_intmic_in3_map;
1008                num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);
1009                break;
1010        case BYT_RT5640_DMIC1_MAP:
1011                custom_map = byt_rt5640_intmic_dmic1_map;
1012                num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
1013                break;
1014        case BYT_RT5640_DMIC2_MAP:
1015                custom_map = byt_rt5640_intmic_dmic2_map;
1016                num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
1017                break;
1018        }
1019
1020        ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
1021        if (ret)
1022                return ret;
1023
1024        if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
1025                ret = snd_soc_dapm_add_routes(&card->dapm,
1026                                        byt_rt5640_ssp2_aif2_map,
1027                                        ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));
1028        } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
1029                ret = snd_soc_dapm_add_routes(&card->dapm,
1030                                        byt_rt5640_ssp0_aif1_map,
1031                                        ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));
1032        } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
1033                ret = snd_soc_dapm_add_routes(&card->dapm,
1034                                        byt_rt5640_ssp0_aif2_map,
1035                                        ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));
1036        } else {
1037                ret = snd_soc_dapm_add_routes(&card->dapm,
1038                                        byt_rt5640_ssp2_aif1_map,
1039                                        ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));
1040        }
1041        if (ret)
1042                return ret;
1043
1044        if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
1045                ret = snd_soc_dapm_add_routes(&card->dapm,
1046                                        byt_rt5640_mono_spk_map,
1047                                        ARRAY_SIZE(byt_rt5640_mono_spk_map));
1048        } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) {
1049                ret = snd_soc_dapm_add_routes(&card->dapm,
1050                                        byt_rt5640_stereo_spk_map,
1051                                        ARRAY_SIZE(byt_rt5640_stereo_spk_map));
1052        }
1053        if (ret)
1054                return ret;
1055
1056        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
1057                /*
1058                 * The firmware might enable the clock at
1059                 * boot (this information may or may not
1060                 * be reflected in the enable clock register).
1061                 * To change the rate we must disable the clock
1062                 * first to cover these cases. Due to common
1063                 * clock framework restrictions that do not allow
1064                 * to disable a clock that has not been enabled,
1065                 * we need to enable the clock first.
1066                 */
1067                ret = clk_prepare_enable(priv->mclk);
1068                if (!ret)
1069                        clk_disable_unprepare(priv->mclk);
1070
1071                if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)
1072                        ret = clk_set_rate(priv->mclk, 25000000);
1073                else
1074                        ret = clk_set_rate(priv->mclk, 19200000);
1075
1076                if (ret) {
1077                        dev_err(card->dev, "unable to set MCLK rate\n");
1078                        return ret;
1079                }
1080        }
1081
1082        if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
1083                ret = snd_soc_card_jack_new(card, "Headset",
1084                                            SND_JACK_HEADSET | SND_JACK_BTN_0,
1085                                            &priv->jack, rt5640_pins,
1086                                            ARRAY_SIZE(rt5640_pins));
1087                if (ret) {
1088                        dev_err(card->dev, "Jack creation failed %d\n", ret);
1089                        return ret;
1090                }
1091                snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
1092                                 KEY_PLAYPAUSE);
1093                snd_soc_component_set_jack(component, &priv->jack, NULL);
1094        }
1095
1096        return 0;
1097}
1098
1099static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
1100                            struct snd_pcm_hw_params *params)
1101{
1102        struct snd_interval *rate = hw_param_interval(params,
1103                        SNDRV_PCM_HW_PARAM_RATE);
1104        struct snd_interval *channels = hw_param_interval(params,
1105                                                SNDRV_PCM_HW_PARAM_CHANNELS);
1106        int ret, bits;
1107
1108        /* The DSP will covert the FE rate to 48k, stereo */
1109        rate->min = rate->max = 48000;
1110        channels->min = channels->max = 2;
1111
1112        if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
1113            (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
1114                /* set SSP0 to 16-bit */
1115                params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
1116                bits = 16;
1117        } else {
1118                /* set SSP2 to 24-bit */
1119                params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
1120                bits = 24;
1121        }
1122
1123        /*
1124         * Default mode for SSP configuration is TDM 4 slot, override config
1125         * with explicit setting to I2S 2ch. The word length is set with
1126         * dai_set_tdm_slot() since there is no other API exposed
1127         */
1128        ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
1129                                  SND_SOC_DAIFMT_I2S     |
1130                                  SND_SOC_DAIFMT_NB_NF   |
1131                                  SND_SOC_DAIFMT_CBS_CFS);
1132        if (ret < 0) {
1133                dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
1134                return ret;
1135        }
1136
1137        ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);
1138        if (ret < 0) {
1139                dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
1140                return ret;
1141        }
1142
1143        return 0;
1144}
1145
1146static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)
1147{
1148        return snd_pcm_hw_constraint_single(substream->runtime,
1149                        SNDRV_PCM_HW_PARAM_RATE, 48000);
1150}
1151
1152static const struct snd_soc_ops byt_rt5640_aif1_ops = {
1153        .startup = byt_rt5640_aif1_startup,
1154};
1155
1156static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {
1157        .hw_params = byt_rt5640_aif1_hw_params,
1158};
1159
1160SND_SOC_DAILINK_DEF(dummy,
1161        DAILINK_COMP_ARRAY(COMP_DUMMY()));
1162
1163SND_SOC_DAILINK_DEF(media,
1164        DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
1165
1166SND_SOC_DAILINK_DEF(deepbuffer,
1167        DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
1168
1169SND_SOC_DAILINK_DEF(ssp2_port,
1170        /* overwritten for ssp0 routing */
1171        DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
1172SND_SOC_DAILINK_DEF(ssp2_codec,
1173        DAILINK_COMP_ARRAY(COMP_CODEC(
1174        /* overwritten with HID */ "i2c-10EC5640:00",
1175        /* changed w/ quirk */  "rt5640-aif1")));
1176
1177SND_SOC_DAILINK_DEF(platform,
1178        DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
1179
1180static struct snd_soc_dai_link byt_rt5640_dais[] = {
1181        [MERR_DPCM_AUDIO] = {
1182                .name = "Baytrail Audio Port",
1183                .stream_name = "Baytrail Audio",
1184                .nonatomic = true,
1185                .dynamic = 1,
1186                .dpcm_playback = 1,
1187                .dpcm_capture = 1,
1188                .ops = &byt_rt5640_aif1_ops,
1189                SND_SOC_DAILINK_REG(media, dummy, platform),
1190        },
1191        [MERR_DPCM_DEEP_BUFFER] = {
1192                .name = "Deep-Buffer Audio Port",
1193                .stream_name = "Deep-Buffer Audio",
1194                .nonatomic = true,
1195                .dynamic = 1,
1196                .dpcm_playback = 1,
1197                .ops = &byt_rt5640_aif1_ops,
1198                SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
1199        },
1200                /* back ends */
1201        {
1202                .name = "SSP2-Codec",
1203                .id = 0,
1204                .no_pcm = 1,
1205                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
1206                                                | SND_SOC_DAIFMT_CBS_CFS,
1207                .be_hw_params_fixup = byt_rt5640_codec_fixup,
1208                .nonatomic = true,
1209                .dpcm_playback = 1,
1210                .dpcm_capture = 1,
1211                .init = byt_rt5640_init,
1212                .ops = &byt_rt5640_be_ssp2_ops,
1213                SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
1214        },
1215};
1216
1217/* SoC card */
1218static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
1219#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
1220static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */
1221#endif
1222static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */
1223
1224static int byt_rt5640_suspend(struct snd_soc_card *card)
1225{
1226        struct snd_soc_component *component;
1227
1228        if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
1229                return 0;
1230
1231        for_each_card_components(card, component) {
1232                if (!strcmp(component->name, byt_rt5640_codec_name)) {
1233                        dev_dbg(component->dev, "disabling jack detect before suspend\n");
1234                        snd_soc_component_set_jack(component, NULL, NULL);
1235                        break;
1236                }
1237        }
1238
1239        return 0;
1240}
1241
1242static int byt_rt5640_resume(struct snd_soc_card *card)
1243{
1244        struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
1245        struct snd_soc_component *component;
1246
1247        if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
1248                return 0;
1249
1250        for_each_card_components(card, component) {
1251                if (!strcmp(component->name, byt_rt5640_codec_name)) {
1252                        dev_dbg(component->dev, "re-enabling jack detect after resume\n");
1253                        snd_soc_component_set_jack(component, &priv->jack, NULL);
1254                        break;
1255                }
1256        }
1257
1258        return 0;
1259}
1260
1261/* use space before codec name to simplify card ID, and simplify driver name */
1262#define SOF_CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */
1263#define SOF_DRIVER_NAME "SOF"
1264
1265#define CARD_NAME "bytcr-rt5640"
1266#define DRIVER_NAME NULL /* card name will be used for driver name */
1267
1268static struct snd_soc_card byt_rt5640_card = {
1269        .owner = THIS_MODULE,
1270        .dai_link = byt_rt5640_dais,
1271        .num_links = ARRAY_SIZE(byt_rt5640_dais),
1272        .dapm_widgets = byt_rt5640_widgets,
1273        .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),
1274        .dapm_routes = byt_rt5640_audio_map,
1275        .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),
1276        .fully_routed = true,
1277        .suspend_pre = byt_rt5640_suspend,
1278        .resume_post = byt_rt5640_resume,
1279};
1280
1281struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
1282        u64 aif_value;       /* 1: AIF1, 2: AIF2 */
1283        u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
1284};
1285
1286static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
1287{
1288        struct device *dev = &pdev->dev;
1289        static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };
1290        __maybe_unused const char *spk_type;
1291        const struct dmi_system_id *dmi_id;
1292        struct byt_rt5640_private *priv;
1293        struct snd_soc_acpi_mach *mach;
1294        const char *platform_name;
1295        struct acpi_device *adev;
1296        bool sof_parent;
1297        int ret_val = 0;
1298        int dai_index = 0;
1299        int i, cfg_spk;
1300        int aif;
1301
1302        is_bytcr = false;
1303        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1304        if (!priv)
1305                return -ENOMEM;
1306
1307        /* register the soc card */
1308        byt_rt5640_card.dev = &pdev->dev;
1309        mach = byt_rt5640_card.dev->platform_data;
1310        snd_soc_card_set_drvdata(&byt_rt5640_card, priv);
1311
1312        /* fix index of codec dai */
1313        for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
1314                if (!strcmp(byt_rt5640_dais[i].codecs->name,
1315                            "i2c-10EC5640:00")) {
1316                        dai_index = i;
1317                        break;
1318                }
1319        }
1320
1321        /* fixup codec name based on HID */
1322        adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
1323        if (adev) {
1324                snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
1325                         "i2c-%s", acpi_dev_name(adev));
1326                put_device(&adev->dev);
1327                byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
1328        }
1329
1330        /*
1331         * swap SSP0 if bytcr is detected
1332         * (will be overridden if DMI quirk is detected)
1333         */
1334        if (soc_intel_is_byt()) {
1335                if (mach->mach_params.acpi_ipc_irq_index == 0)
1336                        is_bytcr = true;
1337        }
1338
1339        if (is_bytcr) {
1340                /*
1341                 * Baytrail CR platforms may have CHAN package in BIOS, try
1342                 * to find relevant routing quirk based as done on Windows
1343                 * platforms. We have to read the information directly from the
1344                 * BIOS, at this stage the card is not created and the links
1345                 * with the codec driver/pdata are non-existent
1346                 */
1347
1348                struct acpi_chan_package chan_package;
1349
1350                /* format specified: 2 64-bit integers */
1351                struct acpi_buffer format = {sizeof("NN"), "NN"};
1352                struct acpi_buffer state = {0, NULL};
1353                struct snd_soc_acpi_package_context pkg_ctx;
1354                bool pkg_found = false;
1355
1356                state.length = sizeof(chan_package);
1357                state.pointer = &chan_package;
1358
1359                pkg_ctx.name = "CHAN";
1360                pkg_ctx.length = 2;
1361                pkg_ctx.format = &format;
1362                pkg_ctx.state = &state;
1363                pkg_ctx.data_valid = false;
1364
1365                pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
1366                                                               &pkg_ctx);
1367                if (pkg_found) {
1368                        if (chan_package.aif_value == 1) {
1369                                dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
1370                                byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;
1371                        } else  if (chan_package.aif_value == 2) {
1372                                dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
1373                                byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1374                        } else {
1375                                dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
1376                                pkg_found = false;
1377                        }
1378                }
1379
1380                if (!pkg_found) {
1381                        /* no BIOS indications, assume SSP0-AIF2 connection */
1382                        byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1383                }
1384
1385                /* change defaults for Baytrail-CR capture */
1386                byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS;
1387        } else {
1388                byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP |
1389                                    BYT_RT5640_JD_SRC_JD2_IN4N |
1390                                    BYT_RT5640_OVCD_TH_2000UA |
1391                                    BYT_RT5640_OVCD_SF_0P75;
1392        }
1393
1394        /* check quirks before creating card */
1395        dmi_id = dmi_first_match(byt_rt5640_quirk_table);
1396        if (dmi_id)
1397                byt_rt5640_quirk = (unsigned long)dmi_id->driver_data;
1398        if (quirk_override != -1) {
1399                dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
1400                         byt_rt5640_quirk, quirk_override);
1401                byt_rt5640_quirk = quirk_override;
1402        }
1403
1404        /* Must be called before register_card, also see declaration comment. */
1405        ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
1406        if (ret_val)
1407                return ret_val;
1408
1409        log_quirks(&pdev->dev);
1410
1411        if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||
1412            (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
1413                byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2";
1414                aif = 2;
1415        } else {
1416                aif = 1;
1417        }
1418
1419        if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
1420            (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2))
1421                byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port";
1422
1423        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
1424                priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
1425                if (IS_ERR(priv->mclk)) {
1426                        ret_val = PTR_ERR(priv->mclk);
1427
1428                        dev_err(&pdev->dev,
1429                                "Failed to get MCLK from pmc_plt_clk_3: %d\n",
1430                                ret_val);
1431
1432                        /*
1433                         * Fall back to bit clock usage for -ENOENT (clock not
1434                         * available likely due to missing dependencies), bail
1435                         * for all other errors, including -EPROBE_DEFER
1436                         */
1437                        if (ret_val != -ENOENT)
1438                                return ret_val;
1439                        byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
1440                }
1441        }
1442
1443        if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {
1444                cfg_spk = 0;
1445                spk_type = "none";
1446        } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
1447                cfg_spk = 1;
1448                spk_type = "mono";
1449        } else {
1450                cfg_spk = 2;
1451                spk_type = "stereo";
1452        }
1453
1454        snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
1455                 "cfg-spk:%d cfg-mic:%s aif:%d", cfg_spk,
1456                 map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif);
1457        byt_rt5640_card.components = byt_rt5640_components;
1458#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
1459        snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
1460                 "bytcr-rt5640-%s-spk-%s-mic", spk_type,
1461                 map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
1462        byt_rt5640_card.long_name = byt_rt5640_long_name;
1463#endif
1464
1465        /* override plaform name, if required */
1466        platform_name = mach->mach_params.platform;
1467
1468        ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,
1469                                                        platform_name);
1470        if (ret_val)
1471                return ret_val;
1472
1473        sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
1474
1475        /* set card and driver name */
1476        if (sof_parent) {
1477                byt_rt5640_card.name = SOF_CARD_NAME;
1478                byt_rt5640_card.driver_name = SOF_DRIVER_NAME;
1479        } else {
1480                byt_rt5640_card.name = CARD_NAME;
1481                byt_rt5640_card.driver_name = DRIVER_NAME;
1482        }
1483
1484        /* set pm ops */
1485        if (sof_parent)
1486                dev->driver->pm = &snd_soc_pm_ops;
1487
1488        ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
1489
1490        if (ret_val) {
1491                dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
1492                        ret_val);
1493                return ret_val;
1494        }
1495        platform_set_drvdata(pdev, &byt_rt5640_card);
1496        return ret_val;
1497}
1498
1499static struct platform_driver snd_byt_rt5640_mc_driver = {
1500        .driver = {
1501                .name = "bytcr_rt5640",
1502        },
1503        .probe = snd_byt_rt5640_mc_probe,
1504};
1505
1506module_platform_driver(snd_byt_rt5640_mc_driver);
1507
1508MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
1509MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
1510MODULE_LICENSE("GPL v2");
1511MODULE_ALIAS("platform:bytcr_rt5640");
1512