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

Hyungwon Hwang human.hwang at samsung.com
Sun Jun 28 20:50:26 PDT 2015


Dear Theirry,

Gentle ping. I modified as you reviewed before. Also I wrote the
reason for using passing variable by reference for error checking. Can
you share your opinion for that, and review this driver?

Best regards,
Hyungwon Hwang

On Fri, 29 May 2015 18:47:02 +0900
Hyungwon Hwang <hyungwon.hwang7 at gmail.com> wrote:
> 
> This patch adds MIPI-DSI based S6E3HA2 panel driver. This panel has
> 1440x2560 resolution in 5.7-inch physical panel.
> 
> Signed-off-by: Donghwa Lee <dh09.lee at samsung.com>
> Signed-off-by: Hyungwon Hwang <human.hwang at samsung.com>
> Cc: Inki Dae <inki.dae at samsung.com>
> ---
> As Thierry Reding said in https://patchwork.kernel.org/patch/5714111/,
> it can be confusing to check the result of a function call using a
> variable which is not explicitly passed to function call. At the same
> time, as Andrzej Hajda said, checking the result using the return
> value in this driver makes the code too bloated. In the situation
> where many simple function calls and the result checking for them are
> needed, I thought that passing variable by reference with explicit
> variable is the best.
> 
> Changes for v2:
> - Fix errata in documentation and source code comments
> Changes for v3:
> - Remove the term LCD to clarify the sort of this panel
> - Rename lcd-en-gpios to panel-en-gpios to clarify the sort of this
> panel
> - Fix errata in documentation and source code comments
> Changes for v4:
> - Add support for brightness control
> - Adjust the sequence of turning on/off
> - Rename variable and properties for clarity
>  .../devicetree/bindings/panel/samsung,s6e3ha2.txt  |  40 +
>  drivers/gpu/drm/panel/Kconfig                      |  11 +
>  drivers/gpu/drm/panel/Makefile                     |   1 +
>  drivers/gpu/drm/panel/panel-s6e3ha2.c              | 904
> +++++++++++++++++++++
>  4 files changed, 956 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
>  create mode 100644 drivers/gpu/drm/panel/panel-s6e3ha2.c
> 
> diff --git
> a/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
> b/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt new
> file mode 100644 index 0000000..b8cacc0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
> @@ -0,0 +1,40 @@
> +Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel
> +
> +Required properties:
> +  - compatible: "samsung,s6e3ha2"
> +  - reg: virtual channel number assigned to the panel
> +  - vdd3-supply: core voltage supply
> +  - vci-supply: voltage supply for analog circuits
> +  - reset-gpio: GPIO spec for resetting
> +  - enable-gpio: GPIO spec for enabling
> +  - te-gpio: GPIO spec for receiving tearing effect synchronization
> signal
> +  - display-timings: resolution, clock, timing information for the
> panel [1]
> +
> +[1]: Documentation/devicetree/bindings/video/display-timing.txt
> +
> +Example:
> +
> +panel at 0 {
> +       compatible = "samsung,s6e3ha2";
> +       reg = <0>;
> +       vdd3-supply = <&ldo27_reg>;
> +       vci-supply = <&ldo28_reg>;
> +       reset-gpio = <&gpg0 0 GPIO_ACTIVE_LOW>;
> +       enable-gpio = <&gpf1 5 GPIO_ACTIVE_HIGH>;
> +       te-gpio = <&gpf1 3 GPIO_ACTIVE_LOW>;
> +
> +       display-timings {
> +               timing-0 {
> +                       clock-frequency = <0>;
> +                       hactive = <1440>;
> +                       vactive = <2560>;
> +                       hfront-porch = <1>;
> +                       hback-porch = <1>;
> +                       hsync-len = <1>;
> +                       vfront-porch = <1>;
> +                       vback-porch = <15>;
> +                       vsync-len = <1>;
> +               };
> +       };
> +};
> +
> diff --git a/drivers/gpu/drm/panel/Kconfig
> b/drivers/gpu/drm/panel/Kconfig index 6d64c7b..7833073 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -43,4 +43,15 @@ config DRM_PANEL_SHARP_LQ101R1SX01
>           To compile this driver as a module, choose M here: the
> module will be called panel-sharp-lq101r1sx01.
> 
> +config DRM_PANEL_S6E3HA2
> +       tristate "S6E3HA2 DSI command mode panel"
> +       depends on OF
> +       depends on BACKLIGHT_CLASS_DEVICE
> +       depends on DRM_MIPI_DSI
> +       select VIDEOMODE_HELPERS
> +         Say Y here if you want to enable support for Samsung S6E3HA2
> +         AMOLED panel module. This panel has a 1440x2560 resolution
> and
> +         uses 32-bit RGB per pixel. It provides a 4 lane MIPI DSI
> interface
> +         to the host.
> +
>  endmenu
> diff --git a/drivers/gpu/drm/panel/Makefile
> b/drivers/gpu/drm/panel/Makefile index 4b2a043..16ff312 100644
> --- a/drivers/gpu/drm/panel/Makefile
> +++ b/drivers/gpu/drm/panel/Makefile
> @@ -2,3 +2,4 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
>  obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o
>  obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o
>  obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) +=
> panel-sharp-lq101r1sx01.o +obj-$(CONFIG_DRM_PANEL_S6E3HA2) +=
> panel-s6e3ha2.o diff --git a/drivers/gpu/drm/panel/panel-s6e3ha2.c
> b/drivers/gpu/drm/panel/panel-s6e3ha2.c
> new file mode 100644
> index 0000000..8cf5b7e
> --- /dev/null
> +++ b/drivers/gpu/drm/panel/panel-s6e3ha2.c
> @@ -0,0 +1,904 @@
> +/*
> + * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver.
> + *
> + * Copyright (c) 2014 Samsung Electronics Co., Ltd
> + *
> + * Donghwa Lee <dh09.lee at samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or
> modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_mipi_dsi.h>
> +#include <drm/drm_panel.h>
> +
> +#include <linux/of_gpio.h>
> +#include <linux/gpio.h>
> +
> +#include <linux/gpio/consumer.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include <video/mipi_display.h>
> +#include <video/of_videomode.h>
> +#include <video/videomode.h>
> +#include <linux/backlight.h>
> +
> +#define MIN_BRIGHTNESS         0
> +#define MAX_BRIGHTNESS         100
> +#define DEFAULT_BRIGHTNESS     80
> +
> +#define MIN_GAMMA              2
> +#define MAX_GAMMA              350
> +#define NUM_GAMMA_STEPS                66
> +#define GAMMA_CMD_CNT          35
> +#define VINT_STATUS_MAX                10
> +
> +static const u8 AOR_TBL[NUM_GAMMA_STEPS][2] = {
> +       { 0xe5, 0x90 }, { 0xcc, 0x90 }, { 0xb6, 0x90 }, { 0xa3,
> 0x90 },
> +       { 0x8e, 0x90 }, { 0x79, 0x90 }, { 0x66, 0x90 }, { 0x57,
> 0x90 },
> +       { 0x44, 0x90 }, { 0x35, 0x90 }, { 0x25, 0x90 }, { 0x14,
> 0x90 },
> +       { 0x05, 0x90 }, { 0xeb, 0x80 }, { 0xe0, 0x80 }, { 0xc7,
> 0x80 },
> +       { 0xa4, 0x80 }, { 0x92, 0x80 }, { 0x7b, 0x80 }, { 0x67,
> 0x80 },
> +       { 0x43, 0x80 }, { 0x2f, 0x80 }, { 0xfd, 0x70 }, { 0xdf,
> 0x70 },
> +       { 0xc7, 0x70 }, { 0xa4, 0x70 }, { 0x6f, 0x70 }, { 0x3d,
> 0x70 },
> +       { 0x14, 0x70 }, { 0xee, 0x60 }, { 0xb2, 0x60 }, { 0x73,
> 0x60 },
> +       { 0x34, 0x60 }, { 0xf4, 0x50 }, { 0xb5, 0x50 }, { 0x5f,
> 0x50 },
> +       { 0x0e, 0x50 }, { 0xb4, 0x40 }, { 0x62, 0x40 }, { 0xed,
> 0x30 },
> +       { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed,
> 0x30 },
> +       { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed,
> 0x30 },
> +       { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed, 0x30 }, { 0xed,
> 0x30 },
> +       { 0xed, 0x30 }, { 0xa7, 0x30 }, { 0x26, 0x30 }, { 0xb5,
> 0x20 },
> +       { 0x26, 0x20 }, { 0x8f, 0x10 }, { 0x03, 0x10 }, { 0x03,
> 0x10 },
> +       { 0x03, 0x10 }, { 0x03, 0x10 }, { 0x03, 0x10 }, { 0x03,
> 0x10 },
> +       { 0x03, 0x10 }, { 0x03, 0x10 },
> +};
> +
> +static const u8 GAMMA_TBL[NUM_GAMMA_STEPS][GAMMA_CMD_CNT] = {
> +       { 0x00, 0xb5, 0x00, 0xc7, 0x00, 0xb1, 0x8c, 0x8c, 0x8b, 0x86,
> 0x8a,
> +         0x8a, 0x86, 0x92, 0x8e, 0x81, 0x97, 0x87, 0x96, 0x9b, 0x98,
> 0x9d,
> +         0x9d, 0x8f, 0xb5, 0x99, 0x8d, 0x5c, 0x51, 0x66, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb5, 0x00, 0xc6, 0x00, 0xb0, 0x8a, 0x89, 0x8a, 0x83,
> 0x88,
> +         0x88, 0x88, 0x93, 0x8e, 0x74, 0x8d, 0x7d, 0x9b, 0x9d, 0x9c,
> 0x9a,
> +         0x9d, 0x90, 0xc7, 0xaa, 0x9e, 0x59, 0x4d, 0x63, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc7, 0x00, 0xb2, 0x89, 0x88, 0x89, 0x85,
> 0x89,
> +         0x89, 0x88, 0x91, 0x8c, 0x81, 0x92, 0x89, 0x89, 0x96, 0x8f,
> 0x93,
> +         0x9c, 0x8b, 0xbe, 0xad, 0x9a, 0xce, 0xaa, 0xc2, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc6, 0x00, 0xb2, 0x88, 0x89, 0x88, 0x84,
> 0x88,
> +         0x88, 0x88, 0x90, 0x8c, 0x82, 0x90, 0x8a, 0x86, 0x93, 0x8c,
> 0x91,
> +         0x9b, 0x8d, 0xbc, 0xac, 0x99, 0xd3, 0xaf, 0xc7, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb6, 0x00, 0xc4, 0x00, 0xaf, 0x89, 0x88, 0x88, 0x84,
> 0x88,
> +         0x88, 0x87, 0x8e, 0x8a, 0x83, 0x90, 0x8a, 0x86, 0x93, 0x8c,
> 0x91,
> +         0x9a, 0x8c, 0xbb, 0xae, 0x98, 0xd6, 0xb2, 0xca, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb7, 0x00, 0xc4, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84,
> 0x88,
> +         0x88, 0x87, 0x8e, 0x8a, 0x85, 0x90, 0x88, 0x85, 0x91, 0x8a,
> 0x94,
> +         0x9b, 0x8e, 0xb5, 0xb0, 0x95, 0xda, 0xb5, 0xcd, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x87, 0x88, 0x87, 0x85,
> 0x88,
> +         0x89, 0x87, 0x8e, 0x8a, 0x86, 0x8f, 0x88, 0x84, 0x91, 0x89,
> 0x92,
> +         0x99, 0x8d, 0xb5, 0xb0, 0x93, 0xd2, 0xaf, 0xc8, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x88, 0x88, 0x87, 0x84,
> 0x87,
> +         0x88, 0x87, 0x8e, 0x8b, 0x87, 0x91, 0x88, 0x86, 0x90, 0x89,
> 0x8f,
> +         0x99, 0x8a, 0xb4, 0xb0, 0x93, 0xcd, 0xab, 0xc5, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84,
> 0x87,
> +         0x88, 0x87, 0x8e, 0x8b, 0x83, 0x8d, 0x84, 0x88, 0x91, 0x8a,
> 0x8f,
> +         0x98, 0x8a, 0xb4, 0xb0, 0x93, 0xdb, 0xb7, 0xcf, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84,
> 0x87,
> +         0x88, 0x88, 0x8d, 0x8a, 0x85, 0x8e, 0x85, 0x85, 0x8e, 0x88,
> 0x92,
> +         0x9a, 0x8c, 0xb2, 0xb0, 0x90, 0xc9, 0xa7, 0xc3, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x89, 0x88, 0x88, 0x84,
> 0x86,
> +         0x87, 0x89, 0x8d, 0x8b, 0x85, 0x8e, 0x85, 0x87, 0x8e, 0x89,
> 0x8f,
> +         0x98, 0x8a, 0xb2, 0xb0, 0x91, 0xd2, 0xaf, 0xca, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb0, 0x88, 0x87, 0x87, 0x84,
> 0x86,
> +         0x87, 0x88, 0x8c, 0x8a, 0x86, 0x8f, 0x86, 0x87, 0x8e, 0x89,
> 0x8e,
> +         0x97, 0x88, 0xb1, 0xb1, 0x90, 0xd2, 0xaf, 0xca, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x85,
> +         0x86, 0x88, 0x8c, 0x89, 0x85, 0x8d, 0x85, 0x88, 0x8d, 0x8a,
> 0x8f,
> +         0x9a, 0x87, 0xb3, 0xb1, 0x90, 0xd7, 0xb3, 0xcd, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84,
> 0x86,
> +         0x87, 0x88, 0x8c, 0x8a, 0x85, 0x8c, 0x84, 0x88, 0x8d, 0x8a,
> 0x8c,
> +         0x96, 0x85, 0xb2, 0xb0, 0x92, 0xcc, 0xaa, 0xc6, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x85,
> +         0x86, 0x88, 0x8c, 0x89, 0x84, 0x8b, 0x83, 0x87, 0x8d, 0x8a,
> 0x8d,
> +         0x96, 0x87, 0xb2, 0xb2, 0x8f, 0xd6, 0xb3, 0xcd, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x84,
> +         0x85, 0x88, 0x8c, 0x89, 0x84, 0x8b, 0x84, 0x87, 0x8d, 0x8a,
> 0x8b,
> +         0x94, 0x84, 0xb3, 0xb1, 0x92, 0xc5, 0xa5, 0xc1, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x84,
> +         0x85, 0x88, 0x8c, 0x89, 0x82, 0x89, 0x82, 0x86, 0x8c, 0x88,
> 0x8b,
> +         0x94, 0x84, 0xb6, 0xb2, 0x91, 0xd0, 0xae, 0xc9, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x84,
> +         0x85, 0x87, 0x8b, 0x89, 0x83, 0x8a, 0x83, 0x85, 0x8b, 0x87,
> 0x8b,
> +         0x95, 0x85, 0xb4, 0xae, 0x8e, 0xbf, 0x9f, 0xbd, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x84,
> +         0x84, 0x87, 0x8b, 0x8a, 0x84, 0x8a, 0x83, 0x83, 0x89, 0x85,
> 0x8e,
> +         0x97, 0x8a, 0xaf, 0xac, 0x8d, 0xb9, 0x9b, 0xb9, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x84,
> +         0x84, 0x87, 0x8b, 0x8a, 0x82, 0x88, 0x82, 0x85, 0x8c, 0x88,
> 0x8c,
> +         0x94, 0x87, 0xb1, 0xaf, 0x8f, 0xc4, 0xa4, 0xc1, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x82,
> 0x83,
> +         0x85, 0x88, 0x8b, 0x8b, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86,
> 0x8c,
> +         0x94, 0x84, 0xb1, 0xaf, 0x8e, 0xcf, 0xad, 0xc9, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84,
> 0x84,
> +         0x85, 0x87, 0x8b, 0x8a, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86,
> 0x8a,
> +         0x93, 0x84, 0xb0, 0xae, 0x8e, 0xc9, 0xa8, 0xc5, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x8a, 0x8a, 0x84, 0x88, 0x81, 0x84, 0x8a, 0x88,
> 0x8a,
> +         0x91, 0x84, 0xb1, 0xae, 0x8b, 0xd5, 0xb2, 0xcc, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x8a, 0x8a, 0x84, 0x87, 0x81, 0x84, 0x8a, 0x87,
> 0x8a,
> +         0x91, 0x85, 0xae, 0xac, 0x8a, 0xc3, 0xa3, 0xc0, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x85,
> 0x85,
> +         0x86, 0x85, 0x88, 0x89, 0x84, 0x89, 0x82, 0x84, 0x87, 0x85,
> 0x8b,
> +         0x91, 0x88, 0xad, 0xab, 0x8a, 0xb7, 0x9b, 0xb6, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x89, 0x8a, 0x84, 0x89, 0x83, 0x83, 0x86, 0x84,
> 0x8b,
> +         0x90, 0x84, 0xb0, 0xae, 0x8b, 0xce, 0xad, 0xc8, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x83,
> +         0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87,
> 0x89,
> +         0x8f, 0x84, 0xac, 0xaa, 0x89, 0xb1, 0x98, 0xaf, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x88, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84,
> 0x8c,
> +         0x91, 0x86, 0xac, 0xaa, 0x89, 0xc2, 0xa5, 0xbd, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87,
> 0x88,
> +         0x8b, 0x82, 0xad, 0xaa, 0x8a, 0xc2, 0xa5, 0xbd, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84,
> 0x8a,
> +         0x8e, 0x84, 0xae, 0xac, 0x89, 0xda, 0xb7, 0xd0, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x80, 0x83, 0x82,
> 0x8b,
> +         0x8e, 0x85, 0xac, 0xaa, 0x89, 0xc8, 0xaa, 0xc1, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x85, 0x86, 0x87, 0x89, 0x81, 0x85, 0x81, 0x84, 0x86, 0x84,
> 0x8c,
> +         0x8c, 0x84, 0xa9, 0xa8, 0x87, 0xa3, 0x92, 0xa1, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x85, 0x86, 0x87, 0x89, 0x84, 0x86, 0x83, 0x80, 0x83, 0x81,
> 0x8c,
> +         0x8d, 0x84, 0xaa, 0xaa, 0x89, 0xce, 0xaf, 0xc5, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x85, 0x86, 0x87, 0x89, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85,
> 0x8c,
> +         0x8c, 0x84, 0xa8, 0xa8, 0x88, 0xb5, 0x9f, 0xb0, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85,
> 0x8c,
> +         0x8b, 0x84, 0xab, 0xa8, 0x86, 0xd4, 0xb4, 0xc9, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x84, 0x84, 0x85,
> 0x8b,
> +         0x8a, 0x83, 0xa6, 0xa5, 0x84, 0xbb, 0xa4, 0xb3, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84,
> 0x84,
> +         0x86, 0x85, 0x86, 0x86, 0x82, 0x85, 0x81, 0x82, 0x83, 0x84,
> 0x8e,
> +         0x8b, 0x83, 0xa4, 0xa3, 0x8a, 0xa1, 0x93, 0x9d, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84,
> 0x8e,
> +         0x8b, 0x83, 0xa4, 0xa2, 0x86, 0xc1, 0xa9, 0xb7, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84,
> 0x8d,
> +         0x89, 0x82, 0xa2, 0xa1, 0x84, 0xa7, 0x98, 0xa1, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83,
> 0x83,
> +         0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x83, 0x83, 0x85,
> 0x8c,
> +         0x87, 0x7f, 0xa2, 0x9d, 0x88, 0x8d, 0x88, 0x8b, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xbb, 0x00, 0xc5, 0x00, 0xb4, 0x87, 0x86, 0x86, 0x84,
> 0x83,
> +         0x86, 0x87, 0x87, 0x87, 0x80, 0x82, 0x7f, 0x86, 0x86, 0x88,
> 0x8a,
> +         0x84, 0x7e, 0x9d, 0x9c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xbd, 0x00, 0xc7, 0x00, 0xb7, 0x87, 0x85, 0x85, 0x84,
> 0x83,
> +         0x86, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x83, 0x84, 0x85,
> 0x8a,
> +         0x85, 0x7e, 0x9c, 0x9b, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xc0, 0x00, 0xca, 0x00, 0xbb, 0x87, 0x86, 0x85, 0x83,
> 0x83,
> +         0x85, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x84, 0x85, 0x86,
> 0x89,
> +         0x83, 0x7d, 0x9c, 0x99, 0x87, 0x7b, 0x7b, 0x7c, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xc4, 0x00, 0xcd, 0x00, 0xbe, 0x87, 0x86, 0x85, 0x83,
> 0x83,
> +         0x86, 0x85, 0x85, 0x87, 0x81, 0x82, 0x80, 0x82, 0x82, 0x83,
> 0x8a,
> +         0x85, 0x7f, 0x9f, 0x9b, 0x86, 0xb4, 0xa1, 0xac, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xc7, 0x00, 0xd0, 0x00, 0xc2, 0x87, 0x85, 0x85, 0x83,
> 0x82,
> +         0x85, 0x85, 0x85, 0x86, 0x82, 0x83, 0x80, 0x82, 0x82, 0x84,
> 0x87,
> +         0x86, 0x80, 0x9e, 0x9a, 0x87, 0xa7, 0x98, 0xa1, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xca, 0x00, 0xd2, 0x00, 0xc5, 0x87, 0x85, 0x84, 0x82,
> 0x82,
> +         0x84, 0x85, 0x85, 0x86, 0x81, 0x82, 0x7f, 0x82, 0x82, 0x84,
> 0x88,
> +         0x86, 0x81, 0x9d, 0x98, 0x86, 0x8d, 0x88, 0x8b, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xce, 0x00, 0xd6, 0x00, 0xca, 0x86, 0x85, 0x84, 0x83,
> 0x83,
> +         0x85, 0x84, 0x84, 0x85, 0x81, 0x82, 0x80, 0x81, 0x81, 0x82,
> 0x89,
> +         0x86, 0x81, 0x9c, 0x97, 0x86, 0xa7, 0x98, 0xa1, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xd1, 0x00, 0xd9, 0x00, 0xce, 0x86, 0x84, 0x83, 0x83,
> 0x82,
> +         0x85, 0x85, 0x85, 0x86, 0x81, 0x83, 0x81, 0x82, 0x82, 0x83,
> 0x86,
> +         0x83, 0x7f, 0x99, 0x95, 0x86, 0xbb, 0xa4, 0xb3, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xd4, 0x00, 0xdb, 0x00, 0xd1, 0x86, 0x85, 0x83, 0x83,
> 0x82,
> +         0x85, 0x84, 0x84, 0x85, 0x80, 0x83, 0x82, 0x80, 0x80, 0x81,
> 0x87,
> +         0x84, 0x81, 0x98, 0x93, 0x85, 0xae, 0x9c, 0xa8, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xd8, 0x00, 0xde, 0x00, 0xd6, 0x86, 0x84, 0x83, 0x81,
> 0x81,
> +         0x83, 0x85, 0x85, 0x85, 0x82, 0x83, 0x81, 0x81, 0x81, 0x83,
> 0x86,
> +         0x84, 0x80, 0x98, 0x91, 0x85, 0x7b, 0x7b, 0x7c, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xda, 0x85, 0x84, 0x83, 0x82,
> 0x82,
> +         0x84, 0x84, 0x84, 0x85, 0x81, 0x82, 0x82, 0x80, 0x80, 0x81,
> 0x83,
> +         0x82, 0x7f, 0x99, 0x93, 0x86, 0x94, 0x8b, 0x92, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xde, 0x85, 0x84, 0x82, 0x82,
> 0x82,
> +         0x84, 0x83, 0x83, 0x84, 0x81, 0x81, 0x80, 0x83, 0x82, 0x84,
> 0x82,
> +         0x81, 0x7f, 0x99, 0x92, 0x86, 0x7b, 0x7b, 0x7c, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81,
> 0x81,
> +         0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x83, 0x83, 0x84,
> 0x80,
> +         0x81, 0x7c, 0x99, 0x92, 0x87, 0xa1, 0x93, 0x9d, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x85, 0x84, 0x83, 0x81,
> 0x81,
> +         0x82, 0x82, 0x82, 0x83, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82,
> 0x83,
> +         0x82, 0x80, 0x91, 0x8d, 0x83, 0x9a, 0x90, 0x96, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81,
> 0x81,
> +         0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82,
> 0x83,
> +         0x81, 0x7f, 0x91, 0x8c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81,
> 0x81,
> +         0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82,
> 0x82,
> +         0x82, 0x7f, 0x94, 0x89, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81,
> 0x81,
> +         0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82,
> 0x83,
> +         0x82, 0x7f, 0x91, 0x85, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81,
> 0x81,
> +         0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x83, 0x82, 0x84,
> 0x83,
> +         0x82, 0x7f, 0x90, 0x84, 0x81, 0x9a, 0x90, 0x96, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x80,
> 0x80,
> +         0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81,
> 0x81,
> +         0x82, 0x83, 0x7e, 0x80, 0x7c, 0xa4, 0x97, 0x9f, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xe9, 0x00, 0xec, 0x00, 0xe8, 0x84, 0x83, 0x82, 0x81,
> 0x81,
> +         0x82, 0x82, 0x82, 0x83, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82,
> 0x83,
> +         0x83, 0x84, 0x79, 0x7c, 0x79, 0xb1, 0xa0, 0xaa, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xed, 0x00, 0xf0, 0x00, 0xec, 0x83, 0x83, 0x82, 0x80,
> 0x80,
> +         0x81, 0x82, 0x82, 0x82, 0x7f, 0x7f, 0x7e, 0x81, 0x81, 0x82,
> 0x80,
> +         0x81, 0x81, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xf1, 0x83, 0x82, 0x82, 0x80,
> 0x80,
> +         0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81,
> 0x7d,
> +         0x7e, 0x7f, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xf6, 0x00, 0xf7, 0x00, 0xf5, 0x82, 0x82, 0x81, 0x80,
> 0x80,
> +         0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f,
> 0x82,
> +         0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfa, 0x81, 0x81, 0x81, 0x80,
> 0x80,
> +         0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
> 0x80,
> +         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80,
> 0x80,
> +         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
> 0x80,
> +         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +       { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80,
> 0x80,
> +         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
> 0x80,
> +         0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
> 0x00,
> +         0x00, 0x00 },
> +};
> +
> +static const unsigned char VINT_TABLE[VINT_STATUS_MAX] = {
> +       0x18, 0x19, 0x1A, 0x1B, 0x1C,
> +       0x1D, 0x1E, 0x1F, 0x20, 0x21
> +};
> +
> +struct s6e3ha2 {
> +       struct device *dev;
> +       struct drm_panel panel;
> +       struct backlight_device *bl_dev;
> +
> +       struct regulator_bulk_data supplies[2];
> +       struct gpio_desc *reset_gpio;
> +       struct gpio_desc *enable_gpio;
> +       struct videomode vm;
> +};
> +
> +static inline struct s6e3ha2 *panel_to_s6e3ha2(struct drm_panel
> *panel) +{
> +       return container_of(panel, struct s6e3ha2, panel);
> +}
> +
> +static void s6e3ha2_dcs_write(struct mipi_dsi_device *dsi, int
> *error,
> +               const u8 cmd, const void *data, size_t len)
> +{
> +       if (*error < 0)
> +               return;
> +
> +       *error = mipi_dsi_dcs_write(dsi, cmd, data, len);
> +       if (*error < 0)
> +               dev_err(&dsi->dev, "error %d writing dcs seq: %*ph\n",
> *error,
> +                                                       (int)len,
> data); +}
> +
> +#define s6e3ha2_dcs_write_seq_static(dsi, error, cmd, seq...) \
> +({\
> +       static const u8 c = cmd;\
> +       static const u8 d[] = { seq };\
> +       s6e3ha2_dcs_write(dsi, error, c, d, ARRAY_SIZE(d));\
> +})
> +
> +static inline void s6e3ha2_test_key_on_f0(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xf0, 0x5a, 0x5a);
> +}
> +
> +static inline void s6e3ha2_test_key_off_f0(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xf0, 0xa5, 0xa5);
> +}
> +
> +static inline void s6e3ha2_test_key_on_fc(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xfc, 0x5a, 0x5a);
> +}
> +
> +static inline void s6e3ha2_test_key_off_fc(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xfc, 0xa5, 0xa5);
> +}
> +
> +static inline void s6e3ha2_single_dsi_set1(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xf2, 0x67);
> +}
> +
> +static inline void s6e3ha2_single_dsi_set2(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xf9, 0x09);
> +}
> +
> +static inline void s6e3ha2_calibration_set1(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xfd, 0x1c);
> +}
> +
> +static inline void s6e3ha2_calibration_set2(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0x20, 0x39);
> +}
> +
> +static inline void s6e3ha2_calibration_set3(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0xa0);
> +}
> +
> +static inline void s6e3ha2_calibration_set4(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0x20);
> +}
> +
> +static inline void s6e3ha2_calibration_set5(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error,
> +                       0xce, 0x03, 0x3B, 0x12, 0x62, 0x40, 0x80,
> 0xC0, 0x28,
> +                       0x28, 0x28, 0x28, 0x39, 0xC5);
> +}
> +
> +static inline void s6e3ha2_caps_elvss_set(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xb6, 0x9c, 0x0a);
> +}
> +
> +static inline void s6e3ha2_acl_off(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0x55, 0x00);
> +}
> +
> +static inline void s6e3ha2_acl_off_opr(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xb5, 0x40);
> +}
> +
> +static inline void s6e3ha2_test_global(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xb0, 0x07);
> +}
> +
> +static inline void s6e3ha2_test(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xb8, 0x19);
> +}
> +
> +static inline void s6e3ha2_touch_hsync_on1(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) {
> +       s6e3ha2_dcs_write_seq_static(dsi, error,
> +                       0xbd, 0x33, 0x11, 0x02, 0x16, 0x02, 0x16);
> +}
> +
> +static inline void s6e3ha2_pentile_control(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xc0, 0x00, 0x00,
> 0xd8, 0xd8);
> +}
> +
> +static inline void s6e3ha2_poc_global(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xb0, 0x20);
> +}
> +
> +static inline void s6e3ha2_poc_setting(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xfe, 0x08);
> +}
> +
> +static inline void s6e3ha2_pcd_set_off(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xcc, 0x40, 0x51);
> +}
> +
> +static inline void s6e3ha2_err_fg_set(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xed, 0x44);
> +}
> +
> +static inline void s6e3ha2_hbm_off(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0x53, 0x00);
> +}
> +
> +static inline void s6e3ha2_te_start_setting(struct mipi_dsi_device
> *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error,
> +                       0xb9, 0x10, 0x09, 0xff, 0x00, 0x09);
> +}
> +
> +static inline void s6e3ha2_gamma_update(struct mipi_dsi_device *dsi,
> +                                                               int
> *error) +{
> +       s6e3ha2_dcs_write_seq_static(dsi, error, 0xf7, 0x03);
> +}
> +
> +static inline unsigned int s6e3ha2_get_vint_idx(unsigned int brt)
> +{
> +       return (brt * (VINT_STATUS_MAX - 1)) / MAX_BRIGHTNESS;
> +}
> +
> +static inline void s6e3ha2_set_vint(struct mipi_dsi_device *dsi, int
> *error,
> +                                                       unsigned int
> brt) {
> +       unsigned int vint_idx = s6e3ha2_get_vint_idx(brt);
> +       unsigned char data[] = { 0x8b, VINT_TABLE[vint_idx] };
> +
> +       s6e3ha2_dcs_write(dsi, error, 0xf4, data, ARRAY_SIZE(data));
> +}
> +
> +static inline unsigned int s6e3ha2_get_brightness_idx(unsigned int
> brt) +{
> +       return (brt * (NUM_GAMMA_STEPS - 1)) / MAX_BRIGHTNESS;
> +}
> +
> +static void s6e3ha2_update_gamma(struct mipi_dsi_device *dsi, int
> *error,
> +                       struct backlight_device *bl_dev, unsigned int
> brt) +{
> +       unsigned int index = s6e3ha2_get_brightness_idx(brt);
> +
> +       s6e3ha2_dcs_write(dsi, error, 0xca, GAMMA_TBL[index],
> +
> GAMMA_CMD_CNT);
> +       s6e3ha2_dcs_write(dsi, error, 0xb2, AOR_TBL[index],
> +
> ARRAY_SIZE(AOR_TBL[0]));
> +       s6e3ha2_gamma_update(dsi, error);
> +       bl_dev->props.brightness = brt;
> +}
> +
> +static inline int s6e3ha2_get_brightness(struct backlight_device
> *bl_dev) +{
> +       return bl_dev->props.brightness;
> +}
> +
> +static int s6e3ha2_set_brightness(struct backlight_device *bl_dev)
> +{
> +       struct s6e3ha2 *ctx = (struct s6e3ha2 *)bl_get_data(bl_dev);
> +       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
> +       unsigned int brt = bl_dev->props.brightness;
> +       int error = 0;
> +
> +       if (brt < MIN_BRIGHTNESS || brt >
> bl_dev->props.max_brightness) {
> +               dev_err(&dsi->dev, "Invalid brightness: %u\n", brt);
> +               return -EINVAL;
> +       }
> +
> +       if (bl_dev->props.power > FB_BLANK_NORMAL) {
> +               dev_err(&dsi->dev,
> +                       "panel must be at least in fb blank normal
> state\n");
> +               return -EPERM;
> +       }
> +
> +       s6e3ha2_test_key_on_f0(dsi, &error);
> +       s6e3ha2_update_gamma(dsi, &error, bl_dev, brt);
> +       s6e3ha2_set_vint(dsi, &error, brt);
> +       s6e3ha2_test_key_off_f0(dsi, &error);
> +
> +       return error;
> +}
> +
> +static const struct backlight_ops s6e3ha2_bl_ops = {
> +       .get_brightness = s6e3ha2_get_brightness,
> +       .update_status = s6e3ha2_set_brightness,
> +};
> +
> +static int s6e3ha2_panel_init(struct s6e3ha2 *ctx)
> +{
> +       struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
> +       int error;
> +
> +       error = mipi_dsi_dcs_exit_sleep_mode(dsi);
> +       if (error < 0)
> +               return error;
> +
> +       usleep_range(5000, 6000);
> +
> +       s6e3ha2_test_key_on_f0(dsi, &error);
> +       s6e3ha2_single_dsi_set1(dsi, &error);
> +       s6e3ha2_single_dsi_set2(dsi, &error);
> +
> +       /* calibration enable */
> +       s6e3ha2_test_key_on_fc(dsi, &error);
> +       s6e3ha2_calibration_set1(dsi, &error);
> +       s6e3ha2_calibration_set2(dsi, &error);
> +       s6e3ha2_calibration_set3(dsi, &error);
> +       s6e3ha2_calibration_set4(dsi, &error);
> +       s6e3ha2_calibration_set5(dsi, &error);
> +
> +       msleep(120);
> +
> +       /* common setting */
> +       error = mipi_dsi_dcs_set_tear_on(dsi,
> MIPI_DSI_DCS_TEAR_MODE_VBLANK);
> +       if (error < 0)
> +               return error;
> +
> +       s6e3ha2_touch_hsync_on1(dsi, &error);
> +       s6e3ha2_pentile_control(dsi, &error);
> +       s6e3ha2_poc_global(dsi, &error);
> +       s6e3ha2_poc_setting(dsi, &error);
> +       s6e3ha2_test_key_off_fc(dsi, &error);
> +
> +       /* pcd setting off for TB */
> +       s6e3ha2_pcd_set_off(dsi, &error);
> +       s6e3ha2_err_fg_set(dsi, &error);
> +       s6e3ha2_te_start_setting(dsi, &error);
> +       s6e3ha2_test_key_off_f0(dsi, &error);
> +
> +       return error;
> +}
> +
> +static int s6e3ha2_power_off(struct s6e3ha2 *ctx)
> +{
> +       return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies),
> ctx->supplies);
> +}
> +
> +static int s6e3ha2_disable(struct drm_panel *panel)
> +{
> +       struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
> +       struct mipi_dsi_device *dsi = to_mipi_dsi_device(panel->dev);
> +       int ret;
> +
> +       ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
> +       if (ret < 0)
> +               goto err;
> +
> +       ret = mipi_dsi_dcs_set_display_off(dsi);
> +       if (ret < 0)
> +               goto err;
> +
> +       msleep(40);
> +
> +       ctx->bl_dev->props.power = FB_BLANK_NORMAL;
> +
> +       return 0;
> +err:
> +       dev_err(ctx->dev, "failed to power off: %d\n", ret);
> +       return ret;
> +}
> +
> +static int s6e3ha2_unprepare(struct drm_panel *panel)
> +{
> +       struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
> +       int ret;
> +
> +       ret = s6e3ha2_power_off(ctx);
> +       if (ret != 0) {
> +               dev_err(ctx->dev, "failed to power off: %d\n", ret);
> +               return ret;
> +       }
> +
> +       ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
> +
> +       return 0;
> +}
> +
> +static int s6e3ha2_power_on(struct s6e3ha2 *ctx)
> +{
> +       int ret;
> +
> +       ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies),
> ctx->supplies);
> +       if (ret != 0)
> +               return ret;
> +
> +       msleep(25);
> +
> +       gpiod_set_value(ctx->enable_gpio, 0);
> +       usleep_range(5000, 6000);
> +       gpiod_set_value(ctx->enable_gpio, 1);
> +
> +       gpiod_set_value(ctx->reset_gpio, 1);
> +       usleep_range(5000, 6000);
> +       gpiod_set_value(ctx->reset_gpio, 0);
> +       usleep_range(5000, 6000);
> +
> +       return 0;
> +}
> +static int s6e3ha2_prepare(struct drm_panel *panel)
> +{
> +       struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
> +       int ret;
> +
> +       ret = s6e3ha2_power_on(ctx);
> +       if (ret < 0) {
> +               dev_err(ctx->dev, "failed to power on: %d\n", ret);
> +               return ret;
> +       }
> +
> +       ret = s6e3ha2_panel_init(ctx);
> +       if (ret < 0) {
> +               dev_err(ctx->dev, "failed to initialize: %d\n", ret);
> +               s6e3ha2_power_off(ctx);
> +               return ret;
> +       }
> +
> +       ctx->bl_dev->props.power = FB_BLANK_NORMAL;
> +
> +       return 0;
> +}
> +
> +static int s6e3ha2_enable(struct drm_panel *panel)
> +{
> +       struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
> +       struct mipi_dsi_device *dsi = to_mipi_dsi_device(panel->dev);
> +       int error;
> +
> +       s6e3ha2_test_key_on_f0(dsi, &error);
> +
> +       /* brightness setting */
> +       error = s6e3ha2_set_brightness(ctx->bl_dev);
> +       if (error < 0)
> +               goto err;
> +
> +       s6e3ha2_caps_elvss_set(dsi, &error);
> +       s6e3ha2_acl_off(dsi, &error);
> +       s6e3ha2_acl_off_opr(dsi, &error);
> +       s6e3ha2_hbm_off(dsi, &error);
> +
> +       /* elvss temp compensation */
> +       s6e3ha2_test_global(dsi, &error);
> +       s6e3ha2_test(dsi, &error);
> +       s6e3ha2_test_key_off_f0(dsi, &error);
> +
> +       error = mipi_dsi_dcs_set_display_on(dsi);
> +       if (error < 0)
> +               goto err;
> +
> +       ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
> +
> +       return 0;
> +err:
> +       dev_err(ctx->dev, "failed to enable: %d\n", error);
> +       return error;
> +}
> +
> +static int s6e3ha2_get_modes(struct drm_panel *panel)
> +{
> +       struct drm_connector *connector = panel->connector;
> +       struct s6e3ha2 *ctx = panel_to_s6e3ha2(panel);
> +       struct drm_display_mode *mode;
> +
> +       mode = drm_mode_create(connector->dev);
> +       if (!mode) {
> +               DRM_ERROR("failed to create a new display mode\n");
> +               return 0;
> +       }
> +
> +       drm_display_mode_from_videomode(&ctx->vm, mode);
> +       mode->vrefresh = 60;
> +       mode->width_mm = 71;
> +       mode->height_mm = 125;
> +       connector->display_info.width_mm = mode->width_mm;
> +       connector->display_info.height_mm = mode->height_mm;
> +
> +       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
> +       drm_mode_probed_add(connector, mode);
> +
> +       return 1;
> +}
> +
> +static const struct drm_panel_funcs s6e3ha2_funcs = {
> +       .disable = s6e3ha2_disable,
> +       .unprepare = s6e3ha2_unprepare,
> +       .prepare = s6e3ha2_prepare,
> +       .enable = s6e3ha2_enable,
> +       .get_modes = s6e3ha2_get_modes,
> +};
> +
> +static int s6e3ha2_probe(struct mipi_dsi_device *dsi)
> +{
> +       struct device *dev = &dsi->dev;
> +       struct s6e3ha2 *ctx;
> +       int ret;
> +
> +       ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
> +       if (!ctx)
> +               return -ENOMEM;
> +
> +       mipi_dsi_set_drvdata(dsi, ctx);
> +
> +       ctx->dev = dev;
> +
> +       dsi->lanes = 4;
> +       dsi->format = MIPI_DSI_FMT_RGB888;
> +       dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
> +
> +       ret = of_get_videomode(dev->of_node, &ctx->vm, 0);
> +       if (ret < 0)
> +               return ret;
> +
> +       ctx->supplies[0].supply = "vdd3";
> +       ctx->supplies[1].supply = "vci";
> +
> +       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
> +                                     ctx->supplies);
> +       if (ret < 0) {
> +               dev_err(dev, "failed to get regulators: %d\n", ret);
> +               return ret;
> +       }
> +
> +       ctx->reset_gpio = devm_gpiod_get(dev, "reset");
> +       if (IS_ERR(ctx->reset_gpio)) {
> +               dev_err(dev, "cannot get reset-gpio %ld\n",
> +                       PTR_ERR(ctx->reset_gpio));
> +               return PTR_ERR(ctx->reset_gpio);
> +       }
> +
> +       ret = gpiod_direction_output(ctx->reset_gpio, 0);
> +       if (ret < 0) {
> +               dev_err(dev, "cannot configure reset-gpio %d\n", ret);
> +               return ret;
> +       }
> +
> +       ctx->enable_gpio = devm_gpiod_get(dev, "enable");
> +       if (IS_ERR(ctx->enable_gpio)) {
> +               dev_err(dev, "cannot get enable-gpio %ld\n",
> +                       PTR_ERR(ctx->enable_gpio));
> +               return PTR_ERR(ctx->enable_gpio);
> +       }
> +       ret = gpiod_direction_output(ctx->enable_gpio, 1);
> +
> +       ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx,
> +                                               &s6e3ha2_bl_ops,
> NULL);
> +       if (IS_ERR(ctx->bl_dev)) {
> +               dev_err(dev, "failed to register backlight device\n");
> +               return PTR_ERR(ctx->bl_dev);
> +       }
> +
> +       ctx->bl_dev->props.max_brightness = MAX_BRIGHTNESS;
> +       ctx->bl_dev->props.brightness = DEFAULT_BRIGHTNESS;
> +       ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
> +
> +       drm_panel_init(&ctx->panel);
> +       ctx->panel.dev = dev;
> +       ctx->panel.funcs = &s6e3ha2_funcs;
> +
> +       ret = drm_panel_add(&ctx->panel);
> +       if (ret < 0)
> +               goto unregister_backlight;
> +
> +       ret = mipi_dsi_attach(dsi);
> +       if (ret < 0)
> +               goto remove_panel;
> +
> +       return ret;
> +
> +remove_panel:
> +       drm_panel_remove(&ctx->panel);
> +
> +unregister_backlight:
> +       backlight_device_unregister(ctx->bl_dev);
> +
> +       return ret;
> +}
> +
> +static int s6e3ha2_remove(struct mipi_dsi_device *dsi)
> +{
> +       struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi);
> +
> +       mipi_dsi_detach(dsi);
> +       drm_panel_remove(&ctx->panel);
> +       backlight_device_unregister(ctx->bl_dev);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id s6e3ha2_of_match[] = {
> +       { .compatible = "samsung,s6e3ha2" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);
> +
> +static struct mipi_dsi_driver s6e3ha2_driver = {
> +       .probe = s6e3ha2_probe,
> +       .remove = s6e3ha2_remove,
> +       .driver = {
> +               .name = "panel-s6e3ha2",
> +               .of_match_table = s6e3ha2_of_match,
> +       },
> +};
> +module_mipi_dsi_driver(s6e3ha2_driver);
> +
> +MODULE_AUTHOR("Donghwa Lee <dh09.lee at samsung.com>");
> +MODULE_AUTHOR("Hyungwon Hwang <human.hwang at samsung.com>");
> +MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver");
> +MODULE_LICENSE("GPL v2");
> --
> 1.9.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel



More information about the dri-devel mailing list