1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2020 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 */
6
7 #include <linux/delay.h>
8 #include <linux/gpio/consumer.h>
9 #include <linux/module.h>
10 #include <linux/of.h>
11 #include <linux/regulator/consumer.h>
12
13 #include <video/mipi_display.h>
14
15 #include <drm/drm_crtc.h>
16 #include <drm/drm_device.h>
17 #include <drm/drm_mipi_dsi.h>
18 #include <drm/drm_modes.h>
19 #include <drm/drm_panel.h>
20
21 struct khadas_ts050_panel {
22 struct drm_panel base;
23 struct mipi_dsi_device *link;
24
25 struct regulator *supply;
26 struct gpio_desc *reset_gpio;
27 struct gpio_desc *enable_gpio;
28 struct khadas_ts050_panel_data *panel_data;
29 };
30
31 struct khadas_ts050_panel_cmd {
32 u8 cmd;
33 u8 data[55];
34 u8 size;
35 };
36
37 struct khadas_ts050_panel_data {
38 struct khadas_ts050_panel_cmd *init_code;
39 int len;
40 };
41
42 static const struct khadas_ts050_panel_cmd ts050v2_init_code[] = {
43 {0xB9, {0xFF, 0x83, 0x99}, 0x03},
44 {0xBA, {0x63, 0x23, 0x68, 0xCF}, 0x04},
45 {0xD2, {0x55}, 0x01},
46 {0xB1, {0x02, 0x04, 0x70, 0x90, 0x01, 0x32, 0x33,
47 0x11, 0x11, 0x4D, 0x57, 0x56, 0x73, 0x02, 0x02}, 0x0f},
48 {0xB2, {0x00, 0x80, 0x80, 0xAE, 0x0A, 0x0E, 0x75, 0x11, 0x00, 0x00, 0x00}, 0x0b},
49 {0xB4, {0x00, 0xFF, 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02,
50 0x00, 0x24, 0x02, 0x04, 0x0A, 0x21, 0x03, 0x00, 0x00, 0x08, 0xA6, 0x88,
51 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x24,
52 0x02, 0x04, 0x0A, 0x00, 0x00, 0x08, 0xA6, 0x00, 0x08, 0x11}, 0x2e},
53 {0xD3, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
54 0x18, 0x32, 0x10, 0x09, 0x00, 0x09, 0x32,
55 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x11, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x0A,
57 0x40}, 0x21},
58 {0xD5, {0x18, 0x18, 0x18, 0x18, 0x21, 0x20, 0x18, 0x18, 0x19, 0x19, 0x19,
59 0x19, 0x18, 0x18, 0x18, 0x18, 0x03, 0x02, 0x01, 0x00, 0x2F, 0x2F,
60 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20},
61 {0xD6, {0x18, 0x18, 0x18, 0x18, 0x20, 0x21, 0x19, 0x19, 0x18, 0x18, 0x19,
62 0x19, 0x18, 0x18, 0x18, 0x18, 0x00, 0x01, 0x02, 0x03, 0x2F, 0x2F,
63 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20},
64 {0xD8, {0x0A, 0xBE, 0xFA, 0xA0, 0x0A, 0xBE, 0xFA, 0xA0}, 0x08},
65 {0xBD, {0x01}, 0x01},
66 {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08},
67 {0xBD, {0x02}, 0x01},
68 {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08},
69 {0xBD, {0x00}, 0x01},
70 {0xE0, {0x01, 0x35, 0x41, 0x3B, 0x79, 0x81, 0x8C, 0x85, 0x8E,
71 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1, 0xB3, 0xB7, 0xC5, 0xBD, 0xC5,
72 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66, 0x73, 0x01, 0x35, 0x41, 0x3B,
73 0x79, 0x81, 0x8C, 0x85, 0x8E, 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1,
74 0xB3, 0xB7, 0xB5, 0xBD, 0xC5, 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66,
75 0x73}, 0x36},
76 {0xB6, {0x97, 0x97}, 0x02},
77 {0xCC, {0xC8}, 0x02},
78 {0xBF, {0x40, 0x41, 0x50, 0x19}, 0x04},
79 {0xC6, {0xFF, 0xF9}, 0x02},
80 {0xC0, {0x25, 0x5A}, 0x02},
81 };
82
83 /* Only the CMD1 User Command set is documented */
84 static const struct khadas_ts050_panel_cmd ts050_init_code[] = {
85 /* Select Unknown CMD Page (Undocumented) */
86 {0xff, {0xee}, 0x01},
87 /* Reload CMD1: Don't reload default value to register */
88 {0xfb, {0x01}, 0x01},
89 {0x1f, {0x45}, 0x01},
90 {0x24, {0x4f}, 0x01},
91 {0x38, {0xc8}, 0x01},
92 {0x39, {0x27}, 0x01},
93 {0x1e, {0x77}, 0x01},
94 {0x1d, {0x0f}, 0x01},
95 {0x7e, {0x71}, 0x01},
96 {0x7c, {0x03}, 0x01},
97 {0xff, {0x00}, 0x01},
98 {0xfb, {0x01}, 0x01},
99 {0x35, {0x01}, 0x01},
100 /* Select CMD2 Page0 (Undocumented) */
101 {0xff, {0x01}, 0x01},
102 /* Reload CMD1: Don't reload default value to register */
103 {0xfb, {0x01}, 0x01},
104 {0x00, {0x01}, 0x01},
105 {0x01, {0x55}, 0x01},
106 {0x02, {0x40}, 0x01},
107 {0x05, {0x40}, 0x01},
108 {0x06, {0x4a}, 0x01},
109 {0x07, {0x24}, 0x01},
110 {0x08, {0x0c}, 0x01},
111 {0x0b, {0x7d}, 0x01},
112 {0x0c, {0x7d}, 0x01},
113 {0x0e, {0xb0}, 0x01},
114 {0x0f, {0xae}, 0x01},
115 {0x11, {0x10}, 0x01},
116 {0x12, {0x10}, 0x01},
117 {0x13, {0x03}, 0x01},
118 {0x14, {0x4a}, 0x01},
119 {0x15, {0x12}, 0x01},
120 {0x16, {0x12}, 0x01},
121 {0x18, {0x00}, 0x01},
122 {0x19, {0x77}, 0x01},
123 {0x1a, {0x55}, 0x01},
124 {0x1b, {0x13}, 0x01},
125 {0x1c, {0x00}, 0x01},
126 {0x1d, {0x00}, 0x01},
127 {0x1e, {0x13}, 0x01},
128 {0x1f, {0x00}, 0x01},
129 {0x23, {0x00}, 0x01},
130 {0x24, {0x00}, 0x01},
131 {0x25, {0x00}, 0x01},
132 {0x26, {0x00}, 0x01},
133 {0x27, {0x00}, 0x01},
134 {0x28, {0x00}, 0x01},
135 {0x35, {0x00}, 0x01},
136 {0x66, {0x00}, 0x01},
137 {0x58, {0x82}, 0x01},
138 {0x59, {0x02}, 0x01},
139 {0x5a, {0x02}, 0x01},
140 {0x5b, {0x02}, 0x01},
141 {0x5c, {0x82}, 0x01},
142 {0x5d, {0x82}, 0x01},
143 {0x5e, {0x02}, 0x01},
144 {0x5f, {0x02}, 0x01},
145 {0x72, {0x31}, 0x01},
146 /* Select CMD2 Page4 (Undocumented) */
147 {0xff, {0x05}, 0x01},
148 /* Reload CMD1: Don't reload default value to register */
149 {0xfb, {0x01}, 0x01},
150 {0x00, {0x01}, 0x01},
151 {0x01, {0x0b}, 0x01},
152 {0x02, {0x0c}, 0x01},
153 {0x03, {0x09}, 0x01},
154 {0x04, {0x0a}, 0x01},
155 {0x05, {0x00}, 0x01},
156 {0x06, {0x0f}, 0x01},
157 {0x07, {0x10}, 0x01},
158 {0x08, {0x00}, 0x01},
159 {0x09, {0x00}, 0x01},
160 {0x0a, {0x00}, 0x01},
161 {0x0b, {0x00}, 0x01},
162 {0x0c, {0x00}, 0x01},
163 {0x0d, {0x13}, 0x01},
164 {0x0e, {0x15}, 0x01},
165 {0x0f, {0x17}, 0x01},
166 {0x10, {0x01}, 0x01},
167 {0x11, {0x0b}, 0x01},
168 {0x12, {0x0c}, 0x01},
169 {0x13, {0x09}, 0x01},
170 {0x14, {0x0a}, 0x01},
171 {0x15, {0x00}, 0x01},
172 {0x16, {0x0f}, 0x01},
173 {0x17, {0x10}, 0x01},
174 {0x18, {0x00}, 0x01},
175 {0x19, {0x00}, 0x01},
176 {0x1a, {0x00}, 0x01},
177 {0x1b, {0x00}, 0x01},
178 {0x1c, {0x00}, 0x01},
179 {0x1d, {0x13}, 0x01},
180 {0x1e, {0x15}, 0x01},
181 {0x1f, {0x17}, 0x01},
182 {0x20, {0x00}, 0x01},
183 {0x21, {0x03}, 0x01},
184 {0x22, {0x01}, 0x01},
185 {0x23, {0x40}, 0x01},
186 {0x24, {0x40}, 0x01},
187 {0x25, {0xed}, 0x01},
188 {0x29, {0x58}, 0x01},
189 {0x2a, {0x12}, 0x01},
190 {0x2b, {0x01}, 0x01},
191 {0x4b, {0x06}, 0x01},
192 {0x4c, {0x11}, 0x01},
193 {0x4d, {0x20}, 0x01},
194 {0x4e, {0x02}, 0x01},
195 {0x4f, {0x02}, 0x01},
196 {0x50, {0x20}, 0x01},
197 {0x51, {0x61}, 0x01},
198 {0x52, {0x01}, 0x01},
199 {0x53, {0x63}, 0x01},
200 {0x54, {0x77}, 0x01},
201 {0x55, {0xed}, 0x01},
202 {0x5b, {0x00}, 0x01},
203 {0x5c, {0x00}, 0x01},
204 {0x5d, {0x00}, 0x01},
205 {0x5e, {0x00}, 0x01},
206 {0x5f, {0x15}, 0x01},
207 {0x60, {0x75}, 0x01},
208 {0x61, {0x00}, 0x01},
209 {0x62, {0x00}, 0x01},
210 {0x63, {0x00}, 0x01},
211 {0x64, {0x00}, 0x01},
212 {0x65, {0x00}, 0x01},
213 {0x66, {0x00}, 0x01},
214 {0x67, {0x00}, 0x01},
215 {0x68, {0x04}, 0x01},
216 {0x69, {0x00}, 0x01},
217 {0x6a, {0x00}, 0x01},
218 {0x6c, {0x40}, 0x01},
219 {0x75, {0x01}, 0x01},
220 {0x76, {0x01}, 0x01},
221 {0x7a, {0x80}, 0x01},
222 {0x7b, {0xa3}, 0x01},
223 {0x7c, {0xd8}, 0x01},
224 {0x7d, {0x60}, 0x01},
225 {0x7f, {0x15}, 0x01},
226 {0x80, {0x81}, 0x01},
227 {0x83, {0x05}, 0x01},
228 {0x93, {0x08}, 0x01},
229 {0x94, {0x10}, 0x01},
230 {0x8a, {0x00}, 0x01},
231 {0x9b, {0x0f}, 0x01},
232 {0xea, {0xff}, 0x01},
233 {0xec, {0x00}, 0x01},
234 /* Select CMD2 Page0 (Undocumented) */
235 {0xff, {0x01}, 0x01},
236 /* Reload CMD1: Don't reload default value to register */
237 {0xfb, {0x01}, 0x01},
238 {0x75, {0x00}, 0x01},
239 {0x76, {0xdf}, 0x01},
240 {0x77, {0x00}, 0x01},
241 {0x78, {0xe4}, 0x01},
242 {0x79, {0x00}, 0x01},
243 {0x7a, {0xed}, 0x01},
244 {0x7b, {0x00}, 0x01},
245 {0x7c, {0xf6}, 0x01},
246 {0x7d, {0x00}, 0x01},
247 {0x7e, {0xff}, 0x01},
248 {0x7f, {0x01}, 0x01},
249 {0x80, {0x07}, 0x01},
250 {0x81, {0x01}, 0x01},
251 {0x82, {0x10}, 0x01},
252 {0x83, {0x01}, 0x01},
253 {0x84, {0x18}, 0x01},
254 {0x85, {0x01}, 0x01},
255 {0x86, {0x20}, 0x01},
256 {0x87, {0x01}, 0x01},
257 {0x88, {0x3d}, 0x01},
258 {0x89, {0x01}, 0x01},
259 {0x8a, {0x56}, 0x01},
260 {0x8b, {0x01}, 0x01},
261 {0x8c, {0x84}, 0x01},
262 {0x8d, {0x01}, 0x01},
263 {0x8e, {0xab}, 0x01},
264 {0x8f, {0x01}, 0x01},
265 {0x90, {0xec}, 0x01},
266 {0x91, {0x02}, 0x01},
267 {0x92, {0x22}, 0x01},
268 {0x93, {0x02}, 0x01},
269 {0x94, {0x23}, 0x01},
270 {0x95, {0x02}, 0x01},
271 {0x96, {0x55}, 0x01},
272 {0x97, {0x02}, 0x01},
273 {0x98, {0x8b}, 0x01},
274 {0x99, {0x02}, 0x01},
275 {0x9a, {0xaf}, 0x01},
276 {0x9b, {0x02}, 0x01},
277 {0x9c, {0xdf}, 0x01},
278 {0x9d, {0x03}, 0x01},
279 {0x9e, {0x01}, 0x01},
280 {0x9f, {0x03}, 0x01},
281 {0xa0, {0x2c}, 0x01},
282 {0xa2, {0x03}, 0x01},
283 {0xa3, {0x39}, 0x01},
284 {0xa4, {0x03}, 0x01},
285 {0xa5, {0x47}, 0x01},
286 {0xa6, {0x03}, 0x01},
287 {0xa7, {0x56}, 0x01},
288 {0xa9, {0x03}, 0x01},
289 {0xaa, {0x66}, 0x01},
290 {0xab, {0x03}, 0x01},
291 {0xac, {0x76}, 0x01},
292 {0xad, {0x03}, 0x01},
293 {0xae, {0x85}, 0x01},
294 {0xaf, {0x03}, 0x01},
295 {0xb0, {0x90}, 0x01},
296 {0xb1, {0x03}, 0x01},
297 {0xb2, {0xcb}, 0x01},
298 {0xb3, {0x00}, 0x01},
299 {0xb4, {0xdf}, 0x01},
300 {0xb5, {0x00}, 0x01},
301 {0xb6, {0xe4}, 0x01},
302 {0xb7, {0x00}, 0x01},
303 {0xb8, {0xed}, 0x01},
304 {0xb9, {0x00}, 0x01},
305 {0xba, {0xf6}, 0x01},
306 {0xbb, {0x00}, 0x01},
307 {0xbc, {0xff}, 0x01},
308 {0xbd, {0x01}, 0x01},
309 {0xbe, {0x07}, 0x01},
310 {0xbf, {0x01}, 0x01},
311 {0xc0, {0x10}, 0x01},
312 {0xc1, {0x01}, 0x01},
313 {0xc2, {0x18}, 0x01},
314 {0xc3, {0x01}, 0x01},
315 {0xc4, {0x20}, 0x01},
316 {0xc5, {0x01}, 0x01},
317 {0xc6, {0x3d}, 0x01},
318 {0xc7, {0x01}, 0x01},
319 {0xc8, {0x56}, 0x01},
320 {0xc9, {0x01}, 0x01},
321 {0xca, {0x84}, 0x01},
322 {0xcb, {0x01}, 0x01},
323 {0xcc, {0xab}, 0x01},
324 {0xcd, {0x01}, 0x01},
325 {0xce, {0xec}, 0x01},
326 {0xcf, {0x02}, 0x01},
327 {0xd0, {0x22}, 0x01},
328 {0xd1, {0x02}, 0x01},
329 {0xd2, {0x23}, 0x01},
330 {0xd3, {0x02}, 0x01},
331 {0xd4, {0x55}, 0x01},
332 {0xd5, {0x02}, 0x01},
333 {0xd6, {0x8b}, 0x01},
334 {0xd7, {0x02}, 0x01},
335 {0xd8, {0xaf}, 0x01},
336 {0xd9, {0x02}, 0x01},
337 {0xda, {0xdf}, 0x01},
338 {0xdb, {0x03}, 0x01},
339 {0xdc, {0x01}, 0x01},
340 {0xdd, {0x03}, 0x01},
341 {0xde, {0x2c}, 0x01},
342 {0xdf, {0x03}, 0x01},
343 {0xe0, {0x39}, 0x01},
344 {0xe1, {0x03}, 0x01},
345 {0xe2, {0x47}, 0x01},
346 {0xe3, {0x03}, 0x01},
347 {0xe4, {0x56}, 0x01},
348 {0xe5, {0x03}, 0x01},
349 {0xe6, {0x66}, 0x01},
350 {0xe7, {0x03}, 0x01},
351 {0xe8, {0x76}, 0x01},
352 {0xe9, {0x03}, 0x01},
353 {0xea, {0x85}, 0x01},
354 {0xeb, {0x03}, 0x01},
355 {0xec, {0x90}, 0x01},
356 {0xed, {0x03}, 0x01},
357 {0xee, {0xcb}, 0x01},
358 {0xef, {0x00}, 0x01},
359 {0xf0, {0xbb}, 0x01},
360 {0xf1, {0x00}, 0x01},
361 {0xf2, {0xc0}, 0x01},
362 {0xf3, {0x00}, 0x01},
363 {0xf4, {0xcc}, 0x01},
364 {0xf5, {0x00}, 0x01},
365 {0xf6, {0xd6}, 0x01},
366 {0xf7, {0x00}, 0x01},
367 {0xf8, {0xe1}, 0x01},
368 {0xf9, {0x00}, 0x01},
369 {0xfa, {0xea}, 0x01},
370 /* Select CMD2 Page2 (Undocumented) */
371 {0xff, {0x02}, 0x01},
372 /* Reload CMD1: Don't reload default value to register */
373 {0xfb, {0x01}, 0x01},
374 {0x00, {0x00}, 0x01},
375 {0x01, {0xf4}, 0x01},
376 {0x02, {0x00}, 0x01},
377 {0x03, {0xef}, 0x01},
378 {0x04, {0x01}, 0x01},
379 {0x05, {0x07}, 0x01},
380 {0x06, {0x01}, 0x01},
381 {0x07, {0x28}, 0x01},
382 {0x08, {0x01}, 0x01},
383 {0x09, {0x44}, 0x01},
384 {0x0a, {0x01}, 0x01},
385 {0x0b, {0x76}, 0x01},
386 {0x0c, {0x01}, 0x01},
387 {0x0d, {0xa0}, 0x01},
388 {0x0e, {0x01}, 0x01},
389 {0x0f, {0xe7}, 0x01},
390 {0x10, {0x02}, 0x01},
391 {0x11, {0x1f}, 0x01},
392 {0x12, {0x02}, 0x01},
393 {0x13, {0x22}, 0x01},
394 {0x14, {0x02}, 0x01},
395 {0x15, {0x54}, 0x01},
396 {0x16, {0x02}, 0x01},
397 {0x17, {0x8b}, 0x01},
398 {0x18, {0x02}, 0x01},
399 {0x19, {0xaf}, 0x01},
400 {0x1a, {0x02}, 0x01},
401 {0x1b, {0xe0}, 0x01},
402 {0x1c, {0x03}, 0x01},
403 {0x1d, {0x01}, 0x01},
404 {0x1e, {0x03}, 0x01},
405 {0x1f, {0x2d}, 0x01},
406 {0x20, {0x03}, 0x01},
407 {0x21, {0x39}, 0x01},
408 {0x22, {0x03}, 0x01},
409 {0x23, {0x47}, 0x01},
410 {0x24, {0x03}, 0x01},
411 {0x25, {0x57}, 0x01},
412 {0x26, {0x03}, 0x01},
413 {0x27, {0x65}, 0x01},
414 {0x28, {0x03}, 0x01},
415 {0x29, {0x77}, 0x01},
416 {0x2a, {0x03}, 0x01},
417 {0x2b, {0x85}, 0x01},
418 {0x2d, {0x03}, 0x01},
419 {0x2f, {0x8f}, 0x01},
420 {0x30, {0x03}, 0x01},
421 {0x31, {0xcb}, 0x01},
422 {0x32, {0x00}, 0x01},
423 {0x33, {0xbb}, 0x01},
424 {0x34, {0x00}, 0x01},
425 {0x35, {0xc0}, 0x01},
426 {0x36, {0x00}, 0x01},
427 {0x37, {0xcc}, 0x01},
428 {0x38, {0x00}, 0x01},
429 {0x39, {0xd6}, 0x01},
430 {0x3a, {0x00}, 0x01},
431 {0x3b, {0xe1}, 0x01},
432 {0x3d, {0x00}, 0x01},
433 {0x3f, {0xea}, 0x01},
434 {0x40, {0x00}, 0x01},
435 {0x41, {0xf4}, 0x01},
436 {0x42, {0x00}, 0x01},
437 {0x43, {0xfe}, 0x01},
438 {0x44, {0x01}, 0x01},
439 {0x45, {0x07}, 0x01},
440 {0x46, {0x01}, 0x01},
441 {0x47, {0x28}, 0x01},
442 {0x48, {0x01}, 0x01},
443 {0x49, {0x44}, 0x01},
444 {0x4a, {0x01}, 0x01},
445 {0x4b, {0x76}, 0x01},
446 {0x4c, {0x01}, 0x01},
447 {0x4d, {0xa0}, 0x01},
448 {0x4e, {0x01}, 0x01},
449 {0x4f, {0xe7}, 0x01},
450 {0x50, {0x02}, 0x01},
451 {0x51, {0x1f}, 0x01},
452 {0x52, {0x02}, 0x01},
453 {0x53, {0x22}, 0x01},
454 {0x54, {0x02}, 0x01},
455 {0x55, {0x54}, 0x01},
456 {0x56, {0x02}, 0x01},
457 {0x58, {0x8b}, 0x01},
458 {0x59, {0x02}, 0x01},
459 {0x5a, {0xaf}, 0x01},
460 {0x5b, {0x02}, 0x01},
461 {0x5c, {0xe0}, 0x01},
462 {0x5d, {0x03}, 0x01},
463 {0x5e, {0x01}, 0x01},
464 {0x5f, {0x03}, 0x01},
465 {0x60, {0x2d}, 0x01},
466 {0x61, {0x03}, 0x01},
467 {0x62, {0x39}, 0x01},
468 {0x63, {0x03}, 0x01},
469 {0x64, {0x47}, 0x01},
470 {0x65, {0x03}, 0x01},
471 {0x66, {0x57}, 0x01},
472 {0x67, {0x03}, 0x01},
473 {0x68, {0x65}, 0x01},
474 {0x69, {0x03}, 0x01},
475 {0x6a, {0x77}, 0x01},
476 {0x6b, {0x03}, 0x01},
477 {0x6c, {0x85}, 0x01},
478 {0x6d, {0x03}, 0x01},
479 {0x6e, {0x8f}, 0x01},
480 {0x6f, {0x03}, 0x01},
481 {0x70, {0xcb}, 0x01},
482 {0x71, {0x00}, 0x01},
483 {0x72, {0x00}, 0x01},
484 {0x73, {0x00}, 0x01},
485 {0x74, {0x21}, 0x01},
486 {0x75, {0x00}, 0x01},
487 {0x76, {0x4c}, 0x01},
488 {0x77, {0x00}, 0x01},
489 {0x78, {0x6b}, 0x01},
490 {0x79, {0x00}, 0x01},
491 {0x7a, {0x85}, 0x01},
492 {0x7b, {0x00}, 0x01},
493 {0x7c, {0x9a}, 0x01},
494 {0x7d, {0x00}, 0x01},
495 {0x7e, {0xad}, 0x01},
496 {0x7f, {0x00}, 0x01},
497 {0x80, {0xbe}, 0x01},
498 {0x81, {0x00}, 0x01},
499 {0x82, {0xcd}, 0x01},
500 {0x83, {0x01}, 0x01},
501 {0x84, {0x01}, 0x01},
502 {0x85, {0x01}, 0x01},
503 {0x86, {0x29}, 0x01},
504 {0x87, {0x01}, 0x01},
505 {0x88, {0x68}, 0x01},
506 {0x89, {0x01}, 0x01},
507 {0x8a, {0x98}, 0x01},
508 {0x8b, {0x01}, 0x01},
509 {0x8c, {0xe5}, 0x01},
510 {0x8d, {0x02}, 0x01},
511 {0x8e, {0x1e}, 0x01},
512 {0x8f, {0x02}, 0x01},
513 {0x90, {0x30}, 0x01},
514 {0x91, {0x02}, 0x01},
515 {0x92, {0x52}, 0x01},
516 {0x93, {0x02}, 0x01},
517 {0x94, {0x88}, 0x01},
518 {0x95, {0x02}, 0x01},
519 {0x96, {0xaa}, 0x01},
520 {0x97, {0x02}, 0x01},
521 {0x98, {0xd7}, 0x01},
522 {0x99, {0x02}, 0x01},
523 {0x9a, {0xf7}, 0x01},
524 {0x9b, {0x03}, 0x01},
525 {0x9c, {0x21}, 0x01},
526 {0x9d, {0x03}, 0x01},
527 {0x9e, {0x2e}, 0x01},
528 {0x9f, {0x03}, 0x01},
529 {0xa0, {0x3d}, 0x01},
530 {0xa2, {0x03}, 0x01},
531 {0xa3, {0x4c}, 0x01},
532 {0xa4, {0x03}, 0x01},
533 {0xa5, {0x5e}, 0x01},
534 {0xa6, {0x03}, 0x01},
535 {0xa7, {0x71}, 0x01},
536 {0xa9, {0x03}, 0x01},
537 {0xaa, {0x86}, 0x01},
538 {0xab, {0x03}, 0x01},
539 {0xac, {0x94}, 0x01},
540 {0xad, {0x03}, 0x01},
541 {0xae, {0xfa}, 0x01},
542 {0xaf, {0x00}, 0x01},
543 {0xb0, {0x00}, 0x01},
544 {0xb1, {0x00}, 0x01},
545 {0xb2, {0x21}, 0x01},
546 {0xb3, {0x00}, 0x01},
547 {0xb4, {0x4c}, 0x01},
548 {0xb5, {0x00}, 0x01},
549 {0xb6, {0x6b}, 0x01},
550 {0xb7, {0x00}, 0x01},
551 {0xb8, {0x85}, 0x01},
552 {0xb9, {0x00}, 0x01},
553 {0xba, {0x9a}, 0x01},
554 {0xbb, {0x00}, 0x01},
555 {0xbc, {0xad}, 0x01},
556 {0xbd, {0x00}, 0x01},
557 {0xbe, {0xbe}, 0x01},
558 {0xbf, {0x00}, 0x01},
559 {0xc0, {0xcd}, 0x01},
560 {0xc1, {0x01}, 0x01},
561 {0xc2, {0x01}, 0x01},
562 {0xc3, {0x01}, 0x01},
563 {0xc4, {0x29}, 0x01},
564 {0xc5, {0x01}, 0x01},
565 {0xc6, {0x68}, 0x01},
566 {0xc7, {0x01}, 0x01},
567 {0xc8, {0x98}, 0x01},
568 {0xc9, {0x01}, 0x01},
569 {0xca, {0xe5}, 0x01},
570 {0xcb, {0x02}, 0x01},
571 {0xcc, {0x1e}, 0x01},
572 {0xcd, {0x02}, 0x01},
573 {0xce, {0x20}, 0x01},
574 {0xcf, {0x02}, 0x01},
575 {0xd0, {0x52}, 0x01},
576 {0xd1, {0x02}, 0x01},
577 {0xd2, {0x88}, 0x01},
578 {0xd3, {0x02}, 0x01},
579 {0xd4, {0xaa}, 0x01},
580 {0xd5, {0x02}, 0x01},
581 {0xd6, {0xd7}, 0x01},
582 {0xd7, {0x02}, 0x01},
583 {0xd8, {0xf7}, 0x01},
584 {0xd9, {0x03}, 0x01},
585 {0xda, {0x21}, 0x01},
586 {0xdb, {0x03}, 0x01},
587 {0xdc, {0x2e}, 0x01},
588 {0xdd, {0x03}, 0x01},
589 {0xde, {0x3d}, 0x01},
590 {0xdf, {0x03}, 0x01},
591 {0xe0, {0x4c}, 0x01},
592 {0xe1, {0x03}, 0x01},
593 {0xe2, {0x5e}, 0x01},
594 {0xe3, {0x03}, 0x01},
595 {0xe4, {0x71}, 0x01},
596 {0xe5, {0x03}, 0x01},
597 {0xe6, {0x86}, 0x01},
598 {0xe7, {0x03}, 0x01},
599 {0xe8, {0x94}, 0x01},
600 {0xe9, {0x03}, 0x01},
601 {0xea, {0xfa}, 0x01},
602 /* Select CMD2 Page0 (Undocumented) */
603 {0xff, {0x01}, 0x01},
604 /* Reload CMD1: Don't reload default value to register */
605 {0xfb, {0x01}, 0x01},
606 /* Select CMD2 Page1 (Undocumented) */
607 {0xff, {0x02}, 0x01},
608 /* Reload CMD1: Don't reload default value to register */
609 {0xfb, {0x01}, 0x01},
610 /* Select CMD2 Page3 (Undocumented) */
611 {0xff, {0x04}, 0x01},
612 /* Reload CMD1: Don't reload default value to register */
613 {0xfb, {0x01}, 0x01},
614 /* Select CMD1 */
615 {0xff, {0x00}, 0x01},
616 {0xd3, {0x22}, 0x01}, /* RGBMIPICTRL: VSYNC back porch = 34 */
617 {0xd4, {0x04}, 0x01}, /* RGBMIPICTRL: VSYNC front porch = 4 */
618 };
619
620 struct khadas_ts050_panel_data ts050_panel_data = {
621 .init_code = (struct khadas_ts050_panel_cmd *)ts050_init_code,
622 .len = ARRAY_SIZE(ts050_init_code)
623 };
624
625 struct khadas_ts050_panel_data ts050v2_panel_data = {
626 .init_code = (struct khadas_ts050_panel_cmd *)ts050v2_init_code,
627 .len = ARRAY_SIZE(ts050v2_init_code)
628 };
629
630 static inline
to_khadas_ts050_panel(struct drm_panel * panel)631 struct khadas_ts050_panel *to_khadas_ts050_panel(struct drm_panel *panel)
632 {
633 return container_of(panel, struct khadas_ts050_panel, base);
634 }
635
khadas_ts050_panel_prepare(struct drm_panel * panel)636 static int khadas_ts050_panel_prepare(struct drm_panel *panel)
637 {
638 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
639 unsigned int i;
640 int err;
641
642 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
643
644 err = regulator_enable(khadas_ts050->supply);
645 if (err < 0)
646 return err;
647
648 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 1);
649
650 msleep(60);
651
652 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1);
653
654 usleep_range(10000, 11000);
655
656 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 0);
657
658 /* Select CMD2 page 4 (Undocumented) */
659 mipi_dsi_dcs_write(khadas_ts050->link, 0xff, (u8[]){ 0x05 }, 1);
660
661 /* Reload CMD1: Don't reload default value to register */
662 mipi_dsi_dcs_write(khadas_ts050->link, 0xfb, (u8[]){ 0x01 }, 1);
663
664 mipi_dsi_dcs_write(khadas_ts050->link, 0xc5, (u8[]){ 0x01 }, 1);
665
666 msleep(100);
667
668 for (i = 0; i < khadas_ts050->panel_data->len; i++) {
669 err = mipi_dsi_dcs_write(khadas_ts050->link,
670 khadas_ts050->panel_data->init_code[i].cmd,
671 &khadas_ts050->panel_data->init_code[i].data,
672 khadas_ts050->panel_data->init_code[i].size);
673 if (err < 0) {
674 dev_err(panel->dev, "failed write cmds: %d\n", err);
675 goto poweroff;
676 }
677 }
678
679 err = mipi_dsi_dcs_exit_sleep_mode(khadas_ts050->link);
680 if (err < 0) {
681 dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);
682 goto poweroff;
683 }
684
685 msleep(120);
686
687 /* Select CMD1 */
688 mipi_dsi_dcs_write(khadas_ts050->link, 0xff, (u8[]){ 0x00 }, 1);
689
690 err = mipi_dsi_dcs_set_tear_on(khadas_ts050->link,
691 MIPI_DSI_DCS_TEAR_MODE_VBLANK);
692 if (err < 0) {
693 dev_err(panel->dev, "failed to set tear on: %d\n", err);
694 goto poweroff;
695 }
696
697 err = mipi_dsi_dcs_set_display_on(khadas_ts050->link);
698 if (err < 0) {
699 dev_err(panel->dev, "failed to set display on: %d\n", err);
700 goto poweroff;
701 }
702
703 usleep_range(10000, 11000);
704
705 return 0;
706
707 poweroff:
708 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
709 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1);
710
711 regulator_disable(khadas_ts050->supply);
712
713 return err;
714 }
715
khadas_ts050_panel_unprepare(struct drm_panel * panel)716 static int khadas_ts050_panel_unprepare(struct drm_panel *panel)
717 {
718 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
719 int err;
720
721 err = mipi_dsi_dcs_enter_sleep_mode(khadas_ts050->link);
722 if (err < 0)
723 dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
724
725 msleep(150);
726
727 gpiod_set_value_cansleep(khadas_ts050->enable_gpio, 0);
728 gpiod_set_value_cansleep(khadas_ts050->reset_gpio, 1);
729
730 err = regulator_disable(khadas_ts050->supply);
731 if (err < 0)
732 return err;
733
734 return 0;
735 }
736
khadas_ts050_panel_disable(struct drm_panel * panel)737 static int khadas_ts050_panel_disable(struct drm_panel *panel)
738 {
739 struct khadas_ts050_panel *khadas_ts050 = to_khadas_ts050_panel(panel);
740 int err;
741
742 err = mipi_dsi_dcs_set_display_off(khadas_ts050->link);
743 if (err < 0)
744 dev_err(panel->dev, "failed to set display off: %d\n", err);
745
746 usleep_range(10000, 11000);
747
748 return 0;
749 }
750
751 static const struct drm_display_mode default_mode = {
752 .clock = 160000,
753 .hdisplay = 1080,
754 .hsync_start = 1080 + 117,
755 .hsync_end = 1080 + 117 + 5,
756 .htotal = 1080 + 117 + 5 + 160,
757 .vdisplay = 1920,
758 .vsync_start = 1920 + 4,
759 .vsync_end = 1920 + 4 + 3,
760 .vtotal = 1920 + 4 + 3 + 31,
761 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
762 };
763
khadas_ts050_panel_get_modes(struct drm_panel * panel,struct drm_connector * connector)764 static int khadas_ts050_panel_get_modes(struct drm_panel *panel,
765 struct drm_connector *connector)
766 {
767 struct drm_display_mode *mode;
768
769 mode = drm_mode_duplicate(connector->dev, &default_mode);
770 if (!mode) {
771 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
772 default_mode.hdisplay, default_mode.vdisplay,
773 drm_mode_vrefresh(&default_mode));
774 return -ENOMEM;
775 }
776
777 drm_mode_set_name(mode);
778
779 drm_mode_probed_add(connector, mode);
780
781 connector->display_info.width_mm = 64;
782 connector->display_info.height_mm = 118;
783 connector->display_info.bpc = 8;
784
785 return 1;
786 }
787
788 static const struct drm_panel_funcs khadas_ts050_panel_funcs = {
789 .prepare = khadas_ts050_panel_prepare,
790 .unprepare = khadas_ts050_panel_unprepare,
791 .disable = khadas_ts050_panel_disable,
792 .get_modes = khadas_ts050_panel_get_modes,
793 };
794
795 static const struct of_device_id khadas_ts050_of_match[] = {
796 { .compatible = "khadas,ts050", .data = &ts050_panel_data, },
797 { .compatible = "khadas,ts050v2", .data = &ts050v2_panel_data, },
798 { /* sentinel */ }
799 };
800 MODULE_DEVICE_TABLE(of, khadas_ts050_of_match);
801
khadas_ts050_panel_add(struct khadas_ts050_panel * khadas_ts050)802 static int khadas_ts050_panel_add(struct khadas_ts050_panel *khadas_ts050)
803 {
804 struct device *dev = &khadas_ts050->link->dev;
805 int err;
806
807 khadas_ts050->supply = devm_regulator_get(dev, "power");
808 if (IS_ERR(khadas_ts050->supply))
809 return dev_err_probe(dev, PTR_ERR(khadas_ts050->supply),
810 "failed to get power supply");
811
812 khadas_ts050->reset_gpio = devm_gpiod_get(dev, "reset",
813 GPIOD_OUT_LOW);
814 if (IS_ERR(khadas_ts050->reset_gpio))
815 return dev_err_probe(dev, PTR_ERR(khadas_ts050->reset_gpio),
816 "failed to get reset gpio");
817
818 khadas_ts050->enable_gpio = devm_gpiod_get(dev, "enable",
819 GPIOD_OUT_HIGH);
820 if (IS_ERR(khadas_ts050->enable_gpio))
821 return dev_err_probe(dev, PTR_ERR(khadas_ts050->enable_gpio),
822 "failed to get enable gpio");
823
824 drm_panel_init(&khadas_ts050->base, &khadas_ts050->link->dev,
825 &khadas_ts050_panel_funcs, DRM_MODE_CONNECTOR_DSI);
826
827 err = drm_panel_of_backlight(&khadas_ts050->base);
828 if (err)
829 return err;
830
831 drm_panel_add(&khadas_ts050->base);
832
833 return 0;
834 }
835
khadas_ts050_panel_probe(struct mipi_dsi_device * dsi)836 static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi)
837 {
838 struct khadas_ts050_panel *khadas_ts050;
839 int err;
840
841 const void *data = of_device_get_match_data(&dsi->dev);
842
843 if (!data) {
844 dev_err(&dsi->dev, "No matching data\n");
845 return -ENODEV;
846 }
847
848 dsi->lanes = 4;
849 dsi->format = MIPI_DSI_FMT_RGB888;
850 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
851 MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
852
853 khadas_ts050 = devm_kzalloc(&dsi->dev, sizeof(*khadas_ts050),
854 GFP_KERNEL);
855 if (!khadas_ts050)
856 return -ENOMEM;
857
858 khadas_ts050->panel_data = (struct khadas_ts050_panel_data *)data;
859 mipi_dsi_set_drvdata(dsi, khadas_ts050);
860 khadas_ts050->link = dsi;
861
862 err = khadas_ts050_panel_add(khadas_ts050);
863 if (err < 0)
864 return err;
865
866 err = mipi_dsi_attach(dsi);
867 if (err)
868 drm_panel_remove(&khadas_ts050->base);
869
870 return err;
871 }
872
khadas_ts050_panel_remove(struct mipi_dsi_device * dsi)873 static void khadas_ts050_panel_remove(struct mipi_dsi_device *dsi)
874 {
875 struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi);
876 int err;
877
878 err = mipi_dsi_detach(dsi);
879 if (err < 0)
880 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
881
882 drm_panel_remove(&khadas_ts050->base);
883 }
884
885 static struct mipi_dsi_driver khadas_ts050_panel_driver = {
886 .driver = {
887 .name = "panel-khadas-ts050",
888 .of_match_table = khadas_ts050_of_match,
889 },
890 .probe = khadas_ts050_panel_probe,
891 .remove = khadas_ts050_panel_remove,
892 };
893 module_mipi_dsi_driver(khadas_ts050_panel_driver);
894
895 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
896 MODULE_DESCRIPTION("Khadas TS050 panel driver");
897 MODULE_LICENSE("GPL v2");
898