xref: /linux/drivers/gpu/drm/panel/panel-ilitek-ili9882t.c (revision ff124bbbca1d3a07fa1392ffdbbdeece71f68ece)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Panels based on the Ilitek ILI9882T display controller.
4  */
5 #include <linux/delay.h>
6 #include <linux/gpio/consumer.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/regulator/consumer.h>
10 
11 #include <drm/display/drm_dsc.h>
12 #include <drm/display/drm_dsc_helper.h>
13 #include <drm/drm_connector.h>
14 #include <drm/drm_crtc.h>
15 #include <drm/drm_mipi_dsi.h>
16 #include <drm/drm_panel.h>
17 
18 #include <video/mipi_display.h>
19 
20 #define DSC_BPG_OFFSET(x)	((u8)((x) & DSC_RANGE_BPG_OFFSET_MASK))
21 
22 struct ili9882t;
23 
24 /*
25  * Use this descriptor struct to describe different panels using the
26  * Ilitek ILI9882T display controller.
27  */
28 struct panel_desc {
29 	const struct drm_display_mode *modes;
30 	const struct drm_dsc_config *dsc;
31 	unsigned int bpc;
32 
33 	/**
34 	 * @width_mm: width of the panel's active display area
35 	 * @height_mm: height of the panel's active display area
36 	 */
37 	struct {
38 		unsigned int width_mm;
39 		unsigned int height_mm;
40 	} size;
41 
42 	unsigned long mode_flags;
43 	enum mipi_dsi_pixel_format format;
44 	int (*init)(struct ili9882t *boe);
45 	unsigned int lanes;
46 };
47 
48 struct ili9882t {
49 	struct drm_panel base;
50 	struct mipi_dsi_device *dsi;
51 
52 	const struct panel_desc *desc;
53 
54 	enum drm_panel_orientation orientation;
55 	struct regulator *pp3300;
56 	struct regulator *pp1800;
57 	struct regulator *avee;
58 	struct regulator *avdd;
59 	struct gpio_desc *enable_gpio;
60 
61 	struct drm_dsc_config dsc;
62 };
63 
64 /* ILI9882-specific commands, add new commands as you decode them */
65 #define ILI9882T_DCS_SWITCH_PAGE	0xFF
66 
67 #define ili9882t_switch_page(ctx, page) \
68 	mipi_dsi_dcs_write_seq_multi(ctx, ILI9882T_DCS_SWITCH_PAGE, \
69 				     0x98, 0x82, (page))
70 
71 /* IL79900A-specific commands, add new commands as you decode them */
72 #define IL79900A_DCS_SWITCH_PAGE	0xFF
73 
74 #define il79900a_switch_page(ctx, page) \
75 	mipi_dsi_dcs_write_seq_multi(ctx, IL79900A_DCS_SWITCH_PAGE, \
76 				     0x5a, 0xa5, (page))
77 
78 static const struct drm_dsc_config tianma_il79900a_dsc = {
79 	.dsc_version_major = 1,
80 	.dsc_version_minor = 2,
81 	.slice_height = 8,
82 	.slice_width = 800,
83 	.slice_count = 2,
84 	.bits_per_component = 8,
85 	.bits_per_pixel = 8 << 4,
86 	.block_pred_enable = true,
87 	.native_420 = false,
88 	.native_422 = false,
89 	.simple_422 = false,
90 	.vbr_enable = false,
91 	.pic_width = 1600,
92 	.pic_height = 2560,
93 	.convert_rgb = 0,
94 	.rc_buf_thresh = {14, 28, 42, 56, 70, 84, 98, 105, 112, 119, 121, 123, 125, 126},
95 	.rc_model_size = DSC_RC_MODEL_SIZE_CONST,
96 	.rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST,
97 	.rc_tgt_offset_high = DSC_RC_TGT_OFFSET_HI_CONST,
98 	.rc_tgt_offset_low = DSC_RC_TGT_OFFSET_LO_CONST,
99 	.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC,
100 	.line_buf_depth = 9,
101 	.first_line_bpg_offset = 12,
102 	.initial_xmit_delay = 512,
103 	.initial_offset = 6144,
104 	.rc_quant_incr_limit0 = 11,
105 	.rc_quant_incr_limit1 = 11,
106 	.rc_range_params = {
107 		{ 0,  4, DSC_BPG_OFFSET(2)},
108 		{ 0,  4, DSC_BPG_OFFSET(0)},
109 		{ 1,  5, DSC_BPG_OFFSET(0)},
110 		{ 1,  6, DSC_BPG_OFFSET(-2)},
111 		{ 3,  7, DSC_BPG_OFFSET(-4)},
112 		{ 3,  7, DSC_BPG_OFFSET(-6)},
113 		{ 3,  7, DSC_BPG_OFFSET(-8)},
114 		{ 3,  8, DSC_BPG_OFFSET(-8)},
115 		{ 3,  9, DSC_BPG_OFFSET(-8)},
116 		{ 3, 10, DSC_BPG_OFFSET(-10)},
117 		{ 5, 10, DSC_BPG_OFFSET(-10)},
118 		{ 5, 11, DSC_BPG_OFFSET(-12)},
119 		{ 5, 11, DSC_BPG_OFFSET(-12)},
120 		{ 9, 12, DSC_BPG_OFFSET(-12)},
121 		{12, 13, DSC_BPG_OFFSET(-12)},
122 	},
123 	.slice_chunk_size = 800,
124 	.initial_dec_delay = 657,
125 	.final_offset = 4320,
126 	.scale_increment_interval = 222,
127 	.scale_decrement_interval = 11,
128 	.initial_scale_value = 32,
129 	.nfl_bpg_offset = 3511,
130 	.slice_bpg_offset = 2179,
131 	.flatness_max_qp = 12,
132 	.flatness_min_qp = 3,
133 };
134 
135 static int starry_ili9882t_init(struct ili9882t *ili)
136 {
137 	struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
138 
139 	usleep_range(5000, 5100);
140 
141 	ili9882t_switch_page(&ctx, 0x01);
142 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x42);
143 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x11);
144 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x00);
145 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x00);
146 
147 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x01);
148 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x11);
149 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x00);
150 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x00);
151 
152 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x80);
153 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x81);
154 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x71);
155 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x00);
156 
157 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x00);
158 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x1a);
159 
160 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x00);
161 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x00);
162 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x00);
163 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
164 
165 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0xd4);
166 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb9, 0x40);
167 
168 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x11);
169 
170 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x32);
171 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd1, 0x30);
172 
173 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
174 
175 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd0, 0x01);
176 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe3, 0x93);
177 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe4, 0x00);
178 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x80);
179 
180 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x07);
181 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x07);
182 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x07);
183 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x07);
184 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x07);
185 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x01);
186 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x00);
187 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x28);
188 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x29);
189 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x11);
190 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x13);
191 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x15);
192 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x17);
193 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x09);
194 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x0d);
195 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x40, 0x02);
196 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x41, 0x02);
197 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x42, 0x02);
198 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x43, 0x02);
199 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x44, 0x02);
200 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x45, 0x02);
201 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x46, 0x02);
202 
203 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x47, 0x07);
204 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x48, 0x07);
205 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x49, 0x07);
206 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4a, 0x07);
207 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4b, 0x07);
208 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4c, 0x01);
209 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4d, 0x00);
210 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4e, 0x28);
211 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x4f, 0x29);
212 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x50, 0x10);
213 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x51, 0x12);
214 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x52, 0x14);
215 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x16);
216 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x54, 0x08);
217 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x55, 0x0c);
218 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x56, 0x02);
219 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x57, 0x02);
220 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x58, 0x02);
221 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x59, 0x02);
222 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5a, 0x02);
223 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5b, 0x02);
224 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5c, 0x02);
225 
226 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x07);
227 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x07);
228 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x63, 0x07);
229 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x07);
230 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x65, 0x07);
231 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x66, 0x01);
232 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x00);
233 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x68, 0x28);
234 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x29);
235 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x16);
236 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6b, 0x14);
237 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6c, 0x12);
238 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x10);
239 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6e, 0x0c);
240 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6f, 0x08);
241 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x70, 0x02);
242 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x71, 0x02);
243 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x72, 0x02);
244 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0x02);
245 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x74, 0x02);
246 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x75, 0x02);
247 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x76, 0x02);
248 
249 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x77, 0x07);
250 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x78, 0x07);
251 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x07);
252 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7a, 0x07);
253 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7b, 0x07);
254 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7c, 0x01);
255 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7d, 0x00);
256 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7e, 0x28);
257 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x29);
258 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x17);
259 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x15);
260 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x82, 0x13);
261 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x83, 0x11);
262 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x0d);
263 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x85, 0x09);
264 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x02);
265 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x07);
266 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x88, 0x07);
267 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x89, 0x07);
268 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8a, 0x07);
269 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8b, 0x07);
270 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x8c, 0x07);
271 
272 	ili9882t_switch_page(&ctx, 0x02);
273 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x3a);
274 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x3b);
275 
276 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x01);
277 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x01);
278 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x0c);
279 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x44);
280 
281 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
282 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x11);
283 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x00);
284 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0c);
285 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x44);
286 
287 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x53, 0x1f);
288 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x40);
289 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x84, 0x00);
290 
291 	ili9882t_switch_page(&ctx, 0x03);
292 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x01);
293 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x3c);
294 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0xfa);
295 
296 	ili9882t_switch_page(&ctx, 0x0a);
297 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x01);
298 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe2, 0x01);
299 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe5, 0x91);
300 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe6, 0x3c);
301 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe7, 0x00);
302 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe8, 0xfa);
303 
304 	ili9882t_switch_page(&ctx, 0x12);
305 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x87, 0x2c);
306 
307 	ili9882t_switch_page(&ctx, 0x05);
308 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x73, 0xe5);
309 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x7f, 0x6b);
310 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0xa4);
311 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x79, 0x54);
312 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x69, 0x97);
313 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6a, 0x97);
314 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa5, 0x3f);
315 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0xda);
316 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xf1);
317 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5f, 0x01);
318 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x62, 0x3f);
319 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x90);
320 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
321 
322 	ili9882t_switch_page(&ctx, 0x06);
323 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x80);
324 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc1, 0x07);
325 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xca, 0x58);
326 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xcb, 0x02);
327 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xce, 0x58);
328 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xcf, 0x02);
329 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x67, 0x60);
330 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x00);
331 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
332 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd3, 0x08);
333 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xd6, 0x55);
334 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xdc, 0x38);
335 
336 	ili9882t_switch_page(&ctx, 0x08);
337 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe0, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
338 				     0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
339 				     0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
340 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xe1, 0x00, 0x10, 0x2a, 0x4d, 0x61, 0x56, 0x6a, 0x6e,
341 				     0x79, 0x76, 0x8f, 0x95, 0x98, 0xae, 0xaa, 0xb2, 0xbb, 0xce,
342 				     0xc6, 0xbd, 0xd5, 0xe2, 0xe8);
343 
344 	ili9882t_switch_page(&ctx, 0x04);
345 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x81);
346 
347 	ili9882t_switch_page(&ctx, 0x0c);
348 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x02);
349 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x01, 0x00);
350 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x03);
351 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x01);
352 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x03);
353 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0x02);
354 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x06, 0x04);
355 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x03);
356 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x03);
357 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x04);
358 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0a, 0x04);
359 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0b, 0x05);
360 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0c, 0x04);
361 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0d, 0x06);
362 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0e, 0x05);
363 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x0f, 0x07);
364 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x10, 0x04);
365 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x11, 0x08);
366 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x05);
367 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x13, 0x09);
368 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x05);
369 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x0a);
370 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x16, 0x06);
371 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x17, 0x0b);
372 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x18, 0x05);
373 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x19, 0x0c);
374 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1a, 0x06);
375 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x0d);
376 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1c, 0x06);
377 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0x0e);
378 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1e, 0x07);
379 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1f, 0x0f);
380 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x06);
381 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x21, 0x10);
382 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x22, 0x07);
383 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x23, 0x11);
384 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x24, 0x07);
385 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x12);
386 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0x08);
387 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x13);
388 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x28, 0x07);
389 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x14);
390 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x08);
391 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x15);
392 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2c, 0x08);
393 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0x16);
394 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2e, 0x09);
395 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2f, 0x17);
396 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x08);
397 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x18);
398 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0x09);
399 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x19);
400 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0x09);
401 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x1a);
402 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0x0a);
403 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x37, 0x1b);
404 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x0a);
405 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x39, 0x1c);
406 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3a, 0x0a);
407 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3b, 0x1d);
408 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3c, 0x0a);
409 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3d, 0x1e);
410 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x0a);
411 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3f, 0x1f);
412 
413 	ili9882t_switch_page(&ctx, 0x04);
414 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xba, 0x01);
415 
416 	ili9882t_switch_page(&ctx, 0x0e);
417 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x02, 0x0c);
418 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x10);
419 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x16);
420 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x26, 0xe0);
421 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x27, 0x00);
422 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x29, 0x71);
423 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x46);
424 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2b, 0x1f);
425 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2d, 0xc7);
426 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x31, 0x02);
427 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x32, 0xdf);
428 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x33, 0x5a);
429 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x34, 0xc0);
430 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x35, 0x5a);
431 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x36, 0xc0);
432 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0x65);
433 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x3e);
434 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0xa0);
435 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x01);
436 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb1, 0xcc);
437 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x12);
438 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc2, 0xcc);
439 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc3, 0xcc);
440 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc4, 0xcc);
441 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc5, 0xcc);
442 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc6, 0xcc);
443 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc7, 0xcc);
444 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc8, 0xcc);
445 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc9, 0xcc);
446 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x30, 0x00);
447 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x81);
448 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x08, 0x02);
449 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x09, 0x00);
450 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x07, 0x21);
451 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x10);
452 
453 	ili9882t_switch_page(&ctx, 0x1e);
454 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x60, 0x00);
455 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x64, 0x00);
456 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x6d, 0x00);
457 
458 	ili9882t_switch_page(&ctx, 0x0b);
459 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa6, 0x44);
460 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa7, 0xb6);
461 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa8, 0x03);
462 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xa9, 0x03);
463 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xaa, 0x51);
464 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xab, 0x51);
465 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xac, 0x04);
466 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xbd, 0x92);
467 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xbe, 0xa1);
468 
469 	ili9882t_switch_page(&ctx, 0x05);
470 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x86, 0x87);
471 
472 	ili9882t_switch_page(&ctx, 0x06);
473 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x92, 0x22);
474 
475 	ili9882t_switch_page(&ctx, 0x00);
476 	mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
477 
478 	mipi_dsi_msleep(&ctx, 120);
479 
480 	mipi_dsi_dcs_set_display_on_multi(&ctx);
481 
482 	mipi_dsi_msleep(&ctx, 20);
483 
484 	return ctx.accum_err;
485 };
486 
487 static int tianma_il79900a_init(struct ili9882t *ili)
488 {
489 	struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
490 	struct drm_dsc_picture_parameter_set pps;
491 
492 	mipi_dsi_usleep_range(&ctx, 5000, 5100);
493 
494 	il79900a_switch_page(&ctx, 0x06);
495 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x3e, 0x62);
496 
497 	il79900a_switch_page(&ctx, 0x01);
498 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xb0, 0x00);
499 
500 	il79900a_switch_page(&ctx, 0x02);
501 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1b, 0x00);
502 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5d, 0x00);
503 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x5e, 0x40);
504 
505 	il79900a_switch_page(&ctx, 0x05);
506 	mipi_dsi_dcs_write_seq_multi(&ctx, 0X9e, 0xe9);
507 
508 	il79900a_switch_page(&ctx, 0x07);
509 	mipi_dsi_dcs_write_seq_multi(&ctx, 0X29, 0x01);
510 
511 	il79900a_switch_page(&ctx, 0x17);
512 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00,
513 				     0x00, 0x89, 0x30, 0x80, 0x0a, 0x00, 0x06, 0x40, 0x00,
514 				     0x08, 0x03, 0x20, 0x03, 0x20, 0x02, 0x00, 0x02, 0x91,
515 				     0x00, 0x20, 0x00, 0xde, 0x00, 0x0b, 0x00, 0x0c, 0x0d,
516 				     0xb7, 0x08, 0x83, 0x18, 0x00, 0x10, 0xe0, 0x03, 0x0c,
517 				     0x20, 0x00, 0x06, 0x0b, 0x0b, 0x33, 0x0e, 0x1c, 0x2a,
518 				     0x38, 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b,
519 				     0x7d, 0x7e, 0x01, 0x02, 0x01, 0x00, 0x09, 0x40, 0x09,
520 				     0xbe, 0x19, 0xfc, 0x19, 0xfa, 0x19, 0xf8, 0x1a, 0x38,
521 				     0x1a, 0x78, 0x1a, 0xb6, 0x2a, 0xb6, 0x2a, 0xf4, 0x2a,
522 				     0xf4, 0x4b, 0x34, 0x63, 0x74);
523 
524 	il79900a_switch_page(&ctx, 0x06);
525 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x91, 0x45);
526 
527 	il79900a_switch_page(&ctx, 0x16);
528 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x03, 0x4b);
529 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x04, 0x73);
530 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x05, 0xdf);
531 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x00, 0x01);
532 
533 	il79900a_switch_page(&ctx, 0x10);
534 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x12, 0x8c);
535 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x14, 0x3c);
536 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x15, 0x3d);
537 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x1d, 0xfc);
538 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x25, 0x9d);
539 
540 	il79900a_switch_page(&ctx, 0x0e);
541 	mipi_dsi_dcs_write_seq_multi(&ctx, 0xc0, 0x18);
542 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x2a, 0x0e);
543 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x38, 0xcd);
544 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x80, 0x53);
545 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x81, 0x0e);
546 
547 	il79900a_switch_page(&ctx, 0x1e);
548 	mipi_dsi_dcs_write_seq_multi(&ctx, 0x61, 0x5c);
549 
550 	drm_dsc_pps_payload_pack(&pps, &tianma_il79900a_dsc);
551 
552 	mipi_dsi_picture_parameter_set_multi(&ctx, &pps);
553 
554 	mipi_dsi_compression_mode_ext_multi(&ctx, true,
555 					    MIPI_DSI_COMPRESSION_DSC, 1);
556 
557 	il79900a_switch_page(&ctx, 0x00);
558 	mipi_dsi_dcs_exit_sleep_mode_multi(&ctx);
559 
560 	mipi_dsi_msleep(&ctx, 120);
561 
562 	mipi_dsi_dcs_set_display_on_multi(&ctx);
563 
564 	mipi_dsi_msleep(&ctx, 20);
565 
566 	return ctx.accum_err;
567 };
568 
569 static inline struct ili9882t *to_ili9882t(struct drm_panel *panel)
570 {
571 	return container_of(panel, struct ili9882t, base);
572 }
573 
574 static int ili9882t_disable(struct drm_panel *panel)
575 {
576 	struct ili9882t *ili = to_ili9882t(panel);
577 	struct mipi_dsi_multi_context ctx = { .dsi = ili->dsi };
578 
579 	ili9882t_switch_page(&ctx, 0x00);
580 
581 	ili->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
582 
583 	mipi_dsi_dcs_set_display_off_multi(&ctx);
584 	mipi_dsi_dcs_enter_sleep_mode_multi(&ctx);
585 
586 	mipi_dsi_msleep(&ctx, 150);
587 
588 	return ctx.accum_err;
589 }
590 
591 static int ili9882t_unprepare(struct drm_panel *panel)
592 {
593 	struct ili9882t *ili = to_ili9882t(panel);
594 
595 	gpiod_set_value(ili->enable_gpio, 0);
596 	usleep_range(1000, 2000);
597 	regulator_disable(ili->avee);
598 	regulator_disable(ili->avdd);
599 	usleep_range(5000, 7000);
600 	regulator_disable(ili->pp1800);
601 	regulator_disable(ili->pp3300);
602 
603 	return 0;
604 }
605 
606 static int ili9882t_prepare(struct drm_panel *panel)
607 {
608 	struct ili9882t *ili = to_ili9882t(panel);
609 	int ret;
610 
611 	gpiod_set_value(ili->enable_gpio, 0);
612 	usleep_range(1000, 1500);
613 
614 	ret = regulator_enable(ili->pp3300);
615 	if (ret < 0)
616 		return ret;
617 
618 	ret = regulator_enable(ili->pp1800);
619 	if (ret < 0)
620 		return ret;
621 
622 	usleep_range(3000, 5000);
623 
624 	ret = regulator_enable(ili->avdd);
625 	if (ret < 0)
626 		goto poweroff1v8;
627 	ret = regulator_enable(ili->avee);
628 	if (ret < 0)
629 		goto poweroffavdd;
630 
631 	usleep_range(10000, 11000);
632 
633 	// MIPI needs to keep the LP11 state before the lcm_reset pin is pulled high
634 	ret = mipi_dsi_dcs_nop(ili->dsi);
635 	if (ret < 0) {
636 		dev_err(&ili->dsi->dev, "Failed to send NOP: %d\n", ret);
637 		goto poweroff;
638 	}
639 	usleep_range(1000, 2000);
640 
641 	gpiod_set_value(ili->enable_gpio, 1);
642 	usleep_range(1000, 2000);
643 	gpiod_set_value(ili->enable_gpio, 0);
644 	msleep(50);
645 	gpiod_set_value(ili->enable_gpio, 1);
646 	usleep_range(6000, 10000);
647 
648 	ret = ili->desc->init(ili);
649 	if (ret < 0)
650 		goto poweroff;
651 
652 	return 0;
653 
654 poweroff:
655 	gpiod_set_value(ili->enable_gpio, 0);
656 	regulator_disable(ili->avee);
657 poweroffavdd:
658 	regulator_disable(ili->avdd);
659 poweroff1v8:
660 	usleep_range(5000, 7000);
661 	regulator_disable(ili->pp1800);
662 
663 	return ret;
664 }
665 
666 static int ili9882t_enable(struct drm_panel *panel)
667 {
668 	msleep(130);
669 	return 0;
670 }
671 
672 static const struct drm_display_mode starry_ili9882t_default_mode = {
673 	.clock = 165280,
674 	.hdisplay = 1200,
675 	.hsync_start = 1200 + 72,
676 	.hsync_end = 1200 + 72 + 30,
677 	.htotal = 1200 + 72 + 30 + 72,
678 	.vdisplay = 1920,
679 	.vsync_start = 1920 + 68,
680 	.vsync_end = 1920 + 68 + 2,
681 	.vtotal = 1920 + 68 + 2 + 10,
682 	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
683 };
684 
685 static const struct drm_display_mode tianma_il79900a_default_mode = {
686 	.clock = 543850,
687 	.hdisplay = 1600,
688 	.hsync_start = 1600 + 20,
689 	.hsync_end = 1600 + 20 + 2,
690 	.htotal = 1600 + 20 + 2 + 20,
691 	.vdisplay = 2560,
692 	.vsync_start = 2560 + 62,
693 	.vsync_end = 2560 + 62 + 2,
694 	.vtotal = 2560 + 62 + 2 + 136,
695 	.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
696 };
697 
698 static const struct panel_desc starry_ili9882t_desc = {
699 	.modes = &starry_ili9882t_default_mode,
700 	.bpc = 8,
701 	.size = {
702 		.width_mm = 141,
703 		.height_mm = 226,
704 	},
705 	.lanes = 4,
706 	.format = MIPI_DSI_FMT_RGB888,
707 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
708 		      MIPI_DSI_MODE_LPM,
709 	.init = starry_ili9882t_init,
710 };
711 
712 static const struct panel_desc tianma_tl121bvms07_desc = {
713 	.modes = &tianma_il79900a_default_mode,
714 	.dsc = &tianma_il79900a_dsc,
715 	.bpc = 8,
716 	.size = {
717 		.width_mm = 163,
718 		.height_mm = 260,
719 	},
720 	.lanes = 3,
721 	.format = MIPI_DSI_FMT_RGB888,
722 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
723 		      MIPI_DSI_MODE_LPM,
724 	.init = tianma_il79900a_init,
725 };
726 
727 static int ili9882t_get_modes(struct drm_panel *panel,
728 			      struct drm_connector *connector)
729 {
730 	struct ili9882t *ili = to_ili9882t(panel);
731 	const struct drm_display_mode *m = ili->desc->modes;
732 	struct drm_display_mode *mode;
733 
734 	mode = drm_mode_duplicate(connector->dev, m);
735 	if (!mode) {
736 		dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
737 			m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
738 		return -ENOMEM;
739 	}
740 
741 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
742 	drm_mode_set_name(mode);
743 	drm_mode_probed_add(connector, mode);
744 
745 	connector->display_info.width_mm = ili->desc->size.width_mm;
746 	connector->display_info.height_mm = ili->desc->size.height_mm;
747 	connector->display_info.bpc = ili->desc->bpc;
748 
749 	return 1;
750 }
751 
752 static enum drm_panel_orientation ili9882t_get_orientation(struct drm_panel *panel)
753 {
754 	struct ili9882t *ili = to_ili9882t(panel);
755 
756 	return ili->orientation;
757 }
758 
759 static const struct drm_panel_funcs ili9882t_funcs = {
760 	.disable = ili9882t_disable,
761 	.unprepare = ili9882t_unprepare,
762 	.prepare = ili9882t_prepare,
763 	.enable = ili9882t_enable,
764 	.get_modes = ili9882t_get_modes,
765 	.get_orientation = ili9882t_get_orientation,
766 };
767 
768 static int ili9882t_add(struct ili9882t *ili)
769 {
770 	struct device *dev = &ili->dsi->dev;
771 	int err;
772 
773 	ili->avdd = devm_regulator_get(dev, "avdd");
774 	if (IS_ERR(ili->avdd))
775 		return PTR_ERR(ili->avdd);
776 
777 	ili->avee = devm_regulator_get(dev, "avee");
778 	if (IS_ERR(ili->avee))
779 		return PTR_ERR(ili->avee);
780 
781 	ili->pp3300 = devm_regulator_get(dev, "pp3300");
782 	if (IS_ERR(ili->pp3300))
783 		return PTR_ERR(ili->pp3300);
784 
785 	ili->pp1800 = devm_regulator_get(dev, "pp1800");
786 	if (IS_ERR(ili->pp1800))
787 		return PTR_ERR(ili->pp1800);
788 
789 	ili->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
790 	if (IS_ERR(ili->enable_gpio)) {
791 		dev_err(dev, "cannot get enable-gpios %ld\n",
792 			PTR_ERR(ili->enable_gpio));
793 		return PTR_ERR(ili->enable_gpio);
794 	}
795 
796 	gpiod_set_value(ili->enable_gpio, 0);
797 
798 	err = of_drm_get_panel_orientation(dev->of_node, &ili->orientation);
799 	if (err < 0) {
800 		dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);
801 		return err;
802 	}
803 
804 	err = drm_panel_of_backlight(&ili->base);
805 	if (err)
806 		return err;
807 
808 	ili->base.funcs = &ili9882t_funcs;
809 	ili->base.dev = &ili->dsi->dev;
810 
811 	drm_panel_add(&ili->base);
812 
813 	return 0;
814 }
815 
816 static int ili9882t_probe(struct mipi_dsi_device *dsi)
817 {
818 	struct ili9882t *ili;
819 	int ret;
820 	const struct panel_desc *desc;
821 
822 	ili = devm_drm_panel_alloc(&dsi->dev, __typeof(*ili), base,
823 				   &ili9882t_funcs, DRM_MODE_CONNECTOR_DSI);
824 
825 	if (IS_ERR(ili))
826 		return PTR_ERR(ili);
827 
828 	desc = of_device_get_match_data(&dsi->dev);
829 	dsi->lanes = desc->lanes;
830 	dsi->format = desc->format;
831 	dsi->mode_flags = desc->mode_flags;
832 	ili->desc = desc;
833 	ili->dsi = dsi;
834 
835 	if (desc->dsc) {
836 		ili->dsc = *desc->dsc;
837 		dsi->dsc = &ili->dsc;
838 	}
839 
840 	ret = ili9882t_add(ili);
841 	if (ret < 0)
842 		return ret;
843 
844 	mipi_dsi_set_drvdata(dsi, ili);
845 
846 	ret = mipi_dsi_attach(dsi);
847 	if (ret)
848 		drm_panel_remove(&ili->base);
849 
850 	return ret;
851 }
852 
853 static void ili9882t_remove(struct mipi_dsi_device *dsi)
854 {
855 	struct ili9882t *ili = mipi_dsi_get_drvdata(dsi);
856 	int ret;
857 
858 	ret = mipi_dsi_detach(dsi);
859 	if (ret < 0)
860 		dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
861 
862 	if (ili->base.dev)
863 		drm_panel_remove(&ili->base);
864 }
865 
866 static const struct of_device_id ili9882t_of_match[] = {
867 	{ .compatible = "starry,ili9882t",
868 	  .data = &starry_ili9882t_desc
869 	},
870 	{ .compatible = "tianma,tl121bvms07-00",
871 	  .data = &tianma_tl121bvms07_desc
872 	},
873 	{ /* sentinel */ }
874 };
875 MODULE_DEVICE_TABLE(of, ili9882t_of_match);
876 
877 static struct mipi_dsi_driver ili9882t_driver = {
878 	.driver = {
879 		.name = "panel-ili9882t",
880 		.of_match_table = ili9882t_of_match,
881 	},
882 	.probe = ili9882t_probe,
883 	.remove = ili9882t_remove,
884 };
885 module_mipi_dsi_driver(ili9882t_driver);
886 
887 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
888 MODULE_DESCRIPTION("Ilitek ILI9882T-based panels driver");
889 MODULE_LICENSE("GPL");
890