diff options
-rw-r--r-- | drivers/gpu/drm/panel/Kconfig | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 739 |
3 files changed, 746 insertions, 0 deletions
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 62aba976e744..d913c834eb71 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig | |||
@@ -52,6 +52,12 @@ config DRM_PANEL_PANASONIC_VVX10F034N00 | |||
52 | WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some | 52 | WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some |
53 | Xperia Z2 tablets | 53 | Xperia Z2 tablets |
54 | 54 | ||
55 | config DRM_PANEL_SAMSUNG_S6E3HA2 | ||
56 | tristate "Samsung S6E3HA2 DSI video mode panel" | ||
57 | depends on OF | ||
58 | depends on DRM_MIPI_DSI | ||
59 | select VIDEOMODE_HELPERS | ||
60 | |||
55 | config DRM_PANEL_SAMSUNG_S6E8AA0 | 61 | config DRM_PANEL_SAMSUNG_S6E8AA0 |
56 | tristate "Samsung S6E8AA0 DSI video mode panel" | 62 | tristate "Samsung S6E8AA0 DSI video mode panel" |
57 | depends on OF | 63 | depends on OF |
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index a5c7ec0236e0..1d483b03178b 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 | |||
3 | obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o | 3 | obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o |
4 | obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o | 4 | obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o |
5 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o | 5 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o |
6 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o | ||
6 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o | 7 | obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o |
7 | obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o | 8 | obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o |
8 | obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o | 9 | 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 000000000000..4cc08d7b3de4 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | |||
@@ -0,0 +1,739 @@ | |||
1 | /* | ||
2 | * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver. | ||
3 | * | ||
4 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. | ||
5 | * Donghwa Lee <dh09.lee@samsung.com> | ||
6 | * Hyungwon Hwang <human.hwang@samsung.com> | ||
7 | * Hoegeun Kwon <hoegeun.kwon@samsung.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <drm/drmP.h> | ||
15 | #include <drm/drm_mipi_dsi.h> | ||
16 | #include <drm/drm_panel.h> | ||
17 | #include <linux/backlight.h> | ||
18 | #include <linux/gpio/consumer.h> | ||
19 | #include <linux/regulator/consumer.h> | ||
20 | |||
21 | #define S6E3HA2_MIN_BRIGHTNESS 0 | ||
22 | #define S6E3HA2_MAX_BRIGHTNESS 100 | ||
23 | #define S6E3HA2_DEFAULT_BRIGHTNESS 80 | ||
24 | |||
25 | #define S6E3HA2_NUM_GAMMA_STEPS 46 | ||
26 | #define S6E3HA2_GAMMA_CMD_CNT 35 | ||
27 | #define S6E3HA2_VINT_STATUS_MAX 10 | ||
28 | |||
29 | static const u8 gamma_tbl[S6E3HA2_NUM_GAMMA_STEPS][S6E3HA2_GAMMA_CMD_CNT] = { | ||
30 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x82, 0x83, | ||
31 | 0x85, 0x88, 0x8b, 0x8b, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8c, | ||
32 | 0x94, 0x84, 0xb1, 0xaf, 0x8e, 0xcf, 0xad, 0xc9, 0x00, 0x00, 0x00, | ||
33 | 0x00, 0x00 }, | ||
34 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84, 0x84, | ||
35 | 0x85, 0x87, 0x8b, 0x8a, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8a, | ||
36 | 0x93, 0x84, 0xb0, 0xae, 0x8e, 0xc9, 0xa8, 0xc5, 0x00, 0x00, 0x00, | ||
37 | 0x00, 0x00 }, | ||
38 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, | ||
39 | 0x85, 0x86, 0x8a, 0x8a, 0x84, 0x88, 0x81, 0x84, 0x8a, 0x88, 0x8a, | ||
40 | 0x91, 0x84, 0xb1, 0xae, 0x8b, 0xd5, 0xb2, 0xcc, 0x00, 0x00, 0x00, | ||
41 | 0x00, 0x00 }, | ||
42 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, | ||
43 | 0x85, 0x86, 0x8a, 0x8a, 0x84, 0x87, 0x81, 0x84, 0x8a, 0x87, 0x8a, | ||
44 | 0x91, 0x85, 0xae, 0xac, 0x8a, 0xc3, 0xa3, 0xc0, 0x00, 0x00, 0x00, | ||
45 | 0x00, 0x00 }, | ||
46 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x85, 0x85, | ||
47 | 0x86, 0x85, 0x88, 0x89, 0x84, 0x89, 0x82, 0x84, 0x87, 0x85, 0x8b, | ||
48 | 0x91, 0x88, 0xad, 0xab, 0x8a, 0xb7, 0x9b, 0xb6, 0x00, 0x00, 0x00, | ||
49 | 0x00, 0x00 }, | ||
50 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, | ||
51 | 0x85, 0x86, 0x89, 0x8a, 0x84, 0x89, 0x83, 0x83, 0x86, 0x84, 0x8b, | ||
52 | 0x90, 0x84, 0xb0, 0xae, 0x8b, 0xce, 0xad, 0xc8, 0x00, 0x00, 0x00, | ||
53 | 0x00, 0x00 }, | ||
54 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, | ||
55 | 0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x89, | ||
56 | 0x8f, 0x84, 0xac, 0xaa, 0x89, 0xb1, 0x98, 0xaf, 0x00, 0x00, 0x00, | ||
57 | 0x00, 0x00 }, | ||
58 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, | ||
59 | 0x85, 0x86, 0x88, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8c, | ||
60 | 0x91, 0x86, 0xac, 0xaa, 0x89, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00, | ||
61 | 0x00, 0x00 }, | ||
62 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
63 | 0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x88, | ||
64 | 0x8b, 0x82, 0xad, 0xaa, 0x8a, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00, | ||
65 | 0x00, 0x00 }, | ||
66 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83, | ||
67 | 0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8a, | ||
68 | 0x8e, 0x84, 0xae, 0xac, 0x89, 0xda, 0xb7, 0xd0, 0x00, 0x00, 0x00, | ||
69 | 0x00, 0x00 }, | ||
70 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
71 | 0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x80, 0x83, 0x82, 0x8b, | ||
72 | 0x8e, 0x85, 0xac, 0xaa, 0x89, 0xc8, 0xaa, 0xc1, 0x00, 0x00, 0x00, | ||
73 | 0x00, 0x00 }, | ||
74 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
75 | 0x85, 0x86, 0x87, 0x89, 0x81, 0x85, 0x81, 0x84, 0x86, 0x84, 0x8c, | ||
76 | 0x8c, 0x84, 0xa9, 0xa8, 0x87, 0xa3, 0x92, 0xa1, 0x00, 0x00, 0x00, | ||
77 | 0x00, 0x00 }, | ||
78 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
79 | 0x85, 0x86, 0x87, 0x89, 0x84, 0x86, 0x83, 0x80, 0x83, 0x81, 0x8c, | ||
80 | 0x8d, 0x84, 0xaa, 0xaa, 0x89, 0xce, 0xaf, 0xc5, 0x00, 0x00, 0x00, | ||
81 | 0x00, 0x00 }, | ||
82 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
83 | 0x85, 0x86, 0x87, 0x89, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c, | ||
84 | 0x8c, 0x84, 0xa8, 0xa8, 0x88, 0xb5, 0x9f, 0xb0, 0x00, 0x00, 0x00, | ||
85 | 0x00, 0x00 }, | ||
86 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
87 | 0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c, | ||
88 | 0x8b, 0x84, 0xab, 0xa8, 0x86, 0xd4, 0xb4, 0xc9, 0x00, 0x00, 0x00, | ||
89 | 0x00, 0x00 }, | ||
90 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
91 | 0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x84, 0x84, 0x85, 0x8b, | ||
92 | 0x8a, 0x83, 0xa6, 0xa5, 0x84, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00, | ||
93 | 0x00, 0x00 }, | ||
94 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84, | ||
95 | 0x86, 0x85, 0x86, 0x86, 0x82, 0x85, 0x81, 0x82, 0x83, 0x84, 0x8e, | ||
96 | 0x8b, 0x83, 0xa4, 0xa3, 0x8a, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00, | ||
97 | 0x00, 0x00 }, | ||
98 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83, | ||
99 | 0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8e, | ||
100 | 0x8b, 0x83, 0xa4, 0xa2, 0x86, 0xc1, 0xa9, 0xb7, 0x00, 0x00, 0x00, | ||
101 | 0x00, 0x00 }, | ||
102 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83, | ||
103 | 0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8d, | ||
104 | 0x89, 0x82, 0xa2, 0xa1, 0x84, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00, | ||
105 | 0x00, 0x00 }, | ||
106 | { 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83, | ||
107 | 0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x83, 0x83, 0x85, 0x8c, | ||
108 | 0x87, 0x7f, 0xa2, 0x9d, 0x88, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, | ||
109 | 0x00, 0x00 }, | ||
110 | { 0x00, 0xbb, 0x00, 0xc5, 0x00, 0xb4, 0x87, 0x86, 0x86, 0x84, 0x83, | ||
111 | 0x86, 0x87, 0x87, 0x87, 0x80, 0x82, 0x7f, 0x86, 0x86, 0x88, 0x8a, | ||
112 | 0x84, 0x7e, 0x9d, 0x9c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, | ||
113 | 0x00, 0x00 }, | ||
114 | { 0x00, 0xbd, 0x00, 0xc7, 0x00, 0xb7, 0x87, 0x85, 0x85, 0x84, 0x83, | ||
115 | 0x86, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x83, 0x84, 0x85, 0x8a, | ||
116 | 0x85, 0x7e, 0x9c, 0x9b, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
117 | 0x00, 0x00 }, | ||
118 | { 0x00, 0xc0, 0x00, 0xca, 0x00, 0xbb, 0x87, 0x86, 0x85, 0x83, 0x83, | ||
119 | 0x85, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x84, 0x85, 0x86, 0x89, | ||
120 | 0x83, 0x7d, 0x9c, 0x99, 0x87, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00, | ||
121 | 0x00, 0x00 }, | ||
122 | { 0x00, 0xc4, 0x00, 0xcd, 0x00, 0xbe, 0x87, 0x86, 0x85, 0x83, 0x83, | ||
123 | 0x86, 0x85, 0x85, 0x87, 0x81, 0x82, 0x80, 0x82, 0x82, 0x83, 0x8a, | ||
124 | 0x85, 0x7f, 0x9f, 0x9b, 0x86, 0xb4, 0xa1, 0xac, 0x00, 0x00, 0x00, | ||
125 | 0x00, 0x00 }, | ||
126 | { 0x00, 0xc7, 0x00, 0xd0, 0x00, 0xc2, 0x87, 0x85, 0x85, 0x83, 0x82, | ||
127 | 0x85, 0x85, 0x85, 0x86, 0x82, 0x83, 0x80, 0x82, 0x82, 0x84, 0x87, | ||
128 | 0x86, 0x80, 0x9e, 0x9a, 0x87, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00, | ||
129 | 0x00, 0x00 }, | ||
130 | { 0x00, 0xca, 0x00, 0xd2, 0x00, 0xc5, 0x87, 0x85, 0x84, 0x82, 0x82, | ||
131 | 0x84, 0x85, 0x85, 0x86, 0x81, 0x82, 0x7f, 0x82, 0x82, 0x84, 0x88, | ||
132 | 0x86, 0x81, 0x9d, 0x98, 0x86, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, | ||
133 | 0x00, 0x00 }, | ||
134 | { 0x00, 0xce, 0x00, 0xd6, 0x00, 0xca, 0x86, 0x85, 0x84, 0x83, 0x83, | ||
135 | 0x85, 0x84, 0x84, 0x85, 0x81, 0x82, 0x80, 0x81, 0x81, 0x82, 0x89, | ||
136 | 0x86, 0x81, 0x9c, 0x97, 0x86, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00, | ||
137 | 0x00, 0x00 }, | ||
138 | { 0x00, 0xd1, 0x00, 0xd9, 0x00, 0xce, 0x86, 0x84, 0x83, 0x83, 0x82, | ||
139 | 0x85, 0x85, 0x85, 0x86, 0x81, 0x83, 0x81, 0x82, 0x82, 0x83, 0x86, | ||
140 | 0x83, 0x7f, 0x99, 0x95, 0x86, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00, | ||
141 | 0x00, 0x00 }, | ||
142 | { 0x00, 0xd4, 0x00, 0xdb, 0x00, 0xd1, 0x86, 0x85, 0x83, 0x83, 0x82, | ||
143 | 0x85, 0x84, 0x84, 0x85, 0x80, 0x83, 0x82, 0x80, 0x80, 0x81, 0x87, | ||
144 | 0x84, 0x81, 0x98, 0x93, 0x85, 0xae, 0x9c, 0xa8, 0x00, 0x00, 0x00, | ||
145 | 0x00, 0x00 }, | ||
146 | { 0x00, 0xd8, 0x00, 0xde, 0x00, 0xd6, 0x86, 0x84, 0x83, 0x81, 0x81, | ||
147 | 0x83, 0x85, 0x85, 0x85, 0x82, 0x83, 0x81, 0x81, 0x81, 0x83, 0x86, | ||
148 | 0x84, 0x80, 0x98, 0x91, 0x85, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00, | ||
149 | 0x00, 0x00 }, | ||
150 | { 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xda, 0x85, 0x84, 0x83, 0x82, 0x82, | ||
151 | 0x84, 0x84, 0x84, 0x85, 0x81, 0x82, 0x82, 0x80, 0x80, 0x81, 0x83, | ||
152 | 0x82, 0x7f, 0x99, 0x93, 0x86, 0x94, 0x8b, 0x92, 0x00, 0x00, 0x00, | ||
153 | 0x00, 0x00 }, | ||
154 | { 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xde, 0x85, 0x84, 0x82, 0x82, 0x82, | ||
155 | 0x84, 0x83, 0x83, 0x84, 0x81, 0x81, 0x80, 0x83, 0x82, 0x84, 0x82, | ||
156 | 0x81, 0x7f, 0x99, 0x92, 0x86, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00, | ||
157 | 0x00, 0x00 }, | ||
158 | { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, | ||
159 | 0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x83, 0x83, 0x84, 0x80, | ||
160 | 0x81, 0x7c, 0x99, 0x92, 0x87, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00, | ||
161 | 0x00, 0x00 }, | ||
162 | { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x85, 0x84, 0x83, 0x81, 0x81, | ||
163 | 0x82, 0x82, 0x82, 0x83, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83, | ||
164 | 0x82, 0x80, 0x91, 0x8d, 0x83, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00, | ||
165 | 0x00, 0x00 }, | ||
166 | { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, | ||
167 | 0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83, | ||
168 | 0x81, 0x7f, 0x91, 0x8c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00, | ||
169 | 0x00, 0x00 }, | ||
170 | { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, | ||
171 | 0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x82, | ||
172 | 0x82, 0x7f, 0x94, 0x89, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
173 | 0x00, 0x00 }, | ||
174 | { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, | ||
175 | 0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x83, | ||
176 | 0x82, 0x7f, 0x91, 0x85, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
177 | 0x00, 0x00 }, | ||
178 | { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81, | ||
179 | 0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x83, 0x82, 0x84, 0x83, | ||
180 | 0x82, 0x7f, 0x90, 0x84, 0x81, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00, | ||
181 | 0x00, 0x00 }, | ||
182 | { 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x80, 0x80, | ||
183 | 0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x81, | ||
184 | 0x82, 0x83, 0x7e, 0x80, 0x7c, 0xa4, 0x97, 0x9f, 0x00, 0x00, 0x00, | ||
185 | 0x00, 0x00 }, | ||
186 | { 0x00, 0xe9, 0x00, 0xec, 0x00, 0xe8, 0x84, 0x83, 0x82, 0x81, 0x81, | ||
187 | 0x82, 0x82, 0x82, 0x83, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x83, | ||
188 | 0x83, 0x84, 0x79, 0x7c, 0x79, 0xb1, 0xa0, 0xaa, 0x00, 0x00, 0x00, | ||
189 | 0x00, 0x00 }, | ||
190 | { 0x00, 0xed, 0x00, 0xf0, 0x00, 0xec, 0x83, 0x83, 0x82, 0x80, 0x80, | ||
191 | 0x81, 0x82, 0x82, 0x82, 0x7f, 0x7f, 0x7e, 0x81, 0x81, 0x82, 0x80, | ||
192 | 0x81, 0x81, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
193 | 0x00, 0x00 }, | ||
194 | { 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xf1, 0x83, 0x82, 0x82, 0x80, 0x80, | ||
195 | 0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x7d, | ||
196 | 0x7e, 0x7f, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
197 | 0x00, 0x00 }, | ||
198 | { 0x00, 0xf6, 0x00, 0xf7, 0x00, 0xf5, 0x82, 0x82, 0x81, 0x80, 0x80, | ||
199 | 0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x82, | ||
200 | 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
201 | 0x00, 0x00 }, | ||
202 | { 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfa, 0x81, 0x81, 0x81, 0x80, 0x80, | ||
203 | 0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, | ||
204 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
205 | 0x00, 0x00 }, | ||
206 | { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, | ||
207 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, | ||
208 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
209 | 0x00, 0x00 }, | ||
210 | { 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, | ||
211 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, | ||
212 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, | ||
213 | 0x00, 0x00 } | ||
214 | }; | ||
215 | |||
216 | unsigned char vint_table[S6E3HA2_VINT_STATUS_MAX] = { | ||
217 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, | ||
218 | 0x1d, 0x1e, 0x1f, 0x20, 0x21 | ||
219 | }; | ||
220 | |||
221 | struct s6e3ha2 { | ||
222 | struct device *dev; | ||
223 | struct drm_panel panel; | ||
224 | struct backlight_device *bl_dev; | ||
225 | |||
226 | struct regulator_bulk_data supplies[2]; | ||
227 | struct gpio_desc *reset_gpio; | ||
228 | struct gpio_desc *enable_gpio; | ||
229 | }; | ||
230 | |||
231 | static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len) | ||
232 | { | ||
233 | struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); | ||
234 | |||
235 | return mipi_dsi_dcs_write_buffer(dsi, data, len); | ||
236 | } | ||
237 | |||
238 | #define s6e3ha2_dcs_write_seq_static(ctx, seq...) do { \ | ||
239 | static const u8 d[] = { seq }; \ | ||
240 | int ret; \ | ||
241 | ret = s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d)); \ | ||
242 | if (ret < 0) \ | ||
243 | return ret; \ | ||
244 | } while (0) | ||
245 | |||
246 | #define s6e3ha2_call_write_func(ret, func) do { \ | ||
247 | ret = (func); \ | ||
248 | if (ret < 0) \ | ||
249 | return ret; \ | ||
250 | } while (0) | ||
251 | |||
252 | static int s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx) | ||
253 | { | ||
254 | s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx) | ||
259 | { | ||
260 | s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx) | ||
265 | { | ||
266 | s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a); | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx) | ||
271 | { | ||
272 | s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx) | ||
277 | { | ||
278 | s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67); | ||
279 | s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx) | ||
284 | { | ||
285 | s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c); | ||
286 | s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39); | ||
287 | s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0); | ||
288 | s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20); | ||
289 | s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62, 0x40, | ||
290 | 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5); | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int s6e3ha2_aor_control(struct s6e3ha2 *ctx) | ||
295 | { | ||
296 | s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx) | ||
301 | { | ||
302 | s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a); | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int s6e3ha2_acl_off(struct s6e3ha2 *ctx) | ||
307 | { | ||
308 | s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx) | ||
313 | { | ||
314 | s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40); | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int s6e3ha2_test_global(struct s6e3ha2 *ctx) | ||
319 | { | ||
320 | s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int s6e3ha2_test(struct s6e3ha2 *ctx) | ||
325 | { | ||
326 | s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx) | ||
331 | { | ||
332 | s6e3ha2_dcs_write_seq_static(ctx, 0xbd, 0x33, 0x11, 0x02, | ||
333 | 0x16, 0x02, 0x16); | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static int s6e3ha2_pentile_control(struct s6e3ha2 *ctx) | ||
338 | { | ||
339 | s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int s6e3ha2_poc_global(struct s6e3ha2 *ctx) | ||
344 | { | ||
345 | s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20); | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int s6e3ha2_poc_setting(struct s6e3ha2 *ctx) | ||
350 | { | ||
351 | s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx) | ||
356 | { | ||
357 | s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51); | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int s6e3ha2_err_fg_set(struct s6e3ha2 *ctx) | ||
362 | { | ||
363 | s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44); | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int s6e3ha2_hbm_off(struct s6e3ha2 *ctx) | ||
368 | { | ||
369 | s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int s6e3ha2_te_start_setting(struct s6e3ha2 *ctx) | ||
374 | { | ||
375 | s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09); | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int s6e3ha2_gamma_update(struct s6e3ha2 *ctx) | ||
380 | { | ||
381 | s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x03); | ||
382 | ndelay(100); /* need for 100ns delay */ | ||
383 | s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x00); | ||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static int s6e3ha2_get_brightness(struct backlight_device *bl_dev) | ||
388 | { | ||
389 | return bl_dev->props.brightness; | ||
390 | } | ||
391 | |||
392 | static int s6e3ha2_set_vint(struct s6e3ha2 *ctx) | ||
393 | { | ||
394 | struct backlight_device *bl_dev = ctx->bl_dev; | ||
395 | unsigned int brightness = bl_dev->props.brightness; | ||
396 | unsigned char data[] = { 0xf4, 0x8b, | ||
397 | vint_table[brightness * (S6E3HA2_VINT_STATUS_MAX - 1) / | ||
398 | S6E3HA2_MAX_BRIGHTNESS] }; | ||
399 | |||
400 | return s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data)); | ||
401 | } | ||
402 | |||
403 | static unsigned int s6e3ha2_get_brightness_index(unsigned int brightness) | ||
404 | { | ||
405 | return (brightness * (S6E3HA2_NUM_GAMMA_STEPS - 1)) / | ||
406 | S6E3HA2_MAX_BRIGHTNESS; | ||
407 | } | ||
408 | |||
409 | static int s6e3ha2_update_gamma(struct s6e3ha2 *ctx, unsigned int brightness) | ||
410 | { | ||
411 | struct backlight_device *bl_dev = ctx->bl_dev; | ||
412 | unsigned int index = s6e3ha2_get_brightness_index(brightness); | ||
413 | u8 data[S6E3HA2_GAMMA_CMD_CNT + 1] = { 0xca, }; | ||
414 | int ret; | ||
415 | |||
416 | memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT); | ||
417 | s6e3ha2_call_write_func(ret, | ||
418 | s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data))); | ||
419 | |||
420 | s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx)); | ||
421 | bl_dev->props.brightness = brightness; | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static int s6e3ha2_set_brightness(struct backlight_device *bl_dev) | ||
427 | { | ||
428 | struct s6e3ha2 *ctx = bl_get_data(bl_dev); | ||
429 | unsigned int brightness = bl_dev->props.brightness; | ||
430 | int ret; | ||
431 | |||
432 | if (brightness < S6E3HA2_MIN_BRIGHTNESS || | ||
433 | brightness > bl_dev->props.max_brightness) { | ||
434 | dev_err(ctx->dev, "Invalid brightness: %u\n", brightness); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | |||
438 | if (bl_dev->props.power > FB_BLANK_NORMAL) | ||
439 | return -EPERM; | ||
440 | |||
441 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx)); | ||
442 | s6e3ha2_call_write_func(ret, s6e3ha2_update_gamma(ctx, brightness)); | ||
443 | s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx)); | ||
444 | s6e3ha2_call_write_func(ret, s6e3ha2_set_vint(ctx)); | ||
445 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx)); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static const struct backlight_ops s6e3ha2_bl_ops = { | ||
451 | .get_brightness = s6e3ha2_get_brightness, | ||
452 | .update_status = s6e3ha2_set_brightness, | ||
453 | }; | ||
454 | |||
455 | static int s6e3ha2_panel_init(struct s6e3ha2 *ctx) | ||
456 | { | ||
457 | struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); | ||
458 | int ret; | ||
459 | |||
460 | s6e3ha2_call_write_func(ret, mipi_dsi_dcs_exit_sleep_mode(dsi)); | ||
461 | usleep_range(5000, 6000); | ||
462 | |||
463 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx)); | ||
464 | s6e3ha2_call_write_func(ret, s6e3ha2_single_dsi_set(ctx)); | ||
465 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx)); | ||
466 | s6e3ha2_call_write_func(ret, s6e3ha2_freq_calibration(ctx)); | ||
467 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx)); | ||
468 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx)); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static int s6e3ha2_power_off(struct s6e3ha2 *ctx) | ||
474 | { | ||
475 | return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); | ||
476 | } | ||
477 | |||
478 | static int s6e3ha2_disable(struct drm_panel *panel) | ||
479 | { | ||
480 | struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); | ||
481 | struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); | ||
482 | int ret; | ||
483 | |||
484 | s6e3ha2_call_write_func(ret, mipi_dsi_dcs_enter_sleep_mode(dsi)); | ||
485 | s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_off(dsi)); | ||
486 | |||
487 | msleep(40); | ||
488 | ctx->bl_dev->props.power = FB_BLANK_NORMAL; | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | static int s6e3ha2_unprepare(struct drm_panel *panel) | ||
494 | { | ||
495 | struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); | ||
496 | |||
497 | return s6e3ha2_power_off(ctx); | ||
498 | } | ||
499 | |||
500 | static int s6e3ha2_power_on(struct s6e3ha2 *ctx) | ||
501 | { | ||
502 | int ret; | ||
503 | |||
504 | ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); | ||
505 | if (ret < 0) | ||
506 | return ret; | ||
507 | |||
508 | msleep(120); | ||
509 | |||
510 | gpiod_set_value(ctx->enable_gpio, 0); | ||
511 | usleep_range(5000, 6000); | ||
512 | gpiod_set_value(ctx->enable_gpio, 1); | ||
513 | |||
514 | gpiod_set_value(ctx->reset_gpio, 1); | ||
515 | usleep_range(5000, 6000); | ||
516 | gpiod_set_value(ctx->reset_gpio, 0); | ||
517 | usleep_range(5000, 6000); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | static int s6e3ha2_prepare(struct drm_panel *panel) | ||
522 | { | ||
523 | struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); | ||
524 | int ret; | ||
525 | |||
526 | ret = s6e3ha2_power_on(ctx); | ||
527 | if (ret < 0) | ||
528 | return ret; | ||
529 | |||
530 | ret = s6e3ha2_panel_init(ctx); | ||
531 | if (ret < 0) | ||
532 | goto err; | ||
533 | |||
534 | ctx->bl_dev->props.power = FB_BLANK_NORMAL; | ||
535 | |||
536 | return 0; | ||
537 | |||
538 | err: | ||
539 | s6e3ha2_power_off(ctx); | ||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | static int s6e3ha2_enable(struct drm_panel *panel) | ||
544 | { | ||
545 | struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); | ||
546 | struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); | ||
547 | int ret; | ||
548 | |||
549 | /* common setting */ | ||
550 | s6e3ha2_call_write_func(ret, | ||
551 | mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK)); | ||
552 | |||
553 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx)); | ||
554 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx)); | ||
555 | s6e3ha2_call_write_func(ret, s6e3ha2_touch_hsync_on1(ctx)); | ||
556 | s6e3ha2_call_write_func(ret, s6e3ha2_pentile_control(ctx)); | ||
557 | s6e3ha2_call_write_func(ret, s6e3ha2_poc_global(ctx)); | ||
558 | s6e3ha2_call_write_func(ret, s6e3ha2_poc_setting(ctx)); | ||
559 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx)); | ||
560 | |||
561 | /* pcd setting off for TB */ | ||
562 | s6e3ha2_call_write_func(ret, s6e3ha2_pcd_set_off(ctx)); | ||
563 | s6e3ha2_call_write_func(ret, s6e3ha2_err_fg_set(ctx)); | ||
564 | s6e3ha2_call_write_func(ret, s6e3ha2_te_start_setting(ctx)); | ||
565 | |||
566 | /* brightness setting */ | ||
567 | s6e3ha2_call_write_func(ret, s6e3ha2_set_brightness(ctx->bl_dev)); | ||
568 | s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx)); | ||
569 | s6e3ha2_call_write_func(ret, s6e3ha2_caps_elvss_set(ctx)); | ||
570 | s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx)); | ||
571 | s6e3ha2_call_write_func(ret, s6e3ha2_acl_off(ctx)); | ||
572 | s6e3ha2_call_write_func(ret, s6e3ha2_acl_off_opr(ctx)); | ||
573 | s6e3ha2_call_write_func(ret, s6e3ha2_hbm_off(ctx)); | ||
574 | |||
575 | /* elvss temp compensation */ | ||
576 | s6e3ha2_call_write_func(ret, s6e3ha2_test_global(ctx)); | ||
577 | s6e3ha2_call_write_func(ret, s6e3ha2_test(ctx)); | ||
578 | s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx)); | ||
579 | |||
580 | s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_on(dsi)); | ||
581 | ctx->bl_dev->props.power = FB_BLANK_UNBLANK; | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static const struct drm_display_mode default_mode = { | ||
587 | .clock = 222372, | ||
588 | .hdisplay = 1440, | ||
589 | .hsync_start = 1440 + 1, | ||
590 | .hsync_end = 1440 + 1 + 1, | ||
591 | .htotal = 1440 + 1 + 1 + 1, | ||
592 | .vdisplay = 2560, | ||
593 | .vsync_start = 2560 + 1, | ||
594 | .vsync_end = 2560 + 1 + 1, | ||
595 | .vtotal = 2560 + 1 + 1 + 15, | ||
596 | .vrefresh = 60, | ||
597 | .flags = 0, | ||
598 | }; | ||
599 | |||
600 | static int s6e3ha2_get_modes(struct drm_panel *panel) | ||
601 | { | ||
602 | struct drm_connector *connector = panel->connector; | ||
603 | struct drm_display_mode *mode; | ||
604 | |||
605 | mode = drm_mode_duplicate(panel->drm, &default_mode); | ||
606 | if (!mode) { | ||
607 | DRM_ERROR("failed to add mode %ux%ux@%u\n", | ||
608 | default_mode.hdisplay, default_mode.vdisplay, | ||
609 | default_mode.vrefresh); | ||
610 | return -ENOMEM; | ||
611 | } | ||
612 | |||
613 | drm_mode_set_name(mode); | ||
614 | |||
615 | mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; | ||
616 | drm_mode_probed_add(connector, mode); | ||
617 | |||
618 | connector->display_info.width_mm = 71; | ||
619 | connector->display_info.height_mm = 125; | ||
620 | |||
621 | return 1; | ||
622 | } | ||
623 | |||
624 | static const struct drm_panel_funcs s6e3ha2_drm_funcs = { | ||
625 | .disable = s6e3ha2_disable, | ||
626 | .unprepare = s6e3ha2_unprepare, | ||
627 | .prepare = s6e3ha2_prepare, | ||
628 | .enable = s6e3ha2_enable, | ||
629 | .get_modes = s6e3ha2_get_modes, | ||
630 | }; | ||
631 | |||
632 | static int s6e3ha2_probe(struct mipi_dsi_device *dsi) | ||
633 | { | ||
634 | struct device *dev = &dsi->dev; | ||
635 | struct s6e3ha2 *ctx; | ||
636 | int ret; | ||
637 | |||
638 | ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); | ||
639 | if (!ctx) | ||
640 | return -ENOMEM; | ||
641 | |||
642 | mipi_dsi_set_drvdata(dsi, ctx); | ||
643 | |||
644 | ctx->dev = dev; | ||
645 | |||
646 | dsi->lanes = 4; | ||
647 | dsi->format = MIPI_DSI_FMT_RGB888; | ||
648 | dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS; | ||
649 | |||
650 | ctx->supplies[0].supply = "vdd3"; | ||
651 | ctx->supplies[1].supply = "vci"; | ||
652 | |||
653 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), | ||
654 | ctx->supplies); | ||
655 | if (ret < 0) { | ||
656 | dev_err(dev, "failed to get regulators: %d\n", ret); | ||
657 | return ret; | ||
658 | } | ||
659 | |||
660 | ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); | ||
661 | if (IS_ERR(ctx->reset_gpio)) { | ||
662 | dev_err(dev, "cannot get reset-gpios %ld\n", | ||
663 | PTR_ERR(ctx->reset_gpio)); | ||
664 | return PTR_ERR(ctx->reset_gpio); | ||
665 | } | ||
666 | |||
667 | ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); | ||
668 | if (IS_ERR(ctx->enable_gpio)) { | ||
669 | dev_err(dev, "cannot get enable-gpios %ld\n", | ||
670 | PTR_ERR(ctx->enable_gpio)); | ||
671 | return PTR_ERR(ctx->enable_gpio); | ||
672 | } | ||
673 | |||
674 | ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx, | ||
675 | &s6e3ha2_bl_ops, NULL); | ||
676 | if (IS_ERR(ctx->bl_dev)) { | ||
677 | dev_err(dev, "failed to register backlight device\n"); | ||
678 | return PTR_ERR(ctx->bl_dev); | ||
679 | } | ||
680 | |||
681 | ctx->bl_dev->props.max_brightness = S6E3HA2_MAX_BRIGHTNESS; | ||
682 | ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS; | ||
683 | ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; | ||
684 | |||
685 | drm_panel_init(&ctx->panel); | ||
686 | ctx->panel.dev = dev; | ||
687 | ctx->panel.funcs = &s6e3ha2_drm_funcs; | ||
688 | |||
689 | ret = drm_panel_add(&ctx->panel); | ||
690 | if (ret < 0) | ||
691 | goto unregister_backlight; | ||
692 | |||
693 | ret = mipi_dsi_attach(dsi); | ||
694 | if (ret < 0) | ||
695 | goto remove_panel; | ||
696 | |||
697 | return ret; | ||
698 | |||
699 | remove_panel: | ||
700 | drm_panel_remove(&ctx->panel); | ||
701 | |||
702 | unregister_backlight: | ||
703 | backlight_device_unregister(ctx->bl_dev); | ||
704 | |||
705 | return ret; | ||
706 | } | ||
707 | |||
708 | static int s6e3ha2_remove(struct mipi_dsi_device *dsi) | ||
709 | { | ||
710 | struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi); | ||
711 | |||
712 | mipi_dsi_detach(dsi); | ||
713 | drm_panel_remove(&ctx->panel); | ||
714 | backlight_device_unregister(ctx->bl_dev); | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | static const struct of_device_id s6e3ha2_of_match[] = { | ||
720 | { .compatible = "samsung,s6e3ha2" }, | ||
721 | { } | ||
722 | }; | ||
723 | MODULE_DEVICE_TABLE(of, s6e3ha2_of_match); | ||
724 | |||
725 | static struct mipi_dsi_driver s6e3ha2_driver = { | ||
726 | .probe = s6e3ha2_probe, | ||
727 | .remove = s6e3ha2_remove, | ||
728 | .driver = { | ||
729 | .name = "panel-samsung-s6e3ha2", | ||
730 | .of_match_table = s6e3ha2_of_match, | ||
731 | }, | ||
732 | }; | ||
733 | module_mipi_dsi_driver(s6e3ha2_driver); | ||
734 | |||
735 | MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>"); | ||
736 | MODULE_AUTHOR("Hyungwon Hwang <human.hwang@samsung.com>"); | ||
737 | MODULE_AUTHOR("Hoegeun Kwon <hoegeun.kwon@samsung.com>"); | ||
738 | MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver"); | ||
739 | MODULE_LICENSE("GPL v2"); | ||