All of lore.kernel.org
 help / color / mirror / Atom feed
* [git:media_stage/master] media: i2c: Add driver for the Analog Devices ADDI9036 ToF front-end
@ 2021-12-14 12:44 Mauro Carvalho Chehab
  2021-12-15  0:00   ` kernel test robot
  0 siblings, 1 reply; 3+ messages in thread
From: Mauro Carvalho Chehab @ 2021-12-14 12:44 UTC (permalink / raw)
  To: linuxtv-commits; +Cc: Bogdan Togorean, linux-kernel

This is an automatic generated email to let you know that the following patch were queued:

Subject: media: i2c: Add driver for the Analog Devices ADDI9036 ToF front-end
Author:  Bogdan Togorean <bogdan.togorean@analog.com>
Date:    Fri Oct 9 13:29:54 2020 +0200

The ADDI9036 is a complete, 45 MHz, front-end solution for charge
coupled device (CCD) time of flight (TOF) imaging applications.

It has 2-lane MIPI CSI-2 RAW12 data output and i2c control interface.

The programming of calibration and firmware is performed by driver
using Linux Firmware API.

Link: https://lore.kernel.org/linux-media/20201009113014.71531-1-bogdan.togorean@analog.com

CC: Bogdan Togorean <bogdan.togorean@analog.com>, kernel test robot <lkp@intel.com>, Mauro Carvalho Chehab <mchehab@kernel.org>, Rob Herring <robh+dt@kernel.org>, "David S. Miller" <davem@davemloft.net>, Sakari Ailus <sakari.ailus@linux.intel.com>, Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>, Jacopo Mondi <jacopo+renesas@jmondi.org>, Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>, Bingbu Cao <bingbu.cao@intel.com>, Dave Stevenson <dave.stevenson@raspberrypi.com>, Ricardo Ribalda <ribalda@kernel.org>, =?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund+renesas@ragnatech.se>, Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>, Dongchun Zhu <dongchun.zhu@mediatek.com>, Shawn Tu <shawnx.tu@intel.com>, <devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Signed-off-by: Bogdan Togorean <bogdan.togorean@analog.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

 MAINTAINERS                        |  10 +
 drivers/media/i2c/Kconfig          |  14 +
 drivers/media/i2c/Makefile         |   1 +
 drivers/media/i2c/addi9036.c       | 785 +++++++++++++++++++++++++++++++++++++
 include/uapi/linux/v4l2-controls.h |   6 +
 5 files changed, 816 insertions(+)

---

diff --git a/MAINTAINERS b/MAINTAINERS
index 38235471fed0..3a19f9acbad0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -490,6 +490,16 @@ W:	http://wiki.analog.com/AD7879
 W:	http://ez.analog.com/community/linux-device-drivers
 F:	drivers/input/touchscreen/ad7879.c
 
+ADDI9036 TOF FRONTEND DRIVER
+M:	Bogdan Togorean <bogdan.togorean@analog.com>
+L:	linux-media@vger.kernel.org
+S:	Supported
+W:	https://www.analog.com/en/products/addi9036.html
+W:	http://ez.analog.com/community/linux-device-drivers
+T:	git git://linuxtv.org/media_tree.git
+F:	Documentation/devicetree/bindings/media/i2c/adi,addi9036.yaml
+F:	drivers/media/i2c/addi9036.c
+
 ADDRESS SPACE LAYOUT RANDOMIZATION (ASLR)
 M:	Jiri Kosina <jikos@kernel.org>
 S:	Maintained
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 69c56e24a612..24b16c8fb89a 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -733,6 +733,20 @@ config VIDEO_APTINA_PLL
 config VIDEO_CCS_PLL
 	tristate
 
+config VIDEO_ADDI9036
+	tristate "Analog Devices ADDI9036 ToF front-end support"
+	depends on I2C && VIDEO_V4L2
+	select MEDIA_CONTROLLER
+	select VIDEO_V4L2_SUBDEV_API
+	select V4L2_FWNODE
+	select REGMAP_I2C
+	help
+	  This is a Video4Linux2 driver for Analog Devices ADDI9036
+	  Time of Flight front-end.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called addi9036.
+
 config VIDEO_HI556
 	tristate "Hynix Hi-556 sensor support"
 	depends on I2C && VIDEO_V4L2
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index b01f6cd05ee8..0a07c0236c62 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_VIDEO_AK7375)  += ak7375.o
 obj-$(CONFIG_VIDEO_DW9714)  += dw9714.o
 obj-$(CONFIG_VIDEO_DW9768)  += dw9768.o
 obj-$(CONFIG_VIDEO_DW9807_VCM)  += dw9807-vcm.o
+obj-$(CONFIG_VIDEO_ADDI9036) += addi9036.o
 obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
 obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
 obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
diff --git a/drivers/media/i2c/addi9036.c b/drivers/media/i2c/addi9036.c
new file mode 100644
index 000000000000..30d7748b9f63
--- /dev/null
+++ b/drivers/media/i2c/addi9036.c
@@ -0,0 +1,785 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the Analog Devices ADDI9036 ToF camera sensor.
+ *
+ * Copyright (C) 2019-2020 Analog Devices, All Rights Reserved.
+ *
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#define FW_FILE_NAME	"adi/addi9036-fw.bin"
+#define ADDI_MAGIC	"ADDI9036"
+
+struct addi9036_mode_info {
+	u32 width;
+	u32 height;
+	u32 pixel_rate;
+	u32 link_freq_idx;
+};
+
+struct addi9036_mode_fw_block {
+	const struct reg_sequence *mode_regs;
+	ssize_t regs_count;
+};
+
+struct addi9036_fw_header {
+	unsigned char magic[8];
+	__le32 modes_nr;
+} __packed;
+
+struct addi9036_mode_block {
+	__le32 mode_id;
+	__le32 size_bytes;
+	__le16 data[];
+} __packed;
+
+struct addi9036 {
+	struct regmap *regmap;
+	struct device *dev;
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+	struct v4l2_mbus_framefmt fmt;
+	struct v4l2_rect crop;
+
+	const struct addi9036_mode_info *current_mode;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *pixel_rate;
+	struct v4l2_ctrl *link_freq;
+	/* custom controls */
+	struct v4l2_ctrl *set_operating_range;
+
+	struct mutex lock;
+	bool streaming;
+
+	struct gpio_desc *rst_gpio;
+
+	/* firmware blocks for each operating mode */
+	struct addi9036_mode_fw_block *mode_fw_blocks;
+	u8 curr_operating_mode;
+
+	const struct firmware *fw;
+};
+
+static inline struct addi9036 *to_addi9036(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct addi9036, sd);
+}
+
+#define V4L2_CID_ADDI9036_OPERATING_MODE  (V4L2_CID_USER_ADDI9036_BASE + 0)
+
+static const struct reg_sequence addi9036_powerup_setting[] = {
+	{ 0xc4c0, 0x001c },
+	{ 0xc4c3, 0x001c },
+	{ 0xc4d7, 0x0000 },
+	{ 0xc4d5, 0x0002 },
+	{ 0xc4da, 0x0001 },
+	{ 0xc4f0, 0x0000 },
+	{ 0xc427, 0x0003 },
+	{ 0xc427, 0x0001 },
+	{ 0xc427, 0x0000 },
+	{ 0xc426, 0x0030 },
+	{ 0xc426, 0x0010 },
+	{ 0xc426, 0x0000 },
+	{ 0xc423, 0x0080 },
+	{ 0xc431, 0x0080 },
+	{ 0x4001, 0x0007 },
+	{ 0x7c22, 0x0004 }
+};
+
+static const struct reg_sequence addi9036_powerdown_setting[] = {
+	{ 0xc022, 0x0001 },
+	{ 0x4001, 0x0006 },
+	{ 0x7c22, 0x0004 },
+	{ 0xc431, 0x0082 },
+	{ 0xc423, 0x0000 },
+	{ 0xc426, 0x0020 },
+	{ 0xc427, 0x0002 },
+	{ 0xc4c0, 0x003c },
+	{ 0xc4c3, 0x003c },
+	{ 0xc4d5, 0x0003 },
+	{ 0xc4da, 0x0000 },
+	{ 0xc4d7, 0x0001 },
+	{ 0xc4f0, 0x0001 }
+};
+
+static const struct reg_sequence addi9036_standby_setting[] = {
+	{ 0xc020, 0x0000 },
+	{ 0xc024, 0x0000 },
+	{ 0xc028, 0x0000 },
+	{ 0xc022, 0x0001 }
+};
+
+static const s64 link_freq_tbl[] = {
+	110529000,
+	221184000,
+};
+
+/* Elements of the structure must be ordered ascending by width & height */
+static const struct addi9036_mode_info addi9036_mode_info_data[] = {
+	{
+		.width = 640,
+		.height = 480,
+		.pixel_rate = 36864000,
+		.link_freq_idx = 0 /* an index in link_freq_tbl[] */
+	},
+	{
+		.width = 640,
+		.height = 960,
+		.pixel_rate = 73728000,
+		.link_freq_idx = 1 /* an index in link_freq_tbl[] */
+	},
+};
+
+static bool addi9306_readable_register(struct device *dev, unsigned int reg)
+{
+	if (((reg >= 0x4000) && (reg <= 0x6fff)) ||
+	    ((reg >= 0x7c00) && (reg <= 0x7fff)) ||
+	    ((reg >= 0xc000) && (reg <= 0xc200)) ||
+	    ((reg >= 0xc300) && (reg <= 0xc6bf)))
+		return true;
+	else
+		return false;
+}
+
+static bool addi9306_writeable_register(struct device *dev, unsigned int reg)
+{
+	if (((reg >= 0x4000) && (reg <= 0x6fff)) ||
+	    ((reg >= 0x7c00) && (reg <= 0x7fff)) ||
+	    ((reg >= 0xc000) && (reg <= 0xc113)) ||
+	    ((reg >= 0xc300) && (reg <= 0xc7ff)))
+		return true;
+	else
+		return false;
+}
+
+static const struct regmap_config addi9036_i2c_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 16,
+	.max_register = 0xc7ff,
+	.writeable_reg = addi9306_writeable_register,
+	.readable_reg = addi9306_readable_register,
+	.cache_type = REGCACHE_NONE,
+};
+
+static int addi9036_power_on(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	int ret;
+
+	if (addi9036->rst_gpio)
+		gpiod_set_value_cansleep(addi9036->rst_gpio, 0);
+
+	ret = regmap_register_patch(addi9036->regmap, addi9036_powerup_setting,
+				    ARRAY_SIZE(addi9036_powerup_setting));
+	if (ret)
+		dev_err(addi9036->dev, "Could not set power up registers\n");
+
+	return ret;
+}
+
+static int addi9036_power_off(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	int ret;
+
+	ret = regmap_register_patch(addi9036->regmap,
+				    addi9036_powerdown_setting,
+				    ARRAY_SIZE(addi9036_powerdown_setting));
+	if (ret)
+		dev_err(addi9036->dev, "could not set power down registers\n");
+
+	if (addi9036->rst_gpio)
+		gpiod_set_value_cansleep(addi9036->rst_gpio, 1);
+
+	return ret;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int addi9036_g_register(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_register *reg)
+{
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	unsigned int read_val;
+	int ret;
+
+	reg->size = 2;
+	ret = regmap_read(addi9036->regmap, reg->reg, &read_val);
+	reg->val = read_val;
+
+	return ret;
+}
+
+static int addi9036_s_register(struct v4l2_subdev *sd,
+			       const struct v4l2_dbg_register *reg)
+{
+	struct addi9036 *addi9036 = to_addi9036(sd);
+
+	return regmap_write(addi9036->regmap, reg->reg, reg->val);
+}
+#endif
+
+static int addi9036_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct addi9036 *addi9036 = container_of(ctrl->handler,
+						 struct addi9036, ctrls);
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_ADDI9036_OPERATING_MODE:
+		addi9036->curr_operating_mode = ctrl->val;
+		break;
+	case V4L2_CID_PIXEL_RATE:
+	case V4L2_CID_LINK_FREQ:
+		break;
+	default:
+		dev_err(addi9036->dev, "%s > Unhandled: %x  param=%x\n",
+			__func__, ctrl->id, ctrl->val);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops addi9036_ctrl_ops = {
+	.s_ctrl = addi9036_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config addi9036_ctrl_operating_mode = {
+	.ops		= &addi9036_ctrl_ops,
+	.id		= V4L2_CID_ADDI9036_OPERATING_MODE,
+	.name		= "Operating Mode",
+	.type		= V4L2_CTRL_TYPE_INTEGER,
+	.def		= 0,
+	.min		= 0,
+	.max		= 1,
+	.step		= 1,
+};
+
+static int addi9036_enum_mbus_code(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_pad_config *cfg,
+				   struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index > 0)
+		return -EINVAL;
+
+	code->code = MEDIA_BUS_FMT_SBGGR12_1X12;
+
+	return 0;
+}
+
+static int addi9036_enum_frame_size(struct v4l2_subdev *subdev,
+				    struct v4l2_subdev_pad_config *cfg,
+				    struct v4l2_subdev_frame_size_enum *fse)
+{
+	if (fse->code != MEDIA_BUS_FMT_SBGGR12_1X12)
+		return -EINVAL;
+
+	if (fse->index >= ARRAY_SIZE(addi9036_mode_info_data))
+		return -EINVAL;
+
+	fse->min_width = addi9036_mode_info_data[fse->index].width;
+	fse->max_width = addi9036_mode_info_data[fse->index].width;
+	fse->min_height = addi9036_mode_info_data[fse->index].height;
+	fse->max_height = addi9036_mode_info_data[fse->index].height;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+addi9036_get_pad_format(struct addi9036 *addi9036,
+			struct v4l2_subdev_pad_config *cfg, unsigned int pad,
+			enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(&addi9036->sd, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &addi9036->fmt;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+}
+
+static int addi9036_get_format(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *format)
+{
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	struct v4l2_mbus_framefmt *pad_format;
+
+	pad_format = addi9036_get_pad_format(addi9036, cfg, format->pad,
+					     format->which);
+	if (IS_ERR(pad_format))
+		return PTR_ERR(pad_format);
+
+	format->format = *pad_format;
+
+	return 0;
+}
+
+static struct v4l2_rect *
+addi9036_get_pad_crop(struct addi9036 *addi9036,
+		      struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(&addi9036->sd, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &addi9036->crop;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+}
+
+static int addi9036_set_format(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *format)
+{
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	struct v4l2_mbus_framefmt *framefmt;
+	struct v4l2_rect *crop;
+	const struct addi9036_mode_info *new_mode;
+	int ret;
+
+	dev_dbg(addi9036->dev, "set_fmt: %x %dx%d %d\n",
+		format->format.code, format->format.width,
+		format->format.height, format->which);
+
+	mutex_lock(&addi9036->lock);
+
+	crop = addi9036_get_pad_crop(addi9036, cfg, format->pad,
+				     format->which);
+	if (IS_ERR(crop))
+		return PTR_ERR(crop);
+
+	new_mode = v4l2_find_nearest_size(addi9036_mode_info_data,
+					  ARRAY_SIZE(addi9036_mode_info_data),
+					  width, height, format->format.width,
+					  format->format.height);
+	crop->width = new_mode->width;
+	crop->height = new_mode->height;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		ret = v4l2_ctrl_s_ctrl_int64(addi9036->pixel_rate,
+					     new_mode->pixel_rate);
+		if (ret < 0)
+			return ret;
+
+		ret = v4l2_ctrl_s_ctrl(addi9036->link_freq,
+				       new_mode->link_freq_idx);
+		if (ret < 0)
+			return ret;
+
+		addi9036->current_mode = new_mode;
+	}
+
+	framefmt = addi9036_get_pad_format(addi9036, cfg, format->pad,
+					   format->which);
+	if (IS_ERR(framefmt))
+		return PTR_ERR(framefmt);
+
+	framefmt->width = crop->width;
+	framefmt->height = crop->height;
+	framefmt->code = MEDIA_BUS_FMT_SBGGR12_1X12;
+	framefmt->field = V4L2_FIELD_NONE;
+	framefmt->colorspace = V4L2_COLORSPACE_SRGB;
+
+	format->format = *framefmt;
+
+	mutex_unlock(&addi9036->lock);
+
+	return 0;
+}
+
+static int addi9036_entity_init_cfg(struct v4l2_subdev *subdev,
+				    struct v4l2_subdev_pad_config *cfg)
+{
+	struct v4l2_subdev_format fmt = { 0 };
+
+	fmt.which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	fmt.format.width = addi9036_mode_info_data[1].width;
+	fmt.format.height = addi9036_mode_info_data[1].height;
+
+	addi9036_set_format(subdev, cfg, &fmt);
+
+	return 0;
+}
+
+static int addi9036_get_selection(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_selection *sel)
+{
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	struct v4l2_rect *crop;
+
+	if (sel->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	crop = addi9036_get_pad_crop(addi9036, cfg, sel->pad, sel->which);
+	if (IS_ERR(crop))
+		return PTR_ERR(crop);
+
+	sel->r = *crop;
+
+	return 0;
+}
+
+static int addi9036_start_streaming(struct addi9036 *addi9036)
+{
+	uint8_t mode = addi9036->curr_operating_mode;
+
+	if (addi9036->mode_fw_blocks[mode].mode_regs == NULL) {
+		dev_err(addi9036->dev, "Selected mode has no data\n");
+		return -EINVAL;
+	}
+
+	return regmap_multi_reg_write(addi9036->regmap,
+			addi9036->mode_fw_blocks[mode].mode_regs,
+			addi9036->mode_fw_blocks[mode].regs_count);
+}
+
+static int addi9036_stop_streaming(struct addi9036 *addi9036)
+{
+	return regmap_register_patch(addi9036->regmap,
+				     addi9036_standby_setting,
+				     ARRAY_SIZE(addi9036_standby_setting));
+}
+
+static int addi9036_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct addi9036 *addi9036 = to_addi9036(subdev);
+	int ret = 0;
+
+	dev_dbg(addi9036->dev, "s_stream: %d\n", enable);
+
+	mutex_lock(&addi9036->lock);
+	if (addi9036->streaming == enable) {
+		mutex_unlock(&addi9036->lock);
+		return 0;
+	}
+
+	if (enable) {
+		ret = pm_runtime_get_sync(addi9036->dev);
+		if (ret < 0) {
+			pm_runtime_put_noidle(addi9036->dev);
+			goto err_unlock;
+		}
+
+		ret = addi9036_start_streaming(addi9036);
+		if (ret)
+			goto err_rpm_put;
+	} else {
+		addi9036_stop_streaming(addi9036);
+		pm_runtime_put(addi9036->dev);
+	}
+
+	addi9036->streaming = enable;
+	mutex_unlock(&addi9036->lock);
+
+	return ret;
+
+err_rpm_put:
+	pm_runtime_put(addi9036->dev);
+err_unlock:
+	mutex_unlock(&addi9036->lock);
+
+	return ret;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static const struct v4l2_subdev_core_ops addi9036_core_ops = {
+	.g_register	= addi9036_g_register,
+	.s_register	= addi9036_s_register,
+};
+#endif
+
+static const struct dev_pm_ops addi9036_pm_ops = {
+	SET_RUNTIME_PM_OPS(addi9036_power_on, addi9036_power_off, NULL)
+};
+
+static const struct v4l2_subdev_video_ops addi9036_video_ops = {
+	.s_stream	= addi9036_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops addi9036_subdev_pad_ops = {
+	.init_cfg		= addi9036_entity_init_cfg,
+	.enum_mbus_code		= addi9036_enum_mbus_code,
+	.enum_frame_size	= addi9036_enum_frame_size,
+	.get_fmt		= addi9036_get_format,
+	.set_fmt		= addi9036_set_format,
+	.get_selection		= addi9036_get_selection,
+};
+
+static const struct v4l2_subdev_ops addi9036_subdev_ops = {
+	.core	= &addi9036_core_ops,
+	.video	= &addi9036_video_ops,
+	.pad	= &addi9036_subdev_pad_ops,
+};
+
+static int addi9036_g_modes_from_firmware(struct v4l2_subdev *sd)
+{
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	const struct firmware *fw = addi9036->fw;
+	const struct addi9036_fw_header *fw_head;
+	const struct addi9036_mode_block *mode_block;
+	unsigned int reg_nr, chunk_len, pos, modes_nr, i, j, k;
+	struct reg_sequence *reg_seq;
+
+	if (fw->size < sizeof(struct addi9036_fw_header) ||
+	    fw->size >= 0x4000000)
+		goto err_size;
+
+	fw_head = (struct addi9036_fw_header *)fw->data;
+
+	if (memcmp(fw_head->magic, ADDI_MAGIC, ARRAY_SIZE(fw_head->magic))) {
+		dev_err(addi9036->dev, "FW loading failed: Invalid magic\n");
+		return -EINVAL;
+	}
+
+	modes_nr = le32_to_cpu(fw_head->modes_nr);
+	if (modes_nr == 0) {
+		dev_err(addi9036->dev, "FW should contain at least 1 mode.\n");
+		return -EINVAL;
+	}
+
+	__v4l2_ctrl_modify_range(addi9036->set_operating_range,
+				 addi9036->set_operating_range->minimum,
+				 modes_nr - 1, 1, 0);
+
+	addi9036->mode_fw_blocks = devm_kcalloc(addi9036->dev, modes_nr,
+			     sizeof(struct addi9036_mode_fw_block), GFP_KERNEL);
+	if (!addi9036->mode_fw_blocks)
+		return -ENOMEM;
+
+	pos = sizeof(struct addi9036_fw_header);
+
+	for (i = 0; i < modes_nr; i++) {
+		if (fw->size < pos + sizeof(struct addi9036_mode_block))
+			goto err_size;
+
+		mode_block = (struct addi9036_mode_block *)(fw->data + pos);
+		chunk_len = le32_to_cpu(mode_block->size_bytes);
+		pos += sizeof(struct addi9036_mode_block);
+
+		if (fw->size < pos + chunk_len)
+			goto err_size;
+
+		reg_nr = chunk_len / sizeof(uint16_t) / 2;
+		reg_seq = devm_kcalloc(addi9036->dev, reg_nr,
+				       sizeof(struct reg_sequence), GFP_KERNEL);
+		if (!reg_seq)
+			return -ENOMEM;
+
+		for (j = 0, k = 0; j < reg_nr * 2; j += 2, k++) {
+			reg_seq[k].reg = le16_to_cpu(mode_block->data[j]);
+			reg_seq[k].def = le16_to_cpu(mode_block->data[j + 1]);
+		}
+
+		addi9036->mode_fw_blocks[i].mode_regs = reg_seq;
+		addi9036->mode_fw_blocks[i].regs_count = reg_nr;
+
+		pos += chunk_len;
+	}
+	return 0;
+
+err_size:
+	dev_err(addi9036->dev, "FW loading failed: Invalid size\n");
+	return -EINVAL;
+}
+
+static int addi9036_mode_firmware_load(struct v4l2_subdev *sd)
+{
+	struct addi9036 *addi9036 = to_addi9036(sd);
+	int ret;
+
+	ret = request_firmware(&addi9036->fw, FW_FILE_NAME, addi9036->dev);
+	if (ret < 0) {
+		dev_err(addi9036->dev, "FW request failed\n");
+		return ret;
+	}
+
+	ret = addi9036_g_modes_from_firmware(sd);
+
+	release_firmware(addi9036->fw);
+	if (ret < 0) {
+		dev_err(addi9036->dev, "FW parsing failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int addi9036_probe(struct i2c_client *client)
+{
+	struct v4l2_fwnode_endpoint bus_cfg = {
+		.bus_type = V4L2_MBUS_CSI2_DPHY
+	};
+	struct device *dev = &client->dev;
+	struct fwnode_handle *endpoint;
+	struct addi9036 *addi9036;
+	int ret;
+
+	dev_dbg(dev, "%s: i2c addr = 0x%x\n", __func__, client->addr);
+
+	addi9036 = devm_kzalloc(dev, sizeof(struct addi9036), GFP_KERNEL);
+	if (!addi9036)
+		return -ENOMEM;
+
+	addi9036->dev = dev;
+
+	addi9036->regmap = devm_regmap_init_i2c(client,
+						&addi9036_i2c_regmap_config);
+	if (IS_ERR(addi9036->regmap)) {
+		dev_err(dev, "Error initializing i2c regmap\n");
+		return PTR_ERR(addi9036->regmap);
+	}
+
+	mutex_init(&addi9036->lock);
+
+	endpoint = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0,
+					     FWNODE_GRAPH_ENDPOINT_NEXT);
+	if (!endpoint) {
+		dev_err(dev, "endpoint node not found\n");
+		return -EINVAL;
+	}
+
+	ret = v4l2_fwnode_endpoint_parse(endpoint, &bus_cfg);
+	fwnode_handle_put(endpoint);
+	if (ret < 0) {
+		dev_err(dev, "parsing endpoint node failed\n");
+		return ret;
+	}
+
+	addi9036->rst_gpio = gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(addi9036->rst_gpio))
+		dev_info(dev, "Unable to get \"reset\" gpio\n");
+
+	v4l2_ctrl_handler_init(&addi9036->ctrls, 3);
+
+	addi9036->pixel_rate = v4l2_ctrl_new_std(&addi9036->ctrls,
+						  &addi9036_ctrl_ops,
+						  V4L2_CID_PIXEL_RATE,
+						  1, INT_MAX, 1, 1);
+	addi9036->link_freq = v4l2_ctrl_new_int_menu(&addi9036->ctrls,
+						     &addi9036_ctrl_ops,
+						     V4L2_CID_LINK_FREQ,
+						     ARRAY_SIZE(
+							     link_freq_tbl) - 1,
+						     0, link_freq_tbl);
+	if (addi9036->link_freq)
+		addi9036->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	addi9036->set_operating_range = v4l2_ctrl_new_custom(&addi9036->ctrls,
+						&addi9036_ctrl_operating_mode,
+						NULL);
+
+	ret = addi9036->ctrls.error;
+	if (ret) {
+		dev_err(dev, "%s: control initialization error %d\n",
+			__func__, ret);
+		goto free_ctrl;
+	}
+	addi9036->sd.ctrl_handler = &addi9036->ctrls;
+
+	v4l2_i2c_subdev_init(&addi9036->sd, client, &addi9036_subdev_ops);
+	addi9036->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	addi9036->pad.flags = MEDIA_PAD_FL_SOURCE;
+	addi9036->sd.dev = &client->dev;
+	addi9036->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+	ret = media_entity_pads_init(&addi9036->sd.entity, 1, &addi9036->pad);
+	if (ret < 0) {
+		dev_err(dev, "could not register media entity\n");
+		goto free_ctrl;
+	}
+
+	ret = addi9036_mode_firmware_load(&addi9036->sd);
+	if (ret < 0)
+		return ret;
+
+	addi9036_entity_init_cfg(&addi9036->sd, NULL);
+
+	ret = v4l2_async_register_subdev(&addi9036->sd);
+	if (ret < 0) {
+		dev_err(dev, "could not register v4l2 device\n");
+		goto free_entity;
+	}
+
+	ret = addi9036_power_on(dev);
+	if (ret < 0) {
+		dev_err(dev, "Could not power on the device\n");
+		goto free_entity;
+	}
+
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+	pm_runtime_idle(dev);
+
+	return 0;
+
+free_entity:
+	media_entity_cleanup(&addi9036->sd.entity);
+free_ctrl:
+	v4l2_ctrl_handler_free(&addi9036->ctrls);
+	mutex_destroy(&addi9036->lock);
+
+	return ret;
+}
+
+static int addi9036_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct addi9036 *addi9036 = to_addi9036(sd);
+
+	v4l2_async_unregister_subdev(&addi9036->sd);
+	media_entity_cleanup(&addi9036->sd.entity);
+	if (addi9036->rst_gpio)
+		gpiod_put(addi9036->rst_gpio);
+	v4l2_ctrl_handler_free(&addi9036->ctrls);
+	mutex_destroy(&addi9036->lock);
+
+	pm_runtime_disable(addi9036->dev);
+	if (!pm_runtime_status_suspended(addi9036->dev))
+		addi9036_power_off(addi9036->dev);
+	pm_runtime_set_suspended(addi9036->dev);
+
+	return 0;
+}
+
+static const struct of_device_id addi9036_of_match[] = {
+	{ .compatible = "adi,addi9036" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, addi9036_of_match);
+
+static struct i2c_driver addi9036_i2c_driver = {
+	.driver			= {
+		.of_match_table = addi9036_of_match,
+		.name		= "addi9036",
+		.pm		= &addi9036_pm_ops,
+	},
+	.probe_new		= addi9036_probe,
+	.remove			= addi9036_remove,
+};
+
+module_i2c_driver(addi9036_i2c_driver);
+
+MODULE_DESCRIPTION("Analog Devices ADDI9036 Camera Driver");
+MODULE_AUTHOR("Bogdan Togorean");
+MODULE_LICENSE("GPL v2");
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index c8e0f84d204d..1b1b4072f8b5 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -219,6 +219,12 @@ enum v4l2_colorfx {
  */
 #define V4L2_CID_USER_ALLEGRO_BASE		(V4L2_CID_USER_BASE + 0x1170)
 
+/*
+ * The base for the addi9036 driver controls.
+ * We reserve 16 controls for this driver.
+ */
+#define V4L2_CID_USER_ADDI9036_BASE		(V4L2_CID_USER_BASE + 0x10e0)
+
 /* MPEG-class control IDs */
 /* The MPEG controls are applicable to all codec controls
  * and the 'MPEG' part of the define is historical */

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [git:media_stage/master] media: i2c: Add driver for the Analog Devices ADDI9036 ToF front-end
  2021-12-14 12:44 [git:media_stage/master] media: i2c: Add driver for the Analog Devices ADDI9036 ToF front-end Mauro Carvalho Chehab
@ 2021-12-15  0:00   ` kernel test robot
  0 siblings, 0 replies; 3+ messages in thread
