From 105becb4174f1fd73be6d2dbf992e15aae352e11 Mon Sep 17 00:00:00 2001 From: Che Song Date: Fri, 22 Feb 2019 11:06:12 +0800 Subject: [PATCH] audio: fix tas5808 no sound [1/1] 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 Change-Id: I1cb920fdba4ad32048518fdad93e3a5a81039dd9 --- sound/soc/codecs/amlogic/tas5805.c | 154 ++++++++++++++++++++++++++++++------- sound/soc/codecs/amlogic/tas5805.h | 10 ++- 2 files changed, 135 insertions(+), 29 deletions(-) diff --git a/sound/soc/codecs/amlogic/tas5805.c b/sound/soc/codecs/amlogic/tas5805.c index 36f11cf..615320e 100644 --- a/sound/soc/codecs/amlogic/tas5805.c +++ b/sound/soc/codecs/amlogic/tas5805.c @@ -24,10 +24,11 @@ #include #include #include +#include #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); } diff --git a/sound/soc/codecs/amlogic/tas5805.h b/sound/soc/codecs/amlogic/tas5805.h index ba60662..5f3fdeb4 100644 --- a/sound/soc/codecs/amlogic/tas5805.h +++ b/sound/soc/codecs/amlogic/tas5805.h @@ -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; +}; + -- 2.7.4