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
16static const char * const regulator_names[] = {
17	"vddi",
18	"avdd",
19	"avee",
20};
21
22static const unsigned long regulator_enable_loads[] = {
23	62000,
24	100000,
25	100000,
26};
27
28static const unsigned long regulator_disable_loads[] = {
29	80,
30	100,
31	100,
32};
33
34struct 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
45struct 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
53static inline struct nt36672e_panel *to_nt36672e_panel(struct drm_panel *panel)
54{
55	return container_of(panel, struct nt36672e_panel, panel);
56}
57
58static 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
349static 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
384static 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
409static 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
442static 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
466static 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
487static 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
504static 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
518static 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
529static 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
548static 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
554static 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
607err_dsi_attach:
608	drm_panel_remove(&ctx->panel);
609	return ret;
610}
611
612static 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	drm_panel_remove(&ctx->panel);
618}
619
620static const struct of_device_id nt36672e_of_match[] = {
621	{
622		.compatible = "novatek,nt36672e",
623		.data = &nt36672e_panel_desc,
624	},
625	{ }
626};
627MODULE_DEVICE_TABLE(of, nt36672e_of_match);
628
629static struct mipi_dsi_driver nt36672e_panel_driver = {
630	.driver = {
631		.name = "panel-novatek-nt36672e",
632		.of_match_table = nt36672e_of_match,
633	},
634	.probe = nt36672e_panel_probe,
635	.remove = nt36672e_panel_remove,
636};
637module_mipi_dsi_driver(nt36672e_panel_driver);
638
639MODULE_AUTHOR("Ritesh Kumar <quic_riteshk@quicinc.com>");
640MODULE_DESCRIPTION("Novatek NT36672E DSI Panel Driver");
641MODULE_LICENSE("GPL");
642