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