~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/atmel/sam9g20_wm8731.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * sam9g20_wm8731  --  SoC audio for AT91SAM9G20-based
  4  *                      ATMEL AT91SAM9G20ek board.
  5  *
  6  *  Copyright (C) 2005 SAN People
  7  *  Copyright (C) 2008 Atmel
  8  *
  9  * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
 10  *
 11  * Based on ati_b1_wm8731.c by:
 12  * Frank Mandarino <fmandarino@endrelia.com>
 13  * Copyright 2006 Endrelia Technologies Inc.
 14  * Based on corgi.c by:
 15  * Copyright 2005 Wolfson Microelectronics PLC.
 16  * Copyright 2005 Openedhand Ltd.
 17  */
 18 
 19 #include <linux/module.h>
 20 #include <linux/moduleparam.h>
 21 #include <linux/kernel.h>
 22 #include <linux/clk.h>
 23 #include <linux/timer.h>
 24 #include <linux/interrupt.h>
 25 #include <linux/platform_device.h>
 26 #include <linux/of.h>
 27 
 28 #include <linux/atmel-ssc.h>
 29 
 30 #include <sound/core.h>
 31 #include <sound/pcm.h>
 32 #include <sound/pcm_params.h>
 33 #include <sound/soc.h>
 34 
 35 #include "../codecs/wm8731.h"
 36 #include "atmel-pcm.h"
 37 #include "atmel_ssc_dai.h"
 38 
 39 #define MCLK_RATE 12000000
 40 
 41 /*
 42  * As shipped the board does not have inputs.  However, it is relatively
 43  * straightforward to modify the board to hook them up so support is left
 44  * in the driver.
 45  */
 46 #undef ENABLE_MIC_INPUT
 47 
 48 static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
 49         SND_SOC_DAPM_MIC("Int Mic", NULL),
 50         SND_SOC_DAPM_SPK("Ext Spk", NULL),
 51 };
 52 
 53 static const struct snd_soc_dapm_route intercon[] = {
 54 
 55         /* speaker connected to LHPOUT/RHPOUT */
 56         {"Ext Spk", NULL, "LHPOUT"},
 57         {"Ext Spk", NULL, "RHPOUT"},
 58 
 59         /* mic is connected to Mic Jack, with WM8731 Mic Bias */
 60         {"MICIN", NULL, "Mic Bias"},
 61         {"Mic Bias", NULL, "Int Mic"},
 62 };
 63 
 64 /*
 65  * Logic for a wm8731 as connected on a at91sam9g20ek board.
 66  */
 67 static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 68 {
 69         struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
 70         struct device *dev = rtd->dev;
 71         int ret;
 72 
 73         dev_dbg(dev, "%s called\n", __func__);
 74 
 75         ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_MCLK,
 76                                      MCLK_RATE, SND_SOC_CLOCK_IN);
 77         if (ret < 0) {
 78                 dev_err(dev, "Failed to set WM8731 SYSCLK: %d\n", ret);
 79                 return ret;
 80         }
 81 
 82 #ifndef ENABLE_MIC_INPUT
 83         snd_soc_dapm_nc_pin(&rtd->card->dapm, "Int Mic");
 84 #endif
 85 
 86         return 0;
 87 }
 88 
 89 SND_SOC_DAILINK_DEFS(pcm,
 90         DAILINK_COMP_ARRAY(COMP_CPU("at91rm9200_ssc.0")),
 91         DAILINK_COMP_ARRAY(COMP_CODEC("wm8731.0-001b", "wm8731-hifi")),
 92         DAILINK_COMP_ARRAY(COMP_PLATFORM("at91rm9200_ssc.0")));
 93 
 94 static struct snd_soc_dai_link at91sam9g20ek_dai = {
 95         .name = "WM8731",
 96         .stream_name = "WM8731 PCM",
 97         .init = at91sam9g20ek_wm8731_init,
 98         .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
 99                    SND_SOC_DAIFMT_CBP_CFP,
100 #ifndef ENABLE_MIC_INPUT
101         .playback_only = true,
102 #endif
103         SND_SOC_DAILINK_REG(pcm),
104 };
105 
106 static struct snd_soc_card snd_soc_at91sam9g20ek = {
107         .name = "AT91SAMG20-EK",
108         .owner = THIS_MODULE,
109         .dai_link = &at91sam9g20ek_dai,
110         .num_links = 1,
111 
112         .dapm_widgets = at91sam9g20ek_dapm_widgets,
113         .num_dapm_widgets = ARRAY_SIZE(at91sam9g20ek_dapm_widgets),
114         .dapm_routes = intercon,
115         .num_dapm_routes = ARRAY_SIZE(intercon),
116         .fully_routed = true,
117 };
118 
119 static int at91sam9g20ek_audio_probe(struct platform_device *pdev)
120 {
121         struct device_node *np = pdev->dev.of_node;
122         struct device_node *codec_np, *cpu_np;
123         struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
124         int ret;
125 
126         if (!np) {
127                 return -ENODEV;
128         }
129 
130         ret = atmel_ssc_set_audio(0);
131         if (ret) {
132                 dev_err(&pdev->dev, "ssc channel is not valid: %d\n", ret);
133                 return ret;
134         }
135 
136         card->dev = &pdev->dev;
137 
138         /* Parse device node info */
139         ret = snd_soc_of_parse_card_name(card, "atmel,model");
140         if (ret)
141                 goto err;
142 
143         ret = snd_soc_of_parse_audio_routing(card,
144                 "atmel,audio-routing");
145         if (ret)
146                 goto err;
147 
148         /* Parse codec info */
149         at91sam9g20ek_dai.codecs->name = NULL;
150         codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
151         if (!codec_np) {
152                 dev_err(&pdev->dev, "codec info missing\n");
153                 ret = -EINVAL;
154                 goto err;
155         }
156         at91sam9g20ek_dai.codecs->of_node = codec_np;
157 
158         /* Parse dai and platform info */
159         at91sam9g20ek_dai.cpus->dai_name = NULL;
160         at91sam9g20ek_dai.platforms->name = NULL;
161         cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
162         if (!cpu_np) {
163                 dev_err(&pdev->dev, "dai and pcm info missing\n");
164                 of_node_put(codec_np);
165                 ret = -EINVAL;
166                 goto err;
167         }
168         at91sam9g20ek_dai.cpus->of_node = cpu_np;
169         at91sam9g20ek_dai.platforms->of_node = cpu_np;
170 
171         of_node_put(codec_np);
172         of_node_put(cpu_np);
173 
174         ret = snd_soc_register_card(card);
175         if (ret) {
176                 dev_err_probe(&pdev->dev, ret,
177                               "snd_soc_register_card() failed\n");
178                 goto err;
179         }
180 
181         return 0;
182 
183 err:
184         atmel_ssc_put_audio(0);
185         return ret;
186 }
187 
188 static void at91sam9g20ek_audio_remove(struct platform_device *pdev)
189 {
190         struct snd_soc_card *card = platform_get_drvdata(pdev);
191 
192         snd_soc_unregister_card(card);
193         atmel_ssc_put_audio(0);
194 }
195 
196 #ifdef CONFIG_OF
197 static const struct of_device_id at91sam9g20ek_wm8731_dt_ids[] = {
198         { .compatible = "atmel,at91sam9g20ek-wm8731-audio", },
199         { }
200 };
201 MODULE_DEVICE_TABLE(of, at91sam9g20ek_wm8731_dt_ids);
202 #endif
203 
204 static struct platform_driver at91sam9g20ek_audio_driver = {
205         .driver = {
206                 .name   = "at91sam9g20ek-audio",
207                 .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids),
208         },
209         .probe  = at91sam9g20ek_audio_probe,
210         .remove_new = at91sam9g20ek_audio_remove,
211 };
212 
213 module_platform_driver(at91sam9g20ek_audio_driver);
214 
215 /* Module information */
216 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
217 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
218 MODULE_ALIAS("platform:at91sam9g20ek-audio");
219 MODULE_LICENSE("GPL");
220 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php