linux/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// mt8183-da7219-max98357.c
   4//      --  MT8183-DA7219-MAX98357 ALSA SoC machine driver
   5//
   6// Copyright (c) 2018 MediaTek Inc.
   7// Author: Shunli Wang <shunli.wang@mediatek.com>
   8
   9#include <linux/module.h>
  10#include <sound/pcm_params.h>
  11#include <sound/soc.h>
  12#include <sound/jack.h>
  13#include <linux/pinctrl/consumer.h>
  14
  15#include "mt8183-afe-common.h"
  16#include "../../codecs/da7219-aad.h"
  17#include "../../codecs/da7219.h"
  18
  19static struct snd_soc_jack headset_jack;
  20
  21static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream,
  22                                       struct snd_pcm_hw_params *params)
  23{
  24        struct snd_soc_pcm_runtime *rtd = substream->private_data;
  25        unsigned int rate = params_rate(params);
  26        unsigned int mclk_fs_ratio = 128;
  27        unsigned int mclk_fs = rate * mclk_fs_ratio;
  28
  29        return snd_soc_dai_set_sysclk(rtd->cpu_dai,
  30                                      0, mclk_fs, SND_SOC_CLOCK_OUT);
  31}
  32
  33static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {
  34        .hw_params = mt8183_mt6358_i2s_hw_params,
  35};
  36
  37static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
  38                                       struct snd_pcm_hw_params *params)
  39{
  40        struct snd_soc_pcm_runtime *rtd = substream->private_data;
  41        unsigned int rate = params_rate(params);
  42        unsigned int mclk_fs_ratio = 256;
  43        unsigned int mclk_fs = rate * mclk_fs_ratio;
  44        unsigned int freq;
  45        int ret = 0, j;
  46
  47        ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, 0,
  48                                     mclk_fs, SND_SOC_CLOCK_OUT);
  49        if (ret < 0)
  50                dev_err(rtd->dev, "failed to set cpu dai sysclk\n");
  51
  52        for (j = 0; j < rtd->num_codecs; j++) {
  53                struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
  54
  55                if (!strcmp(codec_dai->component->name, "da7219.5-001a")) {
  56                        ret = snd_soc_dai_set_sysclk(codec_dai,
  57                                                     DA7219_CLKSRC_MCLK,
  58                                                     mclk_fs,
  59                                                     SND_SOC_CLOCK_IN);
  60                        if (ret < 0)
  61                                dev_err(rtd->dev, "failed to set sysclk\n");
  62
  63                        if ((rate % 8000) == 0)
  64                                freq = DA7219_PLL_FREQ_OUT_98304;
  65                        else
  66                                freq = DA7219_PLL_FREQ_OUT_90316;
  67
  68                        ret = snd_soc_dai_set_pll(codec_dai, 0,
  69                                                  DA7219_SYSCLK_PLL_SRM,
  70                                                  0, freq);
  71                        if (ret)
  72                                dev_err(rtd->dev, "failed to start PLL: %d\n",
  73                                        ret);
  74                }
  75        }
  76
  77        return ret;
  78}
  79
  80static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream)
  81{
  82        struct snd_soc_pcm_runtime *rtd = substream->private_data;
  83        int ret = 0, j;
  84
  85        for (j = 0; j < rtd->num_codecs; j++) {
  86                struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
  87
  88                if (!strcmp(codec_dai->component->name, "da7219.5-001a")) {
  89                        ret = snd_soc_dai_set_pll(codec_dai,
  90                                                  0, DA7219_SYSCLK_MCLK, 0, 0);
  91                        if (ret < 0) {
  92                                dev_err(rtd->dev, "failed to stop PLL: %d\n",
  93                                        ret);
  94                                break;
  95                        }
  96                }
  97        }
  98
  99        return ret;
 100}
 101
 102static const struct snd_soc_ops mt8183_da7219_i2s_ops = {
 103        .hw_params = mt8183_da7219_i2s_hw_params,
 104        .hw_free = mt8183_da7219_hw_free,
 105};
 106
 107static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 108                                      struct snd_pcm_hw_params *params)
 109{
 110        /* fix BE i2s format to 32bit, clean param mask first */
 111        snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
 112                             0, SNDRV_PCM_FORMAT_LAST);
 113
 114        params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
 115
 116        return 0;
 117}
 118
 119static const struct snd_soc_dapm_widget
 120mt8183_da7219_max98357_dapm_widgets[] = {
 121        SND_SOC_DAPM_OUTPUT("IT6505_8CH"),
 122};
 123
 124static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = {
 125        {"IT6505_8CH", NULL, "TDM"},
 126};
 127
 128/* FE */
 129SND_SOC_DAILINK_DEFS(playback1,
 130        DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
 131        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 132        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 133
 134SND_SOC_DAILINK_DEFS(playback2,
 135        DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
 136        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 137        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 138
 139SND_SOC_DAILINK_DEFS(playback3,
 140        DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
 141        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 142        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 143
 144SND_SOC_DAILINK_DEFS(capture1,
 145        DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
 146        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 147        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 148
 149SND_SOC_DAILINK_DEFS(capture2,
 150        DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
 151        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 152        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 153
 154SND_SOC_DAILINK_DEFS(capture3,
 155        DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
 156        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 157        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 158
 159SND_SOC_DAILINK_DEFS(capture_mono,
 160        DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),
 161        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 162        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 163
 164SND_SOC_DAILINK_DEFS(playback_hdmi,
 165        DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
 166        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 167        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 168
 169/* BE */
 170SND_SOC_DAILINK_DEFS(primary_codec,
 171        DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
 172        DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")),
 173        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 174
 175SND_SOC_DAILINK_DEFS(pcm1,
 176        DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
 177        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 178        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 179
 180SND_SOC_DAILINK_DEFS(pcm2,
 181        DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),
 182        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 183        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 184
 185SND_SOC_DAILINK_DEFS(i2s0,
 186        DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
 187        DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
 188        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 189
 190SND_SOC_DAILINK_DEFS(i2s1,
 191        DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
 192        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 193        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 194
 195SND_SOC_DAILINK_DEFS(i2s2,
 196        DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
 197        DAILINK_COMP_ARRAY(COMP_CODEC("da7219.5-001a", "da7219-hifi")),
 198        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 199
 200SND_SOC_DAILINK_DEFS(i2s3,
 201        DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
 202        DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"),
 203                         COMP_CODEC("da7219.5-001a", "da7219-hifi")),
 204        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 205
 206SND_SOC_DAILINK_DEFS(i2s5,
 207        DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),
 208        DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
 209        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 210
 211SND_SOC_DAILINK_DEFS(tdm,
 212        DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
 213        DAILINK_COMP_ARRAY(COMP_DUMMY()),
 214        DAILINK_COMP_ARRAY(COMP_EMPTY()));
 215
 216static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = {
 217        /* FE */
 218        {
 219                .name = "Playback_1",
 220                .stream_name = "Playback_1",
 221                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 222                            SND_SOC_DPCM_TRIGGER_PRE},
 223                .dynamic = 1,
 224                .dpcm_playback = 1,
 225                SND_SOC_DAILINK_REG(playback1),
 226        },
 227        {
 228                .name = "Playback_2",
 229                .stream_name = "Playback_2",
 230                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 231                            SND_SOC_DPCM_TRIGGER_PRE},
 232                .dynamic = 1,
 233                .dpcm_playback = 1,
 234                SND_SOC_DAILINK_REG(playback2),
 235        },
 236        {
 237                .name = "Playback_3",
 238                .stream_name = "Playback_3",
 239                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 240                            SND_SOC_DPCM_TRIGGER_PRE},
 241                .dynamic = 1,
 242                .dpcm_playback = 1,
 243                SND_SOC_DAILINK_REG(playback3),
 244        },
 245        {
 246                .name = "Capture_1",
 247                .stream_name = "Capture_1",
 248                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 249                            SND_SOC_DPCM_TRIGGER_PRE},
 250                .dynamic = 1,
 251                .dpcm_capture = 1,
 252                SND_SOC_DAILINK_REG(capture1),
 253        },
 254        {
 255                .name = "Capture_2",
 256                .stream_name = "Capture_2",
 257                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 258                            SND_SOC_DPCM_TRIGGER_PRE},
 259                .dynamic = 1,
 260                .dpcm_capture = 1,
 261                SND_SOC_DAILINK_REG(capture2),
 262        },
 263        {
 264                .name = "Capture_3",
 265                .stream_name = "Capture_3",
 266                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 267                            SND_SOC_DPCM_TRIGGER_PRE},
 268                .dynamic = 1,
 269                .dpcm_capture = 1,
 270                SND_SOC_DAILINK_REG(capture3),
 271        },
 272        {
 273                .name = "Capture_Mono_1",
 274                .stream_name = "Capture_Mono_1",
 275                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 276                            SND_SOC_DPCM_TRIGGER_PRE},
 277                .dynamic = 1,
 278                .dpcm_capture = 1,
 279                SND_SOC_DAILINK_REG(capture_mono),
 280        },
 281        {
 282                .name = "Playback_HDMI",
 283                .stream_name = "Playback_HDMI",
 284                .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 285                            SND_SOC_DPCM_TRIGGER_PRE},
 286                .dynamic = 1,
 287                .dpcm_playback = 1,
 288                SND_SOC_DAILINK_REG(playback_hdmi),
 289        },
 290        /* BE */
 291        {
 292                .name = "Primary Codec",
 293                .no_pcm = 1,
 294                .dpcm_playback = 1,
 295                .dpcm_capture = 1,
 296                .ignore_suspend = 1,
 297                SND_SOC_DAILINK_REG(primary_codec),
 298        },
 299        {
 300                .name = "PCM 1",
 301                .no_pcm = 1,
 302                .dpcm_playback = 1,
 303                .dpcm_capture = 1,
 304                .ignore_suspend = 1,
 305                SND_SOC_DAILINK_REG(pcm1),
 306        },
 307        {
 308                .name = "PCM 2",
 309                .no_pcm = 1,
 310                .dpcm_playback = 1,
 311                .dpcm_capture = 1,
 312                .ignore_suspend = 1,
 313                SND_SOC_DAILINK_REG(pcm2),
 314        },
 315        {
 316                .name = "I2S0",
 317                .no_pcm = 1,
 318                .dpcm_capture = 1,
 319                .ignore_suspend = 1,
 320                .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
 321                .ops = &mt8183_mt6358_i2s_ops,
 322                SND_SOC_DAILINK_REG(i2s0),
 323        },
 324        {
 325                .name = "I2S1",
 326                .no_pcm = 1,
 327                .dpcm_playback = 1,
 328                .ignore_suspend = 1,
 329                .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
 330                .ops = &mt8183_mt6358_i2s_ops,
 331                SND_SOC_DAILINK_REG(i2s1),
 332        },
 333        {
 334                .name = "I2S2",
 335                .no_pcm = 1,
 336                .dpcm_capture = 1,
 337                .ignore_suspend = 1,
 338                .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
 339                .ops = &mt8183_da7219_i2s_ops,
 340                SND_SOC_DAILINK_REG(i2s2),
 341        },
 342        {
 343                .name = "I2S3",
 344                .no_pcm = 1,
 345                .dpcm_playback = 1,
 346                .ignore_suspend = 1,
 347                .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
 348                .ops = &mt8183_da7219_i2s_ops,
 349                SND_SOC_DAILINK_REG(i2s3),
 350        },
 351        {
 352                .name = "I2S5",
 353                .no_pcm = 1,
 354                .dpcm_playback = 1,
 355                .ignore_suspend = 1,
 356                .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
 357                .ops = &mt8183_mt6358_i2s_ops,
 358                SND_SOC_DAILINK_REG(i2s5),
 359        },
 360        {
 361                .name = "TDM",
 362                .no_pcm = 1,
 363                .dpcm_playback = 1,
 364                .ignore_suspend = 1,
 365                SND_SOC_DAILINK_REG(tdm),
 366        },
 367};
 368
 369static int
 370mt8183_da7219_max98357_headset_init(struct snd_soc_component *component);
 371
 372static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = {
 373        .name = "Headset Chip",
 374        .init = mt8183_da7219_max98357_headset_init,
 375};
 376
 377static struct snd_soc_codec_conf mt6358_codec_conf[] = {
 378        {
 379                .dev_name = "mt6358-sound",
 380                .name_prefix = "Mt6358",
 381        },
 382};
 383
 384static struct snd_soc_card mt8183_da7219_max98357_card = {
 385        .name = "mt8183_da7219_max98357",
 386        .owner = THIS_MODULE,
 387        .dai_link = mt8183_da7219_max98357_dai_links,
 388        .num_links = ARRAY_SIZE(mt8183_da7219_max98357_dai_links),
 389        .aux_dev = &mt8183_da7219_max98357_headset_dev,
 390        .num_aux_devs = 1,
 391        .codec_conf = mt6358_codec_conf,
 392        .num_configs = ARRAY_SIZE(mt6358_codec_conf),
 393};
 394
 395static int
 396mt8183_da7219_max98357_headset_init(struct snd_soc_component *component)
 397{
 398        int ret;
 399
 400        /* Enable Headset and 4 Buttons Jack detection */
 401        ret = snd_soc_card_jack_new(&mt8183_da7219_max98357_card,
 402                                    "Headset Jack",
 403                                    SND_JACK_HEADSET |
 404                                    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
 405                                    SND_JACK_BTN_2 | SND_JACK_BTN_3,
 406                                    &headset_jack,
 407                                    NULL, 0);
 408        if (ret)
 409                return ret;
 410
 411        da7219_aad_jack_det(component, &headset_jack);
 412
 413        return ret;
 414}
 415
 416static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
 417{
 418        struct snd_soc_card *card = &mt8183_da7219_max98357_card;
 419        struct device_node *platform_node;
 420        struct snd_soc_dai_link *dai_link;
 421        struct pinctrl *default_pins;
 422        int ret, i;
 423
 424        card->dev = &pdev->dev;
 425
 426        platform_node = of_parse_phandle(pdev->dev.of_node,
 427                                         "mediatek,platform", 0);
 428        if (!platform_node) {
 429                dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
 430                return -EINVAL;
 431        }
 432
 433        for_each_card_prelinks(card, i, dai_link) {
 434                if (dai_link->platforms->name)
 435                        continue;
 436                dai_link->platforms->of_node = platform_node;
 437        }
 438
 439        mt8183_da7219_max98357_headset_dev.codec_of_node =
 440                of_parse_phandle(pdev->dev.of_node,
 441                                 "mediatek,headset-codec", 0);
 442        if (!mt8183_da7219_max98357_headset_dev.codec_of_node) {
 443                dev_err(&pdev->dev,
 444                        "Property 'mediatek,headset-codec' missing/invalid\n");
 445                return -EINVAL;
 446        }
 447
 448        ret = devm_snd_soc_register_card(&pdev->dev, card);
 449        if (ret) {
 450                dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
 451                        __func__, ret);
 452                return ret;
 453        }
 454
 455        default_pins =
 456                devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT);
 457        if (IS_ERR(default_pins)) {
 458                dev_err(&pdev->dev, "%s set pins failed\n",
 459                        __func__);
 460                return PTR_ERR(default_pins);
 461        }
 462
 463        return ret;
 464}
 465
 466#ifdef CONFIG_OF
 467static const struct of_device_id mt8183_da7219_max98357_dt_match[] = {
 468        {.compatible = "mediatek,mt8183_da7219_max98357",},
 469        {}
 470};
 471#endif
 472
 473static struct platform_driver mt8183_da7219_max98357_driver = {
 474        .driver = {
 475                .name = "mt8183_da7219_max98357",
 476#ifdef CONFIG_OF
 477                .of_match_table = mt8183_da7219_max98357_dt_match,
 478#endif
 479        },
 480        .probe = mt8183_da7219_max98357_dev_probe,
 481};
 482
 483module_platform_driver(mt8183_da7219_max98357_driver);
 484
 485/* Module information */
 486MODULE_DESCRIPTION("MT8183-DA7219-MAX98357 ALSA SoC machine driver");
 487MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>");
 488MODULE_LICENSE("GPL v2");
 489MODULE_ALIAS("mt8183_da7219_max98357 soc card");
 490
 491