Alsa-Devel Archive on lore.kernel.org
 help / color / Atom feed
* [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support
@ 2015-04-02  9:20 Russell King - ARM Linux
  2015-04-02  9:21 ` [PATCH RFC v2 01/13] drm: imx/dw_hdmi: move phy comments Russell King
                   ` (13 more replies)
  0 siblings, 14 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-04-02  9:20 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, Jaroslav Kysela, Mark Brown, Yakir Yang

I'm sending this series for comments, and to allow people to update
their code bases (for those who are using my AHB audio driver on
iMX6).  This is really several series, and I'm not expecting this
to be ready for the upcoming merge window.  That said, if anyone
wants to say that they're happy with some of the initial six patches,
I'm happy to queue those for David, if he's willing to take them.

This series applies on top of my previous series, with the three
patches from the rockchip guys applied, iow:

 drm: rockchip/dw_hdmi-rockchip: improve for HDMI electrical test
 drm: bridge/dw_hdmi: separate VLEVCTRL settting into platform driver
 drm: bridge/dw_hdmi: fixed codec style
 drm: bridge/dw_hdmi: adjust n/cts setting order
 drm: bridge/dw_hdmi: protect n/cts setting with a mutex
 drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()

The first four patches are a few cleanups to the dw_hdmi driver.

The next two patches introduce new interfaces to the dw_hdmi driver
to support AHB audio, including the errata found on iMX6 which
requires N to be programmed to zero when the audio FIFO is not full.
I'm expecting some discussion with these last two as we try to work
out how to deal with the two variants of audio support for this part
(AHB audio vs I2S audio).

The following three add various helpers to the DRM and ALSA subsystems
for audio support which is non-specific to the AHB audio driver.  For
DRM, this is a helper macro to obtain the pointer into the short audio
descriptors.  For ALSA, it's a set of helpers to restrict an audio PCM
device's capabilities according to the ELD, and to generate the IEC958
channel status data.  If these helpers are acceptable, we can convert
a number of drivers to them.

The ELD helper isn't quite finished, but should be sufficient for
initial testing.

The last two patches add support for the dw_hdmi audio.  This is an
ALSA driver rather than an ASoC driver as it's a pretty simple affair.
I couldn't find a suitable location in the sound/ subtree to place it,
so I've placed it next to the bridge - yes, we probably need to find
it a better home in the sound/ subtree, but it currently makes
use of dw_hdmi.h in the directory it lives.

 drivers/gpu/drm/bridge/Kconfig             |  11 +
 drivers/gpu/drm/bridge/Makefile            |   1 +
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 566 +++++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h |  14 +
 drivers/gpu/drm/bridge/dw_hdmi.c           | 321 +++++++++-------
 drivers/gpu/drm/bridge/dw_hdmi.h           |   3 +
 drivers/gpu/drm/imx/dw_hdmi-imx.c          |   5 +
 include/drm/bridge/dw_hdmi.h               |   7 +
 include/drm/drm_edid.h                     |  19 +
 include/sound/pcm_drm_eld.h                |   6 +
 include/sound/pcm_iec958.h                 |   9 +
 sound/core/Kconfig                         |   6 +
 sound/core/Makefile                        |   2 +
 sound/core/pcm_drm_eld.c                   |  92 +++++
 sound/core/pcm_iec958.c                    |  95 +++++
 15 files changed, 1029 insertions(+), 128 deletions(-)

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH RFC v2 01/13] drm: imx/dw_hdmi: move phy comments
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 02/13] drm: bridge/dw_hdmi: clean up phy configuration Russell King
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

The phy comments in dw_hdmi.c applied to the iMX6 version.  Move these
comments to the iMX6 dw_hdmi-imx data along side the data.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c  | 3 ---
 drivers/gpu/drm/imx/dw_hdmi-imx.c | 5 +++++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 49cafb61d290..3494391e4199 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -834,11 +834,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		    phy_config[i].mpixelclock)
 			break;
 
-	/* RESISTANCE TERM 133Ohm Cfg */
 	hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19);  /* TXTERM */
-	/* PREEMP Cgf 0.00 */
 	hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
-	/* TX/CK LVL 10 */
 	hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */
 
 	/* REMOVE CLK TERM */
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index 1032c07773e3..2b2368f50c39 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -73,6 +73,11 @@ static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = {
 	}
 };
 
+/*
+ * Resistance term 133Ohm Cfg
+ * PREEMP config 0.00
+ * TX/CK level 10
+ */
 static const struct dw_hdmi_phy_config imx_phy_config[] = {
 	/*pixelclk   symbol   term   vlev */
 	{ 148500000, 0x800d, 0x0005, 0x01ad},
-- 
1.8.3.1

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

* [PATCH RFC v2 02/13] drm: bridge/dw_hdmi: clean up phy configuration
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
  2015-04-02  9:21 ` [PATCH RFC v2 01/13] drm: imx/dw_hdmi: move phy comments Russell King
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() Russell King
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

The phy configuration is dependent on the SoC, and we look up values for
some of the registers in SoC specific data.  However, we had partially
programmed the phy before we had successfully looked up the clock rate.
Also, we were only checking that we had a valid configuration for the
currctrl register.

Move all these lookups to the start of this function instead, so we can
check that all lookups were successful before beginning to program the
phy.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 68 +++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 3494391e4199..23ea8c5c85b6 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -753,12 +753,12 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 			      unsigned char res, int cscon)
 {
-	unsigned res_idx, i;
+	unsigned res_idx;
 	u8 val, msec;
-	const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data;
-	const struct dw_hdmi_mpll_config *mpll_config = plat_data->mpll_cfg;
-	const struct dw_hdmi_curr_ctrl *curr_ctrl = plat_data->cur_ctr;
-	const struct dw_hdmi_phy_config *phy_config = plat_data->phy_config;
+	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
+	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
+	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
+	const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
 
 	if (prep)
 		return -EINVAL;
@@ -778,6 +778,30 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		return -EINVAL;
 	}
 
+	/* PLL/MPLL Cfg - always match on final entry */
+	for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    mpll_config->mpixelclock)
+			break;
+
+	for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    curr_ctrl->mpixelclock)
+			break;
+
+	for (; phy_config->mpixelclock != ~0UL; phy_config++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    phy_config->mpixelclock)
+			break;
+
+	if (mpll_config->mpixelclock == ~0UL ||
+	    curr_ctrl->mpixelclock == ~0UL ||
+	    phy_config->mpixelclock == ~0UL) {
+		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
+			hdmi->hdmi_data.video_mode.mpixelclock);
+		return -EINVAL;
+	}
+
 	/* Enable csc path */
 	if (cscon)
 		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
@@ -803,40 +827,18 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		    HDMI_PHY_I2CM_SLAVE_ADDR);
 	hdmi_phy_test_clear(hdmi, 0);
 
-	/* PLL/MPLL Cfg - always match on final entry */
-	for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    mpll_config[i].mpixelclock)
-			break;
-
-	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
-	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
-
-	for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    curr_ctrl[i].mpixelclock)
-			break;
-
-	if (curr_ctrl[i].mpixelclock == (~0UL)) {
-		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
-			hdmi->hdmi_data.video_mode.mpixelclock);
-		return -EINVAL;
-	}
+	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06);
+	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
 
 	/* CURRCTRL */
-	hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
+	hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10);
 
 	hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
 	hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
 
-	for (i = 0; phy_config[i].mpixelclock != (~0UL); i++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    phy_config[i].mpixelclock)
-			break;
-
-	hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19);  /* TXTERM */
-	hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
-	hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */
+	hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19);  /* TXTERM */
+	hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
+	hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
 
 	/* REMOVE CLK TERM */
 	hdmi_phy_i2c_write(hdmi, 0x8000, 0x05);  /* CKCALCTRL */
-- 
1.8.3.1

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

* [PATCH RFC v2 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator()
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
  2015-04-02  9:21 ` [PATCH RFC v2 01/13] drm: imx/dw_hdmi: move phy comments Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 02/13] drm: bridge/dw_hdmi: clean up phy configuration Russell King
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode() Russell King
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

Clean up hdmi_set_clk_regenerator() by allowing it to take the audio
sample rate and ratio directly, rather than hiding it inside the
function.  Raise the unsupported pixel clock/sample rate message from
debug to error level as this results in audio not working correctly.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 23ea8c5c85b6..75099b80ca7e 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -335,39 +335,37 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 }
 
 static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
-				     unsigned long pixel_clk)
+	unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio)
 {
-	unsigned int clk_n, clk_cts;
+	unsigned int n, cts;
 
-	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
-			       hdmi->ratio);
-	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
-				   hdmi->ratio);
-
-	if (!clk_cts) {
-		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-			__func__, pixel_clk);
-		return;
+	n = hdmi_compute_n(sample_rate, pixel_clk, ratio);
+	cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio);
+	if (!cts) {
+		dev_err(hdmi->dev,
+			"%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n",
+			__func__, pixel_clk, sample_rate);
 	}
 
-	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
-		__func__, hdmi->sample_rate, hdmi->ratio,
-		pixel_clk, clk_n, clk_cts);
+	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
+		__func__, sample_rate, ratio, pixel_clk, n, cts);
 
-	hdmi_set_cts_n(hdmi, clk_cts, clk_n);
+	hdmi_set_cts_n(hdmi, cts, n);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
 {
 	mutex_lock(&hdmi->audio_mutex);
-	hdmi_set_clk_regenerator(hdmi, 74250000);
+	hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate,
+				 hdmi->ratio);
 	mutex_unlock(&hdmi->audio_mutex);
 }
 
 static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
 {
 	mutex_lock(&hdmi->audio_mutex);
-	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+				 hdmi->sample_rate, hdmi->ratio);
 	mutex_unlock(&hdmi->audio_mutex);
 }
 
-- 
1.8.3.1

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

