2020-11-27 13:30:30 +01:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* Analog Devices ADAU1372 Audio Codec driver
*
* Copyright 2016 Analog Devices Inc .
* Author : Lars - Peter Clausen < lars @ metafoo . de >
*/
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/gpio/consumer.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/pm.h>
# include <linux/slab.h>
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
# include <sound/tlv.h>
# include <sound/soc.h>
# include "adau1372.h"
# include "adau-utils.h"
struct adau1372 {
struct regmap * regmap ;
void ( * switch_mode ) ( struct device * dev ) ;
bool use_pll ;
bool enabled ;
2021-09-16 16:18:01 +01:00
bool clock_provider ;
2020-11-27 13:30:30 +01:00
struct snd_pcm_hw_constraint_list rate_constraints ;
unsigned int slot_width ;
struct clk * mclk ;
struct gpio_desc * pd_gpio ;
struct device * dev ;
} ;
# define ADAU1372_REG_CLK_CTRL 0x00
# define ADAU1372_REG_PLL(x) (0x01 + (x))
# define ADAU1372_REG_DAC_SOURCE 0x11
# define ADAU1372_REG_SOUT_SOURCE_0_1 0x13
# define ADAU1372_REG_SOUT_SOURCE_2_3 0x14
# define ADAU1372_REG_SOUT_SOURCE_4_5 0x15
# define ADAU1372_REG_SOUT_SOURCE_6_7 0x16
# define ADAU1372_REG_ADC_SDATA_CH 0x17
# define ADAU1372_REG_ASRCO_SOURCE_0_1 0x18
# define ADAU1372_REG_ASRCO_SOURCE_2_3 0x19
# define ADAU1372_REG_ASRC_MODE 0x1a
# define ADAU1372_REG_ADC_CTRL0 0x1b
# define ADAU1372_REG_ADC_CTRL1 0x1c
# define ADAU1372_REG_ADC_CTRL2 0x1d
# define ADAU1372_REG_ADC_CTRL3 0x1e
# define ADAU1372_REG_ADC_VOL(x) (0x1f + (x))
# define ADAU1372_REG_PGA_CTRL(x) (0x23 + (x))
# define ADAU1372_REG_PGA_BOOST 0x28
# define ADAU1372_REG_MICBIAS 0x2d
# define ADAU1372_REG_DAC_CTRL 0x2e
# define ADAU1372_REG_DAC_VOL(x) (0x2f + (x))
# define ADAU1372_REG_OP_STAGE_MUTE 0x31
# define ADAU1372_REG_SAI0 0x32
# define ADAU1372_REG_SAI1 0x33
# define ADAU1372_REG_SOUT_CTRL 0x34
# define ADAU1372_REG_MODE_MP(x) (0x38 + (x))
# define ADAU1372_REG_OP_STAGE_CTRL 0x43
# define ADAU1372_REG_DECIM_PWR 0x44
# define ADAU1372_REG_INTERP_PWR 0x45
# define ADAU1372_REG_BIAS_CTRL0 0x46
# define ADAU1372_REG_BIAS_CTRL1 0x47
# define ADAU1372_CLK_CTRL_PLL_EN BIT(7)
# define ADAU1372_CLK_CTRL_XTAL_DIS BIT(4)
# define ADAU1372_CLK_CTRL_CLKSRC BIT(3)
# define ADAU1372_CLK_CTRL_CC_MDIV BIT(1)
# define ADAU1372_CLK_CTRL_MCLK_EN BIT(0)
# define ADAU1372_SAI0_DELAY1 (0x0 << 6)
# define ADAU1372_SAI0_DELAY0 (0x1 << 6)
# define ADAU1372_SAI0_DELAY_MASK (0x3 << 6)
# define ADAU1372_SAI0_SAI_I2S (0x0 << 4)
# define ADAU1372_SAI0_SAI_TDM2 (0x1 << 4)
# define ADAU1372_SAI0_SAI_TDM4 (0x2 << 4)
# define ADAU1372_SAI0_SAI_TDM8 (0x3 << 4)
# define ADAU1372_SAI0_SAI_MASK (0x3 << 4)
# define ADAU1372_SAI0_FS_48 0x0
# define ADAU1372_SAI0_FS_8 0x1
# define ADAU1372_SAI0_FS_12 0x2
# define ADAU1372_SAI0_FS_16 0x3
# define ADAU1372_SAI0_FS_24 0x4
# define ADAU1372_SAI0_FS_32 0x5
# define ADAU1372_SAI0_FS_96 0x6
# define ADAU1372_SAI0_FS_192 0x7
# define ADAU1372_SAI0_FS_MASK 0xf
# define ADAU1372_SAI1_TDM_TS BIT(7)
# define ADAU1372_SAI1_BCLK_TDMC BIT(6)
# define ADAU1372_SAI1_LR_MODE BIT(5)
# define ADAU1372_SAI1_LR_POL BIT(4)
# define ADAU1372_SAI1_BCLKRATE BIT(2)
# define ADAU1372_SAI1_BCLKEDGE BIT(1)
# define ADAU1372_SAI1_MS BIT(0)
static const unsigned int adau1372_rates [ ] = {
[ ADAU1372_SAI0_FS_8 ] = 8000 ,
[ ADAU1372_SAI0_FS_12 ] = 12000 ,
[ ADAU1372_SAI0_FS_16 ] = 16000 ,
[ ADAU1372_SAI0_FS_24 ] = 24000 ,
[ ADAU1372_SAI0_FS_32 ] = 32000 ,
[ ADAU1372_SAI0_FS_48 ] = 48000 ,
[ ADAU1372_SAI0_FS_96 ] = 96000 ,
[ ADAU1372_SAI0_FS_192 ] = 192000 ,
} ;
/* 8k, 12k, 24k, 48k */
# define ADAU1372_RATE_MASK_TDM8 0x17
/* + 16k, 96k */
# define ADAU1372_RATE_MASK_TDM4_MASTER (ADAU1372_RATE_MASK_TDM8 | 0x48 | 0x20)
/* +32k */
# define ADAU1372_RATE_MASK_TDM4 (ADAU1372_RATE_MASK_TDM4_MASTER | 0x20)
/* + 192k */
# define ADAU1372_RATE_MASK_TDM2 (ADAU1372_RATE_MASK_TDM4 | 0x80)
static const DECLARE_TLV_DB_MINMAX ( adau1372_digital_tlv , - 9563 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( adau1372_pga_tlv , - 1200 , 75 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( adau1372_pga_boost_tlv , 0 , 1000 , 0 ) ;
static const char * const adau1372_bias_text [ ] = {
" Normal operation " , " Extreme power saving " , " Enhanced performance " ,
" Power saving " ,
} ;
static const unsigned int adau1372_bias_adc_values [ ] = {
0 , 2 , 3 ,
} ;
static const char * const adau1372_bias_adc_text [ ] = {
" Normal operation " , " Enhanced performance " , " Power saving " ,
} ;
static const char * const adau1372_bias_dac_text [ ] = {
" Normal operation " , " Power saving " , " Superior performance " ,
" Enhanced performance " ,
} ;
static SOC_ENUM_SINGLE_DECL ( adau1372_bias_hp_enum ,
ADAU1372_REG_BIAS_CTRL0 , 6 , adau1372_bias_text ) ;
static SOC_ENUM_SINGLE_DECL ( adau1372_bias_afe0_1_enum ,
ADAU1372_REG_BIAS_CTRL0 , 4 , adau1372_bias_text ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_bias_adc2_3_enum ,
ADAU1372_REG_BIAS_CTRL0 , 2 , 0x3 , adau1372_bias_adc_text ,
adau1372_bias_adc_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_bias_adc0_1_enum ,
ADAU1372_REG_BIAS_CTRL0 , 0 , 0x3 , adau1372_bias_adc_text ,
adau1372_bias_adc_values ) ;
static SOC_ENUM_SINGLE_DECL ( adau1372_bias_afe2_3_enum ,
ADAU1372_REG_BIAS_CTRL1 , 4 , adau1372_bias_text ) ;
static SOC_ENUM_SINGLE_DECL ( adau1372_bias_mic_enum ,
ADAU1372_REG_BIAS_CTRL1 , 2 , adau1372_bias_text ) ;
static SOC_ENUM_SINGLE_DECL ( adau1372_bias_dac_enum ,
ADAU1372_REG_BIAS_CTRL1 , 0 , adau1372_bias_dac_text ) ;
static const char * const adau1372_hpf_text [ ] = {
" Off " ,
" 1 Hz " ,
" 4 Hz " ,
" 8 Hz " ,
} ;
static SOC_ENUM_SINGLE_DECL ( adau1372_hpf0_1_enum , ADAU1372_REG_ADC_CTRL2 , 5 ,
adau1372_hpf_text ) ;
static SOC_ENUM_SINGLE_DECL ( adau1372_hpf2_3_enum , ADAU1372_REG_ADC_CTRL3 , 5 ,
adau1372_hpf_text ) ;
static const struct snd_kcontrol_new adau1372_controls [ ] = {
SOC_SINGLE_TLV ( " ADC 0 Capture Volume " , ADAU1372_REG_ADC_VOL ( 0 ) ,
0 , 0xff , 1 , adau1372_digital_tlv ) ,
SOC_SINGLE_TLV ( " ADC 1 Capture Volume " , ADAU1372_REG_ADC_VOL ( 1 ) ,
0 , 0xff , 1 , adau1372_digital_tlv ) ,
SOC_SINGLE_TLV ( " ADC 2 Capture Volume " , ADAU1372_REG_ADC_VOL ( 2 ) ,
0 , 0xff , 1 , adau1372_digital_tlv ) ,
SOC_SINGLE_TLV ( " ADC 3 Capture Volume " , ADAU1372_REG_ADC_VOL ( 3 ) ,
0 , 0xff , 1 , adau1372_digital_tlv ) ,
SOC_SINGLE ( " ADC 0 Capture Switch " , ADAU1372_REG_ADC_CTRL0 , 3 , 1 , 1 ) ,
SOC_SINGLE ( " ADC 1 Capture Switch " , ADAU1372_REG_ADC_CTRL0 , 4 , 1 , 1 ) ,
SOC_SINGLE ( " ADC 2 Capture Switch " , ADAU1372_REG_ADC_CTRL1 , 3 , 1 , 1 ) ,
SOC_SINGLE ( " ADC 3 Capture Switch " , ADAU1372_REG_ADC_CTRL1 , 4 , 1 , 1 ) ,
SOC_ENUM ( " ADC 0+1 High-Pass-Filter " , adau1372_hpf0_1_enum ) ,
SOC_ENUM ( " ADC 2+3 High-Pass-Filter " , adau1372_hpf2_3_enum ) ,
SOC_SINGLE_TLV ( " PGA 0 Capture Volume " , ADAU1372_REG_PGA_CTRL ( 0 ) ,
0 , 0x3f , 0 , adau1372_pga_tlv ) ,
SOC_SINGLE_TLV ( " PGA 1 Capture Volume " , ADAU1372_REG_PGA_CTRL ( 1 ) ,
0 , 0x3f , 0 , adau1372_pga_tlv ) ,
SOC_SINGLE_TLV ( " PGA 2 Capture Volume " , ADAU1372_REG_PGA_CTRL ( 2 ) ,
0 , 0x3f , 0 , adau1372_pga_tlv ) ,
SOC_SINGLE_TLV ( " PGA 3 Capture Volume " , ADAU1372_REG_PGA_CTRL ( 3 ) ,
0 , 0x3f , 0 , adau1372_pga_tlv ) ,
SOC_SINGLE_TLV ( " PGA 0 Boost Capture Volume " , ADAU1372_REG_PGA_BOOST ,
0 , 1 , 0 , adau1372_pga_boost_tlv ) ,
SOC_SINGLE_TLV ( " PGA 1 Boost Capture Volume " , ADAU1372_REG_PGA_BOOST ,
1 , 1 , 0 , adau1372_pga_boost_tlv ) ,
SOC_SINGLE_TLV ( " PGA 2 Boost Capture Volume " , ADAU1372_REG_PGA_BOOST ,
2 , 1 , 0 , adau1372_pga_boost_tlv ) ,
SOC_SINGLE_TLV ( " PGA 3 Boost Capture Volume " , ADAU1372_REG_PGA_BOOST ,
3 , 1 , 0 , adau1372_pga_boost_tlv ) ,
2022-10-28 17:26:25 +02:00
SOC_SINGLE ( " PGA 0 Capture Switch " , ADAU1372_REG_PGA_CTRL ( 0 ) , 7 , 1 , 0 ) ,
SOC_SINGLE ( " PGA 1 Capture Switch " , ADAU1372_REG_PGA_CTRL ( 1 ) , 7 , 1 , 0 ) ,
SOC_SINGLE ( " PGA 2 Capture Switch " , ADAU1372_REG_PGA_CTRL ( 2 ) , 7 , 1 , 0 ) ,
SOC_SINGLE ( " PGA 3 Capture Switch " , ADAU1372_REG_PGA_CTRL ( 3 ) , 7 , 1 , 0 ) ,
2020-11-27 13:30:30 +01:00
SOC_SINGLE_TLV ( " DAC 0 Playback Volume " , ADAU1372_REG_DAC_VOL ( 0 ) ,
0 , 0xff , 1 , adau1372_digital_tlv ) ,
SOC_SINGLE_TLV ( " DAC 1 Playback Volume " , ADAU1372_REG_DAC_VOL ( 1 ) ,
0 , 0xff , 1 , adau1372_digital_tlv ) ,
SOC_SINGLE ( " DAC 0 Playback Switch " , ADAU1372_REG_DAC_CTRL , 3 , 1 , 1 ) ,
SOC_SINGLE ( " DAC 1 Playback Switch " , ADAU1372_REG_DAC_CTRL , 4 , 1 , 1 ) ,
SOC_ENUM ( " Headphone Bias " , adau1372_bias_hp_enum ) ,
SOC_ENUM ( " Microphone Bias " , adau1372_bias_mic_enum ) ,
SOC_ENUM ( " AFE 0+1 Bias " , adau1372_bias_afe0_1_enum ) ,
SOC_ENUM ( " AFE 2+3 Bias " , adau1372_bias_afe2_3_enum ) ,
SOC_ENUM ( " ADC 0+1 Bias " , adau1372_bias_adc0_1_enum ) ,
SOC_ENUM ( " ADC 2+3 Bias " , adau1372_bias_adc2_3_enum ) ,
SOC_ENUM ( " DAC 0+1 Bias " , adau1372_bias_dac_enum ) ,
} ;
static const char * const adau1372_decimator_mux_text [ ] = {
" ADC " ,
" DMIC " ,
} ;
static SOC_ENUM_SINGLE_DECL ( adau1372_decimator0_1_mux_enum , ADAU1372_REG_ADC_CTRL2 ,
2 , adau1372_decimator_mux_text ) ;
static const struct snd_kcontrol_new adau1372_decimator0_1_mux_control =
SOC_DAPM_ENUM ( " Decimator 0+1 Capture Mux " , adau1372_decimator0_1_mux_enum ) ;
static SOC_ENUM_SINGLE_DECL ( adau1372_decimator2_3_mux_enum , ADAU1372_REG_ADC_CTRL3 ,
2 , adau1372_decimator_mux_text ) ;
static const struct snd_kcontrol_new adau1372_decimator2_3_mux_control =
SOC_DAPM_ENUM ( " Decimator 2+3 Capture Mux " , adau1372_decimator2_3_mux_enum ) ;
static const unsigned int adau1372_asrco_mux_values [ ] = {
4 , 5 , 6 , 7 ,
} ;
static const char * const adau1372_asrco_mux_text [ ] = {
" Decimator0 " ,
" Decimator1 " ,
" Decimator2 " ,
" Decimator3 " ,
} ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_asrco0_mux_enum , ADAU1372_REG_ASRCO_SOURCE_0_1 ,
0 , 0xf , adau1372_asrco_mux_text , adau1372_asrco_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_asrco1_mux_enum , ADAU1372_REG_ASRCO_SOURCE_0_1 ,
4 , 0xf , adau1372_asrco_mux_text , adau1372_asrco_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_asrco2_mux_enum , ADAU1372_REG_ASRCO_SOURCE_2_3 ,
0 , 0xf , adau1372_asrco_mux_text , adau1372_asrco_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_asrco3_mux_enum , ADAU1372_REG_ASRCO_SOURCE_2_3 ,
4 , 0xf , adau1372_asrco_mux_text , adau1372_asrco_mux_values ) ;
static const struct snd_kcontrol_new adau1372_asrco0_mux_control =
SOC_DAPM_ENUM ( " Output ASRC0 Capture Mux " , adau1372_asrco0_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_asrco1_mux_control =
SOC_DAPM_ENUM ( " Output ASRC1 Capture Mux " , adau1372_asrco1_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_asrco2_mux_control =
SOC_DAPM_ENUM ( " Output ASRC2 Capture Mux " , adau1372_asrco2_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_asrco3_mux_control =
SOC_DAPM_ENUM ( " Output ASRC3 Capture Mux " , adau1372_asrco3_mux_enum ) ;
static const unsigned int adau1372_sout_mux_values [ ] = {
4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15
} ;
static const char * const adau1372_sout_mux_text [ ] = {
" Output ASRC0 " ,
" Output ASRC1 " ,
" Output ASRC2 " ,
" Output ASRC3 " ,
" Serial Input 0 " ,
" Serial Input 1 " ,
" Serial Input 2 " ,
" Serial Input 3 " ,
" Serial Input 4 " ,
" Serial Input 5 " ,
" Serial Input 6 " ,
" Serial Input 7 " ,
} ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout0_mux_enum , ADAU1372_REG_SOUT_SOURCE_0_1 ,
0 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout1_mux_enum , ADAU1372_REG_SOUT_SOURCE_0_1 ,
4 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout2_mux_enum , ADAU1372_REG_SOUT_SOURCE_2_3 ,
0 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout3_mux_enum , ADAU1372_REG_SOUT_SOURCE_2_3 ,
4 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout4_mux_enum , ADAU1372_REG_SOUT_SOURCE_4_5 ,
0 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout5_mux_enum , ADAU1372_REG_SOUT_SOURCE_4_5 ,
4 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout6_mux_enum , ADAU1372_REG_SOUT_SOURCE_6_7 ,
0 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_sout7_mux_enum , ADAU1372_REG_SOUT_SOURCE_6_7 ,
4 , 0xf , adau1372_sout_mux_text , adau1372_sout_mux_values ) ;
static const struct snd_kcontrol_new adau1372_sout0_mux_control =
SOC_DAPM_ENUM ( " Serial Output 0 Capture Mux " , adau1372_sout0_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_sout1_mux_control =
SOC_DAPM_ENUM ( " Serial Output 1 Capture Mux " , adau1372_sout1_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_sout2_mux_control =
SOC_DAPM_ENUM ( " Serial Output 2 Capture Mux " , adau1372_sout2_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_sout3_mux_control =
SOC_DAPM_ENUM ( " Serial Output 3 Capture Mux " , adau1372_sout3_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_sout4_mux_control =
SOC_DAPM_ENUM ( " Serial Output 4 Capture Mux " , adau1372_sout4_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_sout5_mux_control =
SOC_DAPM_ENUM ( " Serial Output 5 Capture Mux " , adau1372_sout5_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_sout6_mux_control =
SOC_DAPM_ENUM ( " Serial Output 6 Capture Mux " , adau1372_sout6_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_sout7_mux_control =
SOC_DAPM_ENUM ( " Serial Output 7 Capture Mux " , adau1372_sout7_mux_enum ) ;
static const char * const adau1372_asrci_mux_text [ ] = {
" Serial Input 0+1 " ,
" Serial Input 2+3 " ,
" Serial Input 4+5 " ,
" Serial Input 6+7 " ,
} ;
static SOC_ENUM_SINGLE_DECL ( adau1372_asrci_mux_enum ,
ADAU1372_REG_ASRC_MODE , 2 , adau1372_asrci_mux_text ) ;
static const struct snd_kcontrol_new adau1372_asrci_mux_control =
SOC_DAPM_ENUM ( " Input ASRC Playback Mux " , adau1372_asrci_mux_enum ) ;
static const unsigned int adau1372_dac_mux_values [ ] = {
12 , 13
} ;
static const char * const adau1372_dac_mux_text [ ] = {
" Input ASRC0 " ,
" Input ASRC1 " ,
} ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_dac0_mux_enum , ADAU1372_REG_DAC_SOURCE ,
0 , 0xf , adau1372_dac_mux_text , adau1372_dac_mux_values ) ;
static SOC_VALUE_ENUM_SINGLE_DECL ( adau1372_dac1_mux_enum , ADAU1372_REG_DAC_SOURCE ,
4 , 0xf , adau1372_dac_mux_text , adau1372_dac_mux_values ) ;
static const struct snd_kcontrol_new adau1372_dac0_mux_control =
SOC_DAPM_ENUM ( " DAC 0 Playback Mux " , adau1372_dac0_mux_enum ) ;
static const struct snd_kcontrol_new adau1372_dac1_mux_control =
SOC_DAPM_ENUM ( " DAC 1 Playback Mux " , adau1372_dac1_mux_enum ) ;
static const struct snd_soc_dapm_widget adau1372_dapm_widgets [ ] = {
SND_SOC_DAPM_INPUT ( " AIN0 " ) ,
SND_SOC_DAPM_INPUT ( " AIN1 " ) ,
SND_SOC_DAPM_INPUT ( " AIN2 " ) ,
SND_SOC_DAPM_INPUT ( " AIN3 " ) ,
SND_SOC_DAPM_INPUT ( " DMIC0_1 " ) ,
SND_SOC_DAPM_INPUT ( " DMIC2_3 " ) ,
SND_SOC_DAPM_SUPPLY ( " MICBIAS0 " , ADAU1372_REG_MICBIAS , 4 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " MICBIAS1 " , ADAU1372_REG_MICBIAS , 5 , 0 , NULL , 0 ) ,
2022-10-28 17:26:25 +02:00
SND_SOC_DAPM_PGA ( " PGA0 " , ADAU1372_REG_PGA_CTRL ( 0 ) , 6 , 1 , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " PGA1 " , ADAU1372_REG_PGA_CTRL ( 1 ) , 6 , 1 , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " PGA2 " , ADAU1372_REG_PGA_CTRL ( 2 ) , 6 , 1 , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " PGA3 " , ADAU1372_REG_PGA_CTRL ( 3 ) , 6 , 1 , NULL , 0 ) ,
2020-11-27 13:30:30 +01:00
SND_SOC_DAPM_ADC ( " ADC0 " , NULL , ADAU1372_REG_ADC_CTRL2 , 0 , 0 ) ,
SND_SOC_DAPM_ADC ( " ADC1 " , NULL , ADAU1372_REG_ADC_CTRL2 , 1 , 0 ) ,
SND_SOC_DAPM_ADC ( " ADC2 " , NULL , ADAU1372_REG_ADC_CTRL3 , 0 , 0 ) ,
SND_SOC_DAPM_ADC ( " ADC3 " , NULL , ADAU1372_REG_ADC_CTRL3 , 1 , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " ADC0 Filter " , ADAU1372_REG_DECIM_PWR , 0 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " ADC1 Filter " , ADAU1372_REG_DECIM_PWR , 1 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " ADC2 Filter " , ADAU1372_REG_DECIM_PWR , 2 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " ADC3 Filter " , ADAU1372_REG_DECIM_PWR , 3 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Output ASRC0 Decimator " , ADAU1372_REG_DECIM_PWR , 4 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Output ASRC1 Decimator " , ADAU1372_REG_DECIM_PWR , 5 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Output ASRC2 Decimator " , ADAU1372_REG_DECIM_PWR , 6 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Output ASRC3 Decimator " , ADAU1372_REG_DECIM_PWR , 7 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_MUX ( " Decimator0 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_decimator0_1_mux_control ) ,
SND_SOC_DAPM_MUX ( " Decimator1 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_decimator0_1_mux_control ) ,
SND_SOC_DAPM_MUX ( " Decimator2 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_decimator2_3_mux_control ) ,
SND_SOC_DAPM_MUX ( " Decimator3 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_decimator2_3_mux_control ) ,
SND_SOC_DAPM_MUX ( " Output ASRC0 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_asrco0_mux_control ) ,
SND_SOC_DAPM_MUX ( " Output ASRC1 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_asrco1_mux_control ) ,
SND_SOC_DAPM_MUX ( " Output ASRC2 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_asrco2_mux_control ) ,
SND_SOC_DAPM_MUX ( " Output ASRC3 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_asrco3_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 0 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout0_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 1 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout1_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 2 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout2_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 3 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout3_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 4 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout4_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 5 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout5_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 6 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout6_mux_control ) ,
SND_SOC_DAPM_MUX ( " Serial Output 7 Capture Mux " , SND_SOC_NOPM , 0 , 0 ,
& adau1372_sout7_mux_control ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 0 " , NULL , 0 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 1 " , NULL , 1 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 2 " , NULL , 2 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 3 " , NULL , 3 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 4 " , NULL , 4 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 5 " , NULL , 5 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 6 " , NULL , 6 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " Serial Input 7 " , NULL , 7 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 0 " , NULL , 0 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 1 " , NULL , 1 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 2 " , NULL , 2 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 3 " , NULL , 3 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 4 " , NULL , 4 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 5 " , NULL , 5 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 6 " , NULL , 6 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " Serial Output 7 " , NULL , 7 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Output ASRC Supply " , ADAU1372_REG_ASRC_MODE , 1 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Input ASRC Supply " , ADAU1372_REG_ASRC_MODE , 0 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " DAC1 Modulator " , ADAU1372_REG_INTERP_PWR , 3 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " DAC0 Modulator " , ADAU1372_REG_INTERP_PWR , 2 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Input ASRC1 Interpolator " , ADAU1372_REG_INTERP_PWR , 1 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Input ASRC0 Interpolator " , ADAU1372_REG_INTERP_PWR , 0 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_MUX ( " Input ASRC0 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_asrci_mux_control ) ,
SND_SOC_DAPM_MUX ( " Input ASRC1 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_asrci_mux_control ) ,
SND_SOC_DAPM_MUX ( " DAC 0 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_dac0_mux_control ) ,
SND_SOC_DAPM_MUX ( " DAC 1 Mux " , SND_SOC_NOPM , 0 , 0 , & adau1372_dac1_mux_control ) ,
SND_SOC_DAPM_DAC ( " DAC0 " , NULL , ADAU1372_REG_DAC_CTRL , 0 , 0 ) ,
SND_SOC_DAPM_DAC ( " DAC1 " , NULL , ADAU1372_REG_DAC_CTRL , 1 , 0 ) ,
SND_SOC_DAPM_OUT_DRV ( " OP_STAGE_LP " , ADAU1372_REG_OP_STAGE_CTRL , 0 , 1 , NULL , 0 ) ,
SND_SOC_DAPM_OUT_DRV ( " OP_STAGE_LN " , ADAU1372_REG_OP_STAGE_CTRL , 1 , 1 , NULL , 0 ) ,
SND_SOC_DAPM_OUT_DRV ( " OP_STAGE_RP " , ADAU1372_REG_OP_STAGE_CTRL , 2 , 1 , NULL , 0 ) ,
SND_SOC_DAPM_OUT_DRV ( " OP_STAGE_RN " , ADAU1372_REG_OP_STAGE_CTRL , 3 , 1 , NULL , 0 ) ,
SND_SOC_DAPM_OUTPUT ( " HPOUTL " ) ,
SND_SOC_DAPM_OUTPUT ( " HPOUTR " ) ,
} ;
# define ADAU1372_SOUT_ROUTES(x) \
{ " Serial Output " # x " Capture Mux " , " Output ASRC0 " , " Output ASRC0 Mux " } , \
{ " Serial Output " # x " Capture Mux " , " Output ASRC1 " , " Output ASRC1 Mux " } , \
{ " Serial Output " # x " Capture Mux " , " Output ASRC2 " , " Output ASRC2 Mux " } , \
{ " Serial Output " # x " Capture Mux " , " Output ASRC3 " , " Output ASRC3 Mux " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 0 " , " Serial Input 0 " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 1 " , " Serial Input 1 " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 2 " , " Serial Input 2 " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 3 " , " Serial Input 3 " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 4 " , " Serial Input 4 " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 5 " , " Serial Input 5 " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 6 " , " Serial Input 6 " } , \
{ " Serial Output " # x " Capture Mux " , " Serial Input 7 " , " Serial Input 7 " } , \
{ " Serial Output " # x , NULL , " Serial Output " # x " Capture Mux " } , \
{ " Capture " , NULL , " Serial Output " # x }
# define ADAU1372_ASRCO_ROUTES(x) \
{ " Output ASRC " # x " Mux " , " Decimator0 " , " Decimator0 Mux " } , \
{ " Output ASRC " # x " Mux " , " Decimator1 " , " Decimator1 Mux " } , \
{ " Output ASRC " # x " Mux " , " Decimator2 " , " Decimator2 Mux " } , \
{ " Output ASRC " # x " Mux " , " Decimator3 " , " Decimator3 Mux " }
static const struct snd_soc_dapm_route adau1372_dapm_routes [ ] = {
{ " PGA0 " , NULL , " AIN0 " } ,
{ " PGA1 " , NULL , " AIN1 " } ,
{ " PGA2 " , NULL , " AIN2 " } ,
{ " PGA3 " , NULL , " AIN3 " } ,
{ " ADC0 " , NULL , " PGA0 " } ,
{ " ADC1 " , NULL , " PGA1 " } ,
{ " ADC2 " , NULL , " PGA2 " } ,
{ " ADC3 " , NULL , " PGA3 " } ,
{ " Decimator0 Mux " , " ADC " , " ADC0 " } ,
{ " Decimator1 Mux " , " ADC " , " ADC1 " } ,
{ " Decimator2 Mux " , " ADC " , " ADC2 " } ,
{ " Decimator3 Mux " , " ADC " , " ADC3 " } ,
{ " Decimator0 Mux " , " DMIC " , " DMIC0_1 " } ,
{ " Decimator1 Mux " , " DMIC " , " DMIC0_1 " } ,
{ " Decimator2 Mux " , " DMIC " , " DMIC2_3 " } ,
{ " Decimator3 Mux " , " DMIC " , " DMIC2_3 " } ,
{ " Decimator0 Mux " , NULL , " ADC0 Filter " } ,
{ " Decimator1 Mux " , NULL , " ADC1 Filter " } ,
{ " Decimator2 Mux " , NULL , " ADC2 Filter " } ,
{ " Decimator3 Mux " , NULL , " ADC3 Filter " } ,
{ " Output ASRC0 Mux " , NULL , " Output ASRC Supply " } ,
{ " Output ASRC1 Mux " , NULL , " Output ASRC Supply " } ,
{ " Output ASRC2 Mux " , NULL , " Output ASRC Supply " } ,
{ " Output ASRC3 Mux " , NULL , " Output ASRC Supply " } ,
{ " Output ASRC0 Mux " , NULL , " Output ASRC0 Decimator " } ,
{ " Output ASRC1 Mux " , NULL , " Output ASRC1 Decimator " } ,
{ " Output ASRC2 Mux " , NULL , " Output ASRC2 Decimator " } ,
{ " Output ASRC3 Mux " , NULL , " Output ASRC3 Decimator " } ,
ADAU1372_ASRCO_ROUTES ( 0 ) ,
ADAU1372_ASRCO_ROUTES ( 1 ) ,
ADAU1372_ASRCO_ROUTES ( 2 ) ,
ADAU1372_ASRCO_ROUTES ( 3 ) ,
ADAU1372_SOUT_ROUTES ( 0 ) ,
ADAU1372_SOUT_ROUTES ( 1 ) ,
ADAU1372_SOUT_ROUTES ( 2 ) ,
ADAU1372_SOUT_ROUTES ( 3 ) ,
ADAU1372_SOUT_ROUTES ( 4 ) ,
ADAU1372_SOUT_ROUTES ( 5 ) ,
ADAU1372_SOUT_ROUTES ( 6 ) ,
ADAU1372_SOUT_ROUTES ( 7 ) ,
{ " Serial Input 0 " , NULL , " Playback " } ,
{ " Serial Input 1 " , NULL , " Playback " } ,
{ " Serial Input 2 " , NULL , " Playback " } ,
{ " Serial Input 3 " , NULL , " Playback " } ,
{ " Serial Input 4 " , NULL , " Playback " } ,
{ " Serial Input 5 " , NULL , " Playback " } ,
{ " Serial Input 6 " , NULL , " Playback " } ,
{ " Serial Input 7 " , NULL , " Playback " } ,
{ " Input ASRC0 Mux " , " Serial Input 0+1 " , " Serial Input 0 " } ,
{ " Input ASRC1 Mux " , " Serial Input 0+1 " , " Serial Input 1 " } ,
{ " Input ASRC0 Mux " , " Serial Input 2+3 " , " Serial Input 2 " } ,
{ " Input ASRC1 Mux " , " Serial Input 2+3 " , " Serial Input 3 " } ,
{ " Input ASRC0 Mux " , " Serial Input 4+5 " , " Serial Input 4 " } ,
{ " Input ASRC1 Mux " , " Serial Input 4+5 " , " Serial Input 5 " } ,
{ " Input ASRC0 Mux " , " Serial Input 6+7 " , " Serial Input 6 " } ,
{ " Input ASRC1 Mux " , " Serial Input 6+7 " , " Serial Input 7 " } ,
{ " Input ASRC0 Mux " , NULL , " Input ASRC Supply " } ,
{ " Input ASRC1 Mux " , NULL , " Input ASRC Supply " } ,
{ " Input ASRC0 Mux " , NULL , " Input ASRC0 Interpolator " } ,
{ " Input ASRC1 Mux " , NULL , " Input ASRC1 Interpolator " } ,
{ " DAC 0 Mux " , " Input ASRC0 " , " Input ASRC0 Mux " } ,
{ " DAC 0 Mux " , " Input ASRC1 " , " Input ASRC1 Mux " } ,
{ " DAC 1 Mux " , " Input ASRC0 " , " Input ASRC0 Mux " } ,
{ " DAC 1 Mux " , " Input ASRC1 " , " Input ASRC1 Mux " } ,
{ " DAC0 " , NULL , " DAC 0 Mux " } ,
{ " DAC1 " , NULL , " DAC 1 Mux " } ,
{ " DAC0 " , NULL , " DAC0 Modulator " } ,
{ " DAC1 " , NULL , " DAC1 Modulator " } ,
{ " OP_STAGE_LP " , NULL , " DAC0 " } ,
{ " OP_STAGE_LN " , NULL , " DAC0 " } ,
{ " OP_STAGE_RP " , NULL , " DAC1 " } ,
{ " OP_STAGE_RN " , NULL , " DAC1 " } ,
{ " HPOUTL " , NULL , " OP_STAGE_LP " } ,
{ " HPOUTL " , NULL , " OP_STAGE_LN " } ,
{ " HPOUTR " , NULL , " OP_STAGE_RP " } ,
{ " HPOUTR " , NULL , " OP_STAGE_RN " } ,
} ;
static int adau1372_set_dai_fmt ( struct snd_soc_dai * dai , unsigned int fmt )
{
struct adau1372 * adau1372 = snd_soc_dai_get_drvdata ( dai ) ;
unsigned int sai0 = 0 , sai1 = 0 ;
bool invert_lrclk = false ;
2021-09-16 16:18:01 +01:00
switch ( fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK ) {
case SND_SOC_DAIFMT_CBP_CFP :
adau1372 - > clock_provider = true ;
2020-11-27 13:30:30 +01:00
sai1 | = ADAU1372_SAI1_MS ;
break ;
2021-09-16 16:18:01 +01:00
case SND_SOC_DAIFMT_CBC_CFC :
adau1372 - > clock_provider = false ;
2020-11-27 13:30:30 +01:00
break ;
default :
return - EINVAL ;
}
switch ( fmt & SND_SOC_DAIFMT_INV_MASK ) {
case SND_SOC_DAIFMT_NB_NF :
invert_lrclk = false ;
break ;
case SND_SOC_DAIFMT_NB_IF :
invert_lrclk = true ;
break ;
case SND_SOC_DAIFMT_IB_NF :
invert_lrclk = false ;
sai1 | = ADAU1372_SAI1_BCLKEDGE ;
break ;
case SND_SOC_DAIFMT_IB_IF :
invert_lrclk = true ;
sai1 | = ADAU1372_SAI1_BCLKEDGE ;
break ;
}
switch ( fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
case SND_SOC_DAIFMT_I2S :
sai0 | = ADAU1372_SAI0_DELAY1 ;
break ;
case SND_SOC_DAIFMT_LEFT_J :
sai0 | = ADAU1372_SAI0_DELAY0 ;
invert_lrclk = ! invert_lrclk ;
break ;
case SND_SOC_DAIFMT_DSP_A :
sai0 | = ADAU1372_SAI0_DELAY1 ;
sai1 | = ADAU1372_SAI1_LR_MODE ;
break ;
case SND_SOC_DAIFMT_DSP_B :
sai0 | = ADAU1372_SAI0_DELAY0 ;
sai1 | = ADAU1372_SAI1_LR_MODE ;
break ;
}
if ( invert_lrclk )
sai1 | = ADAU1372_SAI1_LR_POL ;
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI0 , ADAU1372_SAI0_DELAY_MASK , sai0 ) ;
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI1 ,
ADAU1372_SAI1_MS | ADAU1372_SAI1_BCLKEDGE |
ADAU1372_SAI1_LR_MODE | ADAU1372_SAI1_LR_POL , sai1 ) ;
return 0 ;
}
static int adau1372_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params , struct snd_soc_dai * dai )
{
struct adau1372 * adau1372 = snd_soc_dai_get_drvdata ( dai ) ;
unsigned int rate = params_rate ( params ) ;
unsigned int slot_width ;
unsigned int sai0 , sai1 ;
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( adau1372_rates ) ; i + + ) {
if ( rate = = adau1372_rates [ i ] )
break ;
}
if ( i = = ARRAY_SIZE ( adau1372_rates ) )
return - EINVAL ;
sai0 = i ;
slot_width = adau1372 - > slot_width ;
if ( slot_width = = 0 )
slot_width = params_width ( params ) ;
switch ( slot_width ) {
case 16 :
sai1 = ADAU1372_SAI1_BCLKRATE ;
break ;
2022-10-28 17:26:24 +02:00
case 24 :
2020-11-27 13:30:30 +01:00
case 32 :
sai1 = 0 ;
break ;
default :
return - EINVAL ;
}
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI0 , ADAU1372_SAI0_FS_MASK , sai0 ) ;
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI1 , ADAU1372_SAI1_BCLKRATE , sai1 ) ;
return 0 ;
}
static int adau1372_set_tdm_slot ( struct snd_soc_dai * dai , unsigned int tx_mask ,
unsigned int rx_mask , int slots , int width )
{
struct adau1372 * adau1372 = snd_soc_dai_get_drvdata ( dai ) ;
unsigned int sai0 , sai1 ;
/* I2S mode */
if ( slots = = 0 ) {
/* The other settings dont matter in I2S mode */
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI0 ,
ADAU1372_SAI0_SAI_MASK , ADAU1372_SAI0_SAI_I2S ) ;
adau1372 - > rate_constraints . mask = ADAU1372_RATE_MASK_TDM2 ;
adau1372 - > slot_width = 0 ;
return 0 ;
}
/* We have 8 channels anything outside that is not supported */
if ( ( tx_mask & ~ 0xff ) ! = 0 | | ( rx_mask & ~ 0xff ) ! = 0 )
return - EINVAL ;
switch ( width ) {
case 16 :
sai1 = ADAU1372_SAI1_BCLK_TDMC ;
break ;
2022-10-28 17:26:24 +02:00
case 24 :
2020-11-27 13:30:30 +01:00
case 32 :
sai1 = 0 ;
break ;
default :
return - EINVAL ;
}
switch ( slots ) {
case 2 :
sai0 = ADAU1372_SAI0_SAI_TDM2 ;
adau1372 - > rate_constraints . mask = ADAU1372_RATE_MASK_TDM2 ;
break ;
case 4 :
sai0 = ADAU1372_SAI0_SAI_TDM4 ;
2021-09-16 16:18:01 +01:00
if ( adau1372 - > clock_provider )
2020-11-27 13:30:30 +01:00
adau1372 - > rate_constraints . mask = ADAU1372_RATE_MASK_TDM4_MASTER ;
else
adau1372 - > rate_constraints . mask = ADAU1372_RATE_MASK_TDM4 ;
break ;
case 8 :
sai0 = ADAU1372_SAI0_SAI_TDM8 ;
adau1372 - > rate_constraints . mask = ADAU1372_RATE_MASK_TDM8 ;
break ;
default :
return - EINVAL ;
}
adau1372 - > slot_width = width ;
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI0 , ADAU1372_SAI0_SAI_MASK , sai0 ) ;
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI1 , ADAU1372_SAI1_BCLK_TDMC , sai1 ) ;
/* Mask is inverted in hardware */
regmap_write ( adau1372 - > regmap , ADAU1372_REG_SOUT_CTRL , ~ tx_mask ) ;
return 0 ;
}
static int adau1372_set_tristate ( struct snd_soc_dai * dai , int tristate )
{
struct adau1372 * adau1372 = snd_soc_dai_get_drvdata ( dai ) ;
unsigned int sai1 ;
if ( tristate )
sai1 = ADAU1372_SAI1_TDM_TS ;
else
sai1 = 0 ;
return regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_SAI1 , ADAU1372_SAI1_TDM_TS , sai1 ) ;
}
static int adau1372_startup ( struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
{
struct adau1372 * adau1372 = snd_soc_dai_get_drvdata ( dai ) ;
snd_pcm_hw_constraint_list ( substream - > runtime , 0 , SNDRV_PCM_HW_PARAM_RATE ,
& adau1372 - > rate_constraints ) ;
return 0 ;
}
static void adau1372_enable_pll ( struct adau1372 * adau1372 )
{
unsigned int val , timeout = 0 ;
int ret ;
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_CLK_CTRL ,
ADAU1372_CLK_CTRL_PLL_EN , ADAU1372_CLK_CTRL_PLL_EN ) ;
do {
/* Takes about 1ms to lock */
usleep_range ( 1000 , 2000 ) ;
ret = regmap_read ( adau1372 - > regmap , ADAU1372_REG_PLL ( 5 ) , & val ) ;
if ( ret )
break ;
timeout + + ;
} while ( ! ( val & 1 ) & & timeout < 3 ) ;
if ( ret < 0 | | ! ( val & 1 ) )
dev_err ( adau1372 - > dev , " Failed to lock PLL \n " ) ;
}
static void adau1372_set_power ( struct adau1372 * adau1372 , bool enable )
{
if ( adau1372 - > enabled = = enable )
return ;
if ( enable ) {
unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN ;
clk_prepare_enable ( adau1372 - > mclk ) ;
if ( adau1372 - > pd_gpio )
gpiod_set_value ( adau1372 - > pd_gpio , 0 ) ;
if ( adau1372 - > switch_mode )
adau1372 - > switch_mode ( adau1372 - > dev ) ;
regcache_cache_only ( adau1372 - > regmap , false ) ;
/*
* Clocks needs to be enabled before any other register can be
* accessed .
*/
if ( adau1372 - > use_pll ) {
adau1372_enable_pll ( adau1372 ) ;
clk_ctrl | = ADAU1372_CLK_CTRL_CLKSRC ;
}
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_CLK_CTRL ,
ADAU1372_CLK_CTRL_MCLK_EN | ADAU1372_CLK_CTRL_CLKSRC , clk_ctrl ) ;
regcache_sync ( adau1372 - > regmap ) ;
} else {
if ( adau1372 - > pd_gpio ) {
/*
* This will turn everything off and reset the register
* map . No need to do any register writes to manually
* turn things off .
*/
gpiod_set_value ( adau1372 - > pd_gpio , 1 ) ;
regcache_mark_dirty ( adau1372 - > regmap ) ;
} else {
regmap_update_bits ( adau1372 - > regmap , ADAU1372_REG_CLK_CTRL ,
ADAU1372_CLK_CTRL_MCLK_EN | ADAU1372_CLK_CTRL_PLL_EN , 0 ) ;
}
clk_disable_unprepare ( adau1372 - > mclk ) ;
regcache_cache_only ( adau1372 - > regmap , true ) ;
}
adau1372 - > enabled = enable ;
}
static int adau1372_set_bias_level ( struct snd_soc_component * component ,
enum snd_soc_bias_level level )
{
struct adau1372 * adau1372 = snd_soc_component_get_drvdata ( component ) ;
switch ( level ) {
case SND_SOC_BIAS_ON :
break ;
case SND_SOC_BIAS_PREPARE :
break ;
case SND_SOC_BIAS_STANDBY :
adau1372_set_power ( adau1372 , true ) ;
break ;
case SND_SOC_BIAS_OFF :
adau1372_set_power ( adau1372 , false ) ;
break ;
}
return 0 ;
}
static const struct snd_soc_component_driver adau1372_driver = {
. set_bias_level = adau1372_set_bias_level ,
. controls = adau1372_controls ,
. num_controls = ARRAY_SIZE ( adau1372_controls ) ,
. dapm_widgets = adau1372_dapm_widgets ,
. num_dapm_widgets = ARRAY_SIZE ( adau1372_dapm_widgets ) ,
. dapm_routes = adau1372_dapm_routes ,
. num_dapm_routes = ARRAY_SIZE ( adau1372_dapm_routes ) ,
2022-05-04 18:08:39 +01:00
. endianness = 1 ,
2020-11-27 13:30:30 +01:00
} ;
static const struct snd_soc_dai_ops adau1372_dai_ops = {
. set_fmt = adau1372_set_dai_fmt ,
. set_tdm_slot = adau1372_set_tdm_slot ,
. set_tristate = adau1372_set_tristate ,
. hw_params = adau1372_hw_params ,
. startup = adau1372_startup ,
} ;
2022-10-28 17:26:24 +02:00
# define ADAU1372_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE )
2020-11-27 13:30:30 +01:00
static struct snd_soc_dai_driver adau1372_dai_driver = {
. name = " adau1372 " ,
. playback = {
. stream_name = " Playback " ,
. channels_min = 2 ,
. channels_max = 8 ,
. rates = SNDRV_PCM_RATE_KNOT ,
. formats = ADAU1372_FORMATS ,
. sig_bits = 24 ,
} ,
. capture = {
. stream_name = " Capture " ,
. channels_min = 2 ,
. channels_max = 8 ,
. rates = SNDRV_PCM_RATE_KNOT ,
. formats = ADAU1372_FORMATS ,
. sig_bits = 24 ,
} ,
. ops = & adau1372_dai_ops ,
2021-01-15 13:55:01 +09:00
. symmetric_rate = 1 ,
2020-11-27 13:30:30 +01:00
} ;
static int adau1372_setup_pll ( struct adau1372 * adau1372 , unsigned int rate )
{
u8 regs [ 5 ] ;
unsigned int i ;
int ret ;
ret = adau_calc_pll_cfg ( rate , 49152000 , regs ) ;
if ( ret < 0 )
return ret ;
for ( i = 0 ; i < ARRAY_SIZE ( regs ) ; i + + )
regmap_write ( adau1372 - > regmap , ADAU1372_REG_PLL ( i ) , regs [ i ] ) ;
return 0 ;
}
int adau1372_probe ( struct device * dev , struct regmap * regmap ,
void ( * switch_mode ) ( struct device * dev ) )
{
struct adau1372 * adau1372 ;
unsigned int clk_ctrl ;
unsigned long rate ;
int ret ;
if ( IS_ERR ( regmap ) )
return PTR_ERR ( regmap ) ;
adau1372 = devm_kzalloc ( dev , sizeof ( * adau1372 ) , GFP_KERNEL ) ;
if ( ! adau1372 )
return - ENOMEM ;
2022-10-28 17:26:23 +02:00
adau1372 - > mclk = devm_clk_get ( dev , " mclk " ) ;
if ( IS_ERR ( adau1372 - > mclk ) )
return PTR_ERR ( adau1372 - > mclk ) ;
2020-11-27 13:30:30 +01:00
adau1372 - > pd_gpio = devm_gpiod_get_optional ( dev , " powerdown " , GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( adau1372 - > pd_gpio ) )
return PTR_ERR ( adau1372 - > pd_gpio ) ;
adau1372 - > regmap = regmap ;
adau1372 - > switch_mode = switch_mode ;
adau1372 - > dev = dev ;
adau1372 - > rate_constraints . list = adau1372_rates ;
adau1372 - > rate_constraints . count = ARRAY_SIZE ( adau1372_rates ) ;
adau1372 - > rate_constraints . mask = ADAU1372_RATE_MASK_TDM2 ;
dev_set_drvdata ( dev , adau1372 ) ;
/*
* The datasheet says that the internal MCLK always needs to run at
* 12.288 MHz . Automatically choose a valid configuration from the
* external clock .
*/
2022-10-28 17:26:23 +02:00
rate = clk_get_rate ( adau1372 - > mclk ) ;
2020-11-27 13:30:30 +01:00
switch ( rate ) {
case 12288000 :
clk_ctrl = ADAU1372_CLK_CTRL_CC_MDIV ;
break ;
case 24576000 :
clk_ctrl = 0 ;
break ;
default :
clk_ctrl = 0 ;
ret = adau1372_setup_pll ( adau1372 , rate ) ;
if ( ret < 0 )
return ret ;
adau1372 - > use_pll = true ;
break ;
}
/*
* Most of the registers are inaccessible unless the internal clock is
* enabled .
*/
regcache_cache_only ( regmap , true ) ;
regmap_update_bits ( regmap , ADAU1372_REG_CLK_CTRL , ADAU1372_CLK_CTRL_CC_MDIV , clk_ctrl ) ;
/*
* No pinctrl support yet , put the multi - purpose pins in the most
* sensible mode for general purpose CODEC operation .
*/
regmap_write ( regmap , ADAU1372_REG_MODE_MP ( 1 ) , 0x00 ) ; /* SDATA OUT */
regmap_write ( regmap , ADAU1372_REG_MODE_MP ( 6 ) , 0x12 ) ; /* CLOCKOUT */
regmap_write ( regmap , ADAU1372_REG_OP_STAGE_MUTE , 0x0 ) ;
regmap_write ( regmap , 0x7 , 0x01 ) ; /* CLOCK OUT */
return devm_snd_soc_register_component ( dev , & adau1372_driver , & adau1372_dai_driver , 1 ) ;
}
EXPORT_SYMBOL ( adau1372_probe ) ;
static const struct reg_default adau1372_reg_defaults [ ] = {
{ ADAU1372_REG_CLK_CTRL , 0x00 } ,
{ ADAU1372_REG_PLL ( 0 ) , 0x00 } ,
{ ADAU1372_REG_PLL ( 1 ) , 0x00 } ,
{ ADAU1372_REG_PLL ( 2 ) , 0x00 } ,
{ ADAU1372_REG_PLL ( 3 ) , 0x00 } ,
{ ADAU1372_REG_PLL ( 4 ) , 0x00 } ,
{ ADAU1372_REG_PLL ( 5 ) , 0x00 } ,
{ ADAU1372_REG_DAC_SOURCE , 0x10 } ,
{ ADAU1372_REG_SOUT_SOURCE_0_1 , 0x54 } ,
{ ADAU1372_REG_SOUT_SOURCE_2_3 , 0x76 } ,
{ ADAU1372_REG_SOUT_SOURCE_4_5 , 0x54 } ,
{ ADAU1372_REG_SOUT_SOURCE_6_7 , 0x76 } ,
{ ADAU1372_REG_ADC_SDATA_CH , 0x04 } ,
{ ADAU1372_REG_ASRCO_SOURCE_0_1 , 0x10 } ,
{ ADAU1372_REG_ASRCO_SOURCE_2_3 , 0x32 } ,
{ ADAU1372_REG_ASRC_MODE , 0x00 } ,
{ ADAU1372_REG_ADC_CTRL0 , 0x19 } ,
{ ADAU1372_REG_ADC_CTRL1 , 0x19 } ,
{ ADAU1372_REG_ADC_CTRL2 , 0x00 } ,
{ ADAU1372_REG_ADC_CTRL3 , 0x00 } ,
{ ADAU1372_REG_ADC_VOL ( 0 ) , 0x00 } ,
{ ADAU1372_REG_ADC_VOL ( 1 ) , 0x00 } ,
{ ADAU1372_REG_ADC_VOL ( 2 ) , 0x00 } ,
{ ADAU1372_REG_ADC_VOL ( 3 ) , 0x00 } ,
{ ADAU1372_REG_PGA_CTRL ( 0 ) , 0x40 } ,
{ ADAU1372_REG_PGA_CTRL ( 1 ) , 0x40 } ,
{ ADAU1372_REG_PGA_CTRL ( 2 ) , 0x40 } ,
{ ADAU1372_REG_PGA_CTRL ( 3 ) , 0x40 } ,
{ ADAU1372_REG_PGA_BOOST , 0x00 } ,
{ ADAU1372_REG_MICBIAS , 0x00 } ,
{ ADAU1372_REG_DAC_CTRL , 0x18 } ,
{ ADAU1372_REG_DAC_VOL ( 0 ) , 0x00 } ,
{ ADAU1372_REG_DAC_VOL ( 1 ) , 0x00 } ,
{ ADAU1372_REG_OP_STAGE_MUTE , 0x0f } ,
{ ADAU1372_REG_SAI0 , 0x00 } ,
{ ADAU1372_REG_SAI1 , 0x00 } ,
{ ADAU1372_REG_SOUT_CTRL , 0x00 } ,
{ ADAU1372_REG_MODE_MP ( 0 ) , 0x00 } ,
{ ADAU1372_REG_MODE_MP ( 1 ) , 0x10 } ,
{ ADAU1372_REG_MODE_MP ( 4 ) , 0x00 } ,
{ ADAU1372_REG_MODE_MP ( 5 ) , 0x00 } ,
{ ADAU1372_REG_MODE_MP ( 6 ) , 0x11 } ,
{ ADAU1372_REG_OP_STAGE_CTRL , 0x0f } ,
{ ADAU1372_REG_DECIM_PWR , 0x00 } ,
{ ADAU1372_REG_INTERP_PWR , 0x00 } ,
{ ADAU1372_REG_BIAS_CTRL0 , 0x00 } ,
{ ADAU1372_REG_BIAS_CTRL1 , 0x00 } ,
} ;
static bool adau1372_volatile_register ( struct device * dev , unsigned int reg )
{
if ( reg = = ADAU1372_REG_PLL ( 5 ) )
return true ;
return false ;
}
const struct regmap_config adau1372_regmap_config = {
. val_bits = 8 ,
. reg_bits = 16 ,
. max_register = 0x4d ,
. reg_defaults = adau1372_reg_defaults ,
. num_reg_defaults = ARRAY_SIZE ( adau1372_reg_defaults ) ,
. volatile_reg = adau1372_volatile_register ,
2023-07-13 00:13:52 +01:00
. cache_type = REGCACHE_MAPLE ,
2020-11-27 13:30:30 +01:00
} ;
EXPORT_SYMBOL_GPL ( adau1372_regmap_config ) ;
MODULE_DESCRIPTION ( " ASoC ADAU1372 CODEC driver " ) ;
MODULE_AUTHOR ( " Lars-Peter Clausen <lars@metafoo.de> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;