All of lore.kernel.org
 help / color / mirror / Atom feed
From: "stéphane cerveau" <scerveau@gmail.com>
To: "alsa-devel@alsa-project.org" <alsa-devel@alsa-project.org>
Subject: Re: mxc-spdif delay: miss 1-2s at the beginning of the song
Date: Mon, 21 Oct 2013 13:50:26 +0200	[thread overview]
Message-ID: <52651502.7000608@gmail.com> (raw)
In-Reply-To: <525D4F5B.6050105@gmail.com>

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

Dear all,

I had some progress concerning spdif various issues (alsactl store lock, 
rx to tx support).
Here is in attachment the patch.

Concerning the music startup i still have some issues with sync. If 
there is someone who can help me out with this, i will be pleased to 
work on this issue. IMX documentation is not really clear enough to me. 
Especially for the config SPDIF_SCR/TxFifo_ctrl.
For now i put a delay in playback start but this is not clearly fixing 
the issue and this is not a solution for me.

Best regards.

Stéphane


On 10/15/2013 04:21 PM, stéphane cerveau wrote:
> Dear all,
>
> I'm facing a delay during startup missing 1-2s of the song when i'm 
> using mxc spdif with aplay.
> I guess its a problem with spdif synchronization. If i put a 
> msleep(1000) at the end of the function 
> mxc-spdif.c:mxc_spdif_playback_start, the playback is ok.
>
> Is there anyone who already faced this issue?
> BR.
>
> Stéphane


[-- Attachment #2: 006_spdif_fixes.patch --]
[-- Type: text/x-patch, Size: 9945 bytes --]

Index: git/sound/soc/codecs/mxc_spdif.c
===================================================================
--- git.orig/sound/soc/codecs/mxc_spdif.c	2013-10-18 17:00:32.704690599 +0200
+++ git/sound/soc/codecs/mxc_spdif.c	2013-10-18 17:03:20.547153022 +0200
@@ -12,7 +12,6 @@
  * http://www.opensource.org/licenses/gpl-license.html
  * http://www.gnu.org/copyleft/gpl.html
  */
-
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -38,6 +37,12 @@
 
 #define MXC_SPDIF_DEBUG 0
 
+enum spdif_rx2tx_modes {
+	SPDIF_RX2TX_OFF = 0,
+	SPDIF_RX2TX_ON,
+	SPDIF_RX2TX_LAST_MODE,
+};
+
 static unsigned int gainsel_multi[GAINSEL_MULTI_MAX] = {
 	24 * 1024, 16 * 1024, 12 * 1024,
 	8 * 1024, 6 * 1024, 4 * 1024,
@@ -74,6 +79,7 @@
 	atomic_t dpll_locked;	/* DPLL locked status */
 	bool tx_active;
 	bool rx_active;
+	enum spdif_rx2tx_modes rx2tx_en;
 };
 
 struct spdif_mixer_control mxc_spdif_control;
@@ -522,6 +528,99 @@
 	.mask = 0,
 };
 
+static int spdif_get_rx2tx(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec);
+	ucontrol->value.integer.value[0] = spdif_priv->rx2tx_en;
+
+	return 0;
+}
+
+static void enable_rx2tx(struct mxc_spdif_priv *priv)
+{
+	u32 regval;
+	if (!priv->tx_active && !priv->rx_active)
+		clk_enable(priv->plat_data->spdif_core_clk);
+
+	regval = __raw_readl(spdif_base_addr + SPDIF_REG_SCR);
+	regval &= ~SCR_LOW_POWER;
+	if (priv->rx2tx_en) {
+		regval &=  ~SCR_TXSEL_NORMAL;
+		regval |=  SCR_TXSEL_RX;
+	}
+	else {
+		regval &=  ~SCR_TXSEL_RX;
+		regval |=  SCR_TXSEL_NORMAL;
+	}
+
+	__raw_writel(regval, SPDIF_REG_SCR + spdif_base_addr);
+
+	if (!priv->tx_active && !priv->rx_active)
+		clk_disable(priv->plat_data->spdif_core_clk);
+}
+
+static int spdif_set_rx2tx(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec);
+	int ret = 0;
+
+	/* Do not allow changes while stream is running*/
+	if (codec->active)
+		return -EPERM;
+
+	if (ucontrol->value.integer.value[0] < 0 ||
+	    ucontrol->value.integer.value[0] >= SPDIF_RX2TX_LAST_MODE)
+		ret = -EINVAL;
+	else
+		spdif_priv->rx2tx_en = ucontrol->value.integer.value[0];
+
+	enable_rx2tx(spdif_priv);
+
+	return ret;
+}
+
+/*
+ * DAPM controls.
+ */
+static const struct snd_soc_dapm_widget spdif_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("SPDIF", "HiFi Playback", SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_OUTPUT("VOUT"),
+};
+
+static const struct snd_soc_dapm_route spdif_intercon[] = {
+	{"VOUT", NULL, "SPDIF"},
+};
+
+static int spdif_add_widgets(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	snd_soc_dapm_new_controls(dapm, spdif_dapm_widgets,
+				  ARRAY_SIZE(spdif_dapm_widgets));
+	snd_soc_dapm_add_routes(dapm, spdif_intercon, ARRAY_SIZE(spdif_intercon));
+
+	return 0;
+}
+
+/* Codec operation modes */
+static const char *spdif_rx2tx_mode[] = {
+	"Off", "On"
+};
+
+static const struct soc_enum spdif_rx2tx_mode_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spdif_rx2tx_mode),
+			    spdif_rx2tx_mode);
+
+
+static const struct snd_kcontrol_new spdif_rx2tx_mode_snd_controls[] = {
+	SOC_ENUM_EXT("RX2TX_PassThrough", spdif_rx2tx_mode_enum,
+		 spdif_get_rx2tx, spdif_set_rx2tx),
+};
+
 static int mxc_spdif_playback_startup(struct snd_pcm_substream *substream,
 					       struct snd_soc_dai *dai)
 {
@@ -601,6 +700,9 @@
 	regval |= SCR_DMA_TX_EN;
 	__raw_writel(regval, SPDIF_REG_SCR + spdif_base_addr);
 
+	// TODO Get a better way to get synchro
+	// Wait synchro.
+	mdelay(2500);
 	dumpregs(spdif_priv);
 	return 0;
 }
