linux/sound/soc/mediatek/mt8173/mt8173-max98090.c
<<
>>
Prefs
   1/*
   2 * mt8173-max98090.c  --  MT8173 MAX98090 ALSA SoC machine driver
   3 *
   4 * Copyright (c) 2015 MediaTek Inc.
   5 * Author: Koro Chen <koro.chen@mediatek.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 and
   9 * only version 2 as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <linux/module.h>
  18#include <sound/soc.h>
  19#include <sound/jack.h>
  20#include <linux/gpio.h>
  21#include "../../codecs/max98090.h"
  22
  23static struct snd_soc_jack mt8173_max98090_jack;
  24
  25static struct snd_soc_jack_pin mt8173_max98090_jack_pins[] = {
  26        {
  27                .pin    = "Headphone",
  28                .mask   = SND_JACK_HEADPHONE,
  29        },
  30        {
  31                .pin    = "Headset Mic",
  32                .mask   = SND_JACK_MICROPHONE,
  33        },
  34};
  35
  36static const struct snd_soc_dapm_widget mt8173_max98090_widgets[] = {
  37        SND_SOC_DAPM_SPK("Speaker", NULL),
  38        SND_SOC_DAPM_MIC("Int Mic", NULL),
  39        SND_SOC_DAPM_HP("Headphone", NULL),
  40        SND_SOC_DAPM_MIC("Headset Mic", NULL),
  41};
  42
  43static const struct snd_soc_dapm_route mt8173_max98090_routes[] = {
  44        {"Speaker", NULL, "SPKL"},
  45        {"Speaker", NULL, "SPKR"},
  46        {"DMICL", NULL, "Int Mic"},
  47        {"Headphone", NULL, "HPL"},
  48        {"Headphone", NULL, "HPR"},
  49        {"Headset Mic", NULL, "MICBIAS"},
  50        {"IN34", NULL, "Headset Mic"},
  51};
  52
  53static const struct snd_kcontrol_new mt8173_max98090_controls[] = {
  54        SOC_DAPM_PIN_SWITCH("Speaker"),
  55        SOC_DAPM_PIN_SWITCH("Int Mic"),
  56        SOC_DAPM_PIN_SWITCH("Headphone"),
  57        SOC_DAPM_PIN_SWITCH("Headset Mic"),
  58};
  59
  60static int mt8173_max98090_hw_params(struct snd_pcm_substream *substream,
  61                                     struct snd_pcm_hw_params *params)
  62{
  63        struct snd_soc_pcm_runtime *rtd = substream->private_data;
  64        struct snd_soc_dai *codec_dai = rtd->codec_dai;
  65
  66        return snd_soc_dai_set_sysclk(codec_dai, 0, params_rate(params) * 256,
  67                                      SND_SOC_CLOCK_IN);
  68}
  69
  70static struct snd_soc_ops mt8173_max98090_ops = {
  71        .hw_params = mt8173_max98090_hw_params,
  72};
  73
  74static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime)
  75{
  76        int ret;
  77        struct snd_soc_card *card = runtime->card;
  78        struct snd_soc_codec *codec = runtime->codec;
  79
  80        /* enable jack detection */
  81        ret = snd_soc_card_jack_new(card, "Headphone", SND_JACK_HEADPHONE,
  82                                    &mt8173_max98090_jack, NULL, 0);
  83        if (ret) {
  84                dev_err(card->dev, "Can't snd_soc_jack_new %d\n", ret);
  85                return ret;
  86        }
  87
  88        ret = snd_soc_jack_add_pins(&mt8173_max98090_jack,
  89                                    ARRAY_SIZE(mt8173_max98090_jack_pins),
  90                                    mt8173_max98090_jack_pins);
  91        if (ret) {
  92                dev_err(card->dev, "Can't snd_soc_jack_add_pins %d\n", ret);
  93                return ret;
  94        }
  95
  96        return max98090_mic_detect(codec, &mt8173_max98090_jack);
  97}
  98
  99/* Digital audio interface glue - connects codec <---> CPU */
 100static struct snd_soc_dai_link mt8173_max98090_dais[] = {
 101        /* Front End DAI links */
 102        {
 103                .name = "MAX98090 Playback",
 104                .stream_name = "MAX98090 Playback",
 105                .cpu_dai_name = "DL1",
 106                .codec_name = "snd-soc-dummy",
 107                .codec_dai_name = "snd-soc-dummy-dai",
 108                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 109                .dynamic = 1,
 110                .dpcm_playback = 1,
 111        },
 112        {
 113                .name = "MAX98090 Capture",
 114                .stream_name = "MAX98090 Capture",
 115                .cpu_dai_name = "VUL",
 116                .codec_name = "snd-soc-dummy",
 117                .codec_dai_name = "snd-soc-dummy-dai",
 118                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 119                .dynamic = 1,
 120                .dpcm_capture = 1,
 121        },
 122        /* Back End DAI links */
 123        {
 124                .name = "Codec",
 125                .cpu_dai_name = "I2S",
 126                .no_pcm = 1,
 127                .codec_dai_name = "HiFi",
 128                .init = mt8173_max98090_init,
 129                .ops = &mt8173_max98090_ops,
 130                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 131                           SND_SOC_DAIFMT_CBS_CFS,
 132                .dpcm_playback = 1,
 133                .dpcm_capture = 1,
 134        },
 135};
 136
 137static struct snd_soc_card mt8173_max98090_card = {
 138        .name = "mt8173-max98090",
 139        .owner = THIS_MODULE,
 140        .dai_link = mt8173_max98090_dais,
 141        .num_links = ARRAY_SIZE(mt8173_max98090_dais),
 142        .controls = mt8173_max98090_controls,
 143        .num_controls = ARRAY_SIZE(mt8173_max98090_controls),
 144        .dapm_widgets = mt8173_max98090_widgets,
 145        .num_dapm_widgets = ARRAY_SIZE(mt8173_max98090_widgets),
 146        .dapm_routes = mt8173_max98090_routes,
 147        .num_dapm_routes = ARRAY_SIZE(mt8173_max98090_routes),
 148};
 149
 150static int mt8173_max98090_dev_probe(struct platform_device *pdev)
 151{
 152        struct snd_soc_card *card = &mt8173_max98090_card;
 153        struct device_node *codec_node, *platform_node;
 154        int ret, i;
 155
 156        platform_node = of_parse_phandle(pdev->dev.of_node,
 157                                         "mediatek,platform", 0);
 158        if (!platform_node) {
 159                dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
 160                return -EINVAL;
 161        }
 162        for (i = 0; i < card->num_links; i++) {
 163                if (mt8173_max98090_dais[i].platform_name)
 164                        continue;
 165                mt8173_max98090_dais[i].platform_of_node = platform_node;
 166        }
 167
 168        codec_node = of_parse_phandle(pdev->dev.of_node,
 169                                      "mediatek,audio-codec", 0);
 170        if (!codec_node) {
 171                dev_err(&pdev->dev,
 172                        "Property 'audio-codec' missing or invalid\n");
 173                return -EINVAL;
 174        }
 175        for (i = 0; i < card->num_links; i++) {
 176                if (mt8173_max98090_dais[i].codec_name)
 177                        continue;
 178                mt8173_max98090_dais[i].codec_of_node = codec_node;
 179        }
 180        card->dev = &pdev->dev;
 181
 182        ret = devm_snd_soc_register_card(&pdev->dev, card);
 183        if (ret)
 184                dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
 185                        __func__, ret);
 186        return ret;
 187}
 188
 189static const struct of_device_id mt8173_max98090_dt_match[] = {
 190        { .compatible = "mediatek,mt8173-max98090", },
 191        { }
 192};
 193MODULE_DEVICE_TABLE(of, mt8173_max98090_dt_match);
 194
 195static struct platform_driver mt8173_max98090_driver = {
 196        .driver = {
 197                   .name = "mt8173-max98090",
 198                   .of_match_table = mt8173_max98090_dt_match,
 199#ifdef CONFIG_PM
 200                   .pm = &snd_soc_pm_ops,
 201#endif
 202        },
 203        .probe = mt8173_max98090_dev_probe,
 204};
 205
 206module_platform_driver(mt8173_max98090_driver);
 207
 208/* Module information */
 209MODULE_DESCRIPTION("MT8173 MAX98090 ALSA SoC machine driver");
 210MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
 211MODULE_LICENSE("GPL v2");
 212MODULE_ALIAS("platform:mt8173-max98090");
 213
 214