diff --git a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c index d3137131ddc7..7c97bc971b18 100644 --- a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c +++ b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c @@ -171,7 +171,8 @@ char fpd_dp_ser_read_reg(struct i2c_client *client, u8 reg_addr, u8 *val) int fpd_dp_ser_write_reg(struct i2c_client *client, unsigned int reg_addr, u8 val) { - int ret = 0; + int ret = -1; + int count = 0; struct i2c_msg msg; u8 buf[2]; @@ -183,15 +184,23 @@ int fpd_dp_ser_write_reg(struct i2c_client *client, unsigned int reg_addr, u8 va msg.buf = &buf[0]; msg.len = 2; - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret < 0) { - fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-], fail client->addr=0x%02x, reg_addr=0x%02x, val=0x%02x\n", - __FILE__, __func__, __LINE__, client->addr, reg_addr, val); + while ((ret != 0) && (count < 10)) { + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + count++; + fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-], fail client->addr=0x%02x, reg_addr=0x%02x, val=0x%02x\n", + __FILE__, __func__, __LINE__, client->addr, reg_addr, val); + } else + ret = 0; + } + + if (ret == 0) { + fpd_dp_ser_debug("[FPD_DP] WIB 0x%02x: 0x%02x 0x%02x OK\n", + client->addr, reg_addr, val); + return 0; + } else { return -ENXIO; } - fpd_dp_ser_debug("[FPD_DP] WIB 0x%02x: 0x%02x 0x%02x OK\n", - client->addr, reg_addr, val); - return 0; } bool @@ -237,7 +246,6 @@ fpd_dp_mcu_motor_mode(struct i2c_client *client, unsigned int reg_addr, u32 val) int fpd_dp_mcu_read_reg(struct i2c_client *client, unsigned int reg_addr, u8 len, u8 *data) { struct i2c_msg msg[2]; - int i = 0; u8 buf[1]; int ret = 0; @@ -347,6 +355,11 @@ void fpd_dp_ser_reset(struct i2c_client *client) */ void fpd_dp_ser_set_up_variables(struct i2c_client *client) { + int ret = -1; + + /* i2c 400k */ + fpd_dp_ser_write_reg(client, 0x2b, 0x0a); + fpd_dp_ser_write_reg(client, 0x2c, 0x0b); fpd_dp_ser_write_reg(client, 0x70, FPD_DP_SER_RX_ADD_A); fpd_dp_ser_write_reg(client, 0x78, FPD_DP_SER_RX_ADD_A); fpd_dp_ser_write_reg(client, 0x88, 0x0); @@ -465,6 +478,9 @@ int fpd_dp_ser_program_fpd_4_mode(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x5b, 0x23); /* Force FPD4_TX single port 0 mode */ fpd_dp_ser_write_reg(client, 0x05, 0x2c); + /* Soft Reset SER */ + fpd_dp_ser_write_reg(client, 0x01, 0x01); + usleep_range(20000, 22000); return 0; } @@ -520,7 +536,6 @@ int fpd_dp_set_fpd_4_pll(struct i2c_client *client) /* Unset HALFRATE_MODE Override */ fpd_dp_ser_write_reg(client, 0x2, 0x50); - /* Zero out fractional PLL for port 0 */ fpd_dp_ser_write_reg(client, 0x40, 0x08); fpd_dp_ser_write_reg(client, 0x41, 0x04); @@ -656,7 +671,6 @@ int fpd_dp_ser_configue_enable_plls(struct i2c_client *client) /* Enable PLL0 */ fpd_dp_ser_write_reg(client, 0x42,0x00); - /* soft reset Ser */ fpd_dp_ser_write_reg(client, 0x01,0x01); usleep_range(20000, 22000); @@ -689,7 +703,7 @@ int fpd_dp_ser_configue_enable_983_plls(struct i2c_client *client) /* soft reset Ser */ fpd_dp_ser_write_reg(client, 0x01,0x01); - usleep_range(20000, 22000); + msleep(30); return 0; } @@ -720,9 +734,10 @@ int fpd_dp_deser_soft_reset(struct i2c_client *client) int fpd_dp_deser_soft_983_reset(struct i2c_client *client) { - u8 des_read = 0; + /* i2c 400k */ + fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x2b, 0x0a); + fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x2c, 0x0b); - msleep(30); fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); msleep(30); @@ -961,8 +976,6 @@ static void fpd_poll_training_lock(struct work_struct *work) fpd_dp_ser_debug("[FPD_DP] ser training STS %d\n", VP0sts); return; } - - queue_delayed_work(fpd_dp_priv->wq, &fpd_dp_priv->delay_work, msecs_to_jiffies(100)); } /** @@ -1698,7 +1711,6 @@ int fpd_dp_deser_984_override_efuse(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x42, 0x26); /* Soft Reset DES */ /* Override DES 0 eFuse */ - msleep(30); fpd_dp_ser_write_reg(client, 0x1, 0x1); msleep(30); } @@ -1897,11 +1909,6 @@ static bool fpd_dp_deser_984_enable_output(struct i2c_client *client) ret |= fpd_dp_ser_write_reg(client, 0x4e, 0x0); /* Enable INTB_IN */ ret |= fpd_dp_ser_write_reg(client, 0x44, 0x81); - /* i2c speed 400k */ - ret |= fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[0], 0x2b, 0x0a); - ret |= fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[0], 0x2c, 0x0b); - ret |= fpd_dp_ser_write_reg(client, 0x2b, 0x0a); - ret |= fpd_dp_ser_write_reg(client, 0x2c, 0x0b); if (ret) { fpd_dp_ser_err("%s: failed to enable output\n", __func__); @@ -2138,12 +2145,9 @@ static bool fpd_dp_ser_read_display_startup_status(struct i2c_client *client) static bool wait_display_startup_done(struct i2c_client *client) { - int ret; int n = 0; - int i = 0; - bool status; - while (++n < 100) + while (++n < 3) { if (fpd_dp_ser_read_display_startup_status(client)) { return true; @@ -2187,7 +2191,8 @@ bool fpd_dp_ser_init(void) fpd_dp_ser_unlock_global(); - queue_work(fpd_dp_priv->motor_setup_wq, &fpd_dp_priv->motor_setup_work); + if (wait_display_startup_done(fpd_dp_priv->priv_dp_client[2])) + fpd_dp_ser_motor_open(fpd_dp_priv->priv_dp_client[2]); return true; } @@ -2236,25 +2241,6 @@ static int fpd_dp_ser_probe(struct platform_device *pdev) i2c_set_clientdata(priv->priv_dp_client[i], priv); } fpd_dp_priv = priv; - - INIT_DELAYED_WORK(&fpd_dp_priv->delay_work, fpd_poll_training_lock); - fpd_dp_priv->wq = alloc_workqueue("fpd_poll_training_lock", - WQ_HIGHPRI, 0); - if (unlikely(!fpd_dp_priv->wq)) { - fpd_dp_ser_debug("[FPD_DP] Failed to allocate workqueue\n"); - ret = -ENOMEM; - goto err_i2c; - } - - INIT_WORK(&fpd_dp_priv->motor_setup_work, fpd_dp_motor_setup_work); - fpd_dp_priv->motor_setup_wq = alloc_workqueue("fpd_dp_motor_setup", - WQ_HIGHPRI, 0); - if (IS_ERR_OR_NULL(fpd_dp_priv->motor_setup_wq)) { - dev_err(&pdev->dev, "failed to create motor setup wq\n"); - ret = -ENOMEM; - goto err_motor_setup_wq; - } - fpd_dp_priv->count = 0; gpio_cfg = (unsigned char *)ioremap(PAD_CFG_DW0_GPPC_A_16, 0x1); @@ -2269,13 +2255,11 @@ static int fpd_dp_ser_probe(struct platform_device *pdev) if (!fpd_dp_ser_init()) { ret = -ENXIO; - goto err_motor_setup_wq; + goto err_i2c; } return 0; -err_motor_setup_wq: - destroy_workqueue(fpd_dp_priv->wq); err_i2c: for (i = 0; i < ARRAY_SIZE(fpd_dp_i2c_board_info); ++i) i2c_unregister_device(priv->priv_dp_client[i]); @@ -2291,7 +2275,6 @@ static int fpd_dp_ser_remove(struct platform_device *pdev) { (struct fpd_dp_ser_priv*)platform_get_drvdata(pdev); fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-]\n", __FILE__, __func__, __LINE__); if (priv != NULL) { - cancel_delayed_work_sync(&priv->delay_work); fpd_dp_ser_lock_global(); fpd_dp_ser_set_ready(false); for (i = 0; i < ARRAY_SIZE(fpd_dp_i2c_board_info); i++) { @@ -2315,6 +2298,47 @@ static int fpd_dp_ser_remove(struct platform_device *pdev) { return 0; } +static void fpd_dp_ser_shutdown(struct platform_device *pdev) { + unsigned char __iomem *gpio_cfg; + unsigned char data; + + fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-]\n", __FILE__, __func__, __LINE__); + + struct fpd_dp_ser_priv *priv = + (struct fpd_dp_ser_priv*)platform_get_drvdata(pdev); + + if (priv != NULL) { + fpd_dp_ser_lock_global(); + fpd_dp_ser_set_ready(false); + /* first des reset, and then ser reset */ + fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); + /* after reset, wait 20ms to avoid ser/des read/write fail */ + usleep_range(20000, 22000); + + fpd_dp_ser_reset(fpd_dp_priv->priv_dp_client[0]); + fpd_dp_ser_unlock_global(); + devm_kfree(&pdev->dev, priv); + fpd_dp_ser_debug("[-%s-%s-%d-]\n", __FILE__, __func__, __LINE__); + } + i2c_put_adapter(i2c_adap_mcu); + + /* Map GPIO IO address to virtual address */ + gpio_cfg = (unsigned char *)ioremap(PAD_CFG_DW0_GPPC_A_16, 0x1); + if (!gpio_cfg) { + fpd_dp_ser_debug("Ioremap fail in fpd_dp_ser_shutdown\n"); + return; + } + + data = ioread8(gpio_cfg); + + /* Set Serdes DP3 last bit of GPIO IO address to 1 for pulling up DP3 */ + data = data & 0xFE; + iowrite8(data, gpio_cfg); + iounmap(gpio_cfg); + + return; +} + #ifdef CONFIG_PM static int fpd_dp_ser_suspend(struct device *dev) @@ -2441,6 +2465,7 @@ static const struct i2c_device_id fpd_dp_ser_i2c_id_table[] = { static struct platform_driver fpd_dp_ser_driver = { .probe = fpd_dp_ser_probe, .remove = fpd_dp_ser_remove, + .shutdown = fpd_dp_ser_shutdown, .driver = { .name = DEV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c b/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c index 8dba49a81da1..adc4a87f806e 100644 --- a/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c +++ b/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c @@ -641,6 +641,29 @@ static int ef1e_tp_remove(struct platform_device *dev) return 0; } +static void ef1e_dp_shutdown(struct platform_device *pdev) +{ + struct tp_priv *priv = &global_tp; + int ret; + + WRITE_ONCE(priv->initialized, 0); + pr_debug("%s: set initialized to false\n", __func__); + + if (priv->polling) { + if (priv->polling_kthread) + kthread_stop(priv->polling_kthread); + } else { + tp_gpio_irq_destroy(priv); + } + destroy_workqueue(priv->init_wq); + + tp_input_dev_destroy(priv); + i2c_put_adapter(priv->i2c_adap); + + pr_debug("ef1e_tp driver shutdown removed\n"); + + return; +} static int ef1e_tp_resume(struct device *dev) { @@ -672,6 +695,7 @@ static const struct dev_pm_ops ef1e_tp_pm_ops = { static struct platform_driver ef1e_tp_driver = { .probe = ef1e_tp_probe, .remove = ef1e_tp_remove, + .shutdown = ef1e_dp_shutdown, .driver = { .name = EF1E_TP_PLATFORM_DEV_NAME, .owner = THIS_MODULE,