alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x
@ 2016-03-31 13:35 Jyri Sarha
  2016-03-31 13:35 ` [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params Jyri Sarha
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:35 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tiwai, tomi.valkeinen, p.zabel, rmk+kernel

Couple of minor changes since v8 to ALSA/ASoC side patches. The series
is based on top of drm-next. However, it does not look like there is
enough attention to the DRM side so that the tda998x patches would get
in any time soon. So I am happy to rebase the first ALSA-side patches
on top of Mark Brown's for-next tree, for instance, if they would have
a change to go in on their own. The first two IEC958 helper patches
should apply as such.

There is currently two other patch series[2][3] that depend on the
first three (ALSA-) patches of this series. The third ("ASoC:
hdmi-codec: Add audio abort() callback for video side to use") is
currently not used and can be dropped if so decided. The rest depends
on those the first patches and adds hdmi-audio support for
Beaglebone-black.

Best regards,
Jyri

[1] "[PATCH v6 0/6] Implement generic ASoC HDMI codec and use it in tda998x"
    http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105524.html
[2] "[PATCH v6 00/10] ASoC: Add mediatek HDMI codec support" by Philipp Zabel 
    http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105509.html
[3] "[RFC v2 0/6] sti: add audio interface to the hdmi driver"
    http://mailman.alsa-project.org/pipermail/alsa-devel/2016-January/103374.html
    and "[PATCH v4 0/6] add IEC958 channel status control helpers"
    http://mailman.alsa-project.org/pipermail/alsa-devel/2016-March/105502.html
    by Arnaud Pouliquen

Changes since v8
* "ALSA: pcm: add IEC958 channel status helper for hw_params"
  - Split out the 32 bit support
  - add: "ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper"
* "ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders"
  - Set hw_params->msbits to 24 in hw_params() callback if sample width is
    greater than 24 bits

Changes since v7
* "drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding"
  - Remove the unused "int ret" variable from tda998x_configure_audio()

Changes since v6
* "ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders"
 - Add "Acked-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>" and
   "Tested-by: Philipp Zabel <p.zabel@pengutronix.de>", no other changes
* "ALSA: pcm: add IEC958 channel status helper for hw_param"
 - Added kernel-doc for snd_pcm_create_iec958_consumer_hw_params()
* "drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding"
 - Use PTR_ERR_OR_ZERO() in tda998x_audio_codec_init()
 - Fix possible uninitialized use of 'size' in tda998x_get_audio_ports()
 - Store audio configuration in tda998x_audio_hw_params() instead of
   tda998x_configure_audio().

Changes since v5
 - Rebased on top of the latest drm-next branch
 - Allow 32 bit samplewidth in snd_pcm_create_iec958_consumer() and
   snd_pcm_create_iec958_consumer_hw_params()
 - Propose new simpler DT binding for tda998x audio
 - Squash tda998x audio DT binding together with hdmi-codec integration

Changes since RFC v4,
 - Rebased on top of the latest drm-next branch
 - Split the hdmi-codec abort functionality into a separate patch for
   better visibility of what it is all about
   - This does not affect the tda998x patches as the abort
     functionality is not used
 - Drop S18_3* formats from I2S_FORMATS and add a comment about formats
   not supported by HDMI

Changes since RFC v3,
 ASoC side:
 - Add "ALSA: pcm: add IEC958 channel status helper for hw_params"
 - Add "tda998x: Improve tda998x_configure_audio() audio related pdata"
 - use snd_pcm_create_iec958_consumer_hw_params() to construct the stream header
 - Remove set_clk() callback from hdmi-codec. It is not needed for now.
 - Refer to stream header in AIF as specified in HDMI standard
 - Set current_stream to NULL only after video side audio_shutdown() has
   been called. Avoid potential race if video side attempts to abort audio
   at the same time.
 - No need to have video side device pointer in the hdmi codec's pdata as
   it is found from dev->parent.
 - Fix hdmi-codec enum: DAI_ID_I2C > DAI_ID_I2S
 - Improve audio_startup API comment
 - Make improved checkpatch happy 
   - BUG_ON > WARN_ON
   - put */ ending the block comment to a separate line

 DRM side:
 - Fix tda998x get_eld() locking
 - Change tda998x audio parameters in pdata to more generic, that can
   be readily used in tda998x_audio_config()
 - Rename and restructure audio port related private data members to
   be more descriptive
 - Require audio configuration trough ASoC hdmi-codec if HDMI audio is
   configured trough DT binding. 

 DTS:
 - Increase McASP fifo usage form 1 to 32

Jyri Sarha (7):
  ALSA: pcm: add IEC958 channel status helper for hw_params
  ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper
  ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  ASoC: hdmi-codec: Add audio abort() callback for video side to use
  drm/i2c: tda998x: Improve tda998x_configure_audio() audio related
    pdata
  drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
  ARM: dts: am335x-boneblack: Add HDMI audio support

 .../devicetree/bindings/display/bridge/tda998x.txt |  18 +
 arch/arm/boot/dts/am335x-boneblack.dts             |  71 +++-
 drivers/gpu/drm/i2c/Kconfig                        |   1 +
 drivers/gpu/drm/i2c/tda998x_drv.c                  | 275 ++++++++++++--
 include/drm/i2c/tda998x.h                          |  24 +-
 include/dt-bindings/display/tda998x.h              |   7 +
 include/sound/hdmi-codec.h                         | 104 ++++++
 include/sound/pcm_iec958.h                         |   2 +
 sound/core/pcm_iec958.c                            |  65 +++-
 sound/soc/codecs/Kconfig                           |   6 +
 sound/soc/codecs/Makefile                          |   2 +
 sound/soc/codecs/hdmi-codec.c                      | 414 +++++++++++++++++++++
 12 files changed, 917 insertions(+), 72 deletions(-)
 create mode 100644 include/dt-bindings/display/tda998x.h
 create mode 100644 include/sound/hdmi-codec.h
 create mode 100644 sound/soc/codecs/hdmi-codec.c

-- 
1.9.1

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

* [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
@ 2016-03-31 13:35 ` Jyri Sarha
  2016-03-31 13:42   ` Takashi Iwai
  2016-04-06 21:42   ` Applied "ALSA: pcm: add IEC958 channel status helper for hw_params" to the asoc tree Mark Brown
  2016-03-31 13:35 ` [PATCH v9 2/7] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper Jyri Sarha
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:35 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel

Add IEC958 channel status helper that gets the audio properties from
snd_pcm_hw_params instead of snd_pcm_runtime. This is needed to
produce the channel status bits already in audio stream configuration
phase.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 include/sound/pcm_iec958.h |  2 ++
 sound/core/pcm_iec958.c    | 64 ++++++++++++++++++++++++++++++++++------------
 2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
index 0eed397..36f023a 100644
--- a/include/sound/pcm_iec958.h
+++ b/include/sound/pcm_iec958.h
@@ -6,4 +6,6 @@
 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
 	size_t len);
 
+int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
+					     u8 *cs, size_t len);
 #endif
diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index 36b2d7a..e016871 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -9,30 +9,18 @@
 #include <linux/types.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/pcm_iec958.h>
 
-/**
- * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
- * @runtime: pcm runtime structure with ->rate filled in
- * @cs: channel status buffer, at least four bytes
- * @len: length of channel status buffer
- *
- * Create the consumer format channel status data in @cs of maximum size
- * @len corresponding to the parameters of the PCM runtime @runtime.
- *
- * Drivers may wish to tweak the contents of the buffer after creation.
- *
- * Returns: length of buffer, or negative error code if something failed.
- */
-int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
-	size_t len)
+static int create_iec958_consumer(uint rate, uint sample_width,
+				  u8 *cs, size_t len)
 {
 	unsigned int fs, ws;
 
 	if (len < 4)
 		return -EINVAL;
 
-	switch (runtime->rate) {
+	switch (rate) {
 	case 32000:
 		fs = IEC958_AES3_CON_FS_32000;
 		break;
@@ -59,7 +47,7 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
 	}
 
 	if (len > 4) {
-		switch (snd_pcm_format_width(runtime->format)) {
+		switch (sample_width) {
 		case 16:
 			ws = IEC958_AES4_CON_WORDLEN_20_16;
 			break;
@@ -92,4 +80,46 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
 
 	return len;
 }
+
+/**
+ * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
+ * @runtime: pcm runtime structure with ->rate filled in
+ * @cs: channel status buffer, at least four bytes
+ * @len: length of channel status buffer
+ *
+ * Create the consumer format channel status data in @cs of maximum size
+ * @len corresponding to the parameters of the PCM runtime @runtime.
+ *
+ * Drivers may wish to tweak the contents of the buffer after creation.
+ *
+ * Returns: length of buffer, or negative error code if something failed.
+ */
+int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
+	size_t len)
+{
+	return create_iec958_consumer(runtime->rate,
+				      snd_pcm_format_width(runtime->format),
+				      cs, len);
+}
 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
+
+/**
+ * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status
+ * @hw_params: the hw_params instance for extracting rate and sample format
+ * @cs: channel status buffer, at least four bytes
+ * @len: length of channel status buffer
+ *
+ * Create the consumer format channel status data in @cs of maximum size
+ * @len corresponding to the parameters of the PCM runtime @runtime.
+ *
+ * Drivers may wish to tweak the contents of the buffer after creation.
+ *
+ * Returns: length of buffer, or negative error code if something failed.
+ */
+int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
+					     u8 *cs, size_t len)
+{
+	return create_iec958_consumer(params_rate(params), params_width(params),
+				      cs, len);
+}
+EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
-- 
1.9.1

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

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

* [PATCH v9 2/7] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
  2016-03-31 13:35 ` [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params Jyri Sarha
@ 2016-03-31 13:35 ` Jyri Sarha
       [not found]   ` <44ee7ac5c0ddb4d25ac1bd4f189d328f8205e4a0.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
  2016-04-06 21:42   ` Applied "ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper" to the asoc tree Mark Brown
  2016-03-31 13:36 ` [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:35 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel

Treat 32 bit sample width as if it was 24 bits when generating IEC958
channel status bits. On some platforms 24 sample width is problematic
and to get full 24 bit precision a 32 bit format, using only the 24
most significant bits, may have to be used.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 sound/core/pcm_iec958.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index e016871..5e6aed6 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -59,6 +59,7 @@ static int create_iec958_consumer(uint rate, uint sample_width,
 			     IEC958_AES4_CON_MAX_WORDLEN_24;
 			break;
 		case 24:
+		case 32: /* Assume 24-bit width for 32-bit samples. */
 			ws = IEC958_AES4_CON_WORDLEN_24_20 |
 			     IEC958_AES4_CON_MAX_WORDLEN_24;
 			break;
-- 
1.9.1

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

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

* [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
  2016-03-31 13:35 ` [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params Jyri Sarha
  2016-03-31 13:35 ` [PATCH v9 2/7] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper Jyri Sarha
@ 2016-03-31 13:36 ` Jyri Sarha
  2016-04-13  8:06   ` Arnaud Pouliquen
                     ` (2 more replies)
  2016-03-31 13:36 ` [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use Jyri Sarha
                   ` (4 subsequent siblings)
  7 siblings, 3 replies; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:36 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel

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 HDMI 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    | 100 +++++++++++
 sound/soc/codecs/Kconfig      |   6 +
 sound/soc/codecs/Makefile     |   2 +
 sound/soc/codecs/hdmi-codec.c | 396 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 504 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..fc3a481
--- /dev/null
+++ b/include/sound/hdmi-codec.h
@@ -0,0 +1,100 @@
+/*
+ * 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 {
+	/*
+	 * Called when ASoC starts an audio stream setup.
+	 * Optional
+	 */
+	int (*audio_startup)(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
+	 */
+	int (*get_eld)(struct device *dev, uint8_t *buf, size_t len);
+};
+
+/* HDMI codec initalization data */
+struct hdmi_codec_pdata {
+	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 50693c8..62b62fe 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -86,6 +86,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_MC13783 if MFD_MC13XXX
 	select SND_SOC_ML26124 if I2C
 	select SND_SOC_NAU8825 if I2C
+	select SND_SOC_HDMI_CODEC
 	select SND_SOC_PCM1681 if I2C
 	select SND_SOC_PCM179X if SPI_MASTER
 	select SND_SOC_PCM3008
@@ -473,6 +474,11 @@ config SND_SOC_BT_SCO
 config SND_SOC_DMIC
 	tristate
 
+config SND_SOC_HDMI_CODEC
+       tristate
+       select SND_PCM_ELD
+       select SND_PCM_IEC958
+
 config SND_SOC_ES8328
 	tristate "Everest Semi ES8328 CODEC"
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index d44f7d3..5f7b002 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -79,6 +79,7 @@ snd-soc-max9850-objs := max9850.o
 snd-soc-mc13783-objs := mc13783.o
 snd-soc-ml26124-objs := ml26124.o
 snd-soc-nau8825-objs := nau8825.o
+snd-soc-hdmi-codec-objs := hdmi-codec.o
 snd-soc-pcm1681-objs := pcm1681.o
 snd-soc-pcm179x-codec-objs := pcm179x.o
 snd-soc-pcm3008-objs := pcm3008.o
@@ -283,6 +284,7 @@ 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_NAU8825)   += snd-soc-nau8825.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_PCM179X)	+= snd-soc-pcm179x-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..b46b8ed
--- /dev/null
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -0,0 +1,396 @@
+/*
+ * 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/pcm_drm_eld.h>
+#include <sound/hdmi-codec.h>
+#include <sound/pcm_iec958.h>
+
+#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */
+
+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[MAX_ELD_BYTES];
+};
+
+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_I2S = 0,
+	DAI_ID_SPDIF,
+};
+
+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(dai->dev->parent);
+		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) {
+		ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->eld,
+					    sizeof(hcp->eld));
+
+		if (!ret) {
+			ret = snd_pcm_hw_constraint_eld(substream->runtime,
+							hcp->eld);
+			if (ret)
+				return ret;
+		}
+	}
+	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__);
+
+	WARN_ON(hcp->current_stream != substream);
+
+	hcp->hcd.ops->audio_shutdown(dai->dev->parent);
+
+	mutex_lock(&hcp->current_stream_lock);
+	hcp->current_stream = NULL;
+	mutex_unlock(&hcp->current_stream_lock);
+}
+
+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 = {
+		.iec = {
+			.status = { 0 },
+			.subcode = { 0 },
+			.pad = 0,
+			.dig_subframe = { 0 },
+		}
+	};
+	int ret;
+
+	dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
+		params_width(params), params_rate(params),
+		params_channels(params));
+
+	if (params_width(params) > 24)
+		params->msbits = 24;
+
+	ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status,
+						       sizeof(hp.iec.status));
+	if (ret < 0) {
+		dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = hdmi_codec_new_stream(substream, dai);
+	if (ret)
+		return ret;
+
+	hdmi_audio_infoframe_init(&hp.cea);
+	hp.cea.channels = params_channels(params);
+	hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
+	hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
+	hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
+
+	hp.sample_width = params_width(params);
+	hp.sample_rate = params_rate(params);
+	hp.channels = params_channels(params);
+
+	return hcp->hcd.ops->hw_params(dai->dev->parent, &hcp->daifmt[dai->id],
+				       &hp);
+}
+
+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(dai->dev->parent, 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_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)
+
+/*
+ * This list is only for formats allowed on the I2S bus. So there is
+ * some formats listed that are not supported by HDMI interface. For
+ * instance allowing the 32-bit formats enables 24-precision with CPU
+ * DAIs that do not support 24-bit formats. If the extra formats cause
+ * problems, we should add the video side driver an option to disable
+ * them.
+ */
+#define I2S_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 |\
+			 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_I2S,
+	.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->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(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

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

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

* [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
                   ` (2 preceding siblings ...)
  2016-03-31 13:36 ` [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
@ 2016-03-31 13:36 ` Jyri Sarha
  2016-04-13  8:31   ` Arnaud Pouliquen
  2016-03-31 13:36 ` [PATCH v9 5/7] drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata Jyri Sarha
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:36 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel

Add audio abort() callback, that is provided at audio stream start,
for video side. This is for video side to use in case there is a
pressing need to tear down the audio playback for some reason.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 include/sound/hdmi-codec.h    |  8 ++++++--
 sound/soc/codecs/hdmi-codec.c | 20 +++++++++++++++++++-
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
index fc3a481..15fe70f 100644
--- a/include/sound/hdmi-codec.h
+++ b/include/sound/hdmi-codec.h
@@ -55,10 +55,14 @@ struct hdmi_codec_params {
 
 struct hdmi_codec_ops {
 	/*
-	 * Called when ASoC starts an audio stream setup.
+	 * Called when ASoC starts an audio stream setup. The call
+	 * provides an audio abort callback for stoping an ongoing
+	 * stream from video side driver if the HDMI audio becomes
+	 * unavailable.
 	 * Optional
 	 */
-	int (*audio_startup)(struct device *dev);
+	int (*audio_startup)(struct device *dev,
+			     void (*abort_cb)(struct device *dev));
 
 	/*
 	 * Configures HDMI-encoder for audio stream.
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index b46b8ed..35151a4 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -47,6 +47,23 @@ enum {
 	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)
 {
@@ -78,7 +95,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 		return ret;
 
 	if (hcp->hcd.ops->audio_startup) {
-		ret = hcp->hcd.ops->audio_startup(dai->dev->parent);
+		ret = hcp->hcd.ops->audio_startup(dai->dev->parent,
+						  hdmi_codec_abort);
 		if (ret) {
 			mutex_lock(&hcp->current_stream_lock);
 			hcp->current_stream = NULL;
-- 
1.9.1

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

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

* [PATCH v9 5/7] drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
                   ` (3 preceding siblings ...)
  2016-03-31 13:36 ` [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use Jyri Sarha
@ 2016-03-31 13:36 ` Jyri Sarha
  2016-03-31 13:36 ` [PATCH v9 6/7] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding Jyri Sarha
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:36 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel

Define struct tda998x_audio_params in include/drm/i2c/tda998x.h and
use it in pdata and for tda998x_configure_audio() parameters. Also
updates tda998x_write_aif() to take struct hdmi_audio_infoframe *
directly as a parameter.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 drivers/gpu/drm/i2c/tda998x_drv.c | 77 ++++++++++++++++++++-------------------
 include/drm/i2c/tda998x.h         | 24 +++++++-----
 2 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index f4315bc..f97b748 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -41,7 +41,7 @@ struct tda998x_priv {
 	u8 vip_cntrl_0;
 	u8 vip_cntrl_1;
 	u8 vip_cntrl_2;
-	struct tda998x_encoder_params params;
+	struct tda998x_audio_params audio_params;
 
 	wait_queue_head_t wq_edid;
 	volatile int wq_edid_wait;
@@ -666,26 +666,16 @@ tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,
 	reg_set(priv, REG_DIP_IF_FLAGS, bit);
 }
 
-static void
-tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p)
+static int tda998x_write_aif(struct tda998x_priv *priv,
+			     struct hdmi_audio_infoframe *cea)
 {
 	union hdmi_infoframe frame;
 
-	hdmi_audio_infoframe_init(&frame.audio);
-
-	frame.audio.channels = p->audio_frame[1] & 0x07;
-	frame.audio.channel_allocation = p->audio_frame[4];
-	frame.audio.level_shift_value = (p->audio_frame[5] & 0x78) >> 3;
-	frame.audio.downmix_inhibit = (p->audio_frame[5] & 0x80) >> 7;
-
-	/*
-	 * L-PCM and IEC61937 compressed audio shall always set sample
-	 * frequency to "refer to stream".  For others, see the HDMI
-	 * specification.
-	 */
-	frame.audio.sample_frequency = (p->audio_frame[2] & 0x1c) >> 2;
+	frame.audio = *cea;
 
 	tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame);
+
+	return 0;
 }
 
 static void
@@ -710,20 +700,21 @@ static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
 	}
 }
 
-static void
+static int
 tda998x_configure_audio(struct tda998x_priv *priv,
-		struct drm_display_mode *mode, struct tda998x_encoder_params *p)
+			struct tda998x_audio_params *params,
+			unsigned mode_clock)
 {
 	u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
 	u32 n;
 
 	/* Enable audio ports */
-	reg_write(priv, REG_ENA_AP, p->audio_cfg);
-	reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg);
+	reg_write(priv, REG_ENA_AP, params->config);
 
 	/* Set audio input source */
-	switch (p->audio_format) {
+	switch (params->format) {
 	case AFMT_SPDIF:
+		reg_write(priv, REG_ENA_ACLK, 0);
 		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_SPDIF);
 		clksel_aip = AIP_CLKSEL_AIP_SPDIF;
 		clksel_fs = AIP_CLKSEL_FS_FS64SPDIF;
@@ -731,15 +722,29 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 		break;
 
 	case AFMT_I2S:
+		reg_write(priv, REG_ENA_ACLK, 1);
 		reg_write(priv, REG_MUX_AP, MUX_AP_SELECT_I2S);
 		clksel_aip = AIP_CLKSEL_AIP_I2S;
 		clksel_fs = AIP_CLKSEL_FS_ACLK;
-		cts_n = CTS_N_M(3) | CTS_N_K(3);
+		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:
 		BUG();
-		return;
+		return -EINVAL;
 	}
 
 	reg_write(priv, REG_AIP_CLKSEL, clksel_aip);
@@ -755,11 +760,11 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	 * assume 100MHz requires larger divider.
 	 */
 	adiv = AUDIO_DIV_SERCLK_8;
-	if (mode->clock > 100000)
+	if (mode_clock > 100000)
 		adiv++;			/* AUDIO_DIV_SERCLK_16 */
 
 	/* S/PDIF asks for a larger divider */
-	if (p->audio_format == AFMT_SPDIF)
+	if (params->format == AFMT_SPDIF)
 		adiv++;			/* AUDIO_DIV_SERCLK_16 or _32 */
 
 	reg_write(priv, REG_AUDIO_DIV, adiv);
@@ -768,7 +773,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	 * This is the approximate value of N, which happens to be
 	 * the recommended values for non-coherent clocks.
 	 */
-	n = 128 * p->audio_sample_rate / 1000;
+	n = 128 * params->sample_rate / 1000;
 
 	/* Write the CTS and N values */
 	buf[0] = 0x44;
@@ -787,19 +792,13 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
 
 	/* Write the channel status */
-	buf[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
-	buf[1] = 0x00;
-	buf[2] = IEC958_AES3_CON_FS_NOTID;
-	buf[3] = IEC958_AES4_CON_ORIGFS_NOTID |
-			IEC958_AES4_CON_MAX_WORDLEN_24;
-	reg_write_range(priv, REG_CH_STAT_B(0), buf, 4);
+	reg_write_range(priv, REG_CH_STAT_B(0), params->status, 4);
 
 	tda998x_audio_mute(priv, true);
 	msleep(20);
 	tda998x_audio_mute(priv, false);
 
-	/* Write the audio information packet */
-	tda998x_write_aif(priv, p);
+	return tda998x_write_aif(priv, &params->cea);
 }
 
 /* DRM encoder functions */
@@ -820,7 +819,7 @@ static void tda998x_encoder_set_config(struct tda998x_priv *priv,
 			    VIP_CNTRL_2_SWAP_F(p->swap_f) |
 			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
 
-	priv->params = *p;
+	priv->audio_params = p->audio;
 }
 
 static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
@@ -1057,9 +1056,11 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
 
 		tda998x_write_avi(priv, adjusted_mode);
 
-		if (priv->params.audio_cfg)
-			tda998x_configure_audio(priv, adjusted_mode,
-						&priv->params);
+		if (priv->audio_params.format != AFMT_UNUSED) {
+			tda998x_configure_audio(priv,
+						&priv->audio_params,
+						adjusted_mode->clock);
+		}
 	}
 }
 
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 3e419d9..24be7aa 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -1,6 +1,19 @@
 #ifndef __DRM_I2C_TDA998X_H__
 #define __DRM_I2C_TDA998X_H__
 
