linux/sound/soc/qcom/sdm845.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/module.h>
   7#include <linux/platform_device.h>
   8#include <linux/of_device.h>
   9#include <sound/core.h>
  10#include <sound/pcm.h>
  11#include <sound/pcm_params.h>
  12#include <sound/jack.h>
  13#include <sound/soc.h>
  14#include <linux/soundwire/sdw.h>
  15#include <uapi/linux/input-event-codes.h>
  16#include "common.h"
  17#include "qdsp6/q6afe.h"
  18#include "../codecs/rt5663.h"
  19
  20#define DRIVER_NAME     "sdm845"
  21#define DEFAULT_SAMPLE_RATE_48K         48000
  22#define DEFAULT_MCLK_RATE               24576000
  23#define TDM_BCLK_RATE           6144000
  24#define MI2S_BCLK_RATE          1536000
  25#define LEFT_SPK_TDM_TX_MASK    0x30
  26#define RIGHT_SPK_TDM_TX_MASK   0xC0
  27#define SPK_TDM_RX_MASK         0x03
  28#define NUM_TDM_SLOTS           8
  29#define SLIM_MAX_TX_PORTS 16
  30#define SLIM_MAX_RX_PORTS 13
  31#define WCD934X_DEFAULT_MCLK_RATE       9600000
  32
  33struct sdm845_snd_data {
  34        struct snd_soc_jack jack;
  35        bool jack_setup;
  36        bool stream_prepared[AFE_PORT_MAX];
  37        struct snd_soc_card *card;
  38        uint32_t pri_mi2s_clk_count;
  39        uint32_t sec_mi2s_clk_count;
  40        uint32_t quat_tdm_clk_count;
  41        struct sdw_stream_runtime *sruntime[AFE_PORT_MAX];
  42};
  43
  44static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
  45
  46static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
  47                                     struct snd_pcm_hw_params *params)
  48{
  49        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  50        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  51        struct snd_soc_dai *codec_dai;
  52        struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
  53        u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
  54        struct sdw_stream_runtime *sruntime;
  55        u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
  56        int ret = 0, i;
  57
  58        for_each_rtd_codec_dais(rtd, i, codec_dai) {
  59                sruntime = snd_soc_dai_get_sdw_stream(codec_dai,
  60                                                      substream->stream);
  61                if (sruntime != ERR_PTR(-ENOTSUPP))
  62                        pdata->sruntime[cpu_dai->id] = sruntime;
  63
  64                ret = snd_soc_dai_get_channel_map(codec_dai,
  65                                &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
  66
  67                if (ret != 0 && ret != -ENOTSUPP) {
  68                        pr_err("failed to get codec chan map, err:%d\n", ret);
  69                        return ret;
  70                } else if (ret == -ENOTSUPP) {
  71                        /* Ignore unsupported */
  72                        continue;
  73                }
  74
  75                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  76                        ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
  77                                                          rx_ch_cnt, rx_ch);
  78                else
  79                        ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt,
  80                                                          tx_ch, 0, NULL);
  81        }
  82
  83        return 0;
  84}
  85
  86static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
  87                                        struct snd_pcm_hw_params *params)
  88{
  89        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
  90        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
  91        struct snd_soc_dai *codec_dai;
  92        int ret = 0, j;
  93        int channels, slot_width;
  94
  95        switch (params_format(params)) {
  96        case SNDRV_PCM_FORMAT_S16_LE:
  97                slot_width = 16;
  98                break;
  99        default:
 100                dev_err(rtd->dev, "%s: invalid param format 0x%x\n",
 101                                __func__, params_format(params));
 102                return -EINVAL;
 103        }
 104
 105        channels = params_channels(params);
 106        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 107                ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x3,
 108                                8, slot_width);
 109                if (ret < 0) {
 110                        dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
 111                                        __func__, ret);
 112                        goto end;
 113                }
 114
 115                ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
 116                                channels, tdm_slot_offset);
 117                if (ret < 0) {
 118                        dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
 119                                        __func__, ret);
 120                        goto end;
 121                }
 122        } else {
 123                ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
 124                                8, slot_width);
 125                if (ret < 0) {
 126                        dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
 127                                        __func__, ret);
 128                        goto end;
 129                }
 130
 131                ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
 132                                tdm_slot_offset, 0, NULL);
 133                if (ret < 0) {
 134                        dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
 135                                        __func__, ret);
 136                        goto end;
 137                }
 138        }
 139
 140        for_each_rtd_codec_dais(rtd, j, codec_dai) {
 141
 142                if (!strcmp(codec_dai->component->name_prefix, "Left")) {
 143                        ret = snd_soc_dai_set_tdm_slot(
 144                                        codec_dai, LEFT_SPK_TDM_TX_MASK,
 145                                        SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
 146                                        slot_width);
 147                        if (ret < 0) {
 148                                dev_err(rtd->dev,
 149                                        "DEV0 TDM slot err:%d\n", ret);
 150                                return ret;
 151                        }
 152                }
 153
 154                if (!strcmp(codec_dai->component->name_prefix, "Right")) {
 155                        ret = snd_soc_dai_set_tdm_slot(
 156                                        codec_dai, RIGHT_SPK_TDM_TX_MASK,
 157                                        SPK_TDM_RX_MASK, NUM_TDM_SLOTS,
 158                                        slot_width);
 159                        if (ret < 0) {
 160                                dev_err(rtd->dev,
 161                                        "DEV1 TDM slot err:%d\n", ret);
 162                                return ret;
 163                        }
 164                }
 165        }
 166
 167end:
 168        return ret;
 169}
 170
 171static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
 172                                        struct snd_pcm_hw_params *params)
 173{
 174        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 175        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 176        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 177        int ret = 0;
 178
 179        switch (cpu_dai->id) {
 180        case PRIMARY_MI2S_RX:
 181        case PRIMARY_MI2S_TX:
 182                /*
 183                 * Use ASRC for internal clocks, as PLL rate isn't multiple
 184                 * of BCLK.
 185                 */
 186                rt5663_sel_asrc_clk_src(
 187                        codec_dai->component,
 188                        RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER,
 189                        RT5663_CLK_SEL_I2S1_ASRC);
 190                ret = snd_soc_dai_set_sysclk(
 191                        codec_dai, RT5663_SCLK_S_MCLK, DEFAULT_MCLK_RATE,
 192                        SND_SOC_CLOCK_IN);
 193                if (ret < 0)
 194                        dev_err(rtd->dev,
 195                                "snd_soc_dai_set_sysclk err = %d\n", ret);
 196                break;
 197        case QUATERNARY_TDM_RX_0:
 198        case QUATERNARY_TDM_TX_0:
 199                ret = sdm845_tdm_snd_hw_params(substream, params);
 200                break;
 201        case SLIMBUS_0_RX...SLIMBUS_6_TX:
 202                ret = sdm845_slim_snd_hw_params(substream, params);
 203                break;
 204        case QUATERNARY_MI2S_RX:
 205                break;
 206        default:
 207                pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
 208                break;
 209        }
 210        return ret;
 211}
 212
 213static void sdm845_jack_free(struct snd_jack *jack)
 214{
 215        struct snd_soc_component *component = jack->private_data;
 216
 217        snd_soc_component_set_jack(component, NULL, NULL);
 218}
 219
 220static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
 221{
 222        struct snd_soc_component *component;
 223        struct snd_soc_card *card = rtd->card;
 224        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 225        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 226        struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
 227        struct snd_jack *jack;
 228        /*
 229         * Codec SLIMBUS configuration
 230         * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
 231         * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
 232         * TX14, TX15, TX16
 233         */
 234        unsigned int rx_ch[SLIM_MAX_RX_PORTS] = {144, 145, 146, 147, 148, 149,
 235                                        150, 151, 152, 153, 154, 155, 156};
 236        unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133,
 237                                            134, 135, 136, 137, 138, 139,
 238                                            140, 141, 142, 143};
 239        int rval, i;
 240
 241
 242        if (!pdata->jack_setup) {
 243                rval = snd_soc_card_jack_new(card, "Headset Jack",
 244                                SND_JACK_HEADSET |
 245                                SND_JACK_HEADPHONE |
 246                                SND_JACK_BTN_0 | SND_JACK_BTN_1 |
 247                                SND_JACK_BTN_2 | SND_JACK_BTN_3,
 248                                &pdata->jack, NULL, 0);
 249
 250                if (rval < 0) {
 251                        dev_err(card->dev, "Unable to add Headphone Jack\n");
 252                        return rval;
 253                }
 254
 255                jack = pdata->jack.jack;
 256
 257                snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
 258                snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
 259                snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
 260                snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
 261                pdata->jack_setup = true;
 262        }
 263
 264        switch (cpu_dai->id) {
 265        case PRIMARY_MI2S_RX:
 266                jack  = pdata->jack.jack;
 267                component = codec_dai->component;
 268
 269                jack->private_data = component;
 270                jack->private_free = sdm845_jack_free;
 271                rval = snd_soc_component_set_jack(component,
 272                                                  &pdata->jack, NULL);
 273                if (rval != 0 && rval != -ENOTSUPP) {
 274                        dev_warn(card->dev, "Failed to set jack: %d\n", rval);
 275                        return rval;
 276                }
 277                break;
 278        case SLIMBUS_0_RX...SLIMBUS_6_TX:
 279                for_each_rtd_codec_dais(rtd, i, codec_dai) {
 280                        rval = snd_soc_dai_set_channel_map(codec_dai,
 281                                                          ARRAY_SIZE(tx_ch),
 282                                                          tx_ch,
 283                                                          ARRAY_SIZE(rx_ch),
 284                                                          rx_ch);
 285                        if (rval != 0 && rval != -ENOTSUPP)
 286                                return rval;
 287
 288                        snd_soc_dai_set_sysclk(codec_dai, 0,
 289                                               WCD934X_DEFAULT_MCLK_RATE,
 290                                               SNDRV_PCM_STREAM_PLAYBACK);
 291
 292                        rval = snd_soc_component_set_jack(codec_dai->component,
 293                                                          &pdata->jack, NULL);
 294                        if (rval != 0 && rval != -ENOTSUPP) {
 295                                dev_warn(card->dev, "Failed to set jack: %d\n", rval);
 296                                return rval;
 297                        }
 298
 299                }
 300                break;
 301        default:
 302                break;
 303        }
 304
 305        return 0;
 306}
 307
 308
 309static int sdm845_snd_startup(struct snd_pcm_substream *substream)
 310{
 311        unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
 312        unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS;
 313        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 314        struct snd_soc_card *card = rtd->card;
 315        struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
 316        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 317        struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
 318        int j;
 319        int ret;
 320
 321        switch (cpu_dai->id) {
 322        case PRIMARY_MI2S_RX:
 323        case PRIMARY_MI2S_TX:
 324                codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF;
 325                if (++(data->pri_mi2s_clk_count) == 1) {
 326                        snd_soc_dai_set_sysclk(cpu_dai,
 327                                Q6AFE_LPASS_CLK_ID_MCLK_1,
 328                                DEFAULT_MCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
 329                        snd_soc_dai_set_sysclk(cpu_dai,
 330                                Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
 331                                MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
 332                }
 333                snd_soc_dai_set_fmt(cpu_dai, fmt);
 334                snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
 335                break;
 336
 337        case SECONDARY_MI2S_TX:
 338                codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
 339                if (++(data->sec_mi2s_clk_count) == 1) {
 340                        snd_soc_dai_set_sysclk(cpu_dai,
 341                                Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
 342                                MI2S_BCLK_RATE, SNDRV_PCM_STREAM_CAPTURE);
 343                }
 344                snd_soc_dai_set_fmt(cpu_dai, fmt);
 345                snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
 346                break;
 347        case QUATERNARY_MI2S_RX:
 348                snd_soc_dai_set_sysclk(cpu_dai,
 349                        Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
 350                        MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
 351                snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
 352
 353
 354                break;
 355
 356        case QUATERNARY_TDM_RX_0:
 357        case QUATERNARY_TDM_TX_0:
 358                if (++(data->quat_tdm_clk_count) == 1) {
 359                        snd_soc_dai_set_sysclk(cpu_dai,
 360                                Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
 361                                TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
 362                }
 363
 364                codec_dai_fmt |= SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_DSP_B;
 365
 366                for_each_rtd_codec_dais(rtd, j, codec_dai) {
 367
 368                        if (!strcmp(codec_dai->component->name_prefix,
 369                                    "Left")) {
 370                                ret = snd_soc_dai_set_fmt(
 371                                                codec_dai, codec_dai_fmt);
 372                                if (ret < 0) {
 373                                        dev_err(rtd->dev,
 374                                                "Left TDM fmt err:%d\n", ret);
 375                                        return ret;
 376                                }
 377                        }
 378
 379                        if (!strcmp(codec_dai->component->name_prefix,
 380                                    "Right")) {
 381                                ret = snd_soc_dai_set_fmt(
 382                                                codec_dai, codec_dai_fmt);
 383                                if (ret < 0) {
 384                                        dev_err(rtd->dev,
 385                                                "Right TDM slot err:%d\n", ret);
 386                                        return ret;
 387                                }
 388                        }
 389                }
 390                break;
 391        case SLIMBUS_0_RX...SLIMBUS_6_TX:
 392                break;
 393
 394        default:
 395                pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
 396                break;
 397        }
 398        return 0;
 399}
 400
 401static void  sdm845_snd_shutdown(struct snd_pcm_substream *substream)
 402{
 403        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 404        struct snd_soc_card *card = rtd->card;
 405        struct sdm845_snd_data *data = snd_soc_card_get_drvdata(card);
 406        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 407
 408        switch (cpu_dai->id) {
 409        case PRIMARY_MI2S_RX:
 410        case PRIMARY_MI2S_TX:
 411                if (--(data->pri_mi2s_clk_count) == 0) {
 412                        snd_soc_dai_set_sysclk(cpu_dai,
 413                                Q6AFE_LPASS_CLK_ID_MCLK_1,
 414                                0, SNDRV_PCM_STREAM_PLAYBACK);
 415                        snd_soc_dai_set_sysclk(cpu_dai,
 416                                Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
 417                                0, SNDRV_PCM_STREAM_PLAYBACK);
 418                }
 419                break;
 420
 421        case SECONDARY_MI2S_TX:
 422                if (--(data->sec_mi2s_clk_count) == 0) {
 423                        snd_soc_dai_set_sysclk(cpu_dai,
 424                                Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
 425                                0, SNDRV_PCM_STREAM_CAPTURE);
 426                }
 427                break;
 428
 429        case QUATERNARY_TDM_RX_0:
 430        case QUATERNARY_TDM_TX_0:
 431                if (--(data->quat_tdm_clk_count) == 0) {
 432                        snd_soc_dai_set_sysclk(cpu_dai,
 433                                Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
 434                                0, SNDRV_PCM_STREAM_PLAYBACK);
 435                }
 436                break;
 437        case SLIMBUS_0_RX...SLIMBUS_6_TX:
 438        case QUATERNARY_MI2S_RX:
 439                break;
 440
 441        default:
 442                pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
 443                break;
 444        }
 445}
 446
 447static int sdm845_snd_prepare(struct snd_pcm_substream *substream)
 448{
 449        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 450        struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
 451        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 452        struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
 453        int ret;
 454
 455        if (!sruntime)
 456                return 0;
 457
 458        if (data->stream_prepared[cpu_dai->id]) {
 459                sdw_disable_stream(sruntime);
 460                sdw_deprepare_stream(sruntime);
 461                data->stream_prepared[cpu_dai->id] = false;
 462        }
 463
 464        ret = sdw_prepare_stream(sruntime);
 465        if (ret)
 466                return ret;
 467
 468        /**
 469         * NOTE: there is a strict hw requirement about the ordering of port
 470         * enables and actual WSA881x PA enable. PA enable should only happen
 471         * after soundwire ports are enabled if not DC on the line is
 472         * accumulated resulting in Click/Pop Noise
 473         * PA enable/mute are handled as part of codec DAPM and digital mute.
 474         */
 475
 476        ret = sdw_enable_stream(sruntime);
 477        if (ret) {
 478                sdw_deprepare_stream(sruntime);
 479                return ret;
 480        }
 481        data->stream_prepared[cpu_dai->id] = true;
 482
 483        return ret;
 484}
 485
 486static int sdm845_snd_hw_free(struct snd_pcm_substream *substream)
 487{
 488        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
 489        struct sdm845_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
 490        struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
 491        struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
 492
 493        if (sruntime && data->stream_prepared[cpu_dai->id]) {
 494                sdw_disable_stream(sruntime);
 495                sdw_deprepare_stream(sruntime);
 496                data->stream_prepared[cpu_dai->id] = false;
 497        }
 498
 499        return 0;
 500}
 501
 502static const struct snd_soc_ops sdm845_be_ops = {
 503        .hw_params = sdm845_snd_hw_params,
 504        .hw_free = sdm845_snd_hw_free,
 505        .prepare = sdm845_snd_prepare,
 506        .startup = sdm845_snd_startup,
 507        .shutdown = sdm845_snd_shutdown,
 508};
 509
 510static int sdm845_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 511                                struct snd_pcm_hw_params *params)
 512{
 513        struct snd_interval *rate = hw_param_interval(params,
 514                                        SNDRV_PCM_HW_PARAM_RATE);
 515        struct snd_interval *channels = hw_param_interval(params,
 516                                        SNDRV_PCM_HW_PARAM_CHANNELS);
 517        struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 518
 519        rate->min = rate->max = DEFAULT_SAMPLE_RATE_48K;
 520        channels->min = channels->max = 2;
 521        snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
 522
 523        return 0;
 524}
 525
 526static const struct snd_soc_dapm_widget sdm845_snd_widgets[] = {
 527        SND_SOC_DAPM_HP("Headphone Jack", NULL),
 528        SND_SOC_DAPM_MIC("Headset Mic", NULL),
 529        SND_SOC_DAPM_SPK("Left Spk", NULL),
 530        SND_SOC_DAPM_SPK("Right Spk", NULL),
 531        SND_SOC_DAPM_MIC("Int Mic", NULL),
 532};
 533
 534static void sdm845_add_ops(struct snd_soc_card *card)
 535{
 536        struct snd_soc_dai_link *link;
 537        int i;
 538
 539        for_each_card_prelinks(card, i, link) {
 540                if (link->no_pcm == 1) {
 541                        link->ops = &sdm845_be_ops;
 542                        link->be_hw_params_fixup = sdm845_be_hw_params_fixup;
 543                }
 544                link->init = sdm845_dai_init;
 545        }
 546}
 547
 548static int sdm845_snd_platform_probe(struct platform_device *pdev)
 549{
 550        struct snd_soc_card *card;
 551        struct sdm845_snd_data *data;
 552        struct device *dev = &pdev->dev;
 553        int ret;
 554
 555        card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
 556        if (!card)
 557                return -ENOMEM;
 558
 559        /* Allocate the private data */
 560        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 561        if (!data)
 562                return -ENOMEM;
 563
 564        card->driver_name = DRIVER_NAME;
 565        card->dapm_widgets = sdm845_snd_widgets;
 566        card->num_dapm_widgets = ARRAY_SIZE(sdm845_snd_widgets);
 567        card->dev = dev;
 568        card->owner = THIS_MODULE;
 569        dev_set_drvdata(dev, card);
 570        ret = qcom_snd_parse_of(card);
 571        if (ret)
 572                return ret;
 573
 574        data->card = card;
 575        snd_soc_card_set_drvdata(card, data);
 576
 577        sdm845_add_ops(card);
 578        return devm_snd_soc_register_card(dev, card);
 579}
 580
 581static const struct of_device_id sdm845_snd_device_id[]  = {
 582        { .compatible = "qcom,sdm845-sndcard" },
 583        { .compatible = "qcom,db845c-sndcard" },
 584        { .compatible = "lenovo,yoga-c630-sndcard" },
 585        {},
 586};
 587MODULE_DEVICE_TABLE(of, sdm845_snd_device_id);
 588
 589static struct platform_driver sdm845_snd_driver = {
 590        .probe = sdm845_snd_platform_probe,
 591        .driver = {
 592                .name = "msm-snd-sdm845",
 593                .of_match_table = sdm845_snd_device_id,
 594        },
 595};
 596module_platform_driver(sdm845_snd_driver);
 597
 598MODULE_DESCRIPTION("sdm845 ASoC Machine Driver");
 599MODULE_LICENSE("GPL v2");
 600