diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2017-09-14 08:01:01 -0400 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2017-09-19 06:50:44 -0400 |
commit | 6e8edf8a7d8d98e1734ff41e5c69439419319402 (patch) | |
tree | 7834cee31827d42a0619003666907ca1c2878406 | |
parent | 5baf6bb0fd2388742a0846cc7bcacee6dec78235 (diff) |
drm/exynos: Fix suspend/resume support
Commit 7d902c05b480 ("drm: Nuke drm_atomic_helper_connector_dpms")
removed drm_atomic_helper_connector_dpms() helper saying that it was a dead
code. It was however indirectly used by Exynos DRM driver for implementing
suspend/resume support. To fix this regression (after that patch Exynos DRM
suspend/resume functions became no-ops and hardware fails to suspend),
this patch rewrites them with drm_atomic_helper_suspend/resume() helpers.
Fixes: 7d902c05b480 ("drm: Nuke drm_atomic_helper_connector_dpms")
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_fbdev.h | 10 |
4 files changed, 43 insertions, 28 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 7f3cfc5dd320..e651a58c18cf 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
@@ -168,25 +168,19 @@ static struct drm_driver exynos_drm_driver = { | |||
168 | static int exynos_drm_suspend(struct device *dev) | 168 | static int exynos_drm_suspend(struct device *dev) |
169 | { | 169 | { |
170 | struct drm_device *drm_dev = dev_get_drvdata(dev); | 170 | struct drm_device *drm_dev = dev_get_drvdata(dev); |
171 | struct drm_connector *connector; | 171 | struct exynos_drm_private *private = drm_dev->dev_private; |
172 | struct drm_connector_list_iter conn_iter; | ||
173 | 172 | ||
174 | if (pm_runtime_suspended(dev) || !drm_dev) | 173 | if (pm_runtime_suspended(dev) || !drm_dev) |
175 | return 0; | 174 | return 0; |
176 | 175 | ||
177 | drm_modeset_lock_all(drm_dev); | 176 | drm_kms_helper_poll_disable(drm_dev); |
178 | drm_connector_list_iter_begin(drm_dev, &conn_iter); | 177 | exynos_drm_fbdev_suspend(drm_dev); |
179 | drm_for_each_connector_iter(connector, &conn_iter) { | 178 | private->suspend_state = drm_atomic_helper_suspend(drm_dev); |
180 | int old_dpms = connector->dpms; | 179 | if (IS_ERR(private->suspend_state)) { |
181 | 180 | exynos_drm_fbdev_resume(drm_dev); | |
182 | if (connector->funcs->dpms) | 181 | drm_kms_helper_poll_enable(drm_dev); |
183 | connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF); | 182 | return PTR_ERR(private->suspend_state); |
184 | |||
185 | /* Set the old mode back to the connector for resume */ | ||
186 | connector->dpms = old_dpms; | ||
187 | } | 183 | } |
188 | drm_connector_list_iter_end(&conn_iter); | ||
189 | drm_modeset_unlock_all(drm_dev); | ||
190 | 184 | ||
191 | return 0; | 185 | return 0; |
192 | } | 186 | } |
@@ -194,24 +188,14 @@ static int exynos_drm_suspend(struct device *dev) | |||
194 | static int exynos_drm_resume(struct device *dev) | 188 | static int exynos_drm_resume(struct device *dev) |
195 | { | 189 | { |
196 | struct drm_device *drm_dev = dev_get_drvdata(dev); | 190 | struct drm_device *drm_dev = dev_get_drvdata(dev); |
197 | struct drm_connector *connector; | 191 | struct exynos_drm_private *private = drm_dev->dev_private; |
198 | struct drm_connector_list_iter conn_iter; | ||
199 | 192 | ||
200 | if (pm_runtime_suspended(dev) || !drm_dev) | 193 | if (pm_runtime_suspended(dev) || !drm_dev) |
201 | return 0; | 194 | return 0; |
202 | 195 | ||
203 | drm_modeset_lock_all(drm_dev); | 196 | drm_atomic_helper_resume(drm_dev, private->suspend_state); |
204 | drm_connector_list_iter_begin(drm_dev, &conn_iter); | 197 | exynos_drm_fbdev_resume(drm_dev); |
205 | drm_for_each_connector_iter(connector, &conn_iter) { | 198 | drm_kms_helper_poll_enable(drm_dev); |
206 | if (connector->funcs->dpms) { | ||
207 | int dpms = connector->dpms; | ||
208 | |||
209 | connector->dpms = DRM_MODE_DPMS_OFF; | ||
210 | connector->funcs->dpms(connector, dpms); | ||
211 | } | ||
212 | } | ||
213 | drm_connector_list_iter_end(&conn_iter); | ||
214 | drm_modeset_unlock_all(drm_dev); | ||
215 | 199 | ||
216 | return 0; | 200 | return 0; |
217 | } | 201 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index cf131c2aa23e..f8bae4cb4823 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
@@ -202,6 +202,7 @@ struct drm_exynos_file_private { | |||
202 | */ | 202 | */ |
203 | struct exynos_drm_private { | 203 | struct exynos_drm_private { |
204 | struct drm_fb_helper *fb_helper; | 204 | struct drm_fb_helper *fb_helper; |
205 | struct drm_atomic_state *suspend_state; | ||
205 | 206 | ||
206 | struct device *dma_dev; | 207 | struct device *dma_dev; |
207 | void *mapping; | 208 | void *mapping; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index c3a068409b48..dfb66ecf417b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <drm/drm_crtc_helper.h> | 18 | #include <drm/drm_crtc_helper.h> |
19 | #include <drm/exynos_drm.h> | 19 | #include <drm/exynos_drm.h> |
20 | 20 | ||
21 | #include <linux/console.h> | ||
22 | |||
21 | #include "exynos_drm_drv.h" | 23 | #include "exynos_drm_drv.h" |
22 | #include "exynos_drm_fb.h" | 24 | #include "exynos_drm_fb.h" |
23 | #include "exynos_drm_fbdev.h" | 25 | #include "exynos_drm_fbdev.h" |
@@ -285,3 +287,21 @@ void exynos_drm_output_poll_changed(struct drm_device *dev) | |||
285 | 287 | ||
286 | drm_fb_helper_hotplug_event(fb_helper); | 288 | drm_fb_helper_hotplug_event(fb_helper); |
287 | } | 289 | } |
290 | |||
291 | void exynos_drm_fbdev_suspend(struct drm_device *dev) | ||
292 | { | ||
293 | struct exynos_drm_private *private = dev->dev_private; | ||
294 | |||
295 | console_lock(); | ||
296 | drm_fb_helper_set_suspend(private->fb_helper, 1); | ||
297 | console_unlock(); | ||
298 | } | ||
299 | |||
300 | void exynos_drm_fbdev_resume(struct drm_device *dev) | ||
301 | { | ||
302 | struct exynos_drm_private *private = dev->dev_private; | ||
303 | |||
304 | console_lock(); | ||
305 | drm_fb_helper_set_suspend(private->fb_helper, 0); | ||
306 | console_unlock(); | ||
307 | } | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h index 330eef87f718..645d1bb7f665 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h | |||
@@ -21,6 +21,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev); | |||
21 | void exynos_drm_fbdev_fini(struct drm_device *dev); | 21 | void exynos_drm_fbdev_fini(struct drm_device *dev); |
22 | void exynos_drm_fbdev_restore_mode(struct drm_device *dev); | 22 | void exynos_drm_fbdev_restore_mode(struct drm_device *dev); |
23 | void exynos_drm_output_poll_changed(struct drm_device *dev); | 23 | void exynos_drm_output_poll_changed(struct drm_device *dev); |
24 | void exynos_drm_fbdev_suspend(struct drm_device *drm); | ||
25 | void exynos_drm_fbdev_resume(struct drm_device *drm); | ||
24 | 26 | ||
25 | #else | 27 | #else |
26 | 28 | ||
@@ -39,6 +41,14 @@ static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev) | |||
39 | 41 | ||
40 | #define exynos_drm_output_poll_changed (NULL) | 42 | #define exynos_drm_output_poll_changed (NULL) |
41 | 43 | ||
44 | static inline void exynos_drm_fbdev_suspend(struct drm_device *drm) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | static inline void exynos_drm_fbdev_resume(struct drm_device *drm) | ||
49 | { | ||
50 | } | ||
51 | |||
42 | #endif | 52 | #endif |
43 | 53 | ||
44 | #endif | 54 | #endif |