linux/sound/soc/intel/boards/bytcr_rt5651.c
<<
>>
Prefs
   1/*
   2 *  bytcr_rt5651.c - ASoc Machine driver for Intel Byt CR platform
   3 *  (derived from bytcr_rt5640.c)
   4 *
   5 *  Copyright (C) 2015 Intel Corp
   6 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   7 *
   8 *  This program is free software; you can redistribute it and/or modify
   9 *  it under the terms of the GNU General Public License as published by
  10 *  the Free Software Foundation; version 2 of the License.
  11 *
  12 *  This program is distributed in the hope that it will be useful, but
  13 *  WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 *  General Public License for more details.
  16 *
  17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  18 */
  19
  20#include <linux/init.h>
  21#include <linux/module.h>
  22#include <linux/platform_device.h>
  23#include <linux/acpi.h>
  24#include <linux/clk.h>
  25#include <linux/device.h>
  26#include <linux/dmi.h>
  27#include <linux/slab.h>
  28#include <asm/platform_sst_audio.h>
  29#include <sound/pcm.h>
  30#include <sound/pcm_params.h>
  31#include <sound/soc.h>
  32#include <sound/jack.h>
  33#include <sound/soc-acpi.h>
  34#include "../../codecs/rt5651.h"
  35#include "../atom/sst-atom-controls.h"
  36
  37enum {
  38        BYT_RT5651_DMIC_MAP,
  39        BYT_RT5651_IN1_MAP,
  40        BYT_RT5651_IN2_MAP,
  41        BYT_RT5651_IN1_IN2_MAP,
  42        BYT_RT5651_IN3_MAP,
  43};
  44
  45#define BYT_RT5651_MAP(quirk)   ((quirk) & GENMASK(7, 0))
  46#define BYT_RT5651_DMIC_EN      BIT(16)
  47#define BYT_RT5651_MCLK_EN      BIT(17)
  48#define BYT_RT5651_MCLK_25MHZ   BIT(18)
  49
  50struct byt_rt5651_private {
  51        struct clk *mclk;
  52        struct snd_soc_jack jack;
  53};
  54
  55static unsigned long byt_rt5651_quirk = BYT_RT5651_DMIC_MAP |
  56                                        BYT_RT5651_DMIC_EN |
  57                                        BYT_RT5651_MCLK_EN;
  58
  59static void log_quirks(struct device *dev)
  60{
  61        if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_DMIC_MAP)
  62                dev_info(dev, "quirk DMIC_MAP enabled");
  63        if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN1_MAP)
  64                dev_info(dev, "quirk IN1_MAP enabled");
  65        if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN2_MAP)
  66                dev_info(dev, "quirk IN2_MAP enabled");
  67        if (BYT_RT5651_MAP(byt_rt5651_quirk) == BYT_RT5651_IN3_MAP)
  68                dev_info(dev, "quirk IN3_MAP enabled");
  69        if (byt_rt5651_quirk & BYT_RT5651_DMIC_EN)
  70                dev_info(dev, "quirk DMIC enabled");
  71        if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
  72                dev_info(dev, "quirk MCLK_EN enabled");
  73        if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
  74                dev_info(dev, "quirk MCLK_25MHZ enabled");
  75}
  76
  77#define BYT_CODEC_DAI1  "rt5651-aif1"
  78
  79static int platform_clock_control(struct snd_soc_dapm_widget *w,
  80                                  struct snd_kcontrol *k, int  event)
  81{
  82        struct snd_soc_dapm_context *dapm = w->dapm;
  83        struct snd_soc_card *card = dapm->card;
  84        struct snd_soc_dai *codec_dai;
  85        struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
  86        int ret;
  87
  88        codec_dai = snd_soc_card_get_codec_dai(card, BYT_CODEC_DAI1);
  89        if (!codec_dai) {
  90                dev_err(card->dev,
  91                        "Codec dai not found; Unable to set platform clock\n");
  92                return -EIO;
  93        }
  94
  95        if (SND_SOC_DAPM_EVENT_ON(event)) {
  96                if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
  97                        ret = clk_prepare_enable(priv->mclk);
  98                        if (ret < 0) {
  99                                dev_err(card->dev,
 100                                        "could not configure MCLK state");
 101                                return ret;
 102                        }
 103                }
 104                ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
 105                                             48000 * 512,
 106                                             SND_SOC_CLOCK_IN);
 107        } else {
 108                /*
 109                 * Set codec clock source to internal clock before
 110                 * turning off the platform clock. Codec needs clock
 111                 * for Jack detection and button press
 112                 */
 113                ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_RCCLK,
 114                                             48000 * 512,
 115                                             SND_SOC_CLOCK_IN);
 116                if (!ret)
 117                        if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN)
 118                                clk_disable_unprepare(priv->mclk);
 119        }
 120
 121        if (ret < 0) {
 122                dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
 123                return ret;
 124        }
 125
 126        return 0;
 127}
 128
 129static const struct snd_soc_dapm_widget byt_rt5651_widgets[] = {
 130        SND_SOC_DAPM_HP("Headphone", NULL),
 131        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 132        SND_SOC_DAPM_MIC("Internal Mic", NULL),
 133        SND_SOC_DAPM_SPK("Speaker", NULL),
 134        SND_SOC_DAPM_LINE("Line In", NULL),
 135        SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
 136                            platform_clock_control, SND_SOC_DAPM_PRE_PMU |
 137                            SND_SOC_DAPM_POST_PMD),
 138
 139};
 140
 141static const struct snd_soc_dapm_route byt_rt5651_audio_map[] = {
 142        {"Headphone", NULL, "Platform Clock"},
 143        {"Headset Mic", NULL, "Platform Clock"},
 144        {"Internal Mic", NULL, "Platform Clock"},
 145        {"Speaker", NULL, "Platform Clock"},
 146        {"Line In", NULL, "Platform Clock"},
 147
 148        {"AIF1 Playback", NULL, "ssp2 Tx"},
 149        {"ssp2 Tx", NULL, "codec_out0"},
 150        {"ssp2 Tx", NULL, "codec_out1"},
 151        {"codec_in0", NULL, "ssp2 Rx"},
 152        {"codec_in1", NULL, "ssp2 Rx"},
 153        {"ssp2 Rx", NULL, "AIF1 Capture"},
 154
 155        {"Headset Mic", NULL, "micbias1"}, /* lowercase for rt5651 */
 156        {"Headphone", NULL, "HPOL"},
 157        {"Headphone", NULL, "HPOR"},
 158        {"Speaker", NULL, "LOUTL"},
 159        {"Speaker", NULL, "LOUTR"},
 160        {"IN2P", NULL, "Line In"},
 161        {"IN2N", NULL, "Line In"},
 162
 163};
 164
 165static const struct snd_soc_dapm_route byt_rt5651_intmic_dmic_map[] = {
 166        {"IN2P", NULL, "Headset Mic"},
 167        {"DMIC L1", NULL, "Internal Mic"},
 168        {"DMIC R1", NULL, "Internal Mic"},
 169};
 170
 171static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_map[] = {
 172        {"Internal Mic", NULL, "micbias1"},
 173        {"IN2P", NULL, "Headset Mic"},
 174        {"IN1P", NULL, "Internal Mic"},
 175};
 176
 177static const struct snd_soc_dapm_route byt_rt5651_intmic_in2_map[] = {
 178        {"Internal Mic", NULL, "micbias1"},
 179        {"IN1P", NULL, "Headset Mic"},
 180        {"IN2P", NULL, "Internal Mic"},
 181};
 182
 183static const struct snd_soc_dapm_route byt_rt5651_intmic_in1_in2_map[] = {
 184        {"Internal Mic", NULL, "micbias1"},
 185        {"IN1P", NULL, "Internal Mic"},
 186        {"IN2P", NULL, "Internal Mic"},
 187        {"IN3P", NULL, "Headset Mic"},
 188};
 189
 190static const struct snd_soc_dapm_route byt_rt5651_intmic_in3_map[] = {
 191        {"Internal Mic", NULL, "micbias1"},
 192        {"IN3P", NULL, "Headset Mic"},
 193        {"IN1P", NULL, "Internal Mic"},
 194};
 195
 196static const struct snd_kcontrol_new byt_rt5651_controls[] = {
 197        SOC_DAPM_PIN_SWITCH("Headphone"),
 198        SOC_DAPM_PIN_SWITCH("Headset Mic"),
 199        SOC_DAPM_PIN_SWITCH("Internal Mic"),
 200        SOC_DAPM_PIN_SWITCH("Speaker"),
 201        SOC_DAPM_PIN_SWITCH("Line In"),
 202};
 203
 204static struct snd_soc_jack_pin bytcr_jack_pins[] = {
 205        {
 206                .pin    = "Headphone",
 207                .mask   = SND_JACK_HEADPHONE,
 208        },
 209        {
 210                .pin    = "Headset Mic",
 211                .mask   = SND_JACK_MICROPHONE,
 212        },
 213};
 214
 215static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream,
 216                                        struct snd_pcm_hw_params *params)
 217{
 218        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 219        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 220        int ret;
 221
 222        snd_soc_dai_set_bclk_ratio(codec_dai, 50);
 223
 224        ret = snd_soc_dai_set_sysclk(codec_dai, RT5651_SCLK_S_PLL1,
 225                                     params_rate(params) * 512,
 226                                     SND_SOC_CLOCK_IN);
 227        if (ret < 0) {
 228                dev_err(rtd->dev, "can't set codec clock %d\n", ret);
 229                return ret;
 230        }
 231
 232        if (!(byt_rt5651_quirk & BYT_RT5651_MCLK_EN)) {
 233                /* 2x25 bit slots on SSP2 */
 234                ret = snd_soc_dai_set_pll(codec_dai, 0,
 235                                        RT5651_PLL1_S_BCLK1,
 236                                        params_rate(params) * 50,
 237                                        params_rate(params) * 512);
 238        } else {
 239                if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ) {
 240                        ret = snd_soc_dai_set_pll(codec_dai, 0,
 241                                                RT5651_PLL1_S_MCLK,
 242                                                25000000,
 243                                                params_rate(params) * 512);
 244                } else {
 245                        ret = snd_soc_dai_set_pll(codec_dai, 0,
 246                                                RT5651_PLL1_S_MCLK,
 247                                                19200000,
 248                                                params_rate(params) * 512);
 249                }
 250        }
 251
 252        if (ret < 0) {
 253                dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
 254                return ret;
 255        }
 256
 257        return 0;
 258}
 259
 260static int byt_rt5651_quirk_cb(const struct dmi_system_id *id)
 261{
 262        byt_rt5651_quirk = (unsigned long)id->driver_data;
 263        return 1;
 264}
 265
 266static const struct dmi_system_id byt_rt5651_quirk_table[] = {
 267        {
 268                .callback = byt_rt5651_quirk_cb,
 269                .matches = {
 270                        DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
 271                        DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max B3 PLATFORM"),
 272                },
 273                .driver_data = (void *)(BYT_RT5651_IN3_MAP),
 274        },
 275        {
 276                .callback = byt_rt5651_quirk_cb,
 277                .matches = {
 278                        DMI_MATCH(DMI_SYS_VENDOR, "ADI"),
 279                        DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Turbot"),
 280                },
 281                .driver_data = (void *)(BYT_RT5651_MCLK_EN |
 282                                        BYT_RT5651_IN3_MAP),
 283        },
 284        {
 285                .callback = byt_rt5651_quirk_cb,
 286                .matches = {
 287                        DMI_MATCH(DMI_SYS_VENDOR, "KIANO"),
 288                        DMI_MATCH(DMI_PRODUCT_NAME, "KIANO SlimNote 14.2"),
 289                },
 290                .driver_data = (void *)(BYT_RT5651_MCLK_EN |
 291                                        BYT_RT5651_IN1_IN2_MAP),
 292        },
 293        {}
 294};
 295
 296static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime)
 297{
 298        struct snd_soc_card *card = runtime->card;
 299        struct snd_soc_codec *codec = runtime->codec;
 300        struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card);
 301        const struct snd_soc_dapm_route *custom_map;
 302        int num_routes;
 303        int ret;
 304
 305        card->dapm.idle_bias_off = true;
 306
 307        switch (BYT_RT5651_MAP(byt_rt5651_quirk)) {
 308        case BYT_RT5651_IN1_MAP:
 309                custom_map = byt_rt5651_intmic_in1_map;
 310                num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_map);
 311                break;
 312        case BYT_RT5651_IN2_MAP:
 313                custom_map = byt_rt5651_intmic_in2_map;
 314                num_routes = ARRAY_SIZE(byt_rt5651_intmic_in2_map);
 315                break;
 316        case BYT_RT5651_IN1_IN2_MAP:
 317                custom_map = byt_rt5651_intmic_in1_in2_map;
 318                num_routes = ARRAY_SIZE(byt_rt5651_intmic_in1_in2_map);
 319                break;
 320        case BYT_RT5651_IN3_MAP:
 321                custom_map = byt_rt5651_intmic_in3_map;
 322                num_routes = ARRAY_SIZE(byt_rt5651_intmic_in3_map);
 323                break;
 324        default:
 325                custom_map = byt_rt5651_intmic_dmic_map;
 326                num_routes = ARRAY_SIZE(byt_rt5651_intmic_dmic_map);
 327        }
 328        ret = snd_soc_dapm_add_routes(&card->dapm, custom_map, num_routes);
 329        if (ret)
 330                return ret;
 331
 332        ret = snd_soc_add_card_controls(card, byt_rt5651_controls,
 333                                        ARRAY_SIZE(byt_rt5651_controls));
 334        if (ret) {
 335                dev_err(card->dev, "unable to add card controls\n");
 336                return ret;
 337        }
 338        snd_soc_dapm_ignore_suspend(&card->dapm, "Headphone");
 339        snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
 340
 341        if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
 342                /*
 343                 * The firmware might enable the clock at
 344                 * boot (this information may or may not
 345                 * be reflected in the enable clock register).
 346                 * To change the rate we must disable the clock
 347                 * first to cover these cases. Due to common
 348                 * clock framework restrictions that do not allow
 349                 * to disable a clock that has not been enabled,
 350                 * we need to enable the clock first.
 351                 */
 352                ret = clk_prepare_enable(priv->mclk);
 353                if (!ret)
 354                        clk_disable_unprepare(priv->mclk);
 355
 356                if (byt_rt5651_quirk & BYT_RT5651_MCLK_25MHZ)
 357                        ret = clk_set_rate(priv->mclk, 25000000);
 358                else
 359                        ret = clk_set_rate(priv->mclk, 19200000);
 360
 361                if (ret)
 362                        dev_err(card->dev, "unable to set MCLK rate\n");
 363        }
 364
 365        ret = snd_soc_card_jack_new(runtime->card, "Headset",
 366                                    SND_JACK_HEADSET, &priv->jack,
 367                                    bytcr_jack_pins, ARRAY_SIZE(bytcr_jack_pins));
 368        if (ret) {
 369                dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
 370                return ret;
 371        }
 372
 373        rt5651_set_jack_detect(codec, &priv->jack);
 374
 375        return ret;
 376}
 377
 378static const struct snd_soc_pcm_stream byt_rt5651_dai_params = {
 379        .formats = SNDRV_PCM_FMTBIT_S24_LE,
 380        .rate_min = 48000,
 381        .rate_max = 48000,
 382        .channels_min = 2,
 383        .channels_max = 2,
 384};
 385
 386static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
 387                            struct snd_pcm_hw_params *params)
 388{
 389        struct snd_interval *rate = hw_param_interval(params,
 390                        SNDRV_PCM_HW_PARAM_RATE);
 391        struct snd_interval *channels = hw_param_interval(params,
 392                                                SNDRV_PCM_HW_PARAM_CHANNELS);
 393        int ret;
 394
 395        /* The DSP will covert the FE rate to 48k, stereo, 24bits */
 396        rate->min = rate->max = 48000;
 397        channels->min = channels->max = 2;
 398
 399        /* set SSP2 to 24-bit */
 400        params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
 401
 402        /*
 403         * Default mode for SSP configuration is TDM 4 slot, override config
 404         * with explicit setting to I2S 2ch 24-bit. The word length is set with
 405         * dai_set_tdm_slot() since there is no other API exposed
 406         */
 407        ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
 408                                  SND_SOC_DAIFMT_I2S     |
 409                                  SND_SOC_DAIFMT_NB_NF   |
 410                                  SND_SOC_DAIFMT_CBS_CFS
 411                                  );
 412
 413        if (ret < 0) {
 414                dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
 415                return ret;
 416        }
 417
 418        ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
 419        if (ret < 0) {
 420                dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
 421                return ret;
 422        }
 423
 424        return 0;
 425}
 426
 427static const unsigned int rates_48000[] = {
 428        48000,
 429};
 430
 431static const struct snd_pcm_hw_constraint_list constraints_48000 = {
 432        .count = ARRAY_SIZE(rates_48000),
 433        .list  = rates_48000,
 434};
 435
 436static int byt_rt5651_aif1_startup(struct snd_pcm_substream *substream)
 437{
 438        return snd_pcm_hw_constraint_list(substream->runtime, 0,
 439                        SNDRV_PCM_HW_PARAM_RATE,
 440                        &constraints_48000);
 441}
 442
 443static const struct snd_soc_ops byt_rt5651_aif1_ops = {
 444        .startup = byt_rt5651_aif1_startup,
 445};
 446
 447static const struct snd_soc_ops byt_rt5651_be_ssp2_ops = {
 448        .hw_params = byt_rt5651_aif1_hw_params,
 449};
 450
 451static struct snd_soc_dai_link byt_rt5651_dais[] = {
 452        [MERR_DPCM_AUDIO] = {
 453                .name = "Audio Port",
 454                .stream_name = "Audio",
 455                .cpu_dai_name = "media-cpu-dai",
 456                .codec_dai_name = "snd-soc-dummy-dai",
 457                .codec_name = "snd-soc-dummy",
 458                .platform_name = "sst-mfld-platform",
 459                .nonatomic = true,
 460                .dynamic = 1,
 461                .dpcm_playback = 1,
 462                .dpcm_capture = 1,
 463                .ops = &byt_rt5651_aif1_ops,
 464        },
 465        [MERR_DPCM_DEEP_BUFFER] = {
 466                .name = "Deep-Buffer Audio Port",
 467                .stream_name = "Deep-Buffer Audio",
 468                .cpu_dai_name = "deepbuffer-cpu-dai",
 469                .codec_dai_name = "snd-soc-dummy-dai",
 470                .codec_name = "snd-soc-dummy",
 471                .platform_name = "sst-mfld-platform",
 472                .nonatomic = true,
 473                .dynamic = 1,
 474                .dpcm_playback = 1,
 475                .ops = &byt_rt5651_aif1_ops,
 476        },
 477        /* CODEC<->CODEC link */
 478        /* back ends */
 479        {
 480                .name = "SSP2-Codec",
 481                .id = 0,
 482                .cpu_dai_name = "ssp2-port",
 483                .platform_name = "sst-mfld-platform",
 484                .no_pcm = 1,
 485                .codec_dai_name = "rt5651-aif1",
 486                .codec_name = "i2c-10EC5651:00",
 487                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
 488                                                | SND_SOC_DAIFMT_CBS_CFS,
 489                .be_hw_params_fixup = byt_rt5651_codec_fixup,
 490                .ignore_suspend = 1,
 491                .nonatomic = true,
 492                .dpcm_playback = 1,
 493                .dpcm_capture = 1,
 494                .init = byt_rt5651_init,
 495                .ops = &byt_rt5651_be_ssp2_ops,
 496        },
 497};
 498
 499/* SoC card */
 500static struct snd_soc_card byt_rt5651_card = {
 501        .name = "bytcr-rt5651",
 502        .owner = THIS_MODULE,
 503        .dai_link = byt_rt5651_dais,
 504        .num_links = ARRAY_SIZE(byt_rt5651_dais),
 505        .dapm_widgets = byt_rt5651_widgets,
 506        .num_dapm_widgets = ARRAY_SIZE(byt_rt5651_widgets),
 507        .dapm_routes = byt_rt5651_audio_map,
 508        .num_dapm_routes = ARRAY_SIZE(byt_rt5651_audio_map),
 509        .fully_routed = true,
 510};
 511
 512static char byt_rt5651_codec_name[SND_ACPI_I2C_ID_LEN];
 513
 514static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
 515{
 516        struct byt_rt5651_private *priv;
 517        struct snd_soc_acpi_mach *mach;
 518        const char *i2c_name = NULL;
 519        int ret_val = 0;
 520        int dai_index = 0;
 521        int i;
 522
 523        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
 524        if (!priv)
 525                return -ENOMEM;
 526
 527        /* register the soc card */
 528        byt_rt5651_card.dev = &pdev->dev;
 529
 530        mach = byt_rt5651_card.dev->platform_data;
 531        snd_soc_card_set_drvdata(&byt_rt5651_card, priv);
 532
 533        /* fix index of codec dai */
 534        for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
 535                if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) {
 536                        dai_index = i;
 537                        break;
 538                }
 539        }
 540
 541        /* fixup codec name based on HID */
 542        i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
 543        if (i2c_name) {
 544                snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
 545                        "%s%s", "i2c-", i2c_name);
 546
 547                byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;
 548        }
 549
 550        /* check quirks before creating card */
 551        dmi_check_system(byt_rt5651_quirk_table);
 552        log_quirks(&pdev->dev);
 553
 554        if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
 555                priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
 556                if (IS_ERR(priv->mclk)) {
 557                        dev_err(&pdev->dev,
 558                                "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
 559                                PTR_ERR(priv->mclk));
 560                        /*
 561                         * Fall back to bit clock usage for -ENOENT (clock not
 562                         * available likely due to missing dependencies), bail
 563                         * for all other errors, including -EPROBE_DEFER
 564                         */
 565                        if (ret_val != -ENOENT)
 566                                return ret_val;
 567                        byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
 568                }
 569        }
 570
 571        ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);
 572
 573        if (ret_val) {
 574                dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
 575                        ret_val);
 576                return ret_val;
 577        }
 578        platform_set_drvdata(pdev, &byt_rt5651_card);
 579        return ret_val;
 580}
 581
 582static struct platform_driver snd_byt_rt5651_mc_driver = {
 583        .driver = {
 584                .name = "bytcr_rt5651",
 585        },
 586        .probe = snd_byt_rt5651_mc_probe,
 587};
 588
 589module_platform_driver(snd_byt_rt5651_mc_driver);
 590
 591MODULE_DESCRIPTION("ASoC Intel(R) Baytrail CR Machine driver for RT5651");
 592MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
 593MODULE_LICENSE("GPL v2");
 594MODULE_ALIAS("platform:bytcr_rt5651");
 595