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/mod_devicetable.h>
17 #include <linux/module.h>
18 #include <linux/of.h>
19 #include <linux/regulator/consumer.h>
20
21 #include <video/mipi_display.h>
22
23 #include <drm/drm_mipi_dsi.h>
24 #include <drm/drm_modes.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_UNKNOWN1 0xc0
42 #define HX8394_CMD_SETDGCLUT 0xc1
43 #define HX8394_CMD_SETID 0xc3
44 #define HX8394_CMD_SETDDB 0xc4
45 #define HX8394_CMD_UNKNOWN2 0xc6
46 #define HX8394_CMD_SETCABC 0xc9
47 #define HX8394_CMD_SETCABCGAIN 0xca
48 #define HX8394_CMD_SETPANEL 0xcc
49 #define HX8394_CMD_SETOFFSET 0xd2
50 #define HX8394_CMD_SETGIP0 0xd3
51 #define HX8394_CMD_UNKNOWN3 0xd4
52 #define HX8394_CMD_SETGIP1 0xd5
53 #define HX8394_CMD_SETGIP2 0xd6
54 #define HX8394_CMD_SETGPO 0xd6
55 #define HX8394_CMD_SETSCALING 0xdd
56 #define HX8394_CMD_SETIDLE 0xdf
57 #define HX8394_CMD_SETGAMMA 0xe0
58 #define HX8394_CMD_SETCHEMODE_DYN 0xe4
59 #define HX8394_CMD_SETCHE 0xe5
60 #define HX8394_CMD_SETCESEL 0xe6
61 #define HX8394_CMD_SET_SP_CMD 0xe9
62 #define HX8394_CMD_SETREADINDEX 0xfe
63 #define HX8394_CMD_GETSPIREAD 0xff
64
65 struct hx8394 {
66 struct device *dev;
67 struct drm_panel panel;
68 struct gpio_desc *reset_gpio;
69 struct regulator *vcc;
70 struct regulator *iovcc;
71 bool prepared;
72
73 const struct hx8394_panel_desc *desc;
74 };
75
76 struct hx8394_panel_desc {
77 const struct drm_display_mode *mode;
78 unsigned int lanes;
79 unsigned long mode_flags;
80 enum mipi_dsi_pixel_format format;
81 int (*init_sequence)(struct hx8394 *ctx);
82 };
83
panel_to_hx8394(struct drm_panel * panel)84 static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
85 {
86 return container_of(panel, struct hx8394, panel);
87 }
88
hsd060bhw4_init_sequence(struct hx8394 * ctx)89 static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
90 {
91 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
92
93 /* 5.19.8 SETEXTC: Set extension command (B9h) */
94 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC,
95 0xff, 0x83, 0x94);
96
97 /* 5.19.2 SETPOWER: Set power (B1h) */
98 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
99 0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
100
101 /* 5.19.9 SETMIPI: Set MIPI control (BAh) */
102 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI,
103 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
104
105 /* 5.19.3 SETDISP: Set display related register (B2h) */
106 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP,
107 0x00, 0x80, 0x78, 0x0c, 0x07);
108
109 /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */
110 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC,
111 0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55,
112 0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c,
113 0x7c);
114
115 /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */
116 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0,
117 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10,
118 0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00,
119 0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00,
120 0x00, 0x0c, 0x40);
121
122 /* 5.19.20 Set GIP Option1 (D5h) */
123 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1,
124 0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01,
125 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18,
126 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
127 0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
128 0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
129
130 /* 5.19.21 Set GIP Option2 (D6h) */
131 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2,
132 0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06,
133 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18,
134 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
135 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
136 0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
137
138 /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */
139 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA,
140 0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f,
141 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a,
142 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00,
143 0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31,
144 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f,
145 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b,
146 0x4a, 0x4c, 0x4b, 0x7f);
147
148 /* 5.19.17 SETPANEL (CCh) */
149 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL,
150 0x0b);
151
152 /* Unknown command, not listed in the HX8394-F datasheet */
153 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1,
154 0x1f, 0x31);
155
156 /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */
157 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM,
158 0x7d, 0x7d);
159
160 /* Unknown command, not listed in the HX8394-F datasheet */
161 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
162 0x02);
163
164 /* 5.19.11 Set register bank (BDh) */
165 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
166 0x01);
167
168 /* 5.19.2 SETPOWER: Set power (B1h) */
169 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER,
170 0x00);
171
172 /* 5.19.11 Set register bank (BDh) */
173 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK,
174 0x00);
175
176 /* Unknown command, not listed in the HX8394-F datasheet */
177 mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3,
178 0xed);
179
180 return 0;
181 }
182
183 static const struct drm_display_mode hsd060bhw4_mode = {
184 .hdisplay = 720,
185 .hsync_start = 720 + 40,
186 .hsync_end = 720 + 40 + 46,
187 .htotal = 720 + 40 + 46 + 40,
188 .vdisplay = 1440,
189 .vsync_start = 1440 + 9,
190 .vsync_end = 1440 + 9 + 7,
191 .vtotal = 1440 + 9 + 7 + 7,
192 .clock = 74250,
193 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
194 .width_mm = 68,
195 .height_mm = 136,
196 };
197
198 static const struct hx8394_panel_desc hsd060bhw4_desc = {
199 .mode = &hsd060bhw4_mode,
200 .lanes = 4,
201 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,
202 .format = MIPI_DSI_FMT_RGB888,
203 .init_sequence = hsd060bhw4_init_sequence,
204 };
205
hx8394_enable(struct drm_panel * panel)206 static int hx8394_enable(struct drm_panel *panel)
207 {
208 struct hx8394 *ctx = panel_to_hx8394(panel);
209 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
210 int ret;
211
212 ret = ctx->desc->init_sequence(ctx);
213 if (ret) {
214 dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
215 return ret;
216 }
217
218 ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
219 if (ret) {
220 dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
221 return ret;
222 }
223
224 /* Panel is operational 120 msec after reset */
225 msleep(120);
226
227 ret = mipi_dsi_dcs_set_display_on(dsi);
228 if (ret) {
229 dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret);
230 goto sleep_in;
231 }
232
233 return 0;
234
235 sleep_in:
236 /* This will probably fail, but let's try orderly power off anyway. */
237 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
238 if (!ret)
239 msleep(50);
240
241 return ret;
242 }
243
hx8394_disable(struct drm_panel * panel)244 static int hx8394_disable(struct drm_panel *panel)
245 {
246 struct hx8394 *ctx = panel_to_hx8394(panel);
247 struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
248 int ret;
249
250 ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
251 if (ret) {
252 dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
253 return ret;
254 }
255
256 msleep(50); /* about 3 frames */
257
258 return 0;
259 }
260
hx8394_unprepare(struct drm_panel * panel)261 static int hx8394_unprepare(struct drm_panel *panel)
262 {
263 struct hx8394 *ctx = panel_to_hx8394(panel);
264
265 if (!ctx->prepared)
266 return 0;
267
268 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
269
270 regulator_disable(ctx->iovcc);
271 regulator_disable(ctx->vcc);
272
273 ctx->prepared = false;
274
275 return 0;
276 }
277
hx8394_prepare(struct drm_panel * panel)278 static int hx8394_prepare(struct drm_panel *panel)
279 {
280 struct hx8394 *ctx = panel_to_hx8394(panel);
281 int ret;
282
283 if (ctx->prepared)
284 return 0;
285
286 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
287
288 ret = regulator_enable(ctx->vcc);
289 if (ret) {
290 dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
291 return ret;
292 }
293
294 ret = regulator_enable(ctx->iovcc);
295 if (ret) {
296 dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
297 goto disable_vcc;
298 }
299
300 gpiod_set_value_cansleep(ctx->reset_gpio, 0);
301
302 msleep(180);
303
304 ctx->prepared = true;
305
306 return 0;
307
308 disable_vcc:
309 gpiod_set_value_cansleep(ctx->reset_gpio, 1);
310 regulator_disable(ctx->vcc);
311 return ret;
312 }
313
hx8394_get_modes(struct drm_panel * panel,struct drm_connector * connector)314 static int hx8394_get_modes(struct drm_panel *panel,
315 struct drm_connector *connector)
316 {
317 struct hx8394 *ctx = panel_to_hx8394(panel);
318 struct drm_display_mode *mode;
319
320 mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
321 if (!mode) {
322 dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
323 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
324 drm_mode_vrefresh(ctx->desc->mode));
325 return -ENOMEM;
326 }
327
328 drm_mode_set_name(mode);
329
330 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
331 connector->display_info.width_mm = mode->width_mm;
332 connector->display_info.height_mm = mode->height_mm;
333 drm_mode_probed_add(connector, mode);
334
335 return 1;
336 }
337
338 static const struct drm_panel_funcs hx8394_drm_funcs = {
339 .disable = hx8394_disable,
340 .unprepare = hx8394_unprepare,
341 .prepare = hx8394_prepare,
342 .enable = hx8394_enable,
343 .get_modes = hx8394_get_modes,
344 };
345
hx8394_probe(struct mipi_dsi_device * dsi)346 static int hx8394_probe(struct mipi_dsi_device *dsi)
347 {
348 struct device *dev = &dsi->dev;
349 struct hx8394 *ctx;
350 int ret;
351
352 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
353 if (!ctx)
354 return -ENOMEM;
355
356 ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
357 if (IS_ERR(ctx->reset_gpio))
358 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
359 "Failed to get reset gpio\n");
360
361 mipi_dsi_set_drvdata(dsi, ctx);
362
363 ctx->dev = dev;
364 ctx->desc = of_device_get_match_data(dev);
365
366 dsi->mode_flags = ctx->desc->mode_flags;
367 dsi->format = ctx->desc->format;
368 dsi->lanes = ctx->desc->lanes;
369
370 ctx->vcc = devm_regulator_get(dev, "vcc");
371 if (IS_ERR(ctx->vcc))
372 return dev_err_probe(dev, PTR_ERR(ctx->vcc),
373 "Failed to request vcc regulator\n");
374
375 ctx->iovcc = devm_regulator_get(dev, "iovcc");
376 if (IS_ERR(ctx->iovcc))
377 return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
378 "Failed to request iovcc regulator\n");
379
380 drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs,
381 DRM_MODE_CONNECTOR_DSI);
382
383 ret = drm_panel_of_backlight(&ctx->panel);
384 if (ret)
385 return ret;
386
387 drm_panel_add(&ctx->panel);
388
389 ret = mipi_dsi_attach(dsi);
390 if (ret < 0) {
391 dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
392 drm_panel_remove(&ctx->panel);
393 return ret;
394 }
395
396 dev_dbg(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
397 ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
398 drm_mode_vrefresh(ctx->desc->mode),
399 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
400
401 return 0;
402 }
403
hx8394_shutdown(struct mipi_dsi_device * dsi)404 static void hx8394_shutdown(struct mipi_dsi_device *dsi)
405 {
406 struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
407 int ret;
408
409 ret = drm_panel_disable(&ctx->panel);
410 if (ret < 0)
411 dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
412
413 ret = drm_panel_unprepare(&ctx->panel);
414 if (ret < 0)
415 dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
416 }
417
hx8394_remove(struct mipi_dsi_device * dsi)418 static void hx8394_remove(struct mipi_dsi_device *dsi)
419 {
420 struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
421 int ret;
422
423 hx8394_shutdown(dsi);
424
425 ret = mipi_dsi_detach(dsi);
426 if (ret < 0)
427 dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
428
429 drm_panel_remove(&ctx->panel);
430 }
431
432 static const struct of_device_id hx8394_of_match[] = {
433 { .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
434 { /* sentinel */ }
435 };
436 MODULE_DEVICE_TABLE(of, hx8394_of_match);
437
438 static struct mipi_dsi_driver hx8394_driver = {
439 .probe = hx8394_probe,
440 .remove = hx8394_remove,
441 .shutdown = hx8394_shutdown,
442 .driver = {
443 .name = DRV_NAME,
444 .of_match_table = hx8394_of_match,
445 },
446 };
447 module_mipi_dsi_driver(hx8394_driver);
448
449 MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>");
450 MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
451 MODULE_LICENSE("GPL");
452