Post Go back to editing

Daisy Chaining two AD1938 codecs - ALSA System on Chip driver

Hi there,

we are trying to extend our audio system by daisy chaining two AD1938 audio codecs. From the datasheet I got the information that both codecs are configured equally (512 fs DACs / 256 fs ADCs / single line TDM mode). So, of course, both codecs appear as one codec to the platform DAI. I think it should work, if both codecs are configured equally in series via regmap in the codec driver. For example:

static int ad193x_hw_params(...){

   ...

   regmap_update_bits(ad193x_0->regmap, AD193X_PLL_CLK_CTRL0, AD193X_PLL_INPUT_MASK, master_rate);

   regmap_update_bits(ad193x_1->regmap, AD193X_PLL_CLK_CTRL0, AD193X_PLL_INPUT_MASK, master_rate);

   ...

}

Does anybody know, how to pass two regmap configs to the driver, so that I can configure both codecs in the same way? Or any other idea how to get two daisy chained codecs working with ALSA?

Thanks!

  • Hello Henrix,

    I do not have experience using ALSA, but I do see by the two instructions you pasted in that there is a different stream name (I think that is the proper term), for the two parts. ad193x_0 and ad193x_1. Somewhere these will be defined and tied to two different chip select output pins. These chip selects will go to the CLATCH pins on the each individual codec. So when you "talk" to one of the parts it will engage the proper chip select to activate the SPI port on the correct part.

    Your statement: "(512 fs DACs / 256 fs ADCs / single line TDM mode). "

    Why are the DACs configured for 512 fs and the ADCs are configured for 256 fs? Are you using a master clock to drive the PLL? The only way I see this would be if you wanted to run the DACs at a different sample rate from the ADCs. Then you would run the ADCs off of the PLL and directly clock the DAC off of the master clock input pin. Then the master clock would need to be running at 512x fs. The PLL input would have to be the ALRCLK and the loop filter values would have to be setup for the LRCLK frequencies.

    Now  I am fairly sure the statement you made was referring to the bit clock frequency of 512x for the DACs, which is TDM16 and 256x for the ADCs which is TDM 8. So that would be good.

    Now, you will have to make some hardware connections to do this. Send me your schematics. Figure 18 in the datasheet pretty much explains what pins to use for the DACs to be daisy chained.

    But, your basic question asking if you configure both the part the same, the answer is yes. don't forget to ground the input pins of the part on the end of the chain.

    Dave T

  • Hi DaveThib,

    thanks for you reply!

    I think I explained it a little bit vague.

    The code snippets I added are only an example, that both codecs are configured equally. 

    ad193x_0->regmap and ad193x_1->regmap are just placeholders for the regmap configurations of the single codecs.

    So I would extend the codec driver to configure both codecs in the same way in the callback functions.

    My question is how to pass the SPI master device with two chipselects to my codec driver, that I can create two different regmap configurations?

    By default, the codec driver is probed with struct spi_device *spi as parameter, which corresponds to a single codec (client) connected to the SPI master.

    A electrical circuit plan is attached. I think I have to swap ASDATA2 with ASDATA1 on the second codec (as well as DSDATA2 with DSDATA1), right?

    Thanks a lot!

  • Hello henrix,

    Looking at your diagram you are close...

    For the AD1938 labeled as "Aux", you will be coming into the DSDATA1 pin. The DSDATA2 will be unused (left floating) on that part because it is the last DAC in the chain.

    Likewise, for the ADC data the part labeled as "AUX" will output its ADC data on ASDATA1. ASDATA2 pin should be grounded.

    For the part labeled as "Master" you are correct in your port usage.

    For your clocking scheme, This should work. The ADC will be running a TDM8 signal and the DACs will be running a TDM16 signal.

    I am not a Linux expert, I support the codec. I looked into the help files on the Wiki and came up with this. It looks like you can specify a bus number to differentiate between devices. The chip select is also given here. What I do not see is the usage. The init code example that is in the help file does not use a bus number. I will ask around and see if I can find an answer. I did search the Linux part of this forum and came up with nothing.

    Here is a snip of the help file:

    Declaring SPI slave devices

    Unlike PCI or USB devices, SPI devices are not enumerated at the hardware level. Instead, the software must know which devices are connected on each SPI bus segment, and what slave selects these devices are using. For this reason, the kernel code must instantiate SPI devices explicitly. The most common method is to declare the SPI devices by bus number.

    This method is appropriate when the SPI bus is a system bus, as in many embedded systems, wherein each SPI bus has a number which is known in advance. It is thus possible to pre-declare the SPI devices that inhabit this bus. This is done with an array of struct spi_board_info, which is registered by calling spi_register_board_info().

    For more information see: Documentation/spi/spi-summary

    21 Oct 2010 16:10 · Michael Hennerich

    You need to set the modalias of your SPI info according to your codec. Valid values are “ad1935” and “ad1937”, You'll also have to adjust bus_num and chip_select according to your board setup.

    static struct spi_board_info board_spi_board_info[] __initdata = {     [--snip--]     {          .modalias = "ad1936",          .max_speed_hz = 3125000,     /* max spi clock (SCK) speed in HZ */          .bus_num = 0,          .chip_select = 4, /* CS, change it for your board */          .mode = SPI_MODE_3,     },     [--snip--]};
  • Hi,

    I found a way to register auxiliary devices in ASoC core. There is an extra property "aux_dev" in snd_soc_card structure for these applications. The connections of the codecs and the DSP (BeagleBone Green) are like this:

    - clock signals are connected as described in the circuit sketch

    - DAC TDM signal from DSP <-> DSDATA1 of "master" codec

    - DSDATA2 of "master" codec <-> DSDATA2 of "aux" codec

    - ADC TDM signal to DSP <-> ASDATA1 of "master" codec

    - ASDATA2 of "master" codec <-> ASDATA1 of "aux" codec

    - ASDATA2 of "aux" codec <-> GND

    The registers settings of the codecs are both like this:

    [ 477.090537] ad193x spi32766.0: AD193X register 0: 0x5
    [ 477.090685] ad193x spi32766.0: AD193X register 1: 0x0
    [ 477.090815] ad193x spi32766.0: AD193X register 2: 0x40
    [ 477.090946] ad193x spi32766.0: AD193X register 3: 0x3e //0x03 for aux codec (lbclk and lrclk slave (DACs))
    [ 477.091077] ad193x spi32766.0: AD193X register 4: 0x18
    [ 477.091208] ad193x spi32766.0: AD193X register 5: 0x0
    [ 477.091337] ad193x spi32766.0: AD193X register 6: 0x0
    [ 477.091465] ad193x spi32766.0: AD193X register 7: 0x0
    [ 477.091594] ad193x spi32766.0: AD193X register 8: 0x0
    [ 477.091724] ad193x spi32766.0: AD193X register 9: 0x0
    [ 477.091855] ad193x spi32766.0: AD193X register 10: 0x0
    [ 477.091986] ad193x spi32766.0: AD193X register 11: 0x0
    [ 477.092115] ad193x spi32766.0: AD193X register 12: 0x0
    [ 477.092245] ad193x spi32766.0: AD193X register 13: 0x0
    [ 477.092374] ad193x spi32766.0: AD193X register 14: 0x1
    [ 477.092503] ad193x spi32766.0: AD193X register 15: 0x23
    [ 477.093773] ad193x spi32766.0: AD193X register 16: 0x7c //0x34 for aux codec (lbclk and lrclk slave (ADCs))

    When I test the DAC outputs sequentially the master codec will correctly output the test signal (sine) from audio channel 9 to channel 15, but nothing happens with the aux codec. When I swap the DAC connections like this:

    - DAC TDM signal from DSP <-> DSDATA1 of "aux" codec

    - DSDATA2 of "aux" codec <-> DSDATA2 of "master" codec

    the sine test signal is available from channel 1 to channel 8 on "master" codec. So the hardware connections should be fine, but I don't get any output from the aux codec. Does the aux codec need a different configuration or anything else?

    Thanks a lot!

  • Hello henrix,

    Basically, you do not want to run in Aux mode. This is for an auxiliary stereo DAC that will be running at a different rate. You just want two codecs to behave like one 16 channel codec correct?

    Look at table 12 in the datasheet. It shows what pins are input and which are outputs in each mode.

    I will write in responses in Red below.

    I found a way to register auxiliary devices in ASoC core. There is an extra property "aux_dev" in snd_soc_card structure for these applications. The connections of the codecs and the DSP (BeagleBone Green) are like this:

    - clock signals are connected as described in the circuit sketch

    - DAC TDM signal from DSP <-> DSDATA1 of "master" codec

    - DSDATA2 of "master" codec <-> DSDATA2 of "aux" codec  No, DSDATA2 is an output. Setup both codecs the same as TDM mode not "Aux" Mode.

    - ADC TDM signal to DSP <-> ASDATA1 of "master" codec

    - ASDATA2 of "master" codec <-> ASDATA1 of "aux" codec

    - ASDATA2 of "aux" codec <-> GND

     

    The registers settings of the codecs are both like this:

    [ 477.090537] ad193x spi32766.0: AD193X register 0: 0x5 0x5 is for 512x fs master clock input. Is that what you have? I expect you have 12.288MHz master clock. You need to have bits 2:1 = 00 for 256x fs. These calculations are based on 48kHz fs. If you setup the part to run at a different sampling rate it will adjust the dividers. 

    The first bit, bit 0, is set to 1. This powers down the part. I think you want it powered up...

    Wait, I was looking below and noticed that I think you have the bit reversed. Bit 0 is the LSB and bit 7 is the MSB.

    In that case bit 7 is a 1 and bits 6:5 is 10? So enable the ADC and DAC, and use the ALRCLK as the input to the PLL. If you do use LRCLK then you must have the proper loop filter components on the PCB. It is in the applications circuits part of the datasheet.

    so 0x5 is 0xA0  this is what you intended correct? 


    [ 477.090685] ad193x spi32766.0: AD193X register 1: 0x0
    [ 477.090815] ad193x spi32766.0: AD193X register 2: 0x40, This one does not look backwards. 

     477.090946] ad193x spi32766.0: AD193X register 3: 0x3e //0x03 for aux codec (lbclk and lrclk slave (DACs))

    I would set both up for 0x3E, Both as slaves and both in TDM mode.


    [ 477.091077] ad193x spi32766.0: AD193X register 4: 0x18, This should be 0x00.
    [ 477.091208] ad193x spi32766.0: AD193X register 5: 0x0
    [ 477.091337] ad193x spi32766.0: AD193X register 6: 0x0
    [ 477.091465] ad193x spi32766.0: AD193X register 7: 0x0
    [ 477.091594] ad193x spi32766.0: AD193X register 8: 0x0
    [ 477.091724] ad193x spi32766.0: AD193X register 9: 0x0
    [ 477.091855] ad193x spi32766.0: AD193X register 10: 0x0
    [ 477.091986] ad193x spi32766.0: AD193X register 11: 0x0
    [ 477.092115] ad193x spi32766.0: AD193X register 12: 0x0
    [ 477.092245] ad193x spi32766.0: AD193X register 13: 0x0
    [ 477.092374] ad193x spi32766.0: AD193X register 14: 0x1 Do you want the ADCs powered down? That is what 0x01 will do.
    [ 477.092503] ad193x spi32766.0: AD193X register 15: 0x23 I would keep this to 24 bits. 0x20
    [ 477.093773] ad193x spi32766.0: AD193X register 16: 0x7c //0x34 for aux codec (lbclk and lrclk slave (ADCs)) Make them both the same but one might have to be a master and one a slave. I will have to look at your clocking diagram again cannot while editing this. So do you want to be running in TDM8? 512 BCLK per frame is TDM16.

     

     When I test the DAC outputs sequentially the master codec will correctly output the test signal (sine) from audio channel 9 to channel 15, but nothing happens with the aux codec. When I swap the DAC connections like this:

    - DAC TDM signal from DSP <-> DSDATA1 of "aux" codec

    - DSDATA2 of "aux" codec <-> DSDATA2 of "master" codec Again, DSDATA2 is an output. So it will be DSDATA2 --> DSDATA1

    the sine test signal is available from channel 1 to channel 8 on "master" codec. So the hardware connections should be fine, but I don't get any output from the aux codec. Does the aux codec need a different configuration or anything else?

     

    Thanks a lot!

  • Hi DaveThib,

    again, thanks a lot for your support!!!

    Just to clarify: With "aux" codec I just mean the second (daisy chained) codec. So both codecs of course operate in TDM mode, as you can see from the register settings. I will simply call the slave codec AD1938 DC from now.

    I've also made a wrong description for the pin connections...

    These are the current connections:

    DACs:

    - DSP -> DSDATA1 (AD1938)

    - DSDATA2 (AD1938) -> DSDATA1 (AD1938 DC)

    ADCs:

    - DSP <- ASDATA1 (AD1938)

    - ASDATA2 (AD1938) <- ASDATA1 (AD1938 DC) (ASDATA2 of AD1938 DC grounded)

    DaveThib schrieb:

    Hello henrix,

     

    Basically, you do not want to run in Aux mode. This is for an auxiliary stereo DAC that will be running at a different rate. You just want two codecs to behave like one 16 channel codec correct? Correct

    Look at table 12 in the datasheet. It shows what pins are input and which are outputs in each mode. Should be OK (see connections above)

     

    I will write in responses in Red below.

     

     

    I found a way to register auxiliary devices in ASoC core. There is an extra property "aux_dev" in snd_soc_card structure for these applications. The connections of the codecs and the DSP (BeagleBone Green) are like this:

    - clock signals are connected as described in the circuit sketch

    - DAC TDM signal from DSP <-> DSDATA1 of "master" codec

    - DSDATA2 of "master" codec <-> DSDATA2 of "aux" codec  No, DSDATA2 is an output. Setup both codecs the same as TDM mode not "Aux" Mode. My fault (see above)

    - ADC TDM signal to DSP <-> ASDATA1 of "master" codec

    - ASDATA2 of "master" codec <-> ASDATA1 of "aux" codec

    - ASDATA2 of "aux" codec <-> GND

     

    The registers settings of the codecs are both like this:

    [ 477.090537] ad193x spi32766.0: AD193X register 0: 0x5 0x5 is for 512x fs master clock input. Is that what you have? I expect you have 12.288MHz master clock. You need to have bits 2:1 = 00 for 256x fs. These calculations are based on 48kHz fs. If you setup the part to run at a different sampling rate it will adjust the dividers. That's correct. We use a 24.576MHz crystal for master clock. Both codecs use a dedicated crystal.

    The first bit, bit 0, is set to 1. This powers down the part. I think you want it powered up...

     

    Wait, I was looking below and noticed that I think you have the bit reversed. Bit 0 is the LSB and bit 7 is the MSB.

    In that case bit 7 is a 1 and bits 6:5 is 10? So enable the ADC and DAC, and use the ALRCLK as the input to the PLL. If you do use LRCLK then you must have the proper loop filter components on the PCB. It is in the applications circuits part of the datasheet.

    so 0x5 is 0xA0  this is what you intended correct? 


    [ 477.090685] ad193x spi32766.0: AD193X register 1: 0x0
    [ 477.090815] ad193x spi32766.0: AD193X register 2: 0x40, This one does not look backwards. What do you mean with that?

     477.090946] ad193x spi32766.0: AD193X register 3: 0x3e //0x03 for aux codec (lbclk and lrclk slave (DACs))

    I would set both up for 0x3E, Both as slaves and both in TDM mode. As mentioned above, both codecs (currently) use a dedicated crystal, so I think this could lead to problems (or am I wrong?) I thought, that just the master codec should do the frame and bitclocking. All other components (DSP, AD1938 DC) are configured as slaves and will be clocked from master codec. I think the clocking is also correct, because if I put the AD1938 master codec in the end of the chain (DSDATA and ASDATA connections are swaped with AD1938 DC codec) the first 8 TDM slots belong to master codec. The last 8 TDM slots belong to AD1938 DC codec. If the connections are swapped again -> vice versa of channel mapping (first 8 slots belong to AD1938 DC, last 8 slots belong to AD1938 master). So AD1938 DC seems to be clocked correctly and passes the first 8 TDM slots to the master codec (with swapped connections of DSDATA) I did this only for testing purposes).


    [ 477.091077] ad193x spi32766.0: AD193X register 4: 0x18, This should be 0x00.
    [ 477.091208] ad193x spi32766.0: AD193X register 5: 0x0
    [ 477.091337] ad193x spi32766.0: AD193X register 6: 0x0
    [ 477.091465] ad193x spi32766.0: AD193X register 7: 0x0
    [ 477.091594] ad193x spi32766.0: AD193X register 8: 0x0
    [ 477.091724] ad193x spi32766.0: AD193X register 9: 0x0
    [ 477.091855] ad193x spi32766.0: AD193X register 10: 0x0
    [ 477.091986] ad193x spi32766.0: AD193X register 11: 0x0
    [ 477.092115] ad193x spi32766.0: AD193X register 12: 0x0
    [ 477.092245] ad193x spi32766.0: AD193X register 13: 0x0
    [ 477.092374] ad193x spi32766.0: AD193X register 14: 0x1 Do you want the ADCs powered down? That is what 0x01 will do.
    [ 477.092503] ad193x spi32766.0: AD193X register 15: 0x23 I would keep this to 24 bits. 0x20
    [ 477.093773] ad193x spi32766.0: AD193X register 16: 0x7c //0x34 for aux codec (lbclk and lrclk slave (ADCs)) Make them both the same but one might have to be a master and one a slave. I will have to look at your clocking diagram again cannot while editing this. So do you want to be running in TDM8? 512 BCLK per frame is TDM16. I think I will set 256 BCLKs for the ADCs because it's not that error prone like with 512fs, but I've only done some tests with the DACs until now.

     

     

     

     When I test the DAC outputs sequentially the master codec will correctly output the test signal (sine) from audio channel 9 to channel 15, but nothing happens with the aux codec. When I swap the DAC connections like this:

    - DAC TDM signal from DSP <-> DSDATA1 of "aux" codec

    - DSDATA2 of "aux" codec <-> DSDATA2 of "master" codec Again, DSDATA2 is an output. So it will be DSDATA2 --> DSDATA1 My fault (see above)

    the sine test signal is available from channel 1 to channel 8 on "master" codec. So the hardware connections should be fine, but I don't get any output from the aux codec. Does the aux codec need a different configuration or anything else?

     

    Thanks a lot!

  • Hello henrix,

    You have to clock both parts with the exact same master clock. You cannot use two different crystals. They will never run at the same rate and you need exactly 256 MCLK transitions per frame otherwise you will get clicks, pops or nothing out.

    I would look into using a clock/oscillator module instead of a crystal. Then feed that into one MCLK input and take the MCLK output to feed to other codec's MCLK input.

    Dave T

  • Hi DaveThib,

    ok, we will try to do the clocking with an oscillator.

    I will update this thread as soon as I have new results.

    Thanks!

  • This question has been assumed as answered either offline via email or with a multi-part answer. This question has now been closed out. If you have an inquiry related to this topic please post a new question in the applicable product forum.

    Thank you,
    EZ Admin