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