.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License as published by |
---|
6 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
7 | | - * (at your option) any later version. |
---|
8 | 4 | */ |
---|
9 | 5 | |
---|
10 | | -#include <linux/backlight.h> |
---|
| 6 | +#include <linux/delay.h> |
---|
11 | 7 | #include <linux/gpio/consumer.h> |
---|
12 | 8 | #include <linux/module.h> |
---|
13 | 9 | #include <linux/of.h> |
---|
14 | 10 | #include <linux/of_device.h> |
---|
15 | 11 | #include <linux/regulator/consumer.h> |
---|
16 | 12 | |
---|
17 | | -#include <drm/drmP.h> |
---|
18 | | -#include <drm/drm_crtc.h> |
---|
19 | | -#include <drm/drm_mipi_dsi.h> |
---|
20 | | -#include <drm/drm_panel.h> |
---|
21 | | - |
---|
22 | 13 | #include <video/mipi_display.h> |
---|
| 14 | + |
---|
| 15 | +#include <drm/drm_crtc.h> |
---|
| 16 | +#include <drm/drm_device.h> |
---|
| 17 | +#include <drm/drm_mipi_dsi.h> |
---|
| 18 | +#include <drm/drm_modes.h> |
---|
| 19 | +#include <drm/drm_panel.h> |
---|
23 | 20 | |
---|
24 | 21 | struct panel_init_cmd { |
---|
25 | 22 | size_t len; |
---|
.. | .. |
---|
53 | 50 | struct mipi_dsi_device *link; |
---|
54 | 51 | const struct panel_desc *desc; |
---|
55 | 52 | |
---|
56 | | - struct backlight_device *backlight; |
---|
57 | 53 | struct regulator_bulk_data *supplies; |
---|
58 | | - unsigned int num_supplies; |
---|
59 | 54 | struct gpio_desc *enable_gpio; |
---|
60 | 55 | |
---|
61 | 56 | bool prepared; |
---|
.. | .. |
---|
74 | 69 | if (!innolux->enabled) |
---|
75 | 70 | return 0; |
---|
76 | 71 | |
---|
77 | | - backlight_disable(innolux->backlight); |
---|
78 | | - |
---|
79 | 72 | innolux->enabled = false; |
---|
80 | 73 | |
---|
81 | 74 | return 0; |
---|
.. | .. |
---|
91 | 84 | |
---|
92 | 85 | err = mipi_dsi_dcs_set_display_off(innolux->link); |
---|
93 | 86 | if (err < 0) |
---|
94 | | - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", |
---|
95 | | - err); |
---|
| 87 | + dev_err(panel->dev, "failed to set display off: %d\n", err); |
---|
96 | 88 | |
---|
97 | 89 | err = mipi_dsi_dcs_enter_sleep_mode(innolux->link); |
---|
98 | 90 | if (err < 0) { |
---|
99 | | - DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", |
---|
100 | | - err); |
---|
| 91 | + dev_err(panel->dev, "failed to enter sleep mode: %d\n", err); |
---|
101 | 92 | return err; |
---|
102 | 93 | } |
---|
103 | 94 | |
---|
.. | .. |
---|
153 | 144 | err = mipi_dsi_generic_write(innolux->link, cmd->data, |
---|
154 | 145 | cmd->len); |
---|
155 | 146 | if (err < 0) { |
---|
156 | | - dev_err(panel->dev, |
---|
157 | | - "failed to write command %u\n", i); |
---|
| 147 | + dev_err(panel->dev, "failed to write command %u\n", i); |
---|
158 | 148 | goto poweroff; |
---|
159 | 149 | } |
---|
160 | 150 | |
---|
.. | .. |
---|
165 | 155 | */ |
---|
166 | 156 | err = mipi_dsi_dcs_nop(innolux->link); |
---|
167 | 157 | if (err < 0) { |
---|
168 | | - dev_err(panel->dev, |
---|
169 | | - "failed to send DCS nop: %d\n", err); |
---|
| 158 | + dev_err(panel->dev, "failed to send DCS nop: %d\n", err); |
---|
170 | 159 | goto poweroff; |
---|
171 | 160 | } |
---|
172 | 161 | } |
---|
.. | .. |
---|
174 | 163 | |
---|
175 | 164 | err = mipi_dsi_dcs_exit_sleep_mode(innolux->link); |
---|
176 | 165 | if (err < 0) { |
---|
177 | | - DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n", |
---|
178 | | - err); |
---|
| 166 | + dev_err(panel->dev, "failed to exit sleep mode: %d\n", err); |
---|
179 | 167 | goto poweroff; |
---|
180 | 168 | } |
---|
181 | 169 | |
---|
.. | .. |
---|
184 | 172 | |
---|
185 | 173 | err = mipi_dsi_dcs_set_display_on(innolux->link); |
---|
186 | 174 | if (err < 0) { |
---|
187 | | - DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", |
---|
188 | | - err); |
---|
| 175 | + dev_err(panel->dev, "failed to set display on: %d\n", err); |
---|
189 | 176 | goto poweroff; |
---|
190 | 177 | } |
---|
191 | 178 | |
---|
.. | .. |
---|
206 | 193 | static int innolux_panel_enable(struct drm_panel *panel) |
---|
207 | 194 | { |
---|
208 | 195 | struct innolux_panel *innolux = to_innolux_panel(panel); |
---|
209 | | - int ret; |
---|
210 | 196 | |
---|
211 | 197 | if (innolux->enabled) |
---|
212 | 198 | return 0; |
---|
213 | | - |
---|
214 | | - ret = backlight_enable(innolux->backlight); |
---|
215 | | - if (ret) { |
---|
216 | | - DRM_DEV_ERROR(panel->drm->dev, |
---|
217 | | - "Failed to enable backlight %d\n", ret); |
---|
218 | | - return ret; |
---|
219 | | - } |
---|
220 | 199 | |
---|
221 | 200 | innolux->enabled = true; |
---|
222 | 201 | |
---|
.. | .. |
---|
237 | 216 | .vsync_start = 1024 + 20, |
---|
238 | 217 | .vsync_end = 1024 + 20 + 4, |
---|
239 | 218 | .vtotal = 1024 + 20 + 4 + 20, |
---|
240 | | - .vrefresh = 60, |
---|
241 | 219 | }; |
---|
242 | 220 | |
---|
243 | 221 | static const struct panel_desc innolux_p079zca_panel_desc = { |
---|
.. | .. |
---|
271 | 249 | .vsync_start = 2048 + 100, |
---|
272 | 250 | .vsync_end = 2048 + 100 + 2, |
---|
273 | 251 | .vtotal = 2048 + 100 + 2 + 18, |
---|
274 | | - .vrefresh = 60, |
---|
275 | 252 | }; |
---|
276 | 253 | |
---|
277 | 254 | /* |
---|
.. | .. |
---|
405 | 382 | .sleep_mode_delay = 100, /* T15 */ |
---|
406 | 383 | }; |
---|
407 | 384 | |
---|
408 | | -static int innolux_panel_get_modes(struct drm_panel *panel) |
---|
| 385 | +static int innolux_panel_get_modes(struct drm_panel *panel, |
---|
| 386 | + struct drm_connector *connector) |
---|
409 | 387 | { |
---|
410 | 388 | struct innolux_panel *innolux = to_innolux_panel(panel); |
---|
411 | 389 | const struct drm_display_mode *m = innolux->desc->mode; |
---|
412 | 390 | struct drm_display_mode *mode; |
---|
413 | 391 | |
---|
414 | | - mode = drm_mode_duplicate(panel->drm, m); |
---|
| 392 | + mode = drm_mode_duplicate(connector->dev, m); |
---|
415 | 393 | if (!mode) { |
---|
416 | | - DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%ux@%u\n", |
---|
417 | | - m->hdisplay, m->vdisplay, m->vrefresh); |
---|
| 394 | + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", |
---|
| 395 | + m->hdisplay, m->vdisplay, drm_mode_vrefresh(m)); |
---|
418 | 396 | return -ENOMEM; |
---|
419 | 397 | } |
---|
420 | 398 | |
---|
421 | 399 | drm_mode_set_name(mode); |
---|
422 | 400 | |
---|
423 | | - drm_mode_probed_add(panel->connector, mode); |
---|
| 401 | + drm_mode_probed_add(connector, mode); |
---|
424 | 402 | |
---|
425 | | - panel->connector->display_info.width_mm = |
---|
426 | | - innolux->desc->size.width; |
---|
427 | | - panel->connector->display_info.height_mm = |
---|
428 | | - innolux->desc->size.height; |
---|
429 | | - panel->connector->display_info.bpc = innolux->desc->bpc; |
---|
| 403 | + connector->display_info.width_mm = innolux->desc->size.width; |
---|
| 404 | + connector->display_info.height_mm = innolux->desc->size.height; |
---|
| 405 | + connector->display_info.bpc = innolux->desc->bpc; |
---|
430 | 406 | |
---|
431 | 407 | return 1; |
---|
432 | 408 | } |
---|
.. | .. |
---|
485 | 461 | innolux->enable_gpio = NULL; |
---|
486 | 462 | } |
---|
487 | 463 | |
---|
488 | | - innolux->backlight = devm_of_find_backlight(dev); |
---|
489 | | - if (IS_ERR(innolux->backlight)) |
---|
490 | | - return PTR_ERR(innolux->backlight); |
---|
| 464 | + drm_panel_init(&innolux->base, dev, &innolux_panel_funcs, |
---|
| 465 | + DRM_MODE_CONNECTOR_DSI); |
---|
491 | 466 | |
---|
492 | | - drm_panel_init(&innolux->base); |
---|
493 | | - innolux->base.funcs = &innolux_panel_funcs; |
---|
494 | | - innolux->base.dev = dev; |
---|
495 | | - |
---|
496 | | - err = drm_panel_add(&innolux->base); |
---|
497 | | - if (err < 0) |
---|
| 467 | + err = drm_panel_of_backlight(&innolux->base); |
---|
| 468 | + if (err) |
---|
498 | 469 | return err; |
---|
| 470 | + |
---|
| 471 | + drm_panel_add(&innolux->base); |
---|
499 | 472 | |
---|
500 | 473 | mipi_dsi_set_drvdata(dsi, innolux); |
---|
501 | 474 | innolux->link = dsi; |
---|
.. | .. |
---|
505 | 478 | |
---|
506 | 479 | static void innolux_panel_del(struct innolux_panel *innolux) |
---|
507 | 480 | { |
---|
508 | | - if (innolux->base.dev) |
---|
509 | | - drm_panel_remove(&innolux->base); |
---|
| 481 | + drm_panel_remove(&innolux->base); |
---|
510 | 482 | } |
---|
511 | 483 | |
---|
512 | 484 | static int innolux_panel_probe(struct mipi_dsi_device *dsi) |
---|
.. | .. |
---|
539 | 511 | struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi); |
---|
540 | 512 | int err; |
---|
541 | 513 | |
---|
542 | | - err = innolux_panel_unprepare(&innolux->base); |
---|
| 514 | + err = drm_panel_unprepare(&innolux->base); |
---|
543 | 515 | if (err < 0) |
---|
544 | | - DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n", |
---|
545 | | - err); |
---|
| 516 | + dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); |
---|
546 | 517 | |
---|
547 | | - err = innolux_panel_disable(&innolux->base); |
---|
| 518 | + err = drm_panel_disable(&innolux->base); |
---|
548 | 519 | if (err < 0) |
---|
549 | | - DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n", err); |
---|
| 520 | + dev_err(&dsi->dev, "failed to disable panel: %d\n", err); |
---|
550 | 521 | |
---|
551 | 522 | err = mipi_dsi_detach(dsi); |
---|
552 | 523 | if (err < 0) |
---|
553 | | - DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n", |
---|
554 | | - err); |
---|
| 524 | + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); |
---|
555 | 525 | |
---|
556 | 526 | innolux_panel_del(innolux); |
---|
557 | 527 | |
---|
.. | .. |
---|
562 | 532 | { |
---|
563 | 533 | struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi); |
---|
564 | 534 | |
---|
565 | | - innolux_panel_unprepare(&innolux->base); |
---|
566 | | - innolux_panel_disable(&innolux->base); |
---|
| 535 | + drm_panel_unprepare(&innolux->base); |
---|
| 536 | + drm_panel_disable(&innolux->base); |
---|
567 | 537 | } |
---|
568 | 538 | |
---|
569 | 539 | static struct mipi_dsi_driver innolux_panel_driver = { |
---|