From: kernel test robot @ 2021-12-15  0:00 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 8777 bytes --]

Hi Mauro,

I love your patch! Yet something to improve:

[auto build test ERROR on media-tree/master]
[also build test ERROR on linux/master linus/master v5.16-rc5 next-20211213]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Mauro-Carvalho-Chehab/media-i2c-Add-driver-for-the-Analog-Devices-ADDI9036-ToF-front-end/20211214-211851
base:   git://linuxtv.org/media_tree.git master
config: nios2-allyesconfig (https://download.01.org/0day-ci/archive/20211215/202112150733.a6LCjbXP-lkp(a)intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ec03b2029965b84eff6a7d1e8fe130330c3e69ed
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Mauro-Carvalho-Chehab/media-i2c-Add-driver-for-the-Analog-Devices-ADDI9036-ToF-front-end/20211214-211851
        git checkout ec03b2029965b84eff6a7d1e8fe130330c3e69ed
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=nios2 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/media/i2c/addi9036.c: In function 'addi9036_get_pad_format':
>> drivers/media/i2c/addi9036.c:310:66: error: passing argument 2 of 'v4l2_subdev_get_try_format' from incompatible pointer type [-Werror=incompatible-pointer-types]
     310 |                 return v4l2_subdev_get_try_format(&addi9036->sd, cfg, pad);
         |                                                                  ^~~
         |                                                                  |
         |                                                                  struct v4l2_subdev_pad_config *
   In file included from drivers/media/i2c/addi9036.c:17:
   include/media/v4l2-subdev.h:995:54: note: expected 'struct v4l2_subdev_state *' but argument is of type 'struct v4l2_subdev_pad_config *'
     995 |                            struct v4l2_subdev_state *state,
         |                            ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
   drivers/media/i2c/addi9036.c: In function 'addi9036_get_pad_crop':
>> drivers/media/i2c/addi9036.c:342:64: error: passing argument 2 of 'v4l2_subdev_get_try_crop' from incompatible pointer type [-Werror=incompatible-pointer-types]
     342 |                 return v4l2_subdev_get_try_crop(&addi9036->sd, cfg, pad);
         |                                                                ^~~
         |                                                                |
         |                                                                struct v4l2_subdev_pad_config *
   In file included from drivers/media/i2c/addi9036.c:17:
   include/media/v4l2-subdev.h:1013:52: note: expected 'struct v4l2_subdev_state *' but argument is of type 'struct v4l2_subdev_pad_config *'
    1013 |                          struct v4l2_subdev_state *state,
         |                          ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
   drivers/media/i2c/addi9036.c: At top level:
>> drivers/media/i2c/addi9036.c:521:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *)' [-Werror=incompatible-pointer-types]
     521 |         .init_cfg               = addi9036_entity_init_cfg,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:521:35: note: (near initialization for 'addi9036_subdev_pad_ops.init_cfg')
