diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index 308d442a531b..e5957e7da768 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -48,6 +48,7 @@ static LIST_HEAD(panel_list);
 void drm_panel_init(struct drm_panel *panel)
 {
 	INIT_LIST_HEAD(&panel->list);
+	panel->state = DRM_PANEL_POWER_OFF;
 }
 EXPORT_SYMBOL(drm_panel_init);
 
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 14ac240a1f64..425461c4c574 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -24,6 +24,7 @@
 #ifndef __DRM_PANEL_H__
 #define __DRM_PANEL_H__
 
+#include <linux/bug.h>
 #include <linux/errno.h>
 #include <linux/list.h>
 
@@ -84,6 +85,7 @@ struct drm_panel_funcs {
  * @dev: parent device of the panel
  * @funcs: operations that can be performed on the panel
  * @list: panel entry in registry
+ * @power_state: keeps track of the panel power status
  */
 struct drm_panel {
 	struct drm_device *drm;
@@ -93,6 +95,12 @@ struct drm_panel {
 	const struct drm_panel_funcs *funcs;
 
 	struct list_head list;
+
+	enum {
+		DRM_PANEL_POWER_OFF,
+		DRM_PANEL_POWER_PREPARED,
+		DRM_PANEL_POWER_ENABLED
+	} state;
 };
 
 /**
@@ -104,12 +112,21 @@ struct drm_panel {
  * is usually no longer possible to communicate with the panel until another
  * call to drm_panel_prepare().
  *
+ * Atomic framework should ensure that prepare/unprepare are properly balanced.
+ * If this is not the case, a WARNING will be issued.
+ *
  * Return: 0 on success or a negative error code on failure.
  */
 static inline int drm_panel_unprepare(struct drm_panel *panel)
 {
-	if (panel && panel->funcs && panel->funcs->unprepare)
-		return panel->funcs->unprepare(panel);
+	WARN_ON(panel->state != DRM_PANEL_POWER_PREPARED);
+
+	if (panel && panel->funcs && panel->funcs->unprepare) {
+		int ret = panel->funcs->unprepare(panel);
+		if (!ret)
+			panel->state = DRM_PANEL_POWER_OFF;
+		return ret;
+	}
 
 	return panel ? -ENOSYS : -EINVAL;
 }
@@ -122,12 +139,21 @@ static inline int drm_panel_unprepare(struct drm_panel *panel)
  * drivers. For smart panels it should still be possible to communicate with
  * the integrated circuitry via any command bus after this call.
  *
+ * Atomic framework should ensure that enable/disable are properly balanced.
+ * If this is not the case, a WARNING will be issued.
+ *
  * Return: 0 on success or a negative error code on failure.
  */
 static inline int drm_panel_disable(struct drm_panel *panel)
 {
-	if (panel && panel->funcs && panel->funcs->disable)
-		return panel->funcs->disable(panel);
+	WARN_ON(panel->state != DRM_PANEL_POWER_ENABLED);
+
+	if (panel && panel->funcs && panel->funcs->disable) {
+		int ret = panel->funcs->disable(panel);
+		if (!ret)
+			panel->state = DRM_PANEL_POWER_PREPARED;
+		return ret;
+	}
 
 	return panel ? -ENOSYS : -EINVAL;
 }
@@ -140,12 +166,21 @@ static inline int drm_panel_disable(struct drm_panel *panel)
  * the panel. After this has completed it is possible to communicate with any
  * integrated circuitry via a command bus.
  *
+ * Atomic framework should ensure that prepare/unprepare are properly balanced.
+ * If this is not the case, a WARNING will be issued.
+ *
  * Return: 0 on success or a negative error code on failure.
  */
 static inline int drm_panel_prepare(struct drm_panel *panel)
 {
-	if (panel && panel->funcs && panel->funcs->prepare)
-		return panel->funcs->prepare(panel);
+	WARN_ON(panel->state != DRM_PANEL_POWER_OFF);
+
+	if (panel && panel->funcs && panel->funcs->prepare) {
+		int ret = panel->funcs->prepare(panel);
+		if (!ret)
+			panel->state = DRM_PANEL_POWER_PREPARED;
+		return ret;
+	}
 
 	return panel ? -ENOSYS : -EINVAL;
 }
@@ -158,12 +193,21 @@ static inline int drm_panel_prepare(struct drm_panel *panel)
  * and the backlight to be enabled. Content will be visible on screen after
  * this call completes.
  *
+ * Atomic framework should ensure that enable/disable are properly balanced.
+ * If this is not the case, a WARNING will be issued.
+ *
  * Return: 0 on success or a negative error code on failure.
  */
 static inline int drm_panel_enable(struct drm_panel *panel)
 {
-	if (panel && panel->funcs && panel->funcs->enable)
-		return panel->funcs->enable(panel);
+	WARN_ON(panel->state != DRM_PANEL_POWER_PREPARED);
+
+	if (panel && panel->funcs && panel->funcs->enable) {
+		int ret = panel->funcs->enable(panel);
+		if (!ret)
+			panel->state = DRM_PANEL_POWER_ENABLED;
+		return ret;
+	}
 
 	return panel ? -ENOSYS : -EINVAL;
 }