+#define AFMT_UNUSED	0
+#define AFMT_SPDIF	1
+#define AFMT_I2S	2
+
+struct tda998x_audio_params {
+	u8 config;
+	u8 format;
+	unsigned sample_width;
+	unsigned sample_rate;
+	struct hdmi_audio_infoframe cea;
+	u8 status[4];
+};
+
 struct tda998x_encoder_params {
 	u8 swap_b:3;
 	u8 mirr_b:1;
@@ -15,16 +28,7 @@ struct tda998x_encoder_params {
 	u8 swap_e:3;
 	u8 mirr_e:1;
 
-	u8 audio_cfg;
-	u8 audio_clk_cfg;
-	u8 audio_frame[6];
-
-	enum {
-		AFMT_SPDIF,
-		AFMT_I2S
-	} audio_format;
-
-	unsigned audio_sample_rate;
+	struct tda998x_audio_params audio;
 };
 
 #endif
-- 
1.9.1

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

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

* [PATCH v9 6/7] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
                   ` (4 preceding siblings ...)
  2016-03-31 13:36 ` [PATCH v9 5/7] drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata Jyri Sarha
@ 2016-03-31 13:36 ` Jyri Sarha
  2016-04-01 18:37   ` Rob Herring
  2016-03-31 13:36 ` [PATCH v9 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support Jyri Sarha
  2016-04-13  7:02 ` [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Mark Brown
  7 siblings, 1 reply; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:36 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel

Register ASoC HDMI codec for audio functionality and adds device tree
binding for audio configuration.

With the registered HDMI codec the tda998x node can be used like a
regular codec node in ASoC card configurations. HDMI audio info-frame
and audio stream header is generated by the ASoC HDMI codec. The codec
also applies constraints for available sample-rates based on Edid Like
Data from the display. The device tree binding document has been
updated [1].

Part of this patch has been inspired by Jean Francoise's "drm/i2c: tda998x:
Add support of a DT graph of ports"-patch [2]. There may still be some
identical lines left from the original patch and some of the ideas
have come from there.

[1] Documentation/devicetree/bindings/display/bridge/tda998x.txt
[2] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/095255.html

Signed-off-by: Jyri Sarha <jsarha@ti.com>
---
 .../devicetree/bindings/display/bridge/tda998x.txt |  18 ++
 drivers/gpu/drm/i2c/Kconfig                        |   1 +
 drivers/gpu/drm/i2c/tda998x_drv.c                  | 198 ++++++++++++++++++++-
 include/drm/i2c/tda998x.h                          |   4 +-
 include/dt-bindings/display/tda998x.h              |   7 +
 5 files changed, 223 insertions(+), 5 deletions(-)
 create mode 100644 include/dt-bindings/display/tda998x.h

diff --git a/Documentation/devicetree/bindings/display/bridge/tda998x.txt b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
index e178e6b..24cc246 100644
--- a/Documentation/devicetree/bindings/display/bridge/tda998x.txt
+++ b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
@@ -21,8 +21,19 @@ Optional properties:
   - video-ports: 24 bits value which defines how the video controller
 	output is wired to the TDA998x input - default: <0x230145>
 
+  - audio-ports: array of 8-bit values, 2 values per one DAI[1].
+	The first value defines the DAI type: TDA998x_SPDIF or TDA998x_I2S[2].
+	The second value defines the tda998x AP_ENA reg content when the DAI
+	in question is used. The implementation allows one or two DAIs. If two
+	DAIs are defined, they must be of different type.
+
+[1] Documentation/sound/alsa/soc/DAI.txt
+[2] include/dt-bindings/display/tda998x.h
+
 Example:
 
+#include <dt-bindings/display/tda998x.h>
+
 	tda998x: hdmi-encoder {
 		compatible = "nxp,tda998x";
 		reg = <0x70>;
@@ -30,4 +41,11 @@ Example:
 		interrupts = <27 2>;		/* falling edge */
 		pinctrl-0 = <&pmx_camera>;
 		pinctrl-names = "default";
+		video-ports = <0x230145>;
+
+		#sound-dai-cells = <2>;
+			     /*	DAI-format	AP_ENA reg value */
+		audio-ports = <	TDA998x_SPDIF	0x04
+				TDA998x_I2S	0x03>;
+
 	};
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 f97b748..9d37493 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_atomic_helper.h>
@@ -30,6 +31,11 @@
 
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 
+struct tda998x_audio_port {
+	u8 format;		/* AFMT_xxx */
+	u8 config;		/* AP value */
+};
+
 struct tda998x_priv {
 	struct i2c_client *cec;
 	struct i2c_client *hdmi;
@@ -43,6 +49,8 @@ struct tda998x_priv {
 	u8 vip_cntrl_2;
 	struct tda998x_audio_params audio_params;
 
+	struct platform_device *audio_pdev;
+
 	wait_queue_head_t wq_edid;
 	volatile int wq_edid_wait;
 
@@ -53,6 +61,8 @@ struct tda998x_priv {
 
 	struct drm_encoder encoder;
 	struct drm_connector connector;
+
+	struct tda998x_audio_port audio_port[2];
 };
 
 #define conn_to_tda998x_priv(x) \
@@ -743,7 +753,7 @@ tda998x_configure_audio(struct tda998x_priv *priv,
 		break;
 
 	default:
-		BUG();
+		dev_err(&priv->hdmi->dev, "Unsupported I2S format\n");
 		return -EINVAL;
 	}
 
@@ -1160,6 +1170,8 @@ static int tda998x_connector_get_modes(struct drm_connector *connector)
 	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);
+
 	kfree(edid);
 
 	return n;
@@ -1181,6 +1193,9 @@ static void tda998x_destroy(struct tda998x_priv *priv)
 	cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
 	reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
 
+	if (priv->audio_pdev)
+		platform_device_unregister(priv->audio_pdev);
+
 	if (priv->hdmi->irq)
 		free_irq(priv->hdmi->irq, priv);
 
@@ -1190,8 +1205,179 @@ static void tda998x_destroy(struct tda998x_priv *priv)
 	i2c_unregister_device(priv->cec);
 }
 
+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);
+	int i, ret;
+	struct tda998x_audio_params audio = {
+		.sample_width = params->sample_width,
+		.sample_rate = params->sample_rate,
+		.cea = params->cea,
+	};
+
+	if (!priv->encoder.crtc)
+		return -ENODEV;
+
+	memcpy(audio.status, params->iec.status,
+	       min(sizeof(audio.status), sizeof(params->iec.status)));
+
+	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_port); i++)
+			if (priv->audio_port[i].format == AFMT_I2S)
+				audio.config = priv->audio_port[i].config;
+		audio.format = AFMT_I2S;
+		break;
+	case HDMI_SPDIF:
+		for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
+			if (priv->audio_port[i].format == AFMT_SPDIF)
+				audio.config = priv->audio_port[i].config;
+		audio.format = AFMT_SPDIF;
+		break;
+	default:
+		dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
+		return -EINVAL;
+	}
+
+	if (audio.config == 0) {
+		dev_err(dev, "%s: No audio configutation found\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = tda998x_configure_audio(priv,
+				      &audio,
+				      priv->encoder.crtc->hwmode.clock);
+
+	if (ret == 0)
+		priv->audio_params = audio;
+
+	return ret;
+}
+
+static void tda998x_audio_shutdown(struct device *dev)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+	reg_write(priv, REG_ENA_AP, 0);
+
+	priv->audio_params.format = AFMT_UNUSED;
+}
+
+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 int tda998x_audio_get_eld(struct device *dev, uint8_t *buf, size_t len)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+	struct drm_mode_config *config = &priv->encoder.dev->mode_config;
+	struct drm_connector *connector;
+	int ret = -ENODEV;
+
+	mutex_lock(&config->mutex);
+	list_for_each_entry(connector, &config->connector_list, head) {
+		if (&priv->encoder == connector->encoder) {
+			memcpy(buf, connector->eld,
+			       min(sizeof(connector->eld), len));
+			ret = 0;
+		}
+	}
+	mutex_unlock(&config->mutex);
+
+	return ret;
+}
+
+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 = {
+		.ops = &audio_codec_ops,
+		.max_i2s_channels = 2,
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++) {
+		if (priv->audio_port[i].format == AFMT_I2S &&
+		    priv->audio_port[i].config != 0)
+			codec_data.i2s = 1;
+		if (priv->audio_port[i].format == AFMT_SPDIF &&
+		    priv->audio_port[i].config != 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));
+
+	return PTR_ERR_OR_ZERO(priv->audio_pdev);
+}
+
 /* I2C driver functions */
 
