diff --git a/ac101.c b/ac101.c index 74b800a..812636b 100644 --- a/ac101.c +++ b/ac101.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "ac101.h" @@ -48,7 +49,7 @@ #define DMIC_USED 0 #define ADC_DIGITAL_GAIN 0xb0b0 #define AGC_USED 0 -#define DRC_USED 1 +#define DRC_USED 0 #define _MORE_WIDGETS 0 static bool speaker_double_used = false; @@ -103,6 +104,8 @@ struct ac10x_priv { struct work_struct codec_resume; struct delayed_work dlywork; int trgr_cnt; + + struct gpio_desc* gpiod_spk_amp_switch; }; void get_configuration(void) @@ -1105,7 +1108,7 @@ static const struct snd_soc_dapm_route ac10x_dapm_routes[] = { {"DMICR VIR", NULL, "D_MIC"}, }; #else // !_MORE_WIDGETS - #if 0 + #if 1 static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -11925, 75, 0); static const DECLARE_TLV_DB_SCALE(dac_mix_vol_tlv, -600, 600, 0); static const DECLARE_TLV_DB_SCALE(dig_vol_tlv, -7308, 116, 0); @@ -1115,7 +1118,7 @@ static const struct snd_soc_dapm_route ac10x_dapm_routes[] = { static const struct snd_kcontrol_new ac10x_controls[] = { /*DAC*/ - #if 0 + #if 1 SOC_DOUBLE_TLV("DAC volume", DAC_VOL_CTRL, DAC_VOL_L, DAC_VOL_R, 0xff, 0, dac_vol_tlv), SOC_DOUBLE_TLV("DAC mixer gain", DAC_MXR_GAIN, DACL_MXR_GAIN, DACR_MXR_GAIN, 0xf, 0, dac_mix_vol_tlv), SOC_SINGLE_TLV("digital volume", DAC_DBG_CTRL, DVC, 0x3f, 1, dig_vol_tlv), @@ -1214,6 +1217,7 @@ static const unsigned ac10x_bclkdivs[] = { static int ac10x_aif_mute(struct snd_soc_dai *codec_dai, int mute) { struct snd_soc_codec *codec = codec_dai->codec; + struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec); AC10X_DBG("%s() L%d mute=%d\n", __func__, __LINE__, mute); @@ -1224,13 +1228,18 @@ static int ac10x_aif_mute(struct snd_soc_dai *codec_dai, int mute) late_enable_dac(codec, SND_SOC_DAPM_PRE_PMU); ac10x_headphone_event(codec, SND_SOC_DAPM_POST_PMU); if (drc_used) { - drc_enable(codec,1); + drc_enable(codec, 1); + } + if (ac10x->gpiod_spk_amp_switch) { + gpiod_set_value(ac10x->gpiod_spk_amp_switch, 1); } } else { - struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec); + if (ac10x->gpiod_spk_amp_switch) { + gpiod_set_value(ac10x->gpiod_spk_amp_switch, 0); + } if (drc_used) { - drc_enable(codec,0); + drc_enable(codec, 0); } ac10x_headphone_event(codec, SND_SOC_DAPM_PRE_PMD); late_enable_dac(codec, SND_SOC_DAPM_POST_PMD); @@ -1271,8 +1280,9 @@ static int ac10x_hw_params(struct snd_pcm_substream *substream, { int i = 0; int AIF_CLK_CTRL = AIF1_CLK_CTRL; - int aif1_word_size = 16; - int aif1_lrck_div = 64; + int aif1_word_size = 24; + int aif1_slot_size = 32; + int aif1_lrck_div; struct snd_soc_codec *codec = codec_dai->codec; struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec); int reg_val, freq_out; @@ -1282,9 +1292,23 @@ static int ac10x_hw_params(struct snd_pcm_substream *substream, ac10x->trgr_cnt = 0; + /* get channels count & slot size */ channels = params_channels(params); - aif1_lrck_div = 32 * channels; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S32_LE: + aif1_slot_size = 32; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + aif1_slot_size = 16; + break; + } + + + /* set LRCK/BCLK ratio */ + aif1_lrck_div = aif1_slot_size * channels; for (i = 0; i < ARRAY_SIZE(codec_aif1_lrck); i++) { if (codec_aif1_lrck[i].val == aif1_lrck_div) { break; @@ -1292,6 +1316,7 @@ static int ac10x_hw_params(struct snd_pcm_substream *substream, } snd_soc_update_bits(codec, AIF_CLK_CTRL, (0x7< 2) - #else - /* fixed 32 bits */ - i = 2; - #endif - snd_soc_update_bits(codec, AIF1_ADCDAT_CTRL, 0x3 << AIF1_SLOT_SIZ, i << AIF1_SLOT_SIZ); + if ((reg_val = codec_aif1_wsize[i].bit) > 2) reg_val = 2; + snd_soc_update_bits(codec, AIF1_ADCDAT_CTRL, 0x3 << AIF1_SLOT_SIZ, reg_val << AIF1_SLOT_SIZ); /* setting pll if it's master mode */ reg_val = snd_soc_read(codec, AIF_CLK_CTRL); @@ -1903,6 +1913,12 @@ static int ac10x_probe(struct i2c_client *i2c, const struct i2c_device_id *id) if (ret) { pr_err("failed to create attr group\n"); } + + ac10x->gpiod_spk_amp_switch = devm_gpiod_get_optional(&i2c->dev, "spk-amp-switch", GPIOD_OUT_LOW); + if (IS_ERR(ac10x->gpiod_spk_amp_switch)) { + ac10x->gpiod_spk_amp_switch = NULL; + dev_err(&i2c->dev, "failed get spk-amp-switch in device tree\n"); + } return 0; } diff --git a/seeed-8mic-voicecard-overlay.dts b/seeed-8mic-voicecard-overlay.dts index e87148e..684e665 100644 --- a/seeed-8mic-voicecard-overlay.dts +++ b/seeed-8mic-voicecard-overlay.dts @@ -15,7 +15,7 @@ fragment@1 { target-path = "/clocks"; __overlay__ { - ac108_mclk: codec-mclk { + ac10x_mclk: codec-mclk { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <24000000>; @@ -24,6 +24,20 @@ }; fragment@2 { + target = <&gpio>; + __overlay__ { + spk_amp_switch_pins: speaker_amp_switch_pins { + brcm,pins = <17>; + brcm,function = <1>; /* out */ + }; + gpclk0_pins: gpclk0_pins { + brcm,pins = <4>; + brcm,function = <4>; /* alt func 0 */ + }; + }; + }; + + fragment@3 { target = <&i2c1>; __overlay__ { #address-cells = <1>; @@ -32,6 +46,9 @@ ac101: ac101@1a{ compatible = "x-power,ac101"; + pinctrl-names = "default"; + pinctrl-0 = <&spk_amp_switch_pins>,<&gpclk0_pins>; + spk-amp-switch-gpios = <&gpio 17 0>; reg = <0x1a>; #sound-dai-cells = <0>; }; @@ -53,7 +70,7 @@ }; }; - fragment@3 { + fragment@4 { target = <&sound>; sound_overlay: __overlay__ { @@ -76,7 +93,7 @@ }; codec_dai: simple-audio-card,codec { sound-dai = <&ac101>; - clocks = <&ac108_mclk>; + clocks = <&ac10x_mclk>; system-clock-id = <1>; }; }; diff --git a/seeed-8mic-voicecard.dtbo b/seeed-8mic-voicecard.dtbo index a9de216..1360e19 100644 Binary files a/seeed-8mic-voicecard.dtbo and b/seeed-8mic-voicecard.dtbo differ