[v4] drm/panel: add s6e3ha2 AMOLED panel driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds MIPI-DSI based S6E3HA2 panel driver. This panel has
1440x2560 resolution in 5.7-inch physical panel.

Signed-off-by: Donghwa Lee <dh09.lee@xxxxxxxxxxx>
Signed-off-by: Hyungwon Hwang <human.hwang@xxxxxxxxxxx>
Cc: Inki Dae <inki.dae@xxxxxxxxxxx>
---
As Thierry Reding said in https://patchwork.kernel.org/patch/5714111/,
it can be confusing to check the result of a function call using a
variable which is not explicitly passed to function call. At the same
time, as Andrzej Hajda said, checking the result using the return value
in this driver makes the code too bloated. In the situation where many
simple function calls and the result checking for them are needed, I
thought that passing variable by reference with explicit variable is
the best.

Changes for v2:
- Fix errata in documentation and source code comments
Changes for v3:
- Remove the term LCD to clarify the sort of this panel
- Rename lcd-en-gpios to panel-en-gpios to clarify the sort of this panel
- Fix errata in documentation and source code comments
Changes for v4:
- Add support for brightness control
- Adjust the sequence of turning on/off
- Rename variable and properties for clarity
 .../devicetree/bindings/panel/samsung,s6e3ha2.txt  |  40 +
 drivers/gpu/drm/panel/Kconfig                      |  11 +
 drivers/gpu/drm/panel/Makefile                     |   1 +
 drivers/gpu/drm/panel/panel-s6e3ha2.c              | 904 +++++++++++++++++++++
 4 files changed, 956 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
 create mode 100644 drivers/gpu/drm/panel/panel-s6e3ha2.c

diff --git a/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt b/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
new file mode 100644
index 0000000..b8cacc0
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
@@ -0,0 +1,40 @@
+Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel
+
+Required properties:
+  - compatible: "samsung,s6e3ha2"
+  - reg: virtual channel number assigned to the panel
+  - vdd3-supply: core voltage supply
+  - vci-supply: voltage supply for analog circuits
+  - reset-gpio: GPIO spec for resetting
+  - enable-gpio: GPIO spec for enabling
+  - te-gpio: GPIO spec for receiving tearing effect synchronization signal
+  - display-timings: resolution, clock, timing information for the panel [1]
+
+[1]: Documentation/devicetree/bindings/video/display-timing.txt
+
+Example:
+
+panel@0 {
+	compatible = "samsung,s6e3ha2";
+	reg = <0>;
+	vdd3-supply = <&ldo27_reg>;
+	vci-supply = <&ldo28_reg>;
+	reset-gpio = <&gpg0 0 GPIO_ACTIVE_LOW>;
+	enable-gpio = <&gpf1 5 GPIO_ACTIVE_HIGH>;
+	te-gpio = <&gpf1 3 GPIO_ACTIVE_LOW>;
+
+	display-timings {
+		timing-0 {
+			clock-frequency = <0>;
+			hactive = <1440>;
+			vactive = <2560>;
+			hfront-porch = <1>;
+			hback-porch = <1>;
+			hsync-len = <1>;
+			vfront-porch = <1>;
+			vback-porch = <15>;
+			vsync-len = <1>;
+		};
+	};
+};
+
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 6d64c7b..7833073 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -43,4 +43,15 @@ config DRM_PANEL_SHARP_LQ101R1SX01
 	  To compile this driver as a module, choose M here: the module
 	  will be called panel-sharp-lq101r1sx01.

+config DRM_PANEL_S6E3HA2
+	tristate "S6E3HA2 DSI command mode panel"
+	depends on OF
+	depends on BACKLIGHT_CLASS_DEVICE
+	depends on DRM_MIPI_DSI
+	select VIDEOMODE_HELPERS
+	  Say Y here if you want to enable support for Samsung S6E3HA2
+	  AMOLED panel module. This panel has a 1440x2560 resolution and
+	  uses 32-bit RGB per pixel. It provides a 4 lane MIPI DSI interface
+	  to the host.
+
 endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 4b2a043..16ff312 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
 obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o
 obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o
 obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
