[PATCH 2/2] drm/panel: Add Samsung S6E3FA2 DSI panel driver

Sam Ravnborg sam at ravnborg.org
Sun Jul 25 15:01:54 UTC 2021


Hi Alexey,

On Sun, Jul 25, 2021 at 05:03:38PM +0300, Alexey Minnekhanov 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 at postmarketos.org>

General comment - the driver looks neat and clean. There is next to no
style thing and everything (expect backlight) seems to use latest
interfaces.

Please please run "checkpatch --strict" and fix the few
relevant warnings - I spotted a few but they are indeed minor.


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.

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.

Some comments in the following also - but the important points are the
above.

	Sam


> ---
>  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
I recommends to avoid these helpers. They are optional and no need
to pull them in.

> +	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 at 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;
Use panel.backlight.
We are about to fix the comment that discourage this.

And then you will also have the drm_panel core helping you calling
enable/disable.

> +	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;
Use backligt_get_brighthness(bldev) here.


> +	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)
This function does more than check_... It configures the panel type.

> +{
> +	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;

If the panel is not known this should fail I think.

> +		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);
Let drm_panel handle this - it comes for free when you use
drm_panel.backlight.

> +
> +	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);
Likewise.

> +
> +	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 at postmarketos.org>");
> +MODULE_DESCRIPTION("DRM driver for Samsung S6E3FA2 DSI panel");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.31.1


More information about the dri-devel mailing list