audio: fix tas5808 no sound [1/1]
authorChe Song <che.song@amlogic.com>
Fri, 22 Feb 2019 03:06:12 +0000 (11:06 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Fri, 22 Feb 2019 04:28:34 +0000 (20:28 -0800)
PD#SWPL-3081

Problem:
1,lack suspend/resume function
2,lack reset pin control

Solution:
1,add  suspend/resume function
2, add reset pin control

Verify:
962x2

Signed-off-by: Che Song <che.song@amlogic.com>
Change-Id: I1cb920fdba4ad32048518fdad93e3a5a81039dd9

sound/soc/codecs/amlogic/tas5805.c
sound/soc/codecs/amlogic/tas5805.h

index 36f11cf..615320e 100644 (file)
 #include <sound/soc.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
+#include <linux/amlogic/aml_gpio_consumer.h>
 
 #include "tas5805.h"
 
-#define TAS5805M_DRV_NAME    "tas5805m"
+#define TAS5805M_DRV_NAME    "tas5805"
 
 #define TAS5805M_RATES      (SNDRV_PCM_RATE_8000 | \
                       SNDRV_PCM_RATE_11025 | \
@@ -227,9 +228,7 @@ const uint32_t tas5805m_volume[] = {
 
 struct tas5805m_priv {
        struct regmap *regmap;
-
-       struct mutex lock;
-
+       struct tas5805m_platform_data *pdata;
        int vol;
        int mute;
 };
@@ -276,9 +275,7 @@ static int tas5805m_vol_locked_get(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec);
 
-       mutex_lock(&tas5805m->lock);
        ucontrol->value.integer.value[0] = tas5805m->vol;
-       mutex_unlock(&tas5805m->lock);
 
        return 0;
 }
@@ -339,12 +336,10 @@ static int tas5805m_vol_locked_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec);
 
-       mutex_lock(&tas5805m->lock);
 
        tas5805m->vol = ucontrol->value.integer.value[0];
        tas5805m_set_volume(codec, tas5805m->vol);
 
-       mutex_unlock(&tas5805m->lock);
 
        return 0;
 }
@@ -353,7 +348,6 @@ static int tas5805m_mute(struct snd_soc_codec *codec, int mute)
 {
        u8 reg03_value = 0;
        u8 reg35_value = 0;
-//  struct snd_soc_codec *codec = dai->codec;
 
        if (mute) {
                //mute both left & right channels
@@ -380,13 +374,9 @@ static int tas5805m_mute_locked_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec);
 
-       mutex_lock(&tas5805m->lock);
-
        tas5805m->mute = ucontrol->value.integer.value[0];
        tas5805m_mute(codec, tas5805m->mute);
 
-       mutex_unlock(&tas5805m->lock);
-
        return 0;
 }
 
@@ -395,11 +385,7 @@ static int tas5805m_mute_locked_get(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec);
-
-       mutex_lock(&tas5805m->lock);
        ucontrol->value.integer.value[0] = tas5805m->mute;
-       mutex_unlock(&tas5805m->lock);
-
        return 0;
 }
 
@@ -420,6 +406,31 @@ static const struct snd_kcontrol_new tas5805m_vol_control[] = {
        }
 };
 
+static int tas5805m_set_bias_level(struct snd_soc_codec *codec,
+                                 enum snd_soc_bias_level level)
+{
+       pr_debug("level = %d\n", level);
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               /* Full power on */
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               /* The chip runs through the power down sequence for us. */
+               break;
+       }
+       codec->component.dapm.bias_level = level;
+
+       return 0;
+}
+
 static int tas5805m_snd_probe(struct snd_soc_codec *codec)
 {
        int ret;
@@ -429,8 +440,40 @@ static int tas5805m_snd_probe(struct snd_soc_codec *codec)
        return ret;
 }
 
