From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198

---
 kernel/drivers/mfd/rkx110_x120/rkx120_linkrx.c |  780 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 661 insertions(+), 119 deletions(-)

diff --git a/kernel/drivers/mfd/rkx110_x120/rkx120_linkrx.c b/kernel/drivers/mfd/rkx110_x120/rkx120_linkrx.c
index 45d965b..29f338b 100644
--- a/kernel/drivers/mfd/rkx110_x120/rkx120_linkrx.c
+++ b/kernel/drivers/mfd/rkx110_x120/rkx120_linkrx.c
@@ -24,6 +24,7 @@
  #define TRAIN_CLK_SEL_I2S		UPDATE(2, 31, 30)
  #define DUAL_LVDS_CHANNEL_SWAP		BIT(29)
  #define VIDEO_FREQ_AUTO_EN		BIT(28)
+ #define ENGINE_CFG_MASK		GENMASK(23, 20)
  #define ENGINE1_2_LANE			BIT(23)
  #define ENGINE1_EN			BIT(22)
  #define ENGINE0_2_LANE			BIT(21)
@@ -36,6 +37,9 @@
  #define LANE0_DATA_WIDTH_16BIT		UPDATE(1, 13, 12)
  #define LANE0_DATA_WIDTH_24BIT		UPDATE(2, 13, 12)
  #define LANE0_DATA_WIDTH_32BIT		UPDATE(3, 13, 12)
+ #define LANE1_PKT_LOSE_NUM_CLR		BIT(9)
+ #define LANE0_PKT_LOSE_NUM_CLR		BIT(8)
+ #define LANE_CFG_MASK			GENMASK(5, 4)
  #define LANE0_EN			BIT(4)
  #define LANE1_EN			BIT(5)
  #define DES_EN				BIT(0)
@@ -77,6 +81,7 @@
  #define ORDER_FIFO0_WR_ID(x)		UPDATE(x, 2, 0)
 
 #define RKLINK_DES_SOURCE_CFG		LINK_REG(0x0024)
+ #define E1_STREAM_CFG_MASK		GENMASK(23, 20)
  #define E1_CAMERA_SRC_CSI		UPDATE(0, 23, 21)
  #define E1_CAMERA_SRC_LVDS		UPDATE(1, 23, 21)
  #define E1_CAMERA_SRC_DVP		UPDATE(2, 23, 21)
@@ -87,6 +92,7 @@
  #define E1_DISPLAY_SRC_RGB		UPDATE(5, 23, 21)
  #define E1_STREAM_CAMERA		UPDATE(0, 20, 20)
  #define E1_STREAM_DISPLAY		UPDATE(1, 20, 20)
+ #define E0_STREAM_CFG_MASK		GENMASK(19, 16)
  #define E0_CAMERA_SRC_CSI		UPDATE(0, 19, 17)
  #define E0_CAMERA_SRC_LVDS		UPDATE(1, 19, 17)
  #define E0_CAMERA_SRC_DVP		UPDATE(2, 19, 17)
@@ -97,6 +103,7 @@
  #define E0_DISPLAY_SRC_RGB		UPDATE(5, 19, 17)
  #define E0_STREAM_CAMERA		UPDATE(0, 16, 16)
  #define E0_STREAM_DISPLAY		UPDATE(1, 16, 16)
+ #define LANE_ID_CFG_MASK		GENMASK(7, 0)
  #define LANE1_ENGINE_ID(x)		UPDATE(x, 7, 6)
  #define LANE1_LANE_ID(x)		UPDATE(x, 5, 5)
  #define LNAE1_ID_SEL(x)		UPDATE(x, 4, 4)
@@ -104,6 +111,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)
@@ -112,6 +122,42 @@
 #define E2_FIRST_FRAME_DEL		BIT(6)
 #define E1_FIRST_FRAME_DEL		BIT(5)
 #define E0_FIRST_FRAME_DEL		BIT(4)
+#define RKLINK_DES_FIFO_STATUS		LINK_REG(0x0084)
+ #define AUDIO_FIFO_UNDERRUN		BIT(29)
+ #define AUDIO_ORDER_UNDERRUN		BIT(28)
+ #define VIDEO_DATA_FIFO_UNDERRUN	BIT(27)
+ #define VIDEO_ORDER_UNDERRUN		BIT(26)
+ #define CMD_FIFO_UNDERRUN		BIT(25)
+ #define E1_ORDER_MIS			BIT(15)
+ #define E0_ORDER_MIS			BIT(14)
+ #define AUDIO_FIFO_OVERFLOW		BIT(13)
+ #define AUDIO_ORDER_OVERFLOW		BIT(12)
+ #define VIDEO_DATA_FIFO_OVERFLOW	GENMASK(11, 8)
+ #define VIDEO_ORDER_OVERFLOW		GENMASK(7, 4)
+ #define CMD_FIFO_OVERFLOW		GENMASK(3, 0)
+#define RKLINK_DES_SINK_IRQ_EN		LINK_REG(0x0088)
+ #define COMP_NOT_ENOUGH_IRQ_FLAG	BIT(26)
+ #define VIDEO_FM_IRQ_FLAG		BIT(25)
+ #define AUDIO_FM_IRQ_FLAG		BIT(24)
+ #define ORDER_MIS_IRQ_FLAG		BIT(23)
+ #define FIFO_UNDERRUN_IRQ_FLAG		BIT(22)
+ #define FIFO_OVERFLOW_IRQ_FLAG		BIT(21)
+ #define PKT_LOSE_IRQ_FLAG		BIT(20)
+ #define LAST_ERROR_IRQ_FLAG		BIT(19)
+ #define ECC2BIT_ERROR_IRQ_FLAG		BIT(18)
+ #define ECC1BIT_ERROR_IRQ_FLAG		BIT(17)
+ #define CRC_ERROR_IRQ_FLAG		BIT(16)
+ #define COMP_NOT_ENOUGH_IRQ_OUTPUT_EN	BIT(10)
+ #define VIDEO_FM_IRQ_OUTPUT_EN		BIT(9)
+ #define AUDIO_FM_IRQ_OUTPUT_EN		BIT(8)
+ #define ORDER_MIS_IRQ_OUTPUT_EN	BIT(7)
+ #define FIFO_UNDERRUN_IRQ_OUTPUT_EN	BIT(6)
+ #define FIFO_OVERFLOW_IRQ_OUTPUT_EN	BIT(5)
+ #define PKT_LOSE_IRQ_OUTPUT_EN		BIT(4)
+ #define LAST_ERROR_IRQ_OUTPUT_EN	BIT(3)
+ #define ECC2BIT_ERROR_IRQ_OUTPUT_EN	BIT(2)
+ #define ECC1BIT_ERROR_IRQ_OUTPUT_EN	BIT(1)
+ #define CRC_ERROR_IRQ_OUTPUT_EN	BIT(0)
 
 #define DES_RKLINK_STOP_CFG		LINK_REG(0x009C)
  #define STOP_AUDIO			BIT(4)
