UPSTREAM: drm/rockchip: Use atomic PM helpers
authorTomeu Vizoso <tomeu.vizoso@collabora.com>
Mon, 6 Jun 2016 14:53:32 +0000 (16:53 +0200)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 8 Aug 2016 06:39:52 +0000 (14:39 +0800)
This driver was still using the old legacy helpers and that caused a few
NULL dereferences when trying to call empty callbacks.

Change-Id: I9656aed34892260dbf9b571b95befd6af4d9b70f
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Cc: Caesar Wang <wxt@rock-chips.com>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1465224813-7359-1-git-send-email-tomeu.vizoso@collabora.com
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
(cherry picked from 5a5873830972e7d8983dd205b3686f728047d556)

drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.h

index d0cb8b62afea7376b7451b18130629c5e12b086d..37b388d9a9f61e73f7ff796a1cd64bd854b2c7fa 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/of_graph.h>
 #include <linux/component.h>
 #include <linux/fence.h>
+#include <linux/console.h>
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_fb.h"
@@ -491,25 +492,38 @@ static struct drm_driver rockchip_drm_driver = {
 };
 
 #ifdef CONFIG_PM_SLEEP
-static int rockchip_drm_sys_suspend(struct device *dev)
+void rockchip_drm_fb_suspend(struct drm_device *drm)
 {
-       struct drm_device *drm = dev_get_drvdata(dev);
-       struct drm_connector *connector;
+       struct rockchip_drm_private *priv = drm->dev_private;
 
-       if (!drm)
-               return 0;
+       console_lock();
+       drm_fb_helper_set_suspend(&priv->fbdev_helper, 1);
+       console_unlock();
+}
+
+void rockchip_drm_fb_resume(struct drm_device *drm)
+{
+       struct rockchip_drm_private *priv = drm->dev_private;
+
+       console_lock();
+       drm_fb_helper_set_suspend(&priv->fbdev_helper, 0);
+       console_unlock();
+}
 
-       drm_modeset_lock_all(drm);
-       list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
-               int old_dpms = connector->dpms;
+static int rockchip_drm_sys_suspend(struct device *dev)
+{
+       struct drm_device *drm = dev_get_drvdata(dev);
+       struct rockchip_drm_private *priv = drm->dev_private;
 
-               if (connector->funcs->dpms)
-                       connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
+       drm_kms_helper_poll_disable(drm);
+       rockchip_drm_fb_suspend(drm);
 
-               /* Set the old mode back to the connector for resume */
-               connector->dpms = old_dpms;
+       priv->state = drm_atomic_helper_suspend(drm);
+       if (IS_ERR(priv->state)) {
+               rockchip_drm_fb_resume(drm);
+               drm_kms_helper_poll_enable(drm);
+               return PTR_ERR(priv->state);
        }
-       drm_modeset_unlock_all(drm);
 
        return 0;
 }
@@ -517,47 +531,11 @@ static int rockchip_drm_sys_suspend(struct device *dev)
 static int rockchip_drm_sys_resume(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
-       struct drm_connector *connector;
-       enum drm_connector_status status;
-       bool changed = false;
-
-       if (!drm)
-               return 0;
-
-       drm_modeset_lock_all(drm);
-       list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
-               int desired_mode = connector->dpms;
-
-               /*
-                * at suspend time, we save dpms to connector->dpms,
-                * restore the old_dpms, and at current time, the connector
-                * dpms status must be DRM_MODE_DPMS_OFF.
-                */
-               connector->dpms = DRM_MODE_DPMS_OFF;
-
-               /*
-                * If the connector has been disconnected during suspend,
-                * disconnect it from the encoder and leave it off. We'll notify
-                * userspace at the end.
-                */
-               if (desired_mode == DRM_MODE_DPMS_ON) {
-                       status = connector->funcs->detect(connector, true);
-                       if (status == connector_status_disconnected) {
-                               connector->encoder = NULL;
-                               connector->status = status;
-                               changed = true;
-                               continue;
-                       }
-               }
-               if (connector->funcs->dpms)
-                       connector->funcs->dpms(connector, desired_mode);
-       }
-       drm_modeset_unlock_all(drm);
-
-       drm_helper_resume_force_mode(drm);
+       struct rockchip_drm_private *priv = drm->dev_private;
 
-       if (changed)
-               drm_kms_helper_hotplug_event(drm);
+       drm_atomic_helper_resume(drm, priv->state);
+       rockchip_drm_fb_resume(drm);
+       drm_kms_helper_poll_enable(drm);
 
        return 0;
 }
index aaa97dbad5e71b1f133c4cc8d60e502e62d17ee1..163b6f0f3ad3b328a44f12984c3f374dfddbd162 100644 (file)
@@ -93,6 +93,7 @@ struct rockchip_drm_private {
        struct drm_fb_helper fbdev_helper;
        struct drm_gem_object *fbdev_bo;
        const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
+       struct drm_atomic_state *state;
 
        struct rockchip_atomic_commit commit;
        struct iommu_domain *domain;