ADAU1977
ADAU1977 Sound CODEC Linux Driver.
Supported Devices
Evaluation Boards
Source Code
Status
Files
Function |
File |
|
|---|---|---|
driver |
||
driver |
||
driver |
||
include |
||
platform data |
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,adau1978or 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);