alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec
@ 2015-05-26 18:59 Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 1/7] ASoC: core: If component doesn't have of_node use parent's node instead Jyri Sarha
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: peter.ujfalusi, moinejf, broonie, Jyri Sarha, liam.r.girdwood,
	tomi.valkeinen, rmk+kernel

Only the first three patches are meant for serious review.

The ASoC part should be ready for review in other respects but the
EDID SADs handling is waiting for Russell King's DRM ELD helper
patches. There is a copy-pasted not-to-be-merged patch with the same
functionality in the patch series.

The tda998x part is not complete and I do not think Jean-Francois'
binding are ready as such either. At least the usage of reg property in
a port node for something that is not an address or even guaranteed to
be unique is not a good idea. Some documentation of how to configure
AP0-AP4 pins (REG_ENA_AP?) would help in making a proper binding for
the tda998x audio configuration.

These patches, my tilcdc refactoring[1], and my latest BCLK fixes for
davinci-mcasp driver [2], can be found in a branch that produces
working HDMI audio on Beaglebone-Black here:

https://github.com/jsarha/linux.git linux-master-bbb-hdmi-20150512

[1] http://lists.freedesktop.org/archives/dri-devel/2015-May/082537.html
[2] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-April/090974.html

Jean-Francois Moine (1):
  drm/i2c: tda998x: Add support of a DT graph of ports DO NOT MERGE

Jyri Sarha (6):
  ASoC: core: If component doesn't have of_node use parent's node
    instead
  ASoC: hdmi: Remove obsolete dummy HDMI codec
  ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  ASoC: hdmi-codec: Add ELD based audio pcm rules DO NOT MERGE
  drm/i2c: tda998x: Register ASoC HDMI codec for audio functionality DO
    NOT MERGE
  ARM: dts: am335x-boneblack: Add HDMI audio support DO NOT MERGE

 .../devicetree/bindings/drm/i2c/tda998x.txt        |  51 ++
 arch/arm/boot/dts/am335x-boneblack.dts             |  78 ++-
 drivers/gpu/drm/i2c/Kconfig                        |   1 +
 drivers/gpu/drm/i2c/tda998x_drv.c                  | 328 +++++++++++-
 include/sound/hdmi-codec.h                         |  99 ++++
 include/sound/tda998x.h                            |   8 +
 sound/soc/codecs/Kconfig                           |   2 +-
 sound/soc/codecs/Makefile                          |   4 +-
 sound/soc/codecs/hdmi-codec.c                      | 560 +++++++++++++++++++++
 sound/soc/codecs/hdmi.c                            | 109 ----
 sound/soc/soc-core.c                               |  14 +-
 11 files changed, 1129 insertions(+), 125 deletions(-)
 create mode 100644 include/sound/hdmi-codec.h
 create mode 100644 include/sound/tda998x.h
 create mode 100644 sound/soc/codecs/hdmi-codec.c
 delete mode 100644 sound/soc/codecs/hdmi.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH RFC v2 1/7] ASoC: core: If component doesn't have of_node use parent's node instead
  2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
@ 2015-05-26 18:59 ` Jyri Sarha
  2015-06-02 20:09   ` Mark Brown
  2015-05-26 18:59 ` [PATCH RFC v2 2/7] ASoC: hdmi: Remove obsolete dummy HDMI codec Jyri Sarha
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: broonie, liam.r.girdwood, peter.ujfalusi, tomi.valkeinen,
	moinejf, rmk+kernel, Jyri Sarha

If an ASoC component device does not have a device tree node, use its
parent's node instead, when looking for a matching DAI based on a
device tree reference.

This allows video device drivers to register a separate child device
for their ASoC side audio functionality.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 sound/soc/soc-core.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2373252..b1bcff2 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -904,12 +904,17 @@ static struct snd_soc_dai *snd_soc_find_dai(
 {
 	struct snd_soc_component *component;
 	struct snd_soc_dai *dai;
+	struct device_node *component_of_node;
 
 	lockdep_assert_held(&client_mutex);
 
 	/* Find CPU DAI from registered DAIs*/
 	list_for_each_entry(component, &component_list, list) {
-		if (dlc->of_node && component->dev->of_node != dlc->of_node)
+		component_of_node = component->dev->of_node;
+		if (!component_of_node && component->dev->parent)
+			component_of_node = component->dev->parent->of_node;
+
+		if (dlc->of_node && component_of_node != dlc->of_node)
 			continue;
 		if (dlc->name && strcmp(component->name, dlc->name))
 			continue;
@@ -3488,11 +3493,16 @@ static int snd_soc_get_dai_name(struct of_phandle_args *args,
 				const char **dai_name)
 {
 	struct snd_soc_component *pos;
+	struct device_node *component_of_node;
 	int ret = -EPROBE_DEFER;
 
 	mutex_lock(&client_mutex);
 	list_for_each_entry(pos, &component_list, list) {
-		if (pos->dev->of_node != args->np)
+		component_of_node = pos->dev->of_node;
+		if (!component_of_node && pos->dev->parent)
+			component_of_node = pos->dev->parent->of_node;
+
+		if (component_of_node != args->np)
 			continue;
 
 		if (pos->driver->of_xlate_dai_name) {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH RFC v2 2/7] ASoC: hdmi: Remove obsolete dummy HDMI codec
  2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 1/7] ASoC: core: If component doesn't have of_node use parent's node instead Jyri Sarha
@ 2015-05-26 18:59 ` Jyri Sarha
  2015-06-02 20:10   ` Mark Brown
  2015-09-20  0:13   ` Applied "ASoC: hdmi: Remove obsolete dummy HDMI codec" to the asoc tree Mark Brown
  2015-05-26 18:59 ` [PATCH RFC v2 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: peter.ujfalusi, broonie, Jyri Sarha, liam.r.girdwood,
	tomi.valkeinen, rmk+kernel

The hdmi stub codec has not been used since refactoring of OMAP HDMI
audio support.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 sound/soc/codecs/Kconfig  |   4 --
 sound/soc/codecs/Makefile |   2 -
 sound/soc/codecs/hdmi.c   | 109 ----------------------------------------------
 3 files changed, 115 deletions(-)
 delete mode 100644 sound/soc/codecs/hdmi.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 061c465..fb7f978 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -76,7 +76,6 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_MC13783 if MFD_MC13XXX
 	select SND_SOC_ML26124 if I2C
-	select SND_SOC_HDMI_CODEC
 	select SND_SOC_PCM1681 if I2C
 	select SND_SOC_PCM1792A if SPI_MASTER
 	select SND_SOC_PCM3008
@@ -430,9 +429,6 @@ config SND_SOC_BT_SCO
 config SND_SOC_DMIC
 	tristate
 
-config SND_SOC_HDMI_CODEC
-       tristate "HDMI stub CODEC"
-
 config SND_SOC_ES8328
 	tristate "Everest Semi ES8328 CODEC"
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index abe2d7e..4e5d17c 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -69,7 +69,6 @@ snd-soc-max98925-objs := max98925.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
-snd-soc-hdmi-codec-objs := hdmi.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm1792a-codec-objs := pcm1792a.o
 snd-soc-pcm3008-objs := pcm3008.o
@@ -254,7 +253,6 @@ obj-$(CONFIG_SND_SOC_MAX98925)	+= snd-soc-max98925.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
-obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
 obj-$(CONFIG_SND_SOC_PCM1681)	+= snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM1792A)	+= snd-soc-pcm1792a-codec.o
 obj-$(CONFIG_SND_SOC_PCM3008)	+= snd-soc-pcm3008.o
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c
deleted file mode 100644
index bd42ad3..0000000
--- a/sound/soc/codecs/hdmi.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * ALSA SoC codec driver for HDMI audio codecs.
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Ricardo Neri <ricardo.neri@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-#include <linux/module.h>
-#include <sound/soc.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#define DRV_NAME "hdmi-audio-codec"
-
-static const struct snd_soc_dapm_widget hdmi_widgets[] = {
-	SND_SOC_DAPM_INPUT("RX"),
-	SND_SOC_DAPM_OUTPUT("TX"),
-};
-
-static const struct snd_soc_dapm_route hdmi_routes[] = {
-	{ "Capture", NULL, "RX" },
-	{ "TX", NULL, "Playback" },
-};
-
-static struct snd_soc_dai_driver hdmi_codec_dai = {
-	.name = "hdmi-hifi",
-	.playback = {
-		.stream_name = "Playback",
-		.channels_min = 2,
-		.channels_max = 8,
-		.rates = SNDRV_PCM_RATE_32000 |
-			SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE |
-			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
-		.sig_bits = 24,
-	},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 2,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_32000 |
-			SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE |
-			SNDRV_PCM_FMTBIT_S24_LE,
-	},
-
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id hdmi_audio_codec_ids[] = {
-	{ .compatible = "linux,hdmi-audio", },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, hdmi_audio_codec_ids);
-#endif
-
-static struct snd_soc_codec_driver hdmi_codec = {
-	.dapm_widgets = hdmi_widgets,
-	.num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
-	.dapm_routes = hdmi_routes,
-	.num_dapm_routes = ARRAY_SIZE(hdmi_routes),
-	.ignore_pmdown_time = true,
-};
-
-static int hdmi_codec_probe(struct platform_device *pdev)
-{
-	return snd_soc_register_codec(&pdev->dev, &hdmi_codec,
-			&hdmi_codec_dai, 1);
-}
-
-static int hdmi_codec_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_codec(&pdev->dev);
-	return 0;
-}
-
-static struct platform_driver hdmi_codec_driver = {
-	.driver		= {
-		.name	= DRV_NAME,
-		.of_match_table = of_match_ptr(hdmi_audio_codec_ids),
-	},
-
-	.probe		= hdmi_codec_probe,
-	.remove		= hdmi_codec_remove,
-};
-
-module_platform_driver(hdmi_codec_driver);
-
-MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
-MODULE_DESCRIPTION("ASoC generic HDMI codec driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH RFC v2 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 1/7] ASoC: core: If component doesn't have of_node use parent's node instead Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 2/7] ASoC: hdmi: Remove obsolete dummy HDMI codec Jyri Sarha
@ 2015-05-26 18:59 ` Jyri Sarha
  2015-08-14 19:25   ` Mark Brown
  2015-05-26 18:59 ` [PATCH RFC v2 4/7] ASoC: hdmi-codec: Add ELD based audio pcm rules DO NOT MERGE Jyri Sarha
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: broonie, liam.r.girdwood, peter.ujfalusi, tomi.valkeinen,
	moinejf, rmk+kernel, Jyri Sarha

