diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 31af5cf37a09..b8adfe87334b 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -257,6 +257,34 @@ static void drm_client_connectors_enabled(struct drm_connector **connectors,
 		enabled[i] = drm_connector_enabled(connectors[i], false);
 }
 
+static void drm_client_match_edp_lid(struct drm_device *dev,
+				     struct drm_connector **connectors,
+				     unsigned int connector_count,
+				     bool *enabled)
+{
+	int i;
+
+	for (i = 0; i < connector_count; i++) {
+		struct drm_connector *connector = connectors[i];
+
+		switch (connector->connector_type) {
+		case DRM_MODE_CONNECTOR_LVDS:
+		case DRM_MODE_CONNECTOR_eDP:
+			if (!enabled[i])
+				continue;
+			break;
+		default:
+			continue;
+		}
+
+		if (dev->lid_closed) {
+			drm_dbg_kms(dev, "[CONNECTOR:%d:%s] lid is closed, disabling\n",
+				    connector->base.id, connector->name);
+			enabled[i] = false;
+		}
+	}
+}
+
 static bool drm_client_target_cloned(struct drm_device *dev,
 				     struct drm_connector **connectors,
 				     unsigned int connector_count,
@@ -844,6 +872,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
 		memset(crtcs, 0, connector_count * sizeof(*crtcs));
 		memset(offsets, 0, connector_count * sizeof(*offsets));
 
+		drm_client_match_edp_lid(dev, connectors, connector_count, enabled);
 		if (!drm_client_target_cloned(dev, connectors, connector_count, modes,
 					      offsets, enabled, width, height) &&
 		    !drm_client_target_preferred(dev, connectors, connector_count, modes,
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index d612133e2cf7..41dd5887599a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -30,6 +30,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/console.h>
+#include <linux/input.h>
+#include <linux/mod_devicetable.h>
 #include <linux/pci.h>
 #include <linux/sysrq.h>
 #include <linux/vga_switcheroo.h>
@@ -413,6 +415,128 @@ static void drm_fb_helper_damage_work(struct work_struct *work)
 	drm_fb_helper_fb_dirty(helper);
 }
 
+static void drm_fb_helper_lid_event(struct input_handle *handle, unsigned int type,
+				    unsigned int code, int value)
+{
+	if (type == EV_SW && code == SW_LID) {
+		struct drm_fb_helper *fb_helper = handle->handler->private;
+
+		if (value != fb_helper->dev->lid_closed) {
+			fb_helper->dev->lid_closed = value;
+			queue_work(fb_helper->input_wq, &fb_helper->lid_work);
+		}
+	}
+}
+
+struct drm_fb_lid {
+	struct input_handle handle;
+};
+
+static int drm_fb_helper_lid_connect(struct input_handler *handler,
+				     struct input_dev *dev,
+				     const struct input_device_id *id)
+{
+	struct drm_fb_helper *fb_helper = handler->private;
+	struct drm_fb_lid *lid;
+	char *name;
+	int error;
+
+	lid = kzalloc(sizeof(*lid), GFP_KERNEL);
+	if (!lid)
+		return -ENOMEM;
+
+	name = kasprintf(GFP_KERNEL, "drm-fb-helper-lid-%s", dev_name(&dev->dev));
+	if (!name) {
+		error = -ENOMEM;
+		goto err_free_lid;
+	}
+
+	lid->handle.dev = dev;
+	lid->handle.handler = handler;
+	lid->handle.name = name;
+	lid->handle.private = lid;
+
+	error = input_register_handle(&lid->handle);
+	if (error)
+		goto err_free_name;
+
+	error = input_open_device(&lid->handle);
+	if (error)
+		goto err_unregister_handle;
+
+	fb_helper->dev->lid_closed = dev->sw[SW_LID];
+	drm_dbg_kms(fb_helper->dev, "initial lid state is set to %d\n", fb_helper->dev->lid_closed);
+
+	return 0;
+
+err_unregister_handle:
+	input_unregister_handle(&lid->handle);
+err_free_name:
+	kfree(name);
+err_free_lid:
+	kfree(lid);
+	return error;
+}
+
+static void drm_fb_helper_lid_disconnect(struct input_handle *handle)
+{
+	struct drm_fb_lid *lid = handle->private;
+
+	input_close_device(handle);
+	input_unregister_handle(handle);
+
+	kfree(handle->name);
+	kfree(lid);
+}
+
+static const struct input_device_id drm_fb_helper_lid_ids[] = {
+	{
+		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT,
+		.evbit = { BIT_MASK(EV_SW) },
+		.swbit = { [BIT_WORD(SW_LID)] = BIT_MASK(SW_LID) },
+	},
+	{ },
+};
+
+static struct input_handler drm_fb_helper_lid_handler = {
+	.event =	drm_fb_helper_lid_event,
+	.connect =	drm_fb_helper_lid_connect,
+	.disconnect =	drm_fb_helper_lid_disconnect,
+	.name =		"drm-fb-helper-lid",
+	.id_table =	drm_fb_helper_lid_ids,
+};
+
+static void drm_fb_helper_lid_work(struct work_struct *work)
+{
+	struct drm_fb_helper *fb_helper = container_of(work, struct drm_fb_helper,
+						       lid_work);
+	drm_fb_helper_hotplug_event(fb_helper);
+}
+
+static int drm_fb_helper_create_lid_handler(struct drm_fb_helper *fb_helper)
+{
+	int ret = 0;
+
+	if (fb_helper->deferred_setup)
+		return 0;
+
+	fb_helper->input_wq = create_singlethread_workqueue("drm-fb-lid");
+	if (fb_helper->input_wq == NULL)
+		return -ENOMEM;
+
+	drm_fb_helper_lid_handler.private = fb_helper;
+	ret = input_register_handler(&drm_fb_helper_lid_handler);
+	if (ret)
+		goto remove_wq;
+
+	return 0;
+
+remove_wq:
+	destroy_workqueue(fb_helper->input_wq);
+	fb_helper->input_wq = NULL;
+	return ret;
+}
+
 /**
  * drm_fb_helper_prepare - setup a drm_fb_helper structure
  * @dev: DRM device
@@ -445,6 +569,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
 	spin_lock_init(&helper->damage_lock);
 	INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker);
 	INIT_WORK(&helper->damage_work, drm_fb_helper_damage_work);
+	INIT_WORK(&helper->lid_work, drm_fb_helper_lid_work);
 	helper->damage_clip.x1 = helper->damage_clip.y1 = ~0;
 	mutex_init(&helper->lock);
 	helper->funcs = funcs;
@@ -593,6 +718,9 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
 	if (!drm_fbdev_emulation)
 		return;
 
+	input_unregister_handler(&drm_fb_helper_lid_handler);
+	destroy_workqueue(fb_helper->input_wq);
+
 	cancel_work_sync(&fb_helper->resume_work);
 	cancel_work_sync(&fb_helper->damage_work);
 
@@ -1842,6 +1970,10 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
 	width = dev->mode_config.max_width;
 	height = dev->mode_config.max_height;
 
+	ret = drm_fb_helper_create_lid_handler(fb_helper);
+	if (ret)
+		return ret;
+
 	drm_client_modeset_probe(&fb_helper->client, width, height);
 	ret = drm_fb_helper_single_fb_probe(fb_helper);
 	if (ret < 0) {
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 63767cf24371..619af597784c 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -316,6 +316,12 @@ struct drm_device {
 	 * Root directory for debugfs files.
 	 */
 	struct dentry *debugfs_root;
+
+	/**
+	 * @lid_closed: Flag to tell the lid switch state
+	 */
+	bool lid_closed;
+
 };
 
 #endif
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 375737fd6c36..7fb36c10299d 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -143,6 +143,8 @@ struct drm_fb_helper {
 	spinlock_t damage_lock;
 	struct work_struct damage_work;
 	struct work_struct resume_work;
+	struct work_struct lid_work;
+	struct workqueue_struct *input_wq;
 
 	/**
 	 * @lock:
