linux/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2017 NXP Semiconductors.
   4 * Author: Marco Franchi <marco.franchi@nxp.com>
   5 *
   6 * Based on Panel Simple driver by Thierry Reding <treding@nvidia.com>
   7 */
   8
   9#include <linux/delay.h>
  10#include <linux/module.h>
  11#include <linux/of.h>
  12#include <linux/platform_device.h>
  13#include <linux/regulator/consumer.h>
  14
  15#include <video/display_timing.h>
  16#include <video/videomode.h>
  17
  18#include <drm/drm_crtc.h>
  19#include <drm/drm_device.h>
  20#include <drm/drm_panel.h>
  21
  22struct seiko_panel_desc {
  23        const struct drm_display_mode *modes;
  24        unsigned int num_modes;
  25        const struct display_timing *timings;
  26        unsigned int num_timings;
  27
  28        unsigned int bpc;
  29
  30        /**
  31         * @width: width (in millimeters) of the panel's active display area
  32         * @height: height (in millimeters) of the panel's active display area
  33         */
  34        struct {
  35                unsigned int width;
  36                unsigned int height;
  37        } size;
  38
  39        u32 bus_format;
  40        u32 bus_flags;
  41};
  42
  43struct seiko_panel {
  44        struct drm_panel base;
  45        bool prepared;
  46        bool enabled;
  47        const struct seiko_panel_desc *desc;
  48        struct regulator *dvdd;
  49        struct regulator *avdd;
  50};
  51
  52static inline struct seiko_panel *to_seiko_panel(struct drm_panel *panel)
  53{
  54        return container_of(panel, struct seiko_panel, base);
  55}
  56
  57static int seiko_panel_get_fixed_modes(struct seiko_panel *panel,
  58                                       struct drm_connector *connector)
  59{
  60        struct drm_display_mode *mode;
  61        unsigned int i, num = 0;
  62
  63        if (!panel->desc)
  64                return 0;
  65
  66        for (i = 0; i < panel->desc->num_timings; i++) {
  67                const struct display_timing *dt = &panel->desc->timings[i];
  68                struct videomode vm;
  69
  70                videomode_from_timing(dt, &vm);
  71                mode = drm_mode_create(connector->dev);
  72                if (!mode) {
  73                        dev_err(panel->base.dev, "failed to add mode %ux%u\n",
  74                                dt->hactive.typ, dt->vactive.typ);
  75                        continue;
  76                }
  77
  78                drm_display_mode_from_videomode(&vm, mode);
  79
  80                mode->type |= DRM_MODE_TYPE_DRIVER;
  81
  82                if (panel->desc->num_timings == 1)
  83                        mode->type |= DRM_MODE_TYPE_PREFERRED;
  84
  85                drm_mode_probed_add(connector, mode);
  86                num++;
  87        }
  88
  89        for (i = 0; i < panel->desc->num_modes; i++) {
  90                const struct drm_display_mode *m = &panel->desc->modes[i];
  91
  92                mode = drm_mode_duplicate(connector->dev, m);
  93                if (!mode) {
  94                        dev_err(panel->base.dev, "failed to add mode %ux%u@%u\n",
  95                                m->hdisplay, m->vdisplay,
  96                                drm_mode_vrefresh(m));
  97                        continue;
  98                }
  99
 100                mode->type |= DRM_MODE_TYPE_DRIVER;
 101
 102                if (panel->desc->num_modes == 1)
 103                        mode->type |= DRM_MODE_TYPE_PREFERRED;
 104
 105                drm_mode_set_name(mode);
 106
 107                drm_mode_probed_add(connector, mode);
 108                num++;
 109        }
 110
 111        connector->display_info.bpc = panel->desc->bpc;
 112        connector->display_info.width_mm = panel->desc->size.width;
 113        connector->display_info.height_mm = panel->desc->size.height;
 114        if (panel->desc->bus_format)
 115                drm_display_info_set_bus_formats(&connector->display_info,
 116                                                 &panel->desc->bus_format, 1);
 117        connector->display_info.bus_flags = panel->desc->bus_flags;
 118
 119        return num;
 120}
 121
 122static int seiko_panel_disable(struct drm_panel *panel)
 123{
 124        struct seiko_panel *p = to_seiko_panel(panel);
 125
 126        if (!p->enabled)
 127                return 0;
 128
 129        p->enabled = false;
 130
 131        return 0;
 132}
 133
 134static int seiko_panel_unprepare(struct drm_panel *panel)
 135{
 136        struct seiko_panel *p = to_seiko_panel(panel);
 137
 138        if (!p->prepared)
 139                return 0;
 140
 141        regulator_disable(p->avdd);
 142
 143        /* Add a 100ms delay as per the panel datasheet */
 144        msleep(100);
 145
 146        regulator_disable(p->dvdd);
 147
 148        p->prepared = false;
 149
 150        return 0;
 151}
 152
 153static int seiko_panel_prepare(struct drm_panel *panel)
 154{
 155        struct seiko_panel *p = to_seiko_panel(panel);
 156        int err;
 157
 158        if (p->prepared)
 159                return 0;
 160
 161        err = regulator_enable(p->dvdd);
 162        if (err < 0) {
 163                dev_err(panel->dev, "failed to enable dvdd: %d\n", err);
 164                return err;
 165        }
 166
 167        /* Add a 100ms delay as per the panel datasheet */
 168        msleep(100);
 169
 170        err = regulator_enable(p->avdd);
 171        if (err < 0) {
 172                dev_err(panel->dev, "failed to enable avdd: %d\n", err);
 173                goto disable_dvdd;
 174        }
 175
 176        p->prepared = true;
 177
 178        return 0;
 179
 180disable_dvdd:
 181        regulator_disable(p->dvdd);
 182        return err;
 183}
 184
 185static int seiko_panel_enable(struct drm_panel *panel)
 186{
 187        struct seiko_panel *p = to_seiko_panel(panel);
 188
 189        if (p->enabled)
 190                return 0;
 191
 192        p->enabled = true;
 193
 194        return 0;
 195}
 196
 197static int seiko_panel_get_modes(struct drm_panel *panel,
 198                                 struct drm_connector *connector)
 199{
 200        struct seiko_panel *p = to_seiko_panel(panel);
 201
 202        /* add hard-coded panel modes */
 203        return seiko_panel_get_fixed_modes(p, connector);
 204}
 205
 206static int seiko_panel_get_timings(struct drm_panel *panel,
 207                                    unsigned int num_timings,
 208                                    struct display_timing *timings)
 209{
 210        struct seiko_panel *p = to_seiko_panel(panel);
 211        unsigned int i;
 212
 213        if (p->desc->num_timings < num_timings)
 214                num_timings = p->desc->num_timings;
 215
 216        if (timings)
 217                for (i = 0; i < num_timings; i++)
 218                        timings[i] = p->desc->timings[i];
 219
 220        return p->desc->num_timings;
 221}
 222
 223static const struct drm_panel_funcs seiko_panel_funcs = {
 224        .disable = seiko_panel_disable,
 225        .unprepare = seiko_panel_unprepare,
 226        .prepare = seiko_panel_prepare,
 227        .enable = seiko_panel_enable,
 228        .get_modes = seiko_panel_get_modes,
 229        .get_timings = seiko_panel_get_timings,
 230};
 231
 232static int seiko_panel_probe(struct device *dev,
 233                                        const struct seiko_panel_desc *desc)
 234{
 235        struct seiko_panel *panel;
 236        int err;
 237
 238        panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
 239        if (!panel)
 240                return -ENOMEM;
 241
 242        panel->enabled = false;
 243        panel->prepared = false;
 244        panel->desc = desc;
 245
 246        panel->dvdd = devm_regulator_get(dev, "dvdd");
 247        if (IS_ERR(panel->dvdd))
 248                return PTR_ERR(panel->dvdd);
 249
 250        panel->avdd = devm_regulator_get(dev, "avdd");
 251        if (IS_ERR(panel->avdd))
 252                return PTR_ERR(panel->avdd);
 253
 254        drm_panel_init(&panel->base, dev, &seiko_panel_funcs,
 255                       DRM_MODE_CONNECTOR_DPI);
 256
 257        err = drm_panel_of_backlight(&panel->base);
 258        if (err)
 259                return err;
 260
 261        drm_panel_add(&panel->base);
 262
 263        dev_set_drvdata(dev, panel);
 264
 265        return 0;
 266}
 267
 268static int seiko_panel_remove(struct platform_device *pdev)
 269{
 270        struct seiko_panel *panel = platform_get_drvdata(pdev);
 271
 272        drm_panel_remove(&panel->base);
 273        drm_panel_disable(&panel->base);
 274
 275        return 0;
 276}
 277
 278static void seiko_panel_shutdown(struct platform_device *pdev)
 279{
 280        struct seiko_panel *panel = platform_get_drvdata(pdev);
 281
 282        drm_panel_disable(&panel->base);
 283}
 284
 285static const struct display_timing seiko_43wvf1g_timing = {
 286        .pixelclock = { 33500000, 33500000, 33500000 },
 287        .hactive = { 800, 800, 800 },
 288        .hfront_porch = {  164, 164, 164 },
 289        .hback_porch = { 89, 89, 89 },
 290        .hsync_len = { 10, 10, 10 },
 291        .vactive = { 480, 480, 480 },
 292        .vfront_porch = { 10, 10, 10 },
 293        .vback_porch = { 23, 23, 23 },
 294        .vsync_len = { 10, 10, 10 },
 295        .flags = DISPLAY_FLAGS_DE_LOW,
 296};
 297
 298static const struct seiko_panel_desc seiko_43wvf1g = {
 299        .timings = &seiko_43wvf1g_timing,
 300        .num_timings = 1,
 301        .bpc = 8,
 302        .size = {
 303                .width = 93,
 304                .height = 57,
 305        },
 306        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
 307        .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
 308};
 309
 310static const struct of_device_id platform_of_match[] = {
 311        {
 312                .compatible = "sii,43wvf1g",
 313                .data = &seiko_43wvf1g,
 314        }, {
 315                /* sentinel */
 316        }
 317};
 318MODULE_DEVICE_TABLE(of, platform_of_match);
 319
 320static int seiko_panel_platform_probe(struct platform_device *pdev)
 321{
 322        const struct of_device_id *id;
 323
 324        id = of_match_node(platform_of_match, pdev->dev.of_node);
 325        if (!id)
 326                return -ENODEV;
 327
 328        return seiko_panel_probe(&pdev->dev, id->data);
 329}
 330
 331static struct platform_driver seiko_panel_platform_driver = {
 332        .driver = {
 333                .name = "seiko_panel",
 334                .of_match_table = platform_of_match,
 335        },
 336        .probe = seiko_panel_platform_probe,
 337        .remove = seiko_panel_remove,
 338        .shutdown = seiko_panel_shutdown,
 339};
 340module_platform_driver(seiko_panel_platform_driver);
 341
 342MODULE_AUTHOR("Marco Franchi <marco.franchi@nxp.com>");
 343MODULE_DESCRIPTION("Seiko 43WVF1G panel driver");
 344MODULE_LICENSE("GPL v2");
 345