* [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements
@ 2025-01-10 9:14 Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 01/19] media: i2c: ds90ub953: Fix error prints Tomi Valkeinen
` (18 more replies)
0 siblings, 19 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen, devicetree, Rob Herring,
Krzysztof Kozlowski
Hi,
This series has two main parts: 1) add error handling all around, and 2)
update the drivers according to latest (mostly non-public) information
from TI.
The "Update UB9702 init sequences" patch basically rewrites the init
sequence from scratch, and to make that patch easier to read, the
previous patch first removes the current init sequence. In the final
version these two patches need to be squashed together.
Tomi
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
Jai Luthra (5):
media: i2c: ds90ub953: Speed-up I2C watchdog timer
media: i2c: ds90ub960: Enable SSCG for UB9702
media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
media: i2c: ds90ub960: Configure serializer using back-channel
media: i2c: ds90ub9xx: Set serializer temperature ramp
Tomi Valkeinen (14):
media: i2c: ds90ub953: Fix error prints
media: i2c: ds90ub913: Align ub913_read() with other similar functions
media: i2c: ds90ub9xx: Add err parameter to read/write funcs
media: i2c: ds90ub960: Add error handling to multiple places
media: i2c: ds90ub953: Add error handling to ub953_log_status()
media: i2c: ds90ub913: Add error handling to ub913_log_status()
media: i2c: ds90ub960: Move UB9702 registers to a separate section
media: i2c: ds90ub960: Add UB9702 specific registers
media: i2c: ds90ub960: Split ub960_init_tx_ports()
media: i2c: ds90ub960: Refresh ub960_init_tx_ports_ub9702()
media: i2c: ds90ub960: Add RX port iteration support
media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports()
media: i2c: ds90ub960: Remove old ub9702 RX port init code (SQUASH)
media: i2c: ds90ub960: Update UB9702 init sequences
.../bindings/media/i2c/ti,ds90ub960.yaml | 7 +
drivers/media/i2c/ds90ub913.c | 78 +-
drivers/media/i2c/ds90ub953.c | 170 +-
drivers/media/i2c/ds90ub960.c | 2266 +++++++++++++++-----
include/media/i2c/ds90ub9xx.h | 15 +
5 files changed, 1927 insertions(+), 609 deletions(-)
---
base-commit: 40ed9e9b2808beeb835bd0ed971fb364c285d39c
change-id: 20250110-ub9xx-improvements-9172b44eb0bc
Best regards,
--
Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 01/19] media: i2c: ds90ub953: Fix error prints
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 02/19] media: i2c: ds90ub913: Align ub913_read() with other similar functions Tomi Valkeinen
` (17 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
ub953_read_ind() and ub953_write_ind() have broken error prints, and the
register address is printed incorrectly. Fix the prints.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub953.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 028892cfa361..fd1c442e8a07 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -258,7 +258,7 @@ static int ub953_read_ind(struct ub953_data *priv, u8 block, u8 reg, u8 *val)
ret = regmap_write(priv->regmap, UB953_REG_IND_ACC_ADDR, reg);
if (ret) {
dev_err(&priv->client->dev,
- "Write to IND_ACC_ADDR failed when reading %u:%x02x: %d\n",
+ "Write to IND_ACC_ADDR failed when reading %u:0x%02x: %d\n",
block, reg, ret);
goto out_unlock;
}
@@ -266,7 +266,7 @@ static int ub953_read_ind(struct ub953_data *priv, u8 block, u8 reg, u8 *val)
ret = regmap_read(priv->regmap, UB953_REG_IND_ACC_DATA, &v);
if (ret) {
dev_err(&priv->client->dev,
- "Write to IND_ACC_DATA failed when reading %u:%x02x: %d\n",
+ "Write to IND_ACC_DATA failed when reading %u:0x%02x: %d\n",
block, reg, ret);
goto out_unlock;
}
@@ -293,7 +293,7 @@ static int ub953_write_ind(struct ub953_data *priv, u8 block, u8 reg, u8 val)
ret = regmap_write(priv->regmap, UB953_REG_IND_ACC_ADDR, reg);
if (ret) {
dev_err(&priv->client->dev,
- "Write to IND_ACC_ADDR failed when writing %u:%x02x: %d\n",
+ "Write to IND_ACC_ADDR failed when writing %u:0x%02x: %d\n",
block, reg, ret);
goto out_unlock;
}
@@ -301,7 +301,7 @@ static int ub953_write_ind(struct ub953_data *priv, u8 block, u8 reg, u8 val)
ret = regmap_write(priv->regmap, UB953_REG_IND_ACC_DATA, val);
if (ret) {
dev_err(&priv->client->dev,
- "Write to IND_ACC_DATA failed when writing %u:%x02x\n: %d\n",
+ "Write to IND_ACC_DATA failed when writing %u:0x%02x: %d\n",
block, reg, ret);
}
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 02/19] media: i2c: ds90ub913: Align ub913_read() with other similar functions
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 01/19] media: i2c: ds90ub953: Fix error prints Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 03/19] media: i2c: ds90ub9xx: Add err parameter to read/write funcs Tomi Valkeinen
` (16 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
Adjust the ub913_read() to have similar form than the other similar
functions in ub9xx drivers. This makes it easier to deal with all the
read/write functions with a semantic patch.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub913.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
index 7670d6c82d92..1daf0b8ba726 100644
--- a/drivers/media/i2c/ds90ub913.c
+++ b/drivers/media/i2c/ds90ub913.c
@@ -125,14 +125,16 @@ static int ub913_read(const struct ub913_data *priv, u8 reg, u8 *val)
int ret;
ret = regmap_read(priv->regmap, reg, &v);
- if (ret < 0) {
+ if (ret) {
dev_err(&priv->client->dev,
"Cannot read register 0x%02x: %d!\n", reg, ret);
- return ret;
+ goto out;
}
*val = v;
- return 0;
+
+out:
+ return ret;
}
static int ub913_write(const struct ub913_data *priv, u8 reg, u8 val)
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 03/19] media: i2c: ds90ub9xx: Add err parameter to read/write funcs
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 01/19] media: i2c: ds90ub953: Fix error prints Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 02/19] media: i2c: ds90ub913: Align ub913_read() with other similar functions Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 04/19] media: i2c: ds90ub960: Add error handling to multiple places Tomi Valkeinen
` (15 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
To make future error handling in the drivers easier, add "int *err"
parameter to all the i2c register access functions. It functions the
same was as with e.g. CCI reg write/read helpers.
This was accomplished with the following semantic patch:
@@
identifier FUNC =~ "^ub9.._(rxport_|txport_|ind_)?(read|write|update_bits)(16|_ind)?$";
@@
FUNC(...
+ , int *err
) {
...
int ret;
+
+ if (err && *err)
+ return *err;
...
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@
identifier FUNC =~ "^ub9.._(rxport_|txport_|ind_)?(read|write|update_bits)(16|_ind)?$";
@@
FUNC(...
+ , NULL
)
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub913.c | 52 +++--
drivers/media/i2c/ds90ub953.c | 94 +++++----
drivers/media/i2c/ds90ub960.c | 441 ++++++++++++++++++++++++++++--------------
3 files changed, 390 insertions(+), 197 deletions(-)
diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
index 1daf0b8ba726..34f92aa1c56c 100644
--- a/drivers/media/i2c/ds90ub913.c
+++ b/drivers/media/i2c/ds90ub913.c
@@ -119,11 +119,15 @@ static const struct ub913_format_info *ub913_find_format(u32 incode)
return NULL;
}
-static int ub913_read(const struct ub913_data *priv, u8 reg, u8 *val)
+static int ub913_read(const struct ub913_data *priv, u8 reg, u8 *val,
+ int *err)
{
unsigned int v;
int ret;
+ if (err && *err)
+ return *err;
+
ret = regmap_read(priv->regmap, reg, &v);
if (ret) {
dev_err(&priv->client->dev,
@@ -134,31 +138,47 @@ static int ub913_read(const struct ub913_data *priv, u8 reg, u8 *val)
*val = v;
out:
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub913_write(const struct ub913_data *priv, u8 reg, u8 val)
+static int ub913_write(const struct ub913_data *priv, u8 reg, u8 val,
+ int *err)
{
int ret;
+ if (err && *err)
+ return *err;
+
ret = regmap_write(priv->regmap, reg, val);
if (ret < 0)
dev_err(&priv->client->dev,
"Cannot write register 0x%02x: %d!\n", reg, ret);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
static int ub913_update_bits(const struct ub913_data *priv, u8 reg, u8 mask,
- u8 val)
+ u8 val, int *err)
{
int ret;
+ if (err && *err)
+ return *err;
+
ret = regmap_update_bits(priv->regmap, reg, mask, val);
if (ret < 0)
dev_err(&priv->client->dev,
"Cannot update register 0x%02x %d!\n", reg, ret);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@ -206,7 +226,7 @@ static int ub913_gpiochip_probe(struct ub913_data *priv)
int ret;
/* Initialize GPIOs 0 and 1 to local control, tri-state */
- ub913_write(priv, UB913_REG_GPIO_CFG(0), 0);
+ ub913_write(priv, UB913_REG_GPIO_CFG(0), 0, NULL);
gc->label = dev_name(dev);
gc->parent = dev;
@@ -486,23 +506,23 @@ static int ub913_log_status(struct v4l2_subdev *sd)
struct device *dev = &priv->client->dev;
u8 v = 0, v1 = 0, v2 = 0;
- ub913_read(priv, UB913_REG_MODE_SEL, &v);
+ ub913_read(priv, UB913_REG_MODE_SEL, &v, NULL);
dev_info(dev, "MODE_SEL %#02x\n", v);
- ub913_read(priv, UB913_REG_CRC_ERRORS_LSB, &v1);
- ub913_read(priv, UB913_REG_CRC_ERRORS_MSB, &v2);
+ ub913_read(priv, UB913_REG_CRC_ERRORS_LSB, &v1, NULL);
+ ub913_read(priv, UB913_REG_CRC_ERRORS_MSB, &v2, NULL);
dev_info(dev, "CRC errors %u\n", v1 | (v2 << 8));
/* clear CRC errors */
- ub913_read(priv, UB913_REG_GENERAL_CFG, &v);
+ ub913_read(priv, UB913_REG_GENERAL_CFG, &v, NULL);
ub913_write(priv, UB913_REG_GENERAL_CFG,
- v | UB913_REG_GENERAL_CFG_CRC_ERR_RESET);
- ub913_write(priv, UB913_REG_GENERAL_CFG, v);
+ v | UB913_REG_GENERAL_CFG_CRC_ERR_RESET, NULL);
+ ub913_write(priv, UB913_REG_GENERAL_CFG, v, NULL);
- ub913_read(priv, UB913_REG_GENERAL_STATUS, &v);
+ ub913_read(priv, UB913_REG_GENERAL_STATUS, &v, NULL);
dev_info(dev, "GENERAL_STATUS %#02x\n", v);
- ub913_read(priv, UB913_REG_PLL_OVR, &v);
+ ub913_read(priv, UB913_REG_PLL_OVR, &v, NULL);
dev_info(dev, "PLL_OVR %#02x\n", v);
return 0;
@@ -658,11 +678,11 @@ static int ub913_i2c_master_init(struct ub913_data *priv)
scl_high = div64_u64((u64)scl_high * ref, 1000000000);
scl_low = div64_u64((u64)scl_low * ref, 1000000000);
- ret = ub913_write(priv, UB913_REG_SCL_HIGH_TIME, scl_high);
+ ret = ub913_write(priv, UB913_REG_SCL_HIGH_TIME, scl_high, NULL);
if (ret)
return ret;
- ret = ub913_write(priv, UB913_REG_SCL_LOW_TIME, scl_low);
+ ret = ub913_write(priv, UB913_REG_SCL_LOW_TIME, scl_low, NULL);
if (ret)
return ret;
@@ -731,7 +751,7 @@ static int ub913_hw_init(struct ub913_data *priv)
int ret;
u8 v;
- ret = ub913_read(priv, UB913_REG_MODE_SEL, &v);
+ ret = ub913_read(priv, UB913_REG_MODE_SEL, &v, NULL);
if (ret)
return ret;
@@ -752,7 +772,7 @@ static int ub913_hw_init(struct ub913_data *priv)
ret = ub913_update_bits(priv, UB913_REG_GENERAL_CFG,
UB913_REG_GENERAL_CFG_PCLK_RISING,
FIELD_PREP(UB913_REG_GENERAL_CFG_PCLK_RISING,
- priv->pclk_polarity_rising));
+ priv->pclk_polarity_rising), NULL);
if (ret)
return ret;
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index fd1c442e8a07..07d451816855 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -185,11 +185,14 @@ static inline struct ub953_data *sd_to_ub953(struct v4l2_subdev *sd)
* HW Access
*/
-static int ub953_read(struct ub953_data *priv, u8 reg, u8 *val)
+static int ub953_read(struct ub953_data *priv, u8 reg, u8 *val, int *err)
{
unsigned int v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = regmap_read(priv->regmap, reg, &v);
@@ -204,13 +207,19 @@ static int ub953_read(struct ub953_data *priv, u8 reg, u8 *val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub953_write(struct ub953_data *priv, u8 reg, u8 val)
+static int ub953_write(struct ub953_data *priv, u8 reg, u8 val, int *err)
{
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = regmap_write(priv->regmap, reg, val);
@@ -220,6 +229,9 @@ static int ub953_write(struct ub953_data *priv, u8 reg, u8 val)
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@ -244,11 +256,15 @@ static int ub953_select_ind_reg_block(struct ub953_data *priv, u8 block)
}
__maybe_unused
-static int ub953_read_ind(struct ub953_data *priv, u8 block, u8 reg, u8 *val)
+static int ub953_read_ind(struct ub953_data *priv, u8 block, u8 reg, u8 *val,
+ int *err)
{
unsigned int v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub953_select_ind_reg_block(priv, block);
@@ -276,14 +292,21 @@ static int ub953_read_ind(struct ub953_data *priv, u8 block, u8 reg, u8 *val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
__maybe_unused
-static int ub953_write_ind(struct ub953_data *priv, u8 block, u8 reg, u8 val)
+static int ub953_write_ind(struct ub953_data *priv, u8 block, u8 reg, u8 val,
+ int *err)
{
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub953_select_ind_reg_block(priv, block);
@@ -308,6 +331,9 @@ static int ub953_write_ind(struct ub953_data *priv, u8 block, u8 reg, u8 val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@ -320,7 +346,7 @@ static int ub953_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
int ret;
u8 v;
- ret = ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &v);
+ ret = ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &v, NULL);
if (ret)
return ret;
@@ -366,7 +392,7 @@ static int ub953_gpio_get(struct gpio_chip *gc, unsigned int offset)
int ret;
u8 v;
- ret = ub953_read(priv, UB953_REG_GPIO_PIN_STS, &v);
+ ret = ub953_read(priv, UB953_REG_GPIO_PIN_STS, &v, NULL);
if (ret)
return ret;
@@ -400,11 +426,11 @@ static int ub953_gpiochip_probe(struct ub953_data *priv)
int ret;
/* Set all GPIOs to local input mode */
- ret = ub953_write(priv, UB953_REG_LOCAL_GPIO_DATA, 0);
+ ret = ub953_write(priv, UB953_REG_LOCAL_GPIO_DATA, 0, NULL);
if (ret)
return ret;
- ret = ub953_write(priv, UB953_REG_GPIO_INPUT_CTRL, 0xf);
+ ret = ub953_write(priv, UB953_REG_GPIO_INPUT_CTRL, 0xf, NULL);
if (ret)
return ret;
@@ -615,15 +641,15 @@ static int ub953_log_status(struct v4l2_subdev *sd)
u8 gpio_pin_sts = 0;
for (i = 0; i < sizeof(id); i++)
- ub953_read(priv, UB953_REG_FPD3_RX_ID(i), &id[i]);
+ ub953_read(priv, UB953_REG_FPD3_RX_ID(i), &id[i], NULL);
dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
- ub953_read(priv, UB953_REG_GENERAL_STATUS, &v);
+ ub953_read(priv, UB953_REG_GENERAL_STATUS, &v, NULL);
dev_info(dev, "GENERAL_STATUS %#02x\n", v);
- ub953_read(priv, UB953_REG_CRC_ERR_CNT1, &v1);
- ub953_read(priv, UB953_REG_CRC_ERR_CNT2, &v2);
+ ub953_read(priv, UB953_REG_CRC_ERR_CNT1, &v1, NULL);
+ ub953_read(priv, UB953_REG_CRC_ERR_CNT2, &v2, NULL);
dev_info(dev, "CRC error count %u\n", v1 | (v2 << 8));
/* Clear CRC error counter */
@@ -632,34 +658,34 @@ static int ub953_log_status(struct v4l2_subdev *sd)
UB953_REG_BC_CTRL_CRC_ERR_CLR,
UB953_REG_BC_CTRL_CRC_ERR_CLR);
- ub953_read(priv, UB953_REG_CSI_ERR_CNT, &v);
+ ub953_read(priv, UB953_REG_CSI_ERR_CNT, &v, NULL);
dev_info(dev, "CSI error count %u\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_STATUS, &v);
+ ub953_read(priv, UB953_REG_CSI_ERR_STATUS, &v, NULL);
dev_info(dev, "CSI_ERR_STATUS %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_DLANE01, &v);
+ ub953_read(priv, UB953_REG_CSI_ERR_DLANE01, &v, NULL);
dev_info(dev, "CSI_ERR_DLANE01 %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_DLANE23, &v);
+ ub953_read(priv, UB953_REG_CSI_ERR_DLANE23, &v, NULL);
dev_info(dev, "CSI_ERR_DLANE23 %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_CLK_LANE, &v);
+ ub953_read(priv, UB953_REG_CSI_ERR_CLK_LANE, &v, NULL);
dev_info(dev, "CSI_ERR_CLK_LANE %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_PKT_HDR_VC_ID, &v);
+ ub953_read(priv, UB953_REG_CSI_PKT_HDR_VC_ID, &v, NULL);
dev_info(dev, "CSI packet header VC %u ID %u\n", v >> 6, v & 0x3f);
- ub953_read(priv, UB953_REG_PKT_HDR_WC_LSB, &v1);
- ub953_read(priv, UB953_REG_PKT_HDR_WC_MSB, &v2);
+ ub953_read(priv, UB953_REG_PKT_HDR_WC_LSB, &v1, NULL);
+ ub953_read(priv, UB953_REG_PKT_HDR_WC_MSB, &v2, NULL);
dev_info(dev, "CSI packet header WC %u\n", (v2 << 8) | v1);
- ub953_read(priv, UB953_REG_CSI_ECC, &v);
+ ub953_read(priv, UB953_REG_CSI_ECC, &v, NULL);
dev_info(dev, "CSI ECC %#02x\n", v);
- ub953_read(priv, UB953_REG_LOCAL_GPIO_DATA, &gpio_local_data);
- ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &gpio_input_ctrl);
- ub953_read(priv, UB953_REG_GPIO_PIN_STS, &gpio_pin_sts);
+ ub953_read(priv, UB953_REG_LOCAL_GPIO_DATA, &gpio_local_data, NULL);
+ ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &gpio_input_ctrl, NULL);
+ ub953_read(priv, UB953_REG_GPIO_PIN_STS, &gpio_pin_sts, NULL);
for (i = 0; i < UB953_NUM_GPIOS; i++) {
dev_info(dev,
@@ -843,11 +869,11 @@ static int ub953_i2c_master_init(struct ub953_data *priv)
scl_high = div64_u64((u64)scl_high * ref, 1000000000) - 5;
scl_low = div64_u64((u64)scl_low * ref, 1000000000) - 5;
- ret = ub953_write(priv, UB953_REG_SCL_HIGH_TIME, scl_high);
+ ret = ub953_write(priv, UB953_REG_SCL_HIGH_TIME, scl_high, NULL);
if (ret)
return ret;
- ret = ub953_write(priv, UB953_REG_SCL_LOW_TIME, scl_low);
+ ret = ub953_write(priv, UB953_REG_SCL_LOW_TIME, scl_low, NULL);
if (ret)
return ret;
@@ -986,11 +1012,11 @@ static int ub953_write_clkout_regs(struct ub953_data *priv,
clkout_ctrl1 = clkout_data->n;
- ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL0, clkout_ctrl0);
+ ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL0, clkout_ctrl0, NULL);
if (ret)
return ret;
- ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL1, clkout_ctrl1);
+ ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL1, clkout_ctrl1, NULL);
if (ret)
return ret;
@@ -1009,13 +1035,13 @@ static unsigned long ub953_clkout_recalc_rate(struct clk_hw *hw,
u64 rate;
int ret;
- ret = ub953_read(priv, UB953_REG_CLKOUT_CTRL0, &ctrl0);
+ ret = ub953_read(priv, UB953_REG_CLKOUT_CTRL0, &ctrl0, NULL);
if (ret) {
dev_err(dev, "Failed to read CLKOUT_CTRL0: %d\n", ret);
return 0;
}
- ret = ub953_read(priv, UB953_REG_CLKOUT_CTRL1, &ctrl1);
+ ret = ub953_read(priv, UB953_REG_CLKOUT_CTRL1, &ctrl1, NULL);
if (ret) {
dev_err(dev, "Failed to read CLKOUT_CTRL1: %d\n", ret);
return 0;
@@ -1191,7 +1217,7 @@ static int ub953_hw_init(struct ub953_data *priv)
int ret;
u8 v;
- ret = ub953_read(priv, UB953_REG_MODE_SEL, &v);
+ ret = ub953_read(priv, UB953_REG_MODE_SEL, &v, NULL);
if (ret)
return ret;
@@ -1231,13 +1257,13 @@ static int ub953_hw_init(struct ub953_data *priv)
return dev_err_probe(dev, -EINVAL,
"clkin required for non-sync ext mode\n");
- ret = ub953_read(priv, UB953_REG_REV_MASK_ID, &v);
+ ret = ub953_read(priv, UB953_REG_REV_MASK_ID, &v, NULL);
if (ret)
return dev_err_probe(dev, ret, "Failed to read revision");
dev_info(dev, "Found %s rev/mask %#04x\n", priv->hw_data->model, v);
- ret = ub953_read(priv, UB953_REG_GENERAL_CFG, &v);
+ ret = ub953_read(priv, UB953_REG_GENERAL_CFG, &v, NULL);
if (ret)
return ret;
@@ -1254,7 +1280,7 @@ static int ub953_hw_init(struct ub953_data *priv)
UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT;
v |= UB953_REG_GENERAL_CFG_CRC_TX_GEN_ENABLE;
- ret = ub953_write(priv, UB953_REG_GENERAL_CFG, v);
+ ret = ub953_write(priv, UB953_REG_GENERAL_CFG, v, NULL);
if (ret)
return ret;
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index d1cc37246452..03986a2aaf2c 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -618,12 +618,15 @@ static const struct ub960_format_info *ub960_find_format(u32 code)
* Basic device access
*/
-static int ub960_read(struct ub960_data *priv, u8 reg, u8 *val)
+static int ub960_read(struct ub960_data *priv, u8 reg, u8 *val, int *err)
{
struct device *dev = &priv->client->dev;
unsigned int v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = regmap_read(priv->regmap, reg, &v);
@@ -638,14 +641,20 @@ static int ub960_read(struct ub960_data *priv, u8 reg, u8 *val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub960_write(struct ub960_data *priv, u8 reg, u8 val)
+static int ub960_write(struct ub960_data *priv, u8 reg, u8 val, int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = regmap_write(priv->regmap, reg, val);
@@ -655,14 +664,21 @@ static int ub960_write(struct ub960_data *priv, u8 reg, u8 val)
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub960_update_bits(struct ub960_data *priv, u8 reg, u8 mask, u8 val)
+static int ub960_update_bits(struct ub960_data *priv, u8 reg, u8 mask, u8 val,
+ int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = regmap_update_bits(priv->regmap, reg, mask, val);
@@ -672,15 +688,21 @@ static int ub960_update_bits(struct ub960_data *priv, u8 reg, u8 mask, u8 val)
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub960_read16(struct ub960_data *priv, u8 reg, u16 *val)
+static int ub960_read16(struct ub960_data *priv, u8 reg, u16 *val, int *err)
{
struct device *dev = &priv->client->dev;
__be16 __v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = regmap_bulk_read(priv->regmap, reg, &__v, sizeof(__v));
@@ -695,6 +717,9 @@ static int ub960_read16(struct ub960_data *priv, u8 reg, u16 *val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@ -721,12 +746,16 @@ static int ub960_rxport_select(struct ub960_data *priv, u8 nport)
return 0;
}
-static int ub960_rxport_read(struct ub960_data *priv, u8 nport, u8 reg, u8 *val)
+static int ub960_rxport_read(struct ub960_data *priv, u8 nport, u8 reg,
+ u8 *val, int *err)
{
struct device *dev = &priv->client->dev;
unsigned int v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_rxport_select(priv, nport);
@@ -745,14 +774,21 @@ static int ub960_rxport_read(struct ub960_data *priv, u8 nport, u8 reg, u8 *val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub960_rxport_write(struct ub960_data *priv, u8 nport, u8 reg, u8 val)
+static int ub960_rxport_write(struct ub960_data *priv, u8 nport, u8 reg,
+ u8 val, int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_rxport_select(priv, nport);
@@ -767,15 +803,21 @@ static int ub960_rxport_write(struct ub960_data *priv, u8 nport, u8 reg, u8 val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
static int ub960_rxport_update_bits(struct ub960_data *priv, u8 nport, u8 reg,
- u8 mask, u8 val)
+ u8 mask, u8 val, int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_rxport_select(priv, nport);
@@ -790,16 +832,22 @@ static int ub960_rxport_update_bits(struct ub960_data *priv, u8 nport, u8 reg,
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
static int ub960_rxport_read16(struct ub960_data *priv, u8 nport, u8 reg,
- u16 *val)
+ u16 *val, int *err)
{
struct device *dev = &priv->client->dev;
__be16 __v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_rxport_select(priv, nport);
@@ -818,6 +866,9 @@ static int ub960_rxport_read16(struct ub960_data *priv, u8 nport, u8 reg,
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@ -844,12 +895,16 @@ static int ub960_txport_select(struct ub960_data *priv, u8 nport)
return 0;
}
-static int ub960_txport_read(struct ub960_data *priv, u8 nport, u8 reg, u8 *val)
+static int ub960_txport_read(struct ub960_data *priv, u8 nport, u8 reg,
+ u8 *val, int *err)
{
struct device *dev = &priv->client->dev;
unsigned int v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_txport_select(priv, nport);
@@ -868,14 +923,21 @@ static int ub960_txport_read(struct ub960_data *priv, u8 nport, u8 reg, u8 *val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub960_txport_write(struct ub960_data *priv, u8 nport, u8 reg, u8 val)
+static int ub960_txport_write(struct ub960_data *priv, u8 nport, u8 reg,
+ u8 val, int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_txport_select(priv, nport);
@@ -890,15 +952,21 @@ static int ub960_txport_write(struct ub960_data *priv, u8 nport, u8 reg, u8 val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
static int ub960_txport_update_bits(struct ub960_data *priv, u8 nport, u8 reg,
- u8 mask, u8 val)
+ u8 mask, u8 val, int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_txport_select(priv, nport);
@@ -913,6 +981,9 @@ static int ub960_txport_update_bits(struct ub960_data *priv, u8 nport, u8 reg,
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@ -938,12 +1009,16 @@ static int ub960_select_ind_reg_block(struct ub960_data *priv, u8 block)
return 0;
}
-static int ub960_read_ind(struct ub960_data *priv, u8 block, u8 reg, u8 *val)
+static int ub960_read_ind(struct ub960_data *priv, u8 block, u8 reg, u8 *val,
+ int *err)
{
struct device *dev = &priv->client->dev;
unsigned int v;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_select_ind_reg_block(priv, block);
@@ -971,14 +1046,21 @@ static int ub960_read_ind(struct ub960_data *priv, u8 block, u8 reg, u8 *val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
-static int ub960_write_ind(struct ub960_data *priv, u8 block, u8 reg, u8 val)
+static int ub960_write_ind(struct ub960_data *priv, u8 block, u8 reg, u8 val,
+ int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_select_ind_reg_block(priv, block);
@@ -1004,15 +1086,21 @@ static int ub960_write_ind(struct ub960_data *priv, u8 block, u8 reg, u8 val)
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
static int ub960_ind_update_bits(struct ub960_data *priv, u8 block, u8 reg,
- u8 mask, u8 val)
+ u8 mask, u8 val, int *err)
{
struct device *dev = &priv->client->dev;
int ret;
+ if (err && *err)
+ return *err;
+
mutex_lock(&priv->reg_lock);
ret = ub960_select_ind_reg_block(priv, block);
@@ -1039,6 +1127,9 @@ static int ub960_ind_update_bits(struct ub960_data *priv, u8 block, u8 reg,
out_unlock:
mutex_unlock(&priv->reg_lock);
+ if (ret && err)
+ *err = ret;
+
return ret;
}
@@ -1067,9 +1158,9 @@ static int ub960_atr_attach_client(struct i2c_atr *atr, u32 chan_id,
rxport->aliased_clients[reg_idx] = client;
ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ID(reg_idx),
- client->addr << 1);
+ client->addr << 1, NULL);
ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx),
- alias << 1);
+ alias << 1, NULL);
dev_dbg(dev, "rx%u: client 0x%02x assigned alias 0x%02x at slot %u\n",
rxport->nport, client->addr, alias, reg_idx);
@@ -1098,7 +1189,8 @@ static void ub960_atr_detach_client(struct i2c_atr *atr, u32 chan_id,
rxport->aliased_clients[reg_idx] = NULL;
- ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx), 0);
+ ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx), 0,
+ NULL);
dev_dbg(dev, "rx%u: client 0x%02x released at slot %u\n", rxport->nport,
client->addr, reg_idx);
@@ -1199,7 +1291,8 @@ static void ub960_csi_handle_events(struct ub960_data *priv, u8 nport)
u8 csi_tx_isr;
int ret;
- ret = ub960_txport_read(priv, nport, UB960_TR_CSI_TX_ISR, &csi_tx_isr);
+ ret = ub960_txport_read(priv, nport, UB960_TR_CSI_TX_ISR, &csi_tx_isr,
+ NULL);
if (ret)
return;
@@ -1264,15 +1357,15 @@ static void ub960_rxport_clear_errors(struct ub960_data *priv,
{
u8 v;
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v);
- ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &v);
- ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &v);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &v, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &v, NULL);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_LO, &v);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_LO, &v, NULL);
- ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v);
+ ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v, NULL);
}
static void ub960_clear_rx_errors(struct ub960_data *priv)
@@ -1291,24 +1384,24 @@ static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
int ret;
ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_CLK, &v);
+ UB960_IR_RX_ANA_STROBE_SET_CLK, &v, NULL);
clk_delay = (v & UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY) ?
0 : UB960_MANUAL_STROBE_EXTRA_DELAY;
ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_DATA, &v);
+ UB960_IR_RX_ANA_STROBE_SET_DATA, &v, NULL);
data_delay = (v & UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY) ?
0 : UB960_MANUAL_STROBE_EXTRA_DELAY;
- ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_0, &v);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_0, &v, NULL);
if (ret)
return ret;
clk_delay += v & UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK;
- ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v, NULL);
if (ret)
return ret;
@@ -1337,10 +1430,10 @@ static void ub960_rxport_set_strobe_pos(struct ub960_data *priv,
data_delay = strobe_pos | UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY;
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_CLK, clk_delay);
+ UB960_IR_RX_ANA_STROBE_SET_CLK, clk_delay, NULL);
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_DATA, data_delay);
+ UB960_IR_RX_ANA_STROBE_SET_DATA, data_delay, NULL);
}
static void ub960_rxport_set_strobe_range(struct ub960_data *priv,
@@ -1352,7 +1445,8 @@ static void ub960_rxport_set_strobe_range(struct ub960_data *priv,
ub960_write(priv, UB960_XR_SFILTER_CFG,
((u8)strobe_min << UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) |
- ((u8)strobe_max << UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT));
+ ((u8)strobe_max << UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT),
+ NULL);
}
static int ub960_rxport_get_eq_level(struct ub960_data *priv,
@@ -1361,7 +1455,7 @@ static int ub960_rxport_get_eq_level(struct ub960_data *priv,
int ret;
u8 v;
- ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_STATUS, &v);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_STATUS, &v, NULL);
if (ret)
return ret;
@@ -1386,7 +1480,7 @@ static void ub960_rxport_set_eq_level(struct ub960_data *priv,
eq_stage_2_select_value = eq_level - eq_stage_max;
}
- ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v);
+ ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v, NULL);
v &= ~(UB960_RR_AEQ_BYPASS_EQ_STAGE1_VALUE_MASK |
UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_MASK);
@@ -1394,7 +1488,7 @@ static void ub960_rxport_set_eq_level(struct ub960_data *priv,
v |= eq_stage_2_select_value << UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_SHIFT;
v |= UB960_RR_AEQ_BYPASS_ENABLE;
- ub960_rxport_write(priv, nport, UB960_RR_AEQ_BYPASS, v);
+ ub960_rxport_write(priv, nport, UB960_RR_AEQ_BYPASS, v, NULL);
}
static void ub960_rxport_set_eq_range(struct ub960_data *priv,
@@ -1402,12 +1496,13 @@ static void ub960_rxport_set_eq_range(struct ub960_data *priv,
{
ub960_rxport_write(priv, nport, UB960_RR_AEQ_MIN_MAX,
(eq_min << UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT) |
- (eq_max << UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT));
+ (eq_max << UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT),
+ NULL);
/* Enable AEQ min setting */
ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_CTL2,
UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR,
- UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR);
+ UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR, NULL);
}
static void ub960_rxport_config_eq(struct ub960_data *priv, unsigned int nport)
@@ -1419,12 +1514,12 @@ static void ub960_rxport_config_eq(struct ub960_data *priv, unsigned int nport)
if (priv->strobe.manual) {
/* Disable AEQ_SFILTER_EN */
ub960_update_bits(priv, UB960_XR_AEQ_CTL1,
- UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN, 0);
+ UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN, 0, NULL);
} else {
/* Enable SFILTER and error control */
ub960_write(priv, UB960_XR_AEQ_CTL1,
UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_MASK |
- UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN);
+ UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN, NULL);
/* Set AEQ strobe range */
ub960_rxport_set_strobe_range(priv, priv->strobe.min,
@@ -1445,7 +1540,7 @@ static void ub960_rxport_config_eq(struct ub960_data *priv, unsigned int nport)
/* Enable AEQ Bypass */
ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
UB960_RR_AEQ_BYPASS_ENABLE,
- UB960_RR_AEQ_BYPASS_ENABLE);
+ UB960_RR_AEQ_BYPASS_ENABLE, NULL);
} else {
ub960_rxport_set_eq_range(priv, nport,
rxport->eq.aeq.eq_level_min,
@@ -1453,7 +1548,7 @@ static void ub960_rxport_config_eq(struct ub960_data *priv, unsigned int nport)
/* Disable AEQ Bypass */
ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
- UB960_RR_AEQ_BYPASS_ENABLE, 0);
+ UB960_RR_AEQ_BYPASS_ENABLE, 0, NULL);
}
}
@@ -1469,7 +1564,7 @@ static int ub960_rxport_link_ok(struct ub960_data *priv, unsigned int nport,
bool errors;
ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1,
- &rx_port_sts1);
+ &rx_port_sts1, NULL);
if (ret)
return ret;
@@ -1479,25 +1574,27 @@ static int ub960_rxport_link_ok(struct ub960_data *priv, unsigned int nport,
}
ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2,
- &rx_port_sts2);
+ &rx_port_sts2, NULL);
if (ret)
return ret;
- ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &csi_rx_sts);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &csi_rx_sts,
+ NULL);
if (ret)
return ret;
ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER,
- &csi_err_cnt);
+ &csi_err_cnt, NULL);
if (ret)
return ret;
- ret = ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &bcc_sts);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &bcc_sts,
+ NULL);
if (ret)
return ret;
ret = ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI,
- &parity_errors);
+ &parity_errors, NULL);
if (ret)
return ret;
@@ -1600,7 +1697,8 @@ static int ub960_rxport_wait_locks(struct ub960_data *priv,
continue;
}
- ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v);
+ ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v,
+ NULL);
if (priv->hw_data->is_ub9702) {
dev_dbg(dev, "\trx%u: locked, freq %llu Hz\n",
@@ -1787,7 +1885,7 @@ static void ub960_init_tx_port(struct ub960_data *priv,
if (!txport->non_continous_clk)
csi_ctl |= UB960_TR_CSI_CTL_CSI_CONTS_CLOCK;
- ub960_txport_write(priv, nport, UB960_TR_CSI_CTL, csi_ctl);
+ ub960_txport_write(priv, nport, UB960_TR_CSI_CTL, csi_ctl, NULL);
}
static int ub960_init_tx_ports(struct ub960_data *priv)
@@ -1818,24 +1916,30 @@ static int ub960_init_tx_ports(struct ub960_data *priv)
break;
}
- ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select);
+ ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select, NULL);
if (priv->hw_data->is_ub9702) {
- ub960_write(priv, UB960_SR_CSI_PLL_DIV, pll_div);
+ ub960_write(priv, UB960_SR_CSI_PLL_DIV, pll_div, NULL);
switch (priv->tx_data_rate) {
case MHZ(1600):
default:
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x80);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
+ 0x80, NULL);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b,
+ 0x2a, NULL);
break;
case MHZ(800):
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x90);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4f, 0x2a);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
+ 0x90, NULL);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4f,
+ 0x2a, NULL);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b,
+ 0x2a, NULL);
break;
case MHZ(400):
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0xa0);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
+ 0xa0, NULL);
break;
}
}
@@ -1890,21 +1994,22 @@ static void ub960_init_rx_port_ub960(struct ub960_data *priv,
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK,
- bc_freq_val);
+ bc_freq_val, NULL);
switch (rxport->rx_mode) {
case RXPORT_MODE_RAW10:
/* FPD3_MODE = RAW10 Mode (DS90UB913A-Q1 / DS90UB933-Q1 compatible) */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG,
UB960_RR_PORT_CONFIG_FPD3_MODE_MASK,
- 0x3);
+ 0x3, NULL);
/*
* RAW10_8BIT_CTL = 0b10 : 8-bit processing using upper 8 bits
*/
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2,
UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_MASK,
- 0x2 << UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_SHIFT);
+ 0x2 << UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_SHIFT,
+ NULL);
break;
@@ -1917,33 +2022,34 @@ static void ub960_init_rx_port_ub960(struct ub960_data *priv,
case RXPORT_MODE_CSI2_NONSYNC:
/* CSI-2 Mode (DS90UB953-Q1 compatible) */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG, 0x3,
- 0x0);
+ 0x0, NULL);
break;
}
/* LV_POLARITY & FV_POLARITY */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
- rxport->lv_fv_pol);
+ rxport->lv_fv_pol, NULL);
/* Enable all interrupt sources from this port */
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07);
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07, NULL);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f, NULL);
/* Enable I2C_PASS_THROUGH */
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
- UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH);
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, NULL);
/* Enable I2C communication to the serializer via the alias addr */
ub960_rxport_write(priv, nport, UB960_RR_SER_ALIAS_ID,
- rxport->ser.alias << 1);
+ rxport->ser.alias << 1, NULL);
/* Configure EQ related settings */
ub960_rxport_config_eq(priv, nport);
/* Enable RX port */
- ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport));
+ ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
+ NULL);
}
static void ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
@@ -1984,31 +2090,36 @@ static void ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
}
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
- bc_freq_val);
- ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, fpd_func_mode);
+ bc_freq_val, NULL);
+ ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, fpd_func_mode,
+ NULL);
/* set serdes_eq_mode = 1 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa8, 0x80);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa8, 0x80,
+ NULL);
/* enable serdes driver */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x0d, 0x7f);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x0d, 0x7f,
+ NULL);
/* set serdes_eq_offset=4 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04,
+ NULL);
/* init default serdes_eq_max in 0xa9 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa9, 0x23);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa9, 0x23,
+ NULL);
/* init serdes_eq_min in 0xaa */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xaa, 0);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xaa, 0, NULL);
/* serdes_driver_ctl2 control: DS90UB953-Q1/DS90UB933-Q1/DS90UB913A-Q1 */
ub960_ind_update_bits(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b,
- BIT(3), BIT(3));
+ BIT(3), BIT(3), NULL);
/* RX port to half-rate */
ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
- BIT(nport * 2));
+ BIT(nport * 2), NULL);
}
static void ub960_init_rx_port_ub9702_fpd4_aeq(struct ub960_data *priv,
@@ -2021,28 +2132,37 @@ static void ub960_init_rx_port_ub9702_fpd4_aeq(struct ub960_data *priv,
u8 v;
/* AEQ init */
- ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2c, &v);
+ ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2c, &v,
+ NULL);
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, v);
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28, v + 1);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, v,
+ NULL);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28,
+ v + 1, NULL);
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x00);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b,
+ 0x00, NULL);
}
/* enable serdes_eq_ctl2 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x9e, 0x00);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x9e, 0x00,
+ NULL);
/* enable serdes_eq_ctl1 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x90, 0x40);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x90, 0x40,
+ NULL);
/* enable serdes_eq_en */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2e, 0x40);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2e, 0x40,
+ NULL);
/* disable serdes_eq_override */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xf0, 0x00);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xf0, 0x00,
+ NULL);
/* disable serdes_gain_override */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x71, 0x00);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x71, 0x00,
+ NULL);
}
static void ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
@@ -2077,32 +2197,38 @@ static void ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
}
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
- bc_freq_val);
+ bc_freq_val, NULL);
/* FPD4 Sync Mode */
- ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, 0);
+ ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, 0, NULL);
/* add serdes_eq_offset of 4 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04,
+ NULL);
/* FPD4 serdes_start_eq in 0x27: assign default */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, 0x0);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, 0x0, NULL);
/* FPD4 serdes_end_eq in 0x28: assign default */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28, 0x23);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28, 0x23,
+ NULL);
/* set serdes_driver_mode into FPD IV mode */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x04, 0x00);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x04, 0x00,
+ NULL);
/* set FPD PBC drv into FPD IV mode */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b, 0x00);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b, 0x00,
+ NULL);
/* set serdes_system_init to 0x2f */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x21, 0x2f);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x21, 0x2f,
+ NULL);
/* set serdes_system_rst in reset mode */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25, 0xc1);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25, 0xc1,
+ NULL);
/* RX port to 7.55G mode */
ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
- 0 << (nport * 2));
+ 0 << (nport * 2), NULL);
ub960_init_rx_port_ub9702_fpd4_aeq(priv, rxport);
}
@@ -2124,7 +2250,7 @@ static void ub960_init_rx_port_ub9702(struct ub960_data *priv,
* 0b10 : 8-bit processing using upper 8 bits
*/
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2,
- 0x3 << 6, 0x2 << 6);
+ 0x3 << 6, 0x2 << 6, NULL);
break;
@@ -2141,27 +2267,29 @@ static void ub960_init_rx_port_ub9702(struct ub960_data *priv,
/* LV_POLARITY & FV_POLARITY */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
- rxport->lv_fv_pol);
+ rxport->lv_fv_pol, NULL);
/* Enable all interrupt sources from this port */
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07);
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07, NULL);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f, NULL);
/* Enable I2C_PASS_THROUGH */
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
- UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH);
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, NULL);
/* Enable I2C communication to the serializer via the alias addr */
ub960_rxport_write(priv, nport, UB960_RR_SER_ALIAS_ID,
- rxport->ser.alias << 1);
+ rxport->ser.alias << 1, NULL);
/* Enable RX port */
- ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport));
+ ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
+ NULL);
if (rxport->cdr_mode == RXPORT_CDR_FPD4) {
/* unreset 960 AEQ */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25, 0x41);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25,
+ 0x41, NULL);
}
}
@@ -2196,16 +2324,16 @@ static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
/* Read interrupts (also clears most of them) */
if (!ret)
ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1,
- &rx_port_sts1);
+ &rx_port_sts1, NULL);
if (!ret)
ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2,
- &rx_port_sts2);
+ &rx_port_sts2, NULL);
if (!ret)
ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS,
- &csi_rx_sts);
+ &csi_rx_sts, NULL);
if (!ret)
ret = ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS,
- &bcc_sts);
+ &bcc_sts, NULL);
if (ret)
return;
@@ -2214,7 +2342,7 @@ static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
u16 v;
ret = ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI,
- &v);
+ &v, NULL);
if (!ret)
dev_err(dev, "rx%u parity errors: %u\n", nport, v);
}
@@ -2273,7 +2401,8 @@ static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
if (rx_port_sts2 & UB960_RR_RX_PORT_STS2_LINE_LEN_CHG) {
u16 v;
- ret = ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1, &v);
+ ret = ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1,
+ &v, NULL);
if (!ret)
dev_dbg(dev, "rx%u line len changed: %u\n", nport, v);
}
@@ -2282,7 +2411,7 @@ static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
u16 v;
ret = ub960_rxport_read16(priv, nport, UB960_RR_LINE_COUNT_HI,
- &v);
+ &v, NULL);
if (!ret)
dev_dbg(dev, "rx%u line count changed: %u\n", nport, v);
}
@@ -2354,7 +2483,7 @@ static int ub960_enable_tx_port(struct ub960_data *priv, unsigned int nport)
return ub960_txport_update_bits(priv, nport, UB960_TR_CSI_CTL,
UB960_TR_CSI_CTL_CSI_ENABLE,
- UB960_TR_CSI_CTL_CSI_ENABLE);
+ UB960_TR_CSI_CTL_CSI_ENABLE, NULL);
}
static void ub960_disable_tx_port(struct ub960_data *priv, unsigned int nport)
@@ -2364,7 +2493,7 @@ static void ub960_disable_tx_port(struct ub960_data *priv, unsigned int nport)
dev_dbg(dev, "disable TX port %u\n", nport);
ub960_txport_update_bits(priv, nport, UB960_TR_CSI_CTL,
- UB960_TR_CSI_CTL_CSI_ENABLE, 0);
+ UB960_TR_CSI_CTL_CSI_ENABLE, 0, NULL);
}
static int ub960_enable_rx_port(struct ub960_data *priv, unsigned int nport)
@@ -2375,7 +2504,7 @@ static int ub960_enable_rx_port(struct ub960_data *priv, unsigned int nport)
/* Enable forwarding */
return ub960_update_bits(priv, UB960_SR_FWD_CTL1,
- UB960_SR_FWD_CTL1_PORT_DIS(nport), 0);
+ UB960_SR_FWD_CTL1_PORT_DIS(nport), 0, NULL);
}
static void ub960_disable_rx_port(struct ub960_data *priv, unsigned int nport)
@@ -2387,7 +2516,7 @@ static void ub960_disable_rx_port(struct ub960_data *priv, unsigned int nport)
/* Disable forwarding */
ub960_update_bits(priv, UB960_SR_FWD_CTL1,
UB960_SR_FWD_CTL1_PORT_DIS(nport),
- UB960_SR_FWD_CTL1_PORT_DIS(nport));
+ UB960_SR_FWD_CTL1_PORT_DIS(nport), NULL);
}
/*
@@ -2528,12 +2657,13 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
switch (rxport->rx_mode) {
case RXPORT_MODE_RAW10:
ub960_rxport_write(priv, nport, UB960_RR_RAW10_ID,
- rx_data[nport].pixel_dt | (vc << UB960_RR_RAW10_ID_VC_SHIFT));
+ rx_data[nport].pixel_dt | (vc << UB960_RR_RAW10_ID_VC_SHIFT),
+ NULL);
ub960_rxport_write(priv, rxport->nport,
UB960_RR_RAW_EMBED_DTYPE,
(rx_data[nport].meta_lines << UB960_RR_RAW_EMBED_DTYPE_LINES_SHIFT) |
- rx_data[nport].meta_dt);
+ rx_data[nport].meta_dt, NULL);
break;
@@ -2550,7 +2680,8 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
(vc << UB960_RR_CSI_VC_MAP_SHIFT(3)) |
(vc << UB960_RR_CSI_VC_MAP_SHIFT(2)) |
(vc << UB960_RR_CSI_VC_MAP_SHIFT(1)) |
- (vc << UB960_RR_CSI_VC_MAP_SHIFT(0)));
+ (vc << UB960_RR_CSI_VC_MAP_SHIFT(0)),
+ NULL);
} else {
unsigned int i;
@@ -2558,7 +2689,8 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
for (i = 0; i < 8; i++)
ub960_rxport_write(priv, nport,
UB960_RR_VC_ID_MAP(i),
- (nport << 4) | nport);
+ (nport << 4) | nport,
+ NULL);
}
break;
@@ -2570,7 +2702,7 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
fwd_ctl &= ~BIT(nport); /* forward to TX0 */
}
- ub960_write(priv, UB960_SR_FWD_CTL1, fwd_ctl);
+ ub960_write(priv, UB960_SR_FWD_CTL1, fwd_ctl, NULL);
return 0;
}
@@ -2986,7 +3118,7 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
/* Strobe */
- ret = ub960_read(priv, UB960_XR_AEQ_CTL1, &v);
+ ret = ub960_read(priv, UB960_XR_AEQ_CTL1, &v, NULL);
if (ret)
return;
@@ -2995,7 +3127,7 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
"Manual");
if (v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) {
- ret = ub960_read(priv, UB960_XR_SFILTER_CFG, &v);
+ ret = ub960_read(priv, UB960_XR_SFILTER_CFG, &v, NULL);
if (ret)
return;
@@ -3012,7 +3144,7 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
/* EQ */
- ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v, NULL);
if (ret)
return;
@@ -3021,7 +3153,8 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
"Adaptive");
if (!(v & UB960_RR_AEQ_BYPASS_ENABLE)) {
- ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_MIN_MAX, &v);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_MIN_MAX, &v,
+ NULL);
if (ret)
return;
@@ -3047,7 +3180,7 @@ static int ub960_log_status(struct v4l2_subdev *sd)
state = v4l2_subdev_lock_and_get_active_state(sd);
for (unsigned int i = 0; i < sizeof(id); i++)
- ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i]);
+ ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i], NULL);
dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
@@ -3061,20 +3194,24 @@ static int ub960_log_status(struct v4l2_subdev *sd)
continue;
}
- ub960_txport_read(priv, nport, UB960_TR_CSI_STS, &v);
+ ub960_txport_read(priv, nport, UB960_TR_CSI_STS, &v, NULL);
dev_info(dev, "\tsync %u, pass %u\n", v & (u8)BIT(1),
v & (u8)BIT(0));
- ub960_read16(priv, UB960_SR_CSI_FRAME_COUNT_HI(nport), &v16);
+ ub960_read16(priv, UB960_SR_CSI_FRAME_COUNT_HI(nport), &v16,
+ NULL);
dev_info(dev, "\tframe counter %u\n", v16);
- ub960_read16(priv, UB960_SR_CSI_FRAME_ERR_COUNT_HI(nport), &v16);
+ ub960_read16(priv, UB960_SR_CSI_FRAME_ERR_COUNT_HI(nport),
+ &v16, NULL);
dev_info(dev, "\tframe error counter %u\n", v16);
- ub960_read16(priv, UB960_SR_CSI_LINE_COUNT_HI(nport), &v16);
+ ub960_read16(priv, UB960_SR_CSI_LINE_COUNT_HI(nport), &v16,
+ NULL);
dev_info(dev, "\tline counter %u\n", v16);
- ub960_read16(priv, UB960_SR_CSI_LINE_ERR_COUNT_HI(nport), &v16);
+ ub960_read16(priv, UB960_SR_CSI_LINE_ERR_COUNT_HI(nport),
+ &v16, NULL);
dev_info(dev, "\tline error counter %u\n", v16);
}
@@ -3088,7 +3225,8 @@ static int ub960_log_status(struct v4l2_subdev *sd)
continue;
}
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v,
+ NULL);
if (v & UB960_RR_RX_PORT_STS1_LOCK_STS)
dev_info(dev, "\tLocked\n");
@@ -3096,22 +3234,28 @@ static int ub960_log_status(struct v4l2_subdev *sd)
dev_info(dev, "\tNot locked\n");
dev_info(dev, "\trx_port_sts1 %#02x\n", v);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v,
+ NULL);
dev_info(dev, "\trx_port_sts2 %#02x\n", v);
- ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v16);
+ ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v16,
+ NULL);
dev_info(dev, "\tlink freq %llu Hz\n", ((u64)v16 * HZ_PER_MHZ) >> 8);
- ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v16);
+ ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v16,
+ NULL);
dev_info(dev, "\tparity errors %u\n", v16);
- ub960_rxport_read16(priv, nport, UB960_RR_LINE_COUNT_HI, &v16);
+ ub960_rxport_read16(priv, nport, UB960_RR_LINE_COUNT_HI, &v16,
+ NULL);
dev_info(dev, "\tlines per frame %u\n", v16);
- ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1, &v16);
+ ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1, &v16,
+ NULL);
dev_info(dev, "\tbytes per line %u\n", v16);
- ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v);
+ ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v,
+ NULL);
dev_info(dev, "\tcsi_err_counter %u\n", v);
if (!priv->hw_data->is_ub9702)
@@ -3125,7 +3269,7 @@ static int ub960_log_status(struct v4l2_subdev *sd)
ctl_reg = UB960_RR_BC_GPIO_CTL(i / 2);
ctl_shift = (i % 2) * 4;
- ub960_rxport_read(priv, nport, ctl_reg, &v);
+ ub960_rxport_read(priv, nport, ctl_reg, &v, NULL);
dev_info(dev, "\tGPIO%u: mode %u\n", i,
(v >> ctl_shift) & 0xf);
@@ -3168,13 +3312,13 @@ static irqreturn_t ub960_handle_events(int irq, void *arg)
u8 fwd_sts;
int ret;
- ret = ub960_read(priv, UB960_SR_INTERRUPT_STS, &int_sts);
+ ret = ub960_read(priv, UB960_SR_INTERRUPT_STS, &int_sts, NULL);
if (ret || !int_sts)
return IRQ_NONE;
dev_dbg(&priv->client->dev, "INTERRUPT_STS %x\n", int_sts);
- ret = ub960_read(priv, UB960_SR_FWD_STS, &fwd_sts);
+ ret = ub960_read(priv, UB960_SR_FWD_STS, &fwd_sts, NULL);
if (ret)
return IRQ_NONE;
@@ -3804,7 +3948,7 @@ static void ub960_reset(struct ub960_data *priv, bool reset_regs)
bit = reset_regs ? UB960_SR_RESET_DIGITAL_RESET1 :
UB960_SR_RESET_DIGITAL_RESET0;
- ub960_write(priv, UB960_SR_RESET, bit);
+ ub960_write(priv, UB960_SR_RESET, bit, NULL);
mutex_lock(&priv->reg_lock);
@@ -3876,7 +4020,7 @@ static int ub960_enable_core_hw(struct ub960_data *priv)
ub960_reset(priv, true);
/* Runtime check register accessibility */
- ret = ub960_read(priv, UB960_SR_REV_MASK, &rev_mask);
+ ret = ub960_read(priv, UB960_SR_REV_MASK, &rev_mask, NULL);
if (ret) {
dev_err_probe(dev, ret, "Cannot read first register, abort\n");
goto err_pd_gpio;
@@ -3885,14 +4029,16 @@ static int ub960_enable_core_hw(struct ub960_data *priv)
dev_dbg(dev, "Found %s (rev/mask %#04x)\n", priv->hw_data->model,
rev_mask);
- ret = ub960_read(priv, UB960_SR_DEVICE_STS, &dev_sts);
+ ret = ub960_read(priv, UB960_SR_DEVICE_STS, &dev_sts, NULL);
if (ret)
goto err_pd_gpio;
if (priv->hw_data->is_ub9702)
- ret = ub960_read(priv, UB9702_SR_REFCLK_FREQ, &refclk_freq);
+ ret = ub960_read(priv, UB9702_SR_REFCLK_FREQ, &refclk_freq,
+ NULL);
else
- ret = ub960_read(priv, UB960_XR_REFCLK_FREQ, &refclk_freq);
+ ret = ub960_read(priv, UB960_XR_REFCLK_FREQ, &refclk_freq,
+ NULL);
if (ret)
goto err_pd_gpio;
@@ -3901,7 +4047,7 @@ static int ub960_enable_core_hw(struct ub960_data *priv)
clk_get_rate(priv->refclk) / HZ_PER_MHZ);
/* Disable all RX ports by default */
- ret = ub960_write(priv, UB960_SR_RX_PORT_CTL, 0);
+ ret = ub960_write(priv, UB960_SR_RX_PORT_CTL, 0, NULL);
if (ret)
goto err_pd_gpio;
@@ -3909,7 +4055,8 @@ static int ub960_enable_core_hw(struct ub960_data *priv)
if (priv->hw_data->is_ub9702) {
ret = ub960_update_bits(priv, UB960_SR_RESET,
UB960_SR_RESET_GPIO_LOCK_RELEASE,
- UB960_SR_RESET_GPIO_LOCK_RELEASE);
+ UB960_SR_RESET_GPIO_LOCK_RELEASE,
+ NULL);
if (ret)
goto err_pd_gpio;
}
@@ -4035,7 +4182,7 @@ static int ub960_probe(struct i2c_client *client)
#ifdef UB960_DEBUG_I2C_RX_ID
for (unsigned int i = 0; i < priv->hw_data->num_rxports; i++)
ub960_write(priv, UB960_SR_I2C_RX_ID(i),
- (UB960_DEBUG_I2C_RX_ID + i) << 1);
+ (UB960_DEBUG_I2C_RX_ID + i) << 1, NULL);
#endif
return 0;
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 04/19] media: i2c: ds90ub960: Add error handling to multiple places
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (2 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 03/19] media: i2c: ds90ub9xx: Add err parameter to read/write funcs Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 05/19] media: i2c: ds90ub953: Add error handling to ub953_log_status() Tomi Valkeinen
` (14 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
The driver is missing checks for i2c read/write errors in many places.
Now that we have added the err parameter to the read/write functions in
the previous patch, add error handling to all the missing places.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 589 +++++++++++++++++++++++++++---------------
1 file changed, 376 insertions(+), 213 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index 03986a2aaf2c..80bbba0792c1 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -1144,6 +1144,7 @@ static int ub960_atr_attach_client(struct i2c_atr *atr, u32 chan_id,
struct ub960_rxport *rxport = priv->rxports[chan_id];
struct device *dev = &priv->client->dev;
unsigned int reg_idx;
+ int ret = 0;
for (reg_idx = 0; reg_idx < ARRAY_SIZE(rxport->aliased_clients); reg_idx++) {
if (!rxport->aliased_clients[reg_idx])
@@ -1158,9 +1159,12 @@ static int ub960_atr_attach_client(struct i2c_atr *atr, u32 chan_id,
rxport->aliased_clients[reg_idx] = client;
ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ID(reg_idx),
- client->addr << 1, NULL);
+ client->addr << 1, &ret);
ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx),
- alias << 1, NULL);
+ alias << 1, &ret);
+
+ if (ret)
+ return ret;
dev_dbg(dev, "rx%u: client 0x%02x assigned alias 0x%02x at slot %u\n",
rxport->nport, client->addr, alias, reg_idx);
@@ -1175,6 +1179,7 @@ static void ub960_atr_detach_client(struct i2c_atr *atr, u32 chan_id,
struct ub960_rxport *rxport = priv->rxports[chan_id];
struct device *dev = &priv->client->dev;
unsigned int reg_idx;
+ int ret;
for (reg_idx = 0; reg_idx < ARRAY_SIZE(rxport->aliased_clients); reg_idx++) {
if (rxport->aliased_clients[reg_idx] == client)
@@ -1189,8 +1194,13 @@ static void ub960_atr_detach_client(struct i2c_atr *atr, u32 chan_id,
rxport->aliased_clients[reg_idx] = NULL;
- ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx), 0,
- NULL);
+ ret = ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx),
+ 0, NULL);
+ if (ret) {
+ dev_err(dev, "rx%u: unable to fully unmap client 0x%02x: %d\n",
+ rxport->nport, client->addr, ret);
+ return;
+ }
dev_dbg(dev, "rx%u: client 0x%02x released at slot %u\n", rxport->nport,
client->addr, reg_idx);
@@ -1285,7 +1295,7 @@ static int ub960_parse_dt_txport(struct ub960_data *priv,
return ret;
}
-static void ub960_csi_handle_events(struct ub960_data *priv, u8 nport)
+static int ub960_csi_handle_events(struct ub960_data *priv, u8 nport)
{
struct device *dev = &priv->client->dev;
u8 csi_tx_isr;
@@ -1294,13 +1304,15 @@ static void ub960_csi_handle_events(struct ub960_data *priv, u8 nport)
ret = ub960_txport_read(priv, nport, UB960_TR_CSI_TX_ISR, &csi_tx_isr,
NULL);
if (ret)
- return;
+ return ret;
if (csi_tx_isr & UB960_TR_CSI_TX_ISR_IS_CSI_SYNC_ERROR)
dev_warn(dev, "TX%u: CSI_SYNC_ERROR\n", nport);
if (csi_tx_isr & UB960_TR_CSI_TX_ISR_IS_CSI_PASS_ERROR)
dev_warn(dev, "TX%u: CSI_PASS_ERROR\n", nport);
+
+ return 0;
}
/* -----------------------------------------------------------------------------
@@ -1352,28 +1364,38 @@ static void ub960_rxport_disable_vpocs(struct ub960_data *priv)
}
}
-static void ub960_rxport_clear_errors(struct ub960_data *priv,
- unsigned int nport)
+static int ub960_rxport_clear_errors(struct ub960_data *priv,
+ unsigned int nport)
{
+ int ret = 0;
u8 v;
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v, NULL);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v, NULL);
- ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &v, NULL);
- ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &v, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v, &ret);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v, &ret);
+ ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &v, &ret);
+ ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &v, &ret);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v, NULL);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_LO, &v, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v, &ret);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_LO, &v, &ret);
- ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v, &ret);
+
+ return ret;
}
-static void ub960_clear_rx_errors(struct ub960_data *priv)
+static int ub960_clear_rx_errors(struct ub960_data *priv)
{
unsigned int nport;
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++)
- ub960_rxport_clear_errors(priv, nport);
+ for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+ int ret;
+
+ ret = ub960_rxport_clear_errors(priv, nport);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
@@ -1383,14 +1405,18 @@ static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
u8 clk_delay, data_delay;
int ret;
- ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_CLK, &v, NULL);
+ ret = ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB960_IR_RX_ANA_STROBE_SET_CLK, &v, NULL);
+ if (ret)
+ return ret;
clk_delay = (v & UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY) ?
0 : UB960_MANUAL_STROBE_EXTRA_DELAY;
- ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_DATA, &v, NULL);
+ ret = ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB960_IR_RX_ANA_STROBE_SET_DATA, &v, NULL);
+ if (ret)
+ return ret;
data_delay = (v & UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY) ?
0 : UB960_MANUAL_STROBE_EXTRA_DELAY;
@@ -1412,10 +1438,11 @@ static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
return 0;
}
-static void ub960_rxport_set_strobe_pos(struct ub960_data *priv,
- unsigned int nport, s8 strobe_pos)
+static int ub960_rxport_set_strobe_pos(struct ub960_data *priv,
+ unsigned int nport, s8 strobe_pos)
{
u8 clk_delay, data_delay;
+ int ret = 0;
clk_delay = UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY;
data_delay = UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY;
@@ -1430,23 +1457,25 @@ static void ub960_rxport_set_strobe_pos(struct ub960_data *priv,
data_delay = strobe_pos | UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY;
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_CLK, clk_delay, NULL);
+ UB960_IR_RX_ANA_STROBE_SET_CLK, clk_delay, &ret);
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
- UB960_IR_RX_ANA_STROBE_SET_DATA, data_delay, NULL);
+ UB960_IR_RX_ANA_STROBE_SET_DATA, data_delay, &ret);
+
+ return ret;
}
-static void ub960_rxport_set_strobe_range(struct ub960_data *priv,
- s8 strobe_min, s8 strobe_max)
+static int ub960_rxport_set_strobe_range(struct ub960_data *priv, s8 strobe_min,
+ s8 strobe_max)
{
/* Convert the signed strobe pos to positive zero based value */
strobe_min -= UB960_MIN_AEQ_STROBE_POS;
strobe_max -= UB960_MIN_AEQ_STROBE_POS;
- ub960_write(priv, UB960_XR_SFILTER_CFG,
- ((u8)strobe_min << UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) |
- ((u8)strobe_max << UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT),
- NULL);
+ return ub960_write(priv, UB960_XR_SFILTER_CFG,
+ ((u8)strobe_min << UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) |
+ ((u8)strobe_max << UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT),
+ NULL);
}
static int ub960_rxport_get_eq_level(struct ub960_data *priv,
@@ -1465,11 +1494,12 @@ static int ub960_rxport_get_eq_level(struct ub960_data *priv,
return 0;
}
-static void ub960_rxport_set_eq_level(struct ub960_data *priv,
- unsigned int nport, u8 eq_level)
+static int ub960_rxport_set_eq_level(struct ub960_data *priv,
+ unsigned int nport, u8 eq_level)
{
u8 eq_stage_1_select_value, eq_stage_2_select_value;
const unsigned int eq_stage_max = 7;
+ int ret;
u8 v;
if (eq_level <= eq_stage_max) {
@@ -1480,7 +1510,9 @@ static void ub960_rxport_set_eq_level(struct ub960_data *priv,
eq_stage_2_select_value = eq_level - eq_stage_max;
}
- ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v, NULL);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v, NULL);
+ if (ret)
+ return ret;
v &= ~(UB960_RR_AEQ_BYPASS_EQ_STAGE1_VALUE_MASK |
UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_MASK);
@@ -1488,68 +1520,102 @@ static void ub960_rxport_set_eq_level(struct ub960_data *priv,
v |= eq_stage_2_select_value << UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_SHIFT;
v |= UB960_RR_AEQ_BYPASS_ENABLE;
- ub960_rxport_write(priv, nport, UB960_RR_AEQ_BYPASS, v, NULL);
+ ret = ub960_rxport_write(priv, nport, UB960_RR_AEQ_BYPASS, v, NULL);
+ if (ret)
+ return ret;
+
+ return 0;
}
-static void ub960_rxport_set_eq_range(struct ub960_data *priv,
- unsigned int nport, u8 eq_min, u8 eq_max)
+static int ub960_rxport_set_eq_range(struct ub960_data *priv,
+ unsigned int nport, u8 eq_min, u8 eq_max)
{
+ int ret = 0;
+
ub960_rxport_write(priv, nport, UB960_RR_AEQ_MIN_MAX,
(eq_min << UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT) |
(eq_max << UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT),
- NULL);
+ &ret);
/* Enable AEQ min setting */
ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_CTL2,
UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR,
- UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR, NULL);
+ UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR, &ret);
+
+ return ret;
}
-static void ub960_rxport_config_eq(struct ub960_data *priv, unsigned int nport)
+static int ub960_rxport_config_eq(struct ub960_data *priv, unsigned int nport)
{
struct ub960_rxport *rxport = priv->rxports[nport];
+ int ret;
/* We also set common settings here. Should be moved elsewhere. */
if (priv->strobe.manual) {
/* Disable AEQ_SFILTER_EN */
- ub960_update_bits(priv, UB960_XR_AEQ_CTL1,
- UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN, 0, NULL);
+ ret = ub960_update_bits(priv, UB960_XR_AEQ_CTL1,
+ UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN, 0,
+ NULL);
+ if (ret)
+ return ret;
} else {
/* Enable SFILTER and error control */
- ub960_write(priv, UB960_XR_AEQ_CTL1,
- UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_MASK |
- UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN, NULL);
+ ret = ub960_write(priv, UB960_XR_AEQ_CTL1,
+ UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_MASK |
+ UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN,
+ NULL);
+
+ if (ret)
+ return ret;
/* Set AEQ strobe range */
- ub960_rxport_set_strobe_range(priv, priv->strobe.min,
- priv->strobe.max);
+ ret = ub960_rxport_set_strobe_range(priv, priv->strobe.min,
+ priv->strobe.max);
+ if (ret)
+ return ret;
}
/* The rest are port specific */
if (priv->strobe.manual)
- ub960_rxport_set_strobe_pos(priv, nport, rxport->eq.strobe_pos);
+ ret = ub960_rxport_set_strobe_pos(priv, nport,
+ rxport->eq.strobe_pos);
else
- ub960_rxport_set_strobe_pos(priv, nport, 0);
+ ret = ub960_rxport_set_strobe_pos(priv, nport, 0);
+
+ if (ret)
+ return ret;
if (rxport->eq.manual_eq) {
- ub960_rxport_set_eq_level(priv, nport,
- rxport->eq.manual.eq_level);
+ ret = ub960_rxport_set_eq_level(priv, nport,
+ rxport->eq.manual.eq_level);
+ if (ret)
+ return ret;
/* Enable AEQ Bypass */
- ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
- UB960_RR_AEQ_BYPASS_ENABLE,
- UB960_RR_AEQ_BYPASS_ENABLE, NULL);
+ ret = ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
+ UB960_RR_AEQ_BYPASS_ENABLE,
+ UB960_RR_AEQ_BYPASS_ENABLE,
+ NULL);
+ if (ret)
+ return ret;
} else {
- ub960_rxport_set_eq_range(priv, nport,
- rxport->eq.aeq.eq_level_min,
- rxport->eq.aeq.eq_level_max);
+ ret = ub960_rxport_set_eq_range(priv, nport,
+ rxport->eq.aeq.eq_level_min,
+ rxport->eq.aeq.eq_level_max);
+ if (ret)
+ return ret;
/* Disable AEQ Bypass */
- ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
- UB960_RR_AEQ_BYPASS_ENABLE, 0, NULL);
+ ret = ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
+ UB960_RR_AEQ_BYPASS_ENABLE, 0,
+ NULL);
+ if (ret)
+ return ret;
}
+
+ return 0;
}
static int ub960_rxport_link_ok(struct ub960_data *priv, unsigned int nport,
@@ -1697,8 +1763,11 @@ static int ub960_rxport_wait_locks(struct ub960_data *priv,
continue;
}
- ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v,
- NULL);
+ ret = ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH,
+ &v, NULL);
+
+ if (ret)
+ return ret;
if (priv->hw_data->is_ub9702) {
dev_dbg(dev, "\trx%u: locked, freq %llu Hz\n",
@@ -1867,8 +1936,8 @@ static void ub960_rxport_remove_serializers(struct ub960_data *priv)
}
}
-static void ub960_init_tx_port(struct ub960_data *priv,
- struct ub960_txport *txport)
+static int ub960_init_tx_port(struct ub960_data *priv,
+ struct ub960_txport *txport)
{
unsigned int nport = txport->nport;
u8 csi_ctl = 0;
@@ -1885,7 +1954,7 @@ static void ub960_init_tx_port(struct ub960_data *priv,
if (!txport->non_continous_clk)
csi_ctl |= UB960_TR_CSI_CTL_CSI_CONTS_CLOCK;
- ub960_txport_write(priv, nport, UB960_TR_CSI_CTL, csi_ctl, NULL);
+ return ub960_txport_write(priv, nport, UB960_TR_CSI_CTL, csi_ctl, NULL);
}
static int ub960_init_tx_ports(struct ub960_data *priv)
@@ -1893,6 +1962,7 @@ static int ub960_init_tx_ports(struct ub960_data *priv)
unsigned int nport;
u8 speed_select;
u8 pll_div;
+ int ret = 0;
/* TX ports */
@@ -1916,51 +1986,57 @@ static int ub960_init_tx_ports(struct ub960_data *priv)
break;
}
- ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select, NULL);
+ ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select, &ret);
if (priv->hw_data->is_ub9702) {
- ub960_write(priv, UB960_SR_CSI_PLL_DIV, pll_div, NULL);
+ ub960_write(priv, UB960_SR_CSI_PLL_DIV, pll_div, &ret);
switch (priv->tx_data_rate) {
case MHZ(1600):
default:
ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
- 0x80, NULL);
+ 0x80, &ret);
ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b,
- 0x2a, NULL);
+ 0x2a, &ret);
break;
case MHZ(800):
ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
- 0x90, NULL);
+ 0x90, &ret);
ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4f,
- 0x2a, NULL);
+ 0x2a, &ret);
ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b,
- 0x2a, NULL);
+ 0x2a, &ret);
break;
case MHZ(400):
ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
- 0xa0, NULL);
+ 0xa0, &ret);
break;
}
}
+ if (ret)
+ return ret;
+
for (nport = 0; nport < priv->hw_data->num_txports; nport++) {
struct ub960_txport *txport = priv->txports[nport];
if (!txport)
continue;
- ub960_init_tx_port(priv, txport);
+ ret = ub960_init_tx_port(priv, txport);
+ if (ret)
+ return ret;
}
return 0;
}
-static void ub960_init_rx_port_ub960(struct ub960_data *priv,
- struct ub960_rxport *rxport)
+static int ub960_init_rx_port_ub960(struct ub960_data *priv,
+ struct ub960_rxport *rxport)
{
unsigned int nport = rxport->nport;
u32 bc_freq_val;
+ int ret = 0;
/*
* Back channel frequency select.
@@ -1989,19 +2065,19 @@ static void ub960_init_rx_port_ub960(struct ub960_data *priv,
break;
default:
- return;
+ return -EINVAL;
}
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK,
- bc_freq_val, NULL);
+ bc_freq_val, &ret);
switch (rxport->rx_mode) {
case RXPORT_MODE_RAW10:
/* FPD3_MODE = RAW10 Mode (DS90UB913A-Q1 / DS90UB933-Q1 compatible) */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG,
UB960_RR_PORT_CONFIG_FPD3_MODE_MASK,
- 0x3, NULL);
+ 0x3, &ret);
/*
* RAW10_8BIT_CTL = 0b10 : 8-bit processing using upper 8 bits
@@ -2009,55 +2085,58 @@ static void ub960_init_rx_port_ub960(struct ub960_data *priv,
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2,
UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_MASK,
0x2 << UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_SHIFT,
- NULL);
+ &ret);
break;
case RXPORT_MODE_RAW12_HF:
case RXPORT_MODE_RAW12_LF:
/* Not implemented */
- return;
+ return -EINVAL;
case RXPORT_MODE_CSI2_SYNC:
case RXPORT_MODE_CSI2_NONSYNC:
/* CSI-2 Mode (DS90UB953-Q1 compatible) */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG, 0x3,
- 0x0, NULL);
+ 0x0, &ret);
break;
}
/* LV_POLARITY & FV_POLARITY */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
- rxport->lv_fv_pol, NULL);
+ rxport->lv_fv_pol, &ret);
/* Enable all interrupt sources from this port */
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07, NULL);
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f, NULL);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07, &ret);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f, &ret);
/* Enable I2C_PASS_THROUGH */
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
- UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, NULL);
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, &ret);
/* Enable I2C communication to the serializer via the alias addr */
ub960_rxport_write(priv, nport, UB960_RR_SER_ALIAS_ID,
- rxport->ser.alias << 1, NULL);
+ rxport->ser.alias << 1, &ret);
/* Configure EQ related settings */
ub960_rxport_config_eq(priv, nport);
/* Enable RX port */
ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
- NULL);
+ &ret);
+
+ return ret;
}
-static void ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
- struct ub960_rxport *rxport)
+static int ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
+ struct ub960_rxport *rxport)
{
unsigned int nport = rxport->nport;
u8 bc_freq_val;
u8 fpd_func_mode;
+ int ret = 0;
switch (rxport->rx_mode) {
case RXPORT_MODE_RAW10:
@@ -2086,90 +2165,96 @@ static void ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
break;
default:
- return;
+ return -EINVAL;
}
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
- bc_freq_val, NULL);
+ bc_freq_val, &ret);
ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, fpd_func_mode,
- NULL);
+ &ret);
/* set serdes_eq_mode = 1 */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa8, 0x80,
- NULL);
+ &ret);
/* enable serdes driver */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x0d, 0x7f,
- NULL);
+ &ret);
/* set serdes_eq_offset=4 */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04,
- NULL);
+ &ret);
/* init default serdes_eq_max in 0xa9 */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa9, 0x23,
- NULL);
+ &ret);
/* init serdes_eq_min in 0xaa */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xaa, 0, NULL);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xaa, 0, &ret);
/* serdes_driver_ctl2 control: DS90UB953-Q1/DS90UB933-Q1/DS90UB913A-Q1 */
ub960_ind_update_bits(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b,
- BIT(3), BIT(3), NULL);
+ BIT(3), BIT(3), &ret);
/* RX port to half-rate */
ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
- BIT(nport * 2), NULL);
+ BIT(nport * 2), &ret);
+
+ return ret;
}
-static void ub960_init_rx_port_ub9702_fpd4_aeq(struct ub960_data *priv,
- struct ub960_rxport *rxport)
+static int ub960_init_rx_port_ub9702_fpd4_aeq(struct ub960_data *priv,
+ struct ub960_rxport *rxport)
{
unsigned int nport = rxport->nport;
bool first_time_power_up = true;
+ int ret = 0;
if (first_time_power_up) {
u8 v;
/* AEQ init */
ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2c, &v,
- NULL);
+ &ret);
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, v,
- NULL);
+ &ret);
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28,
- v + 1, NULL);
+ v + 1, &ret);
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b,
- 0x00, NULL);
+ 0x00, &ret);
}
/* enable serdes_eq_ctl2 */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x9e, 0x00,
- NULL);
+ &ret);
/* enable serdes_eq_ctl1 */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x90, 0x40,
- NULL);
+ &ret);
/* enable serdes_eq_en */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2e, 0x40,
- NULL);
+ &ret);
/* disable serdes_eq_override */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xf0, 0x00,
- NULL);
+ &ret);
/* disable serdes_gain_override */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x71, 0x00,
- NULL);
+ &ret);
+
+ return ret;
}
-static void ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
- struct ub960_rxport *rxport)
+static int ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
+ struct ub960_rxport *rxport)
{
unsigned int nport = rxport->nport;
u8 bc_freq_val;
+ int ret = 0;
switch (rxport->rx_mode) {
case RXPORT_MODE_RAW10:
@@ -2193,55 +2278,66 @@ static void ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
break;
default:
- return;
+ return -EINVAL;
}
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
- bc_freq_val, NULL);
+ bc_freq_val, &ret);
/* FPD4 Sync Mode */
- ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, 0, NULL);
+ ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, 0, &ret);
/* add serdes_eq_offset of 4 */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04,
- NULL);
+ &ret);
/* FPD4 serdes_start_eq in 0x27: assign default */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, 0x0, NULL);
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, 0x0, &ret);
/* FPD4 serdes_end_eq in 0x28: assign default */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28, 0x23,
- NULL);
+ &ret);
/* set serdes_driver_mode into FPD IV mode */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x04, 0x00,
- NULL);
+ &ret);
/* set FPD PBC drv into FPD IV mode */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b, 0x00,
- NULL);
+ &ret);
/* set serdes_system_init to 0x2f */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x21, 0x2f,
- NULL);
+ &ret);
/* set serdes_system_rst in reset mode */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25, 0xc1,
- NULL);
+ &ret);
/* RX port to 7.55G mode */
ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
- 0 << (nport * 2), NULL);
+ 0 << (nport * 2), &ret);
+
+ if (ret)
+ return ret;
- ub960_init_rx_port_ub9702_fpd4_aeq(priv, rxport);
+ ret = ub960_init_rx_port_ub9702_fpd4_aeq(priv, rxport);
+ if (ret)
+ return ret;
+
+ return 0;
}
-static void ub960_init_rx_port_ub9702(struct ub960_data *priv,
- struct ub960_rxport *rxport)
+static int ub960_init_rx_port_ub9702(struct ub960_data *priv,
+ struct ub960_rxport *rxport)
{
unsigned int nport = rxport->nport;
+ int ret;
if (rxport->cdr_mode == RXPORT_CDR_FPD3)
- ub960_init_rx_port_ub9702_fpd3(priv, rxport);
+ ret = ub960_init_rx_port_ub9702_fpd3(priv, rxport);
else /* RXPORT_CDR_FPD4 */
- ub960_init_rx_port_ub9702_fpd4(priv, rxport);
+ ret = ub960_init_rx_port_ub9702_fpd4(priv, rxport);
+
+ if (ret)
+ return ret;
switch (rxport->rx_mode) {
case RXPORT_MODE_RAW10:
@@ -2250,14 +2346,14 @@ static void ub960_init_rx_port_ub9702(struct ub960_data *priv,
* 0b10 : 8-bit processing using upper 8 bits
*/
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2,
- 0x3 << 6, 0x2 << 6, NULL);
+ 0x3 << 6, 0x2 << 6, &ret);
break;
case RXPORT_MODE_RAW12_HF:
case RXPORT_MODE_RAW12_LF:
/* Not implemented */
- return;
+ return -EINVAL;
case RXPORT_MODE_CSI2_SYNC:
case RXPORT_MODE_CSI2_NONSYNC:
@@ -2267,30 +2363,32 @@ static void ub960_init_rx_port_ub9702(struct ub960_data *priv,
/* LV_POLARITY & FV_POLARITY */
ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
- rxport->lv_fv_pol, NULL);
+ rxport->lv_fv_pol, &ret);
/* Enable all interrupt sources from this port */
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07, NULL);
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f, NULL);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07, &ret);
+ ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f, &ret);
/* Enable I2C_PASS_THROUGH */
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
- UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, NULL);
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, &ret);
/* Enable I2C communication to the serializer via the alias addr */
ub960_rxport_write(priv, nport, UB960_RR_SER_ALIAS_ID,
- rxport->ser.alias << 1, NULL);
+ rxport->ser.alias << 1, &ret);
/* Enable RX port */
ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
- NULL);
+ &ret);
if (rxport->cdr_mode == RXPORT_CDR_FPD4) {
/* unreset 960 AEQ */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25,
- 0x41, NULL);
+ 0x41, &ret);
}
+
+ return ret;
}
static int ub960_init_rx_ports(struct ub960_data *priv)
@@ -2299,20 +2397,24 @@ static int ub960_init_rx_ports(struct ub960_data *priv)
for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
struct ub960_rxport *rxport = priv->rxports[nport];
+ int ret;
if (!rxport)
continue;
if (priv->hw_data->is_ub9702)
- ub960_init_rx_port_ub9702(priv, rxport);
+ ret = ub960_init_rx_port_ub9702(priv, rxport);
else
- ub960_init_rx_port_ub960(priv, rxport);
+ ret = ub960_init_rx_port_ub960(priv, rxport);
+
+ if (ret)
+ return ret;
}
return 0;
}
-static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
+static int ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
{
struct device *dev = &priv->client->dev;
u8 rx_port_sts1;
@@ -2322,21 +2424,15 @@ static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
int ret = 0;
/* Read interrupts (also clears most of them) */
- if (!ret)
- ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1,
- &rx_port_sts1, NULL);
- if (!ret)
- ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2,
- &rx_port_sts2, NULL);
- if (!ret)
- ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS,
- &csi_rx_sts, NULL);
- if (!ret)
- ret = ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS,
- &bcc_sts, NULL);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &rx_port_sts1,
+ &ret);
+ ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &rx_port_sts2,
+ &ret);
+ ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &csi_rx_sts, &ret);
+ ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &bcc_sts, &ret);
if (ret)
- return;
+ return ret;
if (rx_port_sts1 & UB960_RR_RX_PORT_STS1_PARITY_ERROR) {
u16 v;
@@ -2431,6 +2527,8 @@ static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
"stable freq" :
"unstable freq");
}
+
+ return 0;
}
/* -----------------------------------------------------------------------------
@@ -2486,14 +2584,14 @@ static int ub960_enable_tx_port(struct ub960_data *priv, unsigned int nport)
UB960_TR_CSI_CTL_CSI_ENABLE, NULL);
}
-static void ub960_disable_tx_port(struct ub960_data *priv, unsigned int nport)
+static int ub960_disable_tx_port(struct ub960_data *priv, unsigned int nport)
{
struct device *dev = &priv->client->dev;
dev_dbg(dev, "disable TX port %u\n", nport);
- ub960_txport_update_bits(priv, nport, UB960_TR_CSI_CTL,
- UB960_TR_CSI_CTL_CSI_ENABLE, 0, NULL);
+ return ub960_txport_update_bits(priv, nport, UB960_TR_CSI_CTL,
+ UB960_TR_CSI_CTL_CSI_ENABLE, 0, NULL);
}
static int ub960_enable_rx_port(struct ub960_data *priv, unsigned int nport)
@@ -2507,16 +2605,16 @@ static int ub960_enable_rx_port(struct ub960_data *priv, unsigned int nport)
UB960_SR_FWD_CTL1_PORT_DIS(nport), 0, NULL);
}
-static void ub960_disable_rx_port(struct ub960_data *priv, unsigned int nport)
+static int ub960_disable_rx_port(struct ub960_data *priv, unsigned int nport)
{
struct device *dev = &priv->client->dev;
dev_dbg(dev, "disable RX port %u\n", nport);
/* Disable forwarding */
- ub960_update_bits(priv, UB960_SR_FWD_CTL1,
- UB960_SR_FWD_CTL1_PORT_DIS(nport),
- UB960_SR_FWD_CTL1_PORT_DIS(nport), NULL);
+ return ub960_update_bits(priv, UB960_SR_FWD_CTL1,
+ UB960_SR_FWD_CTL1_PORT_DIS(nport),
+ UB960_SR_FWD_CTL1_PORT_DIS(nport), NULL);
}
/*
@@ -2658,12 +2756,12 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
case RXPORT_MODE_RAW10:
ub960_rxport_write(priv, nport, UB960_RR_RAW10_ID,
rx_data[nport].pixel_dt | (vc << UB960_RR_RAW10_ID_VC_SHIFT),
- NULL);
+ &ret);
ub960_rxport_write(priv, rxport->nport,
UB960_RR_RAW_EMBED_DTYPE,
(rx_data[nport].meta_lines << UB960_RR_RAW_EMBED_DTYPE_LINES_SHIFT) |
- rx_data[nport].meta_dt, NULL);
+ rx_data[nport].meta_dt, &ret);
break;
@@ -2681,7 +2779,7 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
(vc << UB960_RR_CSI_VC_MAP_SHIFT(2)) |
(vc << UB960_RR_CSI_VC_MAP_SHIFT(1)) |
(vc << UB960_RR_CSI_VC_MAP_SHIFT(0)),
- NULL);
+ &ret);
} else {
unsigned int i;
@@ -2690,7 +2788,7 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
ub960_rxport_write(priv, nport,
UB960_RR_VC_ID_MAP(i),
(nport << 4) | nport,
- NULL);
+ &ret);
}
break;
@@ -2702,9 +2800,9 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
fwd_ctl &= ~BIT(nport); /* forward to TX0 */
}
- ub960_write(priv, UB960_SR_FWD_CTL1, fwd_ctl, NULL);
+ ub960_write(priv, UB960_SR_FWD_CTL1, fwd_ctl, &ret);
- return 0;
+ return ret;
}
static void ub960_update_streaming_status(struct ub960_data *priv)
@@ -3107,8 +3205,8 @@ static const struct v4l2_subdev_pad_ops ub960_pad_ops = {
.set_fmt = ub960_set_fmt,
};
-static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
- unsigned int nport)
+static int ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
+ unsigned int nport)
{
struct device *dev = &priv->client->dev;
u8 eq_level;
@@ -3120,7 +3218,7 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
ret = ub960_read(priv, UB960_XR_AEQ_CTL1, &v, NULL);
if (ret)
- return;
+ return ret;
dev_info(dev, "\t%s strobe\n",
(v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) ? "Adaptive" :
@@ -3129,7 +3227,7 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
if (v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) {
ret = ub960_read(priv, UB960_XR_SFILTER_CFG, &v, NULL);
if (ret)
- return;
+ return ret;
dev_info(dev, "\tStrobe range [%d, %d]\n",
((v >> UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) & 0xf) - 7,
@@ -3138,7 +3236,7 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
ret = ub960_rxport_get_strobe_pos(priv, nport, &strobe_pos);
if (ret)
- return;
+ return ret;
dev_info(dev, "\tStrobe pos %d\n", strobe_pos);
@@ -3146,7 +3244,7 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v, NULL);
if (ret)
- return;
+ return ret;
dev_info(dev, "\t%s EQ\n",
(v & UB960_RR_AEQ_BYPASS_ENABLE) ? "Manual" :
@@ -3156,15 +3254,20 @@ static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_MIN_MAX, &v,
NULL);
if (ret)
- return;
+ return ret;
dev_info(dev, "\tEQ range [%u, %u]\n",
(v >> UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT) & 0xf,
(v >> UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT) & 0xf);
}
- if (ub960_rxport_get_eq_level(priv, nport, &eq_level) == 0)
- dev_info(dev, "\tEQ level %u\n", eq_level);
+ ret = ub960_rxport_get_eq_level(priv, nport, &eq_level);
+ if (ret)
+ return ret;
+
+ dev_info(dev, "\tEQ level %u\n", eq_level);
+
+ return 0;
}
static int ub960_log_status(struct v4l2_subdev *sd)
@@ -3176,11 +3279,15 @@ static int ub960_log_status(struct v4l2_subdev *sd)
u16 v16 = 0;
u8 v = 0;
u8 id[UB960_SR_FPD3_RX_ID_LEN];
+ int ret = 0;
state = v4l2_subdev_lock_and_get_active_state(sd);
- for (unsigned int i = 0; i < sizeof(id); i++)
- ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i], NULL);
+ for (unsigned int i = 0; i < sizeof(id); i++) {
+ ret = ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i], NULL);
+ if (ret)
+ return ret;
+ }
dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
@@ -3194,24 +3301,39 @@ static int ub960_log_status(struct v4l2_subdev *sd)
continue;
}
- ub960_txport_read(priv, nport, UB960_TR_CSI_STS, &v, NULL);
+ ret = ub960_txport_read(priv, nport, UB960_TR_CSI_STS, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tsync %u, pass %u\n", v & (u8)BIT(1),
v & (u8)BIT(0));
- ub960_read16(priv, UB960_SR_CSI_FRAME_COUNT_HI(nport), &v16,
- NULL);
+ ret = ub960_read16(priv, UB960_SR_CSI_FRAME_COUNT_HI(nport),
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tframe counter %u\n", v16);
- ub960_read16(priv, UB960_SR_CSI_FRAME_ERR_COUNT_HI(nport),
- &v16, NULL);
+ ret = ub960_read16(priv, UB960_SR_CSI_FRAME_ERR_COUNT_HI(nport),
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tframe error counter %u\n", v16);
- ub960_read16(priv, UB960_SR_CSI_LINE_COUNT_HI(nport), &v16,
- NULL);
+ ret = ub960_read16(priv, UB960_SR_CSI_LINE_COUNT_HI(nport),
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tline counter %u\n", v16);
- ub960_read16(priv, UB960_SR_CSI_LINE_ERR_COUNT_HI(nport),
- &v16, NULL);
+ ret = ub960_read16(priv, UB960_SR_CSI_LINE_ERR_COUNT_HI(nport),
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tline error counter %u\n", v16);
}
@@ -3225,8 +3347,10 @@ static int ub960_log_status(struct v4l2_subdev *sd)
continue;
}
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v,
- NULL);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v,
+ NULL);
+ if (ret)
+ return ret;
if (v & UB960_RR_RX_PORT_STS1_LOCK_STS)
dev_info(dev, "\tLocked\n");
@@ -3234,32 +3358,53 @@ static int ub960_log_status(struct v4l2_subdev *sd)
dev_info(dev, "\tNot locked\n");
dev_info(dev, "\trx_port_sts1 %#02x\n", v);
- ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v,
- NULL);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v,
+ NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\trx_port_sts2 %#02x\n", v);
- ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v16,
- NULL);
+ ret = ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH,
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tlink freq %llu Hz\n", ((u64)v16 * HZ_PER_MHZ) >> 8);
- ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v16,
- NULL);
+ ret = ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI,
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tparity errors %u\n", v16);
- ub960_rxport_read16(priv, nport, UB960_RR_LINE_COUNT_HI, &v16,
- NULL);
+ ret = ub960_rxport_read16(priv, nport, UB960_RR_LINE_COUNT_HI,
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tlines per frame %u\n", v16);
- ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1, &v16,
- NULL);
+ ret = ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1,
+ &v16, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tbytes per line %u\n", v16);
- ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v,
- NULL);
+ ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER,
+ &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "\tcsi_err_counter %u\n", v);
- if (!priv->hw_data->is_ub9702)
- ub960_log_status_ub960_sp_eq(priv, nport);
+ if (!priv->hw_data->is_ub9702) {
+ ret = ub960_log_status_ub960_sp_eq(priv, nport);
+ if (ret)
+ return ret;
+ }
/* GPIOs */
for (unsigned int i = 0; i < UB960_NUM_BC_GPIOS; i++) {
@@ -3269,7 +3414,9 @@ static int ub960_log_status(struct v4l2_subdev *sd)
ctl_reg = UB960_RR_BC_GPIO_CTL(i / 2);
ctl_shift = (i % 2) * 4;
- ub960_rxport_read(priv, nport, ctl_reg, &v, NULL);
+ ret = ub960_rxport_read(priv, nport, ctl_reg, &v, NULL);
+ if (ret)
+ return ret;
dev_info(dev, "\tGPIO%u: mode %u\n", i,
(v >> ctl_shift) & 0xf);
@@ -3325,16 +3472,22 @@ static irqreturn_t ub960_handle_events(int irq, void *arg)
dev_dbg(&priv->client->dev, "FWD_STS %#02x\n", fwd_sts);
for (i = 0; i < priv->hw_data->num_txports; i++) {
- if (int_sts & UB960_SR_INTERRUPT_STS_IS_CSI_TX(i))
- ub960_csi_handle_events(priv, i);
+ if (int_sts & UB960_SR_INTERRUPT_STS_IS_CSI_TX(i)) {
+ ret = ub960_csi_handle_events(priv, i);
+ if (ret)
+ return IRQ_NONE;
+ }
}
for (i = 0; i < priv->hw_data->num_rxports; i++) {
if (!priv->rxports[i])
continue;
- if (int_sts & UB960_SR_INTERRUPT_STS_IS_RX(i))
- ub960_rxport_handle_events(priv, i);
+ if (int_sts & UB960_SR_INTERRUPT_STS_IS_RX(i)) {
+ ret = ub960_rxport_handle_events(priv, i);
+ if (ret)
+ return IRQ_NONE;
+ }
}
return IRQ_HANDLED;
@@ -3938,7 +4091,7 @@ static const struct regmap_config ub960_regmap_config = {
.disable_locking = true,
};
-static void ub960_reset(struct ub960_data *priv, bool reset_regs)
+static int ub960_reset(struct ub960_data *priv, bool reset_regs)
{
struct device *dev = &priv->client->dev;
unsigned int v;
@@ -3948,7 +4101,9 @@ static void ub960_reset(struct ub960_data *priv, bool reset_regs)
bit = reset_regs ? UB960_SR_RESET_DIGITAL_RESET1 :
UB960_SR_RESET_DIGITAL_RESET0;
- ub960_write(priv, UB960_SR_RESET, bit, NULL);
+ ret = ub960_write(priv, UB960_SR_RESET, bit, NULL);
+ if (ret)
+ return ret;
mutex_lock(&priv->reg_lock);
@@ -3959,6 +4114,8 @@ static void ub960_reset(struct ub960_data *priv, bool reset_regs)
if (ret)
dev_err(dev, "reset failed: %d\n", ret);
+
+ return ret;
}
static int ub960_get_hw_resources(struct ub960_data *priv)
@@ -4017,7 +4174,9 @@ static int ub960_enable_core_hw(struct ub960_data *priv)
fsleep(2000);
}
- ub960_reset(priv, true);
+ ret = ub960_reset(priv, true);
+ if (ret)
+ goto err_pd_gpio;
/* Runtime check register accessibility */
ret = ub960_read(priv, UB960_SR_REV_MASK, &rev_mask, NULL);
@@ -4132,7 +4291,9 @@ static int ub960_probe(struct i2c_client *client)
if (ret)
goto err_disable_vpocs;
- ub960_reset(priv, false);
+ ret = ub960_reset(priv, false);
+ if (ret)
+ goto err_disable_vpocs;
port_mask = 0;
@@ -4159,7 +4320,9 @@ static int ub960_probe(struct i2c_client *client)
* Clear any errors caused by switching the RX port settings while
* probing.
*/
- ub960_clear_rx_errors(priv);
+ ret = ub960_clear_rx_errors(priv);
+ if (ret)
+ goto err_disable_vpocs;
ret = ub960_init_atr(priv);
if (ret)
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 05/19] media: i2c: ds90ub953: Add error handling to ub953_log_status()
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (3 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 04/19] media: i2c: ds90ub960: Add error handling to multiple places Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 06/19] media: i2c: ds90ub913: Add error handling to ub913_log_status() Tomi Valkeinen
` (13 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
Add error handling to ub953_log_status().
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub953.c | 80 +++++++++++++++++++++++++++++++------------
1 file changed, 58 insertions(+), 22 deletions(-)
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 07d451816855..99a4852b9381 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -633,23 +633,33 @@ static int ub953_log_status(struct v4l2_subdev *sd)
{
struct ub953_data *priv = sd_to_ub953(sd);
struct device *dev = &priv->client->dev;
- u8 v = 0, v1 = 0, v2 = 0;
- unsigned int i;
char id[UB953_REG_FPD3_RX_ID_LEN];
- u8 gpio_local_data = 0;
- u8 gpio_input_ctrl = 0;
- u8 gpio_pin_sts = 0;
+ u8 gpio_local_data;
+ u8 gpio_input_ctrl;
+ u8 gpio_pin_sts;
+ unsigned int i;
+ u8 v, v1, v2;
+ int ret;
- for (i = 0; i < sizeof(id); i++)
- ub953_read(priv, UB953_REG_FPD3_RX_ID(i), &id[i], NULL);
+ for (i = 0; i < sizeof(id); i++) {
+ ret = ub953_read(priv, UB953_REG_FPD3_RX_ID(i), &id[i], NULL);
+ if (ret)
+ return ret;
+ }
dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
- ub953_read(priv, UB953_REG_GENERAL_STATUS, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_GENERAL_STATUS, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "GENERAL_STATUS %#02x\n", v);
- ub953_read(priv, UB953_REG_CRC_ERR_CNT1, &v1, NULL);
- ub953_read(priv, UB953_REG_CRC_ERR_CNT2, &v2, NULL);
+ ub953_read(priv, UB953_REG_CRC_ERR_CNT1, &v1, &ret);
+ ub953_read(priv, UB953_REG_CRC_ERR_CNT2, &v2, &ret);
+ if (ret)
+ return ret;
+
dev_info(dev, "CRC error count %u\n", v1 | (v2 << 8));
/* Clear CRC error counter */
@@ -658,34 +668,60 @@ static int ub953_log_status(struct v4l2_subdev *sd)
UB953_REG_BC_CTRL_CRC_ERR_CLR,
UB953_REG_BC_CTRL_CRC_ERR_CLR);
- ub953_read(priv, UB953_REG_CSI_ERR_CNT, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_CSI_ERR_CNT, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI error count %u\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_STATUS, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_CSI_ERR_STATUS, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI_ERR_STATUS %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_DLANE01, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_CSI_ERR_DLANE01, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI_ERR_DLANE01 %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_DLANE23, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_CSI_ERR_DLANE23, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI_ERR_DLANE23 %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_ERR_CLK_LANE, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_CSI_ERR_CLK_LANE, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI_ERR_CLK_LANE %#02x\n", v);
- ub953_read(priv, UB953_REG_CSI_PKT_HDR_VC_ID, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_CSI_PKT_HDR_VC_ID, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI packet header VC %u ID %u\n", v >> 6, v & 0x3f);
- ub953_read(priv, UB953_REG_PKT_HDR_WC_LSB, &v1, NULL);
- ub953_read(priv, UB953_REG_PKT_HDR_WC_MSB, &v2, NULL);
+ ub953_read(priv, UB953_REG_PKT_HDR_WC_LSB, &v1, &ret);
+ ub953_read(priv, UB953_REG_PKT_HDR_WC_MSB, &v2, &ret);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI packet header WC %u\n", (v2 << 8) | v1);
- ub953_read(priv, UB953_REG_CSI_ECC, &v, NULL);
+ ret = ub953_read(priv, UB953_REG_CSI_ECC, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "CSI ECC %#02x\n", v);
- ub953_read(priv, UB953_REG_LOCAL_GPIO_DATA, &gpio_local_data, NULL);
- ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &gpio_input_ctrl, NULL);
- ub953_read(priv, UB953_REG_GPIO_PIN_STS, &gpio_pin_sts, NULL);
+ ub953_read(priv, UB953_REG_LOCAL_GPIO_DATA, &gpio_local_data, &ret);
+ ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &gpio_input_ctrl, &ret);
+ ub953_read(priv, UB953_REG_GPIO_PIN_STS, &gpio_pin_sts, &ret);
+ if (ret)
+ return ret;
for (i = 0; i < UB953_NUM_GPIOS; i++) {
dev_info(dev,
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 06/19] media: i2c: ds90ub913: Add error handling to ub913_log_status()
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (4 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 05/19] media: i2c: ds90ub953: Add error handling to ub953_log_status() Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer Tomi Valkeinen
` (12 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
Add error handling to ub913_log_status().
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub913.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
index 34f92aa1c56c..111166dbbce3 100644
--- a/drivers/media/i2c/ds90ub913.c
+++ b/drivers/media/i2c/ds90ub913.c
@@ -504,25 +504,41 @@ static int ub913_log_status(struct v4l2_subdev *sd)
{
struct ub913_data *priv = sd_to_ub913(sd);
struct device *dev = &priv->client->dev;
- u8 v = 0, v1 = 0, v2 = 0;
+ u8 v, v1, v2;
+ int ret;
+
+ ret = ub913_read(priv, UB913_REG_MODE_SEL, &v, NULL);
+ if (ret)
+ return ret;
- ub913_read(priv, UB913_REG_MODE_SEL, &v, NULL);
dev_info(dev, "MODE_SEL %#02x\n", v);
- ub913_read(priv, UB913_REG_CRC_ERRORS_LSB, &v1, NULL);
- ub913_read(priv, UB913_REG_CRC_ERRORS_MSB, &v2, NULL);
+ ub913_read(priv, UB913_REG_CRC_ERRORS_LSB, &v1, &ret);
+ ub913_read(priv, UB913_REG_CRC_ERRORS_MSB, &v2, &ret);
+ if (ret)
+ return ret;
+
dev_info(dev, "CRC errors %u\n", v1 | (v2 << 8));
/* clear CRC errors */
- ub913_read(priv, UB913_REG_GENERAL_CFG, &v, NULL);
+ ub913_read(priv, UB913_REG_GENERAL_CFG, &v, &ret);
ub913_write(priv, UB913_REG_GENERAL_CFG,
- v | UB913_REG_GENERAL_CFG_CRC_ERR_RESET, NULL);
- ub913_write(priv, UB913_REG_GENERAL_CFG, v, NULL);
+ v | UB913_REG_GENERAL_CFG_CRC_ERR_RESET, &ret);
+ ub913_write(priv, UB913_REG_GENERAL_CFG, v, &ret);
+
+ if (ret)
+ return ret;
+
+ ret = ub913_read(priv, UB913_REG_GENERAL_STATUS, &v, NULL);
+ if (ret)
+ return ret;
- ub913_read(priv, UB913_REG_GENERAL_STATUS, &v, NULL);
dev_info(dev, "GENERAL_STATUS %#02x\n", v);
- ub913_read(priv, UB913_REG_PLL_OVR, &v, NULL);
+ ret = ub913_read(priv, UB913_REG_PLL_OVR, &v, NULL);
+ if (ret)
+ return ret;
+
dev_info(dev, "PLL_OVR %#02x\n", v);
return 0;
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (5 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 06/19] media: i2c: ds90ub913: Add error handling to ub913_log_status() Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-15 14:17 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 08/19] media: i2c: ds90ub960: Move UB9702 registers to a separate section Tomi Valkeinen
` (11 subsequent siblings)
18 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
From: Jai Luthra <jai.luthra@ideasonboard.com>
On the I2C bus for remote clients (sensors), by default the watchdog
timer expires in 1s. To allow for a quicker system bring-up time, TI
recommends to speed it up to 50us [1].
[1]: Section 7.3.1.1 - https://www.ti.com/lit/gpn/ds90ub953-q1
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub953.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 99a4852b9381..6c36980e8beb 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -54,6 +54,10 @@
#define UB953_REG_CLKOUT_CTRL0 0x06
#define UB953_REG_CLKOUT_CTRL1 0x07
+#define UB953_REG_I2C_CONTROL2 0x0a
+#define UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT 4
+#define UB953_REG_I2C_CONTROL2_BUS_SPEEDUP BIT(1)
+
#define UB953_REG_SCL_HIGH_TIME 0x0b
#define UB953_REG_SCL_LOW_TIME 0x0c
@@ -1320,6 +1324,13 @@ static int ub953_hw_init(struct ub953_data *priv)
if (ret)
return ret;
+ v = 0;
+ v |= 1 << UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT;
+ v |= UB953_REG_I2C_CONTROL2_BUS_SPEEDUP;
+ ret = ub953_write(priv, UB953_REG_I2C_CONTROL2, v, NULL);
+ if (ret)
+ return ret;
+
return 0;
}
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 08/19] media: i2c: ds90ub960: Move UB9702 registers to a separate section
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (6 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 09/19] media: i2c: ds90ub960: Add UB9702 specific registers Tomi Valkeinen
` (10 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
The driver supports both UB960 and UB9702. While devices work in similar
ways and have a lot of identical registers, there are also plenty of
differences.
To clarify the situation a bit, move the UB9702 registers to a separate
section and prefix them with UB9702.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index 80bbba0792c1..fc910d13d7db 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -307,8 +307,6 @@
#define UB960_XR_REFCLK_FREQ 0xa5 /* UB960 */
-#define UB960_RR_VC_ID_MAP(x) (0xa0 + (x)) /* UB9702 */
-
#define UB960_SR_IND_ACC_CTL 0xb0
#define UB960_SR_IND_ACC_CTL_IA_AUTO_INC BIT(1)
@@ -321,9 +319,6 @@
#define UB960_SR_FV_MIN_TIME 0xbc
#define UB960_SR_GPIO_PD_CTL 0xbe
-#define UB960_SR_FPD_RATE_CFG 0xc2 /* UB9702 */
-#define UB960_SR_CSI_PLL_DIV 0xc9 /* UB9702 */
-
#define UB960_RR_PORT_DEBUG 0xd0
#define UB960_RR_AEQ_CTL2 0xd2
#define UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR BIT(2)
@@ -354,15 +349,12 @@
#define UB960_RR_SEN_INT_RISE_STS 0xde
#define UB960_RR_SEN_INT_FALL_STS 0xdf
-#define UB960_RR_CHANNEL_MODE 0xe4 /* UB9702 */
#define UB960_SR_FPD3_RX_ID(n) (0xf0 + (n))
#define UB960_SR_FPD3_RX_ID_LEN 6
#define UB960_SR_I2C_RX_ID(n) (0xf8 + (n))
-#define UB9702_SR_REFCLK_FREQ 0x3d
-
/* Indirect register blocks */
#define UB960_IND_TARGET_PAT_GEN 0x00
#define UB960_IND_TARGET_RX_ANA(n) (0x01 + (n))
@@ -397,6 +389,14 @@
#define UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY BIT(3)
#define UB960_IR_RX_ANA_STROBE_SET_DATA_DELAY_MASK GENMASK(2, 0)
+/* UB9702 Registers */
+
+#define UB9702_SR_REFCLK_FREQ 0x3d
+#define UB9702_RR_VC_ID_MAP(x) (0xa0 + (x))
+#define UB9702_SR_FPD_RATE_CFG 0xc2
+#define UB9702_SR_CSI_PLL_DIV 0xc9
+#define UB9702_RR_CHANNEL_MODE 0xe4
+
/* EQ related */
#define UB960_MIN_AEQ_STROBE_POS -7
@@ -1989,7 +1989,7 @@ static int ub960_init_tx_ports(struct ub960_data *priv)
ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select, &ret);
if (priv->hw_data->is_ub9702) {
- ub960_write(priv, UB960_SR_CSI_PLL_DIV, pll_div, &ret);
+ ub960_write(priv, UB9702_SR_CSI_PLL_DIV, pll_div, &ret);
switch (priv->tx_data_rate) {
case MHZ(1600):
@@ -2170,7 +2170,7 @@ static int ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
bc_freq_val, &ret);
- ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, fpd_func_mode,
+ ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, fpd_func_mode,
&ret);
/* set serdes_eq_mode = 1 */
@@ -2197,7 +2197,7 @@ static int ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
BIT(3), BIT(3), &ret);
/* RX port to half-rate */
- ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
+ ub960_update_bits(priv, UB9702_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
BIT(nport * 2), &ret);
return ret;
@@ -2285,7 +2285,7 @@ static int ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
bc_freq_val, &ret);
/* FPD4 Sync Mode */
- ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, 0, &ret);
+ ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, 0, &ret);
/* add serdes_eq_offset of 4 */
ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04,
@@ -2312,7 +2312,7 @@ static int ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
&ret);
/* RX port to 7.55G mode */
- ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
+ ub960_update_bits(priv, UB9702_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
0 << (nport * 2), &ret);
if (ret)
@@ -2786,7 +2786,7 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
/* Map all VCs from this port to VC(nport) */
for (i = 0; i < 8; i++)
ub960_rxport_write(priv, nport,
- UB960_RR_VC_ID_MAP(i),
+ UB9702_RR_VC_ID_MAP(i),
(nport << 4) | nport,
&ret);
}
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 09/19] media: i2c: ds90ub960: Add UB9702 specific registers
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (7 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 08/19] media: i2c: ds90ub960: Move UB9702 registers to a separate section Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 10/19] media: i2c: ds90ub960: Split ub960_init_tx_ports() Tomi Valkeinen
` (9 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
Add UB9702 specific registers which will be used in the following
patches.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index fc910d13d7db..a890097ad105 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -391,12 +391,47 @@
/* UB9702 Registers */
+#define UB9702_SR_CSI_EXCLUSIVE_FWD2 0x3c
#define UB9702_SR_REFCLK_FREQ 0x3d
+#define UB9702_RR_RX_CTL_1 0x80
+#define UB9702_RR_RX_CTL_2 0x87
#define UB9702_RR_VC_ID_MAP(x) (0xa0 + (x))
#define UB9702_SR_FPD_RATE_CFG 0xc2
#define UB9702_SR_CSI_PLL_DIV 0xc9
+#define UB9702_RR_RX_SM_SEL_2 0xd4
#define UB9702_RR_CHANNEL_MODE 0xe4
+#define UB9702_IND_TARGET_SAR_ADC 0x0a
+
+#define UB9702_IR_RX_ANA_FPD_BC_CTL0 0x04
+#define UB9702_IR_RX_ANA_FPD_BC_CTL1 0x0d
+#define UB9702_IR_RX_ANA_FPD_BC_CTL2 0x1b
+#define UB9702_IR_RX_ANA_SYSTEM_INIT_REG0 0x21
+#define UB9702_IR_RX_ANA_AEQ_ALP_SEL6 0x27
+#define UB9702_IR_RX_ANA_AEQ_ALP_SEL7 0x28
+#define UB9702_IR_RX_ANA_AEQ_ALP_SEL10 0x2b
+#define UB9702_IR_RX_ANA_AEQ_ALP_SEL11 0x2c
+#define UB9702_IR_RX_ANA_EQ_ADAPT_CTRL 0x2e
+#define UB9702_IR_RX_ANA_AEQ_CFG_1 0x34
+#define UB9702_IR_RX_ANA_AEQ_CFG_2 0x4d
+#define UB9702_IR_RX_ANA_GAIN_CTRL_0 0x71
+#define UB9702_IR_RX_ANA_GAIN_CTRL_0 0x71
+#define UB9702_IR_RX_ANA_VGA_CTRL_SEL_1 0x72
+#define UB9702_IR_RX_ANA_VGA_CTRL_SEL_2 0x73
+#define UB9702_IR_RX_ANA_VGA_CTRL_SEL_3 0x74
+#define UB9702_IR_RX_ANA_VGA_CTRL_SEL_6 0x77
+#define UB9702_IR_RX_ANA_AEQ_CFG_3 0x79
+#define UB9702_IR_RX_ANA_AEQ_CFG_4 0x85
+#define UB9702_IR_RX_ANA_EQ_CTRL_SEL_15 0x87
+#define UB9702_IR_RX_ANA_EQ_CTRL_SEL_24 0x90
+#define UB9702_IR_RX_ANA_EQ_CTRL_SEL_38 0x9e
+#define UB9702_IR_RX_ANA_FPD3_CDR_CTRL_SEL_5 0xa5
+#define UB9702_IR_RX_ANA_FPD3_AEQ_CTRL_SEL_1 0xa8
+#define UB9702_IR_RX_ANA_EQ_OVERRIDE_CTRL 0xf0
+#define UB9702_IR_RX_ANA_VGA_CTRL_SEL_8 0xf1
+
+#define UB9702_IR_CSI_ANA_CSIPLL_REG_1 0x92
+
/* EQ related */
#define UB960_MIN_AEQ_STROBE_POS -7
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 10/19] media: i2c: ds90ub960: Split ub960_init_tx_ports()
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (8 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 09/19] media: i2c: ds90ub960: Add UB9702 specific registers Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 11/19] media: i2c: ds90ub960: Refresh ub960_init_tx_ports_ub9702() Tomi Valkeinen
` (8 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
Split ub960_init_tx_ports() to a UB960 and a UB9702 versions to make it
easier to update the UB9702 version in the following patch.
No funcional changes.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 105 +++++++++++++++++++++++++++---------------
1 file changed, 68 insertions(+), 37 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index a890097ad105..3b3e756af86b 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -1992,67 +1992,98 @@ static int ub960_init_tx_port(struct ub960_data *priv,
return ub960_txport_write(priv, nport, UB960_TR_CSI_CTL, csi_ctl, NULL);
}
-static int ub960_init_tx_ports(struct ub960_data *priv)
+static int ub960_init_tx_ports_ub960(struct ub960_data *priv)
{
- unsigned int nport;
u8 speed_select;
- u8 pll_div;
- int ret = 0;
-
- /* TX ports */
switch (priv->tx_data_rate) {
+ case MHZ(400):
+ speed_select = 3;
+ break;
+ case MHZ(800):
+ speed_select = 2;
+ break;
+ case MHZ(1200):
+ speed_select = 1;
+ break;
case MHZ(1600):
default:
speed_select = 0;
- pll_div = 0x10;
break;
- case MHZ(1200):
- speed_select = 1;
- pll_div = 0x18;
+ }
+
+ return ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select, NULL);
+}
+
+static int ub960_init_tx_ports_ub9702(struct ub960_data *priv)
+{
+ u8 speed_select;
+ u8 pll_div;
+ int ret = 0;
+
+ switch (priv->tx_data_rate) {
+ case MHZ(400):
+ speed_select = 3;
+ pll_div = 0x10;
break;
case MHZ(800):
speed_select = 2;
pll_div = 0x10;
break;
- case MHZ(400):
- speed_select = 3;
+ case MHZ(1200):
+ speed_select = 1;
+ pll_div = 0x18;
+ break;
+ case MHZ(1600):
+ default:
+ speed_select = 0;
pll_div = 0x10;
break;
}
ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select, &ret);
- if (priv->hw_data->is_ub9702) {
- ub960_write(priv, UB9702_SR_CSI_PLL_DIV, pll_div, &ret);
-
- switch (priv->tx_data_rate) {
- case MHZ(1600):
- default:
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
- 0x80, &ret);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b,
- 0x2a, &ret);
- break;
- case MHZ(800):
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
- 0x90, &ret);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4f,
- 0x2a, &ret);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b,
- 0x2a, &ret);
- break;
- case MHZ(400):
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92,
- 0xa0, &ret);
- break;
- }
+ ub960_write(priv, UB9702_SR_CSI_PLL_DIV, pll_div, &ret);
+
+ switch (priv->tx_data_rate) {
+ case MHZ(1600):
+ default:
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x80,
+ &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a,
+ &ret);
+ break;
+ case MHZ(800):
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x90,
+ &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4f, 0x2a,
+ &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a,
+ &ret);
+ break;
+ case MHZ(400):
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0xa0,
+ &ret);
+ break;
}
+ return ret;
+}
+
+static int ub960_init_tx_ports(struct ub960_data *priv)
+{
+ int ret;
+
+ if (priv->hw_data->is_ub9702)
+ ret = ub960_init_tx_ports_ub9702(priv);
+ else
+ ret = ub960_init_tx_ports_ub960(priv);
+
if (ret)
return ret;
- for (nport = 0; nport < priv->hw_data->num_txports; nport++) {
+ for (unsigned int nport = 0; nport < priv->hw_data->num_txports;
+ nport++) {
struct ub960_txport *txport = priv->txports[nport];
if (!txport)
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 11/19] media: i2c: ds90ub960: Refresh ub960_init_tx_ports_ub9702()
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (9 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 10/19] media: i2c: ds90ub960: Split ub960_init_tx_ports() Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support Tomi Valkeinen
` (7 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
Refresh the ub960_init_tx_ports_ub9702() using the latest version of the
(non-public) hardware documentation.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 40 +++++++++++++++++-----------------------
1 file changed, 17 insertions(+), 23 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index 3b3e756af86b..bca858172942 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -2018,6 +2018,7 @@ static int ub960_init_tx_ports_ub960(struct ub960_data *priv)
static int ub960_init_tx_ports_ub9702(struct ub960_data *priv)
{
u8 speed_select;
+ u8 ana_pll_div;
u8 pll_div;
int ret = 0;
@@ -2025,47 +2026,40 @@ static int ub960_init_tx_ports_ub9702(struct ub960_data *priv)
case MHZ(400):
speed_select = 3;
pll_div = 0x10;
+ ana_pll_div = 0xa2;
break;
case MHZ(800):
speed_select = 2;
pll_div = 0x10;
+ ana_pll_div = 0x92;
break;
case MHZ(1200):
speed_select = 1;
pll_div = 0x18;
+ ana_pll_div = 0x90;
+ break;
+ case MHZ(1500):
+ speed_select = 0;
+ pll_div = 0x0f;
+ ana_pll_div = 0x82;
break;
case MHZ(1600):
default:
speed_select = 0;
pll_div = 0x10;
+ ana_pll_div = 0x82;
+ break;
+ case MHZ(2500):
+ speed_select = 0x10;
+ pll_div = 0x19;
+ ana_pll_div = 0x80;
break;
}
ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select, &ret);
-
ub960_write(priv, UB9702_SR_CSI_PLL_DIV, pll_div, &ret);
-
- switch (priv->tx_data_rate) {
- case MHZ(1600):
- default:
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x80,
- &ret);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a,
- &ret);
- break;
- case MHZ(800):
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x90,
- &ret);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4f, 0x2a,
- &ret);
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a,
- &ret);
- break;
- case MHZ(400):
- ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0xa0,
- &ret);
- break;
- }
+ ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA,
+ UB9702_IR_CSI_ANA_CSIPLL_REG_1, ana_pll_div, &ret);
return ret;
}
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (10 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 11/19] media: i2c: ds90ub960: Refresh ub960_init_tx_ports_ub9702() Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-15 14:23 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 13/19] media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports() Tomi Valkeinen
` (6 subsequent siblings)
18 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
The driver does a lot of iteration over the RX ports with for loops. In
most cases the driver will skip unused RX ports. Also, in the future
patches the FPD-Link IV support will be refreshed with TI's latest init
sequences which involves a lot of additional iterations over the RX
ports, often only for FPD-Link IV ports.
To make the iteration simpler and to make it clearer what we're
iterating over (all or only-active, all or only-fpd4), add macros and
support functions for iterating the RX ports. Use the macros in the
driver, replacing the for loops.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 260 ++++++++++++++++++++++--------------------
1 file changed, 135 insertions(+), 125 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index bca858172942..02e22ae813fa 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -649,6 +649,63 @@ static const struct ub960_format_info *ub960_find_format(u32 code)
return NULL;
}
+struct ub960_rxport_iter {
+ unsigned int nport;
+ struct ub960_rxport *rxport;
+};
+
+enum ub960_iter_flags {
+ UB960_ITER_ACTIVE_ONLY = BIT(0),
+ UB960_ITER_FPD4_ONLY = BIT(1),
+};
+
+static struct ub960_rxport_iter ub960_iter_rxport(struct ub960_data *priv,
+ struct ub960_rxport_iter it,
+ enum ub960_iter_flags flags)
+{
+ for (; it.nport < priv->hw_data->num_rxports; it.nport++) {
+ it.rxport = priv->rxports[it.nport];
+
+ if ((flags & UB960_ITER_ACTIVE_ONLY) && !it.rxport)
+ continue;
+
+ if ((flags & UB960_ITER_FPD4_ONLY) &&
+ it.rxport->cdr_mode != RXPORT_CDR_FPD4)
+ continue;
+
+ return it;
+ }
+
+ it.rxport = NULL;
+
+ return it;
+}
+
+#define for_each_rxport(priv) \
+ for (struct ub960_rxport_iter it = \
+ ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
+ 0); \
+ it.nport < (priv)->hw_data->num_rxports; \
+ it.nport++, it = ub960_iter_rxport(priv, it, 0))
+
+#define for_each_active_rxport(priv) \
+ for (struct ub960_rxport_iter it = \
+ ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
+ UB960_ITER_ACTIVE_ONLY); \
+ it.nport < (priv)->hw_data->num_rxports; \
+ it.nport++, it = ub960_iter_rxport(priv, it, \
+ UB960_ITER_ACTIVE_ONLY))
+
+#define for_each_active_rxport_fpd4(priv) \
+ for (struct ub960_rxport_iter it = \
+ ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
+ UB960_ITER_ACTIVE_ONLY | \
+ UB960_ITER_FPD4_ONLY); \
+ it.nport < (priv)->hw_data->num_rxports; \
+ it.nport++, it = ub960_iter_rxport(priv, it, \
+ UB960_ITER_ACTIVE_ONLY | \
+ UB960_ITER_FPD4_ONLY))
+
/* -----------------------------------------------------------------------------
* Basic device access
*/
@@ -1356,25 +1413,25 @@ static int ub960_csi_handle_events(struct ub960_data *priv, u8 nport)
static int ub960_rxport_enable_vpocs(struct ub960_data *priv)
{
- unsigned int nport;
+ unsigned int failed_nport;
int ret;
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
-
- if (!rxport || !rxport->vpoc)
+ for_each_active_rxport(priv) {
+ if (!it.rxport->vpoc)
continue;
- ret = regulator_enable(rxport->vpoc);
- if (ret)
+ ret = regulator_enable(it.rxport->vpoc);
+ if (ret) {
+ failed_nport = it.nport;
goto err_disable_vpocs;
+ }
}
return 0;
err_disable_vpocs:
- while (nport--) {
- struct ub960_rxport *rxport = priv->rxports[nport];
+ while (failed_nport--) {
+ struct ub960_rxport *rxport = priv->rxports[failed_nport];
if (!rxport || !rxport->vpoc)
continue;
@@ -1387,15 +1444,11 @@ static int ub960_rxport_enable_vpocs(struct ub960_data *priv)
static void ub960_rxport_disable_vpocs(struct ub960_data *priv)
{
- unsigned int nport;
-
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
-
- if (!rxport || !rxport->vpoc)
+ for_each_active_rxport(priv) {
+ if (!it.rxport->vpoc)
continue;
- regulator_disable(rxport->vpoc);
+ regulator_disable(it.rxport->vpoc);
}
}
@@ -1420,12 +1473,10 @@ static int ub960_rxport_clear_errors(struct ub960_data *priv,
static int ub960_clear_rx_errors(struct ub960_data *priv)
{
- unsigned int nport;
-
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- int ret;
+ int ret;
- ret = ub960_rxport_clear_errors(priv, nport);
+ for_each_rxport(priv) {
+ ret = ub960_rxport_clear_errors(priv, it.nport);
if (ret)
return ret;
}
@@ -1928,30 +1979,27 @@ static void ub960_rxport_remove_serializer(struct ub960_data *priv, u8 nport)
/* Add serializer i2c devices for all initialized ports */
static int ub960_rxport_add_serializers(struct ub960_data *priv)
{
- unsigned int nport;
+ unsigned int failed_nport;
int ret;
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
-
- if (!rxport)
- continue;
-
- ret = ub960_rxport_add_serializer(priv, nport);
- if (ret)
+ for_each_active_rxport(priv) {
+ ret = ub960_rxport_add_serializer(priv, it.nport);
+ if (ret) {
+ failed_nport = it.nport;
goto err_remove_sers;
+ }
}
return 0;
err_remove_sers:
- while (nport--) {
- struct ub960_rxport *rxport = priv->rxports[nport];
+ while (failed_nport--) {
+ struct ub960_rxport *rxport = priv->rxports[failed_nport];
if (!rxport)
continue;
- ub960_rxport_remove_serializer(priv, nport);
+ ub960_rxport_remove_serializer(priv, failed_nport);
}
return ret;
@@ -1959,16 +2007,8 @@ static int ub960_rxport_add_serializers(struct ub960_data *priv)
static void ub960_rxport_remove_serializers(struct ub960_data *priv)
{
- unsigned int nport;
-
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
-
- if (!rxport)
- continue;
-
- ub960_rxport_remove_serializer(priv, nport);
- }
+ for_each_active_rxport(priv)
+ ub960_rxport_remove_serializer(priv, it.nport);
}
static int ub960_init_tx_port(struct ub960_data *priv,
@@ -2453,19 +2493,13 @@ static int ub960_init_rx_port_ub9702(struct ub960_data *priv,
static int ub960_init_rx_ports(struct ub960_data *priv)
{
- unsigned int nport;
-
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
+ for_each_active_rxport(priv) {
int ret;
- if (!rxport)
- continue;
-
if (priv->hw_data->is_ub9702)
- ret = ub960_init_rx_port_ub9702(priv, rxport);
+ ret = ub960_init_rx_port_ub9702(priv, it.rxport);
else
- ret = ub960_init_rx_port_ub960(priv, rxport);
+ ret = ub960_init_rx_port_ub960(priv, it.rxport);
if (ret)
return ret;
@@ -2683,20 +2717,14 @@ static int ub960_disable_rx_port(struct ub960_data *priv, unsigned int nport)
*/
static int ub960_validate_stream_vcs(struct ub960_data *priv)
{
- unsigned int nport;
- unsigned int i;
-
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
+ for_each_active_rxport(priv) {
struct v4l2_mbus_frame_desc desc;
int ret;
u8 vc;
- if (!rxport)
- continue;
-
- ret = v4l2_subdev_call(rxport->source.sd, pad, get_frame_desc,
- rxport->source.pad, &desc);
+ ret = v4l2_subdev_call(it.rxport->source.sd, pad,
+ get_frame_desc, it.rxport->source.pad,
+ &desc);
if (ret)
return ret;
@@ -2708,13 +2736,13 @@ static int ub960_validate_stream_vcs(struct ub960_data *priv)
vc = desc.entry[0].bus.csi2.vc;
- for (i = 1; i < desc.num_entries; i++) {
+ for (unsigned int i = 1; i < desc.num_entries; i++) {
if (vc == desc.entry[i].bus.csi2.vc)
continue;
dev_err(&priv->client->dev,
"rx%u: source with multiple virtual-channels is not supported\n",
- nport);
+ it.nport);
return -ENODEV;
}
}
@@ -2804,21 +2832,21 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
*/
fwd_ctl = GENMASK(7, 4);
- for (unsigned int nport = 0; nport < priv->hw_data->num_rxports;
- nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
+ for_each_active_rxport(priv) {
+ unsigned long nport = it.nport;
+
u8 vc = vc_map[nport];
if (rx_data[nport].num_streams == 0)
continue;
- switch (rxport->rx_mode) {
+ switch (it.rxport->rx_mode) {
case RXPORT_MODE_RAW10:
ub960_rxport_write(priv, nport, UB960_RR_RAW10_ID,
rx_data[nport].pixel_dt | (vc << UB960_RR_RAW10_ID_VC_SHIFT),
&ret);
- ub960_rxport_write(priv, rxport->nport,
+ ub960_rxport_write(priv, nport,
UB960_RR_RAW_EMBED_DTYPE,
(rx_data[nport].meta_lines << UB960_RR_RAW_EMBED_DTYPE_LINES_SHIFT) |
rx_data[nport].meta_dt, &ret);
@@ -2886,7 +2914,6 @@ static int ub960_enable_streams(struct v4l2_subdev *sd,
u64 sink_streams[UB960_MAX_RX_NPORTS] = {};
struct v4l2_subdev_route *route;
unsigned int failed_port;
- unsigned int nport;
int ret;
if (!priv->streaming) {
@@ -2908,6 +2935,8 @@ static int ub960_enable_streams(struct v4l2_subdev *sd,
/* Collect sink streams per pad which we need to enable */
for_each_active_route(&state->routing, route) {
+ unsigned int nport;
+
if (route->source_pad != source_pad)
continue;
@@ -2919,7 +2948,9 @@ static int ub960_enable_streams(struct v4l2_subdev *sd,
sink_streams[nport] |= BIT_ULL(route->sink_stream);
}
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+ for_each_rxport(priv) {
+ unsigned int nport = it.nport;
+
if (!sink_streams[nport])
continue;
@@ -2957,7 +2988,7 @@ static int ub960_enable_streams(struct v4l2_subdev *sd,
return 0;
err:
- for (nport = 0; nport < failed_port; nport++) {
+ for (unsigned int nport = 0; nport < failed_port; nport++) {
if (!sink_streams[nport])
continue;
@@ -2997,11 +3028,12 @@ static int ub960_disable_streams(struct v4l2_subdev *sd,
struct device *dev = &priv->client->dev;
u64 sink_streams[UB960_MAX_RX_NPORTS] = {};
struct v4l2_subdev_route *route;
- unsigned int nport;
int ret;
/* Collect sink streams per pad which we need to disable */
for_each_active_route(&state->routing, route) {
+ unsigned int nport;
+
if (route->source_pad != source_pad)
continue;
@@ -3013,7 +3045,9 @@ static int ub960_disable_streams(struct v4l2_subdev *sd,
sink_streams[nport] |= BIT_ULL(route->sink_stream);
}
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+ for_each_rxport(priv) {
+ unsigned int nport = it.nport;
+
if (!sink_streams[nport])
continue;
@@ -3335,7 +3369,6 @@ static int ub960_log_status(struct v4l2_subdev *sd)
struct ub960_data *priv = sd_to_ub960(sd);
struct device *dev = &priv->client->dev;
struct v4l2_subdev_state *state;
- unsigned int nport;
u16 v16 = 0;
u8 v = 0;
u8 id[UB960_SR_FPD3_RX_ID_LEN];
@@ -3351,7 +3384,8 @@ static int ub960_log_status(struct v4l2_subdev *sd)
dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
- for (nport = 0; nport < priv->hw_data->num_txports; nport++) {
+ for (unsigned int nport = 0; nport < priv->hw_data->num_txports;
+ nport++) {
struct ub960_txport *txport = priv->txports[nport];
dev_info(dev, "TX %u\n", nport);
@@ -3397,12 +3431,12 @@ static int ub960_log_status(struct v4l2_subdev *sd)
dev_info(dev, "\tline error counter %u\n", v16);
}
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
+ for_each_rxport(priv) {
+ unsigned int nport = it.nport;
dev_info(dev, "RX %u\n", nport);
- if (!rxport) {
+ if (!it.rxport) {
dev_info(dev, "\tNot initialized\n");
continue;
}
@@ -3514,7 +3548,6 @@ static const struct media_entity_operations ub960_entity_ops = {
static irqreturn_t ub960_handle_events(int irq, void *arg)
{
struct ub960_data *priv = arg;
- unsigned int i;
u8 int_sts;
u8 fwd_sts;
int ret;
@@ -3531,7 +3564,7 @@ static irqreturn_t ub960_handle_events(int irq, void *arg)
dev_dbg(&priv->client->dev, "FWD_STS %#02x\n", fwd_sts);
- for (i = 0; i < priv->hw_data->num_txports; i++) {
+ for (unsigned int i = 0; i < priv->hw_data->num_txports; i++) {
if (int_sts & UB960_SR_INTERRUPT_STS_IS_CSI_TX(i)) {
ret = ub960_csi_handle_events(priv, i);
if (ret)
@@ -3539,12 +3572,9 @@ static irqreturn_t ub960_handle_events(int irq, void *arg)
}
}
- for (i = 0; i < priv->hw_data->num_rxports; i++) {
- if (!priv->rxports[i])
- continue;
-
- if (int_sts & UB960_SR_INTERRUPT_STS_IS_RX(i)) {
- ret = ub960_rxport_handle_events(priv, i);
+ for_each_active_rxport(priv) {
+ if (int_sts & UB960_SR_INTERRUPT_STS_IS_RX(it.nport)) {
+ ret = ub960_rxport_handle_events(priv, it.nport);
if (ret)
return IRQ_NONE;
}
@@ -3582,19 +3612,12 @@ static void ub960_txport_free_ports(struct ub960_data *priv)
static void ub960_rxport_free_ports(struct ub960_data *priv)
{
- unsigned int nport;
-
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
-
- if (!rxport)
- continue;
-
- fwnode_handle_put(rxport->source.ep_fwnode);
- fwnode_handle_put(rxport->ser.fwnode);
+ for_each_active_rxport(priv) {
+ fwnode_handle_put(it.rxport->source.ep_fwnode);
+ fwnode_handle_put(it.rxport->ser.fwnode);
- kfree(rxport);
- priv->rxports[nport] = NULL;
+ kfree(it.rxport);
+ priv->rxports[it.nport] = NULL;
}
}
@@ -3853,7 +3876,6 @@ static int ub960_parse_dt_rxports(struct ub960_data *priv)
{
struct device *dev = &priv->client->dev;
struct fwnode_handle *links_fwnode;
- unsigned int nport;
int ret;
links_fwnode = fwnode_get_named_child_node(dev_fwnode(dev), "links");
@@ -3868,9 +3890,10 @@ static int ub960_parse_dt_rxports(struct ub960_data *priv)
priv->strobe.manual = fwnode_property_read_bool(links_fwnode, "ti,manual-strobe");
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+ for_each_rxport(priv) {
struct fwnode_handle *link_fwnode;
struct fwnode_handle *ep_fwnode;
+ unsigned int nport = it.nport;
link_fwnode = ub960_fwnode_get_link_by_regs(links_fwnode, nport);
if (!link_fwnode)
@@ -3959,7 +3982,6 @@ static int ub960_notify_bound(struct v4l2_async_notifier *notifier,
struct ub960_rxport *rxport = to_ub960_asd(asd)->rxport;
struct device *dev = &priv->client->dev;
u8 nport = rxport->nport;
- unsigned int i;
int ret;
ret = media_entity_get_fwnode_pad(&subdev->entity,
@@ -3984,8 +4006,8 @@ static int ub960_notify_bound(struct v4l2_async_notifier *notifier,
return ret;
}
- for (i = 0; i < priv->hw_data->num_rxports; i++) {
- if (priv->rxports[i] && !priv->rxports[i]->source.sd) {
+ for_each_active_rxport(priv) {
+ if (!it.rxport->source.sd) {
dev_dbg(dev, "Waiting for more subdevs to be bound\n");
return 0;
}
@@ -4011,29 +4033,24 @@ static const struct v4l2_async_notifier_operations ub960_notify_ops = {
static int ub960_v4l2_notifier_register(struct ub960_data *priv)
{
struct device *dev = &priv->client->dev;
- unsigned int i;
int ret;
v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
- for (i = 0; i < priv->hw_data->num_rxports; i++) {
- struct ub960_rxport *rxport = priv->rxports[i];
+ for_each_active_rxport(priv) {
struct ub960_asd *asd;
- if (!rxport)
- continue;
-
asd = v4l2_async_nf_add_fwnode(&priv->notifier,
- rxport->source.ep_fwnode,
+ it.rxport->source.ep_fwnode,
struct ub960_asd);
if (IS_ERR(asd)) {
dev_err(dev, "Failed to add subdev for source %u: %pe",
- i, asd);
+ it.nport, asd);
v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(asd);
}
- asd->rxport = rxport;
+ asd->rxport = it.rxport;
}
priv->notifier.ops = &ub960_notify_ops;
@@ -4304,7 +4321,6 @@ static int ub960_probe(struct i2c_client *client)
struct ub960_data *priv;
unsigned int port_lock_mask;
unsigned int port_mask;
- unsigned int nport;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -4357,14 +4373,8 @@ static int ub960_probe(struct i2c_client *client)
port_mask = 0;
- for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
- struct ub960_rxport *rxport = priv->rxports[nport];
-
- if (!rxport)
- continue;
-
- port_mask |= BIT(nport);
- }
+ for_each_active_rxport(priv)
+ port_mask |= BIT(it.nport);
ret = ub960_rxport_wait_locks(priv, port_mask, &port_lock_mask);
if (ret)
@@ -4403,9 +4413,9 @@ static int ub960_probe(struct i2c_client *client)
msecs_to_jiffies(UB960_POLL_TIME_MS));
#ifdef UB960_DEBUG_I2C_RX_ID
- for (unsigned int i = 0; i < priv->hw_data->num_rxports; i++)
- ub960_write(priv, UB960_SR_I2C_RX_ID(i),
- (UB960_DEBUG_I2C_RX_ID + i) << 1, NULL);
+ for_each_rxport(priv)
+ ub960_write(priv, UB960_SR_I2C_RX_ID(it.nport),
+ (UB960_DEBUG_I2C_RX_ID + it.nport) << 1, NULL);
#endif
return 0;
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 13/19] media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports()
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (11 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-15 14:25 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 14/19] media: i2c: ds90ub960: Remove old ub9702 RX port init code (SQUASH) Tomi Valkeinen
` (5 subsequent siblings)
18 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
We have some code in probe() which is related to RX port initialization,
and should be in ub960_init_rx_ports(). Move the code there.
We also move ub960_reset() so that it is accessible from
ub960_init_rx_ports().
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 115 ++++++++++++++++++++++--------------------
1 file changed, 59 insertions(+), 56 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index 02e22ae813fa..cc944d737524 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -1225,6 +1225,33 @@ static int ub960_ind_update_bits(struct ub960_data *priv, u8 block, u8 reg,
return ret;
}
+static int ub960_reset(struct ub960_data *priv, bool reset_regs)
+{
+ struct device *dev = &priv->client->dev;
+ unsigned int v;
+ int ret;
+ u8 bit;
+
+ bit = reset_regs ? UB960_SR_RESET_DIGITAL_RESET1 :
+ UB960_SR_RESET_DIGITAL_RESET0;
+
+ ret = ub960_write(priv, UB960_SR_RESET, bit, NULL);
+ if (ret)
+ return ret;
+
+ mutex_lock(&priv->reg_lock);
+
+ ret = regmap_read_poll_timeout(priv->regmap, UB960_SR_RESET, v,
+ (v & bit) == 0, 2000, 100000);
+
+ mutex_unlock(&priv->reg_lock);
+
+ if (ret)
+ dev_err(dev, "reset failed: %d\n", ret);
+
+ return ret;
+}
+
/* -----------------------------------------------------------------------------
* I2C-ATR (address translator)
*/
@@ -2493,6 +2520,11 @@ static int ub960_init_rx_port_ub9702(struct ub960_data *priv,
static int ub960_init_rx_ports(struct ub960_data *priv)
{
+ struct device *dev = &priv->client->dev;
+ unsigned int port_lock_mask;
+ unsigned int port_mask;
+ int ret;
+
for_each_active_rxport(priv) {
int ret;
@@ -2505,6 +2537,33 @@ static int ub960_init_rx_ports(struct ub960_data *priv)
return ret;
}
+ ret = ub960_reset(priv, false);
+ if (ret)
+ return ret;
+
+ port_mask = 0;
+
+ for_each_active_rxport(priv)
+ port_mask |= BIT(it.nport);
+
+ ret = ub960_rxport_wait_locks(priv, port_mask, &port_lock_mask);
+ if (ret)
+ return ret;
+
+ if (port_mask != port_lock_mask) {
+ ret = -EIO;
+ dev_err_probe(dev, ret, "Failed to lock all RX ports\n");
+ return ret;
+ }
+
+ /*
+ * Clear any errors caused by switching the RX port settings while
+ * probing.
+ */
+ ret = ub960_clear_rx_errors(priv);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -4168,33 +4227,6 @@ static const struct regmap_config ub960_regmap_config = {
.disable_locking = true,
};
-static int ub960_reset(struct ub960_data *priv, bool reset_regs)
-{
- struct device *dev = &priv->client->dev;
- unsigned int v;
- int ret;
- u8 bit;
-
- bit = reset_regs ? UB960_SR_RESET_DIGITAL_RESET1 :
- UB960_SR_RESET_DIGITAL_RESET0;
-
- ret = ub960_write(priv, UB960_SR_RESET, bit, NULL);
- if (ret)
- return ret;
-
- mutex_lock(&priv->reg_lock);
-
- ret = regmap_read_poll_timeout(priv->regmap, UB960_SR_RESET, v,
- (v & bit) == 0, 2000, 100000);
-
- mutex_unlock(&priv->reg_lock);
-
- if (ret)
- dev_err(dev, "reset failed: %d\n", ret);
-
- return ret;
-}
-
static int ub960_get_hw_resources(struct ub960_data *priv)
{
struct device *dev = &priv->client->dev;
@@ -4319,8 +4351,6 @@ static int ub960_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct ub960_data *priv;
- unsigned int port_lock_mask;
- unsigned int port_mask;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -4367,33 +4397,6 @@ static int ub960_probe(struct i2c_client *client)
if (ret)
goto err_disable_vpocs;
- ret = ub960_reset(priv, false);
- if (ret)
- goto err_disable_vpocs;
-
- port_mask = 0;
-
- for_each_active_rxport(priv)
- port_mask |= BIT(it.nport);
-
- ret = ub960_rxport_wait_locks(priv, port_mask, &port_lock_mask);
- if (ret)
- goto err_disable_vpocs;
-
- if (port_mask != port_lock_mask) {
- ret = -EIO;
- dev_err_probe(dev, ret, "Failed to lock all RX ports\n");
- goto err_disable_vpocs;
- }
-
- /*
- * Clear any errors caused by switching the RX port settings while
- * probing.
- */
- ret = ub960_clear_rx_errors(priv);
- if (ret)
- goto err_disable_vpocs;
-
ret = ub960_init_atr(priv);
if (ret)
goto err_disable_vpocs;
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 14/19] media: i2c: ds90ub960: Remove old ub9702 RX port init code (SQUASH)
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (12 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 13/19] media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports() Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 15/19] media: i2c: ds90ub960: Update UB9702 init sequences Tomi Valkeinen
` (4 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
We will refresh ub9702 RX port initialization code in the following
patch. To make that patch easier to review, remove the old ub9702 code
here.
This should be squashed in the final version.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 273 +-----------------------------------------
1 file changed, 3 insertions(+), 270 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index cc944d737524..dc9ead85c676 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -2257,268 +2257,7 @@ static int ub960_init_rx_port_ub960(struct ub960_data *priv,
return ret;
}
-static int ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
- struct ub960_rxport *rxport)
-{
- unsigned int nport = rxport->nport;
- u8 bc_freq_val;
- u8 fpd_func_mode;
- int ret = 0;
-
- switch (rxport->rx_mode) {
- case RXPORT_MODE_RAW10:
- bc_freq_val = 0;
- fpd_func_mode = 5;
- break;
-
- case RXPORT_MODE_RAW12_HF:
- bc_freq_val = 0;
- fpd_func_mode = 4;
- break;
-
- case RXPORT_MODE_RAW12_LF:
- bc_freq_val = 0;
- fpd_func_mode = 6;
- break;
-
- case RXPORT_MODE_CSI2_SYNC:
- bc_freq_val = 6;
- fpd_func_mode = 2;
- break;
-
- case RXPORT_MODE_CSI2_NONSYNC:
- bc_freq_val = 2;
- fpd_func_mode = 2;
- break;
-
- default:
- return -EINVAL;
- }
-
- ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
- bc_freq_val, &ret);
- ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, fpd_func_mode,
- &ret);
-
- /* set serdes_eq_mode = 1 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa8, 0x80,
- &ret);
-
- /* enable serdes driver */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x0d, 0x7f,
- &ret);
-
- /* set serdes_eq_offset=4 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04,
- &ret);
-
- /* init default serdes_eq_max in 0xa9 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa9, 0x23,
- &ret);
-
- /* init serdes_eq_min in 0xaa */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xaa, 0, &ret);
-
- /* serdes_driver_ctl2 control: DS90UB953-Q1/DS90UB933-Q1/DS90UB913A-Q1 */
- ub960_ind_update_bits(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b,
- BIT(3), BIT(3), &ret);
-
- /* RX port to half-rate */
- ub960_update_bits(priv, UB9702_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
- BIT(nport * 2), &ret);
-
- return ret;
-}
-
-static int ub960_init_rx_port_ub9702_fpd4_aeq(struct ub960_data *priv,
- struct ub960_rxport *rxport)
-{
- unsigned int nport = rxport->nport;
- bool first_time_power_up = true;
- int ret = 0;
-
- if (first_time_power_up) {
- u8 v;
-
- /* AEQ init */
- ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2c, &v,
- &ret);
-
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, v,
- &ret);
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28,
- v + 1, &ret);
-
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b,
- 0x00, &ret);
- }
-
- /* enable serdes_eq_ctl2 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x9e, 0x00,
- &ret);
-
- /* enable serdes_eq_ctl1 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x90, 0x40,
- &ret);
-
- /* enable serdes_eq_en */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2e, 0x40,
- &ret);
-
- /* disable serdes_eq_override */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xf0, 0x00,
- &ret);
-
- /* disable serdes_gain_override */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x71, 0x00,
- &ret);
-
- return ret;
-}
-
-static int ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
- struct ub960_rxport *rxport)
-{
- unsigned int nport = rxport->nport;
- u8 bc_freq_val;
- int ret = 0;
-
- switch (rxport->rx_mode) {
- case RXPORT_MODE_RAW10:
- bc_freq_val = 0;
- break;
-
- case RXPORT_MODE_RAW12_HF:
- bc_freq_val = 0;
- break;
-
- case RXPORT_MODE_RAW12_LF:
- bc_freq_val = 0;
- break;
-
- case RXPORT_MODE_CSI2_SYNC:
- bc_freq_val = 6;
- break;
-
- case RXPORT_MODE_CSI2_NONSYNC:
- bc_freq_val = 2;
- break;
-
- default:
- return -EINVAL;
- }
-
- ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
- bc_freq_val, &ret);
-
- /* FPD4 Sync Mode */
- ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, 0, &ret);
-
- /* add serdes_eq_offset of 4 */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04,
- &ret);
-
- /* FPD4 serdes_start_eq in 0x27: assign default */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, 0x0, &ret);
- /* FPD4 serdes_end_eq in 0x28: assign default */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28, 0x23,
- &ret);
-
- /* set serdes_driver_mode into FPD IV mode */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x04, 0x00,
- &ret);
- /* set FPD PBC drv into FPD IV mode */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b, 0x00,
- &ret);
-
- /* set serdes_system_init to 0x2f */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x21, 0x2f,
- &ret);
- /* set serdes_system_rst in reset mode */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25, 0xc1,
- &ret);
-
- /* RX port to 7.55G mode */
- ub960_update_bits(priv, UB9702_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
- 0 << (nport * 2), &ret);
-
- if (ret)
- return ret;
-
- ret = ub960_init_rx_port_ub9702_fpd4_aeq(priv, rxport);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static int ub960_init_rx_port_ub9702(struct ub960_data *priv,
- struct ub960_rxport *rxport)
-{
- unsigned int nport = rxport->nport;
- int ret;
-
- if (rxport->cdr_mode == RXPORT_CDR_FPD3)
- ret = ub960_init_rx_port_ub9702_fpd3(priv, rxport);
- else /* RXPORT_CDR_FPD4 */
- ret = ub960_init_rx_port_ub9702_fpd4(priv, rxport);
-
- if (ret)
- return ret;
-
- switch (rxport->rx_mode) {
- case RXPORT_MODE_RAW10:
- /*
- * RAW10_8BIT_CTL = 0b11 : 8-bit processing using lower 8 bits
- * 0b10 : 8-bit processing using upper 8 bits
- */
- ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2,
- 0x3 << 6, 0x2 << 6, &ret);
-
- break;
-
- case RXPORT_MODE_RAW12_HF:
- case RXPORT_MODE_RAW12_LF:
- /* Not implemented */
- return -EINVAL;
-
- case RXPORT_MODE_CSI2_SYNC:
- case RXPORT_MODE_CSI2_NONSYNC:
-
- break;
- }
-
- /* LV_POLARITY & FV_POLARITY */
- ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
- rxport->lv_fv_pol, &ret);
-
- /* Enable all interrupt sources from this port */
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07, &ret);
- ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f, &ret);
-
- /* Enable I2C_PASS_THROUGH */
- ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
- UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
- UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, &ret);
-
- /* Enable I2C communication to the serializer via the alias addr */
- ub960_rxport_write(priv, nport, UB960_RR_SER_ALIAS_ID,
- rxport->ser.alias << 1, &ret);
-
- /* Enable RX port */
- ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
- &ret);
-
- if (rxport->cdr_mode == RXPORT_CDR_FPD4) {
- /* unreset 960 AEQ */
- ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25,
- 0x41, &ret);
- }
-
- return ret;
-}
-
-static int ub960_init_rx_ports(struct ub960_data *priv)
+static int ub960_init_rx_ports_ub960(struct ub960_data *priv)
{
struct device *dev = &priv->client->dev;
unsigned int port_lock_mask;
@@ -2526,13 +2265,7 @@ static int ub960_init_rx_ports(struct ub960_data *priv)
int ret;
for_each_active_rxport(priv) {
- int ret;
-
- if (priv->hw_data->is_ub9702)
- ret = ub960_init_rx_port_ub9702(priv, it.rxport);
- else
- ret = ub960_init_rx_port_ub960(priv, it.rxport);
-
+ ret = ub960_init_rx_port_ub960(priv, it.rxport);
if (ret)
return ret;
}
@@ -4393,7 +4126,7 @@ static int ub960_probe(struct i2c_client *client)
if (ret)
goto err_free_ports;
- ret = ub960_init_rx_ports(priv);
+ ret = ub960_init_rx_ports_ub960(priv);
if (ret)
goto err_disable_vpocs;
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 15/19] media: i2c: ds90ub960: Update UB9702 init sequences
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (13 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 14/19] media: i2c: ds90ub960: Remove old ub9702 RX port init code (SQUASH) Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702 Tomi Valkeinen
` (3 subsequent siblings)
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
Update ub9702 RX port init sequence according to TI's latest
(non-public) documentation. The sequence is based on a Python script
provided by TI.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 737 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 736 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index dc9ead85c676..f6d6c2fe12cd 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -243,6 +243,7 @@
#define UB960_RR_BIST_ERR_COUNT 0x57
#define UB960_RR_BCC_CONFIG 0x58
+#define UB960_RR_BCC_CONFIG_BC_ALWAYS_ON BIT(4)
#define UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH BIT(6)
#define UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK GENMASK(2, 0)
@@ -1788,6 +1789,23 @@ static int ub960_rxport_link_ok(struct ub960_data *priv, unsigned int nport,
return 0;
}
+static int ub960_rxport_lockup_wa_ub9702(struct ub960_data *priv)
+{
+ int ret;
+
+ /* Toggle PI_MODE to avoid possible FPD RX lockup */
+
+ ret = ub960_update_bits(priv, UB9702_RR_CHANNEL_MODE, GENMASK(4, 3),
+ 2 << 3, NULL);
+ if (ret)
+ return ret;
+
+ usleep_range(1000, 5000);
+
+ return ub960_update_bits(priv, UB9702_RR_CHANNEL_MODE, GENMASK(4, 3),
+ 0, NULL);
+}
+
/*
* Wait for the RX ports to lock, have no errors and have stable strobe position
* and EQ level.
@@ -1818,6 +1836,7 @@ static int ub960_rxport_wait_locks(struct ub960_data *priv,
link_ok_mask = 0;
while (time_before(jiffies, timeout)) {
+ bool fpd4_wa = false;
missing = 0;
for_each_set_bit(nport, &port_mask,
@@ -1832,6 +1851,9 @@ static int ub960_rxport_wait_locks(struct ub960_data *priv,
if (ret)
return ret;
+ if (!ok && rxport->cdr_mode == RXPORT_CDR_FPD4)
+ fpd4_wa = true;
+
/*
* We want the link to be ok for two consecutive loops,
* as a link could get established just before our test
@@ -1851,6 +1873,12 @@ static int ub960_rxport_wait_locks(struct ub960_data *priv,
if (missing == 0)
break;
+ if (fpd4_wa) {
+ ret = ub960_rxport_lockup_wa_ub9702(priv);
+ if (ret)
+ return ret;
+ }
+
/*
* The sleep time of 10 ms was found by testing to give a lock
* with a few iterations. It can be decreased if on some setups
@@ -2300,6 +2328,709 @@ static int ub960_init_rx_ports_ub960(struct ub960_data *priv)
return 0;
}
+/*
+ * UB9702 specific initial RX port configuration
+ */
+
+static int ub960_turn_off_rxport_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ int ret = 0;
+
+ /* Disable RX port */
+ ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), 0, &ret);
+
+ /* Disable FPD Rx and FPD BC CMR */
+ ub960_rxport_write(priv, nport, UB9702_RR_RX_CTL_2, 0x1b, &ret);
+
+ /* Disable FPD BC Tx */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, BIT(4), 0,
+ &ret);
+
+ /* Disable internal RX blocks */
+ ub960_rxport_write(priv, nport, UB9702_RR_RX_CTL_1, 0x15, &ret);
+
+ /* Disable AEQ */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_CFG_2, 0x03, &ret);
+
+ /* PI disabled and oDAC disabled */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_CFG_4, 0x09, &ret);
+
+ /* AEQ configured for disabled link */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_CFG_1, 0x20, &ret);
+
+ /* disable AEQ clock and DFE */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_CFG_3, 0x45, &ret);
+
+ /* Powerdown FPD3 CDR */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_FPD3_CDR_CTRL_SEL_5, 0x82, &ret);
+
+ return ret;
+}
+
+static int ub960_set_bc_drv_config_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ u8 fpd_bc_ctl0;
+ u8 fpd_bc_ctl1;
+ u8 fpd_bc_ctl2;
+ int ret = 0;
+
+ if (priv->rxports[nport]->cdr_mode == RXPORT_CDR_FPD4) {
+ /* Set FPD PBC drv into FPD IV mode */
+
+ fpd_bc_ctl0 = 0;
+ fpd_bc_ctl1 = 0;
+ fpd_bc_ctl2 = 0;
+ } else {
+ /* Set FPD PBC drv into FPD III mode */
+
+ fpd_bc_ctl0 = 2;
+ fpd_bc_ctl1 = 1;
+ fpd_bc_ctl2 = 5;
+ }
+
+ ub960_ind_update_bits(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_FPD_BC_CTL0, GENMASK(7, 5),
+ fpd_bc_ctl0 << 5, &ret);
+
+ ub960_ind_update_bits(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_FPD_BC_CTL1, BIT(6),
+ fpd_bc_ctl1 << 6, &ret);
+
+ ub960_ind_update_bits(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_FPD_BC_CTL2, GENMASK(6, 3),
+ fpd_bc_ctl2 << 3, &ret);
+
+ return ret;
+}
+
+static int ub960_set_fpd4_sync_mode_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ int ret = 0;
+
+ /* FPD4 Sync Mode */
+ ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, 0x0, &ret);
+
+ /* BC_FREQ_SELECT = (PLL_FREQ/3200) Mbps */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK, 6, &ret);
+
+ if (ret)
+ return ret;
+
+ ret = ub960_set_bc_drv_config_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ /* Set AEQ timer to 400us/step */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_SYSTEM_INIT_REG0, 0x2f, &ret);
+
+ /* Disable FPD4 Auto Recovery */
+ ub960_update_bits(priv, UB9702_SR_CSI_EXCLUSIVE_FWD2, GENMASK(5, 4), 0,
+ &ret);
+
+ /* Enable RX port */
+ ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
+ &ret);
+
+ /* Enable FPD4 Auto Recovery */
+ ub960_update_bits(priv, UB9702_SR_CSI_EXCLUSIVE_FWD2, GENMASK(5, 4),
+ BIT(4), &ret);
+
+ return ret;
+}
+
+static int ub960_set_fpd4_async_mode_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ int ret = 0;
+
+ /* FPD4 ASync Mode */
+ ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, 0x1, &ret);
+
+ /* 10Mbps w/ BC enabled */
+ /* BC_FREQ_SELECT=(PLL_FREQ/3200) Mbps */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK, 2, &ret);
+
+ if (ret)
+ return ret;
+
+ ret = ub960_set_bc_drv_config_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ /* Set AEQ timer to 400us/step */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_SYSTEM_INIT_REG0, 0x2f, &ret);
+
+ /* Disable FPD4 Auto Recover */
+ ub960_update_bits(priv, UB9702_SR_CSI_EXCLUSIVE_FWD2, GENMASK(5, 4), 0,
+ &ret);
+
+ /* Enable RX port */
+ ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
+ &ret);
+
+ /* Enable FPD4 Auto Recovery */
+ ub960_update_bits(priv, UB9702_SR_CSI_EXCLUSIVE_FWD2, GENMASK(5, 4),
+ BIT(4), &ret);
+
+ return ret;
+}
+
+static int ub960_set_fpd3_sync_mode_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ int ret = 0;
+
+ /* FPD3 Sync Mode */
+ ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, 0x2, &ret);
+
+ /* BC_FREQ_SELECT=(PLL_FREQ/3200) Mbps */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK, 6, &ret);
+
+ /* Set AEQ_LOCK_MODE = 1 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_FPD3_AEQ_CTRL_SEL_1, BIT(7), &ret);
+
+ if (ret)
+ return ret;
+
+ ret = ub960_set_bc_drv_config_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ /* Enable RX port */
+ ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
+ &ret);
+
+ return ret;
+}
+
+static int ub960_set_raw10_dvp_mode_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ int ret = 0;
+
+ /* FPD3 RAW10 Mode */
+ ub960_rxport_write(priv, nport, UB9702_RR_CHANNEL_MODE, 0x5, &ret);
+
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK, 0, &ret);
+
+ /* Set AEQ_LOCK_MODE = 1 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_FPD3_AEQ_CTRL_SEL_1, BIT(7), &ret);
+
+ /*
+ * RAW10_8BIT_CTL = 0b11 : 8-bit processing using lower 8 bits
+ * 0b10 : 8-bit processing using upper 8 bits
+ */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3 << 6,
+ 0x2 << 6, &ret);
+
+ /* LV_POLARITY & FV_POLARITY */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
+ priv->rxports[nport]->lv_fv_pol, &ret);
+
+ if (ret)
+ return ret;
+
+ ret = ub960_set_bc_drv_config_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ /* Enable RX port */
+ ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport),
+ &ret);
+
+ return ret;
+}
+
+static int ub960_configure_rx_port_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ struct device *dev = &priv->client->dev;
+ struct ub960_rxport *rxport = priv->rxports[nport];
+ int ret;
+
+ if (!rxport) {
+ ret = ub960_turn_off_rxport_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: disabled\n", nport);
+ return 0;
+ }
+
+ switch (rxport->cdr_mode) {
+ case RXPORT_CDR_FPD4:
+ switch (rxport->rx_mode) {
+ case RXPORT_MODE_CSI2_SYNC:
+ ret = ub960_set_fpd4_sync_mode_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: FPD-Link IV SYNC mode\n", nport);
+ break;
+ case RXPORT_MODE_CSI2_NONSYNC:
+ ret = ub960_set_fpd4_async_mode_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: FPD-Link IV ASYNC mode\n", nport);
+ break;
+ default:
+ dev_err(dev, "rx%u: unsupported FPD4 mode %u\n", nport,
+ rxport->rx_mode);
+ return -EINVAL;
+ }
+ break;
+
+ case RXPORT_CDR_FPD3:
+ switch (rxport->rx_mode) {
+ case RXPORT_MODE_CSI2_SYNC:
+ ret = ub960_set_fpd3_sync_mode_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: FPD-Link III SYNC mode\n", nport);
+ break;
+ case RXPORT_MODE_RAW10:
+ ret = ub960_set_raw10_dvp_mode_ub9702(priv, nport);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: FPD-Link III RAW10 DVP mode\n",
+ nport);
+ break;
+ default:
+ dev_err(&priv->client->dev,
+ "rx%u: unsupported FPD3 mode %u\n", nport,
+ rxport->rx_mode);
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ dev_err(&priv->client->dev, "rx%u: unsupported CDR mode %u\n",
+ nport, rxport->cdr_mode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ub960_lock_recovery_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ struct device *dev = &priv->client->dev;
+ /* Assumption that max AEQ should be under 16 */
+ const u8 rx_aeq_limit = 16;
+ u8 prev_aeq = 0xff;
+ bool rx_lock;
+
+ for (unsigned int retry = 0; retry < 3; ++retry) {
+ u8 port_sts1;
+ u8 rx_aeq;
+ int ret;
+
+ ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1,
+ &port_sts1, NULL);
+ if (ret)
+ return ret;
+
+ rx_lock = port_sts1 & UB960_RR_RX_PORT_STS1_PORT_PASS;
+
+ if (!rx_lock) {
+ ret = ub960_rxport_lockup_wa_ub9702(priv);
+ if (ret)
+ return ret;
+
+ /* Restart AEQ by changing max to 0 --> 0x23 */
+ ret = ub960_write_ind(priv,
+ UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL7, 0,
+ NULL);
+ if (ret)
+ return ret;
+
+ msleep(20);
+
+ /* AEQ Restart */
+ ret = ub960_write_ind(priv,
+ UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL7,
+ 0x23, NULL);
+
+ if (ret)
+ return ret;
+
+ msleep(20);
+ dev_dbg(dev, "rx%u: no lock, retry = %u\n", nport,
+ retry);
+
+ continue;
+ }
+
+ ret = ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL11, &rx_aeq,
+ NULL);
+ if (ret)
+ return ret;
+
+ if (rx_aeq < rx_aeq_limit) {
+ dev_dbg(dev,
+ "rx%u: locked and AEQ normal before setting AEQ window\n",
+ nport);
+ return 0;
+ }
+
+ if (rx_aeq != prev_aeq) {
+ ret = ub960_rxport_lockup_wa_ub9702(priv);
+ if (ret)
+ return ret;
+
+ /* Restart AEQ by changing max to 0 --> 0x23 */
+ ret = ub960_write_ind(priv,
+ UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL7,
+ 0, NULL);
+ if (ret)
+ return ret;
+
+ msleep(20);
+
+ /* AEQ Restart */
+ ret = ub960_write_ind(priv,
+ UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL7,
+ 0x23, NULL);
+ if (ret)
+ return ret;
+
+ msleep(20);
+
+ dev_dbg(dev,
+ "rx%u: high AEQ at initial check recovery loop, retry=%u\n",
+ nport, retry);
+
+ prev_aeq = rx_aeq;
+ } else {
+ dev_dbg(dev,
+ "rx%u: lossy cable detected, RX_AEQ %#x, RX_AEQ_LIMIT %#x, retry %u\n",
+ nport, rx_aeq, rx_aeq_limit, retry);
+ dev_dbg(dev,
+ "rx%u: will continue with initiation sequence but high AEQ\n",
+ nport);
+ return 0;
+ }
+ }
+
+ dev_err(dev, "rx%u: max number of retries: %s\n", nport,
+ rx_lock ? "unstable AEQ" : "no lock");
+
+ return -EIO;
+}
+
+static int ub960_enable_aeq_lms_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ struct device *dev = &priv->client->dev;
+ u8 read_aeq_init;
+ int ret;
+
+ ret = ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL11, &read_aeq_init,
+ NULL);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: initial AEQ = %#x\n", nport, read_aeq_init);
+
+ /* Set AEQ Min */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL6, read_aeq_init, &ret);
+ /* Set AEQ Max */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL7, read_aeq_init + 1, &ret);
+ /* Set AEQ offset to 0 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL10, 0x0, &ret);
+
+ /* Enable AEQ tap2 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_EQ_CTRL_SEL_38, 0x00, &ret);
+ /* Set VGA Gain 1 Gain 2 override to 0 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_VGA_CTRL_SEL_8, 0x00, &ret);
+ /* Set VGA Initial Sweep Gain to 0 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_VGA_CTRL_SEL_6, 0x80, &ret);
+ /* Set VGA_Adapt (VGA Gain) override to 0 (thermometer encoded) */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_VGA_CTRL_SEL_3, 0x00, &ret);
+ /* Enable VGA_SWEEP */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_EQ_ADAPT_CTRL, 0x40, &ret);
+ /* Disable VGA_SWEEP_GAIN_OV, disable VGA_TUNE_OV */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_EQ_OVERRIDE_CTRL, 0x00, &ret);
+
+ /* Set VGA HIGH Threshold to 43 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_VGA_CTRL_SEL_1, 0x2b, &ret);
+ /* Set VGA LOW Threshold to 18 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_VGA_CTRL_SEL_2, 0x12, &ret);
+ /* Set vga_sweep_th to 32 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_EQ_CTRL_SEL_15, 0x20, &ret);
+ /* Set AEQ timer to 400us/step and parity threshold to 7 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_SYSTEM_INIT_REG0, 0xef, &ret);
+
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: enable FPD-Link IV AEQ LMS\n", nport);
+
+ return 0;
+}
+
+static int ub960_enable_dfe_lms_ub9702(struct ub960_data *priv,
+ unsigned int nport)
+{
+ struct device *dev = &priv->client->dev;
+ int ret = 0;
+
+ /* Enable DFE LMS */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_EQ_CTRL_SEL_24, 0x40, &ret);
+ /* Disable VGA Gain1 override */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_GAIN_CTRL_0, 0x20, &ret);
+
+ if (ret)
+ return ret;
+
+ usleep_range(1000, 5000);
+
+ /* Disable VGA Gain2 override */
+ ret = ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+ UB9702_IR_RX_ANA_GAIN_CTRL_0, 0x00, NULL);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: enabled FPD-Link IV DFE LMS", nport);
+
+ return 0;
+}
+
+static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
+{
+ struct device *dev = &priv->client->dev;
+ unsigned int port_lock_mask;
+ unsigned int port_mask = 0;
+ bool have_fpd4 = false;
+ int ret;
+
+ for_each_active_rxport(priv) {
+ ret = ub960_rxport_update_bits(priv, it.nport,
+ UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_BC_ALWAYS_ON,
+ UB960_RR_BCC_CONFIG_BC_ALWAYS_ON,
+ NULL);
+ if (ret)
+ return ret;
+ }
+
+ /* Disable FPD4 Auto Recovery */
+ ret = ub960_write(priv, UB9702_SR_CSI_EXCLUSIVE_FWD2, 0x0f, NULL);
+ if (ret)
+ return ret;
+
+ for_each_active_rxport_fpd4(priv) {
+ /* Hold state machine in reset */
+ ub960_rxport_write(priv, it.nport, UB9702_RR_RX_SM_SEL_2, 0x10,
+ &ret);
+
+ /* Set AEQ max to 0 */
+ ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(it.nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL7, 0, &ret);
+
+ if (ret)
+ return ret;
+
+ dev_dbg(dev,
+ "rx%u: holding state machine and adjusting AEQ max to 0",
+ it.nport);
+ }
+
+ for_each_active_rxport(priv) {
+ port_mask |= BIT(it.nport);
+
+ if (it.rxport->cdr_mode == RXPORT_CDR_FPD4)
+ have_fpd4 = true;
+ }
+
+ for_each_rxport(priv) {
+ ret = ub960_configure_rx_port_ub9702(priv, it.nport);
+ if (ret)
+ return ret;
+ }
+
+ ret = ub960_reset(priv, false);
+ if (ret)
+ return ret;
+
+ if (have_fpd4) {
+ for_each_active_rxport_fpd4(priv) {
+ /* Release state machine */
+ ret = ub960_rxport_write(priv, it.nport,
+ UB9702_RR_RX_SM_SEL_2, 0x0,
+ NULL);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: state machine released\n",
+ it.nport);
+ }
+
+ /* Wait for SM to resume */
+ fsleep(5000);
+
+ for_each_active_rxport_fpd4(priv) {
+ ret = ub960_write_ind(priv,
+ UB960_IND_TARGET_RX_ANA(it.nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL7,
+ 0x23, NULL);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: AEQ restart\n", it.nport);
+ }
+
+ /* Wait for lock */
+ fsleep(20000);
+
+ for_each_active_rxport_fpd4(priv) {
+ ret = ub960_lock_recovery_ub9702(priv, it.nport);
+ if (ret)
+ return ret;
+ }
+
+ for_each_active_rxport_fpd4(priv) {
+ ret = ub960_enable_aeq_lms_ub9702(priv, it.nport);
+ if (ret)
+ return ret;
+ }
+
+ for_each_active_rxport_fpd4(priv) {
+ /* Hold state machine in reset */
+ ret = ub960_rxport_write(priv, it.nport,
+ UB9702_RR_RX_SM_SEL_2, 0x10,
+ NULL);
+ if (ret)
+ return ret;
+ }
+
+ ret = ub960_reset(priv, false);
+ if (ret)
+ return ret;
+
+ for_each_active_rxport_fpd4(priv) {
+ /* Release state machine */
+ ret = ub960_rxport_write(priv, it.nport,
+ UB9702_RR_RX_SM_SEL_2, 0,
+ NULL);
+ if (ret)
+ return ret;
+ }
+ }
+
+ /* Wait time for stable lock */
+ fsleep(15000);
+
+ for_each_active_rxport_fpd4(priv) {
+ ret = ub960_enable_dfe_lms_ub9702(priv, it.nport);
+ if (ret)
+ return ret;
+ }
+
+ /* Wait for DFE and LMS to adapt */
+ fsleep(5000);
+
+ ret = ub960_rxport_wait_locks(priv, port_mask, &port_lock_mask);
+ if (ret)
+ return ret;
+
+ if (port_mask != port_lock_mask) {
+ ret = -EIO;
+ dev_err_probe(dev, ret, "Failed to lock all RX ports\n");
+ return ret;
+ }
+
+ for_each_active_rxport(priv) {
+ /* Enable all interrupt sources from this port */
+ ub960_rxport_write(priv, it.nport, UB960_RR_PORT_ICR_HI, 0x07,
+ &ret);
+ ub960_rxport_write(priv, it.nport, UB960_RR_PORT_ICR_LO, 0x7f,
+ &ret);
+
+ /* Enable I2C_PASS_THROUGH */
+ ub960_rxport_update_bits(priv, it.nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
+ &ret);
+
+ /* Enable I2C communication to the serializer via the alias */
+ ub960_rxport_write(priv, it.nport, UB960_RR_SER_ALIAS_ID,
+ it.rxport->ser.alias << 1, &ret);
+
+ if (ret)
+ return ret;
+ }
+
+ /* Enable FPD4 Auto Recovery, Recovery loop active */
+ ret = ub960_write(priv, UB9702_SR_CSI_EXCLUSIVE_FWD2, 0x18, NULL);
+ if (ret)
+ return ret;
+
+ for_each_active_rxport_fpd4(priv) {
+ u8 final_aeq;
+
+ ret = ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(it.nport),
+ UB9702_IR_RX_ANA_AEQ_ALP_SEL11, &final_aeq,
+ NULL);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "rx%u: final AEQ = %#x\n", it.nport, final_aeq);
+ }
+
+ /*
+ * Clear any errors caused by switching the RX port settings while
+ * probing.
+ */
+
+ ret = ub960_clear_rx_errors(priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
{
struct device *dev = &priv->client->dev;
@@ -4126,7 +4857,11 @@ static int ub960_probe(struct i2c_client *client)
if (ret)
goto err_free_ports;
- ret = ub960_init_rx_ports_ub960(priv);
+ if (priv->hw_data->is_ub9702)
+ ret = ub960_init_rx_ports_ub9702(priv);
+ else
+ ret = ub960_init_rx_ports_ub960(priv);
+
if (ret)
goto err_disable_vpocs;
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (14 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 15/19] media: i2c: ds90ub960: Update UB9702 init sequences Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-15 14:26 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property Tomi Valkeinen
` (2 subsequent siblings)
18 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
From: Jai Luthra <jai.luthra@ideasonboard.com>
UB9702 supports spread-spectrum clock generation for the back-channel
clock, which is futher used by serializers in synchronous mode to
generate the forward-channel clock, which can help reduce peak EMI
energy. The SSCG is common to all RX ports, so it can only be used if
all the ports are in the same mode.
Add basic support for SSCG by adding a module parameter to enable the
SSCG. The SSCG uses hardcoded configurationg, with 0.5% center-spread at
33kHz modulation rate. See datasheet if different configuration is
required.
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 102 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index f6d6c2fe12cd..a534d077f045 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -52,6 +52,10 @@
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
+static bool ub960_enable_sscg;
+module_param_named(enable_sscg, ub960_enable_sscg, bool, 0644);
+MODULE_PARM_DESC(enable_sscg, "Enable SSCG (if available)");
+
#define MHZ(v) ((u32)((v) * HZ_PER_MHZ))
/*
@@ -359,6 +363,7 @@
/* Indirect register blocks */
#define UB960_IND_TARGET_PAT_GEN 0x00
#define UB960_IND_TARGET_RX_ANA(n) (0x01 + (n))
+#define UB960_IND_TARGET_PLL_CTRL 0x05
#define UB960_IND_TARGET_CSI_ANA 0x07
/* UB960_IR_PGEN_*: Indirect Registers for Test Pattern Generator */
@@ -382,6 +387,22 @@
#define UB960_IR_PGEN_VFP 0x0f
#define UB960_IR_PGEN_COLOR(n) (0x10 + (n)) /* n < 15 */
+#define UB960_IR_PLL_DEN_MASH2 0x80
+#define UB960_IR_PLL_DEN_MASH1 0x81
+#define UB960_IR_PLL_DEN_MASH0 0x82
+#define UB960_IR_PLL_NUM_MASH2 0x83
+#define UB960_IR_PLL_NUM_MASH1 0x84
+#define UB960_IR_PLL_NUM_MASH0 0x85
+#define UB960_IR_PLL_NCOUNT1 0x86
+#define UB960_IR_PLL_NCOUNT0 0x87
+#define UB960_IR_PLL_SSCG_CTRL1 0x88
+#define UB960_IR_PLL_MASH_ORDER 0x8a
+#define UB960_IR_PLL_SSCG_CTRL2 0x8b
+#define UB960_IR_PLL_SSCG_CTRL3 0x8c
+#define UB960_IR_PLL_SSCG_CTRL4 0x8d
+#define UB960_IR_PLL_SSCG_CTRL5 0x8e
+#define UB960_IR_PLL_SSCG_MASH_CTRL 0x8f
+
#define UB960_IR_RX_ANA_STROBE_SET_CLK 0x08
#define UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY BIT(3)
#define UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK GENMASK(2, 0)
@@ -2837,6 +2858,81 @@ static int ub960_enable_dfe_lms_ub9702(struct ub960_data *priv,
return 0;
}
+/*
+ * Configures back-channel spread-spectrum clocking with 0.5% center-spread at
+ * 33kHz modulation rate. See datasheet if different configuration is required.
+ */
+static int ub960_enable_sscg_ub9702(struct ub960_data *priv)
+{
+ struct device *dev = &priv->client->dev;
+ int ret = 0;
+
+ /*
+ * The configuration is hard-coded with FPD4 and BC frequency
+ * 47.1875Mbps, so make sure all RX ports are configured with
+ * synchronous clocking mode.
+ */
+ for_each_active_rxport(priv) {
+ if (it.rxport->cdr_mode != RXPORT_CDR_FPD4 ||
+ it.rxport->rx_mode != RXPORT_MODE_CSI2_SYNC) {
+ dev_warn(dev,
+ "rx%u: Not in FPD4 SYNC mode, skipping SSCG\n",
+ it.nport);
+ return 0;
+ }
+ }
+
+ /* Disable MASH */
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL,
+ UB960_IR_PLL_SSCG_MASH_CTRL, 0x40, &ret);
+
+ /* Set MASH denominator */
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_DEN_MASH2,
+ 0x7f, &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_DEN_MASH1,
+ 0xff, &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_DEN_MASH0,
+ 0xf8, &ret);
+
+ /* Set MASH numerator */
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_NUM_MASH2,
+ 0x7f, &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_NUM_MASH1,
+ 0xff, &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_NUM_MASH0,
+ 0xf8, &ret);
+
+ /* Set NCOUNT */
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_NCOUNT1,
+ 0x00, &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL, UB960_IR_PLL_NCOUNT0,
+ 0x96, &ret);
+
+ /* Set MASH order */
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL,
+ UB960_IR_PLL_MASH_ORDER, 0x20, &ret);
+
+ /* Set rampx increment and stop */
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL,
+ UB960_IR_PLL_SSCG_CTRL2, 0xbd, &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL,
+ UB960_IR_PLL_SSCG_CTRL4, 0x73, &ret);
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL,
+ UB960_IR_PLL_SSCG_CTRL5, 0x41, &ret);
+
+ /* Enable SSCG */
+ ub960_ind_update_bits(priv, UB960_IND_TARGET_PLL_CTRL,
+ UB960_IR_PLL_SSCG_CTRL1, BIT(7), BIT(7), &ret);
+
+ /* Enable MASH */
+ ub960_write_ind(priv, UB960_IND_TARGET_PLL_CTRL,
+ UB960_IR_PLL_SSCG_MASH_CTRL, 0x0, &ret);
+
+ dev_dbg(dev, "SSCG enabled\n");
+
+ return ret;
+}
+
static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
{
struct device *dev = &priv->client->dev;
@@ -2860,6 +2956,12 @@ static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
if (ret)
return ret;
+ if (ub960_enable_sscg) {
+ ret = ub960_enable_sscg_ub9702(priv);
+ if (ret)
+ return ret;
+ }
+
for_each_active_rxport_fpd4(priv) {
/* Hold state machine in reset */
ub960_rxport_write(priv, it.nport, UB9702_RR_RX_SM_SEL_2, 0x10,
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (15 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702 Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-11 10:31 ` Krzysztof Kozlowski
2025-01-10 9:14 ` [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 19/19] media: i2c: ds90ub9xx: Set serializer temperature ramp Tomi Valkeinen
18 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen, devicetree, Rob Herring,
Krzysztof Kozlowski
From: Jai Luthra <jai.luthra@ideasonboard.com>
The serializer's I2C address on the FPD-Link bus is usually communicated
to the deserializer once the forward-channel is established. But in some
cases it might be necessary to program the serializer (over the
back-channel) before the forward-channel is established.
This can be used e.g. to correct serializer configuration which
otherwise would prevent the FC to be enabled.
Add a new optional property to specify the I2C address of the
serializer.
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Cc: devicetree@vger.kernel.org
Cc: Rob Herring <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
---
Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
index 0b71e6f911a8..e17b508b6409 100644
--- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
@@ -75,6 +75,13 @@ properties:
address on the I2C bus where the deserializer resides are
forwarded to the serializer.
+ i2c-addr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ The strap I2C address of the serializer. This is used by the
+ deserializer to internally communicate to the serializer over the
+ FPD-Link back-channel.
+
ti,rx-mode:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (16 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
2025-01-15 14:29 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 19/19] media: i2c: ds90ub9xx: Set serializer temperature ramp Tomi Valkeinen
18 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
From: Jai Luthra <jai.luthra@ideasonboard.com>
For DS90UB9702-Q1, it is recommended to configure some serializer
settings over the back-channel before the forward-channel is active.
This can only be done if the serializer's I2C address on the FPD-Link
bus is populated in the device tree node.
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub960.c | 124 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 120 insertions(+), 4 deletions(-)
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index a534d077f045..1ec3c060d4c6 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -248,13 +248,16 @@ MODULE_PARM_DESC(enable_sscg, "Enable SSCG (if available)");
#define UB960_RR_BCC_CONFIG 0x58
#define UB960_RR_BCC_CONFIG_BC_ALWAYS_ON BIT(4)
+#define UB960_RR_BCC_CONFIG_AUTO_ACK_ALL BIT(5)
#define UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH BIT(6)
#define UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK GENMASK(2, 0)
#define UB960_RR_DATAPATH_CTL1 0x59
#define UB960_RR_DATAPATH_CTL2 0x5a
#define UB960_RR_SER_ID 0x5b
+#define UB960_RR_SER_ID_FREEZE_DEVICE_ID BIT(0)
#define UB960_RR_SER_ALIAS_ID 0x5c
+#define UB960_RR_SER_ALIAS_ID_AUTO_ACK BIT(0)
/* For these two register sets: n < UB960_MAX_PORT_ALIASES */
#define UB960_RR_SLAVE_ID(n) (0x5d + (n))
@@ -507,7 +510,9 @@ struct ub960_rxport {
struct fwnode_handle *fwnode;
struct i2c_client *client;
unsigned short alias; /* I2C alias (lower 7 bits) */
+ short addr; /* Local I2C address (lower 7 bits) */
struct ds90ub9xx_platform_data pdata;
+ struct regmap *regmap;
} ser;
enum ub960_rxport_mode rx_mode;
@@ -2005,6 +2010,78 @@ static unsigned long ub960_calc_bc_clk_rate_ub9702(struct ub960_data *priv,
}
}
+static int ub960_rxport_serializer_write(struct ub960_rxport *rxport, u8 reg,
+ u8 val, int *err)
+{
+ struct ub960_data *priv = rxport->priv;
+ struct device *dev = &priv->client->dev;
+ union i2c_smbus_data data;
+ int ret;
+
+ if (err && *err)
+ return *err;
+
+ data.byte = val;
+
+ ret = i2c_smbus_xfer(priv->client->adapter, rxport->ser.alias, 0,
+ I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &data);
+ if (ret)
+ dev_err(dev,
+ "rx%u: cannot write serializer register 0x%02x (%d)!\n",
+ rxport->nport, reg, ret);
+
+ if (ret && err)
+ *err = ret;
+
+ return ret;
+}
+
+static int ub960_rxport_bc_ser_config(struct ub960_rxport *rxport)
+{
+ struct ub960_data *priv = rxport->priv;
+ struct device *dev = &priv->client->dev;
+ u8 nport = rxport->nport;
+ int ret;
+
+ /* Skip port if serializer's address is not known */
+ if (rxport->ser.addr < 0) {
+ dev_dbg(dev,
+ "rx%u: 'i2c-addr' property missing, skip serializer configuration\n",
+ nport);
+ return 0;
+ }
+
+ /*
+ * Note: the code here probably only works for CSI-2 serializers in
+ * sync mode. To support other serializers the BC related configuration
+ * should be done before calling this function.
+ */
+
+ /* Enable I2C passthrough and auto-ack on BC */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH |
+ UB960_RR_BCC_CONFIG_AUTO_ACK_ALL,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH |
+ UB960_RR_BCC_CONFIG_AUTO_ACK_ALL,
+ &ret);
+
+ if (ret)
+ return ret;
+
+ /* Disable BC alternate mode auto detect */
+ ub960_rxport_serializer_write(rxport, 0x4b, 0x02, &ret);
+ /* Decrease link detect timer */
+ ub960_rxport_serializer_write(rxport, 0x49, 0x06, &ret);
+
+ /* Disable I2C passthrough and auto-ack on BC */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH |
+ UB960_RR_BCC_CONFIG_AUTO_ACK_ALL,
+ 0x0, &ret);
+
+ return ret;
+}
+
static int ub960_rxport_add_serializer(struct ub960_data *priv, u8 nport)
{
struct ub960_rxport *rxport = priv->rxports[nport];
@@ -2956,6 +3033,36 @@ static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
if (ret)
return ret;
+ for_each_active_rxport(priv) {
+ if (it.rxport->ser.addr >= 0) {
+ /*
+ * Set serializer's I2C address if set in the dts file,
+ * and freeze it to prevent updates from the FC.
+ */
+ ub960_rxport_write(priv, it.nport, UB960_RR_SER_ID,
+ it.rxport->ser.addr << 1 |
+ UB960_RR_SER_ID_FREEZE_DEVICE_ID,
+ &ret);
+ }
+
+ /* Set serializer I2C alias with auto-ack */
+ ub960_rxport_write(priv, it.nport, UB960_RR_SER_ALIAS_ID,
+ it.rxport->ser.alias << 1 |
+ UB960_RR_SER_ALIAS_ID_AUTO_ACK, &ret);
+
+ if (ret)
+ return ret;
+ }
+
+ for_each_active_rxport(priv) {
+ if (fwnode_device_is_compatible(it.rxport->ser.fwnode,
+ "ti,ds90ub971-q1")) {
+ ret = ub960_rxport_bc_ser_config(it.rxport);
+ if (ret)
+ return ret;
+ }
+ }
+
if (ub960_enable_sscg) {
ret = ub960_enable_sscg_ub9702(priv);
if (ret)
@@ -3090,16 +3197,17 @@ static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
ub960_rxport_write(priv, it.nport, UB960_RR_PORT_ICR_LO, 0x7f,
&ret);
+ /* Clear serializer I2C alias auto-ack */
+ ub960_rxport_update_bits(priv, it.nport, UB960_RR_SER_ALIAS_ID,
+ UB960_RR_SER_ALIAS_ID_AUTO_ACK, 0,
+ &ret);
+
/* Enable I2C_PASS_THROUGH */
ub960_rxport_update_bits(priv, it.nport, UB960_RR_BCC_CONFIG,
UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
&ret);
- /* Enable I2C communication to the serializer via the alias */
- ub960_rxport_write(priv, it.nport, UB960_RR_SER_ALIAS_ID,
- it.rxport->ser.alias << 1, &ret);
-
if (ret)
return ret;
}
@@ -4258,6 +4366,7 @@ ub960_parse_dt_rxport_link_properties(struct ub960_data *priv,
s32 strobe_pos;
u32 eq_level;
u32 ser_i2c_alias;
+ u32 ser_i2c_addr;
int ret;
cdr_mode = RXPORT_CDR_FPD3;
@@ -4363,6 +4472,13 @@ ub960_parse_dt_rxport_link_properties(struct ub960_data *priv,
}
rxport->ser.alias = ser_i2c_alias;
+ ret = fwnode_property_read_u32(link_fwnode, "i2c-addr",
+ &ser_i2c_addr);
+ if (ret)
+ rxport->ser.addr = -EINVAL;
+ else
+ rxport->ser.addr = ser_i2c_addr;
+
rxport->ser.fwnode = fwnode_get_named_child_node(link_fwnode, "serializer");
if (!rxport->ser.fwnode) {
dev_err(dev, "rx%u: missing 'serializer' node\n", nport);
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 19/19] media: i2c: ds90ub9xx: Set serializer temperature ramp
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
` (17 preceding siblings ...)
2025-01-10 9:14 ` [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel Tomi Valkeinen
@ 2025-01-10 9:14 ` Tomi Valkeinen
18 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-10 9:14 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: linux-media, linux-kernel, Devarsh Thakkar, Jai Luthra,
Sakari Ailus, Tomi Valkeinen
From: Jai Luthra <jai.luthra@ideasonboard.com>
For continuous PLL lock, it is recommended to extend the temperature
ramp down range of the DS90UB953-Q1 serializer based on the device's
initial temperature [1].
The serializer's die temperature is reported only to the deserializer
through the sensor status registers, and for UB9702, it is recommended
to set the temperature ramp during the link setup sequence, i.e. before
we even probe the ub953 driver.
Add support to the deserializer driver to configure ub953's temperature
ramp.
[1]: Section 7.3.1.1 - https://www.ti.com/lit/gpn/ds90ub953-q1
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
drivers/media/i2c/ds90ub953.c | 9 ---
drivers/media/i2c/ds90ub960.c | 125 ++++++++++++++++++++++++++++++++++++++++++
include/media/i2c/ds90ub9xx.h | 15 +++++
3 files changed, 140 insertions(+), 9 deletions(-)
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 6c36980e8beb..bba8be031032 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -35,10 +35,6 @@
#define UB953_DEFAULT_CLKOUT_RATE 25000000UL
-#define UB953_REG_RESET_CTL 0x01
-#define UB953_REG_RESET_CTL_DIGITAL_RESET_1 BIT(1)
-#define UB953_REG_RESET_CTL_DIGITAL_RESET_0 BIT(0)
-
#define UB953_REG_GENERAL_CFG 0x02
#define UB953_REG_GENERAL_CFG_CONT_CLK BIT(6)
#define UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT 4
@@ -92,16 +88,11 @@
#define UB953_REG_PKT_HDR_WC_MSB 0x63
#define UB953_REG_CSI_ECC 0x64
-#define UB953_REG_IND_ACC_CTL 0xb0
-#define UB953_REG_IND_ACC_ADDR 0xb1
-#define UB953_REG_IND_ACC_DATA 0xb2
-
#define UB953_REG_FPD3_RX_ID(n) (0xf0 + (n))
#define UB953_REG_FPD3_RX_ID_LEN 6
/* Indirect register blocks */
#define UB953_IND_TARGET_PAT_GEN 0x00
-#define UB953_IND_TARGET_FPD3_TX 0x01
#define UB953_IND_TARGET_DIE_ID 0x02
#define UB953_IND_PGEN_CTL 0x01
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index 1ec3c060d4c6..6daf760f394b 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -2036,6 +2036,110 @@ static int ub960_rxport_serializer_write(struct ub960_rxport *rxport, u8 reg,
return ret;
}
+static int ub960_rxport_serializer_read(struct ub960_rxport *rxport, u8 reg,
+ u8 *val, int *err)
+{
+ struct ub960_data *priv = rxport->priv;
+ struct device *dev = &priv->client->dev;
+ union i2c_smbus_data data = { 0 };
+ int ret;
+
+ if (err && *err)
+ return *err;
+
+ ret = i2c_smbus_xfer(priv->client->adapter, rxport->ser.alias,
+ priv->client->flags, I2C_SMBUS_READ, reg,
+ I2C_SMBUS_BYTE_DATA, &data);
+ if (ret)
+ dev_err(dev,
+ "rx%u: cannot read serializer register 0x%02x (%d)!\n",
+ rxport->nport, reg, ret);
+ else
+ *val = data.byte;
+
+ if (ret && err)
+ *err = ret;
+
+ return ret;
+}
+
+static int ub960_serializer_temp_ramp(struct ub960_rxport *rxport)
+{
+ struct ub960_data *priv = rxport->priv;
+ short temp_dynamic_offset[] = {-1, -1, 0, 0, 1, 1, 1, 3};
+ u8 temp_dynamic_cfg;
+ u8 nport = rxport->nport;
+ u8 ser_temp_code;
+ int ret;
+
+ /* Configure temp ramp only on UB953 */
+ if (!fwnode_device_is_compatible(rxport->ser.fwnode, "ti,ds90ub953-q1"))
+ return 0;
+
+ /* Read current serializer die temperature */
+ ub960_rxport_read(priv, nport, UB960_RR_SENSOR_STS_2, &ser_temp_code,
+ &ret);
+
+ /* Enable I2C passthrough on back channel */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH, &ret);
+
+ if (ret)
+ return ret;
+
+ /* Select indirect page for analog regs on the serializer */
+ ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_CTL,
+ UB953_IND_TARGET_ANALOG << 2, &ret);
+
+ /* Set temperature ramp dynamic and static config */
+ ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_ADDR,
+ UB953_IND_ANA_TEMP_DYNAMIC_CFG, &ret);
+ ub960_rxport_serializer_read(rxport, UB953_REG_IND_ACC_DATA,
+ &temp_dynamic_cfg, &ret);
+
+ if (ret)
+ return ret;
+
+ temp_dynamic_cfg |= UB953_IND_ANA_TEMP_DYNAMIC_CFG_OV;
+ temp_dynamic_cfg += temp_dynamic_offset[ser_temp_code];
+
+ /* Update temp static config */
+ ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_ADDR,
+ UB953_IND_ANA_TEMP_STATIC_CFG, &ret);
+ ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_DATA,
+ UB953_IND_ANA_TEMP_STATIC_CFG_MASK, &ret);
+
+ /* Update temperature ramp dynamic config */
+ ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_ADDR,
+ UB953_IND_ANA_TEMP_DYNAMIC_CFG, &ret);
+
+ /* Enable I2C auto ack on BC before we set dynamic cfg and reset */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_AUTO_ACK_ALL,
+ UB960_RR_BCC_CONFIG_AUTO_ACK_ALL, &ret);
+
+ ub960_rxport_serializer_write(rxport, UB953_REG_IND_ACC_DATA,
+ temp_dynamic_cfg, &ret);
+
+ if (ret)
+ return ret;
+
+ /* Soft reset to apply PLL updates */
+ ub960_rxport_serializer_write(rxport, UB953_REG_RESET_CTL,
+ UB953_REG_RESET_CTL_DIGITAL_RESET_0,
+ &ret);
+ msleep(20);
+
+ /* Disable I2C passthrough and auto-ack on BC */
+ ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH |
+ UB960_RR_BCC_CONFIG_AUTO_ACK_ALL,
+ 0x0, &ret);
+
+ return ret;
+}
+
static int ub960_rxport_bc_ser_config(struct ub960_rxport *rxport)
{
struct ub960_data *priv = rxport->priv;
@@ -2415,6 +2519,20 @@ static int ub960_init_rx_ports_ub960(struct ub960_data *priv)
return ret;
}
+ /* Set temperature ramp on serializer */
+ for_each_active_rxport(priv) {
+ ret = ub960_serializer_temp_ramp(it.rxport);
+ if (ret)
+ return ret;
+
+ ub960_rxport_update_bits(priv, it.nport, UB960_RR_BCC_CONFIG,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
+ UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
+ &ret);
+ if (ret)
+ return ret;
+ }
+
/*
* Clear any errors caused by switching the RX port settings while
* probing.
@@ -3171,6 +3289,13 @@ static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
/* Wait time for stable lock */
fsleep(15000);
+ /* Set temperature ramp on serializer */
+ for_each_active_rxport(priv) {
+ ret = ub960_serializer_temp_ramp(it.rxport);
+ if (ret)
+ return ret;
+ }
+
for_each_active_rxport_fpd4(priv) {
ret = ub960_enable_dfe_lms_ub9702(priv, it.nport);
if (ret)
diff --git a/include/media/i2c/ds90ub9xx.h b/include/media/i2c/ds90ub9xx.h
index 0245198469ec..d803af07cabc 100644
--- a/include/media/i2c/ds90ub9xx.h
+++ b/include/media/i2c/ds90ub9xx.h
@@ -5,6 +5,21 @@
#include <linux/types.h>
+#define UB953_REG_RESET_CTL 0x01
+#define UB953_REG_RESET_CTL_DIGITAL_RESET_1 BIT(1)
+#define UB953_REG_RESET_CTL_DIGITAL_RESET_0 BIT(0)
+
+#define UB953_REG_IND_ACC_CTL 0xb0
+#define UB953_REG_IND_ACC_ADDR 0xb1
+#define UB953_REG_IND_ACC_DATA 0xb2
+
+#define UB953_IND_TARGET_ANALOG 0x01
+
+#define UB953_IND_ANA_TEMP_DYNAMIC_CFG 0x4b
+#define UB953_IND_ANA_TEMP_DYNAMIC_CFG_OV BIT(5)
+#define UB953_IND_ANA_TEMP_STATIC_CFG 0x4c
+#define UB953_IND_ANA_TEMP_STATIC_CFG_MASK GENMASK(6, 4)
+
struct i2c_atr;
/**
--
2.43.0
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-10 9:14 ` [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property Tomi Valkeinen
@ 2025-01-11 10:31 ` Krzysztof Kozlowski
2025-01-14 11:50 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-11 10:31 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra, Sakari Ailus, devicetree,
Rob Herring, Krzysztof Kozlowski
On Fri, Jan 10, 2025 at 11:14:17AM +0200, Tomi Valkeinen wrote:
> From: Jai Luthra <jai.luthra@ideasonboard.com>
>
> The serializer's I2C address on the FPD-Link bus is usually communicated
> to the deserializer once the forward-channel is established. But in some
> cases it might be necessary to program the serializer (over the
> back-channel) before the forward-channel is established.
>
> This can be used e.g. to correct serializer configuration which
> otherwise would prevent the FC to be enabled.
>
> Add a new optional property to specify the I2C address of the
> serializer.
>
> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> Cc: devicetree@vger.kernel.org
> Cc: Rob Herring <robh@kernel.org>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Why only these folks? Why not all of the maintainers?
Anyway, Please drop the autogenerated scripts/get_maintainer.pl CC-entries from
commit msg. There is no single need to store automated output of
get_maintainers.pl in the git log. It can be easily re-created at any
given time, thus its presence in the git history is redundant and
obfuscates the log.
If you need it for your own patch management purposes, keep it under the
--- separator.
> ---
> Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
> index 0b71e6f911a8..e17b508b6409 100644
> --- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
> +++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
> @@ -75,6 +75,13 @@ properties:
> address on the I2C bus where the deserializer resides are
> forwarded to the serializer.
>
> + i2c-addr:
> + $ref: /schemas/types.yaml#/definitions/uint32
Why isn't this part of reg, if that's the same device? If that is not
the same device, you are not expected to encode addresses of other
devices in this device. Address of 'foo' is not a property of device
'bar'. Phandles or graphs express relationships between devices.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-11 10:31 ` Krzysztof Kozlowski
@ 2025-01-14 11:50 ` Tomi Valkeinen
2025-01-15 8:40 ` Krzysztof Kozlowski
2025-01-15 15:53 ` Konstantin Ryabitsev
0 siblings, 2 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-14 11:50 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra, Sakari Ailus, devicetree,
Rob Herring, Krzysztof Kozlowski
Hi,
On 11/01/2025 12:31, Krzysztof Kozlowski wrote:
> On Fri, Jan 10, 2025 at 11:14:17AM +0200, Tomi Valkeinen wrote:
>> From: Jai Luthra <jai.luthra@ideasonboard.com>
>>
>> The serializer's I2C address on the FPD-Link bus is usually communicated
>> to the deserializer once the forward-channel is established. But in some
>> cases it might be necessary to program the serializer (over the
>> back-channel) before the forward-channel is established.
>>
>> This can be used e.g. to correct serializer configuration which
>> otherwise would prevent the FC to be enabled.
>>
>> Add a new optional property to specify the I2C address of the
>> serializer.
>>
>> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> Cc: devicetree@vger.kernel.org
>> Cc: Rob Herring <robh@kernel.org>
>> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
>
> Why only these folks? Why not all of the maintainers?
The whole series is sent to the media list and maintainers. I thought
this single patch doesn't warrant sending the whole series to DT list
and maintainers, so I cc'd them here.
> Anyway, Please drop the autogenerated scripts/get_maintainer.pl CC-entries from
> commit msg. There is no single need to store automated output of
> get_maintainers.pl in the git log. It can be easily re-created at any
> given time, thus its presence in the git history is redundant and
> obfuscates the log.
I think that's a valid point.
> If you need it for your own patch management purposes, keep it under the
> --- separator.
I'm using b4. I don't know how to do that with b4, but I'll look into it.
>> ---
>> Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml | 7 +++++++
>> 1 file changed, 7 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
>> index 0b71e6f911a8..e17b508b6409 100644
>> --- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
>> +++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
>> @@ -75,6 +75,13 @@ properties:
>> address on the I2C bus where the deserializer resides are
>> forwarded to the serializer.
>>
>> + i2c-addr:
>> + $ref: /schemas/types.yaml#/definitions/uint32
>
> Why isn't this part of reg, if that's the same device? If that is not
> the same device, you are not expected to encode addresses of other
> devices in this device. Address of 'foo' is not a property of device
> 'bar'. Phandles or graphs express relationships between devices.
With the understanding of the HW I have right now, I would have added
the i2c address as the address of the serializer node, with reg
property. I would probably also do a few other changes to the bindings...
But as we already have the current bindings, adding the i2c-addr felt
like an easy way to keep backwards compatibility and add the address of
the serializer.
However, thinking about this more, maybe we could just go and add the
address of the serializer with reg, in the ds90ub953 bindings. It's the
ub960 driver that needs the address, but it shouldn't be much trouble to
get that from the ub953's data.
But we need to keep the address optional to keep the backwards
compatibility. If it's not defined, the ub960 will automatically receive
the serializer's address when the link goes up (as it is handled now).
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-14 11:50 ` Tomi Valkeinen
@ 2025-01-15 8:40 ` Krzysztof Kozlowski
2025-01-15 17:19 ` Tomi Valkeinen
2025-01-15 15:53 ` Konstantin Ryabitsev
1 sibling, 1 reply; 44+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-15 8:40 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra, Sakari Ailus, devicetree,
Rob Herring, Krzysztof Kozlowski
On 14/01/2025 12:50, Tomi Valkeinen wrote:
> Hi,
>
> On 11/01/2025 12:31, Krzysztof Kozlowski wrote:
>> On Fri, Jan 10, 2025 at 11:14:17AM +0200, Tomi Valkeinen wrote:
>>> From: Jai Luthra <jai.luthra@ideasonboard.com>
>>>
>>> The serializer's I2C address on the FPD-Link bus is usually communicated
>>> to the deserializer once the forward-channel is established. But in some
>>> cases it might be necessary to program the serializer (over the
>>> back-channel) before the forward-channel is established.
>>>
>>> This can be used e.g. to correct serializer configuration which
>>> otherwise would prevent the FC to be enabled.
>>>
>>> Add a new optional property to specify the I2C address of the
>>> serializer.
>>>
>>> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>>> Cc: devicetree@vger.kernel.org
>>> Cc: Rob Herring <robh@kernel.org>
>>> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
>>
>> Why only these folks? Why not all of the maintainers?
>
> The whole series is sent to the media list and maintainers. I thought
> this single patch doesn't warrant sending the whole series to DT list
> and maintainers, so I cc'd them here.
I was wondering why only some of the DT maintainers, not all? My usual
assumption is: you are not using get_maintainers.pl or you are working
on an old kernel.
>
>> Anyway, Please drop the autogenerated scripts/get_maintainer.pl CC-entries from
>> commit msg. There is no single need to store automated output of
>> get_maintainers.pl in the git log. It can be easily re-created at any
>> given time, thus its presence in the git history is redundant and
>> obfuscates the log.
>
> I think that's a valid point.
>
>> If you need it for your own patch management purposes, keep it under the
>> --- separator.
>
> I'm using b4. I don't know how to do that with b4, but I'll look into it.
>
>>> ---
>>> Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml | 7 +++++++
>>> 1 file changed, 7 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
>>> index 0b71e6f911a8..e17b508b6409 100644
>>> --- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
>>> +++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
>>> @@ -75,6 +75,13 @@ properties:
>>> address on the I2C bus where the deserializer resides are
>>> forwarded to the serializer.
>>>
>>> + i2c-addr:
>>> + $ref: /schemas/types.yaml#/definitions/uint32
>>
>> Why isn't this part of reg, if that's the same device? If that is not
>> the same device, you are not expected to encode addresses of other
>> devices in this device. Address of 'foo' is not a property of device
>> 'bar'. Phandles or graphs express relationships between devices.
>
> With the understanding of the HW I have right now, I would have added
> the i2c address as the address of the serializer node, with reg
> property. I would probably also do a few other changes to the bindings...
>
> But as we already have the current bindings, adding the i2c-addr felt
> like an easy way to keep backwards compatibility and add the address of
> the serializer.
>
> However, thinking about this more, maybe we could just go and add the
> address of the serializer with reg, in the ds90ub953 bindings. It's the
> ub960 driver that needs the address, but it shouldn't be much trouble to
> get that from the ub953's data.
>
> But we need to keep the address optional to keep the backwards
> compatibility. If it's not defined, the ub960 will automatically receive
> the serializer's address when the link goes up (as it is handled now).
The 'reg' can grow and should not cause ABI issues, because
implementations should just ignore additional entry.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer
2025-01-10 9:14 ` [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer Tomi Valkeinen
@ 2025-01-15 14:17 ` Sakari Ailus
2025-01-24 13:19 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Sakari Ailus @ 2025-01-15 14:17 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Fri, Jan 10, 2025 at 11:14:07AM +0200, Tomi Valkeinen wrote:
> From: Jai Luthra <jai.luthra@ideasonboard.com>
>
> On the I2C bus for remote clients (sensors), by default the watchdog
> timer expires in 1s. To allow for a quicker system bring-up time, TI
> recommends to speed it up to 50us [1].
>
> [1]: Section 7.3.1.1 - https://www.ti.com/lit/gpn/ds90ub953-q1
>
> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> ---
> drivers/media/i2c/ds90ub953.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
> index 99a4852b9381..6c36980e8beb 100644
> --- a/drivers/media/i2c/ds90ub953.c
> +++ b/drivers/media/i2c/ds90ub953.c
> @@ -54,6 +54,10 @@
> #define UB953_REG_CLKOUT_CTRL0 0x06
> #define UB953_REG_CLKOUT_CTRL1 0x07
>
> +#define UB953_REG_I2C_CONTROL2 0x0a
> +#define UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT 4
> +#define UB953_REG_I2C_CONTROL2_BUS_SPEEDUP BIT(1)
> +
> #define UB953_REG_SCL_HIGH_TIME 0x0b
> #define UB953_REG_SCL_LOW_TIME 0x0c
>
> @@ -1320,6 +1324,13 @@ static int ub953_hw_init(struct ub953_data *priv)
> if (ret)
> return ret;
>
> + v = 0;
> + v |= 1 << UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT;
BIT()? Or at least 1U <<< ...;.
> + v |= UB953_REG_I2C_CONTROL2_BUS_SPEEDUP;
> + ret = ub953_write(priv, UB953_REG_I2C_CONTROL2, v, NULL);
I'd just do this without a temporary variable. If you prefer to keep it, do
assign the first calculated value there first and remove the assignment to
zero.
> + if (ret)
> + return ret;
No need for this.
> +
> return 0;
> }
>
>
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support
2025-01-10 9:14 ` [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support Tomi Valkeinen
@ 2025-01-15 14:23 ` Sakari Ailus
2025-01-24 13:34 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Sakari Ailus @ 2025-01-15 14:23 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Fri, Jan 10, 2025 at 11:14:12AM +0200, Tomi Valkeinen wrote:
> The driver does a lot of iteration over the RX ports with for loops. In
> most cases the driver will skip unused RX ports. Also, in the future
> patches the FPD-Link IV support will be refreshed with TI's latest init
> sequences which involves a lot of additional iterations over the RX
> ports, often only for FPD-Link IV ports.
>
> To make the iteration simpler and to make it clearer what we're
> iterating over (all or only-active, all or only-fpd4), add macros and
> support functions for iterating the RX ports. Use the macros in the
> driver, replacing the for loops.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> ---
> drivers/media/i2c/ds90ub960.c | 260 ++++++++++++++++++++++--------------------
> 1 file changed, 135 insertions(+), 125 deletions(-)
>
> diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
> index bca858172942..02e22ae813fa 100644
> --- a/drivers/media/i2c/ds90ub960.c
> +++ b/drivers/media/i2c/ds90ub960.c
> @@ -649,6 +649,63 @@ static const struct ub960_format_info *ub960_find_format(u32 code)
> return NULL;
> }
>
> +struct ub960_rxport_iter {
> + unsigned int nport;
> + struct ub960_rxport *rxport;
> +};
> +
> +enum ub960_iter_flags {
> + UB960_ITER_ACTIVE_ONLY = BIT(0),
> + UB960_ITER_FPD4_ONLY = BIT(1),
> +};
> +
> +static struct ub960_rxport_iter ub960_iter_rxport(struct ub960_data *priv,
> + struct ub960_rxport_iter it,
> + enum ub960_iter_flags flags)
> +{
> + for (; it.nport < priv->hw_data->num_rxports; it.nport++) {
> + it.rxport = priv->rxports[it.nport];
> +
> + if ((flags & UB960_ITER_ACTIVE_ONLY) && !it.rxport)
> + continue;
> +
> + if ((flags & UB960_ITER_FPD4_ONLY) &&
> + it.rxport->cdr_mode != RXPORT_CDR_FPD4)
> + continue;
> +
> + return it;
> + }
> +
> + it.rxport = NULL;
> +
> + return it;
> +}
> +
> +#define for_each_rxport(priv) \
it should be also an argument to the macro as it's visible outside it.
And wouldn't it be reasonable to use a pointer instead for the purpsoe?
> + for (struct ub960_rxport_iter it = \
> + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
> + 0); \
> + it.nport < (priv)->hw_data->num_rxports; \
> + it.nport++, it = ub960_iter_rxport(priv, it, 0))
> +
> +#define for_each_active_rxport(priv) \
> + for (struct ub960_rxport_iter it = \
> + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
> + UB960_ITER_ACTIVE_ONLY); \
> + it.nport < (priv)->hw_data->num_rxports; \
> + it.nport++, it = ub960_iter_rxport(priv, it, \
> + UB960_ITER_ACTIVE_ONLY))
> +
> +#define for_each_active_rxport_fpd4(priv) \
> + for (struct ub960_rxport_iter it = \
> + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
> + UB960_ITER_ACTIVE_ONLY | \
> + UB960_ITER_FPD4_ONLY); \
> + it.nport < (priv)->hw_data->num_rxports; \
> + it.nport++, it = ub960_iter_rxport(priv, it, \
> + UB960_ITER_ACTIVE_ONLY | \
> + UB960_ITER_FPD4_ONLY))
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 13/19] media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports()
2025-01-10 9:14 ` [PATCH 13/19] media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports() Tomi Valkeinen
@ 2025-01-15 14:25 ` Sakari Ailus
2025-01-24 13:23 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Sakari Ailus @ 2025-01-15 14:25 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Fri, Jan 10, 2025 at 11:14:13AM +0200, Tomi Valkeinen wrote:
> We have some code in probe() which is related to RX port initialization,
> and should be in ub960_init_rx_ports(). Move the code there.
>
> We also move ub960_reset() so that it is accessible from
> ub960_init_rx_ports().
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> ---
> drivers/media/i2c/ds90ub960.c | 115 ++++++++++++++++++++++--------------------
> 1 file changed, 59 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
> index 02e22ae813fa..cc944d737524 100644
> --- a/drivers/media/i2c/ds90ub960.c
> +++ b/drivers/media/i2c/ds90ub960.c
> @@ -1225,6 +1225,33 @@ static int ub960_ind_update_bits(struct ub960_data *priv, u8 block, u8 reg,
> return ret;
> }
>
> +static int ub960_reset(struct ub960_data *priv, bool reset_regs)
> +{
> + struct device *dev = &priv->client->dev;
> + unsigned int v;
> + int ret;
> + u8 bit;
> +
> + bit = reset_regs ? UB960_SR_RESET_DIGITAL_RESET1 :
> + UB960_SR_RESET_DIGITAL_RESET0;
> +
> + ret = ub960_write(priv, UB960_SR_RESET, bit, NULL);
> + if (ret)
> + return ret;
Not related to the patch but if you're serialising things below, why aren't
you doing that here?
> +
> + mutex_lock(&priv->reg_lock);
> +
> + ret = regmap_read_poll_timeout(priv->regmap, UB960_SR_RESET, v,
> + (v & bit) == 0, 2000, 100000);
> +
> + mutex_unlock(&priv->reg_lock);
> +
> + if (ret)
> + dev_err(dev, "reset failed: %d\n", ret);
> +
> + return ret;
> +}
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702
2025-01-10 9:14 ` [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702 Tomi Valkeinen
@ 2025-01-15 14:26 ` Sakari Ailus
2025-01-15 16:04 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Sakari Ailus @ 2025-01-15 14:26 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Fri, Jan 10, 2025 at 11:14:16AM +0200, Tomi Valkeinen wrote:
> From: Jai Luthra <jai.luthra@ideasonboard.com>
>
> UB9702 supports spread-spectrum clock generation for the back-channel
> clock, which is futher used by serializers in synchronous mode to
> generate the forward-channel clock, which can help reduce peak EMI
> energy. The SSCG is common to all RX ports, so it can only be used if
> all the ports are in the same mode.
>
> Add basic support for SSCG by adding a module parameter to enable the
> SSCG. The SSCG uses hardcoded configurationg, with 0.5% center-spread at
> 33kHz modulation rate. See datasheet if different configuration is
> required.
>
> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> ---
> drivers/media/i2c/ds90ub960.c | 102 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 102 insertions(+)
>
> diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
> index f6d6c2fe12cd..a534d077f045 100644
> --- a/drivers/media/i2c/ds90ub960.c
> +++ b/drivers/media/i2c/ds90ub960.c
> @@ -52,6 +52,10 @@
> #include <media/v4l2-fwnode.h>
> #include <media/v4l2-subdev.h>
>
> +static bool ub960_enable_sscg;
> +module_param_named(enable_sscg, ub960_enable_sscg, bool, 0644);
> +MODULE_PARM_DESC(enable_sscg, "Enable SSCG (if available)");
Shouldn't this come from DT instead?
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel
2025-01-10 9:14 ` [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel Tomi Valkeinen
@ 2025-01-15 14:29 ` Sakari Ailus
2025-01-24 13:29 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Sakari Ailus @ 2025-01-15 14:29 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Fri, Jan 10, 2025 at 11:14:18AM +0200, Tomi Valkeinen wrote:
> @@ -2956,6 +3033,36 @@ static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
> if (ret)
> return ret;
>
> + for_each_active_rxport(priv) {
> + if (it.rxport->ser.addr >= 0) {
> + /*
> + * Set serializer's I2C address if set in the dts file,
> + * and freeze it to prevent updates from the FC.
> + */
> + ub960_rxport_write(priv, it.nport, UB960_RR_SER_ID,
> + it.rxport->ser.addr << 1 |
> + UB960_RR_SER_ID_FREEZE_DEVICE_ID,
> + &ret);
> + }
> +
> + /* Set serializer I2C alias with auto-ack */
> + ub960_rxport_write(priv, it.nport, UB960_RR_SER_ALIAS_ID,
> + it.rxport->ser.alias << 1 |
> + UB960_RR_SER_ALIAS_ID_AUTO_ACK, &ret);
> +
> + if (ret)
> + return ret;
> + }
> +
> + for_each_active_rxport(priv) {
> + if (fwnode_device_is_compatible(it.rxport->ser.fwnode,
> + "ti,ds90ub971-q1")) {
I guess one instance is fine but consider using match data instead.
> + ret = ub960_rxport_bc_ser_config(it.rxport);
> + if (ret)
> + return ret;
> + }
> + }
> +
> if (ub960_enable_sscg) {
> ret = ub960_enable_sscg_ub9702(priv);
> if (ret)
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-14 11:50 ` Tomi Valkeinen
2025-01-15 8:40 ` Krzysztof Kozlowski
@ 2025-01-15 15:53 ` Konstantin Ryabitsev
2025-01-15 16:09 ` Tomi Valkeinen
1 sibling, 1 reply; 44+ messages in thread
From: Konstantin Ryabitsev @ 2025-01-15 15:53 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Krzysztof Kozlowski, Mauro Carvalho Chehab, linux-media,
linux-kernel, Devarsh Thakkar, Jai Luthra, Sakari Ailus,
devicetree, Rob Herring, Krzysztof Kozlowski
On Tue, Jan 14, 2025 at 01:50:08PM +0200, Tomi Valkeinen wrote:
> > If you need it for your own patch management purposes, keep it under the
> > --- separator.
>
> I'm using b4. I don't know how to do that with b4, but I'll look into it.
You just put them under --- in your git commit message and b4 will preserve
it as-is when it renders the email.
-K
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702
2025-01-15 14:26 ` Sakari Ailus
@ 2025-01-15 16:04 ` Tomi Valkeinen
2025-01-16 9:58 ` Sakari Ailus
0 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-15 16:04 UTC (permalink / raw)
To: Sakari Ailus
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
On 15/01/2025 16:26, Sakari Ailus wrote:
> Moi,
>
> On Fri, Jan 10, 2025 at 11:14:16AM +0200, Tomi Valkeinen wrote:
>> From: Jai Luthra <jai.luthra@ideasonboard.com>
>>
>> UB9702 supports spread-spectrum clock generation for the back-channel
>> clock, which is futher used by serializers in synchronous mode to
>> generate the forward-channel clock, which can help reduce peak EMI
>> energy. The SSCG is common to all RX ports, so it can only be used if
>> all the ports are in the same mode.
>>
>> Add basic support for SSCG by adding a module parameter to enable the
>> SSCG. The SSCG uses hardcoded configurationg, with 0.5% center-spread at
>> 33kHz modulation rate. See datasheet if different configuration is
>> required.
>>
>> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> ---
>> drivers/media/i2c/ds90ub960.c | 102 ++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 102 insertions(+)
>>
>> diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
>> index f6d6c2fe12cd..a534d077f045 100644
>> --- a/drivers/media/i2c/ds90ub960.c
>> +++ b/drivers/media/i2c/ds90ub960.c
>> @@ -52,6 +52,10 @@
>> #include <media/v4l2-fwnode.h>
>> #include <media/v4l2-subdev.h>
>>
>> +static bool ub960_enable_sscg;
>> +module_param_named(enable_sscg, ub960_enable_sscg, bool, 0644);
>> +MODULE_PARM_DESC(enable_sscg, "Enable SSCG (if available)");
>
> Shouldn't this come from DT instead?
SSCG is an option to use or not to use, based on what the user wants. DT
should describe the hardware.
A module parameter is bad for this, though, as it's then used for all
ub960 devices... But I'm not sure what other options we have. We need to
have it at probe time.
Probably the whole driver could be changed to not connect the
serializers at probe, but instead would offer a set of userspace APIs to
enable/disable SSCG, and to enable the links. But that brings in its own
set of problems, as the links are used for i2c communication to the ser
and sensor, not to mention new userspace APIs which always complicates
things.
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-15 15:53 ` Konstantin Ryabitsev
@ 2025-01-15 16:09 ` Tomi Valkeinen
2025-01-15 16:46 ` Krzysztof Kozlowski
0 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-15 16:09 UTC (permalink / raw)
To: Konstantin Ryabitsev
Cc: Krzysztof Kozlowski, Mauro Carvalho Chehab, linux-media,
linux-kernel, Devarsh Thakkar, Jai Luthra, Sakari Ailus,
devicetree, Rob Herring, Krzysztof Kozlowski
Hi,
On 15/01/2025 17:53, Konstantin Ryabitsev wrote:
> On Tue, Jan 14, 2025 at 01:50:08PM +0200, Tomi Valkeinen wrote:
>>> If you need it for your own patch management purposes, keep it under the
>>> --- separator.
>>
>> I'm using b4. I don't know how to do that with b4, but I'll look into it.
>
> You just put them under --- in your git commit message and b4 will preserve
> it as-is when it renders the email.
Alright, thanks!
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-15 16:09 ` Tomi Valkeinen
@ 2025-01-15 16:46 ` Krzysztof Kozlowski
2025-01-15 17:14 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-15 16:46 UTC (permalink / raw)
To: Tomi Valkeinen, Konstantin Ryabitsev
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra, Sakari Ailus, devicetree,
Rob Herring, Krzysztof Kozlowski
On 15/01/2025 17:09, Tomi Valkeinen wrote:
> Hi,
>
> On 15/01/2025 17:53, Konstantin Ryabitsev wrote:
>> On Tue, Jan 14, 2025 at 01:50:08PM +0200, Tomi Valkeinen wrote:
>>>> If you need it for your own patch management purposes, keep it under the
>>>> --- separator.
>>>
>>> I'm using b4. I don't know how to do that with b4, but I'll look into it.
>>
>> You just put them under --- in your git commit message and b4 will preserve
>> it as-is when it renders the email.
>
> Alright, thanks!
>
That's exactly what I wrote:
"If you need it for your own patch management purposes, keep it under
the --- separator."
It's nothing related to b4 - it comes from standard git commit and git
send-email.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-15 16:46 ` Krzysztof Kozlowski
@ 2025-01-15 17:14 ` Tomi Valkeinen
0 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-15 17:14 UTC (permalink / raw)
To: Krzysztof Kozlowski, Konstantin Ryabitsev
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra, Sakari Ailus, devicetree,
Rob Herring, Krzysztof Kozlowski
Hi,
On 15/01/2025 18:46, Krzysztof Kozlowski wrote:
> On 15/01/2025 17:09, Tomi Valkeinen wrote:
>> Hi,
>>
>> On 15/01/2025 17:53, Konstantin Ryabitsev wrote:
>>> On Tue, Jan 14, 2025 at 01:50:08PM +0200, Tomi Valkeinen wrote:
>>>>> If you need it for your own patch management purposes, keep it under the
>>>>> --- separator.
>>>>
>>>> I'm using b4. I don't know how to do that with b4, but I'll look into it.
>>>
>>> You just put them under --- in your git commit message and b4 will preserve
>>> it as-is when it renders the email.
>>
>> Alright, thanks!
>>
> That's exactly what I wrote:
>
> "If you need it for your own patch management purposes, keep it under
> the --- separator."
>
> It's nothing related to b4 - it comes from standard git commit and git
> send-email.
Yep. For some odd reason I was under the impression that I can't have
that in a commit message in my local branch, but would have to add the
---, and the lines after that, to the mail file. And so, as b4 handles
creating and sending the mails, I wasn't sure how to get in between.
This does make my life a bit easier, so I'm glad this topic came up =).
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-15 8:40 ` Krzysztof Kozlowski
@ 2025-01-15 17:19 ` Tomi Valkeinen
2025-01-15 20:25 ` Krzysztof Kozlowski
0 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-15 17:19 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra, Sakari Ailus, devicetree,
Rob Herring, Krzysztof Kozlowski
Hi,
On 15/01/2025 10:40, Krzysztof Kozlowski wrote:
>>> Why only these folks? Why not all of the maintainers?
>>
>> The whole series is sent to the media list and maintainers. I thought
>> this single patch doesn't warrant sending the whole series to DT list
>> and maintainers, so I cc'd them here.
>
>
> I was wondering why only some of the DT maintainers, not all? My usual
> assumption is: you are not using get_maintainers.pl or you are working
> on an old kernel.
It's simpler than that: a copy-paste mistake. I'm not sure how I managed
to miss Conor there.
Any preference on cc'ing the DT maintainers and the dt-list only for
this patch (I'll use --- this time, I promise!), or just sending the
whole series also to DT people?
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property
2025-01-15 17:19 ` Tomi Valkeinen
@ 2025-01-15 20:25 ` Krzysztof Kozlowski
0 siblings, 0 replies; 44+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-15 20:25 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra, Sakari Ailus, devicetree,
Rob Herring, Krzysztof Kozlowski
On 15/01/2025 18:19, Tomi Valkeinen wrote:
> Hi,
>
> On 15/01/2025 10:40, Krzysztof Kozlowski wrote:
>
>>>> Why only these folks? Why not all of the maintainers?
>>>
>>> The whole series is sent to the media list and maintainers. I thought
>>> this single patch doesn't warrant sending the whole series to DT list
>>> and maintainers, so I cc'd them here.
>>
>>
>> I was wondering why only some of the DT maintainers, not all? My usual
>> assumption is: you are not using get_maintainers.pl or you are working
>> on an old kernel.
>
> It's simpler than that: a copy-paste mistake. I'm not sure how I managed
> to miss Conor there.
>
> Any preference on cc'ing the DT maintainers and the dt-list only for
> this patch (I'll use --- this time, I promise!), or just sending the
> whole series also to DT people?
I think only Rob uses DT list entirely. I use both - DT list and being
directly CC-ed on emails, and I think Conor relies on being Cc-ed
directly. IOW, just cc all maintainers + DT list. Unless you touch
multiple subsystems, there is rarely a point to strip get_maintainers.pl
output from maintainers/reviewers/submitters. Do not confuse in skipping
non-maintainers pointed by Git-fallback (not applicable to b4, I think),
because these should be used carefully.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702
2025-01-15 16:04 ` Tomi Valkeinen
@ 2025-01-16 9:58 ` Sakari Ailus
2025-01-16 10:05 ` Tomi Valkeinen
0 siblings, 1 reply; 44+ messages in thread
From: Sakari Ailus @ 2025-01-16 9:58 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Wed, Jan 15, 2025 at 06:04:40PM +0200, Tomi Valkeinen wrote:
> On 15/01/2025 16:26, Sakari Ailus wrote:
> > Moi,
> >
> > On Fri, Jan 10, 2025 at 11:14:16AM +0200, Tomi Valkeinen wrote:
> > > From: Jai Luthra <jai.luthra@ideasonboard.com>
> > >
> > > UB9702 supports spread-spectrum clock generation for the back-channel
> > > clock, which is futher used by serializers in synchronous mode to
> > > generate the forward-channel clock, which can help reduce peak EMI
> > > energy. The SSCG is common to all RX ports, so it can only be used if
> > > all the ports are in the same mode.
> > >
> > > Add basic support for SSCG by adding a module parameter to enable the
> > > SSCG. The SSCG uses hardcoded configurationg, with 0.5% center-spread at
> > > 33kHz modulation rate. See datasheet if different configuration is
> > > required.
> > >
> > > Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
> > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> > > ---
> > > drivers/media/i2c/ds90ub960.c | 102 ++++++++++++++++++++++++++++++++++++++++++
> > > 1 file changed, 102 insertions(+)
> > >
> > > diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
> > > index f6d6c2fe12cd..a534d077f045 100644
> > > --- a/drivers/media/i2c/ds90ub960.c
> > > +++ b/drivers/media/i2c/ds90ub960.c
> > > @@ -52,6 +52,10 @@
> > > #include <media/v4l2-fwnode.h>
> > > #include <media/v4l2-subdev.h>
> > > +static bool ub960_enable_sscg;
> > > +module_param_named(enable_sscg, ub960_enable_sscg, bool, 0644);
> > > +MODULE_PARM_DESC(enable_sscg, "Enable SSCG (if available)");
> >
> > Shouldn't this come from DT instead?
>
> SSCG is an option to use or not to use, based on what the user wants. DT
> should describe the hardware.
>
> A module parameter is bad for this, though, as it's then used for all ub960
> devices... But I'm not sure what other options we have. We need to have it
> at probe time.
>
> Probably the whole driver could be changed to not connect the serializers at
> probe, but instead would offer a set of userspace APIs to enable/disable
> SSCG, and to enable the links. But that brings in its own set of problems,
> as the links are used for i2c communication to the ser and sensor, not to
> mention new userspace APIs which always complicates things.
Typically determining whether you need spread spectrum signalling is highly
specific to the board. I wonder if this topic has been discussed (and
possibly somehow resolved) for other subsystems. CSI-2 appears to allow for
spread spectrum clocks but I don't think I've seen that implemeted
anywhere, scrambling may be more popular (but also that is right now
unsupported but could be supported, probably this would be best to consider
in conjunction with other CSI-2 parameters).
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702
2025-01-16 9:58 ` Sakari Ailus
@ 2025-01-16 10:05 ` Tomi Valkeinen
0 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-16 10:05 UTC (permalink / raw)
To: Sakari Ailus
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Hi,
On 16/01/2025 11:58, Sakari Ailus wrote:
> Moi,
>
> On Wed, Jan 15, 2025 at 06:04:40PM +0200, Tomi Valkeinen wrote:
>> On 15/01/2025 16:26, Sakari Ailus wrote:
>>> Moi,
>>>
>>> On Fri, Jan 10, 2025 at 11:14:16AM +0200, Tomi Valkeinen wrote:
>>>> From: Jai Luthra <jai.luthra@ideasonboard.com>
>>>>
>>>> UB9702 supports spread-spectrum clock generation for the back-channel
>>>> clock, which is futher used by serializers in synchronous mode to
>>>> generate the forward-channel clock, which can help reduce peak EMI
>>>> energy. The SSCG is common to all RX ports, so it can only be used if
>>>> all the ports are in the same mode.
>>>>
>>>> Add basic support for SSCG by adding a module parameter to enable the
>>>> SSCG. The SSCG uses hardcoded configurationg, with 0.5% center-spread at
>>>> 33kHz modulation rate. See datasheet if different configuration is
>>>> required.
>>>>
>>>> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
>>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>>>> ---
>>>> drivers/media/i2c/ds90ub960.c | 102 ++++++++++++++++++++++++++++++++++++++++++
>>>> 1 file changed, 102 insertions(+)
>>>>
>>>> diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
>>>> index f6d6c2fe12cd..a534d077f045 100644
>>>> --- a/drivers/media/i2c/ds90ub960.c
>>>> +++ b/drivers/media/i2c/ds90ub960.c
>>>> @@ -52,6 +52,10 @@
>>>> #include <media/v4l2-fwnode.h>
>>>> #include <media/v4l2-subdev.h>
>>>> +static bool ub960_enable_sscg;
>>>> +module_param_named(enable_sscg, ub960_enable_sscg, bool, 0644);
>>>> +MODULE_PARM_DESC(enable_sscg, "Enable SSCG (if available)");
>>>
>>> Shouldn't this come from DT instead?
>>
>> SSCG is an option to use or not to use, based on what the user wants. DT
>> should describe the hardware.
>>
>> A module parameter is bad for this, though, as it's then used for all ub960
>> devices... But I'm not sure what other options we have. We need to have it
>> at probe time.
>>
>> Probably the whole driver could be changed to not connect the serializers at
>> probe, but instead would offer a set of userspace APIs to enable/disable
>> SSCG, and to enable the links. But that brings in its own set of problems,
>> as the links are used for i2c communication to the ser and sensor, not to
>> mention new userspace APIs which always complicates things.
>
> Typically determining whether you need spread spectrum signalling is highly
> specific to the board. I wonder if this topic has been discussed (and
> possibly somehow resolved) for other subsystems. CSI-2 appears to allow for
> spread spectrum clocks but I don't think I've seen that implemeted
> anywhere, scrambling may be more popular (but also that is right now
> unsupported but could be supported, probably this would be best to consider
> in conjunction with other CSI-2 parameters).
Well, I personally would rather have this option in the DT, so I'm all
for it =). We can change this to a DT parameter, and see how the DT
maintainers react.
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer
2025-01-15 14:17 ` Sakari Ailus
@ 2025-01-24 13:19 ` Tomi Valkeinen
2025-02-03 9:23 ` Sakari Ailus
0 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-24 13:19 UTC (permalink / raw)
To: Sakari Ailus
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Hi,
On 15/01/2025 16:17, Sakari Ailus wrote:
> Moi,
>
> On Fri, Jan 10, 2025 at 11:14:07AM +0200, Tomi Valkeinen wrote:
>> From: Jai Luthra <jai.luthra@ideasonboard.com>
>>
>> On the I2C bus for remote clients (sensors), by default the watchdog
>> timer expires in 1s. To allow for a quicker system bring-up time, TI
>> recommends to speed it up to 50us [1].
>>
>> [1]: Section 7.3.1.1 - https://www.ti.com/lit/gpn/ds90ub953-q1
>>
>> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> ---
>> drivers/media/i2c/ds90ub953.c | 11 +++++++++++
>> 1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
>> index 99a4852b9381..6c36980e8beb 100644
>> --- a/drivers/media/i2c/ds90ub953.c
>> +++ b/drivers/media/i2c/ds90ub953.c
>> @@ -54,6 +54,10 @@
>> #define UB953_REG_CLKOUT_CTRL0 0x06
>> #define UB953_REG_CLKOUT_CTRL1 0x07
>>
>> +#define UB953_REG_I2C_CONTROL2 0x0a
>> +#define UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT 4
>> +#define UB953_REG_I2C_CONTROL2_BUS_SPEEDUP BIT(1)
>> +
>> #define UB953_REG_SCL_HIGH_TIME 0x0b
>> #define UB953_REG_SCL_LOW_TIME 0x0c
>>
>> @@ -1320,6 +1324,13 @@ static int ub953_hw_init(struct ub953_data *priv)
>> if (ret)
>> return ret;
>>
>> + v = 0;
>> + v |= 1 << UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT;
>
> BIT()? Or at least 1U <<< ...;.
It's a three-bit field, the value just happens to be 1. What's wrong
with 1 << SHIFT?
>
>> + v |= UB953_REG_I2C_CONTROL2_BUS_SPEEDUP;
>> + ret = ub953_write(priv, UB953_REG_I2C_CONTROL2, v, NULL);
>
> I'd just do this without a temporary variable. If you prefer to keep it, do
> assign the first calculated value there first and remove the assignment to
> zero.
I think we can do without.
>> + if (ret)
>> + return ret;
>
> No need for this.
No, but it keeps the code structure consistent and allows easy
future/debug modifications.
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 13/19] media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports()
2025-01-15 14:25 ` Sakari Ailus
@ 2025-01-24 13:23 ` Tomi Valkeinen
0 siblings, 0 replies; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-24 13:23 UTC (permalink / raw)
To: Sakari Ailus
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Hi,
On 15/01/2025 16:25, Sakari Ailus wrote:
> Moi,
>
> On Fri, Jan 10, 2025 at 11:14:13AM +0200, Tomi Valkeinen wrote:
>> We have some code in probe() which is related to RX port initialization,
>> and should be in ub960_init_rx_ports(). Move the code there.
>>
>> We also move ub960_reset() so that it is accessible from
>> ub960_init_rx_ports().
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> ---
>> drivers/media/i2c/ds90ub960.c | 115 ++++++++++++++++++++++--------------------
>> 1 file changed, 59 insertions(+), 56 deletions(-)
>>
>> diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
>> index 02e22ae813fa..cc944d737524 100644
>> --- a/drivers/media/i2c/ds90ub960.c
>> +++ b/drivers/media/i2c/ds90ub960.c
>> @@ -1225,6 +1225,33 @@ static int ub960_ind_update_bits(struct ub960_data *priv, u8 block, u8 reg,
>> return ret;
>> }
>>
>> +static int ub960_reset(struct ub960_data *priv, bool reset_regs)
>> +{
>> + struct device *dev = &priv->client->dev;
>> + unsigned int v;
>> + int ret;
>> + u8 bit;
>> +
>> + bit = reset_regs ? UB960_SR_RESET_DIGITAL_RESET1 :
>> + UB960_SR_RESET_DIGITAL_RESET0;
>> +
>> + ret = ub960_write(priv, UB960_SR_RESET, bit, NULL);
>> + if (ret)
>> + return ret;
>
> Not related to the patch but if you're serialising things below, why aren't
> you doing that here?
ub960_write() takes the lock, regmap_read_poll_timeout() doesn't.
Tomi
>
>> +
>> + mutex_lock(&priv->reg_lock);
>> +
>> + ret = regmap_read_poll_timeout(priv->regmap, UB960_SR_RESET, v,
>> + (v & bit) == 0, 2000, 100000);
>> +
>> + mutex_unlock(&priv->reg_lock);
>> +
>> + if (ret)
>> + dev_err(dev, "reset failed: %d\n", ret);
>> +
>> + return ret;
>> +}
>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel
2025-01-15 14:29 ` Sakari Ailus
@ 2025-01-24 13:29 ` Tomi Valkeinen
2025-02-03 9:28 ` Sakari Ailus
0 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-24 13:29 UTC (permalink / raw)
To: Sakari Ailus
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Hi,
On 15/01/2025 16:29, Sakari Ailus wrote:
> Moi,
>
> On Fri, Jan 10, 2025 at 11:14:18AM +0200, Tomi Valkeinen wrote:
>> @@ -2956,6 +3033,36 @@ static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
>> if (ret)
>> return ret;
>>
>> + for_each_active_rxport(priv) {
>> + if (it.rxport->ser.addr >= 0) {
>> + /*
>> + * Set serializer's I2C address if set in the dts file,
>> + * and freeze it to prevent updates from the FC.
>> + */
>> + ub960_rxport_write(priv, it.nport, UB960_RR_SER_ID,
>> + it.rxport->ser.addr << 1 |
>> + UB960_RR_SER_ID_FREEZE_DEVICE_ID,
>> + &ret);
>> + }
>> +
>> + /* Set serializer I2C alias with auto-ack */
>> + ub960_rxport_write(priv, it.nport, UB960_RR_SER_ALIAS_ID,
>> + it.rxport->ser.alias << 1 |
>> + UB960_RR_SER_ALIAS_ID_AUTO_ACK, &ret);
>> +
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + for_each_active_rxport(priv) {
>> + if (fwnode_device_is_compatible(it.rxport->ser.fwnode,
>> + "ti,ds90ub971-q1")) {
>
> I guess one instance is fine but consider using match data instead.
This is checking the model of the (remote) serializer, not the
deserializer (which this driver deals with).
Unfortunately we need to do some early configuration before the
serializer driver probes, and that configuration depends on the
serializer model.
We could, perhaps, get the serializer models once and store it in the
rxport data for later use.
Tomi
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support
2025-01-15 14:23 ` Sakari Ailus
@ 2025-01-24 13:34 ` Tomi Valkeinen
2025-02-03 9:27 ` Sakari Ailus
0 siblings, 1 reply; 44+ messages in thread
From: Tomi Valkeinen @ 2025-01-24 13:34 UTC (permalink / raw)
To: Sakari Ailus
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Hi,
On 15/01/2025 16:23, Sakari Ailus wrote:
> Moi,
>
> On Fri, Jan 10, 2025 at 11:14:12AM +0200, Tomi Valkeinen wrote:
>> The driver does a lot of iteration over the RX ports with for loops. In
>> most cases the driver will skip unused RX ports. Also, in the future
>> patches the FPD-Link IV support will be refreshed with TI's latest init
>> sequences which involves a lot of additional iterations over the RX
>> ports, often only for FPD-Link IV ports.
>>
>> To make the iteration simpler and to make it clearer what we're
>> iterating over (all or only-active, all or only-fpd4), add macros and
>> support functions for iterating the RX ports. Use the macros in the
>> driver, replacing the for loops.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> ---
>> drivers/media/i2c/ds90ub960.c | 260 ++++++++++++++++++++++--------------------
>> 1 file changed, 135 insertions(+), 125 deletions(-)
>>
>> diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
>> index bca858172942..02e22ae813fa 100644
>> --- a/drivers/media/i2c/ds90ub960.c
>> +++ b/drivers/media/i2c/ds90ub960.c
>> @@ -649,6 +649,63 @@ static const struct ub960_format_info *ub960_find_format(u32 code)
>> return NULL;
>> }
>>
>> +struct ub960_rxport_iter {
>> + unsigned int nport;
>> + struct ub960_rxport *rxport;
>> +};
>> +
>> +enum ub960_iter_flags {
>> + UB960_ITER_ACTIVE_ONLY = BIT(0),
>> + UB960_ITER_FPD4_ONLY = BIT(1),
>> +};
>> +
>> +static struct ub960_rxport_iter ub960_iter_rxport(struct ub960_data *priv,
>> + struct ub960_rxport_iter it,
>> + enum ub960_iter_flags flags)
>> +{
>> + for (; it.nport < priv->hw_data->num_rxports; it.nport++) {
>> + it.rxport = priv->rxports[it.nport];
>> +
>> + if ((flags & UB960_ITER_ACTIVE_ONLY) && !it.rxport)
>> + continue;
>> +
>> + if ((flags & UB960_ITER_FPD4_ONLY) &&
>> + it.rxport->cdr_mode != RXPORT_CDR_FPD4)
>> + continue;
>> +
>> + return it;
>> + }
>> +
>> + it.rxport = NULL;
>> +
>> + return it;
>> +}
>> +
>> +#define for_each_rxport(priv) \
>
> it should be also an argument to the macro as it's visible outside it.
>
> And wouldn't it be reasonable to use a pointer instead for the purpsoe?
You mean something like:
struct ub960_rxport_iter it = { 0 };
for_each_rxport(priv, &it) { }
Then we leak the iterator, and I really hate it. I've fixed numerous
bugs caused by such cases.
Tomi
>
>> + for (struct ub960_rxport_iter it = \
>> + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
>> + 0); \
>> + it.nport < (priv)->hw_data->num_rxports; \
>> + it.nport++, it = ub960_iter_rxport(priv, it, 0))
>> +
>> +#define for_each_active_rxport(priv) \
>> + for (struct ub960_rxport_iter it = \
>> + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
>> + UB960_ITER_ACTIVE_ONLY); \
>> + it.nport < (priv)->hw_data->num_rxports; \
>> + it.nport++, it = ub960_iter_rxport(priv, it, \
>> + UB960_ITER_ACTIVE_ONLY))
>> +
>> +#define for_each_active_rxport_fpd4(priv) \
>> + for (struct ub960_rxport_iter it = \
>> + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
>> + UB960_ITER_ACTIVE_ONLY | \
>> + UB960_ITER_FPD4_ONLY); \
>> + it.nport < (priv)->hw_data->num_rxports; \
>> + it.nport++, it = ub960_iter_rxport(priv, it, \
>> + UB960_ITER_ACTIVE_ONLY | \
>> + UB960_ITER_FPD4_ONLY))
>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer
2025-01-24 13:19 ` Tomi Valkeinen
@ 2025-02-03 9:23 ` Sakari Ailus
0 siblings, 0 replies; 44+ messages in thread
From: Sakari Ailus @ 2025-02-03 9:23 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Fri, Jan 24, 2025 at 03:19:32PM +0200, Tomi Valkeinen wrote:
> Hi,
>
> On 15/01/2025 16:17, Sakari Ailus wrote:
> > Moi,
> >
> > On Fri, Jan 10, 2025 at 11:14:07AM +0200, Tomi Valkeinen wrote:
> > > From: Jai Luthra <jai.luthra@ideasonboard.com>
> > >
> > > On the I2C bus for remote clients (sensors), by default the watchdog
> > > timer expires in 1s. To allow for a quicker system bring-up time, TI
> > > recommends to speed it up to 50us [1].
> > >
> > > [1]: Section 7.3.1.1 - https://www.ti.com/lit/gpn/ds90ub953-q1
> > >
> > > Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
> > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> > > ---
> > > drivers/media/i2c/ds90ub953.c | 11 +++++++++++
> > > 1 file changed, 11 insertions(+)
> > >
> > > diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
> > > index 99a4852b9381..6c36980e8beb 100644
> > > --- a/drivers/media/i2c/ds90ub953.c
> > > +++ b/drivers/media/i2c/ds90ub953.c
> > > @@ -54,6 +54,10 @@
> > > #define UB953_REG_CLKOUT_CTRL0 0x06
> > > #define UB953_REG_CLKOUT_CTRL1 0x07
> > > +#define UB953_REG_I2C_CONTROL2 0x0a
> > > +#define UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT 4
> > > +#define UB953_REG_I2C_CONTROL2_BUS_SPEEDUP BIT(1)
> > > +
> > > #define UB953_REG_SCL_HIGH_TIME 0x0b
> > > #define UB953_REG_SCL_LOW_TIME 0x0c
> > > @@ -1320,6 +1324,13 @@ static int ub953_hw_init(struct ub953_data *priv)
> > > if (ret)
> > > return ret;
> > > + v = 0;
> > > + v |= 1 << UB953_REG_I2C_CONTROL2_SDA_OUTPUT_SETUP_SHIFT;
> >
> > BIT()? Or at least 1U <<< ...;.
>
> It's a three-bit field, the value just happens to be 1. What's wrong with 1
> << SHIFT?
Shifting a signed value leads to the sign bit being undefined on some
architectures.
>
> >
> > > + v |= UB953_REG_I2C_CONTROL2_BUS_SPEEDUP;
> > > + ret = ub953_write(priv, UB953_REG_I2C_CONTROL2, v, NULL);
> >
> > I'd just do this without a temporary variable. If you prefer to keep it, do
> > assign the first calculated value there first and remove the assignment to
> > zero.
>
> I think we can do without.
>
> > > + if (ret)
> > > + return ret;
> >
> > No need for this.
>
> No, but it keeps the code structure consistent and allows easy future/debug
> modifications.
Please still remove such redundancies.
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support
2025-01-24 13:34 ` Tomi Valkeinen
@ 2025-02-03 9:27 ` Sakari Ailus
0 siblings, 0 replies; 44+ messages in thread
From: Sakari Ailus @ 2025-02-03 9:27 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
Moi,
On Fri, Jan 24, 2025 at 03:34:44PM +0200, Tomi Valkeinen wrote:
> Hi,
>
> On 15/01/2025 16:23, Sakari Ailus wrote:
> > Moi,
> >
> > On Fri, Jan 10, 2025 at 11:14:12AM +0200, Tomi Valkeinen wrote:
> > > The driver does a lot of iteration over the RX ports with for loops. In
> > > most cases the driver will skip unused RX ports. Also, in the future
> > > patches the FPD-Link IV support will be refreshed with TI's latest init
> > > sequences which involves a lot of additional iterations over the RX
> > > ports, often only for FPD-Link IV ports.
> > >
> > > To make the iteration simpler and to make it clearer what we're
> > > iterating over (all or only-active, all or only-fpd4), add macros and
> > > support functions for iterating the RX ports. Use the macros in the
> > > driver, replacing the for loops.
> > >
> > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> > > ---
> > > drivers/media/i2c/ds90ub960.c | 260 ++++++++++++++++++++++--------------------
> > > 1 file changed, 135 insertions(+), 125 deletions(-)
> > >
> > > diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
> > > index bca858172942..02e22ae813fa 100644
> > > --- a/drivers/media/i2c/ds90ub960.c
> > > +++ b/drivers/media/i2c/ds90ub960.c
> > > @@ -649,6 +649,63 @@ static const struct ub960_format_info *ub960_find_format(u32 code)
> > > return NULL;
> > > }
> > > +struct ub960_rxport_iter {
> > > + unsigned int nport;
> > > + struct ub960_rxport *rxport;
> > > +};
> > > +
> > > +enum ub960_iter_flags {
> > > + UB960_ITER_ACTIVE_ONLY = BIT(0),
> > > + UB960_ITER_FPD4_ONLY = BIT(1),
> > > +};
> > > +
> > > +static struct ub960_rxport_iter ub960_iter_rxport(struct ub960_data *priv,
> > > + struct ub960_rxport_iter it,
> > > + enum ub960_iter_flags flags)
> > > +{
> > > + for (; it.nport < priv->hw_data->num_rxports; it.nport++) {
> > > + it.rxport = priv->rxports[it.nport];
> > > +
> > > + if ((flags & UB960_ITER_ACTIVE_ONLY) && !it.rxport)
> > > + continue;
> > > +
> > > + if ((flags & UB960_ITER_FPD4_ONLY) &&
> > > + it.rxport->cdr_mode != RXPORT_CDR_FPD4)
> > > + continue;
> > > +
> > > + return it;
> > > + }
> > > +
> > > + it.rxport = NULL;
> > > +
> > > + return it;
> > > +}
> > > +
> > > +#define for_each_rxport(priv) \
> >
> > it should be also an argument to the macro as it's visible outside it.
> >
> > And wouldn't it be reasonable to use a pointer instead for the purpsoe?
>
> You mean something like:
>
> struct ub960_rxport_iter it = { 0 };
>
> for_each_rxport(priv, &it) { }
>
> Then we leak the iterator, and I really hate it. I've fixed numerous bugs
> caused by such cases.
You can still define it for the loop only, just give it a name instead of
using a pre-determined name.
Could you also pass the iterator by reference instead of the value?
>
> Tomi
>
> >
> > > + for (struct ub960_rxport_iter it = \
> > > + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
> > > + 0); \
> > > + it.nport < (priv)->hw_data->num_rxports; \
> > > + it.nport++, it = ub960_iter_rxport(priv, it, 0))
> > > +
> > > +#define for_each_active_rxport(priv) \
> > > + for (struct ub960_rxport_iter it = \
> > > + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
> > > + UB960_ITER_ACTIVE_ONLY); \
> > > + it.nport < (priv)->hw_data->num_rxports; \
> > > + it.nport++, it = ub960_iter_rxport(priv, it, \
> > > + UB960_ITER_ACTIVE_ONLY))
> > > +
> > > +#define for_each_active_rxport_fpd4(priv) \
> > > + for (struct ub960_rxport_iter it = \
> > > + ub960_iter_rxport(priv, (struct ub960_rxport_iter){ 0 }, \
> > > + UB960_ITER_ACTIVE_ONLY | \
> > > + UB960_ITER_FPD4_ONLY); \
> > > + it.nport < (priv)->hw_data->num_rxports; \
> > > + it.nport++, it = ub960_iter_rxport(priv, it, \
> > > + UB960_ITER_ACTIVE_ONLY | \
> > > + UB960_ITER_FPD4_ONLY))
> >
>
--
Terveisin,
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel
2025-01-24 13:29 ` Tomi Valkeinen
@ 2025-02-03 9:28 ` Sakari Ailus
0 siblings, 0 replies; 44+ messages in thread
From: Sakari Ailus @ 2025-02-03 9:28 UTC (permalink / raw)
To: Tomi Valkeinen
Cc: Mauro Carvalho Chehab, linux-media, linux-kernel,
Devarsh Thakkar, Jai Luthra
On Fri, Jan 24, 2025 at 03:29:43PM +0200, Tomi Valkeinen wrote:
> Hi,
>
> On 15/01/2025 16:29, Sakari Ailus wrote:
> > Moi,
> >
> > On Fri, Jan 10, 2025 at 11:14:18AM +0200, Tomi Valkeinen wrote:
> > > @@ -2956,6 +3033,36 @@ static int ub960_init_rx_ports_ub9702(struct ub960_data *priv)
> > > if (ret)
> > > return ret;
> > > + for_each_active_rxport(priv) {
> > > + if (it.rxport->ser.addr >= 0) {
> > > + /*
> > > + * Set serializer's I2C address if set in the dts file,
> > > + * and freeze it to prevent updates from the FC.
> > > + */
> > > + ub960_rxport_write(priv, it.nport, UB960_RR_SER_ID,
> > > + it.rxport->ser.addr << 1 |
> > > + UB960_RR_SER_ID_FREEZE_DEVICE_ID,
> > > + &ret);
> > > + }
> > > +
> > > + /* Set serializer I2C alias with auto-ack */
> > > + ub960_rxport_write(priv, it.nport, UB960_RR_SER_ALIAS_ID,
> > > + it.rxport->ser.alias << 1 |
> > > + UB960_RR_SER_ALIAS_ID_AUTO_ACK, &ret);
> > > +
> > > + if (ret)
> > > + return ret;
> > > + }
> > > +
> > > + for_each_active_rxport(priv) {
> > > + if (fwnode_device_is_compatible(it.rxport->ser.fwnode,
> > > + "ti,ds90ub971-q1")) {
> >
> > I guess one instance is fine but consider using match data instead.
>
> This is checking the model of the (remote) serializer, not the deserializer
> (which this driver deals with).
>
> Unfortunately we need to do some early configuration before the serializer
> driver probes, and that configuration depends on the serializer model.
>
> We could, perhaps, get the serializer models once and store it in the rxport
> data for later use.
Ack.
--
Sakari Ailus
^ permalink raw reply [flat|nested] 44+ messages in thread
end of thread, other threads:[~2025-02-03 9:28 UTC | newest]
Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-10 9:14 [PATCH 00/19] media: i2c: ds90ub9xx: Error handling, UB9702 improvements Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 01/19] media: i2c: ds90ub953: Fix error prints Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 02/19] media: i2c: ds90ub913: Align ub913_read() with other similar functions Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 03/19] media: i2c: ds90ub9xx: Add err parameter to read/write funcs Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 04/19] media: i2c: ds90ub960: Add error handling to multiple places Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 05/19] media: i2c: ds90ub953: Add error handling to ub953_log_status() Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 06/19] media: i2c: ds90ub913: Add error handling to ub913_log_status() Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 07/19] media: i2c: ds90ub953: Speed-up I2C watchdog timer Tomi Valkeinen
2025-01-15 14:17 ` Sakari Ailus
2025-01-24 13:19 ` Tomi Valkeinen
2025-02-03 9:23 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 08/19] media: i2c: ds90ub960: Move UB9702 registers to a separate section Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 09/19] media: i2c: ds90ub960: Add UB9702 specific registers Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 10/19] media: i2c: ds90ub960: Split ub960_init_tx_ports() Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 11/19] media: i2c: ds90ub960: Refresh ub960_init_tx_ports_ub9702() Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 12/19] media: i2c: ds90ub960: Add RX port iteration support Tomi Valkeinen
2025-01-15 14:23 ` Sakari Ailus
2025-01-24 13:34 ` Tomi Valkeinen
2025-02-03 9:27 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 13/19] media: i2c: ds90ub960: Move all RX port init code into ub960_init_rx_ports() Tomi Valkeinen
2025-01-15 14:25 ` Sakari Ailus
2025-01-24 13:23 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 14/19] media: i2c: ds90ub960: Remove old ub9702 RX port init code (SQUASH) Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 15/19] media: i2c: ds90ub960: Update UB9702 init sequences Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 16/19] media: i2c: ds90ub960: Enable SSCG for UB9702 Tomi Valkeinen
2025-01-15 14:26 ` Sakari Ailus
2025-01-15 16:04 ` Tomi Valkeinen
2025-01-16 9:58 ` Sakari Ailus
2025-01-16 10:05 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 17/19] media: dt-bindings: ti,ds90ub960: Add "i2c-addr" link property Tomi Valkeinen
2025-01-11 10:31 ` Krzysztof Kozlowski
2025-01-14 11:50 ` Tomi Valkeinen
2025-01-15 8:40 ` Krzysztof Kozlowski
2025-01-15 17:19 ` Tomi Valkeinen
2025-01-15 20:25 ` Krzysztof Kozlowski
2025-01-15 15:53 ` Konstantin Ryabitsev
2025-01-15 16:09 ` Tomi Valkeinen
2025-01-15 16:46 ` Krzysztof Kozlowski
2025-01-15 17:14 ` Tomi Valkeinen
2025-01-10 9:14 ` [PATCH 18/19] media: i2c: ds90ub960: Configure serializer using back-channel Tomi Valkeinen
2025-01-15 14:29 ` Sakari Ailus
2025-01-24 13:29 ` Tomi Valkeinen
2025-02-03 9:28 ` Sakari Ailus
2025-01-10 9:14 ` [PATCH 19/19] media: i2c: ds90ub9xx: Set serializer temperature ramp Tomi Valkeinen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®