root/sound/soc/tegra/tegra_wm9712.c

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

DEFINITIONS

This source file includes following definitions.
  1. tegra_wm9712_init
  2. tegra_wm9712_driver_probe
  3. tegra_wm9712_driver_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * tegra20_wm9712.c - Tegra machine ASoC driver for boards using WM9712 codec.
   4  *
   5  * Copyright 2012 Lucas Stach <dev@lynxeye.de>
   6  *
   7  * Partly based on code copyright/by:
   8  * Copyright 2011,2012 Toradex Inc.
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/slab.h>
  14 #include <linux/gpio.h>
  15 #include <linux/of_gpio.h>
  16 
  17 #include <sound/core.h>
  18 #include <sound/jack.h>
  19 #include <sound/pcm.h>
  20 #include <sound/pcm_params.h>
  21 #include <sound/soc.h>
  22 
  23 #include "tegra_asoc_utils.h"
  24 
  25 #define DRV_NAME "tegra-snd-wm9712"
  26 
  27 struct tegra_wm9712 {
  28         struct platform_device *codec;
  29         struct tegra_asoc_utils_data util_data;
  30 };
  31 
  32 static const struct snd_soc_dapm_widget tegra_wm9712_dapm_widgets[] = {
  33         SND_SOC_DAPM_HP("Headphone", NULL),
  34         SND_SOC_DAPM_LINE("LineIn", NULL),
  35         SND_SOC_DAPM_MIC("Mic", NULL),
  36 };
  37 
  38 static int tegra_wm9712_init(struct snd_soc_pcm_runtime *rtd)
  39 {
  40         return snd_soc_dapm_force_enable_pin(&rtd->card->dapm, "Mic Bias");
  41 }
  42 
  43 SND_SOC_DAILINK_DEFS(hifi,
  44         DAILINK_COMP_ARRAY(COMP_EMPTY()),
  45         DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")),
  46         DAILINK_COMP_ARRAY(COMP_EMPTY()));
  47 
  48 static struct snd_soc_dai_link tegra_wm9712_dai = {
  49         .name = "AC97 HiFi",
  50         .stream_name = "AC97 HiFi",
  51         .init = tegra_wm9712_init,
  52         SND_SOC_DAILINK_REG(hifi),
  53 };
  54 
  55 static struct snd_soc_card snd_soc_tegra_wm9712 = {
  56         .name = "tegra-wm9712",
  57         .owner = THIS_MODULE,
  58         .dai_link = &tegra_wm9712_dai,
  59         .num_links = 1,
  60 
  61         .dapm_widgets = tegra_wm9712_dapm_widgets,
  62         .num_dapm_widgets = ARRAY_SIZE(tegra_wm9712_dapm_widgets),
  63         .fully_routed = true,
  64 };
  65 
  66 static int tegra_wm9712_driver_probe(struct platform_device *pdev)
  67 {
  68         struct device_node *np = pdev->dev.of_node;
  69         struct snd_soc_card *card = &snd_soc_tegra_wm9712;
  70         struct tegra_wm9712 *machine;
  71         int ret;
  72 
  73         machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm9712),
  74                                GFP_KERNEL);
  75         if (!machine)
  76                 return -ENOMEM;
  77 
  78         card->dev = &pdev->dev;
  79         snd_soc_card_set_drvdata(card, machine);
  80 
  81         machine->codec = platform_device_alloc("wm9712-codec", -1);
  82         if (!machine->codec) {
  83                 dev_err(&pdev->dev, "Can't allocate wm9712 platform device\n");
  84                 return -ENOMEM;
  85         }
  86 
  87         ret = platform_device_add(machine->codec);
  88         if (ret)
  89                 goto codec_put;
  90 
  91         ret = snd_soc_of_parse_card_name(card, "nvidia,model");
  92         if (ret)
  93                 goto codec_unregister;
  94 
  95         ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
  96         if (ret)
  97                 goto codec_unregister;
  98 
  99         tegra_wm9712_dai.cpus->of_node = of_parse_phandle(np,
 100                                        "nvidia,ac97-controller", 0);
 101         if (!tegra_wm9712_dai.cpus->of_node) {
 102                 dev_err(&pdev->dev,
 103                         "Property 'nvidia,ac97-controller' missing or invalid\n");
 104                 ret = -EINVAL;
 105                 goto codec_unregister;
 106         }
 107 
 108         tegra_wm9712_dai.platforms->of_node = tegra_wm9712_dai.cpus->of_node;
 109 
 110         ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
 111         if (ret)
 112                 goto codec_unregister;
 113 
 114         ret = tegra_asoc_utils_set_ac97_rate(&machine->util_data);
 115         if (ret)
 116                 goto asoc_utils_fini;
 117 
 118         ret = snd_soc_register_card(card);
 119         if (ret) {
 120                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
 121                         ret);
 122                 goto asoc_utils_fini;
 123         }
 124 
 125         return 0;
 126 
 127 asoc_utils_fini:
 128         tegra_asoc_utils_fini(&machine->util_data);
 129 codec_unregister:
 130         platform_device_del(machine->codec);
 131 codec_put:
 132         platform_device_put(machine->codec);
 133         return ret;
 134 }
 135 
 136 static int tegra_wm9712_driver_remove(struct platform_device *pdev)
 137 {
 138         struct snd_soc_card *card = platform_get_drvdata(pdev);
 139         struct tegra_wm9712 *machine = snd_soc_card_get_drvdata(card);
 140 
 141         snd_soc_unregister_card(card);
 142 
 143         tegra_asoc_utils_fini(&machine->util_data);
 144 
 145         platform_device_unregister(machine->codec);
 146 
 147         return 0;
 148 }
 149 
 150 static const struct of_device_id tegra_wm9712_of_match[] = {
 151         { .compatible = "nvidia,tegra-audio-wm9712", },
 152         {},
 153 };
 154 
 155 static struct platform_driver tegra_wm9712_driver = {
 156         .driver = {
 157                 .name = DRV_NAME,
 158                 .pm = &snd_soc_pm_ops,
 159                 .of_match_table = tegra_wm9712_of_match,
 160         },
 161         .probe = tegra_wm9712_driver_probe,
 162         .remove = tegra_wm9712_driver_remove,
 163 };
 164 module_platform_driver(tegra_wm9712_driver);
 165 
 166 MODULE_AUTHOR("Lucas Stach");
 167 MODULE_DESCRIPTION("Tegra+WM9712 machine ASoC driver");
 168 MODULE_LICENSE("GPL v2");
 169 MODULE_ALIAS("platform:" DRV_NAME);
 170 MODULE_DEVICE_TABLE(of, tegra_wm9712_of_match);

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