>> drivers/media/i2c/addi9036.c:522:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_mbus_code_enum *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_mbus_code_enum *)' [-Werror=incompatible-pointer-types]
     522 |         .enum_mbus_code         = addi9036_enum_mbus_code,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:522:35: note: (near initialization for 'addi9036_subdev_pad_ops.enum_mbus_code')
>> drivers/media/i2c/addi9036.c:523:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_frame_size_enum *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_frame_size_enum *)' [-Werror=incompatible-pointer-types]
     523 |         .enum_frame_size        = addi9036_enum_frame_size,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:523:35: note: (near initialization for 'addi9036_subdev_pad_ops.enum_frame_size')
>> drivers/media/i2c/addi9036.c:524:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_format *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_format *)' [-Werror=incompatible-pointer-types]
     524 |         .get_fmt                = addi9036_get_format,
         |                                   ^~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:524:35: note: (near initialization for 'addi9036_subdev_pad_ops.get_fmt')
   drivers/media/i2c/addi9036.c:525:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_format *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_format *)' [-Werror=incompatible-pointer-types]
     525 |         .set_fmt                = addi9036_set_format,
         |                                   ^~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:525:35: note: (near initialization for 'addi9036_subdev_pad_ops.set_fmt')
>> drivers/media/i2c/addi9036.c:526:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_selection *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_selection *)' [-Werror=incompatible-pointer-types]
     526 |         .get_selection          = addi9036_get_selection,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:526:35: note: (near initialization for 'addi9036_subdev_pad_ops.get_selection')
   cc1: some warnings being treated as errors


