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