2019-05-27 09:55:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2013-02-14 16:02:51 +04:00
/*
* DA7213 ALSA SoC Codec Driver
*
* Copyright ( c ) 2013 Dialog Semiconductor
*
* Author : Adam Thomson < Adam . Thomson . Opensource @ diasemi . com >
* Based on DA9055 ALSA SoC codec driver .
*/
2017-03-10 03:18:58 +03:00
# include <linux/acpi.h>
2017-05-19 17:32:25 +03:00
# include <linux/of_device.h>
# include <linux/property.h>
2015-10-07 16:27:11 +03:00
# include <linux/clk.h>
2013-02-14 16:02:51 +04:00
# include <linux/delay.h>
# include <linux/i2c.h>
# include <linux/regmap.h>
# include <linux/slab.h>
# include <linux/module.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
2020-05-11 16:25:41 +03:00
# include <linux/pm_runtime.h>
2013-02-14 16:02:51 +04:00
# include <sound/soc.h>
# include <sound/initval.h>
# include <sound/tlv.h>
# include <sound/da7213.h>
# include "da7213.h"
/* Gain and Volume */
2015-08-02 18:19:38 +03:00
static const DECLARE_TLV_DB_RANGE ( aux_vol_tlv ,
2013-02-14 16:02:51 +04:00
/* -54dB */
0x0 , 0x11 , TLV_DB_SCALE_ITEM ( - 5400 , 0 , 0 ) ,
/* -52.5dB to 15dB */
0x12 , 0x3f , TLV_DB_SCALE_ITEM ( - 5250 , 150 , 0 )
2015-08-02 18:19:38 +03:00
) ;
2013-02-14 16:02:51 +04:00
2015-08-02 18:19:38 +03:00
static const DECLARE_TLV_DB_RANGE ( digital_gain_tlv ,
2013-02-14 16:02:51 +04:00
0x0 , 0x07 , TLV_DB_SCALE_ITEM ( TLV_DB_GAIN_MUTE , 0 , 1 ) ,
/* -78dB to 12dB */
0x08 , 0x7f , TLV_DB_SCALE_ITEM ( - 7800 , 75 , 0 )
2015-08-02 18:19:38 +03:00
) ;
2013-02-14 16:02:51 +04:00
2015-08-02 18:19:38 +03:00
static const DECLARE_TLV_DB_RANGE ( alc_analog_gain_tlv ,
2013-02-14 16:02:51 +04:00
0x0 , 0x0 , TLV_DB_SCALE_ITEM ( TLV_DB_GAIN_MUTE , 0 , 1 ) ,
/* 0dB to 36dB */
0x01 , 0x07 , TLV_DB_SCALE_ITEM ( 0 , 600 , 0 )
2015-08-02 18:19:38 +03:00
) ;
2013-02-14 16:02:51 +04:00
static const DECLARE_TLV_DB_SCALE ( mic_vol_tlv , - 600 , 600 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( mixin_gain_tlv , - 450 , 150 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( eq_gain_tlv , - 1050 , 150 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( hp_vol_tlv , - 5700 , 100 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( lineout_vol_tlv , - 4800 , 100 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( alc_threshold_tlv , - 9450 , 150 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( alc_gain_tlv , 0 , 600 , 0 ) ;
/* ADC and DAC voice mode (8kHz) high pass cutoff value */
static const char * const da7213_voice_hpf_corner_txt [ ] = {
" 2.5Hz " , " 25Hz " , " 50Hz " , " 100Hz " , " 150Hz " , " 200Hz " , " 300Hz " , " 400Hz "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_voice_hpf_corner ,
DA7213_DAC_FILTERS1 ,
DA7213_VOICE_HPF_CORNER_SHIFT ,
da7213_voice_hpf_corner_txt ) ;
2013-02-14 16:02:51 +04:00
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_adc_voice_hpf_corner ,
DA7213_ADC_FILTERS1 ,
DA7213_VOICE_HPF_CORNER_SHIFT ,
da7213_voice_hpf_corner_txt ) ;
2013-02-14 16:02:51 +04:00
/* ADC and DAC high pass filter cutoff value */
static const char * const da7213_audio_hpf_corner_txt [ ] = {
" Fs/24000 " , " Fs/12000 " , " Fs/6000 " , " Fs/3000 "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_audio_hpf_corner ,
DA7213_DAC_FILTERS1
, DA7213_AUDIO_HPF_CORNER_SHIFT ,
da7213_audio_hpf_corner_txt ) ;
2013-02-14 16:02:51 +04:00
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_adc_audio_hpf_corner ,
DA7213_ADC_FILTERS1 ,
DA7213_AUDIO_HPF_CORNER_SHIFT ,
da7213_audio_hpf_corner_txt ) ;
2013-02-14 16:02:51 +04:00
/* Gain ramping rate value */
static const char * const da7213_gain_ramp_rate_txt [ ] = {
" nominal rate * 8 " , " nominal rate * 16 " , " nominal rate / 16 " ,
" nominal rate / 32 "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_gain_ramp_rate ,
DA7213_GAIN_RAMP_CTRL ,
DA7213_GAIN_RAMP_RATE_SHIFT ,
da7213_gain_ramp_rate_txt ) ;
2013-02-14 16:02:51 +04:00
/* DAC noise gate setup time value */
static const char * const da7213_dac_ng_setup_time_txt [ ] = {
" 256 samples " , " 512 samples " , " 1024 samples " , " 2048 samples "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_ng_setup_time ,
DA7213_DAC_NG_SETUP_TIME ,
DA7213_DAC_NG_SETUP_TIME_SHIFT ,
da7213_dac_ng_setup_time_txt ) ;
2013-02-14 16:02:51 +04:00
/* DAC noise gate rampup rate value */
static const char * const da7213_dac_ng_rampup_txt [ ] = {
" 0.02 ms/dB " , " 0.16 ms/dB "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_ng_rampup_rate ,
DA7213_DAC_NG_SETUP_TIME ,
DA7213_DAC_NG_RAMPUP_RATE_SHIFT ,
da7213_dac_ng_rampup_txt ) ;
2013-02-14 16:02:51 +04:00
/* DAC noise gate rampdown rate value */
static const char * const da7213_dac_ng_rampdown_txt [ ] = {
" 0.64 ms/dB " , " 20.48 ms/dB "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_ng_rampdown_rate ,
DA7213_DAC_NG_SETUP_TIME ,
DA7213_DAC_NG_RAMPDN_RATE_SHIFT ,
da7213_dac_ng_rampdown_txt ) ;
2013-02-14 16:02:51 +04:00
/* DAC soft mute rate value */
static const char * const da7213_dac_soft_mute_rate_txt [ ] = {
" 1 " , " 2 " , " 4 " , " 8 " , " 16 " , " 32 " , " 64 "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_soft_mute_rate ,
DA7213_DAC_FILTERS5 ,
DA7213_DAC_SOFTMUTE_RATE_SHIFT ,
da7213_dac_soft_mute_rate_txt ) ;
2013-02-14 16:02:51 +04:00
/* ALC Attack Rate select */
static const char * const da7213_alc_attack_rate_txt [ ] = {
" 44/fs " , " 88/fs " , " 176/fs " , " 352/fs " , " 704/fs " , " 1408/fs " , " 2816/fs " ,
" 5632/fs " , " 11264/fs " , " 22528/fs " , " 45056/fs " , " 90112/fs " , " 180224/fs "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_alc_attack_rate ,
DA7213_ALC_CTRL2 ,
DA7213_ALC_ATTACK_SHIFT ,
da7213_alc_attack_rate_txt ) ;
2013-02-14 16:02:51 +04:00
/* ALC Release Rate select */
static const char * const da7213_alc_release_rate_txt [ ] = {
" 176/fs " , " 352/fs " , " 704/fs " , " 1408/fs " , " 2816/fs " , " 5632/fs " ,
" 11264/fs " , " 22528/fs " , " 45056/fs " , " 90112/fs " , " 180224/fs "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_alc_release_rate ,
DA7213_ALC_CTRL2 ,
DA7213_ALC_RELEASE_SHIFT ,
da7213_alc_release_rate_txt ) ;
2013-02-14 16:02:51 +04:00
/* ALC Hold Time select */
static const char * const da7213_alc_hold_time_txt [ ] = {
" 62/fs " , " 124/fs " , " 248/fs " , " 496/fs " , " 992/fs " , " 1984/fs " , " 3968/fs " ,
" 7936/fs " , " 15872/fs " , " 31744/fs " , " 63488/fs " , " 126976/fs " ,
" 253952/fs " , " 507904/fs " , " 1015808/fs " , " 2031616/fs "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_alc_hold_time ,
DA7213_ALC_CTRL3 ,
DA7213_ALC_HOLD_SHIFT ,
da7213_alc_hold_time_txt ) ;
2013-02-14 16:02:51 +04:00
/* ALC Input Signal Tracking rate select */
static const char * const da7213_alc_integ_rate_txt [ ] = {
" 1/4 " , " 1/16 " , " 1/256 " , " 1/65536 "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_alc_integ_attack_rate ,
DA7213_ALC_CTRL3 ,
DA7213_ALC_INTEG_ATTACK_SHIFT ,
da7213_alc_integ_rate_txt ) ;
2013-02-14 16:02:51 +04:00
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_alc_integ_release_rate ,
DA7213_ALC_CTRL3 ,
DA7213_ALC_INTEG_RELEASE_SHIFT ,
da7213_alc_integ_rate_txt ) ;
2013-02-14 16:02:51 +04:00
/*
* Control Functions
*/
2018-01-29 07:03:13 +03:00
static int da7213_get_alc_data ( struct snd_soc_component * component , u8 reg_val )
2013-02-14 16:02:51 +04:00
{
int mid_data , top_data ;
int sum = 0 ;
u8 iteration ;
for ( iteration = 0 ; iteration < DA7213_ALC_AVG_ITERATIONS ;
iteration + + ) {
/* Select the left or right channel and capture data */
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ALC_CIC_OP_LVL_CTRL , reg_val ) ;
2013-02-14 16:02:51 +04:00
/* Select middle 8 bits for read back from data register */
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ALC_CIC_OP_LVL_CTRL ,
2013-02-14 16:02:51 +04:00
reg_val | DA7213_ALC_DATA_MIDDLE ) ;
2020-06-16 08:21:42 +03:00
mid_data = snd_soc_component_read ( component , DA7213_ALC_CIC_OP_LVL_DATA ) ;
2013-02-14 16:02:51 +04:00
/* Select top 8 bits for read back from data register */
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ALC_CIC_OP_LVL_CTRL ,
2013-02-14 16:02:51 +04:00
reg_val | DA7213_ALC_DATA_TOP ) ;
2020-06-16 08:21:42 +03:00
top_data = snd_soc_component_read ( component , DA7213_ALC_CIC_OP_LVL_DATA ) ;
2013-02-14 16:02:51 +04:00
sum + = ( ( mid_data < < 8 ) | ( top_data < < 16 ) ) ;
}
return sum / DA7213_ALC_AVG_ITERATIONS ;
}
2018-01-29 07:03:13 +03:00
static void da7213_alc_calib_man ( struct snd_soc_component * component )
2013-02-14 16:02:51 +04:00
{
u8 reg_val ;
int avg_left_data , avg_right_data , offset_l , offset_r ;
/* Calculate average for Left and Right data */
/* Left Data */
2018-01-29 07:03:13 +03:00
avg_left_data = da7213_get_alc_data ( component ,
2013-02-14 16:02:51 +04:00
DA7213_ALC_CIC_OP_CHANNEL_LEFT ) ;
/* Right Data */
2018-01-29 07:03:13 +03:00
avg_right_data = da7213_get_alc_data ( component ,
2013-02-14 16:02:51 +04:00
DA7213_ALC_CIC_OP_CHANNEL_RIGHT ) ;
/* Calculate DC offset */
offset_l = - avg_left_data ;
offset_r = - avg_right_data ;
reg_val = ( offset_l & DA7213_ALC_OFFSET_15_8 ) > > 8 ;
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ALC_OFFSET_MAN_M_L , reg_val ) ;
2013-02-14 16:02:51 +04:00
reg_val = ( offset_l & DA7213_ALC_OFFSET_19_16 ) > > 16 ;
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ALC_OFFSET_MAN_U_L , reg_val ) ;
2013-02-14 16:02:51 +04:00
reg_val = ( offset_r & DA7213_ALC_OFFSET_15_8 ) > > 8 ;
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ALC_OFFSET_MAN_M_R , reg_val ) ;
2013-02-14 16:02:51 +04:00
reg_val = ( offset_r & DA7213_ALC_OFFSET_19_16 ) > > 16 ;
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ALC_OFFSET_MAN_U_R , reg_val ) ;
2013-02-14 16:02:51 +04:00
/* Enable analog/digital gain mode & offset cancellation */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ALC_CTRL1 ,
2013-02-14 16:02:51 +04:00
DA7213_ALC_OFFSET_EN | DA7213_ALC_SYNC_MODE ,
DA7213_ALC_OFFSET_EN | DA7213_ALC_SYNC_MODE ) ;
}
2018-01-29 07:03:13 +03:00
static void da7213_alc_calib_auto ( struct snd_soc_component * component )
2013-02-14 16:02:51 +04:00
{
u8 alc_ctrl1 ;
/* Begin auto calibration and wait for completion */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ALC_CTRL1 , DA7213_ALC_AUTO_CALIB_EN ,
2013-02-14 16:02:51 +04:00
DA7213_ALC_AUTO_CALIB_EN ) ;
do {
2020-06-16 08:21:42 +03:00
alc_ctrl1 = snd_soc_component_read ( component , DA7213_ALC_CTRL1 ) ;
2013-02-14 16:02:51 +04:00
} while ( alc_ctrl1 & DA7213_ALC_AUTO_CALIB_EN ) ;
/* If auto calibration fails, fall back to digital gain only mode */
if ( alc_ctrl1 & DA7213_ALC_CALIB_OVERFLOW ) {
2018-01-29 07:03:13 +03:00
dev_warn ( component - > dev ,
2013-02-14 16:02:51 +04:00
" ALC auto calibration failed with overflow \n " ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ALC_CTRL1 ,
2013-02-14 16:02:51 +04:00
DA7213_ALC_OFFSET_EN | DA7213_ALC_SYNC_MODE ,
0 ) ;
} else {
/* Enable analog/digital gain mode & offset cancellation */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ALC_CTRL1 ,
2013-02-14 16:02:51 +04:00
DA7213_ALC_OFFSET_EN | DA7213_ALC_SYNC_MODE ,
DA7213_ALC_OFFSET_EN | DA7213_ALC_SYNC_MODE ) ;
}
}
2018-01-29 07:03:13 +03:00
static void da7213_alc_calib ( struct snd_soc_component * component )
2013-02-14 16:02:51 +04:00
{
2018-01-29 07:03:13 +03:00
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2013-02-14 16:02:51 +04:00
u8 adc_l_ctrl , adc_r_ctrl ;
u8 mixin_l_sel , mixin_r_sel ;
u8 mic_1_ctrl , mic_2_ctrl ;
/* Save current values from ADC control registers */
2020-06-16 08:21:42 +03:00
adc_l_ctrl = snd_soc_component_read ( component , DA7213_ADC_L_CTRL ) ;
adc_r_ctrl = snd_soc_component_read ( component , DA7213_ADC_R_CTRL ) ;
2013-02-14 16:02:51 +04:00
/* Save current values from MIXIN_L/R_SELECT registers */
2020-06-16 08:21:42 +03:00
mixin_l_sel = snd_soc_component_read ( component , DA7213_MIXIN_L_SELECT ) ;
mixin_r_sel = snd_soc_component_read ( component , DA7213_MIXIN_R_SELECT ) ;
2013-02-14 16:02:51 +04:00
/* Save current values from MIC control registers */
2020-06-16 08:21:42 +03:00
mic_1_ctrl = snd_soc_component_read ( component , DA7213_MIC_1_CTRL ) ;
mic_2_ctrl = snd_soc_component_read ( component , DA7213_MIC_2_CTRL ) ;
2013-02-14 16:02:51 +04:00
/* Enable ADC Left and Right */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ADC_L_CTRL , DA7213_ADC_EN ,
2013-02-14 16:02:51 +04:00
DA7213_ADC_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ADC_R_CTRL , DA7213_ADC_EN ,
2013-02-14 16:02:51 +04:00
DA7213_ADC_EN ) ;
/* Enable MIC paths */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXIN_L_SELECT ,
2013-02-14 16:02:51 +04:00
DA7213_MIXIN_L_MIX_SELECT_MIC_1 |
DA7213_MIXIN_L_MIX_SELECT_MIC_2 ,
DA7213_MIXIN_L_MIX_SELECT_MIC_1 |
DA7213_MIXIN_L_MIX_SELECT_MIC_2 ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXIN_R_SELECT ,
2013-02-14 16:02:51 +04:00
DA7213_MIXIN_R_MIX_SELECT_MIC_2 |
DA7213_MIXIN_R_MIX_SELECT_MIC_1 ,
DA7213_MIXIN_R_MIX_SELECT_MIC_2 |
DA7213_MIXIN_R_MIX_SELECT_MIC_1 ) ;
/* Mute MIC PGAs */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIC_1_CTRL , DA7213_MUTE_EN ,
2013-02-14 16:02:51 +04:00
DA7213_MUTE_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIC_2_CTRL , DA7213_MUTE_EN ,
2013-02-14 16:02:51 +04:00
DA7213_MUTE_EN ) ;
/* Perform calibration */
if ( da7213 - > alc_calib_auto )
2018-01-29 07:03:13 +03:00
da7213_alc_calib_auto ( component ) ;
2013-02-14 16:02:51 +04:00
else
2018-01-29 07:03:13 +03:00
da7213_alc_calib_man ( component ) ;
2013-02-14 16:02:51 +04:00
/* Restore MIXIN_L/R_SELECT registers to their original states */
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_MIXIN_L_SELECT , mixin_l_sel ) ;
snd_soc_component_write ( component , DA7213_MIXIN_R_SELECT , mixin_r_sel ) ;
2013-02-14 16:02:51 +04:00
/* Restore ADC control registers to their original states */
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_ADC_L_CTRL , adc_l_ctrl ) ;
snd_soc_component_write ( component , DA7213_ADC_R_CTRL , adc_r_ctrl ) ;
2013-02-14 16:02:51 +04:00
/* Restore original values of MIC control registers */
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_MIC_1_CTRL , mic_1_ctrl ) ;
snd_soc_component_write ( component , DA7213_MIC_2_CTRL , mic_2_ctrl ) ;
2013-02-14 16:02:51 +04:00
}
static int da7213_put_mixin_gain ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 07:03:13 +03:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2013-02-14 16:02:51 +04:00
int ret ;
ret = snd_soc_put_volsw_2r ( kcontrol , ucontrol ) ;
/* If ALC in operation, make sure calibrated offsets are updated */
if ( ( ! ret ) & & ( da7213 - > alc_en ) )
2018-01-29 07:03:13 +03:00
da7213_alc_calib ( component ) ;
2013-02-14 16:02:51 +04:00
return ret ;
}
static int da7213_put_alc_sw ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 07:03:13 +03:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2013-02-14 16:02:51 +04:00
/* Force ALC offset calibration if enabling ALC */
if ( ucontrol - > value . integer . value [ 0 ] | |
ucontrol - > value . integer . value [ 1 ] ) {
if ( ! da7213 - > alc_en ) {
2018-01-29 07:03:13 +03:00
da7213_alc_calib ( component ) ;
2013-02-14 16:02:51 +04:00
da7213 - > alc_en = true ;
}
} else {
da7213 - > alc_en = false ;
}
return snd_soc_put_volsw ( kcontrol , ucontrol ) ;
}
/*
* KControls
*/
static const struct snd_kcontrol_new da7213_snd_controls [ ] = {
/* Volume controls */
SOC_SINGLE_TLV ( " Mic 1 Volume " , DA7213_MIC_1_GAIN ,
DA7213_MIC_AMP_GAIN_SHIFT , DA7213_MIC_AMP_GAIN_MAX ,
DA7213_NO_INVERT , mic_vol_tlv ) ,
SOC_SINGLE_TLV ( " Mic 2 Volume " , DA7213_MIC_2_GAIN ,
DA7213_MIC_AMP_GAIN_SHIFT , DA7213_MIC_AMP_GAIN_MAX ,
DA7213_NO_INVERT , mic_vol_tlv ) ,
SOC_DOUBLE_R_TLV ( " Aux Volume " , DA7213_AUX_L_GAIN , DA7213_AUX_R_GAIN ,
DA7213_AUX_AMP_GAIN_SHIFT , DA7213_AUX_AMP_GAIN_MAX ,
DA7213_NO_INVERT , aux_vol_tlv ) ,
SOC_DOUBLE_R_EXT_TLV ( " Mixin PGA Volume " , DA7213_MIXIN_L_GAIN ,
DA7213_MIXIN_R_GAIN , DA7213_MIXIN_AMP_GAIN_SHIFT ,
DA7213_MIXIN_AMP_GAIN_MAX , DA7213_NO_INVERT ,
snd_soc_get_volsw_2r , da7213_put_mixin_gain ,
mixin_gain_tlv ) ,
SOC_DOUBLE_R_TLV ( " ADC Volume " , DA7213_ADC_L_GAIN , DA7213_ADC_R_GAIN ,
DA7213_ADC_AMP_GAIN_SHIFT , DA7213_ADC_AMP_GAIN_MAX ,
DA7213_NO_INVERT , digital_gain_tlv ) ,
SOC_DOUBLE_R_TLV ( " DAC Volume " , DA7213_DAC_L_GAIN , DA7213_DAC_R_GAIN ,
DA7213_DAC_AMP_GAIN_SHIFT , DA7213_DAC_AMP_GAIN_MAX ,
DA7213_NO_INVERT , digital_gain_tlv ) ,
SOC_DOUBLE_R_TLV ( " Headphone Volume " , DA7213_HP_L_GAIN , DA7213_HP_R_GAIN ,
DA7213_HP_AMP_GAIN_SHIFT , DA7213_HP_AMP_GAIN_MAX ,
DA7213_NO_INVERT , hp_vol_tlv ) ,
SOC_SINGLE_TLV ( " Lineout Volume " , DA7213_LINE_GAIN ,
DA7213_LINE_AMP_GAIN_SHIFT , DA7213_LINE_AMP_GAIN_MAX ,
DA7213_NO_INVERT , lineout_vol_tlv ) ,
/* DAC Equalizer controls */
SOC_SINGLE ( " DAC EQ Switch " , DA7213_DAC_FILTERS4 , DA7213_DAC_EQ_EN_SHIFT ,
DA7213_DAC_EQ_EN_MAX , DA7213_NO_INVERT ) ,
SOC_SINGLE_TLV ( " DAC EQ1 Volume " , DA7213_DAC_FILTERS2 ,
DA7213_DAC_EQ_BAND1_SHIFT , DA7213_DAC_EQ_BAND_MAX ,
DA7213_NO_INVERT , eq_gain_tlv ) ,
SOC_SINGLE_TLV ( " DAC EQ2 Volume " , DA7213_DAC_FILTERS2 ,
DA7213_DAC_EQ_BAND2_SHIFT , DA7213_DAC_EQ_BAND_MAX ,
DA7213_NO_INVERT , eq_gain_tlv ) ,
SOC_SINGLE_TLV ( " DAC EQ3 Volume " , DA7213_DAC_FILTERS3 ,
DA7213_DAC_EQ_BAND3_SHIFT , DA7213_DAC_EQ_BAND_MAX ,
DA7213_NO_INVERT , eq_gain_tlv ) ,
SOC_SINGLE_TLV ( " DAC EQ4 Volume " , DA7213_DAC_FILTERS3 ,
DA7213_DAC_EQ_BAND4_SHIFT , DA7213_DAC_EQ_BAND_MAX ,
DA7213_NO_INVERT , eq_gain_tlv ) ,
SOC_SINGLE_TLV ( " DAC EQ5 Volume " , DA7213_DAC_FILTERS4 ,
DA7213_DAC_EQ_BAND5_SHIFT , DA7213_DAC_EQ_BAND_MAX ,
DA7213_NO_INVERT , eq_gain_tlv ) ,
/* High Pass Filter and Voice Mode controls */
SOC_SINGLE ( " ADC HPF Switch " , DA7213_ADC_FILTERS1 , DA7213_HPF_EN_SHIFT ,
DA7213_HPF_EN_MAX , DA7213_NO_INVERT ) ,
SOC_ENUM ( " ADC HPF Cutoff " , da7213_adc_audio_hpf_corner ) ,
SOC_SINGLE ( " ADC Voice Mode Switch " , DA7213_ADC_FILTERS1 ,
DA7213_VOICE_EN_SHIFT , DA7213_VOICE_EN_MAX ,
DA7213_NO_INVERT ) ,
SOC_ENUM ( " ADC Voice Cutoff " , da7213_adc_voice_hpf_corner ) ,
SOC_SINGLE ( " DAC HPF Switch " , DA7213_DAC_FILTERS1 , DA7213_HPF_EN_SHIFT ,
DA7213_HPF_EN_MAX , DA7213_NO_INVERT ) ,
SOC_ENUM ( " DAC HPF Cutoff " , da7213_dac_audio_hpf_corner ) ,
SOC_SINGLE ( " DAC Voice Mode Switch " , DA7213_DAC_FILTERS1 ,
DA7213_VOICE_EN_SHIFT , DA7213_VOICE_EN_MAX ,
DA7213_NO_INVERT ) ,
SOC_ENUM ( " DAC Voice Cutoff " , da7213_dac_voice_hpf_corner ) ,
/* Mute controls */
SOC_SINGLE ( " Mic 1 Switch " , DA7213_MIC_1_CTRL , DA7213_MUTE_EN_SHIFT ,
DA7213_MUTE_EN_MAX , DA7213_INVERT ) ,
SOC_SINGLE ( " Mic 2 Switch " , DA7213_MIC_2_CTRL , DA7213_MUTE_EN_SHIFT ,
DA7213_MUTE_EN_MAX , DA7213_INVERT ) ,
SOC_DOUBLE_R ( " Aux Switch " , DA7213_AUX_L_CTRL , DA7213_AUX_R_CTRL ,
DA7213_MUTE_EN_SHIFT , DA7213_MUTE_EN_MAX , DA7213_INVERT ) ,
SOC_DOUBLE_R ( " Mixin PGA Switch " , DA7213_MIXIN_L_CTRL ,
DA7213_MIXIN_R_CTRL , DA7213_MUTE_EN_SHIFT ,
DA7213_MUTE_EN_MAX , DA7213_INVERT ) ,
SOC_DOUBLE_R ( " ADC Switch " , DA7213_ADC_L_CTRL , DA7213_ADC_R_CTRL ,
DA7213_MUTE_EN_SHIFT , DA7213_MUTE_EN_MAX , DA7213_INVERT ) ,
SOC_DOUBLE_R ( " Headphone Switch " , DA7213_HP_L_CTRL , DA7213_HP_R_CTRL ,
DA7213_MUTE_EN_SHIFT , DA7213_MUTE_EN_MAX , DA7213_INVERT ) ,
SOC_SINGLE ( " Lineout Switch " , DA7213_LINE_CTRL , DA7213_MUTE_EN_SHIFT ,
DA7213_MUTE_EN_MAX , DA7213_INVERT ) ,
SOC_SINGLE ( " DAC Soft Mute Switch " , DA7213_DAC_FILTERS5 ,
DA7213_DAC_SOFTMUTE_EN_SHIFT , DA7213_DAC_SOFTMUTE_EN_MAX ,
DA7213_NO_INVERT ) ,
SOC_ENUM ( " DAC Soft Mute Rate " , da7213_dac_soft_mute_rate ) ,
/* Zero Cross controls */
SOC_DOUBLE_R ( " Aux ZC Switch " , DA7213_AUX_L_CTRL , DA7213_AUX_R_CTRL ,
DA7213_ZC_EN_SHIFT , DA7213_ZC_EN_MAX , DA7213_NO_INVERT ) ,
SOC_DOUBLE_R ( " Mixin PGA ZC Switch " , DA7213_MIXIN_L_CTRL ,
DA7213_MIXIN_R_CTRL , DA7213_ZC_EN_SHIFT , DA7213_ZC_EN_MAX ,
DA7213_NO_INVERT ) ,
SOC_DOUBLE_R ( " Headphone ZC Switch " , DA7213_HP_L_CTRL , DA7213_HP_R_CTRL ,
DA7213_ZC_EN_SHIFT , DA7213_ZC_EN_MAX , DA7213_NO_INVERT ) ,
/* Gain Ramping controls */
SOC_DOUBLE_R ( " Aux Gain Ramping Switch " , DA7213_AUX_L_CTRL ,
DA7213_AUX_R_CTRL , DA7213_GAIN_RAMP_EN_SHIFT ,
DA7213_GAIN_RAMP_EN_MAX , DA7213_NO_INVERT ) ,
SOC_DOUBLE_R ( " Mixin Gain Ramping Switch " , DA7213_MIXIN_L_CTRL ,
DA7213_MIXIN_R_CTRL , DA7213_GAIN_RAMP_EN_SHIFT ,
DA7213_GAIN_RAMP_EN_MAX , DA7213_NO_INVERT ) ,
SOC_DOUBLE_R ( " ADC Gain Ramping Switch " , DA7213_ADC_L_CTRL ,
DA7213_ADC_R_CTRL , DA7213_GAIN_RAMP_EN_SHIFT ,
DA7213_GAIN_RAMP_EN_MAX , DA7213_NO_INVERT ) ,
SOC_DOUBLE_R ( " DAC Gain Ramping Switch " , DA7213_DAC_L_CTRL ,
DA7213_DAC_R_CTRL , DA7213_GAIN_RAMP_EN_SHIFT ,
DA7213_GAIN_RAMP_EN_MAX , DA7213_NO_INVERT ) ,
SOC_DOUBLE_R ( " Headphone Gain Ramping Switch " , DA7213_HP_L_CTRL ,
DA7213_HP_R_CTRL , DA7213_GAIN_RAMP_EN_SHIFT ,
DA7213_GAIN_RAMP_EN_MAX , DA7213_NO_INVERT ) ,
SOC_SINGLE ( " Lineout Gain Ramping Switch " , DA7213_LINE_CTRL ,
DA7213_GAIN_RAMP_EN_SHIFT , DA7213_GAIN_RAMP_EN_MAX ,
DA7213_NO_INVERT ) ,
SOC_ENUM ( " Gain Ramping Rate " , da7213_gain_ramp_rate ) ,
/* DAC Noise Gate controls */
SOC_SINGLE ( " DAC NG Switch " , DA7213_DAC_NG_CTRL , DA7213_DAC_NG_EN_SHIFT ,
DA7213_DAC_NG_EN_MAX , DA7213_NO_INVERT ) ,
SOC_ENUM ( " DAC NG Setup Time " , da7213_dac_ng_setup_time ) ,
SOC_ENUM ( " DAC NG Rampup Rate " , da7213_dac_ng_rampup_rate ) ,
SOC_ENUM ( " DAC NG Rampdown Rate " , da7213_dac_ng_rampdown_rate ) ,
SOC_SINGLE ( " DAC NG OFF Threshold " , DA7213_DAC_NG_OFF_THRESHOLD ,
DA7213_DAC_NG_THRESHOLD_SHIFT , DA7213_DAC_NG_THRESHOLD_MAX ,
DA7213_NO_INVERT ) ,
SOC_SINGLE ( " DAC NG ON Threshold " , DA7213_DAC_NG_ON_THRESHOLD ,
DA7213_DAC_NG_THRESHOLD_SHIFT , DA7213_DAC_NG_THRESHOLD_MAX ,
DA7213_NO_INVERT ) ,
/* DAC Routing & Inversion */
SOC_DOUBLE ( " DAC Mono Switch " , DA7213_DIG_ROUTING_DAC ,
DA7213_DAC_L_MONO_SHIFT , DA7213_DAC_R_MONO_SHIFT ,
DA7213_DAC_MONO_MAX , DA7213_NO_INVERT ) ,
SOC_DOUBLE ( " DAC Invert Switch " , DA7213_DIG_CTRL , DA7213_DAC_L_INV_SHIFT ,
DA7213_DAC_R_INV_SHIFT , DA7213_DAC_INV_MAX ,
DA7213_NO_INVERT ) ,
/* DMIC controls */
SOC_DOUBLE_R ( " DMIC Switch " , DA7213_MIXIN_L_SELECT ,
DA7213_MIXIN_R_SELECT , DA7213_DMIC_EN_SHIFT ,
DA7213_DMIC_EN_MAX , DA7213_NO_INVERT ) ,
/* ALC Controls */
SOC_DOUBLE_EXT ( " ALC Switch " , DA7213_ALC_CTRL1 , DA7213_ALC_L_EN_SHIFT ,
DA7213_ALC_R_EN_SHIFT , DA7213_ALC_EN_MAX ,
DA7213_NO_INVERT , snd_soc_get_volsw , da7213_put_alc_sw ) ,
SOC_ENUM ( " ALC Attack Rate " , da7213_alc_attack_rate ) ,
SOC_ENUM ( " ALC Release Rate " , da7213_alc_release_rate ) ,
SOC_ENUM ( " ALC Hold Time " , da7213_alc_hold_time ) ,
/*
* Rate at which input signal envelope is tracked as the signal gets
* larger
*/
SOC_ENUM ( " ALC Integ Attack Rate " , da7213_alc_integ_attack_rate ) ,
/*
* Rate at which input signal envelope is tracked as the signal gets
* smaller
*/
SOC_ENUM ( " ALC Integ Release Rate " , da7213_alc_integ_release_rate ) ,
SOC_SINGLE_TLV ( " ALC Noise Threshold Volume " , DA7213_ALC_NOISE ,
DA7213_ALC_THRESHOLD_SHIFT , DA7213_ALC_THRESHOLD_MAX ,
DA7213_INVERT , alc_threshold_tlv ) ,
SOC_SINGLE_TLV ( " ALC Min Threshold Volume " , DA7213_ALC_TARGET_MIN ,
DA7213_ALC_THRESHOLD_SHIFT , DA7213_ALC_THRESHOLD_MAX ,
DA7213_INVERT , alc_threshold_tlv ) ,
SOC_SINGLE_TLV ( " ALC Max Threshold Volume " , DA7213_ALC_TARGET_MAX ,
DA7213_ALC_THRESHOLD_SHIFT , DA7213_ALC_THRESHOLD_MAX ,
DA7213_INVERT , alc_threshold_tlv ) ,
SOC_SINGLE_TLV ( " ALC Max Attenuation Volume " , DA7213_ALC_GAIN_LIMITS ,
DA7213_ALC_ATTEN_MAX_SHIFT ,
DA7213_ALC_ATTEN_GAIN_MAX_MAX , DA7213_NO_INVERT ,
alc_gain_tlv ) ,
SOC_SINGLE_TLV ( " ALC Max Gain Volume " , DA7213_ALC_GAIN_LIMITS ,
DA7213_ALC_GAIN_MAX_SHIFT , DA7213_ALC_ATTEN_GAIN_MAX_MAX ,
DA7213_NO_INVERT , alc_gain_tlv ) ,
SOC_SINGLE_TLV ( " ALC Min Analog Gain Volume " , DA7213_ALC_ANA_GAIN_LIMITS ,
DA7213_ALC_ANA_GAIN_MIN_SHIFT , DA7213_ALC_ANA_GAIN_MAX ,
DA7213_NO_INVERT , alc_analog_gain_tlv ) ,
SOC_SINGLE_TLV ( " ALC Max Analog Gain Volume " , DA7213_ALC_ANA_GAIN_LIMITS ,
DA7213_ALC_ANA_GAIN_MAX_SHIFT , DA7213_ALC_ANA_GAIN_MAX ,
DA7213_NO_INVERT , alc_analog_gain_tlv ) ,
SOC_SINGLE ( " ALC Anticlip Mode Switch " , DA7213_ALC_ANTICLIP_CTRL ,
DA7213_ALC_ANTICLIP_EN_SHIFT , DA7213_ALC_ANTICLIP_EN_MAX ,
DA7213_NO_INVERT ) ,
SOC_SINGLE ( " ALC Anticlip Level " , DA7213_ALC_ANTICLIP_LEVEL ,
DA7213_ALC_ANTICLIP_LEVEL_SHIFT ,
DA7213_ALC_ANTICLIP_LEVEL_MAX , DA7213_NO_INVERT ) ,
} ;
/*
* DAPM
*/
/*
* Enums
*/
/* MIC PGA source select */
static const char * const da7213_mic_amp_in_sel_txt [ ] = {
" Differential " , " MIC_P " , " MIC_N "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_mic_1_amp_in_sel ,
DA7213_MIC_1_CTRL ,
DA7213_MIC_AMP_IN_SEL_SHIFT ,
da7213_mic_amp_in_sel_txt ) ;
2013-02-14 16:02:51 +04:00
static const struct snd_kcontrol_new da7213_mic_1_amp_in_sel_mux =
SOC_DAPM_ENUM ( " Mic 1 Amp Source MUX " , da7213_mic_1_amp_in_sel ) ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_mic_2_amp_in_sel ,
DA7213_MIC_2_CTRL ,
DA7213_MIC_AMP_IN_SEL_SHIFT ,
da7213_mic_amp_in_sel_txt ) ;
2013-02-14 16:02:51 +04:00
static const struct snd_kcontrol_new da7213_mic_2_amp_in_sel_mux =
SOC_DAPM_ENUM ( " Mic 2 Amp Source MUX " , da7213_mic_2_amp_in_sel ) ;
/* DAI routing select */
static const char * const da7213_dai_src_txt [ ] = {
" ADC Left " , " ADC Right " , " DAI Input Left " , " DAI Input Right "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dai_l_src ,
DA7213_DIG_ROUTING_DAI ,
DA7213_DAI_L_SRC_SHIFT ,
da7213_dai_src_txt ) ;
2013-02-14 16:02:51 +04:00
static const struct snd_kcontrol_new da7213_dai_l_src_mux =
SOC_DAPM_ENUM ( " DAI Left Source MUX " , da7213_dai_l_src ) ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dai_r_src ,
DA7213_DIG_ROUTING_DAI ,
DA7213_DAI_R_SRC_SHIFT ,
da7213_dai_src_txt ) ;
2013-02-14 16:02:51 +04:00
static const struct snd_kcontrol_new da7213_dai_r_src_mux =
SOC_DAPM_ENUM ( " DAI Right Source MUX " , da7213_dai_r_src ) ;
/* DAC routing select */
static const char * const da7213_dac_src_txt [ ] = {
" ADC Output Left " , " ADC Output Right " , " DAI Input Left " ,
" DAI Input Right "
} ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_l_src ,
DA7213_DIG_ROUTING_DAC ,
DA7213_DAC_L_SRC_SHIFT ,
da7213_dac_src_txt ) ;
2013-02-14 16:02:51 +04:00
static const struct snd_kcontrol_new da7213_dac_l_src_mux =
SOC_DAPM_ENUM ( " DAC Left Source MUX " , da7213_dac_l_src ) ;
2014-02-18 13:06:47 +04:00
static SOC_ENUM_SINGLE_DECL ( da7213_dac_r_src ,
DA7213_DIG_ROUTING_DAC ,
DA7213_DAC_R_SRC_SHIFT ,
da7213_dac_src_txt ) ;
2013-02-14 16:02:51 +04:00
static const struct snd_kcontrol_new da7213_dac_r_src_mux =
SOC_DAPM_ENUM ( " DAC Right Source MUX " , da7213_dac_r_src ) ;
/*
* Mixer Controls
*/
/* Mixin Left */
static const struct snd_kcontrol_new da7213_dapm_mixinl_controls [ ] = {
SOC_DAPM_SINGLE ( " Aux Left Switch " , DA7213_MIXIN_L_SELECT ,
DA7213_MIXIN_L_MIX_SELECT_AUX_L_SHIFT ,
DA7213_MIXIN_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mic 1 Switch " , DA7213_MIXIN_L_SELECT ,
DA7213_MIXIN_L_MIX_SELECT_MIC_1_SHIFT ,
DA7213_MIXIN_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mic 2 Switch " , DA7213_MIXIN_L_SELECT ,
DA7213_MIXIN_L_MIX_SELECT_MIC_2_SHIFT ,
DA7213_MIXIN_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Right Switch " , DA7213_MIXIN_L_SELECT ,
DA7213_MIXIN_L_MIX_SELECT_MIXIN_R_SHIFT ,
DA7213_MIXIN_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
} ;
/* Mixin Right */
static const struct snd_kcontrol_new da7213_dapm_mixinr_controls [ ] = {
SOC_DAPM_SINGLE ( " Aux Right Switch " , DA7213_MIXIN_R_SELECT ,
DA7213_MIXIN_R_MIX_SELECT_AUX_R_SHIFT ,
DA7213_MIXIN_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mic 2 Switch " , DA7213_MIXIN_R_SELECT ,
DA7213_MIXIN_R_MIX_SELECT_MIC_2_SHIFT ,
DA7213_MIXIN_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mic 1 Switch " , DA7213_MIXIN_R_SELECT ,
DA7213_MIXIN_R_MIX_SELECT_MIC_1_SHIFT ,
DA7213_MIXIN_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Left Switch " , DA7213_MIXIN_R_SELECT ,
DA7213_MIXIN_R_MIX_SELECT_MIXIN_L_SHIFT ,
DA7213_MIXIN_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
} ;
/* Mixout Left */
static const struct snd_kcontrol_new da7213_dapm_mixoutl_controls [ ] = {
SOC_DAPM_SINGLE ( " Aux Left Switch " , DA7213_MIXOUT_L_SELECT ,
DA7213_MIXOUT_L_MIX_SELECT_AUX_L_SHIFT ,
DA7213_MIXOUT_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Left Switch " , DA7213_MIXOUT_L_SELECT ,
DA7213_MIXOUT_L_MIX_SELECT_MIXIN_L_SHIFT ,
DA7213_MIXOUT_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Right Switch " , DA7213_MIXOUT_L_SELECT ,
DA7213_MIXOUT_L_MIX_SELECT_MIXIN_R_SHIFT ,
DA7213_MIXOUT_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " DAC Left Switch " , DA7213_MIXOUT_L_SELECT ,
DA7213_MIXOUT_L_MIX_SELECT_DAC_L_SHIFT ,
DA7213_MIXOUT_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Aux Left Invert Switch " , DA7213_MIXOUT_L_SELECT ,
DA7213_MIXOUT_L_MIX_SELECT_AUX_L_INVERTED_SHIFT ,
DA7213_MIXOUT_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Left Invert Switch " , DA7213_MIXOUT_L_SELECT ,
DA7213_MIXOUT_L_MIX_SELECT_MIXIN_L_INVERTED_SHIFT ,
DA7213_MIXOUT_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Right Invert Switch " , DA7213_MIXOUT_L_SELECT ,
DA7213_MIXOUT_L_MIX_SELECT_MIXIN_R_INVERTED_SHIFT ,
DA7213_MIXOUT_L_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
} ;
/* Mixout Right */
static const struct snd_kcontrol_new da7213_dapm_mixoutr_controls [ ] = {
SOC_DAPM_SINGLE ( " Aux Right Switch " , DA7213_MIXOUT_R_SELECT ,
DA7213_MIXOUT_R_MIX_SELECT_AUX_R_SHIFT ,
DA7213_MIXOUT_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Right Switch " , DA7213_MIXOUT_R_SELECT ,
DA7213_MIXOUT_R_MIX_SELECT_MIXIN_R_SHIFT ,
DA7213_MIXOUT_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Left Switch " , DA7213_MIXOUT_R_SELECT ,
DA7213_MIXOUT_R_MIX_SELECT_MIXIN_L_SHIFT ,
DA7213_MIXOUT_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " DAC Right Switch " , DA7213_MIXOUT_R_SELECT ,
DA7213_MIXOUT_R_MIX_SELECT_DAC_R_SHIFT ,
DA7213_MIXOUT_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Aux Right Invert Switch " , DA7213_MIXOUT_R_SELECT ,
DA7213_MIXOUT_R_MIX_SELECT_AUX_R_INVERTED_SHIFT ,
DA7213_MIXOUT_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Right Invert Switch " , DA7213_MIXOUT_R_SELECT ,
DA7213_MIXOUT_R_MIX_SELECT_MIXIN_R_INVERTED_SHIFT ,
DA7213_MIXOUT_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
SOC_DAPM_SINGLE ( " Mixin Left Invert Switch " , DA7213_MIXOUT_R_SELECT ,
DA7213_MIXOUT_R_MIX_SELECT_MIXIN_L_INVERTED_SHIFT ,
DA7213_MIXOUT_R_MIX_SELECT_MAX , DA7213_NO_INVERT ) ,
} ;
2016-05-10 18:11:04 +03:00
/*
* DAPM Events
*/
static int da7213_dai_event ( struct snd_soc_dapm_widget * w ,
struct snd_kcontrol * kcontrol , int event )
{
2018-01-29 07:03:13 +03:00
struct snd_soc_component * component = snd_soc_dapm_to_component ( w - > dapm ) ;
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2016-05-10 18:11:05 +03:00
u8 pll_ctrl , pll_status ;
int i = 0 ;
bool srm_lock = false ;
2016-05-10 18:11:04 +03:00
switch ( event ) {
case SND_SOC_DAPM_PRE_PMU :
/* Enable DAI clks for master mode */
if ( da7213 - > master )
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAI_CLK_MODE ,
2016-05-10 18:11:04 +03:00
DA7213_DAI_CLK_EN_MASK ,
DA7213_DAI_CLK_EN_MASK ) ;
2016-05-10 18:11:05 +03:00
2016-05-10 18:11:06 +03:00
/* PC synchronised to DAI */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_PC_COUNT ,
2016-05-10 18:11:06 +03:00
DA7213_PC_FREERUN_MASK , 0 ) ;
2016-08-04 17:35:41 +03:00
/* If SRM not enabled then nothing more to do */
2020-06-16 08:21:42 +03:00
pll_ctrl = snd_soc_component_read ( component , DA7213_PLL_CTRL ) ;
2016-05-10 18:11:05 +03:00
if ( ! ( pll_ctrl & DA7213_PLL_SRM_EN ) )
return 0 ;
2016-08-04 17:35:41 +03:00
/* Assist 32KHz mode PLL lock */
if ( pll_ctrl & DA7213_PLL_32K_MODE ) {
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , 0xF0 , 0x8B ) ;
snd_soc_component_write ( component , 0xF2 , 0x03 ) ;
snd_soc_component_write ( component , 0xF0 , 0x00 ) ;
2016-08-04 17:35:41 +03:00
}
2016-05-10 18:11:05 +03:00
/* Check SRM has locked */
do {
2020-06-16 08:21:42 +03:00
pll_status = snd_soc_component_read ( component , DA7213_PLL_STATUS ) ;
2016-05-10 18:11:05 +03:00
if ( pll_status & DA7219_PLL_SRM_LOCK ) {
srm_lock = true ;
} else {
+ + i ;
msleep ( 50 ) ;
}
2017-05-03 18:15:53 +03:00
} while ( ( i < DA7213_SRM_CHECK_RETRIES ) & & ( ! srm_lock ) ) ;
2016-05-10 18:11:05 +03:00
if ( ! srm_lock )
2018-01-29 07:03:13 +03:00
dev_warn ( component - > dev , " SRM failed to lock \n " ) ;
2016-05-10 18:11:05 +03:00
2016-05-10 18:11:04 +03:00
return 0 ;
case SND_SOC_DAPM_POST_PMD :
2016-08-04 17:35:41 +03:00
/* Revert 32KHz PLL lock udpates if applied previously */
2020-06-16 08:21:42 +03:00
pll_ctrl = snd_soc_component_read ( component , DA7213_PLL_CTRL ) ;
2016-08-04 17:35:41 +03:00
if ( pll_ctrl & DA7213_PLL_32K_MODE ) {
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , 0xF0 , 0x8B ) ;
snd_soc_component_write ( component , 0xF2 , 0x01 ) ;
snd_soc_component_write ( component , 0xF0 , 0x00 ) ;
2016-08-04 17:35:41 +03:00
}
2016-05-10 18:11:06 +03:00
/* PC free-running */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_PC_COUNT ,
2016-05-10 18:11:06 +03:00
DA7213_PC_FREERUN_MASK ,
DA7213_PC_FREERUN_MASK ) ;
2016-05-10 18:11:04 +03:00
/* Disable DAI clks if in master mode */
if ( da7213 - > master )
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAI_CLK_MODE ,
2016-05-10 18:11:04 +03:00
DA7213_DAI_CLK_EN_MASK , 0 ) ;
return 0 ;
default :
return - EINVAL ;
}
}
2013-02-14 16:02:51 +04:00
/*
* DAPM widgets
*/
static const struct snd_soc_dapm_widget da7213_dapm_widgets [ ] = {
2020-05-11 16:25:41 +03:00
/*
* Power Supply
*/
SND_SOC_DAPM_REGULATOR_SUPPLY ( " VDDMIC " , 0 , 0 ) ,
2013-02-14 16:02:51 +04:00
/*
* Input & Output
*/
/* Use a supply here as this controls both input & output DAIs */
SND_SOC_DAPM_SUPPLY ( " DAI " , DA7213_DAI_CTRL , DA7213_DAI_EN_SHIFT ,
2016-05-10 18:11:04 +03:00
DA7213_NO_INVERT , da7213_dai_event ,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD ) ,
2013-02-14 16:02:51 +04:00
/*
* Input
*/
/* Input Lines */
SND_SOC_DAPM_INPUT ( " MIC1 " ) ,
SND_SOC_DAPM_INPUT ( " MIC2 " ) ,
SND_SOC_DAPM_INPUT ( " AUXL " ) ,
SND_SOC_DAPM_INPUT ( " AUXR " ) ,
/* MUXs for Mic PGA source selection */
SND_SOC_DAPM_MUX ( " Mic 1 Amp Source MUX " , SND_SOC_NOPM , 0 , 0 ,
& da7213_mic_1_amp_in_sel_mux ) ,
SND_SOC_DAPM_MUX ( " Mic 2 Amp Source MUX " , SND_SOC_NOPM , 0 , 0 ,
& da7213_mic_2_amp_in_sel_mux ) ,
/* Input PGAs */
SND_SOC_DAPM_PGA ( " Mic 1 PGA " , DA7213_MIC_1_CTRL , DA7213_AMP_EN_SHIFT ,
DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Mic 2 PGA " , DA7213_MIC_2_CTRL , DA7213_AMP_EN_SHIFT ,
DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Aux Left PGA " , DA7213_AUX_L_CTRL , DA7213_AMP_EN_SHIFT ,
DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Aux Right PGA " , DA7213_AUX_R_CTRL ,
DA7213_AMP_EN_SHIFT , DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Mixin Left PGA " , DA7213_MIXIN_L_CTRL ,
DA7213_AMP_EN_SHIFT , DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Mixin Right PGA " , DA7213_MIXIN_R_CTRL ,
DA7213_AMP_EN_SHIFT , DA7213_NO_INVERT , NULL , 0 ) ,
/* Mic Biases */
SND_SOC_DAPM_SUPPLY ( " Mic Bias 1 " , DA7213_MICBIAS_CTRL ,
DA7213_MICBIAS1_EN_SHIFT , DA7213_NO_INVERT ,
NULL , 0 ) ,
SND_SOC_DAPM_SUPPLY ( " Mic Bias 2 " , DA7213_MICBIAS_CTRL ,
DA7213_MICBIAS2_EN_SHIFT , DA7213_NO_INVERT ,
NULL , 0 ) ,
/* Input Mixers */
SND_SOC_DAPM_MIXER ( " Mixin Left " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dapm_mixinl_controls [ 0 ] ,
ARRAY_SIZE ( da7213_dapm_mixinl_controls ) ) ,
SND_SOC_DAPM_MIXER ( " Mixin Right " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dapm_mixinr_controls [ 0 ] ,
ARRAY_SIZE ( da7213_dapm_mixinr_controls ) ) ,
/* ADCs */
SND_SOC_DAPM_ADC ( " ADC Left " , NULL , DA7213_ADC_L_CTRL ,
DA7213_ADC_EN_SHIFT , DA7213_NO_INVERT ) ,
SND_SOC_DAPM_ADC ( " ADC Right " , NULL , DA7213_ADC_R_CTRL ,
DA7213_ADC_EN_SHIFT , DA7213_NO_INVERT ) ,
/* DAI */
SND_SOC_DAPM_MUX ( " DAI Left Source MUX " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dai_l_src_mux ) ,
SND_SOC_DAPM_MUX ( " DAI Right Source MUX " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dai_r_src_mux ) ,
SND_SOC_DAPM_AIF_OUT ( " DAIOUTL " , " Capture " , 0 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_OUT ( " DAIOUTR " , " Capture " , 1 , SND_SOC_NOPM , 0 , 0 ) ,
/*
* Output
*/
/* DAI */
SND_SOC_DAPM_AIF_IN ( " DAIINL " , " Playback " , 0 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_AIF_IN ( " DAIINR " , " Playback " , 1 , SND_SOC_NOPM , 0 , 0 ) ,
SND_SOC_DAPM_MUX ( " DAC Left Source MUX " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dac_l_src_mux ) ,
SND_SOC_DAPM_MUX ( " DAC Right Source MUX " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dac_r_src_mux ) ,
/* DACs */
SND_SOC_DAPM_DAC ( " DAC Left " , NULL , DA7213_DAC_L_CTRL ,
DA7213_DAC_EN_SHIFT , DA7213_NO_INVERT ) ,
SND_SOC_DAPM_DAC ( " DAC Right " , NULL , DA7213_DAC_R_CTRL ,
DA7213_DAC_EN_SHIFT , DA7213_NO_INVERT ) ,
/* Output Mixers */
SND_SOC_DAPM_MIXER ( " Mixout Left " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dapm_mixoutl_controls [ 0 ] ,
ARRAY_SIZE ( da7213_dapm_mixoutl_controls ) ) ,
SND_SOC_DAPM_MIXER ( " Mixout Right " , SND_SOC_NOPM , 0 , 0 ,
& da7213_dapm_mixoutr_controls [ 0 ] ,
ARRAY_SIZE ( da7213_dapm_mixoutr_controls ) ) ,
/* Output PGAs */
SND_SOC_DAPM_PGA ( " Mixout Left PGA " , DA7213_MIXOUT_L_CTRL ,
DA7213_AMP_EN_SHIFT , DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Mixout Right PGA " , DA7213_MIXOUT_R_CTRL ,
DA7213_AMP_EN_SHIFT , DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Lineout PGA " , DA7213_LINE_CTRL , DA7213_AMP_EN_SHIFT ,
DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Headphone Left PGA " , DA7213_HP_L_CTRL ,
DA7213_AMP_EN_SHIFT , DA7213_NO_INVERT , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Headphone Right PGA " , DA7213_HP_R_CTRL ,
DA7213_AMP_EN_SHIFT , DA7213_NO_INVERT , NULL , 0 ) ,
/* Charge Pump */
SND_SOC_DAPM_SUPPLY ( " Charge Pump " , DA7213_CP_CTRL , DA7213_CP_EN_SHIFT ,
DA7213_NO_INVERT , NULL , 0 ) ,
/* Output Lines */
SND_SOC_DAPM_OUTPUT ( " HPL " ) ,
SND_SOC_DAPM_OUTPUT ( " HPR " ) ,
SND_SOC_DAPM_OUTPUT ( " LINE " ) ,
} ;
/*
* DAPM audio route definition
*/
static const struct snd_soc_dapm_route da7213_audio_map [ ] = {
/* Dest Connecting Widget source */
/* Input path */
2020-05-11 16:25:41 +03:00
{ " Mic Bias 1 " , NULL , " VDDMIC " } ,
{ " Mic Bias 2 " , NULL , " VDDMIC " } ,
2013-02-14 16:02:51 +04:00
{ " MIC1 " , NULL , " Mic Bias 1 " } ,
{ " MIC2 " , NULL , " Mic Bias 2 " } ,
{ " Mic 1 Amp Source MUX " , " Differential " , " MIC1 " } ,
{ " Mic 1 Amp Source MUX " , " MIC_P " , " MIC1 " } ,
{ " Mic 1 Amp Source MUX " , " MIC_N " , " MIC1 " } ,
{ " Mic 2 Amp Source MUX " , " Differential " , " MIC2 " } ,
{ " Mic 2 Amp Source MUX " , " MIC_P " , " MIC2 " } ,
{ " Mic 2 Amp Source MUX " , " MIC_N " , " MIC2 " } ,
{ " Mic 1 PGA " , NULL , " Mic 1 Amp Source MUX " } ,
{ " Mic 2 PGA " , NULL , " Mic 2 Amp Source MUX " } ,
{ " Aux Left PGA " , NULL , " AUXL " } ,
{ " Aux Right PGA " , NULL , " AUXR " } ,
{ " Mixin Left " , " Aux Left Switch " , " Aux Left PGA " } ,
{ " Mixin Left " , " Mic 1 Switch " , " Mic 1 PGA " } ,
{ " Mixin Left " , " Mic 2 Switch " , " Mic 2 PGA " } ,
{ " Mixin Left " , " Mixin Right Switch " , " Mixin Right PGA " } ,
{ " Mixin Right " , " Aux Right Switch " , " Aux Right PGA " } ,
{ " Mixin Right " , " Mic 2 Switch " , " Mic 2 PGA " } ,
{ " Mixin Right " , " Mic 1 Switch " , " Mic 1 PGA " } ,
{ " Mixin Right " , " Mixin Left Switch " , " Mixin Left PGA " } ,
{ " Mixin Left PGA " , NULL , " Mixin Left " } ,
{ " ADC Left " , NULL , " Mixin Left PGA " } ,
{ " Mixin Right PGA " , NULL , " Mixin Right " } ,
{ " ADC Right " , NULL , " Mixin Right PGA " } ,
{ " DAI Left Source MUX " , " ADC Left " , " ADC Left " } ,
{ " DAI Left Source MUX " , " ADC Right " , " ADC Right " } ,
{ " DAI Left Source MUX " , " DAI Input Left " , " DAIINL " } ,
{ " DAI Left Source MUX " , " DAI Input Right " , " DAIINR " } ,
{ " DAI Right Source MUX " , " ADC Left " , " ADC Left " } ,
{ " DAI Right Source MUX " , " ADC Right " , " ADC Right " } ,
{ " DAI Right Source MUX " , " DAI Input Left " , " DAIINL " } ,
{ " DAI Right Source MUX " , " DAI Input Right " , " DAIINR " } ,
{ " DAIOUTL " , NULL , " DAI Left Source MUX " } ,
{ " DAIOUTR " , NULL , " DAI Right Source MUX " } ,
{ " DAIOUTL " , NULL , " DAI " } ,
{ " DAIOUTR " , NULL , " DAI " } ,
/* Output path */
{ " DAIINL " , NULL , " DAI " } ,
{ " DAIINR " , NULL , " DAI " } ,
{ " DAC Left Source MUX " , " ADC Output Left " , " ADC Left " } ,
{ " DAC Left Source MUX " , " ADC Output Right " , " ADC Right " } ,
{ " DAC Left Source MUX " , " DAI Input Left " , " DAIINL " } ,
{ " DAC Left Source MUX " , " DAI Input Right " , " DAIINR " } ,
{ " DAC Right Source MUX " , " ADC Output Left " , " ADC Left " } ,
{ " DAC Right Source MUX " , " ADC Output Right " , " ADC Right " } ,
{ " DAC Right Source MUX " , " DAI Input Left " , " DAIINL " } ,
{ " DAC Right Source MUX " , " DAI Input Right " , " DAIINR " } ,
{ " DAC Left " , NULL , " DAC Left Source MUX " } ,
{ " DAC Right " , NULL , " DAC Right Source MUX " } ,
{ " Mixout Left " , " Aux Left Switch " , " Aux Left PGA " } ,
{ " Mixout Left " , " Mixin Left Switch " , " Mixin Left PGA " } ,
{ " Mixout Left " , " Mixin Right Switch " , " Mixin Right PGA " } ,
{ " Mixout Left " , " DAC Left Switch " , " DAC Left " } ,
{ " Mixout Left " , " Aux Left Invert Switch " , " Aux Left PGA " } ,
{ " Mixout Left " , " Mixin Left Invert Switch " , " Mixin Left PGA " } ,
{ " Mixout Left " , " Mixin Right Invert Switch " , " Mixin Right PGA " } ,
{ " Mixout Right " , " Aux Right Switch " , " Aux Right PGA " } ,
{ " Mixout Right " , " Mixin Right Switch " , " Mixin Right PGA " } ,
{ " Mixout Right " , " Mixin Left Switch " , " Mixin Left PGA " } ,
{ " Mixout Right " , " DAC Right Switch " , " DAC Right " } ,
{ " Mixout Right " , " Aux Right Invert Switch " , " Aux Right PGA " } ,
{ " Mixout Right " , " Mixin Right Invert Switch " , " Mixin Right PGA " } ,
{ " Mixout Right " , " Mixin Left Invert Switch " , " Mixin Left PGA " } ,
{ " Mixout Left PGA " , NULL , " Mixout Left " } ,
{ " Mixout Right PGA " , NULL , " Mixout Right " } ,
{ " Headphone Left PGA " , NULL , " Mixout Left PGA " } ,
{ " Headphone Left PGA " , NULL , " Charge Pump " } ,
{ " HPL " , NULL , " Headphone Left PGA " } ,
{ " Headphone Right PGA " , NULL , " Mixout Right PGA " } ,
{ " Headphone Right PGA " , NULL , " Charge Pump " } ,
{ " HPR " , NULL , " Headphone Right PGA " } ,
{ " Lineout PGA " , NULL , " Mixout Right PGA " } ,
{ " LINE " , NULL , " Lineout PGA " } ,
} ;
2015-07-05 12:48:29 +03:00
static const struct reg_default da7213_reg_defaults [ ] = {
2013-02-14 16:02:51 +04:00
{ DA7213_DIG_ROUTING_DAI , 0x10 } ,
{ DA7213_SR , 0x0A } ,
{ DA7213_REFERENCES , 0x80 } ,
{ DA7213_PLL_FRAC_TOP , 0x00 } ,
{ DA7213_PLL_FRAC_BOT , 0x00 } ,
{ DA7213_PLL_INTEGER , 0x20 } ,
{ DA7213_PLL_CTRL , 0x0C } ,
{ DA7213_DAI_CLK_MODE , 0x01 } ,
{ DA7213_DAI_CTRL , 0x08 } ,
{ DA7213_DIG_ROUTING_DAC , 0x32 } ,
{ DA7213_AUX_L_GAIN , 0x35 } ,
{ DA7213_AUX_R_GAIN , 0x35 } ,
{ DA7213_MIXIN_L_SELECT , 0x00 } ,
{ DA7213_MIXIN_R_SELECT , 0x00 } ,
{ DA7213_MIXIN_L_GAIN , 0x03 } ,
{ DA7213_MIXIN_R_GAIN , 0x03 } ,
{ DA7213_ADC_L_GAIN , 0x6F } ,
{ DA7213_ADC_R_GAIN , 0x6F } ,
{ DA7213_ADC_FILTERS1 , 0x80 } ,
{ DA7213_MIC_1_GAIN , 0x01 } ,
{ DA7213_MIC_2_GAIN , 0x01 } ,
{ DA7213_DAC_FILTERS5 , 0x00 } ,
{ DA7213_DAC_FILTERS2 , 0x88 } ,
{ DA7213_DAC_FILTERS3 , 0x88 } ,
{ DA7213_DAC_FILTERS4 , 0x08 } ,
{ DA7213_DAC_FILTERS1 , 0x80 } ,
{ DA7213_DAC_L_GAIN , 0x6F } ,
{ DA7213_DAC_R_GAIN , 0x6F } ,
{ DA7213_CP_CTRL , 0x61 } ,
{ DA7213_HP_L_GAIN , 0x39 } ,
{ DA7213_HP_R_GAIN , 0x39 } ,
{ DA7213_LINE_GAIN , 0x30 } ,
{ DA7213_MIXOUT_L_SELECT , 0x00 } ,
{ DA7213_MIXOUT_R_SELECT , 0x00 } ,
{ DA7213_SYSTEM_MODES_INPUT , 0x00 } ,
{ DA7213_SYSTEM_MODES_OUTPUT , 0x00 } ,
{ DA7213_AUX_L_CTRL , 0x44 } ,
{ DA7213_AUX_R_CTRL , 0x44 } ,
{ DA7213_MICBIAS_CTRL , 0x11 } ,
{ DA7213_MIC_1_CTRL , 0x40 } ,
{ DA7213_MIC_2_CTRL , 0x40 } ,
{ DA7213_MIXIN_L_CTRL , 0x40 } ,
{ DA7213_MIXIN_R_CTRL , 0x40 } ,
{ DA7213_ADC_L_CTRL , 0x40 } ,
{ DA7213_ADC_R_CTRL , 0x40 } ,
{ DA7213_DAC_L_CTRL , 0x48 } ,
{ DA7213_DAC_R_CTRL , 0x40 } ,
{ DA7213_HP_L_CTRL , 0x41 } ,
{ DA7213_HP_R_CTRL , 0x40 } ,
{ DA7213_LINE_CTRL , 0x40 } ,
{ DA7213_MIXOUT_L_CTRL , 0x10 } ,
{ DA7213_MIXOUT_R_CTRL , 0x10 } ,
{ DA7213_LDO_CTRL , 0x00 } ,
{ DA7213_IO_CTRL , 0x00 } ,
{ DA7213_GAIN_RAMP_CTRL , 0x00 } ,
{ DA7213_MIC_CONFIG , 0x00 } ,
{ DA7213_PC_COUNT , 0x00 } ,
{ DA7213_CP_VOL_THRESHOLD1 , 0x32 } ,
{ DA7213_CP_DELAY , 0x95 } ,
{ DA7213_CP_DETECTOR , 0x00 } ,
{ DA7213_DAI_OFFSET , 0x00 } ,
{ DA7213_DIG_CTRL , 0x00 } ,
{ DA7213_ALC_CTRL2 , 0x00 } ,
{ DA7213_ALC_CTRL3 , 0x00 } ,
{ DA7213_ALC_NOISE , 0x3F } ,
{ DA7213_ALC_TARGET_MIN , 0x3F } ,
{ DA7213_ALC_TARGET_MAX , 0x00 } ,
{ DA7213_ALC_GAIN_LIMITS , 0xFF } ,
{ DA7213_ALC_ANA_GAIN_LIMITS , 0x71 } ,
{ DA7213_ALC_ANTICLIP_CTRL , 0x00 } ,
{ DA7213_ALC_ANTICLIP_LEVEL , 0x00 } ,
{ DA7213_ALC_OFFSET_MAN_M_L , 0x00 } ,
{ DA7213_ALC_OFFSET_MAN_U_L , 0x00 } ,
{ DA7213_ALC_OFFSET_MAN_M_R , 0x00 } ,
{ DA7213_ALC_OFFSET_MAN_U_R , 0x00 } ,
{ DA7213_ALC_CIC_OP_LVL_CTRL , 0x00 } ,
{ DA7213_DAC_NG_SETUP_TIME , 0x00 } ,
{ DA7213_DAC_NG_OFF_THRESHOLD , 0x00 } ,
{ DA7213_DAC_NG_ON_THRESHOLD , 0x00 } ,
{ DA7213_DAC_NG_CTRL , 0x00 } ,
} ;
static bool da7213_volatile_register ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case DA7213_STATUS1 :
case DA7213_PLL_STATUS :
case DA7213_AUX_L_GAIN_STATUS :
case DA7213_AUX_R_GAIN_STATUS :
case DA7213_MIC_1_GAIN_STATUS :
case DA7213_MIC_2_GAIN_STATUS :
case DA7213_MIXIN_L_GAIN_STATUS :
case DA7213_MIXIN_R_GAIN_STATUS :
case DA7213_ADC_L_GAIN_STATUS :
case DA7213_ADC_R_GAIN_STATUS :
case DA7213_DAC_L_GAIN_STATUS :
case DA7213_DAC_R_GAIN_STATUS :
case DA7213_HP_L_GAIN_STATUS :
case DA7213_HP_R_GAIN_STATUS :
case DA7213_LINE_GAIN_STATUS :
case DA7213_ALC_CTRL1 :
case DA7213_ALC_OFFSET_AUTO_M_L :
case DA7213_ALC_OFFSET_AUTO_U_L :
case DA7213_ALC_OFFSET_AUTO_M_R :
case DA7213_ALC_OFFSET_AUTO_U_R :
case DA7213_ALC_CIC_OP_LVL_DATA :
2018-08-05 00:54:10 +03:00
return true ;
2013-02-14 16:02:51 +04:00
default :
2018-08-05 00:54:10 +03:00
return false ;
2013-02-14 16:02:51 +04:00
}
}
static int da7213_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params ,
struct snd_soc_dai * dai )
{
2018-01-29 07:03:13 +03:00
struct snd_soc_component * component = dai - > component ;
2020-06-26 19:46:23 +03:00
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2022-12-14 07:40:58 +03:00
u8 dai_clk_mode = DA7213_DAI_BCLKS_PER_WCLK_64 ;
2013-02-14 16:02:51 +04:00
u8 dai_ctrl = 0 ;
u8 fs ;
2022-12-14 07:40:58 +03:00
/* Set channels */
switch ( params_channels ( params ) ) {
case 1 :
if ( da7213 - > fmt ! = DA7213_DAI_FORMAT_DSP ) {
dev_err ( component - > dev , " Mono supported only in DSP mode \n " ) ;
return - EINVAL ;
}
dai_ctrl | = DA7213_DAI_MONO_MODE_EN ;
break ;
case 2 :
dai_ctrl & = ~ ( DA7213_DAI_MONO_MODE_EN ) ;
break ;
default :
return - EINVAL ;
}
2013-02-14 16:02:51 +04:00
/* Set DAI format */
2014-01-08 23:49:51 +04:00
switch ( params_width ( params ) ) {
case 16 :
2013-02-14 16:02:51 +04:00
dai_ctrl | = DA7213_DAI_WORD_LENGTH_S16_LE ;
2022-12-14 07:40:58 +03:00
dai_clk_mode = DA7213_DAI_BCLKS_PER_WCLK_32 ; /* 32bit for 1ch and 2ch */
2013-02-14 16:02:51 +04:00
break ;
2014-01-08 23:49:51 +04:00
case 20 :
2013-02-14 16:02:51 +04:00
dai_ctrl | = DA7213_DAI_WORD_LENGTH_S20_LE ;
break ;
2014-01-08 23:49:51 +04:00
case 24 :
2013-02-14 16:02:51 +04:00
dai_ctrl | = DA7213_DAI_WORD_LENGTH_S24_LE ;
break ;
2014-01-08 23:49:51 +04:00
case 32 :
2013-02-14 16:02:51 +04:00
dai_ctrl | = DA7213_DAI_WORD_LENGTH_S32_LE ;
break ;
default :
return - EINVAL ;
}
/* Set sampling rate */
switch ( params_rate ( params ) ) {
case 8000 :
fs = DA7213_SR_8000 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_98304000 ;
2013-02-14 16:02:51 +04:00
break ;
case 11025 :
fs = DA7213_SR_11025 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_90316800 ;
2013-02-14 16:02:51 +04:00
break ;
case 12000 :
fs = DA7213_SR_12000 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_98304000 ;
2013-02-14 16:02:51 +04:00
break ;
case 16000 :
fs = DA7213_SR_16000 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_98304000 ;
2013-02-14 16:02:51 +04:00
break ;
case 22050 :
fs = DA7213_SR_22050 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_90316800 ;
2013-02-14 16:02:51 +04:00
break ;
case 32000 :
fs = DA7213_SR_32000 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_98304000 ;
2013-02-14 16:02:51 +04:00
break ;
case 44100 :
fs = DA7213_SR_44100 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_90316800 ;
2013-02-14 16:02:51 +04:00
break ;
case 48000 :
fs = DA7213_SR_48000 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_98304000 ;
2013-02-14 16:02:51 +04:00
break ;
case 88200 :
fs = DA7213_SR_88200 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_90316800 ;
2013-02-14 16:02:51 +04:00
break ;
case 96000 :
fs = DA7213_SR_96000 ;
2020-06-26 19:46:23 +03:00
da7213 - > out_rate = DA7213_PLL_FREQ_OUT_98304000 ;
2013-02-14 16:02:51 +04:00
break ;
default :
return - EINVAL ;
}
2022-12-14 07:40:58 +03:00
snd_soc_component_update_bits ( component , DA7213_DAI_CLK_MODE ,
DA7213_DAI_BCLKS_PER_WCLK_MASK , dai_clk_mode ) ;
snd_soc_component_update_bits ( component , DA7213_DAI_CTRL ,
DA7213_DAI_WORD_LENGTH_MASK | DA7213_DAI_MONO_MODE_MASK , dai_ctrl ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_SR , fs ) ;
2013-02-14 16:02:51 +04:00
return 0 ;
}
static int da7213_set_dai_fmt ( struct snd_soc_dai * codec_dai , unsigned int fmt )
{
2018-01-29 07:03:13 +03:00
struct snd_soc_component * component = codec_dai - > component ;
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2013-02-14 16:02:51 +04:00
u8 dai_clk_mode = 0 , dai_ctrl = 0 ;
2017-11-09 01:42:31 +03:00
u8 dai_offset = 0 ;
2013-02-14 16:02:51 +04:00
/* Set master/slave mode */
switch ( fmt & SND_SOC_DAIFMT_MASTER_MASK ) {
case SND_SOC_DAIFMT_CBM_CFM :
da7213 - > master = true ;
break ;
case SND_SOC_DAIFMT_CBS_CFS :
da7213 - > master = false ;
break ;
default :
return - EINVAL ;
}
/* Set clock normal/inverted */
2017-11-09 01:42:31 +03:00
switch ( fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
case SND_SOC_DAIFMT_I2S :
case SND_SOC_DAIFMT_LEFT_J :
case SND_SOC_DAIFMT_RIGHT_J :
switch ( fmt & SND_SOC_DAIFMT_INV_MASK ) {
case SND_SOC_DAIFMT_NB_NF :
break ;
case SND_SOC_DAIFMT_NB_IF :
dai_clk_mode | = DA7213_DAI_WCLK_POL_INV ;
break ;
case SND_SOC_DAIFMT_IB_NF :
dai_clk_mode | = DA7213_DAI_CLK_POL_INV ;
break ;
case SND_SOC_DAIFMT_IB_IF :
dai_clk_mode | = DA7213_DAI_WCLK_POL_INV |
DA7213_DAI_CLK_POL_INV ;
break ;
default :
return - EINVAL ;
}
2013-02-14 16:02:51 +04:00
break ;
2017-11-09 01:42:31 +03:00
case SND_SOC_DAI_FORMAT_DSP_A :
case SND_SOC_DAI_FORMAT_DSP_B :
/* The bclk is inverted wrt ASoC conventions */
switch ( fmt & SND_SOC_DAIFMT_INV_MASK ) {
case SND_SOC_DAIFMT_NB_NF :
dai_clk_mode | = DA7213_DAI_CLK_POL_INV ;
break ;
case SND_SOC_DAIFMT_NB_IF :
dai_clk_mode | = DA7213_DAI_WCLK_POL_INV |
DA7213_DAI_CLK_POL_INV ;
break ;
case SND_SOC_DAIFMT_IB_NF :
break ;
case SND_SOC_DAIFMT_IB_IF :
dai_clk_mode | = DA7213_DAI_WCLK_POL_INV ;
break ;
default :
return - EINVAL ;
}
2013-02-14 16:02:51 +04:00
break ;
default :
return - EINVAL ;
}
/* Only I2S is supported */
switch ( fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
case SND_SOC_DAIFMT_I2S :
dai_ctrl | = DA7213_DAI_FORMAT_I2S_MODE ;
2022-12-14 07:40:58 +03:00
da7213 - > fmt = DA7213_DAI_FORMAT_I2S_MODE ;
2013-02-14 16:02:51 +04:00
break ;
case SND_SOC_DAIFMT_LEFT_J :
dai_ctrl | = DA7213_DAI_FORMAT_LEFT_J ;
2022-12-14 07:40:58 +03:00
da7213 - > fmt = DA7213_DAI_FORMAT_LEFT_J ;
2013-02-14 16:02:51 +04:00
break ;
case SND_SOC_DAIFMT_RIGHT_J :
dai_ctrl | = DA7213_DAI_FORMAT_RIGHT_J ;
2022-12-14 07:40:58 +03:00
da7213 - > fmt = DA7213_DAI_FORMAT_RIGHT_J ;
2013-02-14 16:02:51 +04:00
break ;
2017-11-09 01:42:31 +03:00
case SND_SOC_DAI_FORMAT_DSP_A : /* L data MSB after FRM LRC */
dai_ctrl | = DA7213_DAI_FORMAT_DSP ;
dai_offset = 1 ;
2022-12-14 07:40:58 +03:00
da7213 - > fmt = DA7213_DAI_FORMAT_DSP ;
2017-11-09 01:42:31 +03:00
break ;
case SND_SOC_DAI_FORMAT_DSP_B : /* L data MSB during FRM LRC */
dai_ctrl | = DA7213_DAI_FORMAT_DSP ;
2022-12-14 07:40:58 +03:00
da7213 - > fmt = DA7213_DAI_FORMAT_DSP ;
2017-11-09 01:42:31 +03:00
break ;
2013-02-14 16:02:51 +04:00
default :
return - EINVAL ;
}
2016-08-04 17:35:37 +03:00
/* By default only 64 BCLK per WCLK is supported */
dai_clk_mode | = DA7213_DAI_BCLKS_PER_WCLK_64 ;
2013-02-14 16:02:51 +04:00
2019-05-01 12:04:24 +03:00
snd_soc_component_update_bits ( component , DA7213_DAI_CLK_MODE ,
DA7213_DAI_BCLKS_PER_WCLK_MASK |
DA7213_DAI_CLK_POL_MASK | DA7213_DAI_WCLK_POL_MASK ,
dai_clk_mode ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAI_CTRL , DA7213_DAI_FORMAT_MASK ,
2013-02-14 16:02:51 +04:00
dai_ctrl ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_DAI_OFFSET , dai_offset ) ;
2013-02-14 16:02:51 +04:00
return 0 ;
}
2020-07-09 04:57:02 +03:00
static int da7213_mute ( struct snd_soc_dai * dai , int mute , int direction )
2013-02-14 16:02:51 +04:00
{
2018-01-29 07:03:13 +03:00
struct snd_soc_component * component = dai - > component ;
2013-02-14 16:02:51 +04:00
if ( mute ) {
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAC_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MUTE_EN , DA7213_MUTE_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAC_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MUTE_EN , DA7213_MUTE_EN ) ;
} else {
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAC_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MUTE_EN , 0 ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAC_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MUTE_EN , 0 ) ;
}
return 0 ;
}
# define DA7213_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE )
2020-05-11 16:25:42 +03:00
static int da7213_set_component_sysclk ( struct snd_soc_component * component ,
int clk_id , int source ,
unsigned int freq , int dir )
2013-02-14 16:02:51 +04:00
{
2018-01-29 07:03:13 +03:00
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2015-10-07 16:27:11 +03:00
int ret = 0 ;
if ( ( da7213 - > clk_src = = clk_id ) & & ( da7213 - > mclk_rate = = freq ) )
return 0 ;
if ( ( ( freq < 5000000 ) & & ( freq ! = 32768 ) ) | | ( freq > 54000000 ) ) {
2020-05-11 16:25:42 +03:00
dev_err ( component - > dev , " Unsupported MCLK value %d \n " ,
2015-10-07 16:27:11 +03:00
freq ) ;
return - EINVAL ;
}
2013-02-14 16:02:51 +04:00
switch ( clk_id ) {
case DA7213_CLKSRC_MCLK :
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_PLL_CTRL ,
2016-08-04 17:35:40 +03:00
DA7213_PLL_MCLK_SQR_EN , 0 ) ;
2015-10-07 16:27:11 +03:00
break ;
case DA7213_CLKSRC_MCLK_SQR :
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_PLL_CTRL ,
2016-08-04 17:35:40 +03:00
DA7213_PLL_MCLK_SQR_EN ,
DA7213_PLL_MCLK_SQR_EN ) ;
2013-02-14 16:02:51 +04:00
break ;
default :
2020-05-11 16:25:42 +03:00
dev_err ( component - > dev , " Unknown clock source %d \n " , clk_id ) ;
2013-02-14 16:02:51 +04:00
return - EINVAL ;
}
2015-10-07 16:27:11 +03:00
da7213 - > clk_src = clk_id ;
if ( da7213 - > mclk ) {
freq = clk_round_rate ( da7213 - > mclk , freq ) ;
ret = clk_set_rate ( da7213 - > mclk , freq ) ;
if ( ret ) {
2020-05-11 16:25:42 +03:00
dev_err ( component - > dev , " Failed to set clock rate %d \n " ,
2015-10-07 16:27:11 +03:00
freq ) ;
return ret ;
}
}
da7213 - > mclk_rate = freq ;
return 0 ;
2013-02-14 16:02:51 +04:00
}
2016-08-04 17:35:40 +03:00
/* Supported PLL input frequencies are 32KHz, 5MHz - 54MHz. */
2020-06-26 19:46:23 +03:00
static int _da7213_set_component_pll ( struct snd_soc_component * component ,
int pll_id , int source ,
unsigned int fref , unsigned int fout )
2013-02-14 16:02:51 +04:00
{
2018-01-29 07:03:13 +03:00
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2013-02-14 16:02:51 +04:00
u8 pll_ctrl , indiv_bits , indiv ;
u8 pll_frac_top , pll_frac_bot , pll_integer ;
u32 freq_ref ;
u64 frac_div ;
/* Workout input divider based on MCLK rate */
2016-05-10 18:11:08 +03:00
if ( da7213 - > mclk_rate = = 32768 ) {
2016-08-04 17:35:40 +03:00
if ( ! da7213 - > master ) {
2018-01-29 07:03:13 +03:00
dev_err ( component - > dev ,
2016-08-04 17:35:40 +03:00
" 32KHz only valid if codec is clock master \n " ) ;
return - EINVAL ;
}
2013-02-14 16:02:51 +04:00
/* 32KHz PLL Mode */
2016-05-10 18:11:07 +03:00
indiv_bits = DA7213_PLL_INDIV_9_TO_18_MHZ ;
indiv = DA7213_PLL_INDIV_9_TO_18_MHZ_VAL ;
2016-08-04 17:35:40 +03:00
source = DA7213_SYSCLK_PLL_32KHZ ;
2013-02-14 16:02:51 +04:00
freq_ref = 3750000 ;
2016-08-04 17:35:40 +03:00
2013-02-14 16:02:51 +04:00
} else {
if ( da7213 - > mclk_rate < 5000000 ) {
2018-01-29 07:03:13 +03:00
dev_err ( component - > dev ,
2016-08-04 17:35:40 +03:00
" PLL input clock %d below valid range \n " ,
da7213 - > mclk_rate ) ;
return - EINVAL ;
2016-05-10 18:11:07 +03:00
} else if ( da7213 - > mclk_rate < = 9000000 ) {
indiv_bits = DA7213_PLL_INDIV_5_TO_9_MHZ ;
indiv = DA7213_PLL_INDIV_5_TO_9_MHZ_VAL ;
} else if ( da7213 - > mclk_rate < = 18000000 ) {
indiv_bits = DA7213_PLL_INDIV_9_TO_18_MHZ ;
indiv = DA7213_PLL_INDIV_9_TO_18_MHZ_VAL ;
} else if ( da7213 - > mclk_rate < = 36000000 ) {
indiv_bits = DA7213_PLL_INDIV_18_TO_36_MHZ ;
indiv = DA7213_PLL_INDIV_18_TO_36_MHZ_VAL ;
2013-02-14 16:02:51 +04:00
} else if ( da7213 - > mclk_rate < = 54000000 ) {
2016-05-10 18:11:07 +03:00
indiv_bits = DA7213_PLL_INDIV_36_TO_54_MHZ ;
indiv = DA7213_PLL_INDIV_36_TO_54_MHZ_VAL ;
2013-02-14 16:02:51 +04:00
} else {
2018-01-29 07:03:13 +03:00
dev_err ( component - > dev ,
2016-08-04 17:35:40 +03:00
" PLL input clock %d above valid range \n " ,
da7213 - > mclk_rate ) ;
return - EINVAL ;
2013-02-14 16:02:51 +04:00
}
freq_ref = ( da7213 - > mclk_rate / indiv ) ;
}
2016-08-04 17:35:40 +03:00
pll_ctrl = indiv_bits ;
2013-02-14 16:02:51 +04:00
2016-08-04 17:35:40 +03:00
/* Configure PLL */
switch ( source ) {
case DA7213_SYSCLK_MCLK :
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_PLL_CTRL ,
2016-08-04 17:35:40 +03:00
DA7213_PLL_INDIV_MASK |
DA7213_PLL_MODE_MASK , pll_ctrl ) ;
2013-02-14 16:02:51 +04:00
return 0 ;
2016-08-04 17:35:40 +03:00
case DA7213_SYSCLK_PLL :
break ;
case DA7213_SYSCLK_PLL_SRM :
pll_ctrl | = DA7213_PLL_SRM_EN ;
fout = DA7213_PLL_FREQ_OUT_94310400 ;
break ;
case DA7213_SYSCLK_PLL_32KHZ :
if ( da7213 - > mclk_rate ! = 32768 ) {
2018-01-29 07:03:13 +03:00
dev_err ( component - > dev ,
2016-08-04 17:35:40 +03:00
" 32KHz mode only valid with 32KHz MCLK \n " ) ;
return - EINVAL ;
}
2013-02-14 16:02:51 +04:00
2016-08-04 17:35:40 +03:00
pll_ctrl | = DA7213_PLL_32K_MODE | DA7213_PLL_SRM_EN ;
2013-02-14 16:02:51 +04:00
fout = DA7213_PLL_FREQ_OUT_94310400 ;
2016-08-04 17:35:40 +03:00
break ;
default :
2018-01-29 07:03:13 +03:00
dev_err ( component - > dev , " Invalid PLL config \n " ) ;
2016-08-04 17:35:40 +03:00
return - EINVAL ;
2013-02-14 16:02:51 +04:00
}
/* Calculate dividers for PLL */
pll_integer = fout / freq_ref ;
frac_div = ( u64 ) ( fout % freq_ref ) * 8192ULL ;
do_div ( frac_div , freq_ref ) ;
pll_frac_top = ( frac_div > > DA7213_BYTE_SHIFT ) & DA7213_BYTE_MASK ;
pll_frac_bot = ( frac_div ) & DA7213_BYTE_MASK ;
/* Write PLL dividers */
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , DA7213_PLL_FRAC_TOP , pll_frac_top ) ;
snd_soc_component_write ( component , DA7213_PLL_FRAC_BOT , pll_frac_bot ) ;
snd_soc_component_write ( component , DA7213_PLL_INTEGER , pll_integer ) ;
2013-02-14 16:02:51 +04:00
/* Enable PLL */
pll_ctrl | = DA7213_PLL_EN ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_PLL_CTRL ,
2016-08-04 17:35:40 +03:00
DA7213_PLL_INDIV_MASK | DA7213_PLL_MODE_MASK ,
pll_ctrl ) ;
2013-02-14 16:02:51 +04:00
2016-08-04 17:35:41 +03:00
/* Assist 32KHz mode PLL lock */
if ( source = = DA7213_SYSCLK_PLL_32KHZ ) {
2018-01-29 07:03:13 +03:00
snd_soc_component_write ( component , 0xF0 , 0x8B ) ;
snd_soc_component_write ( component , 0xF1 , 0x03 ) ;
snd_soc_component_write ( component , 0xF1 , 0x01 ) ;
snd_soc_component_write ( component , 0xF0 , 0x00 ) ;
2016-08-04 17:35:41 +03:00
}
2013-02-14 16:02:51 +04:00
return 0 ;
}
2020-06-26 19:46:23 +03:00
static int da7213_set_component_pll ( struct snd_soc_component * component ,
int pll_id , int source ,
unsigned int fref , unsigned int fout )
{
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
da7213 - > fixed_clk_auto_pll = false ;
return _da7213_set_component_pll ( component , pll_id , source , fref , fout ) ;
}
2013-02-14 16:02:51 +04:00
/* DAI operations */
static const struct snd_soc_dai_ops da7213_dai_ops = {
. hw_params = da7213_hw_params ,
. set_fmt = da7213_set_dai_fmt ,
2020-07-09 04:57:02 +03:00
. mute_stream = da7213_mute ,
. no_capture_mute = 1 ,
2013-02-14 16:02:51 +04:00
} ;
static struct snd_soc_dai_driver da7213_dai = {
. name = " da7213-hifi " ,
/* Playback Capabilities */
. playback = {
. stream_name = " Playback " ,
. channels_min = 1 ,
. channels_max = 2 ,
. rates = SNDRV_PCM_RATE_8000_96000 ,
. formats = DA7213_FORMATS ,
} ,
/* Capture Capabilities */
. capture = {
. stream_name = " Capture " ,
. channels_min = 1 ,
. channels_max = 2 ,
. rates = SNDRV_PCM_RATE_8000_96000 ,
. formats = DA7213_FORMATS ,
} ,
. ops = & da7213_dai_ops ,
2021-01-15 07:54:33 +03:00
. symmetric_rate = 1 ,
2013-02-14 16:02:51 +04:00
} ;
2020-06-26 19:46:23 +03:00
static int da7213_set_auto_pll ( struct snd_soc_component * component , bool enable )
{
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
int mode ;
if ( ! da7213 - > fixed_clk_auto_pll )
return 0 ;
da7213 - > mclk_rate = clk_get_rate ( da7213 - > mclk ) ;
if ( enable ) {
/* Slave mode needs SRM for non-harmonic frequencies */
if ( da7213 - > master )
mode = DA7213_SYSCLK_PLL ;
else
mode = DA7213_SYSCLK_PLL_SRM ;
/* PLL is not required for harmonic frequencies */
switch ( da7213 - > out_rate ) {
case DA7213_PLL_FREQ_OUT_90316800 :
if ( da7213 - > mclk_rate = = 11289600 | |
da7213 - > mclk_rate = = 22579200 | |
da7213 - > mclk_rate = = 45158400 )
mode = DA7213_SYSCLK_MCLK ;
break ;
case DA7213_PLL_FREQ_OUT_98304000 :
if ( da7213 - > mclk_rate = = 12288000 | |
da7213 - > mclk_rate = = 24576000 | |
da7213 - > mclk_rate = = 49152000 )
mode = DA7213_SYSCLK_MCLK ;
break ;
default :
return - 1 ;
}
} else {
/* Disable PLL in standby */
mode = DA7213_SYSCLK_MCLK ;
}
return _da7213_set_component_pll ( component , 0 , mode ,
da7213 - > mclk_rate , da7213 - > out_rate ) ;
}
2018-01-29 07:03:13 +03:00
static int da7213_set_bias_level ( struct snd_soc_component * component ,
2013-02-14 16:02:51 +04:00
enum snd_soc_bias_level level )
{
2018-01-29 07:03:13 +03:00
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2015-10-07 16:27:11 +03:00
int ret ;
2013-02-14 16:02:51 +04:00
switch ( level ) {
case SND_SOC_BIAS_ON :
break ;
2016-08-04 17:35:39 +03:00
case SND_SOC_BIAS_PREPARE :
/* Enable MCLK for transition to ON state */
2018-01-29 07:03:13 +03:00
if ( snd_soc_component_get_bias_level ( component ) = = SND_SOC_BIAS_STANDBY ) {
2015-10-07 16:27:11 +03:00
if ( da7213 - > mclk ) {
ret = clk_prepare_enable ( da7213 - > mclk ) ;
if ( ret ) {
2018-01-29 07:03:13 +03:00
dev_err ( component - > dev ,
2015-10-07 16:27:11 +03:00
" Failed to enable mclk \n " ) ;
return ret ;
}
2020-06-26 19:46:23 +03:00
da7213_set_auto_pll ( component , true ) ;
2015-10-07 16:27:11 +03:00
}
2016-08-04 17:35:39 +03:00
}
break ;
case SND_SOC_BIAS_STANDBY :
2018-01-29 07:03:13 +03:00
if ( snd_soc_component_get_bias_level ( component ) = = SND_SOC_BIAS_OFF ) {
2013-02-14 16:02:51 +04:00
/* Enable VMID reference & master bias */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_REFERENCES ,
2013-02-14 16:02:51 +04:00
DA7213_VMID_EN | DA7213_BIAS_EN ,
DA7213_VMID_EN | DA7213_BIAS_EN ) ;
2016-08-04 17:35:39 +03:00
} else {
/* Remove MCLK */
2020-06-26 19:46:23 +03:00
if ( da7213 - > mclk ) {
da7213_set_auto_pll ( component , false ) ;
2016-08-04 17:35:39 +03:00
clk_disable_unprepare ( da7213 - > mclk ) ;
2020-06-26 19:46:23 +03:00
}
2013-02-14 16:02:51 +04:00
}
break ;
case SND_SOC_BIAS_OFF :
/* Disable VMID reference & master bias */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_REFERENCES ,
2013-02-14 16:02:51 +04:00
DA7213_VMID_EN | DA7213_BIAS_EN , 0 ) ;
break ;
}
return 0 ;
}
2017-03-10 03:18:58 +03:00
# if defined(CONFIG_OF)
2015-10-07 16:27:08 +03:00
/* DT */
static const struct of_device_id da7213_of_match [ ] = {
2020-05-11 16:25:40 +03:00
{ . compatible = " dlg,da7212 " , } ,
2015-10-07 16:27:08 +03:00
{ . compatible = " dlg,da7213 " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , da7213_of_match ) ;
2017-03-10 03:18:58 +03:00
# endif
# ifdef CONFIG_ACPI
static const struct acpi_device_id da7213_acpi_match [ ] = {
{ " DLGS7212 " , 0 } ,
{ " DLGS7213 " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( acpi , da7213_acpi_match ) ;
# endif
2015-10-07 16:27:08 +03:00
static enum da7213_micbias_voltage
2018-01-29 07:03:13 +03:00
da7213_of_micbias_lvl ( struct snd_soc_component * component , u32 val )
2015-10-07 16:27:08 +03:00
{
switch ( val ) {
case 1600 :
return DA7213_MICBIAS_1_6V ;
case 2200 :
return DA7213_MICBIAS_2_2V ;
case 2500 :
return DA7213_MICBIAS_2_5V ;
case 3000 :
return DA7213_MICBIAS_3_0V ;
default :
2018-01-29 07:03:13 +03:00
dev_warn ( component - > dev , " Invalid micbias level \n " ) ;
2015-10-07 16:27:08 +03:00
return DA7213_MICBIAS_2_2V ;
}
}
static enum da7213_dmic_data_sel
2018-01-29 07:03:13 +03:00
da7213_of_dmic_data_sel ( struct snd_soc_component * component , const char * str )
2015-10-07 16:27:08 +03:00
{
if ( ! strcmp ( str , " lrise_rfall " ) ) {
return DA7213_DMIC_DATA_LRISE_RFALL ;
} else if ( ! strcmp ( str , " lfall_rrise " ) ) {
return DA7213_DMIC_DATA_LFALL_RRISE ;
} else {
2018-01-29 07:03:13 +03:00
dev_warn ( component - > dev , " Invalid DMIC data select type \n " ) ;
2015-10-07 16:27:08 +03:00
return DA7213_DMIC_DATA_LRISE_RFALL ;
}
}
static enum da7213_dmic_samplephase
2018-01-29 07:03:13 +03:00
da7213_of_dmic_samplephase ( struct snd_soc_component * component , const char * str )
2015-10-07 16:27:08 +03:00
{
if ( ! strcmp ( str , " on_clkedge " ) ) {
return DA7213_DMIC_SAMPLE_ON_CLKEDGE ;
} else if ( ! strcmp ( str , " between_clkedge " ) ) {
return DA7213_DMIC_SAMPLE_BETWEEN_CLKEDGE ;
} else {
2018-01-29 07:03:13 +03:00
dev_warn ( component - > dev , " Invalid DMIC sample phase \n " ) ;
2015-10-07 16:27:08 +03:00
return DA7213_DMIC_SAMPLE_ON_CLKEDGE ;
}
}
static enum da7213_dmic_clk_rate
2018-01-29 07:03:13 +03:00
da7213_of_dmic_clkrate ( struct snd_soc_component * component , u32 val )
2015-10-07 16:27:08 +03:00
{
switch ( val ) {
case 1500000 :
return DA7213_DMIC_CLK_1_5MHZ ;
case 3000000 :
return DA7213_DMIC_CLK_3_0MHZ ;
default :
2018-01-29 07:03:13 +03:00
dev_warn ( component - > dev , " Invalid DMIC clock rate \n " ) ;
2015-10-07 16:27:08 +03:00
return DA7213_DMIC_CLK_1_5MHZ ;
}
}
static struct da7213_platform_data
2018-01-29 07:03:13 +03:00
* da7213_fw_to_pdata ( struct snd_soc_component * component )
2015-10-07 16:27:08 +03:00
{
2018-01-29 07:03:13 +03:00
struct device * dev = component - > dev ;
2015-10-07 16:27:08 +03:00
struct da7213_platform_data * pdata ;
2017-05-19 17:32:25 +03:00
const char * fw_str ;
u32 fw_val32 ;
2015-10-07 16:27:08 +03:00
2018-01-29 07:03:13 +03:00
pdata = devm_kzalloc ( component - > dev , sizeof ( * pdata ) , GFP_KERNEL ) ;
2017-11-23 19:56:54 +03:00
if ( ! pdata )
2015-10-07 16:27:08 +03:00
return NULL ;
2017-05-19 17:32:25 +03:00
if ( device_property_read_u32 ( dev , " dlg,micbias1-lvl " , & fw_val32 ) > = 0 )
2018-01-29 07:03:13 +03:00
pdata - > micbias1_lvl = da7213_of_micbias_lvl ( component , fw_val32 ) ;
2015-10-07 16:27:08 +03:00
else
pdata - > micbias1_lvl = DA7213_MICBIAS_2_2V ;
2017-05-19 17:32:25 +03:00
if ( device_property_read_u32 ( dev , " dlg,micbias2-lvl " , & fw_val32 ) > = 0 )
2018-01-29 07:03:13 +03:00
pdata - > micbias2_lvl = da7213_of_micbias_lvl ( component , fw_val32 ) ;
2015-10-07 16:27:08 +03:00
else
pdata - > micbias2_lvl = DA7213_MICBIAS_2_2V ;
2017-05-19 17:32:25 +03:00
if ( ! device_property_read_string ( dev , " dlg,dmic-data-sel " , & fw_str ) )
2018-01-29 07:03:13 +03:00
pdata - > dmic_data_sel = da7213_of_dmic_data_sel ( component , fw_str ) ;
2015-10-07 16:27:08 +03:00
else
pdata - > dmic_data_sel = DA7213_DMIC_DATA_LRISE_RFALL ;
2017-05-19 17:32:25 +03:00
if ( ! device_property_read_string ( dev , " dlg,dmic-samplephase " , & fw_str ) )
2015-10-07 16:27:08 +03:00
pdata - > dmic_samplephase =
2018-01-29 07:03:13 +03:00
da7213_of_dmic_samplephase ( component , fw_str ) ;
2015-10-07 16:27:08 +03:00
else
pdata - > dmic_samplephase = DA7213_DMIC_SAMPLE_ON_CLKEDGE ;
2017-05-19 17:32:25 +03:00
if ( device_property_read_u32 ( dev , " dlg,dmic-clkrate " , & fw_val32 ) > = 0 )
2018-01-29 07:03:13 +03:00
pdata - > dmic_clk_rate = da7213_of_dmic_clkrate ( component , fw_val32 ) ;
2015-10-07 16:27:08 +03:00
else
pdata - > dmic_clk_rate = DA7213_DMIC_CLK_3_0MHZ ;
return pdata ;
}
2018-01-29 07:03:13 +03:00
static int da7213_probe ( struct snd_soc_component * component )
2013-02-14 16:02:51 +04:00
{
2018-01-29 07:03:13 +03:00
struct da7213_priv * da7213 = snd_soc_component_get_drvdata ( component ) ;
2013-02-14 16:02:51 +04:00
2020-05-11 16:25:41 +03:00
pm_runtime_get_sync ( component - > dev ) ;
2013-02-14 16:02:51 +04:00
/* Default to using ALC auto offset calibration mode. */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ALC_CTRL1 ,
2013-02-14 16:02:51 +04:00
DA7213_ALC_CALIB_MODE_MAN , 0 ) ;
da7213 - > alc_calib_auto = true ;
2016-05-10 18:11:06 +03:00
/* Default PC counter to free-running */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_PC_COUNT , DA7213_PC_FREERUN_MASK ,
2016-05-10 18:11:06 +03:00
DA7213_PC_FREERUN_MASK ) ;
2013-02-14 16:02:51 +04:00
/* Enable all Gain Ramps */
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_AUX_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_AUX_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXIN_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXIN_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ADC_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_ADC_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAC_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_DAC_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_HP_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_HP_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_LINE_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_GAIN_RAMP_EN , DA7213_GAIN_RAMP_EN ) ;
/*
* There are two separate control bits for input and output mixers as
* well as headphone and line outs .
* One to enable corresponding amplifier and other to enable its
* output . As amplifier bits are related to power control , they are
* being managed by DAPM while other ( non power related ) bits are
* enabled here
*/
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXIN_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MIXIN_MIX_EN , DA7213_MIXIN_MIX_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXIN_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MIXIN_MIX_EN , DA7213_MIXIN_MIX_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXOUT_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MIXOUT_MIX_EN , DA7213_MIXOUT_MIX_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIXOUT_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MIXOUT_MIX_EN , DA7213_MIXOUT_MIX_EN ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_HP_L_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_HP_AMP_OE , DA7213_HP_AMP_OE ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_HP_R_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_HP_AMP_OE , DA7213_HP_AMP_OE ) ;
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_LINE_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_LINE_AMP_OE , DA7213_LINE_AMP_OE ) ;
2015-10-07 16:27:08 +03:00
/* Handle DT/Platform data */
2018-01-29 07:03:13 +03:00
da7213 - > pdata = dev_get_platdata ( component - > dev ) ;
2017-05-19 17:32:25 +03:00
if ( ! da7213 - > pdata )
2018-01-29 07:03:13 +03:00
da7213 - > pdata = da7213_fw_to_pdata ( component ) ;
2015-10-07 16:27:08 +03:00
2013-02-14 16:02:51 +04:00
/* Set platform data values */
if ( da7213 - > pdata ) {
2015-10-07 16:27:08 +03:00
struct da7213_platform_data * pdata = da7213 - > pdata ;
2013-02-14 16:02:51 +04:00
u8 micbias_lvl = 0 , dmic_cfg = 0 ;
/* Set Mic Bias voltages */
switch ( pdata - > micbias1_lvl ) {
case DA7213_MICBIAS_1_6V :
case DA7213_MICBIAS_2_2V :
case DA7213_MICBIAS_2_5V :
case DA7213_MICBIAS_3_0V :
micbias_lvl | = ( pdata - > micbias1_lvl < <
DA7213_MICBIAS1_LEVEL_SHIFT ) ;
break ;
}
switch ( pdata - > micbias2_lvl ) {
case DA7213_MICBIAS_1_6V :
case DA7213_MICBIAS_2_2V :
case DA7213_MICBIAS_2_5V :
case DA7213_MICBIAS_3_0V :
micbias_lvl | = ( pdata - > micbias2_lvl < <
DA7213_MICBIAS2_LEVEL_SHIFT ) ;
break ;
}
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MICBIAS_CTRL ,
2013-02-14 16:02:51 +04:00
DA7213_MICBIAS1_LEVEL_MASK |
DA7213_MICBIAS2_LEVEL_MASK , micbias_lvl ) ;
/* Set DMIC configuration */
switch ( pdata - > dmic_data_sel ) {
case DA7213_DMIC_DATA_LFALL_RRISE :
case DA7213_DMIC_DATA_LRISE_RFALL :
dmic_cfg | = ( pdata - > dmic_data_sel < <
DA7213_DMIC_DATA_SEL_SHIFT ) ;
break ;
}
2013-05-09 17:14:20 +04:00
switch ( pdata - > dmic_samplephase ) {
2013-02-14 16:02:51 +04:00
case DA7213_DMIC_SAMPLE_ON_CLKEDGE :
case DA7213_DMIC_SAMPLE_BETWEEN_CLKEDGE :
2013-05-09 17:14:20 +04:00
dmic_cfg | = ( pdata - > dmic_samplephase < <
2013-02-14 16:02:51 +04:00
DA7213_DMIC_SAMPLEPHASE_SHIFT ) ;
break ;
}
2013-05-09 17:14:20 +04:00
switch ( pdata - > dmic_clk_rate ) {
2013-02-14 16:02:51 +04:00
case DA7213_DMIC_CLK_3_0MHZ :
case DA7213_DMIC_CLK_1_5MHZ :
2013-05-09 17:14:20 +04:00
dmic_cfg | = ( pdata - > dmic_clk_rate < <
2013-02-14 16:02:51 +04:00
DA7213_DMIC_CLK_RATE_SHIFT ) ;
break ;
}
2018-01-29 07:03:13 +03:00
snd_soc_component_update_bits ( component , DA7213_MIC_CONFIG ,
2013-02-14 16:02:51 +04:00
DA7213_DMIC_DATA_SEL_MASK |
DA7213_DMIC_SAMPLEPHASE_MASK |
DA7213_DMIC_CLK_RATE_MASK , dmic_cfg ) ;
2015-10-07 16:27:11 +03:00
}
2013-02-14 16:02:51 +04:00
2020-05-11 16:25:41 +03:00
pm_runtime_put_sync ( component - > dev ) ;
2015-10-07 16:27:11 +03:00
/* Check if MCLK provided */
2018-01-29 07:03:13 +03:00
da7213 - > mclk = devm_clk_get ( component - > dev , " mclk " ) ;
2015-10-07 16:27:11 +03:00
if ( IS_ERR ( da7213 - > mclk ) ) {
if ( PTR_ERR ( da7213 - > mclk ) ! = - ENOENT )
return PTR_ERR ( da7213 - > mclk ) ;
else
da7213 - > mclk = NULL ;
2020-06-26 19:46:23 +03:00
} else {
/* Do automatic PLL handling assuming fixed clock until
* set_pll ( ) has been called . This makes the codec usable
* with the simple - audio - card driver . */
da7213 - > fixed_clk_auto_pll = true ;
2013-02-14 16:02:51 +04:00
}
2015-10-07 16:27:08 +03:00
2013-02-14 16:02:51 +04:00
return 0 ;
}
2018-01-29 07:03:13 +03:00
static const struct snd_soc_component_driver soc_component_dev_da7213 = {
2013-02-14 16:02:51 +04:00
. probe = da7213_probe ,
. set_bias_level = da7213_set_bias_level ,
2018-01-29 07:03:13 +03:00
. controls = da7213_snd_controls ,
. num_controls = ARRAY_SIZE ( da7213_snd_controls ) ,
. dapm_widgets = da7213_dapm_widgets ,
. num_dapm_widgets = ARRAY_SIZE ( da7213_dapm_widgets ) ,
. dapm_routes = da7213_audio_map ,
. num_dapm_routes = ARRAY_SIZE ( da7213_audio_map ) ,
2020-05-11 16:25:42 +03:00
. set_sysclk = da7213_set_component_sysclk ,
2020-05-11 16:25:43 +03:00
. set_pll = da7213_set_component_pll ,
2018-01-29 07:03:13 +03:00
. idle_bias_on = 1 ,
. use_pmdown_time = 1 ,
. endianness = 1 ,
2013-02-14 16:02:51 +04:00
} ;
static const struct regmap_config da7213_regmap_config = {
. reg_bits = 8 ,
. val_bits = 8 ,
. reg_defaults = da7213_reg_defaults ,
. num_reg_defaults = ARRAY_SIZE ( da7213_reg_defaults ) ,
. volatile_reg = da7213_volatile_register ,
. cache_type = REGCACHE_RBTREE ,
} ;
2020-05-11 16:25:41 +03:00
static void da7213_power_off ( void * data )
{
struct da7213_priv * da7213 = data ;
regulator_bulk_disable ( DA7213_NUM_SUPPLIES , da7213 - > supplies ) ;
}
static const char * da7213_supply_names [ DA7213_NUM_SUPPLIES ] = {
[ DA7213_SUPPLY_VDDA ] = " VDDA " ,
[ DA7213_SUPPLY_VDDIO ] = " VDDIO " ,
} ;
2022-03-25 20:12:43 +03:00
static int da7213_i2c_probe ( struct i2c_client * i2c )
2013-02-14 16:02:51 +04:00
{
struct da7213_priv * da7213 ;
2020-05-11 16:25:41 +03:00
int i , ret ;
2013-02-14 16:02:51 +04:00
2017-11-23 20:15:30 +03:00
da7213 = devm_kzalloc ( & i2c - > dev , sizeof ( * da7213 ) , GFP_KERNEL ) ;
2013-02-14 16:02:51 +04:00
if ( ! da7213 )
return - ENOMEM ;
i2c_set_clientdata ( i2c , da7213 ) ;
2020-05-11 16:25:41 +03:00
/* Get required supplies */
for ( i = 0 ; i < DA7213_NUM_SUPPLIES ; + + i )
da7213 - > supplies [ i ] . supply = da7213_supply_names [ i ] ;
ret = devm_regulator_bulk_get ( & i2c - > dev , DA7213_NUM_SUPPLIES ,
da7213 - > supplies ) ;
if ( ret ) {
dev_err ( & i2c - > dev , " Failed to get supplies: %d \n " , ret ) ;
return ret ;
}
ret = regulator_bulk_enable ( DA7213_NUM_SUPPLIES , da7213 - > supplies ) ;
if ( ret < 0 )
return ret ;
ret = devm_add_action_or_reset ( & i2c - > dev , da7213_power_off , da7213 ) ;
if ( ret < 0 )
return ret ;
2013-02-14 16:02:51 +04:00
da7213 - > regmap = devm_regmap_init_i2c ( i2c , & da7213_regmap_config ) ;
if ( IS_ERR ( da7213 - > regmap ) ) {
ret = PTR_ERR ( da7213 - > regmap ) ;
dev_err ( & i2c - > dev , " regmap_init() failed: %d \n " , ret ) ;
return ret ;
}
2020-05-11 16:25:41 +03:00
pm_runtime_set_autosuspend_delay ( & i2c - > dev , 100 ) ;
pm_runtime_use_autosuspend ( & i2c - > dev ) ;
pm_runtime_set_active ( & i2c - > dev ) ;
pm_runtime_enable ( & i2c - > dev ) ;
2018-01-29 07:03:13 +03:00
ret = devm_snd_soc_register_component ( & i2c - > dev ,
& soc_component_dev_da7213 , & da7213_dai , 1 ) ;
2013-02-14 16:02:51 +04:00
if ( ret < 0 ) {
2018-01-29 07:03:13 +03:00
dev_err ( & i2c - > dev , " Failed to register da7213 component: %d \n " ,
2013-02-14 16:02:51 +04:00
ret ) ;
}
return ret ;
}
2023-03-28 03:03:03 +03:00
static void da7213_i2c_remove ( struct i2c_client * i2c )
{
pm_runtime_disable ( & i2c - > dev ) ;
}
2020-05-11 16:25:41 +03:00
static int __maybe_unused da7213_runtime_suspend ( struct device * dev )
{
struct da7213_priv * da7213 = dev_get_drvdata ( dev ) ;
regcache_cache_only ( da7213 - > regmap , true ) ;
regcache_mark_dirty ( da7213 - > regmap ) ;
regulator_bulk_disable ( DA7213_NUM_SUPPLIES , da7213 - > supplies ) ;
return 0 ;
}
static int __maybe_unused da7213_runtime_resume ( struct device * dev )
{
struct da7213_priv * da7213 = dev_get_drvdata ( dev ) ;
int ret ;
ret = regulator_bulk_enable ( DA7213_NUM_SUPPLIES , da7213 - > supplies ) ;
if ( ret < 0 )
return ret ;
regcache_cache_only ( da7213 - > regmap , false ) ;
regcache_sync ( da7213 - > regmap ) ;
return 0 ;
}
static const struct dev_pm_ops da7213_pm = {
SET_RUNTIME_PM_OPS ( da7213_runtime_suspend , da7213_runtime_resume , NULL )
} ;
2013-02-14 16:02:51 +04:00
static const struct i2c_device_id da7213_i2c_id [ ] = {
{ " da7213 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , da7213_i2c_id ) ;
/* I2C codec control layer */
static struct i2c_driver da7213_i2c_driver = {
. driver = {
. name = " da7213 " ,
2015-10-07 16:27:08 +03:00
. of_match_table = of_match_ptr ( da7213_of_match ) ,
2017-03-10 03:18:58 +03:00
. acpi_match_table = ACPI_PTR ( da7213_acpi_match ) ,
2020-05-11 16:25:41 +03:00
. pm = & da7213_pm ,
2013-02-14 16:02:51 +04:00
} ,
2023-04-25 12:57:16 +03:00
. probe = da7213_i2c_probe ,
2023-03-28 03:03:03 +03:00
. remove = da7213_i2c_remove ,
2013-02-14 16:02:51 +04:00
. id_table = da7213_i2c_id ,
} ;
module_i2c_driver ( da7213_i2c_driver ) ;
MODULE_DESCRIPTION ( " ASoC DA7213 Codec driver " ) ;
MODULE_AUTHOR ( " Adam Thomson <Adam.Thomson.Opensource@diasemi.com> " ) ;
MODULE_LICENSE ( " GPL " ) ;