2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2011-05-18 19:25:09 +04:00
/*
* ak4641 . c - - AK4641 ALSA Soc Audio driver
*
* Copyright ( C ) 2008 Harald Welte < laforge @ gnufiish . org >
* Copyright ( C ) 2011 Dmitry Artamonow < mad_soft @ inbox . ru >
*
* Based on ak4535 . c by Richard Purdie
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/gpio.h>
# include <linux/pm.h>
# include <linux/i2c.h>
2013-11-22 19:14:48 +04:00
# include <linux/regmap.h>
2011-05-18 19:25:09 +04:00
# include <linux/slab.h>
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
# include <sound/soc.h>
# include <sound/initval.h>
# include <sound/tlv.h>
# include <sound/ak4641.h>
2016-10-15 22:32:41 +03:00
/* AK4641 register space */
# define AK4641_PM1 0x00
# define AK4641_PM2 0x01
# define AK4641_SIG1 0x02
# define AK4641_SIG2 0x03
# define AK4641_MODE1 0x04
# define AK4641_MODE2 0x05
# define AK4641_DAC 0x06
# define AK4641_MIC 0x07
# define AK4641_TIMER 0x08
# define AK4641_ALC1 0x09
# define AK4641_ALC2 0x0a
# define AK4641_PGA 0x0b
# define AK4641_LATT 0x0c
# define AK4641_RATT 0x0d
# define AK4641_VOL 0x0e
# define AK4641_STATUS 0x0f
# define AK4641_EQLO 0x10
# define AK4641_EQMID 0x11
# define AK4641_EQHI 0x12
# define AK4641_BTIF 0x13
2011-05-18 19:25:09 +04:00
/* codec private data */
struct ak4641_priv {
2013-11-22 19:14:48 +04:00
struct regmap * regmap ;
2011-05-18 19:25:09 +04:00
unsigned int sysclk ;
int deemph ;
int playback_fs ;
} ;
/*
* ak4641 register cache
*/
2013-11-22 19:14:48 +04:00
static const struct reg_default ak4641_reg_defaults [ ] = {
{ 0 , 0x00 } , { 1 , 0x80 } , { 2 , 0x00 } , { 3 , 0x80 } ,
{ 4 , 0x02 } , { 5 , 0x00 } , { 6 , 0x11 } , { 7 , 0x05 } ,
{ 8 , 0x00 } , { 9 , 0x00 } , { 10 , 0x36 } , { 11 , 0x10 } ,
{ 12 , 0x00 } , { 13 , 0x00 } , { 14 , 0x57 } , { 15 , 0x00 } ,
{ 16 , 0x88 } , { 17 , 0x88 } , { 18 , 0x08 } , { 19 , 0x08 }
2011-05-18 19:25:09 +04:00
} ;
static const int deemph_settings [ ] = { 44100 , 0 , 48000 , 32000 } ;
2018-01-29 06:14:32 +03:00
static int ak4641_set_deemph ( struct snd_soc_component * component )
2011-05-18 19:25:09 +04:00
{
2018-01-29 06:14:32 +03:00
struct ak4641_priv * ak4641 = snd_soc_component_get_drvdata ( component ) ;
2011-05-18 19:25:09 +04:00
int i , best = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( deemph_settings ) ; i + + ) {
/* if deemphasis is on, select the nearest available rate */
if ( ak4641 - > deemph & & deemph_settings [ i ] ! = 0 & &
abs ( deemph_settings [ i ] - ak4641 - > playback_fs ) <
abs ( deemph_settings [ best ] - ak4641 - > playback_fs ) )
best = i ;
if ( ! ak4641 - > deemph & & deemph_settings [ i ] = = 0 )
best = i ;
}
2018-01-29 06:14:32 +03:00
dev_dbg ( component - > dev , " Set deemphasis %d \n " , best ) ;
2011-05-18 19:25:09 +04:00
2018-01-29 06:14:32 +03:00
return snd_soc_component_update_bits ( component , AK4641_DAC , 0x3 , best ) ;
2011-05-18 19:25:09 +04:00
}
static int ak4641_put_deemph ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 06:14:32 +03:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct ak4641_priv * ak4641 = snd_soc_component_get_drvdata ( component ) ;
2015-03-10 14:39:04 +03:00
int deemph = ucontrol - > value . integer . value [ 0 ] ;
2011-05-18 19:25:09 +04:00
if ( deemph > 1 )
return - EINVAL ;
ak4641 - > deemph = deemph ;
2018-01-29 06:14:32 +03:00
return ak4641_set_deemph ( component ) ;
2011-05-18 19:25:09 +04:00
}
static int ak4641_get_deemph ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
2018-01-29 06:14:32 +03:00
struct snd_soc_component * component = snd_soc_kcontrol_component ( kcontrol ) ;
struct ak4641_priv * ak4641 = snd_soc_component_get_drvdata ( component ) ;
2011-05-18 19:25:09 +04:00
2015-03-10 14:39:04 +03:00
ucontrol - > value . integer . value [ 0 ] = ak4641 - > deemph ;
2011-05-18 19:25:09 +04:00
return 0 ;
} ;
static const char * ak4641_mono_out [ ] = { " (L + R)/2 " , " Hi-Z " } ;
static const char * ak4641_hp_out [ ] = { " Stereo " , " Mono " } ;
static const char * ak4641_mic_select [ ] = { " Internal " , " External " } ;
static const char * ak4641_mic_or_dac [ ] = { " Microphone " , " Voice DAC " } ;
static const DECLARE_TLV_DB_SCALE ( mono_gain_tlv , - 1700 , 2300 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( mic_boost_tlv , 0 , 2000 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( eq_tlv , - 1050 , 150 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( master_tlv , - 12750 , 50 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( mic_stereo_sidetone_tlv , - 2700 , 300 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( mic_mono_sidetone_tlv , - 400 , 400 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( capture_tlv , - 800 , 50 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( alc_tlv , - 800 , 50 , 0 ) ;
static const DECLARE_TLV_DB_SCALE ( aux_in_tlv , - 2100 , 300 , 0 ) ;
2014-02-18 13:43:45 +04:00
static SOC_ENUM_SINGLE_DECL ( ak4641_mono_out_enum ,
AK4641_SIG1 , 6 , ak4641_mono_out ) ;
static SOC_ENUM_SINGLE_DECL ( ak4641_hp_out_enum ,
AK4641_MODE2 , 2 , ak4641_hp_out ) ;
static SOC_ENUM_SINGLE_DECL ( ak4641_mic_select_enum ,
AK4641_MIC , 1 , ak4641_mic_select ) ;
static SOC_ENUM_SINGLE_DECL ( ak4641_mic_or_dac_enum ,
AK4641_BTIF , 4 , ak4641_mic_or_dac ) ;
2011-05-18 19:25:09 +04:00
static const struct snd_kcontrol_new ak4641_snd_controls [ ] = {
SOC_ENUM ( " Mono 1 Output " , ak4641_mono_out_enum ) ,
SOC_SINGLE_TLV ( " Mono 1 Gain Volume " , AK4641_SIG1 , 7 , 1 , 1 ,
mono_gain_tlv ) ,
SOC_ENUM ( " Headphone Output " , ak4641_hp_out_enum ) ,
SOC_SINGLE_BOOL_EXT ( " Playback Deemphasis Switch " , 0 ,
ak4641_get_deemph , ak4641_put_deemph ) ,
SOC_SINGLE_TLV ( " Mic Boost Volume " , AK4641_MIC , 0 , 1 , 0 , mic_boost_tlv ) ,
SOC_SINGLE ( " ALC Operation Time " , AK4641_TIMER , 0 , 3 , 0 ) ,
SOC_SINGLE ( " ALC Recovery Time " , AK4641_TIMER , 2 , 3 , 0 ) ,
SOC_SINGLE ( " ALC ZC Time " , AK4641_TIMER , 4 , 3 , 0 ) ,
SOC_SINGLE ( " ALC 1 Switch " , AK4641_ALC1 , 5 , 1 , 0 ) ,
SOC_SINGLE_TLV ( " ALC Volume " , AK4641_ALC2 , 0 , 71 , 0 , alc_tlv ) ,
SOC_SINGLE ( " Left Out Enable Switch " , AK4641_SIG2 , 1 , 1 , 0 ) ,
SOC_SINGLE ( " Right Out Enable Switch " , AK4641_SIG2 , 0 , 1 , 0 ) ,
SOC_SINGLE_TLV ( " Capture Volume " , AK4641_PGA , 0 , 71 , 0 , capture_tlv ) ,
SOC_DOUBLE_R_TLV ( " Master Playback Volume " , AK4641_LATT ,
AK4641_RATT , 0 , 255 , 1 , master_tlv ) ,
SOC_SINGLE_TLV ( " AUX In Volume " , AK4641_VOL , 0 , 15 , 0 , aux_in_tlv ) ,
SOC_SINGLE ( " Equalizer Switch " , AK4641_DAC , 2 , 1 , 0 ) ,
SOC_SINGLE_TLV ( " EQ1 100 Hz Volume " , AK4641_EQLO , 0 , 15 , 1 , eq_tlv ) ,
SOC_SINGLE_TLV ( " EQ2 250 Hz Volume " , AK4641_EQLO , 4 , 15 , 1 , eq_tlv ) ,
SOC_SINGLE_TLV ( " EQ3 1 kHz Volume " , AK4641_EQMID , 0 , 15 , 1 , eq_tlv ) ,
SOC_SINGLE_TLV ( " EQ4 3.5 kHz Volume " , AK4641_EQMID , 4 , 15 , 1 , eq_tlv ) ,
SOC_SINGLE_TLV ( " EQ5 10 kHz Volume " , AK4641_EQHI , 0 , 15 , 1 , eq_tlv ) ,
} ;
/* Mono 1 Mixer */
static const struct snd_kcontrol_new ak4641_mono1_mixer_controls [ ] = {
SOC_DAPM_SINGLE_TLV ( " Mic Mono Sidetone Volume " , AK4641_VOL , 7 , 1 , 0 ,
mic_mono_sidetone_tlv ) ,
SOC_DAPM_SINGLE ( " Mic Mono Sidetone Switch " , AK4641_SIG1 , 4 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " Mono Playback Switch " , AK4641_SIG1 , 5 , 1 , 0 ) ,
} ;
/* Stereo Mixer */
static const struct snd_kcontrol_new ak4641_stereo_mixer_controls [ ] = {
SOC_DAPM_SINGLE_TLV ( " Mic Sidetone Volume " , AK4641_VOL , 4 , 7 , 0 ,
mic_stereo_sidetone_tlv ) ,
SOC_DAPM_SINGLE ( " Mic Sidetone Switch " , AK4641_SIG2 , 4 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " Playback Switch " , AK4641_SIG2 , 7 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " Aux Bypass Switch " , AK4641_SIG2 , 5 , 1 , 0 ) ,
} ;
/* Input Mixer */
static const struct snd_kcontrol_new ak4641_input_mixer_controls [ ] = {
SOC_DAPM_SINGLE ( " Mic Capture Switch " , AK4641_MIC , 2 , 1 , 0 ) ,
SOC_DAPM_SINGLE ( " Aux Capture Switch " , AK4641_MIC , 5 , 1 , 0 ) ,
} ;
/* Mic mux */
static const struct snd_kcontrol_new ak4641_mic_mux_control =
SOC_DAPM_ENUM ( " Mic Select " , ak4641_mic_select_enum ) ;
/* Input mux */
static const struct snd_kcontrol_new ak4641_input_mux_control =
SOC_DAPM_ENUM ( " Input Select " , ak4641_mic_or_dac_enum ) ;
/* mono 2 switch */
static const struct snd_kcontrol_new ak4641_mono2_control =
SOC_DAPM_SINGLE ( " Switch " , AK4641_SIG1 , 0 , 1 , 0 ) ;
/* ak4641 dapm widgets */
static const struct snd_soc_dapm_widget ak4641_dapm_widgets [ ] = {
SND_SOC_DAPM_MIXER ( " Stereo Mixer " , SND_SOC_NOPM , 0 , 0 ,
& ak4641_stereo_mixer_controls [ 0 ] ,
ARRAY_SIZE ( ak4641_stereo_mixer_controls ) ) ,
SND_SOC_DAPM_MIXER ( " Mono1 Mixer " , SND_SOC_NOPM , 0 , 0 ,
& ak4641_mono1_mixer_controls [ 0 ] ,
ARRAY_SIZE ( ak4641_mono1_mixer_controls ) ) ,
SND_SOC_DAPM_MIXER ( " Input Mixer " , SND_SOC_NOPM , 0 , 0 ,
& ak4641_input_mixer_controls [ 0 ] ,
ARRAY_SIZE ( ak4641_input_mixer_controls ) ) ,
SND_SOC_DAPM_MUX ( " Mic Mux " , SND_SOC_NOPM , 0 , 0 ,
& ak4641_mic_mux_control ) ,
SND_SOC_DAPM_MUX ( " Input Mux " , SND_SOC_NOPM , 0 , 0 ,
& ak4641_input_mux_control ) ,
SND_SOC_DAPM_SWITCH ( " Mono 2 Enable " , SND_SOC_NOPM , 0 , 0 ,
& ak4641_mono2_control ) ,
SND_SOC_DAPM_OUTPUT ( " LOUT " ) ,
SND_SOC_DAPM_OUTPUT ( " ROUT " ) ,
SND_SOC_DAPM_OUTPUT ( " MOUT1 " ) ,
SND_SOC_DAPM_OUTPUT ( " MOUT2 " ) ,
SND_SOC_DAPM_OUTPUT ( " MICOUT " ) ,
SND_SOC_DAPM_ADC ( " ADC " , " HiFi Capture " , AK4641_PM1 , 0 , 0 ) ,
SND_SOC_DAPM_PGA ( " Mic " , AK4641_PM1 , 1 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " AUX In " , AK4641_PM1 , 2 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Mono Out " , AK4641_PM1 , 3 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_PGA ( " Line Out " , AK4641_PM1 , 4 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_DAC ( " DAC " , " HiFi Playback " , AK4641_PM2 , 0 , 0 ) ,
SND_SOC_DAPM_PGA ( " Mono Out 2 " , AK4641_PM2 , 3 , 0 , NULL , 0 ) ,
SND_SOC_DAPM_ADC ( " Voice ADC " , " Voice Capture " , AK4641_BTIF , 0 , 0 ) ,
2011-10-19 19:24:54 +04:00
SND_SOC_DAPM_DAC ( " Voice DAC " , " Voice Playback " , AK4641_BTIF , 1 , 0 ) ,
2011-05-18 19:25:09 +04:00
SND_SOC_DAPM_MICBIAS ( " Mic Int Bias " , AK4641_MIC , 3 , 0 ) ,
SND_SOC_DAPM_MICBIAS ( " Mic Ext Bias " , AK4641_MIC , 4 , 0 ) ,
SND_SOC_DAPM_INPUT ( " MICIN " ) ,
SND_SOC_DAPM_INPUT ( " MICEXT " ) ,
SND_SOC_DAPM_INPUT ( " AUX " ) ,
SND_SOC_DAPM_INPUT ( " AIN " ) ,
} ;
static const struct snd_soc_dapm_route ak4641_audio_map [ ] = {
/* Stereo Mixer */
{ " Stereo Mixer " , " Playback Switch " , " DAC " } ,
{ " Stereo Mixer " , " Mic Sidetone Switch " , " Input Mux " } ,
{ " Stereo Mixer " , " Aux Bypass Switch " , " AUX In " } ,
/* Mono 1 Mixer */
{ " Mono1 Mixer " , " Mic Mono Sidetone Switch " , " Input Mux " } ,
{ " Mono1 Mixer " , " Mono Playback Switch " , " DAC " } ,
/* Mic */
{ " Mic " , NULL , " AIN " } ,
{ " Mic Mux " , " Internal " , " Mic Int Bias " } ,
{ " Mic Mux " , " External " , " Mic Ext Bias " } ,
{ " Mic Int Bias " , NULL , " MICIN " } ,
{ " Mic Ext Bias " , NULL , " MICEXT " } ,
{ " MICOUT " , NULL , " Mic Mux " } ,
/* Input Mux */
{ " Input Mux " , " Microphone " , " Mic " } ,
{ " Input Mux " , " Voice DAC " , " Voice DAC " } ,
/* Line Out */
{ " LOUT " , NULL , " Line Out " } ,
{ " ROUT " , NULL , " Line Out " } ,
{ " Line Out " , NULL , " Stereo Mixer " } ,
/* Mono 1 Out */
{ " MOUT1 " , NULL , " Mono Out " } ,
{ " Mono Out " , NULL , " Mono1 Mixer " } ,
/* Mono 2 Out */
{ " MOUT2 " , NULL , " Mono 2 Enable " } ,
{ " Mono 2 Enable " , " Switch " , " Mono Out 2 " } ,
{ " Mono Out 2 " , NULL , " Stereo Mixer " } ,
{ " Voice ADC " , NULL , " Mono 2 Enable " } ,
/* Aux In */
{ " AUX In " , NULL , " AUX " } ,
/* ADC */
{ " ADC " , NULL , " Input Mixer " } ,
{ " Input Mixer " , " Mic Capture Switch " , " Mic " } ,
{ " Input Mixer " , " Aux Capture Switch " , " AUX In " } ,
} ;
static int ak4641_set_dai_sysclk ( struct snd_soc_dai * codec_dai ,
int clk_id , unsigned int freq , int dir )
{
2018-01-29 06:14:32 +03:00
struct snd_soc_component * component = codec_dai - > component ;
struct ak4641_priv * ak4641 = snd_soc_component_get_drvdata ( component ) ;
2011-05-18 19:25:09 +04:00
ak4641 - > sysclk = freq ;
return 0 ;
}
static int ak4641_i2s_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params ,
struct snd_soc_dai * dai )
{
2018-01-29 06:14:32 +03:00
struct snd_soc_component * component = dai - > component ;
struct ak4641_priv * ak4641 = snd_soc_component_get_drvdata ( component ) ;
2011-05-18 19:25:09 +04:00
int rate = params_rate ( params ) , fs = 256 ;
u8 mode2 ;
if ( rate )
fs = ak4641 - > sysclk / rate ;
else
return - EINVAL ;
/* set fs */
switch ( fs ) {
case 1024 :
mode2 = ( 0x2 < < 5 ) ;
break ;
case 512 :
mode2 = ( 0x1 < < 5 ) ;
break ;
case 256 :
mode2 = ( 0x0 < < 5 ) ;
break ;
default :
2018-01-29 06:14:32 +03:00
dev_err ( component - > dev , " Error: unsupported fs=%d \n " , fs ) ;
2011-05-18 19:25:09 +04:00
return - EINVAL ;
}
2018-01-29 06:14:32 +03:00
snd_soc_component_update_bits ( component , AK4641_MODE2 , ( 0x3 < < 5 ) , mode2 ) ;
2011-05-18 19:25:09 +04:00
/* Update de-emphasis filter for the new rate */
if ( substream - > stream = = SNDRV_PCM_STREAM_PLAYBACK ) {
ak4641 - > playback_fs = rate ;
2018-01-29 06:14:32 +03:00
ak4641_set_deemph ( component ) ;
2013-10-09 02:55:45 +04:00
}
2011-05-18 19:25:09 +04:00
return 0 ;
}
static int ak4641_pcm_set_dai_fmt ( struct snd_soc_dai * codec_dai ,
unsigned int fmt )
{
2018-01-29 06:14:32 +03:00
struct snd_soc_component * component = codec_dai - > component ;
2011-05-18 19:25:09 +04:00
u8 btif ;
2011-12-30 19:34:54 +04:00
int ret ;
2011-05-18 19:25:09 +04:00
/* interface format */
switch ( fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
case SND_SOC_DAIFMT_I2S :
btif = ( 0x3 < < 5 ) ;
break ;
case SND_SOC_DAIFMT_LEFT_J :
btif = ( 0x2 < < 5 ) ;
break ;
case SND_SOC_DAIFMT_DSP_A : /* MSB after FRM */
btif = ( 0x0 < < 5 ) ;
break ;
case SND_SOC_DAIFMT_DSP_B : /* MSB during FRM */
btif = ( 0x1 < < 5 ) ;
break ;
default :
return - EINVAL ;
}
2018-01-29 06:14:32 +03:00
ret = snd_soc_component_update_bits ( component , AK4641_BTIF , ( 0x3 < < 5 ) , btif ) ;
2011-12-30 19:34:54 +04:00
if ( ret < 0 )
return ret ;
return 0 ;
2011-05-18 19:25:09 +04:00
}
static int ak4641_i2s_set_dai_fmt ( struct snd_soc_dai * codec_dai ,
unsigned int fmt )
{
2018-01-29 06:14:32 +03:00
struct snd_soc_component * component = codec_dai - > component ;
2011-05-18 19:25:09 +04:00
u8 mode1 = 0 ;
/* interface format */
switch ( fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
case SND_SOC_DAIFMT_I2S :
mode1 = 0x02 ;
break ;
case SND_SOC_DAIFMT_LEFT_J :
mode1 = 0x01 ;
break ;
default :
return - EINVAL ;
}
2018-01-29 06:14:32 +03:00
return snd_soc_component_write ( component , AK4641_MODE1 , mode1 ) ;
2011-05-18 19:25:09 +04:00
}
2020-07-09 04:57:10 +03:00
static int ak4641_mute ( struct snd_soc_dai * dai , int mute , int direction )
2011-05-18 19:25:09 +04:00
{
2018-01-29 06:14:32 +03:00
struct snd_soc_component * component = dai - > component ;
2011-05-18 19:25:09 +04:00
2018-01-29 06:14:32 +03:00
return snd_soc_component_update_bits ( component , AK4641_DAC , 0x20 , mute ? 0x20 : 0 ) ;
2011-05-18 19:25:09 +04:00
}
2018-01-29 06:14:32 +03:00
static int ak4641_set_bias_level ( struct snd_soc_component * component ,
2011-05-18 19:25:09 +04:00
enum snd_soc_bias_level level )
{
2018-01-29 06:14:32 +03:00
struct ak4641_priv * ak4641 = snd_soc_component_get_drvdata ( component ) ;
struct ak4641_platform_data * pdata = component - > dev - > platform_data ;
2011-05-18 19:25:09 +04:00
int ret ;
switch ( level ) {
case SND_SOC_BIAS_ON :
/* unmute */
2018-01-29 06:14:32 +03:00
snd_soc_component_update_bits ( component , AK4641_DAC , 0x20 , 0 ) ;
2011-05-18 19:25:09 +04:00
break ;
case SND_SOC_BIAS_PREPARE :
/* mute */
2018-01-29 06:14:32 +03:00
snd_soc_component_update_bits ( component , AK4641_DAC , 0x20 , 0x20 ) ;
2011-05-18 19:25:09 +04:00
break ;
case SND_SOC_BIAS_STANDBY :
2018-01-29 06:14:32 +03:00
if ( snd_soc_component_get_bias_level ( component ) = = SND_SOC_BIAS_OFF ) {
2011-05-18 19:25:09 +04:00
if ( pdata & & gpio_is_valid ( pdata - > gpio_power ) )
gpio_set_value ( pdata - > gpio_power , 1 ) ;
mdelay ( 1 ) ;
if ( pdata & & gpio_is_valid ( pdata - > gpio_npdn ) )
gpio_set_value ( pdata - > gpio_npdn , 1 ) ;
mdelay ( 1 ) ;
2013-11-22 19:14:48 +04:00
ret = regcache_sync ( ak4641 - > regmap ) ;
2011-05-18 19:25:09 +04:00
if ( ret ) {
2018-01-29 06:14:32 +03:00
dev_err ( component - > dev ,
2011-05-18 19:25:09 +04:00
" Failed to sync cache: %d \n " , ret ) ;
return ret ;
}
}
2018-01-29 06:14:32 +03:00
snd_soc_component_update_bits ( component , AK4641_PM1 , 0x80 , 0x80 ) ;
snd_soc_component_update_bits ( component , AK4641_PM2 , 0x80 , 0 ) ;
2011-05-18 19:25:09 +04:00
break ;
case SND_SOC_BIAS_OFF :
2018-01-29 06:14:32 +03:00
snd_soc_component_update_bits ( component , AK4641_PM1 , 0x80 , 0 ) ;
2011-05-18 19:25:09 +04:00
if ( pdata & & gpio_is_valid ( pdata - > gpio_npdn ) )
gpio_set_value ( pdata - > gpio_npdn , 0 ) ;
if ( pdata & & gpio_is_valid ( pdata - > gpio_power ) )
gpio_set_value ( pdata - > gpio_power , 0 ) ;
2013-11-22 19:14:48 +04:00
regcache_mark_dirty ( ak4641 - > regmap ) ;
2011-05-18 19:25:09 +04:00
break ;
}
return 0 ;
}
# define AK4641_RATES (SNDRV_PCM_RATE_8000_48000)
# define AK4641_RATES_BT (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 )
# define AK4641_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
2011-11-23 14:40:40 +04:00
static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = {
2011-05-18 19:25:09 +04:00
. hw_params = ak4641_i2s_hw_params ,
. set_fmt = ak4641_i2s_set_dai_fmt ,
2020-07-09 04:57:10 +03:00
. mute_stream = ak4641_mute ,
2011-05-18 19:25:09 +04:00
. set_sysclk = ak4641_set_dai_sysclk ,
2020-07-09 04:57:10 +03:00
. no_capture_mute = 1 ,
2011-05-18 19:25:09 +04:00
} ;
2011-11-23 14:40:40 +04:00
static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
2011-05-18 19:25:09 +04:00
. hw_params = NULL , /* rates are controlled by BT chip */
. set_fmt = ak4641_pcm_set_dai_fmt ,
2020-07-09 04:57:10 +03:00
. mute_stream = ak4641_mute ,
2011-05-18 19:25:09 +04:00
. set_sysclk = ak4641_set_dai_sysclk ,
2020-07-09 04:57:10 +03:00
. no_capture_mute = 1 ,
2011-05-18 19:25:09 +04:00
} ;
2011-06-01 13:10:50 +04:00
static struct snd_soc_dai_driver ak4641_dai [ ] = {
2011-05-18 19:25:09 +04:00
{
. name = " ak4641-hifi " ,
. id = 1 ,
. playback = {
. stream_name = " HiFi Playback " ,
. channels_min = 1 ,
. channels_max = 2 ,
. rates = AK4641_RATES ,
. formats = AK4641_FORMATS ,
} ,
. capture = {
. stream_name = " HiFi Capture " ,
. channels_min = 1 ,
. channels_max = 2 ,
. rates = AK4641_RATES ,
. formats = AK4641_FORMATS ,
} ,
. ops = & ak4641_i2s_dai_ops ,
2021-01-15 07:54:56 +03:00
. symmetric_rate = 1 ,
2011-05-18 19:25:09 +04:00
} ,
{
. name = " ak4641-voice " ,
. id = 1 ,
. playback = {
. stream_name = " Voice Playback " ,
. channels_min = 1 ,
. channels_max = 1 ,
. rates = AK4641_RATES_BT ,
. formats = AK4641_FORMATS ,
} ,
. capture = {
. stream_name = " Voice Capture " ,
. channels_min = 1 ,
. channels_max = 1 ,
. rates = AK4641_RATES_BT ,
. formats = AK4641_FORMATS ,
} ,
. ops = & ak4641_pcm_dai_ops ,
2021-01-15 07:54:56 +03:00
. symmetric_rate = 1 ,
2011-05-18 19:25:09 +04:00
} ,
} ;
2018-01-29 06:14:32 +03:00
static const struct snd_soc_component_driver soc_component_dev_ak4641 = {
. controls = ak4641_snd_controls ,
. num_controls = ARRAY_SIZE ( ak4641_snd_controls ) ,
. dapm_widgets = ak4641_dapm_widgets ,
. num_dapm_widgets = ARRAY_SIZE ( ak4641_dapm_widgets ) ,
. dapm_routes = ak4641_audio_map ,
. num_dapm_routes = ARRAY_SIZE ( ak4641_audio_map ) ,
2011-05-18 19:25:09 +04:00
. set_bias_level = ak4641_set_bias_level ,
2018-01-29 06:14:32 +03:00
. suspend_bias_off = 1 ,
. idle_bias_on = 1 ,
. use_pmdown_time = 1 ,
. endianness = 1 ,
. non_legacy_dai_naming = 1 ,
2011-05-18 19:25:09 +04:00
} ;
2013-11-22 19:14:48 +04:00
static const struct regmap_config ak4641_regmap = {
. reg_bits = 8 ,
. val_bits = 8 ,
. max_register = AK4641_BTIF ,
. reg_defaults = ak4641_reg_defaults ,
. num_reg_defaults = ARRAY_SIZE ( ak4641_reg_defaults ) ,
. cache_type = REGCACHE_RBTREE ,
} ;
2011-05-18 19:25:09 +04:00
2012-12-07 18:26:37 +04:00
static int ak4641_i2c_probe ( struct i2c_client * i2c ,
const struct i2c_device_id * id )
2011-05-18 19:25:09 +04:00
{
2012-03-04 18:20:18 +04:00
struct ak4641_platform_data * pdata = i2c - > dev . platform_data ;
2011-05-18 19:25:09 +04:00
struct ak4641_priv * ak4641 ;
int ret ;
2011-12-20 10:39:20 +04:00
ak4641 = devm_kzalloc ( & i2c - > dev , sizeof ( struct ak4641_priv ) ,
GFP_KERNEL ) ;
2011-05-18 19:25:09 +04:00
if ( ! ak4641 )
return - ENOMEM ;
2013-11-22 19:14:48 +04:00
ak4641 - > regmap = devm_regmap_init_i2c ( i2c , & ak4641_regmap ) ;
if ( IS_ERR ( ak4641 - > regmap ) )
return PTR_ERR ( ak4641 - > regmap ) ;
2012-03-04 18:20:18 +04:00
if ( pdata ) {
if ( gpio_is_valid ( pdata - > gpio_power ) ) {
ret = gpio_request_one ( pdata - > gpio_power ,
GPIOF_OUT_INIT_LOW , " ak4641 power " ) ;
if ( ret )
goto err_out ;
}
if ( gpio_is_valid ( pdata - > gpio_npdn ) ) {
ret = gpio_request_one ( pdata - > gpio_npdn ,
GPIOF_OUT_INIT_LOW , " ak4641 npdn " ) ;
if ( ret )
goto err_gpio ;
udelay ( 1 ) ; /* > 150 ns */
gpio_set_value ( pdata - > gpio_npdn , 1 ) ;
}
}
2011-05-18 19:25:09 +04:00
i2c_set_clientdata ( i2c , ak4641 ) ;
2018-01-29 06:14:32 +03:00
ret = devm_snd_soc_register_component ( & i2c - > dev ,
& soc_component_dev_ak4641 ,
2011-05-18 19:25:09 +04:00
ak4641_dai , ARRAY_SIZE ( ak4641_dai ) ) ;
2012-03-04 18:20:18 +04:00
if ( ret ! = 0 )
goto err_gpio2 ;
return 0 ;
err_gpio2 :
if ( pdata ) {
if ( gpio_is_valid ( pdata - > gpio_power ) )
gpio_set_value ( pdata - > gpio_power , 0 ) ;
if ( gpio_is_valid ( pdata - > gpio_npdn ) )
gpio_free ( pdata - > gpio_npdn ) ;
}
err_gpio :
if ( pdata & & gpio_is_valid ( pdata - > gpio_power ) )
gpio_free ( pdata - > gpio_power ) ;
err_out :
2011-05-18 19:25:09 +04:00
return ret ;
}
2012-12-07 18:26:37 +04:00
static int ak4641_i2c_remove ( struct i2c_client * i2c )
2011-05-18 19:25:09 +04:00
{
2012-03-04 18:20:18 +04:00
struct ak4641_platform_data * pdata = i2c - > dev . platform_data ;
if ( pdata ) {
if ( gpio_is_valid ( pdata - > gpio_power ) ) {
gpio_set_value ( pdata - > gpio_power , 0 ) ;
gpio_free ( pdata - > gpio_power ) ;
}
if ( gpio_is_valid ( pdata - > gpio_npdn ) )
gpio_free ( pdata - > gpio_npdn ) ;
}
2011-05-18 19:25:09 +04:00
return 0 ;
}
static const struct i2c_device_id ak4641_i2c_id [ ] = {
{ " ak4641 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , ak4641_i2c_id ) ;
static struct i2c_driver ak4641_i2c_driver = {
. driver = {
. name = " ak4641 " ,
} ,
. probe = ak4641_i2c_probe ,
2012-12-07 18:26:37 +04:00
. remove = ak4641_i2c_remove ,
2011-05-18 19:25:09 +04:00
. id_table = ak4641_i2c_id ,
} ;
2012-03-04 18:06:36 +04:00
module_i2c_driver ( ak4641_i2c_driver ) ;
2011-05-18 19:25:09 +04:00
MODULE_DESCRIPTION ( " SoC AK4641 driver " ) ;
MODULE_AUTHOR ( " Harald Welte <laforge@gnufiish.org> " ) ;
MODULE_LICENSE ( " GPL " ) ;