@@ -677,6 +779,11 @@
 	struct mxc_spdif_platform_data *plat_data = spdif_priv->plat_data;
 	int err = 0;
 
+	if (spdif_priv->rx2tx_en) {
+		pr_info("rx2tx is enabled");
+		return -EINVAL;
+	}
+
 	if (!plat_data->spdif_rx)
 		return -EINVAL;
 
@@ -708,6 +815,7 @@
 	return err;
 }
 
+
 static int mxc_spdif_capture_start(struct snd_pcm_substream *substream,
 					 struct snd_soc_dai *dai)
 {
@@ -882,10 +990,15 @@
 				 struct snd_ctl_elem_value *ucontrol)
 {
 	unsigned int cstatus;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec);
 
-	if (!(__raw_readl(spdif_base_addr + SPDIF_REG_SIS) & INT_CNEW))
-		return -EAGAIN;
 
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_enable(spdif_priv->plat_data->spdif_core_clk);
+
+	if (!(__raw_readl(spdif_base_addr + SPDIF_REG_SIS) & INT_CNEW))
+		return 0;
 	cstatus = __raw_readl(spdif_base_addr + SPDIF_REG_SRCSLH);
 	ucontrol->value.iec958.status[0] = (cstatus >> 16) & 0xFF;
 	ucontrol->value.iec958.status[1] = (cstatus >> 8) & 0xFF;
@@ -898,6 +1011,9 @@
 	/* clear intr */
 	__raw_writel(INT_CNEW, spdif_base_addr + SPDIF_REG_SIC);
 
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_disable(spdif_priv->plat_data->spdif_core_clk);
+
 	return 0;
 }
 
@@ -917,11 +1033,8 @@
 		       &mxc_spdif_control.subcode[(mxc_spdif_control.ready_buf -
 						   1) * SPDIF_UBITS_SIZE],
 		       SPDIF_UBITS_SIZE);
-	} else {
-		ret = -EAGAIN;
 	}
 	spin_unlock_irqrestore(&mxc_spdif_control.ctl_lock, flags);
-
 	return ret;
 }
 
@@ -953,8 +1066,6 @@
 		       &mxc_spdif_control.qsub[(mxc_spdif_control.ready_buf -
 						1) * SPDIF_QSUB_SIZE],
 		       SPDIF_QSUB_SIZE);
-	} else {
-		ret = -EAGAIN;
 	}
 	spin_unlock_irqrestore(&mxc_spdif_control.ctl_lock, flags);
 
@@ -981,11 +1092,17 @@
 			      struct snd_ctl_elem_value *ucontrol)
 {
 	unsigned int int_val;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec);
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_enable(spdif_priv->plat_data->spdif_core_clk);
 
 	int_val = __raw_readl(spdif_base_addr + SPDIF_REG_SIS);
 	ucontrol->value.integer.value[0] = (int_val & INT_VAL_NOGOOD) != 0;
 	__raw_writel(INT_VAL_NOGOOD, spdif_base_addr + SPDIF_REG_SIC);
 
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_disable(spdif_priv->plat_data->spdif_core_clk);
 	return 0;
 }
 
