[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210725140339.2465677-2-alexeymin@postmarketos.org>
Date: Sun, 25 Jul 2021 17:03:38 +0300
From: Alexey Minnekhanov <alexeymin@...tmarketos.org>
To: Thierry Reding <thierry.reding@...il.com>,
Sam Ravnborg <sam@...nborg.org>,
David Airlie <airlied@...ux.ie>,
Daniel Vetter <daniel@...ll.ch>,
linux-kernel@...r.kernel.org (open list),
dri-devel@...ts.freedesktop.org (open list:DRM PANEL DRIVERS)
Cc: ~postmarketos/upstreaming@...ts.sr.ht, phone-devel@...r.kernel.org,
Linus Walleij <linus.walleij@...aro.org>,
Alexey Minnekhanov <alexeymin@...tmarketos.org>
Subject: [PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver
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@...tmarketos.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@...tmarketos.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@...tmarketos.org>");
+MODULE_DESCRIPTION("DRM driver for Samsung S6E3FA2 DSI panel");
+MODULE_LICENSE("GPL v2");
--
2.31.1
Powered by blists - more mailing lists