Thread (11 messages) read the whole thread 11 messages, 7 authors, 2024-02-18

Re: [PATCH 2/2] media: i2c: Add imx283 camera sensor driver

From: Krzysztof Kozlowski <hidden>
Date: 2024-02-16 08:07:04
Also in: linux-devicetree, linux-media

On 15/02/2024 21:44, Umang Jain wrote:
From: Kieran Bingham <kieran.bingham@ideasonboard.com>

Add a v4l2 subdevice driver for the Sony IMX283 image sensor.

The IMX283 is a 20MP Diagonal 15.86 mm (Type 1) CMOS Image Sensor with
Square Pixel for Color Cameras.
...
+
+static int imx283_power_off(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct imx283 *imx283 = to_imx283(sd);
+
+	gpiod_set_value_cansleep(imx283->reset_gpio, 0);
That's odd. It is reset GPIO, so 0 means deassert means "stop resetting
device". You have wrong handling of the GPIO.
+	regulator_bulk_disable(ARRAY_SIZE(imx283_supply_name), imx283->supplies);
+	clk_disable_unprepare(imx283->xclk);
+
+	return 0;
+}
+
+static int imx283_get_regulators(struct imx283 *imx283)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(imx283_supply_name); i++)
+		imx283->supplies[i].supply = imx283_supply_name[i];
+
+	return devm_regulator_bulk_get(imx283->dev,
+				       ARRAY_SIZE(imx283_supply_name),
+				       imx283->supplies);
+}
...
+static const struct of_device_id imx283_dt_ids[] = {
+	{ .compatible = "sony,imx283", },
+	{ /* sentinel */ }
+};
This goes next to driver structure. You also miss module device table.
+
+static int imx283_parse_endpoint(struct imx283 *imx283)
+{
+	struct fwnode_handle *fwnode = dev_fwnode(imx283->dev);
+	struct v4l2_fwnode_endpoint bus_cfg = {
+		.bus_type = V4L2_MBUS_CSI2_DPHY
+	};
+	struct fwnode_handle *ep;
+	int ret;
+
+	if (!fwnode)
+		return -ENXIO;
+
+	ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
+	if (!ep) {
+		dev_err(imx283->dev, "Failed to get next endpoint\n");
+		return -ENXIO;
+	}
+
+	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
+	fwnode_handle_put(ep);
+	if (ret)
+		return ret;
+
+	if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) {
+		dev_err(imx283->dev,
+			"number of CSI2 data lanes %d is not supported\n",
+			bus_cfg.bus.mipi_csi2.num_data_lanes);
+		ret = -EINVAL;
+		goto done_endpoint_free;
+	}
+
+	ret = v4l2_link_freq_to_bitmap(imx283->dev, bus_cfg.link_frequencies,
+				       bus_cfg.nr_of_link_frequencies,
+				       link_frequencies, ARRAY_SIZE(link_frequencies),
+				       &imx283->link_freq_bitmap);
+
+done_endpoint_free:
+	v4l2_fwnode_endpoint_free(&bus_cfg);
+
+	return ret;
+};
+
+static int imx283_probe(struct i2c_client *client)
+{
+	struct imx283 *imx283;
+	int ret;
+	unsigned int i;
+	unsigned int xclk_freq;
+
+	imx283 = devm_kzalloc(&client->dev, sizeof(*imx283), GFP_KERNEL);
+	if (!imx283)
+		return -ENOMEM;
+
+	imx283->dev = &client->dev;
+
+	v4l2_i2c_subdev_init(&imx283->sd, client, &imx283_subdev_ops);
+
+	imx283->cci = devm_cci_regmap_init_i2c(client, 16);
+	if (IS_ERR(imx283->cci)) {
+		ret = PTR_ERR(imx283->cci);
+		dev_err(imx283->dev, "failed to initialize CCI: %d\n", ret);
+		return ret;
+	}
+
+	/* Get system clock (xclk) */
+	imx283->xclk = devm_clk_get(imx283->dev, NULL);
+	if (IS_ERR(imx283->xclk)) {
+		dev_err(imx283->dev, "failed to get xclk\n");
Syntax is: return dev_err_probe()
+		return PTR_ERR(imx283->xclk);
+	}
+
+	xclk_freq = clk_get_rate(imx283->xclk);
+	for (i = 0; i < ARRAY_SIZE(imx283_frequencies); i++) {
+		if (xclk_freq == imx283_frequencies[i].mhz) {
+			imx283->freq = &imx283_frequencies[i];
+			break;
+		}
+	}
+	if (!imx283->freq) {
+		dev_err(imx283->dev, "xclk frequency unsupported: %d Hz\n", xclk_freq);
+		return -EINVAL;
+	}
+
+	ret = imx283_get_regulators(imx283);
+	if (ret) {
+		dev_err(imx283->dev, "failed to get regulators\n");
+		return ret;
return dev_err_probe()
+	}
+
+	ret = imx283_parse_endpoint(imx283);
+	if (ret) {
+		dev_err(imx283->dev, "failed to parse endpoint configuration\n");
+		return ret;
+	}
+
+	/* Request optional enable pin */
+	imx283->reset_gpio = devm_gpiod_get_optional(imx283->dev, "reset",
+						     GPIOD_OUT_HIGH);
No, that's not allowed in your binding. Don't add undocumented properties.
+
+	mutex_init(&imx283->mutex);
+
+	/*
+	 * The sensor must be powered for imx283_identify_module()
+	 * to be able to read the CHIP_ID register
+	 */
+	ret = imx283_power_on(imx283->dev);
+	if (ret)
+		return ret;
+

Best regards,
Krzysztof


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help