+obj-$(CONFIG_DRM_PANEL_S6E3HA2) += panel-s6e3ha2.o
diff --git a/drivers/gpu/drm/panel/panel-s6e3ha2.c b/drivers/gpu/drm/panel/panel-s6e3ha2.c
new file mode 100644
index 0000000..8cf5b7e
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-s6e3ha2.c
@@ -0,0 +1,904 @@
+/*
+ * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * Donghwa Lee <dh09.lee@xxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <drm/drmP.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+#include <linux/backlight.h>
+
+#define MIN_BRIGHTNESS		0
+#define MAX_BRIGHTNESS		100
+#define DEFAULT_BRIGHTNESS	80
+
+#define MIN_GAMMA		2
+#define MAX_GAMMA		350
+#define NUM_GAMMA_STEPS		66
+#define GAMMA_CMD_CNT		35
+#define VINT_STATUS_MAX		10
+
+static const u8 AOR_TBL[NUM_GAMMA_STEPS][2] = {
+	{ 0xe5, 0x90 }, { 0xcc, 0x90 }, { 0xb6, 0x90 }, { 0xa3, 0x90 },
+	{ 0x8e, 0x90 }, { 0x79, 0x90 }, { 0x66, 0x90 }, { 0x57, 0x90 },
+	{ 0x44, 0x90 }, { 0x35, 0x90 }, { 0x25, 0x90 }, { 0x14, 0x90 },
+	{ 0x05, 0x90 }, { 0xeb, 0x80 }, { 0xe0, 0x80 }, { 0xc7, 0x80 },
+	{ 0xa4, 0x80 }, { 0x92, 0x80 }, { 0x7b, 0x80 }, { 0x67, 0x80 },
+	{ 0x43, 0x80 }, { 0x2f, 0x80 }, { 0xfd, 0x70 }, { 0xdf, 0x70 },
+	{ 0xc7, 0x70 }, { 0xa4, 0x70 }, { 0x6f, 0x70 }, { 0x3d, 0x70 },
+	{ 0x14, 0x70 }, { 0xee, 0x60 }, { 0xb2, 0x60 }, { 0x73, 0x60 },
+	{ 0x34, 0x60 }, { 0xf4, 0x50 }, { 0xb5, 0x50 }, { 0x5f, 0x50 },
+	{ 0x0e, 0x50 }, { 0xb4, 0x40 }, { 0x62, 0x40 }, { 0xed, 0x30 },
+	{ 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 },
+	{ 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 },
+	{ 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 },
+	{ 0xed, 0x30 }, { 0xa7, 0x30 }, { 0x26, 0x30 }, { 0xb5, 0x20 },
+	{ 0x26, 0x20 }, { 0x8f, 0x10 }, { 0x03, 0x10 }, { 0x03, 0x10 },
+	{ 0x03, 0x10 }, { 0x03, 0x10 }, { 0x03, 0x10 }, { 0x03, 0x10 },
+	{ 0x03, 0x10 }, { 0x03, 0x10 },
+};
+
+static const u8 GAMMA_TBL[NUM_GAMMA_STEPS][GAMMA_CMD_CNT] = {
+	{ 0x00, 0xb5, 0x00, 0xc7, 0x00, 0xb1, 0x8c, 0x8c, 0x8b, 0x86, 0x8a,
+	  0x8a, 0x86, 0x92, 0x8e, 0x81, 0x97, 0x87, 0x96, 0x9b, 0x98, 0x9d,
+	  0x9d, 0x8f, 0xb5, 0x99, 0x8d, 0x5c, 0x51, 0x66, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb5, 0x00, 0xc6, 0x00, 0xb0, 0x8a, 0x89, 0x8a, 0x83, 0x88,
+	  0x88, 0x88, 0x93, 0x8e, 0x74, 0x8d, 0x7d, 0x9b, 0x9d, 0x9c, 0x9a,
+	  0x9d, 0x90, 0xc7, 0xaa, 0x9e, 0x59, 0x4d, 0x63, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc7, 0x00, 0xb2, 0x89, 0x88, 0x89, 0x85, 0x89,
+	  0x89, 0x88, 0x91, 0x8c, 0x81, 0x92, 0x89, 0x89, 0x96, 0x8f, 0x93,
+	  0x9c, 0x8b, 0xbe, 0xad, 0x9a, 0xce, 0xaa, 0xc2, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc6, 0x00, 0xb2, 0x88, 0x89, 0x88, 0x84, 0x88,
+	  0x88, 0x88, 0x90, 0x8c, 0x82, 0x90, 0x8a, 0x86, 0x93, 0x8c, 0x91,
+	  0x9b, 0x8d, 0xbc, 0xac, 0x99, 0xd3, 0xaf, 0xc7, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb6, 0x00, 0xc4, 0x00, 0xaf, 0x89, 0x88, 0x88, 0x84, 0x88,
+	  0x88, 0x87, 0x8e, 0x8a, 0x83, 0x90, 0x8a, 0x86, 0x93, 0x8c, 0x91,
+	  0x9a, 0x8c, 0xbb, 0xae, 0x98, 0xd6, 0xb2, 0xca, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb7, 0x00, 0xc4, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84, 0x88,
+	  0x88, 0x87, 0x8e, 0x8a, 0x85, 0x90, 0x88, 0x85, 0x91, 0x8a, 0x94,
+	  0x9b, 0x8e, 0xb5, 0xb0, 0x95, 0xda, 0xb5, 0xcd, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x87, 0x88, 0x87, 0x85, 0x88,
+	  0x89, 0x87, 0x8e, 0x8a, 0x86, 0x8f, 0x88, 0x84, 0x91, 0x89, 0x92,
+	  0x99, 0x8d, 0xb5, 0xb0, 0x93, 0xd2, 0xaf, 0xc8, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x88, 0x88, 0x87, 0x84, 0x87,
+	  0x88, 0x87, 0x8e, 0x8b, 0x87, 0x91, 0x88, 0x86, 0x90, 0x89, 0x8f,
+	  0x99, 0x8a, 0xb4, 0xb0, 0x93, 0xcd, 0xab, 0xc5, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84, 0x87,
+	  0x88, 0x87, 0x8e, 0x8b, 0x83, 0x8d, 0x84, 0x88, 0x91, 0x8a, 0x8f,
+	  0x98, 0x8a, 0xb4, 0xb0, 0x93, 0xdb, 0xb7, 0xcf, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84, 0x87,
+	  0x88, 0x88, 0x8d, 0x8a, 0x85, 0x8e, 0x85, 0x85, 0x8e, 0x88, 0x92,
+	  0x9a, 0x8c, 0xb2, 0xb0, 0x90, 0xc9, 0xa7, 0xc3, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84, 0x86,
+	  0x87, 0x89, 0x8d, 0x8b, 0x85, 0x8e, 0x85, 0x87, 0x8e, 0x89, 0x8f,
+	  0x98, 0x8a, 0xb2, 0xb0, 0x91, 0xd2, 0xaf, 0xca, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x88, 0x87, 0x87, 0x84, 0x86,
+	  0x87, 0x88, 0x8c, 0x8a, 0x86, 0x8f, 0x86, 0x87, 0x8e, 0x89, 0x8e,
+	  0x97, 0x88, 0xb1, 0xb1, 0x90, 0xd2, 0xaf, 0xca, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x85,
+	  0x86, 0x88, 0x8c, 0x89, 0x85, 0x8d, 0x85, 0x88, 0x8d, 0x8a, 0x8f,
+	  0x9a, 0x87, 0xb3, 0xb1, 0x90, 0xd7, 0xb3, 0xcd, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84, 0x86,
+	  0x87, 0x88, 0x8c, 0x8a, 0x85, 0x8c, 0x84, 0x88, 0x8d, 0x8a, 0x8c,
+	  0x96, 0x85, 0xb2, 0xb0, 0x92, 0xcc, 0xaa, 0xc6, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x85,
+	  0x86, 0x88, 0x8c, 0x89, 0x84, 0x8b, 0x83, 0x87, 0x8d, 0x8a, 0x8d,
+	  0x96, 0x87, 0xb2, 0xb2, 0x8f, 0xd6, 0xb3, 0xcd, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x84,
+	  0x85, 0x88, 0x8c, 0x89, 0x84, 0x8b, 0x84, 0x87, 0x8d, 0x8a, 0x8b,
+	  0x94, 0x84, 0xb3, 0xb1, 0x92, 0xc5, 0xa5, 0xc1, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x84,
+	  0x85, 0x88, 0x8c, 0x89, 0x82, 0x89, 0x82, 0x86, 0x8c, 0x88, 0x8b,
+	  0x94, 0x84, 0xb6, 0xb2, 0x91, 0xd0, 0xae, 0xc9, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x84,
+	  0x85, 0x87, 0x8b, 0x89, 0x83, 0x8a, 0x83, 0x85, 0x8b, 0x87, 0x8b,
+	  0x95, 0x85, 0xb4, 0xae, 0x8e, 0xbf, 0x9f, 0xbd, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x84,
+	  0x84, 0x87, 0x8b, 0x8a, 0x84, 0x8a, 0x83, 0x83, 0x89, 0x85, 0x8e,
+	  0x97, 0x8a, 0xaf, 0xac, 0x8d, 0xb9, 0x9b, 0xb9, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x84,
+	  0x84, 0x87, 0x8b, 0x8a, 0x82, 0x88, 0x82, 0x85, 0x8c, 0x88, 0x8c,
+	  0x94, 0x87, 0xb1, 0xaf, 0x8f, 0xc4, 0xa4, 0xc1, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x82, 0x83,
+	  0x85, 0x88, 0x8b, 0x8b, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8c,
+	  0x94, 0x84, 0xb1, 0xaf, 0x8e, 0xcf, 0xad, 0xc9, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84, 0x84,
+	  0x85, 0x87, 0x8b, 0x8a, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8a,
+	  0x93, 0x84, 0xb0, 0xae, 0x8e, 0xc9, 0xa8, 0xc5, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x88, 0x81, 0x84, 0x8a, 0x88, 0x8a,
+	  0x91, 0x84, 0xb1, 0xae, 0x8b, 0xd5, 0xb2, 0xcc, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x87, 0x81, 0x84, 0x8a, 0x87, 0x8a,
+	  0x91, 0x85, 0xae, 0xac, 0x8a, 0xc3, 0xa3, 0xc0, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x85, 0x85,
+	  0x86, 0x85, 0x88, 0x89, 0x84, 0x89, 0x82, 0x84, 0x87, 0x85, 0x8b,
+	  0x91, 0x88, 0xad, 0xab, 0x8a, 0xb7, 0x9b, 0xb6, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x89, 0x8a, 0x84, 0x89, 0x83, 0x83, 0x86, 0x84, 0x8b,
+	  0x90, 0x84, 0xb0, 0xae, 0x8b, 0xce, 0xad, 0xc8, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
+	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x89,
+	  0x8f, 0x84, 0xac, 0xaa, 0x89, 0xb1, 0x98, 0xaf, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x88, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8c,
+	  0x91, 0x86, 0xac, 0xaa, 0x89, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x88,
+	  0x8b, 0x82, 0xad, 0xaa, 0x8a, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8a,
+	  0x8e, 0x84, 0xae, 0xac, 0x89, 0xda, 0xb7, 0xd0, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x80, 0x83, 0x82, 0x8b,
+	  0x8e, 0x85, 0xac, 0xaa, 0x89, 0xc8, 0xaa, 0xc1, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x85, 0x86, 0x87, 0x89, 0x81, 0x85, 0x81, 0x84, 0x86, 0x84, 0x8c,
+	  0x8c, 0x84, 0xa9, 0xa8, 0x87, 0xa3, 0x92, 0xa1, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x85, 0x86, 0x87, 0x89, 0x84, 0x86, 0x83, 0x80, 0x83, 0x81, 0x8c,
+	  0x8d, 0x84, 0xaa, 0xaa, 0x89, 0xce, 0xaf, 0xc5, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x85, 0x86, 0x87, 0x89, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
+	  0x8c, 0x84, 0xa8, 0xa8, 0x88, 0xb5, 0x9f, 0xb0, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
+	  0x8b, 0x84, 0xab, 0xa8, 0x86, 0xd4, 0xb4, 0xc9, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x84, 0x84, 0x85, 0x8b,
+	  0x8a, 0x83, 0xa6, 0xa5, 0x84, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
+	  0x86, 0x85, 0x86, 0x86, 0x82, 0x85, 0x81, 0x82, 0x83, 0x84, 0x8e,
+	  0x8b, 0x83, 0xa4, 0xa3, 0x8a, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8e,
+	  0x8b, 0x83, 0xa4, 0xa2, 0x86, 0xc1, 0xa9, 0xb7, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8d,
+	  0x89, 0x82, 0xa2, 0xa1, 0x84, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
+	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x83, 0x83, 0x85, 0x8c,
+	  0x87, 0x7f, 0xa2, 0x9d, 0x88, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xbb, 0x00, 0xc5, 0x00, 0xb4, 0x87, 0x86, 0x86, 0x84, 0x83,
+	  0x86, 0x87, 0x87, 0x87, 0x80, 0x82, 0x7f, 0x86, 0x86, 0x88, 0x8a,
+	  0x84, 0x7e, 0x9d, 0x9c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xbd, 0x00, 0xc7, 0x00, 0xb7, 0x87, 0x85, 0x85, 0x84, 0x83,
+	  0x86, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x83, 0x84, 0x85, 0x8a,
+	  0x85, 0x7e, 0x9c, 0x9b, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xc0, 0x00, 0xca, 0x00, 0xbb, 0x87, 0x86, 0x85, 0x83, 0x83,
+	  0x85, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x84, 0x85, 0x86, 0x89,
+	  0x83, 0x7d, 0x9c, 0x99, 0x87, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xc4, 0x00, 0xcd, 0x00, 0xbe, 0x87, 0x86, 0x85, 0x83, 0x83,
+	  0x86, 0x85, 0x85, 0x87, 0x81, 0x82, 0x80, 0x82, 0x82, 0x83, 0x8a,
+	  0x85, 0x7f, 0x9f, 0x9b, 0x86, 0xb4, 0xa1, 0xac, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xc7, 0x00, 0xd0, 0x00, 0xc2, 0x87, 0x85, 0x85, 0x83, 0x82,
+	  0x85, 0x85, 0x85, 0x86, 0x82, 0x83, 0x80, 0x82, 0x82, 0x84, 0x87,
+	  0x86, 0x80, 0x9e, 0x9a, 0x87, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xca, 0x00, 0xd2, 0x00, 0xc5, 0x87, 0x85, 0x84, 0x82, 0x82,
+	  0x84, 0x85, 0x85, 0x86, 0x81, 0x82, 0x7f, 0x82, 0x82, 0x84, 0x88,
+	  0x86, 0x81, 0x9d, 0x98, 0x86, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xce, 0x00, 0xd6, 0x00, 0xca, 0x86, 0x85, 0x84, 0x83, 0x83,
+	  0x85, 0x84, 0x84, 0x85, 0x81, 0x82, 0x80, 0x81, 0x81, 0x82, 0x89,
+	  0x86, 0x81, 0x9c, 0x97, 0x86, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xd1, 0x00, 0xd9, 0x00, 0xce, 0x86, 0x84, 0x83, 0x83, 0x82,
+	  0x85, 0x85, 0x85, 0x86, 0x81, 0x83, 0x81, 0x82, 0x82, 0x83, 0x86,
+	  0x83, 0x7f, 0x99, 0x95, 0x86, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xd4, 0x00, 0xdb, 0x00, 0xd1, 0x86, 0x85, 0x83, 0x83, 0x82,
+	  0x85, 0x84, 0x84, 0x85, 0x80, 0x83, 0x82, 0x80, 0x80, 0x81, 0x87,
+	  0x84, 0x81, 0x98, 0x93, 0x85, 0xae, 0x9c, 0xa8, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xd8, 0x00, 0xde, 0x00, 0xd6, 0x86, 0x84, 0x83, 0x81, 0x81,
+	  0x83, 0x85, 0x85, 0x85, 0x82, 0x83, 0x81, 0x81, 0x81, 0x83, 0x86,
+	  0x84, 0x80, 0x98, 0x91, 0x85, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xda, 0x85, 0x84, 0x83, 0x82, 0x82,
+	  0x84, 0x84, 0x84, 0x85, 0x81, 0x82, 0x82, 0x80, 0x80, 0x81, 0x83,
+	  0x82, 0x7f, 0x99, 0x93, 0x86, 0x94, 0x8b, 0x92, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xde, 0x85, 0x84, 0x82, 0x82, 0x82,
+	  0x84, 0x83, 0x83, 0x84, 0x81, 0x81, 0x80, 0x83, 0x82, 0x84, 0x82,
+	  0x81, 0x7f, 0x99, 0x92, 0x86, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
+	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x83, 0x83, 0x84, 0x80,
+	  0x81, 0x7c, 0x99, 0x92, 0x87, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x85, 0x84, 0x83, 0x81, 0x81,
+	  0x82, 0x82, 0x82, 0x83, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
+	  0x82, 0x80, 0x91, 0x8d, 0x83, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
+	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
+	  0x81, 0x7f, 0x91, 0x8c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
+	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x82,
+	  0x82, 0x7f, 0x94, 0x89, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
+	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x83,
+	  0x82, 0x7f, 0x91, 0x85, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
+	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x83, 0x82, 0x84, 0x83,
+	  0x82, 0x7f, 0x90, 0x84, 0x81, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x80, 0x80,
+	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x81,
+	  0x82, 0x83, 0x7e, 0x80, 0x7c, 0xa4, 0x97, 0x9f, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xe9, 0x00, 0xec, 0x00, 0xe8, 0x84, 0x83, 0x82, 0x81, 0x81,
+	  0x82, 0x82, 0x82, 0x83, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x83,
+	  0x83, 0x84, 0x79, 0x7c, 0x79, 0xb1, 0xa0, 0xaa, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xed, 0x00, 0xf0, 0x00, 0xec, 0x83, 0x83, 0x82, 0x80, 0x80,
+	  0x81, 0x82, 0x82, 0x82, 0x7f, 0x7f, 0x7e, 0x81, 0x81, 0x82, 0x80,
+	  0x81, 0x81, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xf1, 0x83, 0x82, 0x82, 0x80, 0x80,
+	  0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x7d,
+	  0x7e, 0x7f, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xf6, 0x00, 0xf7, 0x00, 0xf5, 0x82, 0x82, 0x81, 0x80, 0x80,
+	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x82,
+	  0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfa, 0x81, 0x81, 0x81, 0x80, 0x80,
+	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+	  0x00, 0x00 },
+	{ 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,
+	  0x00, 0x00 },
+	{ 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,
+	  0x00, 0x00 },
+};
+
+static const unsigned char VINT_TABLE[VINT_STATUS_MAX] = {
+	0x18, 0x19, 0x1A, 0x1B, 0x1C,
+	0x1D, 0x1E, 0x1F, 0x20, 0x21
+};
+
+struct s6e3ha2 {
+	struct device *dev;
+	struct drm_panel panel;
+	struct backlight_device *bl_dev;
+
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *enable_gpio;
+	struct videomode vm;
+};
+
+static inline struct s6e3ha2 *panel_to_s6e3ha2(struct drm_panel *panel)
+{
+	return container_of(panel, struct s6e3ha2, panel);
+}
+
+static void s6e3ha2_dcs_write(struct mipi_dsi_device *dsi, int *error,
+		const u8 cmd, const void *data, size_t len)
+{
+	if (*error < 0)
+		return;
+
+	*error = mipi_dsi_dcs_write(dsi, cmd, data, len);
+	if (*error < 0)
+		dev_err(&dsi->dev, "error %d writing dcs seq: %*ph\n", *error,
+							(int)len, data);
+}
+
+#define s6e3ha2_dcs_write_seq_static(dsi, error, cmd, seq...) \
+({\
+	static const u8 c = cmd;\
+	static const u8 d[] = { seq };\
+	s6e3ha2_dcs_write(dsi, error, c, d, ARRAY_SIZE(d));\
+})
+
+static inline void s6e3ha2_test_key_on_f0(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xf0, 0x5a, 0x5a);
+}
+
+static inline void s6e3ha2_test_key_off_f0(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xf0, 0xa5, 0xa5);
+}
+
+static inline void s6e3ha2_test_key_on_fc(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xfc, 0x5a, 0x5a);
+}
+
+static inline void s6e3ha2_test_key_off_fc(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xfc, 0xa5, 0xa5);
+}
+
+static inline void s6e3ha2_single_dsi_set1(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xf2, 0x67);
+}
+
+static inline void s6e3ha2_single_dsi_set2(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xf9, 0x09);
+}
+
+static inline void s6e3ha2_calibration_set1(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xfd, 0x1c);
+}
+
+static inline void s6e3ha2_calibration_set2(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0x20, 0x39);
+}
+
+static inline void s6e3ha2_calibration_set3(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0xa0);
+}
+
+static inline void s6e3ha2_calibration_set4(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0x20);
+}
+
+static inline void s6e3ha2_calibration_set5(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error,
+			0xce, 0x03, 0x3B, 0x12, 0x62, 0x40, 0x80, 0xC0, 0x28,
+			0x28, 0x28, 0x28, 0x39, 0xC5);
+}
+
+static inline void s6e3ha2_caps_elvss_set(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xb6, 0x9c, 0x0a);
+}
+
+static inline void s6e3ha2_acl_off(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0x55, 0x00);
+}
+
+static inline void s6e3ha2_acl_off_opr(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xb5, 0x40);
+}
+
+static inline void s6e3ha2_test_global(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xb0, 0x07);
+}
+
+static inline void s6e3ha2_test(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xb8, 0x19);
+}
+
+static inline void s6e3ha2_touch_hsync_on1(struct mipi_dsi_device *dsi,
+								int *error) {
+	s6e3ha2_dcs_write_seq_static(dsi, error,
+			0xbd, 0x33, 0x11, 0x02, 0x16, 0x02, 0x16);
+}
+
+static inline void s6e3ha2_pentile_control(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xc0, 0x00, 0x00, 0xd8, 0xd8);
+}
+
+static inline void s6e3ha2_poc_global(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xb0, 0x20);
+}
+
+static inline void s6e3ha2_poc_setting(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0x08);
+}
+
+static inline void s6e3ha2_pcd_set_off(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xcc, 0x40, 0x51);
+}
+
+static inline void s6e3ha2_err_fg_set(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xed, 0x44);
+}
+
+static inline void s6e3ha2_hbm_off(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0x53, 0x00);
+}
+
+static inline void s6e3ha2_te_start_setting(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error,
+			0xb9, 0x10, 0x09, 0xff, 0x00, 0x09);
+}
+
+static inline void s6e3ha2_gamma_update(struct mipi_dsi_device *dsi,
+								int *error)
+{
+	s6e3ha2_dcs_write_seq_static(dsi, error, 0xf7, 0x03);
+}
+
+static inline unsigned int s6e3ha2_get_vint_idx(unsigned int brt)
+{
+	return (brt * (VINT_STATUS_MAX - 1)) / MAX_BRIGHTNESS;
+}
+
+static inline void s6e3ha2_set_vint(struct mipi_dsi_device *dsi, int *error,
+							unsigned int brt) {
+	unsigned int vint_idx = s6e3ha2_get_vint_idx(brt);
+	unsigned char data[] = { 0x8b, VINT_TABLE[vint_idx] };
+
+	s6e3ha2_dcs_write(dsi, error, 0xf4, data, ARRAY_SIZE(data));
+}
+
+static inline unsigned int s6e3ha2_get_brightness_idx(unsigned int brt)
+{
+	return (brt * (NUM_GAMMA_STEPS - 1)) / MAX_BRIGHTNESS;
+}
+
+static void s6e3ha2_update_gamma(struct mipi_dsi_device *dsi, int *error,
+			struct backlight_device *bl_dev, unsigned int brt)
+{
+	unsigned int index = s6e3ha2_get_brightness_idx(brt);
+
+	s6e3ha2_dcs_write(dsi, error, 0xca, GAMMA_TBL[index],
+							GAMMA_CMD_CNT);
+	s6e3ha2_dcs_write(dsi, error, 0xb2, AOR_TBL[index],
+						ARRAY_SIZE(AOR_TBL[0]));
+	s6e3ha2_gamma_update(dsi, error);
+	bl_dev->props.brightness = brt;
+}
+
+static inline int s6e3ha2_get_brightness(struct backlight_device *bl_dev)
+{
+	return bl_dev->props.brightness;
+}
+
+static int s6e3ha2_set_brightness(struct backlight_device *bl_dev)
+{
+	struct s6e3ha2 *ctx = (struct s6e3ha2 *)bl_get_data(bl_dev);
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+	unsigned int brt = bl_dev->props.brightness;
+	int error = 0;
+
+	if (brt < MIN_BRIGHTNESS || brt > bl_dev->props.max_brightness) {
+		dev_err(&dsi->dev, "Invalid brightness: %u\n", brt);
+		return -EINVAL;
+	}
+
+	if (bl_dev->props.power > FB_BLANK_NORMAL) {
+		dev_err(&dsi->dev,
+			"panel must be at least in fb blank normal state\n");
+		return -EPERM;
+	}
+
+	s6e3ha2_test_key_on_f0(dsi, &error);
+	s6e3ha2_update_gamma(dsi, &error, bl_dev, brt);
+	s6e3ha2_set_vint(dsi, &error, brt);
+	s6e3ha2_test_key_off_f0(dsi, &error);
+
+	return error;
+}
+
+static const struct backlight_ops s6e3ha2_bl_ops = {
+	.get_brightness = s6e3ha2_get_brightness,
+	.update_status = s6e3ha2_set_brightness,
+};
+
+static int s6e3ha2_panel_init(struct s6e3ha2 *ctx)
+{
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+	int error;
+
+	error = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (error < 0)
+		return error;
+
+	usleep_range(5000, 6000);
+
+	s6e3ha2_test_key_on_f0(dsi, &error);
+	s6e3ha2_single_dsi_set1(dsi, &error);
+	s6e3ha2_single_dsi_set2(dsi, &error);
+
+	/* calibration enable */
+	s6e3ha2_test_key_on_fc(dsi, &error);
+	s6e3ha2_calibration_set1(dsi, &error);
+	s6e3ha2_calibration_set2(dsi, &error);
+	s6e3ha2_calibration_set3(dsi, &error);
+	s6e3ha2_calibration_set4(dsi, &error);
+	s6e3ha2_calibration_set5(dsi, &error);
+
+	msleep(120);
+
+	/* common setting */
+	error = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+	if (error < 0)
+		return error;
+
+	s6e3ha2_touch_hsync_on1(dsi, &error);
+	s6e3ha2_pentile_control(dsi, &error);
+	s6e3ha2_poc_global(dsi, &error);
+	s6e3ha2_poc_setting(dsi, &error);
+	s6e3ha2_test_key_off_fc(dsi, &error);
+
+	/* pcd setting off for TB */
+	s6e3ha2_pcd_set_off(dsi, &error);
+	s6e3ha2_err_fg_set(dsi, &error);
+	s6e3ha2_te_start_setting(dsi, &error);
+	s6e3ha2_test_key_off_f0(dsi, &error);
+
+	return error;
+}
+
+static int s6e3ha2_power_off(struct s6e3ha2 *ctx)
+{
+	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+}
+
+static int s6e3ha2_disable(struct drm_panel *panel)
+{
+	struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(panel->dev);
+	int ret;
+
+	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+	if (ret < 0)
+		goto err;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0)
+		goto err;
+
+	msleep(40);
+
+	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
+
+	return 0;
+err:
+	dev_err(ctx->dev, "failed to power off: %d\n", ret);
+	return ret;
+}
+
+static int s6e3ha2_unprepare(struct drm_panel *panel)
+{
+	struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
+	int ret;
+
+	ret = s6e3ha2_power_off(ctx);
+	if (ret != 0) {
+		dev_err(ctx->dev, "failed to power off: %d\n", ret);
+		return ret;
+	}
+
+	ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
+
+	return 0;
+}
+
+static int s6e3ha2_power_on(struct s6e3ha2 *ctx)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret != 0)
+		return ret;
+
+	msleep(25);
+
+	gpiod_set_value(ctx->enable_gpio, 0);
+	usleep_range(5000, 6000);
+	gpiod_set_value(ctx->enable_gpio, 1);
+
+	gpiod_set_value(ctx->reset_gpio, 1);
+	usleep_range(5000, 6000);
+	gpiod_set_value(ctx->reset_gpio, 0);
+	usleep_range(5000, 6000);
+
+	return 0;
+}
+static int s6e3ha2_prepare(struct drm_panel *panel)
+{
+	struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
+	int ret;
+
+	ret = s6e3ha2_power_on(ctx);
+	if (ret < 0) {
+		dev_err(ctx->dev, "failed to power on: %d\n", ret);
+		return ret;
+	}
+
+	ret = s6e3ha2_panel_init(ctx);
+	if (ret < 0) {
+		dev_err(ctx->dev, "failed to initialize: %d\n", ret);
+		s6e3ha2_power_off(ctx);
+		return ret;
+	}
+
+	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
+
+	return 0;
+}
+
+static int s6e3ha2_enable(struct drm_panel *panel)
+{
+	struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
+	struct mipi_dsi_device *dsi = to_mipi_dsi_device(panel->dev);
+	int error;
+
+	s6e3ha2_test_key_on_f0(dsi, &error);
+
+	/* brightness setting */
+	error = s6e3ha2_set_brightness(ctx->bl_dev);
+	if (error < 0)
+		goto err;
+
+	s6e3ha2_caps_elvss_set(dsi, &error);
+	s6e3ha2_acl_off(dsi, &error);
+	s6e3ha2_acl_off_opr(dsi, &error);
+	s6e3ha2_hbm_off(dsi, &error);
+
+	/* elvss temp compensation */
+	s6e3ha2_test_global(dsi, &error);
+	s6e3ha2_test(dsi, &error);
+	s6e3ha2_test_key_off_f0(dsi, &error);
+
+	error = mipi_dsi_dcs_set_display_on(dsi);
+	if (error < 0)
+		goto err;
+
+	ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
+
+	return 0;
+err:
+	dev_err(ctx->dev, "failed to enable: %d\n", error);
+	return error;
+}
+
+static int s6e3ha2_get_modes(struct drm_panel *panel)
+{
+	struct drm_connector *connector = panel->connector;
+	struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_create(connector->dev);
+	if (!mode) {
+		DRM_ERROR("failed to create a new display mode\n");
+		return 0;
+	}
+
+	drm_display_mode_from_videomode(&ctx->vm, mode);
+	mode->vrefresh = 60;
+	mode->width_mm = 71;
+	mode->height_mm = 125;
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs s6e3ha2_funcs = {
+	.disable = s6e3ha2_disable,
+	.unprepare = s6e3ha2_unprepare,
+	.prepare = s6e3ha2_prepare,
+	.enable = s6e3ha2_enable,
+	.get_modes = s6e3ha2_get_modes,
+};
+
+static int s6e3ha2_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct s6e3ha2 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mipi_dsi_set_drvdata(dsi, ctx);
+
+	ctx->dev = dev;
+
+	dsi->lanes = 4;
+	dsi->format = MIPI_DSI_FMT_RGB888;
+	dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	ret = of_get_videomode(dev->of_node, &ctx->vm, 0);
+	if (ret < 0)
+		return ret;
+
+	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) {
+		dev_err(dev, "failed to get regulators: %d\n", ret);
+		return ret;
+	}
+
+	ctx->reset_gpio = devm_gpiod_get(dev, "reset");
+	if (IS_ERR(ctx->reset_gpio)) {
+		dev_err(dev, "cannot get reset-gpio %ld\n",
+			PTR_ERR(ctx->reset_gpio));
+		return PTR_ERR(ctx->reset_gpio);
+	}
+
+	ret = gpiod_direction_output(ctx->reset_gpio, 0);
+	if (ret < 0) {
+		dev_err(dev, "cannot configure reset-gpio %d\n", ret);
+		return ret;
+	}
+
+	ctx->enable_gpio = devm_gpiod_get(dev, "enable");
+	if (IS_ERR(ctx->enable_gpio)) {
+		dev_err(dev, "cannot get enable-gpio %ld\n",
+			PTR_ERR(ctx->enable_gpio));
+		return PTR_ERR(ctx->enable_gpio);
+	}
+	ret = gpiod_direction_output(ctx->enable_gpio, 1);
+
+	ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx,
+						&s6e3ha2_bl_ops, NULL);
+	if (IS_ERR(ctx->bl_dev)) {
+		dev_err(dev, "failed to register backlight device\n");
+		return PTR_ERR(ctx->bl_dev);
+	}
+
+	ctx->bl_dev->props.max_brightness = MAX_BRIGHTNESS;
+	ctx->bl_dev->props.brightness = DEFAULT_BRIGHTNESS;
+	ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
+
+	drm_panel_init(&ctx->panel);
+	ctx->panel.dev = dev;
+	ctx->panel.funcs = &s6e3ha2_funcs;
+
+	ret = drm_panel_add(&ctx->panel);
+	if (ret < 0)
+		goto unregister_backlight;
+
+	ret = mipi_dsi_attach(dsi);
+	if (ret < 0)
+		goto remove_panel;
+
+	return ret;
+
+remove_panel:
+	drm_panel_remove(&ctx->panel);
+
+unregister_backlight:
+	backlight_device_unregister(ctx->bl_dev);
+
+	return ret;
+}
+
+static int s6e3ha2_remove(struct mipi_dsi_device *dsi)
+{
+	struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi);
+
+	mipi_dsi_detach(dsi);
+	drm_panel_remove(&ctx->panel);
+	backlight_device_unregister(ctx->bl_dev);
+
+	return 0;
+}
+
+static const struct of_device_id s6e3ha2_of_match[] = {
+	{ .compatible = "samsung,s6e3ha2" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);
+
+static struct mipi_dsi_driver s6e3ha2_driver = {
+	.probe = s6e3ha2_probe,
+	.remove = s6e3ha2_remove,
+	.driver = {
+		.name = "panel-s6e3ha2",
+		.of_match_table = s6e3ha2_of_match,
+	},
+};
+module_mipi_dsi_driver(s6e3ha2_driver);
+
+MODULE_AUTHOR("Donghwa Lee <dh09.lee@xxxxxxxxxxx>");
+MODULE_AUTHOR("Hyungwon Hwang <human.hwang@xxxxxxxxxxx>");
+MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver");
+MODULE_LICENSE("GPL v2");
--
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel





[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux