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