* [PATCH RFC v2 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode()
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (2 preceding siblings ...)
  2015-04-02  9:21 ` [PATCH RFC v2 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() Russell King
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little Russell King
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

Use drm_hdmi_avi_infoframe_from_display_mode() to compose the AVI
frame.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 126 +++++++++++++++++++++------------------
 1 file changed, 67 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 75099b80ca7e..0f3ccfa3ccfc 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -918,74 +918,79 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
 		  HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
 }
 
-static void hdmi_config_AVI(struct dw_hdmi *hdmi)
+static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 {
-	u8 val, pix_fmt, under_scan;
-	u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry;
-	bool aspect_16_9;
+	struct hdmi_avi_infoframe frame;
+	u8 val;
 
-	aspect_16_9 = false; /* FIXME */
+	/* Initialise info frame from DRM mode */
+	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 
-	/* AVI Data Byte 1 */
 	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
-		pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444;
+		frame.colorspace = HDMI_COLORSPACE_YUV444;
 	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
-		pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422;
+		frame.colorspace = HDMI_COLORSPACE_YUV422;
 	else
-		pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB;
-
-		under_scan =  HDMI_FC_AVICONF0_SCAN_INFO_NODATA;
-
-	/*
-	 * Active format identification data is present in the AVI InfoFrame.
-	 * Under scan info, no bar data
-	 */
-	val = pix_fmt | under_scan |
-		HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT |
-		HDMI_FC_AVICONF0_BAR_DATA_NO_DATA;
-
-	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
-
-	/* AVI Data Byte 2 -Set the Aspect Ratio */
-	if (aspect_16_9) {
-		act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9;
-		coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9;
-	} else {
-		act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3;
-		coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3;
-	}
+		frame.colorspace = HDMI_COLORSPACE_RGB;
 
 	/* Set up colorimetry */
 	if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
-		colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO;
+		frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
 		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-			ext_colorimetry =
-				HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+			frame.extended_colorimetry =
+				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-			ext_colorimetry =
-				HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709;
+			frame.extended_colorimetry =
+				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
 	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
 		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-			colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE;
+			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
 		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-			colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
-		ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 	} else { /* Carries no data */
-		colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA;
-		ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+		frame.colorimetry = HDMI_COLORIMETRY_NONE;
+		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 	}
 
-	val = colorimetry | coded_ratio | act_ratio;
+	frame.scan_mode = HDMI_SCAN_MODE_NONE;
+
+	/*
+	 * The Designware IP uses a different byte format from standard
+	 * AVI info frames, though generally the bits are in the correct
+	 * bytes.
+	 */
+
+	/*
+	 * AVI data byte 1 differences: Colorspace in bits 4,5 rather than 5,6,
+	 * active aspect present in bit 6 rather than 4.
+	 */
+	val = (frame.colorspace & 3) << 4 | (frame.scan_mode & 0x3);
+	if (frame.active_aspect & 15)
+		val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT;
+	if (frame.top_bar || frame.bottom_bar)
+		val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR;
+	if (frame.left_bar || frame.right_bar)
+		val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR;
+	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
+
+	/* AVI data byte 2 differences: none */
+	val = ((frame.colorimetry & 0x3) << 6) |
+	      ((frame.picture_aspect & 0x3) << 4) |
+	      (frame.active_aspect & 0xf);
 	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1);
 
-	/* AVI Data Byte 3 */
-	val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry |
-		HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT |
-		HDMI_FC_AVICONF2_SCALING_NONE;
+	/* AVI data byte 3 differences: none */
+	val = ((frame.extended_colorimetry & 0x7) << 4) |
+	      ((frame.quantization_range & 0x3) << 2) |
+	      (frame.nups & 0x3);
+	if (frame.itc)
+		val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID;
 	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2);
 
-	/* AVI Data Byte 4 */
-	hdmi_writeb(hdmi, hdmi->vic, HDMI_FC_AVIVID);
+	/* AVI data byte 4 differences: none */
+	val = frame.video_code & 0x7f;
+	hdmi_writeb(hdmi, val, HDMI_FC_AVIVID);
 
 	/* AVI Data Byte 5- set up input and output pixel repetition */
 	val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) <<
@@ -996,20 +1001,23 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi)
 		HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
 	hdmi_writeb(hdmi, val, HDMI_FC_PRCONF);
 
-	/* IT Content and quantization range = don't care */
-	val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS |
-		HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED;
+	/*
+	 * AVI data byte 5 differences: content type in 0,1 rather than 4,5,
+	 * ycc range in bits 2,3 rather than 6,7
+	 */
+	val = ((frame.ycc_quantization_range & 0x3) << 2) |
+	      (frame.content_type & 0x3);
 	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3);
 
 	/* AVI Data Bytes 6-13 */
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB1);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB1);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB1);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1);
+	hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0);
+	hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1);
+	hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0);
+	hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1);
+	hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0);
+	hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1);
+	hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0);
+	hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
 }
 
 static void hdmi_av_composer(struct dw_hdmi *hdmi,
@@ -1243,7 +1251,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 		hdmi_enable_audio_clk(hdmi);
 
 		/* HDMI Initialization Step F - Configure AVI InfoFrame */
-		hdmi_config_AVI(hdmi);
+		hdmi_config_AVI(hdmi, mode);
 	}
 
 	hdmi_video_packetize(hdmi);
-- 
1.8.3.1

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

* [PATCH RFC v2 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (3 preceding siblings ...)
  2015-04-02  9:21 ` [PATCH RFC v2 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode() Russell King
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced Russell King
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

When a YCBCR format is selected, we can merely copy the colorimetry
information directly as we use the same definitions for both the
unpacked AVI info frame and the hdmi_data_info structure.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 0f3ccfa3ccfc..a8bd3fbf4300 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -943,10 +943,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 			frame.extended_colorimetry =
 				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
 	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
-		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
-		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+		frame.colorimetry = hdmi->hdmi_data.colorimetry;
 		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 	} else { /* Carries no data */
 		frame.colorimetry = HDMI_COLORIMETRY_NONE;
-- 
1.8.3.1

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

* [PATCH RFC v2 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (4 preceding siblings ...)
  2015-04-02  9:21 ` [PATCH RFC v2 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little Russell King
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate Russell King
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

Remove the struct hdmi_vmode mhsyncpolarity/mvsyncpolarity/minterlaced
members, which are only used within a single function.  We can directly
reference the appropriate mode->flags instead.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index a8bd3fbf4300..75728ba552d0 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -82,9 +82,6 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
 
 struct hdmi_vmode {
 	bool mdvi;
-	bool mhsyncpolarity;
-	bool mvsyncpolarity;
-	bool minterlaced;
 	bool mdataenablepolarity;
 
 	unsigned int mpixelclock;
@@ -1024,9 +1021,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
 	int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
 
-	vmode->mhsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC);
-	vmode->mvsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC);
-	vmode->minterlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
 	vmode->mpixelclock = mode->clock * 1000;
 
 	dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
@@ -1036,13 +1030,13 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 		HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
 		HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
 
-	inv_val |= (vmode->mvsyncpolarity ?
+	inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
 		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
-		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
+		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW;
 
-	inv_val |= (vmode->mhsyncpolarity ?
+	inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
 		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
-		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
+		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW;
 
 	inv_val |= (vmode->mdataenablepolarity ?
 		HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
@@ -1051,13 +1045,13 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	if (hdmi->vic == 39)
 		inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
 	else
-		inv_val |= (vmode->minterlaced ?
+		inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
 			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
-			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
+			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
 
-	inv_val |= (vmode->minterlaced ?
+	inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
 		HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
-		HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
+		HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
 
 	inv_val |= (vmode->mdvi ?
 		HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
-- 
1.8.3.1

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

* [PATCH RFC v2 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (5 preceding siblings ...)
  2015-04-02  9:21 ` [PATCH RFC v2 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced Russell King
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:21 ` [PATCH RFC v2 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio Russell King
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

Introduce dw_hdmi_set_sample_rate(), which allows us to configure the
audio sample rate, setting the CTS/N values appropriately.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 10 ++++++++++
 include/drm/bridge/dw_hdmi.h     |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 75728ba552d0..0369fab5c695 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -366,6 +366,16 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
 	mutex_unlock(&hdmi->audio_mutex);
 }
 
+void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
+{
+	mutex_lock(&hdmi->audio_mutex);
+	hdmi->sample_rate = rate;
+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+				 hdmi->sample_rate, hdmi->ratio);
+	mutex_unlock(&hdmi->audio_mutex);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
+
 /*
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index de13bfc35634..763af51e1d60 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -12,6 +12,8 @@
 
 #include <drm/drmP.h>
 
+struct dw_hdmi;
+
 enum {
 	DW_HDMI_RES_8,
 	DW_HDMI_RES_10,
@@ -59,4 +61,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		 void *data, struct drm_encoder *encoder,
 		 struct resource *iores, int irq,
 		 const struct dw_hdmi_plat_data *plat_data);
+
+void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
+
 #endif /* __IMX_HDMI_H__ */
-- 
1.8.3.1

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

* [PATCH RFC v2 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (6 preceding siblings ...)
  2015-04-02  9:21 ` [PATCH RFC v2 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate Russell King
@ 2015-04-02  9:21 ` Russell King
  2015-04-02  9:22 ` [PATCH RFC v2 09/13] drm/edid: add function to help find SADs Russell King
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:21 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

iMX6 devices suffer from an errata (ERR005174) where the audio FIFO can
be emptied while it is partially full, resulting in misalignment of the
audio samples.

To prevent this, the errata workaround recommends writing N as zero
until the audio FIFO has been loaded by DMA.  Writing N=0 prevents the
HDMI bridge from reading from the audio FIFO, effectively disabling
audio.

This means we need to provide the audio driver with a pair of functions
to enable/disable audio.  These are dw_hdmi_audio_enable() and
dw_hdmi_audio_disable().

A spinlock is introduced to ensure that setting the CTS/N values can't
race, ensuring that the audio driver calling the enable/disable
functions (which are called in an atomic context) can't race with a
modeset.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 34 +++++++++++++++++++++++++++++++++-
 include/drm/bridge/dw_hdmi.h     |  2 ++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 0369fab5c695..adda3a988f36 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -18,6 +18,7 @@
 #include <linux/hdmi.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
+#include <linux/spinlock.h>
 
 #include <drm/drm_of.h>
 #include <drm/drmP.h>
@@ -124,8 +125,12 @@ struct dw_hdmi {
 	struct i2c_adapter *ddc;
 	void __iomem *regs;
 
+	spinlock_t audio_lock;
 	struct mutex audio_mutex;
 	unsigned int sample_rate;
+	unsigned int audio_cts;
+	unsigned int audio_n;
+	bool audio_enable;
 	int ratio;
 
 	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
@@ -347,7 +352,11 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
 		__func__, sample_rate, ratio, pixel_clk, n, cts);
 
-	hdmi_set_cts_n(hdmi, cts, n);
+	spin_lock_irq(&hdmi->audio_lock);
+	hdmi->audio_n = n;
+	hdmi->audio_cts = cts;
+	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
+	spin_unlock_irq(&hdmi->audio_lock);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
@@ -376,6 +385,28 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
 
+void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hdmi->audio_lock, flags);
+	hdmi->audio_enable = true;
+	hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
+	spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
+
+void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hdmi->audio_lock, flags);
+	hdmi->audio_enable = false;
+	hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
+	spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
+
 /*
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
@@ -1578,6 +1609,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 	hdmi->encoder = encoder;
 
 	mutex_init(&hdmi->audio_mutex);
+	spin_lock_init(&hdmi->audio_lock);
 
 	of_property_read_u32(np, "reg-io-width", &val);
 
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 763af51e1d60..bae79f3c4d28 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -63,5 +63,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		 const struct dw_hdmi_plat_data *plat_data);
 
 void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
+void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
+void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
 
 #endif /* __IMX_HDMI_H__ */
-- 
1.8.3.1

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

* [PATCH RFC v2 09/13] drm/edid: add function to help find SADs
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (7 preceding siblings ...)
  2015-04-02  9:21 ` [PATCH RFC v2 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio Russell King
@ 2015-04-02  9:22 ` Russell King
  2015-04-02  9:22 ` [PATCH RFC v2 10/13] sound/core: add DRM ELD helper Russell King
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:22 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

Add a function to find the start of the SADs in the ELD.  This
complements the helper to retrieve the SAD count.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 include/drm/drm_edid.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 87d85e81d3a7..c44ad513e0f7 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -346,6 +346,25 @@ static inline int drm_eld_mnl(const uint8_t *eld)
 }
 
 /**
+ * drm_eld_sad - Get ELD SAD structures.
+ * @eld: pointer to an eld memory structure with sad_count set
+ */
+static inline const uint8_t *drm_eld_sad(const uint8_t *eld)
+{
+	unsigned int ver, mnl;
+
+	ver = (eld[DRM_ELD_VER] & DRM_ELD_VER_MASK) >> DRM_ELD_VER_SHIFT;
+	if (ver != 2 && ver != 31)
+		return NULL;
+
+	mnl = drm_eld_mnl(eld);
+	if (mnl > 16)
+		return NULL;
+
+	return eld + DRM_ELD_CEA_SAD(mnl, 0);
+}
+
+/**
  * drm_eld_sad_count - Get ELD SAD count.
  * @eld: pointer to an eld memory structure with sad_count set
  */
-- 
1.8.3.1

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

* [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (8 preceding siblings ...)
  2015-04-02  9:22 ` [PATCH RFC v2 09/13] drm/edid: add function to help find SADs Russell King
@ 2015-04-02  9:22 ` Russell King
  2015-04-05 15:57   ` Takashi Iwai
  2015-05-08 13:16   ` [alsa-devel] " Jyri Sarha
  2015-04-02  9:22 ` [PATCH RFC v2 11/13] sound/core: add IEC958 channel status helper Russell King
                   ` (3 subsequent siblings)
  13 siblings, 2 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:22 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, Takashi Iwai, Mark Brown, Philipp Zabel, Yakir Yang

Add a helper for the EDID like data structure, which is typically passed
from a HDMI adapter to its associated audio driver.  This informs the
audio driver of the capabilities of the attached HDMI sink.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 include/sound/pcm_drm_eld.h |  6 +++
 sound/core/Kconfig          |  3 ++
 sound/core/Makefile         |  1 +
 sound/core/pcm_drm_eld.c    | 92 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+)
 create mode 100644 include/sound/pcm_drm_eld.h
 create mode 100644 sound/core/pcm_drm_eld.c

diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
new file mode 100644
index 000000000000..93357b25d2e2
--- /dev/null
+++ b/include/sound/pcm_drm_eld.h
@@ -0,0 +1,6 @@
+#ifndef __SOUND_PCM_DRM_ELD_H
+#define __SOUND_PCM_DRM_ELD_H
+
+int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
+
+#endif
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 313f22e9d929..b534c8a6046b 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -6,6 +6,9 @@ config SND_PCM
 	tristate
 	select SND_TIMER
 
+config SND_PCM_ELD
+	bool
+
 config SND_DMAENGINE_PCM
 	tristate
 
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 4daf2f58261c..591b49157b4d 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -13,6 +13,7 @@ snd-$(CONFIG_SND_JACK)	  += jack.o
 snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
 		pcm_memory.o memalloc.o
 snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
+snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o
 
 # for trace-points
 CFLAGS_pcm_lib.o := -I$(src)
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
new file mode 100644
index 000000000000..47d9b60435fe
--- /dev/null
+++ b/sound/core/pcm_drm_eld.c
@@ -0,0 +1,92 @@
+/*
+ *  PCM DRM helpers
+ *
+ *   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.
+ */
+#include <linux/export.h>
+#include <drm/drm_edid.h>
+#include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
+
+static const unsigned int eld_rates[] = {
+	32000,
+	44100,
+	48000,
+	88200,
+	96000,
+	176400,
+	192000,
+};
+
+static int eld_limit_rates(struct snd_pcm_hw_params *params,
+			   struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval *r = hw_param_interval(params, rule->var);
+	struct snd_interval *c;
+	unsigned int rate_mask = 7, i;
+	const u8 *sad, *eld = rule->private;
+
+	sad = drm_eld_sad(eld);
+	if (sad) {
+		c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
+			unsigned channels = 1 + (sad[0] & 7);
+
+			/*
+			 * Exclude SADs which do not include the
+			 * requested number of channels.
+			 */
+			if (c->min <= channels)
+				rate_mask |= sad[1];
+		}
+printk("%s: r %d-%d c %d-%d m %x\n", __func__, r->min, r->max, c->min, c->max, rate_mask);
+	}
+
+	return snd_interval_list(r, ARRAY_SIZE(eld_rates), eld_rates,
+				 rate_mask);
+}
+
+static int eld_limit_channels(struct snd_pcm_hw_params *params,
+			      struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval *var = hw_param_interval(params, rule->var);
+	struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
+	unsigned int i;
+	const u8 *sad, *eld = rule->private;
+
+	sad = drm_eld_sad(eld);
+	if (sad) {
+		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
+			switch (sad[0] & 0x78) {
+			case 0x08:
+				t.max = max(t.max, (sad[0] & 7) + 1u);
+				break;
+			}
+		}
+	}
+
+	return snd_interval_refine(var, &t);
+}
+
+int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld)
+{
+	int ret;
+
+	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				  eld_limit_rates, eld,
+				  SNDRV_PCM_HW_PARAM_RATE,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  eld_limit_channels, eld,
+				  SNDRV_PCM_HW_PARAM_CHANNELS,
+				  SNDRV_PCM_HW_PARAM_RATE, -1);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_pcm_hw_constraint_eld);
-- 
1.8.3.1

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

* [PATCH RFC v2 11/13] sound/core: add IEC958 channel status helper
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (9 preceding siblings ...)
  2015-04-02  9:22 ` [PATCH RFC v2 10/13] sound/core: add DRM ELD helper Russell King
@ 2015-04-02  9:22 ` Russell King
  2015-04-02  9:22 ` [PATCH RFC v2 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver Russell King
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:22 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, Takashi Iwai, Mark Brown, Philipp Zabel, Yakir Yang

Add a helper to create the IEC958 channel status from an ALSA
snd_pcm_runtime structure, taking account of the sample rate and
sample size.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 include/sound/pcm_iec958.h |  9 +++++
 sound/core/Kconfig         |  3 ++
 sound/core/Makefile        |  1 +
 sound/core/pcm_iec958.c    | 95 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 108 insertions(+)
 create mode 100644 include/sound/pcm_iec958.h
 create mode 100644 sound/core/pcm_iec958.c

diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
new file mode 100644
index 000000000000..0eed397aca8e
--- /dev/null
+++ b/include/sound/pcm_iec958.h
@@ -0,0 +1,9 @@
+#ifndef __SOUND_PCM_IEC958_H
+#define __SOUND_PCM_IEC958_H
+
+#include <linux/types.h>
+
+int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
+	size_t len);
+
+#endif
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index b534c8a6046b..1507469425ec 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -9,6 +9,9 @@ config SND_PCM
 config SND_PCM_ELD
 	bool
 
+config SND_PCM_IEC958
+	bool
+
 config SND_DMAENGINE_PCM
 	tristate
 
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 591b49157b4d..2b925fcc95ea 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -14,6 +14,7 @@ snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
 		pcm_memory.o memalloc.o
 snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
 snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o
+snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
 
 # for trace-points
 CFLAGS_pcm_lib.o := -I$(src)
diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
new file mode 100644
index 000000000000..36b2d7aca1bd
--- /dev/null
+++ b/sound/core/pcm_iec958.c
@@ -0,0 +1,95 @@
+/*
+ *  PCM DRM helpers
+ *
+ *   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.
+ */
+#include <linux/export.h>
+#include <linux/types.h>
+#include <sound/asoundef.h>
+#include <sound/pcm.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)
+{
+	unsigned int fs, ws;
+
+	if (len < 4)
+		return -EINVAL;
+
+	switch (runtime->rate) {
+	case 32000:
+		fs = IEC958_AES3_CON_FS_32000;
+		break;
+	case 44100:
+		fs = IEC958_AES3_CON_FS_44100;
+		break;
+	case 48000:
+		fs = IEC958_AES3_CON_FS_48000;
+		break;
+	case 88200:
+		fs = IEC958_AES3_CON_FS_88200;
+		break;
+	case 96000:
+		fs = IEC958_AES3_CON_FS_96000;
+		break;
+	case 176400:
+		fs = IEC958_AES3_CON_FS_176400;
+		break;
+	case 192000:
+		fs = IEC958_AES3_CON_FS_192000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (len > 4) {
+		switch (snd_pcm_format_width(runtime->format)) {
+		case 16:
+			ws = IEC958_AES4_CON_WORDLEN_20_16;
+			break;
+		case 18:
+			ws = IEC958_AES4_CON_WORDLEN_22_18;
+			break;
+		case 20:
+			ws = IEC958_AES4_CON_WORDLEN_20_16 |
+			     IEC958_AES4_CON_MAX_WORDLEN_24;
+			break;
+		case 24:
+			ws = IEC958_AES4_CON_WORDLEN_24_20 |
+			     IEC958_AES4_CON_MAX_WORDLEN_24;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	memset(cs, 0, len);
+
+	cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
+	cs[1] = IEC958_AES1_CON_GENERAL;
+	cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
+	cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
+
+	if (len > 4)
+		cs[4] = ws;
+
+	return len;
+}
+EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
-- 
1.8.3.1

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

* [PATCH RFC v2 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (10 preceding siblings ...)
  2015-04-02  9:22 ` [PATCH RFC v2 11/13] sound/core: add IEC958 channel status helper Russell King
@ 2015-04-02  9:22 ` Russell King
  2015-04-02  9:22 ` [PATCH RFC v2 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver Russell King
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:22 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

Add ALSA based HDMI AHB audio driver for dw_hdmi.  The only buffer
format supported by the hardware is its own special IEC958 based format,
which is not compatible with any ALSA format.  To avoid doing too much
data manipulation within the driver, we support only ALSAs IEC958 LE and
24-bit PCM formats for 2 to 6 channels, which we convert to its hardware
format.

A more desirable solution would be to have this conversion in userspace,
but ALSA does not appear to allow such transformations outside of
libasound itself.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/Kconfig             |  10 +
 drivers/gpu/drm/bridge/Makefile            |   1 +
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 560 +++++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h |  13 +
 drivers/gpu/drm/bridge/dw_hdmi.c           |  24 ++
 drivers/gpu/drm/bridge/dw_hdmi.h           |   3 +
 6 files changed, 611 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
 create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index f38bbcdf929b..557962a67fc5 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -3,6 +3,16 @@ config DRM_DW_HDMI
 	depends on DRM
 	select DRM_KMS_HELPER
 
+config DRM_DW_HDMI_AHB_AUDIO
+	tristate "Synopsis Designware AHB Audio interface"
+	depends on DRM_DW_HDMI && SND
+	select SND_PCM
+	select SND_PCM_IEC958
+	help
+	  Support the AHB Audio interface which is part of the Synopsis
+	  Designware HDMI block.  This is used in conjunction with
+	  the i.MX6 HDMI driver.
+
 config DRM_PTN3460
 	tristate "PTN3460 DP/LVDS bridge"
 	depends on DRM
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index d8a8cfd12fbb..ebc51905f1df 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,3 +2,4 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_PTN3460) += ptn3460.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw_hdmi-ahb-audio.o
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
new file mode 100644
index 000000000000..e98c291268f4
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
@@ -0,0 +1,560 @@
+/*
+ * DesignWare HDMI audio driver
+ *
+ * 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.
+ *
+ * Written and tested against the Designware HDMI Tx found in iMX6.
+ */
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <drm/bridge/dw_hdmi.h>
+
+#include <sound/asoundef.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_iec958.h>
+
+#include "dw_hdmi-ahb-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-ahb-audio"
+
+/* Provide some bits rather than bit offsets */
+enum {
+	HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7),
+	HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3),
+	HDMI_AHB_DMA_START_START = BIT(0),
+	HDMI_AHB_DMA_STOP_STOP = BIT(0),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL =
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY,
+	HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5),
+	HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4),
+	HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3),
+	HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2),
+	HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
+	HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
+	HDMI_IH_AHBDMAAUD_STAT0_ALL =
+		HDMI_IH_AHBDMAAUD_STAT0_ERROR |
+		HDMI_IH_AHBDMAAUD_STAT0_LOST |
+		HDMI_IH_AHBDMAAUD_STAT0_RETRY |
+		HDMI_IH_AHBDMAAUD_STAT0_DONE |
+		HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL |
+		HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY,
+	HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1,
+	HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1,
+	HDMI_AHB_DMA_CONF0_INCR4 = 0,
+	HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0),
+	HDMI_AHB_DMA_MASK_DONE = BIT(7),
+	HDMI_REVISION_ID = 0x0001,
+	HDMI_IH_AHBDMAAUD_STAT0 = 0x0109,
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189,
+	HDMI_AHB_DMA_CONF0 = 0x3600,
+	HDMI_AHB_DMA_START = 0x3601,
+	HDMI_AHB_DMA_STOP = 0x3602,
+	HDMI_AHB_DMA_THRSLD = 0x3603,
+	HDMI_AHB_DMA_STRADDR0 = 0x3604,
+	HDMI_AHB_DMA_STPADDR0 = 0x3608,
+	HDMI_AHB_DMA_MASK = 0x3614,
+	HDMI_AHB_DMA_POL = 0x3615,
+	HDMI_AHB_DMA_CONF1 = 0x3616,
+	HDMI_AHB_DMA_BUFFPOL = 0x361a,
+};
+
+struct snd_dw_hdmi {
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	struct dw_hdmi_audio_data data;
+	struct snd_pcm_substream *substream;
+	void (*reformat)(struct snd_dw_hdmi *, size_t, size_t);
+	void *buf_src;
+	void *buf_dst;
+	dma_addr_t buf_addr;
+	unsigned buf_offset;
+	unsigned buf_period;
+	unsigned buf_size;
+	unsigned channels;
+	u8 revision;
+	u8 iec_offset;
+	u8 cs[192][8];
+};
+
+static void dw_hdmi_writel(unsigned long val, void __iomem *ptr)
+{
+	writeb_relaxed(val, ptr);
+	writeb_relaxed(val >> 8, ptr + 1);
+	writeb_relaxed(val >> 16, ptr + 2);
+	writeb_relaxed(val >> 24, ptr + 3);
+}
+
+/*
+ * Convert to hardware format: The userspace buffer contains IEC958 samples,
+ * with the PCUV bits in bits 31..28 and audio samples in bits 27..4.  We
+ * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio
+ * samples in 23..0.
+ *
+ * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd
+ *
+ * Ideally, we could do with having the data properly formatted in userspace.
+ */
+static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw,
+	size_t offset, size_t bytes)
+{
+	u32 *src = dw->buf_src + offset;
+	u32 *dst = dw->buf_dst + offset;
+	u32 *end = dw->buf_src + offset + bytes;
+
+	do {
+		u32 b, sample = *src++;
+
+		b = (sample & 8) << (28 - 3);
+
+		sample >>= 4;
+
+		*dst++ = sample | b;
+	} while (src < end);
+}
+
+static u32 parity(u32 sample)
+{
+	sample ^= sample >> 16;
+	sample ^= sample >> 8;
+	sample ^= sample >> 4;
+	sample ^= sample >> 2;
+	sample ^= sample >> 1;
+	return (sample & 1) << 27;
+}
+
+static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw,
+	size_t offset, size_t bytes)
+{
+	u32 *src = dw->buf_src + offset;
+	u32 *dst = dw->buf_dst + offset;
+	u32 *end = dw->buf_src + offset + bytes;
+
+	do {
+		unsigned i;
+		u8 *cs;
+
+		cs = dw->cs[dw->iec_offset++];
+		if (dw->iec_offset >= 192)
+			dw->iec_offset = 0;
+
+		i = dw->channels;
+		do {
+			u32 sample = *src++;
+
+			sample &= ~0xff000000;
+			sample |= *cs++ << 24;
+			sample |= parity(sample & ~0xf8000000);
+
+			*dst++ = sample;
+		} while (--i);
+	} while (src < end);
+}
+
+static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw,
+	struct snd_pcm_runtime *runtime)
+{
+	u8 cs[4];
+	unsigned ch, i, j;
+
+	snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs));
+
+	memset(dw->cs, 0, sizeof(dw->cs));
+
+	for (ch = 0; ch < 8; ch++) {
+		cs[2] &= ~IEC958_AES2_CON_CHANNEL;
+		cs[2] |= (ch + 1) << 4;
+
+		for (i = 0; i < ARRAY_SIZE(cs); i++) {
+			unsigned c = cs[i];
+
+			for (j = 0; j < 8; j++, c >>= 1)
+				dw->cs[i * 8 + j][ch] = (c & 1) << 2;
+		}
+	}
+	dw->cs[0][0] |= BIT(4);
+}
+
+static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw)
+{
+	void __iomem *base = dw->data.base;
+	unsigned offset = dw->buf_offset;
+	unsigned period = dw->buf_period;
+	u32 start, stop;
+
+	dw->reformat(dw, offset, period);
+
+	/* Clear all irqs before enabling irqs and starting DMA */
+	writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL,
+		       base + HDMI_IH_AHBDMAAUD_STAT0);
+
+	start = dw->buf_addr + offset;
+	stop = start + period - 1;
+
+	/* Setup the hardware start/stop addresses */
+	dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0);
+	dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0);
+
+	writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK);
+	writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START);
+
+	offset += period;
+	if (offset >= dw->buf_size)
+		offset = 0;
+	dw->buf_offset = offset;
+}
+
+static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw)
+{
+	dw->substream = NULL;
+
+	/* Disable interrupts before disabling DMA */
+	writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK);
+	writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP);
+}
+
+static irqreturn_t snd_dw_hdmi_irq(int irq, void *data)
+{
+	struct snd_dw_hdmi *dw = data;
+	struct snd_pcm_substream *substream;
+	unsigned stat;
+
+	stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
+	if (!stat)
+		return IRQ_NONE;
+
+	writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
+
+	substream = dw->substream;
+	if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) {
+		snd_pcm_period_elapsed(substream);
+		if (dw->substream)
+			dw_hdmi_start_dma(dw);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct snd_pcm_hardware dw_hdmi_hw = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
+		   SNDRV_PCM_FMTBIT_S24_LE,
+	.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,
+	.channels_min = 2,
+	.channels_max = 8,
+	.buffer_bytes_max = 64 * 1024,
+	.period_bytes_min = 256,
+	.period_bytes_max = 8192,	/* ERR004323: must limit to 8k */
+	.periods_min = 2,
+	.periods_max = 16,
+	.fifo_size = 0,
+};
+
+static int dw_hdmi_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dw_hdmi *dw = substream->private_data;
+	void __iomem *base = dw->data.base;
+	int ret;
+
+	runtime->hw = dw_hdmi_hw;
+
+	ret = snd_pcm_limit_hw_rates(runtime);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		return ret;
+
+	/* Clear FIFO */
+	writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST,
+		       base + HDMI_AHB_DMA_CONF0);
+
+	/* Configure interrupt polarities */
+	writeb_relaxed(~0, base + HDMI_AHB_DMA_POL);
+	writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL);
+
+	/* Keep interrupts masked, and clear any pending */
+	writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK);
+	writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0);
+
+	ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED,
+			  "dw-hdmi-audio", dw);
+	if (ret)
+		return ret;
+
+	/* Un-mute done interrupt */
+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL &
+		       ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE,
+		       base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+	return 0;
+}
+
+static int dw_hdmi_close(struct snd_pcm_substream *substream)
+{
+	struct snd_dw_hdmi *dw = substream->private_data;
+
+	/* Mute all interrupts */
+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
+		       dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+	free_irq(dw->data.irq, dw);
+
+	return 0;
+}
+
+static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+						params_buffer_bytes(params));
+}
+
+static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dw_hdmi *dw = substream->private_data;
+	u8 threshold, conf0, conf1;
+
+	/* Setup as per 3.0.5 FSL 4.1.0 BSP */
+	switch (dw->revision) {
+	case 0x0a:
+		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
+			HDMI_AHB_DMA_CONF0_INCR4;
+		if (runtime->channels == 2)
+			threshold = 126;
+		else
+			threshold = 124;
+		break;
+	case 0x1a:
+		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
+			HDMI_AHB_DMA_CONF0_INCR8;
+		threshold = 128;
+		break;
+	default:
+		/* NOTREACHED */
+		return -EINVAL;
+	}
+
+	dw_hdmi_set_sample_rate(dw->data.hdmi, runtime->rate);
+
+	/* Minimum number of bytes in the fifo. */
+	runtime->hw.fifo_size = threshold * 32;
+
+	conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK;
+	conf1 = (1 << runtime->channels) - 1;
+
+	writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD);
+	writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0);
+	writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1);
+
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+		dw->reformat = dw_hdmi_reformat_iec958;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		dw_hdmi_create_cs(dw, runtime);
+		dw->reformat = dw_hdmi_reformat_s24;
+		break;
+	}
+	dw->iec_offset = 0;
+	dw->channels = runtime->channels;
+	dw->buf_src  = runtime->dma_area;
+	dw->buf_dst  = substream->dma_buffer.area;
+	dw->buf_addr = substream->dma_buffer.addr;
+	dw->buf_period = snd_pcm_lib_period_bytes(substream);
+	dw->buf_size = snd_pcm_lib_buffer_bytes(substream);
+
+	return 0;
+}
+
+static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_dw_hdmi *dw = substream->private_data;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		dw->buf_offset = 0;
+		dw->substream = substream;
+		dw_hdmi_start_dma(dw);
+		dw_hdmi_audio_enable(dw->data.hdmi);
+		substream->runtime->delay = substream->runtime->period_size;
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_hdmi_stop_dma(dw);
+		dw_hdmi_audio_disable(dw->data.hdmi);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dw_hdmi *dw = substream->private_data;
+
+	return bytes_to_frames(runtime, dw->buf_offset);
+}
+
+static struct snd_pcm_ops snd_dw_hdmi_ops = {
+	.open = dw_hdmi_open,
+	.close = dw_hdmi_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = dw_hdmi_hw_params,
+	.hw_free = dw_hdmi_hw_free,
+	.prepare = dw_hdmi_prepare,
+	.trigger = dw_hdmi_trigger,
+	.pointer = dw_hdmi_pointer,
+	.page = snd_pcm_lib_get_vmalloc_page,
+};
+
+static int snd_dw_hdmi_probe(struct platform_device *pdev)
+{
+	const struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
+	struct device *dev = pdev->dev.parent;
+	struct snd_dw_hdmi *dw;
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	unsigned revision;
+	int ret;
+
+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
+		       data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+	revision = readb_relaxed(data->base + HDMI_REVISION_ID);
+	if (revision != 0x0a && revision != 0x1a) {
+		dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n",
+			revision);
+		return -ENXIO;
+	}
+
+	ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			      THIS_MODULE, sizeof(struct snd_dw_hdmi), &card);
+	if (ret < 0)
+		return ret;
+
+	strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+	strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname));
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s rev 0x%02x, irq %d", card->shortname, revision,
+		 data->irq);
+
+	dw = card->private_data;
+	dw->card = card;
+	dw->data = *data;
+	dw->revision = revision;
+
+	ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm);
+	if (ret < 0)
+		goto err;
+
+	dw->pcm = pcm;
+	pcm->private_data = dw;
+	strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops);
+
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+			dev, 64 * 1024, 64 * 1024);
+
+	ret = snd_card_register(card);
+	if (ret < 0)
+		goto err;
+
+	platform_set_drvdata(pdev, dw);
+
+	return 0;
+
+err:
+	snd_card_free(card);
+	return ret;
+}
+
+static int snd_dw_hdmi_remove(struct platform_device *pdev)
+{
+	struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
+
+	snd_card_free(dw->card);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int snd_dw_hdmi_suspend(struct device *dev)
+{
+	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
+
+	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold);
+	snd_pcm_suspend_all(dw->pcm);
+
+	return 0;
+}
+
+static int snd_dw_hdmi_resume(struct device *dev)
+{
+	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
+
+	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
+			 snd_dw_hdmi_resume);
+#define PM_OPS &snd_dw_hdmi_pm
+#else
+#define PM_OPS NULL
+#endif
+
+static struct platform_driver snd_dw_hdmi_driver = {
+	.probe	= snd_dw_hdmi_probe,
+	.remove	= snd_dw_hdmi_remove,
+	.driver	= {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm = PM_OPS,
+	},
+};
+
+module_platform_driver(snd_dw_hdmi_driver);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
new file mode 100644
index 000000000000..1e840118d90a
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
@@ -0,0 +1,13 @@
+#ifndef DW_HDMI_AUDIO_H
+#define DW_HDMI_AUDIO_H
+
+struct dw_hdmi;
+
+struct dw_hdmi_audio_data {
+	phys_addr_t phys;
+	void __iomem *base;
+	int irq;
+	struct dw_hdmi *hdmi;
+};
+
+#endif
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index adda3a988f36..1cb427935ed2 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -28,6 +28,7 @@
 #include <drm/bridge/dw_hdmi.h>
 
 #include "dw_hdmi.h"
+#include "dw_hdmi-ahb-audio.h"
 
 #define HDMI_EDID_LEN		512
 
@@ -105,6 +106,7 @@ struct dw_hdmi {
 	struct drm_encoder *encoder;
 	struct drm_bridge *bridge;
 
+	struct platform_device *audio;
 	enum dw_hdmi_devtype dev_type;
 	struct device *dev;
 	struct clk *isfr_clk;
@@ -1592,7 +1594,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = data;
 	struct device_node *np = dev->of_node;
+	struct platform_device_info pdevinfo;
 	struct device_node *ddc_node;
+	struct dw_hdmi_audio_data audio;
 	struct dw_hdmi *hdmi;
 	int ret;
 	u32 val = 1;
@@ -1712,6 +1716,23 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 	/* Unmute interrupts */
 	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+	pdevinfo.parent = dev;
+	pdevinfo.id = PLATFORM_DEVID_AUTO;
+
+	if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
+		audio.phys = iores->start;
+		audio.base = hdmi->regs;
+		audio.irq = irq;
+		audio.hdmi = hdmi;
+
+		pdevinfo.name = "dw-hdmi-ahb-audio";
+		pdevinfo.data = &audio;
+		pdevinfo.size_data = sizeof(audio);
+		pdevinfo.dma_mask = DMA_BIT_MASK(32);
+		hdmi->audio = platform_device_register_full(&pdevinfo);
+	}
+
 	dev_set_drvdata(dev, hdmi);
 
 	return 0;
@@ -1729,6 +1750,9 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
 {
 	struct dw_hdmi *hdmi = dev_get_drvdata(dev);
 
+	if (hdmi->audio && !IS_ERR(hdmi->audio))
+		platform_device_unregister(hdmi->audio);
+
 	/* Disable all interrupts */
 	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
 
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index 175dbc89a824..78e54e813212 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -545,6 +545,9 @@
 #define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
 
 enum {
+/* CONFIG1_ID field values */
+	HDMI_CONFIG1_AHB = 0x01,
+
 /* IH_FC_INT2 field values */
 	HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
 	HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
-- 
1.8.3.1

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

* [PATCH RFC v2 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (11 preceding siblings ...)
  2015-04-02  9:22 ` [PATCH RFC v2 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver Russell King
@ 2015-04-02  9:22 ` Russell King
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
  13 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-04-02  9:22 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Mark Brown, Philipp Zabel, Yakir Yang

Parse the ELD (EDID like data) stored from the HDMI driver to restrict
the sample rates and channels which are available to ALSA.  This causes
the ALSA device to reflect the capabilities of the overall audio path,
not just what is supported at the HDMI source interface level.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/Kconfig             | 1 +
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 6 ++++++
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h | 1 +
 drivers/gpu/drm/bridge/dw_hdmi.c           | 3 +++
 4 files changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 557962a67fc5..9fff41e76940 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -7,6 +7,7 @@ config DRM_DW_HDMI_AHB_AUDIO
 	tristate "Synopsis Designware AHB Audio interface"
 	depends on DRM_DW_HDMI && SND
 	select SND_PCM
+	select SND_PCM_ELD
 	select SND_PCM_IEC958
 	help
 	  Support the AHB Audio interface which is part of the Synopsis
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
index e98c291268f4..2bb68bda3cb0 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
@@ -12,11 +12,13 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <drm/bridge/dw_hdmi.h>
+#include <drm/drm_edid.h>
 
 #include <sound/asoundef.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
 #include <sound/pcm_iec958.h>
 
 #include "dw_hdmi-ahb-audio.h"
@@ -284,6 +286,10 @@ static int dw_hdmi_open(struct snd_pcm_substream *substream)
 
 	runtime->hw = dw_hdmi_hw;
 
+	ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld);
+	if (ret < 0)
+		return ret;
+
 	ret = snd_pcm_limit_hw_rates(runtime);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
index 1e840118d90a..91f631beecc7 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
@@ -8,6 +8,7 @@ struct dw_hdmi_audio_data {
 	void __iomem *base;
 	int irq;
 	struct dw_hdmi *hdmi;
+	u8 *eld;
 };
 
 #endif
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 1cb427935ed2..dc0aed18019d 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1446,6 +1446,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
 
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
+		/* Store the ELD */
+		drm_edid_to_eld(connector, edid);
 		kfree(edid);
 	} else {
 		dev_dbg(hdmi->dev, "failed to get edid\n");
@@ -1725,6 +1727,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		audio.base = hdmi->regs;
 		audio.irq = irq;
 		audio.hdmi = hdmi;
+		audio.eld = hdmi->connector.eld;
 
 		pdevinfo.name = "dw-hdmi-ahb-audio";
 		pdevinfo.data = &audio;
-- 
1.8.3.1

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-02  9:22 ` [PATCH RFC v2 10/13] sound/core: add DRM ELD helper Russell King
@ 2015-04-05 15:57   ` Takashi Iwai
  2015-04-05 16:20     ` Russell King - ARM Linux
  2015-05-05 22:35     ` Mark Brown
  2015-05-08 13:16   ` [alsa-devel] " Jyri Sarha
  1 sibling, 2 replies; 74+ messages in thread
From: Takashi Iwai @ 2015-04-05 15:57 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

At Thu, 02 Apr 2015 10:22:06 +0100,
Russell King wrote:
> 
> Add a helper for the EDID like data structure, which is typically passed
> from a HDMI adapter to its associated audio driver.  This informs the
> audio driver of the capabilities of the attached HDMI sink.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  include/sound/pcm_drm_eld.h |  6 +++
>  sound/core/Kconfig          |  3 ++
>  sound/core/Makefile         |  1 +
>  sound/core/pcm_drm_eld.c    | 92 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 102 insertions(+)
>  create mode 100644 include/sound/pcm_drm_eld.h
>  create mode 100644 sound/core/pcm_drm_eld.c
> 
> diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
> new file mode 100644
> index 000000000000..93357b25d2e2
> --- /dev/null
> +++ b/include/sound/pcm_drm_eld.h
> @@ -0,0 +1,6 @@
> +#ifndef __SOUND_PCM_DRM_ELD_H
> +#define __SOUND_PCM_DRM_ELD_H
> +
> +int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
> +
> +#endif

IMO, a single line of function declaration can be merged to
sound/pcm.h.


> diff --git a/sound/core/Kconfig b/sound/core/Kconfig
> index 313f22e9d929..b534c8a6046b 100644
> --- a/sound/core/Kconfig
> +++ b/sound/core/Kconfig
> @@ -6,6 +6,9 @@ config SND_PCM
>  	tristate
>  	select SND_TIMER
>  
> +config SND_PCM_ELD
> +	bool

I don't mind much adding this one, but a new Kconfig is always a
question.  I'd like to hear other's opinion, too.

>  config SND_DMAENGINE_PCM
>  	tristate
>  
> diff --git a/sound/core/Makefile b/sound/core/Makefile
> index 4daf2f58261c..591b49157b4d 100644
> --- a/sound/core/Makefile
> +++ b/sound/core/Makefile
> @@ -13,6 +13,7 @@ snd-$(CONFIG_SND_JACK)	  += jack.o
>  snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
>  		pcm_memory.o memalloc.o
>  snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
> +snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o
>  
>  # for trace-points
>  CFLAGS_pcm_lib.o := -I$(src)
> diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
> new file mode 100644
> index 000000000000..47d9b60435fe
> --- /dev/null
> +++ b/sound/core/pcm_drm_eld.c
> @@ -0,0 +1,92 @@
> +/*
> + *  PCM DRM helpers
> + *
> + *   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.
> + */
> +#include <linux/export.h>
> +#include <drm/drm_edid.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_drm_eld.h>
> +
> +static const unsigned int eld_rates[] = {
> +	32000,
> +	44100,
> +	48000,
> +	88200,
> +	96000,
> +	176400,
> +	192000,
> +};
> +
> +static int eld_limit_rates(struct snd_pcm_hw_params *params,
> +			   struct snd_pcm_hw_rule *rule)
> +{
> +	struct snd_interval *r = hw_param_interval(params, rule->var);
> +	struct snd_interval *c;
> +	unsigned int rate_mask = 7, i;
> +	const u8 *sad, *eld = rule->private;
> +
> +	sad = drm_eld_sad(eld);
> +	if (sad) {
> +		c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
> +
> +		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
> +			unsigned channels = 1 + (sad[0] & 7);
> +
> +			/*
> +			 * Exclude SADs which do not include the
> +			 * requested number of channels.
> +			 */
> +			if (c->min <= channels)
> +				rate_mask |= sad[1];
> +		}
> +printk("%s: r %d-%d c %d-%d m %x\n", __func__, r->min, r->max, c->min, c->max, rate_mask);

I guess this will be removed in the final version? ;)

> +	}
> +
> +	return snd_interval_list(r, ARRAY_SIZE(eld_rates), eld_rates,
> +				 rate_mask);
> +}
> +
> +static int eld_limit_channels(struct snd_pcm_hw_params *params,
> +			      struct snd_pcm_hw_rule *rule)
> +{
> +	struct snd_interval *var = hw_param_interval(params, rule->var);
> +	struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
> +	unsigned int i;
> +	const u8 *sad, *eld = rule->private;
> +
> +	sad = drm_eld_sad(eld);
> +	if (sad) {
> +		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
> +			switch (sad[0] & 0x78) {
> +			case 0x08:
> +				t.max = max(t.max, (sad[0] & 7) + 1u);
> +				break;

What about the minimal channel?

Ideally, we should either give a list of channel numbers or process
the hw_constraints dynamically to narrow the min/max matching with the
eld.


thanks,

Takashi

> +			}
> +		}
> +	}
> +
> +	return snd_interval_refine(var, &t);
> +}
> +
> +int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld)
> +{
> +	int ret;
> +
> +	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +				  eld_limit_rates, eld,
> +				  SNDRV_PCM_HW_PARAM_RATE,
> +				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +				  eld_limit_channels, eld,
> +				  SNDRV_PCM_HW_PARAM_CHANNELS,
> +				  SNDRV_PCM_HW_PARAM_RATE, -1);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(snd_pcm_hw_constraint_eld);
> -- 
> 1.8.3.1
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-05 15:57   ` Takashi Iwai
@ 2015-04-05 16:20     ` Russell King - ARM Linux
  2015-04-05 16:46       ` Takashi Iwai
  2015-05-05 22:35     ` Mark Brown
  1 sibling, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-04-05 16:20 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Sun, Apr 05, 2015 at 05:57:09PM +0200, Takashi Iwai wrote:
> > diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
> > new file mode 100644
> > index 000000000000..93357b25d2e2
> > --- /dev/null
> > +++ b/include/sound/pcm_drm_eld.h
> > @@ -0,0 +1,6 @@
> > +#ifndef __SOUND_PCM_DRM_ELD_H
> > +#define __SOUND_PCM_DRM_ELD_H
> > +
> > +int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
> > +
> > +#endif
> 
> IMO, a single line of function declaration can be merged to
> sound/pcm.h.

Ok.

> > diff --git a/sound/core/Kconfig b/sound/core/Kconfig
> > index 313f22e9d929..b534c8a6046b 100644
> > --- a/sound/core/Kconfig
> > +++ b/sound/core/Kconfig
> > @@ -6,6 +6,9 @@ config SND_PCM
> >  	tristate
> >  	select SND_TIMER
> >  
> > +config SND_PCM_ELD
> > +	bool
> 
> I don't mind much adding this one, but a new Kconfig is always a
> question.  I'd like to hear other's opinion, too.

That's more a question whether you want it always included in the build
or not, especially as it is dependent on DRM header files.

> > +printk("%s: r %d-%d c %d-%d m %x\n", __func__, r->min, r->max, c->min, c->max, rate_mask);
> 
> I guess this will be removed in the final version? ;)

Of course.

> > +static int eld_limit_channels(struct snd_pcm_hw_params *params,
> > +			      struct snd_pcm_hw_rule *rule)
> > +{
> > +	struct snd_interval *var = hw_param_interval(params, rule->var);
> > +	struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
> > +	unsigned int i;
> > +	const u8 *sad, *eld = rule->private;
> > +
> > +	sad = drm_eld_sad(eld);
> > +	if (sad) {
> > +		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
> > +			switch (sad[0] & 0x78) {
> > +			case 0x08:
> > +				t.max = max(t.max, (sad[0] & 7) + 1u);
> > +				break;
> 
> What about the minimal channel?

There isn't a minimum.  The SAD describes only the _maximum_ number of
channels.  For example, if a TV supports 5.1 audio, at 32, 44.1 and 48
kHz, it can do that with just one SAD entry which indicates support for
six channels of audio at those sample rates.  However, it will happily
accept 2 channel audio at those sample rates too.

> Ideally, we should either give a list of channel numbers or process
> the hw_constraints dynamically to narrow the min/max matching with the
> eld.

The ELD can change as a result of the HDMI sink deciding to change its
EDID (it does happen) or if the device is unplugged and re-plugged.  If
I wanted to restrict the maximum channel/rates by building some sort of
table, I'd do this at open time and avoid the complexity of having rule
callbacks.

Since (afaik) ALSA has a lack of support for dynamic reconfiguration
according to the attached device changing, the best we can do without
a huge amount of re-work of HDMI support across all adapters is to
process the capabilities of the attached device at prepare time
according to the current capabilities.

Implementing dynamic reconfiguration in ALSA is not something I want to
get involved with, and as we /already/ have HDMI support merged in the
kernel, this is not a blocker for at least trying to get some semblence
of sanity, rather than having every driver re-implementing stuff like
this.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-05 16:20     ` Russell King - ARM Linux
@ 2015-04-05 16:46       ` Takashi Iwai
  2015-04-05 17:26         ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Takashi Iwai @ 2015-04-05 16:46 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

At Sun, 5 Apr 2015 17:20:34 +0100,
Russell King - ARM Linux wrote:
> 
> On Sun, Apr 05, 2015 at 05:57:09PM +0200, Takashi Iwai wrote:
> > > diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
> > > new file mode 100644
> > > index 000000000000..93357b25d2e2
> > > --- /dev/null
> > > +++ b/include/sound/pcm_drm_eld.h
> > > @@ -0,0 +1,6 @@
> > > +#ifndef __SOUND_PCM_DRM_ELD_H
> > > +#define __SOUND_PCM_DRM_ELD_H
> > > +
> > > +int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
> > > +
> > > +#endif
> > 
> > IMO, a single line of function declaration can be merged to
> > sound/pcm.h.
> 
> Ok.
> 
> > > diff --git a/sound/core/Kconfig b/sound/core/Kconfig
> > > index 313f22e9d929..b534c8a6046b 100644
> > > --- a/sound/core/Kconfig
> > > +++ b/sound/core/Kconfig
> > > @@ -6,6 +6,9 @@ config SND_PCM
> > >  	tristate
> > >  	select SND_TIMER
> > >  
> > > +config SND_PCM_ELD
> > > +	bool
> > 
> > I don't mind much adding this one, but a new Kconfig is always a
> > question.  I'd like to hear other's opinion, too.
> 
> That's more a question whether you want it always included in the build
> or not, especially as it is dependent on DRM header files.

OK, then it makes sense to split.


> > > +printk("%s: r %d-%d c %d-%d m %x\n", __func__, r->min, r->max, c->min, c->max, rate_mask);
> > 
> > I guess this will be removed in the final version? ;)
> 
> Of course.
> 
> > > +static int eld_limit_channels(struct snd_pcm_hw_params *params,
> > > +			      struct snd_pcm_hw_rule *rule)
> > > +{
> > > +	struct snd_interval *var = hw_param_interval(params, rule->var);
> > > +	struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
> > > +	unsigned int i;
> > > +	const u8 *sad, *eld = rule->private;
> > > +
> > > +	sad = drm_eld_sad(eld);
> > > +	if (sad) {
> > > +		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
> > > +			switch (sad[0] & 0x78) {
> > > +			case 0x08:
> > > +				t.max = max(t.max, (sad[0] & 7) + 1u);
> > > +				break;
> > 
> > What about the minimal channel?
> 
> There isn't a minimum.  The SAD describes only the _maximum_ number of
> channels.  For example, if a TV supports 5.1 audio, at 32, 44.1 and 48
> kHz, it can do that with just one SAD entry which indicates support for
> six channels of audio at those sample rates.  However, it will happily
> accept 2 channel audio at those sample rates too.

Alright, I remembered wrong.  I took a look at the existing HD-audio
ELD parser code, and it also handles only the max channels.

> > Ideally, we should either give a list of channel numbers or process
> > the hw_constraints dynamically to narrow the min/max matching with the
> > eld.
> 
> The ELD can change as a result of the HDMI sink deciding to change its
> EDID (it does happen) or if the device is unplugged and re-plugged.  If
> I wanted to restrict the maximum channel/rates by building some sort of
> table, I'd do this at open time and avoid the complexity of having rule
> callbacks.

Right, this is the easiest approach.

> Since (afaik) ALSA has a lack of support for dynamic reconfiguration
> according to the attached device changing, the best we can do without
> a huge amount of re-work of HDMI support across all adapters is to
> process the capabilities of the attached device at prepare time
> according to the current capabilities.

Yeah, reconfiguration is tricky.  BTW, how is the HDMI unplug handled
during playback?

> Implementing dynamic reconfiguration in ALSA is not something I want to
> get involved with, and as we /already/ have HDMI support merged in the
> kernel, this is not a blocker for at least trying to get some semblence
> of sanity, rather than having every driver re-implementing stuff like
> this.

Well, I didn't mean about the dynamic reconfiguration.  I thought of
rather min/max pairs, but it was just a wrong assumption.  Scratch
it.

One another question: don't we need to deal with the sample bits in
sad[2]?


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

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-05 16:46       ` Takashi Iwai
@ 2015-04-05 17:26         ` Russell King - ARM Linux
  2015-05-06 17:02           ` Anssi Hannula
  2015-05-08 10:56           ` [alsa-devel] " Jyri Sarha
  0 siblings, 2 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-04-05 17:26 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Sun, Apr 05, 2015 at 06:46:13PM +0200, Takashi Iwai wrote:
> At Sun, 5 Apr 2015 17:20:34 +0100,
> Russell King - ARM Linux wrote:
> > Since (afaik) ALSA has a lack of support for dynamic reconfiguration
> > according to the attached device changing, the best we can do without
> > a huge amount of re-work of HDMI support across all adapters is to
> > process the capabilities of the attached device at prepare time
> > according to the current capabilities.
> 
> Yeah, reconfiguration is tricky.  BTW, how is the HDMI unplug handled
> during playback?

We don't handle it right now - and we don't have any notification to
the audio drivers that that has happened.  Even if we did have such a
notification, I'm not sure what the audio driver could do with it at
the moment.

> > Implementing dynamic reconfiguration in ALSA is not something I want to
> > get involved with, and as we /already/ have HDMI support merged in the
> > kernel, this is not a blocker for at least trying to get some semblence
> > of sanity, rather than having every driver re-implementing stuff like
> > this.
> 
> Well, I didn't mean about the dynamic reconfiguration.  I thought of
> rather min/max pairs, but it was just a wrong assumption.  Scratch
> it.
> 
> One another question: don't we need to deal with the sample bits in
> sad[2]?

It should, but I'm very wary about doing that without seeing more
examples of real SADs.  Right now, all my examples only support
one SAD with either 2 channel or 6 channel audio at the standard
(basic) 32, 44.1 and 48kHz rates.

The HDMI / CEA specs are very loose in their wording about the
short audio descriptors.  I've no idea whether a sink can provide
(for example) descriptors such as:

	LPCM, 6 channel 32, 44.1, 48kHz
	LPCM, 2 channel, 32, 44.1, 48, 96, 192kHz

or whether have to describe that as a single descriptor.  I only
have two TVs to test with here.

What I'm concerned about is that when the ALSA parameter refining
starts, we start with (eg) 2-8 channels, 32-192kHz.  Given that,
if we invoke the channel restriction before the rate restriction,
we would end up limiting to 2 channel at 32-192kHz.  If we apply
the restrictions in the opposite order, we'd restrict to 6
channel, 32-48kHz.  Neither are obviously correct in this
circumstance, and I don't really see a way to solve it given my
understanding of the way ALSA's parameter refinement works.

I suspect this is why most HDMI drivers are implemented such that
they take the maximum capabilities over all SADs, which would end
up restricting audio in the above case to: up to 6 channels, at
32, 44.1, 48, 96 and 192kHz, even though 6 channel @ 192kHz isn't
hasn't been indicated as supported.

Most of this is speculation though, based off what is in the
documentation.  As I say, I don't have enough real-world examples
to get a feel for what manufacturers _actually_ do to give a hint
as to how the documentation should be interpreted.

So, maybe I should just copy what everyone else does and take the
maximum of all descriptors...

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-05 15:57   ` Takashi Iwai
  2015-04-05 16:20     ` Russell King - ARM Linux
@ 2015-05-05 22:35     ` Mark Brown
  2015-05-06  8:58       ` Liam Girdwood
  1 sibling, 1 reply; 74+ messages in thread
From: Mark Brown @ 2015-05-05 22:35 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Philipp Zabel, Yakir Yang,
	Russell King, linux-arm-kernel

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

On Sun, Apr 05, 2015 at 05:57:09PM +0200, Takashi Iwai wrote:
> At Thu, 02 Apr 2015 10:22:06 +0100,
> Russell King wrote:

> > +config SND_PCM_ELD
> > +	bool

> I don't mind much adding this one, but a new Kconfig is always a
> question.  I'd like to hear other's opinion, too.

One point in favour of this is that there's been some discussion
recently of IoT applications with very low resource requirements that
might need audion functionality so it's likely that people will be
taking a look at trying to minimize code size for the audio stack.  This
sort of configurability may well be useful for such applications.

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

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



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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-05-05 22:35     ` Mark Brown
@ 2015-05-06  8:58       ` Liam Girdwood
  0 siblings, 0 replies; 74+ messages in thread
From: Liam Girdwood @ 2015-05-06  8:58 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Philipp Zabel,
	Yakir Yang, Russell King, linux-arm-kernel

On Tue, 2015-05-05 at 23:35 +0100, Mark Brown wrote:
> On Sun, Apr 05, 2015 at 05:57:09PM +0200, Takashi Iwai wrote:
> > At Thu, 02 Apr 2015 10:22:06 +0100,
> > Russell King wrote:
> 
> > > +config SND_PCM_ELD
> > > +	bool
> 
> > I don't mind much adding this one, but a new Kconfig is always a
> > question.  I'd like to hear other's opinion, too.
> 
> One point in favour of this is that there's been some discussion
> recently of IoT applications with very low resource requirements that
> might need audion functionality so it's likely that people will be
> taking a look at trying to minimize code size for the audio stack.  This
> sort of configurability may well be useful for such applications.


Fwiw, Keyon is looking at reducing runtime audio DRAM usage atm and will
probably have to add other Kconfig options to the audio kernel config
e.g. disable DPCM, disable DAPM, disable HW/SW params refinement,
disable async audio ioctls, etc. Currently the kernel audio core and
drivers are coming in at between 300k to 500k, which is a lot for a
device with limited memory and very simple audio requirements.

Liam

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-05 17:26         ` Russell King - ARM Linux
@ 2015-05-06 17:02           ` Anssi Hannula
  2015-05-07 10:41             ` Russell King - ARM Linux
  2015-05-08 10:56           ` [alsa-devel] " Jyri Sarha
  1 sibling, 1 reply; 74+ messages in thread
From: Anssi Hannula @ 2015-05-06 17:02 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, Takashi Iwai, dri-devel, Mark Brown,
	Yakir Yang, linux-arm-kernel

05.04.2015, 20:26, Russell King - ARM Linux kirjoitti:
> On Sun, Apr 05, 2015 at 06:46:13PM +0200, Takashi Iwai wrote:
>>
>> One another question: don't we need to deal with the sample bits in
>> sad[2]?
> 
> It should, but I'm very wary about doing that without seeing more
> examples of real SADs.  Right now, all my examples only support
> one SAD with either 2 channel or 6 channel audio at the standard
> (basic) 32, 44.1 and 48kHz rates.
> 
> The HDMI / CEA specs are very loose in their wording about the
> short audio descriptors.  I've no idea whether a sink can provide
> (for example) descriptors such as:
> 
> 	LPCM, 6 channel 32, 44.1, 48kHz
> 	LPCM, 2 channel, 32, 44.1, 48, 96, 192kHz
> 
> or whether have to describe that as a single descriptor.  I only
> have two TVs to test with here.

For the record, yes, multiple LPCM SADs are relatively common, and I
think I've seen some that offered more rates on a stereo SAD than on a
multichannel SAD (like in your example).


> What I'm concerned about is that when the ALSA parameter refining
> starts, we start with (eg) 2-8 channels, 32-192kHz.  Given that,
> if we invoke the channel restriction before the rate restriction,
> we would end up limiting to 2 channel at 32-192kHz.  If we apply
> the restrictions in the opposite order, we'd restrict to 6
> channel, 32-48kHz.  Neither are obviously correct in this
> circumstance, and I don't really see a way to solve it given my
> understanding of the way ALSA's parameter refinement works.
> 
> I suspect this is why most HDMI drivers are implemented such that
> they take the maximum capabilities over all SADs, which would end
> up restricting audio in the above case to: up to 6 channels, at
> 32, 44.1, 48, 96 and 192kHz, even though 6 channel @ 192kHz isn't
> hasn't been indicated as supported.
> 
> Most of this is speculation though, based off what is in the
> documentation.  As I say, I don't have enough real-world examples
> to get a feel for what manufacturers _actually_ do to give a hint
> as to how the documentation should be interpreted.
> 
> So, maybe I should just copy what everyone else does and take the
> maximum of all descriptors...
> 


-- 
Anssi Hannula

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-05-06 17:02           ` Anssi Hannula
@ 2015-05-07 10:41             ` Russell King - ARM Linux
  2015-05-07 11:11               ` Lars-Peter Clausen
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-07 10:41 UTC (permalink / raw)
  To: Anssi Hannula, Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Wed, May 06, 2015 at 08:02:52PM +0300, Anssi Hannula wrote:
> 05.04.2015, 20:26, Russell King - ARM Linux kirjoitti:
> > On Sun, Apr 05, 2015 at 06:46:13PM +0200, Takashi Iwai wrote:
> >>
> >> One another question: don't we need to deal with the sample bits in
> >> sad[2]?
> > 
> > It should, but I'm very wary about doing that without seeing more
> > examples of real SADs.  Right now, all my examples only support
> > one SAD with either 2 channel or 6 channel audio at the standard
> > (basic) 32, 44.1 and 48kHz rates.
> > 
> > The HDMI / CEA specs are very loose in their wording about the
> > short audio descriptors.  I've no idea whether a sink can provide
> > (for example) descriptors such as:
> > 
> > 	LPCM, 6 channel 32, 44.1, 48kHz
> > 	LPCM, 2 channel, 32, 44.1, 48, 96, 192kHz
> > 
> > or whether have to describe that as a single descriptor.  I only
> > have two TVs to test with here.
> 
> For the record, yes, multiple LPCM SADs are relatively common, and I
> think I've seen some that offered more rates on a stereo SAD than on a
> multichannel SAD (like in your example).

Okay, so we "think" we've seen it in the wild...

> > What I'm concerned about is that when the ALSA parameter refining
> > starts, we start with (eg) 2-8 channels, 32-192kHz.  Given that,
> > if we invoke the channel restriction before the rate restriction,
> > we would end up limiting to 2 channel at 32-192kHz.  If we apply
> > the restrictions in the opposite order, we'd restrict to 6
> > channel, 32-48kHz.  Neither are obviously correct in this
> > circumstance, and I don't really see a way to solve it given my
> > understanding of the way ALSA's parameter refinement works.
> > 
> > I suspect this is why most HDMI drivers are implemented such that
> > they take the maximum capabilities over all SADs, which would end
> > up restricting audio in the above case to: up to 6 channels, at
> > 32, 44.1, 48, 96 and 192kHz, even though 6 channel @ 192kHz isn't
> > hasn't been indicated as supported.
> > 
> > Most of this is speculation though, based off what is in the
> > documentation.  As I say, I don't have enough real-world examples
> > to get a feel for what manufacturers _actually_ do to give a hint
> > as to how the documentation should be interpreted.

... so this is probably less than speculation.

So, ALSA gurus, how do we handle this?  How do we arrange the parameter
resolution such that ALSA can permit _either_ 2 channels at 192kHz or 6
channels at 48kHz, but not 6 channels at 192kHz?  Right now, I don't
see how that's possible.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-05-07 10:41             ` Russell King - ARM Linux
@ 2015-05-07 11:11               ` Lars-Peter Clausen
  0 siblings, 0 replies; 74+ messages in thread
From: Lars-Peter Clausen @ 2015-05-07 11:11 UTC (permalink / raw)
  To: Russell King - ARM Linux, Anssi Hannula, Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On 05/07/2015 12:41 PM, Russell King - ARM Linux wrote:
[...]
>>> What I'm concerned about is that when the ALSA parameter refining
>>> starts, we start with (eg) 2-8 channels, 32-192kHz.  Given that,
>>> if we invoke the channel restriction before the rate restriction,
>>> we would end up limiting to 2 channel at 32-192kHz.  If we apply
>>> the restrictions in the opposite order, we'd restrict to 6
>>> channel, 32-48kHz.  Neither are obviously correct in this
>>> circumstance, and I don't really see a way to solve it given my
>>> understanding of the way ALSA's parameter refinement works.
>>>
>>> I suspect this is why most HDMI drivers are implemented such that
>>> they take the maximum capabilities over all SADs, which would end
>>> up restricting audio in the above case to: up to 6 channels, at
>>> 32, 44.1, 48, 96 and 192kHz, even though 6 channel @ 192kHz isn't
>>> hasn't been indicated as supported.
>>>
>>> Most of this is speculation though, based off what is in the
>>> documentation.  As I say, I don't have enough real-world examples
>>> to get a feel for what manufacturers _actually_ do to give a hint
>>> as to how the documentation should be interpreted.
>
> ... so this is probably less than speculation.
>
> So, ALSA gurus, how do we handle this?  How do we arrange the parameter
> resolution such that ALSA can permit _either_ 2 channels at 192kHz or 6
> channels at 48kHz, but not 6 channels at 192kHz?  Right now, I don't
> see how that's possible.

That's pretty straight forward and can be done using custom rules linking 
the number of channels to the sample rate. Have a look at 
snd_ac97_pcm_double_rate_rules() this is pretty much the same constraint.

- Lars

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

* Re: [alsa-devel] [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-05 17:26         ` Russell King - ARM Linux
  2015-05-06 17:02           ` Anssi Hannula
@ 2015-05-08 10:56           ` Jyri Sarha
  2015-05-08 11:42             ` Russell King - ARM Linux
  1 sibling, 1 reply; 74+ messages in thread
From: Jyri Sarha @ 2015-05-08 10:56 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, Takashi Iwai, dri-devel, Mark Brown,
	Philipp Zabel, Yakir Yang, linux-arm-kernel

On 2015-04-05 20:26, Russell King - ARM Linux wrote:
> On Sun, Apr 05, 2015 at 06:46:13PM +0200, Takashi Iwai wrote:
>> At Sun, 5 Apr 2015 17:20:34 +0100,
>> Russell King - ARM Linux wrote:
>> > Since (afaik) ALSA has a lack of support for dynamic reconfiguration
>> > according to the attached device changing, the best we can do without
>> > a huge amount of re-work of HDMI support across all adapters is to
>> > process the capabilities of the attached device at prepare time
>> > according to the current capabilities.
>> 
>> Yeah, reconfiguration is tricky.  BTW, how is the HDMI unplug handled
>> during playback?
> 
> We don't handle it right now - and we don't have any notification to
> the audio drivers that that has happened.  Even if we did have such a
> notification, I'm not sure what the audio driver could do with it at
> the moment.
> 
>> > Implementing dynamic reconfiguration in ALSA is not something I want to
>> > get involved with, and as we /already/ have HDMI support merged in the
>> > kernel, this is not a blocker for at least trying to get some semblence
>> > of sanity, rather than having every driver re-implementing stuff like
>> > this.
>> 
>> Well, I didn't mean about the dynamic reconfiguration.  I thought of
>> rather min/max pairs, but it was just a wrong assumption.  Scratch
>> it.
>> 
>> One another question: don't we need to deal with the sample bits in
>> sad[2]?
> 
> It should, but I'm very wary about doing that without seeing more
> examples of real SADs.

If the same constraint setting helpers are to be used also with
external HDMI encoders with i2s interface, there should be an option
to leave out the constraints for the sample bits. There is no direct
connection between the number of bits on I2S and HDMI link. The CPU
DAI may apply its own constraints on the available sample formats and
too strict constraints at the encoder end may lead to zero available
formats.

Best regrads,
Jyri

> Right now, all my examples only support
> one SAD with either 2 channel or 6 channel audio at the standard
> (basic) 32, 44.1 and 48kHz rates.
> 
> The HDMI / CEA specs are very loose in their wording about the
> short audio descriptors.  I've no idea whether a sink can provide
> (for example) descriptors such as:
> 
> 	LPCM, 6 channel 32, 44.1, 48kHz
> 	LPCM, 2 channel, 32, 44.1, 48, 96, 192kHz
> 
> or whether have to describe that as a single descriptor.  I only
> have two TVs to test with here.
> 
> What I'm concerned about is that when the ALSA parameter refining
> starts, we start with (eg) 2-8 channels, 32-192kHz.  Given that,
> if we invoke the channel restriction before the rate restriction,
> we would end up limiting to 2 channel at 32-192kHz.  If we apply
> the restrictions in the opposite order, we'd restrict to 6
> channel, 32-48kHz.  Neither are obviously correct in this
> circumstance, and I don't really see a way to solve it given my
> understanding of the way ALSA's parameter refinement works.
> 
> I suspect this is why most HDMI drivers are implemented such that
> they take the maximum capabilities over all SADs, which would end
> up restricting audio in the above case to: up to 6 channels, at
> 32, 44.1, 48, 96 and 192kHz, even though 6 channel @ 192kHz isn't
> hasn't been indicated as supported.
> 
> Most of this is speculation though, based off what is in the
> documentation.  As I say, I don't have enough real-world examples
> to get a feel for what manufacturers _actually_ do to give a hint
> as to how the documentation should be interpreted.
> 
> So, maybe I should just copy what everyone else does and take the
> maximum of all descriptors...

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

* Re: [alsa-devel] [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-05-08 10:56           ` [alsa-devel] " Jyri Sarha
@ 2015-05-08 11:42             ` Russell King - ARM Linux
  0 siblings, 0 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-08 11:42 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Fri, May 08, 2015 at 01:56:02PM +0300, Jyri Sarha wrote:
> On 2015-04-05 20:26, Russell King - ARM Linux wrote:
> >On Sun, Apr 05, 2015 at 06:46:13PM +0200, Takashi Iwai wrote:
> >>At Sun, 5 Apr 2015 17:20:34 +0100,
> >>Russell King - ARM Linux wrote:
> >>> Since (afaik) ALSA has a lack of support for dynamic reconfiguration
> >>> according to the attached device changing, the best we can do without
> >>> a huge amount of re-work of HDMI support across all adapters is to
> >>> process the capabilities of the attached device at prepare time
> >>> according to the current capabilities.
> >>
> >>Yeah, reconfiguration is tricky.  BTW, how is the HDMI unplug handled
> >>during playback?
> >
> >We don't handle it right now - and we don't have any notification to
> >the audio drivers that that has happened.  Even if we did have such a
> >notification, I'm not sure what the audio driver could do with it at
> >the moment.
> >
> >>> Implementing dynamic reconfiguration in ALSA is not something I want to
> >>> get involved with, and as we /already/ have HDMI support merged in the
> >>> kernel, this is not a blocker for at least trying to get some semblence
> >>> of sanity, rather than having every driver re-implementing stuff like
> >>> this.
> >>
> >>Well, I didn't mean about the dynamic reconfiguration.  I thought of
> >>rather min/max pairs, but it was just a wrong assumption.  Scratch
> >>it.
> >>
> >>One another question: don't we need to deal with the sample bits in
> >>sad[2]?
> >
> >It should, but I'm very wary about doing that without seeing more
> >examples of real SADs.
> 
> If the same constraint setting helpers are to be used also with
> external HDMI encoders with i2s interface, there should be an option
> to leave out the constraints for the sample bits. There is no direct
> connection between the number of bits on I2S and HDMI link. The CPU
> DAI may apply its own constraints on the available sample formats and
> too strict constraints at the encoder end may lead to zero available
> formats.

Possibly, but then how do we know which SAD to apply to limit the number
of channels?

I suspect for the use case you're suggesting above, it's better left to
the user rather than generic code to work it out otherwise things get
far too complex.  We'd need to have some way for the driver to report
back to this generic code the actual number of bits on the HDMI link.

However, as we currently know, ALSA appears to have a problem here which
pretty much makes properly restricting the channels and sample rates
impossible to do.  That issue is the one I'm much more keen to solve
right now, because without that being solved, this set of patches is
pretty much dead in the water.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-04-02  9:22 ` [PATCH RFC v2 10/13] sound/core: add DRM ELD helper Russell King
  2015-04-05 15:57   ` Takashi Iwai
@ 2015-05-08 13:16   ` Jyri Sarha
  2015-05-08 13:27     ` Russell King - ARM Linux
  1 sibling, 1 reply; 74+ messages in thread
From: Jyri Sarha @ 2015-05-08 13:16 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, alsa-devel, Takashi Iwai, dri-devel, Mark Brown,
	jsarha, Philipp Zabel, Yakir Yang, linux-arm-kernel

On 2015-04-02 12:22, Russell King wrote:
> Add a helper for the EDID like data structure, which is typically 
> passed
> from a HDMI adapter to its associated audio driver.  This informs the
> audio driver of the capabilities of the attached HDMI sink.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  include/sound/pcm_drm_eld.h |  6 +++
>  sound/core/Kconfig          |  3 ++
>  sound/core/Makefile         |  1 +
>  sound/core/pcm_drm_eld.c    | 92 
> +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 102 insertions(+)
>  create mode 100644 include/sound/pcm_drm_eld.h
>  create mode 100644 sound/core/pcm_drm_eld.c
> 
> diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
> new file mode 100644
> index 000000000000..93357b25d2e2
> --- /dev/null
> +++ b/include/sound/pcm_drm_eld.h
> @@ -0,0 +1,6 @@
> +#ifndef __SOUND_PCM_DRM_ELD_H
> +#define __SOUND_PCM_DRM_ELD_H
> +
> +int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void 
> *eld);
> +
> +#endif
> diff --git a/sound/core/Kconfig b/sound/core/Kconfig
> index 313f22e9d929..b534c8a6046b 100644
> --- a/sound/core/Kconfig
> +++ b/sound/core/Kconfig
> @@ -6,6 +6,9 @@ config SND_PCM
>  	tristate
>  	select SND_TIMER
> 
> +config SND_PCM_ELD
> +	bool
> +
>  config SND_DMAENGINE_PCM
>  	tristate
> 
> diff --git a/sound/core/Makefile b/sound/core/Makefile
> index 4daf2f58261c..591b49157b4d 100644
> --- a/sound/core/Makefile
> +++ b/sound/core/Makefile
> @@ -13,6 +13,7 @@ snd-$(CONFIG_SND_JACK)	  += jack.o
>  snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
>  		pcm_memory.o memalloc.o
>  snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
> +snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o
> 
>  # for trace-points
>  CFLAGS_pcm_lib.o := -I$(src)
> diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
> new file mode 100644
> index 000000000000..47d9b60435fe
> --- /dev/null
> +++ b/sound/core/pcm_drm_eld.c
> @@ -0,0 +1,92 @@
> +/*
> + *  PCM DRM helpers
> + *
> + *   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.
> + */
> +#include <linux/export.h>
> +#include <drm/drm_edid.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_drm_eld.h>
> +
> +static const unsigned int eld_rates[] = {
> +	32000,
> +	44100,
> +	48000,
> +	88200,
> +	96000,
> +	176400,
> +	192000,
> +};
> +

For what I can see, you are setting the cross dependency between
the sample rate and channels incorrectly. You should look for the
currently tested channel count directly from hw params.

> +static int eld_limit_rates(struct snd_pcm_hw_params *params,
> +			   struct snd_pcm_hw_rule *rule)
> +{
> +	struct snd_interval *r = hw_param_interval(params, rule->var);
> +	struct snd_interval *c;
> +	unsigned int rate_mask = 7, i;
> +	const u8 *sad, *eld = rule->private;
> +
> +	sad = drm_eld_sad(eld);
> +	if (sad) {
> +		c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
-               c = hw_param_interval(params, 
SNDRV_PCM_HW_PARAM_CHANNELS);
+               uint pchannels = params_channels(params);
> +
> +		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
> +			unsigned channels = 1 + (sad[0] & 7);
> +
> +			/*
> +			 * Exclude SADs which do not include the
> +			 * requested number of channels.
> +			 */
> +			if (pchannels <= channels)
> +				rate_mask |= sad[1];
> +		}
> +printk("%s: r %d-%d c %d-%d m %x\n", __func__, r->min, r->max,
> c->min, c->max, rate_mask);
> +	}
> +
> +	return snd_interval_list(r, ARRAY_SIZE(eld_rates), eld_rates,
> +				 rate_mask);
> +}
> +

 From this side the dependency is missing all together.

> +static int eld_limit_channels(struct snd_pcm_hw_params *params,
> +			      struct snd_pcm_hw_rule *rule)
> +{
> +	struct snd_interval *var = hw_param_interval(params, rule->var);
> +	struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
> +	unsigned int i;

+       unsigned int j;

> +	const u8 *sad, *eld = rule->private;

+	int rate = params_rate(params);

> +
> +	sad = drm_eld_sad(eld);
> +	if (sad) {
> +		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {

+                for (j = 0; j < ARRAY_SIZE(eld_rates); j++)
+                        if ((sad[1] & (1<<j)) && rate == eld_rates[j]) 
{

> +			 switch (sad[0] & 0x78) {
> +			 case 0x08:
> +				t.max = max(t.max, (sad[0] & 7) + 1u);
> +				break;
> +			}

+               }

> +		}
> +	}
> +
> +	return snd_interval_refine(var, &t);
> +}
> +

The code is completely untested, but I am sure you got the idea.

Best regards,
Jyri

> +int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void 
> *eld)
> +{
> +	int ret;
> +
> +	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
> +				  eld_limit_rates, eld,
> +				  SNDRV_PCM_HW_PARAM_RATE,
> +				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
> +				  eld_limit_channels, eld,
> +				  SNDRV_PCM_HW_PARAM_CHANNELS,
> +				  SNDRV_PCM_HW_PARAM_RATE, -1);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(snd_pcm_hw_constraint_eld);

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

* Re: [alsa-devel] [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-05-08 13:16   ` [alsa-devel] " Jyri Sarha
@ 2015-05-08 13:27     ` Russell King - ARM Linux
  2015-05-08 13:37       ` Jyri Sarha
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-08 13:27 UTC (permalink / raw)
  To: Jyri Sarha
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, jsarha,
	Yakir Yang, linux-arm-kernel

On Fri, May 08, 2015 at 04:16:08PM +0300, Jyri Sarha wrote:
> On 2015-04-02 12:22, Russell King wrote:
> >+static const unsigned int eld_rates[] = {
> >+	32000,
> >+	44100,
> >+	48000,
> >+	88200,
> >+	96000,
> >+	176400,
> >+	192000,
> >+};
> >+
> 
> For what I can see, you are setting the cross dependency between
> the sample rate and channels incorrectly.

There is a dependency between sample rate and channels.

> You should look for the
> currently tested channel count directly from hw params.

I'm not so sure that's right after looking at snd_ac97_pcm_double_rate_rules().
That's pretty much the same problem - AC'97 codecs can operate at a
sample rate of either the bus frame frequency or twice the bus frame
frequency.

They achieve twice the bus frame frequency by reallocating a couple
of the PCM data slots which would otherwise be used for >2 channels
to the first two channels, thus allowing two front channel samples
per frame.

AC'97 limits the number of channels to two if:

        if (rate->min > 48000) {

and limits the sample rate to 1-48kHz if:

        if (channels->min > 2) {

> From this side the dependency is missing all together.

Yes, it I initially couldn't work out how to do that bit... but I have
a solution now which seems to sort-of work.

Testing with aplay, I find that it seems to mostly work, and I guess
that:

	aplay -D hw:0,0 -v -f S24_LE -c 6 -r 192000 /dev/zero

resulting in:

Playing raw data '/dev/zero' : Signed 24 bit Little Endian, Rate 192000 Hz, Channels 6
Warning: rate is not accurate (requested = 192000Hz, got = 48000Hz)
         please, try the plug plugin
Hardware PCM card 0 'DW-HDMI' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S24_LE
  subformat    : STD
  channels     : 6
  rate         : 48000
  exact rate   : 48000 (48000/1)

is acceptable.

Also looking at AC'97, I don't need to list the same parameter as a
dependent of the rule... something I'll try when I'm back from the
hospital later this afternoon...

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH RFC v2 10/13] sound/core: add DRM ELD helper
  2015-05-08 13:27     ` Russell King - ARM Linux
@ 2015-05-08 13:37       ` Jyri Sarha
  0 siblings, 0 replies; 74+ messages in thread
From: Jyri Sarha @ 2015-05-08 13:37 UTC (permalink / raw)
  To: Russell King - ARM Linux, Jyri Sarha
  Cc: Fabio Estevam, alsa-devel, Takashi Iwai, dri-devel, Mark Brown,
	Philipp Zabel, Yakir Yang, linux-arm-kernel

On 05/08/15 16:27, Russell King - ARM Linux wrote:
> On Fri, May 08, 2015 at 04:16:08PM +0300, Jyri Sarha wrote:
>> On 2015-04-02 12:22, Russell King wrote:
...
>> For what I can see, you are setting the cross dependency between
>> the sample rate and channels incorrectly.
>
> There is a dependency between sample rate and channels.
>
>> You should look for the
>> currently tested channel count directly from hw params.
>
> I'm not so sure that's right after looking at snd_ac97_pcm_double_rate_rules().
> That's pretty much the same problem - AC'97 codecs can operate at a
> sample rate of either the bus frame frequency or twice the bus frame
> frequency.
>

Maybe digging the channels from intervals works too, I have just never
used that myself. The param_channels() works too and it is slightly simpler.

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

* [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support
  2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                   ` (12 preceding siblings ...)
  2015-04-02  9:22 ` [PATCH RFC v2 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver Russell King
@ 2015-05-09 10:25 ` Russell King - ARM Linux
  2015-05-09 10:25   ` [PATCH 01/13] drm: imx/dw_hdmi: move phy comments Russell King
                     ` (12 more replies)
  13 siblings, 13 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-09 10:25 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, Jaroslav Kysela, Mark Brown, Yakir Yang

I'm sending this series again for comments, and to allow people to
update their code bases (for those who are using my AHB audio driver
on iMX6).

There have been very few changes from the previous posting, the
exception being the ELD helper in patch 10, which should be correctly
sorted now.

I would like to:
* queue the first six patches for David, so I'm asking for acks for these
* obtain agreement with the Rockchip guys on patches 7 and 8
* queue patches 9 to 11 inclusive as well (as these are cross-subsystem,
  I think we need to discuss how they are to be handled - there is other
  work in the pipelines from others depending on these changes.)  So acks
  for these would be nice too.

Here's the summary of the patches, same as last time:

The first four patches are a few cleanups to the dw_hdmi driver.

The next two patches introduce new interfaces to the dw_hdmi driver
to support AHB audio, including the errata found on iMX6 which
requires N to be programmed to zero when the audio FIFO is not full.
I'm expecting some discussion with these last two as we try to work
out how to deal with the two variants of audio support for this part
(AHB audio vs I2S audio).

The following three add various helpers to the DRM and ALSA subsystems
for audio support which is non-specific to the AHB audio driver.  For
DRM, this is a helper macro to obtain the pointer into the short audio
descriptors.  For ALSA, it's a set of helpers to restrict an audio PCM
device's capabilities according to the ELD, and to generate the IEC958
channel status data.  If these helpers are acceptable, we can convert
a number of drivers to them.

The ELD helper isn't quite finished, but should be sufficient for
initial testing.

The last two patches add support for the dw_hdmi audio.  This is an
ALSA driver rather than an ASoC driver as it's a pretty simple affair.
I couldn't find a suitable location in the sound/ subtree to place it,
so I've placed it next to the bridge - yes, we probably need to find
it a better home in the sound/ subtree, but it currently makes
use of dw_hdmi.h in the directory it lives.

 drivers/gpu/drm/bridge/Kconfig             |  11 +
 drivers/gpu/drm/bridge/Makefile            |   1 +
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 566 +++++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h |  14 +
 drivers/gpu/drm/bridge/dw_hdmi.c           | 321 +++++++++-------
 drivers/gpu/drm/bridge/dw_hdmi.h           |   3 +
 drivers/gpu/drm/imx/dw_hdmi-imx.c          |   5 +
 include/drm/bridge/dw_hdmi.h               |   7 +
 include/drm/drm_edid.h                     |  19 +
 include/sound/pcm_drm_eld.h                |   6 +
 include/sound/pcm_iec958.h                 |   9 +
 sound/core/Kconfig                         |   6 +
 sound/core/Makefile                        |   2 +
 sound/core/pcm_drm_eld.c                   |  99 +++++
 sound/core/pcm_iec958.c                    |  95 +++++
 15 files changed, 1036 insertions(+), 128 deletions(-)

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 01/13] drm: imx/dw_hdmi: move phy comments
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
@ 2015-05-09 10:25   ` Russell King
  2015-05-09 10:26   ` [PATCH 02/13] drm: bridge/dw_hdmi: clean up phy configuration Russell King
                     ` (11 subsequent siblings)
  12 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-05-09 10:25 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown,
	Philipp Zabel, Yakir Yang

The phy comments in dw_hdmi.c applied to the iMX6 version.  Move these
comments to the iMX6 dw_hdmi-imx data along side the data.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c  | 3 ---
 drivers/gpu/drm/imx/dw_hdmi-imx.c | 5 +++++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 49cafb61d290..3494391e4199 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -834,11 +834,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		    phy_config[i].mpixelclock)
 			break;
 
-	/* RESISTANCE TERM 133Ohm Cfg */
 	hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19);  /* TXTERM */
-	/* PREEMP Cgf 0.00 */
 	hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
-	/* TX/CK LVL 10 */
 	hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */
 
 	/* REMOVE CLK TERM */
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index a3ecf1069b76..644edf65dbe0 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -75,6 +75,11 @@ static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = {
 	},
 };
 
+/*
+ * Resistance term 133Ohm Cfg
+ * PREEMP config 0.00
+ * TX/CK level 10
+ */
 static const struct dw_hdmi_phy_config imx_phy_config[] = {
 	/*pixelclk   symbol   term   vlev */
 	{ 148500000, 0x800d, 0x0005, 0x01ad},
-- 
1.8.3.1

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

* [PATCH 02/13] drm: bridge/dw_hdmi: clean up phy configuration
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
  2015-05-09 10:25   ` [PATCH 01/13] drm: imx/dw_hdmi: move phy comments Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-22 15:19     ` Yakir
  2015-05-09 10:26   ` [PATCH 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() Russell King
                     ` (10 subsequent siblings)
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown,
	Philipp Zabel, Yakir Yang

The phy configuration is dependent on the SoC, and we look up values for
some of the registers in SoC specific data.  However, we had partially
programmed the phy before we had successfully looked up the clock rate.
Also, we were only checking that we had a valid configuration for the
currctrl register.

Move all these lookups to the start of this function instead, so we can
check that all lookups were successful before beginning to program the
phy.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 68 +++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 3494391e4199..23ea8c5c85b6 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -753,12 +753,12 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
 static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 			      unsigned char res, int cscon)
 {
-	unsigned res_idx, i;
+	unsigned res_idx;
 	u8 val, msec;
-	const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data;
-	const struct dw_hdmi_mpll_config *mpll_config = plat_data->mpll_cfg;
-	const struct dw_hdmi_curr_ctrl *curr_ctrl = plat_data->cur_ctr;
-	const struct dw_hdmi_phy_config *phy_config = plat_data->phy_config;
+	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
+	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
+	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
+	const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
 
 	if (prep)
 		return -EINVAL;
@@ -778,6 +778,30 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		return -EINVAL;
 	}
 
+	/* PLL/MPLL Cfg - always match on final entry */
+	for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    mpll_config->mpixelclock)
+			break;
+
+	for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    curr_ctrl->mpixelclock)
+			break;
+
+	for (; phy_config->mpixelclock != ~0UL; phy_config++)
+		if (hdmi->hdmi_data.video_mode.mpixelclock <=
+		    phy_config->mpixelclock)
+			break;
+
+	if (mpll_config->mpixelclock == ~0UL ||
+	    curr_ctrl->mpixelclock == ~0UL ||
+	    phy_config->mpixelclock == ~0UL) {
+		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
+			hdmi->hdmi_data.video_mode.mpixelclock);
+		return -EINVAL;
+	}
+
 	/* Enable csc path */
 	if (cscon)
 		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
@@ -803,40 +827,18 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		    HDMI_PHY_I2CM_SLAVE_ADDR);
 	hdmi_phy_test_clear(hdmi, 0);
 
-	/* PLL/MPLL Cfg - always match on final entry */
-	for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    mpll_config[i].mpixelclock)
-			break;
-
-	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
-	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
-
-	for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    curr_ctrl[i].mpixelclock)
-			break;
-
-	if (curr_ctrl[i].mpixelclock == (~0UL)) {
-		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
-			hdmi->hdmi_data.video_mode.mpixelclock);
-		return -EINVAL;
-	}
+	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06);
+	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
 
 	/* CURRCTRL */
