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_MONO_SPEAKER |
 486                                        BYT_RT5640_DIFF_MIC |
 487                                        BYT_RT5640_SSP0_AIF2 |
 488                                        BYT_RT5640_MCLK_EN),
 489        },
 490        {       /* Chuwi Vi8 (CWI506) */
 491                .matches = {
 492                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
 493                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),
 494                        /* The above are too generic, also match BIOS info */
 495                        DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
 496                },
 497                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 498                                        BYT_RT5640_MONO_SPEAKER |
 499                                        BYT_RT5640_SSP0_AIF1 |
 500                                        BYT_RT5640_MCLK_EN),
 501        },
 502        {
 503                /* Chuwi Vi10 (CWI505) */
 504                .matches = {
 505                        DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
 506                        DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"),
 507                        DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
 508                        DMI_MATCH(DMI_PRODUCT_NAME, "S165"),
 509                },
 510                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 511                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 512                                        BYT_RT5640_OVCD_TH_2000UA |
 513                                        BYT_RT5640_OVCD_SF_0P75 |
 514                                        BYT_RT5640_DIFF_MIC |
 515                                        BYT_RT5640_SSP0_AIF1 |
 516                                        BYT_RT5640_MCLK_EN),
 517        },
 518        {
 519                .matches = {
 520                        DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
 521                        DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
 522                },
 523                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP),
 524        },
 525        {       /* Connect Tablet 9 */
 526                .matches = {
 527                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Connect"),
 528                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Tablet 9"),
 529                },
 530                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 531                                        BYT_RT5640_MONO_SPEAKER |
 532                                        BYT_RT5640_SSP0_AIF1 |
 533                                        BYT_RT5640_MCLK_EN),
 534        },
 535        {
 536                .matches = {
 537                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 538                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Venue 8 Pro 5830"),
 539                },
 540                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 541                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 542                                        BYT_RT5640_OVCD_TH_2000UA |
 543                                        BYT_RT5640_OVCD_SF_0P75 |
 544                                        BYT_RT5640_MONO_SPEAKER |
 545                                        BYT_RT5640_MCLK_EN),
 546        },
 547        {       /* Estar Beauty HD MID 7316R */
 548                .matches = {
 549                        DMI_MATCH(DMI_SYS_VENDOR, "Estar"),
 550                        DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
 551                },
 552                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 553                                        BYT_RT5640_MONO_SPEAKER |
 554                                        BYT_RT5640_SSP0_AIF1 |
 555                                        BYT_RT5640_MCLK_EN),
 556        },
 557        {
 558                .matches = {
 559                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 560                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP ElitePad 1000 G2"),
 561                },
 562                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 563                                        BYT_RT5640_MCLK_EN),
 564        },
 565        {       /* HP Pavilion x2 10-k0XX, 10-n0XX */
 566                .matches = {
 567                        DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 568                        DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
 569                },
 570                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 571                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 572                                        BYT_RT5640_OVCD_TH_1500UA |
 573                                        BYT_RT5640_OVCD_SF_0P75 |
 574                                        BYT_RT5640_SSP0_AIF1 |
 575                                        BYT_RT5640_MCLK_EN),
 576        },
 577        {       /* HP Pavilion x2 10-p0XX */
 578                .matches = {
 579                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
 580                        DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
 581                },
 582                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 583                                        BYT_RT5640_JD_SRC_JD1_IN4P |
 584                                        BYT_RT5640_OVCD_TH_2000UA |
 585                                        BYT_RT5640_OVCD_SF_0P75 |
 586                                        BYT_RT5640_MCLK_EN),
 587        },
 588        {       /* HP Stream 7 */
 589                .matches = {
 590                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 591                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Stream 7 Tablet"),
 592                },
 593                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 594                                        BYT_RT5640_MONO_SPEAKER |
 595                                        BYT_RT5640_JD_NOT_INV |
 596                                        BYT_RT5640_SSP0_AIF1 |
 597                                        BYT_RT5640_MCLK_EN),
 598        },
 599        {       /* I.T.Works TW891 */
 600                .matches = {
 601                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
 602                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),
 603                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
 604                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
 605                },
 606                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 607                                        BYT_RT5640_MONO_SPEAKER |
 608                                        BYT_RT5640_SSP0_AIF1 |
 609                                        BYT_RT5640_MCLK_EN),
 610        },
 611        {       /* Lamina I8270 / T701BR.SE */
 612                .matches = {
 613                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Lamina"),
 614                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "T701BR.SE"),
 615                },
 616                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 617                                        BYT_RT5640_MONO_SPEAKER |
 618                                        BYT_RT5640_JD_NOT_INV |
 619                                        BYT_RT5640_SSP0_AIF1 |
 620                                        BYT_RT5640_MCLK_EN),
 621        },
 622        {       /* Lenovo Miix 2 8 */
 623                .matches = {
 624                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 625                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "20326"),
 626                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Hiking"),
 627                },
 628                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 629                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 630                                        BYT_RT5640_OVCD_TH_2000UA |
 631                                        BYT_RT5640_OVCD_SF_0P75 |
 632                                        BYT_RT5640_MONO_SPEAKER |
 633                                        BYT_RT5640_MCLK_EN),
 634        },
 635        {       /* Linx Linx7 tablet */
 636                .matches = {
 637                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"),
 638                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LINX7"),
 639                },
 640                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 641                                        BYT_RT5640_MONO_SPEAKER |
 642                                        BYT_RT5640_JD_NOT_INV |
 643                                        BYT_RT5640_SSP0_AIF1 |
 644                                        BYT_RT5640_MCLK_EN),
 645        },
 646        {       /* Mele PCG03 Mini PC */
 647                .matches = {
 648                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Mini PC"),
 649                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Mini PC"),
 650                },
 651                .driver_data = (void *)(BYT_RT5640_NO_INTERNAL_MIC_MAP |
 652                                        BYT_RT5640_NO_SPEAKERS |
 653                                        BYT_RT5640_SSP0_AIF1),
 654        },
 655        {       /* MPMAN Converter 9, similar hw as the I.T.Works TW891 2-in-1 */
 656                .matches = {
 657                        DMI_MATCH(DMI_SYS_VENDOR, "MPMAN"),
 658                        DMI_MATCH(DMI_PRODUCT_NAME, "Converter9"),
 659                },
 660                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 661                                        BYT_RT5640_MONO_SPEAKER |
 662                                        BYT_RT5640_SSP0_AIF1 |
 663                                        BYT_RT5640_MCLK_EN),
 664        },
 665        {
 666                /* MPMAN MPWIN895CL */
 667                .matches = {
 668                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MPMAN"),
 669                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MPWIN8900CL"),
 670                },
 671                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 672                                        BYT_RT5640_MONO_SPEAKER |
 673                                        BYT_RT5640_SSP0_AIF1 |
 674                                        BYT_RT5640_MCLK_EN),
 675        },
 676        {       /* MSI S100 tablet */
 677                .matches = {
 678                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."),
 679                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "S100"),
 680                },
 681                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 682                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 683                                        BYT_RT5640_OVCD_TH_2000UA |
 684                                        BYT_RT5640_OVCD_SF_0P75 |
 685                                        BYT_RT5640_MONO_SPEAKER |
 686                                        BYT_RT5640_DIFF_MIC |
 687                                        BYT_RT5640_MCLK_EN),
 688        },
 689        {       /* Nuvison/TMax TM800W560 */
 690                .matches = {
 691                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TMAX"),
 692                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TM800W560L"),
 693                },
 694                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 695                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 696                                        BYT_RT5640_OVCD_TH_2000UA |
 697                                        BYT_RT5640_OVCD_SF_0P75 |
 698                                        BYT_RT5640_JD_NOT_INV |
 699                                        BYT_RT5640_DIFF_MIC |
 700                                        BYT_RT5640_SSP0_AIF1 |
 701                                        BYT_RT5640_MCLK_EN),
 702        },
 703        {       /* Onda v975w */
 704                .matches = {
 705                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 706                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 707                        /* The above are too generic, also match BIOS info */
 708                        DMI_EXACT_MATCH(DMI_BIOS_VERSION, "5.6.5"),
 709                        DMI_EXACT_MATCH(DMI_BIOS_DATE, "07/25/2014"),
 710                },
 711                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 712                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 713                                        BYT_RT5640_OVCD_TH_2000UA |
 714                                        BYT_RT5640_OVCD_SF_0P75 |
 715                                        BYT_RT5640_DIFF_MIC |
 716                                        BYT_RT5640_MCLK_EN),
 717        },
 718        {       /* Pipo W4 */
 719                .matches = {
 720                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 721                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 722                        /* The above are too generic, also match BIOS info */
 723                        DMI_MATCH(DMI_BIOS_VERSION, "V8L_WIN32_CHIPHD"),
 724                },
 725                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 726                                        BYT_RT5640_MONO_SPEAKER |
 727                                        BYT_RT5640_SSP0_AIF1 |
 728                                        BYT_RT5640_MCLK_EN),
 729        },
 730        {       /* Point of View Mobii TAB-P800W (V2.0) */
 731                .matches = {
 732                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 733                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 734                        /* The above are too generic, also match BIOS info */
 735                        DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
 736                        DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/24/2014"),
 737                },
 738                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 739                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 740                                        BYT_RT5640_OVCD_TH_2000UA |
 741                                        BYT_RT5640_OVCD_SF_0P75 |
 742                                        BYT_RT5640_MONO_SPEAKER |
 743                                        BYT_RT5640_DIFF_MIC |
 744                                        BYT_RT5640_SSP0_AIF2 |
 745                                        BYT_RT5640_MCLK_EN),
 746        },
 747        {       /* Point of View Mobii TAB-P800W (V2.1) */
 748                .matches = {
 749                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 750                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 751                        /* The above are too generic, also match BIOS info */
 752                        DMI_EXACT_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
 753                        DMI_EXACT_MATCH(DMI_BIOS_DATE, "08/22/2014"),
 754                },
 755                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 756                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 757                                        BYT_RT5640_OVCD_TH_2000UA |
 758                                        BYT_RT5640_OVCD_SF_0P75 |
 759                                        BYT_RT5640_MONO_SPEAKER |
 760                                        BYT_RT5640_DIFF_MIC |
 761                                        BYT_RT5640_SSP0_AIF2 |
 762                                        BYT_RT5640_MCLK_EN),
 763        },
 764        {       /* Point of View Mobii TAB-P1005W-232 (V2.0) */
 765                .matches = {
 766                        DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "POV"),
 767                        DMI_EXACT_MATCH(DMI_BOARD_NAME, "I102A"),
 768                },
 769                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 770                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 771                                        BYT_RT5640_OVCD_TH_2000UA |
 772                                        BYT_RT5640_OVCD_SF_0P75 |
 773                                        BYT_RT5640_DIFF_MIC |
 774                                        BYT_RT5640_SSP0_AIF1 |
 775                                        BYT_RT5640_MCLK_EN),
 776        },
 777        {
 778                /* Prowise PT301 */
 779                .matches = {
 780                        DMI_MATCH(DMI_SYS_VENDOR, "Prowise"),
 781                        DMI_MATCH(DMI_PRODUCT_NAME, "PT301"),
 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_DIFF_MIC |
 788                                        BYT_RT5640_SSP0_AIF1 |
 789                                        BYT_RT5640_MCLK_EN),
 790        },
 791        {
 792                /* Teclast X89 */
 793                .matches = {
 794                        DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
 795                        DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
 796                },
 797                .driver_data = (void *)(BYT_RT5640_IN3_MAP |
 798                                        BYT_RT5640_JD_SRC_JD1_IN4P |
 799                                        BYT_RT5640_OVCD_TH_2000UA |
 800                                        BYT_RT5640_OVCD_SF_1P0 |
 801                                        BYT_RT5640_SSP0_AIF1 |
 802                                        BYT_RT5640_MCLK_EN),
 803        },
 804        {       /* Toshiba Satellite Click Mini L9W-B */
 805                .matches = {
 806                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 807                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"),
 808                },
 809                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 810                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 811                                        BYT_RT5640_OVCD_TH_1500UA |
 812                                        BYT_RT5640_OVCD_SF_0P75 |
 813                                        BYT_RT5640_SSP0_AIF1 |
 814                                        BYT_RT5640_MCLK_EN),
 815        },
 816        {       /* Toshiba Encore WT8-A */
 817                .matches = {
 818                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 819                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT8-A"),
 820                },
 821                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 822                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 823                                        BYT_RT5640_OVCD_TH_2000UA |
 824                                        BYT_RT5640_OVCD_SF_0P75 |
 825                                        BYT_RT5640_JD_NOT_INV |
 826                                        BYT_RT5640_MCLK_EN),
 827        },
 828        {       /* Toshiba Encore WT10-A */
 829                .matches = {
 830                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
 831                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TOSHIBA WT10-A-103"),
 832                },
 833                .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
 834                                        BYT_RT5640_JD_SRC_JD1_IN4P |
 835                                        BYT_RT5640_OVCD_TH_2000UA |
 836                                        BYT_RT5640_OVCD_SF_0P75 |
 837                                        BYT_RT5640_SSP0_AIF2 |
 838                                        BYT_RT5640_MCLK_EN),
 839        },
 840        {       /* Voyo Winpad A15 */
 841                .matches = {
 842                        DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
 843                        DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
 844                        /* Above strings are too generic, also match on BIOS date */
 845                        DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"),
 846                },
 847                .driver_data = (void *)(BYT_RT5640_IN1_MAP |
 848                                        BYT_RT5640_JD_SRC_JD2_IN4N |
 849                                        BYT_RT5640_OVCD_TH_2000UA |
 850                                        BYT_RT5640_OVCD_SF_0P75 |
 851                                        BYT_RT5640_DIFF_MIC |
 852                                        BYT_RT5640_MCLK_EN),
 853        },
 854        {       /* Catch-all for generic Insyde tablets, must be last */
 855                .matches = {
 856                        DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
 857                },
 858                .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
 859                                        BYT_RT5640_MCLK_EN |
 860                                        BYT_RT5640_SSP0_AIF1),
 861
 862        },
 863        {}
 864};
 865
 866/*
 867 * Note this MUST be called before snd_soc_register_card(), so that the props
 868 * are in place before the codec component driver's probe function parses them.
 869 */
 870static int byt_rt5640_add_codec_device_props(const char *i2c_dev_name)
 871{
 872        struct property_entry props[MAX_NO_PROPS] = {};
 873        struct device *i2c_dev;
 874        int ret, cnt = 0;
 875
 876        i2c_dev = bus_find_device_by_name(&i2c_bus_type, NULL, i2c_dev_name);
 877        if (!i2c_dev)
 878                return -EPROBE_DEFER;
 879
 880        switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
 881        case BYT_RT5640_DMIC1_MAP:
 882                props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic1-data-pin",
 883                                                  RT5640_DMIC1_DATA_PIN_IN1P);
 884                break;
 885        case BYT_RT5640_DMIC2_MAP:
 886                props[cnt++] = PROPERTY_ENTRY_U32("realtek,dmic2-data-pin",
 887                                                  RT5640_DMIC2_DATA_PIN_IN1N);
 888                break;
 889        case BYT_RT5640_IN1_MAP:
 890                if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
 891                        props[cnt++] =
 892                                PROPERTY_ENTRY_BOOL("realtek,in1-differential");
 893                break;
 894        case BYT_RT5640_IN3_MAP:
 895                if (byt_rt5640_quirk & BYT_RT5640_DIFF_MIC)
 896                        props[cnt++] =
 897                                PROPERTY_ENTRY_BOOL("realtek,in3-differential");
 898                break;
 899        }
 900
 901        if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
 902                props[cnt++] = PROPERTY_ENTRY_U32(
 903                                    "realtek,jack-detect-source",
 904                                    BYT_RT5640_JDSRC(byt_rt5640_quirk));
 905
 906                props[cnt++] = PROPERTY_ENTRY_U32(
 907                                    "realtek,over-current-threshold-microamp",
 908                                    BYT_RT5640_OVCD_TH(byt_rt5640_quirk) * 100);
 909
 910                props[cnt++] = PROPERTY_ENTRY_U32(
 911                                    "realtek,over-current-scale-factor",
 912                                    BYT_RT5640_OVCD_SF(byt_rt5640_quirk));
 913        }
 914
 915        if (byt_rt5640_quirk & BYT_RT5640_JD_NOT_INV)
 916                props[cnt++] = PROPERTY_ENTRY_BOOL("realtek,jack-detect-not-inverted");
 917
 918        ret = device_add_properties(i2c_dev, props);
 919        put_device(i2c_dev);
 920
 921        return ret;
 922}
 923
 924static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
 925{
 926        struct snd_soc_card *card = runtime->card;
 927        struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
 928        struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component;
 929        const struct snd_soc_dapm_route *custom_map = NULL;
 930        int num_routes = 0;
 931        int ret;
 932
 933        card->dapm.idle_bias_off = true;
 934
 935        /* Start with RC clk for jack-detect (we disable MCLK below) */
 936        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN)
 937                snd_soc_component_update_bits(component, RT5640_GLB_CLK,
 938                        RT5640_SCLK_SRC_MASK, RT5640_SCLK_SRC_RCCLK);
 939
 940        rt5640_sel_asrc_clk_src(component,
 941                                RT5640_DA_STEREO_FILTER |
 942                                RT5640_DA_MONO_L_FILTER |
 943                                RT5640_DA_MONO_R_FILTER |
 944                                RT5640_AD_STEREO_FILTER |
 945                                RT5640_AD_MONO_L_FILTER |
 946                                RT5640_AD_MONO_R_FILTER,
 947                                RT5640_CLK_SEL_ASRC);
 948
 949        ret = snd_soc_add_card_controls(card, byt_rt5640_controls,
 950                                        ARRAY_SIZE(byt_rt5640_controls));
 951        if (ret) {
 952                dev_err(card->dev, "unable to add card controls\n");
 953                return ret;
 954        }
 955
 956        switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
 957        case BYT_RT5640_IN1_MAP:
 958                custom_map = byt_rt5640_intmic_in1_map;
 959                num_routes = ARRAY_SIZE(byt_rt5640_intmic_in1_map);
 960                break;
 961        case BYT_RT5640_IN3_MAP:
 962                custom_map = byt_rt5640_intmic_in3_map;
 963                num_routes = ARRAY_SIZE(byt_rt5640_intmic_in3_map);
 964                break;
 965        case BYT_RT5640_DMIC1_MAP:
 966                custom_map = byt_rt5640_intmic_dmic1_map;
 967                num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic1_map);
 968                break;
 969        case BYT_RT5640_DMIC2_MAP:
 970                custom_map = byt_rt5640_intmic_dmic2_map;
 971                num_routes = ARRAY_SIZE(byt_rt5640_intmic_dmic2_map);
 972                break;
 973        }
 974
 975        ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
 976        if (ret)
 977                return ret;
 978
 979        if (byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) {
 980                ret = snd_soc_dapm_add_routes(&card->dapm,
 981                                        byt_rt5640_ssp2_aif2_map,
 982                                        ARRAY_SIZE(byt_rt5640_ssp2_aif2_map));
 983        } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) {
 984                ret = snd_soc_dapm_add_routes(&card->dapm,
 985                                        byt_rt5640_ssp0_aif1_map,
 986                                        ARRAY_SIZE(byt_rt5640_ssp0_aif1_map));
 987        } else if (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2) {
 988                ret = snd_soc_dapm_add_routes(&card->dapm,
 989                                        byt_rt5640_ssp0_aif2_map,
 990                                        ARRAY_SIZE(byt_rt5640_ssp0_aif2_map));
 991        } else {
 992                ret = snd_soc_dapm_add_routes(&card->dapm,
 993                                        byt_rt5640_ssp2_aif1_map,
 994                                        ARRAY_SIZE(byt_rt5640_ssp2_aif1_map));
 995        }
 996        if (ret)
 997                return ret;
 998
 999        if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
