This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Someone please verify the McAsp working mode;I2S or DSP_B only?

Other Parts Discussed in Thread: TLV320AIC33, TLV320AIC3110

Greetings,

I am working on a custom dm8148 board and we have a hdmi rx to feed stereo I2S audio data to the McAsp of Davinci.

When I trying to modify audio format in davinic-evm.c from SND_SOC_DAIFMT_DSP_B to SND_SOC_DAIFMT_I2S, I can only get either left or right channel data.

Then I checked the davinci-mcasp.c driver file and found that it seems right now McAsp only support DSP mode.

It is okay for tlv320 analog decoder, cuz it support either I2S or DSP mode, however it is a big issue for us. We only have standard I2S audio data from our HDMI rx.

Could any TI employee clarify this for us, in the datasheet of DAvinci 8148, it clearly claim support I2S mode however, in the driver only support DSP_B mode?

How can I set the registers to support standard I2S mode? I hope this is only a driver side limitation.

 

Regards,

Jun Zhang

 =====================================

static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
{
 int i, active_slots;
 u32 mask = 0;

 active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
 for (i = 0; i < active_slots; i++)
  mask |= (1 << i);

 mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);

 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
  /* bit stream is MSB first  with no delay */
  /* DSP_B mode */
  mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
    AHCLKXE);
  mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
  mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);

  if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
   mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
     FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
  else
   printk(KERN_ERR "playback tdm slot %d not supported\n",
    dev->tdm_slots);

  mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
 } else {
  /* bit stream is MSB first with no delay */
  /* DSP_B mode */
  mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
  mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
    AHCLKRE);
  mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);

  if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
   mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
     FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
  else
   printk(KERN_ERR "capture tdm slot %d not supported\n",
    dev->tdm_slots);

  mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
 }
}

  • I found following comments from /sound/soc/davinci/davinci-i2s.c:

        case SND_SOC_DAIFMT_I2S:
            /* Davinci doesn't support TRUE I2S, but some codecs will have
             * the left and right channels contiguous. This allows
             * dsp_a mode to be used with an inverted normal frame clk.
             * If your codec is master and does not have contiguous
             * channels, then you will have sound on only one channel.
             * Try using a different mode, or codec as slave.
             *
             * The TLV320AIC33 is an example of a codec where this works.
             * It has a variable bit clock frequency allowing it to have
             * valid data on every bit clock.
             *
             * The TLV320AIC23 is an example of a codec where this does not
             * work. It has a fixed bit clock frequency with progressively
             * more empty bit clock slots between channels as the sample
             * rate is lowered.
             */

    Although this driver file is for old mode Davinci, it this also the case for DM8148?

    Please verify.

    Thanks,

    Jun

  • Based on the information we have right now, it seems that Davinic cannot accpet true I2S data?

    Is that possible to set it to s/pdif?

    What is register value for McAsp to receive s/pdif?

    Regarads,

    Jun

  • Hi Jun,

    McASP supports only S/PDIF. McBSP supports I2S.

    Best regards,

    Pavel

  • Hi Pavel,

    Thanks for your quick.

    I am working on DM8148 and in the audio_driver user guide of EZSDK clearly say that McAsp support I2S.

    McASP provides a full-duplex direct serial interface between the host device (DM1xx) and other audio devices in
    the system such as the AIC31 codec. It provides a direct interface to industry standard codecs, analog interface chips
    (AICs) and other serially connected A/D and D/A devices:
    • Inter-IC Sound (I2S) compliant devices
    • Pulse Code Modulation (PCM) devices
    • Time Division Multiplexed (TDM) bus devices.

    ======

    Maybe I am wrong. My HDMI rx will output standard I2S master Wclk and bclk to DM8148.

    I was expecting McAsp can accept data as following way.

     

     

     

     

     

     

    However, I checked the driver of McAsp, and found it only support namly DSP mode.

     

    Do you have any idea, how to set McASp to take standard I2S?

    Or, If McBSP is the right one to process I2S data, how can I enable that in EZSDK5.04?

     

    Regards,

     

    Jun

  • Hi Jun,

    Please check the DM814x TRM, chapters 16 McASP and chapter 17 McBSP, for details on configuring the peripherals for I2S compatible format.

    Best regards,

    Pavel

  • Hi Pavel,

    Thanks for your help on this again. I read that TRM before.

    However, I am little bit confused by McAsP and McBsp.

    In TRM, it is claimed that both McAsP and McBsp support I2S.

    =================================================

    16.1.3 Protocols Supported
    The McASP supports a wide variety of protocols.
    • Transmit section supports:
    – Wide variety of I2S and similar bit-stream formats.
    – TDM streams from 2 to 32 time slots.
    – S/PDIF, IEC60958-1, AES-3 formats.
    • Receive section supports:
    – Wide variety of I2S and similar bit-stream formats.
    – TDM streams from 2 to 32 time slots.
    – TDM stream of 384 time slots specifically designed for easy interface to external digital interface

    ===================================================

    In section 17 of McBsP, it seems that McBsP can accept true I2S (first figure above).

    Here are my questions:

    1. Right now McAsp is all I got. If it cannot receive true I2S, is any way I can do to access the data registers to convert the audio data to the right format I want?

    2. How can I enable s/pdif receive mode in McAsp in the dirvers? By defult, s/pdif receiver mode seems to be deactive in ezsdk5.04?

    3. If I want to implement 4 channel true I2S, how can I do that?

     

    Regards,

     

    Jun 

     

     

     

  • We designed the hardware connection based on a design reference of dm6467 and sil9135 connection.

    I attached the link here. In this reference design, 4 channel I2S output of Sil9135 will feed into McAsp of DM6467 AXR0.

     http://www.ti.com/lit/ug/spruer1b/spruer1b.pdf

    Basically, our hdmi rx has the same i2s output as sil9135. How come in the old davinci, mcasp can receive 4 channel standard I2S but not in Dm8148?

    Thanks,

    Jun

  • Hello all,

    we also have a problem interfacing a i2s component to the dm8148's mcasp modules. In our use-case, the dm8148's mcasp2 is interfaced in slave-mode to a radio-tuner module which is delivering standard i2s-stereo output (clockk,frame and data). We modified the Linux-driver (using tdm-2 channel for i2s) delivered by ti and the reception of the signal is nearly working. The problem we still have is that the mcasp should sample on rising and not on falling edge of the bitclk. Setting the ACLKRCTL-registers CLKRP bit has no effect on the capture behaviour. The only workaround we found until now is to invert the bitclk manualy by an additional inverter on the bitclk's bus.

    best regards,

    Andreas

  • Hi Andreas,

    Glad to know that I am the only one facing this issue.

    We have the same problem as you. dm8148 working as slave mode and get stereo data and clocks (wclk,bclk) from our HDMI rx.

    I2S protocol will insert frame sync bit before MSB of left and right channel, however McAsp by default working at DSP_B mode and will consider that frame sync bit as MSB. So far we have not prograss well, the audio I captured is full of noise.

    Could you please share more details with us regarding the driver file you modified? 

    Did you mean you modify the function static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) of davinci-mcasp.c?

     

    Regards,

     

    Jun

     

     

  • Hi Jun,

    to get the driver working in i2s mode, you have to modify the static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)  function. We added a case for case SND_SOC_DAIFMT_I2S with register settings corresponding to our i2s device.

    Regards,

    Andreas

  • Hi Andreas,

    Thanks for your reply very much.

    Could you please share with us your register settings?

    My HDMI rx will output standard I2S audio data.

    I modified the audio format to #define AUDIO_FORMAT (SND_SOC_DAIFMT_I2S |  SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_IF)  in davinci-evm.c

    amd I modified the davinci_hw_param functions, however still the capture is full of noise in one channel.

    Here is my static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)

    static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
    {
     int i, active_slots;
     u32 mask = 0;

     active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
     
     for (i = 0; i < active_slots; i++)
      mask |= (1 << i);
      
     printk("avinci_hw_param: mask %x\n", mask);
     
     mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);

     if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
      /* bit stream is MSB first  with no delay */
      /* DSP_B mode */
      mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
        AHCLKXE);
      mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
      mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);

      if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
       mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
         FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
      else
       printk(KERN_ERR "playback tdm slot %d not supported\n",
        dev->tdm_slots);

      mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
     } else {
       printk("McAsp is working on alsa capture and I2S slave mode\n");
      /* bit stream is MSB first with no delay */
      /* DSP_B mode */
      /*Adaptive to I2S Mode*/
      
      mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); // MSB First, ok
      mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, I2S_LOW); // RDATDLY=01h
      mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, I2S_HIGH); // 1 bit delay 
      mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,AHCLKRE);// external master clk from HDMI Rx
      mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);//frame sync last single word,32 bit in our case
      
      //mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,AHCLKRE);
      mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);

      if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
      {
       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
         FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
      printk("dev->tdm_slots%d\n",dev->tdm_slots);
      }
      else
       printk(KERN_ERR "capture tdm slot %d not supported\n",
        dev->tdm_slots);

      //mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
      
      
     }
    }

     

    Not sure what I am missing here to let mcAsp working to accept I2S.

     

    Regards,

     

    Jun

  • Jun,

    here our code for the reception of a 32bit wide stereo i2s data stream. we receive frame, clk and data over mcasp2.afsx, mcasp2.aclkx mcasp2.axr0 working in ASYNC=0 (synchronous mode).

    soc-dai.h:

    #define SND_SOC_DAIFMT_I2S_WORD16   7 /* I2S mode slot-size 16*/

    davinci-mcasp.c:

    static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                         unsigned int fmt)
    {
        struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *base = dev->base;
       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
          case SND_SOC_DAIFMT_I2S:
             //codec is using i2s data format 32bits
             mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG,   0x00000111);
             mcasp_set_bits(base + DAVINCI_MCASP_RXTDM_REG,     0x00000003);
             mcasp_set_bits(base + DAVINCI_MCASP_RXFMT_REG,     0x000180F4);
             mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
             break;
          case SND_SOC_DAIFMT_I2S_WORD16:
             //codec is using i2s data format 16 bits
             mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG,   0x00000111);
             mcasp_set_bits(base + DAVINCI_MCASP_RXTDM_REG,     0x00000003);
             mcasp_set_bits(base + DAVINCI_MCASP_RXFMT_REG,     0x00018074);
             mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
          default:
                //we don't use i2c - so we need to take care about the frame/bitclk behaviour
                 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
                    case SND_SOC_DAIFMT_IB_NF:
                        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
                        mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

                        mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
                        mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                        break;

                    case SND_SOC_DAIFMT_NB_IF:
                        mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
                        mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

                        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
                        mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                        break;

                    case SND_SOC_DAIFMT_IB_IF:
                        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
                        mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

                        mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
                        mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                        break;

                    case SND_SOC_DAIFMT_NB_NF:
                        mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
                        mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

                        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
                        mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
                        break;

                    default:
                        return -EINVAL;
                 }
       }

        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
           case SND_SOC_DAIFMT_CBS_CFS:
               // codec is clock and frame slave
               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));      
               break;
           case SND_SOC_DAIFMT_CBM_CFS:
               // codec is clock master and frame slave
               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26));
               break;
           case SND_SOC_DAIFMT_CBM_CFM:
               // codec is clock and frame master
               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26));
               break;
           default:
               return -EINVAL;
        }
        return 0;
    }

    we also had to enlarge the 16Bit wide format to 32bits (16 bits of used data) in:

    static int davinci_config_channel_size(struct davinci_audio_dev *dev,
                           int channel_size)

        case DAVINCI_AUDIO_WORD_16:
    #ifdef OUR_PROJECT
           if((mcasp_get_reg(dev->base + DAVINCI_MCASP_RXFMT_REG) & 0x000000F0) == 0x00000070)
              fmt = 0x07;
           else
              fmt = 0x0F;
    #else
           fmt = 0x07;
    #endif
            rotate = 4;
            mask = 0x0000ffff;
            break;

    I hope you get along with this - we didn't make other modifications to the code.

    Best regards,

    Andreas

  • Dear Andreas,

    Really appreciate your reply.  I made some changes then in the davinci-evm.c evm_hw_params function.

    Now I have the clear sound.

    Thanks very much for your help on this matter.

    Regards,

    Jun

  • Hi Jun Zhang,

     

    We have the same problem as you have described in this post.

    We are using TI TLV320AIC3110 audio codec connected to DM8148 on MCASP2 port. This audio codec is a mono ADC recording device.

    We are using the TI Linux PSP. We did not make any change in the davinci drivers.

    All that we did is integrated the new linux driver for TLV320AIC3110 codec.

    One change in davinci-evm.c file.

    Changed Audio format to #define AUDIO_FORMAT (SND_SOC_DAIFMT_I2S | \

                    SND_SOC_DAIFMT_NB_IF | SND_SOC_DAIFMT_CBM_CFM).

    BCLK is connected to MCA2_ACLKX, WCLK is connected to MCA2_AFSX and DOUT is connected to MCA2_AXR1.

    We have not made any other code changes.

    When we record the audio, the recorded audio has only noise, though we see data is sent out from codec using the scope.

    It would be really appreciated, if you could share your code changes on the davinci driver.

  • Hi Andrea,

    I followed your code changes and it worked well.

    Thank you very much.

     

  • Hi ,

    Can you please post complete change list. I am getting pcm_read I/O error when i try to do arecord with 9135 HDMI rx. Can I contact you on email?

    Regards,
    Ajay Bhargav