jagmn

Members
  • Content Count

    2
  • Joined

  • Last visited

About jagmn

  • Rank
    Newbie

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. 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;
  2. 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.