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 
27 struct 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 
panel_to_mantix(struct drm_panel *panel)39 static 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 
mantix_init_sequence(struct mantix *ctx)52 static 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 
mantix_enable(struct drm_panel *panel)78 static 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 
mantix_disable(struct drm_panel *panel)112 static 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 
mantix_unprepare(struct drm_panel *panel)130 static 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 
mantix_prepare(struct drm_panel *panel)149 static 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 
190 static 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 
mantix_get_modes(struct drm_panel *panel, struct drm_connector *connector)205 static 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 
229 static 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 
mantix_probe(struct mipi_dsi_device *dsi)237 static 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 
mantix_shutdown(struct mipi_dsi_device *dsi)303 static 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 
mantix_remove(struct mipi_dsi_device *dsi)311 static 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 
323 static const struct of_device_id mantix_of_match[] = {
324 	{ .compatible = "mantix,mlaf057we51-x" },
325 	{ /* sentinel */ }
326 };
327 MODULE_DEVICE_TABLE(of, mantix_of_match);
328 
329 static 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 };
338 module_mipi_dsi_driver(mantix_driver);
339 
340 MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>");
341 MODULE_DESCRIPTION("DRM driver for Mantix MLAF057WE51-X MIPI DSI panel");
342 MODULE_LICENSE("GPL v2");
343