1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Mantix MLAF057WE51 5.7" MIPI-DSI panel driver
4 *
5 * Copyright (C) Purism SPC 2020
6 */
7
8#include <linux/backlight.h>
9#include <linux/delay.h>
10#include <linux/gpio/consumer.h>
11#include <linux/module.h>
12#include <linux/regulator/consumer.h>
13
14#include <video/mipi_display.h>
15
16#include <drm/drm_mipi_dsi.h>
17#include <drm/drm_modes.h>
18#include <drm/drm_panel.h>
19
20#define DRV_NAME "panel-mantix-mlaf057we51"
21
22/* Manufacturer specific Commands send via DSI */
23#define MANTIX_CMD_OTP_STOP_RELOAD_MIPI 0x41
24#define MANTIX_CMD_INT_CANCEL           0x4C
25#define MANTIX_CMD_SPI_FINISH           0x90
26
27struct mantix {
28	struct device *dev;
29	struct drm_panel panel;
30
31	struct gpio_desc *reset_gpio;
32	struct gpio_desc *tp_rstn_gpio;
33
34	struct regulator *avdd;
35	struct regulator *avee;
36	struct regulator *vddi;
37};
38
39static inline struct mantix *panel_to_mantix(struct drm_panel *panel)
40{
41	return container_of(panel, struct mantix, panel);
42}
43
44#define dsi_generic_write_seq(dsi, seq...) do {				\
45		static const u8 d[] = { seq };				\
46		int ret;						\
47		ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d));	\
48		if (ret < 0)						\
49			return ret;					\
50	} while (0)
51
52static int mantix_init_sequence(struct mantix *ctx)
53{
54	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
55	struct device *dev = ctx->dev;
56
57	/*
58	 * Init sequence was supplied by the panel vendor.
59	 */
60	dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A);
61
62	dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03);
63	dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03);
64	dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00);
65
66	dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09);
67	dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00);
68	msleep(20);
69
70	dsi_generic_write_seq(dsi, MANTIX_CMD_SPI_FINISH, 0xA5);
71	dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x00, 0x2F);
72	msleep(20);
73
74	dev_dbg(dev, "Panel init sequence done\n");
75	return 0;
76}
77
78static int mantix_enable(struct drm_panel *panel)
79{
80	struct mantix *ctx = panel_to_mantix(panel);
81	struct device *dev = ctx->dev;
82	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
83	int ret;
84
85	ret = mantix_init_sequence(ctx);
86	if (ret < 0) {
87		dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
88		return ret;
89	}
90
91	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
92	if (ret < 0) {
93		dev_err(dev, "Failed to exit sleep mode\n");
94		return ret;
95	}
96	msleep(20);
97
98	ret = mipi_dsi_dcs_set_display_on(dsi);
99	if (ret)
100		return ret;
101	usleep_range(10000, 12000);
102
103	ret = mipi_dsi_turn_on_peripheral(dsi);
104	if (ret < 0) {
105		dev_err(dev, "Failed to turn on peripheral\n");
106		return ret;
107	}
108
109	return 0;
110}
111
112static int mantix_disable(struct drm_panel *panel)
113{
114	struct mantix *ctx = panel_to_mantix(panel);
115	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
116	int ret;
117
118	ret = mipi_dsi_dcs_set_display_off(dsi);
119	if (ret < 0)
120		dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
121
122	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
123	if (ret < 0)
124		dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
125
126
127	return 0;
128}
129
130static int mantix_unprepare(struct drm_panel *panel)
131{
132	struct mantix *ctx = panel_to_mantix(panel);
133
134	gpiod_set_value_cansleep(ctx->tp_rstn_gpio, 1);
135	usleep_range(5000, 6000);
136	gpiod_set_value_cansleep(ctx->reset_gpio, 1);
137
138	regulator_disable(ctx->avee);
139	regulator_disable(ctx->avdd);
140	/* T11 */
141	usleep_range(5000, 6000);
142	regulator_disable(ctx->vddi);
143	/* T14 */
144	msleep(50);
145
146	return 0;
147}
148
149static int mantix_prepare(struct drm_panel *panel)
150{
151	struct mantix *ctx = panel_to_mantix(panel);
152	int ret;
153
154	/* Focaltech FT8006P, section 7.3.1 and 7.3.4 */
155	dev_dbg(ctx->dev, "Resetting the panel\n");
156	ret = regulator_enable(ctx->vddi);
157	if (ret < 0) {
158		dev_err(ctx->dev, "Failed to enable vddi supply: %d\n", ret);
159		return ret;
160	}
161
162	/* T1 + T2 */
163	usleep_range(8000, 10000);
164
165	ret = regulator_enable(ctx->avdd);
166	if (ret < 0) {
167		dev_err(ctx->dev, "Failed to enable avdd supply: %d\n", ret);
168		return ret;
169	}
170
171	/* T2d */
172	usleep_range(3500, 4000);
173	ret = regulator_enable(ctx->avee);
174	if (ret < 0) {
175		dev_err(ctx->dev, "Failed to enable avee supply: %d\n", ret);
176		return ret;
177	}
178
179	/* T3 + T4 + time for voltage to become stable: */
180	usleep_range(6000, 7000);
181	gpiod_set_value_cansleep(ctx->reset_gpio, 0);
182	gpiod_set_value_cansleep(ctx->tp_rstn_gpio, 0);
183
184	/* T6 */
185	msleep(50);
186
187	return 0;
188}
189
190static const struct drm_display_mode default_mode = {
191	.hdisplay    = 720,
192	.hsync_start = 720 + 45,
193	.hsync_end   = 720 + 45 + 14,
194	.htotal	     = 720 + 45 + 14 + 25,
195	.vdisplay    = 1440,
196	.vsync_start = 1440 + 130,
197	.vsync_end   = 1440 + 130 + 8,
198	.vtotal	     = 1440 + 130 + 8 + 106,
199	.clock	     = 85298,
200	.flags	     = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
201	.width_mm    = 65,
202	.height_mm   = 130,
203};
204
205static int mantix_get_modes(struct drm_panel *panel,
206			    struct drm_connector *connector)
207{
208	struct mantix *ctx = panel_to_mantix(panel);
209	struct drm_display_mode *mode;
210
211	mode = drm_mode_duplicate(connector->dev, &default_mode);
212	if (!mode) {
213		dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
214			default_mode.hdisplay, default_mode.vdisplay,
215			drm_mode_vrefresh(&default_mode));
216		return -ENOMEM;
217	}
218
219	drm_mode_set_name(mode);
220
221	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
222	connector->display_info.width_mm = mode->width_mm;
223	connector->display_info.height_mm = mode->height_mm;
224	drm_mode_probed_add(connector, mode);
225
226	return 1;
227}
228
229static const struct drm_panel_funcs mantix_drm_funcs = {
230	.disable   = mantix_disable,
231	.unprepare = mantix_unprepare,
232	.prepare   = mantix_prepare,
233	.enable	   = mantix_enable,
234	.get_modes = mantix_get_modes,
235};
236
237static int mantix_probe(struct mipi_dsi_device *dsi)
238{
239	struct device *dev = &dsi->dev;
240	struct mantix *ctx;
241	int ret;
242
243	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
244	if (!ctx)
245		return -ENOMEM;
246
247	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
248	if (IS_ERR(ctx->reset_gpio)) {
249		dev_err(dev, "cannot get reset gpio\n");
250		return PTR_ERR(ctx->reset_gpio);
251	}
252
253	ctx->tp_rstn_gpio = devm_gpiod_get(dev, "mantix,tp-rstn", GPIOD_OUT_HIGH);
254	if (IS_ERR(ctx->tp_rstn_gpio)) {
255		dev_err(dev, "cannot get tp-rstn gpio\n");
256		return PTR_ERR(ctx->tp_rstn_gpio);
257	}
258
259	mipi_dsi_set_drvdata(dsi, ctx);
260	ctx->dev = dev;
261
262	dsi->lanes = 4;
263	dsi->format = MIPI_DSI_FMT_RGB888;
264	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
265		MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
266
267	ctx->avdd = devm_regulator_get(dev, "avdd");
268	if (IS_ERR(ctx->avdd))
269		return dev_err_probe(dev, PTR_ERR(ctx->avdd), "Failed to request avdd regulator\n");
270
271	ctx->avee = devm_regulator_get(dev, "avee");
272	if (IS_ERR(ctx->avee))
273		return dev_err_probe(dev, PTR_ERR(ctx->avee), "Failed to request avee regulator\n");
274
275	ctx->vddi = devm_regulator_get(dev, "vddi");
276	if (IS_ERR(ctx->vddi))
277		return dev_err_probe(dev, PTR_ERR(ctx->vddi), "Failed to request vddi regulator\n");
278
279	drm_panel_init(&ctx->panel, dev, &mantix_drm_funcs,
280		       DRM_MODE_CONNECTOR_DSI);
281
282	ret = drm_panel_of_backlight(&ctx->panel);
283	if (ret)
284		return ret;
285
286	drm_panel_add(&ctx->panel);
287
288	ret = mipi_dsi_attach(dsi);
289	if (ret < 0) {
290		dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
291		drm_panel_remove(&ctx->panel);
292		return ret;
293	}
294
295	dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
296		 default_mode.hdisplay, default_mode.vdisplay,
297		 drm_mode_vrefresh(&default_mode),
298		 mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
299
300	return 0;
301}
302
303static void mantix_shutdown(struct mipi_dsi_device *dsi)
304{
305	struct mantix *ctx = mipi_dsi_get_drvdata(dsi);
306
307	drm_panel_unprepare(&ctx->panel);
308	drm_panel_disable(&ctx->panel);
309}
310
311static int mantix_remove(struct mipi_dsi_device *dsi)
312{
313	struct mantix *ctx = mipi_dsi_get_drvdata(dsi);
314
315	mantix_shutdown(dsi);
316
317	mipi_dsi_detach(dsi);
318	drm_panel_remove(&ctx->panel);
319
320	return 0;
321}
322
323static const struct of_device_id mantix_of_match[] = {
324	{ .compatible = "mantix,mlaf057we51-x" },
325	{ /* sentinel */ }
326};
327MODULE_DEVICE_TABLE(of, mantix_of_match);
328
329static struct mipi_dsi_driver mantix_driver = {
330	.probe	= mantix_probe,
331	.remove = mantix_remove,
332	.shutdown = mantix_shutdown,
333	.driver = {
334		.name = DRV_NAME,
335		.of_match_table = mantix_of_match,
336	},
337};
338module_mipi_dsi_driver(mantix_driver);
339
340MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
341MODULE_DESCRIPTION("DRM driver for Mantix MLAF057WE51-X MIPI DSI panel");
342MODULE_LICENSE("GPL v2");
343