xref: /linux/drivers/gpu/drm/panel/panel-novatek-nt36672e.c (revision ef9226cd56b718c79184a3466d32984a51cb449c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 
4 #include <linux/delay.h>
5 #include <linux/gpio/consumer.h>
6 #include <linux/module.h>
7 #include <linux/of.h>
8 #include <linux/regulator/consumer.h>
9 
10 #include <drm/drm_mipi_dsi.h>
11 #include <drm/drm_modes.h>
12 #include <drm/drm_panel.h>
13 
14 #include <video/mipi_display.h>
15 
16 static const char * const regulator_names[] = {
17 	"vddi",
18 	"avdd",
19 	"avee",
20 };
21 
22 static const unsigned long regulator_enable_loads[] = {
23 	62000,
24 	100000,
25 	100000,
26 };
27 
28 static const unsigned long regulator_disable_loads[] = {
29 	80,
30 	100,
31 	100,
32 };
33 
34 struct panel_desc {
35 	const struct drm_display_mode *display_mode;
36 	u32 width_mm;
37 	u32 height_mm;
38 	unsigned long mode_flags;
39 	enum mipi_dsi_pixel_format format;
40 	unsigned int lanes;
41 	const char *panel_name;
42 	int (*init_sequence)(struct mipi_dsi_device *dsi);
43 };
44 
45 struct nt36672e_panel {
46 	struct drm_panel panel;
47 	struct mipi_dsi_device *dsi;
48 	struct gpio_desc *reset_gpio;
49 	struct regulator_bulk_data supplies[3];
50 	const struct panel_desc *desc;
51 };
52 
53 static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel)
54 {
55 	return container_of(panel, struct nt36672e_panel, panel);
56 }
57 
58 static int nt36672e_1080x2408_60hz_init(struct mipi_dsi_device *dsi)
59 {
60 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
61 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
62 	mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
63 	mipi_dsi_dcs_write_seq(dsi, 0xc0, 0x00);
64 	mipi_dsi_dcs_write_seq(dsi, 0xc1, 0x89, 0x28, 0x00, 0x08, 0x00, 0xaa, 0x02,
65 				0x0e, 0x00, 0x2b, 0x00, 0x07, 0x0d, 0xb7, 0x0c, 0xb7);
66 
67 	mipi_dsi_dcs_write_seq(dsi, 0xc2, 0x1b, 0xa0);
68 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
69 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
70 	mipi_dsi_dcs_write_seq(dsi, 0x01, 0x66);
71 	mipi_dsi_dcs_write_seq(dsi, 0x06, 0x40);
72 	mipi_dsi_dcs_write_seq(dsi, 0x07, 0x38);
73 	mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x83);
74 	mipi_dsi_dcs_write_seq(dsi, 0x69, 0x91);
75 	mipi_dsi_dcs_write_seq(dsi, 0x95, 0xd1);
76 	mipi_dsi_dcs_write_seq(dsi, 0x96, 0xd1);
77 	mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x64);
78 	mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x54);
79 	mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x64);
80 	mipi_dsi_dcs_write_seq(dsi, 0xf5, 0x54);
81 	mipi_dsi_dcs_write_seq(dsi, 0xf6, 0x64);
82 	mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x54);
83 	mipi_dsi_dcs_write_seq(dsi, 0xf8, 0x64);
84 	mipi_dsi_dcs_write_seq(dsi, 0xf9, 0x54);
85 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x24);
86 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
87 	mipi_dsi_dcs_write_seq(dsi, 0x01, 0x0f);
88 	mipi_dsi_dcs_write_seq(dsi, 0x03, 0x0c);
89 	mipi_dsi_dcs_write_seq(dsi, 0x05, 0x1d);
90 	mipi_dsi_dcs_write_seq(dsi, 0x08, 0x2f);
91 	mipi_dsi_dcs_write_seq(dsi, 0x09, 0x2e);
92 	mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x2d);
93 	mipi_dsi_dcs_write_seq(dsi, 0x0b, 0x2c);
94 	mipi_dsi_dcs_write_seq(dsi, 0x11, 0x17);
95 	mipi_dsi_dcs_write_seq(dsi, 0x12, 0x13);
96 	mipi_dsi_dcs_write_seq(dsi, 0x13, 0x15);
97 	mipi_dsi_dcs_write_seq(dsi, 0x15, 0x14);
98 	mipi_dsi_dcs_write_seq(dsi, 0x16, 0x16);
99 	mipi_dsi_dcs_write_seq(dsi, 0x17, 0x18);
100 	mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x01);
101 	mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x1d);
102 	mipi_dsi_dcs_write_seq(dsi, 0x20, 0x2f);
103 	mipi_dsi_dcs_write_seq(dsi, 0x21, 0x2e);
104 	mipi_dsi_dcs_write_seq(dsi, 0x22, 0x2d);
105 	mipi_dsi_dcs_write_seq(dsi, 0x23, 0x2c);
106 	mipi_dsi_dcs_write_seq(dsi, 0x29, 0x17);
107 	mipi_dsi_dcs_write_seq(dsi, 0x2a, 0x13);
108 	mipi_dsi_dcs_write_seq(dsi, 0x2b, 0x15);
109 	mipi_dsi_dcs_write_seq(dsi, 0x2f, 0x14);
110 	mipi_dsi_dcs_write_seq(dsi, 0x30, 0x16);
111 	mipi_dsi_dcs_write_seq(dsi, 0x31, 0x18);
112 	mipi_dsi_dcs_write_seq(dsi, 0x32, 0x04);
113 	mipi_dsi_dcs_write_seq(dsi, 0x34, 0x10);
114 	mipi_dsi_dcs_write_seq(dsi, 0x35, 0x1f);
115 	mipi_dsi_dcs_write_seq(dsi, 0x36, 0x1f);
116 	mipi_dsi_dcs_write_seq(dsi, 0x4d, 0x14);
117 	mipi_dsi_dcs_write_seq(dsi, 0x4e, 0x36);
118 	mipi_dsi_dcs_write_seq(dsi, 0x4f, 0x36);
119 	mipi_dsi_dcs_write_seq(dsi, 0x53, 0x36);
120 	mipi_dsi_dcs_write_seq(dsi, 0x71, 0x30);
121 	mipi_dsi_dcs_write_seq(dsi, 0x79, 0x11);
122 	mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x82);
123 	mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x8f);
124 	mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x04);
125 	mipi_dsi_dcs_write_seq(dsi, 0x80, 0x04);
126 	mipi_dsi_dcs_write_seq(dsi, 0x81, 0x04);
127 	mipi_dsi_dcs_write_seq(dsi, 0x82, 0x13);
128 	mipi_dsi_dcs_write_seq(dsi, 0x84, 0x31);
129 	mipi_dsi_dcs_write_seq(dsi, 0x85, 0x00);
130 	mipi_dsi_dcs_write_seq(dsi, 0x86, 0x00);
131 	mipi_dsi_dcs_write_seq(dsi, 0x87, 0x00);
132 	mipi_dsi_dcs_write_seq(dsi, 0x90, 0x13);
133 	mipi_dsi_dcs_write_seq(dsi, 0x92, 0x31);
134 	mipi_dsi_dcs_write_seq(dsi, 0x93, 0x00);
135 	mipi_dsi_dcs_write_seq(dsi, 0x94, 0x00);
136 	mipi_dsi_dcs_write_seq(dsi, 0x95, 0x00);
137 	mipi_dsi_dcs_write_seq(dsi, 0x9c, 0xf4);
138 	mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x01);
139 	mipi_dsi_dcs_write_seq(dsi, 0xa0, 0x0f);
140 	mipi_dsi_dcs_write_seq(dsi, 0xa2, 0x0f);
141 	mipi_dsi_dcs_write_seq(dsi, 0xa3, 0x02);
142 	mipi_dsi_dcs_write_seq(dsi, 0xa4, 0x04);
143 	mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x04);
144 	mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xc0);
145 	mipi_dsi_dcs_write_seq(dsi, 0xc9, 0x00);
146 	mipi_dsi_dcs_write_seq(dsi, 0xd9, 0x80);
147 	mipi_dsi_dcs_write_seq(dsi, 0xe9, 0x02);
148 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x25);
149 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
150 	mipi_dsi_dcs_write_seq(dsi, 0x18, 0x22);
151 	mipi_dsi_dcs_write_seq(dsi, 0x19, 0xe4);
152 	mipi_dsi_dcs_write_seq(dsi, 0x21, 0x40);
153 	mipi_dsi_dcs_write_seq(dsi, 0x66, 0xd8);
154 	mipi_dsi_dcs_write_seq(dsi, 0x68, 0x50);
155 	mipi_dsi_dcs_write_seq(dsi, 0x69, 0x10);
156 	mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x00);
157 	mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x0d);
158 	mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x48);
159 	mipi_dsi_dcs_write_seq(dsi, 0x72, 0x41);
160 	mipi_dsi_dcs_write_seq(dsi, 0x73, 0x4a);
161 	mipi_dsi_dcs_write_seq(dsi, 0x74, 0xd0);
162 	mipi_dsi_dcs_write_seq(dsi, 0x77, 0x62);
163 	mipi_dsi_dcs_write_seq(dsi, 0x79, 0x7e);
164 	mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x03);
165 	mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x15);
166 	mipi_dsi_dcs_write_seq(dsi, 0x7f, 0x00);
167 	mipi_dsi_dcs_write_seq(dsi, 0x84, 0x4d);
168 	mipi_dsi_dcs_write_seq(dsi, 0xcf, 0x80);
169 	mipi_dsi_dcs_write_seq(dsi, 0xd6, 0x80);
170 	mipi_dsi_dcs_write_seq(dsi, 0xd7, 0x80);
171 	mipi_dsi_dcs_write_seq(dsi, 0xef, 0x20);
172 	mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x84);
173 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x26);
174 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
175 	mipi_dsi_dcs_write_seq(dsi, 0x81, 0x0f);
176 	mipi_dsi_dcs_write_seq(dsi, 0x83, 0x01);
177 	mipi_dsi_dcs_write_seq(dsi, 0x84, 0x03);
178 	mipi_dsi_dcs_write_seq(dsi, 0x85, 0x01);
179 	mipi_dsi_dcs_write_seq(dsi, 0x86, 0x03);
180 	mipi_dsi_dcs_write_seq(dsi, 0x87, 0x01);
181 	mipi_dsi_dcs_write_seq(dsi, 0x88, 0x05);
182 	mipi_dsi_dcs_write_seq(dsi, 0x8a, 0x1a);
183 	mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x11);
184 	mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x24);
185 	mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x42);
186 	mipi_dsi_dcs_write_seq(dsi, 0x8f, 0x11);
187 	mipi_dsi_dcs_write_seq(dsi, 0x90, 0x11);
188 	mipi_dsi_dcs_write_seq(dsi, 0x91, 0x11);
189 	mipi_dsi_dcs_write_seq(dsi, 0x9a, 0x80);
190 	mipi_dsi_dcs_write_seq(dsi, 0x9b, 0x04);
191 	mipi_dsi_dcs_write_seq(dsi, 0x9c, 0x00);
192 	mipi_dsi_dcs_write_seq(dsi, 0x9d, 0x00);
193 	mipi_dsi_dcs_write_seq(dsi, 0x9e, 0x00);
194 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x27);
195 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
196 	mipi_dsi_dcs_write_seq(dsi, 0x01, 0x68);
197 	mipi_dsi_dcs_write_seq(dsi, 0x20, 0x81);
198 	mipi_dsi_dcs_write_seq(dsi, 0x21, 0x6a);
199 	mipi_dsi_dcs_write_seq(dsi, 0x25, 0x81);
200 	mipi_dsi_dcs_write_seq(dsi, 0x26, 0x94);
201 	mipi_dsi_dcs_write_seq(dsi, 0x6e, 0x00);
202 	mipi_dsi_dcs_write_seq(dsi, 0x6f, 0x00);
203 	mipi_dsi_dcs_write_seq(dsi, 0x70, 0x00);
204 	mipi_dsi_dcs_write_seq(dsi, 0x71, 0x00);
205 	mipi_dsi_dcs_write_seq(dsi, 0x72, 0x00);
206 	mipi_dsi_dcs_write_seq(dsi, 0x75, 0x00);
207 	mipi_dsi_dcs_write_seq(dsi, 0x76, 0x00);
208 	mipi_dsi_dcs_write_seq(dsi, 0x77, 0x00);
209 	mipi_dsi_dcs_write_seq(dsi, 0x7d, 0x09);
210 	mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x67);
211 	mipi_dsi_dcs_write_seq(dsi, 0x80, 0x23);
212 	mipi_dsi_dcs_write_seq(dsi, 0x82, 0x09);
213 	mipi_dsi_dcs_write_seq(dsi, 0x83, 0x67);
214 	mipi_dsi_dcs_write_seq(dsi, 0x88, 0x01);
215 	mipi_dsi_dcs_write_seq(dsi, 0x89, 0x10);
216 	mipi_dsi_dcs_write_seq(dsi, 0xa5, 0x10);
217 	mipi_dsi_dcs_write_seq(dsi, 0xa6, 0x23);
218 	mipi_dsi_dcs_write_seq(dsi, 0xa7, 0x01);
219 	mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x40);
220 	mipi_dsi_dcs_write_seq(dsi, 0xe5, 0x02);
221 	mipi_dsi_dcs_write_seq(dsi, 0xe6, 0xd3);
222 	mipi_dsi_dcs_write_seq(dsi, 0xeb, 0x03);
223 	mipi_dsi_dcs_write_seq(dsi, 0xec, 0x28);
224 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2a);
225 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
226 	mipi_dsi_dcs_write_seq(dsi, 0x00, 0x91);
227 	mipi_dsi_dcs_write_seq(dsi, 0x03, 0x20);
228 	mipi_dsi_dcs_write_seq(dsi, 0x07, 0x50);
229 	mipi_dsi_dcs_write_seq(dsi, 0x0a, 0x70);
230 	mipi_dsi_dcs_write_seq(dsi, 0x0c, 0x04);
231 	mipi_dsi_dcs_write_seq(dsi, 0x0d, 0x40);
232 	mipi_dsi_dcs_write_seq(dsi, 0x0f, 0x01);
233 	mipi_dsi_dcs_write_seq(dsi, 0x11, 0xe0);
234 	mipi_dsi_dcs_write_seq(dsi, 0x15, 0x0f);
235 	mipi_dsi_dcs_write_seq(dsi, 0x16, 0xa4);
236 	mipi_dsi_dcs_write_seq(dsi, 0x19, 0x0f);
237 	mipi_dsi_dcs_write_seq(dsi, 0x1a, 0x78);
238 	mipi_dsi_dcs_write_seq(dsi, 0x1b, 0x23);
239 	mipi_dsi_dcs_write_seq(dsi, 0x1d, 0x36);
240 	mipi_dsi_dcs_write_seq(dsi, 0x1e, 0x3e);
241 	mipi_dsi_dcs_write_seq(dsi, 0x1f, 0x3e);
242 	mipi_dsi_dcs_write_seq(dsi, 0x20, 0x3e);
243 	mipi_dsi_dcs_write_seq(dsi, 0x28, 0xfd);
244 	mipi_dsi_dcs_write_seq(dsi, 0x29, 0x12);
245 	mipi_dsi_dcs_write_seq(dsi, 0x2a, 0xe1);
246 	mipi_dsi_dcs_write_seq(dsi, 0x2d, 0x0a);
247 	mipi_dsi_dcs_write_seq(dsi, 0x30, 0x49);
248 	mipi_dsi_dcs_write_seq(dsi, 0x33, 0x96);
249 	mipi_dsi_dcs_write_seq(dsi, 0x34, 0xff);
250 	mipi_dsi_dcs_write_seq(dsi, 0x35, 0x40);
251 	mipi_dsi_dcs_write_seq(dsi, 0x36, 0xde);
252 	mipi_dsi_dcs_write_seq(dsi, 0x37, 0xf9);
253 	mipi_dsi_dcs_write_seq(dsi, 0x38, 0x45);
254 	mipi_dsi_dcs_write_seq(dsi, 0x39, 0xd9);
255 	mipi_dsi_dcs_write_seq(dsi, 0x3a, 0x49);
256 	mipi_dsi_dcs_write_seq(dsi, 0x4a, 0xf0);
257 	mipi_dsi_dcs_write_seq(dsi, 0x7a, 0x09);
258 	mipi_dsi_dcs_write_seq(dsi, 0x7b, 0x40);
259 	mipi_dsi_dcs_write_seq(dsi, 0x7f, 0xf0);
260 	mipi_dsi_dcs_write_seq(dsi, 0x83, 0x0f);
261 	mipi_dsi_dcs_write_seq(dsi, 0x84, 0xa4);
262 	mipi_dsi_dcs_write_seq(dsi, 0x87, 0x0f);
263 	mipi_dsi_dcs_write_seq(dsi, 0x88, 0x78);
264 	mipi_dsi_dcs_write_seq(dsi, 0x89, 0x23);
265 	mipi_dsi_dcs_write_seq(dsi, 0x8b, 0x36);
266 	mipi_dsi_dcs_write_seq(dsi, 0x8c, 0x7d);
267 	mipi_dsi_dcs_write_seq(dsi, 0x8d, 0x7d);
268 	mipi_dsi_dcs_write_seq(dsi, 0x8e, 0x7d);
269 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x20);
270 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
271 	mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
272 				0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
273 	mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
274 				0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
275 	mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
276 				0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
277 	mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
278 				0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
279 	mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
280 				0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
281 	mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
282 				0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
283 	mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
284 				0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
285 	mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
286 				0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
287 	mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
288 				0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
289 	mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
290 				0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
291 	mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
292 				0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
293 	mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
294 				0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
295 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x21);
296 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
297 	mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00, 0x00, 0x00, 0x17, 0x00, 0x49, 0x00,
298 				0x6a, 0x00, 0x89, 0x00, 0x9f, 0x00, 0xb6, 0x00, 0xc8);
299 	mipi_dsi_dcs_write_seq(dsi, 0xb1, 0x00, 0xd9, 0x01, 0x10, 0x01, 0x3a, 0x01,
300 				0x7a, 0x01, 0xa9, 0x01, 0xf2, 0x02, 0x2d, 0x02, 0x2e);
301 	mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x02, 0x64, 0x02, 0xa3, 0x02, 0xca, 0x03,
302 				0x00, 0x03, 0x1e, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
303 	mipi_dsi_dcs_write_seq(dsi, 0xb3, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
304 				0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
305 	mipi_dsi_dcs_write_seq(dsi, 0xb4, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
306 				0x71, 0x00, 0x90, 0x00, 0xa7, 0x00, 0xbf, 0x00, 0xd1);
307 	mipi_dsi_dcs_write_seq(dsi, 0xb5, 0x00, 0xe2, 0x01, 0x1a, 0x01, 0x43, 0x01,
308 				0x83, 0x01, 0xb2, 0x01, 0xfa, 0x02, 0x34, 0x02, 0x36);
309 	mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x02, 0x6b, 0x02, 0xa8, 0x02, 0xd0, 0x03,
310 				0x03, 0x03, 0x21, 0x03, 0x4d, 0x03, 0x5b, 0x03, 0x6b);
311 	mipi_dsi_dcs_write_seq(dsi, 0xb7, 0x03, 0x7e, 0x03, 0x94, 0x03, 0xac, 0x03,
312 				0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
313 	mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x51, 0x00,
314 				0x72, 0x00, 0x92, 0x00, 0xa8, 0x00, 0xbf, 0x00, 0xd1);
315 	mipi_dsi_dcs_write_seq(dsi, 0xb9, 0x00, 0xe2, 0x01, 0x18, 0x01, 0x42, 0x01,
316 				0x81, 0x01, 0xaf, 0x01, 0xf5, 0x02, 0x2f, 0x02, 0x31);
317 	mipi_dsi_dcs_write_seq(dsi, 0xba, 0x02, 0x68, 0x02, 0xa6, 0x02, 0xcd, 0x03,
318 				0x01, 0x03, 0x1f, 0x03, 0x4a, 0x03, 0x59, 0x03, 0x6a);
319 	mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x03, 0x7d, 0x03, 0x93, 0x03, 0xab, 0x03,
320 				0xc8, 0x03, 0xec, 0x03, 0xfe, 0x00, 0x00);
321 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x2c);
322 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
323 	mipi_dsi_dcs_write_seq(dsi, 0x61, 0x1f);
324 	mipi_dsi_dcs_write_seq(dsi, 0x62, 0x1f);
325 	mipi_dsi_dcs_write_seq(dsi, 0x7e, 0x03);
326 	mipi_dsi_dcs_write_seq(dsi, 0x6a, 0x14);
327 	mipi_dsi_dcs_write_seq(dsi, 0x6b, 0x36);
328 	mipi_dsi_dcs_write_seq(dsi, 0x6c, 0x36);
329 	mipi_dsi_dcs_write_seq(dsi, 0x6d, 0x36);
330 	mipi_dsi_dcs_write_seq(dsi, 0x53, 0x04);
331 	mipi_dsi_dcs_write_seq(dsi, 0x54, 0x04);
332 	mipi_dsi_dcs_write_seq(dsi, 0x55, 0x04);
333 	mipi_dsi_dcs_write_seq(dsi, 0x56, 0x0f);
334 	mipi_dsi_dcs_write_seq(dsi, 0x58, 0x0f);
335 	mipi_dsi_dcs_write_seq(dsi, 0x59, 0x0f);
336 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0xf0);
337 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
338 	mipi_dsi_dcs_write_seq(dsi, 0x5a, 0x00);
339 
340 	mipi_dsi_dcs_write_seq(dsi, 0xff, 0x10);
341 	mipi_dsi_dcs_write_seq(dsi, 0xfb, 0x01);
342 	mipi_dsi_dcs_write_seq(dsi, 0x51, 0xff);
343 	mipi_dsi_dcs_write_seq(dsi, 0x53, 0x24);
344 	mipi_dsi_dcs_write_seq(dsi, 0x55, 0x01);
345 
346 	return 0;
347 }
348 
349 static int nt36672e_power_on(struct nt36672e_panel *ctx)
350 {
351 	struct mipi_dsi_device *dsi = ctx->dsi;
352 	int ret, i;
353 
354 	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
355 		ret = regulator_set_load(ctx->supplies[i].consumer,
356 				regulator_enable_loads[i]);
357 		if (ret) {
358 			dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n",
359 				ctx->supplies[i].supply, ret);
360 			return ret;
361 		}
362 	}
363 
364 	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
365 	if (ret < 0) {
366 		dev_err(&dsi->dev, "regulator bulk enable failed: %d\n", ret);
367 		return ret;
368 	}
369 
370 	/*
371 	 * Reset sequence of nt36672e panel requires the panel to be out of reset
372 	 * for 10ms, followed by being held in reset for 10ms and then out again.
373 	 */
374 	gpiod_set_value(ctx->reset_gpio, 1);
375 	usleep_range(10000, 20000);
376 	gpiod_set_value(ctx->reset_gpio, 0);
377 	usleep_range(10000, 20000);
378 	gpiod_set_value(ctx->reset_gpio, 1);
379 	usleep_range(10000, 20000);
380 
381 	return 0;
382 }
383 
384 static int nt36672e_power_off(struct nt36672e_panel *ctx)
385 {
386 	struct mipi_dsi_device *dsi = ctx->dsi;
387 	int ret = 0;
388 	int i;
389 
390 	gpiod_set_value(ctx->reset_gpio, 0);
391 
392 	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++) {
393 		ret = regulator_set_load(ctx->supplies[i].consumer,
394 				regulator_disable_loads[i]);
395 		if (ret) {
396 			dev_err(&dsi->dev, "regulator set load failed for supply %s: %d\n",
397 				ctx->supplies[i].supply, ret);
398 			return ret;
399 		}
400 	}
401 
402 	ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
403 	if (ret)
404 		dev_err(&dsi->dev, "regulator bulk disable failed: %d\n", ret);
405 
406 	return ret;
407 }
408 
409 static int nt36672e_on(struct nt36672e_panel *ctx)
410 {
411 	struct mipi_dsi_device *dsi = ctx->dsi;
412 	const struct panel_desc *desc = ctx->desc;
413 	int ret = 0;
414 
415 	dsi->mode_flags |= MIPI_DSI_MODE_LPM;
416 
417 	if (desc->init_sequence) {
418 		ret = desc->init_sequence(dsi);
419 		if (ret < 0) {
420 			dev_err(&dsi->dev, "panel init sequence failed: %d\n", ret);
421 			return ret;
422 		}
423 	}
424 
425 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
426 	if (ret < 0) {
427 		dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret);
428 		return ret;
429 	}
430 	msleep(120);
431 
432 	ret = mipi_dsi_dcs_set_display_on(dsi);
433 	if (ret < 0) {
434 		dev_err(&dsi->dev, "Failed to set display on: %d\n", ret);
435 		return ret;
436 	}
437 	msleep(100);
438 
439 	return 0;
440 }
441 
442 static int nt36672e_off(struct nt36672e_panel *ctx)
443 {
444 	struct mipi_dsi_device *dsi = ctx->dsi;
445 	int ret = 0;
446 
447 	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
448 
449 	ret = mipi_dsi_dcs_set_display_off(dsi);
450 	if (ret < 0) {
451 		dev_err(&dsi->dev, "Failed to set display off: %d\n", ret);
452 		return ret;
453 	}
454 	msleep(20);
455 
456 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
457 	if (ret < 0) {
458 		dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret);
459 		return ret;
460 	}
461 	msleep(60);
462 
463 	return 0;
464 }
465 
466 static int nt36672e_panel_prepare(struct drm_panel *panel)
467 {
468 	struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
469 	struct mipi_dsi_device *dsi = ctx->dsi;
470 	int ret = 0;
471 
472 	ret = nt36672e_power_on(ctx);
473 	if (ret < 0)
474 		return ret;
475 
476 	ret = nt36672e_on(ctx);
477 	if (ret < 0) {
478 		dev_err(&dsi->dev, "Failed to initialize panel: %d\n", ret);
479 		if (nt36672e_power_off(ctx))
480 			dev_err(&dsi->dev, "power off failed\n");
481 		return ret;
482 	}
483 
484 	return 0;
485 }
486 
487 static int nt36672e_panel_unprepare(struct drm_panel *panel)
488 {
489 	struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
490 	struct mipi_dsi_device *dsi = ctx->dsi;
491 	int ret = 0;
492 
493 	ret = nt36672e_off(ctx);
494 	if (ret < 0)
495 		dev_err(&dsi->dev, "Failed to un-initialize panel: %d\n", ret);
496 
497 	ret = nt36672e_power_off(ctx);
498 	if (ret < 0)
499 		dev_err(&dsi->dev, "power off failed: %d\n", ret);
500 
501 	return 0;
502 }
503 
504 static const struct drm_display_mode nt36672e_1080x2408_60hz = {
505 	.name = "1080x2408",
506 	.clock = 181690,
507 	.hdisplay = 1080,
508 	.hsync_start = 1080 + 76,
509 	.hsync_end = 1080 + 76 + 12,
510 	.htotal = 1080 + 76 + 12 + 56,
511 	.vdisplay = 2408,
512 	.vsync_start = 2408 + 46,
513 	.vsync_end = 2408 + 46 + 10,
514 	.vtotal = 2408 + 46 + 10 + 10,
515 	.flags = 0,
516 };
517 
518 static const struct panel_desc nt36672e_panel_desc = {
519 	.display_mode = &nt36672e_1080x2408_60hz,
520 	.width_mm = 74,
521 	.height_mm = 131,
522 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
523 	.format = MIPI_DSI_FMT_RGB888,
524 	.lanes = 4,
525 	.panel_name = "nt36672e fhd plus panel",
526 	.init_sequence = nt36672e_1080x2408_60hz_init,
527 };
528 
529 static int nt36672e_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector)
530 {
531 	struct nt36672e_panel *ctx = to_nt36672e_panel(panel);
532 	struct drm_display_mode *mode;
533 
534 	mode = drm_mode_duplicate(connector->dev, ctx->desc->display_mode);
535 	if (!mode)
536 		return -ENOMEM;
537 
538 	drm_mode_set_name(mode);
539 
540 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
541 	connector->display_info.width_mm = ctx->desc->width_mm;
542 	connector->display_info.height_mm = ctx->desc->height_mm;
543 	drm_mode_probed_add(connector, mode);
544 
545 	return 1;
546 }
547 
548 static const struct drm_panel_funcs nt36672e_drm_funcs = {
549 	.prepare = nt36672e_panel_prepare,
550 	.unprepare = nt36672e_panel_unprepare,
551 	.get_modes = nt36672e_panel_get_modes,
552 };
553 
554 static int nt36672e_panel_probe(struct mipi_dsi_device *dsi)
555 {
556 	struct device *dev = &dsi->dev;
557 	struct nt36672e_panel *ctx;
558 	int i, ret = 0;
559 
560 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
561 	if (!ctx)
562 		return -ENOMEM;
563 
564 	ctx->desc = of_device_get_match_data(dev);
565 	if (!ctx->desc) {
566 		dev_err(dev, "missing device configuration\n");
567 		return -ENODEV;
568 	}
569 
570 	for (i = 0; i < ARRAY_SIZE(ctx->supplies); i++)
571 		ctx->supplies[i].supply = regulator_names[i];
572 
573 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
574 			ctx->supplies);
575 	if (ret < 0)
576 		return ret;
577 
578 	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
579 	if (IS_ERR(ctx->reset_gpio))
580 		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset-gpios\n");
581 
582 	ctx->dsi = dsi;
583 	mipi_dsi_set_drvdata(dsi, ctx);
584 
585 	dsi->lanes = ctx->desc->lanes;
586 	dsi->format = ctx->desc->format;
587 	dsi->mode_flags = ctx->desc->mode_flags;
588 
589 	drm_panel_init(&ctx->panel, dev, &nt36672e_drm_funcs, DRM_MODE_CONNECTOR_DSI);
590 
591 	ret = drm_panel_of_backlight(&ctx->panel);
592 	if (ret)
593 		return dev_err_probe(dev, ret, "Failed to get backlight\n");
594 
595 	ctx->panel.prepare_prev_first = true;
596 
597 	drm_panel_add(&ctx->panel);
598 
599 	ret = mipi_dsi_attach(dsi);
600 	if (ret < 0) {
601 		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);
602 		goto err_dsi_attach;
603 	}
604 
605 	return 0;
606 
607 err_dsi_attach:
608 	drm_panel_remove(&ctx->panel);
609 	return ret;
610 }
611 
612 static void nt36672e_panel_remove(struct mipi_dsi_device *dsi)
613 {
614 	struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi);
615 
616 	mipi_dsi_detach(ctx->dsi);
617 	mipi_dsi_device_unregister(ctx->dsi);
618 
619 	drm_panel_remove(&ctx->panel);
620 }
621 
622 static const struct of_device_id nt36672e_of_match[] = {
623 	{
624 		.compatible = "novatek,nt36672e",
625 		.data = &nt36672e_panel_desc,
626 	},
627 	{ }
628 };
629 MODULE_DEVICE_TABLE(of, nt36672e_of_match);
630 
631 static struct mipi_dsi_driver nt36672e_panel_driver = {
632 	.driver = {
633 		.name = "panel-novatek-nt36672e",
634 		.of_match_table = nt36672e_of_match,
635 	},
636 	.probe = nt36672e_panel_probe,
637 	.remove = nt36672e_panel_remove,
638 };
639 module_mipi_dsi_driver(nt36672e_panel_driver);
640 
641 MODULE_AUTHOR("Ritesh Kumar <quic_riteshk@quicinc.com>");
642 MODULE_DESCRIPTION("Novatek NT36672E DSI Panel Driver");
643 MODULE_LICENSE("GPL");
644