diff --git a/drivers/mfd/rkx110_x120/rkx110_linktx.c b/drivers/mfd/rkx110_x120/rkx110_linktx.c index 007a825ab19e..59135a990deb 100644 --- a/drivers/mfd/rkx110_x120/rkx110_linktx.c +++ b/drivers/mfd/rkx110_x120/rkx110_linktx.c @@ -428,9 +428,11 @@ static int rk_serdes_link_tx_ctrl_enable(struct rk_serdes *serdes, { struct hwclk *hwclk = serdes->chip[remote_id].hwclk; struct i2c_client *client; + struct videomode *vm = &route->vm; u32 ctrl_val, val; u32 rx_src; u32 stream_type; + u32 length; if (route->stream_type == STREAM_DISPLAY) { client = serdes->chip[DEVICE_LOCAL].client; @@ -459,6 +461,18 @@ static int rk_serdes_link_tx_ctrl_enable(struct rk_serdes *serdes, serdes->i2c_read_reg(client, RKLINK_TX_VIDEO_CTRL, &val); rx_src = rk_serdes_get_stream_source(serdes, route->local_port0); val |= rx_src; + if (serdes->version == SERDES_V1) { + /* + * The serdes v1 have a bug when enable video suspend function, which + * is used to enhance the i2c frequency. A workaround ways to do it is + * reducing the video packet length: + * length = ((hactive x 24 / 32 / 16) + 15) / 16 * 16 + */ + length = vm->hactive * 24 / 32 / 16; + length = (length + 15) / 16 * 16; + val &= ~VIDEO_REPKT_LENGTH(0xffff); + val |= VIDEO_REPKT_LENGTH(length); + } serdes->i2c_write_reg(client, RKLINK_TX_VIDEO_CTRL, val); if (route->local_port0 & RK_SERDES_DUAL_LVDS_RX) { diff --git a/drivers/mfd/rkx110_x120/rkx120_linkrx.c b/drivers/mfd/rkx110_x120/rkx120_linkrx.c index 45d965b077be..bae51fdb0cc6 100644 --- a/drivers/mfd/rkx110_x120/rkx120_linkrx.c +++ b/drivers/mfd/rkx110_x120/rkx120_linkrx.c @@ -104,6 +104,9 @@ #define LANE0_LANE_ID(x) UPDATE(x, 1, 1) #define LNAE0_ID_SEL(x) UPDATE(x, 0, 0) +#define DES_RKLINK_REC01_PKT_LENGTH LINK_REG(0x0028) +#define E1_REPKT_LENGTH(x) UPDATE(x, 29, 16) +#define E0_REPKT_LENGTH(x) UPDATE(x, 13, 0) #define RKLINK_DES_REG01_ENGIN_DEL 0x0030 #define E1_ENGINE_DELAY(x) UPDATE(x, 31, 16) #define E0_ENGINE_DELAY(x) UPDATE(x, 15, 0) @@ -476,12 +479,14 @@ static int rk120_link_rx_cfg(struct rk_serdes *serdes, struct rk_serdes_route *r { struct hwclk *hwclk = serdes->chip[remote_id].hwclk; struct i2c_client *client; + struct videomode *vm = &route->vm; u32 stream_type; u32 rx_src; u32 ctrl_val, mask, val; u32 lane0_dsource_id, lane1_dsource_id; bool is_rx_dual_lanes; bool is_rx_dual_channels; + u32 length; if (route->stream_type == STREAM_DISPLAY) { client = serdes->chip[remote_id].client; @@ -530,6 +535,19 @@ static int rk120_link_rx_cfg(struct rk_serdes *serdes, struct rk_serdes_route *r serdes->i2c_update_bits(client, RKLINK_DES_LANE_ENGINE_DST, mask, val); + if (serdes->version == SERDES_V1) { + /* + * The serdes v1 have a bug when enable video suspend function, which + * is used to enhance the i2c frequency. A workaround ways to do it is + * reducing the video packet length: + * length = ((hactive x 24 / 32 / 16) + 15) / 16 * 16 + */ + length = vm->hactive * 24 / 32 / 16; + length = (length + 15) / 16 * 16; + serdes->i2c_write_reg(client, DES_RKLINK_REC01_PKT_LENGTH, E0_REPKT_LENGTH(length) | + E1_REPKT_LENGTH(length)); + } + serdes->i2c_read_reg(client, RKLINK_DES_SOURCE_CFG, &val); val &= ~(LANE0_ENGINE_ID(1) | LANE0_LANE_ID(1) | LANE1_ENGINE_ID(1) |