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
65struct 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
76struct 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
84static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
85{
86	return container_of(panel, struct hx8394, panel);
87}
88
89static 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
183static 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
198static 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
206static 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
235sleep_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
244static 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
261static 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
278static 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
308disable_vcc:
309	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
310	regulator_disable(ctx->vcc);
311	return ret;
312}
313
314static 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
338static 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
346static 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
404static 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
418static 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
432static const struct of_device_id hx8394_of_match[] = {
433	{ .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
434	{ /* sentinel */ }
435};
436MODULE_DEVICE_TABLE(of, hx8394_of_match);
437
438static 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};
447module_mipi_dsi_driver(hx8394_driver);
448
449MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>");
450MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
451MODULE_LICENSE("GPL");
452