Skip to content

Commit

Permalink
drm/bridge: Add serdes/touch shutdown function
Browse files Browse the repository at this point in the history
1. Add serdes shutdown fucntion
2. Add ef1e shutdown function
3. Remove workqueue in serdes
4. Change 983/984 400k i2c speed
5. Retry i2c write if write fail

Test-done:
    Android s3/s5 tested with panel EF1E-A1

Tracked-On: OAM-121472
Signed-off-by: Jia, Lin A <[email protected]>
  • Loading branch information
ljia5 committed Jul 3, 2024
1 parent 813aefb commit 8b3db67
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 51 deletions.
125 changes: 75 additions & 50 deletions drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand All @@ -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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -347,6 +355,9 @@ void fpd_dp_ser_reset(struct i2c_client *client)
*/
void fpd_dp_ser_set_up_variables(struct i2c_client *client)
{
/* 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);
Expand Down Expand Up @@ -465,6 +476,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;
}
Expand Down Expand Up @@ -520,7 +534,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);
Expand Down Expand Up @@ -656,7 +669,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);
Expand Down Expand Up @@ -689,7 +701,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;
}
Expand Down Expand Up @@ -720,9 +732,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);

Expand Down Expand Up @@ -961,8 +974,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));
}

/**
Expand Down Expand Up @@ -1698,7 +1709,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);
}
Expand Down Expand Up @@ -1897,11 +1907,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__);
Expand Down Expand Up @@ -2136,12 +2141,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;
Expand Down Expand Up @@ -2185,7 +2187,11 @@ 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]);
else
return false;


return true;
}
Expand Down Expand Up @@ -2234,25 +2240,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);
Expand All @@ -2267,13 +2254,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]);
Expand All @@ -2289,7 +2274,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++) {
Expand All @@ -2313,6 +2297,46 @@ 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();

fpd_dp_ser_debug("[-%s-%s-%d-]\n", __FILE__, __func__, __LINE__);
}

/* 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)
Expand Down Expand Up @@ -2439,6 +2463,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,
Expand Down
23 changes: 22 additions & 1 deletion drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,8 @@ static int ef1e_tp_remove(struct platform_device *dev)
} else {
tp_gpio_irq_destroy(priv);
}
destroy_workqueue(priv->init_wq);
if (priv->init_wq)
destroy_workqueue(priv->init_wq);

tp_input_dev_destroy(priv);
i2c_put_adapter(priv->i2c_adap);
Expand All @@ -641,6 +642,25 @@ 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);
}
if (priv->init_wq)
destroy_workqueue(priv->init_wq);

pr_debug("ef1e_tp driver shutdown\n");

return;
}

static int ef1e_tp_resume(struct device *dev)
{
Expand Down Expand Up @@ -672,6 +692,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,
Expand Down

0 comments on commit 8b3db67

Please sign in to comment.