@@ -144,6 +190,7 @@
 #define PCS_REG24(id)			PCS_REG(id, 0x24)
 #define PCS_REG28(id)			PCS_REG(id, 0x28)
 #define PCS_REG30(id)			PCS_REG(id, 0x30)
+ #define DES_PCS_INI_EN(x)		HIWORD_UPDATE(x, GENMASK(15, 0), 0)
 #define PCS_REG34(id)			PCS_REG(id, 0x34)
 #define PCS_REG40(id)			PCS_REG(id, 0x40)
 
@@ -222,6 +269,19 @@
 
 #define DES_PMA_LOAD0E(id)		PMA_REG(id, 0x48)
 #define DES_PMA_REG100(id)		PMA_REG(id, 0x100)
+
+#define DES_PMA_IRQ_EN(id)		PMA_REG(id, 0xF0)
+ #define FORCE_INITIAL_IRQ_EN		HIWORD_UPDATE(1, BIT(6), 6)
+ #define RX_RDY_NEG_IRQ_EN		HIWORD_UPDATE(1, BIT(5), 5)
+ #define RX_LOS_IRQ_EN			HIWORD_UPDATE(1, BIT(4), 4)
+ #define RX_RDY_TIMEOUT_IRQ_EN		HIWORD_UPDATE(1, BIT(2), 2)
+ #define PLL_LOCK_TIMEOUT_IRQ_EN	HIWORD_UPDATE(1, BIT(0), 0)
+#define DES_PMA_IRQ_STATUS(id)		PMA_REG(id, 0xF4)
+ #define FORCE_INITIAL_IRQ_STATUS	BIT(6)
+ #define RX_RDY_NEG_IRQ_STATUS		BIT(5)
+ #define RX_LOS_IRQ_STATUS		BIT(4)
+ #define RX_RDY_TIMEOUT_IRQ_STATUS	BIT(2)
+ #define PLL_LOCK_TIMEOUT_IRQ_STATUS	BIT(0)
 
 static const struct rk_serdes_pt des_pt[] = {
 	{
@@ -409,9 +469,9 @@
 	},
 };
 
-static int rk_des_get_stream_source(struct rk_serdes_route *route, u32 port, u8 engine_id)
+static int rk_des_get_stream_source(u32 stream_type, u32 port, u8 engine_id)
 {
-	if (route->stream_type == STREAM_DISPLAY) {
+	if (stream_type == STREAM_DISPLAY) {
 		if (port & RK_SERDES_RGB_TX)
 			return engine_id ? E1_DISPLAY_SRC_RGB : E0_DISPLAY_SRC_RGB;
 		else if (port & RK_SERDES_LVDS_TX0)
@@ -472,139 +532,267 @@
 			      E1_FIRST_FRAME_DEL | E0_FIRST_FRAME_DEL);
 }
 
-static int rk120_link_rx_cfg(struct rk_serdes *serdes, struct rk_serdes_route *route, u8 remote_id)
+static int rk120_linkrx_des_enable(struct rk_serdes *serdes, u8 dev_id, bool enable)
 {
-	struct hwclk *hwclk = serdes->chip[remote_id].hwclk;
-	struct i2c_client *client;
-	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;
+	struct i2c_client *client = serdes->chip[dev_id].client;
 
-	if (route->stream_type == STREAM_DISPLAY) {
-		client = serdes->chip[remote_id].client;
-		stream_type = E0_STREAM_DISPLAY;
+	serdes->i2c_update_bits(client, RKLINK_DES_LANE_ENGINE_CFG, DES_EN, enable ? DES_EN : 0);
+
+	return 0;
+}
+
+static int rk120_linkrx_video_fm_enable(struct rk_serdes *serdes, u8 dev_id, bool enable)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+
+	serdes->i2c_update_bits(client, RKLINK_DES_LANE_ENGINE_CFG, VIDEO_FREQ_AUTO_EN,
+				enable ? VIDEO_FREQ_AUTO_EN : 0);
+
+	return 0;
+}
+
+static int rk120_linkrx_engine_lane_enable(struct rk_serdes *serdes, u8 dev_id,
+					   bool dual_channels, bool dual_lanes)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val = 0;
+
+	/*
+	 * config engine and lane as fallow:
+	 * 1.linkrx receive 1 channel data in 1 lane, enable engine0 and engine0 use 1 lane.
+	 * 2.linkrx receive 1 channel data in 2 lane, enable engine0 and engine0 user 2 lanes.
+	 * 3.linkrx receive 2 channel data in 1 lane, enable engine0, enagine1. engine0 use
+	 *   1 lane, engine1 use 1 lane.
+	 * 4.linkrx receive 2 channel data in 2 lane, enable engine0, enagine1. engine0 use
+	 *   1 lane, engine1 use 1 lane.
+	 */
+	if (dual_channels) {
+		val |= ENGINE0_EN | ENGINE1_EN;
 	} else {
-		client = serdes->chip[DEVICE_LOCAL].client;
-		stream_type = E0_STREAM_CAMERA;
+		val |= ENGINE0_EN;
+		if (dual_lanes)
+			val |= ENGINE0_2_LANE;
 	}
 
-	is_rx_dual_lanes = (serdes->route_flag & ROUTE_MULTI_LANE) &&
-			   !(serdes->route_flag & ROUTE_MULTI_REMOTE);
-	is_rx_dual_channels = (serdes->route_flag & ROUTE_MULTI_CHANNEL) &&
-			       !(serdes->route_flag & ROUTE_MULTI_REMOTE);
+	serdes->i2c_update_bits(client, RKLINK_DES_LANE_ENGINE_CFG, ENGINE_CFG_MASK, val);
 
-	serdes->i2c_read_reg(client, RKLINK_DES_LANE_ENGINE_CFG, &ctrl_val);
+	return 0;
+}
 
