ADAU1977

ADAU1977 Sound CODEC Linux Driver.

Supported Devices

Evaluation Boards

Source Code

Status

Source

Mainlined?

git

Yes

Files

Adding Linux driver support

Devicetree configuration

The ADAU1977 driver is fully devicetree compatible. Depending on the bus type the device is connected to different properties must/can be specified.

Shared required properties:

  • compatible: Must be adi,adau1977, adi,adau1978 or adi,adau1979``

  • AVDD-supply: A handle to the power supply connected to the AVDD pin

Shared optional properties:

  • DVDD-supply: A handle to the power supply connected to the DVDD pin. If specified the internal LDO will be disabled.

  • reset-gpios: GPIO chip handle and specifier that define which GPIO is connected to the chips PD/RST pin. If not specified the reset pin is assumed to be hardwired to VCC.

  • adi,micbias: Configures the voltage setting for the MICBIAS pin. If not specified the default value will be 8.5 Volts. This property is only valid for the ADAU1977. Valid values for this property are:

  • 0: 5.0V

  • 1: 5.5V

  • 2: 6.0V

  • 3: 6.5V

  • 4: 7.0V

  • 5: 7.5V

  • 6: 8.0V

  • 7: 8.5V

  • 8: 9.0V

I2C required properties:

  • reg: The I2C address of the chip

SPI required properties:

  • reg: The SPI chipselect signal of the SPI master associated with this chip

  • spi-max-frequency: Maximum spi frequency to use.

I2C

codec_supply: fixedregulator@0 {
    compatible = "regulator-fixed";
    regulator-name = "AVDD";
    regulator-min-microvolt = <3300000>;
    regulator-max-microvolt = <3300000>;
};

i2c@41600000 {
    compatible = "...;
    ...

    #size-cells = <0>;
    #address-cells = <1>;

    adau1977: codec@11 {
        compatible = "adi,adau1977";
        reg = <0x11>;
        reset-gpios = <&gpio 5 0>;
        AVDD-supply = <&codec_supply>;
    };
};

SPI

codec_supply: fixedregulator@0 {
    compatible = "regulator-fixed";
    regulator-name = "AVDD";
    regulator-min-microvolt = <3300000>;
    regulator-max-microvolt = <3300000>;
};

spi@41600000 {
    compatible = "...;
    ...

    #size-cells = <0>;
    #address-cells = <1>;

    adau1977: codec@1 {
        compatible = "adi,adau1977";
        reg = <0x1>;
        spi-max-frequency = <10000000>;
        reset-gpios = <&gpio 5 0>;
        AVDD-supply = <&codec_supply>;
        adi,micbias = <5>;
    };
};

Device enumeration

The driver reads adi,micbias from firmware. Values 0 through 8 select 5.0 V through 9.0 V in 0.5 V steps; if the property is omitted, the driver selects 8.5 V.

Voltage Supplies

The AVDD regulator is required. DVDD is optional; when it is supplied, the driver uses the external regulator and disables the internal LDO. See the regulator devicetree bindings documentation and the devicetree examples above.

I2C

The I2C address depends on the ADDR0 and ADDR1 pin settings:

ADDR1

ADDR0

I2C address

0

0

0x11

0

1

0x31

1

0

0x51

1

1

0x71

Driver testing

Routing and DAPM

ASoC DAPM Widgets

Name

Description

Configuration

AIN1

Analog Input Channel 1

AIN2

Analog Input Channel 2

AIN3

Analog Input Channel 3

AIN4

Analog Input Channel 4

VREF

Reference Voltage

MICBIAS

Microphone Bias Output

ADAU1977 only

ALSA controls

Name

Description

ADC1 Capture Volume

Post ADC gain for channel 1

ADC2 Capture Volume

Post ADC gain for channel 2

ADC3 Capture Volume

Post ADC gain for channel 3

ADC4 Capture Volume

Post ADC gain for channel 4

