Thread (16 messages) 16 messages, 2 authors, 2023-03-02

Re: [PATCH v9 0/8] i2c-atr and FPDLink

From: Andy Shevchenko <hidden>
Date: 2023-02-16 15:53:33
Also in: linux-i2c, linux-media, lkml

On Thu, Feb 16, 2023 at 04:07:39PM +0200, Tomi Valkeinen wrote:

...
+	if (!c2a)
I would expect here dev_warn() to let user know about "shouldn't happened, but
have happened" situation.
+		return; /* This shouldn't happen */
...
-	static const struct v4l2_mbus_framefmt format = {
+	static const struct v4l2_mbus_framefmt informat = {
Naming a bit confusing. Is it "information" that cut or what?

in_format
+	static const struct v4l2_mbus_framefmt outformat = {
out_format

...
-out_unlock:
+out:
Why?

...
+/*
+ * (Possible) TODOs
TODOs:
+ *
+ * - PM for serializer and remote peripherals. We need to manage:
+ *   - VPOC
+ *     - Power domain? Regulator? Somehow any remote device should be able to
+ *       cause the VPOC to be turned on.
+ *   - Link between the deserializer and the serializer
+ *     - Related to VPOC management. We probably always want to turn on the VPOC
+ *       and then enable the link.
+ *   - Serializer's services: i2c, gpios, power
+ *     - The serializer needs to resume before the remote peripherals can
+ *       e.g. use the i2c.
+ *     - How to handle gpios? Reserving a gpio essentially keeps the provider
+ *       (serializer) always powered on.
+ * - Do we need a new bus for the FPD-Link? At the moment the serializers
+ *   are children of the same i2c-adapter where the deserializer resides.
+ * - i2c-atr could be made embeddable instead of allocatable.
+ */
...
 struct atr_alias_table_entry {
 	u16 alias_id;	/* Alias ID from DT */
 
-	bool reserved;
+	bool in_use;
 	u8 nport;
 	u8 slave_id;	/* i2c client's local i2c address */
 	u8 port_reg_idx;
Wouldn't be wiser to move boolean at the end so if any obscure
architecture/compiler makes it longer than a byte it won't increase the memory
footprint. (Actually wouldn't it be aligned to u16 followed by u8 as well as
they are different types?)
 };
...
+static int ub960_read16(struct ub960_data *priv, u8 reg, u16 *val)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int v1, v2;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_read(priv->regmap, reg, &v1);
+	if (ret) {
+		dev_err(dev, "%s: cannot read register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+		goto out_unlock;
+	}
+
+	ret = regmap_read(priv->regmap, reg + 1, &v2);
+	if (ret) {
+		dev_err(dev, "%s: cannot read register 0x%02x (%d)!\n",
+			__func__, reg + 1, ret);
+		goto out_unlock;
+	}
Wondering why bulk read can't be used against properly typed __be16 variable?
+	*val = (v1 << 8) | v2;
+ be16_to_cpu() here.
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
...
+static int ub960_rxport_read16(struct ub960_data *priv, u8 nport, u8 reg,
+			       u16 *val)
 {
Ditto.
+}
...
 	struct i2c_board_info ser_info = {
-		.of_node = to_of_node(rxport->remote_fwnode),
-		.fwnode = rxport->remote_fwnode,
+		.of_node = to_of_node(rxport->ser.fwnode),
+		.fwnode = rxport->ser.fwnode,
Why do you need to have both?!
 		.platform_data = ser_pdata,
 	};
...
+	for (nport = 0; nport < priv->hw_data->num_rxports; ++nport) {
Pre-increment is non-standard in the kernel.
+		struct ub960_rxport *rxport = priv->rxports[nport];
+		struct v4l2_mbus_frame_desc desc;
+		int ret;
+		u8 cur_vc;
+
+		if (!rxport)
+			continue;
+
+		ret = v4l2_subdev_call(rxport->source.sd, pad, get_frame_desc,
+				       rxport->source.pad, &desc);
+		if (ret)
+			return ret;
+
+		if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2)
+			continue;
		cur_vc = desc.entry[0].bus.csi2.vc;
+		for (i = 0; i < desc.num_entries; ++i) {
+			u8 vc = desc.entry[i].bus.csi2.vc;
+			if (i == 0) {
+				cur_vc = vc;
+				continue;
+			}
This is an invariant to the loop, see above.
+			if (vc == cur_vc)
+				continue;
+
+			dev_err(&priv->client->dev,
+				"rx%u: source with multiple virtual-channels is not supported\n",
+				nport);
+			return -ENODEV;
+		}
+	}
...
+	for (i = 0; i < 6; ++i)
 		ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i]);
 	id[6] = 0;
Wondering if this magic can be defined.

...
+	priv->atr.aliases = devm_kcalloc(dev, table_size,
+					 sizeof(struct atr_alias_table_entry),
	sizeof(*priv->atr.aliases) ?
+					 GFP_KERNEL);
+	if (!priv->atr.aliases)
 		return -ENOMEM;
...
quoted hunk ↗ jump to hunk
 	if (ret) {
 		if (ret != -EINVAL) {
-			dev_err(dev,
-				"rx%u: failed to read 'ti,strobe-pos': %d\n",
-				nport, ret);
+			dev_err(dev, "rx%u: failed to read '%s': %d\n", nport,
+				"ti,strobe-pos", ret);
 			return ret;
 		}
 	} else if (strobe_pos < UB960_MIN_MANUAL_STROBE_POS ||
@@ -3512,8 +3403,8 @@ ub960_parse_dt_rxport_link_properties(struct ub960_data *priv,
 	ret = fwnode_property_read_u32(link_fwnode, "ti,eq-level", &eq_level);
 	if (ret) {
 		if (ret != -EINVAL) {
-			dev_err(dev, "rx%u: failed to read 'ti,eq-level': %d\n",
-				nport, ret);
+			dev_err(dev, "rx%u: failed to read '%s': %d\n", nport,
+				"ti,eq-level", ret);
 			return ret;
 		}
 	} else if (eq_level > UB960_MAX_EQ_LEVEL) {

Seems like you may do (in both cases) similar to the above:

	var = 0;
	ret = read_u32();
	if (ret && ret != -EINVAL) {
		// error handling
	}
	if (var > limit) {
		// another error handling
	}

...
+	static const char *vpoc_names[UB960_MAX_RX_NPORTS] = { "vpoc0", "vpoc1",
+							       "vpoc2", "vpoc3" };
Wouldn't be better to format it as

	static const char *vpoc_names[UB960_MAX_RX_NPORTS] = {
		"vpoc0", "vpoc1", "vpoc2", "vpoc3",
	};

?

-- 
With Best Regards,
Andy Shevchenko

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help