How to activate SPDIF in/out with UDOObuntu2 RC1 on Quad

Discussion in 'Linux Ubuntu' started by udoo4music, Jan 31, 2016.

  1. udoo4music

    udoo4music New Member

    Joined:
    Jan 24, 2016
    Messages:
    5
    Likes Received:
    2
    I hoped getting an easy way to activate SPDIF in/out on my Udoo Quad with UDOObuntu 2. But I cannot find the option in the new tool "Device Tree Editor" and also cannot find some hint to do it another way (e.g. editing device tree manually?).
    Could anyone help please.
     
  2. Andrea Rovai

    Andrea Rovai Well-Known Member

    Joined:
    Oct 27, 2014
    Messages:
    1,703
    Likes Received:
    240
    At the moment this option is not implemented. You should manually recompile the kernel's device tree to do it.
     
  3. udoo4music

    udoo4music New Member

    Joined:
    Jan 24, 2016
    Messages:
    5
    Likes Received:
    2
    Now I tried to get spdif working.
    I set up the pins for spdif in and out in device tree and got the alsa device visible at /proc/asound/imxspdif.
    Trying to play any wav using aplay results in "write error: Input/output error" after a few seconds.
    "aplay -l" says "imxspdif device 0: S/PDIF PCM snd-soc-dummy-dai-0"
    So what does "dummy" mean? Is the driver in the kernel missing? Do I need to recompile the kernel?
    Thank you for any hint, which brings me further.
     
  4. udoo4music

    udoo4music New Member

    Joined:
    Jan 24, 2016
    Messages:
    5
    Likes Received:
    2
    Update:
    I tried UDOObuntu2 RC2 today. SPDIF now can be enabled using "Device Tree Editor". This works fine, it's a good tool.
    But still the device tree files are not up to date.
    Following this thread: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-June/263732.html
    I aplied to /opt/dtweb/dtbkernel/arch/arm/boot/dts/imx6qdl.dtsi :
    236,238c236,238
    < <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_ASRC>,
    < <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_ESAI_EXTAL>,
    < <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_MLB>,
    ---
    > <&clks IMX6QDL_CLK_SPDIF>, <&clks IMX6QDL_CLK_DUMMY>,
    > <&clks IMX6QDL_CLK_DUMMY>, <&clks IMX6QDL_CLK_DUMMY>,
    > <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_DUMMY>,
    After building device tree again (using the Device Tree Editor) spdif works :)
     
    Francesco likes this.
  5. Francesco

    Francesco Active Member

    Joined:
    Jun 23, 2015
    Messages:
    220
    Likes Received:
    110
    Hi, could you please fix it in the official UDOO kernel as pull-request on github?

    Thank you
     
  6. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    I know this is an old thread, but for anyone else encountering this problem, which appears to still afflict current Udoo 3.14.56 kernels, the clocking fix udoo4music posted can also be done using the Device Tree in /boot, without having to recompile the kernel. Just find your active .dtb file in either /boot/dts or /boot/dts-overlay (the latter is used if /boot/uEnv.txt contains the line "use_custom_dtb=true"), for example imx6q-udoo-hdmi.dtb, and edit the corresponding .dts (dts = Device Tree Source; dtb = Device Tree Blob/Binary). Look for the section beginning with "spdif@02004000" and replace it with this:
    Code:
                spdif@02004000 {
                        compatible = "fsl,imx35-spdif";
                        reg = <0x2004000 0x4000>;
                        interrupts = <0x0 0x34 0x4>;
                        dmas = <0x4 0xe 0x12 0x0 0x4 0xf 0x12 0x0>;
                        dma-names = "rx", "tx";
                        clocks = <0x2 0xf9        // IMX6QDL_CLK_SPDIF_GCLK
                                  0x2 0x3         // IMX6QDL_CLK_OSC
                                  0x2 0xc5        // IMX6QDL_CLK_SPDIF
                                  0x2 0x0         // IMX6QDL_CLK_ASRC 0x6b -> DUMMY
                                  0x2 0x0         // IMX6QDL_CLK_DUMMY
                                  0x2 0x0         // IMX6QDL_CLK_ESAI_EXTAL 0x76 -> DUMMY
                                  0x2 0x3e        // IMX6QDL_CLK_IPG
                                  0x2 0x0         // IMX6QDL_CLK_MLB 0x8b -> DUMMY
                                  0x2 0x0         // IMX6QDL_CLK_DUMMY
                                  0x2 0x9c>;      // IMX6QDL_CLK_SPBA
                        clock-names = "core", "rxtx0", "rxtx1", "rxtx2", "rxtx3", "rxtx4", "rxtx5", "rxtx6", "rxtx7", "dma";
                        status = "okay";
                        pinctrl-names = "default";
                        pinctrl-0 = <0x5>;
                        linux,phandle = <0x39>;
                        phandle = <0x39>;
                };
    
    Only the "clocks" definitions need to be changed, but in this boot-time .dts you have to use numeric constants rather than mnemonic symbols like IMX6QDL_CLK_DUMMY, since the header file defining those ( ./include/dt-bindings/clock/imx6qdl-clock.h off the kernel-source root) isn't read in at boot time. Each clock is defined as 0x2 XX, where XX is a number next to the desired symbol in that .h file. Whitespace and line breaks within the .dts are not significant, and you can also include comments with C / C++ style delimiters as I did above.

    After editing the dts, "compile" it to binary form using the 'dtc' utility ("apt-get device-tree-compiler" if this tool isn't already installed):

    dtc -I dts -O dtb imx6q-udoo-hdmi.dts >imx6q-udoo-hdmi.dtb

    (Best to make a backup of the originals first, just in case!)

    There is one remaining problem with Freescale's SPDIF output driver, which may or may not affect you depending on the specific DAC or amplifier connected: two repeating control flags within the audio stream are set wrong. One is the per-sample VALIDITY bit, which was meant for CD players to set when encountering audio data that's been damaged beyond the capacity of error-correction to fix, such as on a badly scratched disc. The driver erroneously sets this bit to '1' for every sample, when it should be '0'. '1' actually means the sample is INVALID, as explained here in the bit-28 entry:

    http://www.hardwarebook.info/S/PDIF#Word_and_Block_Formats

    The other bad flag is a per-block one called Pre-Emphasis:

    http://www.hardwarebook.info/S/PDIF#Channel_status_and_subcode_information

    This was meant to indicate that the CD or other digital audio source had been recorded/sent with boosted treble, and that the DAC should apply a converse filter to attenuate high frequencies back to their original level - sort of like the Dolby systems on analog tape, this was meant for noise reduction, but the noise level on CDs was so good already that it was rarely, if ever used. Still, some DACs and amps dutifully implement this, and so will give muddy, dull sounding audio if you sent SP-DIF data with the Pre-Emphasis bit turned on, as Freescale's driver also does, for some strange reason.

    Here's a small kernel patch (against 3.14.56) to fix both incorrect flags:
    Code:
    --- linux_kernel-3.14-1.0.x-udoo/sound/soc/fsl/fsl_spdif.c      2018-03-15 12:28:21.000000000 -0400
    +++ linux_kernel-cleanpatch/sound/soc/fsl/fsl_spdif.c   2018-11-18 16:24:34.456895984 -0500
    @@ -488,10 +488,10 @@
            if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                    scr = SCR_TXFIFO_AUTOSYNC | SCR_TXFIFO_CTRL_NORMAL |
    -                       SCR_TXSEL_NORMAL | SCR_USRC_SEL_CHIP |
    +                       SCR_TXSEL_NORMAL | SCR_USRC_SEL_CHIP | SCR_VAL_CLEAR |
                            SCR_TXFIFO_FSEL_IF8;
                    mask = SCR_TXFIFO_AUTOSYNC_MASK | SCR_TXFIFO_CTRL_MASK |
    -                       SCR_TXSEL_MASK | SCR_USRC_SEL_MASK |
    +                       SCR_TXSEL_MASK | SCR_USRC_SEL_MASK | SCR_VAL_MASK |
                            SCR_TXFIFO_FSEL_MASK;
                    for (i = 0; i < SPDIF_TXRATE_MAX; i++)
                            clk_prepare_enable(spdif_priv->txclk[i]);
    @@ -1279,7 +1279,7 @@
            /* Init tx channel status default value */
            ctrl->ch_status[0] = IEC958_AES0_CON_NOT_COPYRIGHT |
    -                            IEC958_AES0_CON_EMPHASIS_5015;
    +                            IEC958_AES0_CON_EMPHASIS_NONE;  //
            ctrl->ch_status[1] = IEC958_AES1_CON_DIGDIGCONV_ID;
            ctrl->ch_status[2] = 0x00;
            ctrl->ch_status[3] = IEC958_AES3_CON_FS_44100 |
    
    Depending on the audio equipment being used, this may not be necessary. Some devices simply ignore both flags - my Yamaha A/V amp is one, while the TC-7510 DAC I use with my headphone amp respects both, emitting absolute silence when receiving Validity=1 samples, and dull sound with no high end for PreEmphasis=1 frames, just as it's supposed to.
     
    waltervl likes this.

Share This Page