alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* mxc-spdif delay: miss 1-2s at the beginning of the song
@ 2013-10-15 14:21 stéphane cerveau
  2013-10-21 11:50 ` stéphane cerveau
  0 siblings, 1 reply; 4+ messages in thread
From: stéphane cerveau @ 2013-10-15 14:21 UTC (permalink / raw)
  To: alsa-devel@alsa-project.org

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

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

* Re: mxc-spdif delay: miss 1-2s at the beginning of the song
  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
  2013-10-21 12:06   ` Clemens Ladisch
  0 siblings, 1 reply; 4+ messages in thread
From: stéphane cerveau @ 2013-10-21 11:50 UTC (permalink / raw)
  To: alsa-devel@alsa-project.org

[-- 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 --]



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

* Re: mxc-spdif delay: miss 1-2s at the beginning of the song
  2013-10-21 11:50 ` stéphane cerveau
@ 2013-10-21 12:06   ` Clemens Ladisch
  2013-10-21 12:08     ` stéphane cerveau
  0 siblings, 1 reply; 4+ messages in thread
From: Clemens Ladisch @ 2013-10-21 12:06 UTC (permalink / raw)
  To: stéphane cerveau, alsa-devel@alsa-project.org

stéphane cerveau wrote:
> Concerning the music startup i still have some issues with sync.
> 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.

Are you sure that the problem isn't that the receiver is slow
to lock on?


Regards,
Clemens

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

* Re: mxc-spdif delay: miss 1-2s at the beginning of the song
  2013-10-21 12:06   ` Clemens Ladisch
@ 2013-10-21 12:08     ` stéphane cerveau
  0 siblings, 0 replies; 4+ messages in thread
From: stéphane cerveau @ 2013-10-21 12:08 UTC (permalink / raw)
  To: Clemens Ladisch, alsa-devel@alsa-project.org

Dear Clemens,

I had a try with a CD player outputing in spdif on the same amplifer and 
i dont face the issue.
BR.

Stéphane

On 10/21/2013 02:06 PM, Clemens Ladisch wrote:
> stéphane cerveau wrote:
>> Concerning the music startup i still have some issues with sync.
>> 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.
> Are you sure that the problem isn't that the receiver is slow
> to lock on?
>
>
> Regards,
> Clemens

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

end of thread, other threads:[~2013-10-21 12:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2013-10-21 12:06   ` Clemens Ladisch
2013-10-21 12:08     ` stéphane cerveau

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