From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 13 May 2024 10:30:14 +0000
Subject: [PATCH] modify sin led gpio
---
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