From: Marek Vasut <marek.vasut@gmail.com>
To: alsa-devel@alsa-project.org
Cc: Vasily Khoruzhick <anarsoul@gmail.com>,
Mark Brown <broonie@opensource.wolfsonmicro.com>,
Ben Dooks <ben-linux@fluff.org>,
Philipp Zabel <philipp.zabel@gmail.com>,
Liam Girdwood <lrg@slimlogic.co.uk>
Subject: Re: [PATCH v4 1/3] ASoC: uda1380: make driver more powersave-friendly
Date: Sun, 29 Aug 2010 19:37:03 +0200 [thread overview]
Message-ID: <201008291937.03205.marek.vasut@gmail.com> (raw)
In-Reply-To: <1283101872-6410-2-git-send-email-anarsoul@gmail.com>
Dne Ne 29. srpna 2010 19:11:10 Vasily Khoruzhick napsal(a):
> Disable some codec modules in standby mode, completely disable
> codec in off mode to save some power.
> Fix suspend/resume: mark mixer regs as dirty on resume to
> restore mixer values, otherwise driver produces no sound
> (master is muted by default).
>
> Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
> ---
> sound/soc/codecs/uda1380.c | 140
> +++++++++++++++++++++++++++++++------------- 1 files changed, 99
> insertions(+), 41 deletions(-)
>
> diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
> index 1a51c81..8646cb3 100644
> --- a/sound/soc/codecs/uda1380.c
> +++ b/sound/soc/codecs/uda1380.c
> @@ -39,6 +39,7 @@ struct uda1380_priv {
> u16 reg_cache[UDA1380_CACHEREGNUM];
> unsigned int dac_clk;
> struct work_struct work;
> + void *control_data;
It's already in codec->control_data, isn't it ?
> };
>
> /*
> @@ -129,7 +130,46 @@ static int uda1380_write(struct snd_soc_codec *codec,
> unsigned int reg, return -EIO;
> }
>
> -#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0)
> +static void uda1380_sync_cache(struct snd_soc_codec *codec)
> +{
> + int reg;
> + u8 data[3];
> + u16 *cache = codec->reg_cache;
> +
> + /* Sync reg_cache with the hardware */
> + for (reg = 0; reg < UDA1380_MVOL; reg++) {
> + data[0] = reg;
> + data[1] = (cache[reg] & 0xff00) >> 8;
> + data[2] = cache[reg] & 0x00ff;
> + if (codec->hw_write(codec->control_data, data, 3) != 3)
> + dev_err(codec->dev, "%s: write to reg 0x%x failed\n",
> + __func__, reg);
> + }
> +}
> +
> +static int uda1380_reset(struct snd_soc_codec *codec)
> +{
> + struct uda1380_platform_data *pdata = codec->dev->platform_data;
> +
> + if (pdata->gpio_reset != -EINVAL) {
> + gpio_set_value(pdata->gpio_reset, 1);
> + mdelay(1);
> + gpio_set_value(pdata->gpio_reset, 0);
> + } else {
> + u8 data[3];
> +
> + data[0] = UDA1380_RESET;
> + data[1] = 0;
> + data[2] = 0;
> +
> + if (codec->hw_write(codec->control_data, data, 3) != 3) {
> + dev_err(codec->dev, "%s: failed\n", __func__);
> + return -EIO;
> + }
> + }
> +
> + return 0;
> +}
>
> static void uda1380_flush_work(struct work_struct *work)
> {
> @@ -145,7 +185,6 @@ static void uda1380_flush_work(struct work_struct
> *work) uda1380_read_reg_cache(uda1380_codec, reg));
> clear_bit(bit, &uda1380_cache_dirty);
> }
> -
Remove
> }
>
> /* declarations of ALSA reg_elem_REAL controls */
> @@ -560,18 +599,40 @@ static int uda1380_set_bias_level(struct
> snd_soc_codec *codec, enum snd_soc_bias_level level)
> {
> int pm = uda1380_read_reg_cache(codec, UDA1380_PM);
> + struct uda1380_platform_data *pdata = codec->dev->platform_data;
> +
> + if (codec->bias_level == level)
> + return 0;
>
> switch (level) {
> case SND_SOC_BIAS_ON:
> case SND_SOC_BIAS_PREPARE:
> + /* ADC, DAC on */
> uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
> break;
> case SND_SOC_BIAS_STANDBY:
> - uda1380_write(codec, UDA1380_PM, R02_PON_BIAS);
> - break;
> - case SND_SOC_BIAS_OFF:
> + if (codec->bias_level == SND_SOC_BIAS_OFF) {
> + if (pdata->gpio_power != -EINVAL) {
> + gpio_set_value(pdata->gpio_power, 1);
> + uda1380_reset(codec);
> + }
> +
> + uda1380_sync_cache(codec);
> + }
> uda1380_write(codec, UDA1380_PM, 0x0);
Maybe some comment won't hurt here about what that 0x0 does.
> break;
> + case SND_SOC_BIAS_OFF:
if (pdata->gpio_power == -EINVAL)
break;
...code...
might help your alignment below.
> + if (pdata->gpio_power != -EINVAL) {
> + int reg;
> + gpio_set_value(pdata->gpio_power, 0);
> +
> + /* Mark mixer regs cache dirty to sync them with
> + * codec regs on power on.
> + */
> + for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM;
> + reg++)
> + set_bit(reg - 0x10, &uda1380_cache_dirty);
> + }
> }
> codec->bias_level = level;
> return 0;
> @@ -651,16 +712,6 @@ static int uda1380_suspend(struct snd_soc_codec
> *codec, pm_message_t state)
>
> static int uda1380_resume(struct snd_soc_codec *codec)
> {
> - int i;
> - u8 data[2];
> - u16 *cache = codec->reg_cache;
> -
> - /* Sync reg_cache with the hardware */
> - for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) {
> - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
> - data[1] = cache[i] & 0x00ff;
> - codec->hw_write(codec->control_data, data, 2);
> - }
> uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
> return 0;
> }
> @@ -671,29 +722,32 @@ static int uda1380_probe(struct snd_soc_codec *codec)
> struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
> int ret;
>
> + uda1380->codec = codec;
> +
> codec->hw_write = (hw_write_t)i2c_master_send;
> + codec->control_data = uda1380->control_data;
>
> - if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)
> + if (!pdata)
> return -EINVAL;
>
> - ret = gpio_request(pdata->gpio_power, "uda1380 power");
> - if (ret)
> - return ret;
> - ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
> - if (ret)
> - goto err_gpio;
> -
> - gpio_direction_output(pdata->gpio_power, 1);
> -
> - /* we may need to have the clock running here - pH5 */
> - gpio_direction_output(pdata->gpio_reset, 1);
> - udelay(5);
> - gpio_set_value(pdata->gpio_reset, 0);
if (gpio_is_valid(...gpio...)) {
}
> + if (pdata->gpio_reset != -EINVAL) {
> + ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
> + if (ret)
> + goto err_out;
> + gpio_direction_output(pdata->gpio_reset, 0);
Handle return value and dont depend on this setting the GPIO value, use
gpio_set_value() too please.
> + }
>
> - ret = uda1380_reset(codec);
> - if (ret < 0) {
> - dev_err(codec->dev, "Failed to issue reset\n");
> - goto err_reset;
> + if (pdata->gpio_power != -EINVAL) {
> + ret = gpio_request(pdata->gpio_power, "uda1380 power");
> + if (ret)
> + goto err_gpio;
> + gpio_direction_output(pdata->gpio_power, 0);
> + } else {
> + ret = uda1380_reset(codec);
> + if (ret) {
> + dev_err(codec->dev, "Failed to issue reset\n");
> + goto err_reset;
> + }
> }
Ditto.
>
> INIT_WORK(&uda1380->work, uda1380_flush_work);
> @@ -703,10 +757,11 @@ static int uda1380_probe(struct snd_soc_codec *codec)
> /* set clock input */
> switch (pdata->dac_clk) {
> case UDA1380_DAC_CLK_SYSCLK:
> - uda1380_write(codec, UDA1380_CLK, 0);
> + uda1380_write_reg_cache(codec, UDA1380_CLK, 0);
> break;
> case UDA1380_DAC_CLK_WSPLL:
> - uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK);
> + uda1380_write_reg_cache(codec, UDA1380_CLK,
> + R00_DAC_CLK);
> break;
> }
>
> @@ -717,10 +772,12 @@ static int uda1380_probe(struct snd_soc_codec *codec)
> return 0;
>
> err_reset:
> - gpio_set_value(pdata->gpio_power, 0);
> - gpio_free(pdata->gpio_reset);
> + if (pdata->gpio_reset != -EINVAL)
> + gpio_free(pdata->gpio_reset);
Ditto
> err_gpio:
> - gpio_free(pdata->gpio_power);
> + if (pdata->gpio_power != -EINVAL)
> + gpio_free(pdata->gpio_power);
Ditto
> +err_out:
> return ret;
> }
>
> @@ -731,7 +788,6 @@ static int uda1380_remove(struct snd_soc_codec *codec)
>
> uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
>
> - gpio_set_value(pdata->gpio_power, 0);
> gpio_free(pdata->gpio_reset);
> gpio_free(pdata->gpio_power);
>
> @@ -743,8 +799,8 @@ static struct snd_soc_codec_driver
> soc_codec_dev_uda1380 = { .remove = uda1380_remove,
> .suspend = uda1380_suspend,
> .resume = uda1380_resume,
> - .read = uda1380_read_reg_cache,
> - .write = uda1380_write,
> + .read = uda1380_read_reg_cache,
> + .write = uda1380_write,
> .set_bias_level = uda1380_set_bias_level,
> .reg_cache_size = ARRAY_SIZE(uda1380_reg),
> .reg_word_size = sizeof(u16),
> @@ -764,11 +820,13 @@ static __devinit int uda1380_i2c_probe(struct
> i2c_client *i2c, return -ENOMEM;
>
> i2c_set_clientdata(i2c, uda1380);
> + uda1380->control_data = i2c;
So is this needed ? Can't you access codec->control_data ?
>
> ret = snd_soc_register_codec(&i2c->dev,
> &soc_codec_dev_uda1380, uda1380_dai,
ARRAY_SIZE(uda1380_dai));
> if (ret < 0)
> kfree(uda1380);
> +
Remove
> return ret;
> }
Cheers
next prev parent reply other threads:[~2010-08-29 17:37 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-29 17:11 [PATCH v4 0/3] ASoC: Add iPAQ RX1950 support Vasily Khoruzhick
2010-08-29 17:11 ` [PATCH v4 1/3] ASoC: uda1380: make driver more powersave-friendly Vasily Khoruzhick
2010-08-29 17:37 ` Marek Vasut [this message]
2010-08-29 18:13 ` Vasily Khoruzhick
2010-08-29 19:11 ` Marek Vasut
2010-08-29 18:50 ` [PATCH v5 " Vasily Khoruzhick
2010-08-29 19:33 ` [PATCH v6 " Vasily Khoruzhick
2010-08-29 17:11 ` [PATCH v4 2/3] ASoC: Add HP iPAQ RX1950 support Vasily Khoruzhick
2010-08-29 17:39 ` Marek Vasut
2010-08-29 18:15 ` Vasily Khoruzhick
2010-08-29 18:53 ` [PATCH v5 " Vasily Khoruzhick
2010-08-29 19:16 ` Marek Vasut
2010-08-29 17:11 ` [PATCH v4 3/3] ARM: S3C24XX: I2S multi-component-related fixes Vasily Khoruzhick
2010-08-29 17:41 ` Marek Vasut
2010-08-29 17:47 ` Vasily Khoruzhick
2010-08-29 19:12 ` Marek Vasut
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201008291937.03205.marek.vasut@gmail.com \
--to=marek.vasut@gmail.com \
--cc=alsa-devel@alsa-project.org \
--cc=anarsoul@gmail.com \
--cc=ben-linux@fluff.org \
--cc=broonie@opensource.wolfsonmicro.com \
--cc=lrg@slimlogic.co.uk \
--cc=philipp.zabel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.