-	ctrl_val &= ~LANE1_EN;
-	ctrl_val |= LANE0_EN;
-	ctrl_val |= ENGINE0_EN;
-	if (is_rx_dual_lanes) {
-		ctrl_val |= LANE1_EN;
-		if (is_rx_dual_channels)
-			ctrl_val |= ENGINE1_EN;
-		else
-			ctrl_val |= ENGINE0_2_LANE;
-	} else {
-		if (is_rx_dual_channels)
-			ctrl_val |= ENGINE1_EN;
-	}
-	serdes->i2c_write_reg(client, RKLINK_DES_LANE_ENGINE_CFG, ctrl_val);
+static int rk120_linkrx_lane_enable(struct rk_serdes *serdes, u8 dev_id, u32 lanes)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val;
 
-	mask = LANE0_ENGINE_CFG_MASK;
-	val = LANE0_ENGINE0;
-	if (is_rx_dual_lanes) {
-		if (is_rx_dual_channels) {
-			mask |= LANE1_ENGINE_CFG_MASK;
-			val |= LANE1_ENGINE1;
+	/*
+	 * when 1 lane connect to linkrx, enable lane0;
+	 * when 2 lane connect to linkrx, enable lane0 and lane1;
+	 */
+
+	if (lanes == 1)
+		val = LANE0_EN;
+	else if (lanes == 2)
+		val = LANE0_EN | LANE1_EN;
+	else
+		val = 0;
+
+	serdes->i2c_update_bits(client, RKLINK_DES_LANE_ENGINE_CFG, LANE_CFG_MASK, val);
+
+	return 0;
+}
+
+static int rk120_linkrx_lane_engine_dst_cfg(struct rk_serdes *serdes, u8 dev_id,
+					     bool dual_channels, bool dual_lanes)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 mask, val;
+
+	/*
+	 * config lane dst engine as fallow:
+	 * 1. 1 channel 1 lane: lane0 data send to engine0
+	 * 2. 1 channel 2 lane: lane0 data send to engine0, lane1 data send to engine0
+	 * 3. 2 channel 1 lane: lane0 data send to engine0, lane0 data send to engine1
+	 * 4. 2 channel 2 lane: lane0 data send to engine0, lane1 data send to engine1
+	 */
+	if (dual_channels) {
+		if (dual_lanes) {
+			mask = LANE0_ENGINE_CFG_MASK | LANE1_ENGINE_CFG_MASK;
+			val = LANE0_ENGINE0 | LANE1_ENGINE1;
 		} else {
-			mask |= LANE1_ENGINE_CFG_MASK;
-			val |= LANE1_ENGINE0;
+			mask = LANE0_ENGINE_CFG_MASK | LANE1_ENGINE_CFG_MASK;
+			val = LANE0_ENGINE0 | LANE0_ENGINE1;
 		}
 	} else {
-		if (is_rx_dual_channels)
-			val |= LANE0_ENGINE1;
-	}
 
+		if (dual_lanes) {
+			mask = LANE0_ENGINE_CFG_MASK | LANE1_ENGINE_CFG_MASK;
+			val = LANE0_ENGINE0 | LANE1_ENGINE0;
+		} else {
+			mask = LANE0_ENGINE_CFG_MASK | LANE1_ENGINE_CFG_MASK;
+			val = LANE0_ENGINE0 | LANE1_ENGINE1;
+		}
+	}
 	serdes->i2c_update_bits(client, RKLINK_DES_LANE_ENGINE_DST, mask, val);
 
-	serdes->i2c_read_reg(client, RKLINK_DES_SOURCE_CFG, &val);
+	return 0;
+}
 
-	val &= ~(LANE0_ENGINE_ID(1) | LANE0_LANE_ID(1) | LANE1_ENGINE_ID(1) |
-		 LANE1_LANE_ID(1) | LNAE0_ID_SEL(1) | LNAE1_ID_SEL(1));
+static int rk120_linkrx_config_pkt_length(struct rk_serdes *serdes, u8 dev_id, u32 length)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
 
-	if (is_rx_dual_lanes) {
-		if (is_rx_dual_channels) {
-			val |= LANE0_ENGINE_ID(0);
-			val |= LANE0_LANE_ID(0);
-			val |= LNAE0_ID_SEL(1);
-			val |= LANE1_ENGINE_ID(1);
-			val |= LANE1_LANE_ID(0);
-			val |= LNAE1_ID_SEL(1);
-			stream_type |= E1_STREAM_DISPLAY;
+	serdes->i2c_write_reg(client, DES_RKLINK_REC01_PKT_LENGTH, E0_REPKT_LENGTH(length) |
+			      E1_REPKT_LENGTH(length));
+
+	return 0;
+}
+
+static int rk120_linkrx_lane_id_cfg(struct rk_serdes *serdes, u8 dev_id,
+				     bool dual_channels, bool dual_lanes)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val;
+
+	if (dual_channels) {
+		if (dual_lanes) {
+			val = LANE0_ENGINE_ID(0) | LANE0_LANE_ID(0) | LNAE0_ID_SEL(1) |
+			      LANE1_ENGINE_ID(1) | LANE1_LANE_ID(0) | LNAE1_ID_SEL(1);
 		} else {
-			val |= LANE0_ENGINE_ID(0);
-			val |= LANE0_LANE_ID(0);
-			val |= LNAE0_ID_SEL(1);
-			val |= LANE1_ENGINE_ID(0);
-			val |= LANE1_LANE_ID(1);
-			val |= LNAE0_ID_SEL(1);
+			val = LANE0_ENGINE_ID(0) | LANE0_LANE_ID(0) | LANE1_ENGINE_ID(1) |
+			      LANE1_LANE_ID(0);
 		}
 	} else {
-		if (is_rx_dual_channels) {
-			val |= LANE0_ENGINE_ID(0);
-			val |= LANE0_LANE_ID(0);
-			val |= LANE1_ENGINE_ID(1);
-			val |= LANE1_LANE_ID(0);
-			stream_type |= E1_STREAM_DISPLAY;
+		if (dual_lanes) {
+			val = LANE0_ENGINE_ID(0) | LANE0_LANE_ID(0) | LNAE0_ID_SEL(1) |
+			      LANE1_ENGINE_ID(0) | LANE1_LANE_ID(1) | LNAE1_ID_SEL(1);
 		} else {
-			val |= LNAE0_ID_SEL(1);
+			val = LNAE0_ID_SEL(1);
 		}
 	}
-	val |= stream_type;
-	if (remote_id == DEVICE_REMOTE0)
-		rx_src = rk_des_get_stream_source(route, route->remote0_port0, 0);
-	else
-		rx_src = rk_des_get_stream_source(route, route->remote1_port0, 0);
-	val |= rx_src;
-	if (is_rx_dual_channels) {
-		rx_src = rk_des_get_stream_source(route, route->remote0_port1, 1);
-		val |= rx_src;
-	}
-	serdes->i2c_write_reg(client, RKLINK_DES_SOURCE_CFG, val);
 
-	if (is_rx_dual_lanes || is_rx_dual_channels) {
-		mask = DATA_FIFO0_WR_ID_MASK | DATA_FIFO1_WR_ID_MASK | DATA_FIFO2_WR_ID_MASK |
-			DATA_FIFO3_WR_ID_MASK;
-		mask |= DATA_FIFO0_RD_ID_MASK | DATA_FIFO1_RD_ID_MASK | DATA_FIFO2_RD_ID_MASK |
-			DATA_FIFO3_RD_ID_MASK;
-		if (is_rx_dual_channels) {
-			lane0_dsource_id = (0 << 1) | 0;
-			lane1_dsource_id = (1 << 1) | 0;
-		} else {
+	serdes->i2c_update_bits(client, RKLINK_DES_SOURCE_CFG, LANE_ID_CFG_MASK, val);
+
+	return 0;
+}
+
+static int rk120_linkrx_stream_type_cfg(struct rk_serdes *serdes, u32 stream_type,
+					 u8 dev_id, u32 port, u32 engine_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val, mask, rx_src;
+
+	mask = engine_id ? E1_STREAM_CFG_MASK : E0_STREAM_CFG_MASK;
+	if (stream_type == STREAM_DISPLAY)
+		val =  engine_id ? E1_STREAM_DISPLAY : E0_STREAM_DISPLAY;
+	else
+		val =  engine_id ? E1_STREAM_CAMERA : E0_STREAM_CAMERA;
+
+	rx_src = rk_des_get_stream_source(stream_type, port, engine_id);
+	val |= rx_src;
+	serdes->i2c_update_bits(client, RKLINK_DES_SOURCE_CFG, mask, val);
+
+	return 0;
+}
+
+static int rk120_linkrx_data_and_order_id_cfg(struct rk_serdes *serdes, u8 dev_id,
+					       bool dual_channels, bool dual_lanes)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 lane0_dsource_id, lane1_dsource_id;
+	u32 data_id_mask;
+	u32 order_id_mask;
+	u32 val;
+
+	data_id_mask = DATA_FIFO0_WR_ID_MASK | DATA_FIFO1_WR_ID_MASK |
+		       DATA_FIFO2_WR_ID_MASK | DATA_FIFO3_WR_ID_MASK |
+		       DATA_FIFO0_RD_ID_MASK | DATA_FIFO1_RD_ID_MASK |
+		       DATA_FIFO2_RD_ID_MASK | DATA_FIFO3_RD_ID_MASK;
+	order_id_mask = ORDER_FIFO0_WR_ID_MASK | ORDER_FIFO1_WR_ID_MASK |
+			ORDER_FIFO0_RD_ID_MASK | ORDER_FIFO1_RD_ID_MASK;
+
+	if (dual_channels) {
+		lane0_dsource_id = (0 << 1) | 0;
+		lane1_dsource_id = (1 << 1) | 0;
+	} else {
+		if (dual_lanes) {
 			lane0_dsource_id = (0 << 1) | 0;
 			lane1_dsource_id = (0 << 1) | 1;
+		} else {
+			lane0_dsource_id = (0 << 1) | 0;
+			lane1_dsource_id = (1 << 1) | 0;
 		}
-		val = DATA_FIFO0_WR_ID(lane0_dsource_id) | DATA_FIFO1_WR_ID(lane0_dsource_id);
-		val |= DATA_FIFO0_RD_ID(lane0_dsource_id) | DATA_FIFO1_RD_ID(lane0_dsource_id);
-
-		val |= DATA_FIFO2_WR_ID(lane1_dsource_id) | DATA_FIFO3_WR_ID(lane1_dsource_id);
-		val |= DATA_FIFO2_RD_ID(lane1_dsource_id) | DATA_FIFO3_RD_ID(lane1_dsource_id);
-
-		serdes->i2c_update_bits(client, RKLINK_DES_DATA_ID_CFG, mask, val);
-
-		mask = ORDER_FIFO0_WR_ID_MASK | ORDER_FIFO1_WR_ID_MASK |
-			ORDER_FIFO0_RD_ID_MASK | ORDER_FIFO1_RD_ID_MASK;
-		val = ORDER_FIFO0_WR_ID(lane0_dsource_id) | ORDER_FIFO1_WR_ID(lane1_dsource_id) |
-			ORDER_FIFO0_RD_ID(lane0_dsource_id) | ORDER_FIFO1_RD_ID(lane1_dsource_id);
-
-		serdes->i2c_update_bits(client, RKLINK_DES_ORDER_ID_CFG, mask, val);
 	}
 
-	ctrl_val |= DES_EN;
-	serdes->i2c_write_reg(client, RKLINK_DES_LANE_ENGINE_CFG, ctrl_val);
+	val = DATA_FIFO0_WR_ID(lane0_dsource_id) | DATA_FIFO1_WR_ID(lane0_dsource_id) |
+	      DATA_FIFO0_RD_ID(lane0_dsource_id) | DATA_FIFO1_RD_ID(lane0_dsource_id) |
+	      DATA_FIFO2_WR_ID(lane1_dsource_id) | DATA_FIFO3_WR_ID(lane1_dsource_id) |
+	      DATA_FIFO2_RD_ID(lane1_dsource_id) | DATA_FIFO3_RD_ID(lane1_dsource_id);
+	serdes->i2c_update_bits(client, RKLINK_DES_DATA_ID_CFG, data_id_mask, val);
+
+	val = ORDER_FIFO0_WR_ID(lane0_dsource_id) | ORDER_FIFO1_WR_ID(lane1_dsource_id) |
+	      ORDER_FIFO0_RD_ID(lane0_dsource_id) | ORDER_FIFO1_RD_ID(lane1_dsource_id);
+
+	serdes->i2c_update_bits(client, RKLINK_DES_ORDER_ID_CFG, order_id_mask, val);
+
+	return 0;
+}
+
+static int rk120_display_linkrx_cfg(struct rk_serdes *serdes,
+				    struct rk_serdes_route *route, u8 dev_id)
+{
+	struct hwclk *hwclk = serdes->chip[dev_id].hwclk;
+	bool is_rx_dual_lanes = false;
+	bool is_rx_dual_channels = false;
+
+	if (serdes->route_nr == 1) {
+		is_rx_dual_lanes = (serdes->lane_nr == 2) &&
+				   !(route->route_flag & ROUTE_MULTI_REMOTE);
+		is_rx_dual_channels = (route->route_flag & ROUTE_MULTI_CHANNEL) &&
+				       !(route->route_flag & ROUTE_MULTI_REMOTE);
+	} else {
+		is_rx_dual_lanes = (serdes->lane_nr == 2) && (serdes->remote_nr == 1);
+		is_rx_dual_channels = (serdes->channel_nr == 2) && (serdes->remote_nr == 1);
+	}
+
+	rk120_linkrx_video_fm_enable(serdes, dev_id, true);
+	rk120_linkrx_engine_lane_enable(serdes, dev_id, is_rx_dual_channels, is_rx_dual_lanes);
+	rk120_linkrx_lane_enable(serdes, dev_id, is_rx_dual_lanes ? 2 : 1);
+
+	rk120_linkrx_lane_engine_dst_cfg(serdes, dev_id, is_rx_dual_channels, is_rx_dual_lanes);
+	rk120_linkrx_lane_id_cfg(serdes, dev_id, is_rx_dual_channels, is_rx_dual_lanes);
+	if (route->local_port0) {
+		if (dev_id == DEVICE_REMOTE0) {
+			rk120_linkrx_stream_type_cfg(serdes, route->stream_type, dev_id,
+						     route->remote0_port0, 0);
+			if (is_rx_dual_channels)
+				rk120_linkrx_stream_type_cfg(serdes, route->stream_type, dev_id,
+						     route->remote0_port1, 1);
+		} else {
+			rk120_linkrx_stream_type_cfg(serdes, route->stream_type, dev_id,
+						     route->remote1_port0, 0);
+		}
+	} else {
+		rk120_linkrx_stream_type_cfg(serdes, route->stream_type, dev_id,
+					     route->remote1_port0, 0);
+	}
+
+	rk120_linkrx_data_and_order_id_cfg(serdes, dev_id, is_rx_dual_channels,
+					    is_rx_dual_lanes);
+	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
+		 */
+		u32 length;
+
+		length = route->vm.hactive * 24 / 32 / 16;
+		length = (length + 15) / 16 * 16;
+		rk120_linkrx_config_pkt_length(serdes, dev_id, length);
+	}
+
+	rk120_linkrx_des_enable(serdes, dev_id, true);
 
 	hwclk_set_rate(hwclk, RKX120_CPS_E0_CLK_RKLINK_RX_PRE, route->vm.pixelclock);
 	dev_info(serdes->dev, "RKX120_CPS_E0_CLK_RKLINK_RX_PRE:%d\n",
@@ -616,17 +804,17 @@
 	}
 
 	if (route->remote0_port0 == RK_SERDES_RGB_TX || route->remote1_port0 == RK_SERDES_RGB_TX)
-		rk_serdes_link_rx_rgb_enable(serdes, route, remote_id);
+		rk_serdes_link_rx_rgb_enable(serdes, route, dev_id);
 
 	if (route->remote0_port0 == RK_SERDES_LVDS_TX0 ||
 	    route->remote1_port0 == RK_SERDES_LVDS_TX0 ||
 	    route->remote0_port0 == RK_SERDES_LVDS_TX1 ||
 	    route->remote1_port0 == RK_SERDES_LVDS_TX1 ||
 	    route->remote0_port0 == RK_SERDES_DUAL_LVDS_TX)
-		rk_serdes_link_rx_lvds_enable(serdes, route, remote_id);
+		rk_serdes_link_rx_lvds_enable(serdes, route, dev_id);
 
 	if (route->remote0_port0 == RK_SERDES_DSI_TX0 || route->remote1_port0 == RK_SERDES_DSI_TX0)
-		rk_serdes_link_rx_dsi_enable(serdes, route, remote_id);
+		rk_serdes_link_rx_dsi_enable(serdes, route, dev_id);
 
 	return 0;
 }
@@ -643,17 +831,18 @@
 	return 0;
 }
 
-int rkx120_linkrx_enable(struct rk_serdes *serdes, struct rk_serdes_route *route, u8 remote_id)
+int rkx120_display_linkrx_enable(struct rk_serdes *serdes,
+				 struct rk_serdes_route *route, u8 dev_id)
 {
-	rk120_link_rx_cfg(serdes, route, remote_id);
+	rk120_display_linkrx_cfg(serdes, route, dev_id);
 
-	rk120_des_pcs_cfg(serdes, route, remote_id, 0);
-	rk120_des_pma_cfg(serdes, route, remote_id, 0);
-	if ((serdes->route_flag & ROUTE_MULTI_LANE) &&
-	    !(serdes->route_flag & ROUTE_MULTI_REMOTE)) {
-		rk120_des_pcs_cfg(serdes, route, remote_id, 1);
-		rk120_des_pma_cfg(serdes, route, remote_id, 1);
+	rk120_des_pcs_cfg(serdes, route, dev_id, 0);
+	rk120_des_pma_cfg(serdes, route, dev_id, 0);
+	if ((serdes->lane_nr == 2) && (serdes->remote_nr == 1)) {
+		rk120_des_pcs_cfg(serdes, route, dev_id, 1);
+		rk120_des_pma_cfg(serdes, route, dev_id, 1);
 	}
+
 
 	return 0;
 }
@@ -691,7 +880,7 @@
 	}
 }
 