-	hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
+	hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10);
 
 	hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
 	hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
 
-	for (i = 0; phy_config[i].mpixelclock != (~0UL); i++)
-		if (hdmi->hdmi_data.video_mode.mpixelclock <=
-		    phy_config[i].mpixelclock)
-			break;
-
-	hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19);  /* TXTERM */
-	hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
-	hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */
+	hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19);  /* TXTERM */
+	hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
+	hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
 
 	/* REMOVE CLK TERM */
 	hdmi_phy_i2c_write(hdmi, 0x8000, 0x05);  /* CKCALCTRL */
-- 
1.8.3.1

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

* [PATCH 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator()
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
  2015-05-09 10:25   ` [PATCH 01/13] drm: imx/dw_hdmi: move phy comments Russell King
  2015-05-09 10:26   ` [PATCH 02/13] drm: bridge/dw_hdmi: clean up phy configuration Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-22 15:22     ` Yakir
  2015-05-09 10:26   ` [PATCH 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode() Russell King
                     ` (9 subsequent siblings)
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

Clean up hdmi_set_clk_regenerator() by allowing it to take the audio
sample rate and ratio directly, rather than hiding it inside the
function.  Raise the unsupported pixel clock/sample rate message from
debug to error level as this results in audio not working correctly.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 23ea8c5c85b6..75099b80ca7e 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -335,39 +335,37 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 }
 
 static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
-				     unsigned long pixel_clk)
+	unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio)
 {
-	unsigned int clk_n, clk_cts;
+	unsigned int n, cts;
 
-	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
-			       hdmi->ratio);
-	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
-				   hdmi->ratio);
-
-	if (!clk_cts) {
-		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
-			__func__, pixel_clk);
-		return;
+	n = hdmi_compute_n(sample_rate, pixel_clk, ratio);
+	cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio);
+	if (!cts) {
+		dev_err(hdmi->dev,
+			"%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n",
+			__func__, pixel_clk, sample_rate);
 	}
 
-	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
-		__func__, hdmi->sample_rate, hdmi->ratio,
-		pixel_clk, clk_n, clk_cts);
+	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
+		__func__, sample_rate, ratio, pixel_clk, n, cts);
 
-	hdmi_set_cts_n(hdmi, clk_cts, clk_n);
+	hdmi_set_cts_n(hdmi, cts, n);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
 {
 	mutex_lock(&hdmi->audio_mutex);
-	hdmi_set_clk_regenerator(hdmi, 74250000);
+	hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate,
+				 hdmi->ratio);
 	mutex_unlock(&hdmi->audio_mutex);
 }
 
 static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
 {
 	mutex_lock(&hdmi->audio_mutex);
-	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+				 hdmi->sample_rate, hdmi->ratio);
 	mutex_unlock(&hdmi->audio_mutex);
 }
 
-- 
1.8.3.1

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

* [PATCH 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode()
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (2 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-09 10:26   ` [PATCH 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little Russell King
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

Use drm_hdmi_avi_infoframe_from_display_mode() to compose the AVI
frame.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 126 +++++++++++++++++++++------------------
 1 file changed, 67 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 75099b80ca7e..0f3ccfa3ccfc 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -918,74 +918,79 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
 		  HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
 }
 
-static void hdmi_config_AVI(struct dw_hdmi *hdmi)
+static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 {
-	u8 val, pix_fmt, under_scan;
-	u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry;
-	bool aspect_16_9;
+	struct hdmi_avi_infoframe frame;
+	u8 val;
 
-	aspect_16_9 = false; /* FIXME */
+	/* Initialise info frame from DRM mode */
+	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
 
-	/* AVI Data Byte 1 */
 	if (hdmi->hdmi_data.enc_out_format == YCBCR444)
-		pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444;
+		frame.colorspace = HDMI_COLORSPACE_YUV444;
 	else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
-		pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422;
+		frame.colorspace = HDMI_COLORSPACE_YUV422;
 	else
-		pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB;
-
-		under_scan =  HDMI_FC_AVICONF0_SCAN_INFO_NODATA;
-
-	/*
-	 * Active format identification data is present in the AVI InfoFrame.
-	 * Under scan info, no bar data
-	 */
-	val = pix_fmt | under_scan |
-		HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT |
-		HDMI_FC_AVICONF0_BAR_DATA_NO_DATA;
-
-	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
-
-	/* AVI Data Byte 2 -Set the Aspect Ratio */
-	if (aspect_16_9) {
-		act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9;
-		coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9;
-	} else {
-		act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3;
-		coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3;
-	}
+		frame.colorspace = HDMI_COLORSPACE_RGB;
 
 	/* Set up colorimetry */
 	if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
-		colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO;
+		frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
 		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-			ext_colorimetry =
-				HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+			frame.extended_colorimetry =
+				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-			ext_colorimetry =
-				HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709;
+			frame.extended_colorimetry =
+				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
 	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
 		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-			colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE;
+			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
 		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-			colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
-		ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 	} else { /* Carries no data */
-		colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA;
-		ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
+		frame.colorimetry = HDMI_COLORIMETRY_NONE;
+		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 	}
 
-	val = colorimetry | coded_ratio | act_ratio;
+	frame.scan_mode = HDMI_SCAN_MODE_NONE;
+
+	/*
+	 * The Designware IP uses a different byte format from standard
+	 * AVI info frames, though generally the bits are in the correct
+	 * bytes.
+	 */
+
+	/*
+	 * AVI data byte 1 differences: Colorspace in bits 4,5 rather than 5,6,
+	 * active aspect present in bit 6 rather than 4.
+	 */
+	val = (frame.colorspace & 3) << 4 | (frame.scan_mode & 0x3);
+	if (frame.active_aspect & 15)
+		val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT;
+	if (frame.top_bar || frame.bottom_bar)
+		val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR;
+	if (frame.left_bar || frame.right_bar)
+		val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR;
+	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
+
+	/* AVI data byte 2 differences: none */
+	val = ((frame.colorimetry & 0x3) << 6) |
+	      ((frame.picture_aspect & 0x3) << 4) |
+	      (frame.active_aspect & 0xf);
 	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1);
 
-	/* AVI Data Byte 3 */
-	val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry |
-		HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT |
-		HDMI_FC_AVICONF2_SCALING_NONE;
+	/* AVI data byte 3 differences: none */
+	val = ((frame.extended_colorimetry & 0x7) << 4) |
+	      ((frame.quantization_range & 0x3) << 2) |
+	      (frame.nups & 0x3);
+	if (frame.itc)
+		val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID;
 	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2);
 