The hdmi-codec is a platform device driver to be registered from
drivers of external HDMI encoders with I2S and/or spdif interface. The
driver in turn registers an ASoC codec for the encoder's audio
functionality.

The structures and definitions in the API header are mostly redundant
copies of similar structures in ASoC headers. This is on purpose to
avoid direct dependencies to ASoC structures in video side driver.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 include/sound/hdmi-codec.h    |  99 +++++++++
 sound/soc/codecs/Kconfig      |   4 +
 sound/soc/codecs/Makefile     |   2 +
 sound/soc/codecs/hdmi-codec.c | 458 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 563 insertions(+)
 create mode 100644 include/sound/hdmi-codec.h
 create mode 100644 sound/soc/codecs/hdmi-codec.c

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
new file mode 100644
index 0000000..0632bcb
--- /dev/null
+++ b/include/sound/hdmi-codec.h
@@ -0,0 +1,99 @@
+/*
+ * hdmi-codec.h - HDMI Codec driver API
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Jyri Sarha <jsarha@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __HDMI_CODEC_H__
+#define __HDMI_CODEC_H__
+
+#include <linux/hdmi.h>
+#include <drm/drm_edid.h>
+#include <sound/asoundef.h>
+#include <uapi/sound/asound.h>
+
+/*
+ * Protocol between ASoC cpu-dai and HDMI-encoder
+ */
+struct hdmi_codec_daifmt {
+	enum {
+		HDMI_I2S,
+		HDMI_RIGHT_J,
+		HDMI_LEFT_J,
+		HDMI_DSP_A,
+		HDMI_DSP_B,
+		HDMI_AC97,
+		HDMI_SPDIF,
+	} fmt;
+	int bit_clk_inv:1;
+	int frame_clk_inv:1;
+	int bit_clk_master:1;
+	int frame_clk_master:1;
+};
+
+/*
+ * HDMI audio parameters
+ */
+struct hdmi_codec_params {
+	struct hdmi_audio_infoframe cea;
+	struct snd_aes_iec958 iec;
+	int sample_rate;
+	int sample_width;
+	int channels;
+};
+
+struct hdmi_codec_ops {
+	/* For runtime clock configuration from ASoC machine driver.
+	 * A direct forward from set_sysclk in struct snd_soc_dai_ops.
+	 * Optional */
+	int (*set_clk)(struct device *dev, int clk_id, int freq);
+
+	/* Called when ASoC starts an audio stream setup. The call
+	 * provides an audio abort callback for stoping an ongoing
+	 * stream if the HDMI audio becomes unavailable.
+	 * Optional */
+	int (*audio_startup)(struct device *dev,
+			     void (*abort_cb)(struct device *dev));
+
+	/* Configures HDMI-encoder for audio stream.
+	 * Mandatory */
+	int (*hw_params)(struct device *dev,
+			 struct hdmi_codec_daifmt *fmt,
+			 struct hdmi_codec_params *hparms);
+
+	/* Shuts down the audio stream.
+	 * Mandatory */
+	void (*audio_shutdown)(struct device *dev);
+
+	/* Mute/unmute HDMI audio stream.
+	 * Optional */
+	int (*digital_mute)(struct device *dev, bool enable);
+
+	/* Provides EDID-Like-Data from connected HDMI device.
+	 * Optional */
+	uint8_t *(*get_eld)(struct device *dev);
+};
+
+/* HDMI codec initalization data */
+struct hdmi_codec_pdata {
+	struct device *dev; /* The HDMI encoder registering the codec */
+	const struct hdmi_codec_ops *ops;
+	uint i2s:1;
+	uint spdif:1;
+	int max_i2s_channels;
+};
+
+#define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
+
+#endif /* __HDMI_CODEC_H__ */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index fb7f978..ef9646f 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -76,6 +76,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_MC13783 if MFD_MC13XXX
 	select SND_SOC_ML26124 if I2C
+	select SND_SOC_HDMI_CODEC
 	select SND_SOC_PCM1681 if I2C
 	select SND_SOC_PCM1792A if SPI_MASTER
 	select SND_SOC_PCM3008
@@ -429,6 +430,9 @@ config SND_SOC_BT_SCO
 config SND_SOC_DMIC
 	tristate
 
+config SND_SOC_HDMI_CODEC
+       tristate
+
 config SND_SOC_ES8328
 	tristate "Everest Semi ES8328 CODEC"
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4e5d17c..a128c2b 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -69,6 +69,7 @@ snd-soc-max98925-objs := max98925.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
+snd-soc-hdmi-codec-objs := hdmi-codec.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm1792a-codec-objs := pcm1792a.o
 snd-soc-pcm3008-objs := pcm3008.o
