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 const 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,
  83                                    mt8173_max98090_jack_pins,
  84                                    ARRAY_SIZE(mt8173_max98090_jack_pins));
  85        if (ret) {
  86                dev_err(card->dev, "Can't create a new Jack %d\n", ret);
  87                return ret;
  88        }
  89
  90        return max98090_mic_detect(codec, &mt8173_max98090_jack);
  91}
  92
  93/* Digital audio interface glue - connects codec <---> CPU */
  94static struct snd_soc_dai_link mt8173_max98090_dais[] = {
  95        /* Front End DAI links */
  96        {
  97                .name = "MAX98090 Playback",
  98                .stream_name = "MAX98090 Playback",
  99                .cpu_dai_name = "DL1",
 100                .codec_name = "snd-soc-dummy",
 101                .codec_dai_name = "snd-soc-dummy-dai",
 102                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 103                .dynamic = 1,
 104                .dpcm_playback = 1,
 105        },
 106        {
 107                .name = "MAX98090 Capture",
 108                .stream_name = "MAX98090 Capture",
 109                .cpu_dai_name = "VUL",
 110                .codec_name = "snd-soc-dummy",
 111                .codec_dai_name = "snd-soc-dummy-dai",
 112                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
 113                .dynamic = 1,
 114                .dpcm_capture = 1,
 115        },
 116        /* Back End DAI links */
 117        {
 118                .name = "Codec",
 119                .cpu_dai_name = "I2S",
 120                .no_pcm = 1,
 121                .codec_dai_name = "HiFi",
 122                .init = mt8173_max98090_init,
 123                .ops = &mt8173_max98090_ops,
 124                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 125                           SND_SOC_DAIFMT_CBS_CFS,
 126                .dpcm_playback = 1,
 127                .dpcm_capture = 1,
 128        },
 129};
 130
 131static struct snd_soc_card mt8173_max98090_card = {
 132        .name = "mt8173-max98090",
 133        .owner = THIS_MODULE,
 134        .dai_link = mt8173_max98090_dais,
 135        .num_links = ARRAY_SIZE(mt8173_max98090_dais),
 136        .controls = mt8173_max98090_controls,
 137        .num_controls = ARRAY_SIZE(mt8173_max98090_controls),
 138        .dapm_widgets = mt8173_max98090_widgets,
 139        .num_dapm_widgets = ARRAY_SIZE(mt8173_max98090_widgets),
 140        .dapm_routes = mt8173_max98090_routes,
 141        .num_dapm_routes = ARRAY_SIZE(mt8173_max98090_routes),
 142};
 143
 144static int mt8173_max98090_dev_probe(struct platform_device *pdev)
 145{
 146        struct snd_soc_card *card = &mt8173_max98090_card;
 147        struct device_node *codec_node, *platform_node;
 148        int ret, i;
 149
 150        platform_node = of_parse_phandle(pdev->dev.of_node,
 151                                         "mediatek,platform", 0);
 152        if (!platform_node) {
 153                dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
 154                return -EINVAL;
 155        }
 156        for (i = 0; i < card->num_links; i++) {
 157                if (mt8173_max98090_dais[i].platform_name)
 158                        continue;
 159                mt8173_max98090_dais[i].platform_of_node = platform_node;
 160        }
 161
 162        codec_node = of_parse_phandle(pdev->dev.of_node,
 163                                      "mediatek,audio-codec", 0);
 164        if (!codec_node) {
 165                dev_err(&pdev->dev,
 166                        "Property 'audio-codec' missing or invalid\n");
 167                return -EINVAL;
 168        }
 169        for (i = 0; i < card->num_links; i++) {
 170                if (mt8173_max98090_dais[i].codec_name)
 171                        continue;
 172                mt8173_max98090_dais[i].codec_of_node = codec_node;
 173        }
 174        card->dev = &pdev->dev;
 175
 176        ret = devm_snd_soc_register_card(&pdev->dev, card);
 177        if (ret)
 178                dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
 179                        __func__, ret);
 180        return ret;
 181}
 182
 183static const struct of_device_id mt8173_max98090_dt_match[] = {
 184        { .compatible = "mediatek,mt8173-max98090", },
 185        { }
 186};
 187MODULE_DEVICE_TABLE(of, mt8173_max98090_dt_match);
 188
 189static struct platform_driver mt8173_max98090_driver = {
 190        .driver = {
 191                   .name = "mt8173-max98090",
 192                   .of_match_table = mt8173_max98090_dt_match,
 193#ifdef CONFIG_PM
 194                   .pm = &snd_soc_pm_ops,
 195#endif
 196        },
 197        .probe = mt8173_max98090_dev_probe,
 198};
 199
 200module_platform_driver(mt8173_max98090_driver);
 201
 202/* Module information */
 203MODULE_DESCRIPTION("MT8173 MAX98090 ALSA SoC machine driver");
 204MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
 205MODULE_LICENSE("GPL v2");
 206MODULE_ALIAS("platform:mt8173-max98090");
 207
 208