blob: 68d69e32681add970c669e2fa4adb975be331739 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Vladimir Barinov310355c2008-02-18 11:40:22 +01002/*
3 * ASoC driver for TI DAVINCI EVM platform
4 *
Vladimir Barinovd6b52032008-09-29 23:14:11 +04005 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
Vladimir Barinov310355c2008-02-18 11:40:22 +01006 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
Vladimir Barinov310355c2008-02-18 11:40:22 +01007 */
8
9#include <linux/module.h>
10#include <linux/moduleparam.h>
11#include <linux/timer.h>
12#include <linux/interrupt.h>
13#include <linux/platform_device.h>
Ben Dooksaa6b9042009-08-20 22:50:42 +010014#include <linux/i2c.h>
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +030015#include <linux/of_platform.h>
Jyri Sarha5ad88652014-01-27 17:37:51 +020016#include <linux/clk.h>
Vladimir Barinov310355c2008-02-18 11:40:22 +010017#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
Vladimir Barinov310355c2008-02-18 11:40:22 +010020
Vladimir Barinov310355c2008-02-18 11:40:22 +010021#include <asm/dma.h>
David Brownellf492ec92009-05-14 13:01:59 -070022#include <asm/mach-types.h>
23
Jyri Sarhabcf25562013-09-17 12:26:00 +030024struct snd_soc_card_drvdata_davinci {
Jyri Sarha5ad88652014-01-27 17:37:51 +020025 struct clk *mclk;
Jyri Sarhabcf25562013-09-17 12:26:00 +030026 unsigned sysclk;
27};
28
Jyri Sarha5ad88652014-01-27 17:37:51 +020029static int evm_startup(struct snd_pcm_substream *substream)
30{
Kuninori Morimoto02cde142020-07-20 10:17:48 +090031 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
Lars-Peter Clausen2896b8b2014-05-19 11:41:47 +020032 struct snd_soc_card *soc_card = rtd->card;
Jyri Sarha5ad88652014-01-27 17:37:51 +020033 struct snd_soc_card_drvdata_davinci *drvdata =
34 snd_soc_card_get_drvdata(soc_card);
35
36 if (drvdata->mclk)
37 return clk_prepare_enable(drvdata->mclk);
38
39 return 0;
40}
41
42static void evm_shutdown(struct snd_pcm_substream *substream)
43{
Kuninori Morimoto02cde142020-07-20 10:17:48 +090044 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
Lars-Peter Clausen2896b8b2014-05-19 11:41:47 +020045 struct snd_soc_card *soc_card = rtd->card;
Jyri Sarha5ad88652014-01-27 17:37:51 +020046 struct snd_soc_card_drvdata_davinci *drvdata =
47 snd_soc_card_get_drvdata(soc_card);
48
Xu Wangff3cfcc2020-10-29 08:25:13 +000049 clk_disable_unprepare(drvdata->mclk);
Jyri Sarha5ad88652014-01-27 17:37:51 +020050}
51
Vladimir Barinov310355c2008-02-18 11:40:22 +010052static int evm_hw_params(struct snd_pcm_substream *substream,
53 struct snd_pcm_hw_params *params)
54{
Kuninori Morimoto02cde142020-07-20 10:17:48 +090055 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
Kuninori Morimoto2842b872020-03-23 14:21:14 +090056 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
57 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Lars-Peter Clausen2896b8b2014-05-19 11:41:47 +020058 struct snd_soc_card *soc_card = rtd->card;
Vladimir Barinov310355c2008-02-18 11:40:22 +010059 int ret = 0;
Jyri Sarhabcf25562013-09-17 12:26:00 +030060 unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
61 snd_soc_card_get_drvdata(soc_card))->sysclk;
Vladimir Barinov310355c2008-02-18 11:40:22 +010062
Vladimir Barinov310355c2008-02-18 11:40:22 +010063 /* set the codec system clock */
David Brownell05d5e992009-01-04 02:50:10 -080064 ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
Vladimir Barinov310355c2008-02-18 11:40:22 +010065 if (ret < 0)
66 return ret;
67
Daniel Mack5b66aa22012-10-04 15:08:41 +020068 /* set the CPU system clock */
69 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
Peter Ujfalusi69f34052019-08-30 13:38:41 +030070 if (ret < 0 && ret != -ENOTSUPP)
Daniel Mack5b66aa22012-10-04 15:08:41 +020071 return ret;
72
Vladimir Barinov310355c2008-02-18 11:40:22 +010073 return 0;
74}
75
Rikard Falkeborn51004362021-09-29 11:31:21 +020076static const struct snd_soc_ops evm_ops = {
Jyri Sarha5ad88652014-01-27 17:37:51 +020077 .startup = evm_startup,
78 .shutdown = evm_shutdown,
Vladimir Barinov310355c2008-02-18 11:40:22 +010079 .hw_params = evm_hw_params,
80};
81
82/* davinci-evm machine dapm widgets */
83static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
84 SND_SOC_DAPM_HP("Headphone Jack", NULL),
85 SND_SOC_DAPM_LINE("Line Out", NULL),
86 SND_SOC_DAPM_MIC("Mic Jack", NULL),
87 SND_SOC_DAPM_LINE("Line In", NULL),
88};
89
90/* davinci-evm machine audio_mapnections to the codec pins */
Mark Brownacf497f2008-05-13 14:58:30 +020091static const struct snd_soc_dapm_route audio_map[] = {
Vladimir Barinov310355c2008-02-18 11:40:22 +010092 /* Headphone connected to HPLOUT, HPROUT */
93 {"Headphone Jack", NULL, "HPLOUT"},
94 {"Headphone Jack", NULL, "HPROUT"},
95
96 /* Line Out connected to LLOUT, RLOUT */
97 {"Line Out", NULL, "LLOUT"},
98 {"Line Out", NULL, "RLOUT"},
99
100 /* Mic connected to (MIC3L | MIC3R) */
Hebbar Gururajae2e8bfd2013-01-31 18:23:04 +0530101 {"MIC3L", NULL, "Mic Bias"},
102 {"MIC3R", NULL, "Mic Bias"},
103 {"Mic Bias", NULL, "Mic Jack"},
Vladimir Barinov310355c2008-02-18 11:40:22 +0100104
105 /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
106 {"LINE1L", NULL, "Line In"},
107 {"LINE2L", NULL, "Line In"},
108 {"LINE1R", NULL, "Line In"},
109 {"LINE2R", NULL, "Line In"},
Vladimir Barinov310355c2008-02-18 11:40:22 +0100110};
111
112/* Logic for a aic3x as connected on a davinci-evm */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000113static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
Vladimir Barinov310355c2008-02-18 11:40:22 +0100114{
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100115 struct snd_soc_card *card = rtd->card;
Lars-Peter Clausen2896b8b2014-05-19 11:41:47 +0200116 struct device_node *np = card->dev->of_node;
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300117 int ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000118
Vladimir Barinov310355c2008-02-18 11:40:22 +0100119 /* Add davinci-evm specific widgets */
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100120 snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets,
Mark Brownacf497f2008-05-13 14:58:30 +0200121 ARRAY_SIZE(aic3x_dapm_widgets));
Vladimir Barinov310355c2008-02-18 11:40:22 +0100122
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300123 if (np) {
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100124 ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing");
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300125 if (ret)
126 return ret;
127 } else {
128 /* Set up davinci-evm specific audio path audio_map */
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100129 snd_soc_dapm_add_routes(&card->dapm, audio_map,
130 ARRAY_SIZE(audio_map));
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300131 }
Vladimir Barinov310355c2008-02-18 11:40:22 +0100132
133 /* not connected */
Lars-Peter Clausenb213b442015-04-11 13:11:28 +0200134 snd_soc_dapm_nc_pin(&card->dapm, "MONO_LOUT");
135 snd_soc_dapm_nc_pin(&card->dapm, "HPLCOM");
136 snd_soc_dapm_nc_pin(&card->dapm, "HPRCOM");
Vladimir Barinov310355c2008-02-18 11:40:22 +0100137
Vladimir Barinov310355c2008-02-18 11:40:22 +0100138 return 0;
139}
140
141/* davinci-evm digital audio interface glue - connects codec <--> CPU */
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900142SND_SOC_DAILINK_DEFS(dm6446,
143 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")),
144 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b",
145 "tlv320aic3x-hifi")),
146 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp")));
147
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000148static struct snd_soc_dai_link dm6446_evm_dai = {
Vladimir Barinov310355c2008-02-18 11:40:22 +0100149 .name = "TLV320AIC3X",
150 .stream_name = "AIC3X",
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000151 .init = evm_aic3x_init,
152 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200153 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
154 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900155 SND_SOC_DAILINK_REG(dm6446),
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000156};
157
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900158SND_SOC_DAILINK_DEFS(dm355,
159 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp.1")),
160 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b",
161 "tlv320aic3x-hifi")),
162 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp.1")));
163
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000164static struct snd_soc_dai_link dm355_evm_dai = {
165 .name = "TLV320AIC3X",
166 .stream_name = "AIC3X",
Vladimir Barinov310355c2008-02-18 11:40:22 +0100167 .init = evm_aic3x_init,
168 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200169 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
170 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900171 SND_SOC_DAILINK_REG(dm355),
Vladimir Barinov310355c2008-02-18 11:40:22 +0100172};
173
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900174#ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC
175SND_SOC_DAILINK_DEFS(dm365,
176 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")),
177 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
178 "tlv320aic3x-hifi")),
179 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp")));
180#elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC)
181SND_SOC_DAILINK_DEFS(dm365,
182 DAILINK_COMP_ARRAY(COMP_CPU("davinci-vcif")),
183 DAILINK_COMP_ARRAY(COMP_CODEC("cq93vc-codec", "cq93vc-hifi")),
184 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-vcif")));
185#endif
186
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600187static struct snd_soc_dai_link dm365_evm_dai = {
Peter Ujfalusif2055e12018-12-17 14:21:34 +0200188#ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600189 .name = "TLV320AIC3X",
190 .stream_name = "AIC3X",
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200191 .init = evm_aic3x_init,
192 .ops = &evm_ops,
193 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
194 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900195 SND_SOC_DAILINK_REG(dm365),
Peter Ujfalusif2055e12018-12-17 14:21:34 +0200196#elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC)
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600197 .name = "Voice Codec - CQ93VC",
198 .stream_name = "CQ93",
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900199 SND_SOC_DAILINK_REG(dm365),
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600200#endif
201};
202
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900203SND_SOC_DAILINK_DEFS(dm6467_aic3x,
204 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")),
205 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.0-001a",
206 "tlv320aic3x-hifi")),
207 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0")));
208
209SND_SOC_DAILINK_DEFS(dm6467_spdif,
210 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")),
211 DAILINK_COMP_ARRAY(COMP_CODEC("spdif_dit", "dit-hifi")),
212 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1")));
213
Chaithrika U S04f80f52009-06-05 06:28:49 -0400214static struct snd_soc_dai_link dm6467_evm_dai[] = {
215 {
216 .name = "TLV320AIC3X",
217 .stream_name = "AIC3X",
Chaithrika U S04f80f52009-06-05 06:28:49 -0400218 .init = evm_aic3x_init,
219 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200220 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
221 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900222 SND_SOC_DAILINK_REG(dm6467_aic3x),
Chaithrika U S04f80f52009-06-05 06:28:49 -0400223 },
224 {
225 .name = "McASP",
226 .stream_name = "spdif",
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200227 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
228 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900229 SND_SOC_DAILINK_REG(dm6467_spdif),
Chaithrika U S04f80f52009-06-05 06:28:49 -0400230 },
231};
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530232
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900233SND_SOC_DAILINK_DEFS(da830,
234 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")),
235 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
236 "tlv320aic3x-hifi")),
237 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1")));
238
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530239static struct snd_soc_dai_link da830_evm_dai = {
240 .name = "TLV320AIC3X",
241 .stream_name = "AIC3X",
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530242 .init = evm_aic3x_init,
243 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200244 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
245 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900246 SND_SOC_DAILINK_REG(da830),
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530247};
248
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900249SND_SOC_DAILINK_DEFS(da850,
250 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")),
251 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
252 "tlv320aic3x-hifi")),
253 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0")));
254
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530255static struct snd_soc_dai_link da850_evm_dai = {
Chaithrika U S7ae59452009-08-07 10:07:51 -0400256 .name = "TLV320AIC3X",
257 .stream_name = "AIC3X",
Chaithrika U S7ae59452009-08-07 10:07:51 -0400258 .init = evm_aic3x_init,
259 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200260 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
261 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900262 SND_SOC_DAILINK_REG(da850),
Chaithrika U S7ae59452009-08-07 10:07:51 -0400263};
Chaithrika U S04f80f52009-06-05 06:28:49 -0400264
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000265/* davinci dm6446 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300266/*
267 * ASP0 in DM6446 EVM is clocked by U55, as configured by
268 * board-dm644x-evm.c using GPIOs from U18. There are six
269 * options; here we "know" we use a 48 KHz sample rate.
270 */
271static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
272 .sysclk = 12288000,
273};
274
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000275static struct snd_soc_card dm6446_snd_soc_card_evm = {
276 .name = "DaVinci DM6446 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800277 .owner = THIS_MODULE,
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000278 .dai_link = &dm6446_evm_dai,
279 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300280 .drvdata = &dm6446_snd_soc_card_drvdata,
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000281};
282
283/* davinci dm355 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300284/* ASP1 on DM355 EVM is clocked by an external oscillator */
285static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
286 .sysclk = 27000000,
287};
288
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000289static struct snd_soc_card dm355_snd_soc_card_evm = {
290 .name = "DaVinci DM355 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800291 .owner = THIS_MODULE,
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000292 .dai_link = &dm355_evm_dai,
Vladimir Barinov310355c2008-02-18 11:40:22 +0100293 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300294 .drvdata = &dm355_snd_soc_card_drvdata,
Vladimir Barinov310355c2008-02-18 11:40:22 +0100295};
296
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600297/* davinci dm365 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300298static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
299 .sysclk = 27000000,
300};
301
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600302static struct snd_soc_card dm365_snd_soc_card_evm = {
303 .name = "DaVinci DM365 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800304 .owner = THIS_MODULE,
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600305 .dai_link = &dm365_evm_dai,
306 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300307 .drvdata = &dm365_snd_soc_card_drvdata,
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600308};
309
Chaithrika U S04f80f52009-06-05 06:28:49 -0400310/* davinci dm6467 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300311static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
312 .sysclk = 27000000,
313};
314
Chaithrika U S04f80f52009-06-05 06:28:49 -0400315static struct snd_soc_card dm6467_snd_soc_card_evm = {
316 .name = "DaVinci DM6467 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800317 .owner = THIS_MODULE,
Chaithrika U S04f80f52009-06-05 06:28:49 -0400318 .dai_link = dm6467_evm_dai,
319 .num_links = ARRAY_SIZE(dm6467_evm_dai),
Jyri Sarhabcf25562013-09-17 12:26:00 +0300320 .drvdata = &dm6467_snd_soc_card_drvdata,
321};
322
323static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
324 .sysclk = 24576000,
Chaithrika U S04f80f52009-06-05 06:28:49 -0400325};
326
Chaithrika U S7ae59452009-08-07 10:07:51 -0400327static struct snd_soc_card da830_snd_soc_card = {
Chaithrika U S30230f42009-08-11 16:59:21 -0400328 .name = "DA830/OMAP-L137 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800329 .owner = THIS_MODULE,
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530330 .dai_link = &da830_evm_dai,
Chaithrika U S30230f42009-08-11 16:59:21 -0400331 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300332 .drvdata = &da830_snd_soc_card_drvdata,
333};
334
335static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
336 .sysclk = 24576000,
Chaithrika U S30230f42009-08-11 16:59:21 -0400337};
338
339static struct snd_soc_card da850_snd_soc_card = {
340 .name = "DA850/OMAP-L138 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800341 .owner = THIS_MODULE,
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530342 .dai_link = &da850_evm_dai,
Chaithrika U S7ae59452009-08-07 10:07:51 -0400343 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300344 .drvdata = &da850_snd_soc_card_drvdata,
Chaithrika U S7ae59452009-08-07 10:07:51 -0400345};
346
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300347#if defined(CONFIG_OF)
348
349/*
350 * The struct is used as place holder. It will be completely
351 * filled with data from dt node.
352 */
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900353SND_SOC_DAILINK_DEFS(evm,
354 DAILINK_COMP_ARRAY(COMP_EMPTY()),
Kuninori Morimoto44e57812019-06-28 10:49:18 +0900355 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi")),
356 DAILINK_COMP_ARRAY(COMP_EMPTY()));
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900357
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300358static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
359 .name = "TLV320AIC3X",
360 .stream_name = "AIC3X",
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300361 .ops = &evm_ops,
362 .init = evm_aic3x_init,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200363 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
364 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900365 SND_SOC_DAILINK_REG(evm),
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300366};
367
368static const struct of_device_id davinci_evm_dt_ids[] = {
369 {
370 .compatible = "ti,da830-evm-audio",
371 .data = (void *) &evm_dai_tlv320aic3x,
372 },
373 { /* sentinel */ }
374};
375MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
376
377/* davinci evm audio machine driver */
378static struct snd_soc_card evm_soc_card = {
379 .owner = THIS_MODULE,
380 .num_links = 1,
381};
382
383static int davinci_evm_probe(struct platform_device *pdev)
384{
385 struct device_node *np = pdev->dev.of_node;
Shailendra Verma3f81d9a2017-01-27 16:40:57 +0530386 const struct of_device_id *match;
387 struct snd_soc_dai_link *dai;
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300388 struct snd_soc_card_drvdata_davinci *drvdata = NULL;
Jyri Sarha5ad88652014-01-27 17:37:51 +0200389 struct clk *mclk;
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300390 int ret = 0;
391
Shailendra Verma3f81d9a2017-01-27 16:40:57 +0530392 match = of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
393 if (!match) {
394 dev_err(&pdev->dev, "Error: No device match found\n");
395 return -ENODEV;
396 }
397
398 dai = (struct snd_soc_dai_link *) match->data;
399
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300400 evm_soc_card.dai_link = dai;
401
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900402 dai->codecs->of_node = of_parse_phandle(np, "ti,audio-codec", 0);
403 if (!dai->codecs->of_node)
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300404 return -EINVAL;
405
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900406 dai->cpus->of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
407 if (!dai->cpus->of_node)
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300408 return -EINVAL;
409
Kuninori Morimoto44e57812019-06-28 10:49:18 +0900410 dai->platforms->of_node = dai->cpus->of_node;
411
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300412 evm_soc_card.dev = &pdev->dev;
413 ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
414 if (ret)
415 return ret;
416
Jyri Sarha5ad88652014-01-27 17:37:51 +0200417 mclk = devm_clk_get(&pdev->dev, "mclk");
418 if (PTR_ERR(mclk) == -EPROBE_DEFER) {
419 return -EPROBE_DEFER;
420 } else if (IS_ERR(mclk)) {
421 dev_dbg(&pdev->dev, "mclk not found.\n");
422 mclk = NULL;
423 }
424
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300425 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
426 if (!drvdata)
427 return -ENOMEM;
428
Jyri Sarha5ad88652014-01-27 17:37:51 +0200429 drvdata->mclk = mclk;
430
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300431 ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
Jyri Sarha5ad88652014-01-27 17:37:51 +0200432
433 if (ret < 0) {
434 if (!drvdata->mclk) {
435 dev_err(&pdev->dev,
436 "No clock or clock rate defined.\n");
437 return -EINVAL;
438 }
439 drvdata->sysclk = clk_get_rate(drvdata->mclk);
440 } else if (drvdata->mclk) {
441 unsigned int requestd_rate = drvdata->sysclk;
442 clk_set_rate(drvdata->mclk, drvdata->sysclk);
443 drvdata->sysclk = clk_get_rate(drvdata->mclk);
444 if (drvdata->sysclk != requestd_rate)
445 dev_warn(&pdev->dev,
446 "Could not get requested rate %u using %u.\n",
447 requestd_rate, drvdata->sysclk);
448 }
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300449
450 snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
451 ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
452
453 if (ret)
454 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
455
456 return ret;
457}
458
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300459static struct platform_driver davinci_evm_driver = {
460 .probe = davinci_evm_probe,
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300461 .driver = {
462 .name = "davinci_evm",
Peter Ujfalusifb6d2082014-01-30 15:21:31 +0200463 .pm = &snd_soc_pm_ops,
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300464 .of_match_table = of_match_ptr(davinci_evm_dt_ids),
465 },
466};
467#endif
468
Vladimir Barinov310355c2008-02-18 11:40:22 +0100469static struct platform_device *evm_snd_device;
470
471static int __init evm_init(void)
472{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000473 struct snd_soc_card *evm_snd_dev_data;
David Brownellf492ec92009-05-14 13:01:59 -0700474 int index;
Vladimir Barinov310355c2008-02-18 11:40:22 +0100475 int ret;
476
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300477 /*
478 * If dtb is there, the devices will be created dynamically.
479 * Only register platfrom driver structure.
480 */
481#if defined(CONFIG_OF)
482 if (of_have_populated_dt())
483 return platform_driver_register(&davinci_evm_driver);
484#endif
485
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600486 if (machine_is_davinci_evm()) {
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000487 evm_snd_dev_data = &dm6446_snd_soc_card_evm;
David Brownellf492ec92009-05-14 13:01:59 -0700488 index = 0;
489 } else if (machine_is_davinci_dm355_evm()) {
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000490 evm_snd_dev_data = &dm355_snd_soc_card_evm;
David Brownellf492ec92009-05-14 13:01:59 -0700491 index = 1;
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600492 } else if (machine_is_davinci_dm365_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000493 evm_snd_dev_data = &dm365_snd_soc_card_evm;
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600494 index = 0;
Chaithrika U S04f80f52009-06-05 06:28:49 -0400495 } else if (machine_is_davinci_dm6467_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000496 evm_snd_dev_data = &dm6467_snd_soc_card_evm;
Chaithrika U S04f80f52009-06-05 06:28:49 -0400497 index = 0;
Chaithrika U S7ae59452009-08-07 10:07:51 -0400498 } else if (machine_is_davinci_da830_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000499 evm_snd_dev_data = &da830_snd_soc_card;
Chaithrika U S7ae59452009-08-07 10:07:51 -0400500 index = 1;
Chaithrika U S30230f42009-08-11 16:59:21 -0400501 } else if (machine_is_davinci_da850_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000502 evm_snd_dev_data = &da850_snd_soc_card;
Chaithrika U S30230f42009-08-11 16:59:21 -0400503 index = 0;
David Brownellf492ec92009-05-14 13:01:59 -0700504 } else
505 return -EINVAL;
506
507 evm_snd_device = platform_device_alloc("soc-audio", index);
Vladimir Barinov310355c2008-02-18 11:40:22 +0100508 if (!evm_snd_device)
509 return -ENOMEM;
510
Chaithrika U S04f80f52009-06-05 06:28:49 -0400511 platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
Vladimir Barinov310355c2008-02-18 11:40:22 +0100512 ret = platform_device_add(evm_snd_device);
513 if (ret)
514 platform_device_put(evm_snd_device);
515
516 return ret;
517}
518
519static void __exit evm_exit(void)
520{
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300521#if defined(CONFIG_OF)
522 if (of_have_populated_dt()) {
523 platform_driver_unregister(&davinci_evm_driver);
524 return;
525 }
526#endif
527
Vladimir Barinov310355c2008-02-18 11:40:22 +0100528 platform_device_unregister(evm_snd_device);
529}
530
531module_init(evm_init);
532module_exit(evm_exit);
533
534MODULE_AUTHOR("Vladimir Barinov");
535MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
536MODULE_LICENSE("GPL");