author | Xiaoliang Wang <xiaoliang.wang@amlogic.com> | 2019-01-10 07:03:32 (GMT) |
---|---|---|
committer | Gerrit Code Review <gituser@droid04> | 2019-01-10 07:03:32 (GMT) |
commit | 03e395302100be525f3df51381040de330b2e4ea (patch) | |
tree | bfc040b4b23c81180f73e124fe0c7b04ae8dca9d | |
parent | 54d2061b0599eca961eaec6cb0bd43a67d460cf4 (diff) | |
parent | abf9d2ad8e93203a91b914f4daca0689d7c53c86 (diff) | |
download | common-03e395302100be525f3df51381040de330b2e4ea.zip common-03e395302100be525f3df51381040de330b2e4ea.tar.gz common-03e395302100be525f3df51381040de330b2e4ea.tar.bz2 |
Merge "audio: add amp mute and optimize codec power on flow[1/2]" into p-tv-atom
-rw-r--r-- | arch/arm64/boot/dts/amlogic/atom.dts | 8 | ||||
-rw-r--r-- | sound/soc/codecs/amlogic/cs42528.c | 142 | ||||
-rw-r--r-- | sound/soc/codecs/amlogic/cs42528.h | 3 |
3 files changed, 126 insertions, 27 deletions
diff --git a/arch/arm64/boot/dts/amlogic/atom.dts b/arch/arm64/boot/dts/amlogic/atom.dts index b025df1..10930ac 100644 --- a/arch/arm64/boot/dts/amlogic/atom.dts +++ b/arch/arm64/boot/dts/amlogic/atom.dts @@ -1235,13 +1235,13 @@ pinctrl-names = "audio_i2s"; pinctrl-0 = <&aml_audio_i2s>; /*avout mute gpio*/ - mute_gpio-gpios = <&gpio GPIODV_5 GPIO_ACTIVE_HIGH>; + /*mute_gpio-gpios = <&gpio GPIODV_5 GPIO_ACTIVE_HIGH>;*/ /*switch ARC_IN & SPDIF_IN*/ source_switch-gpios = <&gpio GPIOZ_4 GPIO_ACTIVE_HIGH>; source_switch_inv = <1>; - sleep_time = <100>; /*analog amp mute*/ - amp_mute_gpio-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>; + /*amp_mute_gpio-gpios = <&gpio GPIOZ_2 GPIO_ACTIVE_HIGH>;*/ + /*sleep_time = <100>;*/ /*aux_dev = <&cs42528>;*/ cpu_list = <&cpudai0 &cpudai1 &cpudai2>; codec_list = <&codec0 &codec1 &codec2>; @@ -1456,6 +1456,8 @@ codec_name = "cs42528"; reg = <0x4E>; reset_pin = <&gpio GPIOZ_17 GPIO_ACTIVE_LOW>; + pdn_pin = <&gpio GPIOZ_2 GPIO_ACTIVE_LOW>; + amp_pin = <&gpio GPIODV_5 GPIO_ACTIVE_LOW>; status = "okay"; }; }; diff --git a/sound/soc/codecs/amlogic/cs42528.c b/sound/soc/codecs/amlogic/cs42528.c index f1f0c96..bb27839 100644 --- a/sound/soc/codecs/amlogic/cs42528.c +++ b/sound/soc/codecs/amlogic/cs42528.c @@ -21,6 +21,7 @@ static void cs42528_early_suspend(struct early_suspend *h); static void cs42528_late_resume(struct early_suspend *h); #endif +static int Enable_Amp(struct snd_soc_codec *codec, int enable); /* Power-up register defaults */ struct reg_default cs42528_reg_defaults[] = { @@ -103,6 +104,36 @@ static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 0); /* -15dB to 15dB with step of 1dB */ static const DECLARE_TLV_DB_SCALE(adc_tlv, -1500, 100, 0); +static const char *const amp_mute_texts[] = { + "UNMUTE", "MUTE"}; + +static const struct soc_enum amp_mute_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(amp_mute_texts), + amp_mute_texts); + +static int get_amp_mute(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct cs42528_priv *cs42528 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.enumerated.item[0] = cs42528->pdata->amp_mute; + + return 0; +} + +static int set_amp_mute(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct cs42528_priv *cs42528 = snd_soc_codec_get_drvdata(codec); + + cs42528->pdata->amp_mute = ucontrol->value.enumerated.item[0]; + Enable_Amp(codec, cs42528->pdata->amp_mute); + + return 0; +} + static const char *const cs42528_szc[] = { "Immediate Change", "Zero Cross", @@ -132,6 +163,8 @@ static const struct snd_kcontrol_new cs42528_snd_controls[] = { SOC_ENUM("DAC Soft Ramp & Zero Cross Control Switch", dac_szc_enum), SOC_SINGLE("DAC Auto Mute Switch", CS42528_TXCTL, 3, 1, 0), SOC_SINGLE("DAC Serial Port Mute Switch", CS42528_TXCTL, 2, 1, 0), + SOC_SINGLE("DAC Channel Mute", CS42528_DACMUTE, 0, 0xff, 0), + SOC_ENUM_EXT("AMP MUTE", amp_mute_enum, get_amp_mute, set_amp_mute), }; #if 0 @@ -203,7 +236,7 @@ static int cs42528_set_dai_sysclk(struct snd_soc_dai *codec_dai, } static int cs42528_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int format) + unsigned int format) { struct snd_soc_codec *codec = codec_dai->codec; struct cs42528_priv *cs42528 = snd_soc_codec_get_drvdata(codec); @@ -245,8 +278,8 @@ static int cs42528_set_dai_fmt(struct snd_soc_dai *codec_dai, } static int cs42528_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) { unsigned int rate; @@ -280,15 +313,6 @@ static int cs42528_hw_params(struct snd_pcm_substream *substream, static int cs42528_digital_mute(struct snd_soc_dai *dai, int mute) { - struct snd_soc_codec *codec = dai->codec; - - pr_info("%s %d mute: %d\n", __func__, __LINE__, mute); - - if (mute) - snd_soc_write(codec, CS42528_DACMUTE, 0xff); - else - snd_soc_write(codec, CS42528_DACMUTE, 0); - return 0; } @@ -324,23 +348,64 @@ static int reset_cs42528(struct snd_soc_codec *codec) struct cs42528_platform_data *pdata = cs42528->pdata; int ret = 0; - if (pdata->reset_pin < 0) + if (pdata->reset_pin <= 0 || pdata->pdn_pin <= 0) return 0; - ret = devm_gpio_request_one(codec->dev, pdata->reset_pin, - GPIOF_OUT_INIT_LOW, - "cs42528-reset-pin"); + ret = devm_gpio_request_one(codec->dev, pdata->pdn_pin, + GPIOF_OUT_INIT_HIGH, + "cs42528-pdn-pin"); if (ret < 0) - return -1; + pr_err("%s %d can't get GPIO pdn pin!\n", __func__, __LINE__); + else { + gpio_direction_output(pdata->pdn_pin, GPIOF_OUT_INIT_HIGH); + pr_info("%s %d set GPIO pdn pin high!\n", __func__, __LINE__); + } - gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); - mdelay(1); - gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); - msleep(85); + ret = devm_gpio_request_one(codec->dev, pdata->reset_pin, + GPIOF_OUT_INIT_LOW, + "cs42528-reset-pin"); + if (ret >= 0) { + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + mdelay(1); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + msleep(85); + pr_info("%s %d set GPIO reset pin high!\n", __func__, __LINE__); + } else { + pr_err("%s %d can't get GPIO reset pin!\n", __func__, __LINE__); + } + + ret = devm_gpio_request_one(codec->dev, pdata->amp_pin, + GPIOF_OUT_INIT_LOW, + "cs42528-amp-pin"); + if (ret >= 0) + pr_info("%s %d set GPIO amp pin high!\n", __func__, __LINE__); + else + pr_err("%s %d can't get GPIO amp pin!\n", __func__, __LINE__); return 0; } +static int Enable_Amp(struct snd_soc_codec *codec, int enable) +{ + struct cs42528_priv *cs42528 = snd_soc_codec_get_drvdata(codec); + struct cs42528_platform_data *pdata = cs42528->pdata; + + if (pdata->amp_pin > 0) { + if (enable == 1) { + gpio_direction_output(pdata->amp_pin, + GPIOF_OUT_INIT_LOW); + pr_info("%s %d set GPIO amp pin low!\n", + __func__, __LINE__); + } else { + gpio_direction_output(pdata->amp_pin, + GPIOF_OUT_INIT_HIGH); + pr_info("%s %d set GPIO amp pin high!\n", + __func__, __LINE__); + } + } + return 0; +} + static int cs42528_init(struct snd_soc_codec *codec) { int i; @@ -360,6 +425,15 @@ static int cs42528_init(struct snd_soc_codec *codec) // Write CS42528 Powerup Register snd_soc_write(codec, CS42528_PWRCTL, 0x40); + // unmute + snd_soc_write(codec, CS42528_VOLCTLA1, 0); + snd_soc_write(codec, CS42528_VOLCTLB1, 0); + snd_soc_write(codec, CS42528_VOLCTLA2, 0); + snd_soc_write(codec, CS42528_VOLCTLB2, 0); + snd_soc_write(codec, CS42528_DACMUTE, 0); + + Enable_Amp(codec, 1); + return 0; } @@ -448,6 +522,8 @@ static int cs42528_parse_dt( { int ret = 0; int reset_pin = -1; + int pdn_pin = -1; + int amp_pin = -1; reset_pin = of_get_named_gpio(np, "reset_pin", 0); if (reset_pin < 0) { @@ -458,11 +534,29 @@ static int cs42528_parse_dt( } cs42528->pdata->reset_pin = reset_pin; + pdn_pin = of_get_named_gpio(np, "pdn_pin", 0); + if (pdn_pin < 0) { + pr_err("%s fail to get pdn pin from dts!\n", __func__); + ret = -1; + } else { + pr_info("%s pdn_pin = %d!\n", __func__, pdn_pin); + } + cs42528->pdata->pdn_pin = pdn_pin; + + amp_pin = of_get_named_gpio(np, "amp_pin", 0); + if (amp_pin < 0) { + pr_err("%s fail to get amp_pin from dts!\n", __func__); + ret = -1; + } else { + pr_info("%s amp_pin = %d!\n", __func__, amp_pin); + } + cs42528->pdata->amp_pin = amp_pin; + return ret; } static int cs42528_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct cs42528_priv *cs42528; struct cs42528_platform_data *pdata; @@ -470,7 +564,7 @@ static int cs42528_i2c_probe(struct i2c_client *i2c, const char *codec_name; cs42528 = devm_kzalloc(&i2c->dev, sizeof(struct cs42528_priv), - GFP_KERNEL); + GFP_KERNEL); if (!cs42528) return -ENOMEM; @@ -507,7 +601,7 @@ static int cs42528_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, cs42528); ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_cs42528, - &cs42528_dai, 1); + &cs42528_dai, 1); if (ret != 0) dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); diff --git a/sound/soc/codecs/amlogic/cs42528.h b/sound/soc/codecs/amlogic/cs42528.h index acd241f..75caa02 100644 --- a/sound/soc/codecs/amlogic/cs42528.h +++ b/sound/soc/codecs/amlogic/cs42528.h @@ -4,6 +4,9 @@ struct cs42528_platform_data { int reset_pin; int mute_pin; + int pdn_pin; + int amp_pin; + int amp_mute; }; /* CS42888 register map */ |