-	/* AVI Data Byte 4 */
-	hdmi_writeb(hdmi, hdmi->vic, HDMI_FC_AVIVID);
+	/* AVI data byte 4 differences: none */
+	val = frame.video_code & 0x7f;
+	hdmi_writeb(hdmi, val, HDMI_FC_AVIVID);
 
 	/* AVI Data Byte 5- set up input and output pixel repetition */
 	val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) <<
@@ -996,20 +1001,23 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi)
 		HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
 	hdmi_writeb(hdmi, val, HDMI_FC_PRCONF);
 
-	/* IT Content and quantization range = don't care */
-	val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS |
-		HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED;
+	/*
+	 * AVI data byte 5 differences: content type in 0,1 rather than 4,5,
+	 * ycc range in bits 2,3 rather than 6,7
+	 */
+	val = ((frame.ycc_quantization_range & 0x3) << 2) |
+	      (frame.content_type & 0x3);
 	hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3);
 
 	/* AVI Data Bytes 6-13 */
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB1);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB1);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB1);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB0);
-	hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1);
+	hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0);
+	hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1);
+	hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0);
+	hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1);
+	hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0);
+	hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1);
+	hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0);
+	hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
 }
 
 static void hdmi_av_composer(struct dw_hdmi *hdmi,
@@ -1243,7 +1251,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 		hdmi_enable_audio_clk(hdmi);
 
 		/* HDMI Initialization Step F - Configure AVI InfoFrame */
-		hdmi_config_AVI(hdmi);
+		hdmi_config_AVI(hdmi, mode);
 	}
 
 	hdmi_video_packetize(hdmi);
-- 
1.8.3.1

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

* [PATCH 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (3 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode() Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-09 10:26   ` [PATCH 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced Russell King
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

When a YCBCR format is selected, we can merely copy the colorimetry
information directly as we use the same definitions for both the
unpacked AVI info frame and the hdmi_data_info structure.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 0f3ccfa3ccfc..a8bd3fbf4300 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -943,10 +943,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 			frame.extended_colorimetry =
 				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
 	} else if (hdmi->hdmi_data.enc_out_format != RGB) {
-		if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
-			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
-		else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
-			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+		frame.colorimetry = hdmi->hdmi_data.colorimetry;
 		frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 	} else { /* Carries no data */
 		frame.colorimetry = HDMI_COLORIMETRY_NONE;
-- 
1.8.3.1

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

* [PATCH 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (4 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-09 10:26   ` [PATCH 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate Russell King
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

Remove the struct hdmi_vmode mhsyncpolarity/mvsyncpolarity/minterlaced
members, which are only used within a single function.  We can directly
reference the appropriate mode->flags instead.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index a8bd3fbf4300..75728ba552d0 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -82,9 +82,6 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
 
 struct hdmi_vmode {
 	bool mdvi;
-	bool mhsyncpolarity;
-	bool mvsyncpolarity;
-	bool minterlaced;
 	bool mdataenablepolarity;
 
 	unsigned int mpixelclock;
@@ -1024,9 +1021,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
 	int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
 
-	vmode->mhsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC);
-	vmode->mvsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC);
-	vmode->minterlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
 	vmode->mpixelclock = mode->clock * 1000;
 
 	dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
@@ -1036,13 +1030,13 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 		HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
 		HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
 
-	inv_val |= (vmode->mvsyncpolarity ?
+	inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
 		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
-		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
+		HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW;
 
-	inv_val |= (vmode->mhsyncpolarity ?
+	inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
 		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
-		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
+		HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW;
 
 	inv_val |= (vmode->mdataenablepolarity ?
 		HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
@@ -1051,13 +1045,13 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 	if (hdmi->vic == 39)
 		inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
 	else
-		inv_val |= (vmode->minterlaced ?
+		inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
 			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
-			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW);
+			HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
 
-	inv_val |= (vmode->minterlaced ?
+	inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
 		HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
-		HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE);
+		HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
 
 	inv_val |= (vmode->mdvi ?
 		HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
-- 
1.8.3.1

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

* [PATCH 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (5 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-22 15:26     ` Yakir
  2015-05-09 10:26   ` [PATCH 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio Russell King
                     ` (5 subsequent siblings)
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

Introduce dw_hdmi_set_sample_rate(), which allows us to configure the
audio sample rate, setting the CTS/N values appropriately.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 10 ++++++++++
 include/drm/bridge/dw_hdmi.h     |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 75728ba552d0..0369fab5c695 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -366,6 +366,16 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
 	mutex_unlock(&hdmi->audio_mutex);
 }
 
+void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
+{
+	mutex_lock(&hdmi->audio_mutex);
+	hdmi->sample_rate = rate;
+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
+				 hdmi->sample_rate, hdmi->ratio);
+	mutex_unlock(&hdmi->audio_mutex);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
+
 /*
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index de13bfc35634..763af51e1d60 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -12,6 +12,8 @@
 
 #include <drm/drmP.h>
 
+struct dw_hdmi;
+
 enum {
 	DW_HDMI_RES_8,
 	DW_HDMI_RES_10,
@@ -59,4 +61,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		 void *data, struct drm_encoder *encoder,
 		 struct resource *iores, int irq,
 		 const struct dw_hdmi_plat_data *plat_data);
+
+void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
+
 #endif /* __IMX_HDMI_H__ */
-- 
1.8.3.1

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

* [PATCH 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (6 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-22 15:28     ` Yakir
  2015-05-09 10:26   ` [PATCH 09/13] drm/edid: add function to help find SADs Russell King
                     ` (4 subsequent siblings)
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

iMX6 devices suffer from an errata (ERR005174) where the audio FIFO can
be emptied while it is partially full, resulting in misalignment of the
audio samples.

To prevent this, the errata workaround recommends writing N as zero
until the audio FIFO has been loaded by DMA.  Writing N=0 prevents the
HDMI bridge from reading from the audio FIFO, effectively disabling
audio.

This means we need to provide the audio driver with a pair of functions
to enable/disable audio.  These are dw_hdmi_audio_enable() and
dw_hdmi_audio_disable().

A spinlock is introduced to ensure that setting the CTS/N values can't
race, ensuring that the audio driver calling the enable/disable
functions (which are called in an atomic context) can't race with a
modeset.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/dw_hdmi.c | 34 +++++++++++++++++++++++++++++++++-
 include/drm/bridge/dw_hdmi.h     |  2 ++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 0369fab5c695..adda3a988f36 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -18,6 +18,7 @@
 #include <linux/hdmi.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
+#include <linux/spinlock.h>
 
 #include <drm/drm_of.h>
 #include <drm/drmP.h>
@@ -124,8 +125,12 @@ struct dw_hdmi {
 	struct i2c_adapter *ddc;
 	void __iomem *regs;
 
+	spinlock_t audio_lock;
 	struct mutex audio_mutex;
 	unsigned int sample_rate;
+	unsigned int audio_cts;
+	unsigned int audio_n;
+	bool audio_enable;
 	int ratio;
 
 	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
@@ -347,7 +352,11 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
 	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
 		__func__, sample_rate, ratio, pixel_clk, n, cts);
 
-	hdmi_set_cts_n(hdmi, cts, n);
+	spin_lock_irq(&hdmi->audio_lock);
+	hdmi->audio_n = n;
+	hdmi->audio_cts = cts;
+	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
+	spin_unlock_irq(&hdmi->audio_lock);
 }
 
 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
@@ -376,6 +385,28 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
 
+void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hdmi->audio_lock, flags);
+	hdmi->audio_enable = true;
+	hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
+	spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
+
+void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hdmi->audio_lock, flags);
+	hdmi->audio_enable = false;
+	hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
+	spin_unlock_irqrestore(&hdmi->audio_lock, flags);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
+
 /*
  * this submodule is responsible for the video data synchronization.
  * for example, for RGB 4:4:4 input, the data map is defined as
@@ -1578,6 +1609,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 	hdmi->encoder = encoder;
 
 	mutex_init(&hdmi->audio_mutex);
+	spin_lock_init(&hdmi->audio_lock);
 
 	of_property_read_u32(np, "reg-io-width", &val);
 
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index 763af51e1d60..bae79f3c4d28 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -63,5 +63,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		 const struct dw_hdmi_plat_data *plat_data);
 
 void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
+void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
+void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
 
 #endif /* __IMX_HDMI_H__ */
-- 
1.8.3.1

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

* [PATCH 09/13] drm/edid: add function to help find SADs
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (7 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-09 10:26   ` [PATCH 10/13] sound/core: add DRM ELD helper Russell King
                     ` (3 subsequent siblings)
  12 siblings, 0 replies; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

Add a function to find the start of the SADs in the ELD.  This
complements the helper to retrieve the SAD count.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 include/drm/drm_edid.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 799050198323..53c53c459b15 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -348,6 +348,25 @@ static inline int drm_eld_mnl(const uint8_t *eld)
 }
 
 /**
+ * drm_eld_sad - Get ELD SAD structures.
+ * @eld: pointer to an eld memory structure with sad_count set
+ */
+static inline const uint8_t *drm_eld_sad(const uint8_t *eld)
+{
+	unsigned int ver, mnl;
+
+	ver = (eld[DRM_ELD_VER] & DRM_ELD_VER_MASK) >> DRM_ELD_VER_SHIFT;
+	if (ver != 2 && ver != 31)
+		return NULL;
+
+	mnl = drm_eld_mnl(eld);
+	if (mnl > 16)
+		return NULL;
+
+	return eld + DRM_ELD_CEA_SAD(mnl, 0);
+}
+
+/**
  * drm_eld_sad_count - Get ELD SAD count.
  * @eld: pointer to an eld memory structure with sad_count set
  */
-- 
1.8.3.1

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

* [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (8 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 09/13] drm/edid: add function to help find SADs Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-22 12:20     ` [alsa-devel] " Mark Brown
  2015-05-09 10:26   ` [PATCH 11/13] sound/core: add IEC958 channel status helper Russell King
                     ` (2 subsequent siblings)
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown,
	Philipp Zabel, Yakir Yang

Add a helper for the EDID like data structure, which is typically passed
from a HDMI adapter to its associated audio driver.  This informs the
audio driver of the capabilities of the attached HDMI sink.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 include/sound/pcm_drm_eld.h |  6 +++
 sound/core/Kconfig          |  3 ++
 sound/core/Makefile         |  1 +
 sound/core/pcm_drm_eld.c    | 99 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+)
 create mode 100644 include/sound/pcm_drm_eld.h
 create mode 100644 sound/core/pcm_drm_eld.c

diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h
new file mode 100644
index 000000000000..93357b25d2e2
--- /dev/null
+++ b/include/sound/pcm_drm_eld.h
@@ -0,0 +1,6 @@
+#ifndef __SOUND_PCM_DRM_ELD_H
+#define __SOUND_PCM_DRM_ELD_H
+
+int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld);
+
+#endif
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 313f22e9d929..b534c8a6046b 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -6,6 +6,9 @@ config SND_PCM
 	tristate
 	select SND_TIMER
 
+config SND_PCM_ELD
+	bool
+
 config SND_DMAENGINE_PCM
 	tristate
 
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 4daf2f58261c..591b49157b4d 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -13,6 +13,7 @@ snd-$(CONFIG_SND_JACK)	  += jack.o
 snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
 		pcm_memory.o memalloc.o
 snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
+snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o
 
 # for trace-points
 CFLAGS_pcm_lib.o := -I$(src)
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
new file mode 100644
index 000000000000..e70379fb63d0
--- /dev/null
+++ b/sound/core/pcm_drm_eld.c
@@ -0,0 +1,99 @@
+/*
+ *  PCM DRM helpers
+ *
+ *   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.
+ */
+#include <linux/export.h>
+#include <drm/drm_edid.h>
+#include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
+
+static const unsigned int eld_rates[] = {
+	32000,
+	44100,
+	48000,
+	88200,
+	96000,
+	176400,
+	192000,
+};
+
+static unsigned int sad_max_channels(const u8 *sad)
+{
+	return 1 + (sad[0] & 7);
+}
+
+static int eld_limit_rates(struct snd_pcm_hw_params *params,
+			   struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval *r = hw_param_interval(params, rule->var);
+	struct snd_interval *c;
+	unsigned int rate_mask = 7, i;
+	const u8 *sad, *eld = rule->private;
+
+	sad = drm_eld_sad(eld);
+	if (sad) {
+		c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
+			unsigned max_channels = sad_max_channels(sad);
+
+			/*
+			 * Exclude SADs which do not include the
+			 * requested number of channels.
+			 */
+			if (c->min <= max_channels)
+				rate_mask |= sad[1];
+		}
+	}
+
+	return snd_interval_list(r, ARRAY_SIZE(eld_rates), eld_rates,
+				 rate_mask);
+}
+
+static int eld_limit_channels(struct snd_pcm_hw_params *params,
+			      struct snd_pcm_hw_rule *rule)
+{
+	struct snd_interval *c = hw_param_interval(params, rule->var);
+	struct snd_interval *r;
+	struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
+	unsigned int i;
+	const u8 *sad, *eld = rule->private;
+
+	sad = drm_eld_sad(eld);
+	if (sad) {
+		unsigned int rate_mask = 0;
+
+		/* Convert the rate interval to a mask */
+		r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+		for (i = 0; i < ARRAY_SIZE(eld_rates); i++)
+			if (r->min <= eld_rates[i] && r->max >= eld_rates[i])
+				rate_mask |= BIT(i);
+
+		for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3)
+			if (rate_mask & sad[1])
+				t.max = max(t.max, sad_max_channels(sad));
+	}
+
+	return snd_interval_refine(c, &t);
+}
+
+int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld)
+{
+	int ret;
+
+	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				  eld_limit_rates, eld,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  eld_limit_channels, eld,
+				  SNDRV_PCM_HW_PARAM_RATE, -1);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_pcm_hw_constraint_eld);
-- 
1.8.3.1

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

* [PATCH 11/13] sound/core: add IEC958 channel status helper
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (9 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 10/13] sound/core: add DRM ELD helper Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-22 12:40     ` Mark Brown
  2015-05-09 10:26   ` [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver Russell King
  2015-05-09 10:26   ` [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver Russell King
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown,
	Philipp Zabel, Yakir Yang

Add a helper to create the IEC958 channel status from an ALSA
snd_pcm_runtime structure, taking account of the sample rate and
sample size.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 include/sound/pcm_iec958.h |  9 +++++
 sound/core/Kconfig         |  3 ++
 sound/core/Makefile        |  1 +
 sound/core/pcm_iec958.c    | 95 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 108 insertions(+)
 create mode 100644 include/sound/pcm_iec958.h
 create mode 100644 sound/core/pcm_iec958.c

diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h
new file mode 100644
index 000000000000..0eed397aca8e
--- /dev/null
+++ b/include/sound/pcm_iec958.h
@@ -0,0 +1,9 @@
+#ifndef __SOUND_PCM_IEC958_H
+#define __SOUND_PCM_IEC958_H
+
+#include <linux/types.h>
+
+int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
+	size_t len);
+
+#endif
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index b534c8a6046b..1507469425ec 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -9,6 +9,9 @@ config SND_PCM
 config SND_PCM_ELD
 	bool
 
+config SND_PCM_IEC958
+	bool
+
 config SND_DMAENGINE_PCM
 	tristate
 
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 591b49157b4d..2b925fcc95ea 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -14,6 +14,7 @@ snd-pcm-y := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
 		pcm_memory.o memalloc.o
 snd-pcm-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
 snd-pcm-$(CONFIG_SND_PCM_ELD) += pcm_drm_eld.o
+snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o
 
 # for trace-points
 CFLAGS_pcm_lib.o := -I$(src)
diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
new file mode 100644
index 000000000000..36b2d7aca1bd
--- /dev/null
+++ b/sound/core/pcm_iec958.c
@@ -0,0 +1,95 @@
+/*
+ *  PCM DRM helpers
+ *
+ *   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.
+ */
+#include <linux/export.h>
+#include <linux/types.h>
+#include <sound/asoundef.h>
+#include <sound/pcm.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)
+{
+	unsigned int fs, ws;
+
+	if (len < 4)
+		return -EINVAL;
+
+	switch (runtime->rate) {
+	case 32000:
+		fs = IEC958_AES3_CON_FS_32000;
+		break;
+	case 44100:
+		fs = IEC958_AES3_CON_FS_44100;
+		break;
+	case 48000:
+		fs = IEC958_AES3_CON_FS_48000;
+		break;
+	case 88200:
+		fs = IEC958_AES3_CON_FS_88200;
+		break;
+	case 96000:
+		fs = IEC958_AES3_CON_FS_96000;
+		break;
+	case 176400:
+		fs = IEC958_AES3_CON_FS_176400;
+		break;
+	case 192000:
+		fs = IEC958_AES3_CON_FS_192000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (len > 4) {
+		switch (snd_pcm_format_width(runtime->format)) {
+		case 16:
+			ws = IEC958_AES4_CON_WORDLEN_20_16;
+			break;
+		case 18:
+			ws = IEC958_AES4_CON_WORDLEN_22_18;
+			break;
+		case 20:
+			ws = IEC958_AES4_CON_WORDLEN_20_16 |
+			     IEC958_AES4_CON_MAX_WORDLEN_24;
+			break;
+		case 24:
+			ws = IEC958_AES4_CON_WORDLEN_24_20 |
+			     IEC958_AES4_CON_MAX_WORDLEN_24;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	memset(cs, 0, len);
+
+	cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
+	cs[1] = IEC958_AES1_CON_GENERAL;
+	cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
+	cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
+
+	if (len > 4)
+		cs[4] = ws;
+
+	return len;
+}
+EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
-- 
1.8.3.1

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

* [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (10 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 11/13] sound/core: add IEC958 channel status helper Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-09 16:49     ` [alsa-devel] " Anssi Hannula
  2015-05-09 10:26   ` [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver Russell King
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Philipp Zabel, Yakir Yang

Add ALSA based HDMI AHB audio driver for dw_hdmi.  The only buffer
format supported by the hardware is its own special IEC958 based format,
which is not compatible with any ALSA format.  To avoid doing too much
data manipulation within the driver, we support only ALSAs IEC958 LE and
24-bit PCM formats for 2 to 6 channels, which we convert to its hardware
format.

A more desirable solution would be to have this conversion in userspace,
but ALSA does not appear to allow such transformations outside of
libasound itself.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/Kconfig             |  10 +
 drivers/gpu/drm/bridge/Makefile            |   1 +
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 560 +++++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h |  13 +
 drivers/gpu/drm/bridge/dw_hdmi.c           |  24 ++
 drivers/gpu/drm/bridge/dw_hdmi.h           |   3 +
 6 files changed, 611 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
 create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index acef3223772c..56ed35fe0734 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -3,6 +3,16 @@ config DRM_DW_HDMI
 	depends on DRM
 	select DRM_KMS_HELPER
 
+config DRM_DW_HDMI_AHB_AUDIO
+	tristate "Synopsis Designware AHB Audio interface"
+	depends on DRM_DW_HDMI && SND
+	select SND_PCM
+	select SND_PCM_IEC958
+	help
+	  Support the AHB Audio interface which is part of the Synopsis
+	  Designware HDMI block.  This is used in conjunction with
+	  the i.MX6 HDMI driver.
+
 config DRM_PTN3460
 	tristate "PTN3460 DP/LVDS bridge"
 	depends on DRM
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 8dfebd984370..eb80dbbb8365 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -3,3 +3,4 @@ ccflags-y := -Iinclude/drm
 obj-$(CONFIG_DRM_PS8622) += ps8622.o
 obj-$(CONFIG_DRM_PTN3460) += ptn3460.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
+obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw_hdmi-ahb-audio.o
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
new file mode 100644
index 000000000000..e98c291268f4
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
@@ -0,0 +1,560 @@
+/*
+ * DesignWare HDMI audio driver
+ *
+ * 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.
+ *
+ * Written and tested against the Designware HDMI Tx found in iMX6.
+ */
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <drm/bridge/dw_hdmi.h>
+
+#include <sound/asoundef.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_iec958.h>
+
+#include "dw_hdmi-ahb-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-ahb-audio"
+
+/* Provide some bits rather than bit offsets */
+enum {
+	HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7),
+	HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3),
+	HDMI_AHB_DMA_START_START = BIT(0),
+	HDMI_AHB_DMA_STOP_STOP = BIT(0),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL =
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL |
+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY,
+	HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5),
+	HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4),
+	HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3),
+	HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2),
+	HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
+	HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
+	HDMI_IH_AHBDMAAUD_STAT0_ALL =
+		HDMI_IH_AHBDMAAUD_STAT0_ERROR |
+		HDMI_IH_AHBDMAAUD_STAT0_LOST |
+		HDMI_IH_AHBDMAAUD_STAT0_RETRY |
+		HDMI_IH_AHBDMAAUD_STAT0_DONE |
+		HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL |
+		HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY,
+	HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1,
+	HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1,
+	HDMI_AHB_DMA_CONF0_INCR4 = 0,
+	HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0),
+	HDMI_AHB_DMA_MASK_DONE = BIT(7),
+	HDMI_REVISION_ID = 0x0001,
+	HDMI_IH_AHBDMAAUD_STAT0 = 0x0109,
+	HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189,
+	HDMI_AHB_DMA_CONF0 = 0x3600,
+	HDMI_AHB_DMA_START = 0x3601,
+	HDMI_AHB_DMA_STOP = 0x3602,
+	HDMI_AHB_DMA_THRSLD = 0x3603,
+	HDMI_AHB_DMA_STRADDR0 = 0x3604,
+	HDMI_AHB_DMA_STPADDR0 = 0x3608,
+	HDMI_AHB_DMA_MASK = 0x3614,
+	HDMI_AHB_DMA_POL = 0x3615,
+	HDMI_AHB_DMA_CONF1 = 0x3616,
+	HDMI_AHB_DMA_BUFFPOL = 0x361a,
+};
+
+struct snd_dw_hdmi {
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	struct dw_hdmi_audio_data data;
+	struct snd_pcm_substream *substream;
+	void (*reformat)(struct snd_dw_hdmi *, size_t, size_t);
+	void *buf_src;
+	void *buf_dst;
+	dma_addr_t buf_addr;
+	unsigned buf_offset;
+	unsigned buf_period;
+	unsigned buf_size;
+	unsigned channels;
+	u8 revision;
+	u8 iec_offset;
+	u8 cs[192][8];
+};
+
+static void dw_hdmi_writel(unsigned long val, void __iomem *ptr)
+{
+	writeb_relaxed(val, ptr);
+	writeb_relaxed(val >> 8, ptr + 1);
+	writeb_relaxed(val >> 16, ptr + 2);
+	writeb_relaxed(val >> 24, ptr + 3);
+}
+
+/*
+ * Convert to hardware format: The userspace buffer contains IEC958 samples,
+ * with the PCUV bits in bits 31..28 and audio samples in bits 27..4.  We
+ * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio
+ * samples in 23..0.
+ *
+ * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd
+ *
+ * Ideally, we could do with having the data properly formatted in userspace.
+ */
+static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw,
+	size_t offset, size_t bytes)
+{
+	u32 *src = dw->buf_src + offset;
+	u32 *dst = dw->buf_dst + offset;
+	u32 *end = dw->buf_src + offset + bytes;
+
+	do {
+		u32 b, sample = *src++;
+
+		b = (sample & 8) << (28 - 3);
+
+		sample >>= 4;
+
+		*dst++ = sample | b;
+	} while (src < end);
+}
+
+static u32 parity(u32 sample)
+{
+	sample ^= sample >> 16;
+	sample ^= sample >> 8;
+	sample ^= sample >> 4;
+	sample ^= sample >> 2;
+	sample ^= sample >> 1;
+	return (sample & 1) << 27;
+}
+
+static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw,
+	size_t offset, size_t bytes)
+{
+	u32 *src = dw->buf_src + offset;
+	u32 *dst = dw->buf_dst + offset;
+	u32 *end = dw->buf_src + offset + bytes;
+
+	do {
+		unsigned i;
+		u8 *cs;
+
+		cs = dw->cs[dw->iec_offset++];
+		if (dw->iec_offset >= 192)
+			dw->iec_offset = 0;
+
+		i = dw->channels;
+		do {
+			u32 sample = *src++;
+
+			sample &= ~0xff000000;
+			sample |= *cs++ << 24;
+			sample |= parity(sample & ~0xf8000000);
+
+			*dst++ = sample;
+		} while (--i);
+	} while (src < end);
+}
+
+static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw,
+	struct snd_pcm_runtime *runtime)
+{
+	u8 cs[4];
+	unsigned ch, i, j;
+
+	snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs));
+
+	memset(dw->cs, 0, sizeof(dw->cs));
+
+	for (ch = 0; ch < 8; ch++) {
+		cs[2] &= ~IEC958_AES2_CON_CHANNEL;
+		cs[2] |= (ch + 1) << 4;
+
+		for (i = 0; i < ARRAY_SIZE(cs); i++) {
+			unsigned c = cs[i];
+
+			for (j = 0; j < 8; j++, c >>= 1)
+				dw->cs[i * 8 + j][ch] = (c & 1) << 2;
+		}
+	}
+	dw->cs[0][0] |= BIT(4);
+}
+
+static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw)
+{
+	void __iomem *base = dw->data.base;
+	unsigned offset = dw->buf_offset;
+	unsigned period = dw->buf_period;
+	u32 start, stop;
+
+	dw->reformat(dw, offset, period);
+
+	/* Clear all irqs before enabling irqs and starting DMA */
+	writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL,
+		       base + HDMI_IH_AHBDMAAUD_STAT0);
+
+	start = dw->buf_addr + offset;
+	stop = start + period - 1;
+
+	/* Setup the hardware start/stop addresses */
+	dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0);
+	dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0);
+
+	writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK);
+	writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START);
+
+	offset += period;
+	if (offset >= dw->buf_size)
+		offset = 0;
+	dw->buf_offset = offset;
+}
+
+static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw)
+{
+	dw->substream = NULL;
+
+	/* Disable interrupts before disabling DMA */
+	writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK);
+	writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP);
+}
+
+static irqreturn_t snd_dw_hdmi_irq(int irq, void *data)
+{
+	struct snd_dw_hdmi *dw = data;
+	struct snd_pcm_substream *substream;
+	unsigned stat;
+
+	stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
+	if (!stat)
+		return IRQ_NONE;
+
+	writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
+
+	substream = dw->substream;
+	if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) {
+		snd_pcm_period_elapsed(substream);
+		if (dw->substream)
+			dw_hdmi_start_dma(dw);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct snd_pcm_hardware dw_hdmi_hw = {
+	.info = SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
+		   SNDRV_PCM_FMTBIT_S24_LE,
+	.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,
+	.channels_min = 2,
+	.channels_max = 8,
+	.buffer_bytes_max = 64 * 1024,
+	.period_bytes_min = 256,
+	.period_bytes_max = 8192,	/* ERR004323: must limit to 8k */
+	.periods_min = 2,
+	.periods_max = 16,
+	.fifo_size = 0,
+};
+
+static int dw_hdmi_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dw_hdmi *dw = substream->private_data;
+	void __iomem *base = dw->data.base;
+	int ret;
+
+	runtime->hw = dw_hdmi_hw;
+
+	ret = snd_pcm_limit_hw_rates(runtime);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (ret < 0)
+		return ret;
+
+	/* Clear FIFO */
+	writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST,
+		       base + HDMI_AHB_DMA_CONF0);
+
+	/* Configure interrupt polarities */
+	writeb_relaxed(~0, base + HDMI_AHB_DMA_POL);
+	writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL);
+
+	/* Keep interrupts masked, and clear any pending */
+	writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK);
+	writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0);
+
+	ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED,
+			  "dw-hdmi-audio", dw);
+	if (ret)
+		return ret;
+
+	/* Un-mute done interrupt */
+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL &
+		       ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE,
+		       base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+	return 0;
+}
+
+static int dw_hdmi_close(struct snd_pcm_substream *substream)
+{
+	struct snd_dw_hdmi *dw = substream->private_data;
+
+	/* Mute all interrupts */
+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
+		       dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+	free_irq(dw->data.irq, dw);
+
+	return 0;
+}
+
+static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
+{
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+						params_buffer_bytes(params));
+}
+
+static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dw_hdmi *dw = substream->private_data;
+	u8 threshold, conf0, conf1;
+
+	/* Setup as per 3.0.5 FSL 4.1.0 BSP */
+	switch (dw->revision) {
+	case 0x0a:
+		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
+			HDMI_AHB_DMA_CONF0_INCR4;
+		if (runtime->channels == 2)
+			threshold = 126;
+		else
+			threshold = 124;
+		break;
+	case 0x1a:
+		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
+			HDMI_AHB_DMA_CONF0_INCR8;
+		threshold = 128;
+		break;
+	default:
+		/* NOTREACHED */
+		return -EINVAL;
+	}
+
+	dw_hdmi_set_sample_rate(dw->data.hdmi, runtime->rate);
+
+	/* Minimum number of bytes in the fifo. */
+	runtime->hw.fifo_size = threshold * 32;
+
+	conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK;
+	conf1 = (1 << runtime->channels) - 1;
+
+	writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD);
+	writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0);
+	writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1);
+
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
+		dw->reformat = dw_hdmi_reformat_iec958;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		dw_hdmi_create_cs(dw, runtime);
+		dw->reformat = dw_hdmi_reformat_s24;
+		break;
+	}
+	dw->iec_offset = 0;
+	dw->channels = runtime->channels;
+	dw->buf_src  = runtime->dma_area;
+	dw->buf_dst  = substream->dma_buffer.area;
+	dw->buf_addr = substream->dma_buffer.addr;
+	dw->buf_period = snd_pcm_lib_period_bytes(substream);
+	dw->buf_size = snd_pcm_lib_buffer_bytes(substream);
+
+	return 0;
+}
+
+static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_dw_hdmi *dw = substream->private_data;
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		dw->buf_offset = 0;
+		dw->substream = substream;
+		dw_hdmi_start_dma(dw);
+		dw_hdmi_audio_enable(dw->data.hdmi);
+		substream->runtime->delay = substream->runtime->period_size;
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_hdmi_stop_dma(dw);
+		dw_hdmi_audio_disable(dw->data.hdmi);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_dw_hdmi *dw = substream->private_data;
+
+	return bytes_to_frames(runtime, dw->buf_offset);
+}
+
+static struct snd_pcm_ops snd_dw_hdmi_ops = {
+	.open = dw_hdmi_open,
+	.close = dw_hdmi_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = dw_hdmi_hw_params,
+	.hw_free = dw_hdmi_hw_free,
+	.prepare = dw_hdmi_prepare,
+	.trigger = dw_hdmi_trigger,
+	.pointer = dw_hdmi_pointer,
+	.page = snd_pcm_lib_get_vmalloc_page,
+};
+
+static int snd_dw_hdmi_probe(struct platform_device *pdev)
+{
+	const struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
+	struct device *dev = pdev->dev.parent;
+	struct snd_dw_hdmi *dw;
+	struct snd_card *card;
+	struct snd_pcm *pcm;
+	unsigned revision;
+	int ret;
+
+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
+		       data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+	revision = readb_relaxed(data->base + HDMI_REVISION_ID);
+	if (revision != 0x0a && revision != 0x1a) {
+		dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n",
+			revision);
+		return -ENXIO;
+	}
+
+	ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			      THIS_MODULE, sizeof(struct snd_dw_hdmi), &card);
+	if (ret < 0)
+		return ret;
+
+	strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+	strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname));
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s rev 0x%02x, irq %d", card->shortname, revision,
+		 data->irq);
+
+	dw = card->private_data;
+	dw->card = card;
+	dw->data = *data;
+	dw->revision = revision;
+
+	ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm);
+	if (ret < 0)
+		goto err;
+
+	dw->pcm = pcm;
+	pcm->private_data = dw;
+	strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops);
+
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+			dev, 64 * 1024, 64 * 1024);
+
+	ret = snd_card_register(card);
+	if (ret < 0)
+		goto err;
+
+	platform_set_drvdata(pdev, dw);
+
+	return 0;
+
+err:
+	snd_card_free(card);
+	return ret;
+}
+
+static int snd_dw_hdmi_remove(struct platform_device *pdev)
+{
+	struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
+
+	snd_card_free(dw->card);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int snd_dw_hdmi_suspend(struct device *dev)
+{
+	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
+
+	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold);
+	snd_pcm_suspend_all(dw->pcm);
+
+	return 0;
+}
+
+static int snd_dw_hdmi_resume(struct device *dev)
+{
+	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
+
+	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
+			 snd_dw_hdmi_resume);
+#define PM_OPS &snd_dw_hdmi_pm
+#else
+#define PM_OPS NULL
+#endif
+
+static struct platform_driver snd_dw_hdmi_driver = {
+	.probe	= snd_dw_hdmi_probe,
+	.remove	= snd_dw_hdmi_remove,
+	.driver	= {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm = PM_OPS,
+	},
+};
+
+module_platform_driver(snd_dw_hdmi_driver);
+
+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
new file mode 100644
index 000000000000..1e840118d90a
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
@@ -0,0 +1,13 @@
+#ifndef DW_HDMI_AUDIO_H
+#define DW_HDMI_AUDIO_H
+
+struct dw_hdmi;
+
+struct dw_hdmi_audio_data {
+	phys_addr_t phys;
+	void __iomem *base;
+	int irq;
+	struct dw_hdmi *hdmi;
+};
+
+#endif
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index adda3a988f36..1cb427935ed2 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -28,6 +28,7 @@
 #include <drm/bridge/dw_hdmi.h>
 
 #include "dw_hdmi.h"
+#include "dw_hdmi-ahb-audio.h"
 
 #define HDMI_EDID_LEN		512
 
@@ -105,6 +106,7 @@ struct dw_hdmi {
 	struct drm_encoder *encoder;
 	struct drm_bridge *bridge;
 
+	struct platform_device *audio;
 	enum dw_hdmi_devtype dev_type;
 	struct device *dev;
 	struct clk *isfr_clk;
@@ -1592,7 +1594,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = data;
 	struct device_node *np = dev->of_node;
+	struct platform_device_info pdevinfo;
 	struct device_node *ddc_node;
+	struct dw_hdmi_audio_data audio;
 	struct dw_hdmi *hdmi;
 	int ret;
 	u32 val = 1;
@@ -1712,6 +1716,23 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 	/* Unmute interrupts */
 	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+	pdevinfo.parent = dev;
+	pdevinfo.id = PLATFORM_DEVID_AUTO;
+
+	if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
+		audio.phys = iores->start;
+		audio.base = hdmi->regs;
+		audio.irq = irq;
+		audio.hdmi = hdmi;
+
+		pdevinfo.name = "dw-hdmi-ahb-audio";
+		pdevinfo.data = &audio;
+		pdevinfo.size_data = sizeof(audio);
+		pdevinfo.dma_mask = DMA_BIT_MASK(32);
+		hdmi->audio = platform_device_register_full(&pdevinfo);
+	}
+
 	dev_set_drvdata(dev, hdmi);
 
 	return 0;
