Merge tag 'for-linus-5.10b-rc1c-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / gpu / drm / panel / panel-boe-tv101wum-nl6.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018 MediaTek Inc.
4  * Author: Jitao Shi <jitao.shi@mediatek.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/of_device.h>
12 #include <linux/regulator/consumer.h>
13
14 #include <drm/drm_connector.h>
15 #include <drm/drm_crtc.h>
16 #include <drm/drm_mipi_dsi.h>
17 #include <drm/drm_panel.h>
18
19 #include <video/mipi_display.h>
20
21 struct panel_desc {
22         const struct drm_display_mode *modes;
23         unsigned int bpc;
24
25         /**
26          * @width_mm: width of the panel's active display area
27          * @height_mm: height of the panel's active display area
28          */
29         struct {
30                 unsigned int width_mm;
31                 unsigned int height_mm;
32         } size;
33
34         unsigned long mode_flags;
35         enum mipi_dsi_pixel_format format;
36         const struct panel_init_cmd *init_cmds;
37         unsigned int lanes;
38         bool discharge_on_disable;
39 };
40
41 struct boe_panel {
42         struct drm_panel base;
43         struct mipi_dsi_device *dsi;
44
45         const struct panel_desc *desc;
46
47         enum drm_panel_orientation orientation;
48         struct regulator *pp1800;
49         struct regulator *avee;
50         struct regulator *avdd;
51         struct gpio_desc *enable_gpio;
52
53         bool prepared;
54 };
55
56 enum dsi_cmd_type {
57         INIT_DCS_CMD,
58         DELAY_CMD,
59 };
60
61 struct panel_init_cmd {
62         enum dsi_cmd_type type;
63         size_t len;
64         const char *data;
65 };
66
67 #define _INIT_DCS_CMD(...) { \
68         .type = INIT_DCS_CMD, \
69         .len = sizeof((char[]){__VA_ARGS__}), \
70         .data = (char[]){__VA_ARGS__} }
71
72 #define _INIT_DELAY_CMD(...) { \
73         .type = DELAY_CMD,\
74         .len = sizeof((char[]){__VA_ARGS__}), \
75         .data = (char[]){__VA_ARGS__} }
76
77 static const struct panel_init_cmd boe_init_cmd[] = {
78         _INIT_DELAY_CMD(24),
79         _INIT_DCS_CMD(0xB0, 0x05),
80         _INIT_DCS_CMD(0xB1, 0xE5),
81         _INIT_DCS_CMD(0xB3, 0x52),
82         _INIT_DCS_CMD(0xB0, 0x00),
83         _INIT_DCS_CMD(0xB3, 0x88),
84         _INIT_DCS_CMD(0xB0, 0x04),
85         _INIT_DCS_CMD(0xB8, 0x00),
86         _INIT_DCS_CMD(0xB0, 0x00),
87         _INIT_DCS_CMD(0xB6, 0x03),
88         _INIT_DCS_CMD(0xBA, 0x8B),
89         _INIT_DCS_CMD(0xBF, 0x1A),
90         _INIT_DCS_CMD(0xC0, 0x0F),
91         _INIT_DCS_CMD(0xC2, 0x0C),
92         _INIT_DCS_CMD(0xC3, 0x02),
93         _INIT_DCS_CMD(0xC4, 0x0C),
94         _INIT_DCS_CMD(0xC5, 0x02),
95         _INIT_DCS_CMD(0xB0, 0x01),
96         _INIT_DCS_CMD(0xE0, 0x26),
97         _INIT_DCS_CMD(0xE1, 0x26),
98         _INIT_DCS_CMD(0xDC, 0x00),
99         _INIT_DCS_CMD(0xDD, 0x00),
100         _INIT_DCS_CMD(0xCC, 0x26),
101         _INIT_DCS_CMD(0xCD, 0x26),
102         _INIT_DCS_CMD(0xC8, 0x00),
103         _INIT_DCS_CMD(0xC9, 0x00),
104         _INIT_DCS_CMD(0xD2, 0x03),
105         _INIT_DCS_CMD(0xD3, 0x03),
106         _INIT_DCS_CMD(0xE6, 0x04),
107         _INIT_DCS_CMD(0xE7, 0x04),
108         _INIT_DCS_CMD(0xC4, 0x09),
109         _INIT_DCS_CMD(0xC5, 0x09),
110         _INIT_DCS_CMD(0xD8, 0x0A),
111         _INIT_DCS_CMD(0xD9, 0x0A),
112         _INIT_DCS_CMD(0xC2, 0x0B),
113         _INIT_DCS_CMD(0xC3, 0x0B),
114         _INIT_DCS_CMD(0xD6, 0x0C),
115         _INIT_DCS_CMD(0xD7, 0x0C),
116         _INIT_DCS_CMD(0xC0, 0x05),
117         _INIT_DCS_CMD(0xC1, 0x05),
118         _INIT_DCS_CMD(0xD4, 0x06),
119         _INIT_DCS_CMD(0xD5, 0x06),
120         _INIT_DCS_CMD(0xCA, 0x07),
121         _INIT_DCS_CMD(0xCB, 0x07),
122         _INIT_DCS_CMD(0xDE, 0x08),
123         _INIT_DCS_CMD(0xDF, 0x08),
124         _INIT_DCS_CMD(0xB0, 0x02),
125         _INIT_DCS_CMD(0xC0, 0x00),
126         _INIT_DCS_CMD(0xC1, 0x0D),
127         _INIT_DCS_CMD(0xC2, 0x17),
128         _INIT_DCS_CMD(0xC3, 0x26),
129         _INIT_DCS_CMD(0xC4, 0x31),
130         _INIT_DCS_CMD(0xC5, 0x1C),
131         _INIT_DCS_CMD(0xC6, 0x2C),
132         _INIT_DCS_CMD(0xC7, 0x33),
133         _INIT_DCS_CMD(0xC8, 0x31),
134         _INIT_DCS_CMD(0xC9, 0x37),
135         _INIT_DCS_CMD(0xCA, 0x37),
136         _INIT_DCS_CMD(0xCB, 0x37),
137         _INIT_DCS_CMD(0xCC, 0x39),
138         _INIT_DCS_CMD(0xCD, 0x2E),
139         _INIT_DCS_CMD(0xCE, 0x2F),
140         _INIT_DCS_CMD(0xCF, 0x2F),
141         _INIT_DCS_CMD(0xD0, 0x07),
142         _INIT_DCS_CMD(0xD2, 0x00),
143         _INIT_DCS_CMD(0xD3, 0x0D),
144         _INIT_DCS_CMD(0xD4, 0x17),
145         _INIT_DCS_CMD(0xD5, 0x26),
146         _INIT_DCS_CMD(0xD6, 0x31),
147         _INIT_DCS_CMD(0xD7, 0x3F),
148         _INIT_DCS_CMD(0xD8, 0x3F),
149         _INIT_DCS_CMD(0xD9, 0x3F),
150         _INIT_DCS_CMD(0xDA, 0x3F),
151         _INIT_DCS_CMD(0xDB, 0x37),
152         _INIT_DCS_CMD(0xDC, 0x37),
153         _INIT_DCS_CMD(0xDD, 0x37),
154         _INIT_DCS_CMD(0xDE, 0x39),
155         _INIT_DCS_CMD(0xDF, 0x2E),
156         _INIT_DCS_CMD(0xE0, 0x2F),
157         _INIT_DCS_CMD(0xE1, 0x2F),
158         _INIT_DCS_CMD(0xE2, 0x07),
159         _INIT_DCS_CMD(0xB0, 0x03),
160         _INIT_DCS_CMD(0xC8, 0x0B),
161         _INIT_DCS_CMD(0xC9, 0x07),
162         _INIT_DCS_CMD(0xC3, 0x00),
163         _INIT_DCS_CMD(0xE7, 0x00),
164         _INIT_DCS_CMD(0xC5, 0x2A),
165         _INIT_DCS_CMD(0xDE, 0x2A),
166         _INIT_DCS_CMD(0xCA, 0x43),
167         _INIT_DCS_CMD(0xC9, 0x07),
168         _INIT_DCS_CMD(0xE4, 0xC0),
169         _INIT_DCS_CMD(0xE5, 0x0D),
170         _INIT_DCS_CMD(0xCB, 0x00),
171         _INIT_DCS_CMD(0xB0, 0x06),
172         _INIT_DCS_CMD(0xB8, 0xA5),
173         _INIT_DCS_CMD(0xC0, 0xA5),
174         _INIT_DCS_CMD(0xC7, 0x0F),
175         _INIT_DCS_CMD(0xD5, 0x32),
176         _INIT_DCS_CMD(0xB8, 0x00),
177         _INIT_DCS_CMD(0xC0, 0x00),
178         _INIT_DCS_CMD(0xBC, 0x00),
179         _INIT_DCS_CMD(0xB0, 0x07),
180         _INIT_DCS_CMD(0xB1, 0x00),
181         _INIT_DCS_CMD(0xB2, 0x02),
182         _INIT_DCS_CMD(0xB3, 0x0F),
183         _INIT_DCS_CMD(0xB4, 0x25),
184         _INIT_DCS_CMD(0xB5, 0x39),
185         _INIT_DCS_CMD(0xB6, 0x4E),
186         _INIT_DCS_CMD(0xB7, 0x72),
187         _INIT_DCS_CMD(0xB8, 0x97),
188         _INIT_DCS_CMD(0xB9, 0xDC),
189         _INIT_DCS_CMD(0xBA, 0x22),
190         _INIT_DCS_CMD(0xBB, 0xA4),
191         _INIT_DCS_CMD(0xBC, 0x2B),
192         _INIT_DCS_CMD(0xBD, 0x2F),
193         _INIT_DCS_CMD(0xBE, 0xA9),
194         _INIT_DCS_CMD(0xBF, 0x25),
195         _INIT_DCS_CMD(0xC0, 0x61),
196         _INIT_DCS_CMD(0xC1, 0x97),
197         _INIT_DCS_CMD(0xC2, 0xB2),
198         _INIT_DCS_CMD(0xC3, 0xCD),
199         _INIT_DCS_CMD(0xC4, 0xD9),
200         _INIT_DCS_CMD(0xC5, 0xE7),
201         _INIT_DCS_CMD(0xC6, 0xF4),
202         _INIT_DCS_CMD(0xC7, 0xFA),
203         _INIT_DCS_CMD(0xC8, 0xFC),
204         _INIT_DCS_CMD(0xC9, 0x00),
205         _INIT_DCS_CMD(0xCA, 0x00),
206         _INIT_DCS_CMD(0xCB, 0x16),
207         _INIT_DCS_CMD(0xCC, 0xAF),
208         _INIT_DCS_CMD(0xCD, 0xFF),
209         _INIT_DCS_CMD(0xCE, 0xFF),
210         _INIT_DCS_CMD(0xB0, 0x08),
211         _INIT_DCS_CMD(0xB1, 0x04),
212         _INIT_DCS_CMD(0xB2, 0x05),
213         _INIT_DCS_CMD(0xB3, 0x11),
214         _INIT_DCS_CMD(0xB4, 0x24),
215         _INIT_DCS_CMD(0xB5, 0x39),
216         _INIT_DCS_CMD(0xB6, 0x4F),
217         _INIT_DCS_CMD(0xB7, 0x72),
218         _INIT_DCS_CMD(0xB8, 0x98),
219         _INIT_DCS_CMD(0xB9, 0xDC),
220         _INIT_DCS_CMD(0xBA, 0x23),
221         _INIT_DCS_CMD(0xBB, 0xA6),
222         _INIT_DCS_CMD(0xBC, 0x2C),
223         _INIT_DCS_CMD(0xBD, 0x30),
224         _INIT_DCS_CMD(0xBE, 0xAA),
225         _INIT_DCS_CMD(0xBF, 0x26),
226         _INIT_DCS_CMD(0xC0, 0x62),
227         _INIT_DCS_CMD(0xC1, 0x9B),
228         _INIT_DCS_CMD(0xC2, 0xB5),
229         _INIT_DCS_CMD(0xC3, 0xCF),
230         _INIT_DCS_CMD(0xC4, 0xDB),
231         _INIT_DCS_CMD(0xC5, 0xE8),
232         _INIT_DCS_CMD(0xC6, 0xF5),
233         _INIT_DCS_CMD(0xC7, 0xFA),
234         _INIT_DCS_CMD(0xC8, 0xFC),
235         _INIT_DCS_CMD(0xC9, 0x00),
236         _INIT_DCS_CMD(0xCA, 0x00),
237         _INIT_DCS_CMD(0xCB, 0x16),
238         _INIT_DCS_CMD(0xCC, 0xAF),
239         _INIT_DCS_CMD(0xCD, 0xFF),
240         _INIT_DCS_CMD(0xCE, 0xFF),
241         _INIT_DCS_CMD(0xB0, 0x09),
242         _INIT_DCS_CMD(0xB1, 0x04),
243         _INIT_DCS_CMD(0xB2, 0x02),
244         _INIT_DCS_CMD(0xB3, 0x16),
245         _INIT_DCS_CMD(0xB4, 0x24),
246         _INIT_DCS_CMD(0xB5, 0x3B),
247         _INIT_DCS_CMD(0xB6, 0x4F),
248         _INIT_DCS_CMD(0xB7, 0x73),
249         _INIT_DCS_CMD(0xB8, 0x99),
250         _INIT_DCS_CMD(0xB9, 0xE0),
251         _INIT_DCS_CMD(0xBA, 0x26),
252         _INIT_DCS_CMD(0xBB, 0xAD),
253         _INIT_DCS_CMD(0xBC, 0x36),
254         _INIT_DCS_CMD(0xBD, 0x3A),
255         _INIT_DCS_CMD(0xBE, 0xAE),
256         _INIT_DCS_CMD(0xBF, 0x2A),
257         _INIT_DCS_CMD(0xC0, 0x66),
258         _INIT_DCS_CMD(0xC1, 0x9E),
259         _INIT_DCS_CMD(0xC2, 0xB8),
260         _INIT_DCS_CMD(0xC3, 0xD1),
261         _INIT_DCS_CMD(0xC4, 0xDD),
262         _INIT_DCS_CMD(0xC5, 0xE9),
263         _INIT_DCS_CMD(0xC6, 0xF6),
264         _INIT_DCS_CMD(0xC7, 0xFA),
265         _INIT_DCS_CMD(0xC8, 0xFC),
266         _INIT_DCS_CMD(0xC9, 0x00),
267         _INIT_DCS_CMD(0xCA, 0x00),
268         _INIT_DCS_CMD(0xCB, 0x16),
269         _INIT_DCS_CMD(0xCC, 0xAF),
270         _INIT_DCS_CMD(0xCD, 0xFF),
271         _INIT_DCS_CMD(0xCE, 0xFF),
272         _INIT_DCS_CMD(0xB0, 0x0A),
273         _INIT_DCS_CMD(0xB1, 0x00),
274         _INIT_DCS_CMD(0xB2, 0x02),
275         _INIT_DCS_CMD(0xB3, 0x0F),
276         _INIT_DCS_CMD(0xB4, 0x25),
277         _INIT_DCS_CMD(0xB5, 0x39),
278         _INIT_DCS_CMD(0xB6, 0x4E),
279         _INIT_DCS_CMD(0xB7, 0x72),
280         _INIT_DCS_CMD(0xB8, 0x97),
281         _INIT_DCS_CMD(0xB9, 0xDC),
282         _INIT_DCS_CMD(0xBA, 0x22),
283         _INIT_DCS_CMD(0xBB, 0xA4),
284         _INIT_DCS_CMD(0xBC, 0x2B),
285         _INIT_DCS_CMD(0xBD, 0x2F),
286         _INIT_DCS_CMD(0xBE, 0xA9),
287         _INIT_DCS_CMD(0xBF, 0x25),
288         _INIT_DCS_CMD(0xC0, 0x61),
289         _INIT_DCS_CMD(0xC1, 0x97),
290         _INIT_DCS_CMD(0xC2, 0xB2),
291         _INIT_DCS_CMD(0xC3, 0xCD),
292         _INIT_DCS_CMD(0xC4, 0xD9),
293         _INIT_DCS_CMD(0xC5, 0xE7),
294         _INIT_DCS_CMD(0xC6, 0xF4),
295         _INIT_DCS_CMD(0xC7, 0xFA),
296         _INIT_DCS_CMD(0xC8, 0xFC),
297         _INIT_DCS_CMD(0xC9, 0x00),
298         _INIT_DCS_CMD(0xCA, 0x00),
299         _INIT_DCS_CMD(0xCB, 0x16),
300         _INIT_DCS_CMD(0xCC, 0xAF),
301         _INIT_DCS_CMD(0xCD, 0xFF),
302         _INIT_DCS_CMD(0xCE, 0xFF),
303         _INIT_DCS_CMD(0xB0, 0x0B),
304         _INIT_DCS_CMD(0xB1, 0x04),
305         _INIT_DCS_CMD(0xB2, 0x05),
306         _INIT_DCS_CMD(0xB3, 0x11),
307         _INIT_DCS_CMD(0xB4, 0x24),
308         _INIT_DCS_CMD(0xB5, 0x39),
309         _INIT_DCS_CMD(0xB6, 0x4F),
310         _INIT_DCS_CMD(0xB7, 0x72),
311         _INIT_DCS_CMD(0xB8, 0x98),
312         _INIT_DCS_CMD(0xB9, 0xDC),
313         _INIT_DCS_CMD(0xBA, 0x23),
314         _INIT_DCS_CMD(0xBB, 0xA6),
315         _INIT_DCS_CMD(0xBC, 0x2C),
316         _INIT_DCS_CMD(0xBD, 0x30),
317         _INIT_DCS_CMD(0xBE, 0xAA),
318         _INIT_DCS_CMD(0xBF, 0x26),
319         _INIT_DCS_CMD(0xC0, 0x62),
320         _INIT_DCS_CMD(0xC1, 0x9B),
321         _INIT_DCS_CMD(0xC2, 0xB5),
322         _INIT_DCS_CMD(0xC3, 0xCF),
323         _INIT_DCS_CMD(0xC4, 0xDB),
324         _INIT_DCS_CMD(0xC5, 0xE8),
325         _INIT_DCS_CMD(0xC6, 0xF5),
326         _INIT_DCS_CMD(0xC7, 0xFA),
327         _INIT_DCS_CMD(0xC8, 0xFC),
328         _INIT_DCS_CMD(0xC9, 0x00),
329         _INIT_DCS_CMD(0xCA, 0x00),
330         _INIT_DCS_CMD(0xCB, 0x16),
331         _INIT_DCS_CMD(0xCC, 0xAF),
332         _INIT_DCS_CMD(0xCD, 0xFF),
333         _INIT_DCS_CMD(0xCE, 0xFF),
334         _INIT_DCS_CMD(0xB0, 0x0C),
335         _INIT_DCS_CMD(0xB1, 0x04),
336         _INIT_DCS_CMD(0xB2, 0x02),
337         _INIT_DCS_CMD(0xB3, 0x16),
338         _INIT_DCS_CMD(0xB4, 0x24),
339         _INIT_DCS_CMD(0xB5, 0x3B),
340         _INIT_DCS_CMD(0xB6, 0x4F),
341         _INIT_DCS_CMD(0xB7, 0x73),
342         _INIT_DCS_CMD(0xB8, 0x99),
343         _INIT_DCS_CMD(0xB9, 0xE0),
344         _INIT_DCS_CMD(0xBA, 0x26),
345         _INIT_DCS_CMD(0xBB, 0xAD),
346         _INIT_DCS_CMD(0xBC, 0x36),
347         _INIT_DCS_CMD(0xBD, 0x3A),
348         _INIT_DCS_CMD(0xBE, 0xAE),
349         _INIT_DCS_CMD(0xBF, 0x2A),
350         _INIT_DCS_CMD(0xC0, 0x66),
351         _INIT_DCS_CMD(0xC1, 0x9E),
352         _INIT_DCS_CMD(0xC2, 0xB8),
353         _INIT_DCS_CMD(0xC3, 0xD1),
354         _INIT_DCS_CMD(0xC4, 0xDD),
355         _INIT_DCS_CMD(0xC5, 0xE9),
356         _INIT_DCS_CMD(0xC6, 0xF6),
357         _INIT_DCS_CMD(0xC7, 0xFA),
358         _INIT_DCS_CMD(0xC8, 0xFC),
359         _INIT_DCS_CMD(0xC9, 0x00),
360         _INIT_DCS_CMD(0xCA, 0x00),
361         _INIT_DCS_CMD(0xCB, 0x16),
362         _INIT_DCS_CMD(0xCC, 0xAF),
363         _INIT_DCS_CMD(0xCD, 0xFF),
364         _INIT_DCS_CMD(0xCE, 0xFF),
365         _INIT_DCS_CMD(0xB0, 0x00),
366         _INIT_DCS_CMD(0xB3, 0x08),
367         _INIT_DCS_CMD(0xB0, 0x04),
368         _INIT_DCS_CMD(0xB8, 0x68),
369         _INIT_DELAY_CMD(150),
370         {},
371 };
372
373 static const struct panel_init_cmd auo_kd101n80_45na_init_cmd[] = {
374         _INIT_DELAY_CMD(24),
375         _INIT_DCS_CMD(0x11),
376         _INIT_DELAY_CMD(120),
377         _INIT_DCS_CMD(0x29),
378         _INIT_DELAY_CMD(120),
379         {},
380 };
381
382 static const struct panel_init_cmd auo_b101uan08_3_init_cmd[] = {
383         _INIT_DELAY_CMD(24),
384         _INIT_DCS_CMD(0xB0, 0x01),
385         _INIT_DCS_CMD(0xC0, 0x48),
386         _INIT_DCS_CMD(0xC1, 0x48),
387         _INIT_DCS_CMD(0xC2, 0x47),
388         _INIT_DCS_CMD(0xC3, 0x47),
389         _INIT_DCS_CMD(0xC4, 0x46),
390         _INIT_DCS_CMD(0xC5, 0x46),
391         _INIT_DCS_CMD(0xC6, 0x45),
392         _INIT_DCS_CMD(0xC7, 0x45),
393         _INIT_DCS_CMD(0xC8, 0x64),
394         _INIT_DCS_CMD(0xC9, 0x64),
395         _INIT_DCS_CMD(0xCA, 0x4F),
396         _INIT_DCS_CMD(0xCB, 0x4F),
397         _INIT_DCS_CMD(0xCC, 0x40),
398         _INIT_DCS_CMD(0xCD, 0x40),
399         _INIT_DCS_CMD(0xCE, 0x66),
400         _INIT_DCS_CMD(0xCF, 0x66),
401         _INIT_DCS_CMD(0xD0, 0x4F),
402         _INIT_DCS_CMD(0xD1, 0x4F),
403         _INIT_DCS_CMD(0xD2, 0x41),
404         _INIT_DCS_CMD(0xD3, 0x41),
405         _INIT_DCS_CMD(0xD4, 0x48),
406         _INIT_DCS_CMD(0xD5, 0x48),
407         _INIT_DCS_CMD(0xD6, 0x47),
408         _INIT_DCS_CMD(0xD7, 0x47),
409         _INIT_DCS_CMD(0xD8, 0x46),
410         _INIT_DCS_CMD(0xD9, 0x46),
411         _INIT_DCS_CMD(0xDA, 0x45),
412         _INIT_DCS_CMD(0xDB, 0x45),
413         _INIT_DCS_CMD(0xDC, 0x64),
414         _INIT_DCS_CMD(0xDD, 0x64),
415         _INIT_DCS_CMD(0xDE, 0x4F),
416         _INIT_DCS_CMD(0xDF, 0x4F),
417         _INIT_DCS_CMD(0xE0, 0x40),
418         _INIT_DCS_CMD(0xE1, 0x40),
419         _INIT_DCS_CMD(0xE2, 0x66),
420         _INIT_DCS_CMD(0xE3, 0x66),
421         _INIT_DCS_CMD(0xE4, 0x4F),
422         _INIT_DCS_CMD(0xE5, 0x4F),
423         _INIT_DCS_CMD(0xE6, 0x41),
424         _INIT_DCS_CMD(0xE7, 0x41),
425         _INIT_DELAY_CMD(150),
426         {},
427 };
428
429 static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
430 {
431         return container_of(panel, struct boe_panel, base);
432 }
433
434 static int boe_panel_init_dcs_cmd(struct boe_panel *boe)
435 {
436         struct mipi_dsi_device *dsi = boe->dsi;
437         struct drm_panel *panel = &boe->base;
438         int i, err = 0;
439
440         if (boe->desc->init_cmds) {
441                 const struct panel_init_cmd *init_cmds = boe->desc->init_cmds;
442
443                 for (i = 0; init_cmds[i].len != 0; i++) {
444                         const struct panel_init_cmd *cmd = &init_cmds[i];
445
446                         switch (cmd->type) {
447                         case DELAY_CMD:
448                                 msleep(cmd->data[0]);
449                                 err = 0;
450                                 break;
451
452                         case INIT_DCS_CMD:
453                                 err = mipi_dsi_dcs_write(dsi, cmd->data[0],
454                                                          cmd->len <= 1 ? NULL :
455                                                          &cmd->data[1],
456                                                          cmd->len - 1);
457                                 break;
458
459                         default:
460                                 err = -EINVAL;
461                         }
462
463                         if (err < 0) {
464                                 dev_err(panel->dev,
465                                         "failed to write command %u\n", i);
466                                 return err;
467                         }
468                 }
469         }
470         return 0;
471 }
472
473 static int boe_panel_enter_sleep_mode(struct boe_panel *boe)
474 {
475         struct mipi_dsi_device *dsi = boe->dsi;
476         int ret;
477
478         dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
479
480         ret = mipi_dsi_dcs_set_display_off(dsi);
481         if (ret < 0)
482                 return ret;
483
484         ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
485         if (ret < 0)
486                 return ret;
487
488         return 0;
489 }
490
491 static int boe_panel_unprepare(struct drm_panel *panel)
492 {
493         struct boe_panel *boe = to_boe_panel(panel);
494         int ret;
495
496         if (!boe->prepared)
497                 return 0;
498
499         ret = boe_panel_enter_sleep_mode(boe);
500         if (ret < 0) {
501                 dev_err(panel->dev, "failed to set panel off: %d\n", ret);
502                 return ret;
503         }
504
505         msleep(150);
506
507         if (boe->desc->discharge_on_disable) {
508                 regulator_disable(boe->avee);
509                 regulator_disable(boe->avdd);
510                 usleep_range(5000, 7000);
511                 gpiod_set_value(boe->enable_gpio, 0);
512                 usleep_range(5000, 7000);
513                 regulator_disable(boe->pp1800);
514         } else {
515                 gpiod_set_value(boe->enable_gpio, 0);
516                 usleep_range(500, 1000);
517                 regulator_disable(boe->avee);
518                 regulator_disable(boe->avdd);
519                 usleep_range(5000, 7000);
520                 regulator_disable(boe->pp1800);
521         }
522
523         boe->prepared = false;
524
525         return 0;
526 }
527
528 static int boe_panel_prepare(struct drm_panel *panel)
529 {
530         struct boe_panel *boe = to_boe_panel(panel);
531         int ret;
532
533         if (boe->prepared)
534                 return 0;
535
536         gpiod_set_value(boe->enable_gpio, 0);
537         usleep_range(1000, 1500);
538
539         ret = regulator_enable(boe->pp1800);
540         if (ret < 0)
541                 return ret;
542
543         usleep_range(3000, 5000);
544
545         ret = regulator_enable(boe->avdd);
546         if (ret < 0)
547                 goto poweroff1v8;
548         ret = regulator_enable(boe->avee);
549         if (ret < 0)
550                 goto poweroffavdd;
551
552         usleep_range(5000, 10000);
553
554         gpiod_set_value(boe->enable_gpio, 1);
555         usleep_range(1000, 2000);
556         gpiod_set_value(boe->enable_gpio, 0);
557         usleep_range(1000, 2000);
558         gpiod_set_value(boe->enable_gpio, 1);
559         usleep_range(6000, 10000);
560
561         ret = boe_panel_init_dcs_cmd(boe);
562         if (ret < 0) {
563                 dev_err(panel->dev, "failed to init panel: %d\n", ret);
564                 goto poweroff;
565         }
566
567         boe->prepared = true;
568
569         return 0;
570
571 poweroff:
572         regulator_disable(boe->avee);
573 poweroffavdd:
574         regulator_disable(boe->avdd);
575 poweroff1v8:
576         usleep_range(5000, 7000);
577         regulator_disable(boe->pp1800);
578         gpiod_set_value(boe->enable_gpio, 0);
579
580         return ret;
581 }
582
583 static int boe_panel_enable(struct drm_panel *panel)
584 {
585         msleep(130);
586         return 0;
587 }
588
589 static const struct drm_display_mode boe_tv101wum_nl6_default_mode = {
590         .clock = 159425,
591         .hdisplay = 1200,
592         .hsync_start = 1200 + 100,
593         .hsync_end = 1200 + 100 + 40,
594         .htotal = 1200 + 100 + 40 + 24,
595         .vdisplay = 1920,
596         .vsync_start = 1920 + 10,
597         .vsync_end = 1920 + 10 + 14,
598         .vtotal = 1920 + 10 + 14 + 4,
599 };
600
601 static const struct panel_desc boe_tv101wum_nl6_desc = {
602         .modes = &boe_tv101wum_nl6_default_mode,
603         .bpc = 8,
604         .size = {
605                 .width_mm = 135,
606                 .height_mm = 216,
607         },
608         .lanes = 4,
609         .format = MIPI_DSI_FMT_RGB888,
610         .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
611                       MIPI_DSI_MODE_LPM,
612         .init_cmds = boe_init_cmd,
613         .discharge_on_disable = false,
614 };
615
616 static const struct drm_display_mode auo_kd101n80_45na_default_mode = {
617         .clock = 157000,
618         .hdisplay = 1200,
619         .hsync_start = 1200 + 60,
620         .hsync_end = 1200 + 60 + 24,
621         .htotal = 1200 + 60 + 24 + 56,
622         .vdisplay = 1920,
623         .vsync_start = 1920 + 16,
624         .vsync_end = 1920 + 16 + 4,
625         .vtotal = 1920 + 16 + 4 + 16,
626 };
627
628 static const struct panel_desc auo_kd101n80_45na_desc = {
629         .modes = &auo_kd101n80_45na_default_mode,
630         .bpc = 8,
631         .size = {
632                 .width_mm = 135,
633                 .height_mm = 216,
634         },
635         .lanes = 4,
636         .format = MIPI_DSI_FMT_RGB888,
637         .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
638                       MIPI_DSI_MODE_LPM,
639         .init_cmds = auo_kd101n80_45na_init_cmd,
640         .discharge_on_disable = true,
641 };
642
643 static const struct drm_display_mode boe_tv101wum_n53_default_mode = {
644         .clock = 159916,
645         .hdisplay = 1200,
646         .hsync_start = 1200 + 80,
647         .hsync_end = 1200 + 80 + 24,
648         .htotal = 1200 + 80 + 24 + 60,
649         .vdisplay = 1920,
650         .vsync_start = 1920 + 20,
651         .vsync_end = 1920 + 20 + 4,
652         .vtotal = 1920 + 20 + 4 + 10,
653         .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
654 };
655
656 static const struct panel_desc boe_tv101wum_n53_desc = {
657         .modes = &boe_tv101wum_n53_default_mode,
658         .bpc = 8,
659         .size = {
660                 .width_mm = 135,
661                 .height_mm = 216,
662         },
663         .lanes = 4,
664         .format = MIPI_DSI_FMT_RGB888,
665         .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
666                       MIPI_DSI_MODE_LPM,
667         .init_cmds = boe_init_cmd,
668 };
669
670 static const struct drm_display_mode auo_b101uan08_3_default_mode = {
671         .clock = 159667,
672         .hdisplay = 1200,
673         .hsync_start = 1200 + 60,
674         .hsync_end = 1200 + 60 + 4,
675         .htotal = 1200 + 60 + 4 + 80,
676         .vdisplay = 1920,
677         .vsync_start = 1920 + 34,
678         .vsync_end = 1920 + 34 + 2,
679         .vtotal = 1920 + 34 + 2 + 24,
680         .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
681 };
682
683 static const struct panel_desc auo_b101uan08_3_desc = {
684         .modes = &auo_b101uan08_3_default_mode,
685         .bpc = 8,
686         .size = {
687                 .width_mm = 135,
688                 .height_mm = 216,
689         },
690         .lanes = 4,
691         .format = MIPI_DSI_FMT_RGB888,
692         .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
693                       MIPI_DSI_MODE_LPM,
694         .init_cmds = auo_b101uan08_3_init_cmd,
695 };
696
697 static const struct drm_display_mode boe_tv105wum_nw0_default_mode = {
698         .clock = 159916,
699         .hdisplay = 1200,
700         .hsync_start = 1200 + 80,
701         .hsync_end = 1200 + 80 + 24,
702         .htotal = 1200 + 80 + 24 + 60,
703         .vdisplay = 1920,
704         .vsync_start = 1920 + 20,
705         .vsync_end = 1920 + 20 + 4,
706         .vtotal = 1920 + 20 + 4 + 10,
707         .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
708 };
709
710 static const struct panel_desc boe_tv105wum_nw0_desc = {
711         .modes = &boe_tv105wum_nw0_default_mode,
712         .bpc = 8,
713         .size = {
714                 .width_mm = 141,
715                 .height_mm = 226,
716         },
717         .lanes = 4,
718         .format = MIPI_DSI_FMT_RGB888,
719         .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
720                       MIPI_DSI_MODE_LPM,
721         .init_cmds = boe_init_cmd,
722 };
723
724 static int boe_panel_get_modes(struct drm_panel *panel,
725                                struct drm_connector *connector)
726 {
727         struct boe_panel *boe = to_boe_panel(panel);
728         const struct drm_display_mode *m = boe->desc->modes;
729         struct drm_display_mode *mode;
730
731         mode = drm_mode_duplicate(connector->dev, m);
732         if (!mode) {
733                 dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
734                         m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
735                 return -ENOMEM;
736         }
737
738         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
739         drm_mode_set_name(mode);
740         drm_mode_probed_add(connector, mode);
741
742         connector->display_info.width_mm = boe->desc->size.width_mm;
743         connector->display_info.height_mm = boe->desc->size.height_mm;
744         connector->display_info.bpc = boe->desc->bpc;
745         drm_connector_set_panel_orientation(connector, boe->orientation);
746
747         return 1;
748 }
749
750 static const struct drm_panel_funcs boe_panel_funcs = {
751         .unprepare = boe_panel_unprepare,
752         .prepare = boe_panel_prepare,
753         .enable = boe_panel_enable,
754         .get_modes = boe_panel_get_modes,
755 };
756
757 static int boe_panel_add(struct boe_panel *boe)
758 {
759         struct device *dev = &boe->dsi->dev;
760         int err;
761
762         boe->avdd = devm_regulator_get(dev, "avdd");
763         if (IS_ERR(boe->avdd))
764                 return PTR_ERR(boe->avdd);
765
766         boe->avee = devm_regulator_get(dev, "avee");
767         if (IS_ERR(boe->avee))
768                 return PTR_ERR(boe->avee);
769
770         boe->pp1800 = devm_regulator_get(dev, "pp1800");
771         if (IS_ERR(boe->pp1800))
772                 return PTR_ERR(boe->pp1800);
773
774         boe->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
775         if (IS_ERR(boe->enable_gpio)) {
776                 dev_err(dev, "cannot get reset-gpios %ld\n",
777                         PTR_ERR(boe->enable_gpio));
778                 return PTR_ERR(boe->enable_gpio);
779         }
780
781         gpiod_set_value(boe->enable_gpio, 0);
782
783         drm_panel_init(&boe->base, dev, &boe_panel_funcs,
784                        DRM_MODE_CONNECTOR_DSI);
785         err = of_drm_get_panel_orientation(dev->of_node, &boe->orientation);
786         if (err < 0) {
787                 dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);
788                 return err;
789         }
790
791         err = drm_panel_of_backlight(&boe->base);
792         if (err)
793                 return err;
794
795         boe->base.funcs = &boe_panel_funcs;
796         boe->base.dev = &boe->dsi->dev;
797
798         drm_panel_add(&boe->base);
799
800         return 0;
801 }
802
803 static int boe_panel_probe(struct mipi_dsi_device *dsi)
804 {
805         struct boe_panel *boe;
806         int ret;
807         const struct panel_desc *desc;
808
809         boe = devm_kzalloc(&dsi->dev, sizeof(*boe), GFP_KERNEL);
810         if (!boe)
811                 return -ENOMEM;
812
813         desc = of_device_get_match_data(&dsi->dev);
814         dsi->lanes = desc->lanes;
815         dsi->format = desc->format;
816         dsi->mode_flags = desc->mode_flags;
817         boe->desc = desc;
818         boe->dsi = dsi;
819         ret = boe_panel_add(boe);
820         if (ret < 0)
821                 return ret;
822
823         mipi_dsi_set_drvdata(dsi, boe);
824
825         ret = mipi_dsi_attach(dsi);
826         if (ret)
827                 drm_panel_remove(&boe->base);
828
829         return ret;
830 }
831
832 static void boe_panel_shutdown(struct mipi_dsi_device *dsi)
833 {
834         struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
835
836         drm_panel_disable(&boe->base);
837         drm_panel_unprepare(&boe->base);
838 }
839
840 static int boe_panel_remove(struct mipi_dsi_device *dsi)
841 {
842         struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
843         int ret;
844
845         boe_panel_shutdown(dsi);
846
847         ret = mipi_dsi_detach(dsi);
848         if (ret < 0)
849                 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
850
851         if (boe->base.dev)
852                 drm_panel_remove(&boe->base);
853
854         return 0;
855 }
856
857 static const struct of_device_id boe_of_match[] = {
858         { .compatible = "boe,tv101wum-nl6",
859           .data = &boe_tv101wum_nl6_desc
860         },
861         { .compatible = "auo,kd101n80-45na",
862           .data = &auo_kd101n80_45na_desc
863         },
864         { .compatible = "boe,tv101wum-n53",
865           .data = &boe_tv101wum_n53_desc
866         },
867         { .compatible = "auo,b101uan08.3",
868           .data = &auo_b101uan08_3_desc
869         },
870         { .compatible = "boe,tv105wum-nw0",
871           .data = &boe_tv105wum_nw0_desc
872         },
873         { /* sentinel */ }
874 };
875 MODULE_DEVICE_TABLE(of, boe_of_match);
876
877 static struct mipi_dsi_driver boe_panel_driver = {
878         .driver = {
879                 .name = "panel-boe-tv101wum-nl6",
880                 .of_match_table = boe_of_match,
881         },
882         .probe = boe_panel_probe,
883         .remove = boe_panel_remove,
884         .shutdown = boe_panel_shutdown,
885 };
886 module_mipi_dsi_driver(boe_panel_driver);
887
888 MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>");
889 MODULE_DESCRIPTION("BOE tv101wum-nl6 1200x1920 video mode panel driver");
890 MODULE_LICENSE("GPL v2");