[alsa-devel] [PATCH] davinci-evm: extend it to support DM81xx and derivatives
Having worked closely with TI DM8148/DM8168 EVMs I came across many derivatives of these boards which didn't use the standard codec but had something like wm897x instead. They all would fit davinci-evm driver nicely if it had support for audio CPU clock divisor and slightly more generic naming. So this patch adds support for reading CPU divisor from a DT and slightly changes names of helper/init functions to be more generic.
It also adds support for DaVinci boards that use wm8978 codec.
Signed-off-by: Vitaly Wool vitaly.wool@konsulko.com --- .../bindings/sound/davinci-evm-audio.txt | 6 +- sound/soc/davinci/davinci-evm.c | 66 ++++++++++++++++++++-- 2 files changed, 65 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt index 963e100514c2..e76966a06f22 100644 --- a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt +++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt @@ -1,7 +1,9 @@ -* Texas Instruments SoC audio setups with TLV320AIC3X Codec +* Texas Instruments SoC audio setups with TLV320AIC3X/WM89XX codecs
Required properties: - compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx + "ti,dm8168-evm-audio" : for DM81xx with TLV320AIC3x + "ti,dm8168-evm-audio-wm8978" : for DM81xx with WM897x - ti,model : The user-visible name of this sound complex. - ti,audio-codec : The phandle of the TLV320AIC3x audio codec - ti,mcasp-controller : The phandle of the McASP controller @@ -14,6 +16,8 @@ Optional properties: - ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec. - clocks : Reference to the master clock - clock-names : The clock should be named "mclk" +- ti,cpu-clkdiv : CPU clock divisor (if codec and cpu are clocked at + different rates) - Either codec-clock-rate or the codec-clock reference has to be defined. If the both are defined the driver attempts to set referenced clock to the defined rate and takes the rate from the clock reference. diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 7a369e0f2093..aa8e11583a84 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -26,7 +26,8 @@
struct snd_soc_card_drvdata_davinci { struct clk *mclk; - unsigned sysclk; + unsigned int sysclk; + unsigned int clkdiv; };
static int evm_startup(struct snd_pcm_substream *substream) @@ -61,8 +62,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_card *soc_card = rtd->card; int ret = 0; - unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) - snd_soc_card_get_drvdata(soc_card))->sysclk; + unsigned int sysclk = ((struct snd_soc_card_drvdata_davinci *) + snd_soc_card_get_drvdata(soc_card))->sysclk; + unsigned int clkdiv = ((struct snd_soc_card_drvdata_davinci *) + snd_soc_card_get_drvdata(soc_card))->clkdiv; +
/* set the codec system clock */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, SND_SOC_CLOCK_OUT); @@ -74,6 +78,13 @@ static int evm_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret;
+ /* set the CPU system clock divisor */ + if (clkdiv) { + ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, clkdiv); + if (ret < 0) + return ret; + } + return 0; }
@@ -84,7 +95,7 @@ static struct snd_soc_ops evm_ops = { };
/* davinci-evm machine dapm widgets */ -static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { +static const struct snd_soc_dapm_widget evm_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL), @@ -121,8 +132,8 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) int ret;
/* Add davinci-evm specific widgets */ - snd_soc_dapm_new_controls(&card->dapm, aic3x_dapm_widgets, - ARRAY_SIZE(aic3x_dapm_widgets)); + snd_soc_dapm_new_controls(&card->dapm, evm_dapm_widgets, + ARRAY_SIZE(evm_dapm_widgets));
if (np) { ret = snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); @@ -142,6 +153,28 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) return 0; }
+/* Logic for a non-aic3x (e. g. wm89xx) connected to a davinci-evm */ +static int evm_simple_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct device_node *np = card->dev->of_node; + + /* Add davinci-evm specific widgets */ + snd_soc_dapm_new_controls(&card->dapm, evm_dapm_widgets, + ARRAY_SIZE(evm_dapm_widgets)); + + /* audio routing is optional here */ + if (np) + snd_soc_of_parse_audio_routing(card, "ti,audio-routing"); + + /* not connected */ + snd_soc_dapm_nc_pin(&card->dapm, "MONO_LOUT"); + snd_soc_dapm_nc_pin(&card->dapm, "HPLCOM"); + snd_soc_dapm_nc_pin(&card->dapm, "HPRCOM"); + + return 0; +} + /* davinci-evm digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link dm6446_evm_dai = { .name = "TLV320AIC3X", @@ -340,11 +373,29 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = { SND_SOC_DAIFMT_IB_NF, };
+static struct snd_soc_dai_link evm_dai_wm8978 = { + .name = "wm8978", + .stream_name = "wm8978", + .codec_dai_name = "wm8978-hifi", + .ops = &evm_ops, + .init = evm_simple_init, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM | + SND_SOC_DAIFMT_IB_NF, +}; + static const struct of_device_id davinci_evm_dt_ids[] = { { .compatible = "ti,da830-evm-audio", .data = (void *) &evm_dai_tlv320aic3x, }, + { + .compatible = "ti,dm8168-evm-audio", + .data = (void *) &evm_dai_tlv320aic3x, + }, + { + .compatible = "ti,dm8168-evm-audio-wm8978", + .data = (void *) &evm_dai_wm8978, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids); @@ -422,6 +473,9 @@ static int davinci_evm_probe(struct platform_device *pdev) requestd_rate, drvdata->sysclk); }
+ /* CPU clock divisor may need to be provided for e. g. wm897x */ + of_property_read_u32(np, "ti,cpu-clkdiv", &drvdata->clkdiv); + snd_soc_card_set_drvdata(&evm_soc_card, drvdata); ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
+ Peter & Jyri
Hi Vitaly,
On Wednesday 12 July 2017 04:13 PM, Vitaly Wool wrote:
Having worked closely with TI DM8148/DM8168 EVMs I came across many derivatives of these boards which didn't use the standard codec but had something like wm897x instead. They all would fit davinci-evm driver nicely if it had support for audio CPU clock divisor and slightly more generic naming. So this patch adds support for reading CPU divisor from a DT and slightly changes names of helper/init functions to be more generic.
It also adds support for DaVinci boards that use wm8978 codec.
Signed-off-by: Vitaly Wool vitaly.wool@konsulko.com
While there are some users of davinci-evm.c, I think a majority are using simple-audio-card instead. Curious on why you chose not to use that. It sounds like codec is not the bitclock and frame-sync master in your case. Did that end up creating issues ?
Thanks, Sekhar
On Thu, Jul 13, 2017 at 01:31:25PM +0530, Sekhar Nori wrote:
While there are some users of davinci-evm.c, I think a majority are using simple-audio-card instead. Curious on why you chose not to use that. It sounds like codec is not the bitclock and frame-sync master in your case. Did that end up creating issues ?
New systems should start using of-graph - that's a more flexible and extensible replacement for simple-card. But yes, if you can use one of the generic cards that's better.
Hi Mark,
2017-07-13 12:33 GMT+02:00 Mark Brown broonie@kernel.org:
On Thu, Jul 13, 2017 at 01:31:25PM +0530, Sekhar Nori wrote:
While there are some users of davinci-evm.c, I think a majority are using simple-audio-card instead. Curious on why you chose not to use that. It sounds like codec is not the bitclock and frame-sync master in your case. Did that end up creating issues ?
New systems should start using of-graph - that's a more flexible and extensible replacement for simple-card. But yes, if you can use one of the generic cards that's better.
Unfortunately I can't. In fact we have a few DM81xx devices which boot nicely using the existing kernel code and have most of the peripherals working fine, but sound is not working even though all the relevant drivers are in place. I believe that unless davinci-evm is deprecated, it is beneficial for everyone to have it supporting DM81xx (and I can take over its maintenance since the current maintainer has invalid e-mail specified in the header). I'll be working on of-graph version, too, but Rome wasn't built in a day, you know :)
Best regards, Vitaly
2017-07-13 10:01 GMT+02:00 Sekhar Nori nsekhar@ti.com:
- Peter & Jyri
<snip>
While there are some users of davinci-evm.c, I think a majority are using simple-audio-card instead. Curious on why you chose not to use that. It sounds like codec is not the bitclock and frame-sync master in your case. Did that end up creating issues ?
Well, one of the problems with simple-audio-card is that you can't snd_soc_dai_set_clkdiv() from it, neither you can set SND_SOC_CLK_OUT for a codec, so for some codecs this just doesn't fit.
Best regards, Vitaly
On Thu, Jul 13, 2017 at 07:26:43PM +0200, Vitaly Wool wrote:
2017-07-13 10:01 GMT+02:00 Sekhar Nori nsekhar@ti.com:
While there are some users of davinci-evm.c, I think a majority are using simple-audio-card instead. Curious on why you chose not to use that. It sounds like codec is not the bitclock and frame-sync master in your case. Did that end up creating issues ?
Well, one of the problems with simple-audio-card is that you can't snd_soc_dai_set_clkdiv() from it, neither you can set SND_SOC_CLK_OUT for a codec, so for some codecs this just doesn't fit.
That's no excuse, the CODEC drivers *really* shouldn't use _set_clkdiv() - fix the drivers to work normally.
Hi Mark,
2017-07-17 16:51 GMT+02:00 Mark Brown broonie@kernel.org:
On Thu, Jul 13, 2017 at 07:26:43PM +0200, Vitaly Wool wrote:
2017-07-13 10:01 GMT+02:00 Sekhar Nori nsekhar@ti.com:
While there are some users of davinci-evm.c, I think a majority are using simple-audio-card instead. Curious on why you chose not to use that. It sounds like codec is not the bitclock and frame-sync master in your case. Did that end up creating issues ?
Well, one of the problems with simple-audio-card is that you can't snd_soc_dai_set_clkdiv() from it, neither you can set SND_SOC_CLK_OUT for a codec, so for some codecs this just doesn't fit.
That's no excuse, the CODEC drivers *really* shouldn't use _set_clkdiv()
- fix the drivers to work normally.
Well that's not the only problem. CPU driver (davinci-mcasp) doesn't work well with simple-audio-card either.
There's no good way to set SND_SOC_CLK_OUT for it if the clock is fixed-rate. asoc_simple_card_init_dai() initializes clocks to SND_SOCK_CLK_IN, and the only way you can change it later is by calling asoc_simple_card_hw_params(). But that's not a real match either, since it won't work with a fixed-rate clock.
So basically I can see 2 ways out here: * extend davinci-evm driver to handle DM81xx (which is implemented in the patch I've sent before) * fix simple-card-utils so that it's possible to set SND_SOC_CLK_OUT in asoc_simple_card_init_dai().
I would personally go the first way but if you prefer the 2nd, I can pursue that track too.
Thanks in advance,
Best regards, Vitaly
participants (3)
-
Mark Brown
-
Sekhar Nori
-
Vitaly Wool