diff options
Diffstat (limited to 'sound/soc/codecs/hdac_hdmi.c')
| -rw-r--r-- | sound/soc/codecs/hdac_hdmi.c | 116 |
1 files changed, 13 insertions, 103 deletions
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 3ab2949c1dfa..b19d7a3e7a2c 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c | |||
| @@ -1890,51 +1890,31 @@ static void hdmi_codec_remove(struct snd_soc_component *component) | |||
| 1890 | pm_runtime_disable(&hdev->dev); | 1890 | pm_runtime_disable(&hdev->dev); |
| 1891 | } | 1891 | } |
| 1892 | 1892 | ||
| 1893 | #ifdef CONFIG_PM | 1893 | #ifdef CONFIG_PM_SLEEP |
| 1894 | static int hdmi_codec_prepare(struct device *dev) | 1894 | static int hdmi_codec_resume(struct device *dev) |
| 1895 | { | ||
| 1896 | struct hdac_device *hdev = dev_to_hdac_dev(dev); | ||
| 1897 | |||
| 1898 | pm_runtime_get_sync(&hdev->dev); | ||
| 1899 | |||
| 1900 | /* | ||
| 1901 | * Power down afg. | ||
| 1902 | * codec_read is preferred over codec_write to set the power state. | ||
| 1903 | * This way verb is send to set the power state and response | ||
| 1904 | * is received. So setting power state is ensured without using loop | ||
| 1905 | * to read the state. | ||
| 1906 | */ | ||
| 1907 | snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE, | ||
| 1908 | AC_PWRST_D3); | ||
| 1909 | |||
| 1910 | return 0; | ||
| 1911 | } | ||
| 1912 | |||
| 1913 | static void hdmi_codec_complete(struct device *dev) | ||
| 1914 | { | 1895 | { |
| 1915 | struct hdac_device *hdev = dev_to_hdac_dev(dev); | 1896 | struct hdac_device *hdev = dev_to_hdac_dev(dev); |
| 1916 | struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); | 1897 | struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); |
| 1898 | int ret; | ||
| 1917 | 1899 | ||
| 1918 | /* Power up afg */ | 1900 | ret = pm_runtime_force_resume(dev); |
| 1919 | snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE, | 1901 | if (ret < 0) |
| 1920 | AC_PWRST_D0); | 1902 | return ret; |
| 1921 | |||
| 1922 | hdac_hdmi_skl_enable_all_pins(hdev); | ||
| 1923 | hdac_hdmi_skl_enable_dp12(hdev); | ||
| 1924 | |||
| 1925 | /* | 1903 | /* |
| 1926 | * As the ELD notify callback request is not entertained while the | 1904 | * As the ELD notify callback request is not entertained while the |
| 1927 | * device is in suspend state. Need to manually check detection of | 1905 | * device is in suspend state. Need to manually check detection of |
| 1928 | * all pins here. pin capablity change is not support, so use the | 1906 | * all pins here. pin capablity change is not support, so use the |
| 1929 | * already set pin caps. | 1907 | * already set pin caps. |
| 1908 | * | ||
| 1909 | * NOTE: this is safe to call even if the codec doesn't actually resume. | ||
| 1910 | * The pin check involves only with DRM audio component hooks, so it | ||
| 1911 | * works even if the HD-audio side is still dreaming peacefully. | ||
| 1930 | */ | 1912 | */ |
| 1931 | hdac_hdmi_present_sense_all_pins(hdev, hdmi, false); | 1913 | hdac_hdmi_present_sense_all_pins(hdev, hdmi, false); |
| 1932 | 1914 | return 0; | |
| 1933 | pm_runtime_put_sync(&hdev->dev); | ||
| 1934 | } | 1915 | } |
| 1935 | #else | 1916 | #else |
| 1936 | #define hdmi_codec_prepare NULL | 1917 | #define hdmi_codec_resume NULL |
| 1937 | #define hdmi_codec_complete NULL | ||
| 1938 | #endif | 1918 | #endif |
| 1939 | 1919 | ||
| 1940 | static const struct snd_soc_component_driver hdmi_hda_codec = { | 1920 | static const struct snd_soc_component_driver hdmi_hda_codec = { |
| @@ -2135,75 +2115,6 @@ static int hdac_hdmi_dev_remove(struct hdac_device *hdev) | |||
| 2135 | } | 2115 | } |
| 2136 | 2116 | ||
| 2137 | #ifdef CONFIG_PM | 2117 | #ifdef CONFIG_PM |
| 2138 | /* | ||
| 2139 | * Power management sequences | ||
| 2140 | * ========================== | ||
| 2141 | * | ||
| 2142 | * The following explains the PM handling of HDAC HDMI with its parent | ||
| 2143 | * device SKL and display power usage | ||
| 2144 | * | ||
| 2145 | * Probe | ||
| 2146 | * ----- | ||
| 2147 | * In SKL probe, | ||
| 2148 | * 1. skl_probe_work() powers up the display (refcount++ -> 1) | ||
| 2149 | * 2. enumerates the codecs on the link | ||
| 2150 | * 3. powers down the display (refcount-- -> 0) | ||
| 2151 | * | ||
| 2152 | * In HDAC HDMI probe, | ||
| 2153 | * 1. hdac_hdmi_dev_probe() powers up the display (refcount++ -> 1) | ||
| 2154 | * 2. probe the codec | ||
| 2155 | * 3. put the HDAC HDMI device to runtime suspend | ||
| 2156 | * 4. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) | ||
| 2157 | * | ||
| 2158 | * Once children are runtime suspended, SKL device also goes to runtime | ||
| 2159 | * suspend | ||
| 2160 | * | ||
| 2161 | * HDMI Playback | ||
| 2162 | * ------------- | ||
| 2163 | * Open HDMI device, | ||
| 2164 | * 1. skl_runtime_resume() invoked | ||
| 2165 | * 2. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1) | ||
| 2166 | * | ||
| 2167 | * Close HDMI device, | ||
| 2168 | * 1. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) | ||
| 2169 | * 2. skl_runtime_suspend() invoked | ||
| 2170 | * | ||
| 2171 | * S0/S3 Cycle with playback in progress | ||
| 2172 | * ------------------------------------- | ||
| 2173 | * When the device is opened for playback, the device is runtime active | ||
| 2174 | * already and the display refcount is 1 as explained above. | ||
| 2175 | * | ||
| 2176 | * Entering to S3, | ||
| 2177 | * 1. hdmi_codec_prepare() invoke the runtime resume of codec which just | ||
| 2178 | * increments the PM runtime usage count of the codec since the device | ||
| 2179 | * is in use already | ||
| 2180 | * 2. skl_suspend() powers down the display (refcount-- -> 0) | ||
| 2181 | * | ||
| 2182 | * Wakeup from S3, | ||
| 2183 | * 1. skl_resume() powers up the display (refcount++ -> 1) | ||
| 2184 | * 2. hdmi_codec_complete() invokes the runtime suspend of codec which just | ||
| 2185 | * decrements the PM runtime usage count of the codec since the device | ||
| 2186 | * is in use already | ||
| 2187 | * | ||
| 2188 | * Once playback is stopped, the display refcount is set to 0 as explained | ||
| 2189 | * above in the HDMI playback sequence. The PM handlings are designed in | ||
| 2190 | * such way that to balance the refcount of display power when the codec | ||
| 2191 | * device put to S3 while playback is going on. | ||
| 2192 | * | ||
| 2193 | * S0/S3 Cycle without playback in progress | ||
| 2194 | * ---------------------------------------- | ||
| 2195 | * Entering to S3, | ||
| 2196 | * 1. hdmi_codec_prepare() invoke the runtime resume of codec | ||
| 2197 | * 2. skl_runtime_resume() invoked | ||
| 2198 | * 3. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1) | ||
| 2199 | * 4. skl_suspend() powers down the display (refcount-- -> 0) | ||
| 2200 | * | ||
| 2201 | * Wakeup from S3, | ||
| 2202 | * 1. skl_resume() powers up the display (refcount++ -> 1) | ||
| 2203 | * 2. hdmi_codec_complete() invokes the runtime suspend of codec | ||
| 2204 | * 3. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0) | ||
| 2205 | * 4. skl_runtime_suspend() invoked | ||
| 2206 | */ | ||
| 2207 | static int hdac_hdmi_runtime_suspend(struct device *dev) | 2118 | static int hdac_hdmi_runtime_suspend(struct device *dev) |
| 2208 | { | 2119 | { |
| 2209 | struct hdac_device *hdev = dev_to_hdac_dev(dev); | 2120 | struct hdac_device *hdev = dev_to_hdac_dev(dev); |
| @@ -2277,8 +2188,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev) | |||
| 2277 | 2188 | ||
| 2278 | static const struct dev_pm_ops hdac_hdmi_pm = { | 2189 | static const struct dev_pm_ops hdac_hdmi_pm = { |
| 2279 | SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) | 2190 | SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL) |
| 2280 | .prepare = hdmi_codec_prepare, | 2191 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume) |
| 2281 | .complete = hdmi_codec_complete, | ||
| 2282 | }; | 2192 | }; |
| 2283 | 2193 | ||
| 2284 | static const struct hda_device_id hdmi_list[] = { | 2194 | static const struct hda_device_id hdmi_list[] = { |
