From 05f91b504b9d1b0f81f4ec4e40711e0f4e8bbe9e Mon Sep 17 00:00:00 2001
From: "msm8916-mainline/linux-panel-drivers@29a5646"
 <msm8916-mainline/linux-panel-drivers@29a5646>
Date: Thu, 18 Mar 2021 11:50:29 +0100
Subject: [PATCH 29/78] MSM8916: drm/panel: Generate using
 linux-mdss-dsi-panel-driver-generator

---
 drivers/gpu/drm/panel/Kconfig                 |   5 +
 drivers/gpu/drm/panel/Makefile                |   1 +
 .../gpu/drm/panel/msm8916-generated/Makefile  |  20 +
 .../panel-alcatel-auo-hx8394d.c               | 321 ++++++++
 .../panel-asus-z00l-otm1284a.c                | 323 ++++++++
 .../panel-asus-z010d-r69339.c                 | 334 ++++++++
 .../panel-longcheer-booyi-otm1287.c           | 430 ++++++++++
 .../panel-longcheer-truly-otm1288a.c          | 430 ++++++++++
 .../panel-longcheer-yushun-nt35520.c          | 467 +++++++++++
 .../panel-motorola-harpia-boe.c               | 327 ++++++++
 .../panel-motorola-harpia-tianma.c            | 323 ++++++++
 .../panel-motorola-osprey-inx.c               | 291 +++++++
 .../panel-motorola-surnia-boe.c               | 271 +++++++
 .../panel-oppo-15009-nt35592-jdi.c            | 746 ++++++++++++++++++
 .../panel-samsung-ea8061v-ams497ee01.c        | 282 +++++++
 .../panel-samsung-s6d7aa0-ltl101at01.c        | 359 +++++++++
 .../panel-samsung-s6e88a0-ams427ap24.c        | 282 +++++++
 .../panel-samsung-tc358764-ltl101al06.c       | 270 +++++++
 .../panel-wingtech-auo-r61308.c               | 301 +++++++
 .../panel-wingtech-ebbg-otm1285a.c            | 259 ++++++
 .../panel-wingtech-sharp-r69431.c             | 269 +++++++
 .../panel-wingtech-tianma-hx8394d.c           | 328 ++++++++
 .../panel-wingtech-yassy-ili9881.c            | 441 +++++++++++
 23 files changed, 7080 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/Makefile
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-alcatel-auo-hx8394d.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-asus-z00l-otm1284a.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-asus-z010d-r69339.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-booyi-otm1287.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-truly-otm1288a.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-yushun-nt35520.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-boe.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-tianma.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-motorola-osprey-inx.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-motorola-surnia-boe.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-oppo-15009-nt35592-jdi.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6d7aa0-ltl101at01.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6e88a0-ams427ap24.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-samsung-tc358764-ltl101al06.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-auo-r61308.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-ebbg-otm1285a.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-sharp-r69431.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-tianma-hx8394d.c
 create mode 100644 drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-yassy-ili9881.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index b9dbedf8f..b6c7ac97c 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -499,4 +499,9 @@ config DRM_PANEL_XINPENG_XPP055C272
 	  Say Y here if you want to enable support for the Xinpeng
 	  XPP055C272 controller for 720x1280 LCD panels with MIPI/RGB/SPI
 	  system interfaces.
+
+config DRM_PANEL_MSM8916_GENERATED
+	tristate "MSM8916 panel drivers generated with linux-mdss-dsi-panel-driver-generator"
+	depends on GPIOLIB && OF && REGULATOR
+	depends on DRM_MIPI_DSI
 endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 2ba560bca..7ad6787f4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_DRM_PANEL_TPO_TPG110) += panel-tpo-tpg110.o
 obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
 obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
 obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += msm8916-generated/