vim +/v4l2_subdev_get_try_format +310 drivers/media/i2c/addi9036.c

   302	
   303	static struct v4l2_mbus_framefmt *
   304	addi9036_get_pad_format(struct addi9036 *addi9036,
   305				struct v4l2_subdev_pad_config *cfg, unsigned int pad,
   306				enum v4l2_subdev_format_whence which)
   307	{
   308		switch (which) {
   309		case V4L2_SUBDEV_FORMAT_TRY:
 > 310			return v4l2_subdev_get_try_format(&addi9036->sd, cfg, pad);
   311		case V4L2_SUBDEV_FORMAT_ACTIVE:
   312			return &addi9036->fmt;
   313		default:
   314			return ERR_PTR(-EINVAL);
   315		}
   316	}
   317	
   318	static int addi9036_get_format(struct v4l2_subdev *sd,
   319				       struct v4l2_subdev_pad_config *cfg,
   320				       struct v4l2_subdev_format *format)
   321	{
   322		struct addi9036 *addi9036 = to_addi9036(sd);
   323		struct v4l2_mbus_framefmt *pad_format;
   324	
   325		pad_format = addi9036_get_pad_format(addi9036, cfg, format->pad,
   326						     format->which);
   327		if (IS_ERR(pad_format))
   328			return PTR_ERR(pad_format);
   329	
   330		format->format = *pad_format;
   331	
   332		return 0;
   333	}
   334	
   335	static struct v4l2_rect *
   336	addi9036_get_pad_crop(struct addi9036 *addi9036,
   337			      struct v4l2_subdev_pad_config *cfg,
   338			      unsigned int pad, enum v4l2_subdev_format_whence which)
   339	{
   340		switch (which) {
   341		case V4L2_SUBDEV_FORMAT_TRY:
 > 342			return v4l2_subdev_get_try_crop(&addi9036->sd, cfg, pad);
   343		case V4L2_SUBDEV_FORMAT_ACTIVE:
   344			return &addi9036->crop;
   345		default:
   346			return ERR_PTR(-EINVAL);
   347		}
   348	}
   349	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [git:media_stage/master] media: i2c: Add driver for the Analog Devices ADDI9036 ToF front-end