@@ -253,6 +254,7 @@ obj-$(CONFIG_SND_SOC_MAX98925)	+= snd-soc-max98925.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
+obj-$(CONFIG_SND_SOC_HDMI_CODEC)	+= snd-soc-hdmi-codec.o
 obj-$(CONFIG_SND_SOC_PCM1681)	+= snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM1792A)	+= snd-soc-pcm1792a-codec.o
 obj-$(CONFIG_SND_SOC_PCM3008)	+= snd-soc-pcm3008.o
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
new file mode 100644
index 0000000..c208cef
--- /dev/null
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -0,0 +1,458 @@
+/*
+ * ALSA SoC codec for HDMI encoder drivers
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Jyri Sarha <jsarha@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/string.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/hdmi-codec.h>
+
+struct hdmi_codec_priv {
+	struct hdmi_codec_pdata hcd;
+	struct snd_soc_dai_driver *daidrv;
+	struct hdmi_codec_daifmt daifmt[2];
+	struct mutex current_stream_lock;
+	struct snd_pcm_substream *current_stream;
+	struct snd_pcm_hw_constraint_list ratec;
+	uint8_t *eld;
+};
+
+static const struct snd_soc_dapm_widget hdmi_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("TX"),
+};
+
+static const struct snd_soc_dapm_route hdmi_routes[] = {
+	{ "TX", NULL, "Playback" },
+};
+
+enum {
+	DAI_ID_I2C = 0,
+	DAI_ID_SPDIF,
+};
+
+static void hdmi_codec_abort(struct device *dev)
+{
+	struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	mutex_lock(&hcp->current_stream_lock);
+	if (hcp->current_stream && hcp->current_stream->runtime &&
+	    snd_pcm_running(hcp->current_stream)) {
+		dev_info(dev, "HDMI audio playback aborted\n");
+		snd_pcm_stream_lock_irq(hcp->current_stream);
+		snd_pcm_stop(hcp->current_stream, SNDRV_PCM_STATE_DISCONNECTED);
+		snd_pcm_stream_unlock_irq(hcp->current_stream);
+	}
+	mutex_unlock(&hcp->current_stream_lock);
+}
+
+static int hdmi_codec_new_stream(struct snd_pcm_substream *substream,
+				 struct snd_soc_dai *dai)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+	int ret = 0;
+
+	mutex_lock(&hcp->current_stream_lock);
+	if (!hcp->current_stream) {
+		hcp->current_stream = substream;
+	} else if (hcp->current_stream != substream) {
+		dev_err(dai->dev, "Only one simultaneous stream supported!\n");
+		ret = -EINVAL;
+	}
+	mutex_unlock(&hcp->current_stream_lock);
+
+	return ret;
+}
+
+static int hdmi_codec_startup(struct snd_pcm_substream *substream,
+			      struct snd_soc_dai *dai)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+	int ret = 0;
+
+	dev_dbg(dai->dev, "%s()\n", __func__);
+
+	ret = hdmi_codec_new_stream(substream, dai);
+	if (ret)
+		return ret;
+
+	if (hcp->hcd.ops->audio_startup) {
+		ret = hcp->hcd.ops->audio_startup(hcp->hcd.dev,
+						  hdmi_codec_abort);
+		if (ret) {
+			mutex_lock(&hcp->current_stream_lock);
+			hcp->current_stream = NULL;
+			mutex_unlock(&hcp->current_stream_lock);
+			return ret;
+		}
+	}
+
+	if (hcp->hcd.ops->get_eld) {
+		hcp->eld = hcp->hcd.ops->get_eld(hcp->hcd.dev);
+
+		/* Call snd_pcm_hw_constraint_eld here */
+	}
+	return 0;
+}
+
+static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
+				struct snd_soc_dai *dai)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+
+	dev_dbg(dai->dev, "%s()\n", __func__);
+
+	mutex_lock(&hcp->current_stream_lock);
+	BUG_ON(hcp->current_stream != substream);
+	hcp->current_stream = NULL;
+	mutex_unlock(&hcp->current_stream_lock);
+
+	hcp->hcd.ops->audio_shutdown(hcp->hcd.dev);
+}
+
+static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+	struct hdmi_codec_params hp = {
+		.cea = { 0 },
+		.iec = {
+			.status = {
+				IEC958_AES0_CON_NOT_COPYRIGHT,
+				IEC958_AES1_CON_GENERAL,
+				IEC958_AES2_CON_SOURCE_UNSPEC,
+				IEC958_AES3_CON_CLOCK_VARIABLE,
+			},
+			.subcode = { 0 },
+			.pad = 0,
+			.dig_subframe = { 0 },
+		}
+	};
+	int ret;
+
+	dev_dbg(dai->dev, "%s()\n", __func__);
+
+	ret = hdmi_codec_new_stream(substream, dai);
+	if (ret)
+		return ret;
+
+	hdmi_audio_infoframe_init(&hp.cea);
+	hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_PCM;
+	hp.cea.channels = params_channels(params);
+
+	switch (params_width(params)) {
+	case 16:
+		hp.iec.status[4] |= IEC958_AES4_CON_WORDLEN_20_16;
+		hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_16;
+		break;
+	case 18:
+		hp.iec.status[4] |= IEC958_AES4_CON_WORDLEN_22_18;
+		hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_20;
+		break;
+	case 20:
+		hp.iec.status[4] |= IEC958_AES4_CON_WORDLEN_24_20;
+		hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_20;
+		break;
+	case 24:
+	case 32:
+		hp.iec.status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24 |
+			IEC958_AES4_CON_WORDLEN_24_20;
+		hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_24;
+		break;
+	default:
+		dev_err(dai->dev, "sample width not supported!\n");
+		return -EINVAL;
+	}
+
+	switch (params_rate(params)) {
+	case 32000:
+		hp.iec.status[3] |= IEC958_AES3_CON_FS_32000;
+		hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_32000;
+		break;
+	case 44100:
+		hp.iec.status[3] |= IEC958_AES3_CON_FS_44100;
+		hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_44100;
+		break;
+	case 48000:
+		hp.iec.status[3] |= IEC958_AES3_CON_FS_48000;
+		hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
+		break;
+	case 88200:
+		hp.iec.status[3] |= IEC958_AES3_CON_FS_88200;
+		hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_88200;
+		break;
+	case 96000:
+		hp.iec.status[3] |= IEC958_AES3_CON_FS_96000;
+		hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_96000;
+		break;
+	case 176400:
+		hp.iec.status[3] |= IEC958_AES3_CON_FS_176400;
+		hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_176400;
+		break;
+	case 192000:
+		hp.iec.status[3] |= IEC958_AES3_CON_FS_192000;
+		hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_192000;
+		break;
+	default:
+		dev_err(dai->dev, "rate not supported!\n");
+		return -EINVAL;
+	}
+	hp.sample_width = params_width(params);
+	hp.sample_rate = params_rate(params);
+	hp.channels = params_channels(params);
+
+	return hcp->hcd.ops->hw_params(hcp->hcd.dev, &hcp->daifmt[dai->id],
+				       &hp);
+}
+
+static int hdmi_codec_set_sysclk(struct snd_soc_dai *dai,
+				 int clk_id, unsigned int freq, int dir)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+
+	dev_dbg(dai->dev, "%s()\n", __func__);
+
+	if (hcp->hcd.ops->set_clk)
+		return hcp->hcd.ops->set_clk(hcp->hcd.dev, clk_id, freq);
+
+	return 0;
+}
+
+static int hdmi_codec_set_fmt(struct snd_soc_dai *dai,
+			      unsigned int fmt)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+	struct hdmi_codec_daifmt cf = { 0 };
+	int ret = 0;
+
+	dev_dbg(dai->dev, "%s()\n", __func__);
+
+	if (dai->id == DAI_ID_SPDIF) {
+		cf.fmt = HDMI_SPDIF;
+	} else {
+		switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+		case SND_SOC_DAIFMT_CBM_CFM:
+			cf.bit_clk_master = 1;
+			cf.frame_clk_master = 1;
+			break;
+		case SND_SOC_DAIFMT_CBS_CFM:
+			cf.frame_clk_master = 1;
+			break;
+		case SND_SOC_DAIFMT_CBM_CFS:
+			cf.bit_clk_master = 1;
+			break;
+		case SND_SOC_DAIFMT_CBS_CFS:
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			break;
+		case SND_SOC_DAIFMT_NB_IF:
+			cf.frame_clk_inv = 1;
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			cf.bit_clk_inv = 1;
+			break;
+		case SND_SOC_DAIFMT_IB_IF:
+			cf.frame_clk_inv = 1;
+			cf.bit_clk_inv = 1;
+			break;
+		}
+
+		switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+		case SND_SOC_DAIFMT_I2S:
+			cf.fmt = HDMI_I2S;
+			break;
+		case SND_SOC_DAIFMT_DSP_A:
+			cf.fmt = HDMI_DSP_A;
+			break;
+		case SND_SOC_DAIFMT_DSP_B:
+			cf.fmt = HDMI_DSP_B;
+			break;
+		case SND_SOC_DAIFMT_RIGHT_J:
+			cf.fmt = HDMI_RIGHT_J;
+			break;
+		case SND_SOC_DAIFMT_LEFT_J:
+			cf.fmt = HDMI_LEFT_J;
+			break;
+		case SND_SOC_DAIFMT_AC97:
+			cf.fmt = HDMI_AC97;
+			break;
+		default:
+			dev_err(dai->dev, "Invalid DAI interface format\n");
+			return -EINVAL;
+		}
+	}
+
+	hcp->daifmt[dai->id] = cf;
+
+	return ret;
+}
+
+static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+
+	dev_dbg(dai->dev, "%s()\n", __func__);
+
+	if (hcp->hcd.ops->digital_mute)
+		return hcp->hcd.ops->digital_mute(hcp->hcd.dev, mute);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops hdmi_dai_ops = {
+	.startup	= hdmi_codec_startup,
+	.shutdown	= hdmi_codec_shutdown,
+	.hw_params	= hdmi_codec_hw_params,
+	.set_sysclk	= hdmi_codec_set_sysclk,
+	.set_fmt	= hdmi_codec_set_fmt,
+	.digital_mute	= hdmi_codec_digital_mute,
+};
+
+
+#define HDMI_RATES	(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+			 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
+			 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
+			 SNDRV_PCM_RATE_192000)
+
+#define SPDIF_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
+			 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
+			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
+			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE)
+
+#define I2S_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
+			 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE |\
+			 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE |\
+			 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |\
+			 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\
+			 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE)
+
+static struct snd_soc_dai_driver hdmi_i2s_dai = {
+	.name = "i2s-hifi",
+	.id = DAI_ID_I2C,
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = HDMI_RATES,
+		.formats = I2S_FORMATS,
+		.sig_bits = 24,
+	},
+	.ops = &hdmi_dai_ops,
+};
+
+static const struct snd_soc_dai_driver hdmi_spdif_dai = {
+	.name = "spdif-hifi",
+	.id = DAI_ID_SPDIF,
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = HDMI_RATES,
+		.formats = SPDIF_FORMATS,
+	},
+	.ops = &hdmi_dai_ops,
+};
+
+static struct snd_soc_codec_driver hdmi_codec = {
+	.dapm_widgets = hdmi_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
+	.dapm_routes = hdmi_routes,
+	.num_dapm_routes = ARRAY_SIZE(hdmi_routes),
+};
+
+static int hdmi_codec_probe(struct platform_device *pdev)
+{
+	struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct hdmi_codec_priv *hcp;
+	int dai_count, i = 0;
+	int ret;
+
+	dev_dbg(dev, "%s()\n", __func__);
+
+	if (!hcd) {
+		dev_err(dev, "%s: No plalform data\n", __func__);
+		return -EINVAL;
+	}
+
+	dai_count = hcd->i2s + hcd->spdif;
+	if (dai_count < 1 || !hcd->dev || !hcd->ops ||
+	    !hcd->ops->hw_params || !hcd->ops->audio_shutdown) {
+		dev_err(dev, "%s: Invalid parameters\n", __func__);
+		return -EINVAL;
+	}
+
+	hcp = devm_kzalloc(dev, sizeof(*hcp), GFP_KERNEL);
+	if (!hcp)
+		return -ENOMEM;
+
+	hcp->hcd = *hcd;
+	mutex_init(&hcp->current_stream_lock);
+
+	hcp->daidrv = devm_kzalloc(hcd->dev, dai_count * sizeof(*hcp->daidrv),
+				   GFP_KERNEL);
+	if (!hcp->daidrv)
+		return -ENOMEM;
+
+	if (hcd->i2s) {
+		hcp->daidrv[i] = hdmi_i2s_dai;
+		hcp->daidrv[i].playback.channels_max =
+			hcd->max_i2s_channels;
+		i++;
+	}
+
+	if (hcd->spdif)
+		hcp->daidrv[i] = hdmi_spdif_dai;
+
+	ret = snd_soc_register_codec(dev, &hdmi_codec, hcp->daidrv,
+				     dai_count);
+	if (ret) {
+		dev_err(dev, "%s: snd_soc_register_codec() failed (%d)\n",
+			__func__, ret);
+		return ret;
+	}
+
+	dev_set_drvdata(dev, hcp);
+	return 0;
+}
+
+static int hdmi_codec_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver hdmi_codec_driver = {
+	.driver = {
+		.name = HDMI_CODEC_DRV_NAME,
+	},
+	.probe = hdmi_codec_probe,
+	.remove = hdmi_codec_remove,
+};
+
+module_platform_driver(hdmi_codec_driver);
+
+MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
+MODULE_DESCRIPTION("HDMI Audio Codec Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" HDMI_CODEC_DRV_NAME);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH RFC v2 4/7] ASoC: hdmi-codec: Add ELD based audio pcm rules DO NOT MERGE
  2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
                   ` (2 preceding siblings ...)
  2015-05-26 18:59 ` [PATCH RFC v2 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
@ 2015-05-26 18:59 ` Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 5/7] drm/i2c: tda998x: Add support of a DT graph of ports " Jyri Sarha
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: broonie, liam.r.girdwood, peter.ujfalusi, tomi.valkeinen,
	moinejf, rmk+kernel, Jyri Sarha

This patch is mostly just a copy paste from Russel King's generic
patchs[1] for the same thing. The patche is included only for testing
purposes. Do not merge!

[1] http://lists.freedesktop.org/archives/dri-devel/2015-April/080525.html

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 sound/soc/codecs/hdmi-codec.c | 104 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 103 insertions(+), 1 deletion(-)

diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index c208cef..2d26ce8 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -78,6 +78,103 @@ static int hdmi_codec_new_stream(struct snd_pcm_substream *substream,
 	return ret;
 }
 
+static const uint8_t *eld_sad(const uint8_t *eld)
+{
+	unsigned int ver, mnl;
+
+	ver = (eld[DRM_ELD_VER] & DRM_ELD_VER_MASK) >> DRM_ELD_VER_SHIFT;
+	if (ver != 2 && ver != 31)
+		return NULL;
+
+	mnl = drm_eld_mnl(eld);
+	if (mnl > 16)
+		return NULL;
+
+	return eld + DRM_ELD_CEA_SAD(mnl, 0);
+}
+
+static const unsigned int eld_rates[] = {
+	32000,
+	44100,
+	48000,
+	88200,
+	96000,
+	176400,
+	192000,
+};
+
+static int eld_limit_rates(struct snd_pcm_hw_params *params,
+			   struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval *r = hw_param_interval(params, rule->var);
+	unsigned int rate_mask = 7, i;
+	const u8 *sad, *eld = rule->private;
+
+	sad = eld_sad(eld);
+	if (sad) {
+		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
+			unsigned channels = 1 + (sad[0] & 7);
+
+			/*
+			 * Exclude SADs which do not include the
+			 * requested number of channels.
+			 */
+			if (params_channels(params) == channels)
+				rate_mask |= sad[1];
+		}
+	}
+
+	return snd_interval_list(r, ARRAY_SIZE(eld_rates), eld_rates,
+				 rate_mask);
+}
+
+static int eld_limit_channels(struct snd_pcm_hw_params *params,
+			      struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval *var = hw_param_interval(params, rule->var);
+	struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
+	unsigned int i, j;
+	const u8 *sad, *eld = rule->private;
+	int rate = params_rate(params);
+
+	sad = eld_sad(eld);
+	if (!sad)
+		return 0;
+
+	for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
+		for (j = 0; j < ARRAY_SIZE(eld_rates); j++) {
+			if ((sad[1] & (1<<j)) && rate == eld_rates[j]) {
+				switch (sad[0] & 0x78) {
+				case 0x08:
+					t.max = max(t.max, (sad[0] & 7) + 1u);
+					break;
+				}
+			}
+		}
+	}
+
+	return snd_interval_refine(var, &t);
+}
+
+static int hdmi_codec_constraint_eld(struct snd_pcm_runtime *runtime, void *eld)
+{
+	int ret;
+
+	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				  eld_limit_rates, eld,
+				  SNDRV_PCM_HW_PARAM_RATE,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  eld_limit_channels, eld,
+				  SNDRV_PCM_HW_PARAM_CHANNELS,
+				  SNDRV_PCM_HW_PARAM_RATE, -1);
+
+	return ret;
+}
+
 static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 			      struct snd_soc_dai *dai)
 {
@@ -104,7 +201,12 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 	if (hcp->hcd.ops->get_eld) {
 		hcp->eld = hcp->hcd.ops->get_eld(hcp->hcd.dev);
 
-		/* Call snd_pcm_hw_constraint_eld here */
+		if (hcp->eld) {
+			ret = hdmi_codec_constraint_eld(substream->runtime,
+							hcp->eld);
+			if (ret)
+				return ret;
+		}
 	}
 	return 0;
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH RFC v2 5/7] drm/i2c: tda998x: Add support of a DT graph of ports DO NOT MERGE
  2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
                   ` (3 preceding siblings ...)
  2015-05-26 18:59 ` [PATCH RFC v2 4/7] ASoC: hdmi-codec: Add ELD based audio pcm rules DO NOT MERGE Jyri Sarha
@ 2015-05-26 18:59 ` Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 6/7] drm/i2c: tda998x: Register ASoC HDMI codec for audio functionality " Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support " Jyri Sarha
  6 siblings, 0 replies; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: broonie, liam.r.girdwood, peter.ujfalusi, tomi.valkeinen,
	moinejf, rmk+kernel, Jyri Sarha

