linux/drivers/gpu/drm/bridge/nxp-ptn3460.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * NXP PTN3460 DP/LVDS bridge driver
   4 *
   5 * Copyright (C) 2013 Google, Inc.
   6 */
   7
   8#include <linux/delay.h>
   9#include <linux/gpio.h>
  10#include <linux/gpio/consumer.h>
  11#include <linux/i2c.h>
  12#include <linux/module.h>
  13#include <linux/of.h>
  14#include <linux/of_gpio.h>
  15#include <drm/drm_atomic_helper.h>
  16#include <drm/drm_crtc.h>
  17#include <drm/drm_edid.h>
  18#include <drm/drm_of.h>
  19#include <drm/drm_panel.h>
  20#include <drm/drm_probe_helper.h>
  21#include <drm/drmP.h>
  22
  23#define PTN3460_EDID_ADDR                       0x0
  24#define PTN3460_EDID_EMULATION_ADDR             0x84
  25#define PTN3460_EDID_ENABLE_EMULATION           0
  26#define PTN3460_EDID_EMULATION_SELECTION        1
  27#define PTN3460_EDID_SRAM_LOAD_ADDR             0x85
  28
  29struct ptn3460_bridge {
  30        struct drm_connector connector;
  31        struct i2c_client *client;
  32        struct drm_bridge bridge;
  33        struct edid *edid;
  34        struct drm_panel *panel;
  35        struct gpio_desc *gpio_pd_n;
  36        struct gpio_desc *gpio_rst_n;
  37        u32 edid_emulation;
  38        bool enabled;
  39};
  40
  41static inline struct ptn3460_bridge *
  42                bridge_to_ptn3460(struct drm_bridge *bridge)
  43{
  44        return container_of(bridge, struct ptn3460_bridge, bridge);
  45}
  46
  47static inline struct ptn3460_bridge *
  48                connector_to_ptn3460(struct drm_connector *connector)
  49{
  50        return container_of(connector, struct ptn3460_bridge, connector);
  51}
  52
  53static int ptn3460_read_bytes(struct ptn3460_bridge *ptn_bridge, char addr,
  54                u8 *buf, int len)
  55{
  56        int ret;
  57
  58        ret = i2c_master_send(ptn_bridge->client, &addr, 1);
  59        if (ret <= 0) {
  60                DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
  61                return ret;
  62        }
  63
  64        ret = i2c_master_recv(ptn_bridge->client, buf, len);
  65        if (ret <= 0) {
  66                DRM_ERROR("Failed to recv i2c data, ret=%d\n", ret);
  67                return ret;
  68        }
  69
  70        return 0;
  71}
  72
  73static int ptn3460_write_byte(struct ptn3460_bridge *ptn_bridge, char addr,
  74                char val)
  75{
  76        int ret;
  77        char buf[2];
  78
  79        buf[0] = addr;
  80        buf[1] = val;
  81
  82        ret = i2c_master_send(ptn_bridge->client, buf, ARRAY_SIZE(buf));
  83        if (ret <= 0) {
  84                DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
  85                return ret;
  86        }
  87
  88        return 0;
  89}
  90
  91static int ptn3460_select_edid(struct ptn3460_bridge *ptn_bridge)
  92{
  93        int ret;
  94        char val;
  95
  96        /* Load the selected edid into SRAM (accessed at PTN3460_EDID_ADDR) */
  97        ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_SRAM_LOAD_ADDR,
  98                        ptn_bridge->edid_emulation);
  99        if (ret) {
 100                DRM_ERROR("Failed to transfer EDID to sram, ret=%d\n", ret);
 101                return ret;
 102        }
 103
 104        /* Enable EDID emulation and select the desired EDID */
 105        val = 1 << PTN3460_EDID_ENABLE_EMULATION |
 106                ptn_bridge->edid_emulation << PTN3460_EDID_EMULATION_SELECTION;
 107
 108        ret = ptn3460_write_byte(ptn_bridge, PTN3460_EDID_EMULATION_ADDR, val);
 109        if (ret) {
 110                DRM_ERROR("Failed to write EDID value, ret=%d\n", ret);
 111                return ret;
 112        }
 113
 114        return 0;
 115}
 116
 117static void ptn3460_pre_enable(struct drm_bridge *bridge)
 118{
 119        struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
 120        int ret;
 121
 122        if (ptn_bridge->enabled)
 123                return;
 124
 125        gpiod_set_value(ptn_bridge->gpio_pd_n, 1);
 126
 127        gpiod_set_value(ptn_bridge->gpio_rst_n, 0);
 128        usleep_range(10, 20);
 129        gpiod_set_value(ptn_bridge->gpio_rst_n, 1);
 130
 131        if (drm_panel_prepare(ptn_bridge->panel)) {
 132                DRM_ERROR("failed to prepare panel\n");
 133                return;
 134        }
 135
 136        /*
 137         * There's a bug in the PTN chip where it falsely asserts hotplug before
 138         * it is fully functional. We're forced to wait for the maximum start up
 139         * time specified in the chip's datasheet to make sure we're really up.
 140         */
 141        msleep(90);
 142
 143        ret = ptn3460_select_edid(ptn_bridge);
 144        if (ret)
 145                DRM_ERROR("Select EDID failed ret=%d\n", ret);
 146
 147        ptn_bridge->enabled = true;
 148}
 149
 150static void ptn3460_enable(struct drm_bridge *bridge)
 151{
 152        struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
 153
 154        if (drm_panel_enable(ptn_bridge->panel)) {
 155                DRM_ERROR("failed to enable panel\n");
 156                return;
 157        }
 158}
 159
 160static void ptn3460_disable(struct drm_bridge *bridge)
 161{
 162        struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
 163
 164        if (!ptn_bridge->enabled)
 165                return;
 166
 167        ptn_bridge->enabled = false;
 168
 169        if (drm_panel_disable(ptn_bridge->panel)) {
 170                DRM_ERROR("failed to disable panel\n");
 171                return;
 172        }
 173
 174        gpiod_set_value(ptn_bridge->gpio_rst_n, 1);
 175        gpiod_set_value(ptn_bridge->gpio_pd_n, 0);
 176}
 177
 178static void ptn3460_post_disable(struct drm_bridge *bridge)
 179{
 180        struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
 181
 182        if (drm_panel_unprepare(ptn_bridge->panel)) {
 183                DRM_ERROR("failed to unprepare panel\n");
 184                return;
 185        }
 186}
 187
 188static int ptn3460_get_modes(struct drm_connector *connector)
 189{
 190        struct ptn3460_bridge *ptn_bridge;
 191        u8 *edid;
 192        int ret, num_modes = 0;
 193        bool power_off;
 194
 195        ptn_bridge = connector_to_ptn3460(connector);
 196
 197        if (ptn_bridge->edid)
 198                return drm_add_edid_modes(connector, ptn_bridge->edid);
 199
 200        power_off = !ptn_bridge->enabled;
 201        ptn3460_pre_enable(&ptn_bridge->bridge);
 202
 203        edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
 204        if (!edid) {
 205                DRM_ERROR("Failed to allocate EDID\n");
 206                return 0;
 207        }
 208
 209        ret = ptn3460_read_bytes(ptn_bridge, PTN3460_EDID_ADDR, edid,
 210                        EDID_LENGTH);
 211        if (ret) {
 212                kfree(edid);
 213                goto out;
 214        }
 215
 216        ptn_bridge->edid = (struct edid *)edid;
 217        drm_connector_update_edid_property(connector, ptn_bridge->edid);
 218
 219        num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
 220
 221out:
 222        if (power_off)
 223                ptn3460_disable(&ptn_bridge->bridge);
 224
 225        return num_modes;
 226}
 227
 228static const struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = {
 229        .get_modes = ptn3460_get_modes,
 230};
 231
 232static const struct drm_connector_funcs ptn3460_connector_funcs = {
 233        .fill_modes = drm_helper_probe_single_connector_modes,
 234        .destroy = drm_connector_cleanup,
 235        .reset = drm_atomic_helper_connector_reset,
 236        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 237        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 238};
 239
 240static int ptn3460_bridge_attach(struct drm_bridge *bridge)
 241{
 242        struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge);
 243        int ret;
 244
 245        if (!bridge->encoder) {
 246                DRM_ERROR("Parent encoder object not found");
 247                return -ENODEV;
 248        }
 249
 250        ptn_bridge->connector.polled = DRM_CONNECTOR_POLL_HPD;
 251        ret = drm_connector_init(bridge->dev, &ptn_bridge->connector,
 252                        &ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
 253        if (ret) {
 254                DRM_ERROR("Failed to initialize connector with drm\n");
 255                return ret;
 256        }
 257        drm_connector_helper_add(&ptn_bridge->connector,
 258                                        &ptn3460_connector_helper_funcs);
 259        drm_connector_register(&ptn_bridge->connector);
 260        drm_connector_attach_encoder(&ptn_bridge->connector,
 261                                                        bridge->encoder);
 262
 263        if (ptn_bridge->panel)
 264                drm_panel_attach(ptn_bridge->panel, &ptn_bridge->connector);
 265
 266        drm_helper_hpd_irq_event(ptn_bridge->connector.dev);
 267
 268        return ret;
 269}
 270
 271static const struct drm_bridge_funcs ptn3460_bridge_funcs = {
 272        .pre_enable = ptn3460_pre_enable,
 273        .enable = ptn3460_enable,
 274        .disable = ptn3460_disable,
 275        .post_disable = ptn3460_post_disable,
 276        .attach = ptn3460_bridge_attach,
 277};
 278
 279static int ptn3460_probe(struct i2c_client *client,
 280                                const struct i2c_device_id *id)
 281{
 282        struct device *dev = &client->dev;
 283        struct ptn3460_bridge *ptn_bridge;
 284        int ret;
 285
 286        ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
 287        if (!ptn_bridge) {
 288                return -ENOMEM;
 289        }
 290
 291        ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL);
 292        if (ret)
 293                return ret;
 294
 295        ptn_bridge->client = client;
 296
 297        ptn_bridge->gpio_pd_n = devm_gpiod_get(&client->dev, "powerdown",
 298                                               GPIOD_OUT_HIGH);
 299        if (IS_ERR(ptn_bridge->gpio_pd_n)) {
 300                ret = PTR_ERR(ptn_bridge->gpio_pd_n);
 301                dev_err(dev, "cannot get gpio_pd_n %d\n", ret);
 302                return ret;
 303        }
 304
 305        /*
 306         * Request the reset pin low to avoid the bridge being
 307         * initialized prematurely
 308         */
 309        ptn_bridge->gpio_rst_n = devm_gpiod_get(&client->dev, "reset",
 310                                                GPIOD_OUT_LOW);
 311        if (IS_ERR(ptn_bridge->gpio_rst_n)) {
 312                ret = PTR_ERR(ptn_bridge->gpio_rst_n);
 313                DRM_ERROR("cannot get gpio_rst_n %d\n", ret);
 314                return ret;
 315        }
 316
 317        ret = of_property_read_u32(dev->of_node, "edid-emulation",
 318                        &ptn_bridge->edid_emulation);
 319        if (ret) {
 320                dev_err(dev, "Can't read EDID emulation value\n");
 321                return ret;
 322        }
 323
 324        ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs;
 325        ptn_bridge->bridge.of_node = dev->of_node;
 326        drm_bridge_add(&ptn_bridge->bridge);
 327
 328        i2c_set_clientdata(client, ptn_bridge);
 329
 330        return 0;
 331}
 332
 333static int ptn3460_remove(struct i2c_client *client)
 334{
 335        struct ptn3460_bridge *ptn_bridge = i2c_get_clientdata(client);
 336
 337        drm_bridge_remove(&ptn_bridge->bridge);
 338
 339        return 0;
 340}
 341
 342static const struct i2c_device_id ptn3460_i2c_table[] = {
 343        {"ptn3460", 0},
 344        {},
 345};
 346MODULE_DEVICE_TABLE(i2c, ptn3460_i2c_table);
 347
 348static const struct of_device_id ptn3460_match[] = {
 349        { .compatible = "nxp,ptn3460" },
 350        {},
 351};
 352MODULE_DEVICE_TABLE(of, ptn3460_match);
 353
 354static struct i2c_driver ptn3460_driver = {
 355        .id_table       = ptn3460_i2c_table,
 356        .probe          = ptn3460_probe,
 357        .remove         = ptn3460_remove,
 358        .driver         = {
 359                .name   = "nxp,ptn3460",
 360                .of_match_table = ptn3460_match,
 361        },
 362};
 363module_i2c_driver(ptn3460_driver);
 364
 365MODULE_AUTHOR("Sean Paul <seanpaul@chromium.org>");
 366MODULE_DESCRIPTION("NXP ptn3460 eDP-LVDS converter driver");
 367MODULE_LICENSE("GPL v2");
 368