+static int tda998x_get_audio_ports(struct tda998x_priv *priv,
+				   struct device_node *np)
+{
+	const u32 *port_data;
+	u32 size;
+	int i;
+
+	port_data = of_get_property(np, "audio-ports", &size);
+	if (!port_data)
+		return 0;
+
+	size /= sizeof(u32);
+	if (size > 2 * ARRAY_SIZE(priv->audio_port) || size % 2 != 0) {
+		dev_err(&priv->hdmi->dev,
+			"Bad number of elements in audio-ports dt-property\n");
+		return -EINVAL;
+	}
+
+	size /= 2;
+
+	for (i = 0; i < size; i++) {
+		u8 afmt = be32_to_cpup(&port_data[2*i]);
+		u8 ena_ap = be32_to_cpup(&port_data[2*i+1]);
+
+		if (afmt != AFMT_SPDIF && afmt != AFMT_I2S) {
+			dev_err(&priv->hdmi->dev,
+				"Bad audio format %u\n", afmt);
+			return -EINVAL;
+		}
+
+		priv->audio_port[i].format = afmt;
+		priv->audio_port[i].config = ena_ap;
+	}
+
+	if (priv->audio_port[0].format == priv->audio_port[1].format) {
+		dev_err(&priv->hdmi->dev,
+			"There can only be on I2S port and one SPDIF port\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
 {
 	struct device_node *np = client->dev.of_node;
@@ -1305,7 +1491,7 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
 	if (!np)
 		return 0;		/* non-DT */
 
-	/* get the optional video properties */
+	/* get the device tree parameters */
 	ret = of_property_read_u32(np, "video-ports", &video);
 	if (ret == 0) {
 		priv->vip_cntrl_0 = video >> 16;
@@ -1313,8 +1499,14 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
 		priv->vip_cntrl_2 = video;
 	}
 
-	return 0;
+	ret = tda998x_get_audio_ports(priv, np);
+	if (ret)
+		goto fail;
 
+	if (priv->audio_port[0].format != AFMT_UNUSED)
+		tda998x_audio_codec_init(priv, &client->dev);
+
+	return 0;
 fail:
 	/* if encoder_init fails, the encoder slave is never registered,
 	 * so cleanup here:
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 24be7aa..b575332 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -1,9 +1,9 @@
 #ifndef __DRM_I2C_TDA998X_H__
 #define __DRM_I2C_TDA998X_H__
 
+#include <dt-bindings/display/tda998x.h>
+
 #define AFMT_UNUSED	0
-#define AFMT_SPDIF	1
-#define AFMT_I2S	2
 
 struct tda998x_audio_params {
 	u8 config;
diff --git a/include/dt-bindings/display/tda998x.h b/include/dt-bindings/display/tda998x.h
new file mode 100644
index 0000000..38ef741
--- /dev/null
+++ b/include/dt-bindings/display/tda998x.h
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_TDA998X_H
+#define _DT_BINDINGS_TDA998X_H
+
+#define AFMT_SPDIF	1
+#define AFMT_I2S	2
+
+#endif /*_DT_BINDINGS_TDA998X_H */
-- 
1.9.1

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

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

* [PATCH v9 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
                   ` (5 preceding siblings ...)
  2016-03-31 13:36 ` [PATCH v9 6/7] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding Jyri Sarha
@ 2016-03-31 13:36 ` Jyri Sarha
  2016-04-13  7:02 ` [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Mark Brown
  7 siblings, 0 replies; 22+ messages in thread
From: Jyri Sarha @ 2016-03-31 13:36 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, Jyri Sarha,
	liam.r.girdwood, tomi.valkeinen, rmk+kernel

Add HDMI audio support. Adds mcasp0_pins, clk_mcasp0_fixed,
clk_mcasp0, mcasp0, sound node, and updates the tda19988 node to
follow the new binding.

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

diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index 55c0e95..2bae4d1 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -9,6 +9,7 @@
 
 #include "am33xx.dtsi"
 #include "am335x-bone-common.dtsi"
+#include <dt-bindings/display/tda998x.h>
 
 / {
 	model = "TI AM335x BeagleBone Black";
@@ -64,6 +65,16 @@
 			AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr0 */
 		>;
 	};
+
+	mcasp0_pins: mcasp0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+			AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+			AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
+			AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
+			AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+		>;
+	};
 };
 
 &lcdc {
@@ -76,16 +87,22 @@
 };
 
 &i2c0 {
-	tda19988 {
+	tda19988: tda19988 {
 		compatible = "nxp,tda998x";
 		reg = <0x70>;
+
 		pinctrl-names = "default", "off";
 		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
 		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
 
-		port {
-			hdmi_0: endpoint@0 {
-				remote-endpoint = <&lcdc_0>;
+		#sound-dai-cells = <0>;
+		audio-ports = <	AFMT_I2S	0x03>;
+
+		ports {
+			port@0 {
+				hdmi_0: endpoint@0 {
+					remote-endpoint = <&lcdc_0>;
+				};
 			};
 		};
 	};
@@ -94,3 +111,49 @@
 &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 = <32>;
+	rx-num-evt = <32>;
+};
+
+/ {
+	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

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

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

* Re: [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params
  2016-03-31 13:35 ` [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params Jyri Sarha
@ 2016-03-31 13:42   ` Takashi Iwai
  2016-04-06 21:42   ` Applied "ALSA: pcm: add IEC958 channel status helper for hw_params" to the asoc tree Mark Brown
  1 sibling, 0 replies; 22+ messages in thread
From: Takashi Iwai @ 2016-03-31 13:42 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: devicetree, alsa-devel, peter.ujfalusi, tomi.valkeinen,
	arnaud.pouliquen, dri-devel, liam.r.girdwood, tony, broonie,
	bcousson, rmk+kernel, linux-omap

On Thu, 31 Mar 2016 15:35:58 +0200,
Jyri Sarha wrote:
> 
> Add IEC958 channel status helper that gets the audio properties from
> snd_pcm_hw_params instead of snd_pcm_runtime. This is needed to
> produce the channel status bits already in audio stream configuration
> phase.
> 
> Signed-off-by: Jyri Sarha <jsarha@ti.com>

Reviewed-by: Takashi Iwai <tiwai@suse.de>


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

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

* Re: [PATCH v9 2/7] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper
       [not found]   ` <44ee7ac5c0ddb4d25ac1bd4f189d328f8205e4a0.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
@ 2016-03-31 13:43     ` Takashi Iwai
  0 siblings, 0 replies; 22+ messages in thread
From: Takashi Iwai @ 2016-03-31 13:43 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, airlied-cv59FeDIM0c,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	bcousson-rdvid1DuHRBWk0Htik3J/w,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw, tony-4v6yS6AI5VpBDgjK7y7TUQ,
	broonie-DgEjT+Ai2ygdnm+yROfE0A,
	liam.r.girdwood-VuQAYsv1563Yd54FQh9/CA,
	peter.ujfalusi-l0cyMroinI0, tomi.valkeinen-l0cyMroinI0,
	rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ, arnaud.pouliquen-qxv4g6HH51o

On Thu, 31 Mar 2016 15:35:59 +0200,
Jyri Sarha wrote:
> 
> Treat 32 bit sample width as if it was 24 bits when generating IEC958
> channel status bits. On some platforms 24 sample width is problematic
> and to get full 24 bit precision a 32 bit format, using only the 24
> most significant bits, may have to be used.
> 
> Signed-off-by: Jyri Sarha <jsarha-l0cyMroinI0@public.gmane.org>

Reviewed-by: Takashi Iwai <tiwai-l3A5Bk7waGM@public.gmane.org>


Takashi
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v9 6/7] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding
  2016-03-31 13:36 ` [PATCH v9 6/7] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding Jyri Sarha
@ 2016-04-01 18:37   ` Rob Herring
  0 siblings, 0 replies; 22+ messages in thread
From: Rob Herring @ 2016-04-01 18:37 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: devicetree, alsa-devel, liam.r.girdwood, tomi.valkeinen,
	arnaud.pouliquen, dri-devel, peter.ujfalusi, tony, broonie,
	bcousson, rmk+kernel, linux-omap

On Thu, Mar 31, 2016 at 04:36:03PM +0300, Jyri Sarha wrote:
> Register ASoC HDMI codec for audio functionality and adds device tree
> binding for audio configuration.
> 
> With the registered HDMI codec the tda998x node can be used like a
> regular codec node in ASoC card configurations. HDMI audio info-frame
> and audio stream header is generated by the ASoC HDMI codec. The codec
> also applies constraints for available sample-rates based on Edid Like
> Data from the display. The device tree binding document has been
> updated [1].
> 
> Part of this patch has been inspired by Jean Francoise's "drm/i2c: tda998x:
> Add support of a DT graph of ports"-patch [2]. There may still be some
> identical lines left from the original patch and some of the ideas
> have come from there.
> 
> [1] Documentation/devicetree/bindings/display/bridge/tda998x.txt
> [2] http://mailman.alsa-project.org/pipermail/alsa-devel/2015-July/095255.html
> 
> Signed-off-by: Jyri Sarha <jsarha@ti.com>
> ---
>  .../devicetree/bindings/display/bridge/tda998x.txt |  18 ++
>  drivers/gpu/drm/i2c/Kconfig                        |   1 +
>  drivers/gpu/drm/i2c/tda998x_drv.c                  | 198 ++++++++++++++++++++-
>  include/drm/i2c/tda998x.h                          |   4 +-
>  include/dt-bindings/display/tda998x.h              |   7 +
>  5 files changed, 223 insertions(+), 5 deletions(-)
>  create mode 100644 include/dt-bindings/display/tda998x.h
> 
> diff --git a/Documentation/devicetree/bindings/display/bridge/tda998x.txt b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
> index e178e6b..24cc246 100644
> --- a/Documentation/devicetree/bindings/display/bridge/tda998x.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
> @@ -21,8 +21,19 @@ Optional properties:
>    - video-ports: 24 bits value which defines how the video controller
>  	output is wired to the TDA998x input - default: <0x230145>
>  
> +  - audio-ports: array of 8-bit values, 2 values per one DAI[1].

This should have nxp prefix. With that,

Acked-by: Rob Herring <robh@kernel.org>


> +	The first value defines the DAI type: TDA998x_SPDIF or TDA998x_I2S[2].
> +	The second value defines the tda998x AP_ENA reg content when the DAI
> +	in question is used. The implementation allows one or two DAIs. If two
> +	DAIs are defined, they must be of different type.
> +
> +[1] Documentation/sound/alsa/soc/DAI.txt
> +[2] include/dt-bindings/display/tda998x.h
> +
>  Example:
>  
> +#include <dt-bindings/display/tda998x.h>
> +
>  	tda998x: hdmi-encoder {
>  		compatible = "nxp,tda998x";
>  		reg = <0x70>;
> @@ -30,4 +41,11 @@ Example:
>  		interrupts = <27 2>;		/* falling edge */
>  		pinctrl-0 = <&pmx_camera>;
>  		pinctrl-names = "default";
> +		video-ports = <0x230145>;
> +
> +		#sound-dai-cells = <2>;
> +			     /*	DAI-format	AP_ENA reg value */
> +		audio-ports = <	TDA998x_SPDIF	0x04
> +				TDA998x_I2S	0x03>;
> +
>  	};
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Applied "ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper" to the asoc tree
  2016-03-31 13:35 ` [PATCH v9 2/7] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper Jyri Sarha
       [not found]   ` <44ee7ac5c0ddb4d25ac1bd4f189d328f8205e4a0.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
@ 2016-04-06 21:42   ` Mark Brown
  1 sibling, 0 replies; 22+ messages in thread
From: Mark Brown @ 2016-04-06 21:42 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: devicetree, alsa-devel, liam.r.girdwood, tomi.valkeinen,
	arnaud.pouliquen, dri-devel, peter.ujfalusi, tony, broonie,
	bcousson, rmk+kernel, linux-omap

The patch

   ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper

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 4a462ce084d5beb92cfc68f53f88c035c82e6b59 Mon Sep 17 00:00:00 2001
From: Jyri Sarha <jsarha@ti.com>
Date: Thu, 31 Mar 2016 16:35:59 +0300
Subject: [PATCH] ALSA: pcm: Allow 32 bit sample format in IEC958 channel
 status helper

Treat 32 bit sample width as if it was 24 bits when generating IEC958
channel status bits. On some platforms 24 sample width is problematic
and to get full 24 bit precision a 32 bit format, using only the 24
most significant bits, may have to be used.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/core/pcm_iec958.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index e016871a978f..5e6aed64f451 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -59,6 +59,7 @@ static int create_iec958_consumer(uint rate, uint sample_width,
 			     IEC958_AES4_CON_MAX_WORDLEN_24;
 			break;
 		case 24:
+		case 32: /* Assume 24-bit width for 32-bit samples. */
 			ws = IEC958_AES4_CON_WORDLEN_24_20 |
 			     IEC958_AES4_CON_MAX_WORDLEN_24;
 			break;
-- 
2.8.0.rc3

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

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

* Applied "ALSA: pcm: add IEC958 channel status helper for hw_params" to the asoc tree
  2016-03-31 13:35 ` [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params Jyri Sarha
  2016-03-31 13:42   ` Takashi Iwai
@ 2016-04-06 21:42   ` Mark Brown
  1 sibling, 0 replies; 22+ messages in thread
From: Mark Brown @ 2016-04-06 21:42 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: devicetree, alsa-devel, liam.r.girdwood, tomi.valkeinen,
	arnaud.pouliquen, dri-devel, peter.ujfalusi, tony, broonie,
	bcousson, rmk+kernel, linux-omap

The patch

   ALSA: pcm: add IEC958 channel status helper for hw_params

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 4a4436573a6669516f73bac25016683d396ed4c4 Mon Sep 17 00:00:00 2001
From: Jyri Sarha <jsarha@ti.com>
Date: Thu, 31 Mar 2016 16:35:58 +0300
Subject: [PATCH] ALSA: pcm: add IEC958 channel status helper for hw_params

Add IEC958 channel status helper that gets the audio properties from
snd_pcm_hw_params instead of snd_pcm_runtime. This is needed to
produce the channel status bits already in audio stream configuration
phase.

Signed-off-by: Jyri Sarha <jsarha@ti.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 include/sound/pcm_iec958.h |  2 ++
 sound/core/pcm_iec958.c    | 64 ++++++++++++++++++++++++++++++++++------------
 2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
index 0eed397aca8e..36f023acb201 100644
--- a/include/sound/pcm_iec958.h
+++ b/include/sound/pcm_iec958.h
@@ -6,4 +6,6 @@
 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
 	size_t len);
 
+int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
+					     u8 *cs, size_t len);
 #endif
diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
index 36b2d7aca1bd..e016871a978f 100644
--- a/sound/core/pcm_iec958.c
+++ b/sound/core/pcm_iec958.c
@@ -9,30 +9,18 @@
 #include <linux/types.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/pcm_iec958.h>
 
-/**
- * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
- * @runtime: pcm runtime structure with ->rate filled in
- * @cs: channel status buffer, at least four bytes
- * @len: length of channel status buffer
- *
- * Create the consumer format channel status data in @cs of maximum size
- * @len corresponding to the parameters of the PCM runtime @runtime.
- *
- * Drivers may wish to tweak the contents of the buffer after creation.
- *
- * Returns: length of buffer, or negative error code if something failed.
- */
-int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
-	size_t len)
+static int create_iec958_consumer(uint rate, uint sample_width,
+				  u8 *cs, size_t len)
 {
 	unsigned int fs, ws;
 
 	if (len < 4)
 		return -EINVAL;
 
-	switch (runtime->rate) {
+	switch (rate) {
 	case 32000:
 		fs = IEC958_AES3_CON_FS_32000;
 		break;
@@ -59,7 +47,7 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
 	}
 
 	if (len > 4) {
-		switch (snd_pcm_format_width(runtime->format)) {
+		switch (sample_width) {
 		case 16:
 			ws = IEC958_AES4_CON_WORDLEN_20_16;
 			break;
@@ -92,4 +80,46 @@ int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
 
 	return len;
 }
+
+/**
+ * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
+ * @runtime: pcm runtime structure with ->rate filled in
+ * @cs: channel status buffer, at least four bytes
+ * @len: length of channel status buffer
+ *
+ * Create the consumer format channel status data in @cs of maximum size
+ * @len corresponding to the parameters of the PCM runtime @runtime.
+ *
+ * Drivers may wish to tweak the contents of the buffer after creation.
+ *
+ * Returns: length of buffer, or negative error code if something failed.
+ */
+int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
+	size_t len)
+{
+	return create_iec958_consumer(runtime->rate,
+				      snd_pcm_format_width(runtime->format),
+				      cs, len);
+}
 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
+
+/**
+ * snd_pcm_create_iec958_consumer_hw_params - create IEC958 channel status
+ * @hw_params: the hw_params instance for extracting rate and sample format
+ * @cs: channel status buffer, at least four bytes
+ * @len: length of channel status buffer
+ *
+ * Create the consumer format channel status data in @cs of maximum size
+ * @len corresponding to the parameters of the PCM runtime @runtime.
+ *
+ * Drivers may wish to tweak the contents of the buffer after creation.
+ *
+ * Returns: length of buffer, or negative error code if something failed.
+ */
+int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
+					     u8 *cs, size_t len)
+{
+	return create_iec958_consumer(params_rate(params), params_width(params),
+				      cs, len);
+}
+EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);
-- 
2.8.0.rc3

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

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

* Re: [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x
  2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
                   ` (6 preceding siblings ...)
  2016-03-31 13:36 ` [PATCH v9 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support Jyri Sarha
@ 2016-04-13  7:02 ` Mark Brown
  2016-04-13  7:53   ` Jyri Sarha
  7 siblings, 1 reply; 22+ messages in thread
From: Mark Brown @ 2016-04-13  7:02 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: devicetree, alsa-devel, peter.ujfalusi, arnaud.pouliquen,
	dri-devel, liam.r.girdwood, tony, tomi.valkeinen, bcousson,
	rmk+kernel, linux-omap


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

On Thu, Mar 31, 2016 at 04:35:57PM +0300, Jyri Sarha wrote:
> Couple of minor changes since v8 to ALSA/ASoC side patches. The series
> is based on top of drm-next. However, it does not look like there is
> enough attention to the DRM side so that the tda998x patches would get
> in any time soon. So I am happy to rebase the first ALSA-side patches
> on top of Mark Brown's for-next tree, for instance, if they would have
> a change to go in on their own. The first two IEC958 helper patches
> should apply as such.

None of the ASoC specific patches here have had any review from other
HDMI users?

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

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

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

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

* Re: [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x
  2016-04-13  7:02 ` [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Mark Brown
@ 2016-04-13  7:53   ` Jyri Sarha
  2016-04-13 17:26     ` Mark Brown
  0 siblings, 1 reply; 22+ messages in thread
From: Jyri Sarha @ 2016-04-13  7:53 UTC (permalink / raw)
  To: Mark Brown
  Cc: devicetree, alsa-devel, peter.ujfalusi, arnaud.pouliquen,
	dri-devel, liam.r.girdwood, tony, tomi.valkeinen, bcousson,
	rmk+kernel, linux-omap


[-- Attachment #1.1.1: Type: text/plain, Size: 1089 bytes --]

On 04/13/16 10:02, Mark Brown wrote:
> On Thu, Mar 31, 2016 at 04:35:57PM +0300, Jyri Sarha wrote:
>> Couple of minor changes since v8 to ALSA/ASoC side patches. The series
>> is based on top of drm-next. However, it does not look like there is
>> enough attention to the DRM side so that the tda998x patches would get
>> in any time soon. So I am happy to rebase the first ALSA-side patches
>> on top of Mark Brown's for-next tree, for instance, if they would have
>> a change to go in on their own. The first two IEC958 helper patches
>> should apply as such.
> 
> None of the ASoC specific patches here have had any review from other
> HDMI users?
> 

I got ack from Arnaud Pouliquen and tested-by from Philipp Zabel for
"ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders" in
previous version of the series. Since then there is one minimal change,
but because I touched the patch I removed the ack and tested-by tags.

The change is setting hw_params->msbits to 24 in hw_params() callback if
sample width is greater than 24 bits.

Best regards,
Jyri


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

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

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

* Re: [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  2016-03-31 13:36 ` [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
@ 2016-04-13  8:06   ` Arnaud Pouliquen
       [not found]   ` <636486b25db48fa13ae640516cdebe7bcfea0d23.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
  2016-04-19 10:42   ` Jyri Sarha
  2 siblings, 0 replies; 22+ messages in thread
From: Arnaud Pouliquen @ 2016-04-13  8:06 UTC (permalink / raw)
  To: Jyri Sarha, dri-devel, airlied, linux-omap, devicetree, bcousson,
	alsa-devel
  Cc: peter.ujfalusi, tony, broonie, liam.r.girdwood, tiwai,
	tomi.valkeinen, p.zabel, rmk+kernel

New version Tested with success on sti platform

Acked-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>

Regards
Arnaud


On 03/31/2016 03:36 PM, Jyri Sarha wrote:
> 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 HDMI 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    | 100 +++++++++++
>  sound/soc/codecs/Kconfig      |   6 +
>  sound/soc/codecs/Makefile     |   2 +
>  sound/soc/codecs/hdmi-codec.c | 396 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 504 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..fc3a481
> --- /dev/null
> +++ b/include/sound/hdmi-codec.h
> @@ -0,0 +1,100 @@
> +/*
> + * 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 {
> +	/*
> +	 * Called when ASoC starts an audio stream setup.
> +	 * Optional
> +	 */
> +	int (*audio_startup)(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
> +	 */
> +	int (*get_eld)(struct device *dev, uint8_t *buf, size_t len);
> +};
> +
> +/* HDMI codec initalization data */
> +struct hdmi_codec_pdata {
> +	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 50693c8..62b62fe 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -86,6 +86,7 @@ config SND_SOC_ALL_CODECS
>  	select SND_SOC_MC13783 if MFD_MC13XXX
>  	select SND_SOC_ML26124 if I2C
>  	select SND_SOC_NAU8825 if I2C
> +	select SND_SOC_HDMI_CODEC
>  	select SND_SOC_PCM1681 if I2C
>  	select SND_SOC_PCM179X if SPI_MASTER
>  	select SND_SOC_PCM3008
> @@ -473,6 +474,11 @@ config SND_SOC_BT_SCO
>  config SND_SOC_DMIC
>  	tristate
>  
> +config SND_SOC_HDMI_CODEC
> +       tristate
> +       select SND_PCM_ELD
> +       select SND_PCM_IEC958
> +
>  config SND_SOC_ES8328
>  	tristate "Everest Semi ES8328 CODEC"
>  
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index d44f7d3..5f7b002 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -79,6 +79,7 @@ snd-soc-max9850-objs := max9850.o
>  snd-soc-mc13783-objs := mc13783.o
>  snd-soc-ml26124-objs := ml26124.o
>  snd-soc-nau8825-objs := nau8825.o
> +snd-soc-hdmi-codec-objs := hdmi-codec.o
>  snd-soc-pcm1681-objs := pcm1681.o
>  snd-soc-pcm179x-codec-objs := pcm179x.o
>  snd-soc-pcm3008-objs := pcm3008.o
> @@ -283,6 +284,7 @@ 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_NAU8825)   += snd-soc-nau8825.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_PCM179X)	+= snd-soc-pcm179x-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..b46b8ed
> --- /dev/null
> +++ b/sound/soc/codecs/hdmi-codec.c
> @@ -0,0 +1,396 @@
> +/*
> + * 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/pcm_drm_eld.h>
> +#include <sound/hdmi-codec.h>
> +#include <sound/pcm_iec958.h>
> +
> +#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */
> +
> +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[MAX_ELD_BYTES];
> +};
> +
> +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_I2S = 0,
> +	DAI_ID_SPDIF,
> +};
> +
> +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(dai->dev->parent);
> +		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) {
> +		ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->eld,
> +					    sizeof(hcp->eld));
> +
> +		if (!ret) {
> +			ret = snd_pcm_hw_constraint_eld(substream->runtime,
> +							hcp->eld);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +	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__);
> +
> +	WARN_ON(hcp->current_stream != substream);
> +
> +	hcp->hcd.ops->audio_shutdown(dai->dev->parent);
> +
> +	mutex_lock(&hcp->current_stream_lock);
> +	hcp->current_stream = NULL;
> +	mutex_unlock(&hcp->current_stream_lock);
> +}
> +
> +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 = {
> +		.iec = {
> +			.status = { 0 },
> +			.subcode = { 0 },
> +			.pad = 0,
> +			.dig_subframe = { 0 },
> +		}
> +	};
> +	int ret;
> +
> +	dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
> +		params_width(params), params_rate(params),
> +		params_channels(params));
> +
> +	if (params_width(params) > 24)
> +		params->msbits = 24;
> +
> +	ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status,
> +						       sizeof(hp.iec.status));
> +	if (ret < 0) {
> +		dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	ret = hdmi_codec_new_stream(substream, dai);
> +	if (ret)
> +		return ret;
> +
> +	hdmi_audio_infoframe_init(&hp.cea);
> +	hp.cea.channels = params_channels(params);
> +	hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
> +	hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
> +	hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
> +
> +	hp.sample_width = params_width(params);
> +	hp.sample_rate = params_rate(params);
> +	hp.channels = params_channels(params);
> +
> +	return hcp->hcd.ops->hw_params(dai->dev->parent, &hcp->daifmt[dai->id],
> +				       &hp);
> +}
> +
> +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(dai->dev->parent, 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_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)
> +
> +/*
> + * This list is only for formats allowed on the I2S bus. So there is
> + * some formats listed that are not supported by HDMI interface. For
> + * instance allowing the 32-bit formats enables 24-precision with CPU
> + * DAIs that do not support 24-bit formats. If the extra formats cause
> + * problems, we should add the video side driver an option to disable
> + * them.
> + */
> +#define I2S_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 |\
> +			 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_I2S,
> +	.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->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(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);
> 

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

* Re: [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use
  2016-03-31 13:36 ` [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use Jyri Sarha
@ 2016-04-13  8:31   ` Arnaud Pouliquen
  2016-04-14  6:21     ` Jyri Sarha
  0 siblings, 1 reply; 22+ messages in thread
From: Arnaud Pouliquen @ 2016-04-13  8:31 UTC (permalink / raw)
  To: Jyri Sarha, dri-devel, airlied, linux-omap, devicetree, bcousson,
	alsa-devel
  Cc: peter.ujfalusi, tony, broonie, liam.r.girdwood, tiwai,
	tomi.valkeinen, p.zabel, rmk+kernel



On 03/31/2016 03:36 PM, Jyri Sarha wrote:
> Add audio abort() callback, that is provided at audio stream start,
> for video side. This is for video side to use in case there is a
> pressing need to tear down the audio playback for some reason.
> 
> Signed-off-by: Jyri Sarha <jsarha@ti.com>
> ---
>  include/sound/hdmi-codec.h    |  8 ++++++--
>  sound/soc/codecs/hdmi-codec.c | 20 +++++++++++++++++++-
>  2 files changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
> index fc3a481..15fe70f 100644
> --- a/include/sound/hdmi-codec.h
> +++ b/include/sound/hdmi-codec.h
> @@ -55,10 +55,14 @@ struct hdmi_codec_params {
>  
>  struct hdmi_codec_ops {
>  	/*
> -	 * Called when ASoC starts an audio stream setup.
> +	 * Called when ASoC starts an audio stream setup. The call
> +	 * provides an audio abort callback for stoping an ongoing
stopping
> +	 * stream from video side driver if the HDMI audio becomes
> +	 * unavailable.
>  	 * Optional
>  	 */
> -	int (*audio_startup)(struct device *dev);
> +	int (*audio_startup)(struct device *dev,
> +			     void (*abort_cb)(struct device *dev));
>  
>  	/*
>  	 * Configures HDMI-encoder for audio stream.
> diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
> index b46b8ed..35151a4 100644
> --- a/sound/soc/codecs/hdmi-codec.c
> +++ b/sound/soc/codecs/hdmi-codec.c
> @@ -47,6 +47,23 @@ enum {
>  	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);
> +}
> +
still not understand the need... i can not find a use case that
justifies it.
As example, in case of HDMI plug/unplug i would not want that audio
stream is stopped (live playback). From my point of view this should be
a decision from user.
But as it is optional, I'm ok if need is justified.

>  static int hdmi_codec_new_stream(struct snd_pcm_substream *substream,
>  				 struct snd_soc_dai *dai)
>  {
> @@ -78,7 +95,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
>  		return ret;
>  
>  	if (hcp->hcd.ops->audio_startup) {
> -		ret = hcp->hcd.ops->audio_startup(dai->dev->parent);
> +		ret = hcp->hcd.ops->audio_startup(dai->dev->parent,
> +						  hdmi_codec_abort);
>  		if (ret) {
>  			mutex_lock(&hcp->current_stream_lock);
>  			hcp->current_stream = NULL;
> 

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

* Re: [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x
  2016-04-13  7:53   ` Jyri Sarha
@ 2016-04-13 17:26     ` Mark Brown
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Brown @ 2016-04-13 17:26 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: devicetree, alsa-devel, peter.ujfalusi, arnaud.pouliquen,
	dri-devel, liam.r.girdwood, tony, tomi.valkeinen, bcousson,
	rmk+kernel, linux-omap


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

On Wed, Apr 13, 2016 at 10:53:01AM +0300, Jyri Sarha wrote:
> On 04/13/16 10:02, Mark Brown wrote:

> > None of the ASoC specific patches here have had any review from other
> > HDMI users?

> I got ack from Arnaud Pouliquen and tested-by from Philipp Zabel for
> "ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders" in
> previous version of the series. Since then there is one minimal change,
> but because I touched the patch I removed the ack and tested-by tags.

Yes, I remember but if you think the change is big enough to warrant
removing the tags I'm hoping to see some interest in review!

> The change is setting hw_params->msbits to 24 in hw_params() callback if
> sample width is greater than 24 bits.

That is reasonably small though...

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

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

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

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

* Re: [alsa-devel] [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
       [not found]   ` <636486b25db48fa13ae640516cdebe7bcfea0d23.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
@ 2016-04-14  5:31     ` PC Liao
  0 siblings, 0 replies; 22+ messages in thread
From: PC Liao @ 2016-04-14  5:31 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, airlied-cv59FeDIM0c,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	bcousson-rdvid1DuHRBWk0Htik3J/w,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw, peter.ujfalusi-l0cyMroinI0,
	tony-4v6yS6AI5VpBDgjK7y7TUQ, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	arnaud.pouliquen-qxv4g6HH51o,
	liam.r.girdwood-VuQAYsv1563Yd54FQh9/CA, tiwai-l3A5Bk7waGM,
	tomi.valkeinen-l0cyMroinI0, p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ,
	rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ

Hi Jyri,

On Thu, 2016-03-31 at 16:36 +0300, Jyri Sarha wrote:
> 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 HDMI 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-l0cyMroinI0@public.gmane.org>

I successfully tested new version on mt8173. 
Acked-by: PC Liao <pc.liao-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use
  2016-04-13  8:31   ` Arnaud Pouliquen
@ 2016-04-14  6:21     ` Jyri Sarha
  0 siblings, 0 replies; 22+ messages in thread
From: Jyri Sarha @ 2016-04-14  6:21 UTC (permalink / raw)
  To: Arnaud Pouliquen, dri-devel, airlied, linux-omap, devicetree,
	bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, liam.r.girdwood, tomi.valkeinen,
	rmk+kernel

On 04/13/16 11:31, Arnaud Pouliquen wrote:
> 
> 
> On 03/31/2016 03:36 PM, Jyri Sarha wrote:
>> Add audio abort() callback, that is provided at audio stream start,
>> for video side. This is for video side to use in case there is a
>> pressing need to tear down the audio playback for some reason.
>>
>> Signed-off-by: Jyri Sarha <jsarha@ti.com>
>> ---
>>  include/sound/hdmi-codec.h    |  8 ++++++--
>>  sound/soc/codecs/hdmi-codec.c | 20 +++++++++++++++++++-
>>  2 files changed, 25 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
>> index fc3a481..15fe70f 100644
>> --- a/include/sound/hdmi-codec.h
>> +++ b/include/sound/hdmi-codec.h
>> @@ -55,10 +55,14 @@ struct hdmi_codec_params {
>>  
>>  struct hdmi_codec_ops {
>>  	/*
>> -	 * Called when ASoC starts an audio stream setup.
>> +	 * Called when ASoC starts an audio stream setup. The call
>> +	 * provides an audio abort callback for stoping an ongoing
> stopping
>> +	 * stream from video side driver if the HDMI audio becomes
>> +	 * unavailable.
>>  	 * Optional
>>  	 */
>> -	int (*audio_startup)(struct device *dev);
>> +	int (*audio_startup)(struct device *dev,
>> +			     void (*abort_cb)(struct device *dev));
>>  
>>  	/*
>>  	 * Configures HDMI-encoder for audio stream.
>> diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
>> index b46b8ed..35151a4 100644
>> --- a/sound/soc/codecs/hdmi-codec.c
>> +++ b/sound/soc/codecs/hdmi-codec.c
>> @@ -47,6 +47,23 @@ enum {
>>  	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);
>> +}
>> +
> still not understand the need... i can not find a use case that
> justifies it.
> As example, in case of HDMI plug/unplug i would not want that audio
> stream is stopped (live playback). From my point of view this should be
> a decision from user.
> But as it is optional, I'm ok if need is justified.
> 

Well, I think we can drop this as there is no use for it ATM.

I copied this feature from my omap-hdmi-audio driver, where the display
module on the SoC implements ASoC CPU-DAI itself. In that setup the DMA
simply stops if the display is turned off, which eventually causes the
audio stream to time out. However, it is unlikely to have a similar
situation here, since the purpose is to implement ASoC codec DAI for an
external HDMI encoder sitting behind i2s and/or spdif wires and the
CPU-DAI can keep on playing the audio even if the whole encoder powered
down. That is if the HDMI encoder does not provide the clocks for the
DAI link. Anyway, we can add this feature later if there ever is a need
for it.

>>  static int hdmi_codec_new_stream(struct snd_pcm_substream *substream,
>>  				 struct snd_soc_dai *dai)
>>  {
>> @@ -78,7 +95,8 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
>>  		return ret;
>>  
>>  	if (hcp->hcd.ops->audio_startup) {
>> -		ret = hcp->hcd.ops->audio_startup(dai->dev->parent);
>> +		ret = hcp->hcd.ops->audio_startup(dai->dev->parent,
>> +						  hdmi_codec_abort);
>>  		if (ret) {
>>  			mutex_lock(&hcp->current_stream_lock);
>>  			hcp->current_stream = NULL;
>>

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

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

* Re: [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
  2016-03-31 13:36 ` [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
  2016-04-13  8:06   ` Arnaud Pouliquen
       [not found]   ` <636486b25db48fa13ae640516cdebe7bcfea0d23.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
@ 2016-04-19 10:42   ` Jyri Sarha
       [not found]     ` <57160B9F.9090907-l0cyMroinI0@public.gmane.org>
  2 siblings, 1 reply; 22+ messages in thread
From: Jyri Sarha @ 2016-04-19 10:42 UTC (permalink / raw)
  To: dri-devel, airlied, linux-omap, devicetree, bcousson, alsa-devel
  Cc: peter.ujfalusi, tony, broonie, arnaud.pouliquen, liam.r.girdwood,
	tiwai, tomi.valkeinen, p.zabel, rmk+kernel

On 03/31/16 16:36, Jyri Sarha wrote:
> 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 HDMI 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.
> 

Mark,
There is now two acks (and a tested-by?) to this patch and reviewed-by
to an earlier version (with very small change this this one). I think it
would make sense to apply this one now, even if there are no users to
the driver just yet. Then all the video side users could (at least in
theory) implement the HW specific hdmi audio support with video side
patches only.

What do you think?

Best regards,
Jyri

> Signed-off-by: Jyri Sarha <jsarha@ti.com>
> ---
>  include/sound/hdmi-codec.h    | 100 +++++++++++
>  sound/soc/codecs/Kconfig      |   6 +
>  sound/soc/codecs/Makefile     |   2 +
>  sound/soc/codecs/hdmi-codec.c | 396 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 504 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..fc3a481
> --- /dev/null
> +++ b/include/sound/hdmi-codec.h
> @@ -0,0 +1,100 @@
> +/*
> + * 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 {
> +	/*
> +	 * Called when ASoC starts an audio stream setup.
> +	 * Optional
> +	 */
> +	int (*audio_startup)(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
> +	 */
> +	int (*get_eld)(struct device *dev, uint8_t *buf, size_t len);
> +};
> +
> +/* HDMI codec initalization data */
> +struct hdmi_codec_pdata {
> +	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 50693c8..62b62fe 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -86,6 +86,7 @@ config SND_SOC_ALL_CODECS
>  	select SND_SOC_MC13783 if MFD_MC13XXX
>  	select SND_SOC_ML26124 if I2C
>  	select SND_SOC_NAU8825 if I2C
> +	select SND_SOC_HDMI_CODEC
>  	select SND_SOC_PCM1681 if I2C
>  	select SND_SOC_PCM179X if SPI_MASTER
>  	select SND_SOC_PCM3008
> @@ -473,6 +474,11 @@ config SND_SOC_BT_SCO
>  config SND_SOC_DMIC
>  	tristate
>  
> +config SND_SOC_HDMI_CODEC
> +       tristate
> +       select SND_PCM_ELD
> +       select SND_PCM_IEC958
> +
>  config SND_SOC_ES8328
>  	tristate "Everest Semi ES8328 CODEC"
>  
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index d44f7d3..5f7b002 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -79,6 +79,7 @@ snd-soc-max9850-objs := max9850.o
>  snd-soc-mc13783-objs := mc13783.o
>  snd-soc-ml26124-objs := ml26124.o
>  snd-soc-nau8825-objs := nau8825.o
> +snd-soc-hdmi-codec-objs := hdmi-codec.o
>  snd-soc-pcm1681-objs := pcm1681.o
>  snd-soc-pcm179x-codec-objs := pcm179x.o
>  snd-soc-pcm3008-objs := pcm3008.o
> @@ -283,6 +284,7 @@ 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_NAU8825)   += snd-soc-nau8825.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_PCM179X)	+= snd-soc-pcm179x-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..b46b8ed
> --- /dev/null
> +++ b/sound/soc/codecs/hdmi-codec.c
> @@ -0,0 +1,396 @@
> +/*
> + * 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/pcm_drm_eld.h>
> +#include <sound/hdmi-codec.h>
> +#include <sound/pcm_iec958.h>
> +
> +#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */
> +
> +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[MAX_ELD_BYTES];
> +};
> +
> +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_I2S = 0,
> +	DAI_ID_SPDIF,
> +};
> +
> +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(dai->dev->parent);
> +		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) {
> +		ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->eld,
> +					    sizeof(hcp->eld));
> +
> +		if (!ret) {
> +			ret = snd_pcm_hw_constraint_eld(substream->runtime,
> +							hcp->eld);
> +			if (ret)
> +				return ret;
> +		}
> +	}
> +	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__);
> +
> +	WARN_ON(hcp->current_stream != substream);
> +
> +	hcp->hcd.ops->audio_shutdown(dai->dev->parent);
> +
> +	mutex_lock(&hcp->current_stream_lock);
> +	hcp->current_stream = NULL;
> +	mutex_unlock(&hcp->current_stream_lock);
> +}
> +
> +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 = {
> +		.iec = {
> +			.status = { 0 },
> +			.subcode = { 0 },
> +			.pad = 0,
> +			.dig_subframe = { 0 },
> +		}
> +	};
> +	int ret;
> +
> +	dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,
> +		params_width(params), params_rate(params),
> +		params_channels(params));
> +
> +	if (params_width(params) > 24)
> +		params->msbits = 24;
> +
> +	ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status,
> +						       sizeof(hp.iec.status));
> +	if (ret < 0) {
> +		dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	ret = hdmi_codec_new_stream(substream, dai);
> +	if (ret)
> +		return ret;
> +
> +	hdmi_audio_infoframe_init(&hp.cea);
> +	hp.cea.channels = params_channels(params);
> +	hp.cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
> +	hp.cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
> +	hp.cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
> +
> +	hp.sample_width = params_width(params);
> +	hp.sample_rate = params_rate(params);
> +	hp.channels = params_channels(params);
> +
> +	return hcp->hcd.ops->hw_params(dai->dev->parent, &hcp->daifmt[dai->id],
> +				       &hp);
> +}
> +
> +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(dai->dev->parent, 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_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)
> +
> +/*
> + * This list is only for formats allowed on the I2S bus. So there is
> + * some formats listed that are not supported by HDMI interface. For
> + * instance allowing the 32-bit formats enables 24-precision with CPU
> + * DAIs that do not support 24-bit formats. If the extra formats cause
> + * problems, we should add the video side driver an option to disable
> + * them.
> + */
> +#define I2S_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 |\
> +			 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_I2S,
> +	.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->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(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);
> 

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

