Purpose of this patch is add support for S6E3HA2 AMOLED panel on the TM2 board. The first patch adds support for S6E3HA2 panel device tree document and driver, the second patch add support for S6E3HA2 panel device tree.
Changes for V4:
- Removed display-timings in devicetree, the display-timings has been fixed to be provided by the device driver. - Added the mode_set callback function into exynos_drm_mic, because the exynos_drm_mic driver can not parse a videomode struct by removing the display-timings from the devicetree.
Hoegeun Kwon (2): drm/exynos: mic: Add mode_set callback function drm/panel: Add support for S6E3HA2 panel driver on TM2 board
Hyungwon Hwang (1): arm64: dts: exynos: Add support for S6E3HA2 panel device on TM2 board
.../bindings/display/panel/samsung,s6e3ha2.txt | 40 ++ arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 17 + drivers/gpu/drm/exynos/exynos_drm_mic.c | 33 +- drivers/gpu/drm/panel/Kconfig | 6 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 741 +++++++++++++++++++++ 6 files changed, 827 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
Before applying the patch, used the of_get_videomode function to parse the display-timings in the panel which is the child driver of dsi in the devicetree. this is wrong. So removed the of_get_videomode and fixed to get videomode struct through mode_set callback function.
Signed-off-by: Hoegeun Kwon hoegeun.kwon@samsung.com --- drivers/gpu/drm/exynos/exynos_drm_mic.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index a0def0b..9a50ceb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c @@ -286,13 +286,6 @@ static int parse_dt(struct exynos_mic *mic) } nodes[j++] = remote_node;
- ret = of_get_videomode(remote_node, - &mic->vm, 0); - if (ret) { - DRM_ERROR("mic: failed to get videomode"); - goto exit; - } - break; default: DRM_ERROR("mic: Unknown endpoint from MIC"); @@ -329,6 +322,27 @@ static void mic_post_disable(struct drm_bridge *bridge) mutex_unlock(&mic_mutex); }
+static void mic_mode_set(struct drm_bridge *bridge, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct exynos_mic *mic = bridge->driver_private; + + mutex_lock(&mic_mutex); + if (mic->enabled) + goto already_enabled; + + drm_display_mode_to_videomode(mode, &mic->vm); + + if (!mic->i80_mode) + mic_set_porch_timing(mic); + mic_set_img_size(mic); + mic_set_output_timing(mic); + +already_enabled: + mutex_unlock(&mic_mutex); +} + static void mic_pre_enable(struct drm_bridge *bridge) { struct exynos_mic *mic = bridge->driver_private; @@ -355,10 +369,6 @@ static void mic_pre_enable(struct drm_bridge *bridge) goto turn_off_clks; }
- if (!mic->i80_mode) - mic_set_porch_timing(mic); - mic_set_img_size(mic); - mic_set_output_timing(mic); mic_set_reg_on(mic, 1); mic->enabled = 1; mutex_unlock(&mic_mutex); @@ -377,6 +387,7 @@ static void mic_enable(struct drm_bridge *bridge) { } static const struct drm_bridge_funcs mic_bridge_funcs = { .disable = mic_disable, .post_disable = mic_post_disable, + .mode_set = mic_mode_set, .pre_enable = mic_pre_enable, .enable = mic_enable, };
2017년 01월 04일 15:58에 Hoegeun Kwon 이(가) 쓴 글:
Before applying the patch, used the of_get_videomode function to parse the display-timings in the panel which is the child driver of dsi in the devicetree. this is wrong. So removed the of_get_videomode and fixed to get videomode struct through mode_set callback function.
Signed-off-by: Hoegeun Kwon hoegeun.kwon@samsung.com
drivers/gpu/drm/exynos/exynos_drm_mic.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index a0def0b..9a50ceb 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c @@ -286,13 +286,6 @@ static int parse_dt(struct exynos_mic *mic) } nodes[j++] = remote_node;
ret = of_get_videomode(remote_node,
&mic->vm, 0);
if (ret) {
DRM_ERROR("mic: failed to get videomode");
goto exit;
}
default: DRM_ERROR("mic: Unknown endpoint from MIC");break;
@@ -329,6 +322,27 @@ static void mic_post_disable(struct drm_bridge *bridge) mutex_unlock(&mic_mutex); }
+static void mic_mode_set(struct drm_bridge *bridge,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
+{
- struct exynos_mic *mic = bridge->driver_private;
- mutex_lock(&mic_mutex);
- if (mic->enabled)
goto already_enabled;
mode setting should be performed every time mode_set callback is called so remove above two lines.
- drm_display_mode_to_videomode(mode, &mic->vm);
- if (!mic->i80_mode)
mic_set_porch_timing(mic);
- mic_set_img_size(mic);
- mic_set_output_timing(mic);
+already_enabled:
So this label is unnecessary.
- mutex_unlock(&mic_mutex);
+}
static void mic_pre_enable(struct drm_bridge *bridge) { struct exynos_mic *mic = bridge->driver_private; @@ -355,10 +369,6 @@ static void mic_pre_enable(struct drm_bridge *bridge) goto turn_off_clks; }
- if (!mic->i80_mode)
mic_set_porch_timing(mic);
- mic_set_img_size(mic);
- mic_set_output_timing(mic); mic_set_reg_on(mic, 1); mic->enabled = 1; mutex_unlock(&mic_mutex);
@@ -377,6 +387,7 @@ static void mic_enable(struct drm_bridge *bridge) { } static const struct drm_bridge_funcs mic_bridge_funcs = { .disable = mic_disable, .post_disable = mic_post_disable,
- .mode_set = mic_mode_set, .pre_enable = mic_pre_enable, .enable = mic_enable,
};
This patch add support for MIPI-DSI based S6E3HA2 AMOLED panel driver. This panel has 1440x2560 resolution in 5.7-inch physical panel in the TM2 device.
Signed-off-by: Donghwa Lee dh09.lee@samsung.com Signed-off-by: Hyungwon Hwang human.hwang@samsung.com Signed-off-by: Hoegeun Kwon hoegeun.kwon@samsung.com --- .../bindings/display/panel/samsung,s6e3ha2.txt | 40 ++ drivers/gpu/drm/panel/Kconfig | 6 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 741 +++++++++++++++++++++ 4 files changed, 788 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt new file mode 100644 index 0000000..6879f51 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt @@ -0,0 +1,40 @@ +Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel + +Required properties: + - compatible: "samsung,s6e3ha2" + - reg: the virtual channel number of a DSI peripheral + - vdd3-supply: I/O voltage supply + - vci-supply: voltage supply for analog circuits + - reset-gpios: a GPIO spec for the reset pin (active low) + - enable-gpios: a GPIO spec for the panel enable pin (active high) + - te-gpios: a GPIO spec for the tearing effect synchronization signal + gpio pin (active high) + +The device node can contain one 'port' child node with one child +'endpoint' node, according to the bindings defined in [1]. This +node should describe panel's video bus. + +[1]: Documentation/devicetree/bindings/media/video-interfaces.txt + +Example: + +&dsi { + ... + + panel@0 { + compatible = "samsung,s6e3ha2"; + reg = <0>; + vdd3-supply = <&ldo27_reg>; + vci-supply = <&ldo28_reg>; + reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>; + enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>; + te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; +}; + diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 62aba97..eea2902 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -52,6 +52,12 @@ config DRM_PANEL_PANASONIC_VVX10F034N00 WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some Xperia Z2 tablets
+config DRM_PANEL_SAMSUNG_S6E3HA2 + tristate "Samsung S6E3HA2 DSI video mode panel" + depends on OF + depends on DRM_MIPI_DSI + select VIDEOMODE_HELPERS + config DRM_PANEL_SAMSUNG_S6E8AA0 tristate "Samsung S6E8AA0 DSI video mode panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index a5c7ec0..1d483b0 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c new file mode 100644 index 0000000..8c5a1c2 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c @@ -0,0 +1,741 @@ +/* + * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver. + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Donghwa Lee dh09.lee@samsung.com + * Hyungwon Hwang human.hwang@samsung.com + * Hoegeun Kwon hoegeun.kwon@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/backlight.h> +#include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h> + +#define S6E3HA2_MIN_BRIGHTNESS 0 +#define S6E3HA2_MAX_BRIGHTNESS 100 +#define S6E3HA2_DEFAULT_BRIGHTNESS 80 + +#define S6E3HA2_NUM_GAMMA_STEPS 46 +#define S6E3HA2_GAMMA_CMD_CNT 35 +#define S6E3HA2_VINT_STATUS_MAX 10 + +static const u8 gamma_tbl[S6E3HA2_NUM_GAMMA_STEPS][S6E3HA2_GAMMA_CMD_CNT] = { + { 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 } +}; + +unsigned char vint_table[S6E3HA2_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; + + /* This field is tested by functions directly accessing DSI bus before + * transfer, transfer is skipped if it is set. In case of transfer + * failure or unexpected response the field is set to error value. + * Such construct allows to eliminate many checks in higher level + * functions. + */ + int error; +}; + +static int s6e3ha2_clear_error(struct s6e3ha2 *ctx) +{ + int ret = ctx->error; + + ctx->error = 0; + return ret; +} + +static void s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + ssize_t ret; + + if (ctx->error < 0) + return; + + ret = mipi_dsi_dcs_write_buffer(dsi, data, len); + if (ret < 0) { + dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", + ret, (int)len, data); + ctx->error = ret; + } +} + +#define s6e3ha2_dcs_write_seq_static(ctx, seq...) do { \ + static const u8 d[] = { seq }; \ + s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d)); \ +} while (0) + +static void s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a); +} + +static void s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5); +} + +static void s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a); +} + +static void s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5); +} + +static void s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67); + s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09); +} + +static void s6e3ha2_freq_calibration(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c); + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39); + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0); + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20); + s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62, + 0x40, 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5); +} + +static void s6e3ha2_aor_control(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10); +} + +static void s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a); +} + +static void s6e3ha2_acl_off(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00); +} + +static void s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40); +} + +static void s6e3ha2_test_global(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07); +} + +static void s6e3ha2_test(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19); +} + +static void s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, + 0xbd, 0x33, 0x11, 0x02, 0x16, 0x02, 0x16); +} + +static void s6e3ha2_pentile_control(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8); +} + +static void s6e3ha2_poc_global(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20); +} + +static void s6e3ha2_poc_setting(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08); +} + +static void s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51); +} + +static void s6e3ha2_err_fg_set(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44); +} + +static void s6e3ha2_hbm_off(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00); +} + +static void s6e3ha2_te_start_setting(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09); +} + +static void s6e3ha2_gamma_update(struct s6e3ha2 *ctx) +{ + s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x03); + ndelay(100); /* need for 100ns delay */ + s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x00); +} + +static int s6e3ha2_get_brightness(struct backlight_device *bl_dev) +{ + return bl_dev->props.brightness; +} + +static void s6e3ha2_set_vint(struct s6e3ha2 *ctx) +{ + struct backlight_device *bl_dev = ctx->bl_dev; + unsigned int brightness = bl_dev->props.brightness; + unsigned char data[] = { 0xf4, 0x8b, + vint_table[brightness * (S6E3HA2_VINT_STATUS_MAX - 1) / + S6E3HA2_MAX_BRIGHTNESS] }; + + s6e3ha2_dcs_write(ctx, data, 3); +} + +static unsigned int s6e3ha2_get_brightness_index(unsigned int brightness) +{ + return (brightness * (S6E3HA2_NUM_GAMMA_STEPS - 1)) / + S6E3HA2_MAX_BRIGHTNESS; +} + +static int s6e3ha2_update_gamma(struct s6e3ha2 *ctx, unsigned int brightness) +{ + struct backlight_device *bl_dev = ctx->bl_dev; + unsigned int index = s6e3ha2_get_brightness_index(brightness); + u8 data[S6E3HA2_GAMMA_CMD_CNT + 1] = { 0xca, }; + + memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT); + s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data)); + + s6e3ha2_gamma_update(ctx); + bl_dev->props.brightness = brightness; + + return 0; +} + +static int s6e3ha2_set_brightness(struct backlight_device *bl_dev) +{ + struct s6e3ha2 *ctx = (struct s6e3ha2 *)bl_get_data(bl_dev); + unsigned int brightness = bl_dev->props.brightness; + + if (brightness < S6E3HA2_MIN_BRIGHTNESS || + brightness > bl_dev->props.max_brightness) { + dev_err(ctx->dev, "Invalid brightness: %u\n", brightness); + return -EINVAL; + } + + if (bl_dev->props.power > FB_BLANK_NORMAL) + return -EPERM; + + s6e3ha2_test_key_on_f0(ctx); + s6e3ha2_update_gamma(ctx, brightness); + s6e3ha2_aor_control(ctx); + s6e3ha2_set_vint(ctx); + s6e3ha2_test_key_off_f0(ctx); + + return ctx->error; +} + +static const struct backlight_ops s6e3ha2_bl_ops = { + .get_brightness = s6e3ha2_get_brightness, + .update_status = s6e3ha2_set_brightness, +}; + +static void s6e3ha2_panel_init(struct s6e3ha2 *ctx) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + mipi_dsi_dcs_exit_sleep_mode(dsi); + usleep_range(5000, 6000); + + s6e3ha2_test_key_on_f0(ctx); + s6e3ha2_single_dsi_set(ctx); + s6e3ha2_test_key_on_fc(ctx); + s6e3ha2_freq_calibration(ctx); + s6e3ha2_test_key_off_fc(ctx); + s6e3ha2_test_key_off_f0(ctx); +} + +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 = container_of(panel, struct s6e3ha2, panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ctx->error != 0) + goto err; + + mipi_dsi_dcs_set_display_off(dsi); + if (ctx->error != 0) + goto err; + + msleep(40); + ctx->bl_dev->props.power = FB_BLANK_NORMAL; + + return 0; +err: + return ctx->error; +} + +static int s6e3ha2_unprepare(struct drm_panel *panel) +{ + struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); + int ret; + + ret = s6e3ha2_clear_error(ctx); + if (!ret) + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + + return s6e3ha2_power_off(ctx); +} + +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(120); + + 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 = container_of(panel, struct s6e3ha2, panel); + int ret; + + ret = s6e3ha2_power_on(ctx); + if (ret < 0) + return ret; + + s6e3ha2_panel_init(ctx); + + ret = s6e3ha2_clear_error(ctx); + if (ret < 0) { + 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 = container_of(panel, struct s6e3ha2, panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + + /* common setting */ + mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + + s6e3ha2_test_key_on_f0(ctx); + s6e3ha2_test_key_on_fc(ctx); + s6e3ha2_touch_hsync_on1(ctx); + s6e3ha2_pentile_control(ctx); + s6e3ha2_poc_global(ctx); + s6e3ha2_poc_setting(ctx); + s6e3ha2_test_key_off_fc(ctx); + + /* pcd setting off for TB */ + s6e3ha2_pcd_set_off(ctx); + s6e3ha2_err_fg_set(ctx); + s6e3ha2_te_start_setting(ctx); + + /* brightness setting */ + s6e3ha2_set_brightness(ctx->bl_dev); + s6e3ha2_aor_control(ctx); + s6e3ha2_caps_elvss_set(ctx); + s6e3ha2_gamma_update(ctx); + s6e3ha2_acl_off(ctx); + s6e3ha2_acl_off_opr(ctx); + s6e3ha2_hbm_off(ctx); + + /* elvss temp compensation */ + s6e3ha2_test_global(ctx); + s6e3ha2_test(ctx); + s6e3ha2_test_key_off_f0(ctx); + + mipi_dsi_dcs_set_display_on(dsi); + if (ctx->error != 0) + return ctx->error; + + ctx->bl_dev->props.power = FB_BLANK_UNBLANK; + + return 0; +} + +static const struct drm_display_mode default_mode = { + .clock = 14874, + .hdisplay = 1440, + .hsync_start = 1440 + 1, + .hsync_end = 1440 + 1 + 1, + .htotal = 1440 + 1 + 1 + 1, + .vdisplay = 2560, + .vsync_start = 2560 + 1, + .vsync_end = 2560 + 1 + 1, + .vtotal = 2560 + 1 + 1 + 15, + .vrefresh = 60, + .flags = 0, +}; + +static int s6e3ha2_get_modes(struct drm_panel *panel) +{ + struct drm_connector *connector = panel->connector; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(panel->drm, &default_mode); + if (!mode) { + DRM_ERROR("failed to create a new display mode\n"); + DRM_ERROR("failed to add mode %ux%ux@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + default_mode.vrefresh); + return -ENOMEM; + } + + drm_mode_set_name(mode); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + connector->display_info.width_mm = 71; + connector->display_info.height_mm = 125; + + return 1; +} + +static const struct drm_panel_funcs s6e3ha2_drm_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; + + 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", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) { + dev_err(dev, "cannot get reset-gpios %ld\n", + PTR_ERR(ctx->reset_gpio)); + return PTR_ERR(ctx->reset_gpio); + } + + ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(ctx->enable_gpio)) { + dev_err(dev, "cannot get enable-gpios %ld\n", + PTR_ERR(ctx->enable_gpio)); + return PTR_ERR(ctx->enable_gpio); + } + + 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 = S6E3HA2_MAX_BRIGHTNESS; + ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS; + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + + drm_panel_init(&ctx->panel); + ctx->panel.dev = dev; + ctx->panel.funcs = &s6e3ha2_drm_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-samsung-s6e3ha2", + .of_match_table = s6e3ha2_of_match, + }, +}; +module_mipi_dsi_driver(s6e3ha2_driver); + +MODULE_AUTHOR("Donghwa Lee dh09.lee@samsung.com"); +MODULE_AUTHOR("Hyungwon Hwang human.hwang@samsung.com"); +MODULE_AUTHOR("Hoegeun Kwon hoegeun.kwon@samsung.com"); +MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver"); +MODULE_LICENSE("GPL v2");
Hi Hoegeun,
I tested this patch on Exynos5433-TM2 board. It is well working
Tested-by: Chanwoo Choi cw00.choi@samsung.com
Regards, Chanwoo Choi
On 2017년 01월 04일 15:58, Hoegeun Kwon wrote:
This patch add support for MIPI-DSI based S6E3HA2 AMOLED panel driver. This panel has 1440x2560 resolution in 5.7-inch physical panel in the TM2 device.
Signed-off-by: Donghwa Lee dh09.lee@samsung.com Signed-off-by: Hyungwon Hwang human.hwang@samsung.com Signed-off-by: Hoegeun Kwon hoegeun.kwon@samsung.com
.../bindings/display/panel/samsung,s6e3ha2.txt | 40 ++ drivers/gpu/drm/panel/Kconfig | 6 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 741 +++++++++++++++++++++ 4 files changed, 788 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt new file mode 100644 index 0000000..6879f51 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2.txt @@ -0,0 +1,40 @@ +Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel
+Required properties:
- compatible: "samsung,s6e3ha2"
- reg: the virtual channel number of a DSI peripheral
- vdd3-supply: I/O voltage supply
- vci-supply: voltage supply for analog circuits
- reset-gpios: a GPIO spec for the reset pin (active low)
- enable-gpios: a GPIO spec for the panel enable pin (active high)
- te-gpios: a GPIO spec for the tearing effect synchronization signal
- gpio pin (active high)
+The device node can contain one 'port' child node with one child +'endpoint' node, according to the bindings defined in [1]. This +node should describe panel's video bus.
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+Example:
+&dsi {
- ...
- panel@0 {
compatible = "samsung,s6e3ha2";
reg = <0>;
vdd3-supply = <&ldo27_reg>;
vci-supply = <&ldo28_reg>;
reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi_out>;
};
};
- };
+};
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 62aba97..eea2902 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -52,6 +52,12 @@ config DRM_PANEL_PANASONIC_VVX10F034N00 WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some Xperia Z2 tablets
+config DRM_PANEL_SAMSUNG_S6E3HA2
- tristate "Samsung S6E3HA2 DSI video mode panel"
- depends on OF
- depends on DRM_MIPI_DSI
- select VIDEOMODE_HELPERS
config DRM_PANEL_SAMSUNG_S6E8AA0 tristate "Samsung S6E8AA0 DSI video mode panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index a5c7ec0..1d483b0 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c new file mode 100644 index 0000000..8c5a1c2 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c @@ -0,0 +1,741 @@ +/*
- MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver.
- Copyright (c) 2016 Samsung Electronics Co., Ltd.
- Donghwa Lee dh09.lee@samsung.com
- Hyungwon Hwang human.hwang@samsung.com
- Hoegeun Kwon hoegeun.kwon@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/backlight.h> +#include <linux/gpio/consumer.h> +#include <linux/regulator/consumer.h>
+#define S6E3HA2_MIN_BRIGHTNESS 0 +#define S6E3HA2_MAX_BRIGHTNESS 100 +#define S6E3HA2_DEFAULT_BRIGHTNESS 80
+#define S6E3HA2_NUM_GAMMA_STEPS 46 +#define S6E3HA2_GAMMA_CMD_CNT 35 +#define S6E3HA2_VINT_STATUS_MAX 10
+static const u8 gamma_tbl[S6E3HA2_NUM_GAMMA_STEPS][S6E3HA2_GAMMA_CMD_CNT] = {
- { 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 }
+};
+unsigned char vint_table[S6E3HA2_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;
- /* This field is tested by functions directly accessing DSI bus before
* transfer, transfer is skipped if it is set. In case of transfer
* failure or unexpected response the field is set to error value.
* Such construct allows to eliminate many checks in higher level
* functions.
*/
- int error;
+};
+static int s6e3ha2_clear_error(struct s6e3ha2 *ctx) +{
- int ret = ctx->error;
- ctx->error = 0;
- return ret;
+}
+static void s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len) +{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- ssize_t ret;
- if (ctx->error < 0)
return;
- ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
- if (ret < 0) {
dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n",
ret, (int)len, data);
ctx->error = ret;
- }
+}
+#define s6e3ha2_dcs_write_seq_static(ctx, seq...) do { \
- static const u8 d[] = { seq }; \
- s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d)); \
+} while (0)
+static void s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
+}
+static void s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5);
+}
+static void s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
+}
+static void s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5);
+}
+static void s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67);
- s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09);
+}
+static void s6e3ha2_freq_calibration(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c);
- s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);
- s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);
- s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);
- s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62,
0x40, 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5);
+}
+static void s6e3ha2_aor_control(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10);
+}
+static void s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a);
+}
+static void s6e3ha2_acl_off(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00);
+}
+static void s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40);
+}
+static void s6e3ha2_test_global(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07);
+}
+static void s6e3ha2_test(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19);
+}
+static void s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx,
0xbd, 0x33, 0x11, 0x02, 0x16, 0x02, 0x16);
+}
+static void s6e3ha2_pentile_control(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8);
+}
+static void s6e3ha2_poc_global(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20);
+}
+static void s6e3ha2_poc_setting(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08);
+}
+static void s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51);
+}
+static void s6e3ha2_err_fg_set(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44);
+}
+static void s6e3ha2_hbm_off(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00);
+}
+static void s6e3ha2_te_start_setting(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09);
+}
+static void s6e3ha2_gamma_update(struct s6e3ha2 *ctx) +{
- s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x03);
- ndelay(100); /* need for 100ns delay */
- s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x00);
+}
+static int s6e3ha2_get_brightness(struct backlight_device *bl_dev) +{
- return bl_dev->props.brightness;
+}
+static void s6e3ha2_set_vint(struct s6e3ha2 *ctx) +{
- struct backlight_device *bl_dev = ctx->bl_dev;
- unsigned int brightness = bl_dev->props.brightness;
- unsigned char data[] = { 0xf4, 0x8b,
vint_table[brightness * (S6E3HA2_VINT_STATUS_MAX - 1) /
S6E3HA2_MAX_BRIGHTNESS] };
- s6e3ha2_dcs_write(ctx, data, 3);
+}
+static unsigned int s6e3ha2_get_brightness_index(unsigned int brightness) +{
- return (brightness * (S6E3HA2_NUM_GAMMA_STEPS - 1)) /
S6E3HA2_MAX_BRIGHTNESS;
+}
+static int s6e3ha2_update_gamma(struct s6e3ha2 *ctx, unsigned int brightness) +{
- struct backlight_device *bl_dev = ctx->bl_dev;
- unsigned int index = s6e3ha2_get_brightness_index(brightness);
- u8 data[S6E3HA2_GAMMA_CMD_CNT + 1] = { 0xca, };
- memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT);
- s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data));
- s6e3ha2_gamma_update(ctx);
- bl_dev->props.brightness = brightness;
- return 0;
+}
+static int s6e3ha2_set_brightness(struct backlight_device *bl_dev) +{
- struct s6e3ha2 *ctx = (struct s6e3ha2 *)bl_get_data(bl_dev);
- unsigned int brightness = bl_dev->props.brightness;
- if (brightness < S6E3HA2_MIN_BRIGHTNESS ||
brightness > bl_dev->props.max_brightness) {
dev_err(ctx->dev, "Invalid brightness: %u\n", brightness);
return -EINVAL;
- }
- if (bl_dev->props.power > FB_BLANK_NORMAL)
return -EPERM;
- s6e3ha2_test_key_on_f0(ctx);
- s6e3ha2_update_gamma(ctx, brightness);
- s6e3ha2_aor_control(ctx);
- s6e3ha2_set_vint(ctx);
- s6e3ha2_test_key_off_f0(ctx);
- return ctx->error;
+}
+static const struct backlight_ops s6e3ha2_bl_ops = {
- .get_brightness = s6e3ha2_get_brightness,
- .update_status = s6e3ha2_set_brightness,
+};
+static void s6e3ha2_panel_init(struct s6e3ha2 *ctx) +{
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- mipi_dsi_dcs_exit_sleep_mode(dsi);
- usleep_range(5000, 6000);
- s6e3ha2_test_key_on_f0(ctx);
- s6e3ha2_single_dsi_set(ctx);
- s6e3ha2_test_key_on_fc(ctx);
- s6e3ha2_freq_calibration(ctx);
- s6e3ha2_test_key_off_fc(ctx);
- s6e3ha2_test_key_off_f0(ctx);
+}
+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 = container_of(panel, struct s6e3ha2, panel);
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ctx->error != 0)
goto err;
- mipi_dsi_dcs_set_display_off(dsi);
- if (ctx->error != 0)
goto err;
- msleep(40);
- ctx->bl_dev->props.power = FB_BLANK_NORMAL;
- return 0;
+err:
- return ctx->error;
+}
+static int s6e3ha2_unprepare(struct drm_panel *panel) +{
- struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
- int ret;
- ret = s6e3ha2_clear_error(ctx);
- if (!ret)
ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
- return s6e3ha2_power_off(ctx);
+}
+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(120);
- 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 = container_of(panel, struct s6e3ha2, panel);
- int ret;
- ret = s6e3ha2_power_on(ctx);
- if (ret < 0)
return ret;
- s6e3ha2_panel_init(ctx);
- ret = s6e3ha2_clear_error(ctx);
- if (ret < 0) {
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 = container_of(panel, struct s6e3ha2, panel);
- struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
- /* common setting */
- mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
- s6e3ha2_test_key_on_f0(ctx);
- s6e3ha2_test_key_on_fc(ctx);
- s6e3ha2_touch_hsync_on1(ctx);
- s6e3ha2_pentile_control(ctx);
- s6e3ha2_poc_global(ctx);
- s6e3ha2_poc_setting(ctx);
- s6e3ha2_test_key_off_fc(ctx);
- /* pcd setting off for TB */
- s6e3ha2_pcd_set_off(ctx);
- s6e3ha2_err_fg_set(ctx);
- s6e3ha2_te_start_setting(ctx);
- /* brightness setting */
- s6e3ha2_set_brightness(ctx->bl_dev);
- s6e3ha2_aor_control(ctx);
- s6e3ha2_caps_elvss_set(ctx);
- s6e3ha2_gamma_update(ctx);
- s6e3ha2_acl_off(ctx);
- s6e3ha2_acl_off_opr(ctx);
- s6e3ha2_hbm_off(ctx);
- /* elvss temp compensation */
- s6e3ha2_test_global(ctx);
- s6e3ha2_test(ctx);
- s6e3ha2_test_key_off_f0(ctx);
- mipi_dsi_dcs_set_display_on(dsi);
- if (ctx->error != 0)
return ctx->error;
- ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
- return 0;
+}
+static const struct drm_display_mode default_mode = {
- .clock = 14874,
- .hdisplay = 1440,
- .hsync_start = 1440 + 1,
- .hsync_end = 1440 + 1 + 1,
- .htotal = 1440 + 1 + 1 + 1,
- .vdisplay = 2560,
- .vsync_start = 2560 + 1,
- .vsync_end = 2560 + 1 + 1,
- .vtotal = 2560 + 1 + 1 + 15,
- .vrefresh = 60,
- .flags = 0,
+};
+static int s6e3ha2_get_modes(struct drm_panel *panel) +{
- struct drm_connector *connector = panel->connector;
- struct drm_display_mode *mode;
- mode = drm_mode_duplicate(panel->drm, &default_mode);
- if (!mode) {
DRM_ERROR("failed to create a new display mode\n");
DRM_ERROR("failed to add mode %ux%ux@%u\n",
default_mode.hdisplay, default_mode.vdisplay,
default_mode.vrefresh);
return -ENOMEM;
- }
- drm_mode_set_name(mode);
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_probed_add(connector, mode);
- connector->display_info.width_mm = 71;
- connector->display_info.height_mm = 125;
- return 1;
+}
+static const struct drm_panel_funcs s6e3ha2_drm_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;
- 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", GPIOD_OUT_LOW);
- if (IS_ERR(ctx->reset_gpio)) {
dev_err(dev, "cannot get reset-gpios %ld\n",
PTR_ERR(ctx->reset_gpio));
return PTR_ERR(ctx->reset_gpio);
- }
- ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
- if (IS_ERR(ctx->enable_gpio)) {
dev_err(dev, "cannot get enable-gpios %ld\n",
PTR_ERR(ctx->enable_gpio));
return PTR_ERR(ctx->enable_gpio);
- }
- 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 = S6E3HA2_MAX_BRIGHTNESS;
- ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS;
- ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
- drm_panel_init(&ctx->panel);
- ctx->panel.dev = dev;
- ctx->panel.funcs = &s6e3ha2_drm_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-samsung-s6e3ha2",
.of_match_table = s6e3ha2_of_match,
- },
+}; +module_mipi_dsi_driver(s6e3ha2_driver);
+MODULE_AUTHOR("Donghwa Lee dh09.lee@samsung.com"); +MODULE_AUTHOR("Hyungwon Hwang human.hwang@samsung.com"); +MODULE_AUTHOR("Hoegeun Kwon hoegeun.kwon@samsung.com"); +MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver"); +MODULE_LICENSE("GPL v2");
From: Hyungwon Hwang human.hwang@samsung.com
This patch add the panel device tree node for S6E3HA2 display controller to TM2 dts.
Signed-off-by: Hyungwon Hwang human.hwang@samsung.com Signed-off-by: Andrzej Hajda a.hajda@samsung.com Signed-off-by: Chanwoo Choi cw00.choi@samsung.com Signed-off-by: Hoegeun Kwon hoegeun.kwon@samsung.com --- arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts index 5b9451d..b3ba1ac 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts @@ -304,11 +304,28 @@ reg = <1>;
dsi_out: endpoint { + remote-endpoint = <&panel_in>; samsung,burst-clock-frequency = <512000000>; samsung,esc-clock-frequency = <16000000>; }; }; }; + + panel@0 { + compatible = "samsung,s6e3ha2"; + reg = <0>; + vdd3-supply = <&ldo27_reg>; + vci-supply = <&ldo28_reg>; + reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>; + enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>; + te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; };
&hsi2c_0 {
Hi Hoegeun,
On 2017년 01월 04일 15:58, Hoegeun Kwon wrote:
From: Hyungwon Hwang human.hwang@samsung.com
This patch add the panel device tree node for S6E3HA2 display controller to TM2 dts.
Signed-off-by: Hyungwon Hwang human.hwang@samsung.com Signed-off-by: Andrzej Hajda a.hajda@samsung.com Signed-off-by: Chanwoo Choi cw00.choi@samsung.com Signed-off-by: Hoegeun Kwon hoegeun.kwon@samsung.com
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts index 5b9451d..b3ba1ac 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts @@ -304,11 +304,28 @@ reg = <1>;
dsi_out: endpoint {
}; };remote-endpoint = <&panel_in>; samsung,burst-clock-frequency = <512000000>; samsung,esc-clock-frequency = <16000000>; };
- panel@0 {
compatible = "samsung,s6e3ha2";
reg = <0>;
vdd3-supply = <&ldo27_reg>;
vci-supply = <&ldo28_reg>;
reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
port {
panel_in: endpoint {
remote-endpoint = <&dsi_out>;
};
};
- };
};
&hsi2c_0 {
I tested this patch on Exynos5433-TM2 board. It is well working to display the image to LCD panel.
Tested-by: Chanwoo Choi cw00.choi@samsung.com
dri-devel@lists.freedesktop.org