| .. | .. |
|---|
| 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"); |
|---|