diff --git a/drivers/gpu/drm/panel/msm8916-generated/Makefile b/drivers/gpu/drm/panel/msm8916-generated/Makefile
new file mode 100644
index 000000000..ca7baeb8f
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/Makefile
@@ -0,0 +1,20 @@
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-alcatel-auo-hx8394d.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-asus-z00l-otm1284a.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-asus-z010d-r69339.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-longcheer-booyi-otm1287.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-longcheer-truly-otm1288a.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-longcheer-yushun-nt35520.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-motorola-harpia-boe.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-motorola-harpia-tianma.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-motorola-osprey-inx.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-motorola-surnia-boe.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-oppo-15009-nt35592-jdi.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-samsung-ea8061v-ams497ee01.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-samsung-s6d7aa0-ltl101at01.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-samsung-s6e88a0-ams427ap24.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-samsung-tc358764-ltl101al06.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-wingtech-auo-r61308.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-wingtech-ebbg-otm1285a.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-wingtech-sharp-r69431.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-wingtech-tianma-hx8394d.o
+obj-$(CONFIG_DRM_PANEL_MSM8916_GENERATED) += panel-wingtech-yassy-ili9881.o
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-alcatel-auo-hx8394d.c b/drivers/gpu/drm/panel/msm8916-generated/panel-alcatel-auo-hx8394d.c
new file mode 100644
index 000000000..d2c61abe3
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-alcatel-auo-hx8394d.c
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct hx8394d_auo {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct hx8394d_auo *to_hx8394d_auo(struct drm_panel *panel)
+{
+	return container_of(panel, struct hx8394d_auo, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void hx8394d_auo_reset(struct hx8394d_auo *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(50);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(120);
+}
+
+static int hx8394d_auo_on(struct hx8394d_auo *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_dcs_write_seq(dsi, 0xb9, 0xff, 0x83, 0x94);
+	dsi_dcs_write_seq(dsi, 0xba,
+			  0x73, 0x83, 0xa0, 0x65, 0xb2, 0x3f, 0x4f, 0x40, 0x50,
+			  0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xb1,
+			  0x6c, 0x12, 0x12, 0x34, 0x04, 0x11, 0xf1, 0x80, 0x9f,
+			  0xa0, 0x23, 0x80, 0xc0, 0xd2, 0x58);
+	dsi_dcs_write_seq(dsi, 0xb2,
+			  0x00, 0x64, 0x05, 0x07, 0x22, 0x1c, 0x08, 0x08, 0x1c,
+			  0x4d, 0x00, 0x03, 0x20, 0x46, 0x48);
+	dsi_dcs_write_seq(dsi, 0xb4,
+			  0x00, 0xff, 0x03, 0x5a, 0x03, 0x5a, 0x03, 0x5a, 0x01,
+			  0x70, 0x01, 0x70);
+	dsi_dcs_write_seq(dsi, 0xbc, 0x07);
+	dsi_dcs_write_seq(dsi, 0xe0,
+			  0x12, 0x2d, 0x36, 0x30, 0x33, 0x39, 0x39, 0x4a, 0x09,
+			  0x0c, 0x0e, 0x18, 0x0f, 0x12, 0x15, 0x13, 0x14, 0x06,
+			  0x10, 0x10, 0x18, 0x12, 0x2d, 0x36, 0x30, 0x33, 0x39,
+			  0x39, 0x4a, 0x09, 0x0c, 0x0e, 0x18, 0x0f, 0x12, 0x15,
+			  0x13, 0x14, 0x0a, 0x16, 0x18, 0x18);
+	dsi_dcs_write_seq(dsi, 0xd3,
+			  0x00, 0x06, 0x00, 0x01, 0x01, 0x10, 0x00, 0x32, 0x10,
+			  0x00, 0x00, 0x00, 0x32, 0x15, 0x04, 0x35, 0x04, 0x32,
+			  0x15, 0x14, 0x05, 0x14, 0x37, 0x33, 0x00, 0x00, 0x37,
+			  0x00, 0x07, 0x37);
+	dsi_dcs_write_seq(dsi, 0xd5,
+			  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x18, 0x18, 0x18, 0x18, 0x18, 0x25, 0x24, 0x27, 0x26,
+			  0x18, 0x18, 0x47, 0x46, 0x43, 0x42, 0x41, 0x40, 0x45,
+			  0x44, 0x05, 0x04, 0x01, 0x00, 0x07, 0x06, 0x03, 0x02,
+			  0x21, 0x20, 0x23, 0x22, 0x18, 0x18, 0x18, 0x18);
+	dsi_dcs_write_seq(dsi, 0xd6,
+			  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x18, 0x18, 0x18, 0x18, 0x18, 0x22, 0x23, 0x20, 0x21,
+			  0x18, 0x18, 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x02,
+			  0x03, 0x02, 0x03, 0x06, 0x07, 0x00, 0x01, 0x04, 0x05,
+			  0x26, 0x27, 0x24, 0x25, 0x18, 0x18, 0x18, 0x18);
+	dsi_dcs_write_seq(dsi, 0xbd, 0x01);
+	dsi_dcs_write_seq(dsi, 0xd8,
+			  0xaa, 0xab, 0xef, 0xff, 0xff, 0xf0, 0xaa, 0xab, 0xef,
+			  0xff, 0xff, 0xf0, 0xaa, 0xab, 0xef, 0xff, 0xff, 0xf0,
+			  0xaa, 0xab, 0xef, 0xff, 0xff, 0xf0, 0xaa, 0xab, 0xef,
+			  0xff, 0xff, 0xf0, 0xaa, 0xab, 0xef, 0xff, 0xff, 0xf0);
+	dsi_dcs_write_seq(dsi, 0xbd, 0x02);
+	dsi_dcs_write_seq(dsi, 0xd8,
+			  0xaa, 0xab, 0xef, 0xff, 0xff, 0xf0, 0xaa, 0xab, 0xef,
+			  0xff, 0xff, 0xf0);
+	dsi_dcs_write_seq(dsi, 0xcc, 0x01);
+	dsi_dcs_write_seq(dsi, 0xb6, 0x62, 0x62);
+	dsi_dcs_write_seq(dsi, 0xc0, 0x30, 0x14);
+	dsi_dcs_write_seq(dsi, 0xc7, 0x00, 0xc0, 0x40, 0xc0);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x02);
+
+	ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set tear on: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	usleep_range(10000, 11000);
+
+	return 0;
+}
+
+static int hx8394d_auo_off(struct hx8394d_auo *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int hx8394d_auo_prepare(struct drm_panel *panel)
+{
+	struct hx8394d_auo *ctx = to_hx8394d_auo(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	hx8394d_auo_reset(ctx);
+
+	ret = hx8394d_auo_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int hx8394d_auo_unprepare(struct drm_panel *panel)
+{
+	struct hx8394d_auo *ctx = to_hx8394d_auo(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = hx8394d_auo_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode hx8394d_auo_mode = {
+	.clock = (720 + 52 + 24 + 100) * (1280 + 9 + 2 + 5) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 52,
+	.hsync_end = 720 + 52 + 24,
+	.htotal = 720 + 52 + 24 + 100,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 9,
+	.vsync_end = 1280 + 9 + 2,
+	.vtotal = 1280 + 9 + 2 + 5,
+	.width_mm = 59,
+	.height_mm = 104,
+};
+
+static int hx8394d_auo_get_modes(struct drm_panel *panel,
+				 struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &hx8394d_auo_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs hx8394d_auo_panel_funcs = {
+	.prepare = hx8394d_auo_prepare,
+	.unprepare = hx8394d_auo_unprepare,
+	.get_modes = hx8394d_auo_get_modes,
+};
+
+static int hx8394d_auo_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct hx8394d_auo *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vsp";
+	ctx->supplies[1].supply = "vsn";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &hx8394d_auo_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int hx8394d_auo_remove(struct mipi_dsi_device *dsi)
+{
+	struct hx8394d_auo *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id hx8394d_auo_of_match[] = {
+	{ .compatible = "alcatel,auo-hx8394d" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hx8394d_auo_of_match);
+
+static struct mipi_dsi_driver hx8394d_auo_driver = {
+	.probe = hx8394d_auo_probe,
+	.remove = hx8394d_auo_remove,
+	.driver = {
+		.name = "panel-hx8394d-auo",
+		.of_match_table = hx8394d_auo_of_match,
+	},
+};
+module_mipi_dsi_driver(hx8394d_auo_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for hx8394d auo 720p video mode dsi panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-asus-z00l-otm1284a.c b/drivers/gpu/drm/panel/msm8916-generated/panel-asus-z00l-otm1284a.c
new file mode 100644
index 000000000..f0ab47ca9
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-asus-z00l-otm1284a.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct otm1284a {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *backlight_gpio;
+	bool prepared;
+};
+
+static inline struct otm1284a *to_otm1284a(struct drm_panel *panel)
+{
+	return container_of(panel, struct otm1284a, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void otm1284a_reset(struct otm1284a *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(10000, 11000);
+}
+
+static int otm1284a_on(struct otm1284a *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0x12, 0x84, 0x01);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xff, 0x12, 0x84);
+	dsi_generic_write_seq(dsi, 0x00, 0xb1);
+	dsi_generic_write_seq(dsi, 0xc6, 0x02);
+	dsi_generic_write_seq(dsi, 0x00, 0xb4);
+	dsi_generic_write_seq(dsi, 0xc6, 0x10);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0xff, 0xff, 0xff);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(125);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	usleep_range(5000, 6000);
+
+	dsi_generic_write_seq(dsi, 0x53, 0x24);
+	dsi_generic_write_seq(dsi, 0x5e, 0x0d);
+
+	return 0;
+}
+
+static int otm1284a_off(struct otm1284a *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_generic_write_seq(dsi, 0x53, 0x00);
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(150);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int otm1284a_prepare(struct drm_panel *panel)
+{
+	struct otm1284a *ctx = to_otm1284a(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	otm1284a_reset(ctx);
+
+	ret = otm1284a_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int otm1284a_unprepare(struct drm_panel *panel)
+{
+	struct otm1284a *ctx = to_otm1284a(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = otm1284a_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode otm1284a_mode = {
+	.clock = (720 + 92 + 12 + 64) * (1280 + 10 + 5 + 13) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 92,
+	.hsync_end = 720 + 92 + 12,
+	.htotal = 720 + 92 + 12 + 64,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 10,
+	.vsync_end = 1280 + 10 + 5,
+	.vtotal = 1280 + 10 + 5 + 13,
+	.width_mm = 68,
+	.height_mm = 121,
+};
+
+static int otm1284a_get_modes(struct drm_panel *panel,
+			      struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &otm1284a_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs otm1284a_panel_funcs = {
+	.prepare = otm1284a_prepare,
+	.unprepare = otm1284a_unprepare,
+	.get_modes = otm1284a_get_modes,
+};
+
+static int otm1284a_bl_update_status(struct backlight_device *bl)
+{
+	struct mipi_dsi_device *dsi = bl_get_data(bl);
+	struct otm1284a *ctx = mipi_dsi_get_drvdata(dsi);
+	u16 brightness = backlight_get_brightness(bl);
+	int ret;
+
+	gpiod_set_value_cansleep(ctx->backlight_gpio, !!brightness);
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+	if (ret < 0)
+		return ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	return 0;
+}
+
+static const struct backlight_ops otm1284a_bl_ops = {
+	.update_status = otm1284a_bl_update_status,
+};
+
+static struct backlight_device *
+otm1284a_create_backlight(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	const struct backlight_properties props = {
+		.type = BACKLIGHT_RAW,
+		.brightness = 255,
+		.max_brightness = 255,
+	};
+
+	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+					      &otm1284a_bl_ops, &props);
+}
+
+static int otm1284a_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct otm1284a *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->backlight_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_LOW);
+	if (IS_ERR(ctx->backlight_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->backlight_gpio),
+				     "Failed to get backlight-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &otm1284a_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ctx->panel.backlight = otm1284a_create_backlight(dsi);
+	if (IS_ERR(ctx->panel.backlight))
+		return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+				     "Failed to create backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int otm1284a_remove(struct mipi_dsi_device *dsi)
+{
+	struct otm1284a *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id otm1284a_of_match[] = {
+	{ .compatible = "asus,z00l-otm1284a" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, otm1284a_of_match);
+
+static struct mipi_dsi_driver otm1284a_driver = {
+	.probe = otm1284a_probe,
+	.remove = otm1284a_remove,
+	.driver = {
+		.name = "panel-otm1284a",
+		.of_match_table = otm1284a_of_match,
+	},
+};
+module_mipi_dsi_driver(otm1284a_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for otm1284a 720p video mode dsi panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-asus-z010d-r69339.c b/drivers/gpu/drm/panel/msm8916-generated/panel-asus-z010d-r69339.c
new file mode 100644
index 000000000..edf588a3c
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-asus-z010d-r69339.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct r69339 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct r69339 *to_r69339(struct drm_panel *panel)
+{
+	return container_of(panel, struct r69339, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void r69339_reset(struct r69339 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(10000, 11000);
+}
+
+static int r69339_on(struct r69339 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x0001);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display brightness: %d\n", ret);
+		return ret;
+	}
+
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(150);
+
+	return 0;
+}
+
+static int r69339_off(struct r69339 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x0000);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display brightness: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int r69339_prepare(struct drm_panel *panel)
+{
+	struct r69339 *ctx = to_r69339(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	r69339_reset(ctx);
+
+	ret = r69339_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int r69339_unprepare(struct drm_panel *panel)
+{
+	struct r69339 *ctx = to_r69339(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = r69339_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode r69339_mode = {
+	.clock = (720 + 100 + 12 + 40) * (1280 + 13 + 1 + 11) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 100,
+	.hsync_end = 720 + 100 + 12,
+	.htotal = 720 + 100 + 12 + 40,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 13,
+	.vsync_end = 1280 + 13 + 1,
+	.vtotal = 1280 + 13 + 1 + 11,
+	.width_mm = 68,
+	.height_mm = 121,
+};
+
+static int r69339_get_modes(struct drm_panel *panel,
+			    struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &r69339_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs r69339_panel_funcs = {
+	.prepare = r69339_prepare,
+	.unprepare = r69339_unprepare,
+	.get_modes = r69339_get_modes,
+};
+
+static int r69339_bl_update_status(struct backlight_device *bl)
+{
+	struct mipi_dsi_device *dsi = bl_get_data(bl);
+	u16 brightness = backlight_get_brightness(bl);
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+	if (ret < 0)
+		return ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	return 0;
+}
+
+// TODO: Check if /sys/class/backlight/.../actual_brightness actually returns
+// correct values. If not, remove this function.
+static int r69339_bl_get_brightness(struct backlight_device *bl)
+{
+	struct mipi_dsi_device *dsi = bl_get_data(bl);
+	u16 brightness;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
+	if (ret < 0)
+		return ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	return brightness & 0xff;
+}
+
+static const struct backlight_ops r69339_bl_ops = {
+	.update_status = r69339_bl_update_status,
+	.get_brightness = r69339_bl_get_brightness,
+};
+
+static struct backlight_device *
+r69339_create_backlight(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	const struct backlight_properties props = {
+		.type = BACKLIGHT_RAW,
+		.brightness = 255,
+		.max_brightness = 255,
+	};
+
+	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+					      &r69339_bl_ops, &props);
+}
+
+static int r69339_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct r69339 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &r69339_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ctx->panel.backlight = r69339_create_backlight(dsi);
+	if (IS_ERR(ctx->panel.backlight))
+		return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+				     "Failed to create backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int r69339_remove(struct mipi_dsi_device *dsi)
+{
+	struct r69339 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id r69339_of_match[] = {
+	{ .compatible = "asus,z010d-r69339" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, r69339_of_match);
+
+static struct mipi_dsi_driver r69339_driver = {
+	.probe = r69339_probe,
+	.remove = r69339_remove,
+	.driver = {
+		.name = "panel-r69339",
+		.of_match_table = r69339_of_match,
+	},
+};
+module_mipi_dsi_driver(r69339_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for sharp 720p video mode dsi panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-booyi-otm1287.c b/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-booyi-otm1287.c
new file mode 100644
index 000000000..6639797be
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-booyi-otm1287.c
@@ -0,0 +1,430 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct booyi_otm1287 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct booyi_otm1287 *to_booyi_otm1287(struct drm_panel *panel)
+{
+	return container_of(panel, struct booyi_otm1287, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void booyi_otm1287_reset(struct booyi_otm1287 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+}
+
+static int booyi_otm1287_on(struct booyi_otm1287 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_dcs_write_seq(dsi, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xff, 0x12, 0x87, 0x01);
+	dsi_dcs_write_seq(dsi, 0x00, 0x80);
+	dsi_dcs_write_seq(dsi, 0xff, 0x12, 0x87);
+	dsi_dcs_write_seq(dsi, 0x00, 0x92);
+	dsi_dcs_write_seq(dsi, 0xff, 0x30);
+	dsi_dcs_write_seq(dsi, 0x00, 0x80);
+	dsi_dcs_write_seq(dsi, 0xc0,
+			  0x00, 0x64, 0x00, 0x0f, 0x11, 0x00, 0x64, 0x0f, 0x11);
+	dsi_dcs_write_seq(dsi, 0x00, 0x90);
+	dsi_dcs_write_seq(dsi, 0xc0, 0x00, 0x5c, 0x00, 0x01, 0x00, 0x04);
+	dsi_dcs_write_seq(dsi, 0x00, 0xa4);
+	dsi_dcs_write_seq(dsi, 0xc0, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb3);
+	dsi_dcs_write_seq(dsi, 0xc0, 0x00, 0x55);
+	dsi_dcs_write_seq(dsi, 0x00, 0x81);
+	dsi_dcs_write_seq(dsi, 0xc1, 0x55);
+	dsi_dcs_write_seq(dsi, 0x00, 0x90);
+	dsi_dcs_write_seq(dsi, 0xf5, 0x02, 0x11, 0x02, 0x15);
+	dsi_dcs_write_seq(dsi, 0x00, 0x90);
+	dsi_dcs_write_seq(dsi, 0xc5, 0x50);
+	dsi_dcs_write_seq(dsi, 0x00, 0x94);
+	dsi_dcs_write_seq(dsi, 0xc5, 0x66);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb2);
+	dsi_dcs_write_seq(dsi, 0xf5, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb6);
+	dsi_dcs_write_seq(dsi, 0xf5, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0x94);
+	dsi_dcs_write_seq(dsi, 0xf5, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xd2);
+	dsi_dcs_write_seq(dsi, 0xf5, 0x06, 0x15);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb4);
+	dsi_dcs_write_seq(dsi, 0xc5, 0xcc);
+	dsi_dcs_write_seq(dsi, 0x00, 0xa0);
+	dsi_dcs_write_seq(dsi, 0xc4,
+			  0x05, 0x10, 0x06, 0x02, 0x05, 0x15, 0x10, 0x05, 0x10,
+			  0x07, 0x02, 0x05, 0x15, 0x10);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb0);
+	dsi_dcs_write_seq(dsi, 0xc4, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0x91);
+	dsi_dcs_write_seq(dsi, 0xc5, 0x19, 0x52);
+	dsi_dcs_write_seq(dsi, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xd8, 0xbc, 0xbc);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb3);
+	dsi_dcs_write_seq(dsi, 0xc5, 0x84);
+	dsi_dcs_write_seq(dsi, 0x00, 0xbb);
+	dsi_dcs_write_seq(dsi, 0xc5, 0x8a);
+	dsi_dcs_write_seq(dsi, 0x00, 0x82);
+	dsi_dcs_write_seq(dsi, 0xc4, 0x0a);
+	dsi_dcs_write_seq(dsi, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xe1,
+			  0x05, 0x44, 0x54, 0x61, 0x72, 0x7f, 0x81, 0xa9, 0x98,
+			  0xb0, 0x55, 0x41, 0x56, 0x38, 0x3a, 0x2e, 0x23, 0x19,
+			  0x0c, 0x05);
+	dsi_dcs_write_seq(dsi, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xe2,
+			  0x05, 0x44, 0x54, 0x61, 0x72, 0x80, 0x80, 0xa9, 0x99,
+			  0xb0, 0x54, 0x41, 0x56, 0x38, 0x3a, 0x2f, 0x23, 0x1a,
+			  0x0d, 0x05);
+	dsi_dcs_write_seq(dsi, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xd9, 0x71);
+	dsi_dcs_write_seq(dsi, 0x00, 0x80);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0x90);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xa0);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb0);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xc0);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xd0);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05,
+			  0x05, 0x05, 0x05, 0x05, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xe0);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x05, 0x05);
+	dsi_dcs_write_seq(dsi, 0x00, 0xf0);
+	dsi_dcs_write_seq(dsi, 0xcb,
+			  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			  0xff, 0xff);
+	dsi_dcs_write_seq(dsi, 0x00, 0x80);
+	dsi_dcs_write_seq(dsi, 0xcc,
+			  0x09, 0x0b, 0x0d, 0x0f, 0x01, 0x03, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0x90);
+	dsi_dcs_write_seq(dsi, 0xcc,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x2d, 0x0a, 0x0c,
+			  0x0e, 0x10, 0x02, 0x04, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xa0);
+	dsi_dcs_write_seq(dsi, 0xcc,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x2e, 0x2d);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb0);
+	dsi_dcs_write_seq(dsi, 0xcc,
+			  0x10, 0x0e, 0x0c, 0x0a, 0x04, 0x02, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xc0);
+	dsi_dcs_write_seq(dsi, 0xcc,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2e, 0x0f, 0x0d,
+			  0x0b, 0x09, 0x03, 0x01, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xd0);
+	dsi_dcs_write_seq(dsi, 0xcc,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x2d, 0x2e);
+	dsi_dcs_write_seq(dsi, 0x00, 0x80);
+	dsi_dcs_write_seq(dsi, 0xce,
+			  0x8b, 0x03, 0x00, 0x8a, 0x03, 0x00, 0x89, 0x03, 0x00,
+			  0x88, 0x03, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0x90);
+	dsi_dcs_write_seq(dsi, 0xce,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xa0);
+	dsi_dcs_write_seq(dsi, 0xce,
+			  0x38, 0x07, 0x84, 0xfc, 0x8b, 0x04, 0x00, 0x38, 0x06,
+			  0x84, 0xfd, 0x8b, 0x04, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb0);
+	dsi_dcs_write_seq(dsi, 0xce,
+			  0x38, 0x05, 0x84, 0xfe, 0x8b, 0x04, 0x00, 0x38, 0x04,
+			  0x84, 0xff, 0x8b, 0x04, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xc0);
+	dsi_dcs_write_seq(dsi, 0xce,
+			  0x38, 0x03, 0x85, 0x00, 0x8b, 0x04, 0x00, 0x38, 0x02,
+			  0x85, 0x01, 0x8b, 0x04, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xd0);
+	dsi_dcs_write_seq(dsi, 0xce,
+			  0x38, 0x01, 0x85, 0x02, 0x8b, 0x04, 0x00, 0x38, 0x00,
+			  0x85, 0x03, 0x8b, 0x04, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0x80);
+	dsi_dcs_write_seq(dsi, 0xcf,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0x90);
+	dsi_dcs_write_seq(dsi, 0xcf,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xa0);
+	dsi_dcs_write_seq(dsi, 0xcf,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb0);
+	dsi_dcs_write_seq(dsi, 0xcf,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x00, 0xc0);
+	dsi_dcs_write_seq(dsi, 0xcf,
+			  0x01, 0x01, 0x20, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
+			  0x02, 0x02);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb5);
+	dsi_dcs_write_seq(dsi, 0xc5, 0x33, 0xf1, 0xff, 0x33, 0xf1, 0xff);
+	dsi_dcs_write_seq(dsi, 0x00, 0xb1);
+	dsi_dcs_write_seq(dsi, 0xc6, 0x05);
+	dsi_dcs_write_seq(dsi, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0x35, 0x01);
+	dsi_dcs_write_seq(dsi, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xff, 0xff, 0xff, 0xff);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int booyi_otm1287_off(struct booyi_otm1287 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int booyi_otm1287_prepare(struct drm_panel *panel)
+{
+	struct booyi_otm1287 *ctx = to_booyi_otm1287(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	booyi_otm1287_reset(ctx);
+
+	ret = booyi_otm1287_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int booyi_otm1287_unprepare(struct drm_panel *panel)
+{
+	struct booyi_otm1287 *ctx = to_booyi_otm1287(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = booyi_otm1287_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode booyi_otm1287_mode = {
+	.clock = (720 + 90 + 10 + 90) * (1280 + 20 + 4 + 16) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 90,
+	.hsync_end = 720 + 90 + 10,
+	.htotal = 720 + 90 + 10 + 90,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 20,
+	.vsync_end = 1280 + 20 + 4,
+	.vtotal = 1280 + 20 + 4 + 16,
+	.width_mm = 62,
+	.height_mm = 110,
+};
+
+static int booyi_otm1287_get_modes(struct drm_panel *panel,
+				   struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &booyi_otm1287_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs booyi_otm1287_panel_funcs = {
+	.prepare = booyi_otm1287_prepare,
+	.unprepare = booyi_otm1287_unprepare,
+	.get_modes = booyi_otm1287_get_modes,
+};
+
+static int booyi_otm1287_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct booyi_otm1287 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			  MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &booyi_otm1287_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int booyi_otm1287_remove(struct mipi_dsi_device *dsi)
+{
+	struct booyi_otm1287 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id booyi_otm1287_of_match[] = {
+	{ .compatible = "longcheer,booyi-otm1287" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, booyi_otm1287_of_match);
+
+static struct mipi_dsi_driver booyi_otm1287_driver = {
+	.probe = booyi_otm1287_probe,
+	.remove = booyi_otm1287_remove,
+	.driver = {
+		.name = "panel-booyi-otm1287",
+		.of_match_table = booyi_otm1287_of_match,
+	},
+};
+module_mipi_dsi_driver(booyi_otm1287_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for booyi OTM1287 720p video mode dsi panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-truly-otm1288a.c b/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-truly-otm1288a.c
new file mode 100644
index 000000000..455bcb434
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-truly-otm1288a.c
@@ -0,0 +1,430 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct truly_otm1288a {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct truly_otm1288a *to_truly_otm1288a(struct drm_panel *panel)
+{
+	return container_of(panel, struct truly_otm1288a, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void truly_otm1288a_reset(struct truly_otm1288a *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+}
+
+static int truly_otm1288a_on(struct truly_otm1288a *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0x12, 0x88, 0x01);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xff, 0x12, 0x88);
+	dsi_generic_write_seq(dsi, 0x00, 0xa0);
+	dsi_generic_write_seq(dsi, 0xf6, 0x02);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xc0,
+			      0x00, 0x64, 0x00, 0x10, 0x10, 0x00, 0x64, 0x10,
+			      0x10);
+	dsi_generic_write_seq(dsi, 0x00, 0x90);
+	dsi_generic_write_seq(dsi, 0xc0, 0x00, 0x00, 0x00, 0x14, 0x00, 0x1b);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x1c, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc0);
+	dsi_generic_write_seq(dsi, 0xb0, 0x4d);
+	dsi_generic_write_seq(dsi, 0x00, 0xa3);
+	dsi_generic_write_seq(dsi, 0xc0, 0x25);
+	dsi_generic_write_seq(dsi, 0x00, 0xb3);
+	dsi_generic_write_seq(dsi, 0xc0, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xc4, 0x43);
+	dsi_generic_write_seq(dsi, 0x00, 0xa2);
+	dsi_generic_write_seq(dsi, 0xc1, 0x41);
+	dsi_generic_write_seq(dsi, 0x00, 0xb6);
+	dsi_generic_write_seq(dsi, 0xb0, 0x18);
+	dsi_generic_write_seq(dsi, 0x00, 0x92);
+	dsi_generic_write_seq(dsi, 0xff, 0x30, 0x02);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xc5, 0x53);
+	dsi_generic_write_seq(dsi, 0x00, 0x93);
+	dsi_generic_write_seq(dsi, 0xc5, 0x66);
+	dsi_generic_write_seq(dsi, 0x00, 0xa0);
+	dsi_generic_write_seq(dsi, 0xc4,
+			      0x05, 0x10, 0x06, 0x02, 0x05, 0x15, 0x10, 0x05,
+			      0x10, 0x07, 0x02, 0x05, 0x15, 0x10);
+	dsi_generic_write_seq(dsi, 0x00, 0xb0);
+	dsi_generic_write_seq(dsi, 0xc4, 0x00, 0x00, 0x03);
+	dsi_generic_write_seq(dsi, 0x00, 0x91);
+	dsi_generic_write_seq(dsi, 0xc5, 0x3d, 0xa6);
+	dsi_generic_write_seq(dsi, 0x00, 0xc2);
+	dsi_generic_write_seq(dsi, 0xc5, 0xb1);
+	dsi_generic_write_seq(dsi, 0x00, 0xe1);
+	dsi_generic_write_seq(dsi, 0xf5, 0x55);
+	dsi_generic_write_seq(dsi, 0x00, 0xc2);
+	dsi_generic_write_seq(dsi, 0xf5, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc4);
+	dsi_generic_write_seq(dsi, 0xf5, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc6);
+	dsi_generic_write_seq(dsi, 0xf5, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xf3);
+	dsi_generic_write_seq(dsi, 0xcf, 0x34);
+	dsi_generic_write_seq(dsi, 0x00, 0x83);
+	dsi_generic_write_seq(dsi, 0xc5, 0x30);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xd0, 0x40);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xd1, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x90);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xa0);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xb0);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc0);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+			      0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xd0);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05,
+			      0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05);
+	dsi_generic_write_seq(dsi, 0x00, 0xe0);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00, 0x05, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xf0);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			      0xff, 0xff, 0xff);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xcc,
+			      0x29, 0x2a, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
+			      0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x90);
+	dsi_generic_write_seq(dsi, 0xcc,
+			      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x29,
+			      0x2a, 0x09, 0x0b, 0x0d, 0x0f, 0x11, 0x13);
+	dsi_generic_write_seq(dsi, 0x00, 0xa0);
+	dsi_generic_write_seq(dsi, 0xcc,
+			      0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00, 0x01, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xb0);
+	dsi_generic_write_seq(dsi, 0xcc,
+			      0x29, 0x2a, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09,
+			      0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc0);
+	dsi_generic_write_seq(dsi, 0xcc,
+			      0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x29,
+			      0x2a, 0x14, 0x12, 0x10, 0x0e, 0x0c, 0x0a);
+	dsi_generic_write_seq(dsi, 0x00, 0xd0);
+	dsi_generic_write_seq(dsi, 0xcc,
+			      0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00, 0x06, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xce,
+			      0x87, 0x05, 0x10, 0x86, 0x05, 0x10, 0x00, 0x00,
+			      0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x90);
+	dsi_generic_write_seq(dsi, 0xce,
+			      0x54, 0xff, 0x10, 0x55, 0x00, 0x10, 0x55, 0x03,
+			      0x10, 0x55, 0x04, 0x10, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xa0);
+	dsi_generic_write_seq(dsi, 0xce,
+			      0x58, 0x05, 0x04, 0xff, 0x00, 0x10, 0x00, 0x58,
+			      0x04, 0x05, 0x00, 0x00, 0x10, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xb0);
+	dsi_generic_write_seq(dsi, 0xce,
+			      0x58, 0x03, 0x05, 0x01, 0x00, 0x10, 0x00, 0x58,
+			      0x02, 0x05, 0x02, 0x00, 0x10, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc0);
+	dsi_generic_write_seq(dsi, 0xce,
+			      0x58, 0x01, 0x05, 0x03, 0x00, 0x10, 0x00, 0x58,
+			      0x00, 0x05, 0x04, 0x00, 0x10, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xd0);
+	dsi_generic_write_seq(dsi, 0xce,
+			      0x50, 0x00, 0x05, 0x05, 0x00, 0x10, 0x00, 0x50,
+			      0x01, 0x05, 0x06, 0x00, 0x10, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xcf,
+			      0x50, 0x02, 0x05, 0x07, 0x00, 0x10, 0x00, 0x50,
+			      0x03, 0x05, 0x08, 0x00, 0x10, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x90);
+	dsi_generic_write_seq(dsi, 0xcf,
+			      0x50, 0x04, 0x05, 0x09, 0x00, 0x10, 0x00, 0x50,
+			      0x05, 0x05, 0x0a, 0x00, 0x10, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc0);
+	dsi_generic_write_seq(dsi, 0xcf,
+			      0x3d, 0x20, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00,
+			      0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0x92);
+	dsi_generic_write_seq(dsi, 0xf5, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x00, 0xc8);
+	dsi_generic_write_seq(dsi, 0xf5, 0x0b, 0x15);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xd8, 0xb6, 0xb6);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xe1,
+			      0x02, 0x27, 0x35, 0x45, 0x54, 0x62, 0x64, 0x8c,
+			      0x7b, 0x93, 0x72, 0x5d, 0x6e, 0x48, 0x45, 0x3a,
+			      0x2d, 0x27, 0x21, 0x1f);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xe2,
+			      0x02, 0x27, 0x35, 0x45, 0x54, 0x62, 0x64, 0x8c,
+			      0x7b, 0x93, 0x72, 0x5d, 0x6e, 0x48, 0x45, 0x3a,
+			      0x2d, 0x27, 0x21, 0x1f);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0xff, 0xff, 0xff);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int truly_otm1288a_off(struct truly_otm1288a *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int truly_otm1288a_prepare(struct drm_panel *panel)
+{
+	struct truly_otm1288a *ctx = to_truly_otm1288a(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	truly_otm1288a_reset(ctx);
+
+	ret = truly_otm1288a_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int truly_otm1288a_unprepare(struct drm_panel *panel)
+{
+	struct truly_otm1288a *ctx = to_truly_otm1288a(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = truly_otm1288a_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode truly_otm1288a_mode = {
+	.clock = (720 + 40 + 12 + 30) * (1280 + 40 + 2 + 11) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 40,
+	.hsync_end = 720 + 40 + 12,
+	.htotal = 720 + 40 + 12 + 30,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 40,
+	.vsync_end = 1280 + 40 + 2,
+	.vtotal = 1280 + 40 + 2 + 11,
+	.width_mm = 62,
+	.height_mm = 111,
+};
+
+static int truly_otm1288a_get_modes(struct drm_panel *panel,
+				    struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &truly_otm1288a_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs truly_otm1288a_panel_funcs = {
+	.prepare = truly_otm1288a_prepare,
+	.unprepare = truly_otm1288a_unprepare,
+	.get_modes = truly_otm1288a_get_modes,
+};
+
+static int truly_otm1288a_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct truly_otm1288a *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &truly_otm1288a_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int truly_otm1288a_remove(struct mipi_dsi_device *dsi)
+{
+	struct truly_otm1288a *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id truly_otm1288a_of_match[] = {
+	{ .compatible = "longcheer,truly-otm1288a" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, truly_otm1288a_of_match);
+
+static struct mipi_dsi_driver truly_otm1288a_driver = {
+	.probe = truly_otm1288a_probe,
+	.remove = truly_otm1288a_remove,
+	.driver = {
+		.name = "panel-truly-otm1288a",
+		.of_match_table = truly_otm1288a_of_match,
+	},
+};
+module_mipi_dsi_driver(truly_otm1288a_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for truly OTM1288A command mode dsi panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-yushun-nt35520.c b/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-yushun-nt35520.c
new file mode 100644
index 000000000..361cdb163
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-longcheer-yushun-nt35520.c
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct yushun_nt35520 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct yushun_nt35520 *to_yushun_nt35520(struct drm_panel *panel)
+{
+	return container_of(panel, struct yushun_nt35520, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void yushun_nt35520_reset(struct yushun_nt35520 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+}
+
+static int yushun_nt35520_on(struct yushun_nt35520 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0xaa, 0x55, 0xa5, 0x80);
+	dsi_generic_write_seq(dsi, 0x6f, 0x13);
+	dsi_generic_write_seq(dsi, 0xf7, 0x00);
+	dsi_generic_write_seq(dsi, 0x6f, 0x01);
+	dsi_generic_write_seq(dsi, 0xf3, 0x00);
+	dsi_generic_write_seq(dsi, 0xb1, 0x68, 0x21);
+	dsi_generic_write_seq(dsi, 0xbd, 0x02, 0x67, 0x20, 0x20, 0x00);
+	dsi_generic_write_seq(dsi, 0x6f, 0x02);
+	dsi_generic_write_seq(dsi, 0xb8, 0x08);
+	dsi_generic_write_seq(dsi, 0xbb, 0x11, 0x11);
+	dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xb6, 0x01);
+	dsi_generic_write_seq(dsi, 0xc8, 0x83);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x01);
+	dsi_generic_write_seq(dsi, 0xb0, 0x0f, 0x0f);
+	dsi_generic_write_seq(dsi, 0xb1, 0x0f, 0x0f);
+	dsi_generic_write_seq(dsi, 0xce, 0x66);
+	dsi_generic_write_seq(dsi, 0xc0, 0x0c);
+	dsi_generic_write_seq(dsi, 0xb5, 0x05, 0x05);
+	dsi_generic_write_seq(dsi, 0xbe, 0x3e);
+	dsi_generic_write_seq(dsi, 0xb3, 0x28, 0x28);
+	dsi_generic_write_seq(dsi, 0xb4, 0x19, 0x19);
+	dsi_generic_write_seq(dsi, 0xb9, 0x34, 0x34);
+	dsi_generic_write_seq(dsi, 0xba, 0x24, 0x24);
+	dsi_generic_write_seq(dsi, 0xbc, 0x70, 0x00);
+	dsi_generic_write_seq(dsi, 0xbd, 0x70, 0x00);
+	dsi_generic_write_seq(dsi, 0xca, 0x00);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x02);
+	dsi_generic_write_seq(dsi, 0xee, 0x00);
+	dsi_generic_write_seq(dsi, 0xb0,
+			      0x00, 0xd2, 0x00, 0xde, 0x00, 0xf0, 0x01, 0x01,
+			      0x01, 0x11, 0x01, 0x29, 0x01, 0x41, 0x01, 0x68);
+	dsi_generic_write_seq(dsi, 0xb1,
+			      0x01, 0x87, 0x01, 0xb8, 0x01, 0xe2, 0x02, 0x23,
+			      0x02, 0x57, 0x02, 0x5a, 0x02, 0x8e, 0x02, 0xc6);
+	dsi_generic_write_seq(dsi, 0xb2,
+			      0x02, 0xef, 0x03, 0x20, 0x03, 0x3e, 0x03, 0x63,
+			      0x03, 0x7e, 0x03, 0x9c, 0x03, 0xaf, 0x03, 0xbf);
+	dsi_generic_write_seq(dsi, 0xb3, 0x03, 0xfc, 0x03, 0xff);
+	dsi_generic_write_seq(dsi, 0xb4,
+			      0x00, 0x07, 0x00, 0x50, 0x00, 0x84, 0x00, 0xa6,
+			      0x00, 0xc1, 0x00, 0xe7, 0x01, 0x08, 0x01, 0x3b);
+	dsi_generic_write_seq(dsi, 0xb5,
+			      0x01, 0x63, 0x01, 0xa0, 0x01, 0xcf, 0x02, 0x18,
+			      0x02, 0x50, 0x02, 0x52, 0x02, 0x88, 0x02, 0xc1);
+	dsi_generic_write_seq(dsi, 0xb6,
+			      0x02, 0xea, 0x03, 0x1b, 0x03, 0x3a, 0x03, 0x60,
+			      0x03, 0x79, 0x03, 0x98, 0x03, 0xa9, 0x03, 0xc6);
+	dsi_generic_write_seq(dsi, 0xb7, 0x03, 0xd6, 0x03, 0xff);
+	dsi_generic_write_seq(dsi, 0xb8,
+			      0x00, 0xb6, 0x00, 0xc1, 0x00, 0xd3, 0x00, 0xe5,
+			      0x00, 0xf5, 0x01, 0x0f, 0x01, 0x29, 0x01, 0x51);
+	dsi_generic_write_seq(dsi, 0xb9,
+			      0x01, 0x73, 0x01, 0xa9, 0x01, 0xd6, 0x02, 0x1c,
+			      0x02, 0x52, 0x02, 0x55, 0x02, 0x8a, 0x02, 0xc4);
+	dsi_generic_write_seq(dsi, 0xba,
+			      0x02, 0xef, 0x03, 0x24, 0x03, 0x4b, 0x03, 0x73,
+			      0x03, 0x87, 0x03, 0x9f, 0x03, 0xa3, 0x03, 0xbd);
+	dsi_generic_write_seq(dsi, 0xbb, 0x03, 0xf2, 0x03, 0xff);
+	dsi_generic_write_seq(dsi, 0xbc,
+			      0x00, 0xd2, 0x00, 0xde, 0x00, 0xf0, 0x01, 0x01,
+			      0x01, 0x11, 0x01, 0x29, 0x01, 0x41, 0x01, 0x68);
+	dsi_generic_write_seq(dsi, 0xbd,
+			      0x01, 0x87, 0x01, 0xb8, 0x01, 0xe2, 0x02, 0x23,
+			      0x02, 0x57, 0x02, 0x5a, 0x02, 0x8e, 0x02, 0xc6);
+	dsi_generic_write_seq(dsi, 0xbe,
+			      0x02, 0xef, 0x03, 0x20, 0x03, 0x3e, 0x03, 0x63,
+			      0x03, 0x7e, 0x03, 0x9c, 0x03, 0xaf, 0x03, 0xbf);
+	dsi_generic_write_seq(dsi, 0xbf, 0x03, 0xfc, 0x03, 0xff);
+	dsi_generic_write_seq(dsi, 0xc0,
+			      0x00, 0x07, 0x00, 0x50, 0x00, 0x84, 0x00, 0xa6,
+			      0x00, 0xc1, 0x00, 0xe7, 0x01, 0x08, 0x01, 0x3b);
+	dsi_generic_write_seq(dsi, 0xc1,
+			      0x01, 0x63, 0x01, 0xa0, 0x01, 0xcf, 0x02, 0x18,
+			      0x02, 0x50, 0x02, 0x52, 0x02, 0x88, 0x02, 0xc1);
+	dsi_generic_write_seq(dsi, 0xc2,
+			      0x02, 0xea, 0x03, 0x1b, 0x03, 0x3a, 0x03, 0x60,
+			      0x03, 0x79, 0x03, 0x98, 0x03, 0xa9, 0x03, 0xc6);
+	dsi_generic_write_seq(dsi, 0xc3, 0x03, 0xd6, 0x03, 0xff);
+	dsi_generic_write_seq(dsi, 0xc4,
+			      0x00, 0xb6, 0x00, 0xc1, 0x00, 0xd3, 0x00, 0xe5,
+			      0x00, 0xf5, 0x01, 0x0f, 0x01, 0x29, 0x01, 0x51);
+	dsi_generic_write_seq(dsi, 0xc5,
+			      0x01, 0x73, 0x01, 0xa9, 0x01, 0xd6, 0x02, 0x1c,
+			      0x02, 0x52, 0x02, 0x55, 0x02, 0x8a, 0x02, 0xc4);
+	dsi_generic_write_seq(dsi, 0xc6,
+			      0x02, 0xef, 0x03, 0x24, 0x03, 0x4b, 0x03, 0x73,
+			      0x03, 0x87, 0x03, 0x9f, 0x03, 0xa3, 0x03, 0xbd);
+	dsi_generic_write_seq(dsi, 0xc7, 0x03, 0xf2, 0x03, 0xff);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x06);
+	dsi_generic_write_seq(dsi, 0xb0, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xb1, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xb2, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xb3, 0x2e, 0x09);
+	dsi_generic_write_seq(dsi, 0xb4, 0x0b, 0x23);
+	dsi_generic_write_seq(dsi, 0xb5, 0x1d, 0x1f);
+	dsi_generic_write_seq(dsi, 0xb6, 0x11, 0x17);
+	dsi_generic_write_seq(dsi, 0xb7, 0x13, 0x19);
+	dsi_generic_write_seq(dsi, 0xb8, 0x01, 0x03);
+	dsi_generic_write_seq(dsi, 0xb9, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xba, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xbb, 0x02, 0x00);
+	dsi_generic_write_seq(dsi, 0xbc, 0x18, 0x12);
+	dsi_generic_write_seq(dsi, 0xbd, 0x16, 0x10);
+	dsi_generic_write_seq(dsi, 0xbe, 0x1e, 0x1c);
+	dsi_generic_write_seq(dsi, 0xbf, 0x22, 0x0a);
+	dsi_generic_write_seq(dsi, 0xc0, 0x08, 0x2e);
+	dsi_generic_write_seq(dsi, 0xc1, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xc2, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xc3, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xe5, 0x25, 0x24);
+	dsi_generic_write_seq(dsi, 0xc4, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xc5, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xc6, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xc7, 0x2e, 0x02);
+	dsi_generic_write_seq(dsi, 0xc8, 0x00, 0x24);
+	dsi_generic_write_seq(dsi, 0xc9, 0x1e, 0x1c);
+	dsi_generic_write_seq(dsi, 0xca, 0x18, 0x12);
+	dsi_generic_write_seq(dsi, 0xcb, 0x16, 0x10);
+	dsi_generic_write_seq(dsi, 0xcc, 0x0a, 0x08);
+	dsi_generic_write_seq(dsi, 0xcd, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xce, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xcf, 0x09, 0x0b);
+	dsi_generic_write_seq(dsi, 0xd0, 0x11, 0x17);
+	dsi_generic_write_seq(dsi, 0xd1, 0x13, 0x19);
+	dsi_generic_write_seq(dsi, 0xd2, 0x1d, 0x1f);
+	dsi_generic_write_seq(dsi, 0xd3, 0x25, 0x01);
+	dsi_generic_write_seq(dsi, 0xd4, 0x03, 0x2e);
+	dsi_generic_write_seq(dsi, 0xd5, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xd6, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xd7, 0x2e, 0x2e);
+	dsi_generic_write_seq(dsi, 0xe6, 0x22, 0x23);
+	dsi_generic_write_seq(dsi, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xe7, 0x00);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+	dsi_generic_write_seq(dsi, 0xed, 0x30);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+	dsi_generic_write_seq(dsi, 0xb0, 0x20, 0x00);
+	dsi_generic_write_seq(dsi, 0xb1, 0x20, 0x00);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+	dsi_generic_write_seq(dsi, 0xb0, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xb8, 0x00);
+	dsi_generic_write_seq(dsi, 0xbd, 0x0f, 0x03, 0x03, 0x00, 0x03);
+	dsi_generic_write_seq(dsi, 0xb1, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xb9, 0x00, 0x03);
+	dsi_generic_write_seq(dsi, 0xb2, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xba, 0x00, 0x03);
+	dsi_generic_write_seq(dsi, 0xb3, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xbb, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xb4, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xb5, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xb6, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xb7, 0x17, 0x06);
+	dsi_generic_write_seq(dsi, 0xbc, 0x00, 0x01);
+	dsi_generic_write_seq(dsi, 0xe5, 0x06);
+	dsi_generic_write_seq(dsi, 0xe6, 0x06);
+	dsi_generic_write_seq(dsi, 0xe7, 0x06);
+	dsi_generic_write_seq(dsi, 0xe8, 0x06);
+	dsi_generic_write_seq(dsi, 0xe9, 0x0a);
+	dsi_generic_write_seq(dsi, 0xea, 0x06);
+	dsi_generic_write_seq(dsi, 0xeb, 0x06);
+	dsi_generic_write_seq(dsi, 0xec, 0x06);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+	dsi_generic_write_seq(dsi, 0xc0, 0x07);
+	dsi_generic_write_seq(dsi, 0xc1, 0x05);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+	dsi_generic_write_seq(dsi, 0xb2, 0x04, 0x00, 0x52, 0x01, 0xce);
+	dsi_generic_write_seq(dsi, 0xb3, 0x04, 0x00, 0x52, 0x01, 0xce);
+	msleep(120);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+	dsi_generic_write_seq(dsi, 0xc4, 0x82);
+	dsi_generic_write_seq(dsi, 0xc5, 0x80);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+	dsi_generic_write_seq(dsi, 0xb6, 0x04, 0x00, 0x52, 0x01, 0xce);
+	dsi_generic_write_seq(dsi, 0xb7, 0x04, 0x00, 0x52, 0x01, 0xce);
+	msleep(120);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+	dsi_generic_write_seq(dsi, 0xc8, 0x03, 0x20);
+	dsi_generic_write_seq(dsi, 0xc9, 0x01, 0x21);
+	dsi_generic_write_seq(dsi, 0xca, 0x03, 0x20);
+	dsi_generic_write_seq(dsi, 0xcb, 0x07, 0x20);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+	dsi_generic_write_seq(dsi, 0xc4, 0x60);
+	dsi_generic_write_seq(dsi, 0xc5, 0x40);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+	dsi_generic_write_seq(dsi, 0xba, 0x44, 0x00, 0x4b, 0x01, 0xbe);
+	dsi_generic_write_seq(dsi, 0xbb, 0x44, 0x00, 0x4b, 0x01, 0xbe);
+	dsi_generic_write_seq(dsi, 0xbc, 0x53, 0x00, 0x03, 0x00, 0x4b);
+	dsi_generic_write_seq(dsi, 0xbd, 0x53, 0x00, 0x03, 0x00, 0x4b);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x05);
+	dsi_generic_write_seq(dsi, 0xd1,
+			      0x03, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xd2,
+			      0x03, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xd3,
+			      0x03, 0x05, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xd4,
+			      0x03, 0x05, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00,
+			      0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x03);
+	dsi_generic_write_seq(dsi, 0xc4, 0x40);
+	dsi_generic_write_seq(dsi, 0xc5, 0x40);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int yushun_nt35520_off(struct yushun_nt35520 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int yushun_nt35520_prepare(struct drm_panel *panel)
+{
+	struct yushun_nt35520 *ctx = to_yushun_nt35520(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	yushun_nt35520_reset(ctx);
+
+	ret = yushun_nt35520_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int yushun_nt35520_unprepare(struct drm_panel *panel)
+{
+	struct yushun_nt35520 *ctx = to_yushun_nt35520(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = yushun_nt35520_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode yushun_nt35520_mode = {
+	.clock = (720 + 90 + 12 + 88) * (1280 + 20 + 4 + 16) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 90,
+	.hsync_end = 720 + 90 + 12,
+	.htotal = 720 + 90 + 12 + 88,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 20,
+	.vsync_end = 1280 + 20 + 4,
+	.vtotal = 1280 + 20 + 4 + 16,
+	.width_mm = 62,
+	.height_mm = 111,
+};
+
+static int yushun_nt35520_get_modes(struct drm_panel *panel,
+				    struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &yushun_nt35520_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs yushun_nt35520_panel_funcs = {
+	.prepare = yushun_nt35520_prepare,
+	.unprepare = yushun_nt35520_unprepare,
+	.get_modes = yushun_nt35520_get_modes,
+};
+
+static int yushun_nt35520_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct yushun_nt35520 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &yushun_nt35520_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int yushun_nt35520_remove(struct mipi_dsi_device *dsi)
+{
+	struct yushun_nt35520 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id yushun_nt35520_of_match[] = {
+	{ .compatible = "longcheer,yushun-nt35520" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, yushun_nt35520_of_match);
+
+static struct mipi_dsi_driver yushun_nt35520_driver = {
+	.probe = yushun_nt35520_probe,
+	.remove = yushun_nt35520_remove,
+	.driver = {
+		.name = "panel-yushun-nt35520",
+		.of_match_table = yushun_nt35520_of_match,
+	},
+};
+module_mipi_dsi_driver(yushun_nt35520_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for yushun NT35520 720p command mode panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-boe.c b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-boe.c
new file mode 100644
index 000000000..22c7e6a8b
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-boe.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct boe_499_v1 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *backlight_gpio;
+	bool prepared;
+};
+
+static inline struct boe_499_v1 *to_boe_499_v1(struct drm_panel *panel)
+{
+	return container_of(panel, struct boe_499_v1, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void boe_499_v1_reset(struct boe_499_v1 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(50);
+}
+
+static int boe_499_v1_on(struct boe_499_v1 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_dcs_write_seq(dsi, 0xb9, 0xff, 0x83, 0x94);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x0000);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display brightness: %d\n", ret);
+		return ret;
+	}
+	usleep_range(5000, 6000);
+
+	dsi_dcs_write_seq(dsi, 0xc9,
+			  0x13, 0x00, 0x00, 0x14, 0xb1, 0x1e, 0x00, 0x91, 0x00);
+	usleep_range(5000, 6000);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x01);
+	usleep_range(5000, 6000);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	usleep_range(10000, 11000);
+
+	return 0;
+}
+
+static int boe_499_v1_off(struct boe_499_v1 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(35);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int boe_499_v1_prepare(struct drm_panel *panel)
+{
+	struct boe_499_v1 *ctx = to_boe_499_v1(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	boe_499_v1_reset(ctx);
+
+	ret = boe_499_v1_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int boe_499_v1_unprepare(struct drm_panel *panel)
+{
+	struct boe_499_v1 *ctx = to_boe_499_v1(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = boe_499_v1_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode boe_499_v1_mode = {
+	.clock = (720 + 52 + 20 + 84) * (1280 + 20 + 8 + 20) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 52,
+	.hsync_end = 720 + 52 + 20,
+	.htotal = 720 + 52 + 20 + 84,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 20,
+	.vsync_end = 1280 + 20 + 8,
+	.vtotal = 1280 + 20 + 8 + 20,
+	.width_mm = 62,
+	.height_mm = 110,
+};
+
+static int boe_499_v1_get_modes(struct drm_panel *panel,
+				struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &boe_499_v1_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs boe_499_v1_panel_funcs = {
+	.prepare = boe_499_v1_prepare,
+	.unprepare = boe_499_v1_unprepare,
+	.get_modes = boe_499_v1_get_modes,
+};
+
+static int boe_499_v1_bl_update_status(struct backlight_device *bl)
+{
+	struct mipi_dsi_device *dsi = bl_get_data(bl);
+	struct boe_499_v1 *ctx = mipi_dsi_get_drvdata(dsi);
+	u16 brightness = backlight_get_brightness(bl);
+	int ret;
+
+	gpiod_set_value_cansleep(ctx->backlight_gpio, !!brightness);
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+	if (ret < 0)
+		return ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	return 0;
+}
+
+static const struct backlight_ops boe_499_v1_bl_ops = {
+	.update_status = boe_499_v1_bl_update_status,
+};
+
+static struct backlight_device *
+boe_499_v1_create_backlight(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	const struct backlight_properties props = {
+		.type = BACKLIGHT_RAW,
+		.brightness = 255,
+		.max_brightness = 255,
+	};
+
+	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+					      &boe_499_v1_bl_ops, &props);
+}
+
+static int boe_499_v1_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct boe_499_v1 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vsp";
+	ctx->supplies[1].supply = "vsn";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->backlight_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_LOW);
+	if (IS_ERR(ctx->backlight_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->backlight_gpio),
+				     "Failed to get backlight-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &boe_499_v1_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ctx->panel.backlight = boe_499_v1_create_backlight(dsi);
+	if (IS_ERR(ctx->panel.backlight))
+		return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+				     "Failed to create backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int boe_499_v1_remove(struct mipi_dsi_device *dsi)
+{
+	struct boe_499_v1 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id boe_499_v1_of_match[] = {
+	{ .compatible = "motorola,harpia-panel-boe" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, boe_499_v1_of_match);
+
+static struct mipi_dsi_driver boe_499_v1_driver = {
+	.probe = boe_499_v1_probe,
+	.remove = boe_499_v1_remove,
+	.driver = {
+		.name = "panel-boe-499-v1",
+		.of_match_table = boe_499_v1_of_match,
+	},
+};
+module_mipi_dsi_driver(boe_499_v1_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for mipi_mot_video_boe_720p_499");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-tianma.c b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-tianma.c
new file mode 100644
index 000000000..785488885
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-harpia-tianma.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct tianma_499_v2 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *backlight_gpio;
+	bool prepared;
+};
+
+static inline struct tianma_499_v2 *to_tianma_499_v2(struct drm_panel *panel)
+{
+	return container_of(panel, struct tianma_499_v2, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void tianma_499_v2_reset(struct tianma_499_v2 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+}
+
+static int tianma_499_v2_on(struct tianma_499_v2 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_dcs_write_seq(dsi, 0xff, 0x98, 0x81, 0x00);
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x0000);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display brightness: %d\n", ret);
+		return ret;
+	}
+
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x01);
+	dsi_dcs_write_seq(dsi, 0x68, 0x06);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	msleep(20);
+
+	return 0;
+}
+
+static int tianma_499_v2_off(struct tianma_499_v2 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(20);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int tianma_499_v2_prepare(struct drm_panel *panel)
+{
+	struct tianma_499_v2 *ctx = to_tianma_499_v2(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	tianma_499_v2_reset(ctx);
+
+	ret = tianma_499_v2_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int tianma_499_v2_unprepare(struct drm_panel *panel)
+{
+	struct tianma_499_v2 *ctx = to_tianma_499_v2(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = tianma_499_v2_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode tianma_499_v2_mode = {
+	.clock = (720 + 52 + 20 + 84) * (1280 + 20 + 8 + 20) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 52,
+	.hsync_end = 720 + 52 + 20,
+	.htotal = 720 + 52 + 20 + 84,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 20,
+	.vsync_end = 1280 + 20 + 8,
+	.vtotal = 1280 + 20 + 8 + 20,
+	.width_mm = 62,
+	.height_mm = 110,
+};
+
+static int tianma_499_v2_get_modes(struct drm_panel *panel,
+				   struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &tianma_499_v2_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs tianma_499_v2_panel_funcs = {
+	.prepare = tianma_499_v2_prepare,
+	.unprepare = tianma_499_v2_unprepare,
+	.get_modes = tianma_499_v2_get_modes,
+};
+
+static int tianma_499_v2_bl_update_status(struct backlight_device *bl)
+{
+	struct mipi_dsi_device *dsi = bl_get_data(bl);
+	struct tianma_499_v2 *ctx = mipi_dsi_get_drvdata(dsi);
+	u16 brightness = backlight_get_brightness(bl);
+	int ret;
+
+	gpiod_set_value_cansleep(ctx->backlight_gpio, !!brightness);
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+	if (ret < 0)
+		return ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	return 0;
+}
+
+static const struct backlight_ops tianma_499_v2_bl_ops = {
+	.update_status = tianma_499_v2_bl_update_status,
+};
+
+static struct backlight_device *
+tianma_499_v2_create_backlight(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	const struct backlight_properties props = {
+		.type = BACKLIGHT_RAW,
+		.brightness = 4095,
+		.max_brightness = 4095,
+	};
+
+	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+					      &tianma_499_v2_bl_ops, &props);
+}
+
+static int tianma_499_v2_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct tianma_499_v2 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vsp";
+	ctx->supplies[1].supply = "vsn";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->backlight_gpio = devm_gpiod_get(dev, "backlight", GPIOD_OUT_LOW);
+	if (IS_ERR(ctx->backlight_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->backlight_gpio),
+				     "Failed to get backlight-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &tianma_499_v2_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ctx->panel.backlight = tianma_499_v2_create_backlight(dsi);
+	if (IS_ERR(ctx->panel.backlight))
+		return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+				     "Failed to create backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int tianma_499_v2_remove(struct mipi_dsi_device *dsi)
+{
+	struct tianma_499_v2 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id tianma_499_v2_of_match[] = {
+	{ .compatible = "motorola,harpia-panel-tianma" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tianma_499_v2_of_match);
+
+static struct mipi_dsi_driver tianma_499_v2_driver = {
+	.probe = tianma_499_v2_probe,
+	.remove = tianma_499_v2_remove,
+	.driver = {
+		.name = "panel-tianma-499-v2",
+		.of_match_table = tianma_499_v2_of_match,
+	},
+};
+module_mipi_dsi_driver(tianma_499_v2_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for mipi_mot_video_tianma_720p_499");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-osprey-inx.c b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-osprey-inx.c
new file mode 100644
index 000000000..cba1d3713
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-osprey-inx.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct inx_500_v0 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[3];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct inx_500_v0 *to_inx_500_v0(struct drm_panel *panel)
+{
+	return container_of(panel, struct inx_500_v0, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void inx_500_v0_reset(struct inx_500_v0 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+}
+
+static int inx_500_v0_on(struct inx_500_v0 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_generic_write_seq(dsi, 0xf0, 0x55, 0xaa, 0x52, 0x08, 0x00);
+	dsi_generic_write_seq(dsi, 0xe8,
+			      0xf3, 0xd9, 0xcc, 0xc0, 0xb8, 0xb0, 0xa0, 0xa0,
+			      0xa0, 0x9c);
+	dsi_generic_write_seq(dsi, 0xd9, 0x03, 0x06);
+	dsi_generic_write_seq(dsi, 0xea, 0x09);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00cf);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display brightness: %d\n", ret);
+		return ret;
+	}
+
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x01);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x03);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int inx_500_v0_off(struct inx_500_v0 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	usleep_range(17000, 18000);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int inx_500_v0_prepare(struct drm_panel *panel)
+{
+	struct inx_500_v0 *ctx = to_inx_500_v0(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	inx_500_v0_reset(ctx);
+
+	ret = inx_500_v0_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int inx_500_v0_unprepare(struct drm_panel *panel)
+{
+	struct inx_500_v0 *ctx = to_inx_500_v0(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = inx_500_v0_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode inx_500_v0_mode = {
+	.clock = (720 + 48 + 8 + 68) * (1280 + 52 + 6 + 50) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 48,
+	.hsync_end = 720 + 48 + 8,
+	.htotal = 720 + 48 + 8 + 68,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 52,
+	.vsync_end = 1280 + 52 + 6,
+	.vtotal = 1280 + 52 + 6 + 50,
+	.width_mm = 62,
+	.height_mm = 110,
+};
+
+static int inx_500_v0_get_modes(struct drm_panel *panel,
+				struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &inx_500_v0_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs inx_500_v0_panel_funcs = {
+	.prepare = inx_500_v0_prepare,
+	.unprepare = inx_500_v0_unprepare,
+	.get_modes = inx_500_v0_get_modes,
+};
+
+static int inx_500_v0_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct inx_500_v0 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vsp";
+	ctx->supplies[1].supply = "vsn";
+	ctx->supplies[2].supply = "vddio";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &inx_500_v0_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int inx_500_v0_remove(struct mipi_dsi_device *dsi)
+{
+	struct inx_500_v0 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id inx_500_v0_of_match[] = {
+	{ .compatible = "motorola,osprey-panel-inx" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, inx_500_v0_of_match);
+
+static struct mipi_dsi_driver inx_500_v0_driver = {
+	.probe = inx_500_v0_probe,
+	.remove = inx_500_v0_remove,
+	.driver = {
+		.name = "panel-inx-500-v0",
+		.of_match_table = inx_500_v0_of_match,
+	},
+};
+module_mipi_dsi_driver(inx_500_v0_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for mipi_mot_video_inx_720p_500_v0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-surnia-boe.c b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-surnia-boe.c
new file mode 100644
index 000000000..56408e12d
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-motorola-surnia-boe.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct boe_450_v3 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct boe_450_v3 *to_boe_450_v3(struct drm_panel *panel)
+{
+	return container_of(panel, struct boe_450_v3, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void boe_450_v3_reset(struct boe_450_v3 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(2000, 3000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(21);
+}
+
+static int boe_450_v3_on(struct boe_450_v3 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x02);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00ff);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display brightness: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	msleep(40);
+
+	return 0;
+}
+
+static int boe_450_v3_off(struct boe_450_v3 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	usleep_range(10000, 11000);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int boe_450_v3_prepare(struct drm_panel *panel)
+{
+	struct boe_450_v3 *ctx = to_boe_450_v3(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	boe_450_v3_reset(ctx);
+
+	ret = boe_450_v3_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int boe_450_v3_unprepare(struct drm_panel *panel)
+{
+	struct boe_450_v3 *ctx = to_boe_450_v3(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = boe_450_v3_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode boe_450_v3_mode = {
+	.clock = (540 + 24 + 4 + 40) * (960 + 16 + 2 + 16) * 60 / 1000,
+	.hdisplay = 540,
+	.hsync_start = 540 + 24,
+	.hsync_end = 540 + 24 + 4,
+	.htotal = 540 + 24 + 4 + 40,
+	.vdisplay = 960,
+	.vsync_start = 960 + 16,
+	.vsync_end = 960 + 16 + 2,
+	.vtotal = 960 + 16 + 2 + 16,
+	.width_mm = 55,
+	.height_mm = 99,
+};
+
+static int boe_450_v3_get_modes(struct drm_panel *panel,
+				struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &boe_450_v3_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs boe_450_v3_panel_funcs = {
+	.prepare = boe_450_v3_prepare,
+	.unprepare = boe_450_v3_unprepare,
+	.get_modes = boe_450_v3_get_modes,
+};
+
+static int boe_450_v3_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct boe_450_v3 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 2;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS |
+			  MIPI_DSI_MODE_LPM;
+
+	drm_panel_init(&ctx->panel, dev, &boe_450_v3_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int boe_450_v3_remove(struct mipi_dsi_device *dsi)
+{
+	struct boe_450_v3 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id boe_450_v3_of_match[] = {
+	{ .compatible = "motorola,surnia-panel-boe" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, boe_450_v3_of_match);
+
+static struct mipi_dsi_driver boe_450_v3_driver = {
+	.probe = boe_450_v3_probe,
+	.remove = boe_450_v3_remove,
+	.driver = {
+		.name = "panel-boe-450-v3",
+		.of_match_table = boe_450_v3_of_match,
+	},
+};
+module_mipi_dsi_driver(boe_450_v3_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for mipi_mot_video_boe_qhd_450_v3");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-oppo-15009-nt35592-jdi.c b/drivers/gpu/drm/panel/msm8916-generated/panel-oppo-15009-nt35592-jdi.c
new file mode 100644
index 000000000..b2c2a7886
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-oppo-15009-nt35592-jdi.c
@@ -0,0 +1,746 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct oppo15009jdi_nt35592 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline
+struct oppo15009jdi_nt35592 *to_oppo15009jdi_nt35592(struct drm_panel *panel)
+{
+	return container_of(panel, struct oppo15009jdi_nt35592, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void oppo15009jdi_nt35592_reset(struct oppo15009jdi_nt35592 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(15000, 16000);
+}
+
+static int oppo15009jdi_nt35592_on(struct oppo15009jdi_nt35592 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_generic_write_seq(dsi, 0xff, 0x01);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x00, 0x1a);
+	dsi_generic_write_seq(dsi, 0x02, 0x43);
+	dsi_generic_write_seq(dsi, 0x04, 0x43);
+	dsi_generic_write_seq(dsi, 0x08, 0x56);
+	dsi_generic_write_seq(dsi, 0x09, 0x00);
+	dsi_generic_write_seq(dsi, 0x0b, 0xb3);
+	dsi_generic_write_seq(dsi, 0x0c, 0xb3);
+	dsi_generic_write_seq(dsi, 0x0d, 0x2f);
+	dsi_generic_write_seq(dsi, 0x0e, 0x1b);
+	dsi_generic_write_seq(dsi, 0x0f, 0xa2);
+	dsi_generic_write_seq(dsi, 0x11, 0x7a);
+	dsi_generic_write_seq(dsi, 0x12, 0x03);
+	dsi_generic_write_seq(dsi, 0x37, 0x02);
+	dsi_generic_write_seq(dsi, 0x23, 0x00);
+	dsi_generic_write_seq(dsi, 0x24, 0x00);
+	dsi_generic_write_seq(dsi, 0x25, 0x00);
+	dsi_generic_write_seq(dsi, 0x26, 0x00);
+	dsi_generic_write_seq(dsi, 0x27, 0x00);
+	dsi_generic_write_seq(dsi, 0x28, 0x00);
+	dsi_generic_write_seq(dsi, 0x36, 0x00);
+	dsi_generic_write_seq(dsi, 0x6f, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0x05);
+	dsi_generic_write_seq(dsi, 0x02, 0x82);
+	dsi_generic_write_seq(dsi, 0x03, 0x82);
+	dsi_generic_write_seq(dsi, 0x04, 0x82);
+	dsi_generic_write_seq(dsi, 0x01, 0x00);
+	dsi_generic_write_seq(dsi, 0x05, 0x30);
+	dsi_generic_write_seq(dsi, 0x06, 0x33);
+	dsi_generic_write_seq(dsi, 0x07, 0x70);
+	dsi_generic_write_seq(dsi, 0x08, 0x00);
+	dsi_generic_write_seq(dsi, 0x11, 0x00);
+	dsi_generic_write_seq(dsi, 0x09, 0x00);
+	dsi_generic_write_seq(dsi, 0x0a, 0x01);
+	dsi_generic_write_seq(dsi, 0x0b, 0x70);
+	dsi_generic_write_seq(dsi, 0x0d, 0x04);
+	dsi_generic_write_seq(dsi, 0x0e, 0x1b);
+	dsi_generic_write_seq(dsi, 0x0f, 0x02);
+	dsi_generic_write_seq(dsi, 0x10, 0x32);
+	dsi_generic_write_seq(dsi, 0x12, 0x00);
+	dsi_generic_write_seq(dsi, 0x14, 0x00);
+	dsi_generic_write_seq(dsi, 0x16, 0x04);
+	dsi_generic_write_seq(dsi, 0x19, 0xff);
+	dsi_generic_write_seq(dsi, 0x1a, 0xff);
+	dsi_generic_write_seq(dsi, 0x1b, 0xff);
+	dsi_generic_write_seq(dsi, 0x1c, 0x80);
+	dsi_generic_write_seq(dsi, 0x1d, 0x00);
+	dsi_generic_write_seq(dsi, 0x1e, 0x00);
+	dsi_generic_write_seq(dsi, 0x1f, 0x77);
+	dsi_generic_write_seq(dsi, 0x21, 0x20);
+	dsi_generic_write_seq(dsi, 0x22, 0x55);
+	dsi_generic_write_seq(dsi, 0x23, 0x0d);
+	dsi_generic_write_seq(dsi, 0x24, 0x03);
+	dsi_generic_write_seq(dsi, 0x25, 0x53);
+	dsi_generic_write_seq(dsi, 0x26, 0x55);
+	dsi_generic_write_seq(dsi, 0x27, 0x35);
+	dsi_generic_write_seq(dsi, 0x28, 0x00);
+	dsi_generic_write_seq(dsi, 0x29, 0x01);
+	dsi_generic_write_seq(dsi, 0x2a, 0x11);
+	dsi_generic_write_seq(dsi, 0x2d, 0x02);
+	dsi_generic_write_seq(dsi, 0x2f, 0x00);
+	dsi_generic_write_seq(dsi, 0x30, 0x11);
+	dsi_generic_write_seq(dsi, 0x31, 0x20);
+	dsi_generic_write_seq(dsi, 0x32, 0x09);
+	dsi_generic_write_seq(dsi, 0x35, 0x0d);
+	dsi_generic_write_seq(dsi, 0x36, 0x00);
+	dsi_generic_write_seq(dsi, 0x37, 0x09);
+	dsi_generic_write_seq(dsi, 0x48, 0x40);
+	dsi_generic_write_seq(dsi, 0x49, 0x23);
+	dsi_generic_write_seq(dsi, 0x4a, 0xc1);
+	dsi_generic_write_seq(dsi, 0x6f, 0x25);
+	dsi_generic_write_seq(dsi, 0x7b, 0x00);
+	dsi_generic_write_seq(dsi, 0x7c, 0x00);
+	dsi_generic_write_seq(dsi, 0x7d, 0x03);
+	dsi_generic_write_seq(dsi, 0x83, 0x00);
+	dsi_generic_write_seq(dsi, 0x8d, 0x00);
+	dsi_generic_write_seq(dsi, 0xa4, 0x8d);
+	dsi_generic_write_seq(dsi, 0xa6, 0x00);
+	dsi_generic_write_seq(dsi, 0xbb, 0x0a);
+	dsi_generic_write_seq(dsi, 0xbc, 0x06);
+	dsi_generic_write_seq(dsi, 0xd7, 0x61);
+	dsi_generic_write_seq(dsi, 0xd8, 0x13);
+	dsi_generic_write_seq(dsi, 0xf5, 0x00);
+	dsi_generic_write_seq(dsi, 0xf6, 0x01);
+	dsi_generic_write_seq(dsi, 0x89, 0xc1);
+	dsi_generic_write_seq(dsi, 0x91, 0x91);
+	dsi_generic_write_seq(dsi, 0xa2, 0x10);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0xff, 0x01);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x75, 0x00);
+	dsi_generic_write_seq(dsi, 0x76, 0x24);
+	dsi_generic_write_seq(dsi, 0x77, 0x00);
+	dsi_generic_write_seq(dsi, 0x78, 0x25);
+	dsi_generic_write_seq(dsi, 0x79, 0x00);
+	dsi_generic_write_seq(dsi, 0x7a, 0x43);
+	dsi_generic_write_seq(dsi, 0x7b, 0x00);
+	dsi_generic_write_seq(dsi, 0x7c, 0x5a);
+	dsi_generic_write_seq(dsi, 0x7d, 0x00);
+	dsi_generic_write_seq(dsi, 0x7e, 0x8f);
+	dsi_generic_write_seq(dsi, 0x7f, 0x00);
+	dsi_generic_write_seq(dsi, 0x80, 0xa6);
+	dsi_generic_write_seq(dsi, 0x81, 0x00);
+	dsi_generic_write_seq(dsi, 0x82, 0xb9);
+	dsi_generic_write_seq(dsi, 0x83, 0x00);
+	dsi_generic_write_seq(dsi, 0x84, 0xc9);
+	dsi_generic_write_seq(dsi, 0x85, 0x00);
+	dsi_generic_write_seq(dsi, 0x86, 0xd9);
+	dsi_generic_write_seq(dsi, 0x87, 0x01);
+	dsi_generic_write_seq(dsi, 0x88, 0x0c);
+	dsi_generic_write_seq(dsi, 0x89, 0x01);
+	dsi_generic_write_seq(dsi, 0x8a, 0x30);
+	dsi_generic_write_seq(dsi, 0x8b, 0x01);
+	dsi_generic_write_seq(dsi, 0x8c, 0x69);
+	dsi_generic_write_seq(dsi, 0x8d, 0x01);
+	dsi_generic_write_seq(dsi, 0x8e, 0x91);
+	dsi_generic_write_seq(dsi, 0x8f, 0x01);
+	dsi_generic_write_seq(dsi, 0x90, 0xd5);
+	dsi_generic_write_seq(dsi, 0x91, 0x02);
+	dsi_generic_write_seq(dsi, 0x92, 0x0d);
+	dsi_generic_write_seq(dsi, 0x93, 0x02);
+	dsi_generic_write_seq(dsi, 0x94, 0x10);
+	dsi_generic_write_seq(dsi, 0x95, 0x02);
+	dsi_generic_write_seq(dsi, 0x96, 0x3f);
+	dsi_generic_write_seq(dsi, 0x97, 0x02);
+	dsi_generic_write_seq(dsi, 0x98, 0x77);
+	dsi_generic_write_seq(dsi, 0x99, 0x02);
+	dsi_generic_write_seq(dsi, 0x9a, 0x9a);
+	dsi_generic_write_seq(dsi, 0x9b, 0x02);
+	dsi_generic_write_seq(dsi, 0x9c, 0xcf);
+	dsi_generic_write_seq(dsi, 0x9d, 0x02);
+	dsi_generic_write_seq(dsi, 0x9e, 0xf1);
+	dsi_generic_write_seq(dsi, 0x9f, 0x03);
+	dsi_generic_write_seq(dsi, 0xa0, 0x1f);
+	dsi_generic_write_seq(dsi, 0xa2, 0x03);
+	dsi_generic_write_seq(dsi, 0xa3, 0x2e);
+	dsi_generic_write_seq(dsi, 0xa4, 0x03);
+	dsi_generic_write_seq(dsi, 0xa5, 0x3e);
+	dsi_generic_write_seq(dsi, 0xa6, 0x03);
+	dsi_generic_write_seq(dsi, 0xa7, 0x4e);
+	dsi_generic_write_seq(dsi, 0xa9, 0x03);
+	dsi_generic_write_seq(dsi, 0xaa, 0x5d);
+	dsi_generic_write_seq(dsi, 0xab, 0x03);
+	dsi_generic_write_seq(dsi, 0xac, 0x8b);
+	dsi_generic_write_seq(dsi, 0xad, 0x03);
+	dsi_generic_write_seq(dsi, 0xae, 0x8e);
+	dsi_generic_write_seq(dsi, 0xaf, 0x03);
+	dsi_generic_write_seq(dsi, 0xb0, 0xb7);
+	dsi_generic_write_seq(dsi, 0xb1, 0x03);
+	dsi_generic_write_seq(dsi, 0xb2, 0xe3);
+	dsi_generic_write_seq(dsi, 0xb3, 0x00);
+	dsi_generic_write_seq(dsi, 0xb4, 0x24);
+	dsi_generic_write_seq(dsi, 0xb5, 0x00);
+	dsi_generic_write_seq(dsi, 0xb6, 0x25);
+	dsi_generic_write_seq(dsi, 0xb7, 0x00);
+	dsi_generic_write_seq(dsi, 0xb8, 0x43);
+	dsi_generic_write_seq(dsi, 0xb9, 0x00);
+	dsi_generic_write_seq(dsi, 0xba, 0x5a);
+	dsi_generic_write_seq(dsi, 0xbb, 0x00);
+	dsi_generic_write_seq(dsi, 0xbc, 0x8f);
+	dsi_generic_write_seq(dsi, 0xbd, 0x00);
+	dsi_generic_write_seq(dsi, 0xbe, 0xa6);
+	dsi_generic_write_seq(dsi, 0xbf, 0x00);
+	dsi_generic_write_seq(dsi, 0xc0, 0xb9);
+	dsi_generic_write_seq(dsi, 0xc1, 0x00);
+	dsi_generic_write_seq(dsi, 0xc2, 0xc9);
+	dsi_generic_write_seq(dsi, 0xc3, 0x00);
+	dsi_generic_write_seq(dsi, 0xc4, 0xd9);
+	dsi_generic_write_seq(dsi, 0xc5, 0x01);
+	dsi_generic_write_seq(dsi, 0xc6, 0x0c);
+	dsi_generic_write_seq(dsi, 0xc7, 0x01);
+	dsi_generic_write_seq(dsi, 0xc8, 0x30);
+	dsi_generic_write_seq(dsi, 0xc9, 0x01);
+	dsi_generic_write_seq(dsi, 0xca, 0x69);
+	dsi_generic_write_seq(dsi, 0xcb, 0x01);
+	dsi_generic_write_seq(dsi, 0xcc, 0x91);
+	dsi_generic_write_seq(dsi, 0xcd, 0x01);
+	dsi_generic_write_seq(dsi, 0xce, 0xd5);
+	dsi_generic_write_seq(dsi, 0xcf, 0x02);
+	dsi_generic_write_seq(dsi, 0xd0, 0x0d);
+	dsi_generic_write_seq(dsi, 0xd1, 0x02);
+	dsi_generic_write_seq(dsi, 0xd2, 0x10);
+	dsi_generic_write_seq(dsi, 0xd3, 0x02);
+	dsi_generic_write_seq(dsi, 0xd4, 0x3f);
+	dsi_generic_write_seq(dsi, 0xd5, 0x02);
+	dsi_generic_write_seq(dsi, 0xd6, 0x77);
+	dsi_generic_write_seq(dsi, 0xd7, 0x02);
+	dsi_generic_write_seq(dsi, 0xd8, 0x9a);
+	dsi_generic_write_seq(dsi, 0xd9, 0x02);
+	dsi_generic_write_seq(dsi, 0xda, 0xcf);
+	dsi_generic_write_seq(dsi, 0xdb, 0x02);
+	dsi_generic_write_seq(dsi, 0xdc, 0xf1);
+	dsi_generic_write_seq(dsi, 0xdd, 0x03);
+	dsi_generic_write_seq(dsi, 0xde, 0x1f);
+	dsi_generic_write_seq(dsi, 0xdf, 0x03);
+	dsi_generic_write_seq(dsi, 0xe0, 0x2e);
+	dsi_generic_write_seq(dsi, 0xe1, 0x03);
+	dsi_generic_write_seq(dsi, 0xe2, 0x3e);
+	dsi_generic_write_seq(dsi, 0xe3, 0x03);
+	dsi_generic_write_seq(dsi, 0xe4, 0x4e);
+	dsi_generic_write_seq(dsi, 0xe5, 0x03);
+	dsi_generic_write_seq(dsi, 0xe6, 0x5d);
+	dsi_generic_write_seq(dsi, 0xe7, 0x03);
+	dsi_generic_write_seq(dsi, 0xe8, 0x8b);
+	dsi_generic_write_seq(dsi, 0xe9, 0x03);
+	dsi_generic_write_seq(dsi, 0xea, 0x8e);
+	dsi_generic_write_seq(dsi, 0xeb, 0x03);
+	dsi_generic_write_seq(dsi, 0xec, 0xb7);
+	dsi_generic_write_seq(dsi, 0xed, 0x03);
+	dsi_generic_write_seq(dsi, 0xee, 0xe3);
+	dsi_generic_write_seq(dsi, 0xef, 0x00);
+	dsi_generic_write_seq(dsi, 0xf0, 0xf5);
+	dsi_generic_write_seq(dsi, 0xf1, 0x00);
+	dsi_generic_write_seq(dsi, 0xf2, 0xfb);
+	dsi_generic_write_seq(dsi, 0xf3, 0x01);
+	dsi_generic_write_seq(dsi, 0xf4, 0x08);
+	dsi_generic_write_seq(dsi, 0xf5, 0x01);
+	dsi_generic_write_seq(dsi, 0xf6, 0x13);
+	dsi_generic_write_seq(dsi, 0xf7, 0x01);
+	dsi_generic_write_seq(dsi, 0xf8, 0x1b);
+	dsi_generic_write_seq(dsi, 0xf9, 0x01);
+	dsi_generic_write_seq(dsi, 0xfa, 0x24);
+	dsi_generic_write_seq(dsi, 0xff, 0x02);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x00, 0x01);
+	dsi_generic_write_seq(dsi, 0x01, 0x2c);
+	dsi_generic_write_seq(dsi, 0x02, 0x01);
+	dsi_generic_write_seq(dsi, 0x03, 0x34);
+	dsi_generic_write_seq(dsi, 0x04, 0x01);
+	dsi_generic_write_seq(dsi, 0x05, 0x3b);
+	dsi_generic_write_seq(dsi, 0x06, 0x01);
+	dsi_generic_write_seq(dsi, 0x07, 0x55);
+	dsi_generic_write_seq(dsi, 0x08, 0x01);
+	dsi_generic_write_seq(dsi, 0x09, 0x6c);
+	dsi_generic_write_seq(dsi, 0x0a, 0x01);
+	dsi_generic_write_seq(dsi, 0x0b, 0x93);
+	dsi_generic_write_seq(dsi, 0x0c, 0x01);
+	dsi_generic_write_seq(dsi, 0x0d, 0xb5);
+	dsi_generic_write_seq(dsi, 0x0e, 0x01);
+	dsi_generic_write_seq(dsi, 0x0f, 0xec);
+	dsi_generic_write_seq(dsi, 0x10, 0x02);
+	dsi_generic_write_seq(dsi, 0x11, 0x1b);
+	dsi_generic_write_seq(dsi, 0x12, 0x02);
+	dsi_generic_write_seq(dsi, 0x13, 0x1c);
+	dsi_generic_write_seq(dsi, 0x14, 0x02);
+	dsi_generic_write_seq(dsi, 0x15, 0x4b);
+	dsi_generic_write_seq(dsi, 0x16, 0x02);
+	dsi_generic_write_seq(dsi, 0x17, 0x82);
+	dsi_generic_write_seq(dsi, 0x18, 0x02);
+	dsi_generic_write_seq(dsi, 0x19, 0xa7);
+	dsi_generic_write_seq(dsi, 0x1a, 0x02);
+	dsi_generic_write_seq(dsi, 0x1b, 0xd9);
+	dsi_generic_write_seq(dsi, 0x1c, 0x02);
+	dsi_generic_write_seq(dsi, 0x1d, 0xfc);
+	dsi_generic_write_seq(dsi, 0x1e, 0x03);
+	dsi_generic_write_seq(dsi, 0x1f, 0x2a);
+	dsi_generic_write_seq(dsi, 0x20, 0x03);
+	dsi_generic_write_seq(dsi, 0x21, 0x38);
+	dsi_generic_write_seq(dsi, 0x22, 0x03);
+	dsi_generic_write_seq(dsi, 0x23, 0x47);
+	dsi_generic_write_seq(dsi, 0x24, 0x03);
+	dsi_generic_write_seq(dsi, 0x25, 0x59);
+	dsi_generic_write_seq(dsi, 0x26, 0x03);
+	dsi_generic_write_seq(dsi, 0x27, 0x65);
+	dsi_generic_write_seq(dsi, 0x28, 0x03);
+	dsi_generic_write_seq(dsi, 0x29, 0x91);
+	dsi_generic_write_seq(dsi, 0x2a, 0x03);
+	dsi_generic_write_seq(dsi, 0x2b, 0xaf);
+	dsi_generic_write_seq(dsi, 0x2d, 0x03);
+	dsi_generic_write_seq(dsi, 0x2f, 0xef);
+	dsi_generic_write_seq(dsi, 0x30, 0x03);
+	dsi_generic_write_seq(dsi, 0x31, 0xf5);
+	dsi_generic_write_seq(dsi, 0x32, 0x00);
+	dsi_generic_write_seq(dsi, 0x33, 0xf5);
+	dsi_generic_write_seq(dsi, 0x34, 0x00);
+	dsi_generic_write_seq(dsi, 0x35, 0xfb);
+	dsi_generic_write_seq(dsi, 0x36, 0x01);
+	dsi_generic_write_seq(dsi, 0x37, 0x08);
+	dsi_generic_write_seq(dsi, 0x38, 0x01);
+	dsi_generic_write_seq(dsi, 0x39, 0x13);
+	dsi_generic_write_seq(dsi, 0x3a, 0x01);
+	dsi_generic_write_seq(dsi, 0x3b, 0x1b);
+	dsi_generic_write_seq(dsi, 0x3d, 0x01);
+	dsi_generic_write_seq(dsi, 0x3f, 0x24);
+	dsi_generic_write_seq(dsi, 0x40, 0x01);
+	dsi_generic_write_seq(dsi, 0x41, 0x2c);
+	dsi_generic_write_seq(dsi, 0x42, 0x01);
+	dsi_generic_write_seq(dsi, 0x43, 0x34);
+	dsi_generic_write_seq(dsi, 0x44, 0x01);
+	dsi_generic_write_seq(dsi, 0x45, 0x3b);
+	dsi_generic_write_seq(dsi, 0x46, 0x01);
+	dsi_generic_write_seq(dsi, 0x47, 0x55);
+	dsi_generic_write_seq(dsi, 0x48, 0x01);
+	dsi_generic_write_seq(dsi, 0x49, 0x6c);
+	dsi_generic_write_seq(dsi, 0x4a, 0x01);
+	dsi_generic_write_seq(dsi, 0x4b, 0x93);
+	dsi_generic_write_seq(dsi, 0x4c, 0x01);
+	dsi_generic_write_seq(dsi, 0x4d, 0xb5);
+	dsi_generic_write_seq(dsi, 0x4e, 0x01);
+	dsi_generic_write_seq(dsi, 0x4f, 0xec);
+	dsi_generic_write_seq(dsi, 0x50, 0x02);
+	dsi_generic_write_seq(dsi, 0x51, 0x1b);
+	dsi_generic_write_seq(dsi, 0x52, 0x02);
+	dsi_generic_write_seq(dsi, 0x53, 0x1c);
+	dsi_generic_write_seq(dsi, 0x54, 0x02);
+	dsi_generic_write_seq(dsi, 0x55, 0x4b);
+	dsi_generic_write_seq(dsi, 0x56, 0x02);
+	dsi_generic_write_seq(dsi, 0x58, 0x82);
+	dsi_generic_write_seq(dsi, 0x59, 0x02);
+	dsi_generic_write_seq(dsi, 0x5a, 0xa7);
+	dsi_generic_write_seq(dsi, 0x5b, 0x02);
+	dsi_generic_write_seq(dsi, 0x5c, 0xd9);
+	dsi_generic_write_seq(dsi, 0x5d, 0x02);
+	dsi_generic_write_seq(dsi, 0x5e, 0xfc);
+	dsi_generic_write_seq(dsi, 0x5f, 0x03);
+	dsi_generic_write_seq(dsi, 0x60, 0x2a);
+	dsi_generic_write_seq(dsi, 0x61, 0x03);
+	dsi_generic_write_seq(dsi, 0x62, 0x38);
+	dsi_generic_write_seq(dsi, 0x63, 0x03);
+	dsi_generic_write_seq(dsi, 0x64, 0x47);
+	dsi_generic_write_seq(dsi, 0x65, 0x03);
+	dsi_generic_write_seq(dsi, 0x66, 0x59);
+	dsi_generic_write_seq(dsi, 0x67, 0x03);
+	dsi_generic_write_seq(dsi, 0x68, 0x65);
+	dsi_generic_write_seq(dsi, 0x69, 0x03);
+	dsi_generic_write_seq(dsi, 0x6a, 0x91);
+	dsi_generic_write_seq(dsi, 0x6b, 0x03);
+	dsi_generic_write_seq(dsi, 0x6c, 0xaf);
+	dsi_generic_write_seq(dsi, 0x6d, 0x03);
+	dsi_generic_write_seq(dsi, 0x6e, 0xef);
+	dsi_generic_write_seq(dsi, 0x6f, 0x03);
+	dsi_generic_write_seq(dsi, 0x70, 0xf5);
+	dsi_generic_write_seq(dsi, 0x71, 0x00);
+	dsi_generic_write_seq(dsi, 0x72, 0x01);
+	dsi_generic_write_seq(dsi, 0x73, 0x00);
+	dsi_generic_write_seq(dsi, 0x74, 0x02);
+	dsi_generic_write_seq(dsi, 0x75, 0x00);
+	dsi_generic_write_seq(dsi, 0x76, 0x41);
+	dsi_generic_write_seq(dsi, 0x77, 0x00);
+	dsi_generic_write_seq(dsi, 0x78, 0x6c);
+	dsi_generic_write_seq(dsi, 0x79, 0x00);
+	dsi_generic_write_seq(dsi, 0x7a, 0x88);
+	dsi_generic_write_seq(dsi, 0x7b, 0x00);
+	dsi_generic_write_seq(dsi, 0x7c, 0x9e);
+	dsi_generic_write_seq(dsi, 0x7d, 0x00);
+	dsi_generic_write_seq(dsi, 0x7e, 0xb1);
+	dsi_generic_write_seq(dsi, 0x7f, 0x00);
+	dsi_generic_write_seq(dsi, 0x80, 0xc1);
+	dsi_generic_write_seq(dsi, 0x81, 0x00);
+	dsi_generic_write_seq(dsi, 0x82, 0xcf);
+	dsi_generic_write_seq(dsi, 0x83, 0x01);
+	dsi_generic_write_seq(dsi, 0x84, 0x02);
+	dsi_generic_write_seq(dsi, 0x85, 0x01);
+	dsi_generic_write_seq(dsi, 0x86, 0x26);
+	dsi_generic_write_seq(dsi, 0x87, 0x01);
+	dsi_generic_write_seq(dsi, 0x88, 0x60);
+	dsi_generic_write_seq(dsi, 0x89, 0x01);
+	dsi_generic_write_seq(dsi, 0x8a, 0x8c);
+	dsi_generic_write_seq(dsi, 0x8b, 0x01);
+	dsi_generic_write_seq(dsi, 0x8c, 0xd2);
+	dsi_generic_write_seq(dsi, 0x8d, 0x02);
+	dsi_generic_write_seq(dsi, 0x8e, 0x09);
+	dsi_generic_write_seq(dsi, 0x8f, 0x02);
+	dsi_generic_write_seq(dsi, 0x90, 0x0b);
+	dsi_generic_write_seq(dsi, 0x91, 0x02);
+	dsi_generic_write_seq(dsi, 0x92, 0x3d);
+	dsi_generic_write_seq(dsi, 0x93, 0x02);
+	dsi_generic_write_seq(dsi, 0x94, 0x76);
+	dsi_generic_write_seq(dsi, 0x95, 0x02);
+	dsi_generic_write_seq(dsi, 0x96, 0x9b);
+	dsi_generic_write_seq(dsi, 0x97, 0x02);
+	dsi_generic_write_seq(dsi, 0x98, 0xd0);
+	dsi_generic_write_seq(dsi, 0x99, 0x02);
+	dsi_generic_write_seq(dsi, 0x9a, 0xf6);
+	dsi_generic_write_seq(dsi, 0x9b, 0x03);
+	dsi_generic_write_seq(dsi, 0x9c, 0x2d);
+	dsi_generic_write_seq(dsi, 0x9d, 0x03);
+	dsi_generic_write_seq(dsi, 0x9e, 0x40);
+	dsi_generic_write_seq(dsi, 0x9f, 0x03);
+	dsi_generic_write_seq(dsi, 0xa0, 0x5a);
+	dsi_generic_write_seq(dsi, 0xa2, 0x03);
+	dsi_generic_write_seq(dsi, 0xa3, 0x7f);
+	dsi_generic_write_seq(dsi, 0xa4, 0x03);
+	dsi_generic_write_seq(dsi, 0xa5, 0xfa);
+	dsi_generic_write_seq(dsi, 0xa6, 0x03);
+	dsi_generic_write_seq(dsi, 0xa7, 0xfb);
+	dsi_generic_write_seq(dsi, 0xa9, 0x03);
+	dsi_generic_write_seq(dsi, 0xaa, 0xfe);
+	dsi_generic_write_seq(dsi, 0xab, 0x03);
+	dsi_generic_write_seq(dsi, 0xac, 0xfe);
+	dsi_generic_write_seq(dsi, 0xad, 0x03);
+	dsi_generic_write_seq(dsi, 0xae, 0xfe);
+	dsi_generic_write_seq(dsi, 0xaf, 0x00);
+	dsi_generic_write_seq(dsi, 0xb0, 0x01);
+	dsi_generic_write_seq(dsi, 0xb1, 0x00);
+	dsi_generic_write_seq(dsi, 0xb2, 0x02);
+	dsi_generic_write_seq(dsi, 0xb3, 0x00);
+	dsi_generic_write_seq(dsi, 0xb4, 0x41);
+	dsi_generic_write_seq(dsi, 0xb5, 0x00);
+	dsi_generic_write_seq(dsi, 0xb6, 0x6c);
+	dsi_generic_write_seq(dsi, 0xb7, 0x00);
+	dsi_generic_write_seq(dsi, 0xb8, 0x88);
+	dsi_generic_write_seq(dsi, 0xb9, 0x00);
+	dsi_generic_write_seq(dsi, 0xba, 0x9e);
+	dsi_generic_write_seq(dsi, 0xbb, 0x00);
+	dsi_generic_write_seq(dsi, 0xbc, 0xb1);
+	dsi_generic_write_seq(dsi, 0xbd, 0x00);
+	dsi_generic_write_seq(dsi, 0xbe, 0xc1);
+	dsi_generic_write_seq(dsi, 0xbf, 0x00);
+	dsi_generic_write_seq(dsi, 0xc0, 0xcf);
+	dsi_generic_write_seq(dsi, 0xc1, 0x01);
+	dsi_generic_write_seq(dsi, 0xc2, 0x02);
+	dsi_generic_write_seq(dsi, 0xc3, 0x01);
+	dsi_generic_write_seq(dsi, 0xc4, 0x26);
+	dsi_generic_write_seq(dsi, 0xc5, 0x01);
+	dsi_generic_write_seq(dsi, 0xc6, 0x60);
+	dsi_generic_write_seq(dsi, 0xc7, 0x01);
+	dsi_generic_write_seq(dsi, 0xc8, 0x8c);
+	dsi_generic_write_seq(dsi, 0xc9, 0x01);
+	dsi_generic_write_seq(dsi, 0xca, 0xd2);
+	dsi_generic_write_seq(dsi, 0xcb, 0x02);
+	dsi_generic_write_seq(dsi, 0xcc, 0x09);
+	dsi_generic_write_seq(dsi, 0xcd, 0x02);
+	dsi_generic_write_seq(dsi, 0xce, 0x0b);
+	dsi_generic_write_seq(dsi, 0xcf, 0x02);
+	dsi_generic_write_seq(dsi, 0xd0, 0x3d);
+	dsi_generic_write_seq(dsi, 0xd1, 0x02);
+	dsi_generic_write_seq(dsi, 0xd2, 0x76);
+	dsi_generic_write_seq(dsi, 0xd3, 0x02);
+	dsi_generic_write_seq(dsi, 0xd4, 0x9b);
+	dsi_generic_write_seq(dsi, 0xd5, 0x02);
+	dsi_generic_write_seq(dsi, 0xd6, 0xd0);
+	dsi_generic_write_seq(dsi, 0xd7, 0x02);
+	dsi_generic_write_seq(dsi, 0xd8, 0xf6);
+	dsi_generic_write_seq(dsi, 0xd9, 0x03);
+	dsi_generic_write_seq(dsi, 0xda, 0x2d);
+	dsi_generic_write_seq(dsi, 0xdb, 0x03);
+	dsi_generic_write_seq(dsi, 0xdc, 0x40);
+	dsi_generic_write_seq(dsi, 0xdd, 0x03);
+	dsi_generic_write_seq(dsi, 0xde, 0x5a);
+	dsi_generic_write_seq(dsi, 0xdf, 0x03);
+	dsi_generic_write_seq(dsi, 0xe0, 0x7f);
+	dsi_generic_write_seq(dsi, 0xe1, 0x03);
+	dsi_generic_write_seq(dsi, 0xe2, 0xfa);
+	dsi_generic_write_seq(dsi, 0xe3, 0x03);
+	dsi_generic_write_seq(dsi, 0xe4, 0xfb);
+	dsi_generic_write_seq(dsi, 0xe5, 0x03);
+	dsi_generic_write_seq(dsi, 0xe6, 0xfe);
+	dsi_generic_write_seq(dsi, 0xe7, 0x03);
+	dsi_generic_write_seq(dsi, 0xe8, 0xfe);
+	dsi_generic_write_seq(dsi, 0xe9, 0x03);
+	dsi_generic_write_seq(dsi, 0xea, 0xfe);
+	dsi_generic_write_seq(dsi, 0xff, 0x03);
+	dsi_generic_write_seq(dsi, 0x56, 0x00);
+	dsi_generic_write_seq(dsi, 0x68, 0x00);
+	dsi_generic_write_seq(dsi, 0x1a, 0x07);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0xff, 0x00);
+	dsi_generic_write_seq(dsi, 0x55, 0x93);
+	dsi_generic_write_seq(dsi, 0x35, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0x01);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x36, 0x7b);
+	dsi_generic_write_seq(dsi, 0x6d, 0x33);
+	dsi_generic_write_seq(dsi, 0x6f, 0x03);
+	dsi_generic_write_seq(dsi, 0xff, 0x01);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x4b, 0x83);
+	dsi_generic_write_seq(dsi, 0xff, 0xff);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x3f, 0x09);
+	dsi_generic_write_seq(dsi, 0xca, 0x80);
+	dsi_generic_write_seq(dsi, 0xff, 0xee);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x2a, 0xa9);
+	dsi_generic_write_seq(dsi, 0xff, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0x04);
+	dsi_generic_write_seq(dsi, 0xfb, 0x01);
+	dsi_generic_write_seq(dsi, 0x21, 0xd9);
+	dsi_generic_write_seq(dsi, 0x22, 0xd9);
+	dsi_generic_write_seq(dsi, 0x23, 0xd9);
+	dsi_generic_write_seq(dsi, 0xff, 0x00);
+	dsi_generic_write_seq(dsi, 0x51, 0xff);
+	usleep_range(1000, 2000);
+	dsi_generic_write_seq(dsi, 0x55, 0x93);
+	usleep_range(1000, 2000);
+	dsi_generic_write_seq(dsi, 0x53, 0x24);
+	usleep_range(1000, 2000);
+	dsi_generic_write_seq(dsi, 0x11, 0x00);
+	msleep(150);
+	dsi_generic_write_seq(dsi, 0x29, 0x00);
+	msleep(64);
+
+	return 0;
+}
+
+static int oppo15009jdi_nt35592_off(struct oppo15009jdi_nt35592 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int oppo15009jdi_nt35592_prepare(struct drm_panel *panel)
+{
+	struct oppo15009jdi_nt35592 *ctx = to_oppo15009jdi_nt35592(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	oppo15009jdi_nt35592_reset(ctx);
+
+	ret = oppo15009jdi_nt35592_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int oppo15009jdi_nt35592_unprepare(struct drm_panel *panel)
+{
+	struct oppo15009jdi_nt35592 *ctx = to_oppo15009jdi_nt35592(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = oppo15009jdi_nt35592_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode oppo15009jdi_nt35592_mode = {
+	.clock = (720 + 160 + 2 + 160) * (1280 + 6 + 1 + 4) * 61 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 160,
+	.hsync_end = 720 + 160 + 2,
+	.htotal = 720 + 160 + 2 + 160,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 6,
+	.vsync_end = 1280 + 6 + 1,
+	.vtotal = 1280 + 6 + 1 + 4,
+	.width_mm = 62,
+	.height_mm = 110,
+};
+
+static int oppo15009jdi_nt35592_get_modes(struct drm_panel *panel,
+					  struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &oppo15009jdi_nt35592_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs oppo15009jdi_nt35592_panel_funcs = {
+	.prepare = oppo15009jdi_nt35592_prepare,
+	.unprepare = oppo15009jdi_nt35592_unprepare,
+	.get_modes = oppo15009jdi_nt35592_get_modes,
+};
+
+static int oppo15009jdi_nt35592_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct oppo15009jdi_nt35592 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vsp";
+	ctx->supplies[1].supply = "vsn";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &oppo15009jdi_nt35592_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int oppo15009jdi_nt35592_remove(struct mipi_dsi_device *dsi)
+{
+	struct oppo15009jdi_nt35592 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id oppo15009jdi_nt35592_of_match[] = {
+	{ .compatible = "oppo,15009-nt35592-jdi" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, oppo15009jdi_nt35592_of_match);
+
+static struct mipi_dsi_driver oppo15009jdi_nt35592_driver = {
+	.probe = oppo15009jdi_nt35592_probe,
+	.remove = oppo15009jdi_nt35592_remove,
+	.driver = {
+		.name = "panel-oppo15009jdi-nt35592",
+		.of_match_table = oppo15009jdi_nt35592_of_match,
+	},
+};
+module_mipi_dsi_driver(oppo15009jdi_nt35592_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for oppo15009jdi nt35592 720p video video mode dsi panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c
new file mode 100644
index 000000000..1dc94be5c
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct ea8061v_ams497ee01 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline
+struct ea8061v_ams497ee01 *to_ea8061v_ams497ee01(struct drm_panel *panel)
+{
+	return container_of(panel, struct ea8061v_ams497ee01, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void ea8061v_ams497ee01_reset(struct ea8061v_ams497ee01 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+}
+
+static int ea8061v_ams497ee01_on(struct ea8061v_ams497ee01 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xf1, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xb8, 0x19, 0x10);
+	dsi_dcs_write_seq(dsi, 0xba, 0x57);
+	dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xb0, 0x0b);
+	dsi_dcs_write_seq(dsi, 0xd2, 0x00, 0x85);
+	dsi_dcs_write_seq(dsi, 0xcb, 0x70);
+	dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
+	dsi_dcs_write_seq(dsi, 0xca,
+			  0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80,
+			  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+			  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+			  0x80, 0x80, 0x80, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x00, 0x00, 0x0a);
+	dsi_dcs_write_seq(dsi, 0xb6, 0x5c, 0x8a);
+	dsi_dcs_write_seq(dsi, 0xf7, 0x01);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	dsi_dcs_write_seq(dsi, 0xf1, 0xa5, 0xa5);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ea8061v_ams497ee01_off(struct ea8061v_ams497ee01 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(35);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(100);
+
+	return 0;
+}
+
+static int ea8061v_ams497ee01_prepare(struct drm_panel *panel)
+{
+	struct ea8061v_ams497ee01 *ctx = to_ea8061v_ams497ee01(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	ea8061v_ams497ee01_reset(ctx);
+
+	ret = ea8061v_ams497ee01_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int ea8061v_ams497ee01_unprepare(struct drm_panel *panel)
+{
+	struct ea8061v_ams497ee01 *ctx = to_ea8061v_ams497ee01(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = ea8061v_ams497ee01_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode ea8061v_ams497ee01_mode = {
+	.clock = (720 + 80 + 96 + 128) * (1280 + 14 + 2 + 8) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 80,
+	.hsync_end = 720 + 80 + 96,
+	.htotal = 720 + 80 + 96 + 128,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 14,
+	.vsync_end = 1280 + 14 + 2,
+	.vtotal = 1280 + 14 + 2 + 8,
+	.width_mm = 62,
+	.height_mm = 110,
+};
+
+static int ea8061v_ams497ee01_get_modes(struct drm_panel *panel,
+					struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &ea8061v_ams497ee01_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs ea8061v_ams497ee01_panel_funcs = {
+	.prepare = ea8061v_ams497ee01_prepare,
+	.unprepare = ea8061v_ams497ee01_unprepare,
+	.get_modes = ea8061v_ams497ee01_get_modes,
+};
+
+static int ea8061v_ams497ee01_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct ea8061v_ams497ee01 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vdd3";
+	ctx->supplies[1].supply = "vci";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_EOT_PACKET;
+
+	drm_panel_init(&ctx->panel, dev, &ea8061v_ams497ee01_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ea8061v_ams497ee01_remove(struct mipi_dsi_device *dsi)
+{
+	struct ea8061v_ams497ee01 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id ea8061v_ams497ee01_of_match[] = {
+	{ .compatible = "samsung,ea8061v-ams497ee01" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ea8061v_ams497ee01_of_match);
+
+static struct mipi_dsi_driver ea8061v_ams497ee01_driver = {
+	.probe = ea8061v_ams497ee01_probe,
+	.remove = ea8061v_ams497ee01_remove,
+	.driver = {
+		.name = "panel-ea8061v-ams497ee01",
+		.of_match_table = ea8061v_ams497ee01_of_match,
+	},
+};
+module_mipi_dsi_driver(ea8061v_ams497ee01_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for ss_dsi_panel_EA8061V_AMS497EE01_HD");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6d7aa0-ltl101at01.c b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6d7aa0-ltl101at01.c
new file mode 100644
index 000000000..5ea25ee5e
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6d7aa0-ltl101at01.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct s6d7aa0_ltl101at01 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline
+struct s6d7aa0_ltl101at01 *to_s6d7aa0_ltl101at01(struct drm_panel *panel)
+{
+	return container_of(panel, struct s6d7aa0_ltl101at01, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void s6d7aa0_ltl101at01_reset(struct s6d7aa0_ltl101at01 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(20);
+}
+
+static int s6d7aa0_ltl101at01_on(struct s6d7aa0_ltl101at01 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xf1, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
+	dsi_dcs_write_seq(dsi, 0xd0, 0x00, 0x10);
+	dsi_dcs_write_seq(dsi, 0xc3, 0x40, 0x00, 0x08);
+	dsi_dcs_write_seq(dsi, 0xbc, 0x01, 0x4e, 0x0b);
+	dsi_dcs_write_seq(dsi, 0xfd, 0x16, 0x10, 0x11, 0x23, 0x09);
+	dsi_dcs_write_seq(dsi, 0xfe, 0x00, 0x02, 0x03, 0x21, 0x80, 0x68);
+	dsi_dcs_write_seq(dsi, 0xb3, 0x51);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+	dsi_dcs_write_seq(dsi, 0xf2, 0x02, 0x08, 0x08);
+	usleep_range(10000, 11000);
+	dsi_dcs_write_seq(dsi, 0xc0, 0x80, 0x80, 0x30);
+	dsi_dcs_write_seq(dsi, 0xcd,
+			  0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+			  0x2e, 0x2e, 0x2e, 0x2e);
+	dsi_dcs_write_seq(dsi, 0xce,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xc1, 0x03);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+	dsi_dcs_write_seq(dsi, 0xf1, 0xa5, 0xa5);
+	dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
+
+	ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set tear on: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	usleep_range(5000, 6000);
+
+	return 0;
+}
+
+static int s6d7aa0_ltl101at01_off(struct s6d7aa0_ltl101at01 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	dsi_dcs_write_seq(dsi, 0x22, 0x00);
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(64);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	usleep_range(10000, 11000);
+
+	return 0;
+}
+
+static int s6d7aa0_ltl101at01_prepare(struct drm_panel *panel)
+{
+	struct s6d7aa0_ltl101at01 *ctx = to_s6d7aa0_ltl101at01(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	s6d7aa0_ltl101at01_reset(ctx);
+
+	ret = s6d7aa0_ltl101at01_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int s6d7aa0_ltl101at01_unprepare(struct drm_panel *panel)
+{
+	struct s6d7aa0_ltl101at01 *ctx = to_s6d7aa0_ltl101at01(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = s6d7aa0_ltl101at01_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode s6d7aa0_ltl101at01_mode = {
+	.clock = (768 + 96 + 16 + 184) * (1024 + 8 + 2 + 6) * 60 / 1000,
+	.hdisplay = 768,
+	.hsync_start = 768 + 96,
+	.hsync_end = 768 + 96 + 16,
+	.htotal = 768 + 96 + 16 + 184,
+	.vdisplay = 1024,
+	.vsync_start = 1024 + 8,
+	.vsync_end = 1024 + 8 + 2,
+	.vtotal = 1024 + 8 + 2 + 6,
+	.width_mm = 148,
+	.height_mm = 197,
+};
+
+static int s6d7aa0_ltl101at01_get_modes(struct drm_panel *panel,
+					struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &s6d7aa0_ltl101at01_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs s6d7aa0_ltl101at01_panel_funcs = {
+	.prepare = s6d7aa0_ltl101at01_prepare,
+	.unprepare = s6d7aa0_ltl101at01_unprepare,
+	.get_modes = s6d7aa0_ltl101at01_get_modes,
+};
+
+static int s6d7aa0_ltl101at01_bl_update_status(struct backlight_device *bl)
+{
+	struct mipi_dsi_device *dsi = bl_get_data(bl);
+	u16 brightness = backlight_get_brightness(bl);
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, brightness);
+	if (ret < 0)
+		return ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	return 0;
+}
+
+// TODO: Check if /sys/class/backlight/.../actual_brightness actually returns
+// correct values. If not, remove this function.
+static int s6d7aa0_ltl101at01_bl_get_brightness(struct backlight_device *bl)
+{
+	struct mipi_dsi_device *dsi = bl_get_data(bl);
+	u16 brightness;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
+	if (ret < 0)
+		return ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	return brightness & 0xff;
+}
+
+static const struct backlight_ops s6d7aa0_ltl101at01_bl_ops = {
+	.update_status = s6d7aa0_ltl101at01_bl_update_status,
+	.get_brightness = s6d7aa0_ltl101at01_bl_get_brightness,
+};
+
+static struct backlight_device *
+s6d7aa0_ltl101at01_create_backlight(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	const struct backlight_properties props = {
+		.type = BACKLIGHT_RAW,
+		.brightness = 255,
+		.max_brightness = 255,
+	};
+
+	return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
+					      &s6d7aa0_ltl101at01_bl_ops, &props);
+}
+
+static int s6d7aa0_ltl101at01_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct s6d7aa0_ltl101at01 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vmipi";
+	ctx->supplies[1].supply = "5p4v";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_EOT_PACKET;
+
+	drm_panel_init(&ctx->panel, dev, &s6d7aa0_ltl101at01_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ctx->panel.backlight = s6d7aa0_ltl101at01_create_backlight(dsi);
+	if (IS_ERR(ctx->panel.backlight))
+		return dev_err_probe(dev, PTR_ERR(ctx->panel.backlight),
+				     "Failed to create backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int s6d7aa0_ltl101at01_remove(struct mipi_dsi_device *dsi)
+{
+	struct s6d7aa0_ltl101at01 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id s6d7aa0_ltl101at01_of_match[] = {
+	{ .compatible = "samsung,s6d7aa0-ltl101at01" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s6d7aa0_ltl101at01_of_match);
+
+static struct mipi_dsi_driver s6d7aa0_ltl101at01_driver = {
+	.probe = s6d7aa0_ltl101at01_probe,
+	.remove = s6d7aa0_ltl101at01_remove,
+	.driver = {
+		.name = "panel-s6d7aa0-ltl101at01",
+		.of_match_table = s6d7aa0_ltl101at01_of_match,
+	},
+};
+module_mipi_dsi_driver(s6d7aa0_ltl101at01_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for S6D7AA0 xga video mode dsi panel");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6e88a0-ams427ap24.c b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6e88a0-ams427ap24.c
new file mode 100644
index 000000000..c14a8ecb3
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-s6e88a0-ams427ap24.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct s6e88a0_ams427ap24 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline
+struct s6e88a0_ams427ap24 *to_s6e88a0_ams427ap24(struct drm_panel *panel)
+{
+	return container_of(panel, struct s6e88a0_ams427ap24, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void s6e88a0_ams427ap24_reset(struct s6e88a0_ams427ap24 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(18000, 19000);
+}
+
+static int s6e88a0_ams427ap24_on(struct s6e88a0_ams427ap24 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xb0, 0x11);
+	dsi_dcs_write_seq(dsi, 0xfd, 0x11);
+	dsi_dcs_write_seq(dsi, 0xb0, 0x13);
+	dsi_dcs_write_seq(dsi, 0xfd, 0x18);
+	dsi_dcs_write_seq(dsi, 0xb0, 0x02);
+	dsi_dcs_write_seq(dsi, 0xb8, 0x30);
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(20);
+
+	dsi_dcs_write_seq(dsi, 0xf1, 0x5a, 0x5a);
+	dsi_dcs_write_seq(dsi, 0xcc, 0x4c);
+	dsi_dcs_write_seq(dsi, 0xf2, 0x03, 0x0d);
+	dsi_dcs_write_seq(dsi, 0xf1, 0xa5, 0xa5);
+	dsi_dcs_write_seq(dsi, 0xca,
+			  0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80,
+			  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+			  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+			  0x80, 0x80, 0x80, 0x00, 0x00, 0x00);
+	dsi_dcs_write_seq(dsi, 0xb2, 0x40, 0x08, 0x20, 0x00, 0x08);
+	dsi_dcs_write_seq(dsi, 0xb6, 0x28, 0x0b);
+	dsi_dcs_write_seq(dsi, 0xf7, 0x03);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+	dsi_dcs_write_seq(dsi, 0xf0, 0xa5, 0xa5);
+	dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5);
+
+	return 0;
+}
+
+static int s6e88a0_ams427ap24_off(struct s6e88a0_ams427ap24 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int s6e88a0_ams427ap24_prepare(struct drm_panel *panel)
+{
+	struct s6e88a0_ams427ap24 *ctx = to_s6e88a0_ams427ap24(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	s6e88a0_ams427ap24_reset(ctx);
+
+	ret = s6e88a0_ams427ap24_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int s6e88a0_ams427ap24_unprepare(struct drm_panel *panel)
+{
+	struct s6e88a0_ams427ap24 *ctx = to_s6e88a0_ams427ap24(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = s6e88a0_ams427ap24_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode s6e88a0_ams427ap24_mode = {
+	.clock = (540 + 94 + 4 + 18) * (960 + 12 + 1 + 3) * 60 / 1000,
+	.hdisplay = 540,
+	.hsync_start = 540 + 94,
+	.hsync_end = 540 + 94 + 4,
+	.htotal = 540 + 94 + 4 + 18,
+	.vdisplay = 960,
+	.vsync_start = 960 + 12,
+	.vsync_end = 960 + 12 + 1,
+	.vtotal = 960 + 12 + 1 + 3,
+	.width_mm = 55,
+	.height_mm = 95,
+};
+
+static int s6e88a0_ams427ap24_get_modes(struct drm_panel *panel,
+					struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &s6e88a0_ams427ap24_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs s6e88a0_ams427ap24_panel_funcs = {
+	.prepare = s6e88a0_ams427ap24_prepare,
+	.unprepare = s6e88a0_ams427ap24_unprepare,
+	.get_modes = s6e88a0_ams427ap24_get_modes,
+};
+
+static int s6e88a0_ams427ap24_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct s6e88a0_ams427ap24 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vdd3";
+	ctx->supplies[1].supply = "vci";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 2;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_EOT_PACKET;
+
+	drm_panel_init(&ctx->panel, dev, &s6e88a0_ams427ap24_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int s6e88a0_ams427ap24_remove(struct mipi_dsi_device *dsi)
+{
+	struct s6e88a0_ams427ap24 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id s6e88a0_ams427ap24_of_match[] = {
+	{ .compatible = "samsung,s6e88a0-ams427ap24" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s6e88a0_ams427ap24_of_match);
+
+static struct mipi_dsi_driver s6e88a0_ams427ap24_driver = {
+	.probe = s6e88a0_ams427ap24_probe,
+	.remove = s6e88a0_ams427ap24_remove,
+	.driver = {
+		.name = "panel-s6e88a0-ams427ap24",
+		.of_match_table = s6e88a0_ams427ap24_of_match,
+	},
+};
+module_mipi_dsi_driver(s6e88a0_ams427ap24_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for ss_dsi_panel_S6E88A0_AMS427AP24_QHD");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-tc358764-ltl101al06.c b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-tc358764-ltl101al06.c
new file mode 100644
index 000000000..404128e11
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-tc358764-ltl101al06.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct tc358764_ltl101a106 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline
+struct tc358764_ltl101a106 *to_tc358764_ltl101a106(struct drm_panel *panel)
+{
+	return container_of(panel, struct tc358764_ltl101a106, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void tc358764_ltl101a106_reset(struct tc358764_ltl101a106 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(1000, 2000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(1000, 2000);
+}
+
+static int tc358764_ltl101a106_on(struct tc358764_ltl101a106 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_generic_write_seq(dsi, 0x3c, 0x01, 0x06, 0x00, 0x05, 0x00);
+	dsi_generic_write_seq(dsi, 0x14, 0x01, 0x04, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x64, 0x01, 0x04, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x68, 0x01, 0x04, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x6c, 0x01, 0x04, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x70, 0x01, 0x04, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x34, 0x01, 0x1f, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x10, 0x02, 0x1f, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x50, 0x04, 0x20, 0x01, 0xf0, 0x03);
+	dsi_generic_write_seq(dsi, 0x54, 0x04, 0x02, 0x00, 0x30, 0x00);
+	dsi_generic_write_seq(dsi, 0x58, 0x04, 0x20, 0x03, 0x30, 0x00);
+	dsi_generic_write_seq(dsi, 0x5c, 0x04, 0x02, 0x00, 0x40, 0x00);
+	dsi_generic_write_seq(dsi, 0x60, 0x04, 0x00, 0x05, 0x20, 0x00);
+	dsi_generic_write_seq(dsi, 0x64, 0x04, 0x01, 0x00, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xa0, 0x04, 0x06, 0x80, 0x44, 0x00);
+	usleep_range(2000, 3000);
+	dsi_generic_write_seq(dsi, 0xa0, 0x04, 0x06, 0x80, 0x04, 0x00);
+	usleep_range(2000, 3000);
+	dsi_generic_write_seq(dsi, 0x04, 0x05, 0x04, 0x00, 0x00, 0x00);
+	usleep_range(2000, 3000);
+	dsi_generic_write_seq(dsi, 0x80, 0x04, 0x00, 0x01, 0x02, 0x03);
+	dsi_generic_write_seq(dsi, 0x84, 0x04, 0x04, 0x07, 0x05, 0x08);
+	dsi_generic_write_seq(dsi, 0x88, 0x04, 0x09, 0x0a, 0x0e, 0x0f);
+	dsi_generic_write_seq(dsi, 0x8c, 0x04, 0x0b, 0x0c, 0x0d, 0x10);
+	dsi_generic_write_seq(dsi, 0x90, 0x04, 0x16, 0x17, 0x11, 0x12);
+	dsi_generic_write_seq(dsi, 0x94, 0x04, 0x13, 0x14, 0x15, 0x1b);
+	dsi_generic_write_seq(dsi, 0x98, 0x04, 0x18, 0x19, 0x1a, 0x06);
+	dsi_generic_write_seq(dsi, 0x9c, 0x04, 0x01, 0x00, 0x00, 0x00);
+
+	return 0;
+}
+
+static int tc358764_ltl101a106_off(struct tc358764_ltl101a106 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	dsi_generic_write_seq(dsi, 0xa0, 0x04, 0x01, 0x00, 0x00, 0x00);
+	usleep_range(1000, 2000);
+	dsi_generic_write_seq(dsi, 0x9c, 0x04, 0x00, 0x00, 0x00, 0x00);
+
+	return 0;
+}
+
+static int tc358764_ltl101a106_prepare(struct drm_panel *panel)
+{
+	struct tc358764_ltl101a106 *ctx = to_tc358764_ltl101a106(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	tc358764_ltl101a106_reset(ctx);
+
+	ret = tc358764_ltl101a106_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int tc358764_ltl101a106_unprepare(struct drm_panel *panel)
+{
+	struct tc358764_ltl101a106 *ctx = to_tc358764_ltl101a106(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = tc358764_ltl101a106_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode tc358764_ltl101a106_mode = {
+	.clock = (1280 + 52 + 4 + 48) * (800 + 32 + 6 + 64) * 60 / 1000,
+	.hdisplay = 1280,
+	.hsync_start = 1280 + 52,
+	.hsync_end = 1280 + 52 + 4,
+	.htotal = 1280 + 52 + 4 + 48,
+	.vdisplay = 800,
+	.vsync_start = 800 + 32,
+	.vsync_end = 800 + 32 + 6,
+	.vtotal = 800 + 32 + 6 + 64,
+	.width_mm = 228,
+	.height_mm = 149,
+};
+
+static int tc358764_ltl101a106_get_modes(struct drm_panel *panel,
+					 struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &tc358764_ltl101a106_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs tc358764_ltl101a106_panel_funcs = {
+	.prepare = tc358764_ltl101a106_prepare,
+	.unprepare = tc358764_ltl101a106_unprepare,
+	.get_modes = tc358764_ltl101a106_get_modes,
+};
+
+static int tc358764_ltl101a106_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct tc358764_ltl101a106 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "lcd";
+	ctx->supplies[1].supply = "lvds";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			  MIPI_DSI_MODE_EOT_PACKET;
+
+	drm_panel_init(&ctx->panel, dev, &tc358764_ltl101a106_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int tc358764_ltl101a106_remove(struct mipi_dsi_device *dsi)
+{
+	struct tc358764_ltl101a106 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id tc358764_ltl101a106_of_match[] = {
+	{ .compatible = "samsung,tc358764-ltl101al06" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tc358764_ltl101a106_of_match);
+
+static struct mipi_dsi_driver tc358764_ltl101a106_driver = {
+	.probe = tc358764_ltl101a106_probe,
+	.remove = tc358764_ltl101a106_remove,
+	.driver = {
+		.name = "panel-tc358764-ltl101a106",
+		.of_match_table = tc358764_ltl101a106_of_match,
+	},
+};
+module_mipi_dsi_driver(tc358764_ltl101a106_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for ss_dsi_panel_TC358764_LTL101A106_WXGA");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-auo-r61308.c b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-auo-r61308.c
new file mode 100644
index 000000000..e5849050f
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-auo-r61308.c
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct r61308 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct r61308 *to_r61308(struct drm_panel *panel)
+{
+	return container_of(panel, struct r61308, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void r61308_reset(struct r61308 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(30);
+}
+
+static int r61308_on(struct r61308 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	dsi_dcs_write_seq(dsi, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
+
+	ret = mipi_dsi_dcs_set_pixel_format(dsi, 0x07);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set pixel format: %d\n", ret);
+		return ret;
+	}
+
+	dsi_generic_write_seq(dsi, 0xb0, 0x04);
+	dsi_generic_write_seq(dsi, 0xc1,
+			      0x50, 0x02, 0x22, 0x00, 0x00, 0xed, 0x11);
+	dsi_generic_write_seq(dsi, 0xc8,
+			      0x1a, 0x24, 0x29, 0x2d, 0x32, 0x37, 0x14, 0x13,
+			      0x10, 0x0c, 0x0a, 0x06, 0x1a, 0x24, 0x28, 0x2d,
+			      0x32, 0x37, 0x14, 0x13, 0x10, 0x0c, 0x0a, 0x06);
+	dsi_generic_write_seq(dsi, 0xcb,
+			      0x10, 0x20, 0x40, 0x80, 0xa0, 0xc0, 0xd0, 0xe0);
+	dsi_generic_write_seq(dsi, 0xcc, 0xc8, 0xd8, 0xff);
+	dsi_generic_write_seq(dsi, 0xcd,
+			      0x1c, 0x1e, 0x1e, 0x1d, 0x1c, 0x1e, 0x1e);
+	dsi_generic_write_seq(dsi, 0xce,
+			      0x1e, 0x1e, 0x1e, 0x1d, 0x1d, 0x1e, 0x1e);
+	dsi_generic_write_seq(dsi, 0xcf,
+			      0x1e, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21);
+	dsi_generic_write_seq(dsi, 0xb0, 0x03);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	usleep_range(10000, 11000);
+
+	return 0;
+}
+
+static int r61308_off(struct r61308 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int r61308_prepare(struct drm_panel *panel)
+{
+	struct r61308 *ctx = to_r61308(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	r61308_reset(ctx);
+
+	ret = r61308_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int r61308_unprepare(struct drm_panel *panel)
+{
+	struct r61308 *ctx = to_r61308(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = r61308_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode r61308_mode = {
+	.clock = (720 + 120 + 2 + 50) * (1280 + 6 + 1 + 14) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 120,
+	.hsync_end = 720 + 120 + 2,
+	.htotal = 720 + 120 + 2 + 50,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 6,
+	.vsync_end = 1280 + 6 + 1,
+	.vtotal = 1280 + 6 + 1 + 14,
+	.width_mm = 58,
+	.height_mm = 103,
+};
+
+static int r61308_get_modes(struct drm_panel *panel,
+			    struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &r61308_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs r61308_panel_funcs = {
+	.prepare = r61308_prepare,
+	.unprepare = r61308_unprepare,
+	.get_modes = r61308_get_modes,
+};
+
+static int r61308_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct r61308 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 3;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &r61308_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int r61308_remove(struct mipi_dsi_device *dsi)
+{
+	struct r61308 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id r61308_of_match[] = {
+	{ .compatible = "wingtech,auo-r61308" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, r61308_of_match);
+
+static struct mipi_dsi_driver r61308_driver = {
+	.probe = r61308_probe,
+	.remove = r61308_remove,
+	.driver = {
+		.name = "panel-r61308",
+		.of_match_table = r61308_of_match,
+	},
+};
+module_mipi_dsi_driver(r61308_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for r61308_HD720p_video_AUO3.5");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-ebbg-otm1285a.c b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-ebbg-otm1285a.c
new file mode 100644
index 000000000..9289d69d1
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-ebbg-otm1285a.c
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct otm1285a_otp {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct otm1285a_otp *to_otm1285a_otp(struct drm_panel *panel)
+{
+	return container_of(panel, struct otm1285a_otp, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void otm1285a_otp_reset(struct otm1285a_otp *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(10000, 11000);
+}
+
+static int otm1285a_otp_on(struct otm1285a_otp *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0xff, 0x12, 0x85, 0x01);
+	dsi_generic_write_seq(dsi, 0x00, 0x80);
+	dsi_generic_write_seq(dsi, 0xff, 0x12, 0x85);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x11);
+	msleep(120);
+	dsi_generic_write_seq(dsi, 0x00, 0x00);
+	dsi_generic_write_seq(dsi, 0x29);
+	usleep_range(10000, 11000);
+
+	return 0;
+}
+
+static int otm1285a_otp_off(struct otm1285a_otp *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int otm1285a_otp_prepare(struct drm_panel *panel)
+{
+	struct otm1285a_otp *ctx = to_otm1285a_otp(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	otm1285a_otp_reset(ctx);
+
+	ret = otm1285a_otp_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int otm1285a_otp_unprepare(struct drm_panel *panel)
+{
+	struct otm1285a_otp *ctx = to_otm1285a_otp(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = otm1285a_otp_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode otm1285a_otp_mode = {
+	.clock = (720 + 28 + 2 + 28) * (1280 + 30 + 2 + 30) * 59 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 28,
+	.hsync_end = 720 + 28 + 2,
+	.htotal = 720 + 28 + 2 + 28,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 30,
+	.vsync_end = 1280 + 30 + 2,
+	.vtotal = 1280 + 30 + 2 + 30,
+	.width_mm = 58,
+	.height_mm = 103,
+};
+
+static int otm1285a_otp_get_modes(struct drm_panel *panel,
+				  struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &otm1285a_otp_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs otm1285a_otp_panel_funcs = {
+	.prepare = otm1285a_otp_prepare,
+	.unprepare = otm1285a_otp_unprepare,
+	.get_modes = otm1285a_otp_get_modes,
+};
+
+static int otm1285a_otp_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct otm1285a_otp *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 3;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_HSE |
+			  MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &otm1285a_otp_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int otm1285a_otp_remove(struct mipi_dsi_device *dsi)
+{
+	struct otm1285a_otp *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id otm1285a_otp_of_match[] = {
+	{ .compatible = "wingtech,ebbg-otm1285a" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, otm1285a_otp_of_match);
+
+static struct mipi_dsi_driver otm1285a_otp_driver = {
+	.probe = otm1285a_otp_probe,
+	.remove = otm1285a_otp_remove,
+	.driver = {
+		.name = "panel-otm1285a-otp",
+		.of_match_table = otm1285a_otp_of_match,
+	},
+};
+module_mipi_dsi_driver(otm1285a_otp_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for otm1285a_otp_720p_video_EBBG");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-sharp-r69431.c b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-sharp-r69431.c
new file mode 100644
index 000000000..20b2e7a50
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-sharp-r69431.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct r69431 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct r69431 *to_r69431(struct drm_panel *panel)
+{
+	return container_of(panel, struct r69431, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void r69431_reset(struct r69431 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(10000, 11000);
+}
+
+static int r69431_on(struct r69431 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_generic_write_seq(dsi, 0xb0, 0x00);
+	dsi_generic_write_seq(dsi, 0xd6, 0x01);
+	dsi_generic_write_seq(dsi, 0xb3, 0x1c);
+	dsi_generic_write_seq(dsi, 0xb0, 0x03);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int r69431_off(struct r69431 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(20);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(220);
+
+	return 0;
+}
+
+static int r69431_prepare(struct drm_panel *panel)
+{
+	struct r69431 *ctx = to_r69431(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_enable(ctx->supply);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulator: %d\n", ret);
+		return ret;
+	}
+
+	r69431_reset(ctx);
+
+	ret = r69431_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_disable(ctx->supply);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int r69431_unprepare(struct drm_panel *panel)
+{
+	struct r69431 *ctx = to_r69431(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = r69431_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_disable(ctx->supply);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode r69431_mode = {
+	.clock = (720 + 120 + 10 + 20) * (1280 + 13 + 1 + 11) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 120,
+	.hsync_end = 720 + 120 + 10,
+	.htotal = 720 + 120 + 10 + 20,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 13,
+	.vsync_end = 1280 + 13 + 1,
+	.vtotal = 1280 + 13 + 1 + 11,
+	.width_mm = 58,
+	.height_mm = 103,
+};
+
+static int r69431_get_modes(struct drm_panel *panel,
+			    struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &r69431_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs r69431_panel_funcs = {
+	.prepare = r69431_prepare,
+	.unprepare = r69431_unprepare,
+	.get_modes = r69431_get_modes,
+};
+
+static int r69431_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct r69431 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supply = devm_regulator_get(dev, "power");
+	if (IS_ERR(ctx->supply))
+		return dev_err_probe(dev, PTR_ERR(ctx->supply),
+				     "Failed to get power regulator\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 3;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+			  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &r69431_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int r69431_remove(struct mipi_dsi_device *dsi)
+{
+	struct r69431 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id r69431_of_match[] = {
+	{ .compatible = "wingtech,sharp-r69431" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, r69431_of_match);
+
+static struct mipi_dsi_driver r69431_driver = {
+	.probe = r69431_probe,
+	.remove = r69431_remove,
+	.driver = {
+		.name = "panel-r69431",
+		.of_match_table = r69431_of_match,
+	},
+};
+module_mipi_dsi_driver(r69431_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for r69431_HD720p_video_sharp");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-tianma-hx8394d.c b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-tianma-hx8394d.c
new file mode 100644
index 000000000..d26cc906b
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-tianma-hx8394d.c
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct hx8394d {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct hx8394d *to_hx8394d(struct drm_panel *panel)
+{
+	return container_of(panel, struct hx8394d, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void hx8394d_reset(struct hx8394d *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(50);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	msleep(20);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+}
+
+static int hx8394d_on(struct hx8394d *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_dcs_write_seq(dsi, 0xb9, 0xff, 0x83, 0x94);
+	dsi_dcs_write_seq(dsi, 0xba, 0x33, 0x83, 0x20, 0x65, 0xb2, 0x09);
+	dsi_dcs_write_seq(dsi, 0xb1,
+			  0x6c, 0x11, 0x11, 0x37, 0x04, 0x11, 0xf1, 0x80, 0xdf,
+			  0x94, 0x23, 0x80, 0xc0, 0xd2, 0x18);
+	dsi_dcs_write_seq(dsi, 0xb2,
+			  0x00, 0x64, 0x0e, 0x0d, 0x32, 0x23, 0x08, 0x08, 0x1c,
+			  0x4d, 0x00);
+	dsi_dcs_write_seq(dsi, 0xb4,
+			  0x00, 0xff, 0x03, 0x46, 0x03, 0x46, 0x03, 0x46, 0x01,
+			  0x6a, 0x01, 0x6a);
+	dsi_dcs_write_seq(dsi, 0xbf, 0x41, 0x0e, 0x01);
+	dsi_dcs_write_seq(dsi, 0xd3,
+			  0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x32, 0x10,
+			  0x05, 0x00, 0x05, 0x32, 0x10, 0x00, 0x00, 0x00, 0x32,
+			  0x10, 0x00, 0x00, 0x00, 0x36, 0x03, 0x09, 0x09, 0x37,
+			  0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+			  0x01);
+	dsi_dcs_write_seq(dsi, 0xd5,
+			  0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x20,
+			  0x21, 0x22, 0x23, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x18, 0x18, 0x24, 0x25, 0x18, 0x18, 0x19, 0x19);
+	dsi_dcs_write_seq(dsi, 0xd6,
+			  0x05, 0x04, 0x07, 0x06, 0x01, 0x00, 0x03, 0x02, 0x23,
+			  0x22, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x58, 0x58, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+			  0x18, 0x18, 0x25, 0x24, 0x19, 0x19, 0x18, 0x18);
+	dsi_dcs_write_seq(dsi, 0xe0,
+			  0x02, 0x10, 0x14, 0x2c, 0x2f, 0x3f, 0x22, 0x40, 0x06,
+			  0x0a, 0x0c, 0x17, 0x0e, 0x12, 0x14, 0x13, 0x14, 0x08,
+			  0x12, 0x14, 0x1b, 0x02, 0x10, 0x14, 0x2c, 0x2f, 0x3f,
+			  0x22, 0x40, 0x06, 0x0a, 0x0c, 0x17, 0x0e, 0x12, 0x14,
+			  0x13, 0x14, 0x08, 0x12, 0x14, 0x1b);
+	dsi_dcs_write_seq(dsi, 0xcc, 0x09);
+	dsi_dcs_write_seq(dsi, 0xc7, 0x00, 0xc0, 0x40, 0xc0);
+	dsi_dcs_write_seq(dsi, 0xc0, 0x30, 0x14);
+	dsi_dcs_write_seq(dsi, 0xbc, 0x07);
+
+	ret = mipi_dsi_dcs_set_display_brightness(dsi, 0x00ff);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display brightness: %d\n", ret);
+		return ret;
+	}
+
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x24);
+	dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x00);
+	dsi_dcs_write_seq(dsi, 0xe4, 0x51, 0x00);
+	dsi_dcs_write_seq(dsi, 0xe6,
+			  0x00, 0x00, 0x00, 0x05, 0x05, 0x10, 0x0a, 0x08, 0x10,
+			  0x20, 0x20, 0x0c, 0x08, 0x0f, 0x20, 0x20, 0x20);
+
+	ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set tear on: %d\n", ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(200);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int hx8394d_off(struct hx8394d *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int hx8394d_prepare(struct drm_panel *panel)
+{
+	struct hx8394d *ctx = to_hx8394d(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	hx8394d_reset(ctx);
+
+	ret = hx8394d_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int hx8394d_unprepare(struct drm_panel *panel)
+{
+	struct hx8394d *ctx = to_hx8394d(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = hx8394d_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode hx8394d_mode = {
+	.clock = (720 + 168 + 24 + 240) * (1280 + 20 + 4 + 12) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 168,
+	.hsync_end = 720 + 168 + 24,
+	.htotal = 720 + 168 + 24 + 240,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 20,
+	.vsync_end = 1280 + 20 + 4,
+	.vtotal = 1280 + 20 + 4 + 12,
+	.width_mm = 59,
+	.height_mm = 104,
+};
+
+static int hx8394d_get_modes(struct drm_panel *panel,
+			     struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &hx8394d_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs hx8394d_panel_funcs = {
+	.prepare = hx8394d_prepare,
+	.unprepare = hx8394d_unprepare,
+	.get_modes = hx8394d_get_modes,
+};
+
+static int hx8394d_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct hx8394d *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vsp";
+	ctx->supplies[1].supply = "vsn";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &hx8394d_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int hx8394d_remove(struct mipi_dsi_device *dsi)
+{
+	struct hx8394d *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id hx8394d_of_match[] = {
+	{ .compatible = "wingtech,tianma-hx8394d" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hx8394d_of_match);
+
+static struct mipi_dsi_driver hx8394d_driver = {
+	.probe = hx8394d_probe,
+	.remove = hx8394d_remove,
+	.driver = {
+		.name = "panel-hx8394d",
+		.of_match_table = hx8394d_of_match,
+	},
+};
+module_mipi_dsi_driver(hx8394d_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for hx8394d_HD720p_video_Tianma");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-yassy-ili9881.c b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-yassy-ili9881.c
new file mode 100644
index 000000000..c59ba1779
--- /dev/null
+++ b/drivers/gpu/drm/panel/msm8916-generated/panel-wingtech-yassy-ili9881.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (c) 2021 FIXME
+// Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:
+//   Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME)
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct ili9881 {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	bool prepared;
+};
+
+static inline struct ili9881 *to_ili9881(struct drm_panel *panel)
+{
+	return container_of(panel, struct ili9881, panel);
+}
+
+#define dsi_dcs_write_seq(dsi, seq...) do {				\
+		static const u8 d[] = { seq };				\
+		int ret;						\
+		ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d));	\
+		if (ret < 0)						\
+			return ret;					\
+	} while (0)
+
+static void ili9881_reset(struct ili9881 *ctx)
+{
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	usleep_range(5000, 6000);
+	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+	msleep(30);
+}
+
+static int ili9881_on(struct ili9881 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	dsi_dcs_write_seq(dsi, 0xff, 0x98, 0x81, 0x07);
+	dsi_dcs_write_seq(dsi, 0x03, 0x20);
+	dsi_dcs_write_seq(dsi, 0x04, 0x06);
+	dsi_dcs_write_seq(dsi, 0x05, 0x00);
+	dsi_dcs_write_seq(dsi, 0x06, 0x01);
+	dsi_dcs_write_seq(dsi, 0x07, 0x00);
+	dsi_dcs_write_seq(dsi, 0x08, 0x00);
+	dsi_dcs_write_seq(dsi, 0x09, 0x00);
+	dsi_dcs_write_seq(dsi, 0x0a, 0x00);
+	dsi_dcs_write_seq(dsi, 0x0b, 0x2f);
+	dsi_dcs_write_seq(dsi, 0x0c, 0x00);
+	dsi_dcs_write_seq(dsi, 0x0d, 0x00);
+	dsi_dcs_write_seq(dsi, 0x0e, 0x00);
+	dsi_dcs_write_seq(dsi, 0x0f, 0x00);
+	dsi_dcs_write_seq(dsi, 0x10, 0x40);
+	dsi_dcs_write_seq(dsi, 0x11, 0x02);
+	dsi_dcs_write_seq(dsi, 0x12, 0x05);
+	dsi_dcs_write_seq(dsi, 0x13, 0x90);
+	dsi_dcs_write_seq(dsi, 0x14, 0x02);
+	dsi_dcs_write_seq(dsi, 0x15, 0x00);
+	dsi_dcs_write_seq(dsi, 0x16, 0x2f);
+	dsi_dcs_write_seq(dsi, 0x17, 0x2f);
+	dsi_dcs_write_seq(dsi, 0x18, 0x00);
+	dsi_dcs_write_seq(dsi, 0x19, 0x00);
+	dsi_dcs_write_seq(dsi, 0x1a, 0x00);
+	dsi_dcs_write_seq(dsi, 0x1b, 0x50);
+	dsi_dcs_write_seq(dsi, 0x1c, 0x2c);
+	dsi_dcs_write_seq(dsi, 0x1d, 0x0c);
+	dsi_dcs_write_seq(dsi, 0x1e, 0x00);
+	dsi_dcs_write_seq(dsi, 0x1f, 0x87);
+	dsi_dcs_write_seq(dsi, 0x20, 0x86);
+	dsi_dcs_write_seq(dsi, 0x21, 0x00);
+	dsi_dcs_write_seq(dsi, 0x22, 0x00);
+	dsi_dcs_write_seq(dsi, 0x23, 0xc0);
+	dsi_dcs_write_seq(dsi, 0x24, 0x30);
+	dsi_dcs_write_seq(dsi, 0x25, 0x00);
+	dsi_dcs_write_seq(dsi, 0x26, 0x00);
+	dsi_dcs_write_seq(dsi, 0x27, 0x03);
+	dsi_dcs_write_seq(dsi, 0x30, 0x01);
+	dsi_dcs_write_seq(dsi, 0x31, 0x23);
+	dsi_dcs_write_seq(dsi, 0x32, 0x45);
+	dsi_dcs_write_seq(dsi, 0x33, 0x67);
+	dsi_dcs_write_seq(dsi, 0x34, 0x89);
+	dsi_dcs_write_seq(dsi, 0x35, 0xab);
+	dsi_dcs_write_seq(dsi, 0x36, 0x01);
+	dsi_dcs_write_seq(dsi, 0x37, 0x23);
+	dsi_dcs_write_seq(dsi, 0x38, 0x45);
+	dsi_dcs_write_seq(dsi, 0x39, 0x67);
+	dsi_dcs_write_seq(dsi, 0x3a, 0x89);
+	dsi_dcs_write_seq(dsi, 0x3b, 0xab);
+	dsi_dcs_write_seq(dsi, 0x3c, 0xcd);
+	dsi_dcs_write_seq(dsi, 0x3d, 0xef);
+	dsi_dcs_write_seq(dsi, 0x50, 0x11);
+	dsi_dcs_write_seq(dsi, 0x51, 0x06);
+	dsi_dcs_write_seq(dsi, 0x52, 0x0c);
+	dsi_dcs_write_seq(dsi, 0x53, 0x0d);
+	dsi_dcs_write_seq(dsi, 0x54, 0x0e);
+	dsi_dcs_write_seq(dsi, 0x55, 0x0f);
+	dsi_dcs_write_seq(dsi, 0x56, 0x02);
+	dsi_dcs_write_seq(dsi, 0x57, 0x02);
+	dsi_dcs_write_seq(dsi, 0x58, 0x02);
+	dsi_dcs_write_seq(dsi, 0x59, 0x02);
+	dsi_dcs_write_seq(dsi, 0x5a, 0x02);
+	dsi_dcs_write_seq(dsi, 0x5b, 0x02);
+	dsi_dcs_write_seq(dsi, 0x5c, 0x02);
+	dsi_dcs_write_seq(dsi, 0x5d, 0x02);
+	dsi_dcs_write_seq(dsi, 0x5e, 0x02);
+	dsi_dcs_write_seq(dsi, 0x5f, 0x02);
+	dsi_dcs_write_seq(dsi, 0x60, 0x05);
+	dsi_dcs_write_seq(dsi, 0x61, 0x05);
+	dsi_dcs_write_seq(dsi, 0x62, 0x05);
+	dsi_dcs_write_seq(dsi, 0x63, 0x02);
+	dsi_dcs_write_seq(dsi, 0x64, 0x01);
+	dsi_dcs_write_seq(dsi, 0x65, 0x00);
+	dsi_dcs_write_seq(dsi, 0x66, 0x08);
+	dsi_dcs_write_seq(dsi, 0x67, 0x08);
+	dsi_dcs_write_seq(dsi, 0x68, 0x0c);
+	dsi_dcs_write_seq(dsi, 0x69, 0x0d);
+	dsi_dcs_write_seq(dsi, 0x6a, 0x0e);
+	dsi_dcs_write_seq(dsi, 0x6b, 0x0f);
+	dsi_dcs_write_seq(dsi, 0x6c, 0x02);
+	dsi_dcs_write_seq(dsi, 0x6d, 0x02);
+	dsi_dcs_write_seq(dsi, 0x6e, 0x02);
+	dsi_dcs_write_seq(dsi, 0x6f, 0x02);
+	dsi_dcs_write_seq(dsi, 0x70, 0x02);
+	dsi_dcs_write_seq(dsi, 0x71, 0x02);
+	dsi_dcs_write_seq(dsi, 0x72, 0x02);
+	dsi_dcs_write_seq(dsi, 0x73, 0x02);
+	dsi_dcs_write_seq(dsi, 0x74, 0x02);
+	dsi_dcs_write_seq(dsi, 0x75, 0x02);
+	dsi_dcs_write_seq(dsi, 0x76, 0x05);
+	dsi_dcs_write_seq(dsi, 0x77, 0x05);
+	dsi_dcs_write_seq(dsi, 0x78, 0x05);
+	dsi_dcs_write_seq(dsi, 0x79, 0x02);
+	dsi_dcs_write_seq(dsi, 0x7a, 0x01);
+	dsi_dcs_write_seq(dsi, 0x7b, 0x00);
+	dsi_dcs_write_seq(dsi, 0x7c, 0x06);
+	dsi_dcs_write_seq(dsi, 0xff, 0x98, 0x81, 0x08);
+	dsi_dcs_write_seq(dsi, 0x76, 0xb4);
+	dsi_dcs_write_seq(dsi, 0x78, 0x02);
+	dsi_dcs_write_seq(dsi, 0x74, 0x2b);
+	dsi_dcs_write_seq(dsi, 0x8e, 0x15);
+	dsi_dcs_write_seq(dsi, 0x40, 0x01);
+	dsi_dcs_write_seq(dsi, 0x7b, 0x04);
+	dsi_dcs_write_seq(dsi, 0x72, 0x25);
+	dsi_dcs_write_seq(dsi, 0x87, 0x3a);
+	dsi_dcs_write_seq(dsi, 0x7e, 0x4c);
+	dsi_dcs_write_seq(dsi, 0x6c, 0x05);
+	dsi_dcs_write_seq(dsi, 0x49, 0x10);
+	dsi_dcs_write_seq(dsi, 0x2d, 0x80);
+	dsi_dcs_write_seq(dsi, 0x50, 0x65);
+	dsi_dcs_write_seq(dsi, 0x53, 0x29);
+	dsi_dcs_write_seq(dsi, 0x54, 0x65);
+	dsi_dcs_write_seq(dsi, 0x55, 0x38);
+	dsi_dcs_write_seq(dsi, 0x57, 0x47);
+	dsi_dcs_write_seq(dsi, 0x58, 0x47);
+	dsi_dcs_write_seq(dsi, 0xff, 0x98, 0x81, 0x01);
+	dsi_dcs_write_seq(dsi, 0x22, 0x0a);
+	dsi_dcs_write_seq(dsi, 0x53, 0x91);
+	dsi_dcs_write_seq(dsi, 0x55, 0x78);
+	dsi_dcs_write_seq(dsi, 0x50, 0xa5);
+	dsi_dcs_write_seq(dsi, 0x51, 0xa2);
+	dsi_dcs_write_seq(dsi, 0x31, 0x00);
+	dsi_dcs_write_seq(dsi, 0xa0, 0x0a);
+	dsi_dcs_write_seq(dsi, 0xa1, 0x1f);
+	dsi_dcs_write_seq(dsi, 0xa2, 0x2e);
+	dsi_dcs_write_seq(dsi, 0xa3, 0x16);
+	dsi_dcs_write_seq(dsi, 0xa4, 0x1b);
+	dsi_dcs_write_seq(dsi, 0xa5, 0x27);
+	dsi_dcs_write_seq(dsi, 0xa6, 0x1f);
+	dsi_dcs_write_seq(dsi, 0xa7, 0x1e);
+	dsi_dcs_write_seq(dsi, 0xa8, 0x94);
+	dsi_dcs_write_seq(dsi, 0xa9, 0x1e);
+	dsi_dcs_write_seq(dsi, 0xaa, 0x2b);
+	dsi_dcs_write_seq(dsi, 0xab, 0x93);
+	dsi_dcs_write_seq(dsi, 0xac, 0x1e);
+	dsi_dcs_write_seq(dsi, 0xad, 0x1d);
+	dsi_dcs_write_seq(dsi, 0xae, 0x53);
+	dsi_dcs_write_seq(dsi, 0xaf, 0x26);
+	dsi_dcs_write_seq(dsi, 0xb0, 0x2d);
+	dsi_dcs_write_seq(dsi, 0xb1, 0x55);
+	dsi_dcs_write_seq(dsi, 0xb2, 0x68);
+	dsi_dcs_write_seq(dsi, 0xb3, 0x3f);
+	dsi_dcs_write_seq(dsi, 0xc0, 0x01);
+	dsi_dcs_write_seq(dsi, 0xc1, 0x0f);
+	dsi_dcs_write_seq(dsi, 0xc2, 0x19);
+	dsi_dcs_write_seq(dsi, 0xc3, 0x16);
+	dsi_dcs_write_seq(dsi, 0xc4, 0x14);
+	dsi_dcs_write_seq(dsi, 0xc5, 0x25);
+	dsi_dcs_write_seq(dsi, 0xc6, 0x15);
+	dsi_dcs_write_seq(dsi, 0xc7, 0x1c);
+	dsi_dcs_write_seq(dsi, 0xc8, 0x78);
+	dsi_dcs_write_seq(dsi, 0xc9, 0x1d);
+	dsi_dcs_write_seq(dsi, 0xca, 0x28);
+	dsi_dcs_write_seq(dsi, 0xcb, 0x6a);
+	dsi_dcs_write_seq(dsi, 0xcc, 0x1c);
+	dsi_dcs_write_seq(dsi, 0xcd, 0x1a);
+	dsi_dcs_write_seq(dsi, 0xce, 0x4c);
+	dsi_dcs_write_seq(dsi, 0xcf, 0x1f);
+	dsi_dcs_write_seq(dsi, 0xd0, 0x25);
+	dsi_dcs_write_seq(dsi, 0xd1, 0x54);
+	dsi_dcs_write_seq(dsi, 0xd2, 0x62);
+	dsi_dcs_write_seq(dsi, 0xd3, 0x3f);
+	dsi_dcs_write_seq(dsi, 0xff, 0x98, 0x81, 0x06);
+	dsi_dcs_write_seq(dsi, 0x1b, 0x02);
+	dsi_dcs_write_seq(dsi, 0x5a, 0x03);
+	dsi_dcs_write_seq(dsi, 0x1a, 0x06);
+	dsi_dcs_write_seq(dsi, 0x20, 0x09);
+	dsi_dcs_write_seq(dsi, 0x21, 0x0c);
+	dsi_dcs_write_seq(dsi, 0x22, 0x0f);
+	dsi_dcs_write_seq(dsi, 0xff, 0x98, 0x81, 0x00);
+	dsi_dcs_write_seq(dsi, 0x55, 0x80);
+	// WARNING: Ignoring weird SET_MAXIMUM_RETURN_PACKET_SIZE
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	ret = mipi_dsi_dcs_set_display_on(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	usleep_range(10000, 11000);
+
+	return 0;
+}
+
+static int ili9881_off(struct ili9881 *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set display off: %d\n", ret);
+		return ret;
+	}
+	msleep(20);
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+	msleep(120);
+
+	return 0;
+}
+
+static int ili9881_prepare(struct drm_panel *panel)
+{
+	struct ili9881 *ctx = to_ili9881(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable regulators: %d\n", ret);
+		return ret;
+	}
+
+	ili9881_reset(ctx);
+
+	ret = ili9881_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+		regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int ili9881_unprepare(struct drm_panel *panel)
+{
+	struct ili9881 *ctx = to_ili9881(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = ili9881_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
+
+	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+static const struct drm_display_mode ili9881_mode = {
+	.clock = (720 + 168 + 24 + 240) * (1280 + 12 + 4 + 20) * 60 / 1000,
+	.hdisplay = 720,
+	.hsync_start = 720 + 168,
+	.hsync_end = 720 + 168 + 24,
+	.htotal = 720 + 168 + 24 + 240,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 12,
+	.vsync_end = 1280 + 12 + 4,
+	.vtotal = 1280 + 12 + 4 + 20,
+	.width_mm = 59,
+	.height_mm = 104,
+};
+
+static int ili9881_get_modes(struct drm_panel *panel,
+			     struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &ili9881_mode);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_set_name(mode);
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs ili9881_panel_funcs = {
+	.prepare = ili9881_prepare,
+	.unprepare = ili9881_unprepare,
+	.get_modes = ili9881_get_modes,
+};
+
+static int ili9881_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct ili9881 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "vsp";
+	ctx->supplies[1].supply = "vsn";
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
+				      ctx->supplies);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+				     "Failed to get reset-gpios\n");
+
+	ctx->dsi = dsi;
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+			  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &ili9881_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
+	ret = drm_panel_of_backlight(&ctx->panel);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get backlight\n");
+
+	drm_panel_add(&ctx->panel);
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
+		drm_panel_remove(&ctx->panel);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ili9881_remove(struct mipi_dsi_device *dsi)
+{
+	struct ili9881 *ctx = mipi_dsi_get_drvdata(dsi);
+	int ret;
+
+	ret = mipi_dsi_detach(dsi);
+	if (ret < 0)
+		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+	drm_panel_remove(&ctx->panel);
+
+	return 0;
+}
+
+static const struct of_device_id ili9881_of_match[] = {
+	{ .compatible = "wingtech,yassy-ili9881" }, // FIXME
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ili9881_of_match);
+
+static struct mipi_dsi_driver ili9881_driver = {
+	.probe = ili9881_probe,
+	.remove = ili9881_remove,
+	.driver = {
+		.name = "panel-ili9881",
+		.of_match_table = ili9881_of_match,
+	},
+};
+module_mipi_dsi_driver(ili9881_driver);
+
+MODULE_AUTHOR("linux-mdss-dsi-panel-driver-generator <fix@me>"); // FIXME
+MODULE_DESCRIPTION("DRM driver for ili9881_HD720p_video_Yassy");
+MODULE_LICENSE("GPL v2");
-- 
2.31.1