@@ -1729,6 +1750,9 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
 {
 	struct dw_hdmi *hdmi = dev_get_drvdata(dev);
 
+	if (hdmi->audio && !IS_ERR(hdmi->audio))
+		platform_device_unregister(hdmi->audio);
+
 	/* Disable all interrupts */
 	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
 
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index 175dbc89a824..78e54e813212 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -545,6 +545,9 @@
 #define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
 
 enum {
+/* CONFIG1_ID field values */
+	HDMI_CONFIG1_AHB = 0x01,
+
 /* IH_FC_INT2 field values */
 	HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
 	HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
-- 
1.8.3.1

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

* [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
                     ` (11 preceding siblings ...)
  2015-05-09 10:26   ` [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver Russell King
@ 2015-05-09 10:26   ` Russell King
  2015-05-27 10:43     ` Daniel Vetter
  12 siblings, 1 reply; 74+ messages in thread
From: Russell King @ 2015-05-09 10:26 UTC (permalink / raw)
  To: alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown,
	Philipp Zabel, Yakir Yang

Parse the ELD (EDID like data) stored from the HDMI driver to restrict
the sample rates and channels which are available to ALSA.  This causes
the ALSA device to reflect the capabilities of the overall audio path,
not just what is supported at the HDMI source interface level.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/bridge/Kconfig             | 1 +
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 6 ++++++
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h | 1 +
 drivers/gpu/drm/bridge/dw_hdmi.c           | 3 +++
 4 files changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 56ed35fe0734..204861bfb867 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -7,6 +7,7 @@ config DRM_DW_HDMI_AHB_AUDIO
 	tristate "Synopsis Designware AHB Audio interface"
 	depends on DRM_DW_HDMI && SND
 	select SND_PCM
+	select SND_PCM_ELD
 	select SND_PCM_IEC958
 	help
 	  Support the AHB Audio interface which is part of the Synopsis
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
index e98c291268f4..2bb68bda3cb0 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
@@ -12,11 +12,13 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <drm/bridge/dw_hdmi.h>
+#include <drm/drm_edid.h>
 
 #include <sound/asoundef.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
+#include <sound/pcm_drm_eld.h>
 #include <sound/pcm_iec958.h>
 
 #include "dw_hdmi-ahb-audio.h"
@@ -284,6 +286,10 @@ static int dw_hdmi_open(struct snd_pcm_substream *substream)
 
 	runtime->hw = dw_hdmi_hw;
 
+	ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld);
+	if (ret < 0)
+		return ret;
+
 	ret = snd_pcm_limit_hw_rates(runtime);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
index 1e840118d90a..91f631beecc7 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
@@ -8,6 +8,7 @@ struct dw_hdmi_audio_data {
 	void __iomem *base;
 	int irq;
 	struct dw_hdmi *hdmi;
+	u8 *eld;
 };
 
 #endif
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 1cb427935ed2..dc0aed18019d 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1446,6 +1446,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
 
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
+		/* Store the ELD */
+		drm_edid_to_eld(connector, edid);
 		kfree(edid);
 	} else {
 		dev_dbg(hdmi->dev, "failed to get edid\n");
@@ -1725,6 +1727,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		audio.base = hdmi->regs;
 		audio.irq = irq;
 		audio.hdmi = hdmi;
+		audio.eld = hdmi->connector.eld;
 
 		pdevinfo.name = "dw-hdmi-ahb-audio";
 		pdevinfo.data = &audio;
-- 
1.8.3.1

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 10:26   ` [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver Russell King
@ 2015-05-09 16:49     ` Anssi Hannula
  2015-05-09 16:55       ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Anssi Hannula @ 2015-05-09 16:49 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

Hi,

A couple of things I noticed below:

09.05.2015, 13:26, Russell King kirjoitti:
> Add ALSA based HDMI AHB audio driver for dw_hdmi.  The only buffer
> format supported by the hardware is its own special IEC958 based format,
> which is not compatible with any ALSA format.  To avoid doing too much
> data manipulation within the driver, we support only ALSAs IEC958 LE and
> 24-bit PCM formats for 2 to 6 channels, which we convert to its hardware
> format.
> 
> A more desirable solution would be to have this conversion in userspace,
> but ALSA does not appear to allow such transformations outside of
> libasound itself.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
>  drivers/gpu/drm/bridge/Kconfig             |  10 +
>  drivers/gpu/drm/bridge/Makefile            |   1 +
>  drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 560 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h |  13 +
>  drivers/gpu/drm/bridge/dw_hdmi.c           |  24 ++
>  drivers/gpu/drm/bridge/dw_hdmi.h           |   3 +
>  6 files changed, 611 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
>  create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
> 
[...]
> +static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw,
> +	struct snd_pcm_runtime *runtime)
> +{
> +	u8 cs[4];
> +	unsigned ch, i, j;
> +
> +	snd_pcm_create_iec958_consumer(runtime, cs, sizeof(cs));


I think generally drivers have left the iec958 bits for userspace to
handle, i.e. via a "IEC958 Playback Default"
(SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT)) mixer element, with
defaults coming from /usr/share/alsa/pcm/hdmi.conf...

Looking at the sound driver tree, now, though, they are already somewhat
inconsistent:

1. Most drivers: iec958 bits from userspace, except for hw-set bits.

2. Some drivers (e.g. ctxfi, fsl_spdif): Some bits such as rate set by
driver, but everything is also exposed to userspace.
At least in fsl_spdif case the driver sets the stuff in hw_params which
would then get overwritten by userspace (which sets them after hw_params).

3. Some drivers (e.g. omap-hdmi-audio): Set by driver, not exposed to
userspace, like in this patch.

(Of course having userspace set them requires that the device has a
proper entry in /usr/share/alsa/cards and the pcm device is accessed via
the standard "hdmi" or "iec958" device names which perform the channel
status word setup. I guess the ARM SoC stuff generally doesn't bother
with that, explaining a bit why some kernel drivers set them by themselves).

The main interest to iec958 bits from userspace is probably towards the
non-audio bit, used for audio passthrough (the bit is not mandatory
there, but it helps).

Other drivers (well, I guess just HDA has this so far) also use the
userspace-provided non-audio bit to also select (in conjunction with
channels==8) the HBR mode, i.e. HD audio passthrough (which dw_hdmi also
supports via DMA_CONF0 but not enabled on this patch).


Since this isn't the first driver doing things this way, and this
doesn't really prevent exposing them to userspace later on, I guess this
patch is still OK here, unless the ALSA people think otherwise...


[...]
> +static struct snd_pcm_hardware dw_hdmi_hw = {
> +	.info = SNDRV_PCM_INFO_INTERLEAVED |
> +		SNDRV_PCM_INFO_BLOCK_TRANSFER |
> +		SNDRV_PCM_INFO_MMAP |
> +		SNDRV_PCM_INFO_MMAP_VALID,
> +	.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
> +		   SNDRV_PCM_FMTBIT_S24_LE,
> +	.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,
> +	.channels_min = 2,
> +	.channels_max = 8,

You are providing multichannel support, but AFAICS you are not setting
the channel allocation (CA) bits in the audio infoframe anywhere
(HDMI_FC_AUDICONF2 register).

HDMI_FC_AUDICONF2 register default value is 0x00, which means plain
stereo (per CEA-861). If this is what goes on to the HDMI link as well,
the audio sink should ignore the other channels.
Did you check that multichannel PCM actually works? (maybe I'm just
missing where CA is set)


Note also that I think this HW uses the native HDMI channel order (from
CEA-861), which is different from the ALSA default channel order, so you
should inform userspace of the channel order (via
snd_pcm_add_chmap_ctls()). The channel order is specified by the CA
value I mentioned above.

Assuming I'm not missing something which makes everything work already,
one of these should be implemented:

(a) Provide all the chmaps (i.e. one per CA value) as a list for
userspace to select one, and provide the active chmap to userspace as well.

(b) Just hardcode a single CA value per channel count (which covers 99%
of use cases), and provide the corresponding active chmap to userspace.

(c) channels_max = 2.

Both (a) and (b) are generic stuff that could/should be in helpers for
all drivers to use (if (b), preferably with an interface that allows
easily extending it to (a) in the future).

Some of the code from sound/pci/hda/patch_hdmi.c should be useful (at
least the CA table it has - this stuff really shoud be outside the
driver). Note that much of the complexity of patch_hdmi.c comes from the
fact that the HW there supports channel remapping
(SNDRV_CTL_TLVT_CHMAP_VAR or _PAIRED), which dw_hdmi doesn't
(SNDRV_CTL_TLVT_CHMAP_FIXED).


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

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 16:49     ` [alsa-devel] " Anssi Hannula
@ 2015-05-09 16:55       ` Russell King - ARM Linux
  2015-05-09 17:07         ` Anssi Hannula
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-09 16:55 UTC (permalink / raw)
  To: Anssi Hannula
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Sat, May 09, 2015 at 07:49:44PM +0300, Anssi Hannula wrote:
> (Of course having userspace set them requires that the device has a
> proper entry in /usr/share/alsa/cards and the pcm device is accessed via
> the standard "hdmi" or "iec958" device names which perform the channel
> status word setup. I guess the ARM SoC stuff generally doesn't bother
> with that, explaining a bit why some kernel drivers set them by themselves).

I'm not sure that's sufficient - I haven't yet found where in the ALSA
userspace, the AES bits are appropriately set according to the sample
rate.

> HDMI_FC_AUDICONF2 register default value is 0x00, which means plain
> stereo (per CEA-861). If this is what goes on to the HDMI link as well,
> the audio sink should ignore the other channels.
> Did you check that multichannel PCM actually works? (maybe I'm just
> missing where CA is set)

I have no way to test multichannel support - not everyone has a plethora
of HDMI devices readily accessible.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 16:55       ` Russell King - ARM Linux
@ 2015-05-09 17:07         ` Anssi Hannula
  2015-05-09 17:40           ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Anssi Hannula @ 2015-05-09 17:07 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

09.05.2015, 19:55, Russell King - ARM Linux kirjoitti:
> On Sat, May 09, 2015 at 07:49:44PM +0300, Anssi Hannula wrote:
>> (Of course having userspace set them requires that the device has a
>> proper entry in /usr/share/alsa/cards and the pcm device is accessed via
>> the standard "hdmi" or "iec958" device names which perform the channel
>> status word setup. I guess the ARM SoC stuff generally doesn't bother
>> with that, explaining a bit why some kernel drivers set them by themselves).
> 
> I'm not sure that's sufficient - I haven't yet found where in the ALSA
> userspace, the AES bits are appropriately set according to the sample
> rate.

Right, that is left to the applications (e.g. VLC and Kodi do that). I'm
under the impression that sinks do not normally care about this value,
though, but that could just be because most desktop HW sets it by
themselves.

But indeed, that is one reason to have the kernel set it.

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

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 17:07         ` Anssi Hannula
@ 2015-05-09 17:40           ` Russell King - ARM Linux
  2015-05-09 17:53             ` Russell King - ARM Linux
  2015-05-09 17:55             ` Anssi Hannula
  0 siblings, 2 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-09 17:40 UTC (permalink / raw)
  To: Anssi Hannula
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Sat, May 09, 2015 at 08:07:45PM +0300, Anssi Hannula wrote:
> 09.05.2015, 19:55, Russell King - ARM Linux kirjoitti:
> > On Sat, May 09, 2015 at 07:49:44PM +0300, Anssi Hannula wrote:
> >> (Of course having userspace set them requires that the device has a
> >> proper entry in /usr/share/alsa/cards and the pcm device is accessed via
> >> the standard "hdmi" or "iec958" device names which perform the channel
> >> status word setup. I guess the ARM SoC stuff generally doesn't bother
> >> with that, explaining a bit why some kernel drivers set them by themselves).
> > 
> > I'm not sure that's sufficient - I haven't yet found where in the ALSA
> > userspace, the AES bits are appropriately set according to the sample
> > rate.
> 
> Right, that is left to the applications (e.g. VLC and Kodi do that). I'm
> under the impression that sinks do not normally care about this value,
> though, but that could just be because most desktop HW sets it by
> themselves.

No, that seems totally wrong to me.

What if you open the device using aplay?  Or pulseaudio?  Or madplay?
Or another audio application which thinks it's addressing a standard
PCM device.

Why should every audio user have some code in it to generate the IEC
bits?

Even VLC _doesn't_ if it's outputting to a standard audio - in other
words, if you don't tick the SPDIF direct output option which defaults
to disabled (which, when enabled, opens the device passing the AES
bits _and_ permits it to send a compressed audio stream.)  I've looked
at this in VLC many times...

I think you're a little confused about what userspace does here.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 17:40           ` Russell King - ARM Linux
@ 2015-05-09 17:53             ` Russell King - ARM Linux
  2015-05-09 17:55             ` Anssi Hannula
  1 sibling, 0 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-09 17:53 UTC (permalink / raw)
  To: Anssi Hannula
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Sat, May 09, 2015 at 06:40:54PM +0100, Russell King - ARM Linux wrote:
> Even VLC _doesn't_ if it's outputting to a standard audio - in other
> words, if you don't tick the SPDIF direct output option which defaults
> to disabled (which, when enabled, opens the device passing the AES
> bits _and_ permits it to send a compressed audio stream.)  I've looked
> at this in VLC many times...

FYI, here's the code:

    vlc_fourcc_t fourcc = aout->format.i_format;
    bool spdif = false;
    switch (fourcc)
    {
... other linear float/integer codec IDs ...
        case VLC_CODEC_U16B:
            pcm_format = SND_PCM_FORMAT_U16_BE;
            break;
        case VLC_CODEC_U16L:
            pcm_format = SND_PCM_FORMAT_U16_LE;
            break;
...
        default:
            if (AOUT_FMT_SPDIF(&aout->format))
                spdif = var_InheritBool (aout, "spdif");
            if (spdif)
            {
                fourcc = VLC_CODEC_SPDIFL;
                pcm_format = SND_PCM_FORMAT_S16;
            }
            else
            if (HAVE_FPU)
            {
                fourcc = VLC_CODEC_FL32;
                pcm_format = SND_PCM_FORMAT_FLOAT;
            }
            else
            {
                fourcc = VLC_CODEC_S16N;
                pcm_format = SND_PCM_FORMAT_S16;
            }
    }

    /* Choose the IEC device for S/PDIF output:
       if the device is overridden by the user then it will be the one.
       Otherwise we compute the default device based on the output format. */
    if (spdif && !strcmp (device, "default"))
    {
        unsigned aes3;

        switch (aout->format.i_rate)
        {
#define FS(freq) \
            case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break;
            FS( 44100) /* def. */ FS( 48000) FS( 32000)
            FS( 22050)            FS( 24000)
            FS( 88200) FS(768000) FS( 96000)
            FS(176400)            FS(192000)
#undef FS
            default:
                aes3 = IEC958_AES3_CON_FS_NOTID;
                break;
        }

        free (device);
        if (asprintf (&device,
                      "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
                      IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
                      IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
                      0, aes3) == -1)
            return VLC_ENOMEM;
    }
...
    /* VLC always has a resampler. No need for ALSA's. */
    const int mode = SND_PCM_NO_AUTO_RESAMPLE;

    int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_PLAYBACK, mode);

So, the result is:

* VLC opens the ALSA device _without_ AES information if the fourcc
  being passed if the format is a linear PCM type.

* If the format is not a linear PCM type _and_ it is a format which
  satisfies AOUT_FMT_SPDIF(), _and_ the SPDIF passthrough option is
  enabled, _then_ we open the IEC958 audio output device with the
  first four AES data bytes specified with SND_PCM_FORMAT_S16.
  Moreover, the first data byte always indicates that the stream is
  non-audio.

So, in the case of linear PCM, the AES data bytes are *not* specified
by VLC.

So, if we don't have the kernel driver specifying the IEC958 information
for HDMI/SPDIF outputs, and users of ALSA's userspace APIs don't generate
them for linear PCM, how are the required AES data bytes generated?

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 17:40           ` Russell King - ARM Linux
  2015-05-09 17:53             ` Russell King - ARM Linux
@ 2015-05-09 17:55             ` Anssi Hannula
  2015-05-09 18:11               ` Russell King - ARM Linux
  1 sibling, 1 reply; 74+ messages in thread
From: Anssi Hannula @ 2015-05-09 17:55 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

09.05.2015, 20:40, Russell King - ARM Linux kirjoitti:
> On Sat, May 09, 2015 at 08:07:45PM +0300, Anssi Hannula wrote:
>> 09.05.2015, 19:55, Russell King - ARM Linux kirjoitti:
>>> On Sat, May 09, 2015 at 07:49:44PM +0300, Anssi Hannula wrote:
>>>> (Of course having userspace set them requires that the device has a
>>>> proper entry in /usr/share/alsa/cards and the pcm device is accessed via
>>>> the standard "hdmi" or "iec958" device names which perform the channel
>>>> status word setup. I guess the ARM SoC stuff generally doesn't bother
>>>> with that, explaining a bit why some kernel drivers set them by themselves).
>>>
>>> I'm not sure that's sufficient - I haven't yet found where in the ALSA
>>> userspace, the AES bits are appropriately set according to the sample
>>> rate.
>>
>> Right, that is left to the applications (e.g. VLC and Kodi do that). I'm
>> under the impression that sinks do not normally care about this value,
>> though, but that could just be because most desktop HW sets it by
>> themselves.
> 
> No, that seems totally wrong to me.
> 
> What if you open the device using aplay?  Or pulseaudio?  Or madplay?
> Or another audio application which thinks it's addressing a standard
> PCM device.

Then, unless the driver or HW sets it, it is not set.

> Why should every audio user have some code in it to generate the IEC
> bits?

Yeah, it makes zero sense of course, I wasn't claiming otherwise (sorry
if it seemed like it).

> Even VLC _doesn't_ if it's outputting to a standard audio - in other
> words, if you don't tick the SPDIF direct output option which defaults
> to disabled (which, when enabled, opens the device passing the AES
> bits _and_ permits it to send a compressed audio stream.)  I've looked
> at this in VLC many times...

That is my understanding as well. Same for pulseaudio, it doesn't set
any AES bits except for passthrough (and most other applications never
set them).

> I think you're a little confused about what userspace does here.

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

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 17:55             ` Anssi Hannula
@ 2015-05-09 18:11               ` Russell King - ARM Linux
  2015-05-10 18:59                 ` Anssi Hannula
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-09 18:11 UTC (permalink / raw)
  To: Anssi Hannula
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Sat, May 09, 2015 at 08:55:10PM +0300, Anssi Hannula wrote:
> 09.05.2015, 20:40, Russell King - ARM Linux kirjoitti:
> > Even VLC _doesn't_ if it's outputting to a standard audio - in other
> > words, if you don't tick the SPDIF direct output option which defaults
> > to disabled (which, when enabled, opens the device passing the AES
> > bits _and_ permits it to send a compressed audio stream.)  I've looked
> > at this in VLC many times...
> 
> That is my understanding as well. Same for pulseaudio, it doesn't set
> any AES bits except for passthrough (and most other applications never
> set them).

Right, so when you're dealing with HDMI, where it's required that the
AES bits contain accurate information, the only real option is to set
it appropriately in the driver if userspace doesn't specify the AES
data bits.

Now, with the dw-hdmi-ahb driver, I'm doing something sensible - and
yes, I do have a card file in /usr/share/alsa (see below).

What this does is ensure that linear PCM is converted to 24-bit PCM
(which makes the kernel conversion to the required hardware format
easier - I hate this, I'd much prefer it to be done in userspace.)

However, in the case of VLC, if it wants to send non-audio, it will
open the IEC958 device, which will use the iec958 plugin to configure
the AES bits for non-audio, and pass IEC958 data to the kernel (which
still needs to be reformatted to the hardware's special format.)

dw-hdmi-ahb-aud.pcm.default {
	@args [ CARD ]
	@args.CARD { type string }
	type asym
	playback.pcm {
		type softvol
		slave.pcm {
			type plug
			slave.pcm {
				@func concat
				strings [ "dmix:" $CARD ",FORMAT=S24_LE" ]
			}
		}
		control {
			name "PCM Playback Volume"
			card $CARD
		}
	}
}

<confdir:pcm/iec958.conf>

dw-hdmi-ahb-aud.pcm.iec958.0 {
	@args [ CARD AES0 AES1 AES2 AES3 ]
	@args.CARD { type string }
	@args.AES0 { type integer }
	@args.AES1 { type integer }
	@args.AES2 { type integer }
	@args.AES3 { type integer }
	type iec958
	slave.pcm {
		type hw
		card $CARD
		device 0
	}
	slave.format IEC958_SUBFRAME_LE
	status [ $AES0 $AES1 $AES2 $AES3 ]
}


-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-09 18:11               ` Russell King - ARM Linux
@ 2015-05-10 18:59                 ` Anssi Hannula
  2015-05-10 19:33                   ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Anssi Hannula @ 2015-05-10 18:59 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

09.05.2015, 21:11, Russell King - ARM Linux kirjoitti:
> On Sat, May 09, 2015 at 08:55:10PM +0300, Anssi Hannula wrote:
>> 09.05.2015, 20:40, Russell King - ARM Linux kirjoitti:
>>> Even VLC _doesn't_ if it's outputting to a standard audio - in other
>>> words, if you don't tick the SPDIF direct output option which defaults
>>> to disabled (which, when enabled, opens the device passing the AES
>>> bits _and_ permits it to send a compressed audio stream.)  I've looked
>>> at this in VLC many times...
>>
>> That is my understanding as well. Same for pulseaudio, it doesn't set
>> any AES bits except for passthrough (and most other applications never
>> set them).
> 
> Right, so when you're dealing with HDMI, where it's required that the
> AES bits contain accurate information, the only real option is to set
> it appropriately in the driver if userspace doesn't specify the AES
> data bits.

I wonder whether receivers actually care with HDMI (they generally don't
with S/PDIF) - that's one tidbit for me to test later... But of course
it doesn't change much with the matter at hand, in any case we should
strive to get the bits correct if only because the HDMI spec requires
them to be (I don't think they were optional in IEC 60958-3 either, though).

> Now, with the dw-hdmi-ahb driver, I'm doing something sensible

Right.

What I'd like to see is arrive at some sort of general consensus on how
the AES bits should be handled (i.e. should the driver always set them
themselves and disallow/allow the userspace to override the rate bits),
which could then be applied to other drivers as well.

But maybe that is for another time, or just a futile effort altogether...

> - and
> yes, I do have a card file in /usr/share/alsa (see below).
> 
> What this does is ensure that linear PCM is converted to 24-bit PCM
> (which makes the kernel conversion to the required hardware format
> easier - I hate this, I'd much prefer it to be done in userspace.)

Indeed. I did notice there is a SND(RV)_PCM_FORMAT_SPECIAL but I guess
it might not be easily used for this purpose since it doesn't have a
specific sample width etc (but I am not familiar enough with this to say
whether it could work or not)...

> However, in the case of VLC, if it wants to send non-audio, it will
> open the IEC958 device, which will use the iec958 plugin to configure
> the AES bits for non-audio, and pass IEC958 data to the kernel (which
> still needs to be reformatted to the hardware's special format.)

Ah, so the AES bits are actually overridable by userspace, which is what
I was initially concerned with :)

Of course, this means that applications opening "iec958" but not setting
rate bits (which is common) will get the default 48kHz bits from
/usr/share/alsa/pcm/(iec958|hdmi).conf). Not sure how big an issue that
is, though. The "iec958" ALSA plugin does seem to have a FIXME comment
about setting AES bits according to sample rate.


[...]
> 
> <confdir:pcm/iec958.conf>
> 
> dw-hdmi-ahb-aud.pcm.iec958.0 {

I think you should s/iec958/hdmi/ for the above two lines. HDMI devices
should be using "hdmi" instead of "iec958" by convention (the latter is
used for optical/coaxial S/PDIF).

> 	@args [ CARD AES0 AES1 AES2 AES3 ]
> 	@args.CARD { type string }
> 	@args.AES0 { type integer }
> 	@args.AES1 { type integer }
> 	@args.AES2 { type integer }
> 	@args.AES3 { type integer }
> 	type iec958
> 	slave.pcm {
> 		type hw
> 		card $CARD
> 		device 0
> 	}
> 	slave.format IEC958_SUBFRAME_LE
> 	status [ $AES0 $AES1 $AES2 $AES3 ]
> }
> 
> 

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

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-10 18:59                 ` Anssi Hannula
@ 2015-05-10 19:33                   ` Russell King - ARM Linux
  2015-05-10 20:47                     ` Anssi Hannula
  2015-05-11 15:58                     ` Mark Brown
  0 siblings, 2 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-10 19:33 UTC (permalink / raw)
  To: Anssi Hannula
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Sun, May 10, 2015 at 09:59:42PM +0300, Anssi Hannula wrote:
> I wonder whether receivers actually care with HDMI (they generally don't
> with S/PDIF) - that's one tidbit for me to test later... But of course
> it doesn't change much with the matter at hand, in any case we should
> strive to get the bits correct if only because the HDMI spec requires
> them to be (I don't think they were optional in IEC 60958-3 either, though).

I suspect they don't care too much, but the HDMI spec does require them
to be correct.  If we're trying to aim for best compatibility, setting
them correctly is something we should strive to do.

> What I'd like to see is arrive at some sort of general consensus on how
> the AES bits should be handled (i.e. should the driver always set them
> themselves and disallow/allow the userspace to override the rate bits),
> which could then be applied to other drivers as well.
> 
> But maybe that is for another time, or just a futile effort altogether...

My personal view is that where we're dealing with PCM audio, the driver
needs to set these bits correctly as there is nothing in userspace to
do this.  This provides an identical interface between each audio device
which accepts PCM samples - whether it's a SPDIF or non-SPDIF based
device.

For non-audio data sent via an audio device, the AES bits need to be
conveyed from userspace, and we should respect what userspace gives us.
(If it's wrong, it's a userspace bug, and userspace should be fixed,
rather than trying to work around the bug by patching the kernel.)

> Indeed. I did notice there is a SND(RV)_PCM_FORMAT_SPECIAL but I guess
> it might not be easily used for this purpose since it doesn't have a
> specific sample width etc (but I am not familiar enough with this to say
> whether it could work or not)...

I spent quite a while looking at alsa-lib, wondering whether I could
move all the conversions out to userspace, but I couldn't without
building them _into_ alsa-lib.  This was a while back now, but from
what I remember, plugins to alsa-lib which aren't built as part of
alsa-lib are not able to do format conversions.

> > However, in the case of VLC, if it wants to send non-audio, it will
> > open the IEC958 device, which will use the iec958 plugin to configure
> > the AES bits for non-audio, and pass IEC958 data to the kernel (which
> > still needs to be reformatted to the hardware's special format.)
> 
> Ah, so the AES bits are actually overridable by userspace, which is what
> I was initially concerned with :)
> 
> Of course, this means that applications opening "iec958" but not setting
> rate bits (which is common) will get the default 48kHz bits from
> /usr/share/alsa/pcm/(iec958|hdmi).conf). Not sure how big an issue that
> is, though. The "iec958" ALSA plugin does seem to have a FIXME comment
> about setting AES bits according to sample rate.

Note that VLC does set the "sample" rate appropriately:

        switch (aout->format.i_rate)
        {
#define FS(freq) \
            case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break;
            FS( 44100) /* def. */ FS( 48000) FS( 32000)
            FS( 22050)            FS( 24000)
            FS( 88200) FS(768000) FS( 96000)
            FS(176400)            FS(192000)
#undef FS
            default:
                aes3 = IEC958_AES3_CON_FS_NOTID;
                break;

> > <confdir:pcm/iec958.conf>
> > 
> > dw-hdmi-ahb-aud.pcm.iec958.0 {
> 
> I think you should s/iec958/hdmi/ for the above two lines. HDMI devices
> should be using "hdmi" instead of "iec958" by convention (the latter is
> used for optical/coaxial S/PDIF).

Except doing that kills VLC's passthrough option (denoted by "spdif"),
which explicitly wants the iec958 device:

    /* Choose the IEC device for S/PDIF output:
       if the device is overridden by the user then it will be the one.
       Otherwise we compute the default device based on the output format. */
    if (spdif && !strcmp (device, "default"))
    {
...
        if (asprintf (&device,
                      "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
                      IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
                      IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
                      0, aes3) == -1)

Yes, technically an application bug, since VLC should allow the device
to be selectable and/or detect hdmi devices.  I wonder if that's
something which has changed between 2.0.8 and the latest vlc.

I did consider having the hdmi output device, but also alias that to
the iec958 device name, which I think can be done via:

<confdir:pcm/hdmi.conf>

dw-hdmi-ahb-aud.pcm.hdmi.0 {
...
}

<confdir:pcm/iec958.conf>

dw-hdmi-ahb-aud.pcm.iec958.0 cards.dw-hdmi-ahb-aud.pcm.hdmi.0

However, for HDMI sinks, I haven't seen any way in Linux to allow
userspace to know the audio capabilities of the attached HDMI sink,
and thus whether the video player can output compressed MPEG audio.
Anyone know?

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-10 19:33                   ` Russell King - ARM Linux
@ 2015-05-10 20:47                     ` Anssi Hannula
  2015-05-11 15:58                     ` Mark Brown
  1 sibling, 0 replies; 74+ messages in thread
From: Anssi Hannula @ 2015-05-10 20:47 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

10.05.2015, 22:33, Russell King - ARM Linux kirjoitti:
> On Sun, May 10, 2015 at 09:59:42PM +0300, Anssi Hannula wrote:
>> What I'd like to see is arrive at some sort of general consensus on how
>> the AES bits should be handled (i.e. should the driver always set them
>> themselves and disallow/allow the userspace to override the rate bits),
>> which could then be applied to other drivers as well.
>>
>> But maybe that is for another time, or just a futile effort altogether...
> 
> My personal view is that where we're dealing with PCM audio, the driver
> needs to set these bits correctly as there is nothing in userspace to
> do this.  This provides an identical interface between each audio device
> which accepts PCM samples - whether it's a SPDIF or non-SPDIF based
> device.
>
> For non-audio data sent via an audio device, the AES bits need to be
> conveyed from userspace, and we should respect what userspace gives us.
> (If it's wrong, it's a userspace bug, and userspace should be fixed,
> rather than trying to work around the bug by patching the kernel.)

Just to make sure I didn't misunderstand. You propose looking at the
"non-pcm" (aka "non-audio") bit in the AES to see whether driver/kernel
should force rate (and maybe other) AES bits?
Because I think that is currently the only way for the kernel/driver to
know if the data is "non-audio".


>> Indeed. I did notice there is a SND(RV)_PCM_FORMAT_SPECIAL but I guess
>> it might not be easily used for this purpose since it doesn't have a
>> specific sample width etc (but I am not familiar enough with this to say
>> whether it could work or not)...
> 
> I spent quite a while looking at alsa-lib, wondering whether I could
> move all the conversions out to userspace, but I couldn't without
> building them _into_ alsa-lib.  This was a while back now, but from
> what I remember, plugins to alsa-lib which aren't built as part of
> alsa-lib are not able to do format conversions.

Sounds a bit strange (assuming one'd plainly reference the plugin from
<hw>.conf directly), but OK. I'm not suggesting to look into it again
unless you really want to yourself :)

