diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-04-29 06:28:52 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-04-29 06:28:52 -0400 |
commit | 85abf3ec5fa663c9638ef2d10d9623880a26458e (patch) | |
tree | ce1cc6166cd34b4a49299ccf4aefaac657a34fcf | |
parent | 49c4a4c5244d2c1a25ec1e01dbb4fba3813d237d (diff) | |
parent | 2bd1f73f4242ee19d8c610bcffe6e7a813451ce0 (diff) |
Merge branch 'topic/hda' into for-next
-rw-r--r-- | include/sound/hdaudio.h | 4 | ||||
-rw-r--r-- | sound/hda/hdac_device.c | 15 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 11 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_i915.c | 18 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 46 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 9 |
9 files changed, 99 insertions, 12 deletions
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 6a2e030c836c..b97c59eab7ab 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h | |||
@@ -74,6 +74,7 @@ struct hdac_device { | |||
74 | 74 | ||
75 | /* misc flags */ | 75 | /* misc flags */ |
76 | atomic_t in_pm; /* suspend/resume being performed */ | 76 | atomic_t in_pm; /* suspend/resume being performed */ |
77 | bool link_power_control:1; | ||
77 | 78 | ||
78 | /* sysfs */ | 79 | /* sysfs */ |
79 | struct hdac_widget_tree *widgets; | 80 | struct hdac_widget_tree *widgets; |
@@ -184,6 +185,8 @@ struct hdac_bus_ops { | |||
184 | /* get a response from the last command */ | 185 | /* get a response from the last command */ |
185 | int (*get_response)(struct hdac_bus *bus, unsigned int addr, | 186 | int (*get_response)(struct hdac_bus *bus, unsigned int addr, |
186 | unsigned int *res); | 187 | unsigned int *res); |
188 | /* control the link power */ | ||
189 | int (*link_power)(struct hdac_bus *bus, bool enable); | ||
187 | }; | 190 | }; |
188 | 191 | ||
189 | /* | 192 | /* |
@@ -311,6 +314,7 @@ static inline void snd_hdac_codec_link_down(struct hdac_device *codec) | |||
311 | int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); | 314 | int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); |
312 | int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, | 315 | int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, |
313 | unsigned int *res); | 316 | unsigned int *res); |
317 | int snd_hdac_link_power(struct hdac_device *codec, bool enable); | ||
314 | 318 | ||
315 | bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); | 319 | bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); |
316 | void snd_hdac_bus_stop_chip(struct hdac_bus *bus); | 320 | void snd_hdac_bus_stop_chip(struct hdac_bus *bus); |
diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 55c7d086b9dd..cdee7103f649 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c | |||
@@ -552,6 +552,21 @@ void snd_hdac_power_down_pm(struct hdac_device *codec) | |||
552 | EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); | 552 | EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); |
553 | #endif | 553 | #endif |
554 | 554 | ||
555 | /* | ||
556 | * Enable/disable the link power for a codec. | ||
557 | */ | ||
558 | int snd_hdac_link_power(struct hdac_device *codec, bool enable) | ||
559 | { | ||
560 | if (!codec->link_power_control) | ||
561 | return 0; | ||
562 | |||
563 | if (codec->bus->ops->link_power) | ||
564 | return codec->bus->ops->link_power(codec->bus, enable); | ||
565 | else | ||
566 | return -EINVAL; | ||
567 | } | ||
568 | EXPORT_SYMBOL_GPL(snd_hdac_link_power); | ||
569 | |||
555 | /* codec vendor labels */ | 570 | /* codec vendor labels */ |
556 | struct hda_vendor_id { | 571 | struct hda_vendor_id { |
557 | unsigned int id; | 572 | unsigned int id; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d65173a62ae9..54380ed03697 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -858,6 +858,7 @@ void snd_hda_codec_register(struct hda_codec *codec) | |||
858 | return; | 858 | return; |
859 | if (device_is_registered(hda_codec_dev(codec))) { | 859 | if (device_is_registered(hda_codec_dev(codec))) { |
860 | snd_hda_register_beep_device(codec); | 860 | snd_hda_register_beep_device(codec); |
861 | snd_hdac_link_power(&codec->core, true); | ||
861 | pm_runtime_enable(hda_codec_dev(codec)); | 862 | pm_runtime_enable(hda_codec_dev(codec)); |
862 | /* it was powered up in snd_hda_codec_new(), now all done */ | 863 | /* it was powered up in snd_hda_codec_new(), now all done */ |
863 | snd_hda_power_down(codec); | 864 | snd_hda_power_down(codec); |
@@ -884,6 +885,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device) | |||
884 | struct hda_codec *codec = device->device_data; | 885 | struct hda_codec *codec = device->device_data; |
885 | 886 | ||
886 | codec->in_freeing = 1; | 887 | codec->in_freeing = 1; |
888 | snd_hdac_link_power(&codec->core, false); | ||
887 | snd_hdac_device_unregister(&codec->core); | 889 | snd_hdac_device_unregister(&codec->core); |
888 | put_device(hda_codec_dev(codec)); | 890 | put_device(hda_codec_dev(codec)); |
889 | return 0; | 891 | return 0; |
@@ -3106,6 +3108,7 @@ static int hda_codec_runtime_suspend(struct device *dev) | |||
3106 | if (codec_has_clkstop(codec) && codec_has_epss(codec) && | 3108 | if (codec_has_clkstop(codec) && codec_has_epss(codec) && |
3107 | (state & AC_PWRST_CLK_STOP_OK)) | 3109 | (state & AC_PWRST_CLK_STOP_OK)) |
3108 | snd_hdac_codec_link_down(&codec->core); | 3110 | snd_hdac_codec_link_down(&codec->core); |
3111 | snd_hdac_link_power(&codec->core, false); | ||
3109 | return 0; | 3112 | return 0; |
3110 | } | 3113 | } |
3111 | 3114 | ||
@@ -3113,6 +3116,7 @@ static int hda_codec_runtime_resume(struct device *dev) | |||
3113 | { | 3116 | { |
3114 | struct hda_codec *codec = dev_to_hda_codec(dev); | 3117 | struct hda_codec *codec = dev_to_hda_codec(dev); |
3115 | 3118 | ||
3119 | snd_hdac_link_power(&codec->core, true); | ||
3116 | snd_hdac_codec_link_up(&codec->core); | 3120 | snd_hdac_codec_link_up(&codec->core); |
3117 | hda_call_codec_resume(codec); | 3121 | hda_call_codec_resume(codec); |
3118 | pm_runtime_mark_last_busy(dev); | 3122 | pm_runtime_mark_last_busy(dev); |
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index e0bb6231ff0c..120854ebd054 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -775,9 +775,20 @@ static int azx_get_response(struct hdac_bus *bus, unsigned int addr, | |||
775 | return azx_rirb_get_response(bus, addr, res); | 775 | return azx_rirb_get_response(bus, addr, res); |
776 | } | 776 | } |
777 | 777 | ||
778 | static int azx_link_power(struct hdac_bus *bus, bool enable) | ||
779 | { | ||
780 | struct azx *chip = bus_to_azx(bus); | ||
781 | |||
782 | if (chip->ops->link_power) | ||
783 | return chip->ops->link_power(chip, enable); | ||
784 | else | ||
785 | return -EINVAL; | ||
786 | } | ||
787 | |||
778 | static const struct hdac_bus_ops bus_core_ops = { | 788 | static const struct hdac_bus_ops bus_core_ops = { |
779 | .command = azx_send_cmd, | 789 | .command = azx_send_cmd, |
780 | .get_response = azx_get_response, | 790 | .get_response = azx_get_response, |
791 | .link_power = azx_link_power, | ||
781 | }; | 792 | }; |
782 | 793 | ||
783 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 794 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 3c6ebaf033a5..314105cd5061 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -89,6 +89,8 @@ struct hda_controller_ops { | |||
89 | struct vm_area_struct *area); | 89 | struct vm_area_struct *area); |
90 | /* Check if current position is acceptable */ | 90 | /* Check if current position is acceptable */ |
91 | int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); | 91 | int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); |
92 | /* enable/disable the link power */ | ||
93 | int (*link_power)(struct azx *chip, bool enable); | ||
92 | }; | 94 | }; |
93 | 95 | ||
94 | struct azx_pcm { | 96 | struct azx_pcm { |
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c index 3052a2b095f7..d9d079330e55 100644 --- a/sound/pci/hda/hda_i915.c +++ b/sound/pci/hda/hda_i915.c | |||
@@ -42,10 +42,15 @@ int hda_display_power(struct hda_intel *hda, bool enable) | |||
42 | 42 | ||
43 | dev_dbg(&hda->chip.pci->dev, "display power %s\n", | 43 | dev_dbg(&hda->chip.pci->dev, "display power %s\n", |
44 | enable ? "enable" : "disable"); | 44 | enable ? "enable" : "disable"); |
45 | if (enable) | 45 | |
46 | acomp->ops->get_power(acomp->dev); | 46 | if (enable) { |
47 | else | 47 | if (!hda->i915_power_refcount++) |
48 | acomp->ops->put_power(acomp->dev); | 48 | acomp->ops->get_power(acomp->dev); |
49 | } else { | ||
50 | WARN_ON(!hda->i915_power_refcount); | ||
51 | if (!--hda->i915_power_refcount) | ||
52 | acomp->ops->put_power(acomp->dev); | ||
53 | } | ||
49 | 54 | ||
50 | return 0; | 55 | return 0; |
51 | } | 56 | } |
@@ -189,6 +194,11 @@ out_err: | |||
189 | int hda_i915_exit(struct hda_intel *hda) | 194 | int hda_i915_exit(struct hda_intel *hda) |
190 | { | 195 | { |
191 | struct device *dev = &hda->chip.pci->dev; | 196 | struct device *dev = &hda->chip.pci->dev; |
197 | struct i915_audio_component *acomp = &hda->audio_component; | ||
198 | |||
199 | WARN_ON(hda->i915_power_refcount); | ||
200 | if (hda->i915_power_refcount > 0 && acomp->ops) | ||
201 | acomp->ops->put_power(acomp->dev); | ||
192 | 202 | ||
193 | component_master_del(dev, &hda_component_master_ops); | 203 | component_master_del(dev, &hda_component_master_ops); |
194 | 204 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c212f13e1721..5aa5cfa517aa 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -543,6 +543,14 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) | |||
543 | return 0; | 543 | return 0; |
544 | } | 544 | } |
545 | 545 | ||
546 | /* Enable/disable i915 display power for the link */ | ||
547 | static int azx_intel_link_power(struct azx *chip, bool enable) | ||
548 | { | ||
549 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | ||
550 | |||
551 | return hda_display_power(hda, enable); | ||
552 | } | ||
553 | |||
546 | /* | 554 | /* |
547 | * Check whether the current DMA position is acceptable for updating | 555 | * Check whether the current DMA position is acceptable for updating |
548 | * periods. Returns non-zero if it's OK. | 556 | * periods. Returns non-zero if it's OK. |
@@ -809,7 +817,8 @@ static int azx_suspend(struct device *dev) | |||
809 | 817 | ||
810 | if (chip->msi) | 818 | if (chip->msi) |
811 | pci_disable_msi(chip->pci); | 819 | pci_disable_msi(chip->pci); |
812 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 820 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
821 | && hda->need_i915_power) | ||
813 | hda_display_power(hda, false); | 822 | hda_display_power(hda, false); |
814 | return 0; | 823 | return 0; |
815 | } | 824 | } |
@@ -829,7 +838,8 @@ static int azx_resume(struct device *dev) | |||
829 | if (chip->disabled || hda->init_failed) | 838 | if (chip->disabled || hda->init_failed) |
830 | return 0; | 839 | return 0; |
831 | 840 | ||
832 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 841 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
842 | && hda->need_i915_power) { | ||
833 | hda_display_power(hda, true); | 843 | hda_display_power(hda, true); |
834 | haswell_set_bclk(hda); | 844 | haswell_set_bclk(hda); |
835 | } | 845 | } |
@@ -872,7 +882,8 @@ static int azx_runtime_suspend(struct device *dev) | |||
872 | azx_stop_chip(chip); | 882 | azx_stop_chip(chip); |
873 | azx_enter_link_reset(chip); | 883 | azx_enter_link_reset(chip); |
874 | azx_clear_irq_pending(chip); | 884 | azx_clear_irq_pending(chip); |
875 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) | 885 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
886 | && hda->need_i915_power) | ||
876 | hda_display_power(hda, false); | 887 | hda_display_power(hda, false); |
877 | 888 | ||
878 | return 0; | 889 | return 0; |
@@ -897,7 +908,8 @@ static int azx_runtime_resume(struct device *dev) | |||
897 | if (!azx_has_pm_runtime(chip)) | 908 | if (!azx_has_pm_runtime(chip)) |
898 | return 0; | 909 | return 0; |
899 | 910 | ||
900 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 911 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL |
912 | && hda->need_i915_power) { | ||
901 | hda_display_power(hda, true); | 913 | hda_display_power(hda, true); |
902 | haswell_set_bclk(hda); | 914 | haswell_set_bclk(hda); |
903 | } | 915 | } |
@@ -1118,7 +1130,8 @@ static int azx_free(struct azx *chip) | |||
1118 | release_firmware(chip->fw); | 1130 | release_firmware(chip->fw); |
1119 | #endif | 1131 | #endif |
1120 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 1132 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1121 | hda_display_power(hda, false); | 1133 | if (hda->need_i915_power) |
1134 | hda_display_power(hda, false); | ||
1122 | hda_i915_exit(hda); | 1135 | hda_i915_exit(hda); |
1123 | } | 1136 | } |
1124 | kfree(hda); | 1137 | kfree(hda); |
@@ -1789,6 +1802,7 @@ static const struct hda_controller_ops pci_hda_ops = { | |||
1789 | .substream_free_pages = substream_free_pages, | 1802 | .substream_free_pages = substream_free_pages, |
1790 | .pcm_mmap_prepare = pcm_mmap_prepare, | 1803 | .pcm_mmap_prepare = pcm_mmap_prepare, |
1791 | .position_check = azx_position_check, | 1804 | .position_check = azx_position_check, |
1805 | .link_power = azx_intel_link_power, | ||
1792 | }; | 1806 | }; |
1793 | 1807 | ||
1794 | static int azx_probe(struct pci_dev *pci, | 1808 | static int azx_probe(struct pci_dev *pci, |
@@ -1882,17 +1896,28 @@ static int azx_probe_continue(struct azx *chip) | |||
1882 | int err; | 1896 | int err; |
1883 | 1897 | ||
1884 | hda->probe_continued = 1; | 1898 | hda->probe_continued = 1; |
1885 | /* Request power well for Haswell HDA controller and codec */ | 1899 | |
1900 | /* Request display power well for the HDA controller or codec. For | ||
1901 | * Haswell/Broadwell, both the display HDA controller and codec need | ||
1902 | * this power. For other platforms, like Baytrail/Braswell, only the | ||
1903 | * display codec needs the power and it can be released after probe. | ||
1904 | */ | ||
1886 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { | 1905 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { |
1906 | /* Baytral/Braswell controllers don't need this power */ | ||
1907 | if (pci->device != 0x0f04 && pci->device != 0x2284) | ||
1908 | hda->need_i915_power = 1; | ||
1909 | |||
1910 | |||
1887 | #ifdef CONFIG_SND_HDA_I915 | 1911 | #ifdef CONFIG_SND_HDA_I915 |
1888 | err = hda_i915_init(hda); | 1912 | err = hda_i915_init(hda); |
1889 | if (err < 0) | 1913 | if (err < 0) |
1890 | goto out_free; | 1914 | goto i915_power_fail; |
1915 | |||
1891 | err = hda_display_power(hda, true); | 1916 | err = hda_display_power(hda, true); |
1892 | if (err < 0) { | 1917 | if (err < 0) { |
1893 | dev_err(chip->card->dev, | 1918 | dev_err(chip->card->dev, |
1894 | "Cannot turn on display power on i915\n"); | 1919 | "Cannot turn on display power on i915\n"); |
1895 | goto out_free; | 1920 | goto i915_power_fail; |
1896 | } | 1921 | } |
1897 | #endif | 1922 | #endif |
1898 | } | 1923 | } |
@@ -1939,6 +1964,11 @@ static int azx_probe_continue(struct azx *chip) | |||
1939 | pm_runtime_put_noidle(&pci->dev); | 1964 | pm_runtime_put_noidle(&pci->dev); |
1940 | 1965 | ||
1941 | out_free: | 1966 | out_free: |
1967 | if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL | ||
1968 | && !hda->need_i915_power) | ||
1969 | hda_display_power(hda, false); | ||
1970 | |||
1971 | i915_power_fail: | ||
1942 | if (err < 0) | 1972 | if (err < 0) |
1943 | hda->init_failed = 1; | 1973 | hda->init_failed = 1; |
1944 | complete_all(&hda->probe_wait); | 1974 | complete_all(&hda->probe_wait); |
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h index 206989878bc6..505f987eb4a2 100644 --- a/sound/pci/hda/hda_intel.h +++ b/sound/pci/hda/hda_intel.h | |||
@@ -45,7 +45,9 @@ struct hda_intel { | |||
45 | struct dev_pm_domain hdmi_pm_domain; | 45 | struct dev_pm_domain hdmi_pm_domain; |
46 | 46 | ||
47 | /* i915 component interface */ | 47 | /* i915 component interface */ |
48 | bool need_i915_power:1; /* the hda controller needs i915 power */ | ||
48 | struct i915_audio_component audio_component; | 49 | struct i915_audio_component audio_component; |
50 | int i915_power_refcount; | ||
49 | }; | 51 | }; |
50 | 52 | ||
51 | #ifdef CONFIG_SND_HDA_I915 | 53 | #ifdef CONFIG_SND_HDA_I915 |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index d925742624ee..e8d847819d71 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -2335,6 +2335,15 @@ static int patch_generic_hdmi(struct hda_codec *codec) | |||
2335 | intel_haswell_fixup_enable_dp12(codec); | 2335 | intel_haswell_fixup_enable_dp12(codec); |
2336 | } | 2336 | } |
2337 | 2337 | ||
2338 | /* For Valleyview/Cherryview, only the display codec is in the display | ||
2339 | * power well and can use link_power ops to request/release the power. | ||
2340 | * For Haswell/Broadwell, the controller is also in the power well and | ||
2341 | * can cover the codec power request, and so need not set this flag. | ||
2342 | * For previous platforms, there is no such power well feature. | ||
2343 | */ | ||
2344 | if (is_valleyview_plus(codec)) | ||
2345 | codec->core.link_power_control = 1; | ||
2346 | |||
2338 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) | 2347 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) |
2339 | codec->depop_delay = 0; | 2348 | codec->depop_delay = 0; |
2340 | 2349 | ||