From: Jean-Francois Moine <moinejf@free.fr>

Two kinds of ports may be declared in a DT graph of ports: video and audio.
This patch accepts the port value from a video port as an alternative
to the video-ports property.
It also accepts audio ports in the case the transmitter is not used as
a slave encoder.
The new file include/sound/tda998x.h prepares to the definition of
a tda998x CODEC.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 .../devicetree/bindings/drm/i2c/tda998x.txt        | 51 ++++++++++++
 drivers/gpu/drm/i2c/tda998x_drv.c                  | 90 +++++++++++++++++++---
 include/sound/tda998x.h                            |  8 ++
 3 files changed, 140 insertions(+), 9 deletions(-)
 create mode 100644 include/sound/tda998x.h

diff --git a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
index e9e4bce..386b6c3 100644
--- a/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
+++ b/Documentation/devicetree/bindings/drm/i2c/tda998x.txt
@@ -16,6 +16,35 @@ Optional properties:
 
   - video-ports: 24 bits value which defines how the video controller
 	output is wired to the TDA998x input - default: <0x230145>
+	This property is not used when ports are defined.
+
+Optional nodes:
+
+  - port: up to three ports.
+	The ports are defined according to [1].
+
+    Video port.
+	There may be only one video port.
+	This one must contain the following property:
+
+	- port-type: must be "rgb"
+
+	and may contain the optional property:
+
+	- reg: 24 bits value which defines how the video controller
+		output is wired to the TDA998x input (video pins)
+		When absent, the default value is <0x230145>.
+
+    Audio ports.
+	There may be one or two audio ports.
+	These ones must contain the following properties:
+
+	- port-type: must be "i2s" or "spdif"
+
+	- reg: 8 bits value which defines how the audio controller
+		output is wired to the TDA998x input (audio pins)
+
+[1] Documentation/devicetree/bindings/graph.txt
 
 Example:
 
