xref: /linux/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c (revision c94cd9508b1335b949fd13ebd269313c65492df0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Panels based on the Ilitek ILI9882T display controller.
4  */
5 #include <linux/delay.h>
6 #include <linux/gpio/consumer.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/regulator/consumer.h>
10 
11 #include <drm/drm_connector.h>
12 #include <drm/drm_crtc.h>
13 #include <drm/drm_mipi_dsi.h>
14 #include <drm/drm_panel.h>
15 
16 #include <video/mipi_display.h>
17 
18 struct ili9882t;
19 
20 /*
21  * Use this descriptor struct to describe different panels using the
22  * Ilitek ILI9882T display controller.
23  */
24 struct panel_desc {
25 	const struct drm_display_mode *modes;
26 	unsigned int bpc;
27 
28 	/**
29 	 * @width_mm: width of the panel's active display area
30 	 * @height_mm: height of the panel's active display area
31 	 */
32 	struct {
33 		unsigned int width_mm;
34 		unsigned int height_mm;
35 	} size;
36 
37 	unsigned long mode_flags;
38 	enum mipi_dsi_pixel_format format;
39 	int (*init)(struct ili9882t *boe);
40 	unsigned int lanes;
41 };
42 
43 struct ili9882t {
44 	struct drm_panel base;
45 	struct mipi_dsi_device *dsi;
46 
47 	const struct panel_desc *desc;
48 
49 	enum drm_panel_orientation orientation;
50 	struct regulator *pp3300;
51 	struct regulator *pp1800;
52 	struct regulator *avee;
53 	struct regulator *avdd;
54 	struct gpio_desc *enable_gpio;
55 };
56 
57 /* ILI9882-specific commands, add new commands as you decode them */
58 #define ILI9882T_DCS_SWITCH_PAGE	0xFF
59 
60 #define ili9882t_switch_page(ctx, page) \
61 	mipi_dsi_dcs_write_seq_multi(ctx, ILI9882T_DCS_SWITCH_PAGE, \
62 				     0x98, 0x82, (page))
63 
64 static int starry_ili9882t_init(struct ili9882t *ili)
65 {
66 	struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
67 
68 	usleep_range(5000, 5100);
69 
70 	ili9882t_switch_page(&ctx, 0x01);
71 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x42);
72 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x11);
73 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x00);
74 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x00);
75 
76 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x01);
77 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x11);
78 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x00);
79 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00);
80 
81 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x80);
82 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x81);
83 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x71);
84 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x00);
85 
86 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x00);
87 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x1a);
88 
89 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
90 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00);
91 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x00);
92 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
93 
94 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0xd4);
95 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x40);
96 
97 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x11);
98 
99 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x32);
100 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x30);
101 
102 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
103 
104 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x01);
105 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x93);
106 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x00);
107 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x80);
108 
109 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x07);
110 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x07);
111 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x07);
112 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x07);
113 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x07);
114 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x01);
115 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x00);
116 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x28);
117 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x29);
118 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x11);
119 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x13);
120 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x15);
121 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x17);
122 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x09);
123 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x0d);
124 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x02);
125 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x02);
126 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x02);
127 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x02);
128 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x02);
129 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x02);
130 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x46, 0x02);
131 
132 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x07);
133 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x07);
134 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x07);
135 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x07);
136 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x07);
137 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x01);
138 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x00);
139 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x28);
140 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x29);
141 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x50, 0x10);
142 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12);
143 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x14);
144 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x16);
145 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x08);
146 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x0c);
147 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x02);
148 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x57, 0x02);
149 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x02);
150 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x02);
151 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x02);
152 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02);
153 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x02);
154 
155 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x07);
156 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x07);
157 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x07);
158 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x07);
159 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x07);
160 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x01);
161 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x00);
162 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x28);
163 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x29);
164 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16);
165 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x14);
166 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x12);
167 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x10);
168 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0c);
169 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6f, 0x08);
170 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x02);
171 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x02);
172 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x02);
173 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0x02);
174 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x74, 0x02);
175 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0x02);
176 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x76, 0x02);
177 
178 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x07);
179 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x07);
180 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x07);
181 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x07);
182 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0x07);
183 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x01);
184 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00);
185 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x28);
186 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x29);
187 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x17);
188 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x15);
189 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x13);
190 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x83, 0x11);
191 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x0d);
192 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0x09);
193 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x02);
194 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x07);
195 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x07);
196 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x07);
197 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8a, 0x07);
198 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8b, 0x07);
199 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8c, 0x07);
200 
201 	ili9882t_switch_page(&ctx, 0x02);
202 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x3a);
203 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x3b);
204 
205 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x01);
206 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x01);
207 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0c);
208 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x44);
209 
210 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
211 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x11);
212 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x00);
213 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0c);
214 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x44);
215 
216 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x1f);
217 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x40);
218 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x00);
219 
220 	ili9882t_switch_page(&ctx, 0x03);
221 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01);
222 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x3c);
223 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0xfa);
224 
225 	ili9882t_switch_page(&ctx, 0x0a);
226 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01);
227 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x01);
228 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x91);
229 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x3c);
230 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
231 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0xfa);
232 
233 	ili9882t_switch_page(&ctx, 0x12);
234 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2c);
235 
236 	ili9882t_switch_page(&ctx, 0x05);
237 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0xe5);
238 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x6b);
239 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0xa4);
240 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x54);
241 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x97);
242 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x97);
243 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x3f);
244 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xda);
245 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xf1);
246 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x01);
247 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x3f);
248 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x90);
249 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
250 
251 	ili9882t_switch_page(&ctx, 0x06);
252 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x80);
253 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x07);
254 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x58);
255 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x02);
256 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x58);
257 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x02);
258 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x60);
259 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x00);
260 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
261 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x08);
262 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
263 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x38);
264 
265 	ili9882t_switch_page(&ctx, 0x08);
266 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
267 				     0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
268 				     0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
269 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
270 				     0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
271 				     0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
272 
273 	ili9882t_switch_page(&ctx, 0x04);
274 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x81);
275 
276 	ili9882t_switch_page(&ctx, 0x0c);
277 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x02);
278 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00);
279 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03);
280 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x01);
281 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x03);
282 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x02);
283 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04);
284 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x03);
285 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x03);
286 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x04);
287 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x04);
288 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x05);
289 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x04);
290 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x06);
291 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x05);
292 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x07);
293 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x04);
294 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08);
295 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x05);
296 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x09);
297 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x05);
298 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x0a);
299 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x06);
300 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x0b);
301 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x05);
302 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0c);
303 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x06);
304 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d);
305 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x06);
306 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x0e);
307 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x07);
308 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f);
309 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x06);
310 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x10);
311 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x07);
312 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x11);
313 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x07);
314 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x12);
315 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08);
316 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x13);
317 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x07);
318 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x14);
319 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x08);
320 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x15);
321 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0x08);
322 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x16);
323 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2e, 0x09);
324 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x17);
325 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x08);
326 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x18);
327 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x09);
328 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x19);
329 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x09);
330 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x1a);
331 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x0a);
332 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x1b);
333 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x0a);
334 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x1c);
335 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0a);
336 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x1d);
337 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
338 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x1e);
339 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x0a);
340 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x1f);
341 
342 	ili9882t_switch_page(&ctx, 0x04);
343 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x01);
344 
345 	ili9882t_switch_page(&ctx, 0x0e);
346 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x0c);
347 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x10);
348 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x16);
349 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xe0);
350 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
351 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x71);
352 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x46);
353 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x1f);
354 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0xc7);
355 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x02);
356 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0xdf);
357 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x5a);
358 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0xc0);
359 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x5a);
360 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0xc0);
361 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x65);
362 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x3e);
363 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0xa0);
364 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
365 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xcc);
366 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x12);
367 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xcc);
368 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcc);
369 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xcc);
370 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xcc);
371 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xcc);
372 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xcc);
373 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xcc);
374 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0xcc);
375 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
376 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x81);
377 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x02);
378 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x00);
379 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x21);
380 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x10);
381 
382 	ili9882t_switch_page(&ctx, 0x1e);
383 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
384 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x00);
385 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x00);
386 
387 	ili9882t_switch_page(&ctx, 0x0b);
388 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa6, 0x44);
389 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xb6);
390 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa8, 0x03);
391 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x03);
392 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x51);
393 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x51);
394 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x04);
395 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x92);
396 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa1);
397 
398 	ili9882t_switch_page(&ctx, 0x05);
399 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
400 
401 	ili9882t_switch_page(&ctx, 0x06);
402 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
403 
404 	ili9882t_switch_page(&ctx, 0x00);
405 	mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
406 
407 	mipi_dsi_msleep(&ctx, 120);
408 
409 	mipi_dsi_dcs_set_display_on_multi(&ctx);
410 
411 	mipi_dsi_msleep(&ctx, 20);
412 
413 	return ctx.accum_err;
414 };
415 
416 static inline struct ili9882t *to_ili9882t(struct drm_panel *panel)
417 {
418 	return container_of(panel, struct ili9882t, base);
419 }
420 
421 static int ili9882t_disable(struct drm_panel *panel)
422 {
423 	struct ili9882t *ili = to_ili9882t(panel);
424 	struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
425 
426 	ili9882t_switch_page(&ctx, 0x00);
427 
428 	ili->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
429 
430 	mipi_dsi_dcs_set_display_off_multi(&ctx);
431 	mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
432 
433 	mipi_dsi_msleep(&ctx, 150);
434 
435 	return ctx.accum_err;
436 }
437 
438 static int ili9882t_unprepare(struct drm_panel *panel)
439 {
440 	struct ili9882t *ili = to_ili9882t(panel);
441 
442 	gpiod_set_value(ili->enable_gpio, 0);
443 	usleep_range(1000, 2000);
444 	regulator_disable(ili->avee);
445 	regulator_disable(ili->avdd);
446 	usleep_range(5000, 7000);
447 	regulator_disable(ili->pp1800);
448 	regulator_disable(ili->pp3300);
449 
450 	return 0;
451 }
452 
453 static int ili9882t_prepare(struct drm_panel *panel)
454 {
455 	struct ili9882t *ili = to_ili9882t(panel);
456 	int ret;
457 
458 	gpiod_set_value(ili->enable_gpio, 0);
459 	usleep_range(1000, 1500);
460 
461 	ret = regulator_enable(ili->pp3300);
462 	if (ret < 0)
463 		return ret;
464 
465 	ret = regulator_enable(ili->pp1800);
466 	if (ret < 0)
467 		return ret;
468 
469 	usleep_range(3000, 5000);
470 
471 	ret = regulator_enable(ili->avdd);
472 	if (ret < 0)
473 		goto poweroff1v8;
474 	ret = regulator_enable(ili->avee);
475 	if (ret < 0)
476 		goto poweroffavdd;
477 
478 	usleep_range(10000, 11000);
479 
480 	// MIPI needs to keep the LP11 state before the lcm_reset pin is pulled high
481 	ret = mipi_dsi_dcs_nop(ili->dsi);
482 	if (ret < 0) {
483 		dev_err(&ili->dsi->dev, "Failed to send NOP: %d\n", ret);
484 		goto poweroff;
485 	}
486 	usleep_range(1000, 2000);
487 
488 	gpiod_set_value(ili->enable_gpio, 1);
489 	usleep_range(1000, 2000);
490 	gpiod_set_value(ili->enable_gpio, 0);
491 	msleep(50);
492 	gpiod_set_value(ili->enable_gpio, 1);
493 	usleep_range(6000, 10000);
494 
495 	ret = ili->desc->init(ili);
496 	if (ret < 0)
497 		goto poweroff;
498 
499 	return 0;
500 
501 poweroff:
502 	gpiod_set_value(ili->enable_gpio, 0);
503 	regulator_disable(ili->avee);
504 poweroffavdd:
505 	regulator_disable(ili->avdd);
506 poweroff1v8:
507 	usleep_range(5000, 7000);
508 	regulator_disable(ili->pp1800);
509 
510 	return ret;
511 }
512 
513 static int ili9882t_enable(struct drm_panel *panel)
514 {
515 	msleep(130);
516 	return 0;
517 }
518 
519 static const struct drm_display_mode starry_ili9882t_default_mode = {
520 	.clock = 165280,
521 	.hdisplay = 1200,
522 	.hsync_start = 1200 + 72,
523 	.hsync_end = 1200 + 72 + 30,
524 	.htotal = 1200 + 72 + 30 + 72,
525 	.vdisplay = 1920,
526 	.vsync_start = 1920 + 68,
527 	.vsync_end = 1920 + 68 + 2,
528 	.vtotal = 1920 + 68 + 2 + 10,
529 	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
530 };
531 
532 static const struct panel_desc starry_ili9882t_desc = {
533 	.modes = &starry_ili9882t_default_mode,
534 	.bpc = 8,
535 	.size = {
536 		.width_mm = 141,
537 		.height_mm = 226,
538 	},
539 	.lanes = 4,
540 	.format = MIPI_DSI_FMT_RGB888,
541 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
542 		      MIPI_DSI_MODE_LPM,
543 	.init = starry_ili9882t_init,
544 };
545 
546 static int ili9882t_get_modes(struct drm_panel *panel,
547 			      struct drm_connector *connector)
548 {
549 	struct ili9882t *ili = to_ili9882t(panel);
550 	const struct drm_display_mode *m = ili->desc->modes;
551 	struct drm_display_mode *mode;
552 
553 	mode = drm_mode_duplicate(connector->dev, m);
554 	if (!mode) {
555 		dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
556 			m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
557 		return -ENOMEM;
558 	}
559 
560 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
561 	drm_mode_set_name(mode);
562 	drm_mode_probed_add(connector, mode);
563 
564 	connector->display_info.width_mm = ili->desc->size.width_mm;
565 	connector->display_info.height_mm = ili->desc->size.height_mm;
566 	connector->display_info.bpc = ili->desc->bpc;
567 
568 	return 1;
569 }
570 
571 static enum drm_panel_orientation ili9882t_get_orientation(struct drm_panel *panel)
572 {
573 	struct ili9882t *ili = to_ili9882t(panel);
574 
575 	return ili->orientation;
576 }
577 
578 static const struct drm_panel_funcs ili9882t_funcs = {
579 	.disable = ili9882t_disable,
580 	.unprepare = ili9882t_unprepare,
581 	.prepare = ili9882t_prepare,
582 	.enable = ili9882t_enable,
583 	.get_modes = ili9882t_get_modes,
584 	.get_orientation = ili9882t_get_orientation,
585 };
586 
587 static int ili9882t_add(struct ili9882t *ili)
588 {
589 	struct device *dev = &ili->dsi->dev;
590 	int err;
591 
592 	ili->avdd = devm_regulator_get(dev, "avdd");
593 	if (IS_ERR(ili->avdd))
594 		return PTR_ERR(ili->avdd);
595 
596 	ili->avee = devm_regulator_get(dev, "avee");
597 	if (IS_ERR(ili->avee))
598 		return PTR_ERR(ili->avee);
599 
600 	ili->pp3300 = devm_regulator_get(dev, "pp3300");
601 	if (IS_ERR(ili->pp3300))
602 		return PTR_ERR(ili->pp3300);
603 
604 	ili->pp1800 = devm_regulator_get(dev, "pp1800");
605 	if (IS_ERR(ili->pp1800))
606 		return PTR_ERR(ili->pp1800);
607 
608 	ili->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
609 	if (IS_ERR(ili->enable_gpio)) {
610 		dev_err(dev, "cannot get reset-gpios %ld\n",
611 			PTR_ERR(ili->enable_gpio));
612 		return PTR_ERR(ili->enable_gpio);
613 	}
614 
615 	gpiod_set_value(ili->enable_gpio, 0);
616 
617 	drm_panel_init(&ili->base, dev, &ili9882t_funcs,
618 		       DRM_MODE_CONNECTOR_DSI);
619 	err = of_drm_get_panel_orientation(dev->of_node, &ili->orientation);
620 	if (err < 0) {
621 		dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);
622 		return err;
623 	}
624 
625 	err = drm_panel_of_backlight(&ili->base);
626 	if (err)
627 		return err;
628 
629 	ili->base.funcs = &ili9882t_funcs;
630 	ili->base.dev = &ili->dsi->dev;
631 
632 	drm_panel_add(&ili->base);
633 
634 	return 0;
635 }
636 
637 static int ili9882t_probe(struct mipi_dsi_device *dsi)
638 {
639 	struct ili9882t *ili;
640 	int ret;
641 	const struct panel_desc *desc;
642 
643 	ili = devm_kzalloc(&dsi->dev, sizeof(*ili), GFP_KERNEL);
644 	if (!ili)
645 		return -ENOMEM;
646 
647 	desc = of_device_get_match_data(&dsi->dev);
648 	dsi->lanes = desc->lanes;
649 	dsi->format = desc->format;
650 	dsi->mode_flags = desc->mode_flags;
651 	ili->desc = desc;
652 	ili->dsi = dsi;
653 	ret = ili9882t_add(ili);
654 	if (ret < 0)
655 		return ret;
656 
657 	mipi_dsi_set_drvdata(dsi, ili);
658 
659 	ret = mipi_dsi_attach(dsi);
660 	if (ret)
661 		drm_panel_remove(&ili->base);
662 
663 	return ret;
664 }
665 
666 static void ili9882t_remove(struct mipi_dsi_device *dsi)
667 {
668 	struct ili9882t *ili = mipi_dsi_get_drvdata(dsi);
669 	int ret;
670 
671 	ret = mipi_dsi_detach(dsi);
672 	if (ret < 0)
673 		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
674 
675 	if (ili->base.dev)
676 		drm_panel_remove(&ili->base);
677 }
678 
679 static const struct of_device_id ili9882t_of_match[] = {
680 	{ .compatible = "starry,ili9882t",
681 	  .data = &starry_ili9882t_desc
682 	},
683 	{ /* sentinel */ }
684 };
685 MODULE_DEVICE_TABLE(of, ili9882t_of_match);
686 
687 static struct mipi_dsi_driver ili9882t_driver = {
688 	.driver = {
689 		.name = "panel-ili9882t",
690 		.of_match_table = ili9882t_of_match,
691 	},
692 	.probe = ili9882t_probe,
693 	.remove = ili9882t_remove,
694 };
695 module_mipi_dsi_driver(ili9882t_driver);
696 
697 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
698 MODULE_DESCRIPTION("Ilitek ILI9882T-based panels driver");
699 MODULE_LICENSE("GPL");
700