linux/drivers/gpu/drm/bridge/parade-ps8640.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2016 MediaTek Inc.
   4 */
   5
   6#include <linux/delay.h>
   7#include <linux/err.h>
   8#include <linux/gpio/consumer.h>
   9#include <linux/i2c.h>
  10#include <linux/module.h>
  11#include <linux/of_graph.h>
  12#include <linux/regulator/consumer.h>
  13
  14#include <drm/drm_bridge.h>
  15#include <drm/drm_mipi_dsi.h>
  16#include <drm/drm_of.h>
  17#include <drm/drm_panel.h>
  18#include <drm/drm_print.h>
  19
  20#define PAGE2_GPIO_H            0xa7
  21#define PS_GPIO9                BIT(1)
  22#define PAGE2_I2C_BYPASS        0xea
  23#define I2C_BYPASS_EN           0xd0
  24#define PAGE2_MCS_EN            0xf3
  25#define MCS_EN                  BIT(0)
  26#define PAGE3_SET_ADD           0xfe
  27#define VDO_CTL_ADD             0x13
  28#define VDO_DIS                 0x18
  29#define VDO_EN                  0x1c
  30#define DP_NUM_LANES            4
  31
  32/*
  33 * PS8640 uses multiple addresses:
  34 * page[0]: for DP control
  35 * page[1]: for VIDEO Bridge
  36 * page[2]: for control top
  37 * page[3]: for DSI Link Control1
  38 * page[4]: for MIPI Phy
  39 * page[5]: for VPLL
  40 * page[6]: for DSI Link Control2
  41 * page[7]: for SPI ROM mapping
  42 */
  43enum page_addr_offset {
  44        PAGE0_DP_CNTL = 0,
  45        PAGE1_VDO_BDG,
  46        PAGE2_TOP_CNTL,
  47        PAGE3_DSI_CNTL1,
  48        PAGE4_MIPI_PHY,
  49        PAGE5_VPLL,
  50        PAGE6_DSI_CNTL2,
  51        PAGE7_SPI_CNTL,
  52        MAX_DEVS
  53};
  54
  55enum ps8640_vdo_control {
  56        DISABLE = VDO_DIS,
  57        ENABLE = VDO_EN,
  58};
  59
  60struct ps8640 {
  61        struct drm_bridge bridge;
  62        struct drm_bridge *panel_bridge;
  63        struct mipi_dsi_device *dsi;
  64        struct i2c_client *page[MAX_DEVS];
  65        struct regulator_bulk_data supplies[2];
  66        struct gpio_desc *gpio_reset;
  67        struct gpio_desc *gpio_powerdown;
  68        bool powered;
  69};
  70
  71static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e)
  72{
  73        return container_of(e, struct ps8640, bridge);
  74}
  75
  76static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge,
  77                                     const enum ps8640_vdo_control ctrl)
  78{
  79        struct i2c_client *client = ps_bridge->page[PAGE3_DSI_CNTL1];
  80        u8 vdo_ctrl_buf[] = { VDO_CTL_ADD, ctrl };
  81        int ret;
  82
  83        ret = i2c_smbus_write_i2c_block_data(client, PAGE3_SET_ADD,
  84                                             sizeof(vdo_ctrl_buf),
  85                                             vdo_ctrl_buf);
  86        if (ret < 0) {
  87                DRM_ERROR("failed to %sable VDO: %d\n",
  88                          ctrl == ENABLE ? "en" : "dis", ret);
  89                return ret;
  90        }
  91
  92        return 0;
  93}
  94
  95static void ps8640_bridge_poweron(struct ps8640 *ps_bridge)
  96{
  97        struct i2c_client *client = ps_bridge->page[PAGE2_TOP_CNTL];
  98        unsigned long timeout;
  99        int ret, status;
 100
 101        if (ps_bridge->powered)
 102                return;
 103
 104        ret = regulator_bulk_enable(ARRAY_SIZE(ps_bridge->supplies),
 105                                    ps_bridge->supplies);
 106        if (ret < 0) {
 107                DRM_ERROR("cannot enable regulators %d\n", ret);
 108                return;
 109        }
 110
 111        gpiod_set_value(ps_bridge->gpio_powerdown, 0);
 112        gpiod_set_value(ps_bridge->gpio_reset, 1);
 113        usleep_range(2000, 2500);
 114        gpiod_set_value(ps_bridge->gpio_reset, 0);
 115
 116        /*
 117         * Wait for the ps8640 embedded MCU to be ready
 118         * First wait 200ms and then check the MCU ready flag every 20ms
 119         */
 120        msleep(200);
 121
 122        timeout = jiffies + msecs_to_jiffies(200) + 1;
 123
 124        while (time_is_after_jiffies(timeout)) {
 125                status = i2c_smbus_read_byte_data(client, PAGE2_GPIO_H);
 126                if (status < 0) {
 127                        DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", status);
 128                        goto err_regulators_disable;
 129                }
 130                if ((status & PS_GPIO9) == PS_GPIO9)
 131                        break;
 132
 133                msleep(20);
 134        }
 135
 136        msleep(50);
 137
 138        /*
 139         * The Manufacturer Command Set (MCS) is a device dependent interface
 140         * intended for factory programming of the display module default
 141         * parameters. Once the display module is configured, the MCS shall be
 142         * disabled by the manufacturer. Once disabled, all MCS commands are
 143         * ignored by the display interface.
 144         */
 145        status = i2c_smbus_read_byte_data(client, PAGE2_MCS_EN);
 146        if (status < 0) {
 147                DRM_ERROR("failed read PAGE2_MCS_EN: %d\n", status);
 148                goto err_regulators_disable;
 149        }
 150
 151        ret = i2c_smbus_write_byte_data(client, PAGE2_MCS_EN,
 152                                        status & ~MCS_EN);
 153        if (ret < 0) {
 154                DRM_ERROR("failed write PAGE2_MCS_EN: %d\n", ret);
 155                goto err_regulators_disable;
 156        }
 157
 158        /* Switch access edp panel's edid through i2c */
 159        ret = i2c_smbus_write_byte_data(client, PAGE2_I2C_BYPASS,
 160                                        I2C_BYPASS_EN);
 161        if (ret < 0) {
 162                DRM_ERROR("failed write PAGE2_I2C_BYPASS: %d\n", ret);
 163                goto err_regulators_disable;
 164        }
 165
 166        ps_bridge->powered = true;
 167
 168        return;
 169
 170err_regulators_disable:
 171        regulator_bulk_disable(ARRAY_SIZE(ps_bridge->supplies),
 172                               ps_bridge->supplies);
 173}
 174
 175static void ps8640_bridge_poweroff(struct ps8640 *ps_bridge)
 176{
 177        int ret;
 178
 179        if (!ps_bridge->powered)
 180                return;
 181
 182        gpiod_set_value(ps_bridge->gpio_reset, 1);
 183        gpiod_set_value(ps_bridge->gpio_powerdown, 1);
 184        ret = regulator_bulk_disable(ARRAY_SIZE(ps_bridge->supplies),
 185                                     ps_bridge->supplies);
 186        if (ret < 0)
 187                DRM_ERROR("cannot disable regulators %d\n", ret);
 188
 189        ps_bridge->powered = false;
 190}
 191
 192static void ps8640_pre_enable(struct drm_bridge *bridge)
 193{
 194        struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
 195        int ret;
 196
 197        ps8640_bridge_poweron(ps_bridge);
 198
 199        ret = ps8640_bridge_vdo_control(ps_bridge, ENABLE);
 200        if (ret < 0)
 201                ps8640_bridge_poweroff(ps_bridge);
 202}
 203
 204static void ps8640_post_disable(struct drm_bridge *bridge)
 205{
 206        struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
 207
 208        ps8640_bridge_vdo_control(ps_bridge, DISABLE);
 209        ps8640_bridge_poweroff(ps_bridge);
 210}
 211
 212static int ps8640_bridge_attach(struct drm_bridge *bridge,
 213                                enum drm_bridge_attach_flags flags)
 214{
 215        struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
 216        struct device *dev = &ps_bridge->page[0]->dev;
 217        struct device_node *in_ep, *dsi_node;
 218        struct mipi_dsi_device *dsi;
 219        struct mipi_dsi_host *host;
 220        int ret;
 221        const struct mipi_dsi_device_info info = { .type = "ps8640",
 222                                                   .channel = 0,
 223                                                   .node = NULL,
 224                                                 };
 225
 226        if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
 227                return -EINVAL;
 228
 229        /* port@0 is ps8640 dsi input port */
 230        in_ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1);
 231        if (!in_ep)
 232                return -ENODEV;
 233
 234        dsi_node = of_graph_get_remote_port_parent(in_ep);
 235        of_node_put(in_ep);
 236        if (!dsi_node)
 237                return -ENODEV;
 238
 239        host = of_find_mipi_dsi_host_by_node(dsi_node);
 240        of_node_put(dsi_node);
 241        if (!host)
 242                return -ENODEV;
 243
 244        dsi = mipi_dsi_device_register_full(host, &info);
 245        if (IS_ERR(dsi)) {
 246                dev_err(dev, "failed to create dsi device\n");
 247                ret = PTR_ERR(dsi);
 248                return ret;
 249        }
 250
 251        ps_bridge->dsi = dsi;
 252
 253        dsi->host = host;
 254        dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
 255                          MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
 256        dsi->format = MIPI_DSI_FMT_RGB888;
 257        dsi->lanes = DP_NUM_LANES;
 258        ret = mipi_dsi_attach(dsi);
 259        if (ret)
 260                goto err_dsi_attach;
 261
 262        /* Attach the panel-bridge to the dsi bridge */
 263        return drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge,
 264                                 &ps_bridge->bridge, flags);
 265
 266err_dsi_attach:
 267        mipi_dsi_device_unregister(dsi);
 268        return ret;
 269}
 270
 271static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge,
 272                                           struct drm_connector *connector)
 273{
 274        struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
 275        bool poweroff = !ps_bridge->powered;
 276        struct edid *edid;
 277
 278        /*
 279         * When we end calling get_edid() triggered by an ioctl, i.e
 280         *
 281         *   drm_mode_getconnector (ioctl)
 282         *     -> drm_helper_probe_single_connector_modes
 283         *        -> drm_bridge_connector_get_modes
 284         *           -> ps8640_bridge_get_edid
 285         *
 286         * We need to make sure that what we need is enabled before reading
 287         * EDID, for this chip, we need to do a full poweron, otherwise it will
 288         * fail.
 289         */
 290        drm_bridge_chain_pre_enable(bridge);
 291
 292        edid = drm_get_edid(connector,
 293                            ps_bridge->page[PAGE0_DP_CNTL]->adapter);
 294
 295        /*
 296         * If we call the get_edid() function without having enabled the chip
 297         * before, return the chip to its original power state.
 298         */
 299        if (poweroff)
 300                drm_bridge_chain_post_disable(bridge);
 301
 302        return edid;
 303}
 304
 305static const struct drm_bridge_funcs ps8640_bridge_funcs = {
 306        .attach = ps8640_bridge_attach,
 307        .get_edid = ps8640_bridge_get_edid,
 308        .post_disable = ps8640_post_disable,
 309        .pre_enable = ps8640_pre_enable,
 310};
 311
 312static int ps8640_probe(struct i2c_client *client)
 313{
 314        struct device *dev = &client->dev;
 315        struct device_node *np = dev->of_node;
 316        struct ps8640 *ps_bridge;
 317        struct drm_panel *panel;
 318        int ret;
 319        u32 i;
 320
 321        ps_bridge = devm_kzalloc(dev, sizeof(*ps_bridge), GFP_KERNEL);
 322        if (!ps_bridge)
 323                return -ENOMEM;
 324
 325        /* port@1 is ps8640 output port */
 326        ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
 327        if (ret < 0)
 328                return ret;
 329        if (!panel)
 330                return -ENODEV;
 331
 332        ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel);
 333        if (IS_ERR(ps_bridge->panel_bridge))
 334                return PTR_ERR(ps_bridge->panel_bridge);
 335
 336        ps_bridge->supplies[0].supply = "vdd33";
 337        ps_bridge->supplies[1].supply = "vdd12";
 338        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies),
 339                                      ps_bridge->supplies);
 340        if (ret)
 341                return ret;
 342
 343        ps_bridge->gpio_powerdown = devm_gpiod_get(&client->dev, "powerdown",
 344                                                   GPIOD_OUT_HIGH);
 345        if (IS_ERR(ps_bridge->gpio_powerdown))
 346                return PTR_ERR(ps_bridge->gpio_powerdown);
 347
 348        /*
 349         * Assert the reset to avoid the bridge being initialized prematurely
 350         */
 351        ps_bridge->gpio_reset = devm_gpiod_get(&client->dev, "reset",
 352                                               GPIOD_OUT_HIGH);
 353        if (IS_ERR(ps_bridge->gpio_reset))
 354                return PTR_ERR(ps_bridge->gpio_reset);
 355
 356        ps_bridge->bridge.funcs = &ps8640_bridge_funcs;
 357        ps_bridge->bridge.of_node = dev->of_node;
 358        ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID;
 359        ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP;
 360
 361        ps_bridge->page[PAGE0_DP_CNTL] = client;
 362
 363        for (i = 1; i < ARRAY_SIZE(ps_bridge->page); i++) {
 364                ps_bridge->page[i] = devm_i2c_new_dummy_device(&client->dev,
 365                                                             client->adapter,
 366                                                             client->addr + i);
 367                if (IS_ERR(ps_bridge->page[i])) {
 368                        dev_err(dev, "failed i2c dummy device, address %02x\n",
 369                                client->addr + i);
 370                        return PTR_ERR(ps_bridge->page[i]);
 371                }
 372        }
 373
 374        i2c_set_clientdata(client, ps_bridge);
 375
 376        drm_bridge_add(&ps_bridge->bridge);
 377
 378        return 0;
 379}
 380
 381static int ps8640_remove(struct i2c_client *client)
 382{
 383        struct ps8640 *ps_bridge = i2c_get_clientdata(client);
 384
 385        drm_bridge_remove(&ps_bridge->bridge);
 386
 387        return 0;
 388}
 389
 390static const struct of_device_id ps8640_match[] = {
 391        { .compatible = "parade,ps8640" },
 392        { }
 393};
 394MODULE_DEVICE_TABLE(of, ps8640_match);
 395
 396static struct i2c_driver ps8640_driver = {
 397        .probe_new = ps8640_probe,
 398        .remove = ps8640_remove,
 399        .driver = {
 400                .name = "ps8640",
 401                .of_match_table = ps8640_match,
 402        },
 403};
 404module_i2c_driver(ps8640_driver);
 405
 406MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>");
 407MODULE_AUTHOR("CK Hu <ck.hu@mediatek.com>");
 408MODULE_AUTHOR("Enric Balletbo i Serra <enric.balletbo@collabora.com>");
 409MODULE_DESCRIPTION("PARADE ps8640 DSI-eDP converter driver");
 410MODULE_LICENSE("GPL v2");
 411