@@ -26,4 +55,26 @@ Example:
 		interrupts = <27 2>;		/* falling edge */
 		pinctrl-0 = <&pmx_camera>;
 		pinctrl-names = "default";
+
+		port at 230145 {
+			port-type = "rgb";
+			reg = <0x230145>;
+			hdmi_0: endpoint {
+				remote-endpoint = <&lcd0_0>;
+			};
+		};
+		port at 3 {			/* AP1 = I2S */
+			port-type = "i2s";
+			reg = <0x03>;
+			tda998x_i2s: endpoint {
+				remote-endpoint = <&audio1_i2s>;
+			};
+		};
+		port at 4 {			 /* AP2 = S/PDIF */
+			port-type = "spdif";
+			reg = <0x04>;
+			tda998x_spdif: endpoint {
+				remote-endpoint = <&audio1_spdif1>;
+			};
+		};
 	};
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 5febffd..bcf96f7 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -27,6 +27,7 @@
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/i2c/tda998x.h>
+#include <sound/tda998x.h>
 
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 
@@ -47,6 +48,8 @@ struct tda998x_priv {
 	wait_queue_head_t wq_edid;
 	volatile int wq_edid_wait;
 	struct drm_encoder *encoder;
+
+	struct tda998x_audio_s audio;
 };
 
 #define to_tda998x_priv(x)  ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
@@ -771,6 +774,8 @@ static void tda998x_encoder_set_config(struct tda998x_priv *priv,
 			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
 
 	priv->params = *p;
+	priv->audio.port_types[0] = p->audio_format;
+	priv->audio.ports[0] = p->audio_cfg;
 }
 
 static void tda998x_encoder_dpms(struct tda998x_priv *priv, int mode)
