Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  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
 46struct nt35560_config {
 47	const struct drm_display_mode *vid_mode;
 48	const struct drm_display_mode *cmd_mode;
 49};
 50
 51struct 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
 60static 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 */
 79static 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
 97static const struct nt35560_config sony_acx424akp_data = {
 98	.vid_mode = &sony_acx424akp_vid_mode,
 99	.cmd_mode = &sony_acx424akp_cmd_mode,
100};
101
102static 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 */
121static 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
135static const struct nt35560_config sony_acx424akm_data = {
136	.vid_mode = &sony_acx424akm_vid_mode,
137	.cmd_mode = &sony_acx424akm_cmd_mode,
138};
139
140static 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
148static 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
237static const struct backlight_ops nt35560_bl_ops = {
238	.update_status = nt35560_set_brightness,
239};
240
241static const struct backlight_properties nt35560_bl_props = {
242	.type = BACKLIGHT_RAW,
243	.brightness = 512,
244	.max_brightness = 1023,
245};
246
247static 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
293static 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
313static 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
322static 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
388err_power_off:
389	nt35560_power_off(nt);
390	return ret;
391}
392
393static 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
419static 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
447static const struct drm_panel_funcs nt35560_drm_funcs = {
448	.unprepare = nt35560_unprepare,
449	.prepare = nt35560_prepare,
450	.get_modes = nt35560_get_modes,
451};
452
453static 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
525static 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
533static 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};
544MODULE_DEVICE_TABLE(of, nt35560_of_match);
545
546static 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};
554module_mipi_dsi_driver(nt35560_driver);
555
556MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>");
557MODULE_DESCRIPTION("MIPI-DSI Novatek NT35560 Panel Driver");
558MODULE_LICENSE("GPL v2");