aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_codec.c16
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_hwdep.c38
-rw-r--r--sound/pci/hda/hda_local.h9
4 files changed, 67 insertions, 0 deletions
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)
515 struct hda_codec *codec; 515 struct hda_codec *codec;
516 list_for_each_entry(codec, &bus->codec_list, list) { 516 list_for_each_entry(codec, &bus->codec_list, list) {
517 snd_hda_hwdep_add_sysfs(codec); 517 snd_hda_hwdep_add_sysfs(codec);
518 snd_hda_hwdep_add_power_sysfs(codec);
518 } 519 }
519 return 0; 520 return 0;
520} 521}
@@ -2452,9 +2453,11 @@ static void hda_call_codec_suspend(struct hda_codec *codec)
2452 codec->afg ? codec->afg : codec->mfg, 2453 codec->afg ? codec->afg : codec->mfg,
2453 AC_PWRST_D3); 2454 AC_PWRST_D3);
2454#ifdef CONFIG_SND_HDA_POWER_SAVE 2455#ifdef CONFIG_SND_HDA_POWER_SAVE
2456 snd_hda_update_power_acct(codec);
2455 cancel_delayed_work(&codec->power_work); 2457 cancel_delayed_work(&codec->power_work);
2456 codec->power_on = 0; 2458 codec->power_on = 0;
2457 codec->power_transition = 0; 2459 codec->power_transition = 0;
2460 codec->power_jiffies = jiffies;
2458#endif 2461#endif
2459} 2462}
2460 2463
@@ -3191,6 +3194,17 @@ static void hda_keep_power_on(struct hda_codec *codec)
3191{ 3194{
3192 codec->power_count++; 3195 codec->power_count++;
3193 codec->power_on = 1; 3196 codec->power_on = 1;
3197 codec->power_jiffies = jiffies;
3198}
3199
3200void snd_hda_update_power_acct(struct hda_codec *codec)
3201{
3202 unsigned long delta = jiffies - codec->power_jiffies;
3203 if (codec->power_on)
3204 codec->power_on_acct += delta;
3205 else
3206 codec->power_off_acct += delta;
3207 codec->power_jiffies += delta;
3194} 3208}
3195 3209
3196void snd_hda_power_up(struct hda_codec *codec) 3210void snd_hda_power_up(struct hda_codec *codec)
@@ -3201,7 +3215,9 @@ void snd_hda_power_up(struct hda_codec *codec)
3201 if (codec->power_on || codec->power_transition) 3215 if (codec->power_on || codec->power_transition)
3202 return; 3216 return;
3203 3217
3218 snd_hda_update_power_acct(codec);
3204 codec->power_on = 1; 3219 codec->power_on = 1;
3220 codec->power_jiffies = jiffies;
3205 if (bus->ops.pm_notify) 3221 if (bus->ops.pm_notify)
3206 bus->ops.pm_notify(bus); 3222 bus->ops.pm_notify(bus);
3207 hda_call_codec_resume(codec); 3223 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 {
812 unsigned int power_transition :1; /* power-state in transition */ 812 unsigned int power_transition :1; /* power-state in transition */
813 int power_count; /* current (global) power refcount */ 813 int power_count; /* current (global) power refcount */
814 struct delayed_work power_work; /* delayed task for powerdown */ 814 struct delayed_work power_work; /* delayed task for powerdown */
815 unsigned long power_on_acct;
816 unsigned long power_off_acct;
817 unsigned long power_jiffies;
815#endif 818#endif
816 819
817 /* codec-specific additional proc output */ 820 /* codec-specific additional proc output */
@@ -936,6 +939,7 @@ const char *snd_hda_get_jack_location(u32 cfg);
936void snd_hda_power_up(struct hda_codec *codec); 939void snd_hda_power_up(struct hda_codec *codec);
937void snd_hda_power_down(struct hda_codec *codec); 940void snd_hda_power_down(struct hda_codec *codec);
938#define snd_hda_codec_needs_resume(codec) codec->power_count 941#define snd_hda_codec_needs_resume(codec) codec->power_count
942void snd_hda_update_power_acct(struct hda_codec *codec);
939#else 943#else
940static inline void snd_hda_power_up(struct hda_codec *codec) {} 944static inline void snd_hda_power_up(struct hda_codec *codec) {}
941static inline void snd_hda_power_down(struct hda_codec *codec) {} 945static 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)
154 return 0; 154 return 0;
155} 155}
156 156
157#ifdef CONFIG_SND_HDA_POWER_SAVE
158static ssize_t power_on_acct_show(struct device *dev,
159 struct device_attribute *attr,
160 char *buf)
161{
162 struct snd_hwdep *hwdep = dev_get_drvdata(dev);
163 struct hda_codec *codec = hwdep->private_data;
164 snd_hda_update_power_acct(codec);
165 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct));
166}
167
168static ssize_t power_off_acct_show(struct device *dev,
169 struct device_attribute *attr,
170 char *buf)
171{
172 struct snd_hwdep *hwdep = dev_get_drvdata(dev);
173 struct hda_codec *codec = hwdep->private_data;
174 snd_hda_update_power_acct(codec);
175 return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct));
176}
177
178static struct device_attribute power_attrs[] = {
179 __ATTR_RO(power_on_acct),
180 __ATTR_RO(power_off_acct),
181};
182
183int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
184{
185 struct snd_hwdep *hwdep = codec->hwdep;
186 int i;
187
188 for (i = 0; i < ARRAY_SIZE(power_attrs); i++)
189 snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
190 hwdep->device, &power_attrs[i]);
191 return 0;
192}
193#endif /* CONFIG_SND_HDA_POWER_SAVE */
194
157#ifdef CONFIG_SND_HDA_RECONFIG 195#ifdef CONFIG_SND_HDA_RECONFIG
158 196
159/* 197/*
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);
437static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } 437static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
438#endif 438#endif
439 439
440#ifdef CONFIG_SND_HDA_POWER_SAVE
441int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec);
442#else
443static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec)
444{
445 return 0;
446}
447#endif
448
440#ifdef CONFIG_SND_HDA_RECONFIG 449#ifdef CONFIG_SND_HDA_RECONFIG
441int snd_hda_hwdep_add_sysfs(struct hda_codec *codec); 450int snd_hda_hwdep_add_sysfs(struct hda_codec *codec);
442#else 451#else