@@ -1227,9 +1232,57 @@ static struct drm_encoder_slave_funcs tda998x_encoder_slave_funcs = {
 
 /* I2C driver functions */
 
+static int tda998x_parse_ports(struct tda998x_priv *priv,
+				struct device_node *np)
+{
+	struct device_node *of_port;
+	const char *port_type;
+	int ret, audio_index, reg, afmt;
+
+	audio_index = 0;
+	for_each_child_of_node(np, of_port) {
+		if (!of_port->name
+		 || of_node_cmp(of_port->name, "port") != 0)
+			continue;
+		ret = of_property_read_string(of_port, "port-type",
+					&port_type);
+		if (ret < 0)
+			continue;
+		ret = of_property_read_u32(of_port, "reg", &reg);
+		if (strcmp(port_type, "rgb") == 0) {
+			if (!ret) {		/* video reg is optional */
+				priv->vip_cntrl_0 = reg >> 16;
+				priv->vip_cntrl_1 = reg >> 8;
+				priv->vip_cntrl_2 = reg;
+			}
+			continue;
+		}
+		if (strcmp(port_type, "i2s") == 0)
+			afmt = AFMT_I2S;
+		else if (strcmp(port_type, "spdif") == 0)
+			afmt = AFMT_SPDIF;
+		else
+			continue;
+		if (ret < 0) {
+			dev_err(&priv->hdmi->dev, "missing reg for %s\n",
+				port_type);
+			return ret;
+		}
+		if (audio_index >= ARRAY_SIZE(priv->audio.ports)) {
+			dev_err(&priv->hdmi->dev, "too many audio ports\n");
+			break;
+		}
+		priv->audio.ports[audio_index] = reg;
+		priv->audio.port_types[audio_index] = afmt;
+		audio_index++;
+	}
+	return 0;
+}
+
 static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
 {
 	struct device_node *np = client->dev.of_node;
+	struct device_node *of_port;
 	u32 video;
 	int rev_lo, rev_hi, ret;
 	unsigned short cec_addr;
@@ -1334,15 +1387,34 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
 	/* enable EDID read irq: */
 	reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
 
-	if (!np)
-		return 0;		/* non-DT */
-
-	/* get the optional video properties */
-	ret = of_property_read_u32(np, "video-ports", &video);
-	if (ret == 0) {
-		priv->vip_cntrl_0 = video >> 16;
-		priv->vip_cntrl_1 = video >> 8;
-		priv->vip_cntrl_2 = video;
+	/* get the device tree parameters */
+	if (np) {
+		of_port = of_get_child_by_name(np, "port");
+		if (of_port) {				/* graph of ports */
+			of_node_put(of_port);
+			ret = tda998x_parse_ports(priv, np);
+			if (ret < 0)
+				goto fail;
+
+			/* initialize the default audio configuration */
+			if (priv->audio.ports[0]) {
+				priv->params.audio_cfg = priv->audio.ports[0];
+				priv->params.audio_format =
+						priv->audio.port_types[0];
+				priv->params.audio_clk_cfg =
+					priv->params.audio_format ==
+							AFMT_SPDIF ? 0 : 1;
+			}
+		} else {
+
+			/* optional video properties */
+			ret = of_property_read_u32(np, "video-ports", &video);
+			if (ret == 0) {
+				priv->vip_cntrl_0 = video >> 16;
+				priv->vip_cntrl_1 = video >> 8;
+				priv->vip_cntrl_2 = video;
+			}
+		}
 	}
 
 	return 0;
diff --git a/include/sound/tda998x.h b/include/sound/tda998x.h
new file mode 100644
index 0000000..487a809
--- /dev/null
+++ b/include/sound/tda998x.h
@@ -0,0 +1,8 @@
+#ifndef SND_TDA998X_H
+#define SND_TDA998X_H
+
+struct tda998x_audio_s {
+	u8 ports[2];			/* AP value */
+	u8 port_types[2];		/* AFMT_xxx */
+};
+#endif
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH RFC v2 6/7] drm/i2c: tda998x: Register ASoC HDMI codec for audio functionality DO NOT MERGE
  2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
                   ` (4 preceding siblings ...)
  2015-05-26 18:59 ` [PATCH RFC v2 5/7] drm/i2c: tda998x: Add support of a DT graph of ports " Jyri Sarha
@ 2015-05-26 18:59 ` Jyri Sarha
  2015-05-26 18:59 ` [PATCH RFC v2 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support " Jyri Sarha
  6 siblings, 0 replies; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: peter.ujfalusi, broonie, Jyri Sarha, liam.r.girdwood,
	tomi.valkeinen, rmk+kernel

This patch is here to demonstrate how to use the ASoC hdmi-codec to
implement ASoC codec API in tda998x driver.

I do not have proper documentation for tda998x family chips so I lack
the necessary information for making a decent binding for audio part
of the chip. In stead I use binding from Jean-Francois Moine's "ASoC:
tda998x: add a codec to the HDMI transmitter" patch series.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 drivers/gpu/drm/i2c/Kconfig       |   1 +
 drivers/gpu/drm/i2c/tda998x_drv.c | 238 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 239 insertions(+)

diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index 22c7ed6..088f278 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -28,6 +28,7 @@ config DRM_I2C_SIL164
 config DRM_I2C_NXP_TDA998X
 	tristate "NXP Semiconductors TDA998X HDMI encoder"
 	default m if DRM_TILCDC
+	select SND_SOC_HDMI_CODEC if SND_SOC
 	help
 	  Support for NXP Semiconductors TDA998X HDMI encoders.
 
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index bcf96f7..3c38911 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/irq.h>
 #include <sound/asoundef.h>
+#include <sound/hdmi-codec.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
@@ -45,6 +46,9 @@ struct tda998x_priv {
 	u8 vip_cntrl_2;
 	struct tda998x_encoder_params params;
 
+	struct platform_device *audio_pdev;
+	uint8_t eld[MAX_ELD_BYTES];
+
 	wait_queue_head_t wq_edid;
 	volatile int wq_edid_wait;
 	struct drm_encoder *encoder;
@@ -1120,6 +1124,9 @@ tda998x_encoder_get_modes(struct tda998x_priv *priv,
 	drm_mode_connector_update_edid_property(connector, edid);
 	n = drm_add_edid_modes(connector, edid);
 	priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
+	drm_edid_to_eld(connector, edid);
+	memcpy(priv->eld, connector->eld, sizeof(priv->eld));
+
 	kfree(edid);
 
 	return n;
@@ -1156,6 +1163,9 @@ static void tda998x_destroy(struct tda998x_priv *priv)
 	}
 
 	i2c_unregister_device(priv->cec);
+
+	if (priv->audio_pdev)
+		platform_device_unregister(priv->audio_pdev);
 }
 
 /* Slave encoder support */
@@ -1230,6 +1240,230 @@ static struct drm_encoder_slave_funcs tda998x_encoder_slave_funcs = {
 	.set_property = tda998x_encoder_set_property,
 };
 
+static int
+tda998x_configure_audio2(struct tda998x_priv *priv,
+			int mode_clock,
+			int ena_ap,
+			struct hdmi_codec_params *params,
+			struct hdmi_codec_daifmt *daifmt)
+{
+	uint8_t buf[6], clksel_aip, clksel_fs, cts_n, adiv;
+	uint8_t infoframe_buf[HDMI_INFOFRAME_SIZE(AUDIO)];
+	int infoframe_len;
+	uint32_t n;
+
+	infoframe_len = hdmi_audio_infoframe_pack(&params->cea, infoframe_buf,
+						  sizeof(infoframe_buf));
+	if (infoframe_len < 0) {
+		dev_err(&priv->hdmi->dev,
+			"Failed to pack audio infoframe: %d\n",
+			infoframe_len);
+		return infoframe_len;
+	}
+
+	/* Enable audio ports */
+	reg_write(priv, REG_ENA_AP, ena_ap);
+	reg_write(priv, REG_ENA_ACLK, daifmt->fmt == HDMI_SPDIF ? 0 : 1);
+
+	/* Set audio input source */
+	switch (daifmt->fmt) {
+	case HDMI_SPDIF:
+		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF);
+		clksel_aip = AIP_CLKSEL_AIP_SPDIF;
+		clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
+		cts_n = CTS_N_M(3) | CTS_N_K(3);
+		break;
+
+	case HDMI_I2S:
+		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S);
+		clksel_aip = AIP_CLKSEL_AIP_I2S;
+		clksel_fs = AIP_CLKSEL_FS_ACLK;
+		switch (params->sample_width) {
+		case 16:
+			cts_n = CTS_N_M(3) | CTS_N_K(1);
+			break;
+		case 18:
+		case 20:
+		case 24:
+			cts_n = CTS_N_M(3) | CTS_N_K(2);
+			break;
+		default:
+		case 32:
+			cts_n = CTS_N_M(3) | CTS_N_K(3);
+			break;
+		}
+		break;
+
+	default:
+		dev_err(&priv->hdmi->dev, "Unsupported I2S format\n");
+		return -EINVAL;
+	}
+
+	reg_write(priv, REG_AIP_CLKSEL, clksel_aip);
+	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT |
+					AIP_CNTRL_0_ACR_MAN);	/* auto CTS */
+	reg_write(priv, REG_CTS_N, cts_n);
+
+	/*
+	 * Audio input somehow depends on HDMI line rate which is
+	 * related to pixclk. Testing showed that modes with pixclk
+	 * >100MHz need a larger divider while <40MHz need the default.
+	 * There is no detailed info in the datasheet, so we just
+	 * assume 100MHz requires larger divider.
+	 */
+	adiv = AUDIO_DIV_SERCLK_8;
+	if (mode_clock > 100000)
+		adiv++;			/* AUDIO_DIV_SERCLK_16 */
+
+	/* S/PDIF asks for a larger divider */
+	if (daifmt->fmt == HDMI_SPDIF)
+		adiv++;			/* AUDIO_DIV_SERCLK_16 or _32 */
+
+	reg_write(priv, REG_AUDIO_DIV, adiv);
+
+	/*
+	 * This is the approximate value of N, which happens to be
+	 * the recommended values for non-coherent clocks.
+	 */
+	n = 128 * params->sample_rate / 1000;
+
+	/* Write the CTS and N values */
+	buf[0] = 0x44;
+	buf[1] = 0x42;
+	buf[2] = 0x01;
+	buf[3] = n;
+	buf[4] = n >> 8;
+	buf[5] = n >> 16;
+	reg_write_range(priv, REG_ACR_CTS_0, buf, 6);
+
+	/* Set CTS clock reference */
+	reg_write(priv, REG_AIP_CLKSEL, clksel_aip | clksel_fs);
+
+	/* Reset CTS generator */
+	reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
+	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
+
+	/* Write the channel status */
+	reg_write_range(priv, REG_CH_STAT_B(0), params->iec.status, 4);
+
+	tda998x_audio_mute(priv, true);
+	msleep(20);
+	tda998x_audio_mute(priv, false);
+
+	/* Write the audio information packet */
+	tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0,
+			 infoframe_buf,
+			 infoframe_len);
+	return 0;
+}
+
+static int tda998x_audio_hw_params(struct device *dev,
+				   struct hdmi_codec_daifmt *daifmt,
+				   struct hdmi_codec_params *params)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+	unsigned int ena_ap = -1;
+	int i;
+
+	if (!priv->encoder->crtc)
+		return -ENODEV;
+
+	switch (daifmt->fmt) {
+	case HDMI_I2S:
+		if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
+		    daifmt->bit_clk_master || daifmt->frame_clk_master) {
+			dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
+				daifmt->bit_clk_inv, daifmt->frame_clk_inv,
+				daifmt->bit_clk_master,
+				daifmt->frame_clk_master);
+			return -EINVAL;
+		}
+		for (i = 0; i < ARRAY_SIZE(priv->audio.ports); i++)
+			if (priv->audio.port_types[i] == AFMT_I2S)
+				ena_ap = priv->audio.ports[i];
+		break;
+	case HDMI_SPDIF:
+		for (i = 0; i < ARRAY_SIZE(priv->audio.ports); i++)
+			if (priv->audio.port_types == AFMT_SPDIF)
+				ena_ap = priv->audio.ports[i];
+		break;
+	default:
+		dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
+		return -EINVAL;
+	}
+
+	if (ena_ap < 0) {
+		dev_err(dev, "%s: No audio configutation found\n", __func__);
+		return -EINVAL;
+	}
+
+
+	return tda998x_configure_audio2(priv,
+					priv->encoder->crtc->hwmode.clock,
+					ena_ap,
+					params,
+					daifmt);
+}
+
+static void tda998x_audio_shutdown(struct device *dev)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+	reg_write(priv, REG_ENA_AP, 0);
+}
+
+int tda998x_audio_digital_mute(struct device *dev, bool enable)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+	tda998x_audio_mute(priv, enable);
+
+	return 0;
+}
+
+static uint8_t *tda998x_audio_get_eld(struct device *dev)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+	return priv->eld;
+}
+
+static const struct hdmi_codec_ops audio_codec_ops = {
+	.hw_params = tda998x_audio_hw_params,
+	.audio_shutdown = tda998x_audio_shutdown,
+	.digital_mute = tda998x_audio_digital_mute,
+	.get_eld = tda998x_audio_get_eld,
+};
+
+static int tda998x_audio_codec_init(struct tda998x_priv *priv,
+				    struct device *dev)
+{
+	struct hdmi_codec_pdata codec_data = {
+		.dev = dev,
+		.ops = &audio_codec_ops,
+		.max_i2s_channels = 2,
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(priv->audio.ports); i++) {
+		if (priv->audio.port_types[i] == AFMT_I2S &&
+		    priv->audio.ports[i] != 0)
+			codec_data.i2s = 1;
+		if (priv->audio.port_types[i] == AFMT_SPDIF &&
+		    priv->audio.ports[i] != 0)
+			codec_data.spdif = 1;
+	}
+
+	priv->audio_pdev = platform_device_register_data(
+		dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
+		&codec_data, sizeof(codec_data));
+
+	if (IS_ERR(priv->audio_pdev))
+		return PTR_ERR(priv->audio_pdev);
+
+	return 0;
+}
+
 /* I2C driver functions */
 
 static int tda998x_parse_ports(struct tda998x_priv *priv,
@@ -1417,6 +1651,8 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
 		}
 	}
 
