am335x: S/PDIF support in Linux

I'm trying to get S/PDIF on McASP1 working. According to your PSP kernel DIT should be supported (sound/soc/davinci/davinci-mcasp.c). So far all I can hear is noise. I found a checklist ( Transmit DIT Clock and Frame Sync Generation) and there are differences in XFMT settings. According to the documentation rotation should be 0x0 or 0x2 depending on data alignment (left/right), but the driver had 0x6. The mask is also different. The user data registers won't be touched.

What is the proper S/PDIF configuration for am335x? Is there any reference hardware that is working with S/PDIF?


2 Replies

  • So far I've made following settings:

    created new struct snd_platform_data for S/PDIF

    static struct snd_platform_data am335x_evm_alekto2_snd_spdif_data1 = {
            .tx_dma_offset  = 0x46400000,   /* McASP1 */
            /*.rx_dma_offset        = 0x46400000,*/
            .op_mode        = DAVINCI_MCASP_DIT_MODE,
            .num_serializer = ARRAY_SIZE(am335x_evm_spdif_serializer_direction1),
            .tdm_slots      = 2,
            .serial_dir     = am335x_evm_spdif_serializer_direction1,
            .asp_chan_q     = EVENTQ_2,
            .version        = MCASP_VERSION_3,
            .txnumevt       = 32,

    Made changes regarding TRM to McASP register settings:

    - clock is derived from 24MHz

    - for 48000Hz divide the clock to get 6MHz (128 * 48000)

    /* S/PDIF */
    static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
            /* Set the PDIR for Serialiser as output */
            mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);

            /* TXMASK for 16 bits */
            mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x0000FFFF);

            /* Set the TX format : 0 bit right rotation, 32 bit slot, Pad 0
               and LSB first */
            mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
                                                    TXROT(0) | TXSSZ(15));

            /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
            mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
                                                    AFSXE | FSXMOD(0x180));

            /* Set the TX tdm : for all the slots */
            mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);

            /* Set the TX clock controls : div = 1 and internal */
            mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
                                                    ACLKXE | TX_ASYNC);

            mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);

            /* Only 44100 and 48000 are valid, both have the same setting */
            mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE | AHCLKXDIV(3));

            /* Enable the DIT */
            mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);

    What about DIT Channel Status and User Data Register Files (DITCSRA0-5, DITUDRA0-5)? Haven't seen them being configured in the driver source code.

  • In reply to rfc2217:

    We made measurements and it looks like one byte is missing. We send 0x55ff and as you can see from the osci picture only 0xff was really transfered: