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/rkx110_x120_core.c |  474 ++++++++++++++++++++++++++++------------------------------
 1 files changed, 229 insertions(+), 245 deletions(-)

diff --git a/kernel/drivers/mfd/rkx110_x120/rkx110_x120_core.c b/kernel/drivers/mfd/rkx110_x120/rkx110_x120_core.c
index 95d875b..ee9e962 100644
--- a/kernel/drivers/mfd/rkx110_x120/rkx110_x120_core.c
+++ b/kernel/drivers/mfd/rkx110_x120/rkx110_x120_core.c
@@ -10,9 +10,12 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
+#include <linux/irq.h>
 #include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
 #include <linux/mfd/core.h>
 #include "rkx110_x120.h"
+#include "rkx110_x120_display.h"
 #include "rkx110_reg.h"
 #include "rkx110_dsi_rx.h"
 #include "rkx120_dsi_tx.h"
@@ -22,8 +25,44 @@
 static const struct mfd_cell rkx110_x120_devs[] = {
 	/* 2 panel device for rkx110_x120 drm panel */
 	{
-		.name = "serdes-panel",
+		.name = "rockchip-serdes-panel",
 		.of_compatible = "rockchip,serdes-panel",
+	},
+	{
+		.name = "rockchip-serdes-panel1",
+		.of_compatible = "rockchip,serdes-panel",
+	},
+	{
+		.name = "rkx120-pwm0",
+		.of_compatible = "rockchip,rkx120-pwm",
+	},
+	{
+		.name = "rkx120-pwm1",
+		.of_compatible = "rockchip,rkx120-pwm",
+	},
+	{
+		.name = "rkx120-pwm2",
+		.of_compatible = "rockchip,rkx120-pwm",
+	},
+	{
+		.name = "rkx120-pwm3",
+		.of_compatible = "rockchip,rkx120-pwm",
+	},
+	{
+		.name = "rkx120-pwm4",
+		.of_compatible = "rockchip,rkx120-pwm",
+	},
+	{
+		.name = "rkx120-pwm5",
+		.of_compatible = "rockchip,rkx120-pwm",
+	},
+	{
+		.name = "rkx120-pwm6",
+		.of_compatible = "rockchip,rkx120-pwm",
+	},
+	{
+		.name = "rkx120-pwm7",
+		.of_compatible = "rockchip,rkx120-pwm",
 	},
 };
 
@@ -111,26 +150,40 @@
 	return serdes->rkx110_debug || serdes->rkx120_debug;
 }
 
-static void rk_serdes_wait_link_ready(struct rk_serdes *serdes)
+static int rk_serdes_wait_link_ready(struct rk_serdes *serdes)
 {
+	int ret;
+
 	if (serdes->stream_type == STREAM_DISPLAY) {
-		rkx110_linktx_wait_link_ready(serdes, 0);
-		if (serdes->route_flag & ROUTE_MULTI_LANE) {
+		ret = rkx110_linktx_wait_link_ready(serdes, 0);
+		if (ret)
+			return ret;
+
+		if (serdes->lane_nr == 2) {
 			rkx110_ser_pma_enable(serdes, true, 1, DEVICE_LOCAL);
-			if (!(serdes->route_flag & ROUTE_MULTI_REMOTE))
+			if (!(serdes->remote_nr == 2))
 				rkx120_des_pma_enable(serdes, true, 1, DEVICE_REMOTE0);
-			rkx110_linktx_wait_link_ready(serdes, 1);
+			ret = rkx110_linktx_wait_link_ready(serdes, 1);
+			if (ret)
+				return ret;
 		}
 
 	} else {
-		rkx120_linkrx_wait_link_ready(serdes, 0);
-		if (serdes->route_flag & ROUTE_MULTI_LANE) {
+		ret = rkx120_linkrx_wait_link_ready(serdes, 0);
+		if (ret)
+			return ret;
+
+		if (serdes->lane_nr == 2) {
 			rkx120_des_pma_enable(serdes, true, 1, DEVICE_LOCAL);
-			if (!(serdes->route_flag & ROUTE_MULTI_REMOTE))
+			if (!(serdes->remote_nr == 2))
 				rkx110_ser_pma_enable(serdes, true, 1, DEVICE_REMOTE0);
-			rkx120_linkrx_wait_link_ready(serdes, 1);
+			ret = rkx120_linkrx_wait_link_ready(serdes, 1);
+			if (ret)
+				return ret;
 		}
 	}
+
+	return 0;
 }
 
 static void rk_serdes_print_rate(struct rk_serdes *serdes, enum rk_serdes_rate rate)
@@ -302,9 +355,9 @@
 	if (serdes->stream_type == STREAM_DISPLAY) {
 		rkx110_pma_set_rate(serdes, &rkx110_pll, 0, DEVICE_LOCAL);
 		rkx120_pma_set_rate(serdes, &rkx120_pll, 0, DEVICE_REMOTE0);
-		if (serdes->route_flag & ROUTE_MULTI_LANE) {
+		if (serdes->lane_nr == 2) {
 			rkx110_pma_set_rate(serdes, &rkx110_pll, 1, DEVICE_LOCAL);
-			if (serdes->route_flag & ROUTE_MULTI_REMOTE)
+			if (serdes->remote_nr == 2)
 				rkx120_pma_set_rate(serdes, &rkx120_pll, 0, DEVICE_REMOTE1);
 			else
 				rkx120_pma_set_rate(serdes, &rkx120_pll, 1, DEVICE_REMOTE0);
@@ -315,9 +368,9 @@
 	} else {
 		rkx120_pma_set_rate(serdes, &rkx120_pll, 0, DEVICE_LOCAL);
 		rkx110_pma_set_rate(serdes, &rkx110_pll, 0, DEVICE_REMOTE0);
-		if (serdes->route_flag & ROUTE_MULTI_LANE) {
+		if (serdes->lane_nr == 2) {
 			rkx120_pma_set_rate(serdes, &rkx120_pll, 1, DEVICE_LOCAL);
-			if (serdes->route_flag & ROUTE_MULTI_REMOTE)
+			if (serdes->remote_nr == 2)
 				rkx110_pma_set_rate(serdes, &rkx110_pll, 0, DEVICE_REMOTE1);
 			else
 				rkx110_pma_set_rate(serdes, &rkx110_pll, 1, DEVICE_REMOTE0);
@@ -330,225 +383,6 @@
 	rk_serdes_wait_link_ready(serdes);
 
 	serdes->rate = rate;
-}
-
-static int rk_serdes_route_prepare(struct rk_serdes *serdes, struct rk_serdes_route *route)
-{
-	if (rk_serdes_debug_mode(serdes))
-		return 0;
-
-	if (route->stream_type == STREAM_DISPLAY) {
-		switch (route->local_port0) {
-		case RK_SERDES_RGB_RX:
-			rkx110_rgb_rx_enable(serdes, route);
-			break;
-		case RK_SERDES_LVDS_RX0:
-			rkx110_lvds_rx_enable(serdes, route, 0);
-			if (serdes->route_flag & ROUTE_MULTI_LVDS_INPUT)
-				rkx110_lvds_rx_enable(serdes, route, 1);
-			break;
-		case RK_SERDES_LVDS_RX1:
-			rkx110_lvds_rx_enable(serdes, route, 1);
-			if (serdes->route_flag & ROUTE_MULTI_LVDS_INPUT)
-				rkx110_lvds_rx_enable(serdes, route, 0);
-			break;
-		case RK_SERDES_DUAL_LVDS_RX:
-			rkx110_lvds_rx_enable(serdes, route, 0);
-			rkx110_lvds_rx_enable(serdes, route, 1);
-			break;
-		case RK_SERDES_DSI_RX0:
-			rkx110_dsi_rx_enable(serdes, route, 0);
-			if (serdes->route_flag & ROUTE_MULTI_DSI_INPUT)
-				rkx110_dsi_rx_enable(serdes, route, 1);
-			break;
-		case RK_SERDES_DSI_RX1:
-			rkx110_dsi_rx_enable(serdes, route, 1);
-			if (serdes->route_flag & ROUTE_MULTI_DSI_INPUT)
-				rkx110_dsi_rx_enable(serdes, route, 0);
-			break;
-		default:
-			dev_info(serdes->dev, "undefined local port0");
-			return -EINVAL;
-		}
-
-		rkx110_linktx_enable(serdes, route);
-
-		rkx120_linkrx_enable(serdes, route, DEVICE_REMOTE0);
-		if (serdes->route_flag & ROUTE_MULTI_REMOTE)
-			rkx120_linkrx_enable(serdes, route, DEVICE_REMOTE1);
-
-		if (route->remote0_port0 & RK_SERDES_DSI_TX0)
-			rkx120_dsi_tx_pre_enable(serdes, route, DEVICE_REMOTE0);
-		if (route->remote1_port0 & RK_SERDES_DSI_TX0)
-			rkx120_dsi_tx_pre_enable(serdes, route, DEVICE_REMOTE1);
-	} else {
-		/* for camera stream */
-	}
-
-	return 0;
-}
-
-static int rk_serdes_route_enable(struct rk_serdes *serdes, struct rk_serdes_route *route)
-{
-	if (rk_serdes_debug_mode(serdes))
-		return 0;
-
-	if (route->stream_type == STREAM_DISPLAY) {
-		switch (route->remote0_port0) {
-		case RK_SERDES_RGB_TX:
-			rkx120_rgb_tx_enable(serdes, route, DEVICE_REMOTE0);
-			break;
-		case RK_SERDES_LVDS_TX0:
-			rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE0, 0);
-			break;
-		case RK_SERDES_LVDS_TX1:
-			rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE0, 1);
-			break;
-		case RK_SERDES_DUAL_LVDS_TX:
-			rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE0, 0);
-			rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE0, 1);
-			break;
-		case RK_SERDES_DSI_TX0:
-			rkx120_dsi_tx_enable(serdes, route, DEVICE_REMOTE0);
-			break;
-		default:
-			dev_err(serdes->dev, "undefined remote0_port0\n");
-			return -EINVAL;
-		}
-
-		if (serdes->route_flag & ROUTE_MULTI_REMOTE) {
-			switch (route->remote1_port0) {
-			case RK_SERDES_RGB_TX:
-				rkx120_rgb_tx_enable(serdes, route, DEVICE_REMOTE1);
-				break;
-			case RK_SERDES_LVDS_TX0:
-				rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE1, 0);
-				break;
-			case RK_SERDES_LVDS_TX1:
-				rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE1, 1);
-				break;
-			case RK_SERDES_DUAL_LVDS_TX:
-				rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE1, 0);
-				rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE1, 1);
-				break;
-			case RK_SERDES_DSI_TX0:
-				rkx120_dsi_tx_enable(serdes, route, DEVICE_REMOTE1);
-				break;
-			default:
-				dev_err(serdes->dev, "undefined remote1_port0\n");
-				return -EINVAL;
-			}
-		} else if (serdes->route_flag & ROUTE_MULTI_CHANNEL) {
-			if (route->remote0_port1 & RK_SERDES_LVDS_TX0) {
-				rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE0, 0);
-			} else if (route->remote0_port1 & RK_SERDES_LVDS_TX1) {
-				rkx120_lvds_tx_enable(serdes, route, DEVICE_REMOTE0, 1);
-			} else {
-				dev_err(serdes->dev, "undefined remote0_port1\n");
-				return -EINVAL;
-			}
-		}
-
-		if (serdes->version == SERDES_V1) {
-			rkx120_linkrx_engine_enable(serdes, 0, DEVICE_REMOTE0, true);
-			rkx110_linktx_channel_enable(serdes, 0, DEVICE_LOCAL, true);
-		}
-
-		rkx110_linktx_video_enable(serdes, DEVICE_LOCAL, true);
-	} else {
-		/* for camera stream */
-	}
-
-	return 0;
-}
-
-static int rk_serdes_route_disable(struct rk_serdes *serdes, struct rk_serdes_route *route)
-{
-	if (route->stream_type == STREAM_DISPLAY) {
-		if (route->remote0_port0 & RK_SERDES_DSI_TX0)
-			rkx120_dsi_tx_disable(serdes, route, DEVICE_REMOTE0);
-
-		if (serdes->version == SERDES_V1) {
-			rkx120_linkrx_engine_enable(serdes, 0, DEVICE_REMOTE0, false);
-			rkx110_linktx_channel_enable(serdes, 0, DEVICE_LOCAL, false);
-
-			if (route->local_port0 == RK_SERDES_DUAL_LVDS_RX) {
-				rkx110_set_stream_source(serdes, RK_SERDES_RGB_RX,
-							 DEVICE_LOCAL);
-				hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
-					    RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX);
-				hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
-					    RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
-				hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
-					    RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
-			}
-
-			if ((route->local_port0 == RK_SERDES_DSI_RX0) ||
-			    (route->local_port1 == RK_SERDES_DSI_RX0)) {
-				serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
-						      0x1400140);
-				hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
-					    RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX);
-				hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
-					    RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX);
-			}
-
-			if ((route->local_port0 == RK_SERDES_DSI_RX1) ||
-			    (route->local_port1 == RK_SERDES_DSI_RX1)) {
-				serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
-						      0x2800280);
-				hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
-					    RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX);
-				hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
-					    RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX);
-			}
-		}
-	}
-
-	return 0;
-}
-
-static int rk_serdes_route_unprepare(struct rk_serdes *serdes, struct rk_serdes_route *route)
-{
-	if (route->stream_type == STREAM_DISPLAY) {
-		if (route->remote0_port0 & RK_SERDES_DSI_TX0)
-			rkx120_dsi_tx_post_disable(serdes, route, DEVICE_REMOTE0);
-
-		if (serdes->version == SERDES_V1) {
-			if (route->local_port0 == RK_SERDES_DUAL_LVDS_RX) {
-				hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
-						     RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX);
-				hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
-						     RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
-				hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
-						     RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
-				rkx110_set_stream_source(serdes, RK_SERDES_DUAL_LVDS_RX,
-							    DEVICE_LOCAL);
-			}
-
-			if ((route->local_port0 == RK_SERDES_DSI_RX0) ||
-			    (route->local_port1 == RK_SERDES_DSI_RX0)) {
-				hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
-						     RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX);
-				hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
-						     RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX);
-				serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
-						      0x1400000);
-			}
-
-			if ((route->local_port0 == RK_SERDES_DSI_RX1) ||
-			    (route->local_port1 == RK_SERDES_DSI_RX1)) {
-				hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
-						     RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX);
-				hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
-						     RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX);
-				serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
-						      0x2800000);
-			}
-		}
-	}
-
-	return 0;
 }
 
 static int rk_serdes_set_hwpin(struct rk_serdes *serdes, struct i2c_client *client,
@@ -576,11 +410,17 @@
 	serdes->i2c_read_reg = rk_serdes_i2c_read;
 	serdes->i2c_write_reg = rk_serdes_i2c_write;
 	serdes->i2c_update_bits = rk_serdes_i2c_update_bits;
-	serdes->route_prepare = rk_serdes_route_prepare;
-	serdes->route_enable = rk_serdes_route_enable;
-	serdes->route_disable = rk_serdes_route_disable;
-	serdes->route_unprepare = rk_serdes_route_unprepare;
 	serdes->set_hwpin = rk_serdes_set_hwpin;
+
+	if (rk_serdes_debug_mode(serdes))
+		return;
+
+	if (serdes->stream_type == STREAM_DISPLAY) {
+		serdes->route_prepare = rk_serdes_display_route_prepare;
+		serdes->route_enable = rk_serdes_display_route_enable;
+		serdes->route_disable = rk_serdes_display_route_disable;
+		serdes->route_unprepare = rk_serdes_display_route_unprepare;
+	}
 }
 
 static int rk_serdes_passthrough_init(struct rk_serdes *serdes)
@@ -649,6 +489,25 @@
 		}
 
 		kfree(configs);
+	}
+
+	/* config irq passthrough */
+	if (serdes->stream_type == STREAM_DISPLAY) {
+		rkx110_linktx_passthrough_cfg(serdes, DEVICE_LOCAL, RK_SERDES_PASSTHROUGH_IRQ,
+					      false);
+		rkx120_linkrx_passthrough_cfg(serdes, DEVICE_REMOTE0, RK_SERDES_PASSTHROUGH_IRQ,
+					      true);
+		if (serdes->remote_nr == 2)
+			rkx120_linkrx_passthrough_cfg(serdes, DEVICE_REMOTE1,
+						      RK_SERDES_PASSTHROUGH_IRQ, true);
+	} else {
+		rkx120_linkrx_passthrough_cfg(serdes, DEVICE_LOCAL, RK_SERDES_PASSTHROUGH_IRQ,
+					      false);
+		rkx110_linktx_passthrough_cfg(serdes, DEVICE_REMOTE0, RK_SERDES_PASSTHROUGH_IRQ,
+					      true);
+		if (serdes->remote_nr == 2)
+			rkx110_linktx_passthrough_cfg(serdes, DEVICE_REMOTE1,
+						      RK_SERDES_PASSTHROUGH_IRQ, true);
 	}
 
 	return 0;
@@ -903,6 +762,9 @@
 		i2c_set_clientdata(client, serdes);
 	}
 
+	if (serdes->remote_nr == 2)
+		serdes->lane_nr = 2;
+
 	if (serdes->remote_nr == 0)
 		return -ENODEV;
 
@@ -952,14 +814,73 @@
 		kfree(configs);
 	}
 
+	/* config irq pinctrl */
+	if (serdes->stream_type == STREAM_DISPLAY) {
+		serdes->set_hwpin(serdes, serdes->chip[DEVICE_LOCAL].client, PIN_RKX110,
+				  RK_SERDES_SER_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
+				  RK_SERDES_PIN_CONFIG_MUX_FUNC2);
+		serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE0].client, PIN_RKX120,
+				  RK_SERDES_DES_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
+				  RK_SERDES_PIN_CONFIG_MUX_FUNC0);
+		if (serdes->remote_nr == 2)
+			serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE1].client, PIN_RKX120,
+					  RK_SERDES_DES_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
+					  RK_SERDES_PIN_CONFIG_MUX_FUNC0);
+	} else {
+		serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE0].client, PIN_RKX110,
+				  RK_SERDES_SER_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
+				  RK_SERDES_PIN_CONFIG_MUX_FUNC0);
+		serdes->set_hwpin(serdes, serdes->chip[DEVICE_LOCAL].client, PIN_RKX120,
+				  RK_SERDES_DES_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
+				  RK_SERDES_PIN_CONFIG_MUX_FUNC2);
+		if (serdes->remote_nr == 2)
+			serdes->set_hwpin(serdes, serdes->chip[DEVICE_REMOTE1].client, PIN_RKX110,
+					  RK_SERDES_SER_GPIO_BANK0, RK_SERDES_GPIO_PIN_A4,
+					  RK_SERDES_PIN_CONFIG_MUX_FUNC2);
+	}
+
 	return 0;
+}
+
+static int rk_serdes_irq_enable(struct rk_serdes *serdes)
+{
+	if (serdes->stream_type == STREAM_DISPLAY)
+		rkx110_irq_enable(serdes, DEVICE_LOCAL);
+	else
+		rkx120_irq_enable(serdes, DEVICE_LOCAL);
+
+	return 0;
+}
+
+__maybe_unused static int rk_serdes_irq_disable(struct rk_serdes *serdes)
+{
+	if (serdes->stream_type == STREAM_DISPLAY)
+		rkx110_irq_disable(serdes, DEVICE_LOCAL);
+	else
+		rkx120_irq_disable(serdes, DEVICE_LOCAL);
+
+	return 0;
+}
+
+static irqreturn_t rk_serdes_irq_handler(int irq, void *arg)
+{
+	struct rk_serdes *serdes = arg;
+
+	if (serdes->stream_type == STREAM_DISPLAY)
+		rkx110_irq_handler(serdes, DEVICE_LOCAL);
+	else
+		rkx120_irq_handler(serdes, DEVICE_LOCAL);
+
+	return IRQ_HANDLED;
 }
 
 static int rk_serdes_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
+	struct device_node *disp_np;
 	struct rk_serdes *serdes;
 	int ret;
+	bool dual_lane;
 
 	serdes = devm_kzalloc(dev, sizeof(*serdes), GFP_KERNEL);
 	if (!serdes)
@@ -988,6 +909,16 @@
 
 	serdes->rate = RATE_2GBPS_83M;
 
