From 84121ad26469846af2deb8da08cc5d60bf7bd5e0 Mon Sep 17 00:00:00 2001 From: Weifeng Liu Date: Mon, 27 May 2024 07:26:28 +0000 Subject: [PATCH 1/7] touchscreen/ef1e_tp: Remove delay in initialization work Signed-off-by: Weifeng Liu --- drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c b/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c index 7de96ea2f541..a5b650a2b27e 100644 --- a/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c +++ b/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c @@ -303,7 +303,7 @@ int tp_kthread_ack(void *data) __func__, fpd_dp_ser_ready(), READ_ONCE(priv->initialized)); fpd_dp_ser_unlock_global(); - msleep(500); + msleep(100); } pr_debug("%s: kthread stopped\n", __func__); return 0; @@ -513,8 +513,6 @@ static void tp_init_work(struct work_struct *work) goto retry; } - msleep(5000); - ret = tp_serdes_irq_init(priv); if (ret < 0) { fpd_dp_ser_unlock_global(); From aef4286523ed17856c3100b287b317802161aa72 Mon Sep 17 00:00:00 2001 From: "Jia, Lin A" Date: Thu, 23 May 2024 14:28:58 +0800 Subject: [PATCH 2/7] drm/bridge: Add serdes startup done function Serdes reset when panel status undone Test-done: Android boot tested with panel EF1E-A1 Tracked-On: OAM- Signed-off-by: Jia, Lin A --- drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c | 74 +++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) 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 05281623f3b0..7beadc63ec81 100644 --- a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c +++ b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c @@ -255,6 +255,40 @@ int fpd_dp_mcu_read_reg(struct i2c_client *client, unsigned int reg_addr, u8 len return 0; } +bool fpd_dp_mcu_write_reg(struct i2c_client *client, unsigned int reg_addr, u32 val) +{ + int ret = 0; + int i = 0; + struct i2c_msg msg; + u8 buf[7]; + + buf[0] = reg_addr & 0xff; + buf[1] = 0x00; + buf[2] = 0x02; + buf[3] = val & 0xff; + buf[4] = buf[0]^buf[1]^buf[2]^buf[3]; + + msg.addr = client->addr; + msg.flags = 0; + msg.buf = &buf[0]; + msg.len = 5; + + ret = i2c_transfer(client->adapter, &msg, 1); + + if (ret < 0) { + pr_info("[FPD_DP] [-%s-%s-%d-], fail client->addr=0x%02x, reg_addr=0x%02x, val=0x%03x\n", + __FILE__, __func__, __LINE__, msg.addr, reg_addr, val); + return false; + } + + for (i=0; i < msg.len; i++) { + pr_info("[FPD_DP] WIB 0x%02x: 0x%02x buf[%d] 0x%02x OK\n", + msg.addr, reg_addr, i, buf[i]); + } + + return true; +} + /* * TODO not used * this code is for check i2c return val @@ -1851,6 +1885,43 @@ int fpd_dp_ser_get_i2c_bus_number(void) } EXPORT_SYMBOL_GPL(fpd_dp_ser_get_i2c_bus_number); +void wait_display_startup_done(struct i2c_client *client) +{ + int ret; + int n = 0; + int i = 0; + uint8_t rdata[5] = { 0 }; + uint8_t cmd_data = 0x01; + + while (++n < 100) + { + //fpd_dp_mcu_write_reg(client, 0x21, cmd_data); + ret = fpd_dp_mcu_read_reg(fpd_dp_priv->priv_dp_client[2], 0x61, 5, &rdata[0]); + + for (i=0; i < 5; i++) + pr_debug("[FPD_DP] RIB [FPD_DP] RIB 0x78: 0x61, rdata[%d] 0x%02x OK\n", + i, rdata[i]); + + if (rdata[0] == 0x61 && rdata[3] == 1) + { + pr_info("[FPD_DP] RIB DP2 UB943 wait_display_startup_done sucess"); + break; + } + usleep_range(5000, 5200); + } + + ret = fpd_dp_mcu_write_reg(client, 0x21, cmd_data); + if (ret < 0) + { + ret = fpd_dp_mcu_write_reg(client, 0x21, cmd_data); + if (ret < 0) + { + pr_info("[FPD_DP] DP2 UB983 wait_display_startup_done error"); + fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); + } + } +} + bool fpd_dp_ser_init(void) { fpd_dp_ser_lock_global(); @@ -1872,6 +1943,7 @@ bool fpd_dp_ser_init(void) fpd_dp_priv->priv_dp_client[2] = i2c_new_dummy_device(fpd_dp_priv->i2c_adap, fpd_dp_i2c_board_info[2].addr); fpd_dp_ser_lock_global(); + wait_display_startup_done(fpd_dp_priv->priv_dp_client[2]); fpd_dp_ser_motor_open(fpd_dp_priv->priv_dp_client[2]); fpd_dp_ser_unlock_global(); @@ -1939,7 +2011,7 @@ static int fpd_dp_ser_probe(struct platform_device *pdev) iowrite8(data, gpio_cfg); iounmap(gpio_cfg); /* Delay for VPs to sync to DP source */ - usleep_range(5000, 5200); + msleep(100); fpd_dp_ser_init(); From b85e19ba3bd6ac0da7d82f430347286bce40c25c Mon Sep 17 00:00:00 2001 From: "Jia, Lin A" Date: Fri, 24 May 2024 22:42:03 +0800 Subject: [PATCH 3/7] drm/bridge: Refine 983 driver and mutex 1. Refine 983 driver according to vendor paython file. 2. Modify serdes mutex to avoid resume slow Test-done: Android boot tested with panel EF1E-A1 Tracked-On: OAM- Signed-off-by: Jia, Lin A --- drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c | 166 +++++++++++++++++++-- 1 file changed, 151 insertions(+), 15 deletions(-) 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 7beadc63ec81..222219e0a451 100644 --- a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c +++ b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c @@ -363,7 +363,7 @@ void fpd_dp_ser_motor_open(struct i2c_client *client) u32 data_motor = 0; int i = 0; - data_motor = 0x0050ff; + data_motor = 0x0064ff; fpd_dp_mcu_motor_mode(client, 0x23, data_motor); fpd_dp_mcu_read_reg(client, 0x63, 7, &read_motor_mode[0]); @@ -529,6 +529,67 @@ int fpd_dp_set_fpd_4_pll(struct i2c_client *client) return 0; } +/** + * Set up FPD IV PLL Settings + */ +int fpd_dp_set_fpd_4_983_pll(struct i2c_client *client) +{ + /* Disable PLL0 */ + fpd_dp_ser_write_reg(client, 0x40, 0x08); + fpd_dp_ser_write_reg(client, 0x41, 0x1b); + fpd_dp_ser_write_reg(client, 0x42, 0x08); + + /* Disable PLL1 */ + fpd_dp_ser_write_reg(client, 0x41, 0x5b); + fpd_dp_ser_write_reg(client, 0x42, 0x08); + + /* Enable mode overwrite*/ + fpd_dp_ser_write_reg(client, 0x2, 0xd1); + fpd_dp_ser_write_reg(client, 0x2d, 0x1); + + /* Select PLL reg page */ + fpd_dp_ser_write_reg(client, 0x40, 0x08); + /* Select Ncount Reg */ + fpd_dp_ser_write_reg(client, 0x41, 0x05); + /* Set Ncount */ + fpd_dp_ser_write_reg(client, 0x42, 0x64); + /* Select post div reg */ + fpd_dp_ser_write_reg(client, 0x41, 0x13); + /* Set post div for 6.75 Gbps */ + fpd_dp_ser_write_reg(client, 0x42, 0x80); + /* Select write reg to port 0 */ + fpd_dp_ser_write_reg(client, 0x2d, 0x01); + /* set BC sampling rate */ + fpd_dp_ser_write_reg(client, 0x6a, 0x0a); + /* set BC fractional sampling */ + fpd_dp_ser_write_reg(client, 0x6e, 0x86); + /* Select FPD page and set BC settings for FPD IV port 0 */ + fpd_dp_ser_write_reg(client, 0x40, 0x04); + + fpd_dp_ser_write_reg(client, 0x41, 0x06); + fpd_dp_ser_write_reg(client, 0x42, 0x00); + fpd_dp_ser_write_reg(client, 0x41, 0x0d); + fpd_dp_ser_write_reg(client, 0x42, 0x34); + fpd_dp_ser_write_reg(client, 0x41, 0x0e); + fpd_dp_ser_write_reg(client, 0x42, 0x53); + + /* Set HALFRATE_MODE */ + fpd_dp_ser_write_reg(client, 0x2, 0x51); + + /* Zero out fractional PLL for port 0 */ + fpd_dp_ser_write_reg(client, 0x40, 0x08); + fpd_dp_ser_write_reg(client, 0x41, 0x04); + fpd_dp_ser_write_reg(client, 0x42, 0x01); + fpd_dp_ser_write_reg(client, 0x41, 0x1e); + fpd_dp_ser_write_reg(client, 0x42, 0x0); + fpd_dp_ser_write_reg(client, 0x41, 0x1f); + fpd_dp_ser_write_reg(client, 0x42, 0x00); + fpd_dp_ser_write_reg(client, 0x41, 0x20); + fpd_dp_ser_write_reg(client, 0x42, 0x0); + + return 0; +} + /** * @brief fpd_dp_ser_enable_I2C_passthrough @@ -585,6 +646,40 @@ int fpd_dp_ser_configue_enable_plls(struct i2c_client *client) return 0; } +/** + * Configure and Enable PLLs + */ +int fpd_dp_ser_configue_enable_983_plls(struct i2c_client *client) +{ + fpd_dp_ser_debug("[FPD_DP] Configure and Enable PLLs\n"); + fpd_dp_ser_debug("[FPD_DP] Set VCO\n"); + + /* Select VCO reg */ + fpd_dp_ser_write_reg(client, 0x41,0x0e); + /* Set VCO */ + fpd_dp_ser_write_reg(client, 0x42,0xc7); + + fpd_dp_ser_debug("[FPD_DP] reset PLL\n"); + /* soft reset PLL */ + fpd_dp_ser_write_reg(client, 0x01,0x30); + + fpd_dp_ser_debug("[FPD_DP] Enable PLL0\n"); + /* Select PLL page */ + fpd_dp_ser_write_reg(client, 0x41,0x1b); + /* Enable PLL0 */ + fpd_dp_ser_write_reg(client, 0x42,0x00); + + /* soft reset Ser */ + fpd_dp_ser_lock_global(); + fpd_dp_ser_write_reg(client, 0x01,0x01); + msleep(40); + fpd_dp_ser_unlock_global(); + + + return 0; +} + + /** * Soft reset Des */ @@ -613,6 +708,27 @@ int fpd_dp_deser_soft_reset(struct i2c_client *client) return 0; } +int fpd_dp_deser_soft_983_reset(struct i2c_client *client) +{ + u8 des_read = 0; + + /* Soft reset Des */ + if (!fpd_dp_priv->priv_dp_client[1]) + fpd_dp_priv->priv_dp_client[1] = i2c_new_dummy_device(fpd_dp_priv->i2c_adap, fpd_dp_i2c_board_info[1].addr); + + if (fpd_dp_priv->priv_dp_client[1] != NULL) { + fpd_dp_ser_lock_global(); + fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); + msleep(40); + fpd_dp_ser_unlock_global(); + } + + /* Select write to port0 reg */ + fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[0], 0x2d, 0x01); + return 0; +} + + /** * @brief Set DP Config * @param client @@ -774,7 +890,6 @@ int fpd_dp_ser_clear_crc_error(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x2, Reg_value); fpd_dp_ser_write_reg(client, 0x2d, 0x1); - usleep_range(20000, 22000); return 0; } @@ -1309,6 +1424,22 @@ bool fpd_dp_ser_setup(struct i2c_client *client) return true; } +bool fpd_dp_ser_983_setup(struct i2c_client *client) +{ + fpd_dp_ser_program_fpd_4_mode(client); + fpd_dp_set_fpd_4_983_pll(client); + fpd_dp_ser_configue_enable_983_plls(client); + fpd_dp_ser_enable_I2C_passthrough(client); + fpd_dp_deser_soft_983_reset(client); + fpd_dp_ser_set_dp_config(client); + fpd_dp_ser_program_vp_configs(client); + fpd_dp_ser_enable_vps(client); + /* Check if VP is synchronized to DP input */ + //queue_delayed_work(fpd_dp_priv->wq, &fpd_dp_priv->delay_work, msecs_to_jiffies(100)); + + return true; +} + bool fpd_dp_ser_enable(void) { fpd_dp_ser_prepare(fpd_dp_priv->priv_dp_client[0]); @@ -1319,6 +1450,17 @@ bool fpd_dp_ser_enable(void) return true; } +bool fpd_dp_ser_983_enable(void) +{ + fpd_dp_ser_set_up_variables(fpd_dp_priv->priv_dp_client[0]); + + if (false == fpd_dp_ser_983_setup(fpd_dp_priv->priv_dp_client[0])) { + fpd_dp_ser_debug("[FPD_DP] DS90UB983 enable fail\n"); + return false; + } + return true; +} + bool fpd_dp_ser_disable(void) { fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-]\n", __FILE__, __func__, __LINE__); @@ -1555,8 +1697,10 @@ int fpd_dp_deser_984_override_efuse(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x41, 0x71); fpd_dp_ser_write_reg(client, 0x42, 0x26); /* Soft Reset DES */ + fpd_dp_ser_lock_global(); fpd_dp_ser_write_reg(client, 0x1, 0x1); - usleep_range(30000, 32000); + msleep(40); + fpd_dp_ser_unlock_global(); } return 0; @@ -1783,15 +1927,15 @@ static void fpd_poll_984_training(void) fpd_dp_ser_debug("[FPD_DP] Check if VP is synchronized to DP input\n"); /* Delay for VPs to sync to DP source */ - usleep_range(20000, 22000); + msleep(100); /* Select VP Page */ fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[0], 0x40, 0x31); fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[0], 0x41, 0x30); fpd_dp_ser_read_reg(fpd_dp_priv->priv_dp_client[0], 0x42, &VP0sts); - fpd_dp_ser_debug("[FPD_DP] VP0sts = 0x%02x\n", (VP0sts & 0x01)); + fpd_dp_ser_debug("[FPD_DP] VP0sts = 0x%02x\n", VP0sts); - if (((VP0sts & 0x01) == 0)) { + if (VP0sts == 0) { fpd_dp_ser_debug("[FPD_DP] VPs not synchronized - performing video input reset\n"); /* Video Input Reset if VP is not synchronized */ fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[0], 0x49, 0x54); @@ -1804,9 +1948,6 @@ static void fpd_poll_984_training(void) fpd_dp_ser_debug("[FPD_DP] ser training lock completed, count = %d\n", fpd_dp_priv->count); - /* Delay for VPs to sync to DP source */ - usleep_range(20000, 22000); - fpd_dp_deser_984_enable(); } @@ -1895,7 +2036,6 @@ void wait_display_startup_done(struct i2c_client *client) while (++n < 100) { - //fpd_dp_mcu_write_reg(client, 0x21, cmd_data); ret = fpd_dp_mcu_read_reg(fpd_dp_priv->priv_dp_client[2], 0x61, 5, &rdata[0]); for (i=0; i < 5; i++) @@ -1924,9 +2064,7 @@ void wait_display_startup_done(struct i2c_client *client) bool fpd_dp_ser_init(void) { - fpd_dp_ser_lock_global(); - - fpd_dp_ser_enable(); + fpd_dp_ser_983_enable(); /* Check if VP is synchronized to DP input */ fpd_poll_984_training(); @@ -1937,8 +2075,6 @@ bool fpd_dp_ser_init(void) fpd_dp_ser_set_ready(true); - fpd_dp_ser_unlock_global(); - if (!fpd_dp_priv->priv_dp_client[2]) fpd_dp_priv->priv_dp_client[2] = i2c_new_dummy_device(fpd_dp_priv->i2c_adap, fpd_dp_i2c_board_info[2].addr); From 164f81c2bb22256f8d233aed7b84b1af322caaec Mon Sep 17 00:00:00 2001 From: "Jia, Lin A" Date: Fri, 24 May 2024 22:53:35 +0800 Subject: [PATCH 4/7] drm/i915: Add backlight adjustment mutex protect 1. Mutex protect during backlight adjustment 2. Remove 984 reset when first boot and resume. Test-done: Android boot tested with panel EF1E-A1 Tracked-On: OAM- Signed-off-by: Jia, Lin A --- drivers/gpu/drm/i915/display/intel_dp.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ec4f87ed4b11..3e4ac68d311d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5611,22 +5611,10 @@ static void mcu_set_backlight(const struct drm_connector_state *conn_state, u32 u16 data = 0; - fpd_dp_ser_lock_global(); - if (!READ_ONCE(deser_reset)) { - /* - * TODO: 984 reset to avoid serdes panel black screen, - * the following should handle 984 reset accoding to panel - * status - */ - intel_dp_ser_write_reg(dev, i2c_adap_mcu, 0x01, 0x01); - usleep_range(20000, 22000); - WRITE_ONCE(deser_reset, 1); - drm_dbg_kms(dev, "[FPD_DP] 984 reset"); - } - panel->backlight.level = level; data = 0x0200 | level; + fpd_dp_ser_lock_global(); intel_dp_mcu_write_reg(dev, i2c_adap_mcu, 0x22, data); fpd_dp_ser_unlock_global(); @@ -5643,7 +5631,9 @@ static void mcu_disable_backlight(const struct drm_connector_state *conn_state, u16 data = 0; data = 0x0100 | panel->backlight.level; + fpd_dp_ser_lock_global(); intel_dp_mcu_write_reg(dev, i2c_adap_mcu, 0x22, data); + fpd_dp_ser_unlock_global() } static void mcu_enable_backlight(const struct intel_crtc_state *crtc_state, From 4ccc9ef4de2b68609a217330179852a5fccf34c9 Mon Sep 17 00:00:00 2001 From: Weifeng Liu Date: Mon, 27 May 2024 08:02:08 +0000 Subject: [PATCH 5/7] WIP: drm/bridge/ti: Refine the code This is an intention to clean up the code. Signed-off-by: Weifeng Liu --- drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c | 279 ++++++++++-------- drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.h | 5 + drivers/gpu/drm/i915/display/intel_dp.c | 56 ++-- .../touchscreen/ef1e_tp/ef1e_tp_driver.c | 13 +- 4 files changed, 187 insertions(+), 166 deletions(-) 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 222219e0a451..2f4d1ff8815d 100644 --- a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c +++ b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c @@ -73,6 +73,8 @@ #define PAD_CFG_DW0_GPPC_A_16 0xfd6e0AA0 +#define fpd_dp_ser_err pr_err +#define fpd_dp_ser_info pr_info #ifdef DEBUG #define fpd_dp_ser_debug pr_info #else @@ -82,7 +84,6 @@ static struct platform_device *pdev; struct fpd_dp_ser_priv *fpd_dp_priv; struct i2c_adapter *i2c_adap_mcu; -int deser_reset; static bool deser_ready = false; /* @@ -191,7 +192,8 @@ bool fpd_dp_ser_write_reg(struct i2c_client *client, unsigned int reg_addr, u8 v return true; } -bool fpd_dp_mcu_motor_mode(struct i2c_client *client, unsigned int reg_addr, u32 val) +bool +fpd_dp_mcu_motor_mode(struct i2c_client *client, unsigned int reg_addr, u32 val) { int ret = 0; int i = 0; @@ -214,8 +216,11 @@ bool fpd_dp_mcu_motor_mode(struct i2c_client *client, unsigned int reg_addr, u32 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%03x\n", - __FILE__, __func__, __LINE__, msg.addr, reg_addr, val); + fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-] cannot set motor mode, " + "client->addr=0x%02x, reg_addr=0x%02x, " + "val=0x%03x\n", + __FILE__, __func__, __LINE__, msg.addr, + reg_addr, val); return false; } @@ -349,7 +354,7 @@ void fpd_dp_ser_set_up_variables(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x88, 0x0); } -void fpd_dp_ser_set_up_mcu(struct i2c_client *client) +static void fpd_dp_ser_set_up_mcu(struct i2c_client *client) { fpd_dp_ser_write_reg(client, 0x70, FPD_DP_SER_MCU_ADD << 1); fpd_dp_ser_write_reg(client, 0x78, FPD_DP_SER_MCU_ADD << 1); @@ -357,34 +362,47 @@ void fpd_dp_ser_set_up_mcu(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x07, 0x88); } -void fpd_dp_ser_motor_open(struct i2c_client *client) +static void fpd_dp_ser_motor_open(struct i2c_client *client) { u8 read_motor_mode[7] = { 0 }; - u32 data_motor = 0; + const u32 data_motor = 0x0064ff; int i = 0; - data_motor = 0x0064ff; - fpd_dp_mcu_motor_mode(client, 0x23, data_motor); + fpd_dp_ser_lock_global(); + if (fpd_dp_ser_ready()) { + fpd_dp_mcu_motor_mode(client, 0x23, data_motor); + fpd_dp_mcu_read_reg(client, 0x63, 7, &read_motor_mode[0]); + for (i = 0; i < 7; i++) + fpd_dp_ser_debug("[FPD_DP] RIB [FPD_DP] RIB 0x78: 0x63," + " read_motor_mode[%d] 0x%02x OK\n", + i, read_motor_mode[i]); + } else { + fpd_dp_ser_info("%s: skip motor open because serdes is not " + "ready\n", __func__); + } + fpd_dp_ser_unlock_global(); - fpd_dp_mcu_read_reg(client, 0x63, 7, &read_motor_mode[0]); - for (i = 0; i < 7; i++) - fpd_dp_ser_debug("[FPD_DP] RIB [FPD_DP] RIB 0x78: 0x63, read_motor_mode[%d] 0x%02x OK\n", - i, read_motor_mode[i]); } -void fpd_dp_ser_motor_close(struct i2c_client *client) +static void fpd_dp_ser_motor_close(struct i2c_client *client) { u8 read_motor_mode[7] = { 0 }; - u32 data_motor = 0; + const u32 data_motor = 0x0000ff; int i = 0; - data_motor = 0x0000ff; - fpd_dp_mcu_motor_mode(client, 0x23, data_motor); - - fpd_dp_mcu_read_reg(client, 0x63, 7, &read_motor_mode[0]); - for (i = 0; i < 7; i++) - fpd_dp_ser_debug("[FPD_DP] RIB [FPD_DP] RIB 0x78: 0x63, read_motor_mode[%d] 0x%02x OK\n", - i, read_motor_mode[i]); + fpd_dp_ser_lock_global(); + if (fpd_dp_ser_ready()) { + fpd_dp_mcu_motor_mode(client, 0x23, data_motor); + fpd_dp_mcu_read_reg(client, 0x63, 7, &read_motor_mode[0]); + for (i = 0; i < 7; i++) + fpd_dp_ser_debug("[FPD_DP] RIB [FPD_DP] RIB 0x78: 0x63," + " read_motor_mode[%d] 0x%02x OK\n", + i, read_motor_mode[i]); + } else { + fpd_dp_ser_info("%s: skip motor close because serdes is not " + "ready\n", __func__); + } + fpd_dp_ser_unlock_global(); } /** @@ -670,11 +688,8 @@ int fpd_dp_ser_configue_enable_983_plls(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x42,0x00); /* soft reset Ser */ - fpd_dp_ser_lock_global(); fpd_dp_ser_write_reg(client, 0x01,0x01); msleep(40); - fpd_dp_ser_unlock_global(); - return 0; } @@ -688,11 +703,6 @@ int fpd_dp_deser_soft_reset(struct i2c_client *client) usleep_range(20000, 22000); u8 des_read = 0; - /* Soft reset Des */ - if (!fpd_dp_priv->priv_dp_client[1]) - fpd_dp_priv->priv_dp_client[1] = i2c_new_dummy_device(fpd_dp_priv->i2c_adap, fpd_dp_i2c_board_info[1].addr); - - if (fpd_dp_priv->priv_dp_client[1] != NULL) { fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); usleep_range(20000, 22000); @@ -712,16 +722,8 @@ int fpd_dp_deser_soft_983_reset(struct i2c_client *client) { u8 des_read = 0; - /* Soft reset Des */ - if (!fpd_dp_priv->priv_dp_client[1]) - fpd_dp_priv->priv_dp_client[1] = i2c_new_dummy_device(fpd_dp_priv->i2c_adap, fpd_dp_i2c_board_info[1].addr); - - if (fpd_dp_priv->priv_dp_client[1] != NULL) { - fpd_dp_ser_lock_global(); - fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); - msleep(40); - fpd_dp_ser_unlock_global(); - } + fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); + msleep(40); /* Select write to port0 reg */ fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[0], 0x2d, 0x01); @@ -1443,8 +1445,8 @@ bool fpd_dp_ser_983_setup(struct i2c_client *client) bool fpd_dp_ser_enable(void) { fpd_dp_ser_prepare(fpd_dp_priv->priv_dp_client[0]); - if (false == fpd_dp_ser_setup(fpd_dp_priv->priv_dp_client[0])) { - fpd_dp_ser_debug("[FPD_DP] DS90UB983 enable fail\n"); + if (!fpd_dp_ser_setup(fpd_dp_priv->priv_dp_client[0])) { + fpd_dp_ser_err("[FPD_DP] DS90UB983 enable fail\n"); return false; } return true; @@ -1455,7 +1457,7 @@ bool fpd_dp_ser_983_enable(void) fpd_dp_ser_set_up_variables(fpd_dp_priv->priv_dp_client[0]); if (false == fpd_dp_ser_983_setup(fpd_dp_priv->priv_dp_client[0])) { - fpd_dp_ser_debug("[FPD_DP] DS90UB983 enable fail\n"); + fpd_dp_ser_err("[FPD_DP] DS90UB983 enable fail\n"); return false; } return true; @@ -1697,10 +1699,8 @@ int fpd_dp_deser_984_override_efuse(struct i2c_client *client) fpd_dp_ser_write_reg(client, 0x41, 0x71); fpd_dp_ser_write_reg(client, 0x42, 0x26); /* Soft Reset DES */ - fpd_dp_ser_lock_global(); fpd_dp_ser_write_reg(client, 0x1, 0x1); msleep(40); - fpd_dp_ser_unlock_global(); } return 0; @@ -1987,14 +1987,12 @@ static int intel_get_i2c_bus_id(int adapter_id, char *adapter_bdf, int bdf_len) if (!adapter_bdf || bdf_len > 32) return -1; - while (retry_count < 100) { + while (retry_count++ < 100) { i = 0; - found = 0; while ((adapter = i2c_get_adapter(i)) != NULL) { parent = adapter->dev.parent; pp = parent->parent; i2c_put_adapter(adapter); - fpd_dp_ser_debug("[FPD_DP] dev_name(pp): %s\n", dev_name(pp)); if (pp && !strncmp(adapter_bdf, dev_name(pp), bdf_len)) { found = 1; break; @@ -2004,16 +2002,12 @@ static int intel_get_i2c_bus_id(int adapter_id, char *adapter_bdf, int bdf_len) if (found) { fpd_dp_ser_debug("[FPD_DP] found dev_name(pp) %s\n", dev_name(pp)); - break; + return i; } - retry_count++; - fpd_dp_ser_debug("[FPD_DP] not found retry_count %d\n", retry_count); msleep(50); } - if (found) - return i; - + fpd_dp_ser_err("%s: cannot find i2c adapter\n", __func__); /* Not found */ return -1; } @@ -2021,68 +2015,103 @@ static int intel_get_i2c_bus_id(int adapter_id, char *adapter_bdf, int bdf_len) int fpd_dp_ser_get_i2c_bus_number(void) { char adapter_bdf[32] = ADAPTER_PP_DEV_NAME; - int bus_number = intel_get_i2c_bus_id(0, adapter_bdf, 32); - return bus_number; + return intel_get_i2c_bus_id(0, adapter_bdf, 32); } EXPORT_SYMBOL_GPL(fpd_dp_ser_get_i2c_bus_number); -void wait_display_startup_done(struct i2c_client *client) +static bool fpd_dp_ser_respond_dhu_startup_status(struct i2c_client *client) { int ret; - int n = 0; - int i = 0; + + ret = fpd_dp_mcu_write_reg(client, + FPD_DP_SER_RESPOND_DHU_STARTUP_STATUS, 0x01); + if (ret < 0) { + fpd_dp_ser_err("%s: failed to write DHU statup status\n", __func__); + return false; + } + return true; +} + +static bool fpd_dp_ser_read_display_startup_status(struct i2c_client *client) +{ + bool status = false; uint8_t rdata[5] = { 0 }; - uint8_t cmd_data = 0x01; + int ret, i; - while (++n < 100) - { - ret = fpd_dp_mcu_read_reg(fpd_dp_priv->priv_dp_client[2], 0x61, 5, &rdata[0]); + fpd_dp_ser_lock_global(); + if (!fpd_dp_ser_ready()) { + fpd_dp_ser_debug("%s: wait for serdes\n", __func__); + goto out; + } + + ret = fpd_dp_mcu_read_reg(fpd_dp_priv->priv_dp_client[2], + FPD_DP_SER_RESPOND_DISPLAY_STARTUP_STATUS, + 5, &rdata[0]); + if (ret < 0) { + fpd_dp_ser_err("%s: failed to get display startup status\n", __func__); + goto out; + } - for (i=0; i < 5; i++) - pr_debug("[FPD_DP] RIB [FPD_DP] RIB 0x78: 0x61, rdata[%d] 0x%02x OK\n", - i, rdata[i]); + for (i = 0; i < 5; i++) + fpd_dp_ser_debug("[FPD_DP] RIB [FPD_DP] RIB 0x78: 0x61, rdata[%d] 0x%02x OK\n", + i, rdata[i]); - if (rdata[0] == 0x61 && rdata[3] == 1) - { - pr_info("[FPD_DP] RIB DP2 UB943 wait_display_startup_done sucess"); - break; + if (rdata[0] == FPD_DP_SER_RESPOND_DISPLAY_STARTUP_STATUS) { + if (rdata[3] == 1) { + fpd_dp_ser_info("[FPD_DP] RIB DP2 UB943 display startup status: done\n"); + status = fpd_dp_ser_respond_dhu_startup_status(client); + } else { + fpd_dp_ser_info("[FPD_DP] RIB DP2 UB943 display startup status: not done\n"); } - usleep_range(5000, 5200); + } else { + fpd_dp_ser_err("%s: not display startup status\n", __func__); } - ret = fpd_dp_mcu_write_reg(client, 0x21, cmd_data); - if (ret < 0) +out: + fpd_dp_ser_unlock_global(); + return status; +} + +static bool wait_display_startup_done(struct i2c_client *client) +{ + int ret; + int n = 0; + int i = 0; + bool status; + + while (++n < 100) { - ret = fpd_dp_mcu_write_reg(client, 0x21, cmd_data); - if (ret < 0) - { - pr_info("[FPD_DP] DP2 UB983 wait_display_startup_done error"); - fpd_dp_ser_write_reg(fpd_dp_priv->priv_dp_client[1], 0x01, 0x01); - } + if (fpd_dp_ser_read_display_startup_status(client)) + return true; + usleep_range(5000, 5200); } + + fpd_dp_ser_err("%s: display startup status not ready\n", __func__); + return false; +} + +/* This would be run in a workqueue. */ +static void fpd_dp_motor_setup_work(struct work_struct *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]); } bool fpd_dp_ser_init(void) { + fpd_dp_ser_lock_global(); fpd_dp_ser_983_enable(); /* Check if VP is synchronized to DP input */ fpd_poll_984_training(); - WRITE_ONCE(deser_reset, 0); - fpd_dp_ser_set_up_mcu(fpd_dp_priv->priv_dp_client[0]); fpd_dp_ser_set_ready(true); - - if (!fpd_dp_priv->priv_dp_client[2]) - fpd_dp_priv->priv_dp_client[2] = i2c_new_dummy_device(fpd_dp_priv->i2c_adap, fpd_dp_i2c_board_info[2].addr); - - fpd_dp_ser_lock_global(); - wait_display_startup_done(fpd_dp_priv->priv_dp_client[2]); - fpd_dp_ser_motor_open(fpd_dp_priv->priv_dp_client[2]); fpd_dp_ser_unlock_global(); + queue_work(fpd_dp_priv->motor_setup_wq, &fpd_dp_priv->motor_setup_work); + return true; } @@ -2091,53 +2120,63 @@ static int fpd_dp_ser_probe(struct platform_device *pdev) struct i2c_adapter *i2c_adap; struct fpd_dp_ser_priv *priv; int bus_number = 0; - int ret = 0; + int ret = 0, i; unsigned char __iomem *gpio_cfg; unsigned char data; - priv = devm_kzalloc(&pdev->dev, sizeof(struct fpd_dp_ser_priv), - GFP_KERNEL); - + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (priv == NULL) { return -ENOMEM; } platform_set_drvdata(pdev, priv); - - memset(priv, 0, sizeof(*priv)); priv->dev = &pdev->dev; bus_number = fpd_dp_ser_get_i2c_bus_number(); fpd_dp_ser_debug("Use bus_number %d \n", bus_number); i2c_adap = i2c_get_adapter(bus_number); if (!i2c_adap) { - fpd_dp_ser_debug("Cannot find a valid i2c bus for max serdes\n"); - return -ENOMEM; + fpd_dp_ser_err("Cannot find a valid i2c bus for max serdes\n"); + ret = -ENODEV; + goto err_adapter; } /* retries when i2c timeout */ i2c_adap->retries = 5; i2c_adap->timeout = msecs_to_jiffies(5 * 10); - i2c_put_adapter(i2c_adap); priv->i2c_adap = i2c_adap; i2c_adap_mcu = i2c_adap; - priv->priv_dp_client[0] = i2c_new_dummy_device(i2c_adap, fpd_dp_i2c_board_info[0].addr); - i2c_set_clientdata(priv->priv_dp_client[0], priv); - + for (i = 0; i < ARRAY_SIZE(fpd_dp_i2c_board_info); ++i) { + priv->priv_dp_client[i] = i2c_new_dummy_device(i2c_adap, fpd_dp_i2c_board_info[i].addr); + if (IS_ERR(priv->priv_dp_client[i])) { + fpd_dp_ser_err("%s: failed to create i2c dummy device, addr = %d\n", + __func__, fpd_dp_i2c_board_info[i].addr); + ret = -EBUSY; + goto err_i2c; + } + 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); - + WQ_HIGHPRI, 0); if (unlikely(!fpd_dp_priv->wq)) { fpd_dp_ser_debug("[FPD_DP] Failed to allocate workqueue\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_i2c; } - INIT_DELAYED_WORK(&fpd_dp_priv->delay_work, - fpd_poll_training_lock); + 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; @@ -2150,7 +2189,16 @@ static int fpd_dp_ser_probe(struct platform_device *pdev) msleep(100); fpd_dp_ser_init(); + 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]); + i2c_put_adapter(i2c_adap); +err_adapter: + devm_kfree(&pdev->dev, priv); return ret; } @@ -2163,7 +2211,7 @@ static int fpd_dp_ser_remove(struct platform_device *pdev) { cancel_delayed_work_sync(&priv->delay_work); fpd_dp_ser_lock_global(); fpd_dp_ser_set_ready(false); - for (i = 0; i < NUM_DEVICE; i++) { + for (i = 0; i < ARRAY_SIZE(fpd_dp_i2c_board_info); i++) { struct i2c_client *client= priv->priv_dp_client[i]; if (i == 0) fpd_dp_ser_reset(client); @@ -2180,6 +2228,7 @@ static int fpd_dp_ser_remove(struct platform_device *pdev) { devm_kfree(&pdev->dev, priv); fpd_dp_ser_debug("[-%s-%s-%d-]\n", __FILE__, __func__, __LINE__); } + i2c_put_adapter(i2c_adap_mcu); return 0; } @@ -2194,16 +2243,11 @@ static int fpd_dp_ser_suspend(struct device *dev) fpd_dp_ser_lock_global(); fpd_dp_ser_set_ready(false); /* first des reset, and then ser reset */ - for (i = 1; i > -1; i--) { - struct i2c_client *client= priv->priv_dp_client[i]; - if (i == 0) - fpd_dp_ser_reset(client); - else - fpd_dp_ser_write_reg(client, 0x01, 0x01); - - /* after reset, wait 20ms to avoid ser/des read/write fail */ - usleep_range(20000, 22000); - } + fpd_dp_ser_write_reg(priv->priv_dp_client[0], 0x01, 0x01); + /* after reset, wait 20ms to avoid ser/des read/write fail */ + usleep_range(20000, 22000); + fpd_dp_ser_reset(priv->priv_dp_client[1]); + usleep_range(20000, 22000); fpd_dp_ser_unlock_global(); #endif fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-]\n", __FILE__, __func__, __LINE__); @@ -2306,7 +2350,7 @@ int __init fpd_dp_ser_module_init(void) int ret = 0; pdev = platform_device_register_simple(DEV_NAME, -1, NULL, 0); - fpd_dp_ser_debug("[FPD_DP] [-%s-%s-%d-]\n", __FILE__, __func__, __LINE__); + fpd_dp_ser_debug("start initialization of %s\n", DEV_NAME); if (!IS_ERR(pdev)) { ret = platform_driver_probe(&fpd_dp_ser_driver, @@ -2329,7 +2373,6 @@ void __exit fpd_dp_ser_module_exit(void) } EXPORT_SYMBOL(i2c_adap_mcu); -EXPORT_SYMBOL(deser_reset); #ifdef MODULE module_init(fpd_dp_ser_module_init); diff --git a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.h b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.h index 1692792bbcd0..253c5763fe66 100644 --- a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.h +++ b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.h @@ -37,6 +37,9 @@ #define FPD_DP_SER_RX_ADD_A 0x30 #define FPD_DP_SER_MCU_ADD 0x78 +#define FPD_DP_SER_RESPOND_DISPLAY_STARTUP_STATUS 0x61 +#define FPD_DP_SER_RESPOND_DHU_STARTUP_STATUS 0x21 + #define FPD_DP_ARRAY_SIZE 4 #define DS90UB983 0 @@ -63,6 +66,8 @@ struct fpd_dp_ser_priv { struct i2c_client *priv_dp_client[NUM_DEVICE]; struct delayed_work delay_work; struct workqueue_struct *wq; + struct work_struct motor_setup_work; + struct workqueue_struct *motor_setup_wq; int count; }; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3e4ac68d311d..174232025974 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -93,8 +93,6 @@ #define I2C_MCU_ADDRESS 0x78 -extern int deser_reset; - /* Constants for DP DSC configurations */ static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15}; @@ -5572,31 +5570,6 @@ bool intel_dp_mcu_write_reg(struct drm_device *dev, struct i2c_adapter *adapter, return true; } -bool intel_dp_ser_write_reg(struct drm_device *dev, struct i2c_adapter *adapter, unsigned int reg_addr, u8 val) -{ - int ret = 0; - struct i2c_msg msg; - u8 buf[2]; - - buf[0] = reg_addr & 0xff; - buf[1] = val; - - msg.addr = 0x30; - msg.flags = 0; - msg.buf = &buf[0]; - msg.len = 2; - - ret = i2c_transfer(adapter, &msg, 1); - if (ret < 0) { - drm_err(dev, "[FPD_DP] [-%s-%s-%d-], fail client->addr=0x%02x, reg_addr=0x%02x, val=0x%02x\n", - __FILE__, __FUNCTION__, __LINE__, msg.addr, reg_addr, val); - return false; - } - drm_dbg_kms(dev, "[FPD_DP] WIB 984 reset0x%02x: 0x%02x 0x%02x OK\n", - msg.addr, reg_addr, val); - return true; -} - static u32 mcu_get_backlight(struct intel_connector *connector, enum pipe unused) { struct intel_panel *panel = &connector->panel; @@ -5611,17 +5584,25 @@ static void mcu_set_backlight(const struct drm_connector_state *conn_state, u32 u16 data = 0; - panel->backlight.level = level; - data = 0x0200 | level; + fpd_dp_ser_lock_global(); - intel_dp_mcu_write_reg(dev, i2c_adap_mcu, 0x22, data); + if (fpd_dp_ser_ready()) { + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] backlight level = 0x%2x\n", + to_intel_connector(conn_state->connector)->base.base.id, + to_intel_connector(conn_state->connector)->base.name, + level); + if (intel_dp_mcu_write_reg(dev, i2c_adap_mcu, 0x22, data)) + panel->backlight.level = level; + else + drm_err(dev, "failed write backlight level\n"); + } else { + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] skip setting backlight " + "because serdes is not ready\n", + to_intel_connector(conn_state->connector)->base.base.id, + to_intel_connector(conn_state->connector)->base.name); + } fpd_dp_ser_unlock_global(); - - drm_dbg_kms(dev, - "[CONNECTOR:%d:%s] level = 0x%2x\n", - to_intel_connector(conn_state->connector)->base.base.id, - to_intel_connector(conn_state->connector)->base.name, level); } static void mcu_disable_backlight(const struct drm_connector_state *conn_state, u32 level) @@ -5632,8 +5613,9 @@ static void mcu_disable_backlight(const struct drm_connector_state *conn_state, data = 0x0100 | panel->backlight.level; fpd_dp_ser_lock_global(); - intel_dp_mcu_write_reg(dev, i2c_adap_mcu, 0x22, data); - fpd_dp_ser_unlock_global() + if (fpd_dp_ser_ready()) + intel_dp_mcu_write_reg(dev, i2c_adap_mcu, 0x22, data); + fpd_dp_ser_unlock_global(); } static void mcu_enable_backlight(const struct intel_crtc_state *crtc_state, diff --git a/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c b/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c index a5b650a2b27e..21a879441aa2 100644 --- a/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c +++ b/drivers/input/touchscreen/ef1e_tp/ef1e_tp_driver.c @@ -504,6 +504,8 @@ static void tp_init_work(struct work_struct *work) struct tp_priv *priv = &global_tp; int ret; + /* Give serdes driver a chance to run first. */ + msleep(10); retry: fpd_dp_ser_lock_global(); if (!fpd_dp_ser_ready()) { @@ -615,11 +617,6 @@ static int ef1e_tp_resume(struct device *dev) queue_work(priv->init_wq, &priv->init_work); - if (priv->polling) - ret = tp_kthread_polling_create(priv); - else - ret = tp_gpio_irq_init(priv); - return ret; } @@ -631,12 +628,6 @@ static int ef1e_tp_suspend(struct device *dev) WRITE_ONCE(priv->initialized, 0); dev_info(dev, "%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); - } return 0; } From bdbc1d559ce36e5f262fb2bde86bf7c5c6e69625 Mon Sep 17 00:00:00 2001 From: "Jia, Lin A" Date: Wed, 29 May 2024 10:24:21 +0800 Subject: [PATCH 6/7] drm/i915: 984 reset operation Add 984 reset when first boot and resume. Test-done: Android boot tested with panel EF1E-A1 Tracked-On: OAM- Signed-off-by: Jia, Lin A --- drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c | 5 +++ drivers/gpu/drm/i915/display/intel_dp.c | 36 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) 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 2f4d1ff8815d..7901eff3e595 100644 --- a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c +++ b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c @@ -86,6 +86,8 @@ struct fpd_dp_ser_priv *fpd_dp_priv; struct i2c_adapter *i2c_adap_mcu; static bool deser_ready = false; +int deser_reset; + /* * Background: This module owns serdes and MCU, that is to say, serdes and MCU * would be initialized here. However, EF1E touchscreen driver depends on the @@ -2105,6 +2107,8 @@ bool fpd_dp_ser_init(void) /* Check if VP is synchronized to DP input */ fpd_poll_984_training(); + WRITE_ONCE(deser_reset, 0); + fpd_dp_ser_set_up_mcu(fpd_dp_priv->priv_dp_client[0]); fpd_dp_ser_set_ready(true); @@ -2373,6 +2377,7 @@ void __exit fpd_dp_ser_module_exit(void) } EXPORT_SYMBOL(i2c_adap_mcu); +EXPORT_SYMBOL(deser_reset); #ifdef MODULE module_init(fpd_dp_ser_module_init); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 174232025974..01981cd43842 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -92,6 +92,7 @@ #define INTEL_DP_RESOLUTION_FAILSAFE (3 << INTEL_DP_RESOLUTION_SHIFT_MASK) #define I2C_MCU_ADDRESS 0x78 +extern int deser_reset; /* Constants for DP DSC configurations */ static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15}; @@ -5570,6 +5571,28 @@ bool intel_dp_mcu_write_reg(struct drm_device *dev, struct i2c_adapter *adapter, return true; } +bool intel_dp_ser_write_reg(struct drm_device *dev, struct i2c_adapter *adapter, unsigned int reg_addr, u8 val) +{ + int ret = 0; + struct i2c_msg msg; + u8 buf[2]; + buf[0] = reg_addr & 0xff; + buf[1] = val; + msg.addr = 0x30; + msg.flags = 0; + msg.buf = &buf[0]; + msg.len = 2; + ret = i2c_transfer(adapter, &msg, 1); + if (ret < 0) { + drm_err(dev, "[FPD_DP] [-%s-%s-%d-], fail client->addr=0x%02x, reg_addr=0x%02x, val=0x%02x\n", + __FILE__, __FUNCTION__, __LINE__, msg.addr, reg_addr, val); + return false; + } + drm_dbg_kms(dev, "[FPD_DP] WIB 984 reset0x%02x: 0x%02x 0x%02x OK\n", + msg.addr, reg_addr, val); + return true; +} + static u32 mcu_get_backlight(struct intel_connector *connector, enum pipe unused) { struct intel_panel *panel = &connector->panel; @@ -5587,7 +5610,20 @@ static void mcu_set_backlight(const struct drm_connector_state *conn_state, u32 data = 0x0200 | level; fpd_dp_ser_lock_global(); + if (fpd_dp_ser_ready()) { + if (!READ_ONCE(deser_reset)) { + /* + * TODO: 984 reset to avoid serdes panel black screen, + * the following should handle 984 reset accoding to panel + * status + */ + intel_dp_ser_write_reg(dev, i2c_adap_mcu, 0x01, 0x01); + msleep(40); + WRITE_ONCE(deser_reset, 1); + drm_dbg_kms(dev, "[FPD_DP] 984 reset"); + } + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] backlight level = 0x%2x\n", to_intel_connector(conn_state->connector)->base.base.id, to_intel_connector(conn_state->connector)->base.name, From 08920d03dd4f994962997d6f19195d2d1e54fae9 Mon Sep 17 00:00:00 2001 From: "Jia, Lin A" Date: Wed, 29 May 2024 10:27:31 +0800 Subject: [PATCH 7/7] drm/bridge: Revert refine 983 driver and mutex Revert 983 driver according to vendor paython file. Test-done: Android boot tested with panel EF1E-A1 Tracked-On: OAM- Signed-off-by: Jia, Lin A --- drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 7901eff3e595..08bfbec5dc9d 100644 --- a/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c +++ b/drivers/gpu/drm/bridge/ti/fpd_dp_ser_drv.c @@ -2102,7 +2102,8 @@ static void fpd_dp_motor_setup_work(struct work_struct *work) bool fpd_dp_ser_init(void) { fpd_dp_ser_lock_global(); - fpd_dp_ser_983_enable(); + //fpd_dp_ser_983_enable(); + fpd_dp_ser_enable(); /* Check if VP is synchronized to DP input */ fpd_poll_984_training();