2 2
cooldaddy

Nanopi neo Air 1.0 spdif-out not work

Recommended Posts

I compiled full-armbian image for nanopi air.

 

root@nanopiair:~# uname -a

Linux nanopiair 4.19.25-sunxi #5.76 SMP Wed Feb 27 13:46:35 KST 2019 armv7l GNU/Linux

 

and by armbian-config, on armbianEnv.txt

overlays=spdif-out

 

root@nanopiair:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: SPDIF [On-board SPDIF], device 0: spdif-dit-hifi dit-hifi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

 

root@nanopiair:~# speaker-test -tway -c2 -Dhw:0

speaker-test 1.1.3

Playback device is hw:0
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 128 to 131072
Period size range from 64 to 16384
Using max buffer size 131072
Periods = 4
was set period_size = 16384
was set buffer_size = 131072
 0 - Front Left
 1 - Front Right
Time per period = 0.503481
 0 - Front Left
 1 - Front Right

 

and my dac doesn't detect any signal by coaxial-input.

 

What I can I check?

Share this post


Link to post
Share on other sites

I've had some success here with the Orange Pi Zero (Allwinner H2+/H3 - same as the Nano Pi Air).

 

I found that the SPDIF output (via optical/TOSLINK or Phono connector) was 'nearly' reaching sync at 44.1khz, almost never at 48khz and nothing beyond that.

 

Digging into the H2+ & H3 datasheets I encountered an important clue on table 8.7.2.2: s_clk needs to be 4x24.576 MHz or 4x22.5782 Mhz. Probably due to how SPDIF is a huge oversample of the audio frequency.

I knocked up a quick patch to sun4i-spdif.c and voila; I get solid sync-locks on all supported frequencies:

diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
index b4af4aabe..5383a35d3 100644
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -280,14 +280,14 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream,
 	case 44100:
 	case 88200:
 	case 176400:
-		mclk = 22579200;
+		mclk = 22579200*4;
 		break;
 	case 24000:
 	case 32000:
 	case 48000:
 	case 96000:
 	case 192000:
-		mclk = 24576000;
+		mclk = 24576000*4;
 		break;
 	default:
 		return -EINVAL;
@@ -306,22 +306,22 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream,
 	switch (rate) {
 	case 22050:
 	case 24000:
-		mclk_div = 8;
+		mclk_div = 8*4;
 		break;
 	case 32000:
-		mclk_div = 6;
+		mclk_div = 6*4;
 		break;
 	case 44100:
 	case 48000:
-		mclk_div = 4;
+		mclk_div = 4*4;
 		break;
 	case 88200:
 	case 96000:
-		mclk_div = 2;
+		mclk_div = 2*4;
 		break;
 	case 176400:
 	case 192000:
-		mclk_div = 1;
+		mclk_div = 1*4;
 		break;
 	default:
 		return -EINVAL;

You can put the above into your ambian/build directory under userpatches/kernel/sunxi-next/0001-spdif-clk-fix.patch or similar and it'll get built as part of the process.

 

I noticed that other chipsets (notably the H5) do not call out this 4x multiplier, so we probably need a more generic fix that chooses the multiplier if it is H2+/H3.

Share this post


Link to post
Share on other sites

If anyone else needs this patch, I've cleaned it up a little after re-reading the driver. It should only get applied to H3 (and related) devices with this:

diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c
index b4af4aabe..195775605 100644
--- a/sound/soc/sunxi/sun4i-spdif.c
+++ b/sound/soc/sunxi/sun4i-spdif.c
@@ -169,6 +169,7 @@ struct sun4i_spdif_dev {
 	struct snd_soc_dai_driver cpu_dai_drv;
 	struct regmap *regmap;
 	struct snd_dmaengine_dai_dma_data dma_params_tx;
+  unsigned int spdif_clk_mult;
 };
 
 static void sun4i_spdif_configure(struct sun4i_spdif_dev *host)
@@ -293,6 +294,8 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+  mclk *= host->spdif_clk_mult;
+
 	ret = clk_set_rate(host->spdif_clk, mclk);
 	if (ret < 0) {
 		dev_err(&pdev->dev,
@@ -327,6 +330,8 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+  mclk_div *= host->spdif_clk_mult;
+
 	reg_val = 0;
 	reg_val |= SUN4I_SPDIF_TXCFG_ASS;
 	reg_val |= fmt; /* set non audio and bit depth */
@@ -408,20 +413,24 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = {
 struct sun4i_spdif_quirks {
 	unsigned int reg_dac_txdata;	/* TX FIFO offset for DMA config */
 	bool has_reset;
+  unsigned int mclk_multiplier;
 };
 
 static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = {
 	.reg_dac_txdata	= SUN4I_SPDIF_TXFIFO,
+  .mclk_multiplier = 1,
 };
 
 static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = {
 	.reg_dac_txdata	= SUN4I_SPDIF_TXFIFO,
 	.has_reset	= true,
+  .mclk_multiplier = 1,
 };
 
 static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = {
 	.reg_dac_txdata	= SUN8I_SPDIF_TXFIFO,
 	.has_reset	= true,
+  .mclk_multiplier = 4,
 };
 
 static const struct of_device_id sun4i_spdif_of_match[] = {
@@ -517,6 +526,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "failed to get a spdif clock.\n");
 		return PTR_ERR(host->spdif_clk);
 	}
+  host->spdif_clk_mult = quirks->mclk_multiplier;
 
 	host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata;
 	host->dma_params_tx.maxburst = 8;

 

Share this post


Link to post
Share on other sites

hi all!

can you help me with same question, how i can enable onboard SPDIF output from NanoPi neo air with this OS:

uname -a
Linux NanoPi-NEO-Air 4.14.111 #3 SMP Tue Aug 27 16:06:24 CST 2019 armv7l armv7l armv7l GNU/Linux
(default linux  Ubuntu 16.04.2 LTS factory image).

Share this post


Link to post
Share on other sites
6 hours ago, nagaudio said:

but some clicks and pops i hear with music....


You will need to contact driver author(s) or do some tricks like setting the fixed CPU frequency.  Can be done via armbian-config as well. Try lower and higher values.

Share this post


Link to post
Share on other sites

I've just pinged one of the original authors about getting my patch upstreamed. 

If you want to build it for yourself, you can use the instructions here: https://docs.armbian.com/Developer-Guide_Build-Preparation/

The patch lives in <build_checkout>/userpatches/kernel/sunxi-current/ and assumes that you'll be building with that kernel. I've attached the latest version to this post.

Note: I haven't tested this myself on the NanoPi neo air but Cooldaddy says that it does the trick.

0002-spdif-clk-fix.patch

Share this post


Link to post
Share on other sites
19 minutes ago, jagmn said:

I've just pinged one of the original authors about getting my patch upstreamed. 

If you want to build it for yourself, you can use the instructions here: https://docs.armbian.com/Developer-Guide_Build-Preparation/

The patch lives in <build_checkout>/userpatches/kernel/sunxi-current/ and assumes that you'll be building with that kernel. I've attached the latest version to this post.

Note: I haven't tested this myself on the NanoPi neo air but Cooldaddy says that it does the trick.


It can take months before patches finds the way into the kernel, so you are welcome to add it here:


https://github.com/armbian/build/tree/master/patch/kernel/sunxi-current

https://github.com/armbian/build/tree/master/patch/kernel/sunxi-legacy

https://github.com/armbian/build/tree/master/patch/kernel/sunxi-dev

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
2 2