blob: 2cfbeebdfb41b6a6a1d1a77fe1aa7a577515022a [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{
31 struct snd_soc_pcm_runtime *rtd = substream->private_data;
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{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data;
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
49 if (drvdata->mclk)
50 clk_disable_unprepare(drvdata->mclk);
51}
52
Vladimir Barinov310355c2008-02-18 11:40:22 +010053static int evm_hw_params(struct snd_pcm_substream *substream,
54 struct snd_pcm_hw_params *params)
55{
56 struct snd_soc_pcm_runtime *rtd = substream->private_data;
Kuninori Morimoto2842b872020-03-23 14:21:14 +090057 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
58 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Lars-Peter Clausen2896b8b2014-05-19 11:41:47 +020059 struct snd_soc_card *soc_card = rtd->card;
Vladimir Barinov310355c2008-02-18 11:40:22 +010060 int ret = 0;
Jyri Sarhabcf25562013-09-17 12:26:00 +030061 unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
62 snd_soc_card_get_drvdata(soc_card))->sysclk;
Vladimir Barinov310355c2008-02-18 11:40:22 +010063
Vladimir Barinov310355c2008-02-18 11:40:22 +010064 /* set the codec system clock */
David Brownell05d5e992009-01-04 02:50:10 -080065 ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
Vladimir Barinov310355c2008-02-18 11:40:22 +010066 if (ret < 0)
67 return ret;
68
Daniel Mack5b66aa22012-10-04 15:08:41 +020069 /* set the CPU system clock */
70 ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
Peter Ujfalusi69f34052019-08-30 13:38:41 +030071 if (ret < 0 && ret != -ENOTSUPP)
Daniel Mack5b66aa22012-10-04 15:08:41 +020072 return ret;
73
Vladimir Barinov310355c2008-02-18 11:40:22 +010074 return 0;
75}
76
77static struct snd_soc_ops evm_ops = {
Jyri Sarha5ad88652014-01-27 17:37:51 +020078 .startup = evm_startup,
79 .shutdown = evm_shutdown,
Vladimir Barinov310355c2008-02-18 11:40:22 +010080 .hw_params = evm_hw_params,
81};
82
83/* davinci-evm machine dapm widgets */
84static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
85 SND_SOC_DAPM_HP("Headphone Jack", NULL),
86 SND_SOC_DAPM_LINE("Line Out", NULL),
87 SND_SOC_DAPM_MIC("Mic Jack", NULL),
88 SND_SOC_DAPM_LINE("Line In", NULL),
89};
90
91/* davinci-evm machine audio_mapnections to the codec pins */
Mark Brownacf497f2008-05-13 14:58:30 +020092static const struct snd_soc_dapm_route audio_map[] = {
Vladimir Barinov310355c2008-02-18 11:40:22 +010093 /* Headphone connected to HPLOUT, HPROUT */
94 {"Headphone Jack", NULL, "HPLOUT"},
95 {"Headphone Jack", NULL, "HPROUT"},
96
97 /* Line Out connected to LLOUT, RLOUT */
98 {"Line Out", NULL, "LLOUT"},
99 {"Line Out", NULL, "RLOUT"},
100
101 /* Mic connected to (MIC3L | MIC3R) */
Hebbar Gururajae2e8bfd2013-01-31 18:23:04 +0530102 {"MIC3L", NULL, "Mic Bias"},
103 {"MIC3R", NULL, "Mic Bias"},
104 {"Mic Bias", NULL, "Mic Jack"},
Vladimir Barinov310355c2008-02-18 11:40:22 +0100105
106 /* Line In connected to (LINE1L | LINE2L), (LINE1R | LINE2R) */
107 {"LINE1L", NULL, "Line In"},
108 {"LINE2L", NULL, "Line In"},
109 {"LINE1R", NULL, "Line In"},
110 {"LINE2R", NULL, "Line In"},
Vladimir Barinov310355c2008-02-18 11:40:22 +0100111};
112
113/* Logic for a aic3x as connected on a davinci-evm */
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000114static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
Vladimir Barinov310355c2008-02-18 11:40:22 +0100115{
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100116 struct snd_soc_card *card = rtd->card;
Lars-Peter Clausen2896b8b2014-05-19 11:41:47 +0200117 struct device_node *np = card->dev->of_node;
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300118 int ret;
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000119
Vladimir Barinov310355c2008-02-18 11:40:22 +0100120 /* Add davinci-evm specific widgets */
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100121 snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets,
Mark Brownacf497f2008-05-13 14:58:30 +0200122 ARRAY_SIZE(aic3x_dapm_widgets));
Vladimir Barinov310355c2008-02-18 11:40:22 +0100123
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300124 if (np) {
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100125 ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing");
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300126 if (ret)
127 return ret;
128 } else {
129 /* Set up davinci-evm specific audio path audio_map */
Lars-Peter Clausend343a662014-03-12 15:27:35 +0100130 snd_soc_dapm_add_routes(&card->dapm, audio_map,
131 ARRAY_SIZE(audio_map));
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300132 }
Vladimir Barinov310355c2008-02-18 11:40:22 +0100133
134 /* not connected */
Lars-Peter Clausenb213b442015-04-11 13:11:28 +0200135 snd_soc_dapm_nc_pin(&card->dapm, "MONO_LOUT");
136 snd_soc_dapm_nc_pin(&card->dapm, "HPLCOM");
137 snd_soc_dapm_nc_pin(&card->dapm, "HPRCOM");
Vladimir Barinov310355c2008-02-18 11:40:22 +0100138
Vladimir Barinov310355c2008-02-18 11:40:22 +0100139 return 0;
140}
141
142/* davinci-evm digital audio interface glue - connects codec <--> CPU */
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900143SND_SOC_DAILINK_DEFS(dm6446,
144 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")),
145 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b",
146 "tlv320aic3x-hifi")),
147 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp")));
148
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000149static struct snd_soc_dai_link dm6446_evm_dai = {
Vladimir Barinov310355c2008-02-18 11:40:22 +0100150 .name = "TLV320AIC3X",
151 .stream_name = "AIC3X",
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000152 .init = evm_aic3x_init,
153 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200154 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
155 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900156 SND_SOC_DAILINK_REG(dm6446),
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000157};
158
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900159SND_SOC_DAILINK_DEFS(dm355,
160 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp.1")),
161 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-001b",
162 "tlv320aic3x-hifi")),
163 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp.1")));
164
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000165static struct snd_soc_dai_link dm355_evm_dai = {
166 .name = "TLV320AIC3X",
167 .stream_name = "AIC3X",
Vladimir Barinov310355c2008-02-18 11:40:22 +0100168 .init = evm_aic3x_init,
169 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200170 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
171 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900172 SND_SOC_DAILINK_REG(dm355),
Vladimir Barinov310355c2008-02-18 11:40:22 +0100173};
174
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900175#ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC
176SND_SOC_DAILINK_DEFS(dm365,
177 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcbsp")),
178 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
179 "tlv320aic3x-hifi")),
180 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcbsp")));
181#elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC)
182SND_SOC_DAILINK_DEFS(dm365,
183 DAILINK_COMP_ARRAY(COMP_CPU("davinci-vcif")),
184 DAILINK_COMP_ARRAY(COMP_CODEC("cq93vc-codec", "cq93vc-hifi")),
185 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-vcif")));
186#endif
187
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600188static struct snd_soc_dai_link dm365_evm_dai = {
Peter Ujfalusif2055e12018-12-17 14:21:34 +0200189#ifdef CONFIG_SND_SOC_DM365_AIC3X_CODEC
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600190 .name = "TLV320AIC3X",
191 .stream_name = "AIC3X",
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200192 .init = evm_aic3x_init,
193 .ops = &evm_ops,
194 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
195 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900196 SND_SOC_DAILINK_REG(dm365),
Peter Ujfalusif2055e12018-12-17 14:21:34 +0200197#elif defined(CONFIG_SND_SOC_DM365_VOICE_CODEC)
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600198 .name = "Voice Codec - CQ93VC",
199 .stream_name = "CQ93",
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900200 SND_SOC_DAILINK_REG(dm365),
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600201#endif
202};
203
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900204SND_SOC_DAILINK_DEFS(dm6467_aic3x,
205 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")),
206 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.0-001a",
207 "tlv320aic3x-hifi")),
208 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0")));
209
210SND_SOC_DAILINK_DEFS(dm6467_spdif,
211 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")),
212 DAILINK_COMP_ARRAY(COMP_CODEC("spdif_dit", "dit-hifi")),
213 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1")));
214
Chaithrika U S04f80f52009-06-05 06:28:49 -0400215static struct snd_soc_dai_link dm6467_evm_dai[] = {
216 {
217 .name = "TLV320AIC3X",
218 .stream_name = "AIC3X",
Chaithrika U S04f80f52009-06-05 06:28:49 -0400219 .init = evm_aic3x_init,
220 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200221 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
222 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900223 SND_SOC_DAILINK_REG(dm6467_aic3x),
Chaithrika U S04f80f52009-06-05 06:28:49 -0400224 },
225 {
226 .name = "McASP",
227 .stream_name = "spdif",
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200228 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
229 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900230 SND_SOC_DAILINK_REG(dm6467_spdif),
Chaithrika U S04f80f52009-06-05 06:28:49 -0400231 },
232};
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530233
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900234SND_SOC_DAILINK_DEFS(da830,
235 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.1")),
236 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
237 "tlv320aic3x-hifi")),
238 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.1")));
239
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530240static struct snd_soc_dai_link da830_evm_dai = {
241 .name = "TLV320AIC3X",
242 .stream_name = "AIC3X",
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530243 .init = evm_aic3x_init,
244 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200245 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
246 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900247 SND_SOC_DAILINK_REG(da830),
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530248};
249
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900250SND_SOC_DAILINK_DEFS(da850,
251 DAILINK_COMP_ARRAY(COMP_CPU("davinci-mcasp.0")),
252 DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic3x-codec.1-0018",
253 "tlv320aic3x-hifi")),
254 DAILINK_COMP_ARRAY(COMP_PLATFORM("davinci-mcasp.0")));
255
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530256static struct snd_soc_dai_link da850_evm_dai = {
Chaithrika U S7ae59452009-08-07 10:07:51 -0400257 .name = "TLV320AIC3X",
258 .stream_name = "AIC3X",
Chaithrika U S7ae59452009-08-07 10:07:51 -0400259 .init = evm_aic3x_init,
260 .ops = &evm_ops,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200261 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
262 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900263 SND_SOC_DAILINK_REG(da850),
Chaithrika U S7ae59452009-08-07 10:07:51 -0400264};
Chaithrika U S04f80f52009-06-05 06:28:49 -0400265
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000266/* davinci dm6446 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300267/*
268 * ASP0 in DM6446 EVM is clocked by U55, as configured by
269 * board-dm644x-evm.c using GPIOs from U18. There are six
270 * options; here we "know" we use a 48 KHz sample rate.
271 */
272static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
273 .sysclk = 12288000,
274};
275
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000276static struct snd_soc_card dm6446_snd_soc_card_evm = {
277 .name = "DaVinci DM6446 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800278 .owner = THIS_MODULE,
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000279 .dai_link = &dm6446_evm_dai,
280 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300281 .drvdata = &dm6446_snd_soc_card_drvdata,
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000282};
283
284/* davinci dm355 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300285/* ASP1 on DM355 EVM is clocked by an external oscillator */
286static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
287 .sysclk = 27000000,
288};
289
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000290static struct snd_soc_card dm355_snd_soc_card_evm = {
291 .name = "DaVinci DM355 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800292 .owner = THIS_MODULE,
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000293 .dai_link = &dm355_evm_dai,
Vladimir Barinov310355c2008-02-18 11:40:22 +0100294 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300295 .drvdata = &dm355_snd_soc_card_drvdata,
Vladimir Barinov310355c2008-02-18 11:40:22 +0100296};
297
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600298/* davinci dm365 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300299static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
300 .sysclk = 27000000,
301};
302
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600303static struct snd_soc_card dm365_snd_soc_card_evm = {
304 .name = "DaVinci DM365 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800305 .owner = THIS_MODULE,
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600306 .dai_link = &dm365_evm_dai,
307 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300308 .drvdata = &dm365_snd_soc_card_drvdata,
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600309};
310
Chaithrika U S04f80f52009-06-05 06:28:49 -0400311/* davinci dm6467 evm audio machine driver */
Jyri Sarhabcf25562013-09-17 12:26:00 +0300312static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
313 .sysclk = 27000000,
314};
315
Chaithrika U S04f80f52009-06-05 06:28:49 -0400316static struct snd_soc_card dm6467_snd_soc_card_evm = {
317 .name = "DaVinci DM6467 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800318 .owner = THIS_MODULE,
Chaithrika U S04f80f52009-06-05 06:28:49 -0400319 .dai_link = dm6467_evm_dai,
320 .num_links = ARRAY_SIZE(dm6467_evm_dai),
Jyri Sarhabcf25562013-09-17 12:26:00 +0300321 .drvdata = &dm6467_snd_soc_card_drvdata,
322};
323
324static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
325 .sysclk = 24576000,
Chaithrika U S04f80f52009-06-05 06:28:49 -0400326};
327
Chaithrika U S7ae59452009-08-07 10:07:51 -0400328static struct snd_soc_card da830_snd_soc_card = {
Chaithrika U S30230f42009-08-11 16:59:21 -0400329 .name = "DA830/OMAP-L137 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800330 .owner = THIS_MODULE,
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530331 .dai_link = &da830_evm_dai,
Chaithrika U S30230f42009-08-11 16:59:21 -0400332 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300333 .drvdata = &da830_snd_soc_card_drvdata,
334};
335
336static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
337 .sysclk = 24576000,
Chaithrika U S30230f42009-08-11 16:59:21 -0400338};
339
340static struct snd_soc_card da850_snd_soc_card = {
341 .name = "DA850/OMAP-L138 EVM",
Axel Lin36a16d12011-12-22 21:19:42 +0800342 .owner = THIS_MODULE,
Vaibhav Bediaf9eb9dd2011-02-03 16:42:25 +0530343 .dai_link = &da850_evm_dai,
Chaithrika U S7ae59452009-08-07 10:07:51 -0400344 .num_links = 1,
Jyri Sarhabcf25562013-09-17 12:26:00 +0300345 .drvdata = &da850_snd_soc_card_drvdata,
Chaithrika U S7ae59452009-08-07 10:07:51 -0400346};
347
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300348#if defined(CONFIG_OF)
349
350/*
351 * The struct is used as place holder. It will be completely
352 * filled with data from dt node.
353 */
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900354SND_SOC_DAILINK_DEFS(evm,
355 DAILINK_COMP_ARRAY(COMP_EMPTY()),
Kuninori Morimoto44e57812019-06-28 10:49:18 +0900356 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "tlv320aic3x-hifi")),
357 DAILINK_COMP_ARRAY(COMP_EMPTY()));
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900358
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300359static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
360 .name = "TLV320AIC3X",
361 .stream_name = "AIC3X",
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300362 .ops = &evm_ops,
363 .init = evm_aic3x_init,
Peter Ujfalusid38970e2013-11-14 11:35:21 +0200364 .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM |
365 SND_SOC_DAIFMT_IB_NF,
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900366 SND_SOC_DAILINK_REG(evm),
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300367};
368
369static const struct of_device_id davinci_evm_dt_ids[] = {
370 {
371 .compatible = "ti,da830-evm-audio",
372 .data = (void *) &evm_dai_tlv320aic3x,
373 },
374 { /* sentinel */ }
375};
376MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
377
378/* davinci evm audio machine driver */
379static struct snd_soc_card evm_soc_card = {
380 .owner = THIS_MODULE,
381 .num_links = 1,
382};
383
384static int davinci_evm_probe(struct platform_device *pdev)
385{
386 struct device_node *np = pdev->dev.of_node;
Shailendra Verma3f81d9a2017-01-27 16:40:57 +0530387 const struct of_device_id *match;
388 struct snd_soc_dai_link *dai;
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300389 struct snd_soc_card_drvdata_davinci *drvdata = NULL;
Jyri Sarha5ad88652014-01-27 17:37:51 +0200390 struct clk *mclk;
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300391 int ret = 0;
392
Shailendra Verma3f81d9a2017-01-27 16:40:57 +0530393 match = of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
394 if (!match) {
395 dev_err(&pdev->dev, "Error: No device match found\n");
396 return -ENODEV;
397 }
398
399 dai = (struct snd_soc_dai_link *) match->data;
400
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300401 evm_soc_card.dai_link = dai;
402
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900403 dai->codecs->of_node = of_parse_phandle(np, "ti,audio-codec", 0);
404 if (!dai->codecs->of_node)
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300405 return -EINVAL;
406
Kuninori Morimotode3582fe2019-06-06 13:12:57 +0900407 dai->cpus->of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
408 if (!dai->cpus->of_node)
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300409 return -EINVAL;
410
Kuninori Morimoto44e57812019-06-28 10:49:18 +0900411 dai->platforms->of_node = dai->cpus->of_node;
412
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300413 evm_soc_card.dev = &pdev->dev;
414 ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
415 if (ret)
416 return ret;
417
Jyri Sarha5ad88652014-01-27 17:37:51 +0200418 mclk = devm_clk_get(&pdev->dev, "mclk");
419 if (PTR_ERR(mclk) == -EPROBE_DEFER) {
420 return -EPROBE_DEFER;
421 } else if (IS_ERR(mclk)) {
422 dev_dbg(&pdev->dev, "mclk not found.\n");
423 mclk = NULL;
424 }
425
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300426 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
427 if (!drvdata)
428 return -ENOMEM;
429
Jyri Sarha5ad88652014-01-27 17:37:51 +0200430 drvdata->mclk = mclk;
431
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300432 ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
Jyri Sarha5ad88652014-01-27 17:37:51 +0200433
434 if (ret < 0) {
435 if (!drvdata->mclk) {
436 dev_err(&pdev->dev,
437 "No clock or clock rate defined.\n");
438 return -EINVAL;
439 }
440 drvdata->sysclk = clk_get_rate(drvdata->mclk);
441 } else if (drvdata->mclk) {
442 unsigned int requestd_rate = drvdata->sysclk;
443 clk_set_rate(drvdata->mclk, drvdata->sysclk);
444 drvdata->sysclk = clk_get_rate(drvdata->mclk);
445 if (drvdata->sysclk != requestd_rate)
446 dev_warn(&pdev->dev,
447 "Could not get requested rate %u using %u.\n",
448 requestd_rate, drvdata->sysclk);
449 }
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300450
451 snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
452 ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
453
454 if (ret)
455 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
456
457 return ret;
458}
459
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300460static struct platform_driver davinci_evm_driver = {
461 .probe = davinci_evm_probe,
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300462 .driver = {
463 .name = "davinci_evm",
Peter Ujfalusifb6d2082014-01-30 15:21:31 +0200464 .pm = &snd_soc_pm_ops,
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300465 .of_match_table = of_match_ptr(davinci_evm_dt_ids),
466 },
467};
468#endif
469
Vladimir Barinov310355c2008-02-18 11:40:22 +0100470static struct platform_device *evm_snd_device;
471
472static int __init evm_init(void)
473{
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000474 struct snd_soc_card *evm_snd_dev_data;
David Brownellf492ec92009-05-14 13:01:59 -0700475 int index;
Vladimir Barinov310355c2008-02-18 11:40:22 +0100476 int ret;
477
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300478 /*
479 * If dtb is there, the devices will be created dynamically.
480 * Only register platfrom driver structure.
481 */
482#if defined(CONFIG_OF)
483 if (of_have_populated_dt())
484 return platform_driver_register(&davinci_evm_driver);
485#endif
486
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600487 if (machine_is_davinci_evm()) {
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000488 evm_snd_dev_data = &dm6446_snd_soc_card_evm;
David Brownellf492ec92009-05-14 13:01:59 -0700489 index = 0;
490 } else if (machine_is_davinci_dm355_evm()) {
Chris Paulson-Ellisbedad0c2010-11-16 12:27:09 +0000491 evm_snd_dev_data = &dm355_snd_soc_card_evm;
David Brownellf492ec92009-05-14 13:01:59 -0700492 index = 1;
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600493 } else if (machine_is_davinci_dm365_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000494 evm_snd_dev_data = &dm365_snd_soc_card_evm;
Miguel Aguilaraa9b88e2010-03-11 09:33:40 -0600495 index = 0;
Chaithrika U S04f80f52009-06-05 06:28:49 -0400496 } else if (machine_is_davinci_dm6467_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000497 evm_snd_dev_data = &dm6467_snd_soc_card_evm;
Chaithrika U S04f80f52009-06-05 06:28:49 -0400498 index = 0;
Chaithrika U S7ae59452009-08-07 10:07:51 -0400499 } else if (machine_is_davinci_da830_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000500 evm_snd_dev_data = &da830_snd_soc_card;
Chaithrika U S7ae59452009-08-07 10:07:51 -0400501 index = 1;
Chaithrika U S30230f42009-08-11 16:59:21 -0400502 } else if (machine_is_davinci_da850_evm()) {
Liam Girdwoodf0fba2a2010-03-17 20:15:21 +0000503 evm_snd_dev_data = &da850_snd_soc_card;
Chaithrika U S30230f42009-08-11 16:59:21 -0400504 index = 0;
David Brownellf492ec92009-05-14 13:01:59 -0700505 } else
506 return -EINVAL;
507
508 evm_snd_device = platform_device_alloc("soc-audio", index);
Vladimir Barinov310355c2008-02-18 11:40:22 +0100509 if (!evm_snd_device)
510 return -ENOMEM;
511
Chaithrika U S04f80f52009-06-05 06:28:49 -0400512 platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
Vladimir Barinov310355c2008-02-18 11:40:22 +0100513 ret = platform_device_add(evm_snd_device);
514 if (ret)
515 platform_device_put(evm_snd_device);
516
517 return ret;
518}
519
520static void __exit evm_exit(void)
521{
Hebbar, Gururajaee2f6152013-10-23 15:30:14 +0300522#if defined(CONFIG_OF)
523 if (of_have_populated_dt()) {
524 platform_driver_unregister(&davinci_evm_driver);
525 return;
526 }
527#endif
528
Vladimir Barinov310355c2008-02-18 11:40:22 +0100529 platform_device_unregister(evm_snd_device);
530}
531
532module_init(evm_init);
533module_exit(evm_exit);
534
535MODULE_AUTHOR("Vladimir Barinov");
536MODULE_DESCRIPTION("TI DAVINCI EVM ASoC driver");
537MODULE_LICENSE("GPL");