+	tda998x_audio_codec_init(priv, &client->dev);
+
 	return 0;
 
 fail:
@@ -1447,6 +1683,8 @@ static int tda998x_encoder_init(struct i2c_client *client,
 		return ret;
 	}
 
+	dev_set_drvdata(&client->dev, priv);
+
 	encoder_slave->slave_priv = priv;
 	encoder_slave->slave_funcs = &tda998x_encoder_slave_funcs;
 
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH RFC v2 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support DO NOT MERGE
  2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
                   ` (5 preceding siblings ...)
  2015-05-26 18:59 ` [PATCH RFC v2 6/7] drm/i2c: tda998x: Register ASoC HDMI codec for audio functionality " Jyri Sarha
@ 2015-05-26 18:59 ` Jyri Sarha
  6 siblings, 0 replies; 13+ messages in thread
From: Jyri Sarha @ 2015-05-26 18:59 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, alsa-devel
  Cc: broonie, liam.r.girdwood, peter.ujfalusi, tomi.valkeinen,
	moinejf, rmk+kernel, Jyri Sarha

This patch is here only to demonstrate HDMI codec functionality on
Beaglebone-Black.

Adds mcasp0_pins, clk_mcasp0_fixed, clk_mcasp0, mcasp0, sound node,
and changes the tda19988 node to follow the new binding.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 arch/arm/boot/dts/am335x-boneblack.dts | 78 +++++++++++++++++++++++++++++++++-
 1 file changed, 76 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index eadbba3..8a8abf5 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -64,6 +64,16 @@
 			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
 		>;
 	};
+
+	mcasp0_pins: mcasp0_pins {
+		pinctrl-single,pins = <
+			0x1ac (PIN_INPUT_PULLUP | MUX_MODE0)	/* mcasp0_ahclkx.mcasp0_ahclkx */
+			0x19c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2 */
+			0x194 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* mcasp0_fsx.mcasp0_fsx */
+			0x190 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp0_aclkx.mcasp0_aclkx */
+			0x06c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a11.GPIO1_27 */
+		>;
+	};
 };
 
 &lcdc {
@@ -76,21 +86,85 @@
 };
 
 &i2c0 {
-	tda19988 {
+	tda19988: tda19988 {
 		compatible = "nxp,tda998x";
 		reg = <0x70>;
+
+		#sound-dai-cells = <0>;
+
 		pinctrl-names = "default", "off";
 		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
 		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
 
-		port {
+		port@0 {
+			port-type = "rgb";
+			reg = <0x230145>;
 			hdmi_0: endpoint@0 {
 				remote-endpoint = <&lcdc_0>;
 			};
 		};
+		port@1 {
+			port-type = "i2s";
+			reg = <0x03>;
+			tda19988_i2s: endpoint {
+				remote-endpoint = <&mcasp0_i2s>;
+			};
+		};
 	};
 };
 
 &rtc {
 	system-power-controller;
 };
+
+&mcasp0	{
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcasp0_pins>;
+	status = "okay";
+	op-mode = <0>;	/* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
+			0 0 1 0
+		>;
+	tx-num-evt = <1>;
+	rx-num-evt = <1>;
+
+	port {
+		mcasp0_i2s: endpoint {
+			remote-endpoint = <&tda19988_i2s>;
+		};
+	};
+};
+
+/ {
+	clk_mcasp0_fixed: clk_mcasp0_fixed {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24576000>;
+	};
+
+	clk_mcasp0: clk_mcasp0 {
+		#clock-cells = <0>;
+		compatible = "gpio-gate-clock";
+		clocks = <&clk_mcasp0_fixed>;
+		enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "TI BeagleBone Black";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink0_master>;
+		simple-audio-card,frame-master = <&dailink0_master>;
+
+		dailink0_master: simple-audio-card,cpu {
+			sound-dai = <&mcasp0>;
+			clocks = <&clk_mcasp0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&tda19988>;
+		};
+	};
+};
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH RFC v2 1/7] ASoC: core: If component doesn't have of_node use parent's node instead
  2015-05-26 18:59 ` [PATCH RFC v2 1/7] ASoC: core: If component doesn't have of_node use parent's node instead Jyri Sarha
@ 2015-06-02 20:09   ` Mark Brown
  0 siblings, 0 replies; 13+ messages in thread
From: Mark Brown @ 2015-06-02 20:09 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: peter.ujfalusi, alsa-devel, moinejf, airlied, dri-devel,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel, linux-omap


[-- Attachment #1.1: Type: text/plain, Size: 243 bytes --]

On Tue, May 26, 2015 at 09:59:05PM +0300, Jyri Sarha wrote:
> If an ASoC component device does not have a device tree node, use its
> parent's node instead, when looking for a matching DAI based on a
> device tree reference.

Applied, thanks.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH RFC v2 2/7] ASoC: hdmi: Remove obsolete dummy HDMI codec
  2015-05-26 18:59 ` [PATCH RFC v2 2/7] ASoC: hdmi: Remove obsolete dummy HDMI codec Jyri Sarha
@ 2015-06-02 20:10   ` Mark Brown
  2015-09-20  0:13   ` Applied "ASoC: hdmi: Remove obsolete dummy HDMI codec" to the asoc tree Mark Brown
  1 sibling, 0 replies; 13+ messages in thread
From: Mark Brown @ 2015-06-02 20:10 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: dri-devel, airlied, linux-omap, alsa-devel, liam.r.girdwood,
	peter.ujfalusi, tomi.valkeinen, moinejf, rmk+kernel

