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 	if (!mipi_dsi_dcs_enter_sleep_mode(dsi))
238 		msleep(50);
239 
240 	return ret;
241 }
242 
hx8394_disable(struct drm_panel * panel)243 static int hx8394_disable(struct drm_panel *panel)
244 {
245 	struct hx8394 *ctx = panel_to_hx8394(panel);
246 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
247 	int ret;
248 
249 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
250 	if (ret) {
251 		dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
252 		return ret;
253 	}
254 
255 	msleep(50); /* about 3 frames */
256 
257 	return 0;
258 }
259 
hx8394_unprepare(struct drm_panel * panel)260 static int hx8394_unprepare(struct drm_panel *panel)
261 {
262 	struct hx8394 *ctx = panel_to_hx8394(panel);
263 
264 	if (!ctx->prepared)
265 		return 0;
266 
267 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
268 
269 	regulator_disable(ctx->iovcc);
270 	regulator_disable(ctx->vcc);
271 
272 	ctx->prepared = false;
273 
274 	return 0;
275 }
276 
hx8394_prepare(struct drm_panel * panel)277 static int hx8394_prepare(struct drm_panel *panel)
278 {
279 	struct hx8394 *ctx = panel_to_hx8394(panel);
280 	int ret;
281 
282 	if (ctx->prepared)
283 		return 0;
284 
285 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
286 
287 	ret = regulator_enable(ctx->vcc);
288 	if (ret) {
289 		dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
290 		return ret;
291 	}
292 
293 	ret = regulator_enable(ctx->iovcc);
294 	if (ret) {
295 		dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
296 		goto disable_vcc;
297 	}
298 
299 	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
300 
301 	msleep(180);
302 
303 	ctx->prepared = true;
304 
305 	return 0;
306 
307 disable_vcc:
308 	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
309 	regulator_disable(ctx->vcc);
310 	return ret;
311 }
312 
hx8394_get_modes(struct drm_panel * panel,struct drm_connector * connector)313 static int hx8394_get_modes(struct drm_panel *panel,
314 			    struct drm_connector *connector)
315 {
316 	struct hx8394 *ctx = panel_to_hx8394(panel);
317 	struct drm_display_mode *mode;
318 
319 	mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
320 	if (!mode) {
321 		dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
322 			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
323 			drm_mode_vrefresh(ctx->desc->mode));
324 		return -ENOMEM;
325 	}
326 
327 	drm_mode_set_name(mode);
328 
329 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
330 	connector->display_info.width_mm = mode->width_mm;
331 	connector->display_info.height_mm = mode->height_mm;
332 	drm_mode_probed_add(connector, mode);
333 
334 	return 1;
335 }
336 
337 static const struct drm_panel_funcs hx8394_drm_funcs = {
338 	.disable   = hx8394_disable,
339 	.unprepare = hx8394_unprepare,
340 	.prepare   = hx8394_prepare,
341 	.enable	   = hx8394_enable,
342 	.get_modes = hx8394_get_modes,
343 };
344 
hx8394_probe(struct mipi_dsi_device * dsi)345 static int hx8394_probe(struct mipi_dsi_device *dsi)
346 {
347 	struct device *dev = &dsi->dev;
348 	struct hx8394 *ctx;
349 	int ret;
350 
351 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
352 	if (!ctx)
353 		return -ENOMEM;
354 
355 	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
356 	if (IS_ERR(ctx->reset_gpio))
357 		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
358 				     "Failed to get reset gpio\n");
359 
360 	mipi_dsi_set_drvdata(dsi, ctx);
361 
362 	ctx->dev = dev;
363 	ctx->desc = of_device_get_match_data(dev);
364 
365 	dsi->mode_flags = ctx->desc->mode_flags;
366 	dsi->format = ctx->desc->format;
367 	dsi->lanes = ctx->desc->lanes;
368 
369 	ctx->vcc = devm_regulator_get(dev, "vcc");
370 	if (IS_ERR(ctx->vcc))
371 		return dev_err_probe(dev, PTR_ERR(ctx->vcc),
372 				     "Failed to request vcc regulator\n");
373 
374 	ctx->iovcc = devm_regulator_get(dev, "iovcc");
375 	if (IS_ERR(ctx->iovcc))
376 		return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
377 				     "Failed to request iovcc regulator\n");
378 
379 	drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs,
380 		       DRM_MODE_CONNECTOR_DSI);
381 
382 	ret = drm_panel_of_backlight(&ctx->panel);
383 	if (ret)
384 		return ret;
385 
386 	drm_panel_add(&ctx->panel);
387 
388 	ret = mipi_dsi_attach(dsi);
389 	if (ret < 0) {
390 		dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
391 		drm_panel_remove(&ctx->panel);
392 		return ret;
393 	}
394 
395 	dev_dbg(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
396 		ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
397 		drm_mode_vrefresh(ctx->desc->mode),
398 		mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
399 
400 	return 0;
401 }
402 
hx8394_shutdown(struct mipi_dsi_device * dsi)403 static void hx8394_shutdown(struct mipi_dsi_device *dsi)
404 {
405 	struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
406 	int ret;
407 
408 	ret = drm_panel_disable(&ctx->panel);
409 	if (ret < 0)
410 		dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
411 
412 	ret = drm_panel_unprepare(&ctx->panel);
413 	if (ret < 0)
414 		dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
415 }
416 
hx8394_remove(struct mipi_dsi_device * dsi)417 static void hx8394_remove(struct mipi_dsi_device *dsi)
418 {
419 	struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
420 	int ret;
421 
422 	hx8394_shutdown(dsi);
423 
424 	ret = mipi_dsi_detach(dsi);
425 	if (ret < 0)
426 		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
427 
428 	drm_panel_remove(&ctx->panel);
429 }
430 
431 static const struct of_device_id hx8394_of_match[] = {
432 	{ .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
433 	{ /* sentinel */ }
434 };
435 MODULE_DEVICE_TABLE(of, hx8394_of_match);
436 
437 static struct mipi_dsi_driver hx8394_driver = {
438 	.probe	= hx8394_probe,
439 	.remove = hx8394_remove,
440 	.shutdown = hx8394_shutdown,
441 	.driver = {
442 		.name = DRV_NAME,
443 		.of_match_table = hx8394_of_match,
444 	},
445 };
446 module_mipi_dsi_driver(hx8394_driver);
447 
448 MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>");
449 MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
450 MODULE_LICENSE("GPL");
451