>>> However, in the case of VLC, if it wants to send non-audio, it will
>>> open the IEC958 device, which will use the iec958 plugin to configure
>>> the AES bits for non-audio, and pass IEC958 data to the kernel (which
>>> still needs to be reformatted to the hardware's special format.)
>>
>> Ah, so the AES bits are actually overridable by userspace, which is what
>> I was initially concerned with :)
>>
>> Of course, this means that applications opening "iec958" but not setting
>> rate bits (which is common) will get the default 48kHz bits from
>> /usr/share/alsa/pcm/(iec958|hdmi).conf). Not sure how big an issue that
>> is, though. The "iec958" ALSA plugin does seem to have a FIXME comment
>> about setting AES bits according to sample rate.
> 
> Note that VLC does set the "sample" rate appropriately:
> 
>         switch (aout->format.i_rate)
>         {
> #define FS(freq) \
>             case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break;
>             FS( 44100) /* def. */ FS( 48000) FS( 32000)
>             FS( 22050)            FS( 24000)
>             FS( 88200) FS(768000) FS( 96000)
>             FS(176400)            FS(192000)
> #undef FS
>             default:
>                 aes3 = IEC958_AES3_CON_FS_NOTID;
>                 break;

Yep, one of the few that do.

>>> <confdir:pcm/iec958.conf>
>>>
>>> dw-hdmi-ahb-aud.pcm.iec958.0 {
>>
>> I think you should s/iec958/hdmi/ for the above two lines. HDMI devices
>> should be using "hdmi" instead of "iec958" by convention (the latter is
>> used for optical/coaxial S/PDIF).
> 
> Except doing that kills VLC's passthrough option (denoted by "spdif"),
> which explicitly wants the iec958 device:
> 
>     /* Choose the IEC device for S/PDIF output:
>        if the device is overridden by the user then it will be the one.
>        Otherwise we compute the default device based on the output format. */
>     if (spdif && !strcmp (device, "default"))
>     {
> ...
>         if (asprintf (&device,
>                       "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
>                       IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
>                       IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
>                       0, aes3) == -1)
> 
> Yes, technically an application bug, since VLC should allow the device
> to be selectable and/or detect hdmi devices.  I wonder if that's
> something which has changed between 2.0.8 and the latest vlc.

Yes, in the current version it appends the parameters to the configured
device if it contains "iec958" or "hdmi" (git log says iec958 was
un-hardcoded on the above line in Jan 2014).

So if you have selected the "HDMI Output" device from the audio dropdown
in settings, it would work.

However, the default device "default" is still mangled to "iec958", (the
code has a "TODO: hdmi" comment).


> I did consider having the hdmi output device, but also alias that to
> the iec958 device name, which I think can be done via:
> 
> <confdir:pcm/hdmi.conf>
> 
> dw-hdmi-ahb-aud.pcm.hdmi.0 {
> ...
> }
> 
> <confdir:pcm/iec958.conf>
> 
> dw-hdmi-ahb-aud.pcm.iec958.0 cards.dw-hdmi-ahb-aud.pcm.hdmi.0

If a userspace workaround is wanted, I think I'd prefer this one myself.

Personally, I don't believe a workaround is of much use here, because
using "iec958" is already broken for majority of HDMI users anyway (i.e.
those that use HDMI outputs on x86 PCs)... but I don't see the
workaround as strictly unacceptable, either.


Also, if this used "hdmi" and no workaround, i.MX6 devices with both
S/PDIF and HDMI connectors would then have just a single iec958* device
and a single hdmi* device. But I guess that doesn't matter *that* much...

> However, for HDMI sinks, I haven't seen any way in Linux to allow
> userspace to know the audio capabilities of the attached HDMI sink,
> and thus whether the video player can output compressed MPEG audio.
> Anyone know?

HDA driver exports the ELD as a mixer control, which the application can
then use to determine the capabilities.

Not the best idea IMHO (I think ELD should've preferably remained
internal since I think it should be considered an implementation detail,
plus it is not very application friendly), but it is what it is and I
guess it was the easiest way to do it from ALSA side.

I know pulseaudio uses the ELD control to:
- get receiver name
- trigger a device change event when it changes

Kodi uses it to:
- get receiver name
- get default passthrough (compressed audio) capabilities
- trigger re-enumeration and device reopening when it changes
(e.g. if the user starts audio playback before turning on their
amplifier/receiver, we might've started the playback with
less-than-optimal parameters due to ALSA driver ELD rate/channel
restrictions, since the amplifier/receiver might've passed us the
probably-more-limited monitor/TV SADs instead of its own SADs when the
receiver was in standby mode).

But I wouldn't be too surprised if those were the only users.

-- 
Anssi Hannula



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

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

* Re: [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver
  2015-05-10 19:33                   ` Russell King - ARM Linux
  2015-05-10 20:47                     ` Anssi Hannula
@ 2015-05-11 15:58                     ` Mark Brown
  1 sibling, 0 replies; 74+ messages in thread
From: Mark Brown @ 2015-05-11 15:58 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, David Airlie, dri-devel, Takashi Iwai,
	Philipp Zabel, Yakir Yang, Anssi Hannula, linux-arm-kernel

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

On Sun, May 10, 2015 at 08:33:20PM +0100, Russell King - ARM Linux wrote:

> My personal view is that where we're dealing with PCM audio, the driver
> needs to set these bits correctly as there is nothing in userspace to
> do this.  This provides an identical interface between each audio device
> which accepts PCM samples - whether it's a SPDIF or non-SPDIF based
> device.

> For non-audio data sent via an audio device, the AES bits need to be
> conveyed from userspace, and we should respect what userspace gives us.
> (If it's wrong, it's a userspace bug, and userspace should be fixed,
> rather than trying to work around the bug by patching the kernel.)

For what it's worth this is exactly what I'd be expecting to happen -
the kernel should do something by default and then let applications
override it if they so desire.

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

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



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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-09 10:26   ` [PATCH 10/13] sound/core: add DRM ELD helper Russell King
@ 2015-05-22 12:20     ` Mark Brown
  2015-05-22 13:15       ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Mark Brown @ 2015-05-22 12:20 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, alsa-devel, David Airlie, dri-devel, Takashi Iwai,
	Philipp Zabel, Yakir Yang, linux-arm-kernel

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

On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> Add a helper for the EDID like data structure, which is typically passed
> from a HDMI adapter to its associated audio driver.  This informs the
> audio driver of the capabilities of the attached HDMI sink.

As far as I can tell people are fairly happy with the implementation
here and unless I'm missing something are definitely happy with the
interface.  If that's the case can we get this into -next?  There's a
lot of interest in HDMI right now (which is great) and this would be
helpful for that, it seems like even if there are issues with the
implementation it would be worth merging as is so we can start adding
users and then do any improvements to the interface in parallel.

From an interface point of view:

Reviewed-by: Mark Brown <broonie@kernel.org>

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 11/13] sound/core: add IEC958 channel status helper
  2015-05-09 10:26   ` [PATCH 11/13] sound/core: add IEC958 channel status helper Russell King
@ 2015-05-22 12:40     ` Mark Brown
  0 siblings, 0 replies; 74+ messages in thread
From: Mark Brown @ 2015-05-22 12:40 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, alsa-devel, David Airlie, dri-devel, Takashi Iwai,
	Philipp Zabel, Yakir Yang, linux-arm-kernel

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

On Sat, May 09, 2015 at 11:26:47AM +0100, Russell King wrote:
> Add a helper to create the IEC958 channel status from an ALSA
> snd_pcm_runtime structure, taking account of the sample rate and
> sample size.

This also looks good to me from an interface point of view:

Reviwed-by: Mark Brown <broonie@kernel.org>

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

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



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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 12:20     ` [alsa-devel] " Mark Brown
@ 2015-05-22 13:15       ` Russell King - ARM Linux
  2015-05-22 13:30         ` Takashi Iwai
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-22 13:15 UTC (permalink / raw)
  To: Mark Brown
  Cc: Fabio Estevam, alsa-devel, dri-devel, Yakir Yang, linux-arm-kernel

On Fri, May 22, 2015 at 01:20:09PM +0100, Mark Brown wrote:
> On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> > Add a helper for the EDID like data structure, which is typically passed
> > from a HDMI adapter to its associated audio driver.  This informs the
> > audio driver of the capabilities of the attached HDMI sink.
> 
> As far as I can tell people are fairly happy with the implementation
> here and unless I'm missing something are definitely happy with the
> interface.  If that's the case can we get this into -next?  There's a
> lot of interest in HDMI right now (which is great) and this would be
> helpful for that, it seems like even if there are issues with the
> implementation it would be worth merging as is so we can start adding
> users and then do any improvements to the interface in parallel.
> 
> From an interface point of view:
> 
> Reviewed-by: Mark Brown <broonie@kernel.org>

I'd be more than happy if Takashi Iwai wants to take them - I'm not
planning on the audio driver itself being merged just yet as we still
need to properly hammer out the differences between the AHB audio (for
iMX6) and I2S audio (for Rockchip) for this device.

Alternatively, I could move these two patches to the beginning of my
series, and merge that point into my for-next and/or publish it as a
separate sub-branch... whatever people want, just let me know.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 13:15       ` Russell King - ARM Linux
@ 2015-05-22 13:30         ` Takashi Iwai
  2015-05-22 13:53           ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Takashi Iwai @ 2015-05-22 13:30 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

At Fri, 22 May 2015 14:15:35 +0100,
Russell King - ARM Linux wrote:
> 
> On Fri, May 22, 2015 at 01:20:09PM +0100, Mark Brown wrote:
> > On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> > > Add a helper for the EDID like data structure, which is typically passed
> > > from a HDMI adapter to its associated audio driver.  This informs the
> > > audio driver of the capabilities of the attached HDMI sink.
> > 
> > As far as I can tell people are fairly happy with the implementation
> > here and unless I'm missing something are definitely happy with the
> > interface.  If that's the case can we get this into -next?  There's a
> > lot of interest in HDMI right now (which is great) and this would be
> > helpful for that, it seems like even if there are issues with the
> > implementation it would be worth merging as is so we can start adding
> > users and then do any improvements to the interface in parallel.
> > 
> > From an interface point of view:
> > 
> > Reviewed-by: Mark Brown <broonie@kernel.org>
> 
> I'd be more than happy if Takashi Iwai wants to take them - I'm not
> planning on the audio driver itself being merged just yet as we still
> need to properly hammer out the differences between the AHB audio (for
> iMX6) and I2S audio (for Rockchip) for this device.

Sorry, I've been on vacation in the last two weeks, so slowly
digesting all backlogs now.

> Alternatively, I could move these two patches to the beginning of my
> series, and merge that point into my for-next and/or publish it as a
> separate sub-branch... whatever people want, just let me know.

I'm fine to take the sound part.  It's only patches 10 and 11, right?
Then I can provide a branch that can be merged for the rest drm
stuff.


thanks,

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

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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 13:30         ` Takashi Iwai
@ 2015-05-22 13:53           ` Russell King - ARM Linux
  2015-05-22 13:54             ` Takashi Iwai
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-22 13:53 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Fri, May 22, 2015 at 03:30:54PM +0200, Takashi Iwai wrote:
> At Fri, 22 May 2015 14:15:35 +0100,
> Russell King - ARM Linux wrote:
> > 
> > On Fri, May 22, 2015 at 01:20:09PM +0100, Mark Brown wrote:
> > > On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> > > > Add a helper for the EDID like data structure, which is typically passed
> > > > from a HDMI adapter to its associated audio driver.  This informs the
> > > > audio driver of the capabilities of the attached HDMI sink.
> > > 
> > > As far as I can tell people are fairly happy with the implementation
> > > here and unless I'm missing something are definitely happy with the
> > > interface.  If that's the case can we get this into -next?  There's a
> > > lot of interest in HDMI right now (which is great) and this would be
> > > helpful for that, it seems like even if there are issues with the
> > > implementation it would be worth merging as is so we can start adding
> > > users and then do any improvements to the interface in parallel.
> > > 
> > > From an interface point of view:
> > > 
> > > Reviewed-by: Mark Brown <broonie@kernel.org>
> > 
> > I'd be more than happy if Takashi Iwai wants to take them - I'm not
> > planning on the audio driver itself being merged just yet as we still
> > need to properly hammer out the differences between the AHB audio (for
> > iMX6) and I2S audio (for Rockchip) for this device.
> 
> Sorry, I've been on vacation in the last two weeks, so slowly
> digesting all backlogs now.
> 
> > Alternatively, I could move these two patches to the beginning of my
> > series, and merge that point into my for-next and/or publish it as a
> > separate sub-branch... whatever people want, just let me know.
> 
> I'm fine to take the sound part.  It's only patches 10 and 11, right?
> Then I can provide a branch that can be merged for the rest drm
> stuff.

Yep, just patches 10 and 11.  If possible, please base these patches on
v4.1-rc1, thanks.

Thanks.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 13:53           ` Russell King - ARM Linux
@ 2015-05-22 13:54             ` Takashi Iwai
  2015-05-22 14:00               ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Takashi Iwai @ 2015-05-22 13:54 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

At Fri, 22 May 2015 14:53:31 +0100,
Russell King - ARM Linux wrote:
> 
> On Fri, May 22, 2015 at 03:30:54PM +0200, Takashi Iwai wrote:
> > At Fri, 22 May 2015 14:15:35 +0100,
> > Russell King - ARM Linux wrote:
> > > 
> > > On Fri, May 22, 2015 at 01:20:09PM +0100, Mark Brown wrote:
> > > > On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> > > > > Add a helper for the EDID like data structure, which is typically passed
> > > > > from a HDMI adapter to its associated audio driver.  This informs the
> > > > > audio driver of the capabilities of the attached HDMI sink.
> > > > 
> > > > As far as I can tell people are fairly happy with the implementation
> > > > here and unless I'm missing something are definitely happy with the
> > > > interface.  If that's the case can we get this into -next?  There's a
> > > > lot of interest in HDMI right now (which is great) and this would be
> > > > helpful for that, it seems like even if there are issues with the
> > > > implementation it would be worth merging as is so we can start adding
> > > > users and then do any improvements to the interface in parallel.
> > > > 
> > > > From an interface point of view:
> > > > 
> > > > Reviewed-by: Mark Brown <broonie@kernel.org>
> > > 
> > > I'd be more than happy if Takashi Iwai wants to take them - I'm not
> > > planning on the audio driver itself being merged just yet as we still
> > > need to properly hammer out the differences between the AHB audio (for
> > > iMX6) and I2S audio (for Rockchip) for this device.
> > 
> > Sorry, I've been on vacation in the last two weeks, so slowly
> > digesting all backlogs now.
> > 
> > > Alternatively, I could move these two patches to the beginning of my
> > > series, and merge that point into my for-next and/or publish it as a
> > > separate sub-branch... whatever people want, just let me know.
> > 
> > I'm fine to take the sound part.  It's only patches 10 and 11, right?
> > Then I can provide a branch that can be merged for the rest drm
> > stuff.
> 
> Yep, just patches 10 and 11.  If possible, please base these patches on
> v4.1-rc1, thanks.

I applied them on top of -rc4, I suppose it's OK?

Now pushed as topic/hdmi branch of sound git tree.
Let me know if anything else needed.


thanks,

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

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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 13:54             ` Takashi Iwai
@ 2015-05-22 14:00               ` Russell King - ARM Linux
  2015-05-22 14:02                 ` Takashi Iwai
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-22 14:00 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Fri, May 22, 2015 at 03:54:56PM +0200, Takashi Iwai wrote:
> At Fri, 22 May 2015 14:53:31 +0100,
> Russell King - ARM Linux wrote:
> > 
> > On Fri, May 22, 2015 at 03:30:54PM +0200, Takashi Iwai wrote:
> > > At Fri, 22 May 2015 14:15:35 +0100,
> > > Russell King - ARM Linux wrote:
> > > > 
> > > > On Fri, May 22, 2015 at 01:20:09PM +0100, Mark Brown wrote:
> > > > > On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> > > > > > Add a helper for the EDID like data structure, which is typically passed
> > > > > > from a HDMI adapter to its associated audio driver.  This informs the
> > > > > > audio driver of the capabilities of the attached HDMI sink.
> > > > > 
> > > > > As far as I can tell people are fairly happy with the implementation
> > > > > here and unless I'm missing something are definitely happy with the
> > > > > interface.  If that's the case can we get this into -next?  There's a
> > > > > lot of interest in HDMI right now (which is great) and this would be
> > > > > helpful for that, it seems like even if there are issues with the
> > > > > implementation it would be worth merging as is so we can start adding
> > > > > users and then do any improvements to the interface in parallel.
> > > > > 
> > > > > From an interface point of view:
> > > > > 
> > > > > Reviewed-by: Mark Brown <broonie@kernel.org>
> > > > 
> > > > I'd be more than happy if Takashi Iwai wants to take them - I'm not
> > > > planning on the audio driver itself being merged just yet as we still
> > > > need to properly hammer out the differences between the AHB audio (for
> > > > iMX6) and I2S audio (for Rockchip) for this device.
> > > 
> > > Sorry, I've been on vacation in the last two weeks, so slowly
> > > digesting all backlogs now.
> > > 
> > > > Alternatively, I could move these two patches to the beginning of my
> > > > series, and merge that point into my for-next and/or publish it as a
> > > > separate sub-branch... whatever people want, just let me know.
> > > 
> > > I'm fine to take the sound part.  It's only patches 10 and 11, right?
> > > Then I can provide a branch that can be merged for the rest drm
> > > stuff.
> > 
> > Yep, just patches 10 and 11.  If possible, please base these patches on
> > v4.1-rc1, thanks.
> 
> I applied them on top of -rc4, I suppose it's OK?

It is, but what it means is that I'll keep my copy of the patches in my
tree rather than pulling your tree.  Having branches spread on different
start points makes it difficult to generate a patch series from the git
tree - which is something I continue to do for the SolidRun iMX6 platforms
(publishing it as separate patches, tarball of those patches and a combined
patch.)

As I say, it doesn't matter that much, I can just keep my copies of the
patches, and when this stuff gets rebased to 4.2-rc1, git rebase should
eliminate them automatically.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 14:00               ` Russell King - ARM Linux
@ 2015-05-22 14:02                 ` Takashi Iwai
  2015-05-22 14:05                   ` Takashi Iwai
  0 siblings, 1 reply; 74+ messages in thread
From: Takashi Iwai @ 2015-05-22 14:02 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

At Fri, 22 May 2015 15:00:10 +0100,
Russell King - ARM Linux wrote:
> 
> On Fri, May 22, 2015 at 03:54:56PM +0200, Takashi Iwai wrote:
> > At Fri, 22 May 2015 14:53:31 +0100,
> > Russell King - ARM Linux wrote:
> > > 
> > > On Fri, May 22, 2015 at 03:30:54PM +0200, Takashi Iwai wrote:
> > > > At Fri, 22 May 2015 14:15:35 +0100,
> > > > Russell King - ARM Linux wrote:
> > > > > 
> > > > > On Fri, May 22, 2015 at 01:20:09PM +0100, Mark Brown wrote:
> > > > > > On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> > > > > > > Add a helper for the EDID like data structure, which is typically passed
> > > > > > > from a HDMI adapter to its associated audio driver.  This informs the
> > > > > > > audio driver of the capabilities of the attached HDMI sink.
> > > > > > 
> > > > > > As far as I can tell people are fairly happy with the implementation
> > > > > > here and unless I'm missing something are definitely happy with the
> > > > > > interface.  If that's the case can we get this into -next?  There's a
> > > > > > lot of interest in HDMI right now (which is great) and this would be
> > > > > > helpful for that, it seems like even if there are issues with the
> > > > > > implementation it would be worth merging as is so we can start adding
> > > > > > users and then do any improvements to the interface in parallel.
> > > > > > 
> > > > > > From an interface point of view:
> > > > > > 
> > > > > > Reviewed-by: Mark Brown <broonie@kernel.org>
> > > > > 
> > > > > I'd be more than happy if Takashi Iwai wants to take them - I'm not
> > > > > planning on the audio driver itself being merged just yet as we still
> > > > > need to properly hammer out the differences between the AHB audio (for
> > > > > iMX6) and I2S audio (for Rockchip) for this device.
> > > > 
> > > > Sorry, I've been on vacation in the last two weeks, so slowly
> > > > digesting all backlogs now.
> > > > 
> > > > > Alternatively, I could move these two patches to the beginning of my
> > > > > series, and merge that point into my for-next and/or publish it as a
> > > > > separate sub-branch... whatever people want, just let me know.
> > > > 
> > > > I'm fine to take the sound part.  It's only patches 10 and 11, right?
> > > > Then I can provide a branch that can be merged for the rest drm
> > > > stuff.
> > > 
> > > Yep, just patches 10 and 11.  If possible, please base these patches on
> > > v4.1-rc1, thanks.
> > 
> > I applied them on top of -rc4, I suppose it's OK?
> 
> It is, but what it means is that I'll keep my copy of the patches in my
> tree rather than pulling your tree.  Having branches spread on different
> start points makes it difficult to generate a patch series from the git
> tree - which is something I continue to do for the SolidRun iMX6 platforms
> (publishing it as separate patches, tarball of those patches and a combined
> patch.)
> 
> As I say, it doesn't matter that much, I can just keep my copies of the
> patches, and when this stuff gets rebased to 4.2-rc1, git rebase should
> eliminate them automatically.

OK, if so, then I rebase on top of -rc1.  The branch isn't merged yet,
so no big problem.


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

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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 14:02                 ` Takashi Iwai
@ 2015-05-22 14:05                   ` Takashi Iwai
  2015-05-22 16:12                     ` Russell King - ARM Linux
  0 siblings, 1 reply; 74+ messages in thread
From: Takashi Iwai @ 2015-05-22 14:05 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

At Fri, 22 May 2015 16:02:13 +0200,
Takashi Iwai wrote:
> 
> At Fri, 22 May 2015 15:00:10 +0100,
> Russell King - ARM Linux wrote:
> > 
> > On Fri, May 22, 2015 at 03:54:56PM +0200, Takashi Iwai wrote:
> > > At Fri, 22 May 2015 14:53:31 +0100,
> > > Russell King - ARM Linux wrote:
> > > > 
> > > > On Fri, May 22, 2015 at 03:30:54PM +0200, Takashi Iwai wrote:
> > > > > At Fri, 22 May 2015 14:15:35 +0100,
> > > > > Russell King - ARM Linux wrote:
> > > > > > 
> > > > > > On Fri, May 22, 2015 at 01:20:09PM +0100, Mark Brown wrote:
> > > > > > > On Sat, May 09, 2015 at 11:26:42AM +0100, Russell King wrote:
> > > > > > > > Add a helper for the EDID like data structure, which is typically passed
> > > > > > > > from a HDMI adapter to its associated audio driver.  This informs the
> > > > > > > > audio driver of the capabilities of the attached HDMI sink.
> > > > > > > 
> > > > > > > As far as I can tell people are fairly happy with the implementation
> > > > > > > here and unless I'm missing something are definitely happy with the
> > > > > > > interface.  If that's the case can we get this into -next?  There's a
> > > > > > > lot of interest in HDMI right now (which is great) and this would be
> > > > > > > helpful for that, it seems like even if there are issues with the
> > > > > > > implementation it would be worth merging as is so we can start adding
> > > > > > > users and then do any improvements to the interface in parallel.
> > > > > > > 
> > > > > > > From an interface point of view:
> > > > > > > 
> > > > > > > Reviewed-by: Mark Brown <broonie@kernel.org>
> > > > > > 
> > > > > > I'd be more than happy if Takashi Iwai wants to take them - I'm not
> > > > > > planning on the audio driver itself being merged just yet as we still
> > > > > > need to properly hammer out the differences between the AHB audio (for
> > > > > > iMX6) and I2S audio (for Rockchip) for this device.
> > > > > 
> > > > > Sorry, I've been on vacation in the last two weeks, so slowly
> > > > > digesting all backlogs now.
> > > > > 
> > > > > > Alternatively, I could move these two patches to the beginning of my
> > > > > > series, and merge that point into my for-next and/or publish it as a
> > > > > > separate sub-branch... whatever people want, just let me know.
> > > > > 
> > > > > I'm fine to take the sound part.  It's only patches 10 and 11, right?
> > > > > Then I can provide a branch that can be merged for the rest drm
> > > > > stuff.
> > > > 
> > > > Yep, just patches 10 and 11.  If possible, please base these patches on
> > > > v4.1-rc1, thanks.
> > > 
> > > I applied them on top of -rc4, I suppose it's OK?
> > 
> > It is, but what it means is that I'll keep my copy of the patches in my
> > tree rather than pulling your tree.  Having branches spread on different
> > start points makes it difficult to generate a patch series from the git
> > tree - which is something I continue to do for the SolidRun iMX6 platforms
> > (publishing it as separate patches, tarball of those patches and a combined
> > patch.)
> > 
> > As I say, it doesn't matter that much, I can just keep my copies of the
> > patches, and when this stuff gets rebased to 4.2-rc1, git rebase should
> > eliminate them automatically.
> 
> OK, if so, then I rebase on top of -rc1.  The branch isn't merged yet,
> so no big problem.

Now the rebased branch is pushed.

I also merged this branch now to for-next branch, so that it'll be
tested through linux-next.


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

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

* Re: [PATCH 02/13] drm: bridge/dw_hdmi: clean up phy configuration
  2015-05-09 10:26   ` [PATCH 02/13] drm: bridge/dw_hdmi: clean up phy configuration Russell King
@ 2015-05-22 15:19     ` Yakir
  0 siblings, 0 replies; 74+ messages in thread
From: Yakir @ 2015-05-22 15:19 UTC (permalink / raw)
  To: Russell King, alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown, Philipp Zabel

Hi Russell,

在 2015/5/9 18:26, Russell King 写道:
> The phy configuration is dependent on the SoC, and we look up values for
> some of the registers in SoC specific data.  However, we had partially
> programmed the phy before we had successfully looked up the clock rate.
> Also, we were only checking that we had a valid configuration for the
> currctrl register.
>
> Move all these lookups to the start of this function instead, so we can
> check that all lookups were successful before beginning to program the
> phy.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Test on RK3288 platform, it works wells  :-)

Test-by: <ykk@rock-chips.com>

Best regards,
Yakir Yang
> ---
>   drivers/gpu/drm/bridge/dw_hdmi.c | 68 +++++++++++++++++++++-------------------
>   1 file changed, 35 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 3494391e4199..23ea8c5c85b6 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -753,12 +753,12 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
>   static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
>   			      unsigned char res, int cscon)
>   {
> -	unsigned res_idx, i;
> +	unsigned res_idx;
>   	u8 val, msec;
> -	const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data;
> -	const struct dw_hdmi_mpll_config *mpll_config = plat_data->mpll_cfg;
> -	const struct dw_hdmi_curr_ctrl *curr_ctrl = plat_data->cur_ctr;
> -	const struct dw_hdmi_phy_config *phy_config = plat_data->phy_config;
> +	const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
> +	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
> +	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
> +	const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
>   
>   	if (prep)
>   		return -EINVAL;
> @@ -778,6 +778,30 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
>   		return -EINVAL;
>   	}
>   
> +	/* PLL/MPLL Cfg - always match on final entry */
> +	for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
> +		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> +		    mpll_config->mpixelclock)
> +			break;
> +
> +	for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
> +		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> +		    curr_ctrl->mpixelclock)
> +			break;
> +
> +	for (; phy_config->mpixelclock != ~0UL; phy_config++)
> +		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> +		    phy_config->mpixelclock)
> +			break;
> +
> +	if (mpll_config->mpixelclock == ~0UL ||
> +	    curr_ctrl->mpixelclock == ~0UL ||
> +	    phy_config->mpixelclock == ~0UL) {
> +		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
> +			hdmi->hdmi_data.video_mode.mpixelclock);
> +		return -EINVAL;
> +	}
> +
>   	/* Enable csc path */
>   	if (cscon)
>   		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
> @@ -803,40 +827,18 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
>   		    HDMI_PHY_I2CM_SLAVE_ADDR);
>   	hdmi_phy_test_clear(hdmi, 0);
>   
> -	/* PLL/MPLL Cfg - always match on final entry */
> -	for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++)
> -		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> -		    mpll_config[i].mpixelclock)
> -			break;
> -
> -	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
> -	hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
> -
> -	for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++)
> -		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> -		    curr_ctrl[i].mpixelclock)
> -			break;
> -
> -	if (curr_ctrl[i].mpixelclock == (~0UL)) {
> -		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
> -			hdmi->hdmi_data.video_mode.mpixelclock);
> -		return -EINVAL;
> -	}
> +	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06);
> +	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
>   
>   	/* CURRCTRL */
> -	hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
> +	hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10);
>   
>   	hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
>   	hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
>   
> -	for (i = 0; phy_config[i].mpixelclock != (~0UL); i++)
> -		if (hdmi->hdmi_data.video_mode.mpixelclock <=
> -		    phy_config[i].mpixelclock)
> -			break;
> -
> -	hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19);  /* TXTERM */
> -	hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
> -	hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */
> +	hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19);  /* TXTERM */
> +	hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
> +	hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
>   
>   	/* REMOVE CLK TERM */
>   	hdmi_phy_i2c_write(hdmi, 0x8000, 0x05);  /* CKCALCTRL */


_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator()
  2015-05-09 10:26   ` [PATCH 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() Russell King
@ 2015-05-22 15:22     ` Yakir
  0 siblings, 0 replies; 74+ messages in thread
From: Yakir @ 2015-05-22 15:22 UTC (permalink / raw)
  To: Russell King, alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown, Philipp Zabel

Hi Russell,

在 2015/5/9 18:26, Russell King 写道:
> Clean up hdmi_set_clk_regenerator() by allowing it to take the audio
> sample rate and ratio directly, rather than hiding it inside the
> function.  Raise the unsupported pixel clock/sample rate message from
> debug to error level as this results in audio not working correctly.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Test on RK3288 platform, it works wells while do not need clear
the ncts_atomic_write bit in aud_n3, so no need more code it's find.

Test-by: <ykk@rock-chips.com>

Best regards,
Yakir Yang
> ---
>   drivers/gpu/drm/bridge/dw_hdmi.c | 32 +++++++++++++++-----------------
>   1 file changed, 15 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 23ea8c5c85b6..75099b80ca7e 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -335,39 +335,37 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
>   }
>   
>   static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
> -				     unsigned long pixel_clk)
> +	unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio)
>   {
> -	unsigned int clk_n, clk_cts;
> +	unsigned int n, cts;
>   
> -	clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
> -			       hdmi->ratio);
> -	clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
> -				   hdmi->ratio);
> -
> -	if (!clk_cts) {
> -		dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
> -			__func__, pixel_clk);
> -		return;
> +	n = hdmi_compute_n(sample_rate, pixel_clk, ratio);
> +	cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio);
> +	if (!cts) {
> +		dev_err(hdmi->dev,
> +			"%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n",
> +			__func__, pixel_clk, sample_rate);
>   	}
>   
> -	dev_dbg(hdmi->dev, "%s: samplerate=%d  ratio=%d  pixelclk=%lu  N=%d cts=%d\n",
> -		__func__, hdmi->sample_rate, hdmi->ratio,
> -		pixel_clk, clk_n, clk_cts);
> +	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
> +		__func__, sample_rate, ratio, pixel_clk, n, cts);
>   
> -	hdmi_set_cts_n(hdmi, clk_cts, clk_n);
> +	hdmi_set_cts_n(hdmi, cts, n);
>   }
>   
>   static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
>   {
>   	mutex_lock(&hdmi->audio_mutex);
> -	hdmi_set_clk_regenerator(hdmi, 74250000);
> +	hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate,
> +				 hdmi->ratio);
>   	mutex_unlock(&hdmi->audio_mutex);
>   }
>   
>   static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
>   {
>   	mutex_lock(&hdmi->audio_mutex);
> -	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
> +	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
> +				 hdmi->sample_rate, hdmi->ratio);
>   	mutex_unlock(&hdmi->audio_mutex);
>   }
>   


_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate
  2015-05-09 10:26   ` [PATCH 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate Russell King
@ 2015-05-22 15:26     ` Yakir
  0 siblings, 0 replies; 74+ messages in thread
From: Yakir @ 2015-05-22 15:26 UTC (permalink / raw)
  To: Russell King, alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown, Philipp Zabel

Hi Russell,

在 2015/5/9 18:26, Russell King 写道:
> Introduce dw_hdmi_set_sample_rate(), which allows us to configure the
> audio sample rate, setting the CTS/N values appropriately.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Test on RK3288 platform, it works wells (like patch 03/13 reply)

Test-by: <ykk@rock-chips.com>

