linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel
@ 2021-07-25 14:03 Alexey Minnekhanov
  2021-07-25 14:03 ` [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver Alexey Minnekhanov
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Alexey Minnekhanov @ 2021-07-25 14:03 UTC (permalink / raw)
  To: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter,
	Rob Herring, open list:DRM PANEL DRIVERS,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list
  Cc: ~postmarketos/upstreaming, phone-devel, Linus Walleij,
	Alexey Minnekhanov

The Samsung S6E3FA2 AMOLED cmd LCD panel is used on Samsung Galaxy
S5 (klte) phone.

Signed-off-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
---
 .../display/panel/samsung,s6e3fa2.yaml        | 63 +++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3fa2.yaml

diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3fa2.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6e3fa2.yaml
new file mode 100644
index 000000000000..d5628ae81141
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3fa2.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/samsung,s6e3fa2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung s6e3fa2 AMOLED CMD LCD DSI panel
+
+maintainers:
+  - Alexey Minnekhanov <alexeymin@postmarketos.org>
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    const: samsung,s6e3fa2
+
+  reg: true
+  reset-gpios: true
+  port: true
+
+  iovdd-supply:
+    description: IOVDD regulator
+
+  vddr-supply:
+    description: VDDR regulator
+
+required:
+  - compatible
+  - reset-gpios
+  - iovdd-supply
+  - vddr-supply
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    /* from Samsung Galaxy S5 klte */
+    #include <dt-bindings/gpio/gpio.h>
+
+    dsi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        panel@0 {
+            compatible = "samsung,s6e3fa2";
+            reg = <0>;
+
+            reset-gpios = <&pma8084_gpios 17 GPIO_ACTIVE_LOW>;
+
+            iovdd-supply = <&pma8084_lvs4>;
+            vddr-supply = <&vreg_panel>;
+
+            port {
+                panel_in: endpoint {
+                    remote-endpoint = <&dsi0_out>;
+                };
+            };
+        };
+    };
+
+...
-- 
2.31.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver
  2021-07-25 14:03 [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Alexey Minnekhanov
@ 2021-07-25 14:03 ` Alexey Minnekhanov
       [not found]   ` <YP184rqayPLbWLx4@ravnborg.org>
  2021-07-26  8:04   ` Linus Walleij
  2021-07-26  7:51 ` [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Linus Walleij
  2021-07-29 22:31 ` Rob Herring
  2 siblings, 2 replies; 7+ messages in thread
From: Alexey Minnekhanov @ 2021-07-25 14:03 UTC (permalink / raw)
  To: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter,
	open list, open list:DRM PANEL DRIVERS
  Cc: ~postmarketos/upstreaming, phone-devel, Linus Walleij,
	Alexey Minnekhanov

Samsung S6E3FA2 panel is amoled 1080x1920 command mode DSI
panel used in Samsung Galaxy S5 phone. There are 2 known
variations of panel that were shipped in this phone, and
this driver handles both of them.

Panel has built-in backlight (like all other AMOLED panels),
controlled over DSI by some vendor specific commands, some
of them include sending long byte sequences of what seems
to be called "smart dimming".

Signed-off-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
---
 drivers/gpu/drm/panel/Kconfig                 |   12 +
 drivers/gpu/drm/panel/Makefile                |    1 +
 drivers/gpu/drm/panel/panel-samsung-s6e3fa2.c | 1218 +++++++++++++++++
 3 files changed, 1231 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e3fa2.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 5270d25b5ff1..968da1819a86 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -357,6 +357,18 @@ config DRM_PANEL_SAMSUNG_S6D16D0
 	depends on DRM_MIPI_DSI
 	select VIDEOMODE_HELPERS
 
+config DRM_PANEL_SAMSUNG_S6E3FA2
+	tristate "Samsung S6E3FA2 DSI 1080p command mode panel"
+	depends on OF
+	depends on DRM_MIPI_DSI
+	depends on BACKLIGHT_CLASS_DEVICE
+	select VIDEOMODE_HELPERS
+	help
+	  Say Y here if you want to enable support for Samsung Electronics
+	  S6E3FA2 1080x1920 DSI AMOLED command mode panel. It is used in
+	  Samsung mobile phones like Galaxy S5 (klte). This driver supports
+	  both panel variants that are shipped in production devices.
+
 config DRM_PANEL_SAMSUNG_S6E3HA2
 	tristate "Samsung S6E3HA2 DSI video mode panel"
 	depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 0f304fc58c58..d119c604dd9e 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o
+obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3FA2) += panel-samsung-s6e3fa2.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
 obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3fa2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3fa2.c