+	serdes->supply = devm_regulator_get_optional(dev, "power");
+	if (IS_ERR(serdes->supply)) {
+		ret = PTR_ERR(serdes->supply);
+
+		if (ret != -ENODEV)
+			return dev_err_probe(dev, ret, "failed to request regulator\n");
+
+		serdes->supply = NULL;
+	}
+
 	serdes->enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
 	if (IS_ERR(serdes->enable)) {
 		ret = PTR_ERR(serdes->enable);
@@ -1002,15 +933,34 @@
 		return ret;
 	}
 
-	gpiod_set_value(serdes->enable, 1);
+	serdes->irq_gpio = devm_gpiod_get_optional(dev, "irq", GPIOD_IN);
+	if (IS_ERR(serdes->irq_gpio)) {
+		ret = PTR_ERR(serdes->irq_gpio);
+		dev_err(dev, "failed to request irq GPIO: %d\n", ret);
+		return ret;
+	}
+	if (serdes->irq_gpio) {
+		serdes->irq = gpiod_to_irq(serdes->irq_gpio);
+		if (serdes->irq < 0)
+			return dev_err_probe(dev, serdes->irq, "failed to get irq\n");
 
-	gpiod_set_value(serdes->reset, 1);
-	usleep_range(10000, 11000);
-	gpiod_set_value(serdes->reset, 0);
+		irq_set_status_flags(serdes->irq, IRQ_NOAUTOEN);
+		ret = devm_request_threaded_irq(dev, serdes->irq, NULL,
+						rk_serdes_irq_handler,
+						IRQF_TRIGGER_LOW |
+						IRQF_ONESHOT, "serdes-irq", serdes);
+		if (ret) {
+			dev_err(dev, "failed to request serdes interrupt\n");
+			return ret;
+		}
+	} else {
+		dev_warn(dev, "no support serdes irq function\n");
+	}
 
-	if (of_get_child_by_name(dev->of_node, "serdes-panel")) {
+	disp_np = of_get_child_by_name(dev->of_node, "serdes-panel");
+	if (disp_np) {
 		serdes->stream_type = STREAM_DISPLAY;
-		of_node_put(dev->of_node);
+		of_node_put(disp_np);
 		dev_info(dev, "serdes display stream");
 	} else {
 		serdes->stream_type = STREAM_CAMERA;
@@ -1021,7 +971,10 @@
 	if (ret)
 		return ret;
 
-	msleep(20);
+	if (serdes->remote_nr != 2) {
+		dual_lane = device_property_read_bool(dev, "dual-lane");
+		serdes->lane_nr = dual_lane ? 2 : 1;
+	}
 
 	ret = mfd_add_devices(dev, -1, rkx110_x120_devs, ARRAY_SIZE(rkx110_x120_devs),
 			      NULL, 0, NULL);
@@ -1030,27 +983,58 @@
 		return ret;
 	}
 
+	if (serdes->supply) {
+		ret = regulator_enable(serdes->supply);
+		if (ret < 0) {
+			dev_err(serdes->dev, "failed to enable supply: %d\n", ret);
+			return ret;
+		}
+	}
+
+	gpiod_set_value(serdes->enable, 1);
+
+	gpiod_set_value(serdes->reset, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value(serdes->reset, 0);
+
+	msleep(20);
+
 	rk_serdes_wait_link_ready(serdes);
 
 	rk_serdes_read_chip_id(serdes);
 
 	ret = rk_serdes_add_hwclk(serdes);
 	if (ret < 0)
-		return ret;
+		goto err;
 
 	rk_serdes_set_rate(serdes, RATE_4GBPS_83M);
 	rk_serdes_pinctrl_init(serdes);
 	rk_serdes_passthrough_init(serdes);
+	rk_serdes_irq_enable(serdes);
+	enable_irq(serdes->irq);
+
+	if (serdes->stream_type == STREAM_DISPLAY)
+		rk_serdes_display_route_init(serdes);
+
 out:
 	rk_serdes_debugfs_init(serdes);
 
 	return 0;
+
+err:
+	if (serdes->supply)
+		ret = regulator_disable(serdes->supply);
+
+	return ret;
 }
 
 static int rk_serdes_i2c_remove(struct i2c_client *client)
 {
 	struct rk_serdes *rk_serdes = i2c_get_clientdata(client);
 
+	if (rk_serdes->supply)
+		regulator_disable(rk_serdes->supply);
+
 	mfd_remove_devices(rk_serdes->dev);
 
 	return 0;

--
Gitblit v1.6.2