@ 2021-12-15  0:00   ` kernel test robot
  0 siblings, 0 replies; 3+ messages in thread
From: kernel test robot @ 2021-12-15  0:00 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, linuxtv-commits
  Cc: kbuild-all, linux-media, Bogdan Togorean, linux-kernel

Hi Mauro,

I love your patch! Yet something to improve:

[auto build test ERROR on media-tree/master]
[also build test ERROR on linux/master linus/master v5.16-rc5 next-20211213]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Mauro-Carvalho-Chehab/media-i2c-Add-driver-for-the-Analog-Devices-ADDI9036-ToF-front-end/20211214-211851
base:   git://linuxtv.org/media_tree.git master
config: nios2-allyesconfig (https://download.01.org/0day-ci/archive/20211215/202112150733.a6LCjbXP-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ec03b2029965b84eff6a7d1e8fe130330c3e69ed
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Mauro-Carvalho-Chehab/media-i2c-Add-driver-for-the-Analog-Devices-ADDI9036-ToF-front-end/20211214-211851
        git checkout ec03b2029965b84eff6a7d1e8fe130330c3e69ed
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=nios2 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/media/i2c/addi9036.c: In function 'addi9036_get_pad_format':
>> drivers/media/i2c/addi9036.c:310:66: error: passing argument 2 of 'v4l2_subdev_get_try_format' from incompatible pointer type [-Werror=incompatible-pointer-types]
     310 |                 return v4l2_subdev_get_try_format(&addi9036->sd, cfg, pad);
         |                                                                  ^~~
         |                                                                  |
         |                                                                  struct v4l2_subdev_pad_config *
   In file included from drivers/media/i2c/addi9036.c:17:
   include/media/v4l2-subdev.h:995:54: note: expected 'struct v4l2_subdev_state *' but argument is of type 'struct v4l2_subdev_pad_config *'
     995 |                            struct v4l2_subdev_state *state,
         |                            ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
   drivers/media/i2c/addi9036.c: In function 'addi9036_get_pad_crop':
>> drivers/media/i2c/addi9036.c:342:64: error: passing argument 2 of 'v4l2_subdev_get_try_crop' from incompatible pointer type [-Werror=incompatible-pointer-types]
     342 |                 return v4l2_subdev_get_try_crop(&addi9036->sd, cfg, pad);
         |                                                                ^~~
         |                                                                |
         |                                                                struct v4l2_subdev_pad_config *
   In file included from drivers/media/i2c/addi9036.c:17:
   include/media/v4l2-subdev.h:1013:52: note: expected 'struct v4l2_subdev_state *' but argument is of type 'struct v4l2_subdev_pad_config *'
    1013 |                          struct v4l2_subdev_state *state,
         |                          ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
   drivers/media/i2c/addi9036.c: At top level:
>> drivers/media/i2c/addi9036.c:521:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *)' [-Werror=incompatible-pointer-types]
     521 |         .init_cfg               = addi9036_entity_init_cfg,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:521:35: note: (near initialization for 'addi9036_subdev_pad_ops.init_cfg')
>> drivers/media/i2c/addi9036.c:522:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_mbus_code_enum *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_mbus_code_enum *)' [-Werror=incompatible-pointer-types]
     522 |         .enum_mbus_code         = addi9036_enum_mbus_code,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:522:35: note: (near initialization for 'addi9036_subdev_pad_ops.enum_mbus_code')
>> drivers/media/i2c/addi9036.c:523:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_frame_size_enum *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_frame_size_enum *)' [-Werror=incompatible-pointer-types]
     523 |         .enum_frame_size        = addi9036_enum_frame_size,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:523:35: note: (near initialization for 'addi9036_subdev_pad_ops.enum_frame_size')
>> drivers/media/i2c/addi9036.c:524:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_format *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_format *)' [-Werror=incompatible-pointer-types]
     524 |         .get_fmt                = addi9036_get_format,
         |                                   ^~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:524:35: note: (near initialization for 'addi9036_subdev_pad_ops.get_fmt')
   drivers/media/i2c/addi9036.c:525:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_format *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_format *)' [-Werror=incompatible-pointer-types]
     525 |         .set_fmt                = addi9036_set_format,
         |                                   ^~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:525:35: note: (near initialization for 'addi9036_subdev_pad_ops.set_fmt')
>> drivers/media/i2c/addi9036.c:526:35: error: initialization of 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_state *, struct v4l2_subdev_selection *)' from incompatible pointer type 'int (*)(struct v4l2_subdev *, struct v4l2_subdev_pad_config *, struct v4l2_subdev_selection *)' [-Werror=incompatible-pointer-types]
     526 |         .get_selection          = addi9036_get_selection,
         |                                   ^~~~~~~~~~~~~~~~~~~~~~
   drivers/media/i2c/addi9036.c:526:35: note: (near initialization for 'addi9036_subdev_pad_ops.get_selection')
   cc1: some warnings being treated as errors


vim +/v4l2_subdev_get_try_format +310 drivers/media/i2c/addi9036.c

   302	
   303	static struct v4l2_mbus_framefmt *
   304	addi9036_get_pad_format(struct addi9036 *addi9036,
   305				struct v4l2_subdev_pad_config *cfg, unsigned int pad,
   306				enum v4l2_subdev_format_whence which)
   307	{
   308		switch (which) {
   309		case V4L2_SUBDEV_FORMAT_TRY:
 > 310			return v4l2_subdev_get_try_format(&addi9036->sd, cfg, pad);
   311		case V4L2_SUBDEV_FORMAT_ACTIVE:
   312			return &addi9036->fmt;
   313		default:
   314			return ERR_PTR(-EINVAL);
   315		}
   316	}
   317	
   318	static int addi9036_get_format(struct v4l2_subdev *sd,
   319				       struct v4l2_subdev_pad_config *cfg,
   320				       struct v4l2_subdev_format *format)
   321	{
   322		struct addi9036 *addi9036 = to_addi9036(sd);
   323		struct v4l2_mbus_framefmt *pad_format;
   324	
   325		pad_format = addi9036_get_pad_format(addi9036, cfg, format->pad,
   326						     format->which);
   327		if (IS_ERR(pad_format))
   328			return PTR_ERR(pad_format);
   329	
   330		format->format = *pad_format;
   331	
   332		return 0;
   333	}
   334	
   335	static struct v4l2_rect *
   336	addi9036_get_pad_crop(struct addi9036 *addi9036,
   337			      struct v4l2_subdev_pad_config *cfg,
   338			      unsigned int pad, enum v4l2_subdev_format_whence which)
   339	{
   340		switch (which) {
   341		case V4L2_SUBDEV_FORMAT_TRY:
 > 342			return v4l2_subdev_get_try_crop(&addi9036->sd, cfg, pad);
   343		case V4L2_SUBDEV_FORMAT_ACTIVE:
   344			return &addi9036->crop;
   345		default:
   346			return ERR_PTR(-EINVAL);
   347		}
   348	}
   349	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-12-15  0:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-12-14 12:44 [git:media_stage/master] media: i2c: Add driver for the Analog Devices ADDI9036 ToF front-end Mauro Carvalho Chehab
2021-12-15  0:00 ` kernel test robot
2021-12-15  0:00   ` kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.