Skip to content

Commit

Permalink
drm/exynos: Fix suspend/resume support
Browse files Browse the repository at this point in the history
Commit 7d902c0 ("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: 7d902c0 ("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>
  • Loading branch information
Marek Szyprowski authored and Inki Dae committed Sep 19, 2017
1 parent 5baf6bb commit 6e8edf8
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 28 deletions.
40 changes: 12 additions & 28 deletions drivers/gpu/drm/exynos/exynos_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,50 +168,34 @@ static struct drm_driver exynos_drm_driver = {
static int exynos_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct exynos_drm_private *private = drm_dev->dev_private;

if (pm_runtime_suspended(dev) || !drm_dev)
return 0;

drm_modeset_lock_all(drm_dev);
drm_connector_list_iter_begin(drm_dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
int old_dpms = connector->dpms;

if (connector->funcs->dpms)
connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);

/* Set the old mode back to the connector for resume */
connector->dpms = old_dpms;
drm_kms_helper_poll_disable(drm_dev);
exynos_drm_fbdev_suspend(drm_dev);
private->suspend_state = drm_atomic_helper_suspend(drm_dev);
if (IS_ERR(private->suspend_state)) {
exynos_drm_fbdev_resume(drm_dev);
drm_kms_helper_poll_enable(drm_dev);
return PTR_ERR(private->suspend_state);
}
drm_connector_list_iter_end(&conn_iter);
drm_modeset_unlock_all(drm_dev);

return 0;
}

static int exynos_drm_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct exynos_drm_private *private = drm_dev->dev_private;

if (pm_runtime_suspended(dev) || !drm_dev)
return 0;

drm_modeset_lock_all(drm_dev);
drm_connector_list_iter_begin(drm_dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
if (connector->funcs->dpms) {
int dpms = connector->dpms;

connector->dpms = DRM_MODE_DPMS_OFF;
connector->funcs->dpms(connector, dpms);
}
}
drm_connector_list_iter_end(&conn_iter);
drm_modeset_unlock_all(drm_dev);
drm_atomic_helper_resume(drm_dev, private->suspend_state);
exynos_drm_fbdev_resume(drm_dev);
drm_kms_helper_poll_enable(drm_dev);

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/exynos/exynos_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ struct drm_exynos_file_private {
*/
struct exynos_drm_private {
struct drm_fb_helper *fb_helper;
struct drm_atomic_state *suspend_state;

struct device *dma_dev;
void *mapping;
Expand Down
20 changes: 20 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_fbdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <drm/drm_crtc_helper.h>
#include <drm/exynos_drm.h>

#include <linux/console.h>

#include "exynos_drm_drv.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_fbdev.h"
Expand Down Expand Up @@ -285,3 +287,21 @@ void exynos_drm_output_poll_changed(struct drm_device *dev)

drm_fb_helper_hotplug_event(fb_helper);
}

void exynos_drm_fbdev_suspend(struct drm_device *dev)
{
struct exynos_drm_private *private = dev->dev_private;

console_lock();
drm_fb_helper_set_suspend(private->fb_helper, 1);
console_unlock();
}

void exynos_drm_fbdev_resume(struct drm_device *dev)
{
struct exynos_drm_private *private = dev->dev_private;

console_lock();
drm_fb_helper_set_suspend(private->fb_helper, 0);
console_unlock();
}
10 changes: 10 additions & 0 deletions drivers/gpu/drm/exynos/exynos_drm_fbdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev);
void exynos_drm_fbdev_fini(struct drm_device *dev);
void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
void exynos_drm_output_poll_changed(struct drm_device *dev);
void exynos_drm_fbdev_suspend(struct drm_device *drm);
void exynos_drm_fbdev_resume(struct drm_device *drm);

#else

Expand All @@ -39,6 +41,14 @@ static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev)

#define exynos_drm_output_poll_changed (NULL)

static inline void exynos_drm_fbdev_suspend(struct drm_device *drm)
{
}

static inline void exynos_drm_fbdev_resume(struct drm_device *drm)
{
}

#endif

#endif

0 comments on commit 6e8edf8

Please sign in to comment.