2017-11-30 00:32:42 +03:00
// SPDX-License-Identifier: GPL-2.0
2014-03-11 14:57:32 +04:00
/*
2017-11-30 00:32:42 +03:00
* ALSA SoC TLV320AIC31xx CODEC Driver
2014-03-11 14:57:32 +04:00
*
2017-11-30 00:32:42 +03:00
* Copyright ( C ) 2014 - 2017 Texas Instruments Incorporated - http : //www.ti.com/
* Jyri Sarha < jsarha @ ti . com >
2014-03-11 14:57:32 +04:00
*
* Based on ground work by : Ajit Kulkarni < x0175765 @ ti . com >
*
2017-11-30 00:32:42 +03:00
* The TLV320AIC31xx series of audio codecs are low - power , highly integrated
* high performance codecs which provides a stereo DAC , a mono ADC ,
2014-03-11 14:57:32 +04:00
* and mono / stereo Class - D speaker driver .
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/pm.h>
# include <linux/i2c.h>
2017-12-07 18:38:51 +03:00
# include <linux/gpio/consumer.h>
2014-03-11 14:57:32 +04:00
# include <linux/regulator/consumer.h>
2016-04-19 19:00:20 +03:00
# include <linux/acpi.h>
2014-04-04 09:59:12 +04:00
# include <linux/of.h>
2014-03-11 14:57:32 +04:00
# include <linux/of_gpio.h>
# include <linux/slab.h>
# include <sound/core.h>
2019-04-01 18:13:28 +03:00
# include <sound/jack.h>
2014-03-11 14:57:32 +04:00
# include <sound/pcm.h>
# include <sound/pcm_params.h>
# include <sound/soc.h>
# include <sound/initval.h>
# include <sound/tlv.h>
# include <dt-bindings/sound/tlv320aic31xx-micbias.h>
# include "tlv320aic31xx.h"
static const struct reg_default aic31xx_reg_defaults [ ] = {
{ AIC31XX_CLKMUX , 0x00 } ,
{ AIC31XX_PLLPR , 0x11 } ,
{ AIC31XX_PLLJ , 0x04 } ,
{ AIC31XX_PLLDMSB , 0x00 } ,
{ AIC31XX_PLLDLSB , 0x00 } ,
{ AIC31XX_NDAC , 0x01 } ,
{ AIC31XX_MDAC , 0x01 } ,
{ AIC31XX_DOSRMSB , 0x00 } ,
{ AIC31XX_DOSRLSB , 0x80 } ,
{ AIC31XX_NADC , 0x01 } ,
{ AIC31XX_MADC , 0x01 } ,
{ AIC31XX_AOSR , 0x80 } ,
{ AIC31XX_IFACE1 , 0x00 } ,
{ AIC31XX_DATA_OFFSET , 0x00 } ,
{ AIC31XX_IFACE2 , 0x00 } ,
{ AIC31XX_BCLKN , 0x01 } ,
{ AIC31XX_DACSETUP , 0x14 } ,
{ AIC31XX_DACMUTE , 0x0c } ,
{ AIC31XX_LDACVOL , 0x00 } ,
{ AIC31XX_RDACVOL , 0x00 } ,
{ AIC31XX_ADCSETUP , 0x00 } ,
{ AIC31XX_ADCFGA , 0x80 } ,
{ AIC31XX_ADCVOL , 0x00 } ,
{ AIC31XX_HPDRIVER , 0x04 } ,
{ AIC31XX_SPKAMP , 0x06 } ,
{ AIC31XX_DACMIXERROUTE , 0x00 } ,
{ AIC31XX_LANALOGHPL , 0x7f } ,
{ AIC31XX_RANALOGHPR , 0x7f } ,
{ AIC31XX_LANALOGSPL , 0x7f } ,
{ AIC31XX_RANALOGSPR , 0x7f } ,
{ AIC31XX_HPLGAIN , 0x02 } ,
{ AIC31XX_HPRGAIN , 0x02 } ,
{ AIC31XX_SPLGAIN , 0x00 } ,
{ AIC31XX_SPRGAIN , 0x00 } ,
{ AIC31XX_MICBIAS , 0x00 } ,
{ AIC31XX_MICPGA , 0x80 } ,
{ AIC31XX_MICPGAPI , 0x00 } ,
{ AIC31XX_MICPGAMI , 0x00 } ,
} ;
static bool aic31xx_volatile ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case AIC31XX_PAGECTL : /* regmap implementation requires this */
case AIC31XX_RESET : /* always clears after write */
case AIC31XX_OT_FLAG :
case AIC31XX_ADCFLAG :
case AIC31XX_DACFLAG1 :
case AIC31XX_DACFLAG2 :
case AIC31XX_OFFLAG : /* Sticky interrupt flags */
case AIC31XX_INTRDACFLAG : /* Sticky interrupt flags */
case AIC31XX_INTRADCFLAG : /* Sticky interrupt flags */
case AIC31XX_INTRDACFLAG2 :
case AIC31XX_INTRADCFLAG2 :
2019-04-01 18:13:28 +03:00
case AIC31XX_HSDETECT :
2014-03-11 14:57:32 +04:00
return true ;
}
return false ;
}
static bool aic31xx_writeable ( struct device * dev , unsigned int reg )
{
switch ( reg ) {
case AIC31XX_OT_FLAG :
case AIC31XX_ADCFLAG :
case AIC31XX_DACFLAG1 :
case AIC31XX_DACFLAG2 :
case AIC31XX_OFFLAG : /* Sticky interrupt flags */
case AIC31XX_INTRDACFLAG : /* Sticky interrupt flags */
case AIC31XX_INTRADCFLAG : /* Sticky interrupt flags */
case AIC31XX_INTRDACFLAG2 :
case AIC31XX_INTRADCFLAG2 :
return false ;
}
return true ;
}
static const struct regmap_range_cfg aic31xx_ranges [ ] = {
{
. range_min = 0 ,
. range_max = 12 * 128 ,
. selector_reg = AIC31XX_PAGECTL ,
. selector_mask = 0xff ,
. selector_shift = 0 ,
. window_start = 0 ,
. window_len = 128 ,
} ,
} ;
2014-03-13 21:44:22 +04:00
static const struct regmap_config aic31xx_i2c_regmap = {
2014-03-11 14:57:32 +04:00
. reg_bits = 8 ,
. val_bits = 8 ,
. writeable_reg = aic31xx_writeable ,
. volatile_reg = aic31xx_volatile ,
. reg_defaults = aic31xx_reg_defaults ,
. num_reg_defaults = ARRAY_SIZE ( aic31xx_reg_defaults ) ,
. cache_type = REGCACHE_RBTREE ,
. ranges = aic31xx_ranges ,
. num_ranges = ARRAY_SIZE ( aic31xx_ranges ) ,
. max_register = 12 * 128 ,
} ;
2017-11-30 00:32:45 +03:00
static const char * const aic31xx_supply_names [ ] = {
2014-03-11 14:57:32 +04:00
" HPVDD " ,
" SPRVDD " ,
" SPLVDD " ,
" AVDD " ,
" IOVDD " ,
" DVDD " ,
} ;
2017-11-30 00:32:45 +03:00
# define AIC31XX_NUM_SUPPLIES ARRAY_SIZE(aic31xx_supply_names)
2014-03-11 14:57:32 +04:00
struct aic31xx_disable_nb {
struct notifier_block nb ;
struct aic31xx_priv * aic31xx ;
} ;
struct aic31xx_priv {
2018-01-29 07:15:27 +03:00
struct snd_soc_component * component ;
2014-03-11 14:57:32 +04:00
u8 i2c_regs_status ;
struct device * dev ;
struct regmap * regmap ;
2017-12-07 18:38:52 +03:00
enum aic31xx_type codec_type ;
2017-11-30 00:32:49 +03:00
struct gpio_desc * gpio_reset ;
2017-12-07 18:38:52 +03:00
int micbias_vg ;
2014-03-11 14:57:32 +04:00
struct aic31xx_pdata pdata ;
struct regulator_bulk_data supplies [ AIC31XX_NUM_SUPPLIES ] ;
struct aic31xx_disable_nb disable_nb [ AIC31XX_NUM_SUPPLIES ] ;
2019-04-01 18:13:28 +03:00
struct snd_soc_jack * jack ;
2014-03-11 14:57:32 +04:00
unsigned int sysclk ;
2014-09-03 16:52:34 +04:00
u8 p_div ;
2014-03-11 14:57:32 +04:00
int rate_div_line ;
2018-02-14 15:20:56 +03:00
bool master_dapm_route_applied ;
2018-08-31 21:24:31 +03:00
int irq ;
2014-03-11 14:57:32 +04:00
} ;
struct aic31xx_rate_divs {
2014-09-03 16:52:34 +04:00
u32 mclk_p ;
2014-03-11 14:57:32 +04:00
u32 rate ;
u8 pll_j ;
u16 pll_d ;
u16 dosr ;
u8 ndac ;
u8 mdac ;
u8 aosr ;
u8 nadc ;
u8 madc ;
} ;
2017-11-30 00:32:45 +03:00
/* ADC dividers can be disabled by configuring them to 0 */
2014-03-11 14:57:32 +04:00
static const struct aic31xx_rate_divs aic31xx_divs [ ] = {
2014-09-03 16:52:34 +04:00
/* mclk/p rate pll: j d dosr ndac mdac aors nadc madc */
2014-03-11 14:57:32 +04:00
/* 8k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 8000 , 8 , 1920 , 128 , 48 , 2 , 128 , 48 , 2 } ,
{ 12000000 , 8000 , 8 , 1920 , 128 , 32 , 3 , 128 , 32 , 3 } ,
{ 12500000 , 8000 , 7 , 8643 , 128 , 48 , 2 , 128 , 48 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 11.025k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 11025 , 7 , 5264 , 128 , 32 , 2 , 128 , 32 , 2 } ,
{ 12000000 , 11025 , 8 , 4672 , 128 , 24 , 3 , 128 , 24 , 3 } ,
{ 12500000 , 11025 , 7 , 2253 , 128 , 32 , 2 , 128 , 32 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 16k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 16000 , 8 , 1920 , 128 , 24 , 2 , 128 , 24 , 2 } ,
{ 12000000 , 16000 , 8 , 1920 , 128 , 16 , 3 , 128 , 16 , 3 } ,
{ 12500000 , 16000 , 7 , 8643 , 128 , 24 , 2 , 128 , 24 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 22.05k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 22050 , 7 , 5264 , 128 , 16 , 2 , 128 , 16 , 2 } ,
{ 12000000 , 22050 , 8 , 4672 , 128 , 12 , 3 , 128 , 12 , 3 } ,
{ 12500000 , 22050 , 7 , 2253 , 128 , 16 , 2 , 128 , 16 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 32k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 32000 , 8 , 1920 , 128 , 12 , 2 , 128 , 12 , 2 } ,
{ 12000000 , 32000 , 8 , 1920 , 128 , 8 , 3 , 128 , 8 , 3 } ,
{ 12500000 , 32000 , 7 , 8643 , 128 , 12 , 2 , 128 , 12 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 44.1k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 44100 , 7 , 5264 , 128 , 8 , 2 , 128 , 8 , 2 } ,
{ 12000000 , 44100 , 8 , 4672 , 128 , 6 , 3 , 128 , 6 , 3 } ,
{ 12500000 , 44100 , 7 , 2253 , 128 , 8 , 2 , 128 , 8 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 48k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 48000 , 8 , 1920 , 128 , 8 , 2 , 128 , 8 , 2 } ,
{ 12000000 , 48000 , 7 , 6800 , 96 , 5 , 4 , 96 , 5 , 4 } ,
{ 12500000 , 48000 , 7 , 8643 , 128 , 8 , 2 , 128 , 8 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 88.2k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 88200 , 7 , 5264 , 64 , 8 , 2 , 64 , 8 , 2 } ,
{ 12000000 , 88200 , 8 , 4672 , 64 , 6 , 3 , 64 , 6 , 3 } ,
{ 12500000 , 88200 , 7 , 2253 , 64 , 8 , 2 , 64 , 8 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 96k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 96000 , 8 , 1920 , 64 , 8 , 2 , 64 , 8 , 2 } ,
{ 12000000 , 96000 , 7 , 6800 , 48 , 5 , 4 , 48 , 5 , 4 } ,
{ 12500000 , 96000 , 7 , 8643 , 64 , 8 , 2 , 64 , 8 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 176.4k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 176400 , 7 , 5264 , 32 , 8 , 2 , 32 , 8 , 2 } ,
{ 12000000 , 176400 , 8 , 4672 , 32 , 6 , 3 , 32 , 6 , 3 } ,
{ 12500000 , 176400 , 7 , 2253 , 32 , 8 , 2 , 32 , 8 , 2 } ,
2014-03-11 14:57:32 +04:00
/* 192k rate */
2014-09-03 16:52:34 +04:00
{ 12000000 , 192000 , 8 , 1920 , 32 , 8 , 2 , 32 , 8 , 2 } ,
{ 12000000 , 192000 , 7 , 6800 , 24 , 5 , 4 , 24 , 5 , 4 } ,
{ 12500000 , 192000 , 7 , 8643 , 32 , 8 , 2 , 32 , 8 , 2 } ,
2014-03-11 14:57:32 +04:00
} ;
static const char * const ldac_in_text [ ] = {
" Off " , " Left Data " , " Right Data " , " Mono "
} ;
static const char * const rdac_in_text [ ] = {
" Off " , " Right Data " , " Left Data " , " Mono "
} ;
static SOC_ENUM_SINGLE_DECL ( ldac_in_enum , AIC31XX_DACSETUP , 4 , ldac_in_text ) ;
static SOC_ENUM_SINGLE_DECL ( rdac_in_enum , AIC31XX_DACSETUP , 2 , rdac_in_text ) ;
static const char * const mic_select_text [ ] = {
" Off " , " FFR 10 Ohm " , " FFR 20 Ohm " , " FFR 40 Ohm "
} ;
2014-06-19 11:40:27 +04:00
static SOC_ENUM_SINGLE_DECL ( mic1lp_p_enum , AIC31XX_MICPGAPI , 6 ,
mic_select_text ) ;
static SOC_ENUM_SINGLE_DECL ( mic1rp_p_enum , AIC31XX_MICPGAPI , 4 ,
mic_select_text ) ;
static SOC_ENUM_SINGLE_DECL ( mic1lm_p_enum , AIC31XX_MICPGAPI , 2 ,
mic_select_text ) ;
2014-03-11 14:57:32 +04:00
2014-06-19 11:40:27 +04:00
static SOC_ENUM_SINGLE_DECL ( mic1lm_m_enum , AIC31XX_MICPGAMI , 4 ,
mic_select_text ) ;
2014-03-11 14:57:32 +04:00
static const DECLARE_TLV_DB_SCALE ( dac_vol_tlv , - 6350 , 50 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( adc_fgain_tlv , 0 , 10 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( adc_cgain_tlv , - 2000 , 50 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( mic_pga_tlv , 0 , 50 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( hp_drv_tlv , 0 , 100 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( class_D_drv_tlv , 600 , 600 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( hp_vol_tlv , - 6350 , 50 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( sp_vol_tlv , - 6350 , 50 , 0 ) ;
/*
* controls to be exported to the user space
*/
2016-09-23 14:52:52 +03:00
static const struct snd_kcontrol_new common31xx_snd_controls [ ] = {
2014-03-11 14:57:32 +04:00
SOC_DOUBLE_R_S_TLV ( " DAC Playback Volume " , AIC31XX_LDACVOL ,
AIC31XX_RDACVOL , 0 , - 127 , 48 , 7 , 0 , dac_vol_tlv ) ,
2016-09-23 14:52:52 +03:00
SOC_DOUBLE_R ( " HP Driver Playback Switch " , AIC31XX_HPLGAIN ,
AIC31XX_HPRGAIN , 2 , 1 , 0 ) ,
SOC_DOUBLE_R_TLV ( " HP Driver Playback Volume " , AIC31XX_HPLGAIN ,
AIC31XX_HPRGAIN , 3 , 0x09 , 0 , hp_drv_tlv ) ,
SOC_DOUBLE_R_TLV ( " HP Analog Playback Volume " , AIC31XX_LANALOGHPL ,
AIC31XX_RANALOGHPR , 0 , 0x7F , 1 , hp_vol_tlv ) ,
} ;
static const struct snd_kcontrol_new aic31xx_snd_controls [ ] = {
2014-03-11 14:57:32 +04:00
SOC_SINGLE_TLV ( " ADC Fine Capture Volume " , AIC31XX_ADCFGA , 4 , 4 , 1 ,
adc_fgain_tlv ) ,
SOC_SINGLE ( " ADC Capture Switch " , AIC31XX_ADCFGA , 7 , 1 , 1 ) ,
SOC_DOUBLE_R_S_TLV ( " ADC Capture Volume " , AIC31XX_ADCVOL , AIC31XX_ADCVOL ,
0 , - 24 , 40 , 6 , 0 , adc_cgain_tlv ) ,
SOC_SINGLE_TLV ( " Mic PGA Capture Volume " , AIC31XX_MICPGA , 0 ,
119 , 0 , mic_pga_tlv ) ,
} ;
static const struct snd_kcontrol_new aic311x_snd_controls [ ] = {
SOC_DOUBLE_R ( " Speaker Driver Playback Switch " , AIC31XX_SPLGAIN ,
AIC31XX_SPRGAIN , 2 , 1 , 0 ) ,
SOC_DOUBLE_R_TLV ( " Speaker Driver Playback Volume " , AIC31XX_SPLGAIN ,
AIC31XX_SPRGAIN , 3 , 3 , 0 , class_D_drv_tlv ) ,
SOC_DOUBLE_R_TLV ( " Speaker Analog Playback Volume " , AIC31XX_LANALOGSPL ,
AIC31XX_RANALOGSPR , 0 , 0x7F , 1 , sp_vol_tlv ) ,
} ;
static const struct snd_kcontrol_new aic310x_snd_controls [ ] = {
SOC_SINGLE ( " Speaker Driver Playback Switch " , AIC31XX_SPLGAIN ,
2 , 1 , 0 ) ,
SOC_SINGLE_TLV ( " Speaker Driver Playback Volume " , AIC31XX_SPLGAIN ,
3 , 3 , 0 , class_D_drv_tlv ) ,
SOC_SINGLE_TLV ( " Speaker Analog Playback Volume " , AIC31XX_LANALOGSPL ,
0 , 0x7F , 1 , sp_vol_tlv ) ,
} ;
static const struct snd_kcontrol_new ldac_in_control =
SOC_DAPM_ENUM ( " DAC Left Input " , ldac_in_enum ) ;
static const struct snd_kcontrol_new rdac_in_control =
SOC_DAPM_ENUM ( " DAC Right Input " , rdac_in_enum ) ;
2014-03-13 21:44:22 +04:00
static int aic31xx_wait_bits ( struct aic31xx_priv * aic31xx , unsigned int reg ,
unsigned int mask , unsigned int wbits , int sleep ,
int count )
2014-03-11 14:57:32 +04:00
{
unsigned int bits ;
int counter = count ;
int ret = regmap_read ( aic31xx - > regmap , reg , & bits ) ;
2014-06-13 10:26:54 +04:00
2014-03-11 14:57:32 +04:00
while ( ( bits & mask ) ! = wbits & & counter & & ! ret ) {
usleep_range ( sleep , sleep * 2 ) ;
ret = regmap_read ( aic31xx - > regmap , reg , & bits ) ;
counter - - ;
}
if ( ( bits & mask ) ! = wbits ) {
dev_err ( aic31xx - > dev ,
" %s: Failed! 0x%x was 0x%x expected 0x%x (%d, 0x%x, %d us) \n " ,
__func__ , reg , bits , wbits , ret , mask ,
( count - counter ) * sleep ) ;
ret = - 1 ;
}
return ret ;
}
# define WIDGET_BIT(reg, shift) (((shift) << 8) | (reg))
static int aic31xx_dapm_power_event ( struct snd_soc_dapm_widget * w ,
struct snd_kcontrol * kcontrol , int event )
{
2018-01-29 07:15:27 +03:00
struct snd_soc_component * component = snd_soc_dapm_to_component ( w - > dapm ) ;
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-03-11 14:57:32 +04:00
unsigned int reg = AIC31XX_DACFLAG1 ;
unsigned int mask ;
switch ( WIDGET_BIT ( w - > reg , w - > shift ) ) {
case WIDGET_BIT ( AIC31XX_DACSETUP , 7 ) :
mask = AIC31XX_LDACPWRSTATUS_MASK ;
break ;
case WIDGET_BIT ( AIC31XX_DACSETUP , 6 ) :
mask = AIC31XX_RDACPWRSTATUS_MASK ;
break ;
case WIDGET_BIT ( AIC31XX_HPDRIVER , 7 ) :
mask = AIC31XX_HPLDRVPWRSTATUS_MASK ;
break ;
case WIDGET_BIT ( AIC31XX_HPDRIVER , 6 ) :
mask = AIC31XX_HPRDRVPWRSTATUS_MASK ;
break ;
case WIDGET_BIT ( AIC31XX_SPKAMP , 7 ) :
mask = AIC31XX_SPLDRVPWRSTATUS_MASK ;
break ;
case WIDGET_BIT ( AIC31XX_SPKAMP , 6 ) :
mask = AIC31XX_SPRDRVPWRSTATUS_MASK ;
break ;
case WIDGET_BIT ( AIC31XX_ADCSETUP , 7 ) :
mask = AIC31XX_ADCPWRSTATUS_MASK ;
reg = AIC31XX_ADCFLAG ;
break ;
default :
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev , " Unknown widget '%s' calling %s \n " ,
2014-03-11 14:57:32 +04:00
w - > name , __func__ ) ;
return - EINVAL ;
}
switch ( event ) {
case SND_SOC_DAPM_POST_PMU :
return aic31xx_wait_bits ( aic31xx , reg , mask , mask , 5000 , 100 ) ;
case SND_SOC_DAPM_POST_PMD :
return aic31xx_wait_bits ( aic31xx , reg , mask , 0 , 5000 , 100 ) ;
default :
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev ,
2014-03-11 14:57:32 +04:00
" Unhandled dapm widget event %d from %s \n " ,
event , w - > name ) ;
}
return 0 ;
}
2016-09-23 14:52:52 +03:00
static const struct snd_kcontrol_new aic31xx_left_output_switches [ ] = {
2014-03-11 14:57:32 +04:00
SOC_DAPM_SINGLE ( " From Left DAC " , AIC31XX_DACMIXERROUTE , 6 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " From MIC1LP " , AIC31XX_DACMIXERROUTE , 5 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " From MIC1RP " , AIC31XX_DACMIXERROUTE , 4 , 1 , 0 ) ,
} ;
2016-09-23 14:52:52 +03:00
static const struct snd_kcontrol_new aic31xx_right_output_switches [ ] = {
2014-03-11 14:57:32 +04:00
SOC_DAPM_SINGLE ( " From Right DAC " , AIC31XX_DACMIXERROUTE , 2 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " From MIC1RP " , AIC31XX_DACMIXERROUTE , 1 , 1 , 0 ) ,
} ;
2016-09-23 14:52:52 +03:00
static const struct snd_kcontrol_new dac31xx_left_output_switches [ ] = {
SOC_DAPM_SINGLE ( " From Left DAC " , AIC31XX_DACMIXERROUTE , 6 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " From AIN1 " , AIC31XX_DACMIXERROUTE , 5 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " From AIN2 " , AIC31XX_DACMIXERROUTE , 4 , 1 , 0 ) ,
} ;
static const struct snd_kcontrol_new dac31xx_right_output_switches [ ] = {
SOC_DAPM_SINGLE ( " From Right DAC " , AIC31XX_DACMIXERROUTE , 2 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " From AIN2 " , AIC31XX_DACMIXERROUTE , 1 , 1 , 0 ) ,
} ;
2014-03-11 14:57:32 +04:00
static const struct snd_kcontrol_new p_term_mic1lp =
SOC_DAPM_ENUM ( " MIC1LP P-Terminal " , mic1lp_p_enum ) ;
static const struct snd_kcontrol_new p_term_mic1rp =
SOC_DAPM_ENUM ( " MIC1RP P-Terminal " , mic1rp_p_enum ) ;
static const struct snd_kcontrol_new p_term_mic1lm =
SOC_DAPM_ENUM ( " MIC1LM P-Terminal " , mic1lm_p_enum ) ;
static const struct snd_kcontrol_new m_term_mic1lm =
SOC_DAPM_ENUM ( " MIC1LM M-Terminal " , mic1lm_m_enum ) ;
static const struct snd_kcontrol_new aic31xx_dapm_hpl_switch =
SOC_DAPM_SINGLE ( " Switch " , AIC31XX_LANALOGHPL , 7 , 1 , 0 ) ;
static const struct snd_kcontrol_new aic31xx_dapm_hpr_switch =
SOC_DAPM_SINGLE ( " Switch " , AIC31XX_RANALOGHPR , 7 , 1 , 0 ) ;
static const struct snd_kcontrol_new aic31xx_dapm_spl_switch =
SOC_DAPM_SINGLE ( " Switch " , AIC31XX_LANALOGSPL , 7 , 1 , 0 ) ;
static const struct snd_kcontrol_new aic31xx_dapm_spr_switch =
SOC_DAPM_SINGLE ( " Switch " , AIC31XX_RANALOGSPR , 7 , 1 , 0 ) ;
static int mic_bias_event ( struct snd_soc_dapm_widget * w ,
struct snd_kcontrol * kcontrol , int event )
{
2018-01-29 07:15:27 +03:00
struct snd_soc_component * component = snd_soc_dapm_to_component ( w - > dapm ) ;
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-06-13 10:26:54 +04:00
2014-03-11 14:57:32 +04:00
switch ( event ) {
case SND_SOC_DAPM_POST_PMU :
/* change mic bias voltage to user defined */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_MICBIAS ,
2014-03-11 14:57:32 +04:00
AIC31XX_MICBIAS_MASK ,
2017-12-07 18:38:52 +03:00
aic31xx - > micbias_vg < <
2014-03-11 14:57:32 +04:00
AIC31XX_MICBIAS_SHIFT ) ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " %s: turned on \n " , __func__ ) ;
2014-03-11 14:57:32 +04:00
break ;
case SND_SOC_DAPM_PRE_PMD :
/* turn mic bias off */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_MICBIAS ,
2014-03-11 14:57:32 +04:00
AIC31XX_MICBIAS_MASK , 0 ) ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " %s: turned off \n " , __func__ ) ;
2014-03-11 14:57:32 +04:00
break ;
}
return 0 ;
}
2016-09-23 14:52:52 +03:00
static const struct snd_soc_dapm_widget common31xx_dapm_widgets [ ] = {
2018-02-19 12:45:07 +03:00
SND_SOC_DAPM_AIF_IN ( " AIF IN " , " Playback " , 0 , SND_SOC_NOPM , 0 , 0 ) ,
2014-03-11 14:57:32 +04:00
SND_SOC_DAPM_MUX ( " DAC Left Input " ,
SND_SOC_NOPM , 0 , 0 , & ldac_in_control ) ,
SND_SOC_DAPM_MUX ( " DAC Right Input " ,
SND_SOC_NOPM , 0 , 0 , & rdac_in_control ) ,
/* DACs */
SND_SOC_DAPM_DAC_E ( " DAC Left " , " Left Playback " ,
AIC31XX_DACSETUP , 7 , 0 , aic31xx_dapm_power_event ,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD ) ,
SND_SOC_DAPM_DAC_E ( " DAC Right " , " Right Playback " ,
AIC31XX_DACSETUP , 6 , 0 , aic31xx_dapm_power_event ,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD ) ,
2016-09-23 14:52:52 +03:00
/* HP */
2014-03-11 14:57:32 +04:00
SND_SOC_DAPM_SWITCH ( " HP Left " , SND_SOC_NOPM , 0 , 0 ,
& aic31xx_dapm_hpl_switch ) ,
SND_SOC_DAPM_SWITCH ( " HP Right " , SND_SOC_NOPM , 0 , 0 ,
& aic31xx_dapm_hpr_switch ) ,
/* Output drivers */
SND_SOC_DAPM_OUT_DRV_E ( " HPL Driver " , AIC31XX_HPDRIVER , 7 , 0 ,
NULL , 0 , aic31xx_dapm_power_event ,
SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU ) ,
SND_SOC_DAPM_OUT_DRV_E ( " HPR Driver " , AIC31XX_HPDRIVER , 6 , 0 ,
NULL , 0 , aic31xx_dapm_power_event ,
SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU ) ,
2016-09-23 14:52:52 +03:00
/* Mic Bias */
SND_SOC_DAPM_SUPPLY ( " MICBIAS " , SND_SOC_NOPM , 0 , 0 , mic_bias_event ,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD ) ,
2018-02-19 12:45:08 +03:00
/* Keep BCLK/WCLK enabled even if DAC/ADC is powered down */
SND_SOC_DAPM_SUPPLY ( " Activate I2S clocks " , AIC31XX_IFACE2 , 2 , 0 ,
NULL , 0 ) ,
2016-09-23 14:52:52 +03:00
/* Outputs */
SND_SOC_DAPM_OUTPUT ( " HPL " ) ,
SND_SOC_DAPM_OUTPUT ( " HPR " ) ,
} ;
static const struct snd_soc_dapm_widget dac31xx_dapm_widgets [ ] = {
/* Inputs */
SND_SOC_DAPM_INPUT ( " AIN1 " ) ,
SND_SOC_DAPM_INPUT ( " AIN2 " ) ,
/* Output Mixers */
SND_SOC_DAPM_MIXER ( " Output Left " , SND_SOC_NOPM , 0 , 0 ,
dac31xx_left_output_switches ,
ARRAY_SIZE ( dac31xx_left_output_switches ) ) ,
SND_SOC_DAPM_MIXER ( " Output Right " , SND_SOC_NOPM , 0 , 0 ,
dac31xx_right_output_switches ,
ARRAY_SIZE ( dac31xx_right_output_switches ) ) ,
} ;
static const struct snd_soc_dapm_widget aic31xx_dapm_widgets [ ] = {
/* Inputs */
SND_SOC_DAPM_INPUT ( " MIC1LP " ) ,
SND_SOC_DAPM_INPUT ( " MIC1RP " ) ,
SND_SOC_DAPM_INPUT ( " MIC1LM " ) ,
2014-03-11 14:57:32 +04:00
/* Input Selection to MIC_PGA */
SND_SOC_DAPM_MUX ( " MIC1LP P-Terminal " , SND_SOC_NOPM , 0 , 0 ,
& p_term_mic1lp ) ,
SND_SOC_DAPM_MUX ( " MIC1RP P-Terminal " , SND_SOC_NOPM , 0 , 0 ,
& p_term_mic1rp ) ,
SND_SOC_DAPM_MUX ( " MIC1LM P-Terminal " , SND_SOC_NOPM , 0 , 0 ,
& p_term_mic1lm ) ,
2016-09-23 14:52:52 +03:00
/* ADC */
SND_SOC_DAPM_ADC_E ( " ADC " , " Capture " , AIC31XX_ADCSETUP , 7 , 0 ,
aic31xx_dapm_power_event , SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD ) ,
2014-03-11 14:57:32 +04:00
SND_SOC_DAPM_MUX ( " MIC1LM M-Terminal " , SND_SOC_NOPM , 0 , 0 ,
& m_term_mic1lm ) ,
2016-09-23 14:52:52 +03:00
2014-03-11 14:57:32 +04:00
/* Enabling & Disabling MIC Gain Ctl */
SND_SOC_DAPM_PGA ( " MIC_GAIN_CTL " , AIC31XX_MICPGA ,
7 , 1 , NULL , 0 ) ,
2016-09-23 14:52:52 +03:00
/* Output Mixers */
SND_SOC_DAPM_MIXER ( " Output Left " , SND_SOC_NOPM , 0 , 0 ,
aic31xx_left_output_switches ,
ARRAY_SIZE ( aic31xx_left_output_switches ) ) ,
SND_SOC_DAPM_MIXER ( " Output Right " , SND_SOC_NOPM , 0 , 0 ,
aic31xx_right_output_switches ,
ARRAY_SIZE ( aic31xx_right_output_switches ) ) ,
2018-02-19 12:45:08 +03:00
SND_SOC_DAPM_AIF_OUT ( " AIF OUT " , " Capture " , 0 , SND_SOC_NOPM , 0 , 0 ) ,
2014-03-11 14:57:32 +04:00
} ;
static const struct snd_soc_dapm_widget aic311x_dapm_widgets [ ] = {
/* AIC3111 and AIC3110 have stereo class-D amplifier */
SND_SOC_DAPM_OUT_DRV_E ( " SPL ClassD " , AIC31XX_SPKAMP , 7 , 0 , NULL , 0 ,
aic31xx_dapm_power_event , SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD ) ,
SND_SOC_DAPM_OUT_DRV_E ( " SPR ClassD " , AIC31XX_SPKAMP , 6 , 0 , NULL , 0 ,
aic31xx_dapm_power_event , SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD ) ,
SND_SOC_DAPM_SWITCH ( " Speaker Left " , SND_SOC_NOPM , 0 , 0 ,
& aic31xx_dapm_spl_switch ) ,
SND_SOC_DAPM_SWITCH ( " Speaker Right " , SND_SOC_NOPM , 0 , 0 ,
& aic31xx_dapm_spr_switch ) ,
SND_SOC_DAPM_OUTPUT ( " SPL " ) ,
SND_SOC_DAPM_OUTPUT ( " SPR " ) ,
} ;
/* AIC3100 and AIC3120 have only mono class-D amplifier */
static const struct snd_soc_dapm_widget aic310x_dapm_widgets [ ] = {
SND_SOC_DAPM_OUT_DRV_E ( " SPK ClassD " , AIC31XX_SPKAMP , 7 , 0 , NULL , 0 ,
aic31xx_dapm_power_event , SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_POST_PMD ) ,
SND_SOC_DAPM_SWITCH ( " Speaker " , SND_SOC_NOPM , 0 , 0 ,
& aic31xx_dapm_spl_switch ) ,
SND_SOC_DAPM_OUTPUT ( " SPK " ) ,
} ;
static const struct snd_soc_dapm_route
2016-09-23 14:52:52 +03:00
common31xx_audio_map [ ] = {
2014-03-11 14:57:32 +04:00
/* DAC Input Routing */
2018-02-19 12:45:07 +03:00
{ " DAC Left Input " , " Left Data " , " AIF IN " } ,
{ " DAC Left Input " , " Right Data " , " AIF IN " } ,
{ " DAC Left Input " , " Mono " , " AIF IN " } ,
{ " DAC Right Input " , " Left Data " , " AIF IN " } ,
{ " DAC Right Input " , " Right Data " , " AIF IN " } ,
{ " DAC Right Input " , " Mono " , " AIF IN " } ,
2014-03-11 14:57:32 +04:00
{ " DAC Left " , NULL , " DAC Left Input " } ,
{ " DAC Right " , NULL , " DAC Right Input " } ,
2016-09-23 14:52:52 +03:00
/* HPL path */
{ " HP Left " , " Switch " , " Output Left " } ,
{ " HPL Driver " , NULL , " HP Left " } ,
{ " HPL " , NULL , " HPL Driver " } ,
/* HPR path */
{ " HP Right " , " Switch " , " Output Right " } ,
{ " HPR Driver " , NULL , " HP Right " } ,
{ " HPR " , NULL , " HPR Driver " } ,
} ;
static const struct snd_soc_dapm_route
dac31xx_audio_map [ ] = {
/* Left Output */
{ " Output Left " , " From Left DAC " , " DAC Left " } ,
{ " Output Left " , " From AIN1 " , " AIN1 " } ,
{ " Output Left " , " From AIN2 " , " AIN2 " } ,
/* Right Output */
{ " Output Right " , " From Right DAC " , " DAC Right " } ,
{ " Output Right " , " From AIN2 " , " AIN2 " } ,
} ;
static const struct snd_soc_dapm_route
aic31xx_audio_map [ ] = {
2014-03-11 14:57:32 +04:00
/* Mic input */
{ " MIC1LP P-Terminal " , " FFR 10 Ohm " , " MIC1LP " } ,
{ " MIC1LP P-Terminal " , " FFR 20 Ohm " , " MIC1LP " } ,
{ " MIC1LP P-Terminal " , " FFR 40 Ohm " , " MIC1LP " } ,
{ " MIC1RP P-Terminal " , " FFR 10 Ohm " , " MIC1RP " } ,
{ " MIC1RP P-Terminal " , " FFR 20 Ohm " , " MIC1RP " } ,
{ " MIC1RP P-Terminal " , " FFR 40 Ohm " , " MIC1RP " } ,
{ " MIC1LM P-Terminal " , " FFR 10 Ohm " , " MIC1LM " } ,
{ " MIC1LM P-Terminal " , " FFR 20 Ohm " , " MIC1LM " } ,
{ " MIC1LM P-Terminal " , " FFR 40 Ohm " , " MIC1LM " } ,
{ " MIC1LM M-Terminal " , " FFR 10 Ohm " , " MIC1LM " } ,
{ " MIC1LM M-Terminal " , " FFR 20 Ohm " , " MIC1LM " } ,
{ " MIC1LM M-Terminal " , " FFR 40 Ohm " , " MIC1LM " } ,
{ " MIC_GAIN_CTL " , NULL , " MIC1LP P-Terminal " } ,
{ " MIC_GAIN_CTL " , NULL , " MIC1RP P-Terminal " } ,
{ " MIC_GAIN_CTL " , NULL , " MIC1LM P-Terminal " } ,
{ " MIC_GAIN_CTL " , NULL , " MIC1LM M-Terminal " } ,
{ " ADC " , NULL , " MIC_GAIN_CTL " } ,
2018-02-19 12:45:08 +03:00
{ " AIF OUT " , NULL , " ADC " } ,
2014-03-11 14:57:32 +04:00
/* Left Output */
{ " Output Left " , " From Left DAC " , " DAC Left " } ,
{ " Output Left " , " From MIC1LP " , " MIC1LP " } ,
{ " Output Left " , " From MIC1RP " , " MIC1RP " } ,
/* Right Output */
{ " Output Right " , " From Right DAC " , " DAC Right " } ,
{ " Output Right " , " From MIC1RP " , " MIC1RP " } ,
} ;
static const struct snd_soc_dapm_route
aic311x_audio_map [ ] = {
/* SP L path */
{ " Speaker Left " , " Switch " , " Output Left " } ,
{ " SPL ClassD " , NULL , " Speaker Left " } ,
{ " SPL " , NULL , " SPL ClassD " } ,
/* SP R path */
{ " Speaker Right " , " Switch " , " Output Right " } ,
{ " SPR ClassD " , NULL , " Speaker Right " } ,
{ " SPR " , NULL , " SPR ClassD " } ,
} ;
static const struct snd_soc_dapm_route
aic310x_audio_map [ ] = {
/* SP L path */
{ " Speaker " , " Switch " , " Output Left " } ,
{ " SPK ClassD " , NULL , " Speaker " } ,
{ " SPK " , NULL , " SPK ClassD " } ,
} ;
2018-02-14 15:20:56 +03:00
/*
* Always connected DAPM routes for codec clock master modes .
2018-02-19 12:45:08 +03:00
* If the codec is the master on the I2S bus , we need to power up components
* to have valid DAC_CLK .
*
* In order to have the I2S clocks on the bus either the DACs / ADC need to be
* enabled , or the P0 / R29 / D2 ( Keep bclk / wclk in power down ) need to be set .
*
2018-02-14 15:20:56 +03:00
* Otherwise the codec will not generate clocks on the bus .
*/
static const struct snd_soc_dapm_route
common31xx_cm_audio_map [ ] = {
2018-02-19 12:45:08 +03:00
{ " HPL " , NULL , " AIF IN " } ,
{ " HPR " , NULL , " AIF IN " } ,
2018-02-14 15:20:56 +03:00
2018-02-19 12:45:08 +03:00
{ " AIF IN " , NULL , " Activate I2S clocks " } ,
2018-02-14 15:20:56 +03:00
} ;
static const struct snd_soc_dapm_route
aic31xx_cm_audio_map [ ] = {
2018-02-19 12:45:08 +03:00
{ " AIF OUT " , NULL , " MIC1LP " } ,
{ " AIF OUT " , NULL , " MIC1RP " } ,
{ " AIF OUT " , NULL , " MIC1LM " } ,
{ " AIF OUT " , NULL , " Activate I2S clocks " } ,
2018-02-14 15:20:56 +03:00
} ;
2018-01-29 07:15:27 +03:00
static int aic31xx_add_controls ( struct snd_soc_component * component )
2014-03-11 14:57:32 +04:00
{
int ret = 0 ;
2018-01-29 07:15:27 +03:00
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-03-11 14:57:32 +04:00
2017-12-07 18:38:52 +03:00
if ( ! ( aic31xx - > codec_type & DAC31XX_BIT ) )
2018-01-29 07:15:27 +03:00
ret = snd_soc_add_component_controls (
component , aic31xx_snd_controls ,
2016-09-23 14:52:52 +03:00
ARRAY_SIZE ( aic31xx_snd_controls ) ) ;
if ( ret )
return ret ;
2017-12-07 18:38:52 +03:00
if ( aic31xx - > codec_type & AIC31XX_STEREO_CLASS_D_BIT )
2018-01-29 07:15:27 +03:00
ret = snd_soc_add_component_controls (
component , aic311x_snd_controls ,
2014-03-11 14:57:32 +04:00
ARRAY_SIZE ( aic311x_snd_controls ) ) ;
else
2018-01-29 07:15:27 +03:00
ret = snd_soc_add_component_controls (
component , aic310x_snd_controls ,
2014-03-11 14:57:32 +04:00
ARRAY_SIZE ( aic310x_snd_controls ) ) ;
return ret ;
}
2018-01-29 07:15:27 +03:00
static int aic31xx_add_widgets ( struct snd_soc_component * component )
2014-03-11 14:57:32 +04:00
{
2018-01-29 07:15:27 +03:00
struct snd_soc_dapm_context * dapm = snd_soc_component_get_dapm ( component ) ;
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-03-11 14:57:32 +04:00
int ret = 0 ;
2017-12-07 18:38:52 +03:00
if ( aic31xx - > codec_type & DAC31XX_BIT ) {
2016-09-23 14:52:52 +03:00
ret = snd_soc_dapm_new_controls (
dapm , dac31xx_dapm_widgets ,
ARRAY_SIZE ( dac31xx_dapm_widgets ) ) ;
if ( ret )
return ret ;
ret = snd_soc_dapm_add_routes ( dapm , dac31xx_audio_map ,
ARRAY_SIZE ( dac31xx_audio_map ) ) ;
if ( ret )
return ret ;
} else {
ret = snd_soc_dapm_new_controls (
dapm , aic31xx_dapm_widgets ,
ARRAY_SIZE ( aic31xx_dapm_widgets ) ) ;
if ( ret )
return ret ;
ret = snd_soc_dapm_add_routes ( dapm , aic31xx_audio_map ,
ARRAY_SIZE ( aic31xx_audio_map ) ) ;
if ( ret )
return ret ;
}
2017-12-07 18:38:52 +03:00
if ( aic31xx - > codec_type & AIC31XX_STEREO_CLASS_D_BIT ) {
2014-03-11 14:57:32 +04:00
ret = snd_soc_dapm_new_controls (
dapm , aic311x_dapm_widgets ,
ARRAY_SIZE ( aic311x_dapm_widgets ) ) ;
if ( ret )
return ret ;
ret = snd_soc_dapm_add_routes ( dapm , aic311x_audio_map ,
ARRAY_SIZE ( aic311x_audio_map ) ) ;
if ( ret )
return ret ;
} else {
ret = snd_soc_dapm_new_controls (
dapm , aic310x_dapm_widgets ,
ARRAY_SIZE ( aic310x_dapm_widgets ) ) ;
if ( ret )
return ret ;
ret = snd_soc_dapm_add_routes ( dapm , aic310x_audio_map ,
ARRAY_SIZE ( aic310x_audio_map ) ) ;
if ( ret )
return ret ;
}
return 0 ;
}
2018-01-29 07:15:27 +03:00
static int aic31xx_setup_pll ( struct snd_soc_component * component ,
2014-03-11 14:57:32 +04:00
struct snd_pcm_hw_params * params )
{
2018-01-29 07:15:27 +03:00
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-09-03 16:52:33 +04:00
int bclk_score = snd_soc_params_to_frame_size ( params ) ;
2017-11-30 00:32:52 +03:00
int mclk_p ;
2014-03-11 14:57:32 +04:00
int bclk_n = 0 ;
2014-09-03 16:52:33 +04:00
int match = - 1 ;
2014-03-11 14:57:32 +04:00
int i ;
2017-11-30 00:32:52 +03:00
if ( ! aic31xx - > sysclk | | ! aic31xx - > p_div ) {
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev , " Master clock not supplied \n " ) ;
2017-11-30 00:32:52 +03:00
return - EINVAL ;
}
mclk_p = aic31xx - > sysclk / aic31xx - > p_div ;
2014-03-11 14:57:32 +04:00
/* Use PLL as CODEC_CLKIN and DAC_CLK as BDIV_CLKIN */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_CLKMUX ,
2014-03-11 14:57:32 +04:00
AIC31XX_CODEC_CLKIN_MASK , AIC31XX_CODEC_CLKIN_PLL ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_IFACE2 ,
2014-03-11 14:57:32 +04:00
AIC31XX_BDIVCLK_MASK , AIC31XX_DAC2BCLK ) ;
for ( i = 0 ; i < ARRAY_SIZE ( aic31xx_divs ) ; i + + ) {
if ( aic31xx_divs [ i ] . rate = = params_rate ( params ) & &
2014-09-03 16:52:34 +04:00
aic31xx_divs [ i ] . mclk_p = = mclk_p ) {
2014-09-03 16:52:33 +04:00
int s = ( aic31xx_divs [ i ] . dosr * aic31xx_divs [ i ] . mdac ) %
snd_soc_params_to_frame_size ( params ) ;
int bn = ( aic31xx_divs [ i ] . dosr * aic31xx_divs [ i ] . mdac ) /
snd_soc_params_to_frame_size ( params ) ;
if ( s < bclk_score & & bn > 0 ) {
match = i ;
bclk_n = bn ;
bclk_score = s ;
}
}
2014-03-11 14:57:32 +04:00
}
2014-09-03 16:52:33 +04:00
if ( match = = - 1 ) {
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev ,
2014-09-03 16:52:33 +04:00
" %s: Sample rate (%u) and format not supported \n " ,
2014-03-11 14:57:32 +04:00
__func__ , params_rate ( params ) ) ;
2014-09-03 16:52:33 +04:00
/* See bellow for details how fix this. */
2014-03-11 14:57:32 +04:00
return - EINVAL ;
}
2014-09-03 16:52:33 +04:00
if ( bclk_score ! = 0 ) {
2018-01-29 07:15:27 +03:00
dev_warn ( component - > dev , " Can not produce exact bitclock " ) ;
2014-09-03 16:52:33 +04:00
/* This is fine if using dsp format, but if using i2s
there may be trouble . To fix the issue edit the
aic31xx_divs table for your mclk and sample
rate . Details can be found from :
http : //www.ti.com/lit/ds/symlink/tlv320aic3100.pdf
Section : 5.6 CLOCK Generation and PLL
*/
}
i = match ;
2014-03-11 14:57:32 +04:00
/* PLL configuration */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_PLLPR , AIC31XX_PLL_MASK ,
2014-09-03 16:52:34 +04:00
( aic31xx - > p_div < < 4 ) | 0x01 ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_write ( component , AIC31XX_PLLJ , aic31xx_divs [ i ] . pll_j ) ;
2014-03-11 14:57:32 +04:00
2018-01-29 07:15:27 +03:00
snd_soc_component_write ( component , AIC31XX_PLLDMSB ,
2014-03-11 14:57:32 +04:00
aic31xx_divs [ i ] . pll_d > > 8 ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_write ( component , AIC31XX_PLLDLSB ,
2014-03-11 14:57:32 +04:00
aic31xx_divs [ i ] . pll_d & 0xff ) ;
/* DAC dividers configuration */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_NDAC , AIC31XX_PLL_MASK ,
2014-03-11 14:57:32 +04:00
aic31xx_divs [ i ] . ndac ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_MDAC , AIC31XX_PLL_MASK ,
2014-03-11 14:57:32 +04:00
aic31xx_divs [ i ] . mdac ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_write ( component , AIC31XX_DOSRMSB , aic31xx_divs [ i ] . dosr > > 8 ) ;
snd_soc_component_write ( component , AIC31XX_DOSRLSB , aic31xx_divs [ i ] . dosr & 0xff ) ;
2014-03-11 14:57:32 +04:00
/* ADC dividers configuration. Write reset value 1 if not used. */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_NADC , AIC31XX_PLL_MASK ,
2014-03-11 14:57:32 +04:00
aic31xx_divs [ i ] . nadc ? aic31xx_divs [ i ] . nadc : 1 ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_MADC , AIC31XX_PLL_MASK ,
2014-03-11 14:57:32 +04:00
aic31xx_divs [ i ] . madc ? aic31xx_divs [ i ] . madc : 1 ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_write ( component , AIC31XX_AOSR , aic31xx_divs [ i ] . aosr ) ;
2014-03-11 14:57:32 +04:00
/* Bit clock divider configuration. */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_BCLKN ,
2014-03-11 14:57:32 +04:00
AIC31XX_PLL_MASK , bclk_n ) ;
aic31xx - > rate_div_line = i ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev ,
2014-03-11 14:57:32 +04:00
" pll %d.%04d/%d dosr %d n %d m %d aosr %d n %d m %d bclk_n %d \n " ,
2017-11-30 00:32:45 +03:00
aic31xx_divs [ i ] . pll_j ,
aic31xx_divs [ i ] . pll_d ,
aic31xx - > p_div ,
aic31xx_divs [ i ] . dosr ,
aic31xx_divs [ i ] . ndac ,
aic31xx_divs [ i ] . mdac ,
aic31xx_divs [ i ] . aosr ,
aic31xx_divs [ i ] . nadc ,
aic31xx_divs [ i ] . madc ,
bclk_n
) ;
2014-03-11 14:57:32 +04:00
return 0 ;
}
static int aic31xx_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params ,
2014-03-14 00:24:54 +04:00
struct snd_soc_dai * dai )
2014-03-11 14:57:32 +04:00
{
2018-01-29 07:15:27 +03:00
struct snd_soc_component * component = dai - > component ;
2014-03-11 14:57:32 +04:00
u8 data = 0 ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " ## %s: width %d rate %d \n " ,
2014-07-31 15:48:13 +04:00
__func__ , params_width ( params ) ,
2014-03-11 14:57:32 +04:00
params_rate ( params ) ) ;
switch ( params_width ( params ) ) {
case 16 :
break ;
case 20 :
data = ( AIC31XX_WORD_LEN_20BITS < <
AIC31XX_IFACE1_DATALEN_SHIFT ) ;
break ;
case 24 :
data = ( AIC31XX_WORD_LEN_24BITS < <
AIC31XX_IFACE1_DATALEN_SHIFT ) ;
break ;
case 32 :
data = ( AIC31XX_WORD_LEN_32BITS < <
AIC31XX_IFACE1_DATALEN_SHIFT ) ;
break ;
default :
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev , " %s: Unsupported width %d \n " ,
2014-07-31 15:48:13 +04:00
__func__ , params_width ( params ) ) ;
2014-03-11 14:57:32 +04:00
return - EINVAL ;
}
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_IFACE1 ,
2014-03-11 14:57:32 +04:00
AIC31XX_IFACE1_DATALEN_MASK ,
data ) ;
2018-01-29 07:15:27 +03:00
return aic31xx_setup_pll ( component , params ) ;
2014-03-11 14:57:32 +04:00
}
static int aic31xx_dac_mute ( struct snd_soc_dai * codec_dai , int mute )
{
2018-01-29 07:15:27 +03:00
struct snd_soc_component * component = codec_dai - > component ;
2014-03-11 14:57:32 +04:00
if ( mute ) {
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_DACMUTE ,
2014-03-11 14:57:32 +04:00
AIC31XX_DACMUTE_MASK ,
AIC31XX_DACMUTE_MASK ) ;
} else {
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_DACMUTE ,
2014-03-11 14:57:32 +04:00
AIC31XX_DACMUTE_MASK , 0x0 ) ;
}
return 0 ;
}
2018-02-14 15:20:56 +03:00
static int aic31xx_clock_master_routes ( struct snd_soc_component * component ,
unsigned int fmt )
{
struct snd_soc_dapm_context * dapm = snd_soc_component_get_dapm ( component ) ;
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
int ret ;
fmt & = SND_SOC_DAIFMT_MASTER_MASK ;
if ( fmt = = SND_SOC_DAIFMT_CBS_CFS & &
aic31xx - > master_dapm_route_applied ) {
/*
* Remove the DAPM route ( s ) for codec clock master modes ,
* if applied
*/
ret = snd_soc_dapm_del_routes ( dapm , common31xx_cm_audio_map ,
ARRAY_SIZE ( common31xx_cm_audio_map ) ) ;
if ( ! ret & & ! ( aic31xx - > codec_type & DAC31XX_BIT ) )
ret = snd_soc_dapm_del_routes ( dapm ,
aic31xx_cm_audio_map ,
ARRAY_SIZE ( aic31xx_cm_audio_map ) ) ;
if ( ret )
return ret ;
aic31xx - > master_dapm_route_applied = false ;
} else if ( fmt ! = SND_SOC_DAIFMT_CBS_CFS & &
! aic31xx - > master_dapm_route_applied ) {
/*
* Add the needed DAPM route ( s ) for codec clock master modes ,
* if it is not done already
*/
ret = snd_soc_dapm_add_routes ( dapm , common31xx_cm_audio_map ,
ARRAY_SIZE ( common31xx_cm_audio_map ) ) ;
if ( ! ret & & ! ( aic31xx - > codec_type & DAC31XX_BIT ) )
ret = snd_soc_dapm_add_routes ( dapm ,
aic31xx_cm_audio_map ,
ARRAY_SIZE ( aic31xx_cm_audio_map ) ) ;
if ( ret )
return ret ;
aic31xx - > master_dapm_route_applied = true ;
}
return 0 ;
}
2014-03-11 14:57:32 +04:00
static int aic31xx_set_dai_fmt ( struct snd_soc_dai * codec_dai ,
unsigned int fmt )
{
2018-01-29 07:15:27 +03:00
struct snd_soc_component * component = codec_dai - > component ;
2014-03-11 14:57:32 +04:00
u8 iface_reg1 = 0 ;
2014-09-01 13:46:37 +04:00
u8 iface_reg2 = 0 ;
2014-03-11 14:57:32 +04:00
u8 dsp_a_val = 0 ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " ## %s: fmt = 0x%x \n " , __func__ , fmt ) ;
2014-03-11 14:57:32 +04:00
/* set master/slave audio interface */
switch ( fmt & SND_SOC_DAIFMT_MASTER_MASK ) {
case SND_SOC_DAIFMT_CBM_CFM :
iface_reg1 | = AIC31XX_BCLK_MASTER | AIC31XX_WCLK_MASTER ;
break ;
2017-11-30 00:32:53 +03:00
case SND_SOC_DAIFMT_CBS_CFM :
iface_reg1 | = AIC31XX_WCLK_MASTER ;
break ;
case SND_SOC_DAIFMT_CBM_CFS :
iface_reg1 | = AIC31XX_BCLK_MASTER ;
break ;
case SND_SOC_DAIFMT_CBS_CFS :
break ;
2014-03-11 14:57:32 +04:00
default :
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev , " Invalid DAI master/slave interface \n " ) ;
2014-03-11 14:57:32 +04:00
return - EINVAL ;
}
2017-11-30 00:32:54 +03:00
/* signal polarity */
switch ( fmt & SND_SOC_DAIFMT_INV_MASK ) {
case SND_SOC_DAIFMT_NB_NF :
break ;
case SND_SOC_DAIFMT_IB_NF :
iface_reg2 | = AIC31XX_BCLKINV_MASK ;
break ;
default :
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev , " Invalid DAI clock signal polarity \n " ) ;
2017-11-30 00:32:54 +03:00
return - EINVAL ;
}
2014-03-11 14:57:32 +04:00
/* interface format */
switch ( fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
case SND_SOC_DAIFMT_I2S :
break ;
case SND_SOC_DAIFMT_DSP_A :
2017-11-08 23:04:17 +03:00
dsp_a_val = 0x1 ; /* fall through */
2014-03-11 14:57:32 +04:00
case SND_SOC_DAIFMT_DSP_B :
2017-11-30 00:32:54 +03:00
/*
* NOTE : This CODEC samples on the falling edge of BCLK in
* DSP mode , this is inverted compared to what most DAIs
* expect , so we invert for this mode
*/
iface_reg2 ^ = AIC31XX_BCLKINV_MASK ;
2014-03-11 14:57:32 +04:00
iface_reg1 | = ( AIC31XX_DSP_MODE < <
AIC31XX_IFACE1_DATATYPE_SHIFT ) ;
break ;
case SND_SOC_DAIFMT_RIGHT_J :
iface_reg1 | = ( AIC31XX_RIGHT_JUSTIFIED_MODE < <
AIC31XX_IFACE1_DATATYPE_SHIFT ) ;
break ;
case SND_SOC_DAIFMT_LEFT_J :
iface_reg1 | = ( AIC31XX_LEFT_JUSTIFIED_MODE < <
AIC31XX_IFACE1_DATATYPE_SHIFT ) ;
break ;
default :
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev , " Invalid DAI interface format \n " ) ;
2014-03-11 14:57:32 +04:00
return - EINVAL ;
}
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_IFACE1 ,
2014-03-11 14:57:32 +04:00
AIC31XX_IFACE1_DATATYPE_MASK |
AIC31XX_IFACE1_MASTER_MASK ,
iface_reg1 ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_DATA_OFFSET ,
2014-03-11 14:57:32 +04:00
AIC31XX_DATA_OFFSET_MASK ,
dsp_a_val ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_IFACE2 ,
2014-03-11 14:57:32 +04:00
AIC31XX_BCLKINV_MASK ,
2014-09-01 13:46:37 +04:00
iface_reg2 ) ;
2014-03-11 14:57:32 +04:00
2018-02-14 15:20:56 +03:00
return aic31xx_clock_master_routes ( component , fmt ) ;
2014-03-11 14:57:32 +04:00
}
static int aic31xx_set_dai_sysclk ( struct snd_soc_dai * codec_dai ,
int clk_id , unsigned int freq , int dir )
{
2018-01-29 07:15:27 +03:00
struct snd_soc_component * component = codec_dai - > component ;
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-03-11 14:57:32 +04:00
int i ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " ## %s: clk_id = %d, freq = %d, dir = %d \n " ,
2014-03-11 14:57:32 +04:00
__func__ , clk_id , freq , dir ) ;
2017-11-30 00:32:45 +03:00
for ( i = 1 ; i < 8 ; i + + )
if ( freq / i < = 20000000 )
break ;
2014-09-03 16:52:34 +04:00
if ( freq / i > 20000000 ) {
dev_err ( aic31xx - > dev , " %s: Too high mclk frequency %u \n " ,
__func__ , freq ) ;
2018-11-16 18:06:33 +03:00
return - EINVAL ;
2014-09-03 16:52:34 +04:00
}
aic31xx - > p_div = i ;
2017-11-30 00:32:45 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( aic31xx_divs ) ; i + + )
if ( aic31xx_divs [ i ] . mclk_p = = freq / aic31xx - > p_div )
break ;
2014-11-24 21:37:12 +03:00
if ( i = = ARRAY_SIZE ( aic31xx_divs ) ) {
dev_err ( aic31xx - > dev , " %s: Unsupported frequency %d \n " ,
__func__ , freq ) ;
return - EINVAL ;
2014-03-11 14:57:32 +04:00
}
/* set clock on MCLK, BCLK, or GPIO1 as PLL input */
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_CLKMUX , AIC31XX_PLL_CLKIN_MASK ,
2014-03-11 14:57:32 +04:00
clk_id < < AIC31XX_PLL_CLKIN_SHIFT ) ;
aic31xx - > sysclk = freq ;
2017-11-30 00:32:45 +03:00
2014-03-11 14:57:32 +04:00
return 0 ;
}
static int aic31xx_regulator_event ( struct notifier_block * nb ,
unsigned long event , void * data )
{
struct aic31xx_disable_nb * disable_nb =
container_of ( nb , struct aic31xx_disable_nb , nb ) ;
struct aic31xx_priv * aic31xx = disable_nb - > aic31xx ;
if ( event & REGULATOR_EVENT_DISABLE ) {
/*
* Put codec to reset and as at least one of the
* supplies was disabled .
*/
2017-11-30 00:32:49 +03:00
if ( aic31xx - > gpio_reset )
gpiod_set_value ( aic31xx - > gpio_reset , 1 ) ;
2014-03-11 14:57:32 +04:00
regcache_mark_dirty ( aic31xx - > regmap ) ;
dev_dbg ( aic31xx - > dev , " ## %s: DISABLE received \n " , __func__ ) ;
}
return 0 ;
}
2017-12-07 18:38:56 +03:00
static int aic31xx_reset ( struct aic31xx_priv * aic31xx )
{
int ret = 0 ;
if ( aic31xx - > gpio_reset ) {
gpiod_set_value ( aic31xx - > gpio_reset , 1 ) ;
ndelay ( 10 ) ; /* At least 10ns */
gpiod_set_value ( aic31xx - > gpio_reset , 0 ) ;
} else {
ret = regmap_write ( aic31xx - > regmap , AIC31XX_RESET , 1 ) ;
}
mdelay ( 1 ) ; /* At least 1ms */
return ret ;
}
2018-01-29 07:15:27 +03:00
static void aic31xx_clk_on ( struct snd_soc_component * component )
2014-03-11 14:57:32 +04:00
{
2018-01-29 07:15:27 +03:00
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-03-11 14:57:32 +04:00
u8 mask = AIC31XX_PM_MASK ;
u8 on = AIC31XX_PM_MASK ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " codec clock -> on (rate %d) \n " ,
2014-03-11 14:57:32 +04:00
aic31xx_divs [ aic31xx - > rate_div_line ] . rate ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_PLLPR , mask , on ) ;
2014-03-11 14:57:32 +04:00
mdelay ( 10 ) ;
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_NDAC , mask , on ) ;
snd_soc_component_update_bits ( component , AIC31XX_MDAC , mask , on ) ;
2014-03-11 14:57:32 +04:00
if ( aic31xx_divs [ aic31xx - > rate_div_line ] . nadc )
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_NADC , mask , on ) ;
2014-03-11 14:57:32 +04:00
if ( aic31xx_divs [ aic31xx - > rate_div_line ] . madc )
2018-01-29 07:15:27 +03:00
snd_soc_component_update_bits ( component , AIC31XX_MADC , mask , on ) ;
snd_soc_component_update_bits ( component , AIC31XX_BCLKN , mask , on ) ;
2014-03-11 14:57:32 +04:00
}
2018-01-29 07:15:27 +03:00
static void aic31xx_clk_off ( struct snd_soc_component * component )
2014-03-11 14:57:32 +04:00
{
u8 mask = AIC31XX_PM_MASK ;
u8 off = 0 ;
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " codec clock -> off \n " ) ;
snd_soc_component_update_bits ( component , AIC31XX_BCLKN , mask , off ) ;
snd_soc_component_update_bits ( component , AIC31XX_MADC , mask , off ) ;
snd_soc_component_update_bits ( component , AIC31XX_NADC , mask , off ) ;
snd_soc_component_update_bits ( component , AIC31XX_MDAC , mask , off ) ;
snd_soc_component_update_bits ( component , AIC31XX_NDAC , mask , off ) ;
snd_soc_component_update_bits ( component , AIC31XX_PLLPR , mask , off ) ;
2014-03-11 14:57:32 +04:00
}
2018-01-29 07:15:27 +03:00
static int aic31xx_power_on ( struct snd_soc_component * component )
2014-03-11 14:57:32 +04:00
{
2018-01-29 07:15:27 +03:00
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2017-11-30 00:32:45 +03:00
int ret ;
2014-03-11 14:57:32 +04:00
ret = regulator_bulk_enable ( ARRAY_SIZE ( aic31xx - > supplies ) ,
aic31xx - > supplies ) ;
if ( ret )
return ret ;
regcache_cache_only ( aic31xx - > regmap , false ) ;
2017-12-07 18:38:56 +03:00
/* Reset device registers for a consistent power-on like state */
ret = aic31xx_reset ( aic31xx ) ;
if ( ret < 0 )
dev_err ( aic31xx - > dev , " Could not reset device: %d \n " , ret ) ;
2014-03-11 14:57:32 +04:00
ret = regcache_sync ( aic31xx - > regmap ) ;
2017-11-30 00:32:45 +03:00
if ( ret ) {
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev ,
2014-03-11 14:57:32 +04:00
" Failed to restore cache: %d \n " , ret ) ;
regcache_cache_only ( aic31xx - > regmap , true ) ;
regulator_bulk_disable ( ARRAY_SIZE ( aic31xx - > supplies ) ,
aic31xx - > supplies ) ;
return ret ;
}
2017-11-30 00:32:45 +03:00
2014-03-11 14:57:32 +04:00
return 0 ;
}
2018-01-29 07:15:27 +03:00
static void aic31xx_power_off ( struct snd_soc_component * component )
2014-03-11 14:57:32 +04:00
{
2018-01-29 07:15:27 +03:00
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2014-03-11 14:57:32 +04:00
regcache_cache_only ( aic31xx - > regmap , true ) ;
2017-11-30 00:32:43 +03:00
regulator_bulk_disable ( ARRAY_SIZE ( aic31xx - > supplies ) ,
aic31xx - > supplies ) ;
2014-03-11 14:57:32 +04:00
}
2018-01-29 07:15:27 +03:00
static int aic31xx_set_bias_level ( struct snd_soc_component * component ,
2014-03-11 14:57:32 +04:00
enum snd_soc_bias_level level )
{
2018-01-29 07:15:27 +03:00
dev_dbg ( component - > dev , " ## %s: %d -> %d \n " , __func__ ,
snd_soc_component_get_bias_level ( component ) , level ) ;
2014-03-11 14:57:32 +04:00
switch ( level ) {
case SND_SOC_BIAS_ON :
break ;
case SND_SOC_BIAS_PREPARE :
2018-01-29 07:15:27 +03:00
if ( snd_soc_component_get_bias_level ( component ) = = SND_SOC_BIAS_STANDBY )
aic31xx_clk_on ( component ) ;
2014-03-11 14:57:32 +04:00
break ;
case SND_SOC_BIAS_STANDBY :
2018-01-29 07:15:27 +03:00
switch ( snd_soc_component_get_bias_level ( component ) ) {
2014-03-11 14:57:32 +04:00
case SND_SOC_BIAS_OFF :
2018-01-29 07:15:27 +03:00
aic31xx_power_on ( component ) ;
2014-03-11 14:57:32 +04:00
break ;
case SND_SOC_BIAS_PREPARE :
2018-01-29 07:15:27 +03:00
aic31xx_clk_off ( component ) ;
2014-03-11 14:57:32 +04:00
break ;
default :
BUG ( ) ;
}
break ;
case SND_SOC_BIAS_OFF :
2018-01-29 07:15:27 +03:00
if ( snd_soc_component_get_bias_level ( component ) = = SND_SOC_BIAS_STANDBY )
aic31xx_power_off ( component ) ;
2014-03-11 14:57:32 +04:00
break ;
}
return 0 ;
}
2019-04-02 14:46:18 +03:00
static int aic31xx_set_jack ( struct snd_soc_component * component ,
struct snd_soc_jack * jack , void * data )
2019-04-01 18:13:28 +03:00
{
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
aic31xx - > jack = jack ;
/* Enable/Disable jack detection */
regmap_write ( aic31xx - > regmap , AIC31XX_HSDETECT ,
jack ? AIC31XX_HSD_ENABLE : 0 ) ;
return 0 ;
}
2018-01-29 07:15:27 +03:00
static int aic31xx_codec_probe ( struct snd_soc_component * component )
2014-03-11 14:57:32 +04:00
{
2018-01-29 07:15:27 +03:00
struct aic31xx_priv * aic31xx = snd_soc_component_get_drvdata ( component ) ;
2017-11-30 00:32:45 +03:00
int i , ret ;
2014-03-11 14:57:32 +04:00
dev_dbg ( aic31xx - > dev , " ## %s \n " , __func__ ) ;
2018-01-29 07:15:27 +03:00
aic31xx - > component = component ;
2014-03-11 14:57:32 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( aic31xx - > supplies ) ; i + + ) {
aic31xx - > disable_nb [ i ] . nb . notifier_call =
aic31xx_regulator_event ;
aic31xx - > disable_nb [ i ] . aic31xx = aic31xx ;
2019-02-08 16:45:20 +03:00
ret = devm_regulator_register_notifier (
aic31xx - > supplies [ i ] . consumer ,
& aic31xx - > disable_nb [ i ] . nb ) ;
2014-03-11 14:57:32 +04:00
if ( ret ) {
2018-01-29 07:15:27 +03:00
dev_err ( component - > dev ,
2014-03-11 14:57:32 +04:00
" Failed to request regulator notifier: %d \n " ,
ret ) ;
return ret ;
}
}
regcache_cache_only ( aic31xx - > regmap , true ) ;
regcache_mark_dirty ( aic31xx - > regmap ) ;
2018-01-29 07:15:27 +03:00
ret = aic31xx_add_controls ( component ) ;
2014-03-11 14:57:32 +04:00
if ( ret )
return ret ;
2018-01-29 07:15:27 +03:00
ret = aic31xx_add_widgets ( component ) ;
2017-11-30 00:32:45 +03:00
if ( ret )
return ret ;
2014-03-11 14:57:32 +04:00
2017-11-30 00:32:45 +03:00
return 0 ;
2014-03-11 14:57:32 +04:00
}
2018-01-29 07:15:27 +03:00
static const struct snd_soc_component_driver soc_codec_driver_aic31xx = {
2014-03-11 14:57:32 +04:00
. probe = aic31xx_codec_probe ,
2019-04-01 18:13:28 +03:00
. set_jack = aic31xx_set_jack ,
2014-03-11 14:57:32 +04:00
. set_bias_level = aic31xx_set_bias_level ,
2018-01-29 07:15:27 +03:00
. controls = common31xx_snd_controls ,
. num_controls = ARRAY_SIZE ( common31xx_snd_controls ) ,
. dapm_widgets = common31xx_dapm_widgets ,
. num_dapm_widgets = ARRAY_SIZE ( common31xx_dapm_widgets ) ,
. dapm_routes = common31xx_audio_map ,
. num_dapm_routes = ARRAY_SIZE ( common31xx_audio_map ) ,
. suspend_bias_off = 1 ,
. idle_bias_on = 1 ,
. use_pmdown_time = 1 ,
. endianness = 1 ,
. non_legacy_dai_naming = 1 ,
2014-03-11 14:57:32 +04:00
} ;
2015-07-15 10:38:14 +03:00
static const struct snd_soc_dai_ops aic31xx_dai_ops = {
2014-03-11 14:57:32 +04:00
. hw_params = aic31xx_hw_params ,
. set_sysclk = aic31xx_set_dai_sysclk ,
. set_fmt = aic31xx_set_dai_fmt ,
. digital_mute = aic31xx_dac_mute ,
} ;
2016-09-23 14:52:52 +03:00
static struct snd_soc_dai_driver dac31xx_dai_driver [ ] = {
{
2017-05-13 00:29:37 +03:00
. name = " tlv320dac31xx-hifi " ,
2016-09-23 14:52:52 +03:00
. playback = {
. stream_name = " Playback " ,
2016-09-27 11:30:15 +03:00
. channels_min = 2 ,
2016-09-23 14:52:52 +03:00
. channels_max = 2 ,
. rates = AIC31XX_RATES ,
. formats = AIC31XX_FORMATS ,
} ,
. ops = & aic31xx_dai_ops ,
. symmetric_rates = 1 ,
}
} ;
2014-03-11 14:57:32 +04:00
static struct snd_soc_dai_driver aic31xx_dai_driver [ ] = {
{
. name = " tlv320aic31xx-hifi " ,
. playback = {
. stream_name = " Playback " ,
2016-09-27 11:30:15 +03:00
. channels_min = 2 ,
2014-03-11 14:57:32 +04:00
. channels_max = 2 ,
. rates = AIC31XX_RATES ,
. formats = AIC31XX_FORMATS ,
} ,
. capture = {
. stream_name = " Capture " ,
2016-09-27 11:30:15 +03:00
. channels_min = 2 ,
2014-03-11 14:57:32 +04:00
. channels_max = 2 ,
. rates = AIC31XX_RATES ,
. formats = AIC31XX_FORMATS ,
} ,
. ops = & aic31xx_dai_ops ,
. symmetric_rates = 1 ,
}
} ;
# if defined(CONFIG_OF)
static const struct of_device_id tlv320aic31xx_of_match [ ] = {
{ . compatible = " ti,tlv320aic310x " } ,
{ . compatible = " ti,tlv320aic311x " } ,
{ . compatible = " ti,tlv320aic3100 " } ,
{ . compatible = " ti,tlv320aic3110 " } ,
{ . compatible = " ti,tlv320aic3120 " } ,
{ . compatible = " ti,tlv320aic3111 " } ,
2016-11-10 10:55:54 +03:00
{ . compatible = " ti,tlv320dac3100 " } ,
2016-11-10 10:55:55 +03:00
{ . compatible = " ti,tlv320dac3101 " } ,
2014-03-11 14:57:32 +04:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , tlv320aic31xx_of_match ) ;
# endif /* CONFIG_OF */
2017-11-30 00:32:44 +03:00
# ifdef CONFIG_ACPI
static const struct acpi_device_id aic31xx_acpi_match [ ] = {
{ " 10TI3100 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( acpi , aic31xx_acpi_match ) ;
# endif
2018-08-31 21:24:31 +03:00
static irqreturn_t aic31xx_irq ( int irq , void * data )
{
struct aic31xx_priv * aic31xx = data ;
struct device * dev = aic31xx - > dev ;
unsigned int value ;
bool handled = false ;
int ret ;
ret = regmap_read ( aic31xx - > regmap , AIC31XX_INTRDACFLAG , & value ) ;
if ( ret ) {
dev_err ( dev , " Failed to read interrupt mask: %d \n " , ret ) ;
goto exit ;
}
if ( value )
handled = true ;
else
2018-09-04 18:36:17 +03:00
goto read_overflow ;
2018-08-31 21:24:31 +03:00
if ( value & AIC31XX_HPLSCDETECT )
dev_err ( dev , " Short circuit on Left output is detected \n " ) ;
if ( value & AIC31XX_HPRSCDETECT )
dev_err ( dev , " Short circuit on Right output is detected \n " ) ;
2019-04-01 18:13:29 +03:00
if ( value & ( AIC31XX_HSPLUG | AIC31XX_BUTTONPRESS ) ) {
2019-04-01 18:13:28 +03:00
unsigned int val ;
int status = 0 ;
2019-04-01 18:13:29 +03:00
ret = regmap_read ( aic31xx - > regmap , AIC31XX_INTRDACFLAG2 ,
& val ) ;
if ( ret ) {
dev_err ( dev , " Failed to read interrupt mask: %d \n " ,
ret ) ;
goto exit ;
}
if ( val & AIC31XX_BUTTONPRESS )
status | = SND_JACK_BTN_0 ;
2019-04-01 18:13:28 +03:00
ret = regmap_read ( aic31xx - > regmap , AIC31XX_HSDETECT , & val ) ;
if ( ret ) {
dev_err ( dev , " Failed to read headset type: %d \n " , ret ) ;
goto exit ;
}
switch ( ( val & AIC31XX_HSD_TYPE_MASK ) > >
AIC31XX_HSD_TYPE_SHIFT ) {
case AIC31XX_HSD_HP :
status | = SND_JACK_HEADPHONE ;
break ;
case AIC31XX_HSD_HS :
status | = SND_JACK_HEADSET ;
break ;
default :
break ;
}
if ( aic31xx - > jack )
snd_soc_jack_report ( aic31xx - > jack , status ,
AIC31XX_JACK_MASK ) ;
}
2018-08-31 21:24:31 +03:00
if ( value & ~ ( AIC31XX_HPLSCDETECT |
2019-04-01 18:13:28 +03:00
AIC31XX_HPRSCDETECT |
2019-04-01 18:13:29 +03:00
AIC31XX_HSPLUG |
AIC31XX_BUTTONPRESS ) )
2018-08-31 21:24:31 +03:00
dev_err ( dev , " Unknown DAC interrupt flags: 0x%08x \n " , value ) ;
2018-09-04 18:36:17 +03:00
read_overflow :
ret = regmap_read ( aic31xx - > regmap , AIC31XX_OFFLAG , & value ) ;
if ( ret ) {
dev_err ( dev , " Failed to read overflow flag: %d \n " , ret ) ;
goto exit ;
}
if ( value )
handled = true ;
else
goto exit ;
if ( value & AIC31XX_DAC_OF_LEFT )
dev_warn ( dev , " Left-channel DAC overflow has occurred \n " ) ;
if ( value & AIC31XX_DAC_OF_RIGHT )
dev_warn ( dev , " Right-channel DAC overflow has occurred \n " ) ;
if ( value & AIC31XX_DAC_OF_SHIFTER )
dev_warn ( dev , " DAC barrel shifter overflow has occurred \n " ) ;
if ( value & AIC31XX_ADC_OF )
dev_warn ( dev , " ADC overflow has occurred \n " ) ;
if ( value & AIC31XX_ADC_OF_SHIFTER )
dev_warn ( dev , " ADC barrel shifter overflow has occurred \n " ) ;
if ( value & ~ ( AIC31XX_DAC_OF_LEFT |
AIC31XX_DAC_OF_RIGHT |
AIC31XX_DAC_OF_SHIFTER |
AIC31XX_ADC_OF |
AIC31XX_ADC_OF_SHIFTER ) )
dev_warn ( dev , " Unknown overflow interrupt flags: 0x%08x \n " , value ) ;
2018-08-31 21:24:31 +03:00
exit :
if ( handled )
return IRQ_HANDLED ;
else
return IRQ_NONE ;
}
2017-11-30 00:32:48 +03:00
static int aic31xx_i2c_probe ( struct i2c_client * i2c ,
const struct i2c_device_id * id )
2014-03-11 14:57:32 +04:00
{
2017-11-30 00:32:48 +03:00
struct aic31xx_priv * aic31xx ;
2017-12-07 18:38:52 +03:00
unsigned int micbias_value = MICBIAS_2_0V ;
2017-11-30 00:32:48 +03:00
int i , ret ;
dev_dbg ( & i2c - > dev , " ## %s: %s codec_type = %d \n " , __func__ ,
id - > name , ( int ) id - > driver_data ) ;
aic31xx = devm_kzalloc ( & i2c - > dev , sizeof ( * aic31xx ) , GFP_KERNEL ) ;
if ( ! aic31xx )
return - ENOMEM ;
aic31xx - > regmap = devm_regmap_init_i2c ( i2c , & aic31xx_i2c_regmap ) ;
if ( IS_ERR ( aic31xx - > regmap ) ) {
ret = PTR_ERR ( aic31xx - > regmap ) ;
dev_err ( & i2c - > dev , " Failed to allocate register map: %d \n " ,
ret ) ;
return ret ;
}
aic31xx - > dev = & i2c - > dev ;
2018-08-31 21:24:31 +03:00
aic31xx - > irq = i2c - > irq ;
2017-11-30 00:32:48 +03:00
2017-12-07 18:38:52 +03:00
aic31xx - > codec_type = id - > driver_data ;
2014-03-11 14:57:32 +04:00
dev_set_drvdata ( aic31xx - > dev , aic31xx ) ;
2017-12-07 18:38:52 +03:00
fwnode_property_read_u32 ( aic31xx - > dev - > fwnode , " ai31xx-micbias-vg " ,
& micbias_value ) ;
switch ( micbias_value ) {
case MICBIAS_2_0V :
case MICBIAS_2_5V :
case MICBIAS_AVDDV :
aic31xx - > micbias_vg = micbias_value ;
break ;
default :
dev_err ( aic31xx - > dev , " Bad ai31xx-micbias-vg value %d \n " ,
micbias_value ) ;
aic31xx - > micbias_vg = MICBIAS_2_0V ;
}
if ( dev_get_platdata ( aic31xx - > dev ) ) {
memcpy ( & aic31xx - > pdata , dev_get_platdata ( aic31xx - > dev ) , sizeof ( aic31xx - > pdata ) ) ;
aic31xx - > codec_type = aic31xx - > pdata . codec_type ;
aic31xx - > micbias_vg = aic31xx - > pdata . micbias_vg ;
}
2014-03-11 14:57:32 +04:00
2017-11-30 00:32:49 +03:00
aic31xx - > gpio_reset = devm_gpiod_get_optional ( aic31xx - > dev , " reset " ,
GPIOD_OUT_LOW ) ;
if ( IS_ERR ( aic31xx - > gpio_reset ) ) {
2019-07-19 17:36:37 +03:00
if ( PTR_ERR ( aic31xx - > gpio_reset ) ! = - EPROBE_DEFER )
dev_err ( aic31xx - > dev , " not able to acquire gpio \n " ) ;
2017-11-30 00:32:49 +03:00
return PTR_ERR ( aic31xx - > gpio_reset ) ;
2014-03-11 14:57:32 +04:00
}
for ( i = 0 ; i < ARRAY_SIZE ( aic31xx - > supplies ) ; i + + )
aic31xx - > supplies [ i ] . supply = aic31xx_supply_names [ i ] ;
ret = devm_regulator_bulk_get ( aic31xx - > dev ,
ARRAY_SIZE ( aic31xx - > supplies ) ,
aic31xx - > supplies ) ;
2017-11-30 00:32:45 +03:00
if ( ret ) {
2019-07-19 17:36:37 +03:00
if ( ret ! = - EPROBE_DEFER )
dev_err ( aic31xx - > dev ,
" Failed to request supplies: %d \n " , ret ) ;
2017-11-30 00:32:45 +03:00
return ret ;
}
2014-03-11 14:57:32 +04:00
2018-08-31 21:24:31 +03:00
if ( aic31xx - > irq > 0 ) {
regmap_update_bits ( aic31xx - > regmap , AIC31XX_GPIO1 ,
AIC31XX_GPIO1_FUNC_MASK ,
AIC31XX_GPIO1_INT1 < <
AIC31XX_GPIO1_FUNC_SHIFT ) ;
regmap_write ( aic31xx - > regmap , AIC31XX_INT1CTRL ,
2019-04-01 18:13:28 +03:00
AIC31XX_HSPLUGDET |
2019-04-01 18:13:29 +03:00
AIC31XX_BUTTONPRESSDET |
2018-09-04 18:36:17 +03:00
AIC31XX_SC |
AIC31XX_ENGINE ) ;
2018-08-31 21:24:31 +03:00
ret = devm_request_threaded_irq ( aic31xx - > dev , aic31xx - > irq ,
NULL , aic31xx_irq ,
IRQF_ONESHOT , " aic31xx-irq " ,
aic31xx ) ;
if ( ret ) {
dev_err ( aic31xx - > dev , " Unable to request IRQ \n " ) ;
return ret ;
}
}
2017-12-07 18:38:52 +03:00
if ( aic31xx - > codec_type & DAC31XX_BIT )
2018-01-29 07:15:27 +03:00
return devm_snd_soc_register_component ( & i2c - > dev ,
2016-09-23 14:52:52 +03:00
& soc_codec_driver_aic31xx ,
dac31xx_dai_driver ,
ARRAY_SIZE ( dac31xx_dai_driver ) ) ;
else
2018-01-29 07:15:27 +03:00
return devm_snd_soc_register_component ( & i2c - > dev ,
2016-09-23 14:52:52 +03:00
& soc_codec_driver_aic31xx ,
aic31xx_dai_driver ,
ARRAY_SIZE ( aic31xx_dai_driver ) ) ;
2014-03-11 14:57:32 +04:00
}
static const struct i2c_device_id aic31xx_i2c_id [ ] = {
{ " tlv320aic310x " , AIC3100 } ,
{ " tlv320aic311x " , AIC3110 } ,
{ " tlv320aic3100 " , AIC3100 } ,
{ " tlv320aic3110 " , AIC3110 } ,
{ " tlv320aic3120 " , AIC3120 } ,
{ " tlv320aic3111 " , AIC3111 } ,
2016-09-23 14:52:52 +03:00
{ " tlv320dac3100 " , DAC3100 } ,
2016-11-10 10:55:55 +03:00
{ " tlv320dac3101 " , DAC3101 } ,
2014-03-11 14:57:32 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , aic31xx_i2c_id ) ;
static struct i2c_driver aic31xx_i2c_driver = {
. driver = {
. name = " tlv320aic31xx-codec " ,
. of_match_table = of_match_ptr ( tlv320aic31xx_of_match ) ,
2016-04-19 19:00:20 +03:00
. acpi_match_table = ACPI_PTR ( aic31xx_acpi_match ) ,
2014-03-11 14:57:32 +04:00
} ,
. probe = aic31xx_i2c_probe ,
. id_table = aic31xx_i2c_id ,
} ;
module_i2c_driver ( aic31xx_i2c_driver ) ;
2017-11-30 00:32:42 +03:00
MODULE_AUTHOR ( " Jyri Sarha <jsarha@ti.com> " ) ;
MODULE_DESCRIPTION ( " ASoC TLV320AIC31xx CODEC Driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;