* Re: [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders
       [not found]     ` <57160B9F.9090907-l0cyMroinI0@public.gmane.org>
@ 2016-04-19 10:54       ` Mark Brown
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Brown @ 2016-04-19 10:54 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, airlied-cv59FeDIM0c,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	bcousson-rdvid1DuHRBWk0Htik3J/w,
	alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw, tony-4v6yS6AI5VpBDgjK7y7TUQ,
	liam.r.girdwood-VuQAYsv1563Yd54FQh9/CA,
	peter.ujfalusi-l0cyMroinI0, tomi.valkeinen-l0cyMroinI0,
	tiwai-l3A5Bk7waGM, rmk+kernel-lFZ/pmaqli7XmaaqVzeoHQ,
	p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ, arnaud.pouliquen-qxv4g6HH51o

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

On Tue, Apr 19, 2016 at 01:42:39PM +0300, Jyri Sarha wrote:

> There is now two acks (and a tested-by?) to this patch and reviewed-by
> to an earlier version (with very small change this this one). I think it
> would make sense to apply this one now, even if there are no users to
> the driver just yet. Then all the video side users could (at least in
> theory) implement the HW specific hdmi audio support with video side
> patches only.

> What do you think?

I applied it yesterday.

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

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

end of thread, other threads:[~2016-04-19 10:54 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-31 13:35 [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Jyri Sarha
2016-03-31 13:35 ` [PATCH v9 1/7] ALSA: pcm: add IEC958 channel status helper for hw_params Jyri Sarha
2016-03-31 13:42   ` Takashi Iwai
2016-04-06 21:42   ` Applied "ALSA: pcm: add IEC958 channel status helper for hw_params" to the asoc tree Mark Brown
2016-03-31 13:35 ` [PATCH v9 2/7] ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper Jyri Sarha
     [not found]   ` <44ee7ac5c0ddb4d25ac1bd4f189d328f8205e4a0.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
2016-03-31 13:43     ` Takashi Iwai
2016-04-06 21:42   ` Applied "ALSA: pcm: Allow 32 bit sample format in IEC958 channel status helper" to the asoc tree Mark Brown
2016-03-31 13:36 ` [PATCH v9 3/7] ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders Jyri Sarha
2016-04-13  8:06   ` Arnaud Pouliquen
     [not found]   ` <636486b25db48fa13ae640516cdebe7bcfea0d23.1459431292.git.jsarha-l0cyMroinI0@public.gmane.org>
2016-04-14  5:31     ` [alsa-devel] " PC Liao
2016-04-19 10:42   ` Jyri Sarha
     [not found]     ` <57160B9F.9090907-l0cyMroinI0@public.gmane.org>
2016-04-19 10:54       ` Mark Brown
2016-03-31 13:36 ` [PATCH v9 4/7] ASoC: hdmi-codec: Add audio abort() callback for video side to use Jyri Sarha
2016-04-13  8:31   ` Arnaud Pouliquen
2016-04-14  6:21     ` Jyri Sarha
2016-03-31 13:36 ` [PATCH v9 5/7] drm/i2c: tda998x: Improve tda998x_configure_audio() audio related pdata Jyri Sarha
2016-03-31 13:36 ` [PATCH v9 6/7] drm/i2c: tda998x: Register ASoC hdmi-codec and add audio DT binding Jyri Sarha
2016-04-01 18:37   ` Rob Herring
2016-03-31 13:36 ` [PATCH v9 7/7] ARM: dts: am335x-boneblack: Add HDMI audio support Jyri Sarha
2016-04-13  7:02 ` [PATCH v9 0/7] Implement generic ASoC HDMI codec and use it in tda998x Mark Brown
2016-04-13  7:53   ` Jyri Sarha
2016-04-13 17:26     ` Mark Brown

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).