root/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mt8183_mt6358_i2s_hw_params
  2. mt8183_da7219_i2s_hw_params
  3. mt8183_da7219_hw_free
  4. mt8183_i2s_hw_params_fixup
  5. mt8183_da7219_max98357_headset_init
  6. mt8183_da7219_max98357_dev_probe

   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 
  19 static struct snd_soc_jack headset_jack;
  20 
  21 static 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 
  33 static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {
  34         .hw_params = mt8183_mt6358_i2s_hw_params,
  35 };
  36 
  37 static 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 
  80 static 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 
 102 static 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 
 107 static 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 
 119 /* FE */
 120 SND_SOC_DAILINK_DEFS(playback1,
 121         DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
 122         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 123         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 124 
 125 SND_SOC_DAILINK_DEFS(playback2,
 126         DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
 127         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 128         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 129 
 130 SND_SOC_DAILINK_DEFS(playback3,
 131         DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
 132         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 133         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 134 
 135 SND_SOC_DAILINK_DEFS(capture1,
 136         DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
 137         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 138         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 139 
 140 SND_SOC_DAILINK_DEFS(capture2,
 141         DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
 142         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 143         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 144 
 145 SND_SOC_DAILINK_DEFS(capture3,
 146         DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
 147         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 148         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 149 
 150 SND_SOC_DAILINK_DEFS(capture_mono,
 151         DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),
 152         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 153         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 154 
 155 SND_SOC_DAILINK_DEFS(playback_hdmi,
 156         DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
 157         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 158         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 159 
 160 /* BE */
 161 SND_SOC_DAILINK_DEFS(primary_codec,
 162         DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
 163         DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")),
 164         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 165 
 166 SND_SOC_DAILINK_DEFS(pcm1,
 167         DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
 168         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 169         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 170 
 171 SND_SOC_DAILINK_DEFS(pcm2,
 172         DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),
 173         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 174         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 175 
 176 SND_SOC_DAILINK_DEFS(i2s0,
 177         DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
 178         DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
 179         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 180 
 181 SND_SOC_DAILINK_DEFS(i2s1,
 182         DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
 183         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 184         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 185 
 186 SND_SOC_DAILINK_DEFS(i2s2,
 187         DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
 188         DAILINK_COMP_ARRAY(COMP_CODEC("da7219.5-001a", "da7219-hifi")),
 189         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 190 
 191 SND_SOC_DAILINK_DEFS(i2s3,
 192         DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
 193         DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"),
 194                          COMP_CODEC("da7219.5-001a", "da7219-hifi")),
 195         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 196 
 197 SND_SOC_DAILINK_DEFS(i2s5,
 198         DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),
 199         DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
 200         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 201 
 202 SND_SOC_DAILINK_DEFS(tdm,
 203         DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
 204         DAILINK_COMP_ARRAY(COMP_DUMMY()),
 205         DAILINK_COMP_ARRAY(COMP_EMPTY()));
 206 
 207 static struct snd_soc_dai_link mt8183_da7219_max98357_dai_links[] = {
 208         /* FE */
 209         {
 210                 .name = "Playback_1",
 211                 .stream_name = "Playback_1",
 212                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 213                             SND_SOC_DPCM_TRIGGER_PRE},
 214                 .dynamic = 1,
 215                 .dpcm_playback = 1,
 216                 SND_SOC_DAILINK_REG(playback1),
 217         },
 218         {
 219                 .name = "Playback_2",
 220                 .stream_name = "Playback_2",
 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(playback2),
 226         },
 227         {
 228                 .name = "Playback_3",
 229                 .stream_name = "Playback_3",
 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(playback3),
 235         },
 236         {
 237                 .name = "Capture_1",
 238                 .stream_name = "Capture_1",
 239                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 240                             SND_SOC_DPCM_TRIGGER_PRE},
 241                 .dynamic = 1,
 242                 .dpcm_capture = 1,
 243                 SND_SOC_DAILINK_REG(capture1),
 244         },
 245         {
 246                 .name = "Capture_2",
 247                 .stream_name = "Capture_2",
 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(capture2),
 253         },
 254         {
 255                 .name = "Capture_3",
 256                 .stream_name = "Capture_3",
 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(capture3),
 262         },
 263         {
 264                 .name = "Capture_Mono_1",
 265                 .stream_name = "Capture_Mono_1",
 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(capture_mono),
 271         },
 272         {
 273                 .name = "Playback_HDMI",
 274                 .stream_name = "Playback_HDMI",
 275                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
 276                             SND_SOC_DPCM_TRIGGER_PRE},
 277                 .dynamic = 1,
 278                 .dpcm_playback = 1,
 279                 SND_SOC_DAILINK_REG(playback_hdmi),
 280         },
 281         /* BE */
 282         {
 283                 .name = "Primary Codec",
 284                 .no_pcm = 1,
 285                 .dpcm_playback = 1,
 286                 .dpcm_capture = 1,
 287                 .ignore_suspend = 1,
 288                 SND_SOC_DAILINK_REG(primary_codec),
 289         },
 290         {
 291                 .name = "PCM 1",
 292                 .no_pcm = 1,
 293                 .dpcm_playback = 1,
 294                 .dpcm_capture = 1,
 295                 .ignore_suspend = 1,
 296                 SND_SOC_DAILINK_REG(pcm1),
 297         },
 298         {
 299                 .name = "PCM 2",
 300                 .no_pcm = 1,
 301                 .dpcm_playback = 1,
 302                 .dpcm_capture = 1,
 303                 .ignore_suspend = 1,
 304                 SND_SOC_DAILINK_REG(pcm2),
 305         },
 306         {
 307                 .name = "I2S0",
 308                 .no_pcm = 1,
 309                 .dpcm_capture = 1,
 310                 .ignore_suspend = 1,
 311                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
 312                 .ops = &mt8183_mt6358_i2s_ops,
 313                 SND_SOC_DAILINK_REG(i2s0),
 314         },
 315         {
 316                 .name = "I2S1",
 317                 .no_pcm = 1,
 318                 .dpcm_playback = 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(i2s1),
 323         },
 324         {
 325                 .name = "I2S2",
 326                 .no_pcm = 1,
 327                 .dpcm_capture = 1,
 328                 .ignore_suspend = 1,
 329                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
 330                 .ops = &mt8183_da7219_i2s_ops,
 331                 SND_SOC_DAILINK_REG(i2s2),
 332         },
 333         {
 334                 .name = "I2S3",
 335                 .no_pcm = 1,
 336                 .dpcm_playback = 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(i2s3),
 341         },
 342         {
 343                 .name = "I2S5",
 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_mt6358_i2s_ops,
 349                 SND_SOC_DAILINK_REG(i2s5),
 350         },
 351         {
 352                 .name = "TDM",
 353                 .no_pcm = 1,
 354                 .dpcm_playback = 1,
 355                 .ignore_suspend = 1,
 356                 SND_SOC_DAILINK_REG(tdm),
 357         },
 358 };
 359 
 360 static int
 361 mt8183_da7219_max98357_headset_init(struct snd_soc_component *component);
 362 
 363 static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = {
 364         .dlc = COMP_EMPTY(),
 365         .init = mt8183_da7219_max98357_headset_init,
 366 };
 367 
 368 static struct snd_soc_codec_conf mt6358_codec_conf[] = {
 369         {
 370                 .dev_name = "mt6358-sound",
 371                 .name_prefix = "Mt6358",
 372         },
 373 };
 374 
 375 static struct snd_soc_card mt8183_da7219_max98357_card = {
 376         .name = "mt8183_da7219_max98357",
 377         .owner = THIS_MODULE,
 378         .dai_link = mt8183_da7219_max98357_dai_links,
 379         .num_links = ARRAY_SIZE(mt8183_da7219_max98357_dai_links),
 380         .aux_dev = &mt8183_da7219_max98357_headset_dev,
 381         .num_aux_devs = 1,
 382         .codec_conf = mt6358_codec_conf,
 383         .num_configs = ARRAY_SIZE(mt6358_codec_conf),
 384 };
 385 
 386 static int
 387 mt8183_da7219_max98357_headset_init(struct snd_soc_component *component)
 388 {
 389         int ret;
 390 
 391         /* Enable Headset and 4 Buttons Jack detection */
 392         ret = snd_soc_card_jack_new(&mt8183_da7219_max98357_card,
 393                                     "Headset Jack",
 394                                     SND_JACK_HEADSET |
 395                                     SND_JACK_BTN_0 | SND_JACK_BTN_1 |
 396                                     SND_JACK_BTN_2 | SND_JACK_BTN_3,
 397                                     &headset_jack,
 398                                     NULL, 0);
 399         if (ret)
 400                 return ret;
 401 
 402         da7219_aad_jack_det(component, &headset_jack);
 403 
 404         return ret;
 405 }
 406 
 407 static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
 408 {
 409         struct snd_soc_card *card = &mt8183_da7219_max98357_card;
 410         struct device_node *platform_node;
 411         struct snd_soc_dai_link *dai_link;
 412         struct pinctrl *default_pins;
 413         int ret, i;
 414 
 415         card->dev = &pdev->dev;
 416 
 417         platform_node = of_parse_phandle(pdev->dev.of_node,
 418                                          "mediatek,platform", 0);
 419         if (!platform_node) {
 420                 dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
 421                 return -EINVAL;
 422         }
 423 
 424         for_each_card_prelinks(card, i, dai_link) {
 425                 if (dai_link->platforms->name)
 426                         continue;
 427                 dai_link->platforms->of_node = platform_node;
 428         }
 429 
 430         mt8183_da7219_max98357_headset_dev.dlc.of_node =
 431                 of_parse_phandle(pdev->dev.of_node,
 432                                  "mediatek,headset-codec", 0);
 433         if (!mt8183_da7219_max98357_headset_dev.dlc.of_node) {
 434                 dev_err(&pdev->dev,
 435                         "Property 'mediatek,headset-codec' missing/invalid\n");
 436                 return -EINVAL;
 437         }
 438 
 439         ret = devm_snd_soc_register_card(&pdev->dev, card);
 440         if (ret) {
 441                 dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
 442                         __func__, ret);
 443                 return ret;
 444         }
 445 
 446         default_pins =
 447                 devm_pinctrl_get_select(&pdev->dev, PINCTRL_STATE_DEFAULT);
 448         if (IS_ERR(default_pins)) {
 449                 dev_err(&pdev->dev, "%s set pins failed\n",
 450                         __func__);
 451                 return PTR_ERR(default_pins);
 452         }
 453 
 454         return ret;
 455 }
 456 
 457 #ifdef CONFIG_OF
 458 static const struct of_device_id mt8183_da7219_max98357_dt_match[] = {
 459         {.compatible = "mediatek,mt8183_da7219_max98357",},
 460         {}
 461 };
 462 #endif
 463 
 464 static struct platform_driver mt8183_da7219_max98357_driver = {
 465         .driver = {
 466                 .name = "mt8183_da7219_max98357",
 467 #ifdef CONFIG_OF
 468                 .of_match_table = mt8183_da7219_max98357_dt_match,
 469 #endif
 470         },
 471         .probe = mt8183_da7219_max98357_dev_probe,
 472 };
 473 
 474 module_platform_driver(mt8183_da7219_max98357_driver);
 475 
 476 /* Module information */
 477 MODULE_DESCRIPTION("MT8183-DA7219-MAX98357 ALSA SoC machine driver");
 478 MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>");
 479 MODULE_LICENSE("GPL v2");
 480 MODULE_ALIAS("mt8183_da7219_max98357 soc card");
 481 

/* [<][>][^][v][top][bottom][index][help] */