Yakir Yang
> ---
>   drivers/gpu/drm/bridge/dw_hdmi.c | 10 ++++++++++
>   include/drm/bridge/dw_hdmi.h     |  5 +++++
>   2 files changed, 15 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 75728ba552d0..0369fab5c695 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -366,6 +366,16 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
>   	mutex_unlock(&hdmi->audio_mutex);
>   }
>   
> +void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
> +{
> +	mutex_lock(&hdmi->audio_mutex);
> +	hdmi->sample_rate = rate;
> +	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
> +				 hdmi->sample_rate, hdmi->ratio);
> +	mutex_unlock(&hdmi->audio_mutex);
> +}
> +EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
> +
>   /*
>    * this submodule is responsible for the video data synchronization.
>    * for example, for RGB 4:4:4 input, the data map is defined as
> diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
> index de13bfc35634..763af51e1d60 100644
> --- a/include/drm/bridge/dw_hdmi.h
> +++ b/include/drm/bridge/dw_hdmi.h
> @@ -12,6 +12,8 @@
>   
>   #include <drm/drmP.h>
>   
> +struct dw_hdmi;
> +
>   enum {
>   	DW_HDMI_RES_8,
>   	DW_HDMI_RES_10,
> @@ -59,4 +61,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
>   		 void *data, struct drm_encoder *encoder,
>   		 struct resource *iores, int irq,
>   		 const struct dw_hdmi_plat_data *plat_data);
> +
> +void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
> +
>   #endif /* __IMX_HDMI_H__ */


_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio
  2015-05-09 10:26   ` [PATCH 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio Russell King
@ 2015-05-22 15:28     ` Yakir
  0 siblings, 0 replies; 74+ messages in thread
From: Yakir @ 2015-05-22 15:28 UTC (permalink / raw)
  To: Russell King, alsa-devel, dri-devel, linux-arm-kernel
  Cc: Fabio Estevam, David Airlie, Takashi Iwai, Mark Brown, Philipp Zabel

Hi Russell,

在 2015/5/9 18:26, Russell King 写道:
> iMX6 devices suffer from an errata (ERR005174) where the audio FIFO can
> be emptied while it is partially full, resulting in misalignment of the
> audio samples.
>
> To prevent this, the errata workaround recommends writing N as zero
> until the audio FIFO has been loaded by DMA.  Writing N=0 prevents the
> HDMI bridge from reading from the audio FIFO, effectively disabling
> audio.
>
> This means we need to provide the audio driver with a pair of functions
> to enable/disable audio.  These are dw_hdmi_audio_enable() and
> dw_hdmi_audio_disable().
>
> A spinlock is introduced to ensure that setting the CTS/N values can't
> race, ensuring that the audio driver calling the enable/disable
> functions (which are called in an atomic context) can't race with a
> modeset.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Test on RK3288 platform, it works wells. Previously I use to switch off
the i2s audio clock, for now seems it is not necessary.

Test-by: Yakir Yang <ykk@rock-chips.com>

Thanks,
Yakir Yang

> ---
>   drivers/gpu/drm/bridge/dw_hdmi.c | 34 +++++++++++++++++++++++++++++++++-
>   include/drm/bridge/dw_hdmi.h     |  2 ++
>   2 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 0369fab5c695..adda3a988f36 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -18,6 +18,7 @@
>   #include <linux/hdmi.h>
>   #include <linux/mutex.h>
>   #include <linux/of_device.h>
> +#include <linux/spinlock.h>
>   
>   #include <drm/drm_of.h>
>   #include <drm/drmP.h>
> @@ -124,8 +125,12 @@ struct dw_hdmi {
>   	struct i2c_adapter *ddc;
>   	void __iomem *regs;
>   
> +	spinlock_t audio_lock;
>   	struct mutex audio_mutex;
>   	unsigned int sample_rate;
> +	unsigned int audio_cts;
> +	unsigned int audio_n;
> +	bool audio_enable;
>   	int ratio;
>   
>   	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
> @@ -347,7 +352,11 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
>   	dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
>   		__func__, sample_rate, ratio, pixel_clk, n, cts);
>   
> -	hdmi_set_cts_n(hdmi, cts, n);
> +	spin_lock_irq(&hdmi->audio_lock);
> +	hdmi->audio_n = n;
> +	hdmi->audio_cts = cts;
> +	hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
> +	spin_unlock_irq(&hdmi->audio_lock);
>   }
>   
>   static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
> @@ -376,6 +385,28 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
>   }
>   EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
>   
> +void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&hdmi->audio_lock, flags);
> +	hdmi->audio_enable = true;
> +	hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
> +	spin_unlock_irqrestore(&hdmi->audio_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
> +
> +void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&hdmi->audio_lock, flags);
> +	hdmi->audio_enable = false;
> +	hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
> +	spin_unlock_irqrestore(&hdmi->audio_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
> +
>   /*
>    * this submodule is responsible for the video data synchronization.
>    * for example, for RGB 4:4:4 input, the data map is defined as
> @@ -1578,6 +1609,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
>   	hdmi->encoder = encoder;
>   
>   	mutex_init(&hdmi->audio_mutex);
> +	spin_lock_init(&hdmi->audio_lock);
>   
>   	of_property_read_u32(np, "reg-io-width", &val);
>   
> diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
> index 763af51e1d60..bae79f3c4d28 100644
> --- a/include/drm/bridge/dw_hdmi.h
> +++ b/include/drm/bridge/dw_hdmi.h
> @@ -63,5 +63,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
>   		 const struct dw_hdmi_plat_data *plat_data);
>   
>   void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
> +void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
> +void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
>   
>   #endif /* __IMX_HDMI_H__ */


_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [alsa-devel] [PATCH 10/13] sound/core: add DRM ELD helper
  2015-05-22 14:05                   ` Takashi Iwai
@ 2015-05-22 16:12                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-22 16:12 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

On Fri, May 22, 2015 at 04:05:22PM +0200, Takashi Iwai wrote:
> At Fri, 22 May 2015 16:02:13 +0200,
> Takashi Iwai wrote:
> > OK, if so, then I rebase on top of -rc1.  The branch isn't merged yet,
> > so no big problem.
> 
> Now the rebased branch is pushed.
> 
> I also merged this branch now to for-next branch, so that it'll be
> tested through linux-next.

Thanks!

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-09 10:26   ` [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver Russell King
@ 2015-05-27 10:43     ` Daniel Vetter
  2015-05-27 11:43       ` Mark Brown
  2015-05-27 17:31       ` Russell King - ARM Linux
  0 siblings, 2 replies; 74+ messages in thread
From: Daniel Vetter @ 2015-05-27 10:43 UTC (permalink / raw)
  To: Russell King
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Sat, May 09, 2015 at 11:26:57AM +0100, Russell King wrote:
> Parse the ELD (EDID like data) stored from the HDMI driver to restrict
> the sample rates and channels which are available to ALSA.  This causes
> the ALSA device to reflect the capabilities of the overall audio path,
> not just what is supported at the HDMI source interface level.
> 
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

I completely missed the new eld helpers in this series, so fairly late
with a few questions here.

In x86/desktop gpus we pass around the eld in hw, and there's an interrupt
on the snd side every time that materially changes. Same goes for other
state changes like the display pipe getting lit up/disabled again.

How is hotplug handling done here? You update the eld in get_modes, but I
don't see any notification from hdmi->audio (it only seems to get updated
at open time, no idea whether that's enough). And it looks like there's a
potential use-after-free when the drm side updates the eld and frees the
old one, while the snd side tries to access this.

Just curious questions really, I probably don't understand what's exactly
going on. But I do think that we need a more formal way for drm/snd to
talk to each another (i915 is growing quite a few hairy things in that
area outside of eld atm). Problems we have are around shared power wells
and clocks (x86 doesn't help here without all the dt goodness). But
there's also stuff like figuring out the right dividers for a given
audio/video clock. eld and hotplug is still done in hw, but I've heard
noises that we need to have a sw approach too on some platforms at least.

Cheers, Daniel
> ---
>  drivers/gpu/drm/bridge/Kconfig             | 1 +
>  drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c | 6 ++++++
>  drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h | 1 +
>  drivers/gpu/drm/bridge/dw_hdmi.c           | 3 +++
>  4 files changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 56ed35fe0734..204861bfb867 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -7,6 +7,7 @@ config DRM_DW_HDMI_AHB_AUDIO
>  	tristate "Synopsis Designware AHB Audio interface"
>  	depends on DRM_DW_HDMI && SND
>  	select SND_PCM
> +	select SND_PCM_ELD
>  	select SND_PCM_IEC958
>  	help
>  	  Support the AHB Audio interface which is part of the Synopsis
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
> index e98c291268f4..2bb68bda3cb0 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
> @@ -12,11 +12,13 @@
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include <drm/bridge/dw_hdmi.h>
> +#include <drm/drm_edid.h>
>  
>  #include <sound/asoundef.h>
>  #include <sound/core.h>
>  #include <sound/initval.h>
>  #include <sound/pcm.h>
> +#include <sound/pcm_drm_eld.h>
>  #include <sound/pcm_iec958.h>
>  
>  #include "dw_hdmi-ahb-audio.h"
> @@ -284,6 +286,10 @@ static int dw_hdmi_open(struct snd_pcm_substream *substream)
>  
>  	runtime->hw = dw_hdmi_hw;
>  
> +	ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld);
> +	if (ret < 0)
> +		return ret;
> +
>  	ret = snd_pcm_limit_hw_rates(runtime);
>  	if (ret < 0)
>  		return ret;
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
> index 1e840118d90a..91f631beecc7 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
> +++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
> @@ -8,6 +8,7 @@ struct dw_hdmi_audio_data {
>  	void __iomem *base;
>  	int irq;
>  	struct dw_hdmi *hdmi;
> +	u8 *eld;
>  };
>  
>  #endif
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 1cb427935ed2..dc0aed18019d 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -1446,6 +1446,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
>  
>  		drm_mode_connector_update_edid_property(connector, edid);
>  		ret = drm_add_edid_modes(connector, edid);
> +		/* Store the ELD */
> +		drm_edid_to_eld(connector, edid);
>  		kfree(edid);
>  	} else {
>  		dev_dbg(hdmi->dev, "failed to get edid\n");
> @@ -1725,6 +1727,7 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
>  		audio.base = hdmi->regs;
>  		audio.irq = irq;
>  		audio.hdmi = hdmi;
> +		audio.eld = hdmi->connector.eld;
>  
>  		pdevinfo.name = "dw-hdmi-ahb-audio";
>  		pdevinfo.data = &audio;
> -- 
> 1.8.3.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-27 10:43     ` Daniel Vetter
@ 2015-05-27 11:43       ` Mark Brown
  2015-05-27 17:31       ` Russell King - ARM Linux
  1 sibling, 0 replies; 74+ messages in thread
From: Mark Brown @ 2015-05-27 11:43 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Fabio Estevam, alsa-devel, dri-devel, Yakir Yang, Russell King,
	linux-arm-kernel

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

On Wed, May 27, 2015 at 12:43:08PM +0200, Daniel Vetter wrote:

> Just curious questions really, I probably don't understand what's exactly
> going on. But I do think that we need a more formal way for drm/snd to
> talk to each another (i915 is growing quite a few hairy things in that
> area outside of eld atm). Problems we have are around shared power wells

Yes, I agree strongly with this - I've been asking for a while for more
code sharing and common code in this path, the helpers in here are
really good from that point of view and I'm very pleased we've got them
applied.

> and clocks (x86 doesn't help here without all the dt goodness). But
> there's also stuff like figuring out the right dividers for a given
> audio/video clock. eld and hotplug is still done in hw, but I've heard
> noises that we need to have a sw approach too on some platforms at least.

That seems to be the case, yes - FWIW quite a few of the embedded
systems are basically connecting a standard S/PDIF or I2S output to a
HDMI encoder chip or IP block so the audio controller knows nothing of
HDMI directly.

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

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



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

* Re: [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-27 10:43     ` Daniel Vetter
  2015-05-27 11:43       ` Mark Brown
@ 2015-05-27 17:31       ` Russell King - ARM Linux
  2015-05-27 21:29         ` Daniel Vetter
  2015-05-28  4:56         ` [alsa-devel] " Takashi Iwai
  1 sibling, 2 replies; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-27 17:31 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Wed, May 27, 2015 at 12:43:08PM +0200, Daniel Vetter wrote:
> On Sat, May 09, 2015 at 11:26:57AM +0100, Russell King wrote:
> > Parse the ELD (EDID like data) stored from the HDMI driver to restrict
> > the sample rates and channels which are available to ALSA.  This causes
> > the ALSA device to reflect the capabilities of the overall audio path,
> > not just what is supported at the HDMI source interface level.
> > 
> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> 
> I completely missed the new eld helpers in this series, so fairly late
> with a few questions here.
> 
> In x86/desktop gpus we pass around the eld in hw, and there's an interrupt
> on the snd side every time that materially changes. Same goes for other
> state changes like the display pipe getting lit up/disabled again.
> 
> How is hotplug handling done here? You update the eld in get_modes, but I
> don't see any notification from hdmi->audio (it only seems to get updated
> at open time, no idea whether that's enough). And it looks like there's a
> potential use-after-free when the drm side updates the eld and frees the
> old one, while the snd side tries to access this.

It doesn't handle hotplug at all, per se.

The problem with hotplug is that (afaik) ALSA has no way to notify
userspace that something has changed: if I were to add such a
notification from the DRM side of the driver to the audio side, I
wouldn't know what to do with it when the audio side received it.

In any case, I tend to think of unplugging the display as being much
like unplugging the 3.5mm line out jack to your hifi system - just
because you've disconnected the speakers does not stop the audio
playing - the audio continues despite you not being able to hear it.

Sure, there's the problem that if you plug in a display with different
capabilities, the existing format may not be supported, but I don't
see a reasonable method which could provoke what effectively would be
a restart on the ALSA side.

In any case, hotplug is kind-of outside of the remit of these helpers -
these helpers are more to do with decoding an existing ELD and limiting
the capabilities of the audio side to that specified in the ELD.  It's
up to the driver how it gets the ELD, and it's left to the driver to
determine how to handle the change-of-ELD notification.

Given your description of i915 hardware above, I think this makes sense
anyway: if you have a hardware notification system, it makes sense to use
that rather than some software implementation, and requiring a software
implementation for everything to me sounds too limiting.

That's not to say that we couldn't have a software implementation in the
future: right now, I merely concentrated on the parsing issue.

The dw-hdmi audio driver isn't ready for mainlining yet - there's two
variants of this at the moment (one for iMX6 and a different one for
Rockchip - same IP but configured with different interfaces for getting
the audio data into the HDMI block.)  There's still some work to be done
to properly unify the two approaches into something sane.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-27 17:31       ` Russell King - ARM Linux
@ 2015-05-27 21:29         ` Daniel Vetter
  2015-05-27 21:44           ` Russell King - ARM Linux
  2015-05-28  4:56         ` [alsa-devel] " Takashi Iwai
  1 sibling, 1 reply; 74+ messages in thread
From: Daniel Vetter @ 2015-05-27 21:29 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Wed, May 27, 2015 at 7:31 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Wed, May 27, 2015 at 12:43:08PM +0200, Daniel Vetter wrote:
>> On Sat, May 09, 2015 at 11:26:57AM +0100, Russell King wrote:
>> > Parse the ELD (EDID like data) stored from the HDMI driver to restrict
>> > the sample rates and channels which are available to ALSA.  This causes
>> > the ALSA device to reflect the capabilities of the overall audio path,
>> > not just what is supported at the HDMI source interface level.
>> >
>> > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>>
>> I completely missed the new eld helpers in this series, so fairly late
>> with a few questions here.
>>
>> In x86/desktop gpus we pass around the eld in hw, and there's an interrupt
>> on the snd side every time that materially changes. Same goes for other
>> state changes like the display pipe getting lit up/disabled again.
>>
>> How is hotplug handling done here? You update the eld in get_modes, but I
>> don't see any notification from hdmi->audio (it only seems to get updated
>> at open time, no idea whether that's enough). And it looks like there's a
>> potential use-after-free when the drm side updates the eld and frees the
>> old one, while the snd side tries to access this.
>
> It doesn't handle hotplug at all, per se.
>
> The problem with hotplug is that (afaik) ALSA has no way to notify
> userspace that something has changed: if I were to add such a
> notification from the DRM side of the driver to the audio side, I
> wouldn't know what to do with it when the audio side received it.
>
> In any case, I tend to think of unplugging the display as being much
> like unplugging the 3.5mm line out jack to your hifi system - just
> because you've disconnected the speakers does not stop the audio
> playing - the audio continues despite you not being able to hear it.

Yeah, afaik that's the same that happens on intel.

> Sure, there's the problem that if you plug in a display with different
> capabilities, the existing format may not be supported, but I don't
> see a reasonable method which could provoke what effectively would be
> a restart on the ALSA side.
>
> In any case, hotplug is kind-of outside of the remit of these helpers -
> these helpers are more to do with decoding an existing ELD and limiting
> the capabilities of the audio side to that specified in the ELD.  It's
> up to the driver how it gets the ELD, and it's left to the driver to
> determine how to handle the change-of-ELD notification.
>
> Given your description of i915 hardware above, I think this makes sense
> anyway: if you have a hardware notification system, it makes sense to use
> that rather than some software implementation, and requiring a software
> implementation for everything to me sounds too limiting.
>
> That's not to say that we couldn't have a software implementation in the
> future: right now, I merely concentrated on the parsing issue.
>
> The dw-hdmi audio driver isn't ready for mainlining yet - there's two
> variants of this at the moment (one for iMX6 and a different one for
> Rockchip - same IP but configured with different interfaces for getting
> the audio data into the HDMI block.)  There's still some work to be done
> to properly unify the two approaches into something sane.

I agree that it makes sense to start with the parsing issues. And some
of the reconfiguration work we need to do in i915 like retuning
derived clocks when the master display clock changes is definitely
solved better already in the arm world I think ;-) I also don't think
that hotplug handling is all that important, at least a quick read
through the intel snd stuff suggest it doesn't handle any of the
reconfiguration all that well at all. The only issue that might be
there with your sw approach is that a concurrent probe/hotplug in drm
might free the edid and hence the eld, while the snd side is trying to
copy that. I'm not sure how that's prevented. Not really a problem
with the helpers though.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-27 21:29         ` Daniel Vetter
@ 2015-05-27 21:44           ` Russell King - ARM Linux
  2015-05-28  6:43             ` Daniel Vetter
  0 siblings, 1 reply; 74+ messages in thread
From: Russell King - ARM Linux @ 2015-05-27 21:44 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Wed, May 27, 2015 at 11:29:52PM +0200, Daniel Vetter wrote:
> The only issue that might be
> there with your sw approach is that a concurrent probe/hotplug in drm
> might free the edid and hence the eld, while the snd side is trying to
> copy that.

Talking only about the particular case of dw-hdmi-ahb-audio...

The worst that may happen is that the ELD will be overwritten with an
update on hotplug - it won't be freed unless the underlying connector
is freed, as the eld is stored as an array inside struct drm_connector.
Before the DRM connector is freed, we pull the audio driver's struct
device, which will destroy the ALSA device.

Hopefully ALSA already copes gracefully with the removal of an in-use
device... it should do, it's no different from having a USB audio device
and you pull it out of the USB socket while the device is in-use.

(It's also worth noting as we're talking about this, that as the audio
struct device is a child of the HDMI device, any PM activity will be
correctly ordered: the child gets suspended before the parent... the
audio device gets suspended before the video, and resume is of course
the reverse order.)

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [alsa-devel] [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-27 17:31       ` Russell King - ARM Linux
  2015-05-27 21:29         ` Daniel Vetter
@ 2015-05-28  4:56         ` Takashi Iwai
  1 sibling, 0 replies; 74+ messages in thread
From: Takashi Iwai @ 2015-05-28  4:56 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Mark Brown, Yakir Yang,
	linux-arm-kernel

At Wed, 27 May 2015 18:31:25 +0100,
Russell King - ARM Linux wrote:
> 
> On Wed, May 27, 2015 at 12:43:08PM +0200, Daniel Vetter wrote:
> > On Sat, May 09, 2015 at 11:26:57AM +0100, Russell King wrote:
> > > Parse the ELD (EDID like data) stored from the HDMI driver to restrict
> > > the sample rates and channels which are available to ALSA.  This causes
> > > the ALSA device to reflect the capabilities of the overall audio path,
> > > not just what is supported at the HDMI source interface level.
> > > 
> > > Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> > 
> > I completely missed the new eld helpers in this series, so fairly late
> > with a few questions here.
> > 
> > In x86/desktop gpus we pass around the eld in hw, and there's an interrupt
> > on the snd side every time that materially changes. Same goes for other
> > state changes like the display pipe getting lit up/disabled again.
> > 
> > How is hotplug handling done here? You update the eld in get_modes, but I
> > don't see any notification from hdmi->audio (it only seems to get updated
> > at open time, no idea whether that's enough). And it looks like there's a
> > potential use-after-free when the drm side updates the eld and frees the
> > old one, while the snd side tries to access this.
> 
> It doesn't handle hotplug at all, per se.
> 
> The problem with hotplug is that (afaik) ALSA has no way to notify
> userspace that something has changed: if I were to add such a
> notification from the DRM side of the driver to the audio side, I
> wouldn't know what to do with it when the audio side received it.

The notification itself is present.  For HD-audio HDMI/DP, the driver
creates jack kctl for each port for notifying the monitor/ELD change.
The recent PA actually listens to it and handles accordingly.

But it doesn't mean that the PCM and other state changes are
proactively dealt inside the driver.  Rather it gives the
notification, keeps running and waits for the further action from
user-space.

> In any case, I tend to think of unplugging the display as being much
> like unplugging the 3.5mm line out jack to your hifi system - just
> because you've disconnected the speakers does not stop the audio
> playing - the audio continues despite you not being able to hear it.

Ditto for HD-audio.  The interface is still present, even playable,
without the connection.  Maybe we should return an error explicitly
when played during unconnected?  The handling of HDMI/DP hotplug has
been discussed many times, and I vaguely remember of pros/cons with
the above shown in past threads.


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

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

* Re: [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver
  2015-05-27 21:44           ` Russell King - ARM Linux
@ 2015-05-28  6:43             ` Daniel Vetter
  0 siblings, 0 replies; 74+ messages in thread
From: Daniel Vetter @ 2015-05-28  6:43 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Fabio Estevam, alsa-devel, dri-devel, Jaroslav Kysela,
	Mark Brown, Yakir Yang, linux-arm-kernel

On Wed, May 27, 2015 at 10:44:40PM +0100, Russell King - ARM Linux wrote:
> On Wed, May 27, 2015 at 11:29:52PM +0200, Daniel Vetter wrote:
> > The only issue that might be
> > there with your sw approach is that a concurrent probe/hotplug in drm
> > might free the edid and hence the eld, while the snd side is trying to
> > copy that.
> 
> Talking only about the particular case of dw-hdmi-ahb-audio...
> 
> The worst that may happen is that the ELD will be overwritten with an
> update on hotplug - it won't be freed unless the underlying connector
> is freed, as the eld is stored as an array inside struct drm_connector.
> Before the DRM connector is freed, we pull the audio driver's struct
> device, which will destroy the ALSA device.

Oh right I've forgotten that eld is stored as a full array and only the
edid floats around as a pointer in drm_connector. 

> Hopefully ALSA already copes gracefully with the removal of an in-use
> device... it should do, it's no different from having a USB audio device
> and you pull it out of the USB socket while the device is in-use.
> 
> (It's also worth noting as we're talking about this, that as the audio
> struct device is a child of the HDMI device, any PM activity will be
> correctly ordered: the child gets suspended before the parent... the
> audio device gets suspended before the video, and resume is of course
> the reverse order.)

Yeah, being able to control the nesting with DT seems so nice compared to
intel ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, back to index

Thread overview: 74+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-02  9:20 [RFC v2 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
2015-04-02  9:21 ` [PATCH RFC v2 01/13] drm: imx/dw_hdmi: move phy comments Russell King
2015-04-02  9:21 ` [PATCH RFC v2 02/13] drm: bridge/dw_hdmi: clean up phy configuration Russell King
2015-04-02  9:21 ` [PATCH RFC v2 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() Russell King
2015-04-02  9:21 ` [PATCH RFC v2 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode() Russell King
2015-04-02  9:21 ` [PATCH RFC v2 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little Russell King
2015-04-02  9:21 ` [PATCH RFC v2 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced Russell King
2015-04-02  9:21 ` [PATCH RFC v2 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate Russell King
2015-04-02  9:21 ` [PATCH RFC v2 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio Russell King
2015-04-02  9:22 ` [PATCH RFC v2 09/13] drm/edid: add function to help find SADs Russell King
2015-04-02  9:22 ` [PATCH RFC v2 10/13] sound/core: add DRM ELD helper Russell King
2015-04-05 15:57   ` Takashi Iwai
2015-04-05 16:20     ` Russell King - ARM Linux
2015-04-05 16:46       ` Takashi Iwai
2015-04-05 17:26         ` Russell King - ARM Linux
2015-05-06 17:02           ` Anssi Hannula
2015-05-07 10:41             ` Russell King - ARM Linux
2015-05-07 11:11               ` Lars-Peter Clausen
2015-05-08 10:56           ` [alsa-devel] " Jyri Sarha
2015-05-08 11:42             ` Russell King - ARM Linux
2015-05-05 22:35     ` Mark Brown
2015-05-06  8:58       ` Liam Girdwood
2015-05-08 13:16   ` [alsa-devel] " Jyri Sarha
2015-05-08 13:27     ` Russell King - ARM Linux
2015-05-08 13:37       ` Jyri Sarha
2015-04-02  9:22 ` [PATCH RFC v2 11/13] sound/core: add IEC958 channel status helper Russell King
2015-04-02  9:22 ` [PATCH RFC v2 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver Russell King
2015-04-02  9:22 ` [PATCH RFC v2 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver Russell King
2015-05-09 10:25 ` [PATCH v3 0/13] dw_hdmi cleanups, audio preparation, helpers and ahb audio support Russell King - ARM Linux
2015-05-09 10:25   ` [PATCH 01/13] drm: imx/dw_hdmi: move phy comments Russell King
2015-05-09 10:26   ` [PATCH 02/13] drm: bridge/dw_hdmi: clean up phy configuration Russell King
2015-05-22 15:19     ` Yakir
2015-05-09 10:26   ` [PATCH 03/13] drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() Russell King
2015-05-22 15:22     ` Yakir
2015-05-09 10:26   ` [PATCH 04/13] drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode() Russell King
2015-05-09 10:26   ` [PATCH 05/13] drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little Russell King
2015-05-09 10:26   ` [PATCH 06/13] drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced Russell King
2015-05-09 10:26   ` [PATCH 07/13] drm: bridge/dw_hdmi: introduce interface to setting sample rate Russell King
2015-05-22 15:26     ` Yakir
2015-05-09 10:26   ` [PATCH 08/13] drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio Russell King
2015-05-22 15:28     ` Yakir
2015-05-09 10:26   ` [PATCH 09/13] drm/edid: add function to help find SADs Russell King
2015-05-09 10:26   ` [PATCH 10/13] sound/core: add DRM ELD helper Russell King
2015-05-22 12:20     ` [alsa-devel] " Mark Brown
2015-05-22 13:15       ` Russell King - ARM Linux
2015-05-22 13:30         ` Takashi Iwai
2015-05-22 13:53           ` Russell King - ARM Linux
2015-05-22 13:54             ` Takashi Iwai
2015-05-22 14:00               ` Russell King - ARM Linux
2015-05-22 14:02                 ` Takashi Iwai
2015-05-22 14:05                   ` Takashi Iwai
2015-05-22 16:12                     ` Russell King - ARM Linux
2015-05-09 10:26   ` [PATCH 11/13] sound/core: add IEC958 channel status helper Russell King
2015-05-22 12:40     ` Mark Brown
2015-05-09 10:26   ` [PATCH 12/13] drm: bridge/dw_hdmi-ahb-audio: add audio driver Russell King
2015-05-09 16:49     ` [alsa-devel] " Anssi Hannula
2015-05-09 16:55       ` Russell King - ARM Linux
2015-05-09 17:07         ` Anssi Hannula
2015-05-09 17:40           ` Russell King - ARM Linux
2015-05-09 17:53             ` Russell King - ARM Linux
2015-05-09 17:55             ` Anssi Hannula
2015-05-09 18:11               ` Russell King - ARM Linux
2015-05-10 18:59                 ` Anssi Hannula
2015-05-10 19:33                   ` Russell King - ARM Linux
2015-05-10 20:47                     ` Anssi Hannula
2015-05-11 15:58                     ` Mark Brown
2015-05-09 10:26   ` [PATCH 13/13] drm: bridge/dw_hdmi-ahb-audio: parse ELD from HDMI driver Russell King
2015-05-27 10:43     ` Daniel Vetter
2015-05-27 11:43       ` Mark Brown
2015-05-27 17:31       ` Russell King - ARM Linux
2015-05-27 21:29         ` Daniel Vetter
2015-05-27 21:44           ` Russell King - ARM Linux
2015-05-28  6:43             ` Daniel Vetter
2015-05-28  4:56         ` [alsa-devel] " Takashi Iwai

Alsa-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/alsa-devel/0 alsa-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 alsa-devel alsa-devel/ https://lore.kernel.org/alsa-devel \
		alsa-devel@alsa-project.org
	public-inbox-index alsa-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.alsa-project.alsa-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git