1000                ret = snd_soc_dapm_add_routes(&card->dapm,
1001                                        byt_rt5640_mono_spk_map,
1002                                        ARRAY_SIZE(byt_rt5640_mono_spk_map));
1003        } else if (!(byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS)) {
1004                ret = snd_soc_dapm_add_routes(&card->dapm,
1005                                        byt_rt5640_stereo_spk_map,
1006                                        ARRAY_SIZE(byt_rt5640_stereo_spk_map));
1007        }
1008        if (ret)
1009                return ret;
1010
1011        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
1012                /*
1013                 * The firmware might enable the clock at
1014                 * boot (this information may or may not
1015                 * be reflected in the enable clock register).
1016                 * To change the rate we must disable the clock
1017                 * first to cover these cases. Due to common
1018                 * clock framework restrictions that do not allow
1019                 * to disable a clock that has not been enabled,
1020                 * we need to enable the clock first.
1021                 */
1022                ret = clk_prepare_enable(priv->mclk);
1023                if (!ret)
1024                        clk_disable_unprepare(priv->mclk);
1025
1026                if (byt_rt5640_quirk & BYT_RT5640_MCLK_25MHZ)
1027                        ret = clk_set_rate(priv->mclk, 25000000);
1028                else
1029                        ret = clk_set_rate(priv->mclk, 19200000);
1030
1031                if (ret) {
1032                        dev_err(card->dev, "unable to set MCLK rate\n");
1033                        return ret;
1034                }
1035        }
1036
1037        if (BYT_RT5640_JDSRC(byt_rt5640_quirk)) {
1038                ret = snd_soc_card_jack_new(card, "Headset",
1039                                            SND_JACK_HEADSET | SND_JACK_BTN_0,
1040                                            &priv->jack, rt5640_pins,
1041                                            ARRAY_SIZE(rt5640_pins));
1042                if (ret) {
1043                        dev_err(card->dev, "Jack creation failed %d\n", ret);
1044                        return ret;
1045                }
1046                snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0,
1047                                 KEY_PLAYPAUSE);
1048                snd_soc_component_set_jack(component, &priv->jack, NULL);
1049        }
1050
1051        return 0;
1052}
1053
1054static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd,
1055                            struct snd_pcm_hw_params *params)
1056{
1057        struct snd_interval *rate = hw_param_interval(params,
1058                        SNDRV_PCM_HW_PARAM_RATE);
1059        struct snd_interval *channels = hw_param_interval(params,
1060                                                SNDRV_PCM_HW_PARAM_CHANNELS);
1061        int ret, bits;
1062
1063        /* The DSP will covert the FE rate to 48k, stereo */
1064        rate->min = rate->max = 48000;
1065        channels->min = channels->max = 2;
1066
1067        if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
1068            (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) {
1069                /* set SSP0 to 16-bit */
1070                params_set_format(params, SNDRV_PCM_FORMAT_S16_LE);
1071                bits = 16;
1072        } else {
1073                /* set SSP2 to 24-bit */
1074                params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
1075                bits = 24;
1076        }
1077
1078        /*
1079         * Default mode for SSP configuration is TDM 4 slot, override config
1080         * with explicit setting to I2S 2ch. The word length is set with
1081         * dai_set_tdm_slot() since there is no other API exposed
1082         */
1083        ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0),
1084                                  SND_SOC_DAIFMT_I2S     |
1085                                  SND_SOC_DAIFMT_NB_NF   |
1086                                  SND_SOC_DAIFMT_CBS_CFS);
1087        if (ret < 0) {
1088                dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
1089                return ret;
1090        }
1091
1092        ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits);
1093        if (ret < 0) {
1094                dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
1095                return ret;
1096        }
1097
1098        return 0;
1099}
1100
1101static int byt_rt5640_aif1_startup(struct snd_pcm_substream *substream)
1102{
1103        return snd_pcm_hw_constraint_single(substream->runtime,
1104                        SNDRV_PCM_HW_PARAM_RATE, 48000);
1105}
1106
1107static const struct snd_soc_ops byt_rt5640_aif1_ops = {
1108        .startup = byt_rt5640_aif1_startup,
1109};
1110
1111static const struct snd_soc_ops byt_rt5640_be_ssp2_ops = {
1112        .hw_params = byt_rt5640_aif1_hw_params,
1113};
1114
1115SND_SOC_DAILINK_DEF(dummy,
1116        DAILINK_COMP_ARRAY(COMP_DUMMY()));
1117
1118SND_SOC_DAILINK_DEF(media,
1119        DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
1120
1121SND_SOC_DAILINK_DEF(deepbuffer,
1122        DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
1123
1124SND_SOC_DAILINK_DEF(ssp2_port,
1125        /* overwritten for ssp0 routing */
1126        DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
1127SND_SOC_DAILINK_DEF(ssp2_codec,
1128        DAILINK_COMP_ARRAY(COMP_CODEC(
1129        /* overwritten with HID */ "i2c-10EC5640:00",
1130        /* changed w/ quirk */  "rt5640-aif1")));
1131
1132SND_SOC_DAILINK_DEF(platform,
1133        DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
1134
1135static struct snd_soc_dai_link byt_rt5640_dais[] = {
1136        [MERR_DPCM_AUDIO] = {
1137                .name = "Baytrail Audio Port",
1138                .stream_name = "Baytrail Audio",
1139                .nonatomic = true,
1140                .dynamic = 1,
1141                .dpcm_playback = 1,
1142                .dpcm_capture = 1,
1143                .ops = &byt_rt5640_aif1_ops,
1144                SND_SOC_DAILINK_REG(media, dummy, platform),
1145        },
1146        [MERR_DPCM_DEEP_BUFFER] = {
1147                .name = "Deep-Buffer Audio Port",
1148                .stream_name = "Deep-Buffer Audio",
1149                .nonatomic = true,
1150                .dynamic = 1,
1151                .dpcm_playback = 1,
1152                .ops = &byt_rt5640_aif1_ops,
1153                SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
1154        },
1155                /* back ends */
1156        {
1157                .name = "SSP2-Codec",
1158                .id = 0,
1159                .no_pcm = 1,
1160                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
1161                                                | SND_SOC_DAIFMT_CBS_CFS,
1162                .be_hw_params_fixup = byt_rt5640_codec_fixup,
1163                .nonatomic = true,
1164                .dpcm_playback = 1,
1165                .dpcm_capture = 1,
1166                .init = byt_rt5640_init,
1167                .ops = &byt_rt5640_be_ssp2_ops,
1168                SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
1169        },
1170};
1171
1172/* SoC card */
1173static char byt_rt5640_codec_name[SND_ACPI_I2C_ID_LEN];
1174#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
1175static char byt_rt5640_long_name[40]; /* = "bytcr-rt5640-*-spk-*-mic" */
1176#endif
1177static char byt_rt5640_components[32]; /* = "cfg-spk:* cfg-mic:*" */
1178
1179static int byt_rt5640_suspend(struct snd_soc_card *card)
1180{
1181        struct snd_soc_component *component;
1182
1183        if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
1184                return 0;
1185
1186        for_each_card_components(card, component) {
1187                if (!strcmp(component->name, byt_rt5640_codec_name)) {
1188                        dev_dbg(component->dev, "disabling jack detect before suspend\n");
1189                        snd_soc_component_set_jack(component, NULL, NULL);
1190                        break;
1191                }
1192        }
1193
1194        return 0;
1195}
1196
1197static int byt_rt5640_resume(struct snd_soc_card *card)
1198{
1199        struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card);
1200        struct snd_soc_component *component;
1201
1202        if (!BYT_RT5640_JDSRC(byt_rt5640_quirk))
1203                return 0;
1204
1205        for_each_card_components(card, component) {
1206                if (!strcmp(component->name, byt_rt5640_codec_name)) {
1207                        dev_dbg(component->dev, "re-enabling jack detect after resume\n");
1208                        snd_soc_component_set_jack(component, &priv->jack, NULL);
1209                        break;
1210                }
1211        }
1212
1213        return 0;
1214}
1215
1216/* use space before codec name to simplify card ID, and simplify driver name */
1217#define SOF_CARD_NAME "bytcht rt5640" /* card name will be 'sof-bytcht rt5640' */
1218#define SOF_DRIVER_NAME "SOF"
1219
1220#define CARD_NAME "bytcr-rt5640"
1221#define DRIVER_NAME NULL /* card name will be used for driver name */
1222
1223static struct snd_soc_card byt_rt5640_card = {
1224        .owner = THIS_MODULE,
1225        .dai_link = byt_rt5640_dais,
1226        .num_links = ARRAY_SIZE(byt_rt5640_dais),
1227        .dapm_widgets = byt_rt5640_widgets,
1228        .num_dapm_widgets = ARRAY_SIZE(byt_rt5640_widgets),
1229        .dapm_routes = byt_rt5640_audio_map,
1230        .num_dapm_routes = ARRAY_SIZE(byt_rt5640_audio_map),
1231        .fully_routed = true,
1232        .suspend_pre = byt_rt5640_suspend,
1233        .resume_post = byt_rt5640_resume,
1234};
1235
1236struct acpi_chan_package {   /* ACPICA seems to require 64 bit integers */
1237        u64 aif_value;       /* 1: AIF1, 2: AIF2 */
1238        u64 mclock_value;    /* usually 25MHz (0x17d7940), ignored */
1239};
1240
1241static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
1242{
1243        struct device *dev = &pdev->dev;
1244        static const char * const map_name[] = { "dmic1", "dmic2", "in1", "in3", "none" };
1245        __maybe_unused const char *spk_type;
1246        const struct dmi_system_id *dmi_id;
1247        struct byt_rt5640_private *priv;
1248        struct snd_soc_acpi_mach *mach;
1249        const char *platform_name;
1250        struct acpi_device *adev;
1251        bool sof_parent;
1252        int ret_val = 0;
1253        int dai_index = 0;
1254        int i, cfg_spk;
1255
1256        is_bytcr = false;
1257        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1258        if (!priv)
1259                return -ENOMEM;
1260
1261        /* register the soc card */
1262        byt_rt5640_card.dev = &pdev->dev;
1263        mach = byt_rt5640_card.dev->platform_data;
1264        snd_soc_card_set_drvdata(&byt_rt5640_card, priv);
1265
1266        /* fix index of codec dai */
1267        for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
1268                if (!strcmp(byt_rt5640_dais[i].codecs->name,
1269                            "i2c-10EC5640:00")) {
1270                        dai_index = i;
1271                        break;
1272                }
1273        }
1274
1275        /* fixup codec name based on HID */
1276        adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1);
1277        if (adev) {
1278                snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
1279                         "i2c-%s", acpi_dev_name(adev));
1280                put_device(&adev->dev);
1281                byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name;
1282        }
1283
1284        /*
1285         * swap SSP0 if bytcr is detected
1286         * (will be overridden if DMI quirk is detected)
1287         */
1288        if (soc_intel_is_byt()) {
1289                if (mach->mach_params.acpi_ipc_irq_index == 0)
1290                        is_bytcr = true;
1291        }
1292
1293        if (is_bytcr) {
1294                /*
1295                 * Baytrail CR platforms may have CHAN package in BIOS, try
1296                 * to find relevant routing quirk based as done on Windows
1297                 * platforms. We have to read the information directly from the
1298                 * BIOS, at this stage the card is not created and the links
1299                 * with the codec driver/pdata are non-existent
1300                 */
1301
1302                struct acpi_chan_package chan_package;
1303
1304                /* format specified: 2 64-bit integers */
1305                struct acpi_buffer format = {sizeof("NN"), "NN"};
1306                struct acpi_buffer state = {0, NULL};
1307                struct snd_soc_acpi_package_context pkg_ctx;
1308                bool pkg_found = false;
1309
1310                state.length = sizeof(chan_package);
1311                state.pointer = &chan_package;
1312
1313                pkg_ctx.name = "CHAN";
1314                pkg_ctx.length = 2;
1315                pkg_ctx.format = &format;
1316                pkg_ctx.state = &state;
1317                pkg_ctx.data_valid = false;
1318
1319                pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
1320                                                               &pkg_ctx);
1321                if (pkg_found) {
1322                        if (chan_package.aif_value == 1) {
1323                                dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
1324                                byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF1;
1325                        } else  if (chan_package.aif_value == 2) {
1326                                dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
1327                                byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1328                        } else {
1329                                dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
1330                                pkg_found = false;
1331                        }
1332                }
1333
1334                if (!pkg_found) {
1335                        /* no BIOS indications, assume SSP0-AIF2 connection */
1336                        byt_rt5640_quirk |= BYT_RT5640_SSP0_AIF2;
1337                }
1338
1339                /* change defaults for Baytrail-CR capture */
1340                byt_rt5640_quirk |= BYTCR_INPUT_DEFAULTS;
1341        } else {
1342                byt_rt5640_quirk |= BYT_RT5640_DMIC1_MAP |
1343                                    BYT_RT5640_JD_SRC_JD2_IN4N |
1344                                    BYT_RT5640_OVCD_TH_2000UA |
1345                                    BYT_RT5640_OVCD_SF_0P75;
1346        }
1347
1348        /* check quirks before creating card */
1349        dmi_id = dmi_first_match(byt_rt5640_quirk_table);
1350        if (dmi_id)
1351                byt_rt5640_quirk = (unsigned long)dmi_id->driver_data;
1352        if (quirk_override != -1) {
1353                dev_info(&pdev->dev, "Overriding quirk 0x%lx => 0x%x\n",
1354                         byt_rt5640_quirk, quirk_override);
1355                byt_rt5640_quirk = quirk_override;
1356        }
1357
1358        /* Must be called before register_card, also see declaration comment. */
1359        ret_val = byt_rt5640_add_codec_device_props(byt_rt5640_codec_name);
1360        if (ret_val)
1361                return ret_val;
1362
1363        log_quirks(&pdev->dev);
1364
1365        if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) ||
1366            (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2))
1367                byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2";
1368
1369        if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) ||
1370            (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2))
1371                byt_rt5640_dais[dai_index].cpus->dai_name = "ssp0-port";
1372
1373        if (byt_rt5640_quirk & BYT_RT5640_MCLK_EN) {
1374                priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
1375                if (IS_ERR(priv->mclk)) {
1376                        ret_val = PTR_ERR(priv->mclk);
1377
1378                        dev_err(&pdev->dev,
1379                                "Failed to get MCLK from pmc_plt_clk_3: %d\n",
1380                                ret_val);
1381
1382                        /*
1383                         * Fall back to bit clock usage for -ENOENT (clock not
1384                         * available likely due to missing dependencies), bail
1385                         * for all other errors, including -EPROBE_DEFER
1386                         */
1387                        if (ret_val != -ENOENT)
1388                                return ret_val;
1389                        byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
1390                }
1391        }
1392
1393        if (byt_rt5640_quirk & BYT_RT5640_NO_SPEAKERS) {
1394                cfg_spk = 0;
1395                spk_type = "none";
1396        } else if (byt_rt5640_quirk & BYT_RT5640_MONO_SPEAKER) {
1397                cfg_spk = 1;
1398                spk_type = "mono";
1399        } else {
1400                cfg_spk = 2;
1401                spk_type = "stereo";
1402        }
1403
1404        snprintf(byt_rt5640_components, sizeof(byt_rt5640_components),
1405                 "cfg-spk:%d cfg-mic:%s", cfg_spk,
1406                 map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
1407        byt_rt5640_card.components = byt_rt5640_components;
1408#if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES)
1409        snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name),
1410                 "bytcr-rt5640-%s-spk-%s-mic", spk_type,
1411                 map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]);
1412        byt_rt5640_card.long_name = byt_rt5640_long_name;
1413#endif
1414
1415        /* override plaform name, if required */
1416        platform_name = mach->mach_params.platform;
1417
1418        ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card,
1419                                                        platform_name);
1420        if (ret_val)
1421                return ret_val;
1422
1423        sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
1424
1425        /* set card and driver name */
1426        if (sof_parent) {
1427                byt_rt5640_card.name = SOF_CARD_NAME;
1428                byt_rt5640_card.driver_name = SOF_DRIVER_NAME;
1429        } else {
1430                byt_rt5640_card.name = CARD_NAME;
1431                byt_rt5640_card.driver_name = DRIVER_NAME;
1432        }
1433
1434        /* set pm ops */
1435        if (sof_parent)
1436                dev->driver->pm = &snd_soc_pm_ops;
1437
1438        ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
1439
1440        if (ret_val) {
1441                dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
1442                        ret_val);
1443                return ret_val;
1444        }
1445        platform_set_drvdata(pdev, &byt_rt5640_card);
1446        return ret_val;
1447}
1448
1449static struct platform_driver snd_byt_rt5640_mc_driver = {
1450        .driver = {
1451                .name = "bytcr_rt5640",
1452        },
1453        .probe = snd_byt_rt5640_mc_probe,
1454};
1455
1456module_platform_driver(snd_byt_rt5640_mc_driver);
1457
1458MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver");
1459MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
1460MODULE_LICENSE("GPL v2");
1461MODULE_ALIAS("platform:bytcr_rt5640");
1462