[alsa-devel] [PATCH] hda: Advanced power management for codecs.
Takashi Iwai
tiwai at suse.de
Mon Jan 7 18:10:38 CET 2008
At Mon, 07 Jan 2008 11:44:08 -0500,
Matthew Ranostay wrote:
>
> [1 <text/plain; ISO-8859-1 (7bit)>]
> Added support for advanced power management features in new IDT codecs.
> Inactive ADCs and DACs are changed to D3 mode when not in playback or
> capture, also inactive line-out/headphone ports are disabled when jack
> detect does not sense a connection.
Thanks. This is an interesting patch.
> ---
> Signed-off-by: Matthew Ranostay <mranostay at embeddedalley.com>
> [2 stac92hd7xxx_power_save.patch <text/plain (7bit)>]
> diff -r 5b03c0176aa5 pci/hda/patch_sigmatel.c
> --- a/pci/hda/patch_sigmatel.c Mon Jan 07 13:33:45 2008 +0100
> +++ b/pci/hda/patch_sigmatel.c Mon Jan 07 11:22:56 2008 -0500
> @@ -160,6 +160,7 @@ struct sigmatel_spec {
>
> /* i/o switches */
> unsigned int io_switch[2];
> + unsigned int io_state[2];
> unsigned int clfe_swap;
> unsigned int aloopback;
>
> @@ -438,6 +439,52 @@ static int stac92xx_aloopback_put(struct
> kcontrol->private_value >> 16, dac_mode);
>
> return 1;
> +}
> +
> +static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
> +{
> + int i;
> +
> + for (i = 0; i < spec->multiout.num_dacs; i++) {
> + if (spec->multiout.dac_nids[i] == nid)
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> +static int stac92xx_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
> + struct sigmatel_spec *spec = codec->spec;
> + hda_nid_t nid = kcontrol->private_value & 0xffff;
> + int idx = (kcontrol->private_value >> 19) & 0xf;
> + int chs = (kcontrol->private_value >> 16) & 0x3;
> + long *valp = ucontrol->value.integer.value;
> + unsigned int wid_caps, val, change;
> +
> + change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
> +#ifdef CONFIG_SND_HDA_POWER_SAVE
> + if (!is_in_dac_nids(spec, nid))
> + nid = spec->adc_nids[idx];
> +
> + val = *valp++;
> + wid_caps = get_wcaps(codec, nid);
> + if (wid_caps & AC_WCAP_POWER) {
> + if (chs == 3)
> + val |= *valp;
> + else { /* Center/LFE mixers workaround */
> + spec->io_state[--chs] = val;
> + val |= spec->io_state[chs ? 0 : 1];
> + }
> +
> + /* set to power state D3 mode if DAC/ADC isn't being used */
> + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
> + val ? 0: AC_PWRST_D3);
> + }
> +#endif
> + return change;
This stuff should go rather to snd_hda_mixer_amp_switch_put(). It's
not specific to STAC codecs.
The #ifdef doesn't suffice, BTW. The power-saving is a dynamic switch
(via module parameter and/or sysfs), so you need to check whether
power-saving mode is active nor not. Also, these calls should be
within the snd_hda_power_up/down() block.
> @@ -2830,7 +2883,12 @@ static void stac92xx_hp_detect(struct hd
> for (i = 0; i < cfg->speaker_outs; i++)
> stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
> AC_PINCTL_OUT_EN);
> - }
> + for (i = 0; i < cfg->hp_outs; i++)
> + pwr_state |= 1 << (cfg->hp_pins[i] - 0xa);
> + }
> +
> + /* power down unused ports */
> + snd_hda_codec_write(codec, codec->afg, 0, 0x7ec, pwr_state);
Is this verb available on every STAC codec? I took a look at some
specs but they don't show this verb at all.
Takashi
More information about the Alsa-devel
mailing list