+static int tas5805m_snd_suspend(struct snd_soc_codec *codec)
+{
+       dev_info(codec->dev, "tas5805m_suspend!\n");
+       tas5805m_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int tas5805m_snd_resume(struct snd_soc_codec *codec)
+{
+       int ret;
+       struct tas5805m_priv *tas5805m = snd_soc_codec_get_drvdata(codec);
+
+       dev_info(codec->dev, "tas5805m_snd_resume!\n");
+       ret =
+           regmap_register_patch(tas5805m->regmap, tas5805m_init_sequence,
+                                 ARRAY_SIZE(tas5805m_init_sequence));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to initialize TAS5805M: %d\n", ret);
+               goto err;
+       }
+
+       tas5805m_set_volume(codec, tas5805m->vol);
+       tas5805m_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
+err:
+       return ret;
+}
+
 static struct snd_soc_codec_driver soc_codec_tas5805m = {
        .probe = tas5805m_snd_probe,
+       .suspend = tas5805m_snd_suspend,
+       .resume = tas5805m_snd_resume,
+       .set_bias_level = tas5805m_set_bias_level,
 };
 
 static const struct snd_soc_dai_ops tas5805m_dai_ops = {
@@ -449,28 +492,60 @@ static struct snd_soc_dai_driver tas5805m_dai = {
        .ops = &tas5805m_dai_ops,
 };
 
-static int tas5805m_probe(struct device *dev, struct regmap *regmap)
+static int reset_tas5805m_GPIO(struct device *dev)
 {
-       struct tas5805m_priv *tas5805m;
-       int ret;
+       struct tas5805m_priv *tas5805m = dev_get_drvdata(dev);
+       struct tas5805m_platform_data *pdata = tas5805m->pdata;
+       int ret = 0;
 
-       tas5805m = devm_kzalloc(dev, sizeof(struct tas5805m_priv), GFP_KERNEL);
-       if (!tas5805m)
-               return -ENOMEM;
+       if (pdata->reset_pin < 0)
+               return 0;
 
-       dev_set_drvdata(dev, tas5805m);
-       tas5805m->regmap = regmap;
-       tas5805m->vol = 100;    //100, -10dB
+       ret = devm_gpio_request_one(dev, pdata->reset_pin,
+                                           GPIOF_OUT_INIT_LOW,
+                                           "tas5805m-reset-pin");
+       if (ret < 0)
+               return -1;
+
+       gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW);
+       mdelay(1);
+       gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH);
+       mdelay(1);
+
+       return 0;
+}
+
+static int tas5805m_parse_dt(
+       struct tas5805m_priv *tas5805m,
+       struct device_node *np)
+{
+       int ret = 0;
+       int reset_pin = -1;
+
+       reset_pin = of_get_named_gpio(np, "reset_pin", 0);
+       if (reset_pin < 0) {
+               pr_err("%s fail to get reset pin from dts!\n", __func__);
+               ret = -1;
+       } else {
+               pr_info("%s pdata->reset_pin = %d!\n", __func__,
+                               tas5805m->pdata->reset_pin);
+       }
+       tas5805m->pdata->reset_pin = reset_pin;
+
+       return ret;
+}
 
-       mutex_init(&tas5805m->lock);
+static int tas5805m_probe(struct device *dev, struct regmap *regmap)
+{
+       int ret;
 
+       reset_tas5805m_GPIO(dev);
        ret =
            regmap_register_patch(regmap, tas5805m_init_sequence,
                                  ARRAY_SIZE(tas5805m_init_sequence));
        if (ret != 0) {
                dev_err(dev, "Failed to initialize TAS5805M: %d\n", ret);
                goto err;
-
        }
 
        ret =
@@ -487,16 +562,39 @@ err:
 
 }
 
+
 static int tas5805m_i2c_probe(struct i2c_client *i2c,
                              const struct i2c_device_id *id)
 {
        struct regmap *regmap;
        struct regmap_config config = tas5805m_regmap;
+       struct tas5805m_priv *tas5805m;
+       struct tas5805m_platform_data *pdata;
+
+       tas5805m = devm_kzalloc(&i2c->dev,
+               sizeof(struct tas5805m_priv), GFP_KERNEL);
+       if (!tas5805m)
+               return -ENOMEM;
 
        regmap = devm_regmap_init_i2c(i2c, &config);
        if (IS_ERR(regmap))
                return PTR_ERR(regmap);
 
+       pdata = devm_kzalloc(&i2c->dev,
+                               sizeof(struct tas5805m_platform_data),
+                               GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s failed to kzalloc for tas5805 pdata\n", __func__);
+               return -ENOMEM;
+       }
+       tas5805m->pdata = pdata;
+
+       tas5805m_parse_dt(tas5805m, i2c->dev.of_node);
+       tas5805m->regmap = regmap;
+       tas5805m->vol = 100;    //100, -10dB
+
+       dev_set_drvdata(&i2c->dev, tas5805m);
+
        return tas5805m_probe(&i2c->dev, regmap);
 }
 
index ba60662..5f3fdeb 100644 (file)
@@ -27,7 +27,10 @@ static const struct reg_sequence tas5805m_init_sequence[] = {
        {0x00, 0x00},
        {0x7f, 0x00},
        {0x00, 0x00},
+       {0x02, 0x11},//Fsw=384kHz, BD Mode, 1SPW Mode
        {0x66, 0x85},
+       {0x6b, 0x03},//Enable SS
+       {0x6c, 0x03},//Set Tri-freq to 24Hz, SS range 336~432kHz
        {0x00, 0x00},
        {0x7f, 0x8c},
        {0x00, 0x2a},
@@ -1871,10 +1874,15 @@ static const struct reg_sequence tas5805m_init_sequence[] = {
        {0x00, 0x00},
        {0x7f, 0x00},
        {0x00, 0x00},
-       {0x02, 0x00},
+       {0x02, 0x11},//Fsw=384kHz, 1SPW Mode
        {0x00, 0x00},
        {0x7f, 0x00},
        {0x00, 0x00},
        {0x03, 0x03},
        {0x35, 0x11},
 };
+
+struct tas5805m_platform_data {
+       int reset_pin;
+};
+