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