@@ -1047,8 +1164,17 @@
 			       struct snd_ctl_elem_value *ucontrol)
 {
 	unsigned int int_val;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec);
+
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_enable(spdif_priv->plat_data->spdif_core_clk);
+
 	int_val = __raw_readl(spdif_base_addr + SPDIF_REG_SRCD);
 	ucontrol->value.integer.value[0] = (int_val & SRCD_CD_USER) != 0;
+
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_disable(spdif_priv->plat_data->spdif_core_clk);
 	return 0;
 }
 
@@ -1061,9 +1187,15 @@
 				   struct snd_ctl_elem_value *ucontrol)
 {
 	unsigned int int_val;
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct mxc_spdif_priv *spdif_priv = snd_soc_codec_get_drvdata(codec);
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_enable(spdif_priv->plat_data->spdif_core_clk);
 
 	int_val = ucontrol->value.integer.value[0] << SRCD_CD_USER_OFFSET;
 	__raw_writel(int_val, spdif_base_addr + SPDIF_REG_SRCD);
+	if (!spdif_priv->tx_active && !spdif_priv->rx_active)
+		clk_disable(spdif_priv->plat_data->spdif_core_clk);
 	return 0;
 }
 
@@ -1140,6 +1272,10 @@
 	struct mxc_spdif_platform_data *plat_data = spdif_priv->plat_data;
 	int ret = 0;
 
+	if (spdif_priv->rx2tx_en) {
+		pr_info("rx2tx is enabled");
+		return -EINVAL;
+	}
 	/* enable spdif_xtal_clk */
 	ret = clk_enable(plat_data->spdif_core_clk);
 	if (ret < 0)
@@ -1198,7 +1334,10 @@
 static int mxc_spdif_soc_probe(struct snd_soc_codec *codec)
 {
 	snd_soc_add_controls(codec, mxc_spdif_ctrls,
-			     ARRAY_SIZE(mxc_spdif_ctrls));
+					ARRAY_SIZE(mxc_spdif_ctrls));
+	snd_soc_add_controls(codec, spdif_rx2tx_mode_snd_controls,
+					ARRAY_SIZE(spdif_rx2tx_mode_snd_controls));
+     spdif_add_widgets(codec);
 	return 0;
 }
 
@@ -1260,6 +1399,7 @@
 
 	spdif_priv->tx_active = false;
 	spdif_priv->rx_active = false;
+	spdif_priv->rx2tx_en = SPDIF_RX2TX_OFF;
 	platform_set_drvdata(pdev, spdif_priv);
 
 	spdif_priv->reg_phys_base = res->start;
@@ -1307,6 +1447,7 @@
 		goto card_err;
 	}
 
+
 	dumpregs(spdif_priv);
 
 	return 0;
Index: git/sound/soc/imx/imx-spdif.c
===================================================================
--- git.orig/sound/soc/imx/imx-spdif.c	2013-10-18 17:00:32.704690599 +0200
+++ git/sound/soc/imx/imx-spdif.c	2013-10-18 17:01:25.505465029 +0200
@@ -33,6 +33,35 @@
 #include "imx-ssi.h"
 #include "../codecs/mxc_spdif.h"
 
+/* imx_3stack card dapm widgets */
+static const struct snd_soc_dapm_widget imx_3stack_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+/* imx_3stack machine connections to the codec pins */
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* LINE_OUT --> Ext Speaker */
+	{"Ext Spk", NULL, "VOUT"},
+};
+
+
+static int imx_3stack_spdif_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	int ret;
+
+		/* Add imx_3stack specific widgets */
+	snd_soc_dapm_new_controls(&codec->dapm, imx_3stack_dapm_widgets,
+				  ARRAY_SIZE(imx_3stack_dapm_widgets));
+
+	/* Set up imx_3stack specific audio path audio_map */
+	snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
+
+	snd_soc_dapm_sync(&codec->dapm);
+
+	return 0;
+}
+
 /* imx digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link imx_spdif_dai_link = {
 	.name = "IMX SPDIF",
@@ -41,6 +70,7 @@
 	.codec_name = "mxc_spdif.0",
 	.cpu_dai_name = "imx-spdif-dai.0",
 	.platform_name = "imx-pcm-audio.2", /* imx-pcm-dma-mx2 */
+	.init = imx_3stack_spdif_init
 };
 
 static struct snd_soc_card snd_soc_card_imx_spdif = {

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



  reply	other threads:[~2013-10-21 11:50 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-15 14:21 mxc-spdif delay: miss 1-2s at the beginning of the song stéphane cerveau
2013-10-21 11:50 ` stéphane cerveau [this message]
2013-10-21 12:06   ` Clemens Ladisch
2013-10-21 12:08     ` stéphane cerveau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52651502.7000608@gmail.com \
    --to=scerveau@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.