[PATCH 4/9] ASoC: davinci-evm: HDMI audio support for TDA998x trough McASP I2S bus

From: Jyri Sarha
Date: Wed Aug 06 2014 - 09:49:43 EST


Add machine driver support for BeagleBone-Black HDMI audio. BBB has
NXP TDA998X HDMI transmitter connected to McASP port in I2S mode. The
44100 Hz sample-rate and it's multiples can not be accurately produced
on BBB. The only supported sample format is SNDRV_PCM_FORMAT_S32_LE.
The 8 least significant bits are ignored.

Signed-off-by: Jyri Sarha <jsarha@xxxxxx>
---
.../bindings/sound/davinci-evm-audio.txt | 4 +-
sound/soc/davinci/davinci-evm.c | 82 +++++++++++++++++++-
2 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
index 963e100..c137436 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

Required properties:
-- compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx
+- compatible : "ti,da830-evm-audio" : for DM365/DA8xx/OMAPL1x/AM33xx
+ "ti,am335x-beaglebone-black-audio" : for Beaglebone-black HDMI
+ audio
- 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
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index a50010e..9b98667 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -21,6 +21,7 @@
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
+#include <sound/pcm_params.h>

#include <asm/dma.h>
#include <asm/mach-types.h>
@@ -83,12 +84,46 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
return 0;
}

+/* If changing sample format the tda998x configuration (REG_CTS_N) needs
+ to be changed. */
+#define TDA998X_SAMPLE_FORMAT SNDRV_PCM_FORMAT_S32_LE
+static int evm_tda998x_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_mask *fmt = constrs_mask(&runtime->hw_constraints,
+ SNDRV_PCM_HW_PARAM_FORMAT);
+ snd_mask_none(fmt);
+ snd_mask_set(fmt, TDA998X_SAMPLE_FORMAT);
+
+ return evm_startup(substream);
+}
+
+static int evm_tda998x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_card *soc_card = rtd->card;
+ struct snd_soc_card_drvdata_davinci *drvdata =
+ snd_soc_card_get_drvdata(soc_card);
+
+ return snd_soc_dai_set_sysclk(cpu_dai, 0, drvdata->sysclk,
+ SND_SOC_CLOCK_IN);
+}
+
static struct snd_soc_ops evm_ops = {
.startup = evm_startup,
.shutdown = evm_shutdown,
.hw_params = evm_hw_params,
};

+
+static struct snd_soc_ops evm_tda998x_ops = {
+ .startup = evm_tda998x_startup,
+ .shutdown = evm_shutdown,
+ .hw_params = evm_tda998x_hw_params,
+};
+
/* davinci-evm machine dapm widgets */
static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -149,6 +184,35 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}

+static const struct snd_soc_dapm_widget tda998x_dapm_widgets[] = {
+ SND_SOC_DAPM_OUTPUT("HDMI Out"),
+};
+
+static int evm_tda998x_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dapm_context *dapm = &rtd->codec->dapm;
+ struct snd_soc_card *soc_card = rtd->card;
+ int ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, 1);
+ if (ret < 0)
+ return ret;
+
+ snd_soc_dapm_new_controls(dapm, tda998x_dapm_widgets,
+ ARRAY_SIZE(tda998x_dapm_widgets));
+
+ ret = snd_soc_of_parse_audio_routing(soc_card, "ti,audio-routing");
+
+ /* not connected */
+ snd_soc_dapm_disable_pin(dapm, "RX");
+
+ /* always connected */
+ snd_soc_dapm_enable_pin(dapm, "HDMI Out");
+
+ return 0;
+}
+
/* davinci-evm digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link dm6446_evm_dai = {
.name = "TLV320AIC3X",
@@ -334,7 +398,7 @@ static struct snd_soc_card da850_snd_soc_card = {
#if defined(CONFIG_OF)

/*
- * The struct is used as place holder. It will be completely
+ * The structs are used as place holders. They will be completely
* filled with data from dt node.
*/
static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
@@ -347,10 +411,24 @@ static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
SND_SOC_DAIFMT_IB_NF,
};

+static struct snd_soc_dai_link evm_dai_tda998x_hdmi = {
+ .name = "NXP TDA998x HDMI Chip",
+ .stream_name = "HDMI",
+ .codec_dai_name = "hdmi-hifi",
+ .ops = &evm_tda998x_ops,
+ .init = evm_tda998x_init,
+ .dai_fmt = (SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S |
+ 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,
+ .data = &evm_dai_tlv320aic3x,
+ },
+ {
+ .compatible = "ti,am335x-beaglebone-black-audio",
+ .data = &evm_dai_tda998x_hdmi,
},
{ /* sentinel */ }
};
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/