-void rkx120_linkrx_wait_link_ready(struct rk_serdes *serdes, u8 id)
+int rkx120_linkrx_wait_link_ready(struct rk_serdes *serdes, u8 id)
 {
 	struct i2c_client *client = serdes->chip[DEVICE_LOCAL].client;
 	u32 val;
@@ -711,6 +900,8 @@
 		dev_err(&client->dev, "wait link ready timeout: 0x%08x\n", val);
 	else
 		dev_info(&client->dev, "link success: 0x%08x\n", val);
+
+	return ret;
 }
 
 static void rkx120_pma_link_config(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
@@ -795,3 +986,354 @@
 
 	serdes->i2c_update_bits(client, DES_GRF_SOC_CON4, mask, val);
 }
+
+
+static void rkx120_linkrx_irq_enable(struct rk_serdes *serdes, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+
+	serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_LINK_EN);
+
+	serdes->i2c_write_reg(client, RKLINK_DES_SINK_IRQ_EN, FIFO_UNDERRUN_IRQ_OUTPUT_EN |
+			      FIFO_OVERFLOW_IRQ_OUTPUT_EN);
+}
+
+static void rkx120_linkrx_irq_disable(struct rk_serdes *serdes, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val = 0;
+
+	serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_LINK_DIS);
+
+	serdes->i2c_read_reg(client, RKLINK_DES_SINK_IRQ_EN, &val);
+	val &= ~(FIFO_UNDERRUN_IRQ_OUTPUT_EN | FIFO_OVERFLOW_IRQ_OUTPUT_EN);
+	serdes->i2c_write_reg(client, RKLINK_DES_SINK_IRQ_EN, val);
+}
+
+static void rkx120_linkrx_fifo_handler(struct rk_serdes *serdes, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 value;
+
+	serdes->i2c_read_reg(client, RKLINK_DES_FIFO_STATUS, &value);
+	dev_err(serdes->dev, "des rklink fifo status:0x%x\n", value);
+
+	if (value & AUDIO_FIFO_UNDERRUN)
+		dev_err(serdes->dev, "linkrx audio fifo underrun\n");
+	if (value & AUDIO_ORDER_UNDERRUN)
+		dev_err(serdes->dev, "linkrx audio order underrun\n");
+	if (value & VIDEO_DATA_FIFO_UNDERRUN)
+		dev_err(serdes->dev, "linkrx video data fifo underrun\n");
+	if (value & VIDEO_ORDER_UNDERRUN)
+		dev_err(serdes->dev, "linkrx video order underrun\n");
+	if (value & CMD_FIFO_UNDERRUN)
+		dev_err(serdes->dev, "linkrx cmd fifo underrun\n");
+	if (value & E1_ORDER_MIS)
+		dev_err(serdes->dev, "linkrx e1 order miss\n");
+	if (value & E0_ORDER_MIS)
+		dev_err(serdes->dev, "linkrx e0 order miss\n");
+	if (value & AUDIO_FIFO_OVERFLOW)
+		dev_err(serdes->dev, "linkrx audio fifo overflow\n");
+	if (value & AUDIO_ORDER_OVERFLOW)
+		dev_err(serdes->dev, "linkrx audio order overflow\n");
+	if (value & VIDEO_DATA_FIFO_OVERFLOW)
+		dev_err(serdes->dev, "linkrx video data fifo overflow\n");
+	if (value & VIDEO_ORDER_OVERFLOW)
+		dev_err(serdes->dev, "linkrx video order overflow\n");
+	if (value & CMD_FIFO_OVERFLOW)
+		dev_err(serdes->dev, "linkrx cmd fifo overflow\n");
+
+	serdes->i2c_write_reg(client, RKLINK_DES_FIFO_STATUS, value);
+}
+
+static void rkx120_linkrx_irq_handler(struct rk_serdes *serdes, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 flag, value;
+	int i = 0;
+
+	serdes->i2c_read_reg(client, RKLINK_DES_SINK_IRQ_EN, &flag);
+	flag &= COMP_NOT_ENOUGH_IRQ_FLAG | VIDEO_FM_IRQ_FLAG | AUDIO_FM_IRQ_FLAG |
+		ORDER_MIS_IRQ_FLAG | FIFO_UNDERRUN_IRQ_FLAG | FIFO_OVERFLOW_IRQ_FLAG |
+		PKT_LOSE_IRQ_FLAG | LAST_ERROR_IRQ_FLAG | ECC2BIT_ERROR_IRQ_FLAG |
+		ECC1BIT_ERROR_IRQ_FLAG | CRC_ERROR_IRQ_FLAG;
+	dev_info(serdes->dev, "linkrx irq flag:0x%08x\n", flag);
+	while (flag) {
+		switch (flag & BIT(i)) {
+		case COMP_NOT_ENOUGH_IRQ_FLAG:
+			break;
+		case VIDEO_FM_IRQ_FLAG:
+			break;
+		case AUDIO_FM_IRQ_FLAG:
+			break;
+		case ORDER_MIS_IRQ_FLAG:
+		case FIFO_UNDERRUN_IRQ_FLAG:
+		case FIFO_OVERFLOW_IRQ_FLAG:
+			flag &= ~(ORDER_MIS_IRQ_FLAG | FIFO_UNDERRUN_IRQ_FLAG |
+				FIFO_OVERFLOW_IRQ_FLAG);
+			rkx120_linkrx_fifo_handler(serdes, dev_id);
+			break;
+		case PKT_LOSE_IRQ_FLAG:
+			/* clear pkt lost irq flag */
+			serdes->i2c_read_reg(client, RKLINK_DES_LANE_ENGINE_CFG, &value);
+			value |= LANE0_PKT_LOSE_NUM_CLR | LANE1_PKT_LOSE_NUM_CLR;
+			serdes->i2c_write_reg(client, RKLINK_DES_LANE_ENGINE_CFG, value);
+			break;
+		case LAST_ERROR_IRQ_FLAG:
+		case ECC2BIT_ERROR_IRQ_FLAG:
+		case ECC1BIT_ERROR_IRQ_FLAG:
+		case CRC_ERROR_IRQ_FLAG:
+			flag &= ~(LAST_ERROR_IRQ_FLAG | ECC2BIT_ERROR_IRQ_FLAG |
+				ECC1BIT_ERROR_IRQ_FLAG | CRC_ERROR_IRQ_FLAG);
+			serdes->i2c_read_reg(client, RKLINK_DES_SINK_IRQ_EN, &value);
+			dev_info(serdes->dev, "linkrx ecc crc result:0x%08x\n", value);
+			/* clear ecc crc irq flag */
+			serdes->i2c_write_reg(client, RKLINK_DES_SINK_IRQ_EN, value);
+			break;
+		default:
+			break;
+		}
+		flag &= ~BIT(i);
+		i++;
+	}
+}
+static void rkx120_pcs_irq_enable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val = 0;
+
+	val = pcs_id ? DES_IRQ_PCS1_EN : DES_IRQ_PCS0_EN;
+	serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
+
+	serdes->i2c_write_reg(client, PCS_REG30(pcs_id), DES_PCS_INI_EN(0xffff));
+}
+
+static void rkx120_pcs_irq_disable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val = 0;
+
+	val = pcs_id ? DES_IRQ_PCS1_DIS : DES_IRQ_PCS0_DIS;
+	serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
+
+	serdes->i2c_write_reg(client, PCS_REG30(pcs_id), DES_PCS_INI_EN(0));
+}
+
+static void rkx120_pcs_irq_handler(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 value;
+
+	serdes->i2c_read_reg(client, PCS_REG20(pcs_id), &value);
+	dev_info(serdes->dev, "des pcs%d fatal status:0x%08x\n", pcs_id, value);
+
+	/* clear fatal status */
+	serdes->i2c_write_reg(client, PCS_REG10(pcs_id), 0xffffffff);
+	serdes->i2c_write_reg(client, PCS_REG10(pcs_id), 0xffff0000);
+}
+
+static void rkx120_pma_irq_enable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val = 0;
+
+	val = pcs_id ? DES_IRQ_PMA_ADAPT1_EN : DES_IRQ_PMA_ADAPT0_EN;
+	serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
+
+	serdes->i2c_write_reg(client, DES_PMA_IRQ_EN(pcs_id), FORCE_INITIAL_IRQ_EN |
+			      RX_RDY_NEG_IRQ_EN | RX_LOS_IRQ_EN | RX_RDY_TIMEOUT_IRQ_EN |
+			      PLL_LOCK_TIMEOUT_IRQ_EN);
+}
+
+static void rkx120_pma_irq_disable(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 val = 0;
+
+	val = pcs_id ? DES_IRQ_PMA_ADAPT1_DIS : DES_IRQ_PMA_ADAPT0_DIS;
+	serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, val);
+
+	serdes->i2c_write_reg(client, DES_PMA_IRQ_EN(pcs_id), 0);
+}
+
+static void rkx120_pma_irq_handler(struct rk_serdes *serdes, u8 pcs_id, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 value;
+
+	serdes->i2c_read_reg(client, DES_PMA_IRQ_STATUS(pcs_id), &value);
+	dev_info(serdes->dev, "des pma%d irq status:0x%08x\n", pcs_id, value);
+
+	if (value & FORCE_INITIAL_IRQ_STATUS)
+		dev_info(serdes->dev, "des pma trig force initial pulse status\n");
+	else if (value & RX_RDY_NEG_IRQ_STATUS)
+		dev_info(serdes->dev, "des pma trig rx rdy neg status\n");
+	else if (value & RX_LOS_IRQ_STATUS)
+		dev_info(serdes->dev, "des pma trig rx los status\n");
+	else if (value & RX_RDY_TIMEOUT_IRQ_STATUS)
+		dev_info(serdes->dev, "des pma trig rx rdy timeout status\n");
+	else if (value & PLL_LOCK_TIMEOUT_IRQ_STATUS)
+		dev_info(serdes->dev, "des pma trig pll lock timeout status\n");
+
+	/* clear pma irq status */
+	serdes->i2c_write_reg(client, DES_PMA_IRQ_STATUS(pcs_id), value);
+}
+
+static void rkx120_remote_irq_enable(struct rk_serdes *serdes, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+
+	if (serdes->stream_type == STREAM_CAMERA) {
+		serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_REMOTE_EN);
+		rkx110_irq_enable(serdes, DEVICE_REMOTE0);
+	}
+}
+
+static void rkx120_remote_irq_disable(struct rk_serdes *serdes, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+
+	if (serdes->stream_type == STREAM_CAMERA) {
+		serdes->i2c_write_reg(client, DES_GRF_IRQ_EN, DES_IRQ_REMOTE_DIS);
+		rkx110_irq_disable(serdes, DEVICE_REMOTE0);
+	}
+}
+
+static void rkx120_remote_irq_handler(struct rk_serdes *serdes, u8 dev_id)
+{
+	if (serdes->stream_type == STREAM_CAMERA)
+		rkx110_irq_handler(serdes, DEVICE_REMOTE0);
+}
+
+void rkx120_irq_enable(struct rk_serdes *serdes, u8 dev_id)
+{
+	/* enable pcs irq */
+	rkx120_pcs_irq_enable(serdes, 0, dev_id);
+
+	/* enable efuse irq */
+
+	/* enable gpio irq */
+
+	/* enable csitx irq */
+
+	/* enable mipi dsi host irq */
+
+	/* enable pma adapt irq */
+	rkx120_pma_irq_enable(serdes, 0, dev_id);
+
+	/* enable remote irq and other lane irq */
+	rkx120_remote_irq_enable(serdes, dev_id);
+
+	/* enable pwm irq */
+
+	/* enable dvp tx irq */
+
+	/* enable link irq */
+	rkx120_linkrx_irq_enable(serdes, dev_id);
+
+	/* enable ext irq */
+
+	/* enable ext irq */
+}
+
+void rkx120_irq_disable(struct rk_serdes *serdes, u8 dev_id)
+{
+	/* disable pcs irq */
+	rkx120_pcs_irq_disable(serdes, 0, dev_id);
+
+	/* disable efuse irq */
+
+	/* disable gpio irq */
+
+	/* disable csitx irq */
+
+	/* disable mipi dsi host irq */
+
+	/* disable pma adapt irq */
+	rkx120_pma_irq_disable(serdes, 0, dev_id);
+
+	/* disable remote irq */
+	rkx120_remote_irq_disable(serdes, dev_id);
+
+	/* disable pwm irq */
+
+	/* disable dvp tx irq */
+
+	/* disable link irq */
+	rkx120_linkrx_irq_disable(serdes, dev_id);
+
+	/* disable ext irq */
+}
+
+int rkx120_irq_handler(struct rk_serdes *serdes, u8 dev_id)
+{
+	struct i2c_client *client = serdes->chip[dev_id].client;
+	u32 status = 0;
+	u32 mask = 0;
+	u32 i = 0;
+
+	serdes->i2c_read_reg(client, DES_GRF_IRQ_EN, &mask);
+	serdes->i2c_read_reg(client, DES_GRF_IRQ_STATUS, &status);
+	dev_info(serdes->dev, "dev%d get the des irq status:0x%08x\n", dev_id, status);
+	status &= mask;
+
+	while (status) {
+		switch (status & BIT(i)) {
+		case DES_IRQ_PCS0:
+			rkx120_pcs_irq_handler(serdes, 0, dev_id);
+			break;
+		case DES_IRQ_PCS1:
+			rkx120_pcs_irq_handler(serdes, 1, dev_id);
+			break;
+		case DES_IRQ_EFUSE:
+			/* TBD */
+			break;
+		case DES_IRQ_GPIO0:
+			/* TBD */
+			break;
+		case DES_IRQ_GPIO1:
+			/* TBD */
+			break;
+		case DES_IRQ_CSITX0:
+			/* TBD */
+			break;
+		case DES_IRQ_CSITX1:
+			/* TBD */
+			break;
+		case DES_IRQ_MIPI_DSI_HOST:
+			/* TBD */
+			break;
+		case DES_IRQ_PMA_ADAPT0:
+			rkx120_pma_irq_handler(serdes, 0, dev_id);
+			break;
+		case DES_IRQ_PMA_ADAPT1:
+			rkx120_pma_irq_handler(serdes, 1, dev_id);
+			break;
+		case DES_IRQ_REMOTE:
+			rkx120_remote_irq_handler(serdes, dev_id);
+			break;
+		case DES_IRQ_PWM:
+			/* TBD */
+			break;
+		case DES_IRQ_DVP_TX:
+			/* TBD */
+			break;
+		case DES_IRQ_LINK:
+			rkx120_linkrx_irq_handler(serdes, dev_id);
+			break;
+		case DES_IRQ_EXT:
+			/* TBD */
+			break;
+		case DES_IRQ_OTHER_LANE:
+			/* TBD */
+			break;
+		default:
+			break;
+		}
+		status &= ~BIT(i);
+		i++;
+	}
+
+	return 0;
+}
+

--
Gitblit v1.6.2