[-- Attachment #1: Type: text/plain, Size: 328 bytes --]

On Tue, May 26, 2015 at 09:59:06PM +0300, Jyri Sarha wrote:

> -#ifdef CONFIG_OF
> -static const struct of_device_id hdmi_audio_codec_ids[] = {
> -	{ .compatible = "linux,hdmi-audio", },
> -	{ }
> -};
> -MODULE_DEVICE_TABLE(of, hdmi_audio_codec_ids);
> -#endif

There is actually a binding document, you should remove that too.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH RFC v2 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  2015-05-26 18:59 ` [PATCH RFC v2 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
@ 2015-08-14 19:25   ` Mark Brown
  2015-08-17  8:39     ` Jyri Sarha
  0 siblings, 1 reply; 13+ messages in thread
From: Mark Brown @ 2015-08-14 19:25 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: peter.ujfalusi, alsa-devel, moinejf, airlied, dri-devel,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel, linux-omap


[-- Attachment #1.1: Type: text/plain, Size: 843 bytes --]

On Tue, May 26, 2015 at 09:59:07PM +0300, Jyri Sarha wrote:

> +
> +	mutex_lock(&hcp->current_stream_lock);
> +	if (hcp->current_stream && hcp->current_stream->runtime &&
> +	    snd_pcm_running(hcp->current_stream)) {
> +		dev_info(dev, "HDMI audio playback aborted\n");

Does this really need to be dev_info()?

> +	if (hcp->hcd.ops->get_eld) {
> +		hcp->eld = hcp->hcd.ops->get_eld(hcp->hcd.dev);
> +
> +		/* Call snd_pcm_hw_constraint_eld here */
> +	}

...

> +	dev_dbg(dai->dev, "%s()\n", __func__);
> +
> +	mutex_lock(&hcp->current_stream_lock);
> +	BUG_ON(hcp->current_stream != substream);
> +	hcp->current_stream = NULL;
> +	mutex_unlock(&hcp->current_stream_lock);
> +
> +	hcp->hcd.ops->audio_shutdown(hcp->hcd.dev);

Shouldn't the callback be in or before the lock?  Otherwise we could
potentially race with starting a new stream.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH RFC v2 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  2015-08-14 19:25   ` Mark Brown
@ 2015-08-17  8:39     ` Jyri Sarha
  0 siblings, 0 replies; 13+ messages in thread
From: Jyri Sarha @ 2015-08-17  8:39 UTC (permalink / raw)
  To: Mark Brown
  Cc: peter.ujfalusi, alsa-devel, dri-devel, liam.r.girdwood,
	tomi.valkeinen, rmk+kernel, linux-omap

On 08/14/15 22:25, Mark Brown wrote:
> On Tue, May 26, 2015 at 09:59:07PM +0300, Jyri Sarha wrote:
>
>> +
>> +	mutex_lock(&hcp->current_stream_lock);
>> +	if (hcp->current_stream && hcp->current_stream->runtime &&
>> +	    snd_pcm_running(hcp->current_stream)) {
>> +		dev_info(dev, "HDMI audio playback aborted\n");
>
> Does this really need to be dev_info()?
>

No, I'll change that to debug level.

>> +	if (hcp->hcd.ops->get_eld) {
>> +		hcp->eld = hcp->hcd.ops->get_eld(hcp->hcd.dev);
>> +
>> +		/* Call snd_pcm_hw_constraint_eld here */
>> +	}
>
> ...
>
>> +	dev_dbg(dai->dev, "%s()\n", __func__);
>> +
>> +	mutex_lock(&hcp->current_stream_lock);
>> +	BUG_ON(hcp->current_stream != substream);
>> +	hcp->current_stream = NULL;
>> +	mutex_unlock(&hcp->current_stream_lock);
>> +
>> +	hcp->hcd.ops->audio_shutdown(hcp->hcd.dev);
>
> Shouldn't the callback be in or before the lock?  Otherwise we could
> potentially race with starting a new stream.
>

Yes, it should be before it. I'll fix that.

If it is inside, there is a "possible deadlock" warning (atleast in the 
similar place in omap-hdmi-audio there was) if those warnings are turned 
on and there is another lock that is taken in the video side callbacks.

Thanks,
Jyri
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Applied "ASoC: hdmi: Remove obsolete dummy HDMI codec" to the asoc tree
  2015-05-26 18:59 ` [PATCH RFC v2 2/7] ASoC: hdmi: Remove obsolete dummy HDMI codec Jyri Sarha
  2015-06-02 20:10   ` Mark Brown
@ 2015-09-20  0:13   ` Mark Brown
  1 sibling, 0 replies; 13+ messages in thread
From: Mark Brown @ 2015-09-20  0:13 UTC (permalink / raw)
  To: Jyri Sarha, Mark Brown; +Cc: alsa-devel

The patch

   ASoC: hdmi: Remove obsolete dummy HDMI codec

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 9529138276c852297967b5d3cc2f6dda3ddb9526 Mon Sep 17 00:00:00 2001
From: Jyri Sarha <jsarha@ti.com>
Date: Fri, 18 Sep 2015 14:06:38 +0300
Subject: [PATCH] ASoC: hdmi: Remove obsolete dummy HDMI codec

The hdmi stub codec has not been used since refactoring of OMAP HDMI
audio support.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/codecs/Kconfig  |   4 --
 sound/soc/codecs/Makefile |   2 -
 sound/soc/codecs/hdmi.c   | 109 ----------------------------------------------
 3 files changed, 115 deletions(-)
 delete mode 100644 sound/soc/codecs/hdmi.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0c9733e..0142396 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -79,7 +79,6 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_MC13783 if MFD_MC13XXX
 	select SND_SOC_ML26124 if I2C
-	select SND_SOC_HDMI_CODEC
 	select SND_SOC_PCM1681 if I2C
 	select SND_SOC_PCM1792A if SPI_MASTER
 	select SND_SOC_PCM3008
@@ -442,9 +441,6 @@ config SND_SOC_BT_SCO
 config SND_SOC_DMIC
 	tristate
 
-config SND_SOC_HDMI_CODEC
-       tristate "HDMI stub CODEC"
-
 config SND_SOC_ES8328
 	tristate "Everest Semi ES8328 CODEC"
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 4a32077..7d7cc1b 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -72,7 +72,6 @@ snd-soc-max98925-objs := max98925.o
 snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
-snd-soc-hdmi-codec-objs := hdmi.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm1792a-codec-objs := pcm1792a.o
 snd-soc-pcm3008-objs := pcm3008.o
@@ -264,7 +263,6 @@ obj-$(CONFIG_SND_SOC_MAX98925)	+= snd-soc-max98925.o
 obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_MC13783)	+= snd-soc-mc13783.o
 obj-$(CONFIG_SND_SOC_ML26124)	+= snd-soc-ml26124.o
-obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
 obj-$(CONFIG_SND_SOC_PCM1681)	+= snd-soc-pcm1681.o
 obj-$(CONFIG_SND_SOC_PCM1792A)	+= snd-soc-pcm1792a-codec.o
 obj-$(CONFIG_SND_SOC_PCM3008)	+= snd-soc-pcm3008.o
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c
deleted file mode 100644
index bd42ad3..0000000
--- a/sound/soc/codecs/hdmi.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * ALSA SoC codec driver for HDMI audio codecs.
- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Ricardo Neri <ricardo.neri@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-#include <linux/module.h>
-#include <sound/soc.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#define DRV_NAME "hdmi-audio-codec"
-
-static const struct snd_soc_dapm_widget hdmi_widgets[] = {
-	SND_SOC_DAPM_INPUT("RX"),
-	SND_SOC_DAPM_OUTPUT("TX"),
-};
-
-static const struct snd_soc_dapm_route hdmi_routes[] = {
-	{ "Capture", NULL, "RX" },
-	{ "TX", NULL, "Playback" },
-};
-
-static struct snd_soc_dai_driver hdmi_codec_dai = {
-	.name = "hdmi-hifi",
-	.playback = {
-		.stream_name = "Playback",
-		.channels_min = 2,
-		.channels_max = 8,
-		.rates = SNDRV_PCM_RATE_32000 |
-			SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE |
-			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
-		.sig_bits = 24,
-	},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 2,
-		.channels_max = 2,
-		.rates = SNDRV_PCM_RATE_32000 |
-			SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE |
-			SNDRV_PCM_FMTBIT_S24_LE,
-	},
-
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id hdmi_audio_codec_ids[] = {
-	{ .compatible = "linux,hdmi-audio", },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, hdmi_audio_codec_ids);
-#endif
-
-static struct snd_soc_codec_driver hdmi_codec = {
-	.dapm_widgets = hdmi_widgets,
-	.num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),
-	.dapm_routes = hdmi_routes,
-	.num_dapm_routes = ARRAY_SIZE(hdmi_routes),
-	.ignore_pmdown_time = true,
-};
-
-static int hdmi_codec_probe(struct platform_device *pdev)
-{
-	return snd_soc_register_codec(&pdev->dev, &hdmi_codec,
-			&hdmi_codec_dai, 1);
-}
-
-static int hdmi_codec_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_codec(&pdev->dev);
-	return 0;
-}
-
-static struct platform_driver hdmi_codec_driver = {
-	.driver		= {
-		.name	= DRV_NAME,
-		.of_match_table = of_match_ptr(hdmi_audio_codec_ids),
-	},
-
-	.probe		= hdmi_codec_probe,
-	.remove		= hdmi_codec_remove,
-};
-
-module_platform_driver(hdmi_codec_driver);
-
-MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
-MODULE_DESCRIPTION("ASoC generic HDMI codec driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-09-20  0:13 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-26 18:59 [PATCH RFC v2 0/7] Implement generic ASoC HDMI codec Jyri Sarha
2015-05-26 18:59 ` [PATCH RFC v2 1/7] ASoC: core: If component doesn't have of_node use parent's node instead Jyri Sarha
2015-06-02 20:09   ` Mark Brown
2015-05-26 18:59 ` [PATCH RFC v2 2/7] ASoC: hdmi: Remove obsolete dummy HDMI codec Jyri Sarha
2015-06-02 20:10   ` Mark Brown
2015-09-20  0:13   ` Applied "ASoC: hdmi: Remove obsolete dummy HDMI codec" to the asoc tree Mark Brown
2015-05-26 18:59 ` [PATCH RFC v2 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
2015-08-14 19:25   ` Mark Brown
2015-08-17  8:39     ` Jyri Sarha
2015-05-26 18:59 ` [PATCH RFC v2 4/7] ASoC: hdmi-codec: Add ELD based audio pcm rules DO NOT MERGE Jyri Sarha
2015-05-26 18:59 ` [PATCH RFC v2 5/7] drm/i2c: tda998x: Add support of a DT graph of ports " Jyri Sarha
2015-05-26 18:59 ` [PATCH RFC v2 6/7] drm/i2c: tda998x: Register ASoC HDMI codec for audio functionality " Jyri Sarha
2015-05-26 18:59 ` [PATCH RFC v2 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support " Jyri Sarha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).