new file mode 100644
index 000000000000..7bad7e71069a
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e3fa2.c
@@ -0,0 +1,1218 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright (c) 2021, Alexey Minnekhanov <alexeymin@postmarketos.org>
+// Copyright (c) 2021, The Linux Foundation. All rights reserved.
+
+#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>
+
+#include <video/mipi_display.h>
+
+
+#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 int s6e3fa2_dsi_dcs_read1(struct mipi_dsi_device *dsi, const u8 cmd,
+				u8 *data)
+{
+	int ret;
+
+	ret = mipi_dsi_dcs_read(dsi, cmd, data, 1);
+	if (ret < 0) {
+		dev_err(&dsi->dev, "could not read DCS CMD %02x\n", cmd);
+		return ret;
+	}
+	return 0;
+}
+
+/* Panel variants */
+#define LCD_ID_S6E3FA2		0x602813
+#define LCD_ID_EA8064G		0x622872
+
+/* Manufacturer Command Set */
+#define MCS_AID_CONTROL		0xb2  /* Samsung AMOLED Impulsive Driving */
+#define MCS_ELVSS_CONTROL	0xb6  /* Amoled negative power supply */
+#define MCS_GAMMA		0xca
+/* Read ID commands */
+#define MCS_READ_ID1		0xda
+#define MCS_READ_ID2		0xdb
+#define MCS_READ_ID3		0xdc
+
+/* Number of brightness levels */
+#define S6E3FA2_NUM_GAMMA_LEVELS	60
+#define S6E3FA2_MAX_BRIGHTNESS		(S6E3FA2_NUM_GAMMA_LEVELS - 1)
+
+#define NUM_AID_SEQUENCES	45
+#define AID_SEQUENCE_LEN	5
+
+/*
+ * Which AID sequence to use for each candela level.
+ * This lookup table is same for both panels.
+ */
+static const u8 map_candela_to_aid[S6E3FA2_NUM_GAMMA_LEVELS] = {
+	 0,  2,  3,  4,  6,  7,  8, 10, 11, 13, 14, 15,
+	16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+	29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36,
+	36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 38,
+	39, 40, 41, 42, 43, 44, 44, 44, 44, 44, 44, 44
+};
+
+/* AID (Amoled Impulsive Driving) tables */
+static const u8 seq_s6e3fa2_aid[NUM_AID_SEQUENCES][AID_SEQUENCE_LEN] = {
+	{MCS_AID_CONTROL, 0x07, 0x68, 0x00, 0x0E}, /* 0 */
+	{MCS_AID_CONTROL, 0x07, 0x58, 0x00, 0x0E}, /* 1 */
+	{MCS_AID_CONTROL, 0x07, 0x49, 0x00, 0x0E}, /* 2 */
+	{MCS_AID_CONTROL, 0x07, 0x39, 0x00, 0x0E}, /* 3 */
+	{MCS_AID_CONTROL, 0x07, 0x29, 0x00, 0x0E}, /* 4 */
+	{MCS_AID_CONTROL, 0x07, 0x19, 0x00, 0x0E}, /* 5 */
+	{MCS_AID_CONTROL, 0x07, 0x09, 0x00, 0x0E}, /* 6 */
+	{MCS_AID_CONTROL, 0x06, 0xF8, 0x00, 0x0E}, /* 7 */
+	{MCS_AID_CONTROL, 0x06, 0xE7, 0x00, 0x0E}, /* 8 */
+	{MCS_AID_CONTROL, 0x06, 0xD7, 0x00, 0x0E}, /* 9 */
+	{MCS_AID_CONTROL, 0x06, 0xC8, 0x00, 0x0E}, /* 10 */
+	{MCS_AID_CONTROL, 0x06, 0xB7, 0x00, 0x0E}, /* 11 */
+	{MCS_AID_CONTROL, 0x06, 0xA5, 0x00, 0x0E}, /* 12 */
+	{MCS_AID_CONTROL, 0x06, 0x95, 0x00, 0x0E}, /* 13 */
+	{MCS_AID_CONTROL, 0x06, 0x83, 0x00, 0x0E}, /* 14 */
+	{MCS_AID_CONTROL, 0x06, 0x73, 0x00, 0x0E}, /* 15 */
+	{MCS_AID_CONTROL, 0x06, 0x53, 0x00, 0x0E}, /* 16 */
+	{MCS_AID_CONTROL, 0x06, 0x2F, 0x00, 0x0E}, /* 17 */
+	{MCS_AID_CONTROL, 0x06, 0x27, 0x00, 0x0E}, /* 18 */
+	{MCS_AID_CONTROL, 0x06, 0x17, 0x00, 0x0E}, /* 19 */
+	{MCS_AID_CONTROL, 0x05, 0xFF, 0x00, 0x0E}, /* 20 */
+	{MCS_AID_CONTROL, 0x05, 0xEF, 0x00, 0x0E}, /* 21 */
+	{MCS_AID_CONTROL, 0x05, 0xCC, 0x00, 0x0E}, /* 22 */
+	{MCS_AID_CONTROL, 0x05, 0xAB, 0x00, 0x0E}, /* 23 */
+	{MCS_AID_CONTROL, 0x05, 0x98, 0x00, 0x0E}, /* 24 */
+	{MCS_AID_CONTROL, 0x05, 0x76, 0x00, 0x0E}, /* 25 */
+	{MCS_AID_CONTROL, 0x05, 0x53, 0x00, 0x0E}, /* 26 */
+	{MCS_AID_CONTROL, 0x05, 0x1D, 0x00, 0x0E}, /* 27 */
+	{MCS_AID_CONTROL, 0x04, 0xFB, 0x00, 0x0E}, /* 28 */
+	{MCS_AID_CONTROL, 0x04, 0xD2, 0x00, 0x0E}, /* 29 */
+	{MCS_AID_CONTROL, 0x04, 0x9E, 0x00, 0x0E}, /* 30 */
+	{MCS_AID_CONTROL, 0x04, 0x62, 0x00, 0x0E}, /* 31 */
+	{MCS_AID_CONTROL, 0x04, 0x2B, 0x00, 0x0E}, /* 32 */
+	{MCS_AID_CONTROL, 0x03, 0xED, 0x00, 0x0E}, /* 33 */
+	{MCS_AID_CONTROL, 0x03, 0xAD, 0x00, 0x0E}, /* 34 */
+	{MCS_AID_CONTROL, 0x03, 0x56, 0x00, 0x0E}, /* 35 */
+	{MCS_AID_CONTROL, 0x03, 0x29, 0x00, 0x0E}, /* 36 */
+	{MCS_AID_CONTROL, 0x02, 0xBE, 0x00, 0x0E}, /* 37 */
+	{MCS_AID_CONTROL, 0x02, 0x67, 0x00, 0x0E}, /* 38 */
+	{MCS_AID_CONTROL, 0x02, 0x1D, 0x00, 0x0E}, /* 39 */
+	{MCS_AID_CONTROL, 0x01, 0xBD, 0x00, 0x0E}, /* 40 */
+	{MCS_AID_CONTROL, 0x01, 0x4E, 0x00, 0x0E}, /* 41 */
+	{MCS_AID_CONTROL, 0x00, 0xD6, 0x00, 0x0E}, /* 42 */
+	{MCS_AID_CONTROL, 0x00, 0x53, 0x00, 0x0E}, /* 43 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x00, 0x0E}  /* 44 */
+};
+
+static const u8 seq_ea8064g_aid[NUM_AID_SEQUENCES][AID_SEQUENCE_LEN] = {
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x07, 0x68}, /* 0 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x07, 0x58}, /* 1 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x07, 0x49}, /* 2 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x07, 0x39}, /* 3 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x07, 0x29}, /* 4 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x07, 0x19}, /* 5 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x07, 0x09}, /* 6 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0xF8}, /* 7 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0xE7}, /* 8 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0xD7}, /* 9 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0xC8}, /* 10 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0xB7}, /* 11 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0xA5}, /* 12 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0x95}, /* 13 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0x83}, /* 14 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0x73}, /* 15 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0x53}, /* 16 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0x2F}, /* 17 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0x27}, /* 18 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x06, 0x17}, /* 19 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0xFF}, /* 20 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0xEF}, /* 21 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0xCC}, /* 22 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0xAB}, /* 23 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0x98}, /* 24 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0x76}, /* 25 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0x53}, /* 26 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x05, 0x1D}, /* 27 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x04, 0xFB}, /* 28 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x04, 0xD2}, /* 29 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x04, 0x9E}, /* 30 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x04, 0x62}, /* 31 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x04, 0x2B}, /* 32 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x03, 0xED}, /* 33 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x03, 0xAD}, /* 34 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x03, 0x56}, /* 35 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x03, 0x29}, /* 36 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x02, 0xBE}, /* 37 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x02, 0x67}, /* 38 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x02, 0x1D}, /* 39 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x01, 0xBD}, /* 40 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x01, 0x4E}, /* 41 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x00, 0xD6}, /* 42 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x00, 0x53}, /* 43 */
+	{MCS_AID_CONTROL, 0x00, 0x0E, 0x00, 0x0E}  /* 44 */
+};
+
+/*
+ * Which ELVSS sequence to use for which candela level.
+ * This lookup table is the same for both panels.
+ */
+static const u8 map_candela_to_elvss[S6E3FA2_NUM_GAMMA_LEVELS] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 2, 3, 4, 5, 6,
+	7, 7, 7, 7, 7,
+	8, 8, 8,
+	9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+	21, 22, 23, 24, 25, 26, 27, 28, 29, 30
+};
+
+/* ELVSS (Amoled negative power supply) tables */
+#define NUM_ELVSS_SEQUENCES	31
+#define ELVSS_SEQUENCE_LEN	3
+static const u8 seq_s6e3fa2_elvss[NUM_ELVSS_SEQUENCES][ELVSS_SEQUENCE_LEN] = {
+	{MCS_ELVSS_CONTROL, 0x98, 0x0B}, {MCS_ELVSS_CONTROL, 0x98, 0x0C},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0C}, {MCS_ELVSS_CONTROL, 0x98, 0x0D},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0D}, {MCS_ELVSS_CONTROL, 0x98, 0x0E},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0F}, {MCS_ELVSS_CONTROL, 0x98, 0x10},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0F}, {MCS_ELVSS_CONTROL, 0x98, 0x0E},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0E}, {MCS_ELVSS_CONTROL, 0x98, 0x0D},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0D}, {MCS_ELVSS_CONTROL, 0x98, 0x0C},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0C}, {MCS_ELVSS_CONTROL, 0x98, 0x0B},
+	{MCS_ELVSS_CONTROL, 0x98, 0x0A}, {MCS_ELVSS_CONTROL, 0x98, 0x09},
+	{MCS_ELVSS_CONTROL, 0x98, 0x09}, {MCS_ELVSS_CONTROL, 0x98, 0x09},
+	{MCS_ELVSS_CONTROL, 0x98, 0x09}, {MCS_ELVSS_CONTROL, 0x98, 0x09},
+	{MCS_ELVSS_CONTROL, 0x98, 0x09}, {MCS_ELVSS_CONTROL, 0x98, 0x09},
+	{MCS_ELVSS_CONTROL, 0x98, 0x09}, {MCS_ELVSS_CONTROL, 0x98, 0x08},
+	{MCS_ELVSS_CONTROL, 0x98, 0x07}, {MCS_ELVSS_CONTROL, 0x98, 0x06},
+	{MCS_ELVSS_CONTROL, 0x98, 0x06}, {MCS_ELVSS_CONTROL, 0x98, 0x05},
+	{MCS_ELVSS_CONTROL, 0x98, 0x04}
+};
+static const u8 seq_ea8064g_elvss[NUM_ELVSS_SEQUENCES][ELVSS_SEQUENCE_LEN] = {
+	{MCS_ELVSS_CONTROL, 0x48, 0x8B}, {MCS_ELVSS_CONTROL, 0x48, 0x8C},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8C}, {MCS_ELVSS_CONTROL, 0x48, 0x8D},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8D}, {MCS_ELVSS_CONTROL, 0x48, 0x8E},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8F}, {MCS_ELVSS_CONTROL, 0x48, 0x90},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8F}, {MCS_ELVSS_CONTROL, 0x48, 0x8E},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8E}, {MCS_ELVSS_CONTROL, 0x48, 0x8D},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8D}, {MCS_ELVSS_CONTROL, 0x48, 0x8C},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8C}, {MCS_ELVSS_CONTROL, 0x48, 0x8B},
+	{MCS_ELVSS_CONTROL, 0x48, 0x8A}, {MCS_ELVSS_CONTROL, 0x48, 0x89},
+	{MCS_ELVSS_CONTROL, 0x48, 0x89}, {MCS_ELVSS_CONTROL, 0x48, 0x89},
+	{MCS_ELVSS_CONTROL, 0x48, 0x89}, {MCS_ELVSS_CONTROL, 0x48, 0x89},
+	{MCS_ELVSS_CONTROL, 0x48, 0x89}, {MCS_ELVSS_CONTROL, 0x48, 0x89},
+	{MCS_ELVSS_CONTROL, 0x48, 0x89}, {MCS_ELVSS_CONTROL, 0x48, 0x88},
+	{MCS_ELVSS_CONTROL, 0x48, 0x87}, {MCS_ELVSS_CONTROL, 0x48, 0x86},
+	{MCS_ELVSS_CONTROL, 0x48, 0x86}, {MCS_ELVSS_CONTROL, 0x48, 0x85},
+	{MCS_ELVSS_CONTROL, 0x48, 0x84}
+};
+
+/* Gamma (lux) smart dimming tables */
+#define GAMMA_SEQ_LEN	34
+static const u8 seq_s6e3fa2_lux[S6E3FA2_NUM_GAMMA_LEVELS][GAMMA_SEQ_LEN] = {
+	{MCS_GAMMA, 0x00, 0xB7, 0x00, 0xC6, 0x00, 0xAB, 0x8B, 0x90, 0x8C, 0x8C,
+	 0x91, 0x8A, 0x8E, 0x99, 0x91, 0x92, 0x9D, 0x8E, 0x93, 0x96, 0x8F, 0x91,
+	 0x92, 0x8D, 0xAD, 0xA2, 0x9B, 0x9B, 0x93, 0xAC, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBB, 0x00, 0xC6, 0x00, 0xB0, 0x8A, 0x8D, 0x8A, 0x8B,
+	 0x8F, 0x8B, 0x8C, 0x94, 0x8C, 0x8D, 0x98, 0x8E, 0x8E, 0x93, 0x8C, 0x8F,
+	 0x93, 0x8A, 0xAA, 0xA2, 0x97, 0x9C, 0x94, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBC, 0x00, 0xC6, 0x00, 0xB1, 0x8A, 0x8D, 0x8B, 0x8A,
+	 0x8E, 0x89, 0x8B, 0x93, 0x8C, 0x8E, 0x97, 0x8E, 0x8C, 0x92, 0x8D, 0x8E,
+	 0x91, 0x87, 0xA8, 0xA1, 0x94, 0x9E, 0x96, 0xAF, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBC, 0x00, 0xC6, 0x00, 0xB2, 0x8B, 0x8C, 0x8A, 0x8A,
+	 0x8D, 0x89, 0x8C, 0x92, 0x8C, 0x8C, 0x95, 0x8D, 0x8B, 0x91, 0x8A, 0x8E,
+	 0x91, 0x88, 0xA6, 0xA1, 0x92, 0x9C, 0x94, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBD, 0x00, 0xC6, 0x00, 0xB3, 0x8B, 0x8C, 0x8A, 0x89,
+	 0x8C, 0x89, 0x8A, 0x8F, 0x89, 0x8B, 0x93, 0x8B, 0x8B, 0x90, 0x8A, 0x8B,
+	 0x91, 0x89, 0xA6, 0xA0, 0x8E, 0x9D, 0x95, 0xAE, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBD, 0x00, 0xC6, 0x00, 0xB3, 0x8A, 0x8C, 0x8B, 0x89,
+	 0x8B, 0x87, 0x8A, 0x8F, 0x8A, 0x8B, 0x92, 0x8C, 0x8B, 0x90, 0x8A, 0x8A,
+	 0x90, 0x88, 0xA5, 0xA0, 0x8E, 0x98, 0x91, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBD, 0x00, 0xC6, 0x00, 0xB3, 0x8A, 0x8C, 0x8A, 0x89,
+	 0x8C, 0x88, 0x8A, 0x8F, 0x8A, 0x89, 0x91, 0x8A, 0x8B, 0x90, 0x8A, 0x8B,
+	 0x90, 0x89, 0xA5, 0x9F, 0x8D, 0x98, 0x91, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x8A, 0x8C, 0x8A, 0x89,
+	 0x8B, 0x88, 0x8A, 0x8C, 0x89, 0x89, 0x91, 0x8A, 0x89, 0x8E, 0x89, 0x8B,
+	 0x8F, 0x88, 0xA2, 0x9D, 0x88, 0x9F, 0x97, 0xB0, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8B, 0x89, 0x8A,
+	 0x8B, 0x89, 0x88, 0x8C, 0x8A, 0x89, 0x90, 0x89, 0x88, 0x8E, 0x88, 0x8A,
+	 0x8F, 0x88, 0xA4, 0x9E, 0x8A, 0x98, 0x91, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x8A, 0x8B, 0x8A, 0x89,
+	 0x8A, 0x88, 0x89, 0x8C, 0x89, 0x8A, 0x90, 0x8A, 0x85, 0x8C, 0x86, 0x89,
+	 0x8D, 0x85, 0xA3, 0x9F, 0x8B, 0x9D, 0x95, 0xAE, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8B, 0x8A, 0x8A,
+	 0x8A, 0x88, 0x89, 0x8C, 0x89, 0x87, 0x8E, 0x88, 0x87, 0x8D, 0x88, 0x8B,
+	 0x8E, 0x88, 0xA0, 0x9D, 0x86, 0x97, 0x91, 0xAB, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x89,
+	 0x8A, 0x87, 0x89, 0x8B, 0x8A, 0x87, 0x8E, 0x87, 0x87, 0x8D, 0x88, 0x88,
+	 0x8E, 0x87, 0xA0, 0x9C, 0x86, 0x9A, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x89,
+	 0x8A, 0x87, 0x89, 0x8A, 0x8B, 0x87, 0x8D, 0x86, 0x87, 0x8C, 0x87, 0x88,
+	 0x8D, 0x85, 0xA2, 0x9E, 0x8A, 0x9A, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBD, 0x00, 0xC6, 0x00, 0xB3, 0x8A, 0x8A, 0x89, 0x88,
+	 0x89, 0x87, 0x88, 0x8A, 0x88, 0x86, 0x8D, 0x88, 0x86, 0x8B, 0x86, 0x8B,
+	 0x8E, 0x88, 0x9F, 0x9D, 0x86, 0x96, 0x91, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x89,
+	 0x8A, 0x88, 0x88, 0x89, 0x87, 0x87, 0x8D, 0x88, 0x87, 0x8C, 0x88, 0x8A,
+	 0x8E, 0x87, 0x9D, 0x9B, 0x85, 0x99, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x8A,
+	 0x8A, 0x88, 0x88, 0x89, 0x88, 0x87, 0x8D, 0x88, 0x84, 0x89, 0x85, 0x89,
+	 0x8D, 0x86, 0x9E, 0x9C, 0x87, 0x99, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x89,
+	 0x89, 0x87, 0x88, 0x89, 0x88, 0x86, 0x8C, 0x86, 0x87, 0x8B, 0x88, 0x89,
+	 0x8D, 0x86, 0x9C, 0x9B, 0x85, 0x95, 0x90, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x8A, 0x8A, 0x89, 0x88,
+	 0x89, 0x87, 0x88, 0x89, 0x88, 0x87, 0x8C, 0x87, 0x87, 0x8B, 0x88, 0x87,
+	 0x8A, 0x83, 0x9C, 0x9A, 0x86, 0x91, 0x8E, 0xA7, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x89,
+	 0x89, 0x87, 0x88, 0x89, 0x89, 0x84, 0x8B, 0x84, 0x87, 0x8A, 0x87, 0x88,
+	 0x8A, 0x84, 0x9C, 0x9A, 0x87, 0x91, 0x8E, 0xA7, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x89,
+	 0x89, 0x87, 0x88, 0x89, 0x89, 0x85, 0x8B, 0x85, 0x87, 0x8A, 0x87, 0x87,
+	 0x8A, 0x84, 0x9B, 0x99, 0x85, 0x8D, 0x8B, 0xA4, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x89,
+	 0x89, 0x87, 0x89, 0x89, 0x89, 0x83, 0x89, 0x84, 0x87, 0x8A, 0x86, 0x88,
+	 0x8A, 0x85, 0x9B, 0x99, 0x85, 0x95, 0x90, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x89, 0x8A, 0x89, 0x88,
+	 0x89, 0x86, 0x88, 0x88, 0x8A, 0x85, 0x8A, 0x86, 0x85, 0x88, 0x85, 0x86,
+	 0x89, 0x83, 0x9C, 0x9A, 0x86, 0x91, 0x8D, 0xA7, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x87, 0x88, 0x88, 0x8A, 0x84, 0x89, 0x84, 0x87, 0x8A, 0x88, 0x87,
+	 0x89, 0x84, 0x96, 0x98, 0x82, 0x95, 0x90, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x88, 0x88, 0x87, 0x88, 0x85, 0x8A, 0x85, 0x84, 0x87, 0x83, 0x89,
+	 0x8C, 0x87, 0x96, 0x97, 0x81, 0x99, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x87, 0x88, 0x87, 0x89, 0x85, 0x8A, 0x85, 0x84, 0x87, 0x83, 0x8A,
+	 0x8C, 0x88, 0x96, 0x97, 0x82, 0x95, 0x90, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x88, 0x89, 0x88, 0x8A, 0x84, 0x89, 0x84, 0x85, 0x88, 0x85, 0x85,
+	 0x88, 0x84, 0x98, 0x97, 0x83, 0x90, 0x8D, 0xA6, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x88, 0x88, 0x86, 0x87, 0x83, 0x89, 0x84, 0x87, 0x89, 0x86, 0x85,
+	 0x88, 0x85, 0x98, 0x98, 0x85, 0x88, 0x87, 0x9E, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x89,
+	 0x89, 0x88, 0x87, 0x86, 0x87, 0x84, 0x89, 0x85, 0x85, 0x87, 0x84, 0x84,
+	 0x88, 0x83, 0x99, 0x98, 0x84, 0x94, 0x90, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x89,
+	 0x89, 0x88, 0x88, 0x87, 0x88, 0x81, 0x86, 0x83, 0x88, 0x89, 0x86, 0x85,
+	 0x88, 0x84, 0x95, 0x95, 0x81, 0x99, 0x93, 0xAC, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x87, 0x88, 0x86, 0x88, 0x84, 0x89, 0x85, 0x86, 0x87, 0x84, 0x84,
+	 0x88, 0x84, 0x9A, 0x98, 0x86, 0x8C, 0x8A, 0xA0, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC6, 0x00, 0xB4, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x87, 0x88, 0x86, 0x88, 0x83, 0x88, 0x84, 0x88, 0x89, 0x86, 0x81,
+	 0x84, 0x81, 0x98, 0x96, 0x83, 0x99, 0x93, 0xAC, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC7, 0x00, 0xB5, 0x89, 0x89, 0x89, 0x89,
+	 0x89, 0x87, 0x88, 0x88, 0x88, 0x83, 0x87, 0x85, 0x87, 0x87, 0x84, 0x85,
+	 0x88, 0x85, 0x96, 0x95, 0x83, 0x8C, 0x8A, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xC2, 0x00, 0xC9, 0x00, 0xB8, 0x88, 0x89, 0x89, 0x88,
+	 0x89, 0x87, 0x88, 0x86, 0x87, 0x84, 0x88, 0x85, 0x84, 0x85, 0x82, 0x85,
+	 0x88, 0x85, 0x95, 0x94, 0x83, 0x8C, 0x8A, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xC4, 0x00, 0xCB, 0x00, 0xBA, 0x89, 0x89, 0x89, 0x87,
+	 0x87, 0x85, 0x87, 0x87, 0x88, 0x83, 0x86, 0x84, 0x85, 0x87, 0x84, 0x82,
+	 0x85, 0x83, 0x95, 0x94, 0x82, 0x8C, 0x8A, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xC7, 0x00, 0xCE, 0x00, 0xBE, 0x87, 0x88, 0x88, 0x88,
+	 0x88, 0x87, 0x87, 0x86, 0x86, 0x82, 0x86, 0x83, 0x84, 0x86, 0x83, 0x83,
+	 0x85, 0x83, 0x94, 0x94, 0x83, 0x8C, 0x8A, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xCA, 0x00, 0xD0, 0x00, 0xC1, 0x88, 0x88, 0x88, 0x87,
+	 0x88, 0x86, 0x86, 0x86, 0x86, 0x83, 0x85, 0x83, 0x84, 0x86, 0x84, 0x84,
+	 0x86, 0x82, 0x96, 0x95, 0x85, 0x94, 0x90, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xCD, 0x00, 0xD2, 0x00, 0xC5, 0x87, 0x88, 0x88, 0x87,
+	 0x87, 0x85, 0x86, 0x86, 0x87, 0x82, 0x86, 0x84, 0x86, 0x87, 0x86, 0x81,
+	 0x84, 0x7F, 0x93, 0x92, 0x83, 0x84, 0x84, 0x91, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD0, 0x00, 0xD5, 0x00, 0xC8, 0x86, 0x87, 0x87, 0x87,
+	 0x87, 0x86, 0x85, 0x84, 0x85, 0x84, 0x86, 0x84, 0x84, 0x85, 0x83, 0x82,
+	 0x85, 0x81, 0x93, 0x92, 0x85, 0x7C, 0x7E, 0x84, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD2, 0x00, 0xD7, 0x00, 0xCB, 0x86, 0x87, 0x87, 0x87,
+	 0x88, 0x86, 0x85, 0x85, 0x86, 0x85, 0x86, 0x85, 0x81, 0x84, 0x81, 0x83,
+	 0x85, 0x81, 0x93, 0x92, 0x83, 0x84, 0x84, 0x94, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD6, 0x00, 0xDA, 0x00, 0xCF, 0x86, 0x87, 0x87, 0x85,
+	 0x86, 0x84, 0x86, 0x85, 0x86, 0x84, 0x85, 0x83, 0x81, 0x84, 0x81, 0x83,
+	 0x85, 0x82, 0x92, 0x91, 0x83, 0x80, 0x81, 0x8E, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD9, 0x00, 0xDD, 0x00, 0xD2, 0x85, 0x86, 0x87, 0x86,
+	 0x86, 0x85, 0x85, 0x84, 0x85, 0x83, 0x84, 0x85, 0x81, 0x82, 0x81, 0x85,
+	 0x86, 0x83, 0x8E, 0x8E, 0x82, 0x7C, 0x7E, 0x84, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xDD, 0x00, 0xE0, 0x00, 0xD7, 0x85, 0x86, 0x85, 0x85,
+	 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x85, 0x84, 0x83, 0x85, 0x84, 0x83,
+	 0x84, 0x7F, 0x8C, 0x8C, 0x7F, 0x88, 0x87, 0x97, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xDF, 0x00, 0xE3, 0x00, 0xD9, 0x85, 0x85, 0x86, 0x85,
+	 0x85, 0x84, 0x84, 0x84, 0x85, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
+	 0x84, 0x80, 0x8A, 0x8B, 0x7E, 0x84, 0x84, 0x91, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE2, 0x00, 0xE5, 0x00, 0xDE, 0x85, 0x85, 0x85, 0x85,
+	 0x85, 0x83, 0x82, 0x83, 0x84, 0x83, 0x84, 0x83, 0x81, 0x84, 0x83, 0x81,
+	 0x82, 0x7D, 0x8F, 0x8E, 0x83, 0x78, 0x7B, 0x82, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE5, 0x00, 0xE8, 0x00, 0xE0, 0x84, 0x85, 0x85, 0x84,
+	 0x84, 0x83, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x80, 0x82, 0x81, 0x82,
+	 0x84, 0x80, 0x8C, 0x8B, 0x80, 0x7C, 0x7E, 0x88, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEB, 0x00, 0xE5, 0x85, 0x84, 0x85, 0x83,
+	 0x84, 0x84, 0x82, 0x83, 0x83, 0x82, 0x83, 0x83, 0x81, 0x83, 0x82, 0x80,
+	 0x82, 0x7D, 0x8C, 0x8B, 0x81, 0x78, 0x7B, 0x82, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xE3, 0x85, 0x85, 0x85, 0x84,
+	 0x84, 0x84, 0x82, 0x82, 0x83, 0x84, 0x83, 0x84, 0x80, 0x82, 0x81, 0x83,
+	 0x84, 0x80, 0x86, 0x87, 0x7B, 0x80, 0x80, 0x87, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xE3, 0x85, 0x85, 0x85, 0x84,
+	 0x84, 0x84, 0x82, 0x82, 0x83, 0x81, 0x82, 0x82, 0x80, 0x82, 0x80, 0x84,
+	 0x84, 0x80, 0x89, 0x88, 0x7E, 0x78, 0x7A, 0x7A, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE8, 0x00, 0xEB, 0x00, 0xE4, 0x84, 0x84, 0x84, 0x84,
+	 0x84, 0x83, 0x83, 0x83, 0x84, 0x83, 0x82, 0x83, 0x81, 0x82, 0x82, 0x82,
+	 0x82, 0x7E, 0x87, 0x87, 0x7C, 0x88, 0x86, 0x93, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEB, 0x00, 0xE4, 0x84, 0x84, 0x85, 0x85,
+	 0x84, 0x82, 0x82, 0x82, 0x83, 0x82, 0x82, 0x82, 0x80, 0x82, 0x81, 0x84,
+	 0x84, 0x80, 0x87, 0x86, 0x7D, 0x78, 0x7A, 0x7A, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEB, 0x00, 0xE4, 0x84, 0x84, 0x84, 0x83,
+	 0x84, 0x83, 0x82, 0x83, 0x83, 0x82, 0x82, 0x82, 0x80, 0x82, 0x81, 0x81,
+	 0x81, 0x7D, 0x8A, 0x89, 0x82, 0x78, 0x7A, 0x7A, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEB, 0x00, 0xE4, 0x84, 0x84, 0x84, 0x83,
+	 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x81, 0x83, 0x82, 0x83, 0x81, 0x82,
+	 0x81, 0x7E, 0x87, 0x86, 0x7F, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEB, 0x00, 0xE4, 0x84, 0x84, 0x84, 0x83,
+	 0x83, 0x83, 0x81, 0x81, 0x81, 0x84, 0x82, 0x84, 0x80, 0x81, 0x81, 0x83,
+	 0x83, 0x7F, 0x88, 0x86, 0x80, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xEA, 0x00, 0xED, 0x00, 0xE6, 0x83, 0x83, 0x83, 0x84,
+	 0x83, 0x83, 0x82, 0x82, 0x82, 0x81, 0x82, 0x81, 0x7F, 0x7F, 0x80, 0x83,
+	 0x83, 0x83, 0x88, 0x86, 0x86, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xED, 0x00, 0xEF, 0x00, 0xEA, 0x83, 0x83, 0x83, 0x83,
+	 0x83, 0x83, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x81, 0x80,
+	 0x81, 0x81, 0x88, 0x86, 0x86, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xF1, 0x00, 0xF3, 0x00, 0xEE, 0x82, 0x82, 0x82, 0x83,
+	 0x83, 0x83, 0x81, 0x81, 0x81, 0x81, 0x82, 0x81, 0x81, 0x81, 0x81, 0x82,
+	 0x82, 0x82, 0x84, 0x83, 0x83, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xF5, 0x00, 0xF6, 0x00, 0xF3, 0x81, 0x82, 0x82, 0x82,
+	 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x81, 0x80, 0x81, 0x81, 0x81, 0x82,
+	 0x82, 0x82, 0x84, 0x83, 0x83, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xF9, 0x00, 0xFA, 0x00, 0xF8, 0x81, 0x81, 0x81, 0x81,
+	 0x81, 0x81, 0x81, 0x81, 0x82, 0x7F, 0x7F, 0x7F, 0x81, 0x81, 0x81, 0x80,
+	 0x80, 0x80, 0x82, 0x81, 0x80, 0x80, 0x80, 0x83, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xFC, 0x00, 0xFD, 0x00, 0xFC, 0x80, 0x80, 0x80, 0x81,
+	 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	 0x80, 0x80, 0x82, 0x81, 0x80, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 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}
+};
+
+static const u8 seq_ea8064g_lux[S6E3FA2_NUM_GAMMA_LEVELS][GAMMA_SEQ_LEN] = {
+	{MCS_GAMMA, 0x00, 0xB8, 0x00, 0xC5, 0x00, 0xA9, 0x8B, 0x91, 0x8D, 0x8A,
+	 0x90, 0x8A, 0x8E, 0x99, 0x91, 0x92, 0x9D, 0x8F, 0x92, 0x95, 0x8E, 0x93,
+	 0x92, 0x8C, 0xAE, 0xA5, 0x9C, 0x9B, 0x93, 0xAC, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBC, 0x00, 0xC5, 0x00, 0xAE, 0x8A, 0x8E, 0x8B, 0x89,
+	 0x8E, 0x8B, 0x8C, 0x94, 0x8C, 0x8D, 0x98, 0x8E, 0x8D, 0x92, 0x8B, 0x91,
+	 0x93, 0x89, 0xAB, 0xA5, 0x99, 0x9C, 0x94, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBD, 0x00, 0xC5, 0x00, 0xAF, 0x8A, 0x8E, 0x8C, 0x88,
+	 0x8D, 0x89, 0x8B, 0x93, 0x8B, 0x8E, 0x97, 0x8E, 0x8B, 0x91, 0x8B, 0x90,
+	 0x91, 0x86, 0xA9, 0xA4, 0x96, 0x9E, 0x96, 0xAF, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBD, 0x00, 0xC5, 0x00, 0xB0, 0x8B, 0x8D, 0x8B, 0x88,
+	 0x8C, 0x89, 0x8C, 0x92, 0x8C, 0x8C, 0x96, 0x8D, 0x8A, 0x91, 0x89, 0x90,
+	 0x91, 0x88, 0xA8, 0xA4, 0x93, 0x9C, 0x94, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC5, 0x00, 0xB1, 0x8B, 0x8D, 0x8B, 0x87,
+	 0x8B, 0x89, 0x8A, 0x8F, 0x89, 0x8B, 0x93, 0x8C, 0x8A, 0x90, 0x89, 0x8E,
+	 0x91, 0x88, 0xA7, 0xA3, 0x8F, 0x9D, 0x95, 0xAE, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC5, 0x00, 0xB1, 0x8A, 0x8D, 0x8C, 0x87,
+	 0x8A, 0x87, 0x8A, 0x8E, 0x89, 0x8B, 0x93, 0x8C, 0x8A, 0x90, 0x8A, 0x8D,
+	 0x90, 0x87, 0xA6, 0xA3, 0x90, 0x98, 0x91, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC5, 0x00, 0xB1, 0x8A, 0x8C, 0x8B, 0x87,
+	 0x8B, 0x88, 0x8A, 0x8E, 0x89, 0x89, 0x91, 0x8A, 0x8A, 0x90, 0x8A, 0x8E,
+	 0x90, 0x88, 0xA5, 0xA2, 0x8E, 0x98, 0x91, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x8A, 0x8C, 0x8B, 0x87,
+	 0x8A, 0x88, 0x8A, 0x8C, 0x88, 0x89, 0x91, 0x8B, 0x88, 0x8E, 0x89, 0x8D,
+	 0x8F, 0x88, 0xA3, 0xA0, 0x8A, 0x9F, 0x97, 0xB0, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8C, 0x8A, 0x88,
+	 0x8A, 0x89, 0x88, 0x8B, 0x89, 0x8A, 0x91, 0x8A, 0x87, 0x8E, 0x88, 0x8C,
+	 0x8F, 0x88, 0xA5, 0xA1, 0x8C, 0x97, 0x91, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x8A, 0x8C, 0x8B, 0x87,
+	 0x89, 0x88, 0x89, 0x8B, 0x88, 0x8A, 0x91, 0x8B, 0x85, 0x8C, 0x85, 0x8A,
+	 0x8D, 0x85, 0xA3, 0xA2, 0x8C, 0x9C, 0x95, 0xAE, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8C, 0x8B, 0x88,
+	 0x89, 0x88, 0x89, 0x8B, 0x88, 0x87, 0x8F, 0x89, 0x87, 0x8D, 0x87, 0x8C,
+	 0x8E, 0x88, 0xA0, 0xA0, 0x88, 0x97, 0x91, 0xAB, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x87,
+	 0x89, 0x87, 0x89, 0x8B, 0x89, 0x88, 0x8E, 0x88, 0x87, 0x8D, 0x87, 0x89,
+	 0x8E, 0x86, 0xA0, 0x9F, 0x88, 0x99, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x87,
+	 0x89, 0x87, 0x89, 0x89, 0x8A, 0x87, 0x8E, 0x88, 0x86, 0x8C, 0x87, 0x89,
+	 0x8D, 0x84, 0xA2, 0xA1, 0x8B, 0x99, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBE, 0x00, 0xC5, 0x00, 0xB1, 0x8A, 0x8B, 0x8A, 0x86,
+	 0x88, 0x87, 0x88, 0x89, 0x87, 0x86, 0x8E, 0x89, 0x85, 0x8B, 0x86, 0x8C,
+	 0x8E, 0x87, 0x9F, 0xA0, 0x87, 0x95, 0x90, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x87,
+	 0x89, 0x88, 0x88, 0x88, 0x87, 0x87, 0x8E, 0x89, 0x86, 0x8C, 0x88, 0x8B,
+	 0x8E, 0x86, 0x9D, 0x9D, 0x86, 0x99, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x88,
+	 0x89, 0x88, 0x88, 0x88, 0x88, 0x87, 0x8E, 0x89, 0x83, 0x89, 0x84, 0x8A,
+	 0x8D, 0x85, 0x9F, 0x9E, 0x88, 0x99, 0x93, 0xAD, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x87,
+	 0x88, 0x87, 0x88, 0x88, 0x87, 0x87, 0x8D, 0x87, 0x85, 0x8B, 0x87, 0x8A,
+	 0x8D, 0x85, 0x9D, 0x9D, 0x86, 0x95, 0x90, 0xAA, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x8A, 0x8B, 0x8A, 0x86,
+	 0x88, 0x87, 0x88, 0x88, 0x87, 0x88, 0x8D, 0x88, 0x85, 0x8B, 0x87, 0x88,
+	 0x8A, 0x83, 0x9C, 0x9C, 0x87, 0x91, 0x8D, 0xA7, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x87,
+	 0x88, 0x87, 0x88, 0x88, 0x88, 0x85, 0x8C, 0x86, 0x86, 0x8A, 0x87, 0x89,
+	 0x8A, 0x84, 0x9C, 0x9C, 0x88, 0x91, 0x8D, 0xA7, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x87,
+	 0x88, 0x87, 0x88, 0x88, 0x88, 0x86, 0x8C, 0x87, 0x86, 0x8A, 0x87, 0x88,
+	 0x8A, 0x84, 0x9B, 0x9B, 0x86, 0x8C, 0x8A, 0xA4, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x87,
+	 0x88, 0x87, 0x89, 0x88, 0x88, 0x84, 0x8A, 0x86, 0x85, 0x8A, 0x86, 0x88,
+	 0x8A, 0x85, 0x9C, 0x9B, 0x85, 0x95, 0x90, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x89, 0x8B, 0x8A, 0x86,
+	 0x88, 0x86, 0x88, 0x87, 0x89, 0x85, 0x8B, 0x88, 0x83, 0x88, 0x84, 0x87,
+	 0x89, 0x83, 0x9C, 0x9C, 0x86, 0x90, 0x8C, 0xA6, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x87, 0x88, 0x87, 0x89, 0x85, 0x89, 0x86, 0x85, 0x8A, 0x87, 0x88,
+	 0x89, 0x84, 0x97, 0x99, 0x83, 0x94, 0x8F, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x88, 0x88, 0x86, 0x87, 0x86, 0x8B, 0x86, 0x82, 0x87, 0x83, 0x89,
+	 0x8B, 0x86, 0x97, 0x98, 0x82, 0x99, 0x92, 0xAC, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x87, 0x88, 0x86, 0x88, 0x86, 0x8B, 0x86, 0x82, 0x87, 0x83, 0x8A,
+	 0x8B, 0x87, 0x97, 0x98, 0x83, 0x94, 0x8F, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x88, 0x89, 0x87, 0x89, 0x85, 0x89, 0x86, 0x83, 0x88, 0x85, 0x86,
+	 0x88, 0x83, 0x98, 0x98, 0x84, 0x90, 0x8C, 0xA6, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x88, 0x88, 0x85, 0x86, 0x84, 0x8A, 0x86, 0x85, 0x89, 0x86, 0x86,
+	 0x88, 0x84, 0x99, 0x9A, 0x86, 0x88, 0x86, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x87,
+	 0x88, 0x88, 0x87, 0x85, 0x86, 0x85, 0x8A, 0x87, 0x83, 0x87, 0x84, 0x85,
+	 0x87, 0x82, 0x9A, 0x99, 0x85, 0x94, 0x8F, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x87,
+	 0x88, 0x88, 0x88, 0x86, 0x87, 0x82, 0x87, 0x85, 0x86, 0x88, 0x86, 0x86,
+	 0x87, 0x83, 0x96, 0x97, 0x81, 0x98, 0x92, 0xAC, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x87, 0x88, 0x85, 0x87, 0x85, 0x8A, 0x87, 0x84, 0x87, 0x84, 0x85,
+	 0x87, 0x83, 0x9B, 0x99, 0x87, 0x8C, 0x89, 0xA0, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xBF, 0x00, 0xC5, 0x00, 0xB2, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x87, 0x88, 0x85, 0x87, 0x84, 0x88, 0x86, 0x86, 0x88, 0x86, 0x82,
+	 0x83, 0x80, 0x98, 0x98, 0x83, 0x98, 0x92, 0xAC, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xC0, 0x00, 0xC6, 0x00, 0xB3, 0x89, 0x8A, 0x8A, 0x87,
+	 0x88, 0x87, 0x88, 0x87, 0x87, 0x84, 0x88, 0x86, 0x85, 0x87, 0x84, 0x86,
+	 0x87, 0x84, 0x97, 0x97, 0x83, 0x8C, 0x89, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xC3, 0x00, 0xC8, 0x00, 0xB6, 0x88, 0x8A, 0x8A, 0x86,
+	 0x88, 0x87, 0x88, 0x86, 0x87, 0x84, 0x88, 0x87, 0x82, 0x85, 0x82, 0x86,
+	 0x87, 0x84, 0x96, 0x96, 0x83, 0x8C, 0x89, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xC4, 0x00, 0xCA, 0x00, 0xB8, 0x89, 0x8A, 0x8A, 0x85,
+	 0x86, 0x85, 0x87, 0x86, 0x87, 0x84, 0x87, 0x86, 0x83, 0x87, 0x84, 0x83,
+	 0x85, 0x82, 0x96, 0x96, 0x82, 0x8C, 0x89, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xC8, 0x00, 0xCD, 0x00, 0xBC, 0x88, 0x89, 0x89, 0x86,
+	 0x87, 0x87, 0x87, 0x85, 0x85, 0x83, 0x86, 0x85, 0x83, 0x86, 0x83, 0x84,
+	 0x85, 0x82, 0x95, 0x96, 0x83, 0x8C, 0x89, 0x9D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xCA, 0x00, 0xCF, 0x00, 0xBF, 0x89, 0x89, 0x89, 0x85,
+	 0x87, 0x86, 0x86, 0x85, 0x85, 0x84, 0x86, 0x84, 0x82, 0x86, 0x84, 0x84,
+	 0x86, 0x82, 0x96, 0x96, 0x86, 0x94, 0x8F, 0xA9, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xCD, 0x00, 0xD1, 0x00, 0xC3, 0x88, 0x89, 0x89, 0x85,
+	 0x86, 0x85, 0x86, 0x85, 0x86, 0x83, 0x86, 0x85, 0x84, 0x87, 0x86, 0x82,
+	 0x84, 0x7E, 0x93, 0x93, 0x83, 0x84, 0x83, 0x90, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD1, 0x00, 0xD4, 0x00, 0xC6, 0x87, 0x88, 0x88, 0x85,
+	 0x86, 0x86, 0x85, 0x84, 0x84, 0x84, 0x87, 0x85, 0x82, 0x85, 0x83, 0x83,
+	 0x85, 0x80, 0x93, 0x93, 0x85, 0x7C, 0x7D, 0x84, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD2, 0x00, 0xD6, 0x00, 0xC9, 0x87, 0x89, 0x88, 0x85,
+	 0x87, 0x86, 0x85, 0x84, 0x85, 0x86, 0x86, 0x85, 0x80, 0x84, 0x81, 0x83,
+	 0x85, 0x80, 0x93, 0x93, 0x84, 0x84, 0x83, 0x94, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD6, 0x00, 0xD9, 0x00, 0xCD, 0x88, 0x88, 0x88, 0x83,
+	 0x85, 0x84, 0x86, 0x85, 0x86, 0x84, 0x85, 0x84, 0x80, 0x84, 0x81, 0x83,
+	 0x85, 0x81, 0x92, 0x92, 0x84, 0x80, 0x80, 0x8E, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xD9, 0x00, 0xDC, 0x00, 0xD1, 0x86, 0x88, 0x88, 0x84,
+	 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x85, 0x86, 0x80, 0x82, 0x80, 0x85,
+	 0x86, 0x82, 0x8E, 0x8F, 0x82, 0x7C, 0x7D, 0x84, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xDC, 0x00, 0xDE, 0x00, 0xD5, 0x87, 0x88, 0x86, 0x83,
+	 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x85, 0x84, 0x82, 0x85, 0x84, 0x84,
+	 0x84, 0x7F, 0x8C, 0x8D, 0x7F, 0x88, 0x86, 0x97, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xDE, 0x00, 0xE1, 0x00, 0xD7, 0x86, 0x87, 0x87, 0x84,
+	 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x82, 0x83, 0x83, 0x84,
+	 0x84, 0x80, 0x8A, 0x8C, 0x7E, 0x84, 0x83, 0x90, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE1, 0x00, 0xE4, 0x00, 0xDC, 0x86, 0x87, 0x86, 0x83,
+	 0x84, 0x83, 0x82, 0x83, 0x83, 0x83, 0x84, 0x83, 0x81, 0x84, 0x83, 0x81,
+	 0x82, 0x7D, 0x90, 0x8F, 0x83, 0x78, 0x7A, 0x81, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE5, 0x00, 0xE7, 0x00, 0xDF, 0x85, 0x86, 0x86, 0x83,
+	 0x84, 0x83, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x80, 0x82, 0x81, 0x83,
+	 0x84, 0x80, 0x8C, 0x8C, 0x80, 0x7C, 0x7D, 0x87, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xE4, 0x86, 0x85, 0x85, 0x82,
+	 0x84, 0x84, 0x82, 0x83, 0x82, 0x83, 0x83, 0x83, 0x81, 0x83, 0x82, 0x80,
+	 0x82, 0x7D, 0x8C, 0x8C, 0x81, 0x78, 0x7A, 0x81, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE6, 0x00, 0xE9, 0x00, 0xE2, 0x85, 0x86, 0x86, 0x83,
+	 0x83, 0x84, 0x82, 0x82, 0x83, 0x84, 0x83, 0x84, 0x80, 0x82, 0x81, 0x84,
+	 0x84, 0x80, 0x86, 0x87, 0x7C, 0x80, 0x80, 0x87, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE6, 0x00, 0xE9, 0x00, 0xE2, 0x85, 0x86, 0x86, 0x83,
+	 0x83, 0x84, 0x82, 0x82, 0x83, 0x81, 0x82, 0x83, 0x7F, 0x82, 0x80, 0x85,
+	 0x84, 0x80, 0x89, 0x88, 0x7E, 0x77, 0x7A, 0x7A, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE8, 0x00, 0xEA, 0x00, 0xE3, 0x85, 0x85, 0x85, 0x83,
+	 0x84, 0x83, 0x83, 0x83, 0x84, 0x83, 0x82, 0x83, 0x81, 0x82, 0x82, 0x82,
+	 0x82, 0x7E, 0x87, 0x87, 0x7C, 0x88, 0x86, 0x93, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xE3, 0x85, 0x85, 0x86, 0x84,
+	 0x84, 0x82, 0x82, 0x82, 0x83, 0x82, 0x82, 0x83, 0x7F, 0x82, 0x81, 0x85,
+	 0x84, 0x80, 0x87, 0x86, 0x7D, 0x77, 0x7A, 0x7A, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xE3, 0x85, 0x85, 0x85, 0x82,
+	 0x83, 0x83, 0x82, 0x83, 0x83, 0x82, 0x82, 0x83, 0x7F, 0x82, 0x81, 0x81,
+	 0x80, 0x7D, 0x8B, 0x8A, 0x82, 0x77, 0x7A, 0x7A, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xE3, 0x85, 0x85, 0x85, 0x82,
+	 0x82, 0x83, 0x82, 0x82, 0x82, 0x83, 0x81, 0x83, 0x81, 0x83, 0x81, 0x82,
+	 0x80, 0x7E, 0x87, 0x86, 0x7F, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xE3, 0x85, 0x85, 0x85, 0x82,
+	 0x82, 0x83, 0x81, 0x81, 0x81, 0x84, 0x82, 0x84, 0x80, 0x81, 0x81, 0x83,
+	 0x83, 0x7F, 0x88, 0x86, 0x80, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xEA, 0x00, 0xEC, 0x00, 0xE5, 0x84, 0x84, 0x84, 0x83,
+	 0x83, 0x83, 0x82, 0x82, 0x82, 0x81, 0x82, 0x82, 0x7F, 0x7F, 0x80, 0x83,
+	 0x83, 0x83, 0x88, 0x86, 0x86, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xED, 0x00, 0xEF, 0x00, 0xE9, 0x83, 0x84, 0x84, 0x82,
+	 0x82, 0x83, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x81, 0x80,
+	 0x80, 0x81, 0x88, 0x86, 0x86, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xF1, 0x00, 0xF2, 0x00, 0xEE, 0x82, 0x83, 0x82, 0x82,
+	 0x82, 0x83, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x80, 0x81, 0x81, 0x82,
+	 0x82, 0x82, 0x84, 0x83, 0x83, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xF5, 0x00, 0xF6, 0x00, 0xF2, 0x82, 0x82, 0x82, 0x81,
+	 0x81, 0x82, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x80, 0x81, 0x81, 0x82,
+	 0x82, 0x82, 0x84, 0x83, 0x83, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xF9, 0x00, 0xFA, 0x00, 0xF8, 0x81, 0x82, 0x82, 0x81,
+	 0x81, 0x81, 0x81, 0x81, 0x82, 0x7F, 0x7F, 0x7F, 0x81, 0x81, 0x81, 0x80,
+	 0x80, 0x80, 0x82, 0x81, 0x80, 0x80, 0x80, 0x83, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 0x00, 0xFC, 0x00, 0xFD, 0x00, 0xFC, 0x80, 0x81, 0x81, 0x81,
+	 0x80, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	 0x80, 0x80, 0x82, 0x81, 0x80, 0x7B, 0x7D, 0x7D, 0x00, 0x00, 0x00},
+	{MCS_GAMMA, 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},
+};
+
+/* Other panel drivers call these commands test_key_enable/disable */
+static const u8 seq_s6e3fa2_test_key_en[6] = {
+	0xf0, 0x5a, 0x5a,
+	0xfc, 0x5a, 0x5a
+};
+static const u8 seq_s6e3fa2_test_key_dis[6] = {
+	0xf0, 0xa5, 0xa5,
+	0xfc, 0xa5, 0xa5
+};
+static const u8 seq_ea8064g_test_key_en[6] = {
+	0xf0, 0x5a, 0x5a,
+	0xf1, 0x5a, 0x5a
+};
+static const u8 seq_ea8064g_test_key_dis[6] = {
+	0xf1, 0xa5, 0xa5,
+	0xf0, 0xa5, 0xa5
+};
+
+struct s6e3fa2_sequences_data {
+	const u8 *test_key_enable_seq;
+	const u8 *test_key_disable_seq;
+	/* Whether to send 2nd seq during set_brigthness or not */
+	bool send_both_test_seq;
+
+	const u8 (*aid_seq)[NUM_AID_SEQUENCES][AID_SEQUENCE_LEN];
+	const u8 (*elvss_seq)[NUM_ELVSS_SEQUENCES][ELVSS_SEQUENCE_LEN];
+	const u8 (*gamma_seq)[S6E3FA2_NUM_GAMMA_LEVELS][GAMMA_SEQ_LEN];
+};
+
+static const struct s6e3fa2_sequences_data seqdata_s6e3fa2 = {
+	.test_key_enable_seq = seq_s6e3fa2_test_key_en,
+	.test_key_disable_seq = seq_s6e3fa2_test_key_dis,
+	.send_both_test_seq = false,
+	.aid_seq = &seq_s6e3fa2_aid,
+	.elvss_seq = &seq_s6e3fa2_elvss,
+	.gamma_seq = &seq_s6e3fa2_lux
+};
+
+static const struct s6e3fa2_sequences_data seqdata_ea8064g = {
+	.test_key_enable_seq = seq_ea8064g_test_key_en,
+	.test_key_disable_seq = seq_ea8064g_test_key_dis,
+	.send_both_test_seq = true,
+	.aid_seq = &seq_ea8064g_aid,
+	.elvss_seq = &seq_ea8064g_elvss,
+	.gamma_seq = &seq_ea8064g_lux
+};
+
+enum s6e3fa2_panel_subtype {
+	PANEL_UNKNOWN = 0,
+	PANEL_S6E3FA2,
+	PANEL_EA8064G,
+};
+
+struct s6e3fa2_ctx {
+	struct drm_panel panel;
+	struct mipi_dsi_device *dsi;
+	struct regulator_bulk_data supplies[2];
+	struct gpio_desc *reset_gpio;
+	struct backlight_device *bl_dev;
+	bool prepared;
+	bool enabled;
+
+	enum s6e3fa2_panel_subtype subtype;
+	const struct s6e3fa2_sequences_data *seq_data;
+};
+
+static inline
+struct s6e3fa2_ctx *panel_to_s6e3fa2(struct drm_panel *panel)
+{
+	return container_of(panel, struct s6e3fa2_ctx, panel);
+}
+
+enum s6e3fa2_test_key_mode {
+	TK_DEFAULT_MODE = 0,
+	TK_INIT_MODE
+};
+
+static int s6e3fa2_test_key_enable(struct s6e3fa2_ctx *ctx, bool enable,
+				   enum s6e3fa2_test_key_mode mode)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	int ret;
+	const u8 *seq;
+
+	if (!ctx->seq_data)
+		return -ENODEV;
+
+	if (enable)
+		seq = ctx->seq_data->test_key_enable_seq;
+	else
+		seq = ctx->seq_data->test_key_disable_seq;
+
+	/*
+	 * There are actually 2 separate commands.
+	 * Send first 3 bytes, then send other 3 bytes.
+	 */
+	ret = mipi_dsi_generic_write(dsi, seq, 3);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * During init sequence always send both parts.
+	 * Otherwise - depends on panel subtype.
+	 */
+	if ((mode == TK_INIT_MODE) || ctx->seq_data->send_both_test_seq)
+		ret = mipi_dsi_generic_write(dsi, seq + 3, 3);
+	return ret;
+}
+
+static int s6e3fa2_write_aid_control(struct s6e3fa2_ctx *ctx, int candela)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	int idx;
+	const u8 *seq;
+
+	if (!ctx->seq_data)
+		return -ENODEV;
+
+	idx = map_candela_to_aid[candela];
+	seq = (*ctx->seq_data->aid_seq)[idx];
+	return mipi_dsi_generic_write(dsi, seq, AID_SEQUENCE_LEN);
+}
+
+static int s6e3fa2_write_elvss(struct s6e3fa2_ctx *ctx, int candela)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	int idx;
+	const u8 *seq;
+
+	if (!ctx->seq_data)
+		return -ENODEV;
+
+	idx = map_candela_to_elvss[candela];
+	seq = (*ctx->seq_data->elvss_seq)[idx];
+	return mipi_dsi_generic_write(dsi, seq, ELVSS_SEQUENCE_LEN);
+}
+
+static int s6e3fa2_write_gamma(struct s6e3fa2_ctx *ctx, int candela)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	const u8 *seq;
+
+	if (!ctx->seq_data)
+		return -ENODEV;
+
+	/* Gamma sequence is directly indexed by candela value */
+	seq = (*ctx->seq_data->gamma_seq)[candela];
+	return mipi_dsi_generic_write(dsi, seq, GAMMA_SEQ_LEN);
+}
+
+static int s6e3fa2_write_gamma_apply(struct s6e3fa2_ctx *ctx)
+{
+	/* From vendor driver: Gamma, LTPS(AID) update */
+	dsi_generic_write_seq(ctx->dsi, 0xf7, 0x03);
+	/* S6E3FA2 has additional command */
+	if (ctx->subtype == PANEL_S6E3FA2)
+		dsi_generic_write_seq(ctx->dsi, 0xf7, 0x00);
+	return 0;
+}
+
+static int s6e3fa2_set_brightness(struct backlight_device *bldev)
+{
+	struct s6e3fa2_ctx *ctx = bl_get_data(bldev);
+	const int candela = bldev->props.brightness;
+	int r;
+
+	r = s6e3fa2_test_key_enable(ctx, true, TK_DEFAULT_MODE);
+	if (r < 0)
+		return r;
+	r = s6e3fa2_write_aid_control(ctx, candela);
+	if (r < 0)
+		return r;
+	r = s6e3fa2_write_elvss(ctx, candela);
+	if (r < 0)
+		return r;
+	r = s6e3fa2_write_gamma(ctx, candela);
+	if (r < 0)
+		return r;
+	r = s6e3fa2_write_gamma_apply(ctx);
+	if (r < 0)
+		return r;
+	r = s6e3fa2_test_key_enable(ctx, false, TK_DEFAULT_MODE);
+	if (r < 0)
+		return r;
+
+	return 0;
+}
+
+static int s6e3fa2_check_lcd_type(struct s6e3fa2_ctx *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	u8 id1, id2, id3;
+	unsigned int lcd_id;
+	int ret;
+
+	ret = s6e3fa2_dsi_dcs_read1(dsi, MCS_READ_ID1, &id1);
+	if (ret < 0)
+		return ret;
+	ret = s6e3fa2_dsi_dcs_read1(dsi, MCS_READ_ID2, &id2);
+	if (ret < 0)
+		return ret;
+	ret = s6e3fa2_dsi_dcs_read1(dsi, MCS_READ_ID3, &id3);
+	if (ret < 0)
+		return ret;
+
+	lcd_id = id1 << 16 | id2 << 8 | id3;
+
+	switch (lcd_id) {
+	case LCD_ID_S6E3FA2:
+		dev_info(&dsi->dev, "detected S6E3FA2 panel (ID: 0x%x)\n",
+			 lcd_id);
+		ctx->subtype = PANEL_S6E3FA2;
+		ctx->seq_data = &seqdata_s6e3fa2;
+		break;
+	case LCD_ID_EA8064G:
+		dev_info(&dsi->dev, "detected EA8064G panel (ID: 0x%x)\n",
+			 lcd_id);
+		ctx->subtype = PANEL_EA8064G;
+		ctx->seq_data = &seqdata_ea8064g;
+		break;
+	default:
+		dev_warn(&dsi->dev, "unsupported panel ID: 0x%x\n", lcd_id);
+		ctx->subtype = PANEL_UNKNOWN;
+		break;
+	}
+
+	return 0;
+}
+
+static int s6e3fa2_init(struct s6e3fa2_ctx *ctx)
+{
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	struct device *dev = &dsi->dev;
+	int ret;
+
+	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
+
+	s6e3fa2_test_key_enable(ctx, true, TK_INIT_MODE);
+
+	if (ctx->subtype == PANEL_S6E3FA2) {
+		/* Configure MIPI Interface (Single DSI) */
+		dsi_dcs_write_seq(dsi, 0xf2);
+		dsi_dcs_write_seq(dsi, 0xf9);
+
+		usleep_range(5000, 6000);
+
+		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); /* Sleep out, wait 20ms(0x14) */
+
+		s6e3fa2_write_gamma(ctx, S6E3FA2_MAX_BRIGHTNESS);
+		s6e3fa2_write_aid_control(ctx, S6E3FA2_MAX_BRIGHTNESS);
+
+		/* CAPS ELVSS Set */
+		dsi_generic_write_seq(dsi, MCS_ELVSS_CONTROL,
+				0x98, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+				0x55, 0x54, 0x20, 0x00, 0x0a, 0xaa, 0xaf, 0x0f,
+				0x02, 0x22, 0x22, 0x10);
+
+		/* Unknown command: 16 frame Averaging (0x41) */
+		dsi_generic_write_seq(dsi, 0xb5, 0x41);
+
+		s6e3fa2_write_gamma_apply(ctx);
+
+		/* TE Vsync ON  */
+		dsi_generic_write_seq(dsi, 0xb0, 0x02);
+		dsi_generic_write_seq(dsi, 0xfd, 0x0a);
+		dsi_generic_write_seq(dsi, 0xfe, 0x80);
+		dsi_generic_write_seq(dsi, 0xfe, 0x00);
+
+		mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+
+		/* Touch Hsync Enable */
+		dsi_generic_write_seq(dsi, 0xbd, 0x05, 0x02, 0x02);
+	} else if (ctx->subtype == PANEL_EA8064G) {
+		s6e3fa2_write_gamma(ctx, S6E3FA2_MAX_BRIGHTNESS);
+		s6e3fa2_write_aid_control(ctx, S6E3FA2_MAX_BRIGHTNESS);
+
+		/* CAPS ELVSS Set */
+		dsi_generic_write_seq(dsi, MCS_ELVSS_CONTROL, 0x58, 0x84);
+
+		/* Unknown command: 16 frame Averaging (0x21) */
+		dsi_generic_write_seq(dsi, 0xb5, 0x21);
+
+		/* Disable high brightness mode */
+		dsi_generic_write_seq(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
+				      0x00);
+
+		s6e3fa2_write_gamma_apply(ctx);
+
+		/* TE Vsync ON  */
+		dsi_generic_write_seq(dsi, 0xb0, 0x01);
+		dsi_generic_write_seq(dsi, 0xb8, 0x04);
+		dsi_generic_write_seq(dsi, 0xba, 0x32, 0x30, 0x01);
+
+		mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+
+		/* Touch Hsync Enable */
+		dsi_generic_write_seq(dsi, 0xb9, 0x05, 0x17, 0x1b);
+
+		ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+		if (ret < 0) {
+			dev_err(dev, "Failed to exit sleep mode: %d\n", ret);
+			return ret;
+		};
+		/* sleep 120ms after exiting sleep mode */
+		msleep(120);
+	} else {
+		dev_warn(&dsi->dev, "init: skipped, unknown panel!\n");
+	}
+
+	s6e3fa2_test_key_enable(ctx, false, TK_INIT_MODE);
+
+	return 0;
+}
+
+static int s6e3fa2_power_on(struct s6e3fa2_ctx *ctx)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0) {
+		dev_err(&ctx->dsi->dev, "Failed to enable regulators: %d\n",
+			ret);
+		return ret;
+	}
+	msleep(30);
+
+	/* send reset pulse */
+	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(7000, 8000);
+
+	/* Panel init sequence does not work without this delay! */
+	msleep(60);
+
+	return 0;
+}
+
+static int s6e3fa2_power_off(struct s6e3fa2_ctx *ctx)
+{
+	int ret;
+
+	gpiod_set_value(ctx->reset_gpio, 1);
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int s6e3fa2_enable(struct drm_panel *panel)
+{
+	struct s6e3fa2_ctx *ctx = panel_to_s6e3fa2(panel);
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	int ret;
+
+	if (ctx->enabled)
+		return 0;
+
+	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+	if (ret < 0) {
+		dev_err(&dsi->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(&dsi->dev, "Failed to set display on: %d\n", ret);
+		return ret;
+	}
+	msleep(50);
+
+	backlight_enable(ctx->bl_dev);
+
+	ctx->enabled = true;
+	return 0;
+}
+
+static int s6e3fa2_disable(struct drm_panel *panel)
+{
+	struct s6e3fa2_ctx *ctx = panel_to_s6e3fa2(panel);
+	struct mipi_dsi_device *dsi = ctx->dsi;
+	int ret;
+
+	if (!ctx->enabled)
+		return 0;
+
+	backlight_disable(ctx->bl_dev);
+
+	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
+
+	ret = mipi_dsi_dcs_set_display_off(dsi);
+	if (ret < 0) {
+		dev_err(&dsi->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(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
+		return ret;
+	}
+
+	ctx->enabled = false;
+	return 0;
+}
+
+static int s6e3fa2_prepare(struct drm_panel *panel)
+{
+	struct s6e3fa2_ctx *ctx = panel_to_s6e3fa2(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (ctx->prepared)
+		return 0;
+
+	ret = s6e3fa2_power_on(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to power on the panel!\n");
+		return ret;
+	}
+
+	/* Detect panel subtype */
+	ret = s6e3fa2_check_lcd_type(ctx);
+	if (ret < 0)
+		dev_warn(dev, "Failed to check LCD type!\n");
+
+	ret = s6e3fa2_init(ctx);
+	if (ret < 0) {
+		dev_err(dev, "Failed to initialize panel: %d\n", ret);
+		s6e3fa2_power_off(ctx);
+		return ret;
+	}
+
+	ctx->prepared = true;
+	return 0;
+}
+
+static int s6e3fa2_unprepare(struct drm_panel *panel)
+{
+	struct s6e3fa2_ctx *ctx = panel_to_s6e3fa2(panel);
+	struct device *dev = &ctx->dsi->dev;
+	int ret;
+
+	if (!ctx->prepared)
+		return 0;
+
+	ret = s6e3fa2_power_off(ctx);
+	if (ret < 0)
+		dev_err(dev, "Failed to power off panel: %d\n", ret);
+
+	ctx->prepared = false;
+	return 0;
+}
+
+/* Resolution, size and timing values are the same for both panels. */
+static const struct drm_display_mode s6e3fa2_display_mode = {
+	.clock = (1080 + 162 + 10 + 36) * (1920 + 13 + 2 + 3) * 60 / 1000,
+	.hdisplay = 1080,
+	.hsync_start = 1080 + 162,
+	.hsync_end = 1080 + 162 + 10,
+	.htotal = 1080 + 162 + 10 + 36,
+	.vdisplay = 1920,
+	.vsync_start = 1920 + 13,
+	.vsync_end = 1920 + 13 + 2,
+	.vtotal = 1920 + 13 + 2 + 3,
+	.width_mm = 65,
+	.height_mm = 115,
+};
+
+static int s6e3fa2_get_modes(struct drm_panel *panel,
+			     struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev, &s6e3fa2_display_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;
+	connector->display_info.panel_orientation =
+			DRM_MODE_PANEL_ORIENTATION_NORMAL;
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_panel_funcs s6e3fa2_panel_funcs = {
+	.prepare = s6e3fa2_prepare,
+	.enable = s6e3fa2_enable,
+	.disable = s6e3fa2_disable,
+	.unprepare = s6e3fa2_unprepare,
+	.get_modes = s6e3fa2_get_modes,
+};
+
+static const struct backlight_ops s6e3fa2_backlight_ops = {
+	.update_status	= s6e3fa2_set_brightness,
+};
+
+static int s6e3fa2_backlight_register(struct s6e3fa2_ctx *ctx)
+{
+	struct backlight_properties props = {
+		.type		= BACKLIGHT_RAW,
+		.scale		= BACKLIGHT_SCALE_LINEAR,
+		.brightness	= S6E3FA2_MAX_BRIGHTNESS,
+		.max_brightness = S6E3FA2_MAX_BRIGHTNESS,
+	};
+	struct device *dev = &ctx->dsi->dev;
+	int ret = 0;
+
+	ctx->bl_dev = devm_backlight_device_register(dev, "panel", dev, ctx,
+						     &s6e3fa2_backlight_ops,
+						     &props);
+	if (IS_ERR(ctx->bl_dev)) {
+		ret = PTR_ERR(ctx->bl_dev);
+		dev_err(dev, "error registering backlight device (%d)\n", ret);
+	}
+
+	return ret;
+}
+
+static int s6e3fa2_probe(struct mipi_dsi_device *dsi)
+{
+	struct device *dev = &dsi->dev;
+	struct s6e3fa2_ctx *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->supplies[0].supply = "iovdd";
+	ctx->supplies[1].supply = "vddr";
+	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");
+
+	/* We don't know panel variant yet */
+	ctx->subtype = PANEL_UNKNOWN;
+
+	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_BURST |
+			  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+
+	drm_panel_init(&ctx->panel, dev, &s6e3fa2_panel_funcs,
+			DRM_MODE_CONNECTOR_DSI);
+
+	ret = s6e3fa2_backlight_register(ctx);
+	if (ret < 0)
+		return ret;
+
+	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 s6e3fa2_remove(struct mipi_dsi_device *dsi)
+{
+	struct s6e3fa2_ctx *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 samsung_s6e3fa2_of_match[] = {
+	{ .compatible = "samsung,s6e3fa2" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, samsung_s6e3fa2_of_match);
+
+static struct mipi_dsi_driver samsung_s6e3fa2_driver = {
+	.probe = s6e3fa2_probe,
+	.remove = s6e3fa2_remove,
+	.driver = {
+		.name = "panel-samsung-s6e3fa2",
+		.of_match_table = samsung_s6e3fa2_of_match,
+	},
+};
+module_mipi_dsi_driver(samsung_s6e3fa2_driver);
+
+MODULE_AUTHOR("Alexey Minnekhanov <alexeymin@postmarketos.org>");
+MODULE_DESCRIPTION("DRM driver for Samsung S6E3FA2 DSI panel");
+MODULE_LICENSE("GPL v2");
-- 
2.31.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver
       [not found]   ` <YP184rqayPLbWLx4@ravnborg.org>
@ 2021-07-26  7:44     ` Linus Walleij
  0 siblings, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2021-07-26  7:44 UTC (permalink / raw)
  To: Sam Ravnborg
  Cc: Alexey Minnekhanov, Thierry Reding, David Airlie, Daniel Vetter,
	open list, open list:DRM PANEL DRIVERS,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
	<devicetree@vger.kernel.org>,
	Hans de Goede <hdegoede@redhat.com>,
	Andy Shevchenko <andy.shevchenko@gmail.com>,,
	phone-devel

 On Sun, Jul 25, 2021 at 5:01 PM Sam Ravnborg <sam@ravnborg.org> wrote:

> This driver supports two different panels:
>
>         S6E3FA2
>         EA8064G
>
> They differ on a lot of the tables and requires different init.
> In other words there is only a little boiler plate code that is in
> common.
>
> I think it would be much cleaner with individual drivers for each panel.

Sometimes Samsung have different *physical* panels connected
to the same display controller, but I don't know what is the case
here. This looks like it could actually be two different display
controllers. (I don't like these opaque binary drops from Samsung,
datasheets would be nice...)

What I think is most intuitive is to have one driver per display controller.
If the two drivers are writing some very similar registers with very
similar values they are probably the same display controller.

If they are not then they are not...

If they are obviously the same display controller I think parameterizing
a display controller driver along the line of panel-novatek-nt35510.c
is the best. If different display controllers, we need different drivers.

> Which brings me to next topic - this is two different panels and the DT
> are supports to describe the HW - so the DT tree should have different
> entries depending on the actual panel. As it is now you try to hide the
> fact that one compatible describes two different panels.

(...)
> > +     ret = s6e3fa2_dsi_dcs_read1(dsi, MCS_READ_ID1, &id1);
> > +     if (ret < 0)
> > +             return ret;
> > +     ret = s6e3fa2_dsi_dcs_read1(dsi, MCS_READ_ID2, &id2);
> > +     if (ret < 0)
> > +             return ret;
> > +     ret = s6e3fa2_dsi_dcs_read1(dsi, MCS_READ_ID3, &id3);
> > +     if (ret < 0)
> > +             return ret;
> > +
> > +     lcd_id = id1 << 16 | id2 << 8 | id3;
> > +
> > +     switch (lcd_id) {
> > +     case LCD_ID_S6E3FA2:
> > +             dev_info(&dsi->dev, "detected S6E3FA2 panel (ID: 0x%x)\n",
> > +                      lcd_id);
> > +             ctx->subtype = PANEL_S6E3FA2;
> > +             ctx->seq_data = &seqdata_s6e3fa2;
> > +             break;
> > +     case LCD_ID_EA8064G:
> > +             dev_info(&dsi->dev, "detected EA8064G panel (ID: 0x%x)\n",
> > +                      lcd_id);
> > +             ctx->subtype = PANEL_EA8064G;
> > +             ctx->seq_data = &seqdata_ea8064g;
> > +             break;
> > +     default:
> > +             dev_warn(&dsi->dev, "unsupported panel ID: 0x%x\n", lcd_id);
> > +             ctx->subtype = PANEL_UNKNOWN;

This does look like two different panels, I'd like to know the MTP
IDs printed (also wrote in different mail). The MTP print I think
should be kept.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel
  2021-07-25 14:03 [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Alexey Minnekhanov
  2021-07-25 14:03 ` [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver Alexey Minnekhanov
@ 2021-07-26  7:51 ` Linus Walleij
  2021-07-29 22:30   ` Rob Herring
  2021-07-29 22:31 ` Rob Herring
  2 siblings, 1 reply; 7+ messages in thread
From: Linus Walleij @ 2021-07-26  7:51 UTC (permalink / raw)
  To: Alexey Minnekhanov
  Cc: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter,
	Rob Herring, open list:DRM PANEL DRIVERS,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
	<devicetree@vger.kernel.org>,
	Hans de Goede <hdegoede@redhat.com>,
	Andy Shevchenko <andy.shevchenko@gmail.com>,,
	phone-devel

On Sun, Jul 25, 2021 at 4:04 PM Alexey Minnekhanov
<alexeymin@postmarketos.org> wrote:

> The Samsung S6E3FA2 AMOLED cmd LCD panel is used on Samsung Galaxy
> S5 (klte) phone.
>
> Signed-off-by: Alexey Minnekhanov <alexeymin@postmarketos.org>

Grr gmail put this in my spam folder, sorry for confused mails.

With Sam's comments addressed:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver
  2021-07-25 14:03 ` [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver Alexey Minnekhanov
       [not found]   ` <YP184rqayPLbWLx4@ravnborg.org>
@ 2021-07-26  8:04   ` Linus Walleij
  1 sibling, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2021-07-26  8:04 UTC (permalink / raw)
  To: Alexey Minnekhanov
  Cc: Thierry Reding, Sam Ravnborg, David Airlie, Daniel Vetter,
	open list, open list:DRM PANEL DRIVERS,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
	<devicetree@vger.kernel.org>,
	Hans de Goede <hdegoede@redhat.com>,
	Andy Shevchenko <andy.shevchenko@gmail.com>,,
	phone-devel

Hi Alexey,

I had some gmail problems and replied to the very old driver
by Iskren, sorry for the mess.

I overall like this driver a lot. Some of Sam's comments could
be addressed especially for backlight.

I think the driver should indeed handle both the physical
displays like you do here.

On Sun, Jul 25, 2021 at 4:05 PM Alexey Minnekhanov
<alexeymin@postmarketos.org> wrote:

> Samsung S6E3FA2 panel is amoled 1080x1920 command mode DSI
> panel used in Samsung Galaxy S5 phone. There are 2 known
> variations of panel that were shipped in this phone, and
> this driver handles both of them.
>
> Panel has built-in backlight (like all other AMOLED panels),
> controlled over DSI by some vendor specific commands, some
> of them include sending long byte sequences of what seems
> to be called "smart dimming".
>
> Signed-off-by: Alexey Minnekhanov <alexeymin@postmarketos.org>

(...)

> +#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)

These look generic as pointed out in other mail.

> +static int s6e3fa2_dsi_dcs_read1(struct mipi_dsi_device *dsi, const u8 cmd,
> +                               u8 *data)
> +{
> +       int ret;
> +
> +       ret = mipi_dsi_dcs_read(dsi, cmd, data, 1);
> +       if (ret < 0) {
> +               dev_err(&dsi->dev, "could not read DCS CMD %02x\n", cmd);
> +               return ret;
> +       }
> +       return 0;
> +}

I don't think this needs a wrapper, just call mipi_dsi_dcs_read() directly.

> +/* Panel variants */
> +#define LCD_ID_S6E3FA2         0x602813
> +#define LCD_ID_EA8064G         0x622872

Interesting use of the "vendor" byte by Samsung here. It seems they are
repurposing the non-standard MTP bytes as they seem fit.

> +/*
> + * Which AID sequence to use for each candela level.
> + * This lookup table is same for both panels.
> + */
> +static const u8 map_candela_to_aid[S6E3FA2_NUM_GAMMA_LEVELS] = {
> +        0,  2,  3,  4,  6,  7,  8, 10, 11, 13, 14, 15,
> +       16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28,
> +       29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36,
> +       36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 38,
> +       39, 40, 41, 42, 43, 44, 44, 44, 44, 44, 44, 44
> +};

This and other things hints that we are dealing with the same display
controller.

> +/* Other panel drivers call these commands test_key_enable/disable */
> +static const u8 seq_s6e3fa2_test_key_en[6] = {
> +       0xf0, 0x5a, 0x5a,
> +       0xfc, 0x5a, 0x5a
> +};

0xf0 and 0xfc is obviously some "level 2 unlock" commands.
Maybe #define them as pointed out in other comments.

> +static const u8 seq_s6e3fa2_test_key_dis[6] = {
> +       0xf0, 0xa5, 0xa5,
> +       0xfc, 0xa5, 0xa5
> +};
> +static const u8 seq_ea8064g_test_key_en[6] = {
> +       0xf0, 0x5a, 0x5a,
> +       0xf1, 0x5a, 0x5a
> +};
> +static const u8 seq_ea8064g_test_key_dis[6] = {
> +       0xf1, 0xa5, 0xa5,
> +       0xf0, 0xa5, 0xa5
> +};

The use of two different registers for locking is suspicious, that
may point to different display controllers. :/

This is an icky panel, but it seems they are close enough to
be handled by the same driver IMO.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel
  2021-07-26  7:51 ` [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Linus Walleij
@ 2021-07-29 22:30   ` Rob Herring
  0 siblings, 0 replies; 7+ messages in thread
From: Rob Herring @ 2021-07-29 22:30 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Alexey Minnekhanov, Thierry Reding, Sam Ravnborg, David Airlie,
	Daniel Vetter, open list:DRM PANEL DRIVERS,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
	<devicetree@vger.kernel.org>,
	Hans de Goede <hdegoede@redhat.com>,
	Andy Shevchenko <andy.shevchenko@gmail.com>,,
	phone-devel

On Mon, Jul 26, 2021 at 09:51:40AM +0200, Linus Walleij wrote:
> On Sun, Jul 25, 2021 at 4:04 PM Alexey Minnekhanov
> <alexeymin@postmarketos.org> wrote:
> 
> > The Samsung S6E3FA2 AMOLED cmd LCD panel is used on Samsung Galaxy
> > S5 (klte) phone.
> >
> > Signed-off-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
> 
> Grr gmail put this in my spam folder, sorry for confused mails.
> 
> With Sam's comments addressed:

What comments? Sam's mails seem to have problems getting to the lists.

Rob

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel
  2021-07-25 14:03 [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Alexey Minnekhanov
  2021-07-25 14:03 ` [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver Alexey Minnekhanov
  2021-07-26  7:51 ` [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Linus Walleij
@ 2021-07-29 22:31 ` Rob Herring
  2 siblings, 0 replies; 7+ messages in thread
From: Rob Herring @ 2021-07-29 22:31 UTC (permalink / raw)
  To: Alexey Minnekhanov
  Cc: Daniel Vetter, linux-kernel, Rob Herring, David Airlie,
	~postmarketos/upstreaming, Sam Ravnborg, devicetree,
	Thierry Reding, phone-devel, dri-devel, Linus Walleij

On Sun, 25 Jul 2021 17:03:37 +0300, Alexey Minnekhanov wrote:
> The Samsung S6E3FA2 AMOLED cmd LCD panel is used on Samsung Galaxy
> S5 (klte) phone.
> 
> Signed-off-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
> ---
>  .../display/panel/samsung,s6e3fa2.yaml        | 63 +++++++++++++++++++
>  1 file changed, 63 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3fa2.yaml
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-07-29 22:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-25 14:03 [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Alexey Minnekhanov
2021-07-25 14:03 ` [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver Alexey Minnekhanov
     [not found]   ` <YP184rqayPLbWLx4@ravnborg.org>
2021-07-26  7:44     ` Linus Walleij
2021-07-26  8:04   ` Linus Walleij
2021-07-26  7:51 ` [PATCH 1/2] dt-bindings: panel: Add Samsung S6E3FA2 panel Linus Walleij
2021-07-29 22:30   ` Rob Herring
2021-07-29 22:31 ` Rob Herring

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).