xref: /linux/drivers/gpu/drm/panel/panel-dsi-cm.c (revision 808094fcbf4196be0feb17afbbdc182ec95c8cec)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Generic DSI Command Mode panel driver
4  *
5  * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/
6  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
7  */
8 
9 #include <linux/backlight.h>
10 #include <linux/delay.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/jiffies.h>
13 #include <linux/module.h>
14 #include <linux/of_device.h>
15 #include <linux/regulator/consumer.h>
16 
17 #include <drm/drm_connector.h>
18 #include <drm/drm_mipi_dsi.h>
19 #include <drm/drm_modes.h>
20 #include <drm/drm_panel.h>
21 
22 #include <video/mipi_display.h>
23 
24 #define DCS_GET_ID1		0xda
25 #define DCS_GET_ID2		0xdb
26 #define DCS_GET_ID3		0xdc
27 
28 #define DCS_REGULATOR_SUPPLY_NUM 2
29 
30 static const struct of_device_id dsicm_of_match[];
31 
32 struct dsic_panel_data {
33 	u32 xres;
34 	u32 yres;
35 	u32 refresh;
36 	u32 width_mm;
37 	u32 height_mm;
38 	u32 max_hs_rate;
39 	u32 max_lp_rate;
40 };
41 
42 struct panel_drv_data {
43 	struct mipi_dsi_device *dsi;
44 	struct drm_panel panel;
45 	struct drm_display_mode mode;
46 
47 	struct mutex lock;
48 
49 	struct backlight_device *bldev;
50 	struct backlight_device *extbldev;
51 
52 	unsigned long	hw_guard_end;	/* next value of jiffies when we can
53 					 * issue the next sleep in/out command
54 					 */
55 	unsigned long	hw_guard_wait;	/* max guard time in jiffies */
56 
57 	const struct dsic_panel_data *panel_data;
58 
59 	struct gpio_desc *reset_gpio;
60 
61 	struct regulator_bulk_data supplies[DCS_REGULATOR_SUPPLY_NUM];
62 
63 	bool use_dsi_backlight;
64 
65 	/* runtime variables */
66 	bool enabled;
67 
68 	bool intro_printed;
69 };
70 
71 static inline struct panel_drv_data *panel_to_ddata(struct drm_panel *panel)
72 {
73 	return container_of(panel, struct panel_drv_data, panel);
74 }
75 
76 static void dsicm_bl_power(struct panel_drv_data *ddata, bool enable)
77 {
78 	struct backlight_device *backlight;
79 
80 	if (ddata->bldev)
81 		backlight = ddata->bldev;
82 	else if (ddata->extbldev)
83 		backlight = ddata->extbldev;
84 	else
85 		return;
86 
87 	if (enable) {
88 		backlight->props.fb_blank = FB_BLANK_UNBLANK;
89 		backlight->props.state = ~(BL_CORE_FBBLANK | BL_CORE_SUSPENDED);
90 		backlight->props.power = FB_BLANK_UNBLANK;
91 	} else {
92 		backlight->props.fb_blank = FB_BLANK_NORMAL;
93 		backlight->props.power = FB_BLANK_POWERDOWN;
94 		backlight->props.state |= BL_CORE_FBBLANK | BL_CORE_SUSPENDED;
95 	}
96 
97 	backlight_update_status(backlight);
98 }
99 
100 static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
101 {
102 	ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
103 	ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
104 }
105 
106 static void hw_guard_wait(struct panel_drv_data *ddata)
107 {
108 	unsigned long wait = ddata->hw_guard_end - jiffies;
109 
110 	if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
111 		set_current_state(TASK_UNINTERRUPTIBLE);
112 		schedule_timeout(wait);
113 	}
114 }
115 
116 static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
117 {
118 	return mipi_dsi_dcs_read(ddata->dsi, dcs_cmd, data, 1);
119 }
120 
121 static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
122 {
123 	return mipi_dsi_dcs_write(ddata->dsi, dcs_cmd, &param, 1);
124 }
125 
126 static int dsicm_sleep_in(struct panel_drv_data *ddata)
127 
128 {
129 	int r;
130 
131 	hw_guard_wait(ddata);
132 
133 	r = mipi_dsi_dcs_enter_sleep_mode(ddata->dsi);
134 	if (r)
135 		return r;
136 
137 	hw_guard_start(ddata, 120);
138 
139 	usleep_range(5000, 10000);
140 
141 	return 0;
142 }
143 
144 static int dsicm_sleep_out(struct panel_drv_data *ddata)
145 {
146 	int r;
147 
148 	hw_guard_wait(ddata);
149 
150 	r = mipi_dsi_dcs_exit_sleep_mode(ddata->dsi);
151 	if (r)
152 		return r;
153 
154 	hw_guard_start(ddata, 120);
155 
156 	usleep_range(5000, 10000);
157 
158 	return 0;
159 }
160 
161 static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
162 {
163 	int r;
164 
165 	r = dsicm_dcs_read_1(ddata, DCS_GET_ID1, id1);
166 	if (r)
167 		return r;
168 	r = dsicm_dcs_read_1(ddata, DCS_GET_ID2, id2);
169 	if (r)
170 		return r;
171 	r = dsicm_dcs_read_1(ddata, DCS_GET_ID3, id3);
172 	if (r)
173 		return r;
174 
175 	return 0;
176 }
177 
178 static int dsicm_set_update_window(struct panel_drv_data *ddata)
179 {
180 	struct mipi_dsi_device *dsi = ddata->dsi;
181 	int r;
182 
183 	r = mipi_dsi_dcs_set_column_address(dsi, 0, ddata->mode.hdisplay - 1);
184 	if (r < 0)
185 		return r;
186 
187 	r = mipi_dsi_dcs_set_page_address(dsi, 0, ddata->mode.vdisplay - 1);
188 	if (r < 0)
189 		return r;
190 
191 	return 0;
192 }
193 
194 static int dsicm_bl_update_status(struct backlight_device *dev)
195 {
196 	struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
197 	int r = 0;
198 	int level;
199 
200 	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
201 			dev->props.power == FB_BLANK_UNBLANK)
202 		level = dev->props.brightness;
203 	else
204 		level = 0;
205 
206 	dev_dbg(&ddata->dsi->dev, "update brightness to %d\n", level);
207 
208 	mutex_lock(&ddata->lock);
209 
210 	if (ddata->enabled)
211 		r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
212 				      level);
213 
214 	mutex_unlock(&ddata->lock);
215 
216 	return r;
217 }
218 
219 static int dsicm_bl_get_intensity(struct backlight_device *dev)
220 {
221 	if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
222 			dev->props.power == FB_BLANK_UNBLANK)
223 		return dev->props.brightness;
224 
225 	return 0;
226 }
227 
228 static const struct backlight_ops dsicm_bl_ops = {
229 	.get_brightness = dsicm_bl_get_intensity,
230 	.update_status  = dsicm_bl_update_status,
231 };
232 
233 static ssize_t num_dsi_errors_show(struct device *dev,
234 		struct device_attribute *attr, char *buf)
235 {
236 	struct panel_drv_data *ddata = dev_get_drvdata(dev);
237 	u8 errors = 0;
238 	int r = -ENODEV;
239 
240 	mutex_lock(&ddata->lock);
241 
242 	if (ddata->enabled)
243 		r = dsicm_dcs_read_1(ddata, MIPI_DCS_GET_ERROR_COUNT_ON_DSI, &errors);
244 
245 	mutex_unlock(&ddata->lock);
246 
247 	if (r)
248 		return r;
249 
250 	return snprintf(buf, PAGE_SIZE, "%d\n", errors);
251 }
252 
253 static ssize_t hw_revision_show(struct device *dev,
254 		struct device_attribute *attr, char *buf)
255 {
256 	struct panel_drv_data *ddata = dev_get_drvdata(dev);
257 	u8 id1, id2, id3;
258 	int r = -ENODEV;
259 
260 	mutex_lock(&ddata->lock);
261 
262 	if (ddata->enabled)
263 		r = dsicm_get_id(ddata, &id1, &id2, &id3);
264 
265 	mutex_unlock(&ddata->lock);
266 
267 	if (r)
268 		return r;
269 
270 	return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
271 }
272 
273 static DEVICE_ATTR_RO(num_dsi_errors);
274 static DEVICE_ATTR_RO(hw_revision);
275 
276 static struct attribute *dsicm_attrs[] = {
277 	&dev_attr_num_dsi_errors.attr,
278 	&dev_attr_hw_revision.attr,
279 	NULL,
280 };
281 
282 static const struct attribute_group dsicm_attr_group = {
283 	.attrs = dsicm_attrs,
284 };
285 
286 static void dsicm_hw_reset(struct panel_drv_data *ddata)
287 {
288 	gpiod_set_value(ddata->reset_gpio, 1);
289 	udelay(10);
290 	/* reset the panel */
291 	gpiod_set_value(ddata->reset_gpio, 0);
292 	/* assert reset */
293 	udelay(10);
294 	gpiod_set_value(ddata->reset_gpio, 1);
295 	/* wait after releasing reset */
296 	usleep_range(5000, 10000);
297 }
298 
299 static int dsicm_power_on(struct panel_drv_data *ddata)
300 {
301 	u8 id1, id2, id3;
302 	int r;
303 
304 	dsicm_hw_reset(ddata);
305 
306 	ddata->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
307 
308 	r = dsicm_sleep_out(ddata);
309 	if (r)
310 		goto err;
311 
312 	r = dsicm_get_id(ddata, &id1, &id2, &id3);
313 	if (r)
314 		goto err;
315 
316 	r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 0xff);
317 	if (r)
318 		goto err;
319 
320 	r = dsicm_dcs_write_1(ddata, MIPI_DCS_WRITE_CONTROL_DISPLAY,
321 			(1<<2) | (1<<5));	/* BL | BCTRL */
322 	if (r)
323 		goto err;
324 
325 	r = mipi_dsi_dcs_set_pixel_format(ddata->dsi, MIPI_DCS_PIXEL_FMT_24BIT);
326 	if (r)
327 		goto err;
328 
329 	r = dsicm_set_update_window(ddata);
330 	if (r)
331 		goto err;
332 
333 	r = mipi_dsi_dcs_set_display_on(ddata->dsi);
334 	if (r)
335 		goto err;
336 
337 	r = mipi_dsi_dcs_set_tear_on(ddata->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
338 	if (r)
339 		goto err;
340 
341 	/* possible panel bug */
342 	msleep(100);
343 
344 	ddata->enabled = true;
345 
346 	if (!ddata->intro_printed) {
347 		dev_info(&ddata->dsi->dev, "panel revision %02x.%02x.%02x\n",
348 			id1, id2, id3);
349 		ddata->intro_printed = true;
350 	}
351 
352 	ddata->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
353 
354 	return 0;
355 err:
356 	dev_err(&ddata->dsi->dev, "error while enabling panel, issuing HW reset\n");
357 
358 	dsicm_hw_reset(ddata);
359 
360 	return r;
361 }
362 
363 static int dsicm_power_off(struct panel_drv_data *ddata)
364 {
365 	int r;
366 
367 	ddata->enabled = false;
368 
369 	r = mipi_dsi_dcs_set_display_off(ddata->dsi);
370 	if (!r)
371 		r = dsicm_sleep_in(ddata);
372 
373 	if (r) {
374 		dev_err(&ddata->dsi->dev,
375 				"error disabling panel, issuing HW reset\n");
376 		dsicm_hw_reset(ddata);
377 	}
378 
379 	return r;
380 }
381 
382 static int dsicm_prepare(struct drm_panel *panel)
383 {
384 	struct panel_drv_data *ddata = panel_to_ddata(panel);
385 	int r;
386 
387 	r = regulator_bulk_enable(ARRAY_SIZE(ddata->supplies), ddata->supplies);
388 	if (r)
389 		dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r);
390 
391 	return r;
392 }
393 
394 static int dsicm_enable(struct drm_panel *panel)
395 {
396 	struct panel_drv_data *ddata = panel_to_ddata(panel);
397 	int r;
398 
399 	mutex_lock(&ddata->lock);
400 
401 	r = dsicm_power_on(ddata);
402 	if (r)
403 		goto err;
404 
405 	mutex_unlock(&ddata->lock);
406 
407 	dsicm_bl_power(ddata, true);
408 
409 	return 0;
410 err:
411 	dev_err(&ddata->dsi->dev, "enable failed (%d)\n", r);
412 	mutex_unlock(&ddata->lock);
413 	return r;
414 }
415 
416 static int dsicm_unprepare(struct drm_panel *panel)
417 {
418 	struct panel_drv_data *ddata = panel_to_ddata(panel);
419 	int r;
420 
421 	r = regulator_bulk_disable(ARRAY_SIZE(ddata->supplies), ddata->supplies);
422 	if (r)
423 		dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r);
424 
425 	return r;
426 }
427 
428 static int dsicm_disable(struct drm_panel *panel)
429 {
430 	struct panel_drv_data *ddata = panel_to_ddata(panel);
431 	int r;
432 
433 	dsicm_bl_power(ddata, false);
434 
435 	mutex_lock(&ddata->lock);
436 
437 	r = dsicm_power_off(ddata);
438 
439 	mutex_unlock(&ddata->lock);
440 
441 	return r;
442 }
443 
444 static int dsicm_get_modes(struct drm_panel *panel,
445 			   struct drm_connector *connector)
446 {
447 	struct panel_drv_data *ddata = panel_to_ddata(panel);
448 	struct drm_display_mode *mode;
449 
450 	mode = drm_mode_duplicate(connector->dev, &ddata->mode);
451 	if (!mode) {
452 		dev_err(&ddata->dsi->dev, "failed to add mode %ux%ux@%u kHz\n",
453 			ddata->mode.hdisplay, ddata->mode.vdisplay,
454 			ddata->mode.clock);
455 		return -ENOMEM;
456 	}
457 
458 	connector->display_info.width_mm = ddata->panel_data->width_mm;
459 	connector->display_info.height_mm = ddata->panel_data->height_mm;
460 
461 	drm_mode_probed_add(connector, mode);
462 
463 	return 1;
464 }
465 
466 static const struct drm_panel_funcs dsicm_panel_funcs = {
467 	.unprepare = dsicm_unprepare,
468 	.disable = dsicm_disable,
469 	.prepare = dsicm_prepare,
470 	.enable = dsicm_enable,
471 	.get_modes = dsicm_get_modes,
472 };
473 
474 static int dsicm_probe_of(struct mipi_dsi_device *dsi)
475 {
476 	struct backlight_device *backlight;
477 	struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
478 	int err;
479 	struct drm_display_mode *mode = &ddata->mode;
480 
481 	ddata->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
482 	if (IS_ERR(ddata->reset_gpio)) {
483 		err = PTR_ERR(ddata->reset_gpio);
484 		dev_err(&dsi->dev, "reset gpio request failed: %d", err);
485 		return err;
486 	}
487 
488 	mode->hdisplay = mode->hsync_start = mode->hsync_end = mode->htotal =
489 		ddata->panel_data->xres;
490 	mode->vdisplay = mode->vsync_start = mode->vsync_end = mode->vtotal =
491 		ddata->panel_data->yres;
492 	mode->clock = ddata->panel_data->xres * ddata->panel_data->yres *
493 		ddata->panel_data->refresh / 1000;
494 	mode->width_mm = ddata->panel_data->width_mm;
495 	mode->height_mm = ddata->panel_data->height_mm;
496 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
497 	drm_mode_set_name(mode);
498 
499 	ddata->supplies[0].supply = "vpnl";
500 	ddata->supplies[1].supply = "vddi";
501 	err = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(ddata->supplies),
502 				      ddata->supplies);
503 	if (err)
504 		return err;
505 
506 	backlight = devm_of_find_backlight(&dsi->dev);
507 	if (IS_ERR(backlight))
508 		return PTR_ERR(backlight);
509 
510 	/* If no backlight device is found assume native backlight support */
511 	if (backlight)
512 		ddata->extbldev = backlight;
513 	else
514 		ddata->use_dsi_backlight = true;
515 
516 	return 0;
517 }
518 
519 static int dsicm_probe(struct mipi_dsi_device *dsi)
520 {
521 	struct panel_drv_data *ddata;
522 	struct backlight_device *bldev = NULL;
523 	struct device *dev = &dsi->dev;
524 	int r;
525 
526 	dev_dbg(dev, "probe\n");
527 
528 	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
529 	if (!ddata)
530 		return -ENOMEM;
531 
532 	mipi_dsi_set_drvdata(dsi, ddata);
533 	ddata->dsi = dsi;
534 
535 	ddata->panel_data = of_device_get_match_data(dev);
536 	if (!ddata->panel_data)
537 		return -ENODEV;
538 
539 	r = dsicm_probe_of(dsi);
540 	if (r)
541 		return r;
542 
543 	mutex_init(&ddata->lock);
544 
545 	dsicm_hw_reset(ddata);
546 
547 	drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
548 		       DRM_MODE_CONNECTOR_DSI);
549 
550 	if (ddata->use_dsi_backlight) {
551 		struct backlight_properties props = { 0 };
552 		props.max_brightness = 255;
553 		props.type = BACKLIGHT_RAW;
554 
555 		bldev = devm_backlight_device_register(dev, dev_name(dev),
556 			dev, ddata, &dsicm_bl_ops, &props);
557 		if (IS_ERR(bldev)) {
558 			r = PTR_ERR(bldev);
559 			goto err_bl;
560 		}
561 
562 		ddata->bldev = bldev;
563 	}
564 
565 	r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
566 	if (r) {
567 		dev_err(dev, "failed to create sysfs files\n");
568 		goto err_bl;
569 	}
570 
571 	dsi->lanes = 2;
572 	dsi->format = MIPI_DSI_FMT_RGB888;
573 	dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
574 			  MIPI_DSI_MODE_EOT_PACKET;
575 	dsi->hs_rate = ddata->panel_data->max_hs_rate;
576 	dsi->lp_rate = ddata->panel_data->max_lp_rate;
577 
578 	drm_panel_add(&ddata->panel);
579 
580 	r = mipi_dsi_attach(dsi);
581 	if (r < 0)
582 		goto err_dsi_attach;
583 
584 	return 0;
585 
586 err_dsi_attach:
587 	drm_panel_remove(&ddata->panel);
588 	sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
589 err_bl:
590 	if (ddata->extbldev)
591 		put_device(&ddata->extbldev->dev);
592 
593 	return r;
594 }
595 
596 static int dsicm_remove(struct mipi_dsi_device *dsi)
597 {
598 	struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
599 
600 	dev_dbg(&dsi->dev, "remove\n");
601 
602 	mipi_dsi_detach(dsi);
603 
604 	drm_panel_remove(&ddata->panel);
605 
606 	sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
607 
608 	if (ddata->extbldev)
609 		put_device(&ddata->extbldev->dev);
610 
611 	return 0;
612 }
613 
614 static const struct dsic_panel_data taal_data = {
615 	.xres = 864,
616 	.yres = 480,
617 	.refresh = 60,
618 	.width_mm = 0,
619 	.height_mm = 0,
620 	.max_hs_rate = 300000000,
621 	.max_lp_rate = 10000000,
622 };
623 
624 static const struct dsic_panel_data himalaya_data = {
625 	.xres = 480,
626 	.yres = 864,
627 	.refresh = 60,
628 	.width_mm = 49,
629 	.height_mm = 88,
630 	.max_hs_rate = 300000000,
631 	.max_lp_rate = 10000000,
632 };
633 
634 static const struct dsic_panel_data droid4_data = {
635 	.xres = 540,
636 	.yres = 960,
637 	.refresh = 60,
638 	.width_mm = 50,
639 	.height_mm = 89,
640 	.max_hs_rate = 300000000,
641 	.max_lp_rate = 10000000,
642 };
643 
644 static const struct of_device_id dsicm_of_match[] = {
645 	{ .compatible = "tpo,taal", .data = &taal_data },
646 	{ .compatible = "nokia,himalaya", &himalaya_data },
647 	{ .compatible = "motorola,droid4-panel", &droid4_data },
648 	{},
649 };
650 
651 MODULE_DEVICE_TABLE(of, dsicm_of_match);
652 
653 static struct mipi_dsi_driver dsicm_driver = {
654 	.probe = dsicm_probe,
655 	.remove = dsicm_remove,
656 	.driver = {
657 		.name = "panel-dsi-cm",
658 		.of_match_table = dsicm_of_match,
659 	},
660 };
661 module_mipi_dsi_driver(dsicm_driver);
662 
663 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
664 MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");
665 MODULE_LICENSE("GPL");
666