xref: /linux/drivers/gpu/drm/panel/panel-himax-hx8394.c (revision 889600e21e3be388a6817c2a0dac0411df860751)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for panels based on Himax HX8394 controller, such as:
4  *
5  * - HannStar HSD060BHW4 5.99" MIPI-DSI panel
6  *
7  * Copyright (C) 2021 Kamil Trzciński
8  *
9  * Based on drivers/gpu/drm/panel/panel-sitronix-st7703.c
10  * Copyright (C) Purism SPC 2019
11  */
12 
13 #include <linux/delay.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/media-bus-format.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/regulator/consumer.h>
19 
20 #include <video/mipi_display.h>
21 
22 #include <drm/drm_mipi_dsi.h>
23 #include <drm/drm_modes.h>
24 #include <drm/drm_of.h>
25 #include <drm/drm_panel.h>
26 
27 #define DRV_NAME "panel-himax-hx8394"
28 
29 /* Manufacturer specific commands sent via DSI, listed in HX8394-F datasheet */
30 #define HX8394_CMD_SETSEQUENCE	  0xb0
31 #define HX8394_CMD_SETPOWER	  0xb1
32 #define HX8394_CMD_SETDISP	  0xb2
33 #define HX8394_CMD_SETCYC	  0xb4
34 #define HX8394_CMD_SETVCOM	  0xb6
35 #define HX8394_CMD_SETTE	  0xb7
36 #define HX8394_CMD_SETSENSOR	  0xb8
37 #define HX8394_CMD_SETEXTC	  0xb9
38 #define HX8394_CMD_SETMIPI	  0xba
39 #define HX8394_CMD_SETOTP	  0xbb
40 #define HX8394_CMD_SETREGBANK	  0xbd
41 #define HX8394_CMD_UNKNOWN5	  0xbf
42 #define HX8394_CMD_UNKNOWN1	  0xc0
43 #define HX8394_CMD_SETDGCLUT	  0xc1
44 #define HX8394_CMD_SETID	  0xc3
45 #define HX8394_CMD_SETDDB	  0xc4
46 #define HX8394_CMD_UNKNOWN2	  0xc6
47 #define HX8394_CMD_UNKNOWN6	  0xc7
48 #define HX8394_CMD_SETCABC	  0xc9
49 #define HX8394_CMD_SETCABCGAIN	  0xca
50 #define HX8394_CMD_SETPANEL	  0xcc
51 #define HX8394_CMD_SETOFFSET	  0xd2
52 #define HX8394_CMD_SETGIP0	  0xd3
53 #define HX8394_CMD_UNKNOWN3	  0xd4
54 #define HX8394_CMD_SETGIP1	  0xd5
55 #define HX8394_CMD_SETGIP2	  0xd6
56 #define HX8394_CMD_SETGPO	  0xd6
57 #define HX8394_CMD_UNKNOWN4	  0xd8
58 #define HX8394_CMD_SETSCALING	  0xdd
59 #define HX8394_CMD_SETIDLE	  0xdf
60 #define HX8394_CMD_SETGAMMA	  0xe0
61 #define HX8394_CMD_SETCHEMODE_DYN 0xe4
62 #define HX8394_CMD_SETCHE	  0xe5
63 #define HX8394_CMD_SETCESEL	  0xe6
64 #define HX8394_CMD_SET_SP_CMD	  0xe9
65 #define HX8394_CMD_SETREADINDEX	  0xfe
66 #define HX8394_CMD_GETSPIREAD	  0xff
67 
68 struct hx8394 {
69 	struct device *dev;
70 	struct drm_panel panel;
71 	struct gpio_desc *reset_gpio;
72 	struct regulator *vcc;
73 	struct regulator *iovcc;
74 	enum drm_panel_orientation orientation;
75 
76 	const struct hx8394_panel_desc *desc;
77 };
78 
79 struct hx8394_panel_desc {
80 	const struct drm_display_mode *mode;
81 	unsigned int lanes;
82 	unsigned long mode_flags;
83 	enum mipi_dsi_pixel_format format;
84 	void (*init_sequence)(struct mipi_dsi_multi_context *dsi_ctx);
85 };
86 
panel_to_hx8394(struct drm_panel * panel)87 static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
88 {
89 	return container_of(panel, struct hx8394, panel);
90 }
91 
hsd060bhw4_init_sequence(struct mipi_dsi_multi_context * dsi_ctx)92 static void hsd060bhw4_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
93 {
94 	/* 5.19.8 SETEXTC: Set extension command (B9h) */
95 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC,
96 				     0xff, 0x83, 0x94);
97 
98 	/* 5.19.2 SETPOWER: Set power (B1h) */
99 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
100 				     0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
101 
102 	/* 5.19.9 SETMIPI: Set MIPI control (BAh) */
103 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI,
104 				     0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
105 
106 	/* 5.19.3 SETDISP: Set display related register (B2h) */
107 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP,
108 				     0x00, 0x80, 0x78, 0x0c, 0x07);
109 
110 	/* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
111 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC,
112 				     0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55,
113 				     0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c,
114 				     0x7c);
115 
116 	/* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
117 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0,
118 				     0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10,
119 				     0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00,
120 				     0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00,
121 				     0x00, 0x0c, 0x40);
122 
123 	/* 5.19.20 Set GIP Option1 (D5h) */
124 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1,
125 				     0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01,
126 				     0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18,
127 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
128 				     0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
129 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
130 
131 	/* 5.19.21 Set GIP Option2 (D6h) */
132 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2,
133 				     0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06,
134 				     0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18,
135 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
136 				     0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
137 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
138 
139 	/* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
140 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA,
141 				     0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f,
142 				     0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a,
143 				     0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00,
144 				     0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31,
145 				     0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f,
146 				     0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b,
147 				     0x4a, 0x4c, 0x4b, 0x7f);
148 
149 	/* 5.19.17 SETPANEL (CCh) */
150 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL,
151 				     0x0b);
152 
153 	/* Unknown command, not listed in the HX8394-F datasheet */
154 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1,
155 				     0x1f, 0x31);
156 
157 	/* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
158 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM,
159 				     0x7d, 0x7d);
160 
161 	/* Unknown command, not listed in the HX8394-F datasheet */
162 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3,
163 				     0x02);
164 
165 	/* 5.19.11 Set register bank (BDh) */
166 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
167 				     0x01);
168 
169 	/* 5.19.2 SETPOWER: Set power (B1h) */
170 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
171 				     0x00);
172 
173 	/* 5.19.11 Set register bank (BDh) */
174 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
175 				     0x00);
176 
177 	/* Unknown command, not listed in the HX8394-F datasheet */
178 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3,
179 				     0xed);
180 }
181 
182 static const struct drm_display_mode hsd060bhw4_mode = {
183 	.hdisplay    = 720,
184 	.hsync_start = 720 + 40,
185 	.hsync_end   = 720 + 40 + 46,
186 	.htotal	     = 720 + 40 + 46 + 40,
187 	.vdisplay    = 1440,
188 	.vsync_start = 1440 + 9,
189 	.vsync_end   = 1440 + 9 + 7,
190 	.vtotal	     = 1440 + 9 + 7 + 7,
191 	.clock	     = 74250,
192 	.flags	     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
193 	.width_mm    = 68,
194 	.height_mm   = 136,
195 };
196 
197 static const struct hx8394_panel_desc hsd060bhw4_desc = {
198 	.mode = &hsd060bhw4_mode,
199 	.lanes = 4,
200 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
201 	.format = MIPI_DSI_FMT_RGB888,
202 	.init_sequence = hsd060bhw4_init_sequence,
203 };
204 
powkiddy_x55_init_sequence(struct mipi_dsi_multi_context * dsi_ctx)205 static void powkiddy_x55_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
206 {
207 	/* 5.19.8 SETEXTC: Set extension command (B9h) */
208 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC,
209 				     0xff, 0x83, 0x94);
210 
211 	/* 5.19.9 SETMIPI: Set MIPI control (BAh) */
212 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI,
213 				     0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
214 
215 	/* 5.19.2 SETPOWER: Set power (B1h) */
216 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
217 				     0x48, 0x12, 0x72, 0x09, 0x32, 0x54, 0x71, 0x71, 0x57, 0x47);
218 
219 	/* 5.19.3 SETDISP: Set display related register (B2h) */
220 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP,
221 				     0x00, 0x80, 0x64, 0x2c, 0x16, 0x2f);
222 
223 	/* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
224 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC,
225 				     0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, 0x86, 0x75,
226 				     0x00, 0x3f, 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c,
227 				     0x86);
228 
229 	/* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
230 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM,
231 				     0x6e, 0x6e);
232 
233 	/* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
234 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0,
235 				     0x00, 0x00, 0x07, 0x07, 0x40, 0x07, 0x0c, 0x00, 0x08, 0x10,
236 				     0x08, 0x00, 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, 0x02, 0x15,
237 				     0x06, 0x05, 0x06, 0x47, 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07,
238 				     0x07, 0x0c, 0x40);
239 
240 	/* 5.19.20 Set GIP Option1 (D5h) */
241 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1,
242 				     0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
243 				     0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, 0x18, 0x18,
244 				     0x26, 0x27, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
245 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x21,
246 				     0x18, 0x18, 0x18, 0x18);
247 
248 	/* 5.19.21 Set GIP Option2 (D6h) */
249 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2,
250 				     0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
251 				     0x01, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, 0x18, 0x18,
252 				     0x27, 0x26, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
253 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x25, 0x24,
254 				     0x18, 0x18, 0x18, 0x18);
255 
256 	/* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
257 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA,
258 				     0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56,
259 				     0x65, 0x66, 0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d, 0x98, 0xa8,
260 				     0xb9, 0x5d, 0x5c, 0x61, 0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00,
261 				     0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56, 0x65,
262 				     0x65, 0x6e, 0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99, 0xa8, 0xba,
263 				     0x5d, 0x5d, 0x62, 0x67, 0x6b, 0x72, 0x7f, 0x7f);
264 
265 	/* Unknown command, not listed in the HX8394-F datasheet */
266 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1,
267 				     0x1f, 0x31);
268 
269 	/* 5.19.17 SETPANEL (CCh) */
270 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL,
271 				     0x0b);
272 
273 	/* Unknown command, not listed in the HX8394-F datasheet */
274 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3,
275 				     0x02);
276 
277 	/* 5.19.11 Set register bank (BDh) */
278 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
279 				     0x02);
280 
281 	/* Unknown command, not listed in the HX8394-F datasheet */
282 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4,
283 				     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
284 				     0xff, 0xff);
285 
286 	/* 5.19.11 Set register bank (BDh) */
287 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
288 				     0x00);
289 
290 	/* 5.19.11 Set register bank (BDh) */
291 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
292 				     0x01);
293 
294 	/* 5.19.2 SETPOWER: Set power (B1h) */
295 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
296 				     0x00);
297 
298 	/* 5.19.11 Set register bank (BDh) */
299 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
300 				     0x00);
301 
302 	/* Unknown command, not listed in the HX8394-F datasheet */
303 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN5,
304 				     0x40, 0x81, 0x50, 0x00, 0x1a, 0xfc, 0x01);
305 
306 	/* Unknown command, not listed in the HX8394-F datasheet */
307 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN2,
308 				     0xed);
309 }
310 
311 static const struct drm_display_mode powkiddy_x55_mode = {
312 	.hdisplay	= 720,
313 	.hsync_start	= 720 + 44,
314 	.hsync_end	= 720 + 44 + 20,
315 	.htotal		= 720 + 44 + 20 + 20,
316 	.vdisplay	= 1280,
317 	.vsync_start	= 1280 + 12,
318 	.vsync_end	= 1280 + 12 + 10,
319 	.vtotal		= 1280 + 12 + 10 + 10,
320 	.clock		= 63290,
321 	.flags		= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
322 	.width_mm	= 67,
323 	.height_mm	= 121,
324 };
325 
326 static const struct hx8394_panel_desc powkiddy_x55_desc = {
327 	.mode = &powkiddy_x55_mode,
328 	.lanes = 4,
329 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
330 		      MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET,
331 	.format = MIPI_DSI_FMT_RGB888,
332 	.init_sequence = powkiddy_x55_init_sequence,
333 };
334 
mchp_ac40t08a_init_sequence(struct mipi_dsi_multi_context * dsi_ctx)335 static void mchp_ac40t08a_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
336 {
337 	/* DCS commands do not seem to be sent correclty without this delay */
338 	mipi_dsi_msleep(dsi_ctx, 20);
339 
340 	/* 5.19.8 SETEXTC: Set extension command (B9h) */
341 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC,
342 				     0xff, 0x83, 0x94);
343 
344 	/* 5.19.9 SETMIPI: Set MIPI control (BAh) */
345 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI,
346 				     0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
347 
348 	/* 5.19.2 SETPOWER: Set power (B1h) */
349 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
350 				     0x48, 0x12, 0x72, 0x09, 0x32, 0x54,
351 				     0x71, 0x71, 0x57, 0x47);
352 
353 	/* 5.19.3 SETDISP: Set display related register (B2h) */
354 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP,
355 				     0x00, 0x80, 0x64, 0x0c, 0x0d, 0x2f);
356 
357 	/* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
358 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC,
359 				     0x73, 0x74, 0x73, 0x74, 0x73, 0x74,
360 				     0x01, 0x0c, 0x86, 0x75, 0x00, 0x3f,
361 				     0x73, 0x74, 0x73, 0x74, 0x73, 0x74,
362 				     0x01, 0x0c, 0x86);
363 
364 	/* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
365 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM,
366 				     0x6e, 0x6e);
367 
368 	/* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
369 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0,
370 				     0x00, 0x00, 0x07, 0x07, 0x40, 0x07,
371 				     0x0c, 0x00, 0x08, 0x10, 0x08, 0x00,
372 				     0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a,
373 				     0x02, 0x15, 0x06, 0x05, 0x06, 0x47,
374 				     0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07,
375 				     0x07, 0x0c, 0x40);
376 
377 	/* 5.19.20 Set GIP Option1 (D5h) */
378 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1,
379 				     0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01,
380 				     0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
381 				     0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25,
382 				     0x18, 0x18, 0x26, 0x27, 0x18, 0x18,
383 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
384 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
385 				     0x18, 0x18, 0x20, 0x21, 0x18, 0x18,
386 				     0x18, 0x18);
387 
388 	/* 5.19.21 Set GIP Option2 (D6h) */
389 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2,
390 				     0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06,
391 				     0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
392 				     0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20,
393 				     0x18, 0x18, 0x27, 0x26, 0x18, 0x18,
394 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
395 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
396 				     0x18, 0x18, 0x25, 0x24, 0x18, 0x18,
397 				     0x18, 0x18);
398 
399 	/* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
400 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA,
401 				     0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21,
402 				     0x24, 0x22, 0x47, 0x56, 0x65, 0x66,
403 				     0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d,
404 				     0x98, 0xa8, 0xb9, 0x5d, 0x5c, 0x61,
405 				     0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00,
406 				     0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24,
407 				     0x22, 0x47, 0x56, 0x65, 0x65, 0x6e,
408 				     0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99,
409 				     0xa8, 0xba, 0x5d, 0x5d, 0x62, 0x67,
410 				     0x6b, 0x72, 0x7f, 0x7f);
411 
412 	/* Unknown command, not listed in the HX8394-F datasheet (C0H) */
413 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1,
414 				     0x1f, 0x73);
415 
416 	/* Set CABC control (C9h)*/
417 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCABC,
418 				     0x76, 0x00, 0x30);
419 
420 	/* 5.19.17 SETPANEL (CCh) */
421 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL,
422 				     0x0b);
423 
424 	/* Unknown command, not listed in the HX8394-F datasheet (D4h) */
425 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3,
426 				     0x02);
427 
428 	/* 5.19.11 Set register bank (BDh) */
429 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
430 				     0x02);
431 
432 	/* 5.19.11 Set register bank (D8h) */
433 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4,
434 				     0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
435 				     0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
436 
437 	/* 5.19.11 Set register bank (BDh) */
438 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
439 				     0x00);
440 
441 	/* 5.19.11 Set register bank (BDh) */
442 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
443 				     0x01);
444 
445 	/* 5.19.2 SETPOWER: Set power (B1h) */
446 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
447 				     0x00);
448 
449 	/* 5.19.11 Set register bank (BDh) */
450 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
451 				     0x00);
452 
453 	/* Unknown command, not listed in the HX8394-F datasheet (C6h) */
454 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN2,
455 				     0xed);
456 }
457 
458 static const struct drm_display_mode mchp_ac40t08a_mode = {
459 	.hdisplay    = 720,
460 	.hsync_start = 720 + 12,
461 	.hsync_end   = 720 + 12 + 24,
462 	.htotal	     = 720 + 12 + 12 + 24,
463 	.vdisplay    = 1280,
464 	.vsync_start = 1280 + 13,
465 	.vsync_end   = 1280 + 14,
466 	.vtotal	     = 1280 + 14 + 13,
467 	.clock	     = 60226,
468 	.flags	     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
469 	.width_mm    = 76,
470 	.height_mm   = 132,
471 };
472 
473 static const struct hx8394_panel_desc mchp_ac40t08a_desc = {
474 	.mode = &mchp_ac40t08a_mode,
475 	.lanes = 4,
476 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
477 	.format = MIPI_DSI_FMT_RGB888,
478 	.init_sequence = mchp_ac40t08a_init_sequence,
479 };
480 
481 /*
482  * HL055FHAV028C is based on Himax HX8399, so datasheet pages are
483  * slightly different than HX8394 based panels.
484  */
hl055fhav028c_init_sequence(struct mipi_dsi_multi_context * dsi_ctx)485 static void hl055fhav028c_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
486 {
487 	/* 6.3.6 SETEXTC: Set extension command (B9h) */
488 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC,
489 				     0xff, 0x83, 0x99);
490 
491 	/* 6.3.17 SETOFFSET: Set offset voltage (D2h) */
492 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETOFFSET,
493 				     0x77);
494 
495 	/* 6.3.1 SETPOWER: Set power (B1h) */
496 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
497 				     0x02, 0x04, 0x74, 0x94, 0x01, 0x32,
498 				     0x33, 0x11, 0x11, 0xab, 0x4d, 0x56,
499 				     0x73, 0x02, 0x02);
500 
501 	/* 6.3.2 SETDISP: Set display related register (B2h) */
502 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP,
503 				     0x00, 0x80, 0x80, 0xae, 0x05, 0x07,
504 				     0x5a, 0x11, 0x00, 0x00, 0x10, 0x1e,
505 				     0x70, 0x03, 0xd4);
506 
507 	/* 6.3.3 SETCYC: Set display waveform cycles (B4h) */
508 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC,
509 				     0x00, 0xff, 0x02, 0xc0, 0x02, 0xc0,
510 				     0x00, 0x00, 0x08, 0x00, 0x04, 0x06,
511 				     0x00, 0x32, 0x04, 0x0a, 0x08, 0x21,
512 				     0x03, 0x01, 0x00, 0x0f, 0xb8, 0x8b,
513 				     0x02, 0xc0, 0x02, 0xc0, 0x00, 0x00,
514 				     0x08, 0x00, 0x04, 0x06, 0x00, 0x32,
515 				     0x04, 0x0a, 0x08, 0x01, 0x00, 0x0f,
516 				     0xb8, 0x01);
517 
518 	/* 6.3.18 SETGIP0: Set GIP Option0 (D3h) */
519 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0,
520 				     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 				     0x06, 0x00, 0x00, 0x10, 0x04, 0x00,
522 				     0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
523 				     0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
524 				     0x00, 0x05, 0x05, 0x07, 0x00, 0x00,
525 				     0x00, 0x05, 0x40);
526 
527 	/* 6.3.19 Set GIP Option1 (D5h) */
528 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1,
529 				     0x18, 0x18, 0x19, 0x19, 0x18, 0x18,
530 				     0x21, 0x20, 0x01, 0x00, 0x07, 0x06,
531 				     0x05, 0x04, 0x03, 0x02, 0x18, 0x18,
532 				     0x18, 0x18, 0x18, 0x18, 0x2f, 0x2f,
533 				     0x30, 0x30, 0x31, 0x31, 0x18, 0x18,
534 				     0x18, 0x18);
535 
536 	/* 6.3.20 Set GIP Option2 (D6h) */
537 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2,
538 				     0x18, 0x18, 0x19, 0x19, 0x40, 0x40,
539 				     0x20, 0x21, 0x02, 0x03, 0x04, 0x05,
540 				     0x06, 0x07, 0x00, 0x01, 0x40, 0x40,
541 				     0x40, 0x40, 0x40, 0x40, 0x2f, 0x2f,
542 				     0x30, 0x30, 0x31, 0x31, 0x40, 0x40,
543 				     0x40, 0x40);
544 
545 	/* 6.3.21 Set GIP Option3 (D8h) */
546 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4,
547 				     0xa2, 0xaa, 0x02, 0xa0, 0xa2, 0xa8,
548 				     0x02, 0xa0, 0xb0, 0x00, 0x00, 0x00,
549 				     0xb0, 0x00, 0x00, 0x00);
550 
551 	/* 6.3.9 Set register bank (BDh) */
552 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
553 				     0x01);
554 
555 	/* 6.3.21 Set GIP Option3 (D8h) */
556 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4,
557 				     0xb0, 0x00, 0x00, 0x00, 0xb0, 0x00,
558 				     0x00, 0x00, 0xe2, 0xaa, 0x03, 0xf0,
559 				     0xe2, 0xaa, 0x03, 0xf0);
560 
561 	/* 6.3.9 Set register bank (BDh) */
562 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
563 				     0x02);
564 
565 	/* 6.3.21 Set GIP Option3 (D8h) */
566 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4,
567 				     0xe2, 0xaa, 0x03, 0xf0, 0xe2, 0xaa,
568 				     0x03, 0xf0);
569 
570 	/* 6.3.9 Set register bank (BDh) */
571 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
572 				     0x00);
573 
574 	/* 6.3.4 SETVCOM: Set VCOM voltage (B6h) */
575 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM,
576 				     0x7a, 0x7a);
577 
578 	/* 6.3.26 SETGAMMA: Set gamma curve related setting (E0h) */
579 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA,
580 				     0x00, 0x18, 0x27, 0x24, 0x5a, 0x68,
581 				     0x79, 0x78, 0x81, 0x8a, 0x92, 0x99,
582 				     0x9e, 0xa7, 0xaf, 0xb4, 0xb9, 0xc3,
583 				     0xc7, 0xd1, 0xc6, 0xd4, 0xd5, 0x6c,
584 				     0x67, 0x71, 0x77, 0x00, 0x00, 0x18,
585 				     0x27, 0x24, 0x5a, 0x68, 0x79, 0x78,
586 				     0x81, 0x8a, 0x92, 0x99, 0x9e, 0xa7,
587 				     0xaf, 0xb4, 0xb9, 0xc3, 0xc7, 0xd1,
588 				     0xc6, 0xd4, 0xd5, 0x6c, 0x67, 0x77);
589 
590 	/* Unknown command, not listed in the HX8399-C datasheet (C6h) */
591 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN2,
592 				     0xff, 0xf9);
593 
594 	/* 6.3.16 SETPANEL (CCh) */
595 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL,
596 				     0x08);
597 }
598 
599 static const struct drm_display_mode hl055fhav028c_mode = {
600 	.hdisplay	= 1080,
601 	.hsync_start	= 1080 + 32,
602 	.hsync_end	= 1080 + 32 + 8,
603 	.htotal		= 1080 + 32 + 8 + 32,
604 	.vdisplay	= 1920,
605 	.vsync_start	= 1920 + 16,
606 	.vsync_end	= 1920 + 16 + 2,
607 	.vtotal		= 1920 + 16 + 2 + 14,
608 	.clock		= 134920,
609 	.flags		= DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
610 	.width_mm	= 70,
611 	.height_mm	= 127,
612 };
613 
614 static const struct hx8394_panel_desc hl055fhav028c_desc = {
615 	.mode = &hl055fhav028c_mode,
616 	.lanes = 4,
617 	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
618 	.format = MIPI_DSI_FMT_RGB888,
619 	.init_sequence = hl055fhav028c_init_sequence,
620 };
621 
waveshare_5_0_inch_a_init_sequence(struct mipi_dsi_multi_context * dsi_ctx)622 static void waveshare_5_0_inch_a_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
623 {
624 	/* 5.19.8 SETEXTC: Set extension command (B9h) */
625 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC,
626 				     0xff, 0x83, 0x94);
627 
628 	/* 5.19.2 SETPOWER: Set power (B1h) */
629 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
630 				     0x48, 0x0a, 0x6a, 0x09, 0x33, 0x54, 0x71, 0x71, 0x2e, 0x45);
631 
632 	/* 5.19.9 SETMIPI: Set MIPI control (BAh) */
633 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI,
634 				     0x61, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
635 
636 	/* 5.19.3 SETDISP: Set display related register (B2h) */
637 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP,
638 				     0x00, 0x80, 0x64, 0x0c, 0x06, 0x2f);
639 
640 	/* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
641 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC,
642 				     0x1c, 0x78, 0x1c, 0x78, 0x1c, 0x78, 0x01, 0x0c, 0x86, 0x75,
643 				     0x00, 0x3f, 0x1c, 0x78, 0x1c, 0x78, 0x1c, 0x78, 0x01, 0x0c,
644 				     0x86);
645 
646 	/* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
647 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0,
648 				     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x32, 0x10,
649 				     0x05, 0x00, 0x05, 0x32, 0x13, 0xc1, 0x00, 0x01, 0x32, 0x10,
650 				     0x08, 0x00, 0x00, 0x37, 0x03, 0x07, 0x07, 0x37, 0x05, 0x05,
651 				     0x37, 0x0c, 0x40);
652 
653 	/* 5.19.20 Set GIP Option1 (D5h) */
654 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1,
655 				     0x18, 0x18, 0x18, 0x18, 0x22, 0x23, 0x20, 0x21, 0x04, 0x05,
656 				     0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x18, 0x18, 0x18, 0x18,
657 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
658 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
659 				     0x19, 0x19, 0x19, 0x19);
660 
661 	/* 5.19.21 Set GIP Option2 (D6h) */
662 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2,
663 				     0x18, 0x18, 0x19, 0x19, 0x21, 0x20, 0x23, 0x22, 0x03, 0x02,
664 				     0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x18, 0x18, 0x18, 0x18,
665 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
666 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
667 				     0x19, 0x19, 0x18, 0x18);
668 
669 	/* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
670 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA,
671 				     0x07, 0x08, 0x09, 0x0d, 0x10, 0x14, 0x16, 0x13, 0x24, 0x36,
672 				     0x48, 0x4a, 0x58, 0x6f, 0x76, 0x80, 0x97, 0xa5, 0xa8, 0xb5,
673 				     0xc6, 0x62, 0x63, 0x68, 0x6f, 0x72, 0x78, 0x7f, 0x7f, 0x00,
674 				     0x02, 0x08, 0x0d, 0x0c, 0x0e, 0x0f, 0x10, 0x24, 0x36, 0x48,
675 				     0x4a, 0x58, 0x6f, 0x78, 0x82, 0x99, 0xa4, 0xa0, 0xb1, 0xc0,
676 				     0x5e, 0x5e, 0x64, 0x6b, 0x6c, 0x73, 0x7f, 0x7f);
677 
678 	/* 5.19.17 SETPANEL (CCh) */
679 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL,
680 				     0x0b);
681 
682 	/* Unknown command, not listed in the HX8394-F datasheet */
683 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1,
684 				     0x1f, 0x73);
685 
686 	/* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
687 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM,
688 				     0x6b, 0x6b);
689 
690 	/* Unknown command, not listed in the HX8394-F datasheet */
691 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3,
692 				     0x02);
693 
694 	/* 5.19.11 Set register bank (BDh) */
695 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
696 				     0x01);
697 
698 	/* 5.19.2 SETPOWER: Set power (B1h) */
699 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
700 				     0x00);
701 
702 	/* 5.19.11 Set register bank (BDh) */
703 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
704 				     0x00);
705 
706 	/* Unknown command, not listed in the HX8394-F datasheet */
707 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN5,
708 				     0x40, 0x81, 0x50, 0x00, 0x1a, 0xfc, 0x01);
709 };
710 
711 static const struct drm_display_mode waveshare_5_0_inch_a_mode = {
712 	.clock = 70000,
713 	.hdisplay = 720,
714 	.hsync_start = 720 + 40,
715 	.hsync_end = 720 + 40 + 20,
716 	.htotal = 720 + 40 + 20 + 20,
717 	.vdisplay = 1280,
718 	.vsync_start = 1280 + 30,
719 	.vsync_end = 1280 + 30 + 10,
720 	.vtotal = 1280 + 30 + 10 + 4,
721 	.width_mm = 62,
722 	.height_mm = 110,
723 };
724 
725 static const struct hx8394_panel_desc waveshare_5_0_inch_a_desc = {
726 	.mode = &waveshare_5_0_inch_a_mode,
727 	.lanes = 2,
728 	.mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
729 		      MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
730 	.format = MIPI_DSI_FMT_RGB888,
731 	.init_sequence = waveshare_5_0_inch_a_init_sequence,
732 };
733 
734 static const struct drm_display_mode waveshare_5_5_inch_a_mode = {
735 	.clock = 65000,
736 	.hdisplay = 720,
737 	.hsync_start = 720 + 50,
738 	.hsync_end = 720 + 50 + 50,
739 	.htotal = 720 + 50 + 50 + 10,
740 	.vdisplay = 1280,
741 	.vsync_start = 1280 + 15,
742 	.vsync_end = 1280 + 15 + 12,
743 	.vtotal = 1280 + 15 + 12 + 4,
744 	.width_mm = 62,
745 	.height_mm = 110,
746 };
747 
waveshare_5_5_inch_a_init_sequence(struct mipi_dsi_multi_context * dsi_ctx)748 static void waveshare_5_5_inch_a_init_sequence(struct mipi_dsi_multi_context *dsi_ctx)
749 {
750 	/* 5.19.8 SETEXTC: Set extension command (B9h) */
751 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETEXTC,
752 				     0xff, 0x83, 0x94);
753 
754 	/* 5.19.9 SETMIPI: Set MIPI control (BAh) */
755 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETMIPI,
756 				     0x61, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
757 
758 	/* 5.19.2 SETPOWER: Set power (B1h) */
759 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
760 				     0x48, 0x12, 0x72, 0x09, 0x32, 0x54, 0x71, 0x71, 0x57, 0x47);
761 
762 	/* 5.19.3 SETDISP: Set display related register (B2h) */
763 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETDISP,
764 				     0x00, 0x80, 0x64, 0x0c, 0x0d, 0x2f);
765 
766 	/* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
767 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETCYC,
768 				     0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, 0x86, 0x75,
769 				     0x00, 0x3f, 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c,
770 				     0x86);
771 
772 	/* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
773 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETVCOM,
774 				     0x86, 0x86);
775 
776 	/* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
777 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP0,
778 				     0x00, 0x00, 0x07, 0x07, 0x40, 0x07, 0x0c, 0x00, 0x08, 0x10,
779 				     0x08, 0x00, 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, 0x02, 0x15,
780 				     0x06, 0x05, 0x06, 0x47, 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07,
781 				     0x07, 0x0c, 0x40);
782 
783 	/* 5.19.20 Set GIP Option1 (D5h) */
784 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP1,
785 				     0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
786 				     0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, 0x18, 0x18,
787 				     0x26, 0x27, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
788 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x21,
789 				     0x18, 0x18, 0x18, 0x18);
790 
791 	/* 5.19.21 Set GIP Option2 (D6h) */
792 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGIP2,
793 				     0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
794 				     0x01, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, 0x18, 0x18,
795 				     0x27, 0x26, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
796 				     0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x25, 0x24,
797 				     0x18, 0x18, 0x18, 0x18);
798 
799 	/* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
800 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETGAMMA,
801 				     0x00, 0x13, 0x21, 0x28, 0x2b, 0x2e, 0x32, 0x2f, 0x61, 0x6e,
802 				     0x7e, 0x7b, 0x80, 0x8f, 0x91, 0x93, 0x9d, 0x9d, 0x97, 0xa4,
803 				     0xb1, 0x57, 0x55, 0x58, 0x5d, 0x60, 0x67, 0x74, 0x7f, 0x00,
804 				     0x13, 0x21, 0x28, 0x2b, 0x2e, 0x32, 0x2f, 0x61, 0x6e, 0x7d,
805 				     0x7b, 0x7f, 0x8e, 0x90, 0x93, 0x9c, 0x9d, 0x98, 0xa4, 0xb1,
806 				     0x58, 0x55, 0x59, 0x5e, 0x61, 0x68, 0x76, 0x7f);
807 
808 	/* Unknown command, not listed in the HX8394-F datasheet */
809 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN1,
810 				     0x1f, 0x31);
811 
812 	/* 5.19.17 SETPANEL (CCh) */
813 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPANEL,
814 				     0x07);
815 
816 	/* Unknown command, not listed in the HX8394-F datasheet */
817 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN3,
818 				     0x02);
819 
820 	/* 5.19.11 Set register bank (BDh) */
821 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
822 				     0x02);
823 
824 	/* Unknown command, not listed in the HX8394-F datasheet */
825 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN4,
826 				     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
827 				     0xff, 0xff);
828 
829 	/* 5.19.11 Set register bank (BDh) */
830 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
831 				     0x00);
832 
833 	/* 5.19.11 Set register bank (BDh) */
834 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
835 				     0x01);
836 
837 	/* 5.19.2 SETPOWER: Set power (B1h) */
838 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETPOWER,
839 				     0x00);
840 
841 	/* 5.19.11 Set register bank (BDh) */
842 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_SETREGBANK,
843 				     0x00);
844 
845 	/* Unknown command, not listed in the HX8394-F datasheet */
846 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN2,
847 				     0xed);
848 
849 	/* Unknown command, not listed in the HX8394-F datasheet */
850 	mipi_dsi_dcs_write_seq_multi(dsi_ctx, HX8394_CMD_UNKNOWN6,
851 				     0x00, 0xc0);
852 };
853 
854 static const struct hx8394_panel_desc waveshare_5_5_inch_a_desc = {
855 	.mode = &waveshare_5_5_inch_a_mode,
856 	.lanes = 2,
857 	.mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
858 		      MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS,
859 	.format = MIPI_DSI_FMT_RGB888,
860 	.init_sequence = waveshare_5_5_inch_a_init_sequence,
861 };
862 
hx8394_disable(struct drm_panel * panel)863 static int hx8394_disable(struct drm_panel *panel)
864 {
865 	struct hx8394 *ctx = panel_to_hx8394(panel);
866 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
867 	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
868 
869 	mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
870 	mipi_dsi_msleep(&dsi_ctx, 50); /* about 3 frames */
871 
872 	return dsi_ctx.accum_err;
873 }
874 
hx8394_enable(struct drm_panel * panel)875 static int hx8394_enable(struct drm_panel *panel)
876 {
877 	struct hx8394 *ctx = panel_to_hx8394(panel);
878 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
879 	struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
880 
881 	ctx->desc->init_sequence(&dsi_ctx);
882 
883 	mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
884 
885 	/* Panel is operational 120 msec after reset */
886 	mipi_dsi_msleep(&dsi_ctx, 120);
887 
888 	mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
889 	if (dsi_ctx.accum_err)
890 		hx8394_disable(panel);
891 
892 	return dsi_ctx.accum_err;
893 }
894 
hx8394_unprepare(struct drm_panel * panel)895 static int hx8394_unprepare(struct drm_panel *panel)
896 {
897 	struct hx8394 *ctx = panel_to_hx8394(panel);
898 
899 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
900 
901 	regulator_disable(ctx->iovcc);
902 	regulator_disable(ctx->vcc);
903 
904 	return 0;
905 }
906 
hx8394_prepare(struct drm_panel * panel)907 static int hx8394_prepare(struct drm_panel *panel)
908 {
909 	struct hx8394 *ctx = panel_to_hx8394(panel);
910 	int ret;
911 
912 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
913 
914 	ret = regulator_enable(ctx->vcc);
915 	if (ret) {
916 		dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
917 		return ret;
918 	}
919 
920 	ret = regulator_enable(ctx->iovcc);
921 	if (ret) {
922 		dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
923 		goto disable_vcc;
924 	}
925 
926 	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
927 
928 	msleep(180);
929 
930 	return 0;
931 
932 disable_vcc:
933 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
934 	regulator_disable(ctx->vcc);
935 	return ret;
936 }
937 
hx8394_get_modes(struct drm_panel * panel,struct drm_connector * connector)938 static int hx8394_get_modes(struct drm_panel *panel,
939 			    struct drm_connector *connector)
940 {
941 	struct hx8394 *ctx = panel_to_hx8394(panel);
942 	struct drm_display_mode *mode;
943 
944 	mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
945 	if (!mode) {
946 		dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
947 			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
948 			drm_mode_vrefresh(ctx->desc->mode));
949 		return -ENOMEM;
950 	}
951 
952 	drm_mode_set_name(mode);
953 
954 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
955 	connector->display_info.width_mm = mode->width_mm;
956 	connector->display_info.height_mm = mode->height_mm;
957 	drm_mode_probed_add(connector, mode);
958 
959 	return 1;
960 }
961 
hx8394_get_orientation(struct drm_panel * panel)962 static enum drm_panel_orientation hx8394_get_orientation(struct drm_panel *panel)
963 {
964 	struct hx8394 *ctx = panel_to_hx8394(panel);
965 
966 	return ctx->orientation;
967 }
968 
969 static const struct drm_panel_funcs hx8394_drm_funcs = {
970 	.disable   = hx8394_disable,
971 	.unprepare = hx8394_unprepare,
972 	.prepare   = hx8394_prepare,
973 	.enable	   = hx8394_enable,
974 	.get_modes = hx8394_get_modes,
975 	.get_orientation = hx8394_get_orientation,
976 };
977 
hx8394_probe(struct mipi_dsi_device * dsi)978 static int hx8394_probe(struct mipi_dsi_device *dsi)
979 {
980 	struct device *dev = &dsi->dev;
981 	struct hx8394 *ctx;
982 	int ret;
983 
984 	ctx = devm_drm_panel_alloc(dev, struct hx8394, panel,
985 				   &hx8394_drm_funcs,
986 				   DRM_MODE_CONNECTOR_DSI);
987 	if (IS_ERR(ctx))
988 		return PTR_ERR(ctx);
989 
990 	ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
991 	if (IS_ERR(ctx->reset_gpio))
992 		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
993 				     "Failed to get reset gpio\n");
994 
995 	ret = drm_of_get_panel_orientation(dev->of_node, &ctx->orientation);
996 	if (ret < 0) {
997 		dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, ret);
998 		return ret;
999 	}
1000 
1001 	mipi_dsi_set_drvdata(dsi, ctx);
1002 
1003 	ctx->dev = dev;
1004 	ctx->desc = of_device_get_match_data(dev);
1005 
1006 	dsi->mode_flags = ctx->desc->mode_flags;
1007 	dsi->format = ctx->desc->format;
1008 	dsi->lanes = ctx->desc->lanes;
1009 
1010 	ctx->vcc = devm_regulator_get(dev, "vcc");
1011 	if (IS_ERR(ctx->vcc))
1012 		return dev_err_probe(dev, PTR_ERR(ctx->vcc),
1013 				     "Failed to request vcc regulator\n");
1014 
1015 	ctx->iovcc = devm_regulator_get(dev, "iovcc");
1016 	if (IS_ERR(ctx->iovcc))
1017 		return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
1018 				     "Failed to request iovcc regulator\n");
1019 
1020 	ret = drm_panel_of_backlight(&ctx->panel);
1021 	if (ret)
1022 		return ret;
1023 
1024 	ctx->panel.prepare_prev_first = true;
1025 
1026 	drm_panel_add(&ctx->panel);
1027 
1028 	ret = mipi_dsi_attach(dsi);
1029 	if (ret < 0) {
1030 		dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
1031 		drm_panel_remove(&ctx->panel);
1032 		return ret;
1033 	}
1034 
1035 	dev_dbg(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
1036 		ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
1037 		drm_mode_vrefresh(ctx->desc->mode),
1038 		mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
1039 
1040 	return 0;
1041 }
1042 
hx8394_remove(struct mipi_dsi_device * dsi)1043 static void hx8394_remove(struct mipi_dsi_device *dsi)
1044 {
1045 	struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
1046 	int ret;
1047 
1048 	ret = mipi_dsi_detach(dsi);
1049 	if (ret < 0)
1050 		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
1051 
1052 	drm_panel_remove(&ctx->panel);
1053 }
1054 
1055 static const struct of_device_id hx8394_of_match[] = {
1056 	{ .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
1057 	{ .compatible = "huiling,hl055fhav028c", .data = &hl055fhav028c_desc },
1058 	{ .compatible = "powkiddy,x55-panel", .data = &powkiddy_x55_desc },
1059 	{ .compatible = "microchip,ac40t08a-mipi-panel", .data = &mchp_ac40t08a_desc },
1060 	{ .compatible = "waveshare,5.0-dsi-touch-a", .data = &waveshare_5_0_inch_a_desc },
1061 	{ .compatible = "waveshare,5.5-dsi-touch-a", .data = &waveshare_5_5_inch_a_desc },
1062 	{ /* sentinel */ }
1063 };
1064 MODULE_DEVICE_TABLE(of, hx8394_of_match);
1065 
1066 static struct mipi_dsi_driver hx8394_driver = {
1067 	.probe	= hx8394_probe,
1068 	.remove = hx8394_remove,
1069 	.driver = {
1070 		.name = DRV_NAME,
1071 		.of_match_table = hx8394_of_match,
1072 	},
1073 };
1074 module_mipi_dsi_driver(hx8394_driver);
1075 
1076 MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>");
1077 MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
1078 MODULE_LICENSE("GPL");
1079