From a2f6309e8392e2c14c04594fca8b4876c8c9bc36 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 11 Nov 2009 09:34:25 +0100 Subject: [PATCH] ALSA: hda - Add power on/off counter Added the power on/off counter and expose via sysfs files. The sysfs files, power_on_acct and power_off_acct, are created under each codec hwdep sysfs directory (e.g. /sys/class/sound/hwC0D0). The files show the msec length of the codec power-on and power-off, respectively. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 16 ++++++++++++++++ sound/pci/hda/hda_codec.h | 4 ++++ sound/pci/hda/hda_hwdep.c | 38 ++++++++++++++++++++++++++++++++++++++ sound/pci/hda/hda_local.h | 9 +++++++++ 4 files changed, 67 insertions(+) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 2b787b013e93..444d9039c1ac 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -515,6 +515,7 @@ static int snd_hda_bus_dev_register(struct snd_device *device) struct hda_codec *codec; list_for_each_entry(codec, &bus->codec_list, list) { snd_hda_hwdep_add_sysfs(codec); + snd_hda_hwdep_add_power_sysfs(codec); } return 0; } @@ -2452,9 +2453,11 @@ static void hda_call_codec_suspend(struct hda_codec *codec) codec->afg ? codec->afg : codec->mfg, AC_PWRST_D3); #ifdef CONFIG_SND_HDA_POWER_SAVE + snd_hda_update_power_acct(codec); cancel_delayed_work(&codec->power_work); codec->power_on = 0; codec->power_transition = 0; + codec->power_jiffies = jiffies; #endif } @@ -3191,6 +3194,17 @@ static void hda_keep_power_on(struct hda_codec *codec) { codec->power_count++; codec->power_on = 1; + codec->power_jiffies = jiffies; +} + +void snd_hda_update_power_acct(struct hda_codec *codec) +{ + unsigned long delta = jiffies - codec->power_jiffies; + if (codec->power_on) + codec->power_on_acct += delta; + else + codec->power_off_acct += delta; + codec->power_jiffies += delta; } void snd_hda_power_up(struct hda_codec *codec) @@ -3201,7 +3215,9 @@ void snd_hda_power_up(struct hda_codec *codec) if (codec->power_on || codec->power_transition) return; + snd_hda_update_power_acct(codec); codec->power_on = 1; + codec->power_jiffies = jiffies; if (bus->ops.pm_notify) bus->ops.pm_notify(bus); hda_call_codec_resume(codec); diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index cbf199a98ab2..b16678cade18 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -812,6 +812,9 @@ struct hda_codec { unsigned int power_transition :1; /* power-state in transition */ int power_count; /* current (global) power refcount */ struct delayed_work power_work; /* delayed task for powerdown */ + unsigned long power_on_acct; + unsigned long power_off_acct; + unsigned long power_jiffies; #endif /* codec-specific additional proc output */ @@ -936,6 +939,7 @@ const char *snd_hda_get_jack_location(u32 cfg); void snd_hda_power_up(struct hda_codec *codec); void snd_hda_power_down(struct hda_codec *codec); #define snd_hda_codec_needs_resume(codec) codec->power_count +void snd_hda_update_power_acct(struct hda_codec *codec); #else static inline void snd_hda_power_up(struct hda_codec *codec) {} static inline void snd_hda_power_down(struct hda_codec *codec) {} diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index cc24e6721d74..d24328661c6a 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c @@ -154,6 +154,44 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) return 0; } +#ifdef CONFIG_SND_HDA_POWER_SAVE +static ssize_t power_on_acct_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct snd_hwdep *hwdep = dev_get_drvdata(dev); + struct hda_codec *codec = hwdep->private_data; + snd_hda_update_power_acct(codec); + return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct)); +} + +static ssize_t power_off_acct_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct snd_hwdep *hwdep = dev_get_drvdata(dev); + struct hda_codec *codec = hwdep->private_data; + snd_hda_update_power_acct(codec); + return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct)); +} + +static struct device_attribute power_attrs[] = { + __ATTR_RO(power_on_acct), + __ATTR_RO(power_off_acct), +}; + +int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) +{ + struct snd_hwdep *hwdep = codec->hwdep; + int i; + + for (i = 0; i < ARRAY_SIZE(power_attrs); i++) + snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, + hwdep->device, &power_attrs[i]); + return 0; +} +#endif /* CONFIG_SND_HDA_POWER_SAVE */ + #ifdef CONFIG_SND_HDA_RECONFIG /* diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 461e0c15c77a..015fbac914b3 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -437,6 +437,15 @@ int snd_hda_create_hwdep(struct hda_codec *codec); static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } #endif +#ifdef CONFIG_SND_HDA_POWER_SAVE +int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec); +#else +static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) +{ + return 0; +} +#endif + #ifdef CONFIG_SND_HDA_RECONFIG int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); #else -- 2.34.1