X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=sound%2Fsoc%2Fcodecs%2Fes8316.c;h=1e082f39e97b3a1d35a3ab482f523d0e2ceb7b12;hb=46265c1e20cc42540ba242b8de9ce64dc113f2a8;hp=e6f982691b2a048883d974d61b33cc1cb8429577;hpb=a203a16126bb63d92a438531d626f986eb3310bf;p=firefly-linux-kernel-4.4.55.git diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index e6f982691b2a..1e082f39e97b 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -34,36 +35,10 @@ #include #include "es8316.h" -#if 1 -#define DBG(x...) printk(x) -#else -#define DBG(x...) do { } while (0) -#endif -#define alsa_dbg DBG - -#define dmic_used 1 -#define amic_used 0 - #define INVALID_GPIO -1 - -#define ES8316_CODEC_SET_SPK 1 -#define ES8316_CODEC_SET_HP 2 - - -int HP_IRQ = 0; -int hp_irq_flag = 0; -int es8316_init_reg = 0; - #define GPIO_LOW 0 #define GPIO_HIGH 1 -#ifndef es8316_DEF_VOL #define es8316_DEF_VOL 0x1e -#endif - -struct snd_soc_codec *es8316_codec; -static int es8316_init_regs(struct snd_soc_codec *codec); -static int es8316_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level); static const struct reg_default es8316_reg_defaults[] = { {0x00, 0x03}, {0x01, 0x03}, {0x02, 0x00}, {0x03, 0x20}, @@ -89,104 +64,51 @@ static const struct reg_default es8316_reg_defaults[] = { {0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00}, }; -static inline unsigned int es8316_readable(struct device *dev, unsigned int reg) -{ - if (reg <= 90) - return 0; - else - return -1; -} -static inline unsigned int es8316_volatile(struct device *dev, unsigned int reg) -{ - if (reg <= 90) - return 0; - else - return -1; -} /* codec private data */ struct es8316_priv { struct regmap *regmap; unsigned int dmic_amic; unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; + struct clk *mclk; + int debounce_time; + int hp_det_invert; + struct delayed_work work; int spk_ctl_gpio; - int hp_ctl_gpio; int hp_det_gpio; + bool muted; + bool hp_inserted; + bool spk_active_level; - bool spk_gpio_level; - bool hp_gpio_level; - bool hp_det_level; + int pwr_count; }; -struct es8316_priv *es8316_private; -static int es8316_set_gpio(int gpio, bool level) +/* + * es8316_reset + * write value 0xff to reg0x00, the chip will be in reset mode + * then, writer 0x00 to reg0x00, unreset the chip + */ +static int es8316_reset(struct snd_soc_codec *codec) { - struct es8316_priv *es8316 = es8316_private; - - if (!es8316) { - DBG("%s : es8316_priv is NULL\n", __func__); - return 0; - } - DBG("%s : set %s %s ctl gpio %s\n", __func__, - gpio & ES8316_CODEC_SET_SPK ? "spk" : "", - gpio & ES8316_CODEC_SET_HP ? "hp" : "", - level ? "HIGH" : "LOW"); - if ((gpio & ES8316_CODEC_SET_SPK) - && es8316 && es8316->spk_ctl_gpio != INVALID_GPIO) { - DBG("%d,set_value%s\n", es8316->spk_ctl_gpio, level ? - "HIGH" : "LOW"); - gpio_set_value(es8316->spk_ctl_gpio, level); - } - return 0; + snd_soc_write(codec, ES8316_RESET_REG00, 0x3F); + usleep_range(5000, 5500); + return snd_soc_write(codec, ES8316_RESET_REG00, 0x03); } -static char mute_flag = 1; -static irqreturn_t hp_det_irq_handler(int irq, void *dev_id) +static void es8316_enable_spk(struct es8316_priv *es8316, bool enable) { - int ret; - unsigned int type; - struct es8316_priv *es8316 = es8316_private; - - disable_irq_nosync(irq); - - type = gpio_get_value(es8316->hp_det_gpio) ? - IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING; - ret = irq_set_irq_type(irq, type); - if (ret < 0) { - DBG("%s: irq_set_irq_type(%d, %d) failed\n", - __func__, irq, type); - return -1; - } - - if (type == IRQ_TYPE_EDGE_FALLING) - hp_irq_flag = 0; - else - hp_irq_flag = 1; - if (mute_flag == 0) { - if (es8316->hp_det_level == gpio_get_value(es8316->hp_det_gpio)) - es8316_set_gpio(ES8316_CODEC_SET_SPK, - !es8316->spk_gpio_level); - else - es8316_set_gpio(ES8316_CODEC_SET_SPK, - es8316->spk_gpio_level); - } - enable_irq(irq); + bool level; - return IRQ_HANDLED; + level = enable ? es8316->spk_active_level : !es8316->spk_active_level; + gpio_set_value(es8316->spk_ctl_gpio, level); } -/* -* es8316S Controls -*/ -/*#define DECLARE_TLV_DB_SCALE(name, min, step, mute) */ -/*static const DECLARE_TLV_DB_SCALE(hpout_vol_tlv, -4800, 1200, 0);*/ static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9600, 50, 1); static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -9600, 50, 1); static const DECLARE_TLV_DB_SCALE(hpmixer_gain_tlv, -1200, 150, 0); static const DECLARE_TLV_DB_SCALE(mic_bst_tlv, 0, 1200, 0); -/*static const DECLARE_TLV_DB_SCALE(linin_pga_tlv, 0, 300, 0);*/ -/* {0, +3, +6, +9, +12, +15, +18, +21, +24,+27,+30,+33} dB */ + static unsigned int linin_pga_tlv[] = { TLV_DB_RANGE_HEAD(12), 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), @@ -199,24 +121,31 @@ static unsigned int linin_pga_tlv[] = { 7, 7, TLV_DB_SCALE_ITEM(2100, 0, 0), 8, 8, TLV_DB_SCALE_ITEM(2400, 0, 0), }; + static unsigned int hpout_vol_tlv[] = { TLV_DB_RANGE_HEAD(1), 0, 3, TLV_DB_SCALE_ITEM(-4800, 1200, 0), }; -static const char *const alc_func_txt[] = {"Off", "On"}; + +static const char *const alc_func_txt[] = { "Off", "On" }; + static const struct soc_enum alc_func = SOC_ENUM_SINGLE(ES8316_ADC_ALC1_REG29, 6, 2, alc_func_txt); -static const char *const ng_type_txt[] = {"Constant PGA Gain", - "Mute ADC Output"}; +static const char *const ng_type_txt[] = { + "Constant PGA Gain", "Mute ADC Output" }; + static const struct soc_enum ng_type = SOC_ENUM_SINGLE(ES8316_ADC_ALC6_REG2E, 6, 2, ng_type_txt); -static const char *const adcpol_txt[] = {"Normal", "Invert"}; +static const char *const adcpol_txt[] = { "Normal", "Invert" }; + static const struct soc_enum adcpol = SOC_ENUM_SINGLE(ES8316_ADC_MUTE_REG26, 1, 2, adcpol_txt); -static const char *const dacpol_txt[] = {"Normal", "R Invert", "L Invert", - "L + R Invert"}; + +static const char *const dacpol_txt[] = { + "Normal", "R Invert", "L Invert", "L + R Invert" }; + static const struct soc_enum dacpol = SOC_ENUM_SINGLE(ES8316_DAC_SET1_REG30, 0, 4, dacpol_txt); @@ -270,41 +199,38 @@ static const struct snd_kcontrol_new es8316_snd_controls[] = { /* Analog Input MUX */ static const char * const es8316_analog_in_txt[] = { - "lin1-rin1", - "lin2-rin2", - "lin1-rin1 with 20db Boost", - "lin2-rin2 with 20db Boost" -}; -static const unsigned int es8316_analog_in_values[] = { - 0,/*1,*/ - 1, - 2, - 3 + "lin1-rin1", + "lin2-rin2", + "lin1-rin1 with 20db Boost", + "lin2-rin2 with 20db Boost" }; + +static const unsigned int es8316_analog_in_values[] = { 0, 1, 2, 3 }; + static const struct soc_enum es8316_analog_input_enum = SOC_VALUE_ENUM_SINGLE(ES8316_ADC_PDN_LINSEL_REG22, 4, 3, ARRAY_SIZE(es8316_analog_in_txt), es8316_analog_in_txt, es8316_analog_in_values); + static const struct snd_kcontrol_new es8316_analog_in_mux_controls = SOC_DAPM_ENUM("Route", es8316_analog_input_enum); /* Dmic MUX */ static const char * const es8316_dmic_txt[] = { - "dmic disable", - "dmic data at high level", - "dmic data at low level", -}; -static const unsigned int es8316_dmic_values[] = { - 0,/*1,*/ - 1, - 2 + "dmic disable", + "dmic data at high level", + "dmic data at low level", }; + +static const unsigned int es8316_dmic_values[] = { 0, 1, 2 }; + static const struct soc_enum es8316_dmic_src_enum = SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC_REG25, 0, 3, ARRAY_SIZE(es8316_dmic_txt), es8316_dmic_txt, es8316_dmic_values); + static const struct snd_kcontrol_new es8316_dmic_src_controls = SOC_DAPM_ENUM("Route", es8316_dmic_src_enum); @@ -316,23 +242,25 @@ static const char *const es8316_hpmux_texts[] = { "lin-rin with Boost and PGA" }; -static const unsigned int es8316_hpmux_values[] = {0, 1, 2, 3}; +static const unsigned int es8316_hpmux_values[] = { 0, 1, 2, 3 }; static const struct soc_enum es8316_left_hpmux_enum = SOC_VALUE_ENUM_SINGLE(ES8316_HPMIX_SEL_REG13, 4, 7, ARRAY_SIZE(es8316_hpmux_texts), es8316_hpmux_texts, es8316_hpmux_values); + static const struct snd_kcontrol_new es8316_left_hpmux_controls = - SOC_DAPM_VALUE_ENUM("Route", es8316_left_hpmux_enum); + SOC_DAPM_ENUM("Route", es8316_left_hpmux_enum); static const struct soc_enum es8316_right_hpmux_enum = SOC_VALUE_ENUM_SINGLE(ES8316_HPMIX_SEL_REG13, 0, 7, ARRAY_SIZE(es8316_hpmux_texts), es8316_hpmux_texts, es8316_hpmux_values); + static const struct snd_kcontrol_new es8316_right_hpmux_controls = - SOC_DAPM_VALUE_ENUM("Route", es8316_right_hpmux_enum); + SOC_DAPM_ENUM("Route", es8316_right_hpmux_enum); /* headphone Output Mixer */ static const struct snd_kcontrol_new es8316_out_left_mix[] = { @@ -341,6 +269,7 @@ static const struct snd_kcontrol_new es8316_out_left_mix[] = { SOC_DAPM_SINGLE("Left DAC Switch", ES8316_HPMIX_SWITCH_REG14, 7, 1, 0), }; + static const struct snd_kcontrol_new es8316_out_right_mix[] = { SOC_DAPM_SINGLE("RLIN Switch", ES8316_HPMIX_SWITCH_REG14, 2, 1, 0), @@ -356,8 +285,7 @@ static const char * const es8316_dacsrc_texts[] = { "RDATA TO LDAC, LDATA TO RDAC", }; -static const unsigned int es8316_dacsrc_values[] = { - 0, 1, 2, 3}; +static const unsigned int es8316_dacsrc_values[] = { 0, 1, 2, 3 }; static const struct soc_enum es8316_dacsrc_mux_enum = SOC_VALUE_ENUM_SINGLE(ES8316_DAC_SET1_REG30, 6, 4, @@ -365,8 +293,7 @@ static const struct soc_enum es8316_dacsrc_mux_enum = es8316_dacsrc_texts, es8316_dacsrc_values); static const struct snd_kcontrol_new es8316_dacsrc_mux_controls = - SOC_DAPM_VALUE_ENUM("Route", es8316_dacsrc_mux_enum); - + SOC_DAPM_ENUM("Route", es8316_dacsrc_mux_enum); static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = { /* Input Lines */ @@ -379,19 +306,21 @@ static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = { /* Input MUX */ SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0, &es8316_analog_in_mux_controls), - SND_SOC_DAPM_PGA("Line input PGA", SND_SOC_NOPM, - 0, 0, NULL, 0), + + SND_SOC_DAPM_PGA("Line input PGA", ES8316_ADC_PDN_LINSEL_REG22, + 7, 1, NULL, 0), /* ADCs */ - SND_SOC_DAPM_ADC("Mono ADC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("Mono ADC", NULL, ES8316_ADC_PDN_LINSEL_REG22, 6, 1), /* Dmic MUX */ SND_SOC_DAPM_MUX("Digital Mic Mux", SND_SOC_NOPM, 0, 0, &es8316_dmic_src_controls), /* Digital Interface */ - SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 1, - SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("I2S OUT", "I2S1 Capture", 1, + ES8316_SDP_ADCFMT_REG0A, 6, 0), + SND_SOC_DAPM_AIF_IN("I2S IN", "I2S1 Playback", 0, SND_SOC_NOPM, 0, 0), @@ -399,10 +328,8 @@ static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = { SND_SOC_DAPM_MUX("DAC SRC Mux", SND_SOC_NOPM, 0, 0, &es8316_dacsrc_mux_controls), /* DACs */ - SND_SOC_DAPM_DAC("Right DAC", NULL, SND_SOC_NOPM, 0, 0), - - /*SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN_REG2F, 4, 0),*/ - SND_SOC_DAPM_DAC("Left DAC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("Right DAC", NULL, ES8316_DAC_PDN_REG2F, 0, 1), + SND_SOC_DAPM_DAC("Left DAC", NULL, ES8316_DAC_PDN_REG2F, 4, 1), /* Headphone Output Side */ /* hpmux for hp mixer */ @@ -412,26 +339,41 @@ static const struct snd_soc_dapm_widget es8316_dapm_widgets[] = { &es8316_right_hpmux_controls), /* Output mixer */ SND_SOC_DAPM_MIXER("Left Hp mixer", ES8316_HPMIX_PDN_REG15, - 4, 0, &es8316_out_left_mix[0], + 4, 1, &es8316_out_left_mix[0], ARRAY_SIZE(es8316_out_left_mix)), SND_SOC_DAPM_MIXER("Right Hp mixer", ES8316_HPMIX_PDN_REG15, - 0, 0, &es8316_out_right_mix[0], + 0, 1, &es8316_out_right_mix[0], + ARRAY_SIZE(es8316_out_right_mix)), + SND_SOC_DAPM_MIXER("Left Hp mixer", SND_SOC_NOPM, + 4, 1, &es8316_out_left_mix[0], + ARRAY_SIZE(es8316_out_left_mix)), + SND_SOC_DAPM_MIXER("Right Hp mixer", SND_SOC_NOPM, + 0, 1, &es8316_out_right_mix[0], ARRAY_SIZE(es8316_out_right_mix)), - - /* Ouput charge pump */ + /* Output charge pump */ SND_SOC_DAPM_PGA("HPCP L", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("HPCP R", SND_SOC_NOPM, 0, 0, NULL, 0), - /* Ouput Driver */ + SND_SOC_DAPM_PGA("HPCP L", ES8316_CPHP_OUTEN_REG17, + 6, 0, NULL, 0), + SND_SOC_DAPM_PGA("HPCP R", ES8316_CPHP_OUTEN_REG17, + 2, 0, NULL, 0), + + /* Output Driver */ SND_SOC_DAPM_PGA("HPVOL L", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("HPVOL R", SND_SOC_NOPM, 0, 0, NULL, 0), + /* Output Driver */ + SND_SOC_DAPM_PGA("HPVOL L", ES8316_CPHP_OUTEN_REG17, + 5, 0, NULL, 0), + SND_SOC_DAPM_PGA("HPVOL R", ES8316_CPHP_OUTEN_REG17, + 1, 0, NULL, 0), /* Output Lines */ SND_SOC_DAPM_OUTPUT("HPOL"), SND_SOC_DAPM_OUTPUT("HPOR"), @@ -503,61 +445,61 @@ struct _coeff_div { u8 osr; /*adc osr*/ }; - /* codec hifi mclk clock divider coefficients */ static const struct _coeff_div coeff_div[] = { /* 8k */ - {12288000, 8000 , 6 , 0x06, 0x00, 21, 32}, - {11289600, 8000 , 6 , 0x05, 0x83, 20, 29}, - {18432000, 8000 , 9 , 0x09, 0x00, 27, 32}, - {16934400, 8000 , 8 , 0x08, 0x44, 25, 33}, - {12000000, 8000 , 7 , 0x05, 0xdc, 21, 25}, - {19200000, 8000 , 12, 0x09, 0x60, 27, 25}, + { 12288000, 8000, 6, 0x06, 0x00, 21, 32 }, + { 11289600, 8000, 6, 0x05, 0x83, 20, 29 }, + { 18432000, 8000, 9, 0x09, 0x00, 27, 32 }, + { 16934400, 8000, 8, 0x08, 0x44, 25, 33 }, + { 12000000, 8000, 7, 0x05, 0xdc, 21, 25 }, + { 19200000, 8000, 12, 0x09, 0x60, 27, 25 }, /* 11.025k */ - {11289600, 11025, 4 , 0x04, 0x00, 16, 32}, - {16934400, 11025, 6 , 0x06, 0x00, 21, 32}, - {12000000, 11025, 4 , 0x04, 0x40, 17, 34}, + { 11289600, 11025, 4, 0x04, 0x00, 16, 32 }, + { 16934400, 11025, 6, 0x06, 0x00, 21, 32 }, + { 12000000, 11025, 4, 0x04, 0x40, 17, 34 }, /* 16k */ - {12288000, 16000, 3 , 0x03, 0x00, 12, 32}, - {18432000, 16000, 5 , 0x04, 0x80, 18, 25}, - {12000000, 16000, 3 , 0x02, 0xee, 12, 31}, - {19200000, 16000, 6 , 0x04, 0xb0, 18, 25}, + { 12288000, 16000, 3, 0x03, 0x00, 12, 32 }, + { 18432000, 16000, 5, 0x04, 0x80, 18, 25 }, + { 12000000, 16000, 3, 0x02, 0xee, 12, 31 }, + { 19200000, 16000, 6, 0x04, 0xb0, 18, 25 }, /* 22.05k */ - {11289600, 22050, 2 , 0x02, 0x00, 8 , 32}, - {16934400, 22050, 3 , 0x03, 0x00, 12, 32}, - {12000000, 22050, 2 , 0x02, 0x20, 8 , 34}, + { 11289600, 22050, 2, 0x02, 0x00, 8, 32 }, + { 16934400, 22050, 3, 0x03, 0x00, 12, 32 }, + { 12000000, 22050, 2, 0x02, 0x20, 8, 34 }, /* 32k */ - {12288000, 32000, 1 , 0x01, 0x80, 6 , 48}, - {18432000, 32000, 2 , 0x02, 0x40, 9 , 32}, - {12000000, 32000, 1 , 0x01, 0x77, 6 , 31}, - {19200000, 32000, 3 , 0x02, 0x58, 10, 25}, + { 12288000, 32000, 1, 0x01, 0x80, 6, 48 }, + { 18432000, 32000, 2, 0x02, 0x40, 9, 32 }, + { 12000000, 32000, 1, 0x01, 0x77, 6, 31 }, + { 19200000, 32000, 3, 0x02, 0x58, 10, 25 }, /* 44.1k */ - {11289600, 44100, 1 , 0x01, 0x00, 4 , 32}, - {16934400, 44100, 1 , 0x01, 0x80, 6 , 32}, - {12000000, 44100, 1 , 0x01, 0x10, 4 , 34}, + { 11289600, 44100, 1, 0x01, 0x00, 4, 32 }, + { 16934400, 44100, 1, 0x01, 0x80, 6, 32 }, + { 12000000, 44100, 1, 0x01, 0x10, 4, 34 }, /* 48k */ - {12288000, 48000, 1 , 0x01, 0x00, 4 , 32}, - {18432000, 48000, 1 , 0x01, 0x80, 6 , 32}, - {12000000, 48000, 1 , 0x00, 0xfa, 4 , 31}, - {19200000, 48000, 2 , 0x01, 0x90, 6, 25}, + { 12288000, 48000, 1, 0x01, 0x00, 4, 32 }, + { 18432000, 48000, 1, 0x01, 0x80, 6, 32 }, + { 12000000, 48000, 1, 0x00, 0xfa, 4, 31 }, + { 19200000, 48000, 2, 0x01, 0x90, 6, 25 }, /* 88.2k */ - {11289600, 88200, 1 , 0x00, 0x80, 2 , 32}, - {16934400, 88200, 1 , 0x00, 0xc0, 3 , 48}, - {12000000, 88200, 1 , 0x00, 0x88, 2 , 34}, + { 11289600, 88200, 1, 0x00, 0x80, 2, 32 }, + { 16934400, 88200, 1, 0x00, 0xc0, 3, 48 }, + { 12000000, 88200, 1, 0x00, 0x88, 2, 34 }, /* 96k */ - {12288000, 96000, 1 , 0x00, 0x80, 2 , 32}, - {18432000, 96000, 1 , 0x00, 0xc0, 3 , 48}, - {12000000, 96000, 1 , 0x00, 0x7d, 1 , 31}, - {19200000, 96000, 1 , 0x00, 0xc8, 3 , 25}, + { 12288000, 96000, 1, 0x00, 0x80, 2, 32 }, + { 18432000, 96000, 1, 0x00, 0xc0, 3, 48 }, + { 12000000, 96000, 1, 0x00, 0x7d, 1, 31 }, + { 19200000, 96000, 1, 0x00, 0xc8, 3, 25 }, }; + static inline int get_coeff(int mclk, int rate) { int i; @@ -601,8 +543,8 @@ static struct snd_pcm_hw_constraint_list constraints_12 = { }; /* -* Note that this should be called from init rather than from hw_params. -*/ + * Note that this should be called from init rather than from hw_params. + */ static int es8316_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { @@ -642,8 +584,6 @@ static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai, u8 adciface = 0; u8 daciface = 0; - alsa_dbg("%s----%d, fmt[%02x]\n", __func__, __LINE__, fmt); - iface = snd_soc_read(codec, ES8316_IFACE); adciface = snd_soc_read(codec, ES8316_ADC_IFACE); daciface = snd_soc_read(codec, ES8316_DAC_IFACE); @@ -651,18 +591,15 @@ static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: - alsa_dbg("es8316 in master mode"); iface |= 0x80; break; case SND_SOC_DAIFMT_CBS_CFS: - alsa_dbg("es8316 in slave mode"); iface &= 0x7F; break; default: return -EINVAL; } - /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -694,7 +631,6 @@ static int es8316_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - /* clock inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: @@ -731,151 +667,133 @@ static int es8316_pcm_startup(struct snd_pcm_substream *substream, { struct snd_soc_codec *codec = dai->codec; struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); + bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - DBG("Enter::%s----%d es8316->sysclk=%d\n", - __func__, __LINE__, es8316->sysclk); - - /* The set of sample rates that can be supported depends on the - * MCLK supplied to the CODEC - enforce this. - */ - if (!es8316->sysclk) { - dev_err(codec->dev, - "No MCLK configured, call set_sysclk() on init\n"); - return -EINVAL; + snd_soc_write(codec, ES8316_RESET_REG00, 0xC0); + snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x00); + /* es8316: both playback and capture need dac mclk */ + snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW_REG01, + ES8316_CLKMGR_MCLK_DIV_MASK | + ES8316_CLKMGR_DAC_MCLK_MASK, + ES8316_CLKMGR_MCLK_DIV_NML | + ES8316_CLKMGR_DAC_MCLK_EN); + es8316->pwr_count++; + + if (playback) { + snd_soc_write(codec, ES8316_SYS_LP1_REG0E, 0x3F); + snd_soc_write(codec, ES8316_SYS_LP2_REG0F, 0x1F); + snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x88); + snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x00); + snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0xBB); + snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x10); + snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x30); + snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x02); + snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x00); + snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x66); + snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW_REG01, + ES8316_CLKMGR_DAC_MCLK_MASK | + ES8316_CLKMGR_DAC_ANALOG_MASK, + ES8316_CLKMGR_DAC_MCLK_EN | + ES8316_CLKMGR_DAC_ANALOG_EN); + msleep(50); + } else { + snd_soc_update_bits(codec, + ES8316_ADC_PDN_LINSEL_REG22, 0xC0, 0x20); + snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW_REG01, + ES8316_CLKMGR_ADC_MCLK_MASK | + ES8316_CLKMGR_ADC_ANALOG_MASK, + ES8316_CLKMGR_ADC_MCLK_EN | + ES8316_CLKMGR_ADC_ANALOG_EN); } - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - es8316->sysclk_constraints); - return 0; } -static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, + +static void es8316_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); - int retv; - - u16 osrate = snd_soc_read(codec, - ES8316_CLKMGR_ADCOSR_REG03) & 0xc0; - u16 mclkdiv = snd_soc_read(codec, - ES8316_CLKMGR_CLKSW_REG01) & 0x7f; - u16 srate = snd_soc_read(codec, - ES8316_SDP_MS_BCKDIV_REG09) & 0xE0; - u16 adciface = snd_soc_read(codec, - ES8316_SDP_ADCFMT_REG0A) & 0xE3; - u16 daciface = snd_soc_read(codec, - ES8316_SDP_DACFMT_REG0B) & 0xE3; - u16 adcdiv = snd_soc_read(codec, - ES8316_CLKMGR_ADCDIV1_REG04); - u16 adclrckdiv_l = snd_soc_read(codec, - ES8316_CLKMGR_ADCDIV2_REG05) & 0x00; - u16 dacdiv = snd_soc_read(codec, ES8316_CLKMGR_DACDIV1_REG06); - u16 daclrckdiv_l = snd_soc_read(codec, - ES8316_CLKMGR_DACDIV2_REG07) & 0x00; - int coeff; - u16 adclrckdiv_h = adcdiv & 0xf0; - u16 daclrckdiv_h = dacdiv & 0xf0; - - adcdiv &= 0x0f; - dacdiv &= 0x0f; - - - coeff = get_coeff(es8316->sysclk, params_rate(params)); - if (coeff < 0) { - coeff = get_coeff(es8316->sysclk / 2, params_rate(params)); - mclkdiv |= 0x80; + bool playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + + if (playback) { + snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x00); + snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x11); + snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x03); + snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x22); + snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x06); + snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x00); + snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x33); + snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0x00); + snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x00); + snd_soc_write(codec, ES8316_SYS_LP1_REG0E, 0xFF); + snd_soc_write(codec, ES8316_SYS_LP2_REG0F, 0xFF); + snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW_REG01, + ES8316_CLKMGR_DAC_ANALOG_MASK, + ES8316_CLKMGR_DAC_ANALOG_DIS); + } else { + snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0xc0); + snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW_REG01, + ES8316_CLKMGR_ADC_MCLK_MASK | + ES8316_CLKMGR_ADC_ANALOG_MASK, + ES8316_CLKMGR_ADC_MCLK_DIS | + ES8316_CLKMGR_ADC_ANALOG_DIS); } - if (coeff < 0) { - dev_err(codec->dev, - "Unable to configure sample rate %dHz with %dHz MCLK\n", - params_rate(params), es8316->sysclk); - return coeff; + + if (--es8316->pwr_count == 0) { + snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x3F); + snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0xF3); } +} + +static int es8316_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + int val; - /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - adciface |= 0x000C; - daciface |= 0x000C; + val = ES8316_DACWL_16; break; case SNDRV_PCM_FORMAT_S20_3LE: - adciface |= 0x0004; - daciface |= 0x0004; + val = ES8316_DACWL_20; break; case SNDRV_PCM_FORMAT_S24_LE: + val = ES8316_DACWL_24; break; case SNDRV_PCM_FORMAT_S32_LE: - adciface |= 0x0010; - daciface |= 0x0010; + val = ES8316_DACWL_32; break; } - /* set iface & srate*/ - snd_soc_update_bits(codec, ES8316_SDP_DACFMT_REG0B, 0xe3, daciface); - snd_soc_update_bits(codec, ES8316_SDP_ADCFMT_REG0A, 0xe3, adciface); - snd_soc_update_bits(codec, ES8316_CLKMGR_CLKSW_REG01, 0x80, mclkdiv); - if (coeff >= 0) { - osrate = coeff_div[coeff].osr; - osrate &= 0x3f; - - srate |= coeff_div[coeff].sr; - srate &= 0x1f; - - adcdiv |= (coeff_div[coeff].div << 4); - adclrckdiv_h |= coeff_div[coeff].lrck_h; - adcdiv &= 0xf0; - adclrckdiv_h &= 0x0f; - adcdiv |= adclrckdiv_h; - adclrckdiv_l = coeff_div[coeff].lrck_l; - - dacdiv |= (coeff_div[coeff].div << 4); - daclrckdiv_h |= coeff_div[coeff].lrck_h; - dacdiv &= 0xf0; - daclrckdiv_h &= 0x0f; - dacdiv |= daclrckdiv_h; - daclrckdiv_l = coeff_div[coeff].lrck_l; - - retv = snd_soc_read(codec, ES8316_CLKMGR_ADCDIV2_REG05); - if (retv == 0) { - es8316_init_regs(codec); - if (es8316->dmic_amic == dmic_used) - snd_soc_write(codec, ES8316_GPIO_SEL_REG4D, - 0x02); - else - snd_soc_write(codec, ES8316_GPIO_SEL_REG4D, - 0x00); - snd_soc_write(codec, ES8316_GPIO_DEBUNCE_INT_REG4E, - 0xf3); - es8316_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - es8316_init_reg = 1; - } - } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_update_bits(codec, ES8316_SDP_DACFMT_REG0B, + ES8316_DACWL_MASK, val); + else + snd_soc_update_bits(codec, ES8316_SDP_ADCFMT_REG0A, + ES8316_ADCWL_MASK, val); - retv = snd_soc_read(codec, ES8316_GPIO_FLAG); return 0; } static int es8316_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - struct es8316_priv *es8316 = es8316_private; + struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); - mute_flag = mute; + es8316->muted = mute; if (mute) { - es8316_set_gpio(ES8316_CODEC_SET_SPK, !es8316->spk_gpio_level); + es8316_enable_spk(es8316, false); msleep(100); snd_soc_write(codec, ES8316_DAC_SET1_REG30, 0x20); } else if (dai->playback_active) { snd_soc_write(codec, ES8316_DAC_SET1_REG30, 0x00); msleep(130); - if (hp_irq_flag == 0) - es8316_set_gpio(ES8316_CODEC_SET_SPK, - es8316->spk_gpio_level); - msleep(150); + if (!es8316->hp_inserted) + es8316_enable_spk(es8316, true); } return 0; } @@ -883,56 +801,32 @@ static int es8316_mute(struct snd_soc_dai *dai, int mute) static int es8316_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - return 0; + struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); + int ret; + switch (level) { case SND_SOC_BIAS_ON: - dev_dbg(codec->dev, "%s on\n", __func__); break; + case SND_SOC_BIAS_PREPARE: - dev_dbg(codec->dev, "%s prepare\n", __func__); - if (es8316_init_reg > 0) { - snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0x7F); - snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x00); - snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0x00); - snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x00); - snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x88); - snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x88); - snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0xBB); - snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x10); - snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x30); - snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x02); - snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x00); - snd_soc_write(codec, ES8316_RESET_REG00, 0xC0); - snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x66); + if (IS_ERR(es8316->mclk)) + break; + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { + clk_disable_unprepare(es8316->mclk); + } else { + ret = clk_prepare_enable(es8316->mclk); + if (ret) + return ret; } break; + case SND_SOC_BIAS_STANDBY: - dev_dbg(codec->dev, "%s standby\n", __func__); - if (es8316_init_reg > 0) { - snd_soc_write(codec, - ES8316_CLKMGR_CLKSW_REG01, 0x7F); - snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x00); - snd_soc_write(codec, - ES8316_ADC_PDN_LINSEL_REG22, 0x00); - snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x00); - snd_soc_write(codec, - ES8316_HPMIX_SWITCH_REG14, 0x88); - snd_soc_write(codec, - ES8316_HPMIX_PDN_REG15, 0x88); - snd_soc_write(codec, - ES8316_HPMIX_VOL_REG16, 0xBB); - snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x10); - snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x30); - snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x02); - snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x00); - snd_soc_write(codec, ES8316_RESET_REG00, 0xC0); - snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x66); - } break; + case SND_SOC_BIAS_OFF: - dev_dbg(codec->dev, "%s off\n", __func__); - snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x33); snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x00); + snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x11); snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x03); snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x22); snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x06); @@ -940,13 +834,12 @@ static int es8316_set_bias_level(struct snd_soc_codec *codec, snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x33); snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0x00); snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0xC0); - snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x11); snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x3F); - snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0x03); - snd_soc_write(codec, ES8316_RESET_REG00, 0x7F); + snd_soc_write(codec, ES8316_SYS_LP1_REG0E, 0x3F); + snd_soc_write(codec, ES8316_SYS_LP2_REG0F, 0x1F); + snd_soc_write(codec, ES8316_RESET_REG00, 0x00); break; } - codec->dapm.bias_level = level; return 0; } @@ -962,6 +855,7 @@ static struct snd_soc_dai_ops es8316_ops = { .set_fmt = es8316_set_dai_fmt, .set_sysclk = es8316_set_dai_sysclk, .digital_mute = es8316_mute, + .shutdown = es8316_pcm_shutdown, }; static struct snd_soc_dai_driver es8316_dai = { @@ -984,50 +878,60 @@ static struct snd_soc_dai_driver es8316_dai = { .symmetric_rates = 1, }; - static int es8316_init_regs(struct snd_soc_codec *codec) { - dev_dbg(codec->dev, "%s\n", __func__); + snd_soc_write(codec, ES8316_RESET_REG00, 0x3f); + usleep_range(5000, 5500); + snd_soc_write(codec, ES8316_RESET_REG00, 0x00); + snd_soc_write(codec, ES8316_SYS_VMIDSEL_REG0C, 0xFF); + msleep(30); + snd_soc_write(codec, ES8316_CLKMGR_CLKSEL_REG02, 0x08); + snd_soc_write(codec, ES8316_CLKMGR_ADCOSR_REG03, 0x20); + snd_soc_write(codec, ES8316_CLKMGR_ADCDIV1_REG04, 0x11); + snd_soc_write(codec, ES8316_CLKMGR_ADCDIV2_REG05, 0x00); + snd_soc_write(codec, ES8316_CLKMGR_DACDIV1_REG06, 0x11); + snd_soc_write(codec, ES8316_CLKMGR_DACDIV2_REG07, 0x00); + snd_soc_write(codec, ES8316_CLKMGR_CPDIV_REG08, 0x00); + snd_soc_write(codec, ES8316_SDP_MS_BCKDIV_REG09, 0x04); + snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0x7F); + snd_soc_write(codec, ES8316_CAL_TYPE_REG1C, 0x0F); + snd_soc_write(codec, ES8316_CAL_HPLIV_REG1E, 0x90); + snd_soc_write(codec, ES8316_CAL_HPRIV_REG1F, 0x90); snd_soc_write(codec, ES8316_ADC_VOLUME_REG27, 0x00); - snd_soc_write(codec, ES8316_DAC_SET2_REG31, 0x00); + snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0xc0); + snd_soc_write(codec, ES8316_ADC_D2SEPGA_REG24, 0x00); + snd_soc_write(codec, ES8316_ADC_DMIC_REG25, 0x08); + snd_soc_write(codec, ES8316_DAC_SET2_REG31, 0x20); + snd_soc_write(codec, ES8316_DAC_SET3_REG32, 0x00); snd_soc_write(codec, ES8316_DAC_VOLL_REG33, 0x00); snd_soc_write(codec, ES8316_DAC_VOLR_REG34, 0x00); - snd_soc_write(codec, ES8316_SDP_ADCFMT_REG0A, 0x0C); - snd_soc_write(codec, ES8316_SDP_DACFMT_REG0B, 0x0C); - snd_soc_write(codec, ES8316_CLKMGR_CLKSEL_REG02, 0x09); - snd_soc_write(codec, 0x03, 0x19); - snd_soc_write(codec, 0x04, 0x21); - snd_soc_write(codec, 0x05, 0x90); - snd_soc_write(codec, 0x06, 0x21); - snd_soc_write(codec, 0x07, 0x90); - snd_soc_write(codec, 0x09, 0x06); - snd_soc_write(codec, ES8316_CLKMGR_CPDIV_REG08, 0x00); - snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0x7F); - snd_soc_write(codec, ES8316_SYS_VMIDSEL_REG0C, 0xFa); - snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x00); - snd_soc_write(codec, ES8316_RESET_REG00, 0xC0); - msleep(50); - snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0x20); - snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x00); + snd_soc_write(codec, ES8316_SDP_ADCFMT_REG0A, 0x00); + snd_soc_write(codec, ES8316_SDP_DACFMT_REG0B, 0x00); + snd_soc_write(codec, ES8316_SYS_VMIDLOW_REG10, 0x11); + snd_soc_write(codec, ES8316_SYS_VSEL_REG11, 0xFC); + snd_soc_write(codec, ES8316_SYS_REF_REG12, 0x28); + snd_soc_write(codec, ES8316_SYS_LP1_REG0E, 0x04); + snd_soc_write(codec, ES8316_SYS_LP2_REG0F, 0x0C); + snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x11); snd_soc_write(codec, ES8316_HPMIX_SEL_REG13, 0x00); snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x88); snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x00); snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0xBB); snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x10); - snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x00); - snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x03); + snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x30); + snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x02); snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x00); - snd_soc_write(codec, ES8316_SYS_VMIDLOW_REG10, 0x09); - msleep(20); - snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x66); - - snd_soc_write(codec, ES8316_GPIO_DEBUNCE_INT_REG4E, 0xf3); + snd_soc_write(codec, ES8316_GPIO_SEL_REG4D, 0x00); + snd_soc_write(codec, ES8316_GPIO_DEBUNCE_INT_REG4E, 0x02); snd_soc_write(codec, ES8316_TESTMODE_REG50, 0xA0); - snd_soc_write(codec, ES8316_TEST2_REG52, 0x03); - /*alc set*/ + snd_soc_write(codec, ES8316_TEST1_REG51, 0x00); + snd_soc_write(codec, ES8316_TEST2_REG52, 0x00); + snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x00); + snd_soc_write(codec, ES8316_RESET_REG00, 0xC0); + msleep(50); snd_soc_write(codec, ES8316_ADC_PGAGAIN_REG23, 0x60); snd_soc_write(codec, ES8316_ADC_D2SEPGA_REG24, 0x01); - /*adc ds mode, HPF enable*/ + /* adc ds mode, HPF enable */ snd_soc_write(codec, ES8316_ADC_DMIC_REG25, 0x08); snd_soc_write(codec, ES8316_ADC_ALC1_REG29, 0xcd); snd_soc_write(codec, ES8316_ADC_ALC2_REG2A, 0x08); @@ -1040,66 +944,108 @@ static int es8316_init_regs(struct snd_soc_codec *codec) static int es8316_suspend(struct snd_soc_codec *codec) { - snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x33); - snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x00); - snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x03); - snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x22); - snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x06); - snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x00); - snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x33); - snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0x00); - snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0xC0); - snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0x03); return 0; } static int es8316_resume(struct snd_soc_codec *codec) { - snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x00); - snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x30); - snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x10); - snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x02); - snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x88); - snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x88); - snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0xbb); - snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0x20); - snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0x7f); - snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x66); + int ret; + + es8316_reset(codec); /* UPDATED BY DAVID,15-3-5 */ + ret = snd_soc_read(codec, ES8316_CLKMGR_ADCDIV2_REG05); + if (!ret) { + es8316_init_regs(codec); + snd_soc_write(codec, ES8316_GPIO_SEL_REG4D, 0x00); + /* max debance time, enable interrupt, low active */ + snd_soc_write(codec, ES8316_GPIO_DEBUNCE_INT_REG4E, 0xf3); + /* es8316_set_bias_level(codec, SND_SOC_BIAS_OFF); */ + snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x00); + snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x11); + snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x03); + snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x22); + snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x06); + snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x00); + snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x33); + snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0x00); + snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x3F); + snd_soc_write(codec, ES8316_SYS_LP1_REG0E, 0xFF); + snd_soc_write(codec, ES8316_SYS_LP2_REG0F, 0xFF); + snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0xF3); + snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0xc0); + } return 0; } -static int es8316_probe(struct snd_soc_codec *codec) +static irqreturn_t es8316_irq_handler(int irq, void *data) { - int ret = 0, retv; - struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); + struct es8316_priv *es8316 = data; - DBG("---%s--start--\n", __func__); + queue_delayed_work(system_power_efficient_wq, &es8316->work, + msecs_to_jiffies(es8316->debounce_time)); - ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); + return IRQ_HANDLED; +} - if (ret < 0) { - dev_err(codec->dev, "fail to reset audio (%d)\n", ret); - goto err; - } - retv = snd_soc_read(codec, ES8316_CLKMGR_ADCDIV2_REG05); - if (retv == 0) { - snd_soc_write(codec, ES8316_GPIO_DEBUNCE_INT_REG4E, 0xf0); - snd_soc_write(codec, 0x01, 0x7f); - snd_soc_write(codec, 0x00, 0xc3); - msleep(100); - if (es8316->dmic_amic == dmic_used) - snd_soc_write(codec, ES8316_GPIO_SEL_REG4D, 0x02); +static void hp_work(struct work_struct *work) +{ + struct es8316_priv *es8316; + int enable; + + es8316 = container_of(work, struct es8316_priv, work.work); + enable = gpio_get_value(es8316->hp_det_gpio); + if (es8316->hp_det_invert) + enable = !enable; + + es8316->hp_inserted = enable ? true : false; + if (!es8316->muted) { + if (es8316->hp_inserted) + es8316_enable_spk(es8316, false); else + es8316_enable_spk(es8316, true); + } +} + +static int es8316_probe(struct snd_soc_codec *codec) +{ + struct es8316_priv *es8316 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + es8316->mclk = devm_clk_get(codec->dev, "mclk"); + if (PTR_ERR(es8316->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + ret = clk_prepare_enable(es8316->mclk); + if (ret) + return ret; + ret = snd_soc_read(codec, ES8316_CLKMGR_ADCDIV2_REG05); + if (!ret) { + es8316_reset(codec); /* UPDATED BY DAVID,15-3-5 */ + ret = snd_soc_read(codec, ES8316_CLKMGR_ADCDIV2_REG05); + if (!ret) { + es8316_init_regs(codec); snd_soc_write(codec, ES8316_GPIO_SEL_REG4D, 0x00); - snd_soc_write(codec, ES8316_GPIO_DEBUNCE_INT_REG4E, 0xf3); + /* max debance time, enable interrupt, low active */ + snd_soc_write(codec, + ES8316_GPIO_DEBUNCE_INT_REG4E, 0xf3); + + /* es8316_set_bias_level(codec, SND_SOC_BIAS_OFF); */ + snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x00); + snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x11); + snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x03); + snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x22); + snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x06); + snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x00); + snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x33); + snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0x00); + snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x3F); + snd_soc_write(codec, ES8316_SYS_LP1_REG0E, 0xFF); + snd_soc_write(codec, ES8316_SYS_LP2_REG0F, 0xFF); + snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0xF3); + snd_soc_write(codec, + ES8316_ADC_PDN_LINSEL_REG22, 0xc0); + } } - codec->dapm.idle_bias_off = 0; -#if defined(HS_IRQ) - det_initalize(); -#elif defined(HS_TIMER) - hsdet_init(); -#endif -err: + return ret; } @@ -1109,15 +1055,21 @@ static int es8316_remove(struct snd_soc_codec *codec) return 0; } +const struct regmap_config es8316_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ES8316_TEST3_REG53, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = es8316_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(es8316_reg_defaults), +}; + static struct snd_soc_codec_driver soc_codec_dev_es8316 = { .probe = es8316_probe, .remove = es8316_remove, .suspend = es8316_suspend, .resume = es8316_resume, .set_bias_level = es8316_set_bias_level, - .reg_cache_size = ARRAY_SIZE(es8316_reg_defaults), - .reg_word_size = sizeof(u8), - .reg_cache_default = es8316_reg_defaults, .controls = es8316_snd_controls, .num_controls = ARRAY_SIZE(es8316_snd_controls), @@ -1127,150 +1079,85 @@ static struct snd_soc_codec_driver soc_codec_dev_es8316 = { .num_dapm_routes = ARRAY_SIZE(es8316_dapm_routes), }; -#if defined(CONFIG_SPI_MASTER) -static int es8316_spi_probe(struct spi_device *spi) -{ - struct es8316_priv *es8316; - int ret; - - es8316 = kzalloc(sizeof(*es8316), GFP_KERNEL); - if (es8316 == NULL) - return -ENOMEM; - - spi_set_drvdata(spi, es8316); - ret = snd_soc_register_codec(&spi->dev, - &soc_codec_dev_es8316, - &es8316_dai, 1); - if (ret < 0) - kfree(es8316); - return ret; -} - -static int es8316_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - kfree(spi_get_drvdata(spi)); - return 0; -} - -static struct spi_driver es8316_spi_driver = { - .driver = { - .name = "es8316", - .owner = THIS_MODULE, - }, - .probe = es8316_spi_probe, - .remove = es8316_spi_remove, -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -static void es8316_i2c_shutdown(struct i2c_client *i2c) -{ - struct snd_soc_codec *codec; - struct es8316_priv *es8316 = es8316_private; - - if (!es8316_codec) - goto err; - - es8316_set_gpio(ES8316_CODEC_SET_SPK, !es8316->spk_gpio_level); - mdelay(150); - - - codec = es8316_codec; - snd_soc_write(codec, ES8316_CPHP_ICAL_VOL_REG18, 0x33); - snd_soc_write(codec, ES8316_CPHP_OUTEN_REG17, 0x00); - snd_soc_write(codec, ES8316_CPHP_LDOCTL_REG1B, 0x03); - snd_soc_write(codec, ES8316_CPHP_PDN2_REG1A, 0x22); - snd_soc_write(codec, ES8316_CPHP_PDN1_REG19, 0x06); - snd_soc_write(codec, ES8316_HPMIX_SWITCH_REG14, 0x00); - snd_soc_write(codec, ES8316_HPMIX_PDN_REG15, 0x33); - snd_soc_write(codec, ES8316_HPMIX_VOL_REG16, 0x00); - snd_soc_write(codec, ES8316_ADC_PDN_LINSEL_REG22, 0xC0); - snd_soc_write(codec, ES8316_DAC_PDN_REG2F, 0x11); - snd_soc_write(codec, ES8316_SYS_PDN_REG0D, 0x3F); - snd_soc_write(codec, ES8316_CLKMGR_CLKSW_REG01, 0x03); - snd_soc_write(codec, ES8316_RESET_REG00, 0x7F); -err: - return; -} - -static int es8316_i2c_probe(struct i2c_client *i2c_client, +static int es8316_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct es8316_priv *es8316; int ret = -1; - unsigned long irq_flag = 0; - int hp_irq = 0; + int hp_irq; enum of_gpio_flags flags; - struct device_node *np = i2c_client->dev.of_node; + struct device_node *np = i2c->dev.of_node; - DBG("---%s---probe start\n", __func__); - - es8316 = kzalloc(sizeof(*es8316), GFP_KERNEL); - if (es8316 == NULL) + es8316 = devm_kzalloc(&i2c->dev, sizeof(*es8316), GFP_KERNEL); + if (!es8316) return -ENOMEM; - else - es8316_private = es8316; - es8316->dmic_amic = amic_used; /*if internal mic is amic*/ - i2c_set_clientdata(i2c_client, es8316); + es8316->debounce_time = 200; + es8316->hp_det_invert = 0; + es8316->pwr_count = 0; + es8316->hp_inserted = false; + es8316->muted = true; + es8316->regmap = devm_regmap_init_i2c(i2c, &es8316_regmap_config); + if (IS_ERR(es8316->regmap)) { + ret = PTR_ERR(es8316->regmap); + dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); + return ret; + } + + i2c_set_clientdata(i2c, es8316); es8316->spk_ctl_gpio = of_get_named_gpio_flags(np, - "spk-con-gpio", 0, &flags); + "spk-con-gpio", + 0, + &flags); if (es8316->spk_ctl_gpio < 0) { - DBG("%s() Can not read property spk codec-en-gpio\n", __func__); + dev_info(&i2c->dev, "Can not read property spk_ctl_gpio\n"); es8316->spk_ctl_gpio = INVALID_GPIO; } else { - es8316->spk_gpio_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; - ret = gpio_request(es8316->spk_ctl_gpio, NULL); - gpio_direction_output(es8316->spk_ctl_gpio, - !es8316->spk_gpio_level); - } - - es8316->hp_ctl_gpio = of_get_named_gpio_flags(np, - "hp-con-gpio", 0, &flags); - if (es8316->hp_ctl_gpio < 0) { - DBG("%s() Can not read property hp codec-en-gpio\n", __func__); - es8316->hp_ctl_gpio = INVALID_GPIO; - } else { - es8316->hp_gpio_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; - ret = gpio_request(es8316->hp_ctl_gpio, NULL); - gpio_direction_output(es8316->hp_ctl_gpio, !es8316->hp_gpio_level); + es8316->spk_active_level = !(flags & OF_GPIO_ACTIVE_LOW); + ret = devm_gpio_request_one(&i2c->dev, es8316->spk_ctl_gpio, + GPIOF_DIR_OUT, NULL); + if (ret) { + dev_err(&i2c->dev, "Failed to request spk_ctl_gpio\n"); + return ret; + } + es8316_enable_spk(es8316, false); } es8316->hp_det_gpio = of_get_named_gpio_flags(np, - "hp-det-gpio", 0, &flags); + "hp-det-gpio", + 0, + &flags); if (es8316->hp_det_gpio < 0) { - DBG("%s() Can not read property hp_det gpio\n", __func__); + dev_info(&i2c->dev, "Can not read property hp_det_gpio\n"); es8316->hp_det_gpio = INVALID_GPIO; } else { - es8316->hp_det_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1; - ret = gpio_request(es8316->hp_det_gpio, NULL); - if (ret != 0) { - DBG("%s request HP_DET error", __func__); + INIT_DELAYED_WORK(&es8316->work, hp_work); + es8316->hp_det_invert = !!(flags & OF_GPIO_ACTIVE_LOW); + ret = devm_gpio_request_one(&i2c->dev, es8316->hp_det_gpio, + GPIOF_IN, "hp det"); + if (ret < 0) return ret; - } - gpio_direction_input(es8316->hp_det_gpio); - - irq_flag = IRQF_TRIGGER_LOW | IRQF_ONESHOT; hp_irq = gpio_to_irq(es8316->hp_det_gpio); + ret = devm_request_threaded_irq(&i2c->dev, hp_irq, NULL, + es8316_irq_handler, + IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | + IRQF_ONESHOT, + "es8316_interrupt", es8316); + if (ret < 0) { + dev_err(&i2c->dev, "request_irq failed: %d\n", ret); + return ret; + } - if (hp_irq) - ret = request_threaded_irq(hp_irq, NULL, - hp_det_irq_handler, irq_flag, "ES8316", NULL); + schedule_delayed_work(&es8316->work, + msecs_to_jiffies(es8316->debounce_time)); } - ret = snd_soc_register_codec(&i2c_client->dev, + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_es8316, &es8316_dai, 1); - if (ret < 0) { - kfree(es8316); - return ret; - } - - return ret; } @@ -1278,11 +1165,9 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client, static int es8316_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); - kfree(i2c_get_clientdata(client)); return 0; } -static const unsigned short normal_i2c[] = {0x10, I2C_CLIENT_END}; static const struct i2c_device_id es8316_i2c_id[] = { {"es8316", 0}, {"10ES8316:00", 0}, @@ -1291,44 +1176,23 @@ static const struct i2c_device_id es8316_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, es8316_i2c_id); +static const struct of_device_id es8316_of_match[] = { + { .compatible = "everest,es8316", }, + { } +}; +MODULE_DEVICE_TABLE(of, es8316_of_match); + static struct i2c_driver es8316_i2c_driver = { .driver = { - .name = "es8316", - .owner = THIS_MODULE, + .name = "es8316", + .of_match_table = es8316_of_match, }, - .shutdown = es8316_i2c_shutdown, - .probe = es8316_i2c_probe, - .remove = es8316_i2c_remove, + .probe = es8316_i2c_probe, + .remove = es8316_i2c_remove, .id_table = es8316_i2c_id, - .class = I2C_CLASS_HWMON, - .address_list = normal_i2c, }; -#endif - -static int __init es8316_init(void) -{ - DBG("--%s--start--\n", __func__); -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - return i2c_add_driver(&es8316_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - return spi_register_driver(&es8316_spi_driver); -#endif -} - -static void __exit es8316_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - return i2c_del_driver(&es8316_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - return spi_unregister_driver(&es8316_spi_driver); -#endif -} - -module_init(es8316_init); -module_exit(es8316_exit); +module_i2c_driver(es8316_i2c_driver); MODULE_DESCRIPTION("ASoC es8316 driver"); MODULE_AUTHOR("Will ");