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