xref: /linux/drivers/gpu/drm/panel/panel-novatek-nt35560.c (revision a940daa52167e9db8ecce82213813b735a9d9f23)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * MIPI-DSI Novatek NT35560-based panel controller.
4  *
5  * Supported panels include:
6  * Sony ACX424AKM - a 480x854 AMOLED DSI panel
7  * Sony ACX424AKP - a 480x864 AMOLED DSI panel
8  *
9  * Copyright (C) Linaro Ltd. 2019-2021
10  * Author: Linus Walleij
11  * Based on code and know-how from Marcus Lorentzon
12  * Copyright (C) ST-Ericsson SA 2010
13  * Based on code and know-how from Johan Olson and Joakim Wesslen
14  * Copyright (C) Sony Ericsson Mobile Communications 2010
15  */
16 #include <linux/backlight.h>
17 #include <linux/delay.h>
18 #include <linux/gpio/consumer.h>
19 #include <linux/module.h>
20 #include <linux/of.h>
21 #include <linux/regulator/consumer.h>
22 
23 #include <video/mipi_display.h>
24 
25 #include <drm/drm_mipi_dsi.h>
26 #include <drm/drm_modes.h>
27 #include <drm/drm_panel.h>
28 
29 #define NT35560_DCS_READ_ID1		0xDA
30 #define NT35560_DCS_READ_ID2		0xDB
31 #define NT35560_DCS_READ_ID3		0xDC
32 #define NT35560_DCS_SET_MDDI		0xAE
33 
34 /*
35  * Sony seems to use vendor ID 0x81
36  */
37 #define DISPLAY_SONY_ACX424AKP_ID1	0x8103
38 #define DISPLAY_SONY_ACX424AKP_ID2	0x811a
39 #define DISPLAY_SONY_ACX424AKP_ID3	0x811b
40 /*
41  * The fourth ID looks like a bug, vendor IDs begin at 0x80
42  * and panel 00 ... seems like default values.
43  */
44 #define DISPLAY_SONY_ACX424AKP_ID4	0x8000
45 
46 struct nt35560_config {
47 	const struct drm_display_mode *vid_mode;
48 	const struct drm_display_mode *cmd_mode;
49 };
50 
51 struct nt35560 {
52 	const struct nt35560_config *conf;
53 	struct drm_panel panel;
54 	struct device *dev;
55 	struct regulator *supply;
56 	struct gpio_desc *reset_gpio;
57 	bool video_mode;
58 };
59 
60 static const struct drm_display_mode sony_acx424akp_vid_mode = {
61 	.clock = 27234,
62 	.hdisplay = 480,
63 	.hsync_start = 480 + 15,
64 	.hsync_end = 480 + 15 + 0,
65 	.htotal = 480 + 15 + 0 + 15,
66 	.vdisplay = 864,
67 	.vsync_start = 864 + 14,
68 	.vsync_end = 864 + 14 + 1,
69 	.vtotal = 864 + 14 + 1 + 11,
70 	.width_mm = 48,
71 	.height_mm = 84,
72 	.flags = DRM_MODE_FLAG_PVSYNC,
73 };
74 
75 /*
76  * The timings are not very helpful as the display is used in
77  * command mode using the maximum HS frequency.
78  */
79 static const struct drm_display_mode sony_acx424akp_cmd_mode = {
80 	.clock = 35478,
81 	.hdisplay = 480,
82 	.hsync_start = 480 + 154,
83 	.hsync_end = 480 + 154 + 16,
84 	.htotal = 480 + 154 + 16 + 32,
85 	.vdisplay = 864,
86 	.vsync_start = 864 + 1,
87 	.vsync_end = 864 + 1 + 1,
88 	.vtotal = 864 + 1 + 1 + 1,
89 	/*
90 	 * Some desired refresh rate, experiments at the maximum "pixel"
91 	 * clock speed (HS clock 420 MHz) yields around 117Hz.
92 	 */
93 	.width_mm = 48,
94 	.height_mm = 84,
95 };
96 
97 static const struct nt35560_config sony_acx424akp_data = {
98 	.vid_mode = &sony_acx424akp_vid_mode,
99 	.cmd_mode = &sony_acx424akp_cmd_mode,
100 };
101 
102 static const struct drm_display_mode sony_acx424akm_vid_mode = {
103 	.clock = 27234,
104 	.hdisplay = 480,
105 	.hsync_start = 480 + 15,
106 	.hsync_end = 480 + 15 + 0,
107 	.htotal = 480 + 15 + 0 + 15,
108 	.vdisplay = 854,
109 	.vsync_start = 854 + 14,
110 	.vsync_end = 854 + 14 + 1,
111 	.vtotal = 854 + 14 + 1 + 11,
112 	.width_mm = 46,
113 	.height_mm = 82,
114 	.flags = DRM_MODE_FLAG_PVSYNC,
115 };
116 
117 /*
118  * The timings are not very helpful as the display is used in
119  * command mode using the maximum HS frequency.
120  */
121 static const struct drm_display_mode sony_acx424akm_cmd_mode = {
122 	.clock = 35478,
123 	.hdisplay = 480,
124 	.hsync_start = 480 + 154,
125 	.hsync_end = 480 + 154 + 16,
126 	.htotal = 480 + 154 + 16 + 32,
127 	.vdisplay = 854,
128 	.vsync_start = 854 + 1,
129 	.vsync_end = 854 + 1 + 1,
130 	.vtotal = 854 + 1 + 1 + 1,
131 	.width_mm = 46,
132 	.height_mm = 82,
133 };
134 
135 static const struct nt35560_config sony_acx424akm_data = {
136 	.vid_mode = &sony_acx424akm_vid_mode,
137 	.cmd_mode = &sony_acx424akm_cmd_mode,
138 };
139 
panel_to_nt35560(struct drm_panel * panel)140 static inline struct nt35560 *panel_to_nt35560(struct drm_panel *panel)
141 {
142 	return container_of(panel, struct nt35560, panel);
143 }
144 
145 #define FOSC			20 /* 20Mhz */
146 #define SCALE_FACTOR_NS_DIV_MHZ	1000
147 
nt35560_set_brightness(struct backlight_device * bl)148 static int nt35560_set_brightness(struct backlight_device *bl)
149 {
150 	struct nt35560 *nt = bl_get_data(bl);
151 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
152 	int period_ns = 1023;
153 	int duty_ns = bl->props.brightness;
154 	u8 pwm_ratio;
155 	u8 pwm_div;
156 	u8 par;
157 	int ret;
158 
159 	if (backlight_is_blank(bl)) {
160 		/* Disable backlight */
161 		par = 0x00;
162 		ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
163 					 &par, 1);
164 		if (ret) {
165 			dev_err(nt->dev, "failed to disable display backlight (%d)\n", ret);
166 			return ret;
167 		}
168 		return 0;
169 	}
170 
171 	/* Calculate the PWM duty cycle in n/256's */
172 	pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1);
173 	pwm_div = max(1,
174 		      ((FOSC * period_ns) / 256) /
175 		      SCALE_FACTOR_NS_DIV_MHZ);
176 
177 	/* Set up PWM dutycycle ONE byte (differs from the standard) */
178 	dev_dbg(nt->dev, "calculated duty cycle %02x\n", pwm_ratio);
179 	ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
180 				 &pwm_ratio, 1);
181 	if (ret < 0) {
182 		dev_err(nt->dev, "failed to set display PWM ratio (%d)\n", ret);
183 		return ret;
184 	}
185 
186 	/*
187 	 * Sequence to write PWMDIV:
188 	 *	address		data
189 	 *	0xF3		0xAA   CMD2 Unlock
190 	 *	0x00		0x01   Enter CMD2 page 0
191 	 *	0X7D		0x01   No reload MTP of CMD2 P1
192 	 *	0x22		PWMDIV
193 	 *	0x7F		0xAA   CMD2 page 1 lock
194 	 */
195 	par = 0xaa;
196 	ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1);
197 	if (ret < 0) {
198 		dev_err(nt->dev, "failed to unlock CMD 2 (%d)\n", ret);
199 		return ret;
200 	}
201 	par = 0x01;
202 	ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1);
203 	if (ret < 0) {
204 		dev_err(nt->dev, "failed to enter page 1 (%d)\n", ret);
205 		return ret;
206 	}
207 	par = 0x01;
208 	ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1);
209 	if (ret < 0) {
210 		dev_err(nt->dev, "failed to disable MTP reload (%d)\n", ret);
211 		return ret;
212 	}
213 	ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1);
214 	if (ret < 0) {
215 		dev_err(nt->dev, "failed to set PWM divisor (%d)\n", ret);
216 		return ret;
217 	}
218 	par = 0xaa;
219 	ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1);
220 	if (ret < 0) {
221 		dev_err(nt->dev, "failed to lock CMD 2 (%d)\n", ret);
222 		return ret;
223 	}
224 
225 	/* Enable backlight */
226 	par = 0x24;
227 	ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
228 				 &par, 1);
229 	if (ret < 0) {
230 		dev_err(nt->dev, "failed to enable display backlight (%d)\n", ret);
231 		return ret;
232 	}
233 
234 	return 0;
235 }
236 
237 static const struct backlight_ops nt35560_bl_ops = {
238 	.update_status = nt35560_set_brightness,
239 };
240 
241 static const struct backlight_properties nt35560_bl_props = {
242 	.type = BACKLIGHT_RAW,
243 	.brightness = 512,
244 	.max_brightness = 1023,
245 };
246 
nt35560_read_id(struct nt35560 * nt)247 static int nt35560_read_id(struct nt35560 *nt)
248 {
249 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
250 	u8 vendor, version, panel;
251 	u16 val;
252 	int ret;
253 
254 	ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID1, &vendor, 1);
255 	if (ret < 0) {
256 		dev_err(nt->dev, "could not vendor ID byte\n");
257 		return ret;
258 	}
259 	ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID2, &version, 1);
260 	if (ret < 0) {
261 		dev_err(nt->dev, "could not read device version byte\n");
262 		return ret;
263 	}
264 	ret = mipi_dsi_dcs_read(dsi, NT35560_DCS_READ_ID3, &panel, 1);
265 	if (ret < 0) {
266 		dev_err(nt->dev, "could not read panel ID byte\n");
267 		return ret;
268 	}
269 
270 	if (vendor == 0x00) {
271 		dev_err(nt->dev, "device vendor ID is zero\n");
272 		return -ENODEV;
273 	}
274 
275 	val = (vendor << 8) | panel;
276 	switch (val) {
277 	case DISPLAY_SONY_ACX424AKP_ID1:
278 	case DISPLAY_SONY_ACX424AKP_ID2:
279 	case DISPLAY_SONY_ACX424AKP_ID3:
280 	case DISPLAY_SONY_ACX424AKP_ID4:
281 		dev_info(nt->dev, "MTP vendor: %02x, version: %02x, panel: %02x\n",
282 			 vendor, version, panel);
283 		break;
284 	default:
285 		dev_info(nt->dev, "unknown vendor: %02x, version: %02x, panel: %02x\n",
286 			 vendor, version, panel);
287 		break;
288 	}
289 
290 	return 0;
291 }
292 
nt35560_power_on(struct nt35560 * nt)293 static int nt35560_power_on(struct nt35560 *nt)
294 {
295 	int ret;
296 
297 	ret = regulator_enable(nt->supply);
298 	if (ret) {
299 		dev_err(nt->dev, "failed to enable supply (%d)\n", ret);
300 		return ret;
301 	}
302 
303 	/* Assert RESET */
304 	gpiod_set_value_cansleep(nt->reset_gpio, 1);
305 	udelay(20);
306 	/* De-assert RESET */
307 	gpiod_set_value_cansleep(nt->reset_gpio, 0);
308 	usleep_range(11000, 20000);
309 
310 	return 0;
311 }
312 
nt35560_power_off(struct nt35560 * nt)313 static void nt35560_power_off(struct nt35560 *nt)
314 {
315 	/* Assert RESET */
316 	gpiod_set_value_cansleep(nt->reset_gpio, 1);
317 	usleep_range(11000, 20000);
318 
319 	regulator_disable(nt->supply);
320 }
321 
nt35560_prepare(struct drm_panel * panel)322 static int nt35560_prepare(struct drm_panel *panel)
323 {
324 	struct nt35560 *nt = panel_to_nt35560(panel);
325 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
326 	const u8 mddi = 3;
327 	int ret;
328 
329 	ret = nt35560_power_on(nt);
330 	if (ret)
331 		return ret;
332 
333 	ret = nt35560_read_id(nt);
334 	if (ret) {
335 		dev_err(nt->dev, "failed to read panel ID (%d)\n", ret);
336 		goto err_power_off;
337 	}
338 
339 	/* Enabe tearing mode: send TE (tearing effect) at VBLANK */
340 	ret = mipi_dsi_dcs_set_tear_on(dsi,
341 				       MIPI_DSI_DCS_TEAR_MODE_VBLANK);
342 	if (ret) {
343 		dev_err(nt->dev, "failed to enable vblank TE (%d)\n", ret);
344 		goto err_power_off;
345 	}
346 
347 	/*
348 	 * Set MDDI
349 	 *
350 	 * This presumably deactivates the Qualcomm MDDI interface and
351 	 * selects DSI, similar code is found in other drivers such as the
352 	 * Sharp LS043T1LE01 which makes us suspect that this panel may be
353 	 * using a Novatek NT35565 or similar display driver chip that shares
354 	 * this command. Due to the lack of documentation we cannot know for
355 	 * sure.
356 	 */
357 	ret = mipi_dsi_dcs_write(dsi, NT35560_DCS_SET_MDDI,
358 				 &mddi, sizeof(mddi));
359 	if (ret < 0) {
360 		dev_err(nt->dev, "failed to set MDDI (%d)\n", ret);
361 		goto err_power_off;
362 	}
363 
364 	/* Exit sleep mode */
365 	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
366 	if (ret) {
367 		dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret);
368 		goto err_power_off;
369 	}
370 	msleep(140);
371 
372 	ret = mipi_dsi_dcs_set_display_on(dsi);
373 	if (ret) {
374 		dev_err(nt->dev, "failed to turn display on (%d)\n", ret);
375 		goto err_power_off;
376 	}
377 	if (nt->video_mode) {
378 		/* In video mode turn peripheral on */
379 		ret = mipi_dsi_turn_on_peripheral(dsi);
380 		if (ret) {
381 			dev_err(nt->dev, "failed to turn on peripheral\n");
382 			goto err_power_off;
383 		}
384 	}
385 
386 	return 0;
387 
388 err_power_off:
389 	nt35560_power_off(nt);
390 	return ret;
391 }
392 
nt35560_unprepare(struct drm_panel * panel)393 static int nt35560_unprepare(struct drm_panel *panel)
394 {
395 	struct nt35560 *nt = panel_to_nt35560(panel);
396 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(nt->dev);
397 	int ret;
398 
399 	ret = mipi_dsi_dcs_set_display_off(dsi);
400 	if (ret) {
401 		dev_err(nt->dev, "failed to turn display off (%d)\n", ret);
402 		return ret;
403 	}
404 
405 	/* Enter sleep mode */
406 	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
407 	if (ret) {
408 		dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret);
409 		return ret;
410 	}
411 	msleep(85);
412 
413 	nt35560_power_off(nt);
414 
415 	return 0;
416 }
417 
418 
nt35560_get_modes(struct drm_panel * panel,struct drm_connector * connector)419 static int nt35560_get_modes(struct drm_panel *panel,
420 			     struct drm_connector *connector)
421 {
422 	struct nt35560 *nt = panel_to_nt35560(panel);
423 	const struct nt35560_config *conf = nt->conf;
424 	struct drm_display_mode *mode;
425 
426 	if (nt->video_mode)
427 		mode = drm_mode_duplicate(connector->dev,
428 					  conf->vid_mode);
429 	else
430 		mode = drm_mode_duplicate(connector->dev,
431 					  conf->cmd_mode);
432 	if (!mode) {
433 		dev_err(panel->dev, "bad mode or failed to add mode\n");
434 		return -EINVAL;
435 	}
436 	drm_mode_set_name(mode);
437 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
438 
439 	connector->display_info.width_mm = mode->width_mm;
440 	connector->display_info.height_mm = mode->height_mm;
441 
442 	drm_mode_probed_add(connector, mode);
443 
444 	return 1; /* Number of modes */
445 }
446 
447 static const struct drm_panel_funcs nt35560_drm_funcs = {
448 	.unprepare = nt35560_unprepare,
449 	.prepare = nt35560_prepare,
450 	.get_modes = nt35560_get_modes,
451 };
452 
nt35560_probe(struct mipi_dsi_device * dsi)453 static int nt35560_probe(struct mipi_dsi_device *dsi)
454 {
455 	struct device *dev = &dsi->dev;
456 	struct nt35560 *nt;
457 	int ret;
458 
459 	nt = devm_kzalloc(dev, sizeof(struct nt35560), GFP_KERNEL);
460 	if (!nt)
461 		return -ENOMEM;
462 	nt->video_mode = of_property_read_bool(dev->of_node,
463 						"enforce-video-mode");
464 
465 	mipi_dsi_set_drvdata(dsi, nt);
466 	nt->dev = dev;
467 
468 	nt->conf = of_device_get_match_data(dev);
469 	if (!nt->conf) {
470 		dev_err(dev, "missing device configuration\n");
471 		return -ENODEV;
472 	}
473 
474 	dsi->lanes = 2;
475 	dsi->format = MIPI_DSI_FMT_RGB888;
476 	/*
477 	 * FIXME: these come from the ST-Ericsson vendor driver for the
478 	 * HREF520 and seems to reflect limitations in the PLLs on that
479 	 * platform, if you have the datasheet, please cross-check the
480 	 * actual max rates.
481 	 */
482 	dsi->lp_rate = 19200000;
483 	dsi->hs_rate = 420160000;
484 
485 	if (nt->video_mode)
486 		/* Burst mode using event for sync */
487 		dsi->mode_flags =
488 			MIPI_DSI_MODE_VIDEO |
489 			MIPI_DSI_MODE_VIDEO_BURST;
490 	else
491 		dsi->mode_flags =
492 			MIPI_DSI_CLOCK_NON_CONTINUOUS;
493 
494 	nt->supply = devm_regulator_get(dev, "vddi");
495 	if (IS_ERR(nt->supply))
496 		return PTR_ERR(nt->supply);
497 
498 	/* This asserts RESET by default */
499 	nt->reset_gpio = devm_gpiod_get_optional(dev, "reset",
500 						 GPIOD_OUT_HIGH);
501 	if (IS_ERR(nt->reset_gpio))
502 		return dev_err_probe(dev, PTR_ERR(nt->reset_gpio),
503 				     "failed to request GPIO\n");
504 
505 	drm_panel_init(&nt->panel, dev, &nt35560_drm_funcs,
506 		       DRM_MODE_CONNECTOR_DSI);
507 
508 	nt->panel.backlight = devm_backlight_device_register(dev, "nt35560", dev, nt,
509 					&nt35560_bl_ops, &nt35560_bl_props);
510 	if (IS_ERR(nt->panel.backlight))
511 		return dev_err_probe(dev, PTR_ERR(nt->panel.backlight),
512 				     "failed to register backlight device\n");
513 
514 	drm_panel_add(&nt->panel);
515 
516 	ret = mipi_dsi_attach(dsi);
517 	if (ret < 0) {
518 		drm_panel_remove(&nt->panel);
519 		return ret;
520 	}
521 
522 	return 0;
523 }
524 
nt35560_remove(struct mipi_dsi_device * dsi)525 static void nt35560_remove(struct mipi_dsi_device *dsi)
526 {
527 	struct nt35560 *nt = mipi_dsi_get_drvdata(dsi);
528 
529 	mipi_dsi_detach(dsi);
530 	drm_panel_remove(&nt->panel);
531 }
532 
533 static const struct of_device_id nt35560_of_match[] = {
534 	{
535 		.compatible = "sony,acx424akp",
536 		.data = &sony_acx424akp_data,
537 	},
538 	{
539 		.compatible = "sony,acx424akm",
540 		.data = &sony_acx424akm_data,
541 	},
542 	{ /* sentinel */ }
543 };
544 MODULE_DEVICE_TABLE(of, nt35560_of_match);
545 
546 static struct mipi_dsi_driver nt35560_driver = {
547 	.probe = nt35560_probe,
548 	.remove = nt35560_remove,
549 	.driver = {
550 		.name = "panel-novatek-nt35560",
551 		.of_match_table = nt35560_of_match,
552 	},
553 };
554 module_mipi_dsi_driver(nt35560_driver);
555 
556 MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>");
557 MODULE_DESCRIPTION("MIPI-DSI Novatek NT35560 Panel Driver");
558 MODULE_LICENSE("GPL v2");
559