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