.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2017 NXP Semiconductors. |
---|
3 | 4 | * Author: Marco Franchi <marco.franchi@nxp.com> |
---|
4 | 5 | * |
---|
5 | 6 | * Based on Panel Simple driver by Thierry Reding <treding@nvidia.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License version |
---|
9 | | - * 2 as published by the Free Software Foundation. |
---|
10 | 7 | */ |
---|
11 | 8 | |
---|
12 | | -#include <linux/backlight.h> |
---|
| 9 | +#include <linux/delay.h> |
---|
13 | 10 | #include <linux/module.h> |
---|
14 | 11 | #include <linux/of.h> |
---|
| 12 | +#include <linux/platform_device.h> |
---|
15 | 13 | #include <linux/regulator/consumer.h> |
---|
16 | | - |
---|
17 | | -#include <drm/drmP.h> |
---|
18 | | -#include <drm/drm_crtc.h> |
---|
19 | | -#include <drm/drm_panel.h> |
---|
20 | 14 | |
---|
21 | 15 | #include <video/display_timing.h> |
---|
22 | 16 | #include <video/videomode.h> |
---|
| 17 | + |
---|
| 18 | +#include <drm/drm_crtc.h> |
---|
| 19 | +#include <drm/drm_device.h> |
---|
| 20 | +#include <drm/drm_panel.h> |
---|
23 | 21 | |
---|
24 | 22 | struct seiko_panel_desc { |
---|
25 | 23 | const struct drm_display_mode *modes; |
---|
.. | .. |
---|
47 | 45 | bool prepared; |
---|
48 | 46 | bool enabled; |
---|
49 | 47 | const struct seiko_panel_desc *desc; |
---|
50 | | - struct backlight_device *backlight; |
---|
51 | 48 | struct regulator *dvdd; |
---|
52 | 49 | struct regulator *avdd; |
---|
53 | 50 | }; |
---|
.. | .. |
---|
57 | 54 | return container_of(panel, struct seiko_panel, base); |
---|
58 | 55 | } |
---|
59 | 56 | |
---|
60 | | -static int seiko_panel_get_fixed_modes(struct seiko_panel *panel) |
---|
| 57 | +static int seiko_panel_get_fixed_modes(struct seiko_panel *panel, |
---|
| 58 | + struct drm_connector *connector) |
---|
61 | 59 | { |
---|
62 | | - struct drm_connector *connector = panel->base.connector; |
---|
63 | | - struct drm_device *drm = panel->base.drm; |
---|
64 | 60 | struct drm_display_mode *mode; |
---|
65 | 61 | unsigned int i, num = 0; |
---|
66 | 62 | |
---|
.. | .. |
---|
72 | 68 | struct videomode vm; |
---|
73 | 69 | |
---|
74 | 70 | videomode_from_timing(dt, &vm); |
---|
75 | | - mode = drm_mode_create(drm); |
---|
| 71 | + mode = drm_mode_create(connector->dev); |
---|
76 | 72 | if (!mode) { |
---|
77 | | - dev_err(drm->dev, "failed to add mode %ux%u\n", |
---|
| 73 | + dev_err(panel->base.dev, "failed to add mode %ux%u\n", |
---|
78 | 74 | dt->hactive.typ, dt->vactive.typ); |
---|
79 | 75 | continue; |
---|
80 | 76 | } |
---|
.. | .. |
---|
93 | 89 | for (i = 0; i < panel->desc->num_modes; i++) { |
---|
94 | 90 | const struct drm_display_mode *m = &panel->desc->modes[i]; |
---|
95 | 91 | |
---|
96 | | - mode = drm_mode_duplicate(drm, m); |
---|
| 92 | + mode = drm_mode_duplicate(connector->dev, m); |
---|
97 | 93 | if (!mode) { |
---|
98 | | - dev_err(drm->dev, "failed to add mode %ux%u@%u\n", |
---|
99 | | - m->hdisplay, m->vdisplay, m->vrefresh); |
---|
| 94 | + dev_err(panel->base.dev, "failed to add mode %ux%u@%u\n", |
---|
| 95 | + m->hdisplay, m->vdisplay, |
---|
| 96 | + drm_mode_vrefresh(m)); |
---|
100 | 97 | continue; |
---|
101 | 98 | } |
---|
102 | 99 | |
---|
.. | .. |
---|
128 | 125 | |
---|
129 | 126 | if (!p->enabled) |
---|
130 | 127 | return 0; |
---|
131 | | - |
---|
132 | | - if (p->backlight) { |
---|
133 | | - p->backlight->props.power = FB_BLANK_POWERDOWN; |
---|
134 | | - p->backlight->props.state |= BL_CORE_FBBLANK; |
---|
135 | | - backlight_update_status(p->backlight); |
---|
136 | | - } |
---|
137 | 128 | |
---|
138 | 129 | p->enabled = false; |
---|
139 | 130 | |
---|
.. | .. |
---|
198 | 189 | if (p->enabled) |
---|
199 | 190 | return 0; |
---|
200 | 191 | |
---|
201 | | - if (p->backlight) { |
---|
202 | | - p->backlight->props.state &= ~BL_CORE_FBBLANK; |
---|
203 | | - p->backlight->props.power = FB_BLANK_UNBLANK; |
---|
204 | | - backlight_update_status(p->backlight); |
---|
205 | | - } |
---|
206 | | - |
---|
207 | 192 | p->enabled = true; |
---|
208 | 193 | |
---|
209 | 194 | return 0; |
---|
210 | 195 | } |
---|
211 | 196 | |
---|
212 | | -static int seiko_panel_get_modes(struct drm_panel *panel) |
---|
| 197 | +static int seiko_panel_get_modes(struct drm_panel *panel, |
---|
| 198 | + struct drm_connector *connector) |
---|
213 | 199 | { |
---|
214 | 200 | struct seiko_panel *p = to_seiko_panel(panel); |
---|
215 | 201 | |
---|
216 | 202 | /* add hard-coded panel modes */ |
---|
217 | | - return seiko_panel_get_fixed_modes(p); |
---|
| 203 | + return seiko_panel_get_fixed_modes(p, connector); |
---|
218 | 204 | } |
---|
219 | 205 | |
---|
220 | 206 | static int seiko_panel_get_timings(struct drm_panel *panel, |
---|
.. | .. |
---|
246 | 232 | static int seiko_panel_probe(struct device *dev, |
---|
247 | 233 | const struct seiko_panel_desc *desc) |
---|
248 | 234 | { |
---|
249 | | - struct device_node *backlight; |
---|
250 | 235 | struct seiko_panel *panel; |
---|
251 | 236 | int err; |
---|
252 | 237 | |
---|
.. | .. |
---|
266 | 251 | if (IS_ERR(panel->avdd)) |
---|
267 | 252 | return PTR_ERR(panel->avdd); |
---|
268 | 253 | |
---|
269 | | - backlight = of_parse_phandle(dev->of_node, "backlight", 0); |
---|
270 | | - if (backlight) { |
---|
271 | | - panel->backlight = of_find_backlight_by_node(backlight); |
---|
272 | | - of_node_put(backlight); |
---|
| 254 | + drm_panel_init(&panel->base, dev, &seiko_panel_funcs, |
---|
| 255 | + DRM_MODE_CONNECTOR_DPI); |
---|
273 | 256 | |
---|
274 | | - if (!panel->backlight) |
---|
275 | | - return -EPROBE_DEFER; |
---|
276 | | - } |
---|
277 | | - |
---|
278 | | - drm_panel_init(&panel->base); |
---|
279 | | - panel->base.dev = dev; |
---|
280 | | - panel->base.funcs = &seiko_panel_funcs; |
---|
281 | | - |
---|
282 | | - err = drm_panel_add(&panel->base); |
---|
283 | | - if (err < 0) |
---|
| 257 | + err = drm_panel_of_backlight(&panel->base); |
---|
| 258 | + if (err) |
---|
284 | 259 | return err; |
---|
| 260 | + |
---|
| 261 | + drm_panel_add(&panel->base); |
---|
285 | 262 | |
---|
286 | 263 | dev_set_drvdata(dev, panel); |
---|
287 | 264 | |
---|
.. | .. |
---|
293 | 270 | struct seiko_panel *panel = dev_get_drvdata(&pdev->dev); |
---|
294 | 271 | |
---|
295 | 272 | drm_panel_remove(&panel->base); |
---|
296 | | - |
---|
297 | | - seiko_panel_disable(&panel->base); |
---|
298 | | - |
---|
299 | | - if (panel->backlight) |
---|
300 | | - put_device(&panel->backlight->dev); |
---|
| 273 | + drm_panel_disable(&panel->base); |
---|
301 | 274 | |
---|
302 | 275 | return 0; |
---|
303 | 276 | } |
---|
.. | .. |
---|
306 | 279 | { |
---|
307 | 280 | struct seiko_panel *panel = dev_get_drvdata(&pdev->dev); |
---|
308 | 281 | |
---|
309 | | - seiko_panel_disable(&panel->base); |
---|
| 282 | + drm_panel_disable(&panel->base); |
---|
310 | 283 | } |
---|
311 | 284 | |
---|
312 | 285 | static const struct display_timing seiko_43wvf1g_timing = { |
---|
.. | .. |
---|
331 | 304 | .height = 57, |
---|
332 | 305 | }, |
---|
333 | 306 | .bus_format = MEDIA_BUS_FMT_RGB888_1X24, |
---|
334 | | - .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_NEGEDGE, |
---|
| 307 | + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, |
---|
335 | 308 | }; |
---|
336 | 309 | |
---|
337 | 310 | static const struct of_device_id platform_of_match[] = { |
---|
.. | .. |
---|
366 | 339 | }; |
---|
367 | 340 | module_platform_driver(seiko_panel_platform_driver); |
---|
368 | 341 | |
---|
369 | | -MODULE_AUTHOR("Marco Franchi <marco.franchi@nxp.com"); |
---|
| 342 | +MODULE_AUTHOR("Marco Franchi <marco.franchi@nxp.com>"); |
---|
370 | 343 | MODULE_DESCRIPTION("Seiko 43WVF1G panel driver"); |
---|
371 | 344 | MODULE_LICENSE("GPL v2"); |
---|