aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2017-09-14 08:01:01 -0400
committerInki Dae <inki.dae@samsung.com>2017-09-19 06:50:44 -0400
commit6e8edf8a7d8d98e1734ff41e5c69439419319402 (patch)
tree7834cee31827d42a0619003666907ca1c2878406
parent5baf6bb0fd2388742a0846cc7bcacee6dec78235 (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.c40
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c20
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.h10
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 = {
168static int exynos_drm_suspend(struct device *dev) 168static 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)
194static int exynos_drm_resume(struct device *dev) 188static 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 */
203struct exynos_drm_private { 203struct 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
291void 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
300void 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);
21void exynos_drm_fbdev_fini(struct drm_device *dev); 21void exynos_drm_fbdev_fini(struct drm_device *dev);
22void exynos_drm_fbdev_restore_mode(struct drm_device *dev); 22void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
23void exynos_drm_output_poll_changed(struct drm_device *dev); 23void exynos_drm_output_poll_changed(struct drm_device *dev);
24void exynos_drm_fbdev_suspend(struct drm_device *drm);
25void 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
44static inline void exynos_drm_fbdev_suspend(struct drm_device *drm)
45{
46}
47
48static inline void exynos_drm_fbdev_resume(struct drm_device *drm)
49{
50}
51
42#endif 52#endif
43 53
44#endif 54#endif