ADC1 Highpass-Filter Capture Switch

Enables/disables the highpass-filter for channel 1

ADC2 Highpass-Filter Capture Switch

Enables/disables the highpass-filter for channel 2

ADC3 Highpass-Filter Capture Switch

Enables/disables the highpass-filter for channel 3

ADC4 Highpass-Filter Capture Switch

Enables/disables the highpass-filter for channel 4

ADC1 DC Subtraction Capture Switch

Enables/disables DC offset subtraction for channel 1

ADC2 DC Subtraction Capture Switch

Enables/disables DC offset subtraction for channel 2

ADC3 DC Subtraction Capture Switch

Enables/disables DC offset subtraction for channel 3

ADC4 DC Subtraction Capture Switch

Enables/disables DC offset subtraction for channel 4

DAI formats and clocks

DAI configuration

The codec driver registers one DAI: adau1977-hifi

Supported DAI formats

Name

Supported by driver

Description

Notes

SND_SOC_DAIFMT_I2S

yes

I2S mode

SND_SOC_DAIFMT_RIGHT_J

yes

Right Justified mode

SND_SOC_DAIFMT_LEFT_J

yes

Left Justified mode

SND_SOC_DAIFMT_DSP_A

yes

data MSB after FRM LRC

SND_SOC_DAIFMT_DSP_B

yes

data MSB during FRM LRC

SND_SOC_DAIFMT_AC97

no

AC97 mode

SND_SOC_DAIFMT_PDM

no

Pulse density modulation

SND_SOC_DAIFMT_NB_NF

yes

Normal bit- and frameclock

SND_SOC_DAIFMT_NB_IF

yes

Normal bitclock, inverted frameclock

SND_SOC_DAIFMT_IB_NF

yes

Inverted frameclock, normal bitclock

SND_SOC_DAIFMT_IB_IF

yes

Inverted bit- and frameclock

SND_SOC_DAIFMT_CBM_CFM

yes

Codec bit- and frameclock master

Master mode is not supported if the LRCLK is used as clock source

SND_SOC_DAIFMT_CBS_CFM

no

Codec bitclock slave, frameclock master

SND_SOC_DAIFMT_CBM_CFS

no

Codec bitclock master, frameclock slave

SND_SOC_DAIFMT_CBS_CFS

yes

Codec bit- and frameclock slave

System clock configuration

The sysclk can either be provided by the internal PLL derived from the MCLK signal or by the LRCLK signal.

enum adau1977_clk_id {
    ADAU1977_SYSCLK,
};

enum adau1977_sysclk_src {
    ADAU1977_SYSCLK_SRC_MCLK,
    ADAU1977_SYSCLK_SRC_LRCLK,
};

When MCLK is used, the supported sampling rates are constrained to those that can be derived from it. The codec applies its rate-constraint list in startup, so configure sysclk before the codec’s startup callback, for example from the machine driver’s startup or init callback.

The 44.1 kHz sampling-rate family includes 11.025, 22.05, 44.1, 88.2 and 176.4 kHz. Select an MCLK frequency compatible with the required sampling rate.

For some hardware configurations it might be possible to change the MCLK frequency at runtime (e.g. to support both 44.1kHz and 48kHz based sample rates). Setting the MCLK sysclk frequency to 0 until the desired frequency is known avoids restricting startup to one MCLK-derived rate family. Set sysclk to 0 in the machine driver’s startup callback, then set the actual frequency in hw_params before the codec configures the stream.

Example machine driver configuration
Fixed MCLK
static int eval_adau1977_init(struct snd_soc_pcm_runtime *rtd)
{
    return snd_soc_component_set_sysclk(
        snd_soc_rtd_to_codec(rtd, 0)->component, ADAU1977_SYSCLK,
        ADAU1977_SYSCLK_SRC_MCLK, 12288000, SND_SOC_CLOCK_IN);
}

static struct snd_soc_dai_link eval_adau1977_dai = {
    .name = "adau1977",
    .stream_name = "ADAU1977",
    .cpu_dai_name = "bfin-i2s.0",
    .codec_dai_name = "adau1977-hifi",
    .platform_name = "bfin-i2s-pcm-audio",
    .codec_name = "adau1977.0-0011",
    .init = eval_adau1977_init,
    .dai_fmt = SND_SOC_DAIFMT_I2S |
        SND_SOC_DAIFMT_NB_NF |
        SND_SOC_DAIFMT_CBM_CFM,
};
Configurable MCLK

The machine driver must obtain and enable the actual board MCLK during probe, store it in the private data below, and attach that data to the card with snd_soc_card_set_drvdata().

struct eval_adau1977_priv {
    struct clk *mclk;
};

static int eval_adau1977_init(struct snd_soc_pcm_runtime *rtd)
{
    return snd_soc_component_set_sysclk(
        snd_soc_rtd_to_codec(rtd, 0)->component, ADAU1977_SYSCLK,
        ADAU1977_SYSCLK_SRC_MCLK, 0, SND_SOC_CLOCK_IN);
}

static int eval_adau1977_hw_params(struct snd_pcm_substream *substream,
    struct snd_pcm_hw_params *params)
{
    struct snd_soc_pcm_runtime *rtd = substream->private_data;
    struct eval_adau1977_priv *priv = snd_soc_card_get_drvdata(rtd->card);
    unsigned long mclk_rate;
    int ret;

    if (params_rate(params) % 11025 == 0)
        mclk_rate = 11289600;
    else
        mclk_rate = 12288000;

    ret = clk_set_rate(priv->mclk, mclk_rate);
    if (ret)
        return ret;
    mclk_rate = clk_get_rate(priv->mclk);

    return snd_soc_component_set_sysclk(
        snd_soc_rtd_to_codec(rtd, 0)->component, ADAU1977_SYSCLK,
        ADAU1977_SYSCLK_SRC_MCLK, mclk_rate, SND_SOC_CLOCK_IN);
}

static struct snd_soc_ops eval_adau1977_ops = {
    .hw_params = eval_adau1977_hw_params,
};

static struct snd_soc_dai_link eval_adau1977_dai = {
    .name = "adau1977",
    .stream_name = "ADAU1977",
    .cpu_dai_name = "bfin-i2s.0",
    .codec_dai_name = "adau1977-hifi",
    .platform_name = "bfin-i2s-pcm-audio",
    .codec_name = "adau1977.0-0011",
    .ops = &eval_adau1977_ops,
    .init = eval_adau1977_init,
    .dai_fmt = SND_SOC_DAIFMT_I2S |
        SND_SOC_DAIFMT_NB_NF |
        SND_SOC_DAIFMT_CBM_CFM,
};

Need Help?

TDM configuration

The TDM mode of the ADAU1977 can be configured using the snd_soc_dai_set_tdm_slot() function.

  • The number of slots can be either 2, 4, 8 or 16. If the number of slots is set to 0 the device will go to I2S mode.

  • The slot width can be 16, 24, 32 bits per slot (In master mode only 16 and 32 bits per slot are supported)

  • tx_mask must always be 0.

  • Each slot can hold the data sample of one channel. Which slot holds which channel is configured by rx_mask. The first bit that is set in rx_mask is the slot that holds the first channel, the second bit the slot that holds the second channel and so on. If less then 4 bits are set the channels for which no slot has been provided are disabled. (E.g. 0x33, configures channel 0 to slot 0, channel 1 to slot 1, channel 2 to slot 4 and channel 3 to slot 5).

Example TDM configuration:

ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0f, 4, 32);

To configure whether the unused TDM slots should be tristated or actively driven low the snd_soc_dai_set_tristate() function is used. By default they are driven low.

Example tristate configuration:

ret = snd_soc_dai_set_tristate(codec_dai, true);