From 3180449e6c5c54fbcb32b5ec3f5ea3d20f3a7041 Mon Sep 17 00:00:00 2001 From: Nikolay Kyx Date: Sun, 21 Feb 2021 15:10:20 +0300 Subject: staging: media: ipu3: code style fix - avoid multiple line dereference This patch fixes the following checkpatch.pl warning: WARNING: Avoid multiple line dereference in file ipu3-css.c Signed-off-by: Nikolay Kyx Signed-off-by: Hans Verkuil --- drivers/staging/media/ipu3/ipu3-css.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/ipu3/ipu3-css.c b/drivers/staging/media/ipu3/ipu3-css.c index 8c70497d744c..9c10f1474c35 100644 --- a/drivers/staging/media/ipu3/ipu3-css.c +++ b/drivers/staging/media/ipu3/ipu3-css.c @@ -1193,14 +1193,14 @@ static int imgu_css_binary_preallocate(struct imgu_css *css, unsigned int pipe) for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++) if (!imgu_dmamap_alloc(imgu, - &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF]. - mem[i], CSS_BDS_SIZE)) + &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].mem[i], + CSS_BDS_SIZE)) goto out_of_memory; for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++) if (!imgu_dmamap_alloc(imgu, - &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR]. - mem[i], CSS_GDC_SIZE)) + &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].mem[i], + CSS_GDC_SIZE)) goto out_of_memory; return 0; @@ -1428,13 +1428,11 @@ static int imgu_css_map_init(struct imgu_css *css, unsigned int pipe) for (p = 0; p < IPU3_CSS_PIPE_ID_NUM; p++) for (i = 0; i < IMGU_ABI_MAX_STAGES; i++) { if (!imgu_dmamap_alloc(imgu, - &css_pipe-> - xmem_sp_stage_ptrs[p][i], + &css_pipe->xmem_sp_stage_ptrs[p][i], sizeof(struct imgu_abi_sp_stage))) return -ENOMEM; if (!imgu_dmamap_alloc(imgu, - &css_pipe-> - xmem_isp_stage_ptrs[p][i], + &css_pipe->xmem_isp_stage_ptrs[p][i], sizeof(struct imgu_abi_isp_stage))) return -ENOMEM; } -- cgit v1.2.3 From cd063027c3049bbdd8bbfa65ca46b51a373686f3 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 25 Apr 2023 11:08:04 +0200 Subject: media: imx: Unstage the imx8mq-mipi-csi2 driver The imx8mq-mipi-csi2 MIPI CSI-2 receiver driver is used and maintained. There is no reason to keep it in staging. The accompanying CSI bridge driver that uses it is in drivers/media/platform/nxp as well. One TODO is to get rid of csi_state's "state" and "lock" variables. Especially make sure suspend/resume is working without them. That can very well be worked on from the new location. Also add a MAINTAINERS section for the imx8mq-mipi-csi2 mipi receiver driver. Signed-off-by: Martin Kepplinger Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- MAINTAINERS | 6 +- drivers/media/platform/nxp/Kconfig | 11 + drivers/media/platform/nxp/Makefile | 1 + drivers/media/platform/nxp/imx8mq-mipi-csi2.c | 966 ++++++++++++++++++++++++++ drivers/staging/media/imx/Kconfig | 10 - drivers/staging/media/imx/Makefile | 2 - drivers/staging/media/imx/imx8mq-mipi-csi2.c | 966 -------------------------- 7 files changed, 983 insertions(+), 979 deletions(-) create mode 100644 drivers/media/platform/nxp/imx8mq-mipi-csi2.c delete mode 100644 drivers/staging/media/imx/imx8mq-mipi-csi2.c (limited to 'drivers/staging') diff --git a/MAINTAINERS b/MAINTAINERS index b955943e2697..2f1ab99cc27c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13004,17 +13004,21 @@ F: drivers/staging/media/imx/ F: include/linux/imx-media.h F: include/media/imx.h -MEDIA DRIVERS FOR FREESCALE IMX7 +MEDIA DRIVERS FOR FREESCALE IMX7/8 M: Rui Miguel Silva M: Laurent Pinchart +M: Martin Kepplinger +R: Purism Kernel Team L: linux-media@vger.kernel.org S: Maintained T: git git://linuxtv.org/media_tree.git F: Documentation/admin-guide/media/imx7.rst F: Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml +F: Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml F: drivers/media/platform/nxp/imx-mipi-csis.c F: drivers/media/platform/nxp/imx7-media-csi.c +F: drivers/media/platform/nxp/imx8mq-mipi-csi.c MEDIA DRIVERS FOR HELENE M: Abylay Ospan diff --git a/drivers/media/platform/nxp/Kconfig b/drivers/media/platform/nxp/Kconfig index a0ca6b297fb8..40e3436669e2 100644 --- a/drivers/media/platform/nxp/Kconfig +++ b/drivers/media/platform/nxp/Kconfig @@ -17,6 +17,17 @@ config VIDEO_IMX7_CSI Driver for the NXP Camera Sensor Interface (CSI) Bridge. This device is found in the i.MX6UL/L, i.MX7 and i.MX8M[MQ] SoCs. +config VIDEO_IMX8MQ_MIPI_CSI2 + tristate "NXP i.MX8MQ MIPI CSI-2 receiver" + depends on ARCH_MXC || COMPILE_TEST + depends on VIDEO_DEV + select MEDIA_CONTROLLER + select V4L2_FWNODE + select VIDEO_V4L2_SUBDEV_API + help + Video4Linux2 driver for the MIPI CSI-2 receiver found on the i.MX8MQ + SoC. + config VIDEO_IMX_MIPI_CSIS tristate "NXP MIPI CSI-2 CSIS receiver found on i.MX7 and i.MX8 models" depends on ARCH_MXC || COMPILE_TEST diff --git a/drivers/media/platform/nxp/Makefile b/drivers/media/platform/nxp/Makefile index b8e672b75fed..4d90eb713652 100644 --- a/drivers/media/platform/nxp/Makefile +++ b/drivers/media/platform/nxp/Makefile @@ -5,6 +5,7 @@ obj-y += imx-jpeg/ obj-y += imx8-isi/ obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o +obj-$(CONFIG_VIDEO_IMX8MQ_MIPI_CSI2) += imx8mq-mipi-csi2.o obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o diff --git a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c new file mode 100644 index 000000000000..ca2efcc21efe --- /dev/null +++ b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c @@ -0,0 +1,966 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver + * + * Copyright (C) 2021 Purism SPC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MIPI_CSI2_DRIVER_NAME "imx8mq-mipi-csi2" +#define MIPI_CSI2_SUBDEV_NAME MIPI_CSI2_DRIVER_NAME + +#define MIPI_CSI2_PAD_SINK 0 +#define MIPI_CSI2_PAD_SOURCE 1 +#define MIPI_CSI2_PADS_NUM 2 + +#define MIPI_CSI2_DEF_PIX_WIDTH 640 +#define MIPI_CSI2_DEF_PIX_HEIGHT 480 + +/* Register map definition */ + +/* i.MX8MQ CSI-2 controller CSR */ +#define CSI2RX_CFG_NUM_LANES 0x100 +#define CSI2RX_CFG_DISABLE_DATA_LANES 0x104 +#define CSI2RX_BIT_ERR 0x108 +#define CSI2RX_IRQ_STATUS 0x10c +#define CSI2RX_IRQ_MASK 0x110 +#define CSI2RX_IRQ_MASK_ALL 0x1ff +#define CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE 0x8 +#define CSI2RX_ULPS_STATUS 0x114 +#define CSI2RX_PPI_ERRSOT_HS 0x118 +#define CSI2RX_PPI_ERRSOTSYNC_HS 0x11c +#define CSI2RX_PPI_ERRESC 0x120 +#define CSI2RX_PPI_ERRSYNCESC 0x124 +#define CSI2RX_PPI_ERRCONTROL 0x128 +#define CSI2RX_CFG_DISABLE_PAYLOAD_0 0x12c +#define CSI2RX_CFG_VID_VC_IGNORE 0x180 +#define CSI2RX_CFG_VID_VC 0x184 +#define CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL 0x188 +#define CSI2RX_CFG_DISABLE_PAYLOAD_1 0x130 + +enum { + ST_POWERED = 1, + ST_STREAMING = 2, + ST_SUSPENDED = 4, +}; + +enum imx8mq_mipi_csi_clk { + CSI2_CLK_CORE, + CSI2_CLK_ESC, + CSI2_CLK_UI, + CSI2_NUM_CLKS, +}; + +static const char * const imx8mq_mipi_csi_clk_id[CSI2_NUM_CLKS] = { + [CSI2_CLK_CORE] = "core", + [CSI2_CLK_ESC] = "esc", + [CSI2_CLK_UI] = "ui", +}; + +#define CSI2_NUM_CLKS ARRAY_SIZE(imx8mq_mipi_csi_clk_id) + +#define GPR_CSI2_1_RX_ENABLE BIT(13) +#define GPR_CSI2_1_VID_INTFC_ENB BIT(12) +#define GPR_CSI2_1_HSEL BIT(10) +#define GPR_CSI2_1_CONT_CLK_MODE BIT(8) +#define GPR_CSI2_1_S_PRG_RXHS_SETTLE(x) (((x) & 0x3f) << 2) + +/* + * The send level configures the number of entries that must accumulate in + * the Pixel FIFO before the data will be transferred to the video output. + * The exact value needed for this configuration is dependent on the rate at + * which the sensor transfers data to the CSI-2 Controller and the user + * video clock. + * + * The calculation is the classical rate-in rate-out type of problem: If the + * video bandwidth is 10% faster than the incoming mipi data and the video + * line length is 500 pixels, then the fifo should be allowed to fill + * 10% of the line length or 50 pixels. If the gap data is ok, then the level + * can be set to 16 and ignored. + */ +#define CSI2RX_SEND_LEVEL 64 + +struct csi_state { + struct device *dev; + void __iomem *regs; + struct clk_bulk_data clks[CSI2_NUM_CLKS]; + struct reset_control *rst; + struct regulator *mipi_phy_regulator; + + struct v4l2_subdev sd; + struct media_pad pads[MIPI_CSI2_PADS_NUM]; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *src_sd; + + struct v4l2_mbus_config_mipi_csi2 bus; + + struct mutex lock; /* Protect state */ + u32 state; + + struct regmap *phy_gpr; + u8 phy_gpr_reg; + + struct icc_path *icc_path; + s32 icc_path_bw; +}; + +/* ----------------------------------------------------------------------------- + * Format helpers + */ + +struct csi2_pix_format { + u32 code; + u8 width; +}; + +static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = { + /* RAW (Bayer and greyscale) formats. */ + { + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_Y8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SGBRG10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_Y10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SBGGR12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SGRBG12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_Y12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SBGGR14_1X14, + .width = 14, + }, { + .code = MEDIA_BUS_FMT_SGBRG14_1X14, + .width = 14, + }, { + .code = MEDIA_BUS_FMT_SGRBG14_1X14, + .width = 14, + }, { + .code = MEDIA_BUS_FMT_SRGGB14_1X14, + .width = 14, + }, + /* YUV formats */ + { + .code = MEDIA_BUS_FMT_YUYV8_1X16, + .width = 16, + }, { + .code = MEDIA_BUS_FMT_UYVY8_1X16, + .width = 16, + } +}; + +static const struct csi2_pix_format *find_csi2_format(u32 code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(imx8mq_mipi_csi_formats); i++) + if (code == imx8mq_mipi_csi_formats[i].code) + return &imx8mq_mipi_csi_formats[i]; + return NULL; +} + +/* ----------------------------------------------------------------------------- + * Hardware configuration + */ + +static inline void imx8mq_mipi_csi_write(struct csi_state *state, u32 reg, u32 val) +{ + writel(val, state->regs + reg); +} + +static int imx8mq_mipi_csi_sw_reset(struct csi_state *state) +{ + int ret; + + /* + * these are most likely self-clearing reset bits. to make it + * more clear, the reset-imx7 driver should implement the + * .reset() operation. + */ + ret = reset_control_assert(state->rst); + if (ret < 0) { + dev_err(state->dev, "Failed to assert resets: %d\n", ret); + return ret; + } + + return 0; +} + +static void imx8mq_mipi_csi_set_params(struct csi_state *state) +{ + int lanes = state->bus.num_data_lanes; + + imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, lanes - 1); + imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, + (0xf << lanes) & 0xf); + imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, CSI2RX_IRQ_MASK_ALL); + /* + * 0x180 bit 0 controls the Virtual Channel behaviour: when set the + * interface ignores the Virtual Channel (VC) field in received packets; + * when cleared it causes the interface to only accept packets whose VC + * matches the value to which VC is set at offset 0x184. + */ + imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_VC_IGNORE, 1); + imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL, + CSI2RX_SEND_LEVEL); +} + +static int imx8mq_mipi_csi_clk_enable(struct csi_state *state) +{ + return clk_bulk_prepare_enable(CSI2_NUM_CLKS, state->clks); +} + +static void imx8mq_mipi_csi_clk_disable(struct csi_state *state) +{ + clk_bulk_disable_unprepare(CSI2_NUM_CLKS, state->clks); +} + +static int imx8mq_mipi_csi_clk_get(struct csi_state *state) +{ + unsigned int i; + + for (i = 0; i < CSI2_NUM_CLKS; i++) + state->clks[i].id = imx8mq_mipi_csi_clk_id[i]; + + return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks); +} + +static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state, + struct v4l2_subdev_state *sd_state, + u32 *hs_settle) +{ + s64 link_freq; + u32 lane_rate; + unsigned long esc_clk_rate; + u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns; + const struct v4l2_mbus_framefmt *fmt; + const struct csi2_pix_format *csi2_fmt; + + /* Calculate the line rate from the pixel rate. */ + + fmt = v4l2_subdev_get_pad_format(&state->sd, sd_state, MIPI_CSI2_PAD_SINK); + csi2_fmt = find_csi2_format(fmt->code); + + link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler, + csi2_fmt->width, + state->bus.num_data_lanes * 2); + if (link_freq < 0) { + dev_err(state->dev, "Unable to obtain link frequency: %d\n", + (int)link_freq); + return link_freq; + } + + lane_rate = link_freq * 2; + if (lane_rate < 80000000 || lane_rate > 1500000000) { + dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate); + return -EINVAL; + } + + /* + * The D-PHY specification requires Ths-settle to be in the range + * 85ns + 6*UI to 140ns + 10*UI, with the unit interval UI being half + * the clock period. + * + * The Ths-settle value is expressed in the hardware as a multiple of + * the Esc clock period: + * + * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc + * + * Due to the one cycle inaccuracy introduced by rounding, the + * documentation recommends picking a value away from the boundaries. + * Let's pick the average. + */ + esc_clk_rate = clk_get_rate(state->clks[CSI2_CLK_ESC].clk); + if (!esc_clk_rate) { + dev_err(state->dev, "Could not get esc clock rate.\n"); + return -EINVAL; + } + + dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate); + esc_clk_period_ns = 1000000000 / esc_clk_rate; + + min_ths_settle = 85 + 6 * 1000000 / (lane_rate / 1000); + max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000); + ths_settle_ns = (min_ths_settle + max_ths_settle) / 2; + + *hs_settle = ths_settle_ns / esc_clk_period_ns - 1; + + dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n", + lane_rate, ths_settle_ns, *hs_settle); + + return 0; +} + +static int imx8mq_mipi_csi_start_stream(struct csi_state *state, + struct v4l2_subdev_state *sd_state) +{ + int ret; + u32 hs_settle = 0; + + ret = imx8mq_mipi_csi_sw_reset(state); + if (ret) + return ret; + + imx8mq_mipi_csi_set_params(state); + ret = imx8mq_mipi_csi_calc_hs_settle(state, sd_state, &hs_settle); + if (ret) + return ret; + + regmap_update_bits(state->phy_gpr, + state->phy_gpr_reg, + 0x3fff, + GPR_CSI2_1_RX_ENABLE | + GPR_CSI2_1_VID_INTFC_ENB | + GPR_CSI2_1_HSEL | + GPR_CSI2_1_CONT_CLK_MODE | + GPR_CSI2_1_S_PRG_RXHS_SETTLE(hs_settle)); + + return 0; +} + +static void imx8mq_mipi_csi_stop_stream(struct csi_state *state) +{ + imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf); +} + +/* ----------------------------------------------------------------------------- + * V4L2 subdev operations + */ + +static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev) +{ + return container_of(sdev, struct csi_state, sd); +} + +static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct csi_state *state = mipi_sd_to_csi2_state(sd); + struct v4l2_subdev_state *sd_state; + int ret = 0; + + if (enable) { + ret = pm_runtime_resume_and_get(state->dev); + if (ret < 0) + return ret; + } + + mutex_lock(&state->lock); + + if (enable) { + if (state->state & ST_SUSPENDED) { + ret = -EBUSY; + goto unlock; + } + + sd_state = v4l2_subdev_lock_and_get_active_state(sd); + ret = imx8mq_mipi_csi_start_stream(state, sd_state); + v4l2_subdev_unlock_state(sd_state); + + if (ret < 0) + goto unlock; + + ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1); + if (ret < 0) + goto unlock; + + state->state |= ST_STREAMING; + } else { + v4l2_subdev_call(state->src_sd, video, s_stream, 0); + imx8mq_mipi_csi_stop_stream(state); + state->state &= ~ST_STREAMING; + } + +unlock: + mutex_unlock(&state->lock); + + if (!enable || ret < 0) + pm_runtime_put(state->dev); + + return ret; +} + +static int imx8mq_mipi_csi_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) +{ + struct v4l2_mbus_framefmt *fmt_sink; + struct v4l2_mbus_framefmt *fmt_source; + + fmt_sink = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SINK); + fmt_source = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SOURCE); + + fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10; + fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH; + fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT; + fmt_sink->field = V4L2_FIELD_NONE; + + fmt_sink->colorspace = V4L2_COLORSPACE_RAW; + fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace); + fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace); + fmt_sink->quantization = + V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace, + fmt_sink->ycbcr_enc); + + *fmt_source = *fmt_sink; + + return 0; +} + +static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + /* + * We can't transcode in any way, the source format is identical + * to the sink format. + */ + if (code->pad == MIPI_CSI2_PAD_SOURCE) { + struct v4l2_mbus_framefmt *fmt; + + if (code->index > 0) + return -EINVAL; + + fmt = v4l2_subdev_get_pad_format(sd, sd_state, code->pad); + code->code = fmt->code; + return 0; + } + + if (code->pad != MIPI_CSI2_PAD_SINK) + return -EINVAL; + + if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats)) + return -EINVAL; + + code->code = imx8mq_mipi_csi_formats[code->index].code; + + return 0; +} + +static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *sdformat) +{ + const struct csi2_pix_format *csi2_fmt; + struct v4l2_mbus_framefmt *fmt; + + /* + * The device can't transcode in any way, the source format can't be + * modified. + */ + if (sdformat->pad == MIPI_CSI2_PAD_SOURCE) + return v4l2_subdev_get_fmt(sd, sd_state, sdformat); + + if (sdformat->pad != MIPI_CSI2_PAD_SINK) + return -EINVAL; + + csi2_fmt = find_csi2_format(sdformat->format.code); + if (!csi2_fmt) + csi2_fmt = &imx8mq_mipi_csi_formats[0]; + + fmt = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad); + + fmt->code = csi2_fmt->code; + fmt->width = sdformat->format.width; + fmt->height = sdformat->format.height; + + sdformat->format = *fmt; + + /* Propagate the format from sink to source. */ + fmt = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SOURCE); + *fmt = sdformat->format; + + return 0; +} + +static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = { + .s_stream = imx8mq_mipi_csi_s_stream, +}; + +static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = { + .init_cfg = imx8mq_mipi_csi_init_cfg, + .enum_mbus_code = imx8mq_mipi_csi_enum_mbus_code, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = imx8mq_mipi_csi_set_fmt, +}; + +static const struct v4l2_subdev_ops imx8mq_mipi_csi_subdev_ops = { + .video = &imx8mq_mipi_csi_video_ops, + .pad = &imx8mq_mipi_csi_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * Media entity operations + */ + +static const struct media_entity_operations imx8mq_mipi_csi_entity_ops = { + .link_validate = v4l2_subdev_link_validate, + .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1, +}; + +/* ----------------------------------------------------------------------------- + * Async subdev notifier + */ + +static struct csi_state * +mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n) +{ + return container_of(n, struct csi_state, notifier); +} + +static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct csi_state *state = mipi_notifier_to_csi2_state(notifier); + struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK]; + + state->src_sd = sd; + + return v4l2_create_fwnode_links_to_pad(sd, sink, MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); +} + +static const struct v4l2_async_notifier_operations imx8mq_mipi_csi_notify_ops = { + .bound = imx8mq_mipi_csi_notify_bound, +}; + +static int imx8mq_mipi_csi_async_register(struct csi_state *state) +{ + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + struct v4l2_async_subdev *asd; + struct fwnode_handle *ep; + unsigned int i; + int ret; + + v4l2_async_nf_init(&state->notifier); + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!ep) + return -ENOTCONN; + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (ret) + goto err_parse; + + for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) { + if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) { + dev_err(state->dev, + "data lanes reordering is not supported"); + ret = -EINVAL; + goto err_parse; + } + } + + state->bus = vep.bus.mipi_csi2; + + dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n", + state->bus.num_data_lanes, + state->bus.flags); + + asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep, + struct v4l2_async_subdev); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + goto err_parse; + } + + fwnode_handle_put(ep); + + state->notifier.ops = &imx8mq_mipi_csi_notify_ops; + + ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier); + if (ret) + return ret; + + return v4l2_async_register_subdev(&state->sd); + +err_parse: + fwnode_handle_put(ep); + + return ret; +} + +/* ----------------------------------------------------------------------------- + * Suspend/resume + */ + +static void imx8mq_mipi_csi_pm_suspend(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + mutex_lock(&state->lock); + + if (state->state & ST_POWERED) { + imx8mq_mipi_csi_stop_stream(state); + imx8mq_mipi_csi_clk_disable(state); + state->state &= ~ST_POWERED; + } + + mutex_unlock(&state->lock); +} + +static int imx8mq_mipi_csi_pm_resume(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + struct v4l2_subdev_state *sd_state; + int ret = 0; + + mutex_lock(&state->lock); + + if (!(state->state & ST_POWERED)) { + state->state |= ST_POWERED; + ret = imx8mq_mipi_csi_clk_enable(state); + } + if (state->state & ST_STREAMING) { + sd_state = v4l2_subdev_lock_and_get_active_state(sd); + ret = imx8mq_mipi_csi_start_stream(state, sd_state); + v4l2_subdev_unlock_state(sd_state); + if (ret) + goto unlock; + } + + state->state &= ~ST_SUSPENDED; + +unlock: + mutex_unlock(&state->lock); + + return ret ? -EAGAIN : 0; +} + +static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + imx8mq_mipi_csi_pm_suspend(dev); + + state->state |= ST_SUSPENDED; + + return 0; +} + +static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + if (!(state->state & ST_SUSPENDED)) + return 0; + + return imx8mq_mipi_csi_pm_resume(dev); +} + +static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + int ret; + + imx8mq_mipi_csi_pm_suspend(dev); + + ret = icc_set_bw(state->icc_path, 0, 0); + if (ret) + dev_err(dev, "icc_set_bw failed with %d\n", ret); + + return ret; +} + +static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + int ret; + + ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw); + if (ret) { + dev_err(dev, "icc_set_bw failed with %d\n", ret); + return ret; + } + + return imx8mq_mipi_csi_pm_resume(dev); +} + +static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = { + SET_RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend, + imx8mq_mipi_csi_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume) +}; + +/* ----------------------------------------------------------------------------- + * Probe/remove & platform driver + */ + +static int imx8mq_mipi_csi_subdev_init(struct csi_state *state) +{ + struct v4l2_subdev *sd = &state->sd; + int ret; + + v4l2_subdev_init(sd, &imx8mq_mipi_csi_subdev_ops); + sd->owner = THIS_MODULE; + snprintf(sd->name, sizeof(sd->name), "%s %s", + MIPI_CSI2_SUBDEV_NAME, dev_name(state->dev)); + + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + sd->entity.ops = &imx8mq_mipi_csi_entity_ops; + + sd->dev = state->dev; + + state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; + state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE + | MEDIA_PAD_FL_MUST_CONNECT; + ret = media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM, + state->pads); + if (ret) + return ret; + + ret = v4l2_subdev_init_finalize(sd); + if (ret) { + media_entity_cleanup(&sd->entity); + return ret; + } + + return 0; +} + +static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + icc_put(state->icc_path); +} + +static int imx8mq_mipi_csi_init_icc(struct platform_device *pdev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + /* Optional interconnect request */ + state->icc_path = of_icc_get(&pdev->dev, "dram"); + if (IS_ERR_OR_NULL(state->icc_path)) + return PTR_ERR_OR_ZERO(state->icc_path); + + state->icc_path_bw = MBps_to_icc(700); + + return 0; +} + +static int imx8mq_mipi_csi_parse_dt(struct csi_state *state) +{ + struct device *dev = state->dev; + struct device_node *np = state->dev->of_node; + struct device_node *node; + phandle ph; + u32 out_val[2]; + int ret = 0; + + state->rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(state->rst)) { + dev_err(dev, "Failed to get reset: %pe\n", state->rst); + return PTR_ERR(state->rst); + } + + ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val, + ARRAY_SIZE(out_val)); + if (ret) { + dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret); + return ret; + } + + ph = *out_val; + + node = of_find_node_by_phandle(ph); + if (!node) { + dev_err(dev, "Error finding node by phandle\n"); + return -ENODEV; + } + state->phy_gpr = syscon_node_to_regmap(node); + of_node_put(node); + if (IS_ERR(state->phy_gpr)) { + dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr); + return PTR_ERR(state->phy_gpr); + } + + state->phy_gpr_reg = out_val[1]; + dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg); + + return ret; +} + +static int imx8mq_mipi_csi_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct csi_state *state; + int ret; + + state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->dev = dev; + + ret = imx8mq_mipi_csi_parse_dt(state); + if (ret < 0) { + dev_err(dev, "Failed to parse device tree: %d\n", ret); + return ret; + } + + /* Acquire resources. */ + state->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(state->regs)) + return PTR_ERR(state->regs); + + ret = imx8mq_mipi_csi_clk_get(state); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, &state->sd); + + mutex_init(&state->lock); + + ret = imx8mq_mipi_csi_subdev_init(state); + if (ret < 0) + goto mutex; + + ret = imx8mq_mipi_csi_init_icc(pdev); + if (ret) + goto mutex; + + /* Enable runtime PM. */ + pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) { + ret = imx8mq_mipi_csi_runtime_resume(dev); + if (ret < 0) + goto icc; + } + + ret = imx8mq_mipi_csi_async_register(state); + if (ret < 0) + goto cleanup; + + return 0; + +cleanup: + pm_runtime_disable(&pdev->dev); + imx8mq_mipi_csi_runtime_suspend(&pdev->dev); + + media_entity_cleanup(&state->sd.entity); + v4l2_subdev_cleanup(&state->sd); + v4l2_async_nf_unregister(&state->notifier); + v4l2_async_nf_cleanup(&state->notifier); + v4l2_async_unregister_subdev(&state->sd); +icc: + imx8mq_mipi_csi_release_icc(pdev); +mutex: + mutex_destroy(&state->lock); + + return ret; +} + +static void imx8mq_mipi_csi_remove(struct platform_device *pdev) +{ + struct v4l2_subdev *sd = platform_get_drvdata(pdev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + v4l2_async_nf_unregister(&state->notifier); + v4l2_async_nf_cleanup(&state->notifier); + v4l2_async_unregister_subdev(&state->sd); + + pm_runtime_disable(&pdev->dev); + imx8mq_mipi_csi_runtime_suspend(&pdev->dev); + media_entity_cleanup(&state->sd.entity); + v4l2_subdev_cleanup(&state->sd); + mutex_destroy(&state->lock); + pm_runtime_set_suspended(&pdev->dev); + imx8mq_mipi_csi_release_icc(pdev); +} + +static const struct of_device_id imx8mq_mipi_csi_of_match[] = { + { .compatible = "fsl,imx8mq-mipi-csi2", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match); + +static struct platform_driver imx8mq_mipi_csi_driver = { + .probe = imx8mq_mipi_csi_probe, + .remove_new = imx8mq_mipi_csi_remove, + .driver = { + .of_match_table = imx8mq_mipi_csi_of_match, + .name = MIPI_CSI2_DRIVER_NAME, + .pm = &imx8mq_mipi_csi_pm_ops, + }, +}; + +module_platform_driver(imx8mq_mipi_csi_driver); + +MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver"); +MODULE_AUTHOR("Martin Kepplinger "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:imx8mq-mipi-csi2"); diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig index 21fd79515042..b42af427b88b 100644 --- a/drivers/staging/media/imx/Kconfig +++ b/drivers/staging/media/imx/Kconfig @@ -25,13 +25,3 @@ config VIDEO_IMX_CSI A video4linux camera sensor interface driver for i.MX5/6. endmenu endif - -config VIDEO_IMX8MQ_MIPI_CSI2 - tristate "NXP i.MX8MQ MIPI CSI-2 receiver" - depends on ARCH_MXC || COMPILE_TEST - depends on VIDEO_DEV - select MEDIA_CONTROLLER - select V4L2_FWNODE - select VIDEO_V4L2_SUBDEV_API - help - V4L2 driver for the MIPI CSI-2 receiver found in the i.MX8MQ SoC. diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile index 906a422aa656..b69951deff9a 100644 --- a/drivers/staging/media/imx/Makefile +++ b/drivers/staging/media/imx/Makefile @@ -13,5 +13,3 @@ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media.o obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o - -obj-$(CONFIG_VIDEO_IMX8MQ_MIPI_CSI2) += imx8mq-mipi-csi2.o diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c deleted file mode 100644 index ca2efcc21efe..000000000000 --- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c +++ /dev/null @@ -1,966 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver - * - * Copyright (C) 2021 Purism SPC - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define MIPI_CSI2_DRIVER_NAME "imx8mq-mipi-csi2" -#define MIPI_CSI2_SUBDEV_NAME MIPI_CSI2_DRIVER_NAME - -#define MIPI_CSI2_PAD_SINK 0 -#define MIPI_CSI2_PAD_SOURCE 1 -#define MIPI_CSI2_PADS_NUM 2 - -#define MIPI_CSI2_DEF_PIX_WIDTH 640 -#define MIPI_CSI2_DEF_PIX_HEIGHT 480 - -/* Register map definition */ - -/* i.MX8MQ CSI-2 controller CSR */ -#define CSI2RX_CFG_NUM_LANES 0x100 -#define CSI2RX_CFG_DISABLE_DATA_LANES 0x104 -#define CSI2RX_BIT_ERR 0x108 -#define CSI2RX_IRQ_STATUS 0x10c -#define CSI2RX_IRQ_MASK 0x110 -#define CSI2RX_IRQ_MASK_ALL 0x1ff -#define CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE 0x8 -#define CSI2RX_ULPS_STATUS 0x114 -#define CSI2RX_PPI_ERRSOT_HS 0x118 -#define CSI2RX_PPI_ERRSOTSYNC_HS 0x11c -#define CSI2RX_PPI_ERRESC 0x120 -#define CSI2RX_PPI_ERRSYNCESC 0x124 -#define CSI2RX_PPI_ERRCONTROL 0x128 -#define CSI2RX_CFG_DISABLE_PAYLOAD_0 0x12c -#define CSI2RX_CFG_VID_VC_IGNORE 0x180 -#define CSI2RX_CFG_VID_VC 0x184 -#define CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL 0x188 -#define CSI2RX_CFG_DISABLE_PAYLOAD_1 0x130 - -enum { - ST_POWERED = 1, - ST_STREAMING = 2, - ST_SUSPENDED = 4, -}; - -enum imx8mq_mipi_csi_clk { - CSI2_CLK_CORE, - CSI2_CLK_ESC, - CSI2_CLK_UI, - CSI2_NUM_CLKS, -}; - -static const char * const imx8mq_mipi_csi_clk_id[CSI2_NUM_CLKS] = { - [CSI2_CLK_CORE] = "core", - [CSI2_CLK_ESC] = "esc", - [CSI2_CLK_UI] = "ui", -}; - -#define CSI2_NUM_CLKS ARRAY_SIZE(imx8mq_mipi_csi_clk_id) - -#define GPR_CSI2_1_RX_ENABLE BIT(13) -#define GPR_CSI2_1_VID_INTFC_ENB BIT(12) -#define GPR_CSI2_1_HSEL BIT(10) -#define GPR_CSI2_1_CONT_CLK_MODE BIT(8) -#define GPR_CSI2_1_S_PRG_RXHS_SETTLE(x) (((x) & 0x3f) << 2) - -/* - * The send level configures the number of entries that must accumulate in - * the Pixel FIFO before the data will be transferred to the video output. - * The exact value needed for this configuration is dependent on the rate at - * which the sensor transfers data to the CSI-2 Controller and the user - * video clock. - * - * The calculation is the classical rate-in rate-out type of problem: If the - * video bandwidth is 10% faster than the incoming mipi data and the video - * line length is 500 pixels, then the fifo should be allowed to fill - * 10% of the line length or 50 pixels. If the gap data is ok, then the level - * can be set to 16 and ignored. - */ -#define CSI2RX_SEND_LEVEL 64 - -struct csi_state { - struct device *dev; - void __iomem *regs; - struct clk_bulk_data clks[CSI2_NUM_CLKS]; - struct reset_control *rst; - struct regulator *mipi_phy_regulator; - - struct v4l2_subdev sd; - struct media_pad pads[MIPI_CSI2_PADS_NUM]; - struct v4l2_async_notifier notifier; - struct v4l2_subdev *src_sd; - - struct v4l2_mbus_config_mipi_csi2 bus; - - struct mutex lock; /* Protect state */ - u32 state; - - struct regmap *phy_gpr; - u8 phy_gpr_reg; - - struct icc_path *icc_path; - s32 icc_path_bw; -}; - -/* ----------------------------------------------------------------------------- - * Format helpers - */ - -struct csi2_pix_format { - u32 code; - u8 width; -}; - -static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = { - /* RAW (Bayer and greyscale) formats. */ - { - .code = MEDIA_BUS_FMT_SBGGR8_1X8, - .width = 8, - }, { - .code = MEDIA_BUS_FMT_SGBRG8_1X8, - .width = 8, - }, { - .code = MEDIA_BUS_FMT_SGRBG8_1X8, - .width = 8, - }, { - .code = MEDIA_BUS_FMT_SRGGB8_1X8, - .width = 8, - }, { - .code = MEDIA_BUS_FMT_Y8_1X8, - .width = 8, - }, { - .code = MEDIA_BUS_FMT_SBGGR10_1X10, - .width = 10, - }, { - .code = MEDIA_BUS_FMT_SGBRG10_1X10, - .width = 10, - }, { - .code = MEDIA_BUS_FMT_SGRBG10_1X10, - .width = 10, - }, { - .code = MEDIA_BUS_FMT_SRGGB10_1X10, - .width = 10, - }, { - .code = MEDIA_BUS_FMT_Y10_1X10, - .width = 10, - }, { - .code = MEDIA_BUS_FMT_SBGGR12_1X12, - .width = 12, - }, { - .code = MEDIA_BUS_FMT_SGBRG12_1X12, - .width = 12, - }, { - .code = MEDIA_BUS_FMT_SGRBG12_1X12, - .width = 12, - }, { - .code = MEDIA_BUS_FMT_SRGGB12_1X12, - .width = 12, - }, { - .code = MEDIA_BUS_FMT_Y12_1X12, - .width = 12, - }, { - .code = MEDIA_BUS_FMT_SBGGR14_1X14, - .width = 14, - }, { - .code = MEDIA_BUS_FMT_SGBRG14_1X14, - .width = 14, - }, { - .code = MEDIA_BUS_FMT_SGRBG14_1X14, - .width = 14, - }, { - .code = MEDIA_BUS_FMT_SRGGB14_1X14, - .width = 14, - }, - /* YUV formats */ - { - .code = MEDIA_BUS_FMT_YUYV8_1X16, - .width = 16, - }, { - .code = MEDIA_BUS_FMT_UYVY8_1X16, - .width = 16, - } -}; - -static const struct csi2_pix_format *find_csi2_format(u32 code) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(imx8mq_mipi_csi_formats); i++) - if (code == imx8mq_mipi_csi_formats[i].code) - return &imx8mq_mipi_csi_formats[i]; - return NULL; -} - -/* ----------------------------------------------------------------------------- - * Hardware configuration - */ - -static inline void imx8mq_mipi_csi_write(struct csi_state *state, u32 reg, u32 val) -{ - writel(val, state->regs + reg); -} - -static int imx8mq_mipi_csi_sw_reset(struct csi_state *state) -{ - int ret; - - /* - * these are most likely self-clearing reset bits. to make it - * more clear, the reset-imx7 driver should implement the - * .reset() operation. - */ - ret = reset_control_assert(state->rst); - if (ret < 0) { - dev_err(state->dev, "Failed to assert resets: %d\n", ret); - return ret; - } - - return 0; -} - -static void imx8mq_mipi_csi_set_params(struct csi_state *state) -{ - int lanes = state->bus.num_data_lanes; - - imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, lanes - 1); - imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, - (0xf << lanes) & 0xf); - imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, CSI2RX_IRQ_MASK_ALL); - /* - * 0x180 bit 0 controls the Virtual Channel behaviour: when set the - * interface ignores the Virtual Channel (VC) field in received packets; - * when cleared it causes the interface to only accept packets whose VC - * matches the value to which VC is set at offset 0x184. - */ - imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_VC_IGNORE, 1); - imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL, - CSI2RX_SEND_LEVEL); -} - -static int imx8mq_mipi_csi_clk_enable(struct csi_state *state) -{ - return clk_bulk_prepare_enable(CSI2_NUM_CLKS, state->clks); -} - -static void imx8mq_mipi_csi_clk_disable(struct csi_state *state) -{ - clk_bulk_disable_unprepare(CSI2_NUM_CLKS, state->clks); -} - -static int imx8mq_mipi_csi_clk_get(struct csi_state *state) -{ - unsigned int i; - - for (i = 0; i < CSI2_NUM_CLKS; i++) - state->clks[i].id = imx8mq_mipi_csi_clk_id[i]; - - return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks); -} - -static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state, - struct v4l2_subdev_state *sd_state, - u32 *hs_settle) -{ - s64 link_freq; - u32 lane_rate; - unsigned long esc_clk_rate; - u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns; - const struct v4l2_mbus_framefmt *fmt; - const struct csi2_pix_format *csi2_fmt; - - /* Calculate the line rate from the pixel rate. */ - - fmt = v4l2_subdev_get_pad_format(&state->sd, sd_state, MIPI_CSI2_PAD_SINK); - csi2_fmt = find_csi2_format(fmt->code); - - link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler, - csi2_fmt->width, - state->bus.num_data_lanes * 2); - if (link_freq < 0) { - dev_err(state->dev, "Unable to obtain link frequency: %d\n", - (int)link_freq); - return link_freq; - } - - lane_rate = link_freq * 2; - if (lane_rate < 80000000 || lane_rate > 1500000000) { - dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate); - return -EINVAL; - } - - /* - * The D-PHY specification requires Ths-settle to be in the range - * 85ns + 6*UI to 140ns + 10*UI, with the unit interval UI being half - * the clock period. - * - * The Ths-settle value is expressed in the hardware as a multiple of - * the Esc clock period: - * - * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc - * - * Due to the one cycle inaccuracy introduced by rounding, the - * documentation recommends picking a value away from the boundaries. - * Let's pick the average. - */ - esc_clk_rate = clk_get_rate(state->clks[CSI2_CLK_ESC].clk); - if (!esc_clk_rate) { - dev_err(state->dev, "Could not get esc clock rate.\n"); - return -EINVAL; - } - - dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate); - esc_clk_period_ns = 1000000000 / esc_clk_rate; - - min_ths_settle = 85 + 6 * 1000000 / (lane_rate / 1000); - max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000); - ths_settle_ns = (min_ths_settle + max_ths_settle) / 2; - - *hs_settle = ths_settle_ns / esc_clk_period_ns - 1; - - dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n", - lane_rate, ths_settle_ns, *hs_settle); - - return 0; -} - -static int imx8mq_mipi_csi_start_stream(struct csi_state *state, - struct v4l2_subdev_state *sd_state) -{ - int ret; - u32 hs_settle = 0; - - ret = imx8mq_mipi_csi_sw_reset(state); - if (ret) - return ret; - - imx8mq_mipi_csi_set_params(state); - ret = imx8mq_mipi_csi_calc_hs_settle(state, sd_state, &hs_settle); - if (ret) - return ret; - - regmap_update_bits(state->phy_gpr, - state->phy_gpr_reg, - 0x3fff, - GPR_CSI2_1_RX_ENABLE | - GPR_CSI2_1_VID_INTFC_ENB | - GPR_CSI2_1_HSEL | - GPR_CSI2_1_CONT_CLK_MODE | - GPR_CSI2_1_S_PRG_RXHS_SETTLE(hs_settle)); - - return 0; -} - -static void imx8mq_mipi_csi_stop_stream(struct csi_state *state) -{ - imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf); -} - -/* ----------------------------------------------------------------------------- - * V4L2 subdev operations - */ - -static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev) -{ - return container_of(sdev, struct csi_state, sd); -} - -static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct csi_state *state = mipi_sd_to_csi2_state(sd); - struct v4l2_subdev_state *sd_state; - int ret = 0; - - if (enable) { - ret = pm_runtime_resume_and_get(state->dev); - if (ret < 0) - return ret; - } - - mutex_lock(&state->lock); - - if (enable) { - if (state->state & ST_SUSPENDED) { - ret = -EBUSY; - goto unlock; - } - - sd_state = v4l2_subdev_lock_and_get_active_state(sd); - ret = imx8mq_mipi_csi_start_stream(state, sd_state); - v4l2_subdev_unlock_state(sd_state); - - if (ret < 0) - goto unlock; - - ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1); - if (ret < 0) - goto unlock; - - state->state |= ST_STREAMING; - } else { - v4l2_subdev_call(state->src_sd, video, s_stream, 0); - imx8mq_mipi_csi_stop_stream(state); - state->state &= ~ST_STREAMING; - } - -unlock: - mutex_unlock(&state->lock); - - if (!enable || ret < 0) - pm_runtime_put(state->dev); - - return ret; -} - -static int imx8mq_mipi_csi_init_cfg(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state) -{ - struct v4l2_mbus_framefmt *fmt_sink; - struct v4l2_mbus_framefmt *fmt_source; - - fmt_sink = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SINK); - fmt_source = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SOURCE); - - fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10; - fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH; - fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT; - fmt_sink->field = V4L2_FIELD_NONE; - - fmt_sink->colorspace = V4L2_COLORSPACE_RAW; - fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace); - fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace); - fmt_sink->quantization = - V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace, - fmt_sink->ycbcr_enc); - - *fmt_source = *fmt_sink; - - return 0; -} - -static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - /* - * We can't transcode in any way, the source format is identical - * to the sink format. - */ - if (code->pad == MIPI_CSI2_PAD_SOURCE) { - struct v4l2_mbus_framefmt *fmt; - - if (code->index > 0) - return -EINVAL; - - fmt = v4l2_subdev_get_pad_format(sd, sd_state, code->pad); - code->code = fmt->code; - return 0; - } - - if (code->pad != MIPI_CSI2_PAD_SINK) - return -EINVAL; - - if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats)) - return -EINVAL; - - code->code = imx8mq_mipi_csi_formats[code->index].code; - - return 0; -} - -static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *sdformat) -{ - const struct csi2_pix_format *csi2_fmt; - struct v4l2_mbus_framefmt *fmt; - - /* - * The device can't transcode in any way, the source format can't be - * modified. - */ - if (sdformat->pad == MIPI_CSI2_PAD_SOURCE) - return v4l2_subdev_get_fmt(sd, sd_state, sdformat); - - if (sdformat->pad != MIPI_CSI2_PAD_SINK) - return -EINVAL; - - csi2_fmt = find_csi2_format(sdformat->format.code); - if (!csi2_fmt) - csi2_fmt = &imx8mq_mipi_csi_formats[0]; - - fmt = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad); - - fmt->code = csi2_fmt->code; - fmt->width = sdformat->format.width; - fmt->height = sdformat->format.height; - - sdformat->format = *fmt; - - /* Propagate the format from sink to source. */ - fmt = v4l2_subdev_get_pad_format(sd, sd_state, MIPI_CSI2_PAD_SOURCE); - *fmt = sdformat->format; - - return 0; -} - -static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = { - .s_stream = imx8mq_mipi_csi_s_stream, -}; - -static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = { - .init_cfg = imx8mq_mipi_csi_init_cfg, - .enum_mbus_code = imx8mq_mipi_csi_enum_mbus_code, - .get_fmt = v4l2_subdev_get_fmt, - .set_fmt = imx8mq_mipi_csi_set_fmt, -}; - -static const struct v4l2_subdev_ops imx8mq_mipi_csi_subdev_ops = { - .video = &imx8mq_mipi_csi_video_ops, - .pad = &imx8mq_mipi_csi_pad_ops, -}; - -/* ----------------------------------------------------------------------------- - * Media entity operations - */ - -static const struct media_entity_operations imx8mq_mipi_csi_entity_ops = { - .link_validate = v4l2_subdev_link_validate, - .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1, -}; - -/* ----------------------------------------------------------------------------- - * Async subdev notifier - */ - -static struct csi_state * -mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n) -{ - return container_of(n, struct csi_state, notifier); -} - -static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) -{ - struct csi_state *state = mipi_notifier_to_csi2_state(notifier); - struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK]; - - state->src_sd = sd; - - return v4l2_create_fwnode_links_to_pad(sd, sink, MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); -} - -static const struct v4l2_async_notifier_operations imx8mq_mipi_csi_notify_ops = { - .bound = imx8mq_mipi_csi_notify_bound, -}; - -static int imx8mq_mipi_csi_async_register(struct csi_state *state) -{ - struct v4l2_fwnode_endpoint vep = { - .bus_type = V4L2_MBUS_CSI2_DPHY, - }; - struct v4l2_async_subdev *asd; - struct fwnode_handle *ep; - unsigned int i; - int ret; - - v4l2_async_nf_init(&state->notifier); - - ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0, - FWNODE_GRAPH_ENDPOINT_NEXT); - if (!ep) - return -ENOTCONN; - - ret = v4l2_fwnode_endpoint_parse(ep, &vep); - if (ret) - goto err_parse; - - for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) { - if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) { - dev_err(state->dev, - "data lanes reordering is not supported"); - ret = -EINVAL; - goto err_parse; - } - } - - state->bus = vep.bus.mipi_csi2; - - dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n", - state->bus.num_data_lanes, - state->bus.flags); - - asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep, - struct v4l2_async_subdev); - if (IS_ERR(asd)) { - ret = PTR_ERR(asd); - goto err_parse; - } - - fwnode_handle_put(ep); - - state->notifier.ops = &imx8mq_mipi_csi_notify_ops; - - ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier); - if (ret) - return ret; - - return v4l2_async_register_subdev(&state->sd); - -err_parse: - fwnode_handle_put(ep); - - return ret; -} - -/* ----------------------------------------------------------------------------- - * Suspend/resume - */ - -static void imx8mq_mipi_csi_pm_suspend(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - - mutex_lock(&state->lock); - - if (state->state & ST_POWERED) { - imx8mq_mipi_csi_stop_stream(state); - imx8mq_mipi_csi_clk_disable(state); - state->state &= ~ST_POWERED; - } - - mutex_unlock(&state->lock); -} - -static int imx8mq_mipi_csi_pm_resume(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - struct v4l2_subdev_state *sd_state; - int ret = 0; - - mutex_lock(&state->lock); - - if (!(state->state & ST_POWERED)) { - state->state |= ST_POWERED; - ret = imx8mq_mipi_csi_clk_enable(state); - } - if (state->state & ST_STREAMING) { - sd_state = v4l2_subdev_lock_and_get_active_state(sd); - ret = imx8mq_mipi_csi_start_stream(state, sd_state); - v4l2_subdev_unlock_state(sd_state); - if (ret) - goto unlock; - } - - state->state &= ~ST_SUSPENDED; - -unlock: - mutex_unlock(&state->lock); - - return ret ? -EAGAIN : 0; -} - -static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - - imx8mq_mipi_csi_pm_suspend(dev); - - state->state |= ST_SUSPENDED; - - return 0; -} - -static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - - if (!(state->state & ST_SUSPENDED)) - return 0; - - return imx8mq_mipi_csi_pm_resume(dev); -} - -static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - int ret; - - imx8mq_mipi_csi_pm_suspend(dev); - - ret = icc_set_bw(state->icc_path, 0, 0); - if (ret) - dev_err(dev, "icc_set_bw failed with %d\n", ret); - - return ret; -} - -static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - int ret; - - ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw); - if (ret) { - dev_err(dev, "icc_set_bw failed with %d\n", ret); - return ret; - } - - return imx8mq_mipi_csi_pm_resume(dev); -} - -static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = { - SET_RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend, - imx8mq_mipi_csi_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume) -}; - -/* ----------------------------------------------------------------------------- - * Probe/remove & platform driver - */ - -static int imx8mq_mipi_csi_subdev_init(struct csi_state *state) -{ - struct v4l2_subdev *sd = &state->sd; - int ret; - - v4l2_subdev_init(sd, &imx8mq_mipi_csi_subdev_ops); - sd->owner = THIS_MODULE; - snprintf(sd->name, sizeof(sd->name), "%s %s", - MIPI_CSI2_SUBDEV_NAME, dev_name(state->dev)); - - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - - sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; - sd->entity.ops = &imx8mq_mipi_csi_entity_ops; - - sd->dev = state->dev; - - state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK - | MEDIA_PAD_FL_MUST_CONNECT; - state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE - | MEDIA_PAD_FL_MUST_CONNECT; - ret = media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM, - state->pads); - if (ret) - return ret; - - ret = v4l2_subdev_init_finalize(sd); - if (ret) { - media_entity_cleanup(&sd->entity); - return ret; - } - - return 0; -} - -static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - - icc_put(state->icc_path); -} - -static int imx8mq_mipi_csi_init_icc(struct platform_device *pdev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - - /* Optional interconnect request */ - state->icc_path = of_icc_get(&pdev->dev, "dram"); - if (IS_ERR_OR_NULL(state->icc_path)) - return PTR_ERR_OR_ZERO(state->icc_path); - - state->icc_path_bw = MBps_to_icc(700); - - return 0; -} - -static int imx8mq_mipi_csi_parse_dt(struct csi_state *state) -{ - struct device *dev = state->dev; - struct device_node *np = state->dev->of_node; - struct device_node *node; - phandle ph; - u32 out_val[2]; - int ret = 0; - - state->rst = devm_reset_control_array_get_exclusive(dev); - if (IS_ERR(state->rst)) { - dev_err(dev, "Failed to get reset: %pe\n", state->rst); - return PTR_ERR(state->rst); - } - - ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val, - ARRAY_SIZE(out_val)); - if (ret) { - dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret); - return ret; - } - - ph = *out_val; - - node = of_find_node_by_phandle(ph); - if (!node) { - dev_err(dev, "Error finding node by phandle\n"); - return -ENODEV; - } - state->phy_gpr = syscon_node_to_regmap(node); - of_node_put(node); - if (IS_ERR(state->phy_gpr)) { - dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr); - return PTR_ERR(state->phy_gpr); - } - - state->phy_gpr_reg = out_val[1]; - dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg); - - return ret; -} - -static int imx8mq_mipi_csi_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct csi_state *state; - int ret; - - state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - state->dev = dev; - - ret = imx8mq_mipi_csi_parse_dt(state); - if (ret < 0) { - dev_err(dev, "Failed to parse device tree: %d\n", ret); - return ret; - } - - /* Acquire resources. */ - state->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(state->regs)) - return PTR_ERR(state->regs); - - ret = imx8mq_mipi_csi_clk_get(state); - if (ret < 0) - return ret; - - platform_set_drvdata(pdev, &state->sd); - - mutex_init(&state->lock); - - ret = imx8mq_mipi_csi_subdev_init(state); - if (ret < 0) - goto mutex; - - ret = imx8mq_mipi_csi_init_icc(pdev); - if (ret) - goto mutex; - - /* Enable runtime PM. */ - pm_runtime_enable(dev); - if (!pm_runtime_enabled(dev)) { - ret = imx8mq_mipi_csi_runtime_resume(dev); - if (ret < 0) - goto icc; - } - - ret = imx8mq_mipi_csi_async_register(state); - if (ret < 0) - goto cleanup; - - return 0; - -cleanup: - pm_runtime_disable(&pdev->dev); - imx8mq_mipi_csi_runtime_suspend(&pdev->dev); - - media_entity_cleanup(&state->sd.entity); - v4l2_subdev_cleanup(&state->sd); - v4l2_async_nf_unregister(&state->notifier); - v4l2_async_nf_cleanup(&state->notifier); - v4l2_async_unregister_subdev(&state->sd); -icc: - imx8mq_mipi_csi_release_icc(pdev); -mutex: - mutex_destroy(&state->lock); - - return ret; -} - -static void imx8mq_mipi_csi_remove(struct platform_device *pdev) -{ - struct v4l2_subdev *sd = platform_get_drvdata(pdev); - struct csi_state *state = mipi_sd_to_csi2_state(sd); - - v4l2_async_nf_unregister(&state->notifier); - v4l2_async_nf_cleanup(&state->notifier); - v4l2_async_unregister_subdev(&state->sd); - - pm_runtime_disable(&pdev->dev); - imx8mq_mipi_csi_runtime_suspend(&pdev->dev); - media_entity_cleanup(&state->sd.entity); - v4l2_subdev_cleanup(&state->sd); - mutex_destroy(&state->lock); - pm_runtime_set_suspended(&pdev->dev); - imx8mq_mipi_csi_release_icc(pdev); -} - -static const struct of_device_id imx8mq_mipi_csi_of_match[] = { - { .compatible = "fsl,imx8mq-mipi-csi2", }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match); - -static struct platform_driver imx8mq_mipi_csi_driver = { - .probe = imx8mq_mipi_csi_probe, - .remove_new = imx8mq_mipi_csi_remove, - .driver = { - .of_match_table = imx8mq_mipi_csi_of_match, - .name = MIPI_CSI2_DRIVER_NAME, - .pm = &imx8mq_mipi_csi_pm_ops, - }, -}; - -module_platform_driver(imx8mq_mipi_csi_driver); - -MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver"); -MODULE_AUTHOR("Martin Kepplinger "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:imx8mq-mipi-csi2"); -- cgit v1.2.3 From c8f0e924902d6b54fc3b01af18604b54eef98d1b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 20 Jul 2023 09:18:22 +0200 Subject: staging: media: sun6i-isp: drop of_match_ptr for ID table The driver can match only via the DT table so the table should be always used and the of_match_ptr does not make any sense. This also fixes this !CONFIG_OF error: drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c:529:34: warning: 'sun6i_isp_of_match' defined but not used [-Wunused-const-variable=] 529 | static const struct of_device_id sun6i_isp_of_match[] = { | ^~~~~~~~~~~~~~~~~ Signed-off-by: Hans Verkuil Reviewed-by: Chen-Yu Tsai --- drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c index 0dc75adbd9d8..472057f03bc2 100644 --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c @@ -541,7 +541,7 @@ static struct platform_driver sun6i_isp_platform_driver = { .remove_new = sun6i_isp_remove, .driver = { .name = SUN6I_ISP_NAME, - .of_match_table = of_match_ptr(sun6i_isp_of_match), + .of_match_table = sun6i_isp_of_match, .pm = &sun6i_isp_pm_ops, }, }; -- cgit v1.2.3 From 466ae77a8cd45fa1a0bef370ca18782a1ed5aac2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 20 Jul 2023 09:20:03 +0200 Subject: staging: media: tegra-video: include video.h header This tells sparse that tegra_vip_driver is actually used, and so avoids this warning: drivers/staging/media/tegra-video/vip.c:280:31: warning: 'tegra_vip_driver' defined but not used [-Wunused-variable] 280 | static struct platform_driver tegra_vip_driver = { | ^~~~~~~~~~~~~~~~ Signed-off-by: Hans Verkuil Reviewed-by: Luca Ceresoli --- drivers/staging/media/tegra-video/vip.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/staging') diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c index a1ab886acc18..bc5fc82a7702 100644 --- a/drivers/staging/media/tegra-video/vip.c +++ b/drivers/staging/media/tegra-video/vip.c @@ -20,6 +20,7 @@ #include #include "vip.h" +#include "video.h" static inline struct tegra_vip *host1x_client_to_vip(struct host1x_client *client) { -- cgit v1.2.3 From cd37409f1f2d442057c1372e485452a982c10be6 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Tue, 13 Jun 2023 17:39:39 +0200 Subject: media: meson: vdec: Add MODULE_FIRMWARE macro The meson-vdec module loads firmware so add MODULE_FIRMWARE macros to provide that information via modinfo. Signed-off-by: Juerg Haefliger Reviewed-by: Neil Armstrong Signed-off-by: Hans Verkuil --- drivers/staging/media/meson/vdec/vdec_platform.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/media/meson/vdec/vdec_platform.c b/drivers/staging/media/meson/vdec/vdec_platform.c index 88c9d72e1c83..70c9fd7c8bc5 100644 --- a/drivers/staging/media/meson/vdec/vdec_platform.c +++ b/drivers/staging/media/meson/vdec/vdec_platform.c @@ -280,3 +280,12 @@ const struct vdec_platform vdec_platform_sm1 = { .num_formats = ARRAY_SIZE(vdec_formats_sm1), .revision = VDEC_REVISION_SM1, }; + +MODULE_FIRMWARE("meson/vdec/g12a_h264.bin"); +MODULE_FIRMWARE("meson/vdec/g12a_vp9.bin"); +MODULE_FIRMWARE("meson/vdec/gxbb_h264.bin"); +MODULE_FIRMWARE("meson/vdec/gxl_h264.bin"); +MODULE_FIRMWARE("meson/vdec/gxl_mpeg12.bin"); +MODULE_FIRMWARE("meson/vdec/gxl_vp9.bin"); +MODULE_FIRMWARE("meson/vdec/gxm_h264.bin"); +MODULE_FIRMWARE("meson/vdec/sm1_vp9_mmu.bin"); -- cgit v1.2.3 From 3194d514ea5133b269c07d403fd6ddb4e1016e92 Mon Sep 17 00:00:00 2001 From: Emma Christy Date: Wed, 21 Jun 2023 18:42:47 +0300 Subject: media: rkvdec: removed redundant blank line Adhere to Linux kernel coding style. Removed redundant blank line. Issue found by checkpatch. Signed-off-by: Emma Christy Reviewed-by: Nicolas Dufresne Reviewed-by: Mauro Carvalho Chehab Signed-off-by: Hans Verkuil --- drivers/staging/media/rkvdec/rkvdec-vp9.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/rkvdec/rkvdec-vp9.c b/drivers/staging/media/rkvdec/rkvdec-vp9.c index cfae99b40ccb..0e7e16f20eeb 100644 --- a/drivers/staging/media/rkvdec/rkvdec-vp9.c +++ b/drivers/staging/media/rkvdec/rkvdec-vp9.c @@ -227,7 +227,6 @@ static void init_intra_only_probs(struct rkvdec_ctx *ctx, } } } - } for (i = 0; i < sizeof(v4l2_vp9_kf_uv_mode_prob); ++i) { -- cgit v1.2.3 From f000e6ca2d60fefd02a180a57df2c4162fa0c1b7 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Mon, 17 Jul 2023 17:06:11 +0200 Subject: media: rkvdec: increase max supported height for H.264 After testing it is possible for the hardware to decode H264 bistream with a height up to 2560. Signed-off-by: Benjamin Gaignard Fixes: cd33c830448ba ("media: rkvdec: Add the rkvdec driver") Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil --- drivers/staging/media/rkvdec/rkvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index 134e2b9fa7d9..84a41792cb4b 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -120,7 +120,7 @@ static const struct rkvdec_coded_fmt_desc rkvdec_coded_fmts[] = { .max_width = 4096, .step_width = 16, .min_height = 48, - .max_height = 2304, + .max_height = 2560, .step_height = 16, }, .ctrls = &rkvdec_h264_ctrls, -- cgit v1.2.3 From b6d42c35c03dc1a0e5c2800c2137017a62ee58f9 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 22 Feb 2023 12:02:39 +0100 Subject: media: v4l: async: Clean up list heads and entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The naming of list heads and list entries is confusing as they're named similarly. Use _list for list head and _entry for list entries. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +- drivers/media/platform/xilinx/xilinx-vipp.c | 6 ++-- drivers/media/v4l2-core/v4l2-async.c | 54 ++++++++++++++--------------- drivers/staging/media/tegra-video/vi.c | 4 +-- include/media/v4l2-async.h | 22 ++++++------ include/media/v4l2-subdev.h | 4 +-- 6 files changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index dc09fbdb062b..8dcc4e963498 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1421,7 +1421,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) struct cio2_queue *q; int ret; - list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) { + list_for_each_entry(asd, &cio2->notifier.asd_list, asd_entry) { s_asd = to_sensor_asd(asd); q = &cio2->queue[s_asd->csi2.port]; diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index b309af0c8374..52c5a7decf28 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev, struct xvip_graph_entity *entity; struct v4l2_async_subdev *asd; - list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) { entity = to_xvip_entity(asd); if (entity->asd.match.fwnode == fwnode) return entity; @@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) dev_dbg(xdev->dev, "notify complete, all subdevs registered\n"); /* Create links for every entity. */ - list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) { entity = to_xvip_entity(asd); ret = xvip_graph_build_one(xdev, entity); if (ret < 0) @@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev) if (ret < 0) return 0; - list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) { entity = to_xvip_entity(asd); ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode); if (ret < 0) { diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 465eb072e7c5..04ea6f9a8ed3 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -213,7 +213,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier, struct v4l2_async_match_desc *match); struct v4l2_async_subdev *asd; - list_for_each_entry(asd, ¬ifier->waiting, list) { + list_for_each_entry(asd, ¬ifier->waiting_list, waiting_entry) { /* bus_type has been verified valid before */ switch (asd->match.type) { case V4L2_ASYNC_MATCH_TYPE_I2C: @@ -262,7 +262,7 @@ v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd) { struct v4l2_async_notifier *n; - list_for_each_entry(n, ¬ifier_list, list) + list_for_each_entry(n, ¬ifier_list, notifier_entry) if (n->sd == sd) return n; @@ -287,10 +287,10 @@ v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier) { struct v4l2_subdev *sd; - if (!list_empty(¬ifier->waiting)) + if (!list_empty(¬ifier->waiting_list)) return false; - list_for_each_entry(sd, ¬ifier->done, async_list) { + list_for_each_entry(sd, ¬ifier->done_list, async_list) { struct v4l2_async_notifier *subdev_notifier = v4l2_async_find_subdev_notifier(sd); @@ -312,7 +312,7 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier) struct v4l2_async_notifier *__notifier = notifier; /* Quick check whether there are still more sub-devices here. */ - if (!list_empty(¬ifier->waiting)) + if (!list_empty(¬ifier->waiting_list)) return 0; if (notifier->sd) @@ -391,13 +391,12 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, return ret; } - /* Remove from the waiting list */ - list_del(&asd->list); + list_del(&asd->waiting_entry); sd->asd = asd; sd->notifier = notifier; /* Move from the global subdevice list to notifier's done */ - list_move(&sd->async_list, ¬ifier->done); + list_move(&sd->async_list, ¬ifier->done_list); dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n", dev_name(sd->dev), ret); @@ -478,7 +477,7 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier, { struct v4l2_subdev *sd, *tmp; - list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) { + list_for_each_entry_safe(sd, tmp, ¬ifier->done_list, async_list) { struct v4l2_async_notifier *subdev_notifier = v4l2_async_find_subdev_notifier(sd); @@ -487,7 +486,8 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier, v4l2_async_nf_call_unbind(notifier, sd, sd->asd); if (readd) - list_add_tail(&sd->asd->list, ¬ifier->waiting); + list_add_tail(&sd->asd->waiting_entry, + ¬ifier->waiting_list); v4l2_async_cleanup(sd); list_move(&sd->async_list, &subdev_list); @@ -504,11 +504,11 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier, struct v4l2_async_subdev *asd; struct v4l2_subdev *sd; - list_for_each_entry(asd, ¬ifier->waiting, list) + list_for_each_entry(asd, ¬ifier->waiting_list, waiting_entry) if (v4l2_async_match_equal(&asd->match, match)) return true; - list_for_each_entry(sd, ¬ifier->done, async_list) { + list_for_each_entry(sd, ¬ifier->done_list, async_list) { if (WARN_ON(!sd->asd)) continue; @@ -535,7 +535,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier, lockdep_assert_held(&list_lock); /* Check that an asd is not being added more than once. */ - list_for_each_entry(asd, ¬ifier->asd_list, asd_list) { + list_for_each_entry(asd, ¬ifier->asd_list, asd_entry) { if (skip_self && &asd->match == match) continue; if (v4l2_async_match_equal(&asd->match, match)) @@ -543,7 +543,7 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier, } /* Check that an asd does not exist in other notifiers. */ - list_for_each_entry(notifier, ¬ifier_list, list) + list_for_each_entry(notifier, ¬ifier_list, notifier_entry) if (v4l2_async_nf_has_async_match_entry(notifier, match)) return true; @@ -585,17 +585,17 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) struct v4l2_async_subdev *asd; int ret; - INIT_LIST_HEAD(¬ifier->waiting); - INIT_LIST_HEAD(¬ifier->done); + INIT_LIST_HEAD(¬ifier->waiting_list); + INIT_LIST_HEAD(¬ifier->done_list); mutex_lock(&list_lock); - list_for_each_entry(asd, ¬ifier->asd_list, asd_list) { + list_for_each_entry(asd, ¬ifier->asd_list, asd_entry) { ret = v4l2_async_nf_match_valid(notifier, &asd->match, true); if (ret) goto err_unlock; - list_add_tail(&asd->list, ¬ifier->waiting); + list_add_tail(&asd->waiting_entry, ¬ifier->waiting_list); } ret = v4l2_async_nf_try_all_subdevs(notifier); @@ -607,7 +607,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) goto err_unbind; /* Keep also completed notifiers on the list */ - list_add(¬ifier->list, ¬ifier_list); + list_add(¬ifier->notifier_entry, ¬ifier_list); mutex_unlock(&list_lock); @@ -672,7 +672,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier) notifier->sd = NULL; notifier->v4l2_dev = NULL; - list_del(¬ifier->list); + list_del(¬ifier->notifier_entry); } void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier) @@ -692,7 +692,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier) if (!notifier || !notifier->asd_list.next) return; - list_for_each_entry_safe(asd, tmp, ¬ifier->asd_list, asd_list) { + list_for_each_entry_safe(asd, tmp, ¬ifier->asd_list, asd_entry) { switch (asd->match.type) { case V4L2_ASYNC_MATCH_TYPE_FWNODE: fwnode_handle_put(asd->match.fwnode); @@ -701,7 +701,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier) break; } - list_del(&asd->asd_list); + list_del(&asd->asd_entry); v4l2_async_nf_call_destroy(notifier, asd); kfree(asd); } @@ -729,7 +729,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier, if (ret) goto unlock; - list_add_tail(&asd->asd_list, ¬ifier->asd_list); + list_add_tail(&asd->asd_entry, ¬ifier->asd_list); unlock: mutex_unlock(&list_lock); @@ -827,7 +827,7 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) INIT_LIST_HEAD(&sd->async_list); - list_for_each_entry(notifier, ¬ifier_list, list) { + list_for_each_entry(notifier, ¬ifier_list, notifier_entry) { struct v4l2_device *v4l2_dev = v4l2_async_nf_find_v4l2_dev(notifier); struct v4l2_async_subdev *asd; @@ -894,7 +894,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) if (sd->asd) { struct v4l2_async_notifier *notifier = sd->notifier; - list_add(&sd->asd->list, ¬ifier->waiting); + list_add(&sd->asd->waiting_entry, ¬ifier->waiting_list); v4l2_async_nf_call_unbind(notifier, sd, sd->asd); } @@ -948,9 +948,9 @@ static int pending_subdevs_show(struct seq_file *s, void *data) mutex_lock(&list_lock); - list_for_each_entry(notif, ¬ifier_list, list) { + list_for_each_entry(notif, ¬ifier_list, notifier_entry) { seq_printf(s, "%s:\n", v4l2_async_nf_name(notif)); - list_for_each_entry(asd, ¬if->waiting, list) + list_for_each_entry(asd, ¬if->waiting_list, waiting_entry) print_waiting_match(s, &asd->match); } diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 79284c3b6cae..9c5b6cfdc8e9 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1464,7 +1464,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan, struct tegra_vi_graph_entity *entity; struct v4l2_async_subdev *asd; - list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) { + list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) { entity = to_tegra_vi_graph_entity(asd); if (entity->asd.match.fwnode == fwnode) return entity; @@ -1608,7 +1608,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier) } /* create links between the entities */ - list_for_each_entry(asd, &chan->notifier.asd_list, asd_list) { + list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) { entity = to_tegra_vi_graph_entity(asd); ret = tegra_vi_graph_build(chan, entity); if (ret < 0) diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 8d1506a9755c..03ac6520f3d2 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -65,10 +65,10 @@ struct v4l2_async_match_desc { * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge * * @match: struct of match type and per-bus type matching data sets - * @asd_list: used to add struct v4l2_async_subdev objects to the + * @asd_entry: used to add struct v4l2_async_subdev objects to the * master notifier @asd_list - * @list: used to link struct v4l2_async_subdev objects, waiting to be - * probed, to a notifier->waiting list + * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be + * probed, to a notifier->waiting_list list * * When this struct is used as a member in a driver specific struct, * the driver specific struct shall contain the &struct @@ -76,8 +76,8 @@ struct v4l2_async_match_desc { */ struct v4l2_async_subdev { struct v4l2_async_match_desc match; - struct list_head list; - struct list_head asd_list; + struct list_head asd_entry; + struct list_head waiting_entry; }; /** @@ -107,9 +107,9 @@ struct v4l2_async_notifier_operations { * @sd: sub-device that registered the notifier, NULL otherwise * @parent: parent notifier * @asd_list: master list of struct v4l2_async_subdev - * @waiting: list of struct v4l2_async_subdev, waiting for their drivers - * @done: list of struct v4l2_subdev, already probed - * @list: member in a global list of notifiers + * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers + * @done_list: list of struct v4l2_subdev, already probed + * @notifier_entry: member in a global list of notifiers */ struct v4l2_async_notifier { const struct v4l2_async_notifier_operations *ops; @@ -117,9 +117,9 @@ struct v4l2_async_notifier { struct v4l2_subdev *sd; struct v4l2_async_notifier *parent; struct list_head asd_list; - struct list_head waiting; - struct list_head done; - struct list_head list; + struct list_head waiting_list; + struct list_head done_list; + struct list_head notifier_entry; }; /** diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b325df0d54d6..b58c7a325e99 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1020,8 +1020,8 @@ struct v4l2_subdev_platform_data { * @dev: pointer to the physical device, if any * @fwnode: The fwnode_handle of the subdev, usually the same as * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). - * @async_list: Links this subdev to a global subdev_list or @notifier->done - * list. + * @async_list: Links this subdev to a global subdev_list or + * @notifier->done_list list. * @asd: Pointer to respective &struct v4l2_async_subdev. * @notifier: Pointer to the managing notifier. * @subdev_notifier: A sub-device notifier implicitly registered for the sub- -- cgit v1.2.3 From adb2dcd5f2d49d3ba3171160fabd4be0d4b2a86c Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 16 Feb 2023 14:54:53 +0100 Subject: media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename v4l2_async_subdev as v4l2_async_connection, in order to differentiate between the sub-devices and their connections: one sub-device can have many connections but the V4L2 async framework has so far allowed just a single one. Connections in this context will later translate into either MC ancillary or data links. This patch prepares changing that relation by changing existing users of v4l2_async_subdev to switch to v4l2_async_connection. Async sub-devices themselves will not be needed anymore Additionally, __v4l2_async_nf_add_subdev() has been renamed __v4l2_async_nf_add_connection(). Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- Documentation/driver-api/media/v4l2-subdev.rst | 51 ++++--- drivers/media/i2c/ds90ub913.c | 6 +- drivers/media/i2c/ds90ub953.c | 6 +- drivers/media/i2c/ds90ub960.c | 8 +- drivers/media/i2c/max9286.c | 9 +- drivers/media/i2c/st-mipid02.c | 8 +- drivers/media/i2c/tc358746.c | 6 +- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 10 +- drivers/media/platform/atmel/atmel-isi.c | 8 +- drivers/media/platform/cadence/cdns-csi2rx.c | 6 +- drivers/media/platform/intel/pxa_camera.c | 12 +- drivers/media/platform/marvell/cafe-driver.c | 5 +- drivers/media/platform/marvell/mcam-core.c | 4 +- drivers/media/platform/marvell/mmp-driver.c | 4 +- .../media/platform/microchip/microchip-csi2dc.c | 6 +- .../media/platform/microchip/microchip-isc-base.c | 4 +- drivers/media/platform/microchip/microchip-isc.h | 2 +- .../platform/microchip/microchip-sama5d2-isc.c | 4 +- .../platform/microchip/microchip-sama7g5-isc.c | 4 +- drivers/media/platform/nxp/imx-mipi-csis.c | 6 +- drivers/media/platform/nxp/imx7-media-csi.c | 6 +- .../media/platform/nxp/imx8-isi/imx8-isi-core.c | 8 +- drivers/media/platform/nxp/imx8mq-mipi-csi2.c | 6 +- drivers/media/platform/qcom/camss/camss.c | 2 +- drivers/media/platform/qcom/camss/camss.h | 2 +- drivers/media/platform/renesas/rcar-isp.c | 8 +- .../media/platform/renesas/rcar-vin/rcar-core.c | 44 +++--- .../media/platform/renesas/rcar-vin/rcar-csi2.c | 16 +-- drivers/media/platform/renesas/rcar-vin/rcar-vin.h | 10 +- drivers/media/platform/renesas/rcar_drif.c | 8 +- drivers/media/platform/renesas/renesas-ceu.c | 6 +- .../media/platform/renesas/rzg2l-cru/rzg2l-core.c | 10 +- .../media/platform/renesas/rzg2l-cru/rzg2l-cru.h | 2 +- .../media/platform/renesas/rzg2l-cru/rzg2l-csi2.c | 8 +- .../media/platform/rockchip/rkisp1/rkisp1-common.h | 2 +- .../media/platform/rockchip/rkisp1/rkisp1-dev.c | 8 +- .../media/platform/samsung/exynos4-is/media-dev.c | 6 +- .../media/platform/samsung/exynos4-is/media-dev.h | 2 +- drivers/media/platform/st/stm32/stm32-dcmi.c | 8 +- drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c | 6 +- .../platform/sunxi/sun6i-csi/sun6i_csi_bridge.c | 2 +- .../platform/sunxi/sun6i-csi/sun6i_csi_bridge.h | 2 +- .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 6 +- .../sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c | 6 +- drivers/media/platform/ti/am437x/am437x-vpfe.c | 5 +- drivers/media/platform/ti/am437x/am437x-vpfe.h | 2 +- drivers/media/platform/ti/cal/cal.c | 6 +- drivers/media/platform/ti/davinci/vpif_capture.c | 7 +- drivers/media/platform/ti/omap3isp/isp.c | 4 +- drivers/media/platform/ti/omap3isp/isp.h | 2 +- drivers/media/platform/video-mux.c | 6 +- drivers/media/platform/xilinx/xilinx-vipp.c | 22 +-- drivers/media/v4l2-core/v4l2-async.c | 159 ++++++++++----------- drivers/media/v4l2-core/v4l2-fwnode.c | 8 +- .../media/atomisp/pci/atomisp_csi2_bridge.c | 6 +- .../media/deprecated/atmel/atmel-isc-base.c | 4 +- drivers/staging/media/deprecated/atmel/atmel-isc.h | 2 +- .../media/deprecated/atmel/atmel-sama5d2-isc.c | 4 +- .../media/deprecated/atmel/atmel-sama7g5-isc.c | 4 +- drivers/staging/media/imx/imx-media-csi.c | 6 +- drivers/staging/media/imx/imx-media-dev-common.c | 2 +- drivers/staging/media/imx/imx-media-dev.c | 2 +- drivers/staging/media/imx/imx-media-of.c | 4 +- drivers/staging/media/imx/imx6-mipi-csi2.c | 8 +- .../staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c | 2 +- .../staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h | 2 +- drivers/staging/media/tegra-video/vi.c | 16 +-- include/media/davinci/vpif_types.h | 2 +- include/media/v4l2-async.h | 87 +++++------ include/media/v4l2-subdev.h | 4 +- 70 files changed, 368 insertions(+), 361 deletions(-) (limited to 'drivers/staging') diff --git a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst index 327d444f34dc..eba5e4468282 100644 --- a/Documentation/driver-api/media/v4l2-subdev.rst +++ b/Documentation/driver-api/media/v4l2-subdev.rst @@ -206,60 +206,67 @@ of an unregister notifier, it must be cleaned up by calling Before registering the notifier, bridge drivers must do two things: first, the notifier must be initialized using the :c:func:`v4l2_async_nf_init`. Second, -bridge drivers can then begin to form a list of subdevice descriptors that the -bridge device needs for its operation. :c:func:`v4l2_async_nf_add_fwnode`, +bridge drivers can then begin to form a list of async connection descriptors +that the bridge device needs for its +operation. :c:func:`v4l2_async_nf_add_fwnode`, :c:func:`v4l2_async_nf_add_fwnode_remote` and :c:func:`v4l2_async_nf_add_i2c` -are available for that purpose. + +Async connection descriptors describe connections to external sub-devices the +drivers for which are not yet probed. Based on an async connection, a media data +or ancillary link may be created when the related sub-device becomes +available. There may be one or more async connections to a given sub-device but +this is not known at the time of adding the connections to the notifier. Async +connections are bound as matching async sub-devices are found, one by one. Asynchronous sub-device registration helper for camera sensor drivers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :c:func:`v4l2_async_register_subdev_sensor` is a helper function for sensor -drivers registering their own async sub-device, but it also registers a notifier -and further registers async sub-devices for lens and flash devices found in +drivers registering their own async connection, but it also registers a notifier +and further registers async connections for lens and flash devices found in firmware. The notifier for the sub-device is unregistered and cleaned up with the async sub-device, using :c:func:`v4l2_async_unregister_subdev`. Asynchronous sub-device notifier example ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -These functions allocate an async sub-device descriptor which is of type struct -:c:type:`v4l2_async_subdev` embedded in a driver-specific struct. The &struct -:c:type:`v4l2_async_subdev` shall be the first member of this struct: +These functions allocate an async connection descriptor which is of type struct +:c:type:`v4l2_async_connection` embedded in a driver-specific struct. The &struct +:c:type:`v4l2_async_connection` shall be the first member of this struct: .. code-block:: c - struct my_async_subdev { - struct v4l2_async_subdev asd; + struct my_async_connection { + struct v4l2_async_connection asc; ... }; - struct my_async_subdev *my_asd; + struct my_async_connection *my_asc; struct fwnode_handle *ep; ... - my_asd = v4l2_async_nf_add_fwnode_remote(¬ifier, ep, - struct my_async_subdev); + my_asc = v4l2_async_nf_add_fwnode_remote(¬ifier, ep, + struct my_async_connection); fwnode_handle_put(ep); - if (IS_ERR(my_asd)) - return PTR_ERR(my_asd); + if (IS_ERR(my_asc)) + return PTR_ERR(my_asc); Asynchronous sub-device notifier callbacks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The V4L2 core will then use these descriptors to match asynchronously -registered subdevices to them. If a match is detected the ``.bound()`` -notifier callback is called. After all subdevices have been located the -.complete() callback is called. When a subdevice is removed from the -system the .unbind() method is called. All three callbacks are optional. +The V4L2 core will then use these connection descriptors to match asynchronously +registered subdevices to them. If a match is detected the ``.bound()`` notifier +callback is called. After all connections have been bound the .complete() +callback is called. When a connection is removed from the system the +``.unbind()`` method is called. All three callbacks are optional. Drivers can store any type of custom data in their driver-specific -:c:type:`v4l2_async_subdev` wrapper. If any of that data requires special +:c:type:`v4l2_async_connection` wrapper. If any of that data requires special handling when the structure is freed, drivers must implement the ``.destroy()`` notifier callback. The framework will call it right before freeing the -:c:type:`v4l2_async_subdev`. +:c:type:`v4l2_async_connection`. Calling subdev operations ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c index 55be28463ca2..349c34724eee 100644 --- a/drivers/media/i2c/ds90ub913.c +++ b/drivers/media/i2c/ds90ub913.c @@ -518,7 +518,7 @@ static const struct media_entity_operations ub913_entity_ops = { static int ub913_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *source_subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct ub913_data *priv = sd_to_ub913(notifier->sd); struct device *dev = &priv->client->dev; @@ -557,7 +557,7 @@ static const struct v4l2_async_notifier_operations ub913_notify_ops = { static int ub913_v4l2_notifier_register(struct ub913_data *priv) { struct device *dev = &priv->client->dev; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep_fwnode; int ret; @@ -571,7 +571,7 @@ static int ub913_v4l2_notifier_register(struct ub913_data *priv) v4l2_async_nf_init(&priv->notifier); asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep_fwnode); diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c index 591b52bf71c2..440af7bdd73a 100644 --- a/drivers/media/i2c/ds90ub953.c +++ b/drivers/media/i2c/ds90ub953.c @@ -723,7 +723,7 @@ static const struct media_entity_operations ub953_entity_ops = { static int ub953_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *source_subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct ub953_data *priv = sd_to_ub953(notifier->sd); struct device *dev = &priv->client->dev; @@ -762,7 +762,7 @@ static const struct v4l2_async_notifier_operations ub953_notify_ops = { static int ub953_v4l2_notifier_register(struct ub953_data *priv) { struct device *dev = &priv->client->dev; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep_fwnode; int ret; @@ -776,7 +776,7 @@ static int ub953_v4l2_notifier_register(struct ub953_data *priv) v4l2_async_nf_init(&priv->notifier); asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep_fwnode); diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c index b9a1ef63629b..a2b1056ba99b 100644 --- a/drivers/media/i2c/ds90ub960.c +++ b/drivers/media/i2c/ds90ub960.c @@ -471,11 +471,11 @@ struct ub960_rxport { }; struct ub960_asd { - struct v4l2_async_subdev base; + struct v4l2_async_connection base; struct ub960_rxport *rxport; }; -static inline struct ub960_asd *to_ub960_asd(struct v4l2_async_subdev *asd) +static inline struct ub960_asd *to_ub960_asd(struct v4l2_async_connection *asd) { return container_of(asd, struct ub960_asd, base); } @@ -3538,7 +3538,7 @@ err_free_rxports: static int ub960_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct ub960_data *priv = sd_to_ub960(notifier->sd); struct ub960_rxport *rxport = to_ub960_asd(asd)->rxport; @@ -3581,7 +3581,7 @@ static int ub960_notify_bound(struct v4l2_async_notifier *notifier, static void ub960_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct ub960_rxport *rxport = to_ub960_asd(asd)->rxport; diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index a1f86dbc9e1a..78c77cd50823 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -161,11 +161,12 @@ struct max9286_source { }; struct max9286_asd { - struct v4l2_async_subdev base; + struct v4l2_async_connection base; struct max9286_source *source; }; -static inline struct max9286_asd *to_max9286_asd(struct v4l2_async_subdev *asd) +static inline struct max9286_asd * +to_max9286_asd(struct v4l2_async_connection *asd) { return container_of(asd, struct max9286_asd, base); } @@ -659,7 +660,7 @@ static int max9286_set_pixelrate(struct max9286_priv *priv) static int max9286_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct max9286_priv *priv = sd_to_max9286(notifier->sd); struct max9286_source *source = to_max9286_asd(asd)->source; @@ -721,7 +722,7 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier, static void max9286_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct max9286_priv *priv = sd_to_max9286(notifier->sd); struct max9286_source *source = to_max9286_asd(asd)->source; diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c index 906553a28676..5cd87b1d5759 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -829,7 +829,7 @@ static const struct media_entity_operations mipid02_subdev_entity_ops = { static int mipid02_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *s_subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); struct i2c_client *client = bridge->i2c_client; @@ -863,7 +863,7 @@ static int mipid02_async_bound(struct v4l2_async_notifier *notifier, static void mipid02_async_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *s_subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); @@ -879,7 +879,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge) { struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; struct i2c_client *client = bridge->i2c_client; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct device_node *ep_node; int ret; @@ -914,7 +914,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge) v4l2_async_nf_init(&bridge->notifier); asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier, of_fwnode_handle(ep_node), - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(ep_node); if (IS_ERR(asd)) { diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c index f37373c257c6..203eb337efce 100644 --- a/drivers/media/i2c/tc358746.c +++ b/drivers/media/i2c/tc358746.c @@ -1426,7 +1426,7 @@ static int tc358746_init_controls(struct tc358746 *tc358746) static int tc358746_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct tc358746 *tc358746 = container_of(notifier, struct tc358746, notifier); @@ -1445,7 +1445,7 @@ static int tc358746_async_register(struct tc358746 *tc358746) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_PARALLEL, }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep; int err; @@ -1462,7 +1462,7 @@ static int tc358746_async_register(struct tc358746 *tc358746) v4l2_async_nf_init(&tc358746->notifier); asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep); if (IS_ERR(asd)) { diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 8dcc4e963498..8319d27fa0e6 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1372,7 +1372,7 @@ static const struct v4l2_subdev_ops cio2_subdev_ops = { /******* V4L2 sub-device asynchronous registration callbacks***********/ struct sensor_async_subdev { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; struct csi2_bus_info csi2; }; @@ -1382,7 +1382,7 @@ struct sensor_async_subdev { /* The .bound() notifier callback when a match is found */ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct cio2_device *cio2 = to_cio2_device(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); @@ -1403,7 +1403,7 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, /* The .unbind callback */ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct cio2_device *cio2 = to_cio2_device(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); @@ -1417,11 +1417,11 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) struct cio2_device *cio2 = to_cio2_device(notifier); struct device *dev = &cio2->pci_dev->dev; struct sensor_async_subdev *s_asd; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct cio2_queue *q; int ret; - list_for_each_entry(asd, &cio2->notifier.asd_list, asd_entry) { + list_for_each_entry(asd, &cio2->notifier.asc_list, asc_entry) { s_asd = to_sensor_asd(asd); q = &cio2->queue[s_asd->csi2.port]; diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index 086353198d2a..13902b944731 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -1120,7 +1120,7 @@ static int isi_graph_notify_complete(struct v4l2_async_notifier *notifier) static void isi_graph_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct atmel_isi *isi = notifier_to_isi(notifier); @@ -1132,7 +1132,7 @@ static void isi_graph_notify_unbind(struct v4l2_async_notifier *notifier, static int isi_graph_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct atmel_isi *isi = notifier_to_isi(notifier); @@ -1151,7 +1151,7 @@ static const struct v4l2_async_notifier_operations isi_graph_notify_ops = { static int isi_graph_init(struct atmel_isi *isi) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct device_node *ep; int ret; @@ -1163,7 +1163,7 @@ static int isi_graph_init(struct atmel_isi *isi) asd = v4l2_async_nf_add_fwnode_remote(&isi->notifier, of_fwnode_handle(ep), - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(ep); if (IS_ERR(asd)) diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c index f2b4574b8216..a6d7de98b755 100644 --- a/drivers/media/platform/cadence/cdns-csi2rx.c +++ b/drivers/media/platform/cadence/cdns-csi2rx.c @@ -313,7 +313,7 @@ static const struct v4l2_subdev_ops csi2rx_subdev_ops = { static int csi2rx_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *s_subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct v4l2_subdev *subdev = notifier->sd; struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev); @@ -440,7 +440,7 @@ static int csi2rx_get_resources(struct csi2rx_priv *csi2rx, static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx) { struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *fwh; struct device_node *ep; int ret; @@ -477,7 +477,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx) v4l2_async_nf_init(&csi2rx->notifier); asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh, - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(ep); if (IS_ERR(asd)) return PTR_ERR(asd); diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c index f229c5f02b3c..1544102554da 100644 --- a/drivers/media/platform/intel/pxa_camera.c +++ b/drivers/media/platform/intel/pxa_camera.c @@ -2044,7 +2044,7 @@ static const struct video_device pxa_camera_videodev_template = { static int pxa_camera_sensor_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { int err; struct v4l2_device *v4l2_dev = notifier->v4l2_dev; @@ -2123,7 +2123,7 @@ out: static void pxa_camera_sensor_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct pxa_camera_dev *pcdev = v4l2_dev_to_pcdev(notifier->v4l2_dev); @@ -2197,7 +2197,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev, struct pxa_camera_dev *pcdev) { u32 mclk_rate; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct device_node *np = dev->of_node; struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; int err = of_property_read_u32(np, "clock-frequency", @@ -2252,7 +2252,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev, asd = v4l2_async_nf_add_fwnode_remote(&pcdev->notifier, of_fwnode_handle(np), - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(asd)) err = PTR_ERR(asd); out: @@ -2299,14 +2299,14 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->res = res; pcdev->pdata = pdev->dev.platform_data; if (pcdev->pdata) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; pcdev->platform_flags = pcdev->pdata->flags; pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; asd = v4l2_async_nf_add_i2c(&pcdev->notifier, pcdev->pdata->sensor_i2c_adapter_id, pcdev->pdata->sensor_i2c_address, - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(asd)) err = PTR_ERR(asd); } else if (pdev->dev.of_node) { diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c index ae97ce4ead98..dd1bba70bd79 100644 --- a/drivers/media/platform/marvell/cafe-driver.c +++ b/drivers/media/platform/marvell/cafe-driver.c @@ -478,7 +478,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, int ret; struct cafe_camera *cam; struct mcam_camera *mcam; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct i2c_client *i2c_dev; /* @@ -540,7 +540,8 @@ static int cafe_pci_probe(struct pci_dev *pdev, asd = v4l2_async_nf_add_i2c(&mcam->notifier, i2c_adapter_id(cam->i2c_adapter), - ov7670_info.addr, struct v4l2_async_subdev); + ov7670_info.addr, + struct v4l2_async_connection); if (IS_ERR(asd)) { ret = PTR_ERR(asd); goto out_smbus_shutdown; diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c index 154bdcb3f2cc..3cee6d6b83fa 100644 --- a/drivers/media/platform/marvell/mcam-core.c +++ b/drivers/media/platform/marvell/mcam-core.c @@ -1756,7 +1756,7 @@ EXPORT_SYMBOL_GPL(mccic_irq); */ static int mccic_notify_bound(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd) + struct v4l2_subdev *subdev, struct v4l2_async_connection *asd) { struct mcam_camera *cam = notifier_to_mcam(notifier); int ret; @@ -1801,7 +1801,7 @@ out: } static void mccic_notify_unbind(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd) + struct v4l2_subdev *subdev, struct v4l2_async_connection *asd) { struct mcam_camera *cam = notifier_to_mcam(notifier); diff --git a/drivers/media/platform/marvell/mmp-driver.c b/drivers/media/platform/marvell/mmp-driver.c index 862583e9f40d..43e046b82115 100644 --- a/drivers/media/platform/marvell/mmp-driver.c +++ b/drivers/media/platform/marvell/mmp-driver.c @@ -180,7 +180,7 @@ static int mmpcam_probe(struct platform_device *pdev) struct resource *res; struct fwnode_handle *ep; struct mmp_camera_platform_data *pdata; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; int ret; cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL); @@ -241,7 +241,7 @@ static int mmpcam_probe(struct platform_device *pdev) v4l2_async_nf_init(&mcam->notifier); asd = v4l2_async_nf_add_fwnode_remote(&mcam->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep); if (IS_ERR(asd)) { ret = PTR_ERR(asd); diff --git a/drivers/media/platform/microchip/microchip-csi2dc.c b/drivers/media/platform/microchip/microchip-csi2dc.c index bfb3edcf018a..d631c3880c53 100644 --- a/drivers/media/platform/microchip/microchip-csi2dc.c +++ b/drivers/media/platform/microchip/microchip-csi2dc.c @@ -476,7 +476,7 @@ static const struct v4l2_subdev_ops csi2dc_subdev_ops = { static int csi2dc_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct csi2dc_device *csi2dc = container_of(notifier, struct csi2dc_device, notifier); @@ -520,14 +520,14 @@ static const struct v4l2_async_notifier_operations csi2dc_async_ops = { static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc, struct fwnode_handle *input_fwnode) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; int ret = 0; v4l2_async_nf_init(&csi2dc->notifier); asd = v4l2_async_nf_add_fwnode_remote(&csi2dc->notifier, input_fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(input_fwnode); diff --git a/drivers/media/platform/microchip/microchip-isc-base.c b/drivers/media/platform/microchip/microchip-isc-base.c index 4e657fad33d0..8dbf7bc1e863 100644 --- a/drivers/media/platform/microchip/microchip-isc-base.c +++ b/drivers/media/platform/microchip/microchip-isc-base.c @@ -1712,7 +1712,7 @@ static int isc_ctrl_init(struct isc_device *isc) static int isc_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct isc_device *isc = container_of(notifier->v4l2_dev, struct isc_device, v4l2_dev); @@ -1741,7 +1741,7 @@ static int isc_async_bound(struct v4l2_async_notifier *notifier, static void isc_async_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct isc_device *isc = container_of(notifier->v4l2_dev, struct isc_device, v4l2_dev); diff --git a/drivers/media/platform/microchip/microchip-isc.h b/drivers/media/platform/microchip/microchip-isc.h index e3a6c7367e70..ad4e98a1dd8f 100644 --- a/drivers/media/platform/microchip/microchip-isc.h +++ b/drivers/media/platform/microchip/microchip-isc.h @@ -44,7 +44,7 @@ struct isc_buffer { struct isc_subdev_entity { struct v4l2_subdev *sd; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct device_node *epn; struct v4l2_async_notifier notifier; diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c index dfebb58bfd07..e8dfe30cc62d 100644 --- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c +++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c @@ -523,7 +523,7 @@ static int microchip_isc_probe(struct platform_device *pdev) } list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); @@ -531,7 +531,7 @@ static int microchip_isc_probe(struct platform_device *pdev) asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(subdev_entity->epn); subdev_entity->epn = NULL; diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c index 2543e05a3389..cd982a995d72 100644 --- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c +++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c @@ -513,7 +513,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) } list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); @@ -521,7 +521,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(subdev_entity->epn); subdev_entity->epn = NULL; diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c index 8483ce576975..f7d64fb48434 100644 --- a/drivers/media/platform/nxp/imx-mipi-csis.c +++ b/drivers/media/platform/nxp/imx-mipi-csis.c @@ -1229,7 +1229,7 @@ mipi_notifier_to_csis_state(struct v4l2_async_notifier *n) static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct mipi_csis_device *csis = mipi_notifier_to_csis_state(notifier); struct media_pad *sink = &csis->sd.entity.pads[CSIS_PAD_SINK]; @@ -1246,7 +1246,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY, }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep; unsigned int i; int ret; @@ -1277,7 +1277,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis) dev_dbg(csis->dev, "flags: 0x%08x\n", csis->bus.flags); asd = v4l2_async_nf_add_fwnode_remote(&csis->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(asd)) { ret = PTR_ERR(asd); goto err_parse; diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index 2ec1f3cd56a0..565c093fdff2 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -2032,7 +2032,7 @@ static const struct media_entity_operations imx7_csi_entity_ops = { static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier); struct media_pad *sink = &csi->sd.entity.pads[IMX7_CSI_PAD_SINK]; @@ -2057,7 +2057,7 @@ static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = { static int imx7_csi_async_register(struct imx7_csi *csi) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep; int ret; @@ -2072,7 +2072,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi) } asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep); diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c index 186db02aa84e..da1572f8ff42 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c @@ -30,12 +30,12 @@ */ struct mxc_isi_async_subdev { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; unsigned int port; }; static inline struct mxc_isi_async_subdev * -asd_to_mxc_isi_async_subdev(struct v4l2_async_subdev *asd) +asd_to_mxc_isi_async_subdev(struct v4l2_async_connection *asd) { return container_of(asd, struct mxc_isi_async_subdev, asd); }; @@ -48,12 +48,12 @@ notifier_to_mxc_isi_dev(struct v4l2_async_notifier *n) static int mxc_isi_async_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { const unsigned int link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; struct mxc_isi_dev *isi = notifier_to_mxc_isi_dev(notifier); - struct mxc_isi_async_subdev *masd = asd_to_mxc_isi_async_subdev(asd); + struct mxc_isi_async_subdev *masd = asd_to_mxc_isi_async_subdev(asc); struct media_pad *pad = &isi->crossbar.pads[masd->port]; struct device_link *link; diff --git a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c index ca2efcc21efe..326c3763b85a 100644 --- a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c +++ b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c @@ -567,7 +567,7 @@ mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n) static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct csi_state *state = mipi_notifier_to_csi2_state(notifier); struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK]; @@ -587,7 +587,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY, }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep; unsigned int i; int ret; @@ -619,7 +619,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state) state->bus.flags); asd = v4l2_async_nf_add_fwnode_remote(&state->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(asd)) { ret = PTR_ERR(asd); goto err_parse; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 1ef26aea3eae..006855bf076b 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -1383,7 +1383,7 @@ static void camss_unregister_entities(struct camss *camss) static int camss_subdev_notifier_bound(struct v4l2_async_notifier *async, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct camss *camss = container_of(async, struct camss, notifier); struct camss_async_subdev *csd = diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 3acd2b3403e8..f6c326cb853b 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -113,7 +113,7 @@ struct camss_camera_interface { }; struct camss_async_subdev { - struct v4l2_async_subdev asd; /* must be first */ + struct v4l2_async_connection asd; /* must be first */ struct camss_camera_interface interface; }; diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c index 5e300fffd676..9e3b8a8850a0 100644 --- a/drivers/media/platform/renesas/rcar-isp.c +++ b/drivers/media/platform/renesas/rcar-isp.c @@ -326,7 +326,7 @@ static const struct v4l2_subdev_ops rcar_isp_subdev_ops = { static int risp_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rcar_isp *isp = notifier_to_isp(notifier); int pad; @@ -350,7 +350,7 @@ static int risp_notify_bound(struct v4l2_async_notifier *notifier, static void risp_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rcar_isp *isp = notifier_to_isp(notifier); @@ -366,7 +366,7 @@ static const struct v4l2_async_notifier_operations risp_notify_ops = { static int risp_parse_dt(struct rcar_isp *isp) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *fwnode; struct fwnode_handle *ep; unsigned int id; @@ -396,7 +396,7 @@ static int risp_parse_dt(struct rcar_isp *isp) isp->notifier.ops = &risp_notify_ops; asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(fwnode); if (IS_ERR(asd)) return PTR_ERR(asd); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index 36f1bf5803a4..5bba9e068fe3 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -251,7 +251,7 @@ static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier) static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); unsigned int i; @@ -263,7 +263,7 @@ static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier, mutex_lock(&vin->group->lock); for (i = 0; i < RVIN_CSI_MAX; i++) { - if (vin->group->remotes[i].asd != asd) + if (vin->group->remotes[i].asc != asc) continue; vin->group->remotes[i].subdev = NULL; vin_dbg(vin, "Unbind %s from slot %u\n", subdev->name, i); @@ -277,7 +277,7 @@ static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier, static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); unsigned int i; @@ -285,7 +285,7 @@ static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier, mutex_lock(&vin->group->lock); for (i = 0; i < RVIN_CSI_MAX; i++) { - if (vin->group->remotes[i].asd != asd) + if (vin->group->remotes[i].asc != asc) continue; vin->group->remotes[i].subdev = subdev; vin_dbg(vin, "Bound %s to slot %u\n", subdev->name, i); @@ -310,7 +310,7 @@ static int rvin_group_parse_of(struct rvin_dev *vin, unsigned int port, struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY, }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; int ret; ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), port, id, 0); @@ -326,14 +326,14 @@ static int rvin_group_parse_of(struct rvin_dev *vin, unsigned int port, goto out; } - asd = v4l2_async_nf_add_fwnode(&vin->group->notifier, fwnode, - struct v4l2_async_subdev); - if (IS_ERR(asd)) { - ret = PTR_ERR(asd); + asc = v4l2_async_nf_add_fwnode(&vin->group->notifier, fwnode, + struct v4l2_async_connection); + if (IS_ERR(asc)) { + ret = PTR_ERR(asc); goto out; } - vin->group->remotes[vep.base.id].asd = asd; + vin->group->remotes[vep.base.id].asc = asc; vin_dbg(vin, "Add group OF device %pOF to slot %u\n", to_of_node(fwnode), vep.base.id); @@ -386,7 +386,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port, continue; for (id = 0; id < max_id; id++) { - if (vin->group->remotes[id].asd) + if (vin->group->remotes[id].asc) continue; ret = rvin_group_parse_of(vin->group->vin[i], port, id); @@ -395,7 +395,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port, } } - if (list_empty(&vin->group->notifier.asd_list)) + if (list_empty(&vin->group->notifier.asc_list)) return 0; vin->group->notifier.ops = &rvin_group_notify_ops; @@ -610,7 +610,7 @@ static int rvin_parallel_notify_complete(struct v4l2_async_notifier *notifier) static void rvin_parallel_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); @@ -623,7 +623,7 @@ static void rvin_parallel_notify_unbind(struct v4l2_async_notifier *notifier, static int rvin_parallel_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); int ret; @@ -655,7 +655,7 @@ static int rvin_parallel_parse_of(struct rvin_dev *vin) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_UNKNOWN, }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; int ret; ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), 0, 0, 0); @@ -686,14 +686,14 @@ static int rvin_parallel_parse_of(struct rvin_dev *vin) goto out; } - asd = v4l2_async_nf_add_fwnode(&vin->notifier, fwnode, - struct v4l2_async_subdev); - if (IS_ERR(asd)) { - ret = PTR_ERR(asd); + asc = v4l2_async_nf_add_fwnode(&vin->notifier, fwnode, + struct v4l2_async_connection); + if (IS_ERR(asc)) { + ret = PTR_ERR(asc); goto out; } - vin->parallel.asd = asd; + vin->parallel.asc = asc; vin_dbg(vin, "Add parallel OF device %pOF\n", to_of_node(fwnode)); out: @@ -718,11 +718,11 @@ static int rvin_parallel_init(struct rvin_dev *vin) if (ret) return ret; - if (!vin->parallel.asd) + if (!vin->parallel.asc) return -ENODEV; vin_dbg(vin, "Found parallel subdevice %pOF\n", - to_of_node(vin->parallel.asd->match.fwnode)); + to_of_node(vin->parallel.asc->match.fwnode)); vin->notifier.ops = &rvin_parallel_notify_ops; ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->notifier); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c index e4aac84d0b5f..c3a117995493 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c @@ -988,12 +988,12 @@ static irqreturn_t rcsi2_irq_thread(int irq, void *data) static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct rcar_csi2 *priv = notifier_to_csi2(notifier); int pad; - pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, + pad = media_entity_get_fwnode_pad(&subdev->entity, asc->match.fwnode, MEDIA_PAD_FL_SOURCE); if (pad < 0) { dev_err(priv->dev, "Failed to find pad for %s\n", subdev->name); @@ -1013,7 +1013,7 @@ static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier, static void rcsi2_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct rcar_csi2 *priv = notifier_to_csi2(notifier); @@ -1090,7 +1090,7 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv, static int rcsi2_parse_dt(struct rcar_csi2 *priv) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; struct fwnode_handle *fwnode; struct fwnode_handle *ep; struct v4l2_fwnode_endpoint v4l2_ep = { @@ -1125,11 +1125,11 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv) v4l2_async_nf_init(&priv->notifier); priv->notifier.ops = &rcar_csi2_notify_ops; - asd = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode, - struct v4l2_async_subdev); + asc = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode, + struct v4l2_async_connection); fwnode_handle_put(fwnode); - if (IS_ERR(asd)) - return PTR_ERR(asd); + if (IS_ERR(asc)) + return PTR_ERR(asc); ret = v4l2_async_subdev_nf_register(&priv->subdev, &priv->notifier); if (ret) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h index cb206d3976dd..792336dada44 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h +++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h @@ -106,7 +106,7 @@ struct rvin_video_format { /** * struct rvin_parallel_entity - Parallel video input endpoint descriptor - * @asd: sub-device descriptor for async framework + * @asc: async connection descriptor for async framework * @subdev: subdevice matched using async framework * @mbus_type: media bus type * @bus: media bus parallel configuration @@ -115,7 +115,7 @@ struct rvin_video_format { * */ struct rvin_parallel_entity { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; struct v4l2_subdev *subdev; enum v4l2_mbus_type mbus_type; @@ -272,10 +272,10 @@ struct rvin_dev { * * @lock: protects the count, notifier, vin and csi members * @count: number of enabled VIN instances found in DT - * @notifier: group notifier for CSI-2 async subdevices + * @notifier: group notifier for CSI-2 async connections * @vin: VIN instances which are part of the group * @link_setup: Callback to create all links for the media graph - * @remotes: array of pairs of fwnode and subdev pointers + * @remotes: array of pairs of async connection and subdev pointers * to all remote subdevices. */ struct rvin_group { @@ -291,7 +291,7 @@ struct rvin_group { int (*link_setup)(struct rvin_dev *vin); struct { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; struct v4l2_subdev *subdev; } remotes[RVIN_REMOTES_MAX]; }; diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c index 06173cae354c..ef24bab04995 100644 --- a/drivers/media/platform/renesas/rcar_drif.c +++ b/drivers/media/platform/renesas/rcar_drif.c @@ -1098,7 +1098,7 @@ static void rcar_drif_sdr_unregister(struct rcar_drif_sdr *sdr) /* Sub-device bound callback */ static int rcar_drif_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rcar_drif_sdr *sdr = container_of(notifier, struct rcar_drif_sdr, notifier); @@ -1113,7 +1113,7 @@ static int rcar_drif_notify_bound(struct v4l2_async_notifier *notifier, /* Sub-device unbind callback */ static void rcar_drif_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rcar_drif_sdr *sdr = container_of(notifier, struct rcar_drif_sdr, notifier); @@ -1206,7 +1206,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr) { struct v4l2_async_notifier *notifier = &sdr->notifier; struct fwnode_handle *fwnode, *ep; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; v4l2_async_nf_init(notifier); @@ -1226,7 +1226,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr) } asd = v4l2_async_nf_add_fwnode(notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(fwnode); if (IS_ERR(asd)) return PTR_ERR(asd); diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c index a5f9d7bcd172..f9e0bb954307 100644 --- a/drivers/media/platform/renesas/renesas-ceu.c +++ b/drivers/media/platform/renesas/renesas-ceu.c @@ -151,7 +151,7 @@ static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf) * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice. */ struct ceu_subdev { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; struct v4l2_subdev *v4l2_sd; /* per-subdevice mbus configuration options */ @@ -159,7 +159,7 @@ struct ceu_subdev { struct ceu_mbus_fmt mbus_fmt; }; -static struct ceu_subdev *to_ceu_subdev(struct v4l2_async_subdev *asd) +static struct ceu_subdev *to_ceu_subdev(struct v4l2_async_connection *asd) { return container_of(asd, struct ceu_subdev, asd); } @@ -1374,7 +1374,7 @@ static void ceu_vdev_release(struct video_device *vdev) static int ceu_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *v4l2_sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct v4l2_device *v4l2_dev = notifier->v4l2_dev; struct ceu_device *ceudev = v4l2_to_ceu(v4l2_dev); diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c index baa9cf554910..46912e770058 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c @@ -92,7 +92,7 @@ static int rzg2l_cru_group_notify_complete(struct v4l2_async_notifier *notifier) static void rzg2l_cru_group_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rzg2l_cru_dev *cru = notifier_to_cru(notifier); @@ -110,7 +110,7 @@ static void rzg2l_cru_group_notify_unbind(struct v4l2_async_notifier *notifier, static int rzg2l_cru_group_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rzg2l_cru_dev *cru = notifier_to_cru(notifier); @@ -138,7 +138,7 @@ static int rzg2l_cru_mc_parse_of(struct rzg2l_cru_dev *cru) .bus_type = V4L2_MBUS_CSI2_DPHY, }; struct fwnode_handle *ep, *fwnode; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; int ret; ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(cru->dev), 1, 0, 0); @@ -162,7 +162,7 @@ static int rzg2l_cru_mc_parse_of(struct rzg2l_cru_dev *cru) } asd = v4l2_async_nf_add_fwnode(&cru->notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(asd)) { ret = PTR_ERR(asd); goto out; @@ -190,7 +190,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru) cru->notifier.ops = &rzg2l_cru_async_ops; - if (list_empty(&cru->notifier.asd_list)) + if (list_empty(&cru->notifier.asc_list)) return 0; ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier); diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h index 0b682cbae3eb..811603f18af0 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h @@ -45,7 +45,7 @@ enum rzg2l_cru_dma_state { }; struct rzg2l_cru_csi { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct v4l2_subdev *subdev; u32 channel; }; diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c index 7002b63f109e..da233d76c315 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c @@ -599,7 +599,7 @@ static const struct v4l2_subdev_ops rzg2l_csi2_subdev_ops = { static int rzg2l_csi2_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier); @@ -615,7 +615,7 @@ static int rzg2l_csi2_notify_bound(struct v4l2_async_notifier *notifier, static void rzg2l_csi2_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct rzg2l_csi2 *csi2 = notifier_to_csi2(notifier); @@ -646,7 +646,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2) struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *fwnode; struct fwnode_handle *ep; int ret; @@ -677,7 +677,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2) csi2->notifier.ops = &rzg2l_csi2_notify_ops; asd = v4l2_async_nf_add_fwnode(&csi2->notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(fwnode); if (IS_ERR(asd)) return PTR_ERR(asd); diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h index a1293c45aae1..d30f0ecb1bfd 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h @@ -148,7 +148,7 @@ struct rkisp1_info { * @port: port number (0: MIPI, 1: Parallel) */ struct rkisp1_sensor_async { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; unsigned int index; struct fwnode_handle *source_ep; unsigned int lanes; diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index 7a530bdc6a21..6b9bd97afabe 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -122,12 +122,12 @@ struct rkisp1_isr_data { static int rkisp1_subdev_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct rkisp1_device *rkisp1 = container_of(notifier, struct rkisp1_device, notifier); struct rkisp1_sensor_async *s_asd = - container_of(asd, struct rkisp1_sensor_async, asd); + container_of(asc, struct rkisp1_sensor_async, asd); int source_pad; int ret; @@ -165,10 +165,10 @@ static int rkisp1_subdev_notifier_complete(struct v4l2_async_notifier *notifier) return v4l2_device_register_subdev_nodes(&rkisp1->v4l2_dev); } -static void rkisp1_subdev_notifier_destroy(struct v4l2_async_subdev *asd) +static void rkisp1_subdev_notifier_destroy(struct v4l2_async_connection *asc) { struct rkisp1_sensor_async *rk_asd = - container_of(asd, struct rkisp1_sensor_async, asd); + container_of(asc, struct rkisp1_sensor_async, asd); fwnode_handle_put(rk_asd->source_ep); } diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c index d172581c85f4..cb9a22b5b6b1 100644 --- a/drivers/media/platform/samsung/exynos4-is/media-dev.c +++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c @@ -400,7 +400,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd, int index = fmd->num_sensors; struct fimc_source_info *pd = &fmd->sensor[index].pdata; struct device_node *rem, *np; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; int ret; @@ -465,7 +465,7 @@ static int fimc_md_parse_one_endpoint(struct fimc_md *fmd, asd = v4l2_async_nf_add_fwnode_remote(&fmd->subdev_notifier, of_fwnode_handle(ep), - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(ep); @@ -1371,7 +1371,7 @@ err: static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct fimc_md *fmd = notifier_to_fimc_md(notifier); struct fimc_sensor_info *si = NULL; diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.h b/drivers/media/platform/samsung/exynos4-is/media-dev.h index 079105d88bab..786264cf79dc 100644 --- a/drivers/media/platform/samsung/exynos4-is/media-dev.h +++ b/drivers/media/platform/samsung/exynos4-is/media-dev.h @@ -82,7 +82,7 @@ struct fimc_camclk_info { */ struct fimc_sensor_info { struct fimc_source_info pdata; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct v4l2_subdev *subdev; struct fimc_dev *host; }; diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c index b2e2af593291..b029efa992d6 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmi.c +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c @@ -1837,7 +1837,7 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier) static void dcmi_graph_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); @@ -1849,7 +1849,7 @@ static void dcmi_graph_notify_unbind(struct v4l2_async_notifier *notifier, static int dcmi_graph_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct stm32_dcmi *dcmi = notifier_to_dcmi(notifier); unsigned int ret; @@ -1887,7 +1887,7 @@ static const struct v4l2_async_notifier_operations dcmi_graph_notify_ops = { static int dcmi_graph_init(struct stm32_dcmi *dcmi) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct device_node *ep; int ret; @@ -1901,7 +1901,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) asd = v4l2_async_nf_add_fwnode_remote(&dcmi->notifier, of_fwnode_handle(ep), - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(ep); diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c index ea5e98a26be1..3b6e9071a545 100644 --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c @@ -41,7 +41,7 @@ static const struct media_entity_operations sun4i_csi_video_entity_ops = { static int sun4i_csi_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct sun4i_csi *csi = container_of(notifier, struct sun4i_csi, notifier); @@ -117,7 +117,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_PARALLEL, }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep; int ret; @@ -135,7 +135,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi) csi->bus = vep.bus.parallel; asd = v4l2_async_nf_add_fwnode_remote(&csi->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(asd)) { ret = PTR_ERR(asd); goto out; diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c index 4db950973ce2..ebb725fc11ba 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c @@ -642,7 +642,7 @@ static int sun6i_csi_bridge_link(struct sun6i_csi_device *csi_dev, static int sun6i_csi_bridge_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *remote_subdev, - struct v4l2_async_subdev *async_subdev) + struct v4l2_async_connection *async_subdev) { struct sun6i_csi_device *csi_dev = container_of(notifier, struct sun6i_csi_device, diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h index ee592a14b9c5..44653b38f722 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h @@ -34,7 +34,7 @@ struct sun6i_csi_bridge_source { }; struct sun6i_csi_bridge_async_subdev { - struct v4l2_async_subdev async_subdev; + struct v4l2_async_connection async_subdev; struct sun6i_csi_bridge_source *source; }; diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c index 0b8da0debf16..82da38e0547e 100644 --- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c +++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c @@ -407,7 +407,7 @@ static const struct media_entity_operations sun6i_mipi_csi2_entity_ops = { static int sun6i_mipi_csi2_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *remote_subdev, - struct v4l2_async_subdev *async_subdev) + struct v4l2_async_connection *async_subdev) { struct v4l2_subdev *subdev = notifier->sd; struct sun6i_mipi_csi2_device *csi2_dev = @@ -461,7 +461,7 @@ sun6i_mipi_csi2_bridge_source_setup(struct sun6i_mipi_csi2_device *csi2_dev) { struct v4l2_async_notifier *notifier = &csi2_dev->bridge.notifier; struct v4l2_fwnode_endpoint *endpoint = &csi2_dev->bridge.endpoint; - struct v4l2_async_subdev *subdev_async; + struct v4l2_async_connection *subdev_async; struct fwnode_handle *handle; struct device *dev = csi2_dev->dev; int ret; @@ -479,7 +479,7 @@ sun6i_mipi_csi2_bridge_source_setup(struct sun6i_mipi_csi2_device *csi2_dev) subdev_async = v4l2_async_nf_add_fwnode_remote(notifier, handle, - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(subdev_async)) ret = PTR_ERR(subdev_async); diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c index 47acadd89acb..b96b8faf9fb9 100644 --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c @@ -444,7 +444,7 @@ static const struct media_entity_operations sun8i_a83t_mipi_csi2_entity_ops = { static int sun8i_a83t_mipi_csi2_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *remote_subdev, - struct v4l2_async_subdev *async_subdev) + struct v4l2_async_connection *async_subdev) { struct v4l2_subdev *subdev = notifier->sd; struct sun8i_a83t_mipi_csi2_device *csi2_dev = @@ -498,7 +498,7 @@ sun8i_a83t_mipi_csi2_bridge_source_setup(struct sun8i_a83t_mipi_csi2_device *csi { struct v4l2_async_notifier *notifier = &csi2_dev->bridge.notifier; struct v4l2_fwnode_endpoint *endpoint = &csi2_dev->bridge.endpoint; - struct v4l2_async_subdev *subdev_async; + struct v4l2_async_connection *subdev_async; struct fwnode_handle *handle; struct device *dev = csi2_dev->dev; int ret; @@ -516,7 +516,7 @@ sun8i_a83t_mipi_csi2_bridge_source_setup(struct sun8i_a83t_mipi_csi2_device *csi subdev_async = v4l2_async_nf_add_fwnode_remote(notifier, handle, - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(subdev_async)) ret = PTR_ERR(subdev_async); diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c index 81a63a3865cf..d00be75a3e4f 100644 --- a/drivers/media/platform/ti/am437x/am437x-vpfe.c +++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c @@ -2144,7 +2144,7 @@ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { static int vpfe_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct vpfe_device *vpfe = container_of(notifier->v4l2_dev, struct vpfe_device, v4l2_dev); @@ -2370,8 +2370,7 @@ vpfe_get_pdata(struct vpfe_device *vpfe) pdata->asd[i] = v4l2_async_nf_add_fwnode(&vpfe->notifier, of_fwnode_handle(rem), - struct - v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(rem); if (IS_ERR(pdata->asd[i])) goto cleanup; diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.h b/drivers/media/platform/ti/am437x/am437x-vpfe.h index f8b4e917b91a..50c3c793b370 100644 --- a/drivers/media/platform/ti/am437x/am437x-vpfe.h +++ b/drivers/media/platform/ti/am437x/am437x-vpfe.h @@ -84,7 +84,7 @@ struct vpfe_config { /* information about each subdev */ struct vpfe_subdev_info sub_devs[VPFE_MAX_SUBDEV]; /* Flat array, arranged in groups */ - struct v4l2_async_subdev *asd[VPFE_MAX_SUBDEV]; + struct v4l2_async_connection *asd[VPFE_MAX_SUBDEV]; }; struct vpfe_cap_buffer { diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c index 5d49c4435a08..7cd50629d9d3 100644 --- a/drivers/media/platform/ti/cal/cal.c +++ b/drivers/media/platform/ti/cal/cal.c @@ -774,19 +774,19 @@ static irqreturn_t cal_irq(int irq_cal, void *data) */ struct cal_v4l2_async_subdev { - struct v4l2_async_subdev asd; /* Must be first */ + struct v4l2_async_connection asd; /* Must be first */ struct cal_camerarx *phy; }; static inline struct cal_v4l2_async_subdev * -to_cal_asd(struct v4l2_async_subdev *asd) +to_cal_asd(struct v4l2_async_connection *asd) { return container_of(asd, struct cal_v4l2_async_subdev, asd); } static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct cal_camerarx *phy = to_cal_asd(asd)->phy; int pad; diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c index 44d269d6038c..a63c9e51dac4 100644 --- a/drivers/media/platform/ti/davinci/vpif_capture.c +++ b/drivers/media/platform/ti/davinci/vpif_capture.c @@ -1363,12 +1363,12 @@ static inline void free_vpif_objs(void) static int vpif_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { int i; for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) { - struct v4l2_async_subdev *_asd = vpif_obj.config->asd[i]; + struct v4l2_async_connection *_asd = vpif_obj.config->asd[i]; const struct fwnode_handle *fwnode = _asd->match.fwnode; if (fwnode == subdev->fwnode) { @@ -1570,8 +1570,7 @@ vpif_capture_get_pdata(struct platform_device *pdev) pdata->asd[i] = v4l2_async_nf_add_fwnode(&vpif_obj.notifier, of_fwnode_handle(rem), - struct - v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(pdata->asd[i])) goto err_cleanup; diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c index b01d70dbd0c4..84ac5b74f5cf 100644 --- a/drivers/media/platform/ti/omap3isp/isp.c +++ b/drivers/media/platform/ti/omap3isp/isp.c @@ -2024,12 +2024,12 @@ enum isp_of_phy { static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct isp_device *isp = container_of(async, struct isp_device, notifier); struct isp_bus_cfg *bus_cfg = - &container_of(asd, struct isp_async_subdev, asd)->bus; + &container_of(asc, struct isp_async_subdev, asd)->bus; int ret; mutex_lock(&isp->media_dev.graph_mutex); diff --git a/drivers/media/platform/ti/omap3isp/isp.h b/drivers/media/platform/ti/omap3isp/isp.h index a9d760fbf349..32ea70c8d2f9 100644 --- a/drivers/media/platform/ti/omap3isp/isp.h +++ b/drivers/media/platform/ti/omap3isp/isp.h @@ -220,7 +220,7 @@ struct isp_device { }; struct isp_async_subdev { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; struct isp_bus_cfg bus; }; diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 6d273abfe16c..6cc0dde42e80 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -314,7 +314,7 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = { static int video_mux_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct video_mux *vmux = notifier_to_video_mux(notifier); @@ -334,7 +334,7 @@ static int video_mux_async_register(struct video_mux *vmux, v4l2_async_nf_init(&vmux->notifier); for (i = 0; i < num_input_pads; i++) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep, *remote_ep; ep = fwnode_graph_get_endpoint_by_id( @@ -352,7 +352,7 @@ static int video_mux_async_register(struct video_mux *vmux, fwnode_handle_put(remote_ep); asd = v4l2_async_nf_add_fwnode_remote(&vmux->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep); diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index 52c5a7decf28..96fbbc55eb12 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -34,13 +34,13 @@ * @subdev: V4L2 subdev */ struct xvip_graph_entity { - struct v4l2_async_subdev asd; /* must be first */ + struct v4l2_async_connection asd; /* must be first */ struct media_entity *entity; struct v4l2_subdev *subdev; }; static inline struct xvip_graph_entity * -to_xvip_entity(struct v4l2_async_subdev *asd) +to_xvip_entity(struct v4l2_async_connection *asd) { return container_of(asd, struct xvip_graph_entity, asd); } @@ -54,9 +54,9 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev, const struct fwnode_handle *fwnode) { struct xvip_graph_entity *entity; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; - list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) { + list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) { entity = to_xvip_entity(asd); if (entity->asd.match.fwnode == fwnode) return entity; @@ -285,13 +285,13 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) struct xvip_composite_device *xdev = container_of(notifier, struct xvip_composite_device, notifier); struct xvip_graph_entity *entity; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; int ret; dev_dbg(xdev->dev, "notify complete, all subdevs registered\n"); /* Create links for every entity. */ - list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) { + list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) { entity = to_xvip_entity(asd); ret = xvip_graph_build_one(xdev, entity); if (ret < 0) @@ -312,9 +312,9 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { - struct xvip_graph_entity *entity = to_xvip_entity(asd); + struct xvip_graph_entity *entity = to_xvip_entity(asc); entity->entity = &subdev->entity; entity->subdev = subdev; @@ -380,7 +380,7 @@ err_notifier_cleanup: static int xvip_graph_parse(struct xvip_composite_device *xdev) { struct xvip_graph_entity *entity; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; int ret; /* @@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev) if (ret < 0) return 0; - list_for_each_entry(asd, &xdev->notifier.asd_list, asd_entry) { + list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) { entity = to_xvip_entity(asd); ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode); if (ret < 0) { @@ -501,7 +501,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev) goto done; } - if (list_empty(&xdev->notifier.asd_list)) { + if (list_empty(&xdev->notifier.asc_list)) { dev_err(xdev->dev, "no subdev found in graph\n"); ret = -ENOENT; goto done; diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 11d336e783bd..9964d7f38480 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -28,22 +28,22 @@ static int v4l2_async_nf_call_bound(struct v4l2_async_notifier *n, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { if (!n->ops || !n->ops->bound) return 0; - return n->ops->bound(n, subdev, asd); + return n->ops->bound(n, subdev, asc); } static void v4l2_async_nf_call_unbind(struct v4l2_async_notifier *n, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { if (!n->ops || !n->ops->unbind) return; - n->ops->unbind(n, subdev, asd); + n->ops->unbind(n, subdev, asc); } static int v4l2_async_nf_call_complete(struct v4l2_async_notifier *n) @@ -55,12 +55,12 @@ static int v4l2_async_nf_call_complete(struct v4l2_async_notifier *n) } static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { if (!n->ops || !n->ops->destroy) return; - n->ops->destroy(asd); + n->ops->destroy(asc); } static bool match_i2c(struct v4l2_async_notifier *notifier, @@ -151,18 +151,18 @@ static LIST_HEAD(subdev_list); static LIST_HEAD(notifier_list); static DEFINE_MUTEX(list_lock); -static struct v4l2_async_subdev * +static struct v4l2_async_connection * v4l2_async_find_match(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd) { bool (*match)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, struct v4l2_async_match_desc *match); - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; - list_for_each_entry(asd, ¬ifier->waiting_list, waiting_entry) { + list_for_each_entry(asc, ¬ifier->waiting_list, waiting_entry) { /* bus_type has been verified valid before */ - switch (asd->match.type) { + switch (asc->match.type) { case V4L2_ASYNC_MATCH_TYPE_I2C: match = match_i2c; break; @@ -176,8 +176,8 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier, } /* match cannot be NULL here */ - if (match(notifier, sd, &asd->match)) - return asd; + if (match(notifier, sd, &asc->match)) + return asc; } return NULL; @@ -310,7 +310,7 @@ static int v4l2_async_create_ancillary_links(struct v4l2_async_notifier *n, static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, struct v4l2_device *v4l2_dev, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asc) { struct v4l2_async_notifier *subdev_notifier; int ret; @@ -319,7 +319,7 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, if (ret < 0) return ret; - ret = v4l2_async_nf_call_bound(notifier, sd, asd); + ret = v4l2_async_nf_call_bound(notifier, sd, asc); if (ret < 0) { v4l2_device_unregister_subdev(sd); return ret; @@ -333,13 +333,13 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, */ ret = v4l2_async_create_ancillary_links(notifier, sd); if (ret) { - v4l2_async_nf_call_unbind(notifier, sd, asd); + v4l2_async_nf_call_unbind(notifier, sd, asc); v4l2_device_unregister_subdev(sd); return ret; } - list_del(&asd->waiting_entry); - sd->asd = asd; + list_del(&asc->waiting_entry); + sd->asd = asc; sd->notifier = notifier; /* Move from the global subdevice list to notifier's done */ @@ -380,17 +380,17 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier) again: list_for_each_entry(sd, &subdev_list, async_list) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; int ret; - asd = v4l2_async_find_match(notifier, sd); - if (!asd) + asc = v4l2_async_find_match(notifier, sd); + if (!asc) continue; dev_dbg(notifier_dev(notifier), "v4l2-async: match found, subdev %s\n", sd->name); - ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd); + ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asc); if (ret < 0) return ret; @@ -448,11 +448,11 @@ static bool v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier, struct v4l2_async_match_desc *match) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; struct v4l2_subdev *sd; - list_for_each_entry(asd, ¬ifier->waiting_list, waiting_entry) - if (v4l2_async_match_equal(&asd->match, match)) + list_for_each_entry(asc, ¬ifier->waiting_list, waiting_entry) + if (v4l2_async_match_equal(&asc->match, match)) return true; list_for_each_entry(sd, ¬ifier->done_list, async_list) { @@ -477,19 +477,19 @@ v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier, struct v4l2_async_match_desc *match, bool skip_self) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; lockdep_assert_held(&list_lock); /* Check that an asd is not being added more than once. */ - list_for_each_entry(asd, ¬ifier->asd_list, asd_entry) { - if (skip_self && &asd->match == match) + list_for_each_entry(asc, ¬ifier->asc_list, asc_entry) { + if (skip_self && &asc->match == match) continue; - if (v4l2_async_match_equal(&asd->match, match)) + if (v4l2_async_match_equal(&asc->match, match)) return true; } - /* Check that an asd does not exist in other notifiers. */ + /* Check that an asc does not exist in other notifiers. */ list_for_each_entry(notifier, ¬ifier_list, notifier_entry) if (v4l2_async_nf_has_async_match_entry(notifier, match)) return true; @@ -523,13 +523,13 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier, void v4l2_async_nf_init(struct v4l2_async_notifier *notifier) { - INIT_LIST_HEAD(¬ifier->asd_list); + INIT_LIST_HEAD(¬ifier->asc_list); } EXPORT_SYMBOL(v4l2_async_nf_init); static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; int ret; INIT_LIST_HEAD(¬ifier->waiting_list); @@ -537,12 +537,12 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) mutex_lock(&list_lock); - list_for_each_entry(asd, ¬ifier->asd_list, asd_entry) { - ret = v4l2_async_nf_match_valid(notifier, &asd->match, true); + list_for_each_entry(asc, ¬ifier->asc_list, asc_entry) { + ret = v4l2_async_nf_match_valid(notifier, &asc->match, true); if (ret) goto err_unlock; - list_add_tail(&asd->waiting_entry, ¬ifier->waiting_list); + list_add_tail(&asc->waiting_entry, ¬ifier->waiting_list); } ret = v4l2_async_nf_try_all_subdevs(notifier); @@ -634,23 +634,23 @@ EXPORT_SYMBOL(v4l2_async_nf_unregister); static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier) { - struct v4l2_async_subdev *asd, *tmp; + struct v4l2_async_connection *asc, *tmp; - if (!notifier || !notifier->asd_list.next) + if (!notifier || !notifier->asc_list.next) return; - list_for_each_entry_safe(asd, tmp, ¬ifier->asd_list, asd_entry) { - switch (asd->match.type) { + list_for_each_entry_safe(asc, tmp, ¬ifier->asc_list, asc_entry) { + switch (asc->match.type) { case V4L2_ASYNC_MATCH_TYPE_FWNODE: - fwnode_handle_put(asd->match.fwnode); + fwnode_handle_put(asc->match.fwnode); break; default: break; } - list_del(&asd->asd_entry); - v4l2_async_nf_call_destroy(notifier, asd); - kfree(asd); + list_del(&asc->asc_entry); + v4l2_async_nf_call_destroy(notifier, asc); + kfree(asc); } } @@ -664,95 +664,94 @@ void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier) } EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup); - -static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier, - struct v4l2_async_subdev *asd) +static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier, + struct v4l2_async_connection *asc) { int ret; mutex_lock(&list_lock); - ret = v4l2_async_nf_match_valid(notifier, &asd->match, false); + ret = v4l2_async_nf_match_valid(notifier, &asc->match, false); if (ret) goto unlock; - list_add_tail(&asd->asd_entry, ¬ifier->asd_list); + list_add_tail(&asc->asc_entry, ¬ifier->asc_list); unlock: mutex_unlock(&list_lock); return ret; } -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode, - unsigned int asd_struct_size) + unsigned int asc_struct_size) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; int ret; - asd = kzalloc(asd_struct_size, GFP_KERNEL); - if (!asd) + asc = kzalloc(asc_struct_size, GFP_KERNEL); + if (!asc) return ERR_PTR(-ENOMEM); - asd->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE; - asd->match.fwnode = fwnode_handle_get(fwnode); + asc->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE; + asc->match.fwnode = fwnode_handle_get(fwnode); - ret = __v4l2_async_nf_add_subdev(notifier, asd); + ret = __v4l2_async_nf_add_connection(notifier, asc); if (ret) { fwnode_handle_put(fwnode); - kfree(asd); + kfree(asc); return ERR_PTR(ret); } - return asd; + return asc; } EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode); -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif, struct fwnode_handle *endpoint, - unsigned int asd_struct_size) + unsigned int asc_struct_size) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; struct fwnode_handle *remote; remote = fwnode_graph_get_remote_endpoint(endpoint); if (!remote) return ERR_PTR(-ENOTCONN); - asd = __v4l2_async_nf_add_fwnode(notif, remote, asd_struct_size); + asc = __v4l2_async_nf_add_fwnode(notif, remote, asc_struct_size); /* * Calling __v4l2_async_nf_add_fwnode grabs a refcount, * so drop the one we got in fwnode_graph_get_remote_port_parent. */ fwnode_handle_put(remote); - return asd; + return asc; } EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode_remote); -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id, - unsigned short address, unsigned int asd_struct_size) + unsigned short address, unsigned int asc_struct_size) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; int ret; - asd = kzalloc(asd_struct_size, GFP_KERNEL); - if (!asd) + asc = kzalloc(asc_struct_size, GFP_KERNEL); + if (!asc) return ERR_PTR(-ENOMEM); - asd->match.type = V4L2_ASYNC_MATCH_TYPE_I2C; - asd->match.i2c.adapter_id = adapter_id; - asd->match.i2c.address = address; + asc->match.type = V4L2_ASYNC_MATCH_TYPE_I2C; + asc->match.i2c.adapter_id = adapter_id; + asc->match.i2c.address = address; - ret = __v4l2_async_nf_add_subdev(notifier, asd); + ret = __v4l2_async_nf_add_connection(notifier, asc); if (ret) { - kfree(asd); + kfree(asc); return ERR_PTR(ret); } - return asd; + return asc; } EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c); @@ -784,16 +783,16 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) list_for_each_entry(notifier, ¬ifier_list, notifier_entry) { struct v4l2_device *v4l2_dev = v4l2_async_nf_find_v4l2_dev(notifier); - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; if (!v4l2_dev) continue; - asd = v4l2_async_find_match(notifier, sd); - if (!asd) + asc = v4l2_async_find_match(notifier, sd); + if (!asc) continue; - ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd); + ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asc); if (ret) goto err_unbind; @@ -898,14 +897,14 @@ v4l2_async_nf_name(struct v4l2_async_notifier *notifier) static int pending_subdevs_show(struct seq_file *s, void *data) { struct v4l2_async_notifier *notif; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asc; mutex_lock(&list_lock); list_for_each_entry(notif, ¬ifier_list, notifier_entry) { seq_printf(s, "%s:\n", v4l2_async_nf_name(notif)); - list_for_each_entry(asd, ¬if->waiting_list, waiting_entry) - print_waiting_match(s, &asd->match); + list_for_each_entry(asc, ¬if->waiting_list, waiting_entry) + print_waiting_match(s, &asc->match); } mutex_unlock(&list_lock); diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index d818f88d2b49..f30f98b9f2d0 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -831,10 +831,10 @@ static int v4l2_fwnode_reference_parse(struct device *dev, !(ret = fwnode_property_get_reference_args(dev_fwnode(dev), prop, NULL, 0, index, &args)); index++) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; asd = v4l2_async_nf_add_fwnode(notifier, args.fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(args.fwnode); if (IS_ERR(asd)) { /* not an error if asd already exists */ @@ -1136,10 +1136,10 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev, props, nprops))); index++) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; asd = v4l2_async_nf_add_fwnode(notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(fwnode); if (IS_ERR(asd)) { ret = PTR_ERR(asd); diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index 0d12ba78d9c1..dbb0160e71b7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -767,7 +767,7 @@ err_free_bridge: /******* V4L2 sub-device asynchronous registration callbacks***********/ struct sensor_async_subdev { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; int port; }; @@ -777,7 +777,7 @@ struct sensor_async_subdev { /* .bound() notifier callback when a match is found */ static int atomisp_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct atomisp_device *isp = notifier_to_atomisp(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); @@ -799,7 +799,7 @@ static int atomisp_notifier_bound(struct v4l2_async_notifier *notifier, /* The .unbind callback */ static void atomisp_notifier_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct atomisp_device *isp = notifier_to_atomisp(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); diff --git a/drivers/staging/media/deprecated/atmel/atmel-isc-base.c b/drivers/staging/media/deprecated/atmel/atmel-isc-base.c index 61c5afa58142..f5d963904201 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-isc-base.c +++ b/drivers/staging/media/deprecated/atmel/atmel-isc-base.c @@ -1727,7 +1727,7 @@ static int isc_ctrl_init(struct isc_device *isc) static int isc_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct isc_device *isc = container_of(notifier->v4l2_dev, struct isc_device, v4l2_dev); @@ -1746,7 +1746,7 @@ static int isc_async_bound(struct v4l2_async_notifier *notifier, static void isc_async_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct isc_device *isc = container_of(notifier->v4l2_dev, struct isc_device, v4l2_dev); diff --git a/drivers/staging/media/deprecated/atmel/atmel-isc.h b/drivers/staging/media/deprecated/atmel/atmel-isc.h index dfc030b5a08f..31767ea74be6 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-isc.h +++ b/drivers/staging/media/deprecated/atmel/atmel-isc.h @@ -44,7 +44,7 @@ struct isc_buffer { struct isc_subdev_entity { struct v4l2_subdev *sd; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct device_node *epn; struct v4l2_async_notifier notifier; diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c index cc86ebcc76af..58c8c7813e0f 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c +++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c @@ -503,7 +503,7 @@ static int atmel_isc_probe(struct platform_device *pdev) } list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); @@ -511,7 +511,7 @@ static int atmel_isc_probe(struct platform_device *pdev) asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(subdev_entity->epn); subdev_entity->epn = NULL; diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c index 68ef3374d25e..f10ddee0949e 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c +++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c @@ -493,7 +493,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) } list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); @@ -501,7 +501,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, - struct v4l2_async_subdev); + struct v4l2_async_connection); of_node_put(subdev_entity->epn); subdev_entity->epn = NULL; diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 097171bb930d..09b8b396022e 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -1892,7 +1892,7 @@ static const struct v4l2_subdev_internal_ops csi_internal_ops = { static int imx_csi_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct csi_priv *priv = notifier_to_dev(notifier); struct media_pad *sink = &priv->sd.entity.pads[CSI_SINK_PAD]; @@ -1913,7 +1913,7 @@ static const struct v4l2_async_notifier_operations csi_notify_ops = { static int imx_csi_async_register(struct csi_priv *priv) { - struct v4l2_async_subdev *asd = NULL; + struct v4l2_async_connection *asd = NULL; struct fwnode_handle *ep; unsigned int port; int ret; @@ -1930,7 +1930,7 @@ static int imx_csi_async_register(struct csi_priv *priv) FWNODE_GRAPH_ENDPOINT_NEXT); if (ep) { asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep); diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c index 991820a8500f..c1216b4557b6 100644 --- a/drivers/staging/media/imx/imx-media-dev-common.c +++ b/drivers/staging/media/imx/imx-media-dev-common.c @@ -384,7 +384,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd, int ret; /* no subdevs? just bail */ - if (list_empty(&imxmd->notifier.asd_list)) { + if (list_empty(&imxmd->notifier.asc_list)) { v4l2_err(&imxmd->v4l2_dev, "no subdevs\n"); return -ENODEV; } diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index c80113905069..be54dca11465 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -20,7 +20,7 @@ static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n) /* async subdev bound notifier */ static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct imx_media_dev *imxmd = notifier2dev(notifier); int ret; diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c index 92a99010c150..118bff988bc7 100644 --- a/drivers/staging/media/imx/imx-media-of.c +++ b/drivers/staging/media/imx/imx-media-of.c @@ -19,7 +19,7 @@ static int imx_media_of_add_csi(struct imx_media_dev *imxmd, struct device_node *csi_np) { - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; int ret = 0; if (!of_device_is_available(csi_np)) { @@ -31,7 +31,7 @@ static int imx_media_of_add_csi(struct imx_media_dev *imxmd, /* add CSI fwnode to async notifier */ asd = v4l2_async_nf_add_fwnode(&imxmd->notifier, of_fwnode_handle(csi_np), - struct v4l2_async_subdev); + struct v4l2_async_connection); if (IS_ERR(asd)) { ret = PTR_ERR(asd); if (ret == -EEXIST) diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index ab565b4e29ec..e3273c5c9b60 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -636,7 +636,7 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = { static int csi2_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct csi2_dev *csi2 = notifier_to_dev(notifier); struct media_pad *sink = &csi2->sd.entity.pads[CSI2_SINK_PAD]; @@ -659,7 +659,7 @@ static int csi2_notify_bound(struct v4l2_async_notifier *notifier, static void csi2_notify_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct csi2_dev *csi2 = notifier_to_dev(notifier); @@ -676,7 +676,7 @@ static int csi2_async_register(struct csi2_dev *csi2) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY, }; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct fwnode_handle *ep; int ret; @@ -697,7 +697,7 @@ static int csi2_async_register(struct csi2_dev *csi2) dev_dbg(csi2->dev, "flags: 0x%08x\n", vep.bus.mipi_csi2.flags); asd = v4l2_async_nf_add_fwnode_remote(&csi2->notifier, ep, - struct v4l2_async_subdev); + struct v4l2_async_connection); fwnode_handle_put(ep); if (IS_ERR(asd)) diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c index 1ca4673df2b3..dd7dfecb9ef3 100644 --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c @@ -395,7 +395,7 @@ static int sun6i_isp_proc_link(struct sun6i_isp_device *isp_dev, static int sun6i_isp_proc_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *remote_subdev, - struct v4l2_async_subdev *async_subdev) + struct v4l2_async_connection *async_subdev) { struct sun6i_isp_device *isp_dev = container_of(notifier, struct sun6i_isp_device, proc.notifier); diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h index c5c274e21ad5..db6738a39147 100644 --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h @@ -34,7 +34,7 @@ struct sun6i_isp_proc_source { }; struct sun6i_isp_proc_async_subdev { - struct v4l2_async_subdev async_subdev; + struct v4l2_async_connection async_subdev; struct sun6i_isp_proc_source *source; }; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 9c5b6cfdc8e9..07e3eb8c7056 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -40,7 +40,7 @@ * @subdev: V4L2 subdev */ struct tegra_vi_graph_entity { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; struct media_entity *entity; struct v4l2_subdev *subdev; }; @@ -58,7 +58,7 @@ to_tegra_channel_buffer(struct vb2_v4l2_buffer *vb) } static inline struct tegra_vi_graph_entity * -to_tegra_vi_graph_entity(struct v4l2_async_subdev *asd) +to_tegra_vi_graph_entity(struct v4l2_async_connection *asd) { return container_of(asd, struct tegra_vi_graph_entity, asd); } @@ -1462,9 +1462,9 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan, const struct fwnode_handle *fwnode) { struct tegra_vi_graph_entity *entity; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; - list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) { + list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) { entity = to_tegra_vi_graph_entity(asd); if (entity->asd.match.fwnode == fwnode) return entity; @@ -1578,7 +1578,7 @@ create_link: static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier) { struct tegra_vi_graph_entity *entity; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct v4l2_subdev *subdev; struct tegra_vi_channel *chan; struct tegra_vi *vi; @@ -1608,7 +1608,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier) } /* create links between the entities */ - list_for_each_entry(asd, &chan->notifier.asd_list, asd_entry) { + list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) { entity = to_tegra_vi_graph_entity(asd); ret = tegra_vi_graph_build(chan, entity); if (ret < 0) @@ -1651,7 +1651,7 @@ unregister_video: static int tegra_vi_graph_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct tegra_vi_graph_entity *entity; struct tegra_vi *vi; @@ -1775,7 +1775,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) ret = tegra_vi_graph_parse_one(chan, remote); fwnode_handle_put(remote); - if (ret < 0 || list_empty(&chan->notifier.asd_list)) + if (ret < 0 || list_empty(&chan->notifier.asc_list)) continue; chan->notifier.ops = &tegra_vi_async_ops; diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h index d03e5c54347a..6cce1f09c721 100644 --- a/include/media/davinci/vpif_types.h +++ b/include/media/davinci/vpif_types.h @@ -72,7 +72,7 @@ struct vpif_capture_config { int i2c_adapter_id; const char *card_name; - struct v4l2_async_subdev *asd[VPIF_CAPTURE_MAX_CHANNELS]; + struct v4l2_async_connection *asd[VPIF_CAPTURE_MAX_CHANNELS]; int asd_sizes[VPIF_CAPTURE_MAX_CHANNELS]; }; #endif /* _VPIF_TYPES_H */ diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 03ac6520f3d2..a27d9dc8afcb 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -25,7 +25,7 @@ struct v4l2_async_notifier; * @V4L2_ASYNC_MATCH_TYPE_I2C: Match will check for I2C adapter ID and address * @V4L2_ASYNC_MATCH_TYPE_FWNODE: Match will use firmware node * - * This enum is used by the asynchronous sub-device logic to define the + * This enum is used by the asynchronous connection logic to define the * algorithm that will be used to match an asynchronous device. */ enum v4l2_async_match_type { @@ -34,7 +34,7 @@ enum v4l2_async_match_type { }; /** - * struct v4l2_async_match_desc - async sub-device match information + * struct v4l2_async_match_desc - async connection match information * * @type: type of match that will be used * @fwnode: pointer to &struct fwnode_handle to be matched. @@ -62,21 +62,21 @@ struct v4l2_async_match_desc { }; /** - * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge + * struct v4l2_async_connection - connection descriptor, as known to a bridge * * @match: struct of match type and per-bus type matching data sets - * @asd_entry: used to add struct v4l2_async_subdev objects to the - * master notifier @asd_list - * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be - * probed, to a notifier->waiting_list list + * @asc_entry: used to add struct v4l2_async_connection objects to the + * master notifier @asc_list + * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to + * be probed, to a notifier->waiting_list list * * When this struct is used as a member in a driver specific struct, * the driver specific struct shall contain the &struct - * v4l2_async_subdev as its first member. + * v4l2_async_connection as its first member. */ -struct v4l2_async_subdev { +struct v4l2_async_connection { struct v4l2_async_match_desc match; - struct list_head asd_entry; + struct list_head asc_entry; struct list_head waiting_entry; }; @@ -86,17 +86,17 @@ struct v4l2_async_subdev { * @complete: All subdevices have been probed successfully. The complete * callback is only executed for the root notifier. * @unbind: a subdevice is leaving - * @destroy: the asd is about to be freed + * @destroy: the asc is about to be freed */ struct v4l2_async_notifier_operations { int (*bound)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd); + struct v4l2_async_connection *asc); int (*complete)(struct v4l2_async_notifier *notifier); void (*unbind)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd); - void (*destroy)(struct v4l2_async_subdev *asd); + struct v4l2_async_connection *asc); + void (*destroy)(struct v4l2_async_connection *asc); }; /** @@ -106,8 +106,9 @@ struct v4l2_async_notifier_operations { * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise * @sd: sub-device that registered the notifier, NULL otherwise * @parent: parent notifier - * @asd_list: master list of struct v4l2_async_subdev - * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers + * @asc_list: master list of struct v4l2_async_connection + * @waiting_list: list of struct v4l2_async_connection, waiting for their + * drivers * @done_list: list of struct v4l2_subdev, already probed * @notifier_entry: member in a global list of notifiers */ @@ -116,7 +117,7 @@ struct v4l2_async_notifier { struct v4l2_device *v4l2_dev; struct v4l2_subdev *sd; struct v4l2_async_notifier *parent; - struct list_head asd_list; + struct list_head asc_list; struct list_head waiting_list; struct list_head done_list; struct list_head notifier_entry; @@ -134,53 +135,53 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir); * * @notifier: pointer to &struct v4l2_async_notifier * - * This function initializes the notifier @asd_list. It must be called + * This function initializes the notifier @asc_list. It must be called * before adding a subdevice to a notifier, using one of: * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or * v4l2_async_nf_add_i2c(). */ void v4l2_async_nf_init(struct v4l2_async_notifier *notifier); -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode, - unsigned int asd_struct_size); + unsigned int asc_struct_size); /** * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async - * subdev to the notifier's master asd_list. + * subdev to the notifier's master asc_list. * * @notifier: pointer to &struct v4l2_async_notifier * @fwnode: fwnode handle of the sub-device to be matched, pointer to * &struct fwnode_handle - * @type: Type of the driver's async sub-device struct. The &struct - * v4l2_async_subdev shall be the first member of the driver's async - * sub-device struct, i.e. both begin at the same memory address. + * @type: Type of the driver's async sub-device or connection struct. The + * &struct v4l2_async_connection shall be the first member of the + * driver's async struct, i.e. both begin at the same memory address. * - * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the - * notifiers @asd_list. The function also gets a reference of the fwnode which + * Allocate a fwnode-matched asc of size asc_struct_size, and add it to the + * notifiers @asc_list. The function also gets a reference of the fwnode which * is released later at notifier cleanup time. */ #define v4l2_async_nf_add_fwnode(notifier, fwnode, type) \ ((type *)__v4l2_async_nf_add_fwnode(notifier, fwnode, sizeof(type))) -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif, struct fwnode_handle *endpoint, - unsigned int asd_struct_size); + unsigned int asc_struct_size); /** * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode * remote async subdev to the - * notifier's master asd_list. + * notifier's master asc_list. * * @notifier: pointer to &struct v4l2_async_notifier - * @ep: local endpoint pointing to the remote sub-device to be matched, + * @ep: local endpoint pointing to the remote connection to be matched, * pointer to &struct fwnode_handle - * @type: Type of the driver's async sub-device struct. The &struct - * v4l2_async_subdev shall be the first member of the driver's async - * sub-device struct, i.e. both begin at the same memory address. + * @type: Type of the driver's async connection struct. The &struct + * v4l2_async_connection shall be the first member of the driver's async + * connection struct, i.e. both begin at the same memory address. * * Gets the remote endpoint of a given local endpoint, set it up for fwnode - * matching and adds the async sub-device to the notifier's @asd_list. The + * matching and adds the async connection to the notifier's @asc_list. The * function also gets a reference of the fwnode which is released later at * notifier cleanup time. * @@ -190,23 +191,23 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif, #define v4l2_async_nf_add_fwnode_remote(notifier, ep, type) \ ((type *)__v4l2_async_nf_add_fwnode_remote(notifier, ep, sizeof(type))) -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id, unsigned short address, - unsigned int asd_struct_size); + unsigned int asc_struct_size); /** * v4l2_async_nf_add_i2c - Allocate and add an i2c async - * subdev to the notifier's master asd_list. + * subdev to the notifier's master asc_list. * * @notifier: pointer to &struct v4l2_async_notifier * @adapter: I2C adapter ID to be matched - * @address: I2C address of sub-device to be matched - * @type: Type of the driver's async sub-device struct. The &struct - * v4l2_async_subdev shall be the first member of the driver's async - * sub-device struct, i.e. both begin at the same memory address. + * @address: I2C address of connection to be matched + * @type: Type of the driver's async connection struct. The &struct + * v4l2_async_connection shall be the first member of the driver's async + * connection struct, i.e. both begin at the same memory address. * * Same as v4l2_async_nf_add_fwnode() but for I2C matched - * sub-devices. + * connections. */ #define v4l2_async_nf_add_i2c(notifier, adapter, address, type) \ ((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \ @@ -244,7 +245,7 @@ void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier); * @notifier: the notifier the resources of which are to be cleaned up * * Release memory resources related to a notifier, including the async - * sub-devices allocated for the purposes of the notifier but not the notifier + * connections allocated for the purposes of the notifier but not the notifier * itself. The user is responsible for calling this function to clean up the * notifier after calling v4l2_async_nf_add_fwnode_remote(), * v4l2_async_nf_add_fwnode() or v4l2_async_nf_add_i2c(). diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b58c7a325e99..212d7f1ac525 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1022,7 +1022,7 @@ struct v4l2_subdev_platform_data { * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). * @async_list: Links this subdev to a global subdev_list or * @notifier->done_list list. - * @asd: Pointer to respective &struct v4l2_async_subdev. + * @asd: Pointer to respective &struct v4l2_async_connection. * @notifier: Pointer to the managing notifier. * @subdev_notifier: A sub-device notifier implicitly registered for the sub- * device using v4l2_async_register_subdev_sensor(). @@ -1065,7 +1065,7 @@ struct v4l2_subdev { struct device *dev; struct fwnode_handle *fwnode; struct list_head async_list; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct v4l2_async_notifier *notifier; struct v4l2_async_notifier *subdev_notifier; struct v4l2_subdev_platform_data *pdata; -- cgit v1.2.3 From 9bf19fbf0c8bc4392210c1ea104a8db732624f3d Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 18 Apr 2023 14:00:54 +0200 Subject: media: v4l: async: Rework internal lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch re-arranges internal V4L2 async lists for preparation of supporting multiple connections per sub-device as well as cleaning up used lists. The list of unbound V4L2 sub-devices shall be maintained for the purpose of listing those sub-devices only, not for their bindin status. Also, the V4L2 async connections now have, instead of two list entries, a single list entry in the notifier's list, be that either waiting or done lists, while the notifier's asc_list is removed. The one-to-one relation between a sub-device and a connection is still maintained in this patch. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 2 +- .../media/platform/renesas/rcar-vin/rcar-core.c | 2 +- .../media/platform/renesas/rzg2l-cru/rzg2l-core.c | 2 +- drivers/media/platform/xilinx/xilinx-vipp.c | 8 +- drivers/media/v4l2-core/v4l2-async.c | 102 +++++++++++---------- drivers/staging/media/imx/imx-media-dev-common.c | 2 +- drivers/staging/media/tegra-video/vi.c | 6 +- include/media/v4l2-async.h | 9 +- 8 files changed, 68 insertions(+), 65 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 8319d27fa0e6..0e89a3b9293a 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1421,7 +1421,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) struct cio2_queue *q; int ret; - list_for_each_entry(asd, &cio2->notifier.asc_list, asc_entry) { + list_for_each_entry(asd, &cio2->notifier.done_list, asc_entry) { s_asd = to_sensor_asd(asd); q = &cio2->queue[s_asd->csi2.port]; diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index 5bba9e068fe3..b44f12bd01c4 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -395,7 +395,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port, } } - if (list_empty(&vin->group->notifier.asc_list)) + if (list_empty(&vin->group->notifier.waiting_list)) return 0; vin->group->notifier.ops = &rvin_group_notify_ops; diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c index 46912e770058..a5aa6a73f84d 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c @@ -190,7 +190,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru) cru->notifier.ops = &rzg2l_cru_async_ops; - if (list_empty(&cru->notifier.asc_list)) + if (list_empty(&cru->notifier.waiting_list)) return 0; ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier); diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index 96fbbc55eb12..a535a7584da0 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -56,7 +56,7 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev, struct xvip_graph_entity *entity; struct v4l2_async_connection *asd; - list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) { + list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) { entity = to_xvip_entity(asd); if (entity->asd.match.fwnode == fwnode) return entity; @@ -291,7 +291,7 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) dev_dbg(xdev->dev, "notify complete, all subdevs registered\n"); /* Create links for every entity. */ - list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) { + list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) { entity = to_xvip_entity(asd); ret = xvip_graph_build_one(xdev, entity); if (ret < 0) @@ -393,7 +393,7 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev) if (ret < 0) return 0; - list_for_each_entry(asd, &xdev->notifier.asc_list, asc_entry) { + list_for_each_entry(asd, &xdev->notifier.waiting_list, asc_entry) { entity = to_xvip_entity(asd); ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode); if (ret < 0) { @@ -501,7 +501,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev) goto done; } - if (list_empty(&xdev->notifier.asc_list)) { + if (list_empty(&xdev->notifier.waiting_list)) { dev_err(xdev->dev, "no subdev found in graph\n"); ret = -ENOENT; goto done; diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 0cd4e18e628c..95fecf39ba65 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -160,7 +160,7 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier, struct v4l2_async_match_desc *match); struct v4l2_async_connection *asc; - list_for_each_entry(asc, ¬ifier->waiting_list, waiting_entry) { + list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry) { /* bus_type has been verified valid before */ switch (asc->match.type) { case V4L2_ASYNC_MATCH_TYPE_I2C: @@ -232,14 +232,14 @@ v4l2_async_nf_find_v4l2_dev(struct v4l2_async_notifier *notifier) static bool v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier) { - struct v4l2_subdev *sd; + struct v4l2_async_connection *asc; if (!list_empty(¬ifier->waiting_list)) return false; - list_for_each_entry(sd, ¬ifier->done_list, async_list) { + list_for_each_entry(asc, ¬ifier->done_list, asc_entry) { struct v4l2_async_notifier *subdev_notifier = - v4l2_async_find_subdev_notifier(sd); + v4l2_async_find_subdev_notifier(asc->sd); if (subdev_notifier && !v4l2_async_nf_can_complete(subdev_notifier)) @@ -333,12 +333,13 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, if (ret) goto err_call_unbind; - list_del(&asc->waiting_entry); sd->asd = asc; sd->notifier = notifier; - /* Move from the global subdevice list to notifier's done */ - list_move(&sd->async_list, ¬ifier->done_list); + asc->sd = sd; + + /* Move from the waiting list to notifier's done */ + list_move(&asc->asc_entry, ¬ifier->done_list); dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n", dev_name(sd->dev), ret); @@ -422,25 +423,23 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd) /* Unbind all sub-devices in the notifier tree. */ static void -v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier, - bool readd) +v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier) { - struct v4l2_subdev *sd, *tmp; + struct v4l2_async_connection *asc, *asc_tmp; - list_for_each_entry_safe(sd, tmp, ¬ifier->done_list, async_list) { + list_for_each_entry_safe(asc, asc_tmp, ¬ifier->done_list, + asc_entry) { struct v4l2_async_notifier *subdev_notifier = - v4l2_async_find_subdev_notifier(sd); + v4l2_async_find_subdev_notifier(asc->sd); if (subdev_notifier) - v4l2_async_nf_unbind_all_subdevs(subdev_notifier, true); + v4l2_async_nf_unbind_all_subdevs(subdev_notifier); - v4l2_async_nf_call_unbind(notifier, sd, sd->asd); - if (readd) - list_add_tail(&sd->asd->waiting_entry, - ¬ifier->waiting_list); - v4l2_async_cleanup(sd); - - list_move(&sd->async_list, &subdev_list); + v4l2_async_nf_call_unbind(notifier, asc->sd, asc); + v4l2_async_cleanup(asc->sd); + list_move_tail(&asc->asc_entry, ¬ifier->waiting_list); + list_move(&asc->sd->async_list, &subdev_list); + asc->sd = NULL; } notifier->parent = NULL; @@ -452,17 +451,16 @@ v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier, struct v4l2_async_match_desc *match) { struct v4l2_async_connection *asc; - struct v4l2_subdev *sd; - list_for_each_entry(asc, ¬ifier->waiting_list, waiting_entry) + list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry) if (v4l2_async_match_equal(&asc->match, match)) return true; - list_for_each_entry(sd, ¬ifier->done_list, async_list) { - if (WARN_ON(!sd->asd)) + list_for_each_entry(asc, ¬ifier->done_list, asc_entry) { + if (WARN_ON(!asc->sd->asd)) continue; - if (v4l2_async_match_equal(&sd->asd->match, match)) + if (v4l2_async_match_equal(&asc->match, match)) return true; } @@ -477,16 +475,24 @@ static bool v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier, struct v4l2_async_match_desc *match) { - struct v4l2_async_connection *asc; + struct list_head *heads[] = { + ¬ifier->waiting_list, + ¬ifier->done_list, + }; + unsigned int i; lockdep_assert_held(&list_lock); /* Check that an asd is not being added more than once. */ - list_for_each_entry(asc, ¬ifier->asc_list, asc_entry) { - if (&asc->match == match) - continue; - if (v4l2_async_match_equal(&asc->match, match)) - return true; + for (i = 0; i < ARRAY_SIZE(heads); i++) { + struct v4l2_async_connection *asc; + + list_for_each_entry(asc, heads[i], asc_entry) { + if (&asc->match == match) + continue; + if (v4l2_async_match_equal(&asc->match, match)) + return true; + } } /* Check that an asc does not exist in other notifiers. */ @@ -521,7 +527,8 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier, void v4l2_async_nf_init(struct v4l2_async_notifier *notifier) { - INIT_LIST_HEAD(¬ifier->asc_list); + INIT_LIST_HEAD(¬ifier->waiting_list); + INIT_LIST_HEAD(¬ifier->done_list); } EXPORT_SYMBOL(v4l2_async_nf_init); @@ -530,17 +537,12 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) struct v4l2_async_connection *asc; int ret; - INIT_LIST_HEAD(¬ifier->waiting_list); - INIT_LIST_HEAD(¬ifier->done_list); - mutex_lock(&list_lock); - list_for_each_entry(asc, ¬ifier->asc_list, asc_entry) { + list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry) { ret = v4l2_async_nf_match_valid(notifier, &asc->match); if (ret) goto err_unlock; - - list_add_tail(&asc->waiting_entry, ¬ifier->waiting_list); } ret = v4l2_async_nf_try_all_subdevs(notifier); @@ -562,7 +564,7 @@ err_unbind: /* * On failure, unbind all sub-devices registered through this notifier. */ - v4l2_async_nf_unbind_all_subdevs(notifier, false); + v4l2_async_nf_unbind_all_subdevs(notifier); err_unlock: mutex_unlock(&list_lock); @@ -612,7 +614,7 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier) if (!notifier || (!notifier->v4l2_dev && !notifier->sd)) return; - v4l2_async_nf_unbind_all_subdevs(notifier, false); + v4l2_async_nf_unbind_all_subdevs(notifier); notifier->sd = NULL; notifier->v4l2_dev = NULL; @@ -634,10 +636,12 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier) { struct v4l2_async_connection *asc, *tmp; - if (!notifier || !notifier->asc_list.next) + if (!notifier || !notifier->waiting_list.next) return; - list_for_each_entry_safe(asc, tmp, ¬ifier->asc_list, asc_entry) { + WARN_ON(!list_empty(¬ifier->done_list)); + + list_for_each_entry_safe(asc, tmp, ¬ifier->waiting_list, asc_entry) { switch (asc->match.type) { case V4L2_ASYNC_MATCH_TYPE_FWNODE: fwnode_handle_put(asc->match.fwnode); @@ -667,7 +671,7 @@ static int __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier, { mutex_lock(&list_lock); - list_add_tail(&asc->asc_entry, ¬ifier->asc_list); + list_add_tail(&asc->asc_entry, ¬ifier->waiting_list); mutex_unlock(&list_lock); @@ -810,10 +814,12 @@ err_unbind: */ subdev_notifier = v4l2_async_find_subdev_notifier(sd); if (subdev_notifier) - v4l2_async_nf_unbind_all_subdevs(subdev_notifier, false); + v4l2_async_nf_unbind_all_subdevs(subdev_notifier); - if (sd->asd) + if (sd->asd) { v4l2_async_nf_call_unbind(notifier, sd, sd->asd); + sd->asd->sd = NULL; + } v4l2_async_cleanup(sd); mutex_unlock(&list_lock); @@ -839,9 +845,9 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) if (sd->asd) { struct v4l2_async_notifier *notifier = sd->notifier; - list_add(&sd->asd->waiting_entry, ¬ifier->waiting_list); - + list_move(&sd->asd->asc_entry, ¬ifier->waiting_list); v4l2_async_nf_call_unbind(notifier, sd, sd->asd); + sd->asd->sd = NULL; } v4l2_async_cleanup(sd); @@ -895,7 +901,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data) list_for_each_entry(notif, ¬ifier_list, notifier_entry) { seq_printf(s, "%s:\n", v4l2_async_nf_name(notif)); - list_for_each_entry(asc, ¬if->waiting_list, waiting_entry) + list_for_each_entry(asc, ¬if->waiting_list, asc_entry) print_waiting_match(s, &asc->match); } diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c index c1216b4557b6..67c1b16db655 100644 --- a/drivers/staging/media/imx/imx-media-dev-common.c +++ b/drivers/staging/media/imx/imx-media-dev-common.c @@ -384,7 +384,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd, int ret; /* no subdevs? just bail */ - if (list_empty(&imxmd->notifier.asc_list)) { + if (list_empty(&imxmd->notifier.waiting_list)) { v4l2_err(&imxmd->v4l2_dev, "no subdevs\n"); return -ENODEV; } diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 07e3eb8c7056..ee4ae1f1f2fa 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1464,7 +1464,7 @@ tegra_vi_graph_find_entity(struct tegra_vi_channel *chan, struct tegra_vi_graph_entity *entity; struct v4l2_async_connection *asd; - list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) { + list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) { entity = to_tegra_vi_graph_entity(asd); if (entity->asd.match.fwnode == fwnode) return entity; @@ -1608,7 +1608,7 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier) } /* create links between the entities */ - list_for_each_entry(asd, &chan->notifier.asc_list, asc_entry) { + list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) { entity = to_tegra_vi_graph_entity(asd); ret = tegra_vi_graph_build(chan, entity); if (ret < 0) @@ -1775,7 +1775,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) ret = tegra_vi_graph_parse_one(chan, remote); fwnode_handle_put(remote); - if (ret < 0 || list_empty(&chan->notifier.asc_list)) + if (ret < 0 || list_empty(&chan->notifier.waiting_list)) continue; chan->notifier.ops = &tegra_vi_async_ops; diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index a27d9dc8afcb..c06b3b832228 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -66,9 +66,8 @@ struct v4l2_async_match_desc { * * @match: struct of match type and per-bus type matching data sets * @asc_entry: used to add struct v4l2_async_connection objects to the - * master notifier @asc_list - * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to - * be probed, to a notifier->waiting_list list + * notifier @waiting_list or @done_list + * @sd: the related sub-device * * When this struct is used as a member in a driver specific struct, * the driver specific struct shall contain the &struct @@ -77,7 +76,7 @@ struct v4l2_async_match_desc { struct v4l2_async_connection { struct v4l2_async_match_desc match; struct list_head asc_entry; - struct list_head waiting_entry; + struct v4l2_subdev *sd; }; /** @@ -106,7 +105,6 @@ struct v4l2_async_notifier_operations { * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise * @sd: sub-device that registered the notifier, NULL otherwise * @parent: parent notifier - * @asc_list: master list of struct v4l2_async_connection * @waiting_list: list of struct v4l2_async_connection, waiting for their * drivers * @done_list: list of struct v4l2_subdev, already probed @@ -117,7 +115,6 @@ struct v4l2_async_notifier { struct v4l2_device *v4l2_dev; struct v4l2_subdev *sd; struct v4l2_async_notifier *parent; - struct list_head asc_list; struct list_head waiting_list; struct list_head done_list; struct list_head notifier_entry; -- cgit v1.2.3 From b8ec754ae4c563f6aab8c0cb47aeb2eae67f1da3 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 23 Feb 2023 16:24:48 +0100 Subject: media: v4l: async: Set v4l2_device and subdev in async notifier init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the v4l2_device already in async notifier init, so struct device related to it will be available before the notifier is registered. This requires separating notifier initialisation into two functions, one that takes v4l2_device as its argument, v4l2_async_nf_init and v4l2_async_subdev_nf_init, for sub-device notifiers. Registering the notifier will use a single function, v4l2_async_nf_register. This is done in order to make struct device available earlier, during construction of the async connections, for sensible debug prints. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ds90ub913.c | 4 +- drivers/media/i2c/ds90ub953.c | 4 +- drivers/media/i2c/ds90ub960.c | 4 +- drivers/media/i2c/max9286.c | 4 +- drivers/media/i2c/st-mipid02.c | 4 +- drivers/media/i2c/tc358746.c | 4 +- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 4 +- drivers/media/platform/atmel/atmel-isi.c | 4 +- drivers/media/platform/cadence/cdns-csi2rx.c | 4 +- drivers/media/platform/intel/pxa_camera.c | 4 +- drivers/media/platform/marvell/cafe-driver.c | 2 +- drivers/media/platform/marvell/mcam-core.c | 2 +- drivers/media/platform/marvell/mmp-driver.c | 2 +- .../media/platform/microchip/microchip-csi2dc.c | 5 +-- .../platform/microchip/microchip-sama5d2-isc.c | 5 +-- .../platform/microchip/microchip-sama7g5-isc.c | 5 +-- drivers/media/platform/nxp/imx-mipi-csis.c | 4 +- drivers/media/platform/nxp/imx7-media-csi.c | 4 +- .../media/platform/nxp/imx8-isi/imx8-isi-core.c | 4 +- drivers/media/platform/nxp/imx8mq-mipi-csi2.c | 4 +- drivers/media/platform/qcom/camss/camss.c | 5 +-- drivers/media/platform/renesas/rcar-isp.c | 4 +- .../media/platform/renesas/rcar-vin/rcar-core.c | 8 ++-- .../media/platform/renesas/rcar-vin/rcar-csi2.c | 4 +- drivers/media/platform/renesas/rcar_drif.c | 4 +- drivers/media/platform/renesas/renesas-ceu.c | 4 +- .../media/platform/renesas/rzg2l-cru/rzg2l-core.c | 4 +- .../media/platform/renesas/rzg2l-cru/rzg2l-csi2.c | 4 +- .../media/platform/rockchip/rkisp1/rkisp1-dev.c | 4 +- .../media/platform/samsung/exynos4-is/media-dev.c | 5 +-- drivers/media/platform/st/stm32/stm32-dcmi.c | 4 +- drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c | 4 +- .../platform/sunxi/sun6i-csi/sun6i_csi_bridge.c | 10 ++--- .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 4 +- .../sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c | 4 +- drivers/media/platform/ti/am437x/am437x-vpfe.c | 4 +- drivers/media/platform/ti/cal/cal.c | 4 +- drivers/media/platform/ti/davinci/vpif_capture.c | 11 +++--- drivers/media/platform/ti/omap3isp/isp.c | 4 +- drivers/media/platform/video-mux.c | 4 +- drivers/media/platform/xilinx/xilinx-vipp.c | 4 +- drivers/media/v4l2-core/v4l2-async.c | 44 +++++++++------------- drivers/media/v4l2-core/v4l2-fwnode.c | 4 +- .../media/atomisp/pci/atomisp_csi2_bridge.c | 2 +- drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 2 +- .../media/deprecated/atmel/atmel-sama5d2-isc.c | 5 +-- .../media/deprecated/atmel/atmel-sama7g5-isc.c | 5 +-- drivers/staging/media/imx/imx-media-csi.c | 4 +- drivers/staging/media/imx/imx-media-dev-common.c | 4 +- drivers/staging/media/imx/imx6-mipi-csi2.c | 4 +- .../staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c | 4 +- drivers/staging/media/tegra-video/vi.c | 5 +-- include/media/v4l2-async.h | 33 +++++++++------- 53 files changed, 142 insertions(+), 154 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c index 349c34724eee..80d9cf6dd945 100644 --- a/drivers/media/i2c/ds90ub913.c +++ b/drivers/media/i2c/ds90ub913.c @@ -568,7 +568,7 @@ static int ub913_v4l2_notifier_register(struct ub913_data *priv) return -ENODEV; } - v4l2_async_nf_init(&priv->notifier); + v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd); asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode, struct v4l2_async_connection); @@ -583,7 +583,7 @@ static int ub913_v4l2_notifier_register(struct ub913_data *priv) priv->notifier.ops = &ub913_notify_ops; - ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier); + ret = v4l2_async_nf_register(&priv->notifier); if (ret) { dev_err(dev, "Failed to register subdev_notifier"); v4l2_async_nf_cleanup(&priv->notifier); diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c index 440af7bdd73a..cadf75eb0773 100644 --- a/drivers/media/i2c/ds90ub953.c +++ b/drivers/media/i2c/ds90ub953.c @@ -773,7 +773,7 @@ static int ub953_v4l2_notifier_register(struct ub953_data *priv) return -ENODEV; } - v4l2_async_nf_init(&priv->notifier); + v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd); asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode, struct v4l2_async_connection); @@ -788,7 +788,7 @@ static int ub953_v4l2_notifier_register(struct ub953_data *priv) priv->notifier.ops = &ub953_notify_ops; - ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier); + ret = v4l2_async_nf_register(&priv->notifier); if (ret) { dev_err(dev, "Failed to register subdev_notifier"); v4l2_async_nf_cleanup(&priv->notifier); diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c index a2b1056ba99b..4833b39b9178 100644 --- a/drivers/media/i2c/ds90ub960.c +++ b/drivers/media/i2c/ds90ub960.c @@ -3599,7 +3599,7 @@ static int ub960_v4l2_notifier_register(struct ub960_data *priv) unsigned int i; int ret; - v4l2_async_nf_init(&priv->notifier); + 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]; @@ -3623,7 +3623,7 @@ static int ub960_v4l2_notifier_register(struct ub960_data *priv) priv->notifier.ops = &ub960_notify_ops; - ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier); + ret = v4l2_async_nf_register(&priv->notifier); if (ret) { dev_err(dev, "Failed to register subdev_notifier"); v4l2_async_nf_cleanup(&priv->notifier); diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 78c77cd50823..20e7c7cf5eeb 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -746,7 +746,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv) if (!priv->nsources) return 0; - v4l2_async_nf_init(&priv->notifier); + v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd); for_each_source(priv, source) { unsigned int i = to_index(priv, source); @@ -766,7 +766,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv) priv->notifier.ops = &max9286_notify_ops; - ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier); + ret = v4l2_async_nf_register(&priv->notifier); if (ret) { dev_err(dev, "Failed to register subdev_notifier"); v4l2_async_nf_cleanup(&priv->notifier); diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c index 5cd87b1d5759..782633b9e11e 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -911,7 +911,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge) bridge->rx = ep; /* register async notifier so we get noticed when sensor is connected */ - v4l2_async_nf_init(&bridge->notifier); + v4l2_async_subdev_nf_init(&bridge->notifier, &bridge->sd); asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier, of_fwnode_handle(ep_node), struct v4l2_async_connection); @@ -924,7 +924,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge) } bridge->notifier.ops = &mipid02_notifier_ops; - ret = v4l2_async_subdev_nf_register(&bridge->sd, &bridge->notifier); + ret = v4l2_async_nf_register(&bridge->notifier); if (ret) v4l2_async_nf_cleanup(&bridge->notifier); diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c index 203eb337efce..566f5eaddd57 100644 --- a/drivers/media/i2c/tc358746.c +++ b/drivers/media/i2c/tc358746.c @@ -1460,7 +1460,7 @@ static int tc358746_async_register(struct tc358746 *tc358746) return err; } - v4l2_async_nf_init(&tc358746->notifier); + v4l2_async_subdev_nf_init(&tc358746->notifier, &tc358746->sd); asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep, struct v4l2_async_connection); fwnode_handle_put(ep); @@ -1472,7 +1472,7 @@ static int tc358746_async_register(struct tc358746 *tc358746) tc358746->notifier.ops = &tc358746_notify_ops; - err = v4l2_async_subdev_nf_register(&tc358746->sd, &tc358746->notifier); + err = v4l2_async_nf_register(&tc358746->notifier); if (err) goto err_cleanup; diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 0e89a3b9293a..4ebab0a95f35 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1500,7 +1500,7 @@ err_parse: * suspend. */ cio2->notifier.ops = &cio2_async_ops; - ret = v4l2_async_nf_register(&cio2->v4l2_dev, &cio2->notifier); + ret = v4l2_async_nf_register(&cio2->notifier); if (ret) dev_err(dev, "failed to register async notifier : %d\n", ret); @@ -1795,7 +1795,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, if (r) goto fail_v4l2_device_unregister; - v4l2_async_nf_init(&cio2->notifier); + v4l2_async_nf_init(&cio2->notifier, &cio2->v4l2_dev); /* Register notifier for subdevices we care */ r = cio2_parse_firmware(cio2); diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index 13902b944731..4046212d48b4 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -1159,7 +1159,7 @@ static int isi_graph_init(struct atmel_isi *isi) if (!ep) return -EINVAL; - v4l2_async_nf_init(&isi->notifier); + v4l2_async_nf_init(&isi->notifier, &isi->v4l2_dev); asd = v4l2_async_nf_add_fwnode_remote(&isi->notifier, of_fwnode_handle(ep), @@ -1171,7 +1171,7 @@ static int isi_graph_init(struct atmel_isi *isi) isi->notifier.ops = &isi_graph_notify_ops; - ret = v4l2_async_nf_register(&isi->v4l2_dev, &isi->notifier); + ret = v4l2_async_nf_register(&isi->notifier); if (ret < 0) { dev_err(isi->dev, "Notifier registration failed\n"); v4l2_async_nf_cleanup(&isi->notifier); diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c index a6d7de98b755..0d879d71d818 100644 --- a/drivers/media/platform/cadence/cdns-csi2rx.c +++ b/drivers/media/platform/cadence/cdns-csi2rx.c @@ -474,7 +474,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx) return -EINVAL; } - v4l2_async_nf_init(&csi2rx->notifier); + v4l2_async_subdev_nf_init(&csi2rx->notifier, &csi2rx->subdev); asd = v4l2_async_nf_add_fwnode_remote(&csi2rx->notifier, fwh, struct v4l2_async_connection); @@ -484,7 +484,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx) csi2rx->notifier.ops = &csi2rx_notifier_ops; - ret = v4l2_async_subdev_nf_register(&csi2rx->subdev, &csi2rx->notifier); + ret = v4l2_async_nf_register(&csi2rx->notifier); if (ret) v4l2_async_nf_cleanup(&csi2rx->notifier); diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c index 6112d31c2228..6e6caf50e11e 100644 --- a/drivers/media/platform/intel/pxa_camera.c +++ b/drivers/media/platform/intel/pxa_camera.c @@ -2302,7 +2302,7 @@ static int pxa_camera_probe(struct platform_device *pdev) if (err) return err; - v4l2_async_nf_init(&pcdev->notifier); + v4l2_async_nf_init(&pcdev->notifier, &pcdev->v4l2_dev); pcdev->res = res; pcdev->pdata = pdev->dev.platform_data; if (pcdev->pdata) { @@ -2402,7 +2402,7 @@ static int pxa_camera_probe(struct platform_device *pdev) } pcdev->notifier.ops = &pxa_camera_sensor_ops; - err = v4l2_async_nf_register(&pcdev->v4l2_dev, &pcdev->notifier); + err = v4l2_async_nf_register(&pcdev->notifier); if (err) goto exit_deactivate; diff --git a/drivers/media/platform/marvell/cafe-driver.c b/drivers/media/platform/marvell/cafe-driver.c index fbfbb9f67ddf..ef810249def6 100644 --- a/drivers/media/platform/marvell/cafe-driver.c +++ b/drivers/media/platform/marvell/cafe-driver.c @@ -540,7 +540,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, if (ret) goto out_smbus_shutdown; - v4l2_async_nf_init(&mcam->notifier); + v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev); asd = v4l2_async_nf_add_i2c(&mcam->notifier, i2c_adapter_id(cam->i2c_adapter), diff --git a/drivers/media/platform/marvell/mcam-core.c b/drivers/media/platform/marvell/mcam-core.c index 7a6e043ac753..66688b4aece5 100644 --- a/drivers/media/platform/marvell/mcam-core.c +++ b/drivers/media/platform/marvell/mcam-core.c @@ -1870,7 +1870,7 @@ int mccic_register(struct mcam_camera *cam) cam->mbus_code = mcam_def_mbus_code; cam->notifier.ops = &mccic_notify_ops; - ret = v4l2_async_nf_register(&cam->v4l2_dev, &cam->notifier); + ret = v4l2_async_nf_register(&cam->notifier); if (ret < 0) { cam_warn(cam, "failed to register a sensor notifier"); goto out; diff --git a/drivers/media/platform/marvell/mmp-driver.c b/drivers/media/platform/marvell/mmp-driver.c index 43e046b82115..170907cc1885 100644 --- a/drivers/media/platform/marvell/mmp-driver.c +++ b/drivers/media/platform/marvell/mmp-driver.c @@ -238,7 +238,7 @@ static int mmpcam_probe(struct platform_device *pdev) if (!ep) return -ENODEV; - v4l2_async_nf_init(&mcam->notifier); + v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev); asd = v4l2_async_nf_add_fwnode_remote(&mcam->notifier, ep, struct v4l2_async_connection); diff --git a/drivers/media/platform/microchip/microchip-csi2dc.c b/drivers/media/platform/microchip/microchip-csi2dc.c index d631c3880c53..988c1cc1d8b6 100644 --- a/drivers/media/platform/microchip/microchip-csi2dc.c +++ b/drivers/media/platform/microchip/microchip-csi2dc.c @@ -523,7 +523,7 @@ static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc, struct v4l2_async_connection *asd; int ret = 0; - v4l2_async_nf_init(&csi2dc->notifier); + v4l2_async_subdev_nf_init(&csi2dc->notifier, &csi2dc->csi2dc_sd); asd = v4l2_async_nf_add_fwnode_remote(&csi2dc->notifier, input_fwnode, @@ -542,8 +542,7 @@ static int csi2dc_prepare_notifier(struct csi2dc_device *csi2dc, csi2dc->notifier.ops = &csi2dc_async_ops; - ret = v4l2_async_subdev_nf_register(&csi2dc->csi2dc_sd, - &csi2dc->notifier); + ret = v4l2_async_nf_register(&csi2dc->notifier); if (ret) { dev_err(csi2dc->dev, "fail to register async notifier: %d\n", ret); diff --git a/drivers/media/platform/microchip/microchip-sama5d2-isc.c b/drivers/media/platform/microchip/microchip-sama5d2-isc.c index e8dfe30cc62d..5ac149cf3647 100644 --- a/drivers/media/platform/microchip/microchip-sama5d2-isc.c +++ b/drivers/media/platform/microchip/microchip-sama5d2-isc.c @@ -527,7 +527,7 @@ static int microchip_isc_probe(struct platform_device *pdev) struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); - v4l2_async_nf_init(&subdev_entity->notifier); + v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev); asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, @@ -543,8 +543,7 @@ static int microchip_isc_probe(struct platform_device *pdev) subdev_entity->notifier.ops = µchip_isc_async_ops; - ret = v4l2_async_nf_register(&isc->v4l2_dev, - &subdev_entity->notifier); + ret = v4l2_async_nf_register(&subdev_entity->notifier); if (ret) { dev_err(dev, "fail to register async notifier\n"); goto cleanup_subdev; diff --git a/drivers/media/platform/microchip/microchip-sama7g5-isc.c b/drivers/media/platform/microchip/microchip-sama7g5-isc.c index cd982a995d72..73445f33d26b 100644 --- a/drivers/media/platform/microchip/microchip-sama7g5-isc.c +++ b/drivers/media/platform/microchip/microchip-sama7g5-isc.c @@ -517,7 +517,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); - v4l2_async_nf_init(&subdev_entity->notifier); + v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev); asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, @@ -533,8 +533,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) subdev_entity->notifier.ops = µchip_isc_async_ops; - ret = v4l2_async_nf_register(&isc->v4l2_dev, - &subdev_entity->notifier); + ret = v4l2_async_nf_register(&subdev_entity->notifier); if (ret) { dev_err(dev, "fail to register async notifier\n"); goto cleanup_subdev; diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c index f7d64fb48434..16f19a640130 100644 --- a/drivers/media/platform/nxp/imx-mipi-csis.c +++ b/drivers/media/platform/nxp/imx-mipi-csis.c @@ -1251,7 +1251,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis) unsigned int i; int ret; - v4l2_async_nf_init(&csis->notifier); + v4l2_async_subdev_nf_init(&csis->notifier, &csis->sd); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csis->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -1287,7 +1287,7 @@ static int mipi_csis_async_register(struct mipi_csis_device *csis) csis->notifier.ops = &mipi_csis_notify_ops; - ret = v4l2_async_subdev_nf_register(&csis->sd, &csis->notifier); + ret = v4l2_async_nf_register(&csis->notifier); if (ret) return ret; diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index 565c093fdff2..50f6efaaa7f2 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -2061,7 +2061,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi) struct fwnode_handle *ep; int ret; - v4l2_async_nf_init(&csi->notifier); + v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -2084,7 +2084,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi) csi->notifier.ops = &imx7_csi_notify_ops; - ret = v4l2_async_nf_register(&csi->v4l2_dev, &csi->notifier); + ret = v4l2_async_nf_register(&csi->notifier); if (ret) goto error; diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c index da1572f8ff42..5fdd0fe9efbe 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c @@ -175,7 +175,7 @@ static int mxc_isi_v4l2_init(struct mxc_isi_dev *isi) } /* Initialize, fill and register the async notifier. */ - v4l2_async_nf_init(&isi->notifier); + v4l2_async_nf_init(&isi->notifier, v4l2_dev); isi->notifier.ops = &mxc_isi_async_notifier_ops; for (i = 0; i < isi->pdata->num_ports; ++i) { @@ -200,7 +200,7 @@ static int mxc_isi_v4l2_init(struct mxc_isi_dev *isi) masd->port = i; } - ret = v4l2_async_nf_register(v4l2_dev, &isi->notifier); + ret = v4l2_async_nf_register(&isi->notifier); if (ret < 0) { dev_err(isi->dev, "Failed to register async notifier: %d\n", ret); diff --git a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c index 326c3763b85a..39f7e86ad531 100644 --- a/drivers/media/platform/nxp/imx8mq-mipi-csi2.c +++ b/drivers/media/platform/nxp/imx8mq-mipi-csi2.c @@ -592,7 +592,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state) unsigned int i; int ret; - v4l2_async_nf_init(&state->notifier); + v4l2_async_subdev_nf_init(&state->notifier, &state->sd); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -629,7 +629,7 @@ static int imx8mq_mipi_csi_async_register(struct csi_state *state) state->notifier.ops = &imx8mq_mipi_csi_notify_ops; - ret = v4l2_async_subdev_nf_register(&state->sd, &state->notifier); + ret = v4l2_async_nf_register(&state->notifier); if (ret) return ret; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index b89e2bb5b505..f11dc59135a5 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -1640,7 +1640,7 @@ static int camss_probe(struct platform_device *pdev) goto err_cleanup; } - v4l2_async_nf_init(&camss->notifier); + v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev); num_subdevs = camss_of_parse_ports(camss); if (num_subdevs < 0) { @@ -1655,8 +1655,7 @@ static int camss_probe(struct platform_device *pdev) if (num_subdevs) { camss->notifier.ops = &camss_subdev_notifier_ops; - ret = v4l2_async_nf_register(&camss->v4l2_dev, - &camss->notifier); + ret = v4l2_async_nf_register(&camss->notifier); if (ret) { dev_err(dev, "Failed to register async subdev nodes: %d\n", diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c index 9e3b8a8850a0..7360cf3863f2 100644 --- a/drivers/media/platform/renesas/rcar-isp.c +++ b/drivers/media/platform/renesas/rcar-isp.c @@ -392,7 +392,7 @@ static int risp_parse_dt(struct rcar_isp *isp) dev_dbg(isp->dev, "Found '%pOF'\n", to_of_node(fwnode)); - v4l2_async_nf_init(&isp->notifier); + v4l2_async_subdev_nf_init(&isp->notifier, &isp->subdev); isp->notifier.ops = &risp_notify_ops; asd = v4l2_async_nf_add_fwnode(&isp->notifier, fwnode, @@ -401,7 +401,7 @@ static int risp_parse_dt(struct rcar_isp *isp) if (IS_ERR(asd)) return PTR_ERR(asd); - ret = v4l2_async_subdev_nf_register(&isp->subdev, &isp->notifier); + ret = v4l2_async_nf_register(&isp->notifier); if (ret) v4l2_async_nf_cleanup(&isp->notifier); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index b44f12bd01c4..809c3a38cc4a 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -375,7 +375,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port, mutex_unlock(&vin->group->lock); - v4l2_async_nf_init(&vin->group->notifier); + v4l2_async_nf_init(&vin->group->notifier, &vin->v4l2_dev); /* * Some subdevices may overlap but the parser function can handle it and @@ -399,7 +399,7 @@ static int rvin_group_notifier_init(struct rvin_dev *vin, unsigned int port, return 0; vin->group->notifier.ops = &rvin_group_notify_ops; - ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->group->notifier); + ret = v4l2_async_nf_register(&vin->group->notifier); if (ret < 0) { vin_err(vin, "Notifier registration failed\n"); v4l2_async_nf_cleanup(&vin->group->notifier); @@ -712,7 +712,7 @@ static int rvin_parallel_init(struct rvin_dev *vin) { int ret; - v4l2_async_nf_init(&vin->notifier); + v4l2_async_nf_init(&vin->notifier, &vin->v4l2_dev); ret = rvin_parallel_parse_of(vin); if (ret) @@ -725,7 +725,7 @@ static int rvin_parallel_init(struct rvin_dev *vin) to_of_node(vin->parallel.asc->match.fwnode)); vin->notifier.ops = &rvin_parallel_notify_ops; - ret = v4l2_async_nf_register(&vin->v4l2_dev, &vin->notifier); + ret = v4l2_async_nf_register(&vin->notifier); if (ret < 0) { vin_err(vin, "Notifier registration failed\n"); v4l2_async_nf_cleanup(&vin->notifier); diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c index c3a117995493..f536b6359146 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c @@ -1122,7 +1122,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv) dev_dbg(priv->dev, "Found '%pOF'\n", to_of_node(fwnode)); - v4l2_async_nf_init(&priv->notifier); + v4l2_async_subdev_nf_init(&priv->notifier, &priv->subdev); priv->notifier.ops = &rcar_csi2_notify_ops; asc = v4l2_async_nf_add_fwnode(&priv->notifier, fwnode, @@ -1131,7 +1131,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv) if (IS_ERR(asc)) return PTR_ERR(asc); - ret = v4l2_async_subdev_nf_register(&priv->subdev, &priv->notifier); + ret = v4l2_async_nf_register(&priv->notifier); if (ret) v4l2_async_nf_cleanup(&priv->notifier); diff --git a/drivers/media/platform/renesas/rcar_drif.c b/drivers/media/platform/renesas/rcar_drif.c index ef24bab04995..163a4ba61c17 100644 --- a/drivers/media/platform/renesas/rcar_drif.c +++ b/drivers/media/platform/renesas/rcar_drif.c @@ -1208,7 +1208,7 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr) struct fwnode_handle *fwnode, *ep; struct v4l2_async_connection *asd; - v4l2_async_nf_init(notifier); + v4l2_async_nf_init(&sdr->notifier, &sdr->v4l2_dev); ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(sdr->dev->of_node), NULL); @@ -1342,7 +1342,7 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr) sdr->notifier.ops = &rcar_drif_notify_ops; /* Register notifier */ - ret = v4l2_async_nf_register(&sdr->v4l2_dev, &sdr->notifier); + ret = v4l2_async_nf_register(&sdr->notifier); if (ret < 0) { dev_err(sdr->dev, "failed: notifier register ret %d\n", ret); goto cleanup; diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c index f9e0bb954307..ec631c6e2a57 100644 --- a/drivers/media/platform/renesas/renesas-ceu.c +++ b/drivers/media/platform/renesas/renesas-ceu.c @@ -1657,7 +1657,7 @@ static int ceu_probe(struct platform_device *pdev) if (ret) goto error_pm_disable; - v4l2_async_nf_init(&ceudev->notifier); + v4l2_async_nf_init(&ceudev->notifier, &ceudev->v4l2_dev); if (IS_ENABLED(CONFIG_OF) && dev->of_node) { ceu_data = of_device_get_match_data(dev); @@ -1679,7 +1679,7 @@ static int ceu_probe(struct platform_device *pdev) ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev; ceudev->notifier.ops = &ceu_notify_ops; - ret = v4l2_async_nf_register(&ceudev->v4l2_dev, &ceudev->notifier); + ret = v4l2_async_nf_register(&ceudev->notifier); if (ret) goto error_cleanup; diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c index a5aa6a73f84d..280efd2a8185 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c @@ -182,7 +182,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru) { int ret; - v4l2_async_nf_init(&cru->notifier); + v4l2_async_nf_init(&cru->notifier, &cru->v4l2_dev); ret = rzg2l_cru_mc_parse_of(cru); if (ret) @@ -193,7 +193,7 @@ static int rzg2l_cru_mc_parse_of_graph(struct rzg2l_cru_dev *cru) if (list_empty(&cru->notifier.waiting_list)) return 0; - ret = v4l2_async_nf_register(&cru->v4l2_dev, &cru->notifier); + ret = v4l2_async_nf_register(&cru->notifier); if (ret < 0) { dev_err(cru->dev, "Notifier registration failed\n"); v4l2_async_nf_cleanup(&cru->notifier); diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c index da233d76c315..ad2bd71037ab 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c @@ -673,7 +673,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2) fwnode = fwnode_graph_get_remote_endpoint(ep); fwnode_handle_put(ep); - v4l2_async_nf_init(&csi2->notifier); + v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->subdev); csi2->notifier.ops = &rzg2l_csi2_notify_ops; asd = v4l2_async_nf_add_fwnode(&csi2->notifier, fwnode, @@ -682,7 +682,7 @@ static int rzg2l_csi2_parse_dt(struct rzg2l_csi2 *csi2) if (IS_ERR(asd)) return PTR_ERR(asd); - ret = v4l2_async_subdev_nf_register(&csi2->subdev, &csi2->notifier); + ret = v4l2_async_nf_register(&csi2->notifier); if (ret) v4l2_async_nf_cleanup(&csi2->notifier); diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c index 6b9bd97afabe..c41abd2833f1 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c @@ -187,7 +187,7 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1) unsigned int index = 0; int ret = 0; - v4l2_async_nf_init(ntf); + v4l2_async_nf_init(ntf, &rkisp1->v4l2_dev); ntf->ops = &rkisp1_subdev_notifier_ops; @@ -287,7 +287,7 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1) if (!index) dev_dbg(rkisp1->dev, "no remote subdevice found\n"); - ret = v4l2_async_nf_register(&rkisp1->v4l2_dev, ntf); + ret = v4l2_async_nf_register(ntf); if (ret) { v4l2_async_nf_cleanup(ntf); return ret; diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.c b/drivers/media/platform/samsung/exynos4-is/media-dev.c index cb9a22b5b6b1..5f10bb4eb4f7 100644 --- a/drivers/media/platform/samsung/exynos4-is/media-dev.c +++ b/drivers/media/platform/samsung/exynos4-is/media-dev.c @@ -1478,7 +1478,7 @@ static int fimc_md_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fmd); - v4l2_async_nf_init(&fmd->subdev_notifier); + v4l2_async_nf_init(&fmd->subdev_notifier, &fmd->v4l2_dev); ret = fimc_md_register_platform_entities(fmd, dev->of_node); if (ret) @@ -1506,8 +1506,7 @@ static int fimc_md_probe(struct platform_device *pdev) fmd->subdev_notifier.ops = &subdev_notifier_ops; fmd->num_sensors = 0; - ret = v4l2_async_nf_register(&fmd->v4l2_dev, - &fmd->subdev_notifier); + ret = v4l2_async_nf_register(&fmd->subdev_notifier); if (ret) goto err_clk_p; } diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c index b029efa992d6..b026876415ca 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmi.c +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c @@ -1897,7 +1897,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) return -EINVAL; } - v4l2_async_nf_init(&dcmi->notifier); + v4l2_async_nf_init(&dcmi->notifier, &dcmi->v4l2_dev); asd = v4l2_async_nf_add_fwnode_remote(&dcmi->notifier, of_fwnode_handle(ep), @@ -1912,7 +1912,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) dcmi->notifier.ops = &dcmi_graph_notify_ops; - ret = v4l2_async_nf_register(&dcmi->v4l2_dev, &dcmi->notifier); + ret = v4l2_async_nf_register(&dcmi->notifier); if (ret < 0) { dev_err(dcmi->dev, "Failed to register notifier\n"); v4l2_async_nf_cleanup(&dcmi->notifier); diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c index 3b6e9071a545..ad13d447d483 100644 --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c @@ -121,7 +121,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi) struct fwnode_handle *ep; int ret; - v4l2_async_nf_init(&csi->notifier); + v4l2_async_nf_init(&csi->notifier, &csi->v4l); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -239,7 +239,7 @@ static int sun4i_csi_probe(struct platform_device *pdev) if (ret) goto err_unregister_media; - ret = v4l2_async_nf_register(&csi->v4l, &csi->notifier); + ret = v4l2_async_nf_register(&csi->notifier); if (ret) { dev_err(csi->dev, "Couldn't register our notifier.\n"); goto err_unregister_media; diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c index ebb725fc11ba..e573413123b9 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c @@ -819,7 +819,10 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev) /* V4L2 Async */ - v4l2_async_nf_init(notifier); + if (csi_dev->isp_available) + v4l2_async_subdev_nf_init(notifier, subdev); + else + v4l2_async_nf_init(notifier, v4l2_dev); notifier->ops = &sun6i_csi_bridge_notifier_ops; sun6i_csi_bridge_source_setup(csi_dev, &bridge->source_parallel, @@ -828,10 +831,7 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev) sun6i_csi_bridge_source_setup(csi_dev, &bridge->source_mipi_csi2, SUN6I_CSI_PORT_MIPI_CSI2, NULL); - if (csi_dev->isp_available) - ret = v4l2_async_subdev_nf_register(subdev, notifier); - else - ret = v4l2_async_nf_register(v4l2_dev, notifier); + ret = v4l2_async_nf_register(notifier); if (ret) { dev_err(dev, "failed to register v4l2 async notifier: %d\n", ret); diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c index 82da38e0547e..08d86c17b284 100644 --- a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c +++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c @@ -530,7 +530,7 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev) /* V4L2 Async */ - v4l2_async_nf_init(notifier); + v4l2_async_subdev_nf_init(notifier, subdev); notifier->ops = &sun6i_mipi_csi2_notifier_ops; ret = sun6i_mipi_csi2_bridge_source_setup(csi2_dev); @@ -539,7 +539,7 @@ static int sun6i_mipi_csi2_bridge_setup(struct sun6i_mipi_csi2_device *csi2_dev) /* Only register the notifier when a sensor is connected. */ if (ret != -ENODEV) { - ret = v4l2_async_subdev_nf_register(subdev, notifier); + ret = v4l2_async_nf_register(notifier); if (ret < 0) goto error_v4l2_notifier_cleanup; diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c index b96b8faf9fb9..14a1844812c0 100644 --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c @@ -568,7 +568,7 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev) /* V4L2 Async */ - v4l2_async_nf_init(notifier); + v4l2_async_subdev_nf_init(notifier, subdev); notifier->ops = &sun8i_a83t_mipi_csi2_notifier_ops; ret = sun8i_a83t_mipi_csi2_bridge_source_setup(csi2_dev); @@ -577,7 +577,7 @@ sun8i_a83t_mipi_csi2_bridge_setup(struct sun8i_a83t_mipi_csi2_device *csi2_dev) /* Only register the notifier when a sensor is connected. */ if (ret != -ENODEV) { - ret = v4l2_async_subdev_nf_register(subdev, notifier); + ret = v4l2_async_nf_register(notifier); if (ret < 0) goto error_v4l2_notifier_cleanup; diff --git a/drivers/media/platform/ti/am437x/am437x-vpfe.c b/drivers/media/platform/ti/am437x/am437x-vpfe.c index f559d2bcaacb..319ec5ea0527 100644 --- a/drivers/media/platform/ti/am437x/am437x-vpfe.c +++ b/drivers/media/platform/ti/am437x/am437x-vpfe.c @@ -2300,7 +2300,7 @@ vpfe_get_pdata(struct vpfe_device *vpfe) dev_dbg(dev, "vpfe_get_pdata\n"); - v4l2_async_nf_init(&vpfe->notifier); + v4l2_async_nf_init(&vpfe->notifier, &vpfe->v4l2_dev); if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) return dev->platform_data; @@ -2466,7 +2466,7 @@ static int vpfe_probe(struct platform_device *pdev) } vpfe->notifier.ops = &vpfe_async_ops; - ret = v4l2_async_nf_register(&vpfe->v4l2_dev, &vpfe->notifier); + ret = v4l2_async_nf_register(&vpfe->notifier); if (ret) { vpfe_err(vpfe, "Error registering async notifier\n"); ret = -EINVAL; diff --git a/drivers/media/platform/ti/cal/cal.c b/drivers/media/platform/ti/cal/cal.c index 7cd50629d9d3..528909ae4bd6 100644 --- a/drivers/media/platform/ti/cal/cal.c +++ b/drivers/media/platform/ti/cal/cal.c @@ -865,7 +865,7 @@ static int cal_async_notifier_register(struct cal_dev *cal) unsigned int i; int ret; - v4l2_async_nf_init(&cal->notifier); + v4l2_async_nf_init(&cal->notifier, &cal->v4l2_dev); cal->notifier.ops = &cal_async_notifier_ops; for (i = 0; i < cal->data->num_csi2_phy; ++i) { @@ -889,7 +889,7 @@ static int cal_async_notifier_register(struct cal_dev *cal) casd->phy = phy; } - ret = v4l2_async_nf_register(&cal->v4l2_dev, &cal->notifier); + ret = v4l2_async_nf_register(&cal->notifier); if (ret) { cal_err(cal, "Error registering async notifier\n"); goto error; diff --git a/drivers/media/platform/ti/davinci/vpif_capture.c b/drivers/media/platform/ti/davinci/vpif_capture.c index 10b13d8e76e5..bf5330b6fcd5 100644 --- a/drivers/media/platform/ti/davinci/vpif_capture.c +++ b/drivers/media/platform/ti/davinci/vpif_capture.c @@ -1483,7 +1483,8 @@ static const struct v4l2_async_notifier_operations vpif_async_ops = { }; static struct vpif_capture_config * -vpif_capture_get_pdata(struct platform_device *pdev) +vpif_capture_get_pdata(struct platform_device *pdev, + struct v4l2_device *v4l2_dev) { struct device_node *endpoint = NULL; struct device_node *rem = NULL; @@ -1492,7 +1493,7 @@ vpif_capture_get_pdata(struct platform_device *pdev) struct vpif_capture_chan_config *chan; unsigned int i; - v4l2_async_nf_init(&vpif_obj.notifier); + v4l2_async_nf_init(&vpif_obj.notifier, v4l2_dev); /* * DT boot: OF node from parent device contains @@ -1640,7 +1641,8 @@ static __init int vpif_probe(struct platform_device *pdev) goto vpif_unregister; } while (++res_idx); - pdev->dev.platform_data = vpif_capture_get_pdata(pdev); + pdev->dev.platform_data = + vpif_capture_get_pdata(pdev, &vpif_obj.v4l2_dev); if (!pdev->dev.platform_data) { dev_warn(&pdev->dev, "Missing platform data. Giving up.\n"); goto vpif_unregister; @@ -1683,8 +1685,7 @@ static __init int vpif_probe(struct platform_device *pdev) goto probe_subdev_out; } else { vpif_obj.notifier.ops = &vpif_async_ops; - err = v4l2_async_nf_register(&vpif_obj.v4l2_dev, - &vpif_obj.notifier); + err = v4l2_async_nf_register(&vpif_obj.notifier); if (err) { vpif_err("Error registering async notifier\n"); err = -EINVAL; diff --git a/drivers/media/platform/ti/omap3isp/isp.c b/drivers/media/platform/ti/omap3isp/isp.c index f0de621f7f8b..52c480437ed2 100644 --- a/drivers/media/platform/ti/omap3isp/isp.c +++ b/drivers/media/platform/ti/omap3isp/isp.c @@ -2420,13 +2420,13 @@ static int isp_probe(struct platform_device *pdev) isp->notifier.ops = &isp_subdev_notifier_ops; - v4l2_async_nf_init(&isp->notifier); + v4l2_async_nf_init(&isp->notifier, &isp->v4l2_dev); ret = isp_parse_of_endpoints(isp); if (ret < 0) goto error_register_entities; - ret = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier); + ret = v4l2_async_nf_register(&isp->notifier); if (ret) goto error_register_entities; diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 6cc0dde42e80..5de6b6694f53 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -331,7 +331,7 @@ static int video_mux_async_register(struct video_mux *vmux, unsigned int i; int ret; - v4l2_async_nf_init(&vmux->notifier); + v4l2_async_subdev_nf_init(&vmux->notifier, &vmux->subdev); for (i = 0; i < num_input_pads; i++) { struct v4l2_async_connection *asd; @@ -366,7 +366,7 @@ static int video_mux_async_register(struct video_mux *vmux, vmux->notifier.ops = &video_mux_notify_ops; - ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier); + ret = v4l2_async_nf_register(&vmux->notifier); if (ret) goto err_nf_cleanup; diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index 6bb426a25fe9..4285770fde18 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -494,7 +494,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev) goto done; } - v4l2_async_nf_init(&xdev->notifier); + v4l2_async_nf_init(&xdev->notifier, &xdev->v4l2_dev); /* Parse the graph to extract a list of subdevice DT nodes. */ ret = xvip_graph_parse(xdev); @@ -512,7 +512,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev) /* Register the subdevices notifier. */ xdev->notifier.ops = &xvip_graph_notify_ops; - ret = v4l2_async_nf_register(&xdev->v4l2_dev, &xdev->notifier); + ret = v4l2_async_nf_register(&xdev->notifier); if (ret < 0) { dev_err(xdev->dev, "notifier registration failed\n"); goto done; diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index ea27e04f0f75..f465a0964adf 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -558,13 +558,24 @@ static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier, return 0; } -void v4l2_async_nf_init(struct v4l2_async_notifier *notifier) +void v4l2_async_nf_init(struct v4l2_async_notifier *notifier, + struct v4l2_device *v4l2_dev) { INIT_LIST_HEAD(¬ifier->waiting_list); INIT_LIST_HEAD(¬ifier->done_list); + notifier->v4l2_dev = v4l2_dev; } EXPORT_SYMBOL(v4l2_async_nf_init); +void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd) +{ + INIT_LIST_HEAD(¬ifier->waiting_list); + INIT_LIST_HEAD(¬ifier->done_list); + notifier->sd = sd; +} +EXPORT_SYMBOL_GPL(v4l2_async_subdev_nf_init); + static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) { struct v4l2_async_connection *asc; @@ -605,16 +616,13 @@ err_unlock: return ret; } -int v4l2_async_nf_register(struct v4l2_device *v4l2_dev, - struct v4l2_async_notifier *notifier) +int v4l2_async_nf_register(struct v4l2_async_notifier *notifier) { int ret; - if (WARN_ON(!v4l2_dev || notifier->sd)) + if (WARN_ON(!notifier->v4l2_dev == !notifier->sd)) return -EINVAL; - notifier->v4l2_dev = v4l2_dev; - ret = __v4l2_async_nf_register(notifier); if (ret) notifier->v4l2_dev = NULL; @@ -623,24 +631,6 @@ int v4l2_async_nf_register(struct v4l2_device *v4l2_dev, } EXPORT_SYMBOL(v4l2_async_nf_register); -int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd, - struct v4l2_async_notifier *notifier) -{ - int ret; - - if (WARN_ON(!sd || notifier->v4l2_dev)) - return -EINVAL; - - notifier->sd = sd; - - ret = __v4l2_async_nf_register(notifier); - if (ret) - notifier->sd = NULL; - - return ret; -} -EXPORT_SYMBOL(v4l2_async_subdev_nf_register); - static void __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier) { @@ -649,9 +639,6 @@ __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier) v4l2_async_nf_unbind_all_subdevs(notifier); - notifier->sd = NULL; - notifier->v4l2_dev = NULL; - list_del(¬ifier->notifier_entry); } @@ -683,6 +670,9 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier) kfree(asc); } + + notifier->sd = NULL; + notifier->v4l2_dev = NULL; } void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index f30f98b9f2d0..7f181fbbb140 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -1215,7 +1215,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd) if (!notifier) return -ENOMEM; - v4l2_async_nf_init(notifier); + v4l2_async_subdev_nf_init(notifier, sd); ret = v4l2_subdev_get_privacy_led(sd); if (ret < 0) @@ -1225,7 +1225,7 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd) if (ret < 0) goto out_cleanup; - ret = v4l2_async_subdev_nf_register(sd, notifier); + ret = v4l2_async_nf_register(notifier); if (ret < 0) goto out_cleanup; diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index dbb0160e71b7..46d9f31986c9 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -825,7 +825,7 @@ int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp) { int i, mipi_port, ret; - v4l2_async_nf_init(&isp->notifier); + v4l2_async_nf_init(&isp->notifier, &isp->v4l2_dev); isp->notifier.ops = &atomisp_async_ops; for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index c43b916a006e..21233e68b1e1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1508,7 +1508,7 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i isp->firmware = NULL; isp->css_env.isp_css_fw.data = NULL; - err = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier); + err = v4l2_async_nf_register(&isp->notifier); if (err) { dev_err(isp->dev, "failed to register async notifier : %d\n", err); goto css_init_fail; diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c index 58c8c7813e0f..31b2b48085c5 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c +++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c @@ -507,7 +507,7 @@ static int atmel_isc_probe(struct platform_device *pdev) struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); - v4l2_async_nf_init(&subdev_entity->notifier); + v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev); asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, @@ -523,8 +523,7 @@ static int atmel_isc_probe(struct platform_device *pdev) subdev_entity->notifier.ops = &atmel_isc_async_ops; - ret = v4l2_async_nf_register(&isc->v4l2_dev, - &subdev_entity->notifier); + ret = v4l2_async_nf_register(&subdev_entity->notifier); if (ret) { dev_err(dev, "fail to register async notifier\n"); goto cleanup_subdev; diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c index f10ddee0949e..020034f631f5 100644 --- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c +++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c @@ -497,7 +497,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) struct fwnode_handle *fwnode = of_fwnode_handle(subdev_entity->epn); - v4l2_async_nf_init(&subdev_entity->notifier); + v4l2_async_nf_init(&subdev_entity->notifier, &isc->v4l2_dev); asd = v4l2_async_nf_add_fwnode_remote(&subdev_entity->notifier, fwnode, @@ -513,8 +513,7 @@ static int microchip_xisc_probe(struct platform_device *pdev) subdev_entity->notifier.ops = &atmel_isc_async_ops; - ret = v4l2_async_nf_register(&isc->v4l2_dev, - &subdev_entity->notifier); + ret = v4l2_async_nf_register(&subdev_entity->notifier); if (ret) { dev_err(dev, "fail to register async notifier\n"); goto cleanup_subdev; diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 09b8b396022e..dda1ebc34692 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -1918,7 +1918,7 @@ static int imx_csi_async_register(struct csi_priv *priv) unsigned int port; int ret; - v4l2_async_nf_init(&priv->notifier); + v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd); /* get this CSI's port id */ ret = fwnode_property_read_u32(dev_fwnode(priv->dev), "reg", &port); @@ -1944,7 +1944,7 @@ static int imx_csi_async_register(struct csi_priv *priv) priv->notifier.ops = &csi_notify_ops; - ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier); + ret = v4l2_async_nf_register(&priv->notifier); if (ret) return ret; diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c index 67c1b16db655..46bf717255b3 100644 --- a/drivers/staging/media/imx/imx-media-dev-common.c +++ b/drivers/staging/media/imx/imx-media-dev-common.c @@ -367,7 +367,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev, INIT_LIST_HEAD(&imxmd->vdev_list); - v4l2_async_nf_init(&imxmd->notifier); + v4l2_async_nf_init(&imxmd->notifier, &imxmd->v4l2_dev); return imxmd; @@ -391,7 +391,7 @@ int imx_media_dev_notifier_register(struct imx_media_dev *imxmd, /* prepare the async subdev notifier and register it */ imxmd->notifier.ops = ops ? ops : &imx_media_notifier_ops; - ret = v4l2_async_nf_register(&imxmd->v4l2_dev, &imxmd->notifier); + ret = v4l2_async_nf_register(&imxmd->notifier); if (ret) { v4l2_err(&imxmd->v4l2_dev, "v4l2_async_nf_register failed with %d\n", ret); diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index e3273c5c9b60..b2d8476d83a0 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -680,7 +680,7 @@ static int csi2_async_register(struct csi2_dev *csi2) struct fwnode_handle *ep; int ret; - v4l2_async_nf_init(&csi2->notifier); + v4l2_async_subdev_nf_init(&csi2->notifier, &csi2->sd); ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi2->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); @@ -705,7 +705,7 @@ static int csi2_async_register(struct csi2_dev *csi2) csi2->notifier.ops = &csi2_notify_ops; - ret = v4l2_async_subdev_nf_register(&csi2->sd, &csi2->notifier); + ret = v4l2_async_nf_register(&csi2->notifier); if (ret) return ret; diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c index dd7dfecb9ef3..ccbb530aa2e2 100644 --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c @@ -536,7 +536,7 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev) /* V4L2 Async */ - v4l2_async_nf_init(notifier); + v4l2_async_nf_init(notifier, v4l2_dev); notifier->ops = &sun6i_isp_proc_notifier_ops; sun6i_isp_proc_source_setup(isp_dev, &proc->source_csi0, @@ -544,7 +544,7 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev) sun6i_isp_proc_source_setup(isp_dev, &proc->source_csi1, SUN6I_ISP_PORT_CSI1); - ret = v4l2_async_nf_register(v4l2_dev, notifier); + ret = v4l2_async_nf_register(notifier); if (ret) { v4l2_err(v4l2_dev, "failed to register v4l2 async notifier: %d\n", ret); diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index ee4ae1f1f2fa..b5facc0640fb 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1181,7 +1181,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) } if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) - v4l2_async_nf_init(&chan->notifier); + v4l2_async_nf_init(&chan->notifier, &vid->v4l2_dev); return 0; @@ -1748,7 +1748,6 @@ cleanup: static int tegra_vi_graph_init(struct tegra_vi *vi) { - struct tegra_video_device *vid = dev_get_drvdata(vi->client.host); struct tegra_vi_channel *chan; struct fwnode_handle *fwnode = dev_fwnode(vi->dev); int ret; @@ -1779,7 +1778,7 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) continue; chan->notifier.ops = &tegra_vi_async_ops; - ret = v4l2_async_nf_register(&vid->v4l2_dev, &chan->notifier); + ret = v4l2_async_nf_register(&chan->notifier); if (ret < 0) { dev_err(vi->dev, "failed to register channel %d notifier: %d\n", diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 41a9c4bada8a..9bd326d31181 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -148,13 +148,30 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir); * v4l2_async_nf_init - Initialize a notifier. * * @notifier: pointer to &struct v4l2_async_notifier + * @v4l2_dev: pointer to &struct v4l2_device + * + * This function initializes the notifier @asc_entry. It must be called + * before adding a subdevice to a notifier, using one of: + * v4l2_async_nf_add_fwnode_remote(), + * v4l2_async_nf_add_fwnode() or + * v4l2_async_nf_add_i2c(). + */ +void v4l2_async_nf_init(struct v4l2_async_notifier *notifier, + struct v4l2_device *v4l2_dev); + +/** + * v4l2_async_subdev_nf_init - Initialize a sub-device notifier. + * + * @notifier: pointer to &struct v4l2_async_notifier + * @sd: pointer to &struct v4l2_subdev * * This function initializes the notifier @asc_list. It must be called * before adding a subdevice to a notifier, using one of: * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or * v4l2_async_nf_add_i2c(). */ -void v4l2_async_nf_init(struct v4l2_async_notifier *notifier); +void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd); struct v4l2_async_connection * __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier, @@ -259,21 +276,9 @@ v4l2_async_connection_unique(struct v4l2_subdev *sd); /** * v4l2_async_nf_register - registers a subdevice asynchronous notifier * - * @v4l2_dev: pointer to &struct v4l2_device - * @notifier: pointer to &struct v4l2_async_notifier - */ -int v4l2_async_nf_register(struct v4l2_device *v4l2_dev, - struct v4l2_async_notifier *notifier); - -/** - * v4l2_async_subdev_nf_register - registers a subdevice asynchronous - * notifier for a sub-device - * - * @sd: pointer to &struct v4l2_subdev * @notifier: pointer to &struct v4l2_async_notifier */ -int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd, - struct v4l2_async_notifier *notifier); +int v4l2_async_nf_register(struct v4l2_async_notifier *notifier); /** * v4l2_async_nf_unregister - unregisters a subdevice -- cgit v1.2.3 From a2c77032465711e4ee34dbeb5491938aedccffdb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 19 Jun 2023 12:52:07 +0200 Subject: media: atomisp: Remove bogus asd == NULL checks The asd is a sub-structure of the main driver data struct, so it is never NULL. Drop the unnecessary NULL checks in a couple of places. Reported-by: Dan Carpenter Closes: https://lore.kernel.org/linux-media/533f6930-434a-45f3-afff-127003fa64c9@moroto.mountain/ Signed-off-by: Hans de Goede Signed-off-by: Hans Verkuil --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 24 ---------------------- .../media/atomisp/pci/atomisp_compat_css20.c | 3 --- 2 files changed, 27 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index e27f9dc8e7aa..0803b296e9ac 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3001,12 +3001,6 @@ void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) bool need_to_enqueue_buffer = false; int i; - if (!asd) { - dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, pipe->vdev.name); - return; - } - lockdep_assert_held(&asd->isp->mutex); /* @@ -3068,12 +3062,6 @@ int atomisp_set_parameters(struct video_device *vdev, struct atomisp_css_params *css_param = &asd->params.css_param; int ret; - if (!asd) { - dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, vdev->name); - return -EINVAL; - } - lockdep_assert_held(&asd->isp->mutex); if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].stream) { @@ -4067,12 +4055,6 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, const struct atomisp_in_fmt_conv *fc = NULL; int ret, i; - if (!asd) { - dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, vdev->name); - return -EINVAL; - } - isp_sink_crop = atomisp_subdev_get_rect( &asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK, V4L2_SEL_TGT_CROP); @@ -4280,12 +4262,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p (struct atomisp_input_stream_info *)ffmt->reserved; int ret; - if (!asd) { - dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, vdev->name); - return -EINVAL; - } - format = atomisp_get_format_bridge(f->pixelformat); if (!format) return -EINVAL; diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index b13d1cb4668d..b97ec85aa0ba 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -613,9 +613,6 @@ static void __apply_additional_pipe_config( static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, enum ia_css_pipe_id pipe_id) { - if (!asd) - return false; - if (pipe_id == IA_CSS_PIPE_ID_YUVPP) return true; -- cgit v1.2.3 From 7b4846b6515483396af706329cb51794eb6afb6d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 30 Jul 2023 17:33:42 +0200 Subject: media: atomisp: Fix smatch warnings caused by atomisp custom assert() usage The atomisp code base has a custom assert() macro, a couple of functions use this in a construction like the following: assert(pipe); assert(pipe->stream); if ((!pipe) || (!pipe->stream)) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: ...\n", pipe); return -EINVAL; } The second assert is seen by smatch as dereferencing "pipe" in the above example (and dereferencing "dvs_6axis_config" in the other case). Following by the dereferenced variable being checked (a second time) in the following if () statement. This triggers the following smatch warnings: drivers/staging/media/atomisp/pci/sh_css_mipi.c:356 allocate_mipi_frames() warn: variable dereferenced before check 'pipe' (see line 355) drivers/staging/media/atomisp/pci/sh_css_mipi.c:562 send_mipi_frames() warn: variable dereferenced before check 'pipe' (see line 561) drivers/staging/media/atomisp/pci/sh_css_param_dvs.c:208 free_dvs_6axis_table() warn: variable dereferenced before check 'dvs_6axis_config' (see line 206) The custom assert() macro actually expands to a BUG() call and BUG() calls should not be used in the kernel. Remove the assert() calls to fix the smatch warnings and in case of [allocate|send]_mipi_frames() also remove the if () return -EINVAL block since these functions are never called with a NULL pipe. Reported-by: Hans Verkuil Signed-off-by: Hans de Goede Signed-off-by: Hans Verkuil --- drivers/staging/media/atomisp/pci/sh_css_mipi.c | 16 ---------------- drivers/staging/media/atomisp/pci/sh_css_param_dvs.c | 3 --- 2 files changed, 19 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index b20acaab0595..ced21dedf7ac 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -351,15 +351,6 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) enter:\n", pipe); - assert(pipe); - assert(pipe->stream); - if ((!pipe) || (!pipe->stream)) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "allocate_mipi_frames(%p) exit: pipe or stream is null.\n", - pipe); - return -EINVAL; - } - if (IS_ISP2401 && pipe->stream->config.online) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n", @@ -557,13 +548,6 @@ send_mipi_frames(struct ia_css_pipe *pipe) IA_CSS_ENTER_PRIVATE("pipe=%p", pipe); - assert(pipe); - assert(pipe->stream); - if (!pipe || !pipe->stream) { - IA_CSS_ERROR("pipe or stream is null"); - return -EINVAL; - } - /* multi stream video needs mipi buffers */ /* nothing to be done in other cases. */ if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { diff --git a/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c b/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c index ff0082d02af3..5174bc210ae1 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c +++ b/drivers/staging/media/atomisp/pci/sh_css_param_dvs.c @@ -202,9 +202,6 @@ generate_dvs_6axis_table_from_config(struct ia_css_dvs_6axis_config void free_dvs_6axis_table(struct ia_css_dvs_6axis_config **dvs_6axis_config) { - assert(dvs_6axis_config); - assert(*dvs_6axis_config); - if ((dvs_6axis_config) && (*dvs_6axis_config)) { IA_CSS_ENTER_PRIVATE("dvs_6axis_config %p", (*dvs_6axis_config)); if ((*dvs_6axis_config)->xcoords_y) { -- cgit v1.2.3 From 9e2a90d75662d2cad22d8e3f3358c1b5392f037d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 30 Jul 2023 17:33:43 +0200 Subject: media: atomisp: Fix me->stages error checking in sh_css_sp_init_pipeline() The current error-checking of me->stages in sh_css_sp_init_pipeline() has some issues / weirdness: 1. It is checked at the top of the function, but only using the atomisp custom assert() macro which e.g. smatch does not recognize 2. It is first dereferenced in "first_binary = me->stages->binary", but outside of the assert it is checked much later, triggering the following smatch warning: drivers/staging/media/atomisp/pci/sh_css_sp.c:1255 sh_css_sp_init_pipeline() warn: variable dereferenced before check 'me->stages' (see line 1224) Drop the custom assert() calls (note 'me' is never NULL) and instead add a regular check for me->stages not being set. Reported-by: Hans Verkuil Closes: https://lore.kernel.org/linux-media/7c8fc5b4-280e-844e-cdf5-b6ec2a1616aa@xs4all.nl/ Signed-off-by: Hans de Goede Signed-off-by: Hans Verkuil --- drivers/staging/media/atomisp/pci/sh_css_sp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 297e1b981720..f35c745c22c0 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -51,6 +51,7 @@ #include "ia_css_event.h" #include "mmu_device.h" #include "ia_css_spctrl.h" +#include "atomisp_internal.h" #ifndef offsetof #define offsetof(T, x) ((unsigned int)&(((T *)0)->x)) @@ -1212,14 +1213,15 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, struct ia_css_binary *first_binary = NULL; struct ia_css_pipe *pipe = NULL; unsigned int num; - enum ia_css_pipe_id pipe_id = id; unsigned int thread_id; u8 if_config_index, tmp_if_config_index; - assert(me); - - assert(me->stages); + if (!me->stages) { + dev_err(atomisp_dev, "%s called on a pipeline without stages\n", + __func__); + return; /* FIXME should be able to return an error */ + } first_binary = me->stages->binary; @@ -1252,8 +1254,8 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, } /* if (first_binary != NULL) */ /* Signal the host immediately after start for SP_ISYS_COPY only */ - if ((me->num_stages == 1) && me->stages && - (me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY)) + if (me->num_stages == 1 && + me->stages->sp_func == IA_CSS_PIPELINE_ISYS_COPY) sh_css_sp_group.config.no_isp_sync = true; /* Init stage data */ -- cgit v1.2.3 From 483fe862488f9116a80839f46b06842330b679d9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 24 Apr 2023 12:48:32 +0300 Subject: staging: media: imx: Merge VIDEO_IMX_CSI into VIDEO_IMX_MEDIA The VIDEO_IMX_MEDIA Kconfig symbol used to select helpers shared between independent drivers for different i.MX SoCs, and VIDEO_IMX_MEDIA then selects drivers specific to the i.MX5 and i.MX6. Now that i.MX7 and i.MX8 support has moved to drivers/media/ and doesn't depend on VIDEO_IMX_CSI, there's no need to have separate Kconfig options. Merge VIDEO_IMX_CSI into VIDEO_IMX_MEDIA. Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/staging/media/imx/Kconfig | 17 +++-------------- drivers/staging/media/imx/Makefile | 7 +++---- 2 files changed, 6 insertions(+), 18 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig index b42af427b88b..426310e1ea5b 100644 --- a/drivers/staging/media/imx/Kconfig +++ b/drivers/staging/media/imx/Kconfig @@ -1,10 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 config VIDEO_IMX_MEDIA - tristate "i.MX5/6 V4L2 media core driver" + tristate "i.MX5/6 V4L2 media drivers" depends on ARCH_MXC || COMPILE_TEST depends on HAS_DMA depends on VIDEO_DEV depends on VIDEO_DEV + depends on IMX_IPUV3_CORE select MEDIA_CONTROLLER select V4L2_FWNODE select V4L2_MEM2MEM_DEV @@ -12,16 +13,4 @@ config VIDEO_IMX_MEDIA select VIDEO_V4L2_SUBDEV_API help Say yes here to enable support for video4linux media controller - driver for the i.MX5/6 SOC. - -if VIDEO_IMX_MEDIA -menu "i.MX5/6/7/8 Media Sub devices" - -config VIDEO_IMX_CSI - tristate "i.MX5/6 Camera Sensor Interface driver" - depends on IMX_IPUV3_CORE - default y - help - A video4linux camera sensor interface driver for i.MX5/6. -endmenu -endif + drivers for the i.MX5/6 SOC. diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile index b69951deff9a..330e0825f506 100644 --- a/drivers/staging/media/imx/Makefile +++ b/drivers/staging/media/imx/Makefile @@ -9,7 +9,6 @@ imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \ imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o - -obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media.o -obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o -obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o +obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o +obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media-csi.o +obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-mipi-csi2.o -- cgit v1.2.3 From b67b291449486d51bcbc4c9d117134e332d96196 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 27 Jun 2023 14:51:07 +0200 Subject: media: atomisp: ov2680: Convert to new CCI register access helpers Use the new comon CCI register access helpers to replace the private register access helpers in the ov2680 driver. While at it also switch to using the same register address defines as the standard drivers/media/i2c/ov2680.c driver to make merging the 2 drivers simpler. Reviewed-by: Laurent Pinchart Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/Kconfig | 1 + drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 247 ++++++++++----------- drivers/staging/media/atomisp/i2c/ov2680.h | 86 +------ 3 files changed, 119 insertions(+), 215 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/i2c/Kconfig b/drivers/staging/media/atomisp/i2c/Kconfig index e726101b24e4..e34646d7dadc 100644 --- a/drivers/staging/media/atomisp/i2c/Kconfig +++ b/drivers/staging/media/atomisp/i2c/Kconfig @@ -61,6 +61,7 @@ config VIDEO_ATOMISP_OV2680 tristate "Omnivision OV2680 sensor support" depends on ACPI depends on I2C && VIDEO_DEV + select V4L2_CCI_I2C help This is a Video4Linux2 sensor-level driver for the Omnivision OV2680 raw camera. diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 4cc2839937af..f933a65ac8d4 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -23,13 +23,50 @@ #include #include #include +#include #include -#include #include #include "ov2680.h" +#define OV2680_CHIP_ID 0x2680 + +#define OV2680_REG_STREAM_CTRL CCI_REG8(0x0100) +#define OV2680_REG_SOFT_RESET CCI_REG8(0x0103) + +#define OV2680_REG_CHIP_ID CCI_REG16(0x300a) +#define OV2680_REG_SC_CMMN_SUB_ID CCI_REG8(0x302a) + +#define OV2680_REG_EXPOSURE_PK CCI_REG24(0x3500) +#define OV2680_REG_R_MANUAL CCI_REG8(0x3503) +#define OV2680_REG_GAIN_PK CCI_REG16(0x350a) + +#define OV2680_REG_SENSOR_CTRL_0A CCI_REG8(0x370a) + +#define OV2680_REG_HORIZONTAL_START CCI_REG16(0x3800) +#define OV2680_REG_VERTICAL_START CCI_REG16(0x3802) +#define OV2680_REG_HORIZONTAL_END CCI_REG16(0x3804) +#define OV2680_REG_VERTICAL_END CCI_REG16(0x3806) +#define OV2680_REG_HORIZONTAL_OUTPUT_SIZE CCI_REG16(0x3808) +#define OV2680_REG_VERTICAL_OUTPUT_SIZE CCI_REG16(0x380a) +#define OV2680_REG_TIMING_HTS CCI_REG16(0x380c) +#define OV2680_REG_TIMING_VTS CCI_REG16(0x380e) +#define OV2680_REG_ISP_X_WIN CCI_REG16(0x3810) +#define OV2680_REG_ISP_Y_WIN CCI_REG16(0x3812) +#define OV2680_REG_X_INC CCI_REG8(0x3814) +#define OV2680_REG_Y_INC CCI_REG8(0x3815) +#define OV2680_REG_FORMAT1 CCI_REG8(0x3820) +#define OV2680_REG_FORMAT2 CCI_REG8(0x3821) + +#define OV2680_REG_ISP_CTRL00 CCI_REG8(0x5080) + +#define OV2680_REG_X_WIN CCI_REG16(0x5704) +#define OV2680_REG_Y_WIN CCI_REG16(0x5706) + +#define OV2680_FRAME_RATE 30 +#define OV2680_INTEGRATION_TIME_MARGIN 8 + static const struct v4l2_rect ov2680_default_crop = { .left = OV2680_ACTIVE_START_LEFT, .top = OV2680_ACTIVE_START_TOP, @@ -37,21 +74,6 @@ static const struct v4l2_rect ov2680_default_crop = { .height = OV2680_ACTIVE_HEIGHT, }; -static int ov2680_write_reg_array(struct i2c_client *client, - const struct ov2680_reg *reglist) -{ - const struct ov2680_reg *next = reglist; - int ret; - - for (; next->reg != 0; next++) { - ret = ov_write_reg8(client, next->reg, next->val); - if (ret) - return ret; - } - - return 0; -} - static void ov2680_set_bayer_order(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt) { static const int ov2680_hv_flip_bayer_order[] = { @@ -78,7 +100,8 @@ static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val) if (sensor->is_streaming) return -EBUSY; - ret = ov_update_reg(sensor->client, OV2680_REG_FORMAT1, BIT(2), val ? BIT(2) : 0); + ret = cci_update_bits(sensor->regmap, OV2680_REG_FORMAT1, BIT(2), + val ? BIT(2) : 0, NULL); if (ret < 0) return ret; @@ -93,7 +116,8 @@ static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val) if (sensor->is_streaming) return -EBUSY; - ret = ov_update_reg(sensor->client, OV2680_REG_FORMAT2, BIT(2), val ? BIT(2) : 0); + ret = cci_update_bits(sensor->regmap, OV2680_REG_FORMAT2, BIT(2), + val ? BIT(2) : 0, NULL); if (ret < 0) return ret; @@ -103,30 +127,29 @@ static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val) static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp) { - return ov_write_reg24(sensor->client, OV2680_REG_EXPOSURE_PK_HIGH, exp << 4); + return cci_write(sensor->regmap, OV2680_REG_EXPOSURE_PK, exp << 4, + NULL); } static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain) { - return ov_write_reg16(sensor->client, OV2680_REG_GAIN_PK, gain); + return cci_write(sensor->regmap, OV2680_REG_GAIN_PK, gain, NULL); } static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value) { - int ret; + int ret = 0; if (!value) - return ov_update_reg(sensor->client, OV2680_REG_ISP_CTRL00, BIT(7), 0); - - ret = ov_update_reg(sensor->client, OV2680_REG_ISP_CTRL00, 0x03, value - 1); - if (ret < 0) - return ret; + return cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, + BIT(7), 0, NULL); - ret = ov_update_reg(sensor->client, OV2680_REG_ISP_CTRL00, BIT(7), BIT(7)); - if (ret < 0) - return ret; + cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, 0x03, value - 1, + &ret); + cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, BIT(7), BIT(7), + &ret); - return 0; + return ret; } static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl) @@ -171,17 +194,18 @@ static const struct v4l2_ctrl_ops ov2680_ctrl_ops = { static int ov2680_init_registers(struct v4l2_subdev *sd) { - struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); int ret; - ret = ov_write_reg8(client, OV2680_SW_RESET, 0x01); + ret = cci_write(sensor->regmap, OV2680_REG_SOFT_RESET, 0x01, NULL); + if (ret < 0) + return ret; /* Wait for sensor reset */ usleep_range(1000, 2000); - ret |= ov2680_write_reg_array(client, ov2680_global_setting); - - return ret; + return regmap_multi_reg_write(sensor->regmap, ov2680_global_setting, + ARRAY_SIZE(ov2680_global_setting)); } static struct v4l2_mbus_framefmt * @@ -247,9 +271,8 @@ static void ov2680_calc_mode(struct ov2680_dev *sensor) static int ov2680_set_mode(struct ov2680_dev *sensor) { - struct i2c_client *client = sensor->client; u8 sensor_ctrl_0a, inc, fmt1, fmt2; - int ret; + int ret = 0; if (sensor->mode.binning) { sensor_ctrl_0a = 0x23; @@ -263,77 +286,36 @@ static int ov2680_set_mode(struct ov2680_dev *sensor) fmt2 = 0x00; } - ret = ov_write_reg8(client, OV2680_REG_SENSOR_CTRL_0A, sensor_ctrl_0a); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_HORIZONTAL_START_H, sensor->mode.h_start); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_VERTICAL_START_H, sensor->mode.v_start); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_HORIZONTAL_END_H, sensor->mode.h_end); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_VERTICAL_END_H, sensor->mode.v_end); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_HORIZONTAL_OUTPUT_SIZE_H, - sensor->mode.h_output_size); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_VERTICAL_OUTPUT_SIZE_H, - sensor->mode.v_output_size); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_HTS, sensor->mode.hts); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_VTS, sensor->mode.vts); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_ISP_X_WIN, 0); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_ISP_Y_WIN, 0); - if (ret) - return ret; - - ret = ov_write_reg8(client, OV2680_X_INC, inc); - if (ret) - return ret; - - ret = ov_write_reg8(client, OV2680_Y_INC, inc); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_X_WIN, sensor->mode.h_output_size); - if (ret) - return ret; - - ret = ov_write_reg16(client, OV2680_Y_WIN, sensor->mode.v_output_size); - if (ret) - return ret; - - ret = ov_write_reg8(client, OV2680_REG_FORMAT1, fmt1); - if (ret) - return ret; - - ret = ov_write_reg8(client, OV2680_REG_FORMAT2, fmt2); - if (ret) - return ret; + cci_write(sensor->regmap, OV2680_REG_SENSOR_CTRL_0A, + sensor_ctrl_0a, &ret); + cci_write(sensor->regmap, OV2680_REG_HORIZONTAL_START, + sensor->mode.h_start, &ret); + cci_write(sensor->regmap, OV2680_REG_VERTICAL_START, + sensor->mode.v_start, &ret); + cci_write(sensor->regmap, OV2680_REG_HORIZONTAL_END, + sensor->mode.h_end, &ret); + cci_write(sensor->regmap, OV2680_REG_VERTICAL_END, + sensor->mode.v_end, &ret); + cci_write(sensor->regmap, OV2680_REG_HORIZONTAL_OUTPUT_SIZE, + sensor->mode.h_output_size, &ret); + cci_write(sensor->regmap, OV2680_REG_VERTICAL_OUTPUT_SIZE, + sensor->mode.v_output_size, &ret); + cci_write(sensor->regmap, OV2680_REG_TIMING_HTS, + sensor->mode.hts, &ret); + cci_write(sensor->regmap, OV2680_REG_TIMING_VTS, + sensor->mode.vts, &ret); + cci_write(sensor->regmap, OV2680_REG_ISP_X_WIN, 0, &ret); + cci_write(sensor->regmap, OV2680_REG_ISP_Y_WIN, 0, &ret); + cci_write(sensor->regmap, OV2680_REG_X_INC, inc, &ret); + cci_write(sensor->regmap, OV2680_REG_Y_INC, inc, &ret); + cci_write(sensor->regmap, OV2680_REG_X_WIN, + sensor->mode.h_output_size, &ret); + cci_write(sensor->regmap, OV2680_REG_Y_WIN, + sensor->mode.v_output_size, &ret); + cci_write(sensor->regmap, OV2680_REG_FORMAT1, fmt1, &ret); + cci_write(sensor->regmap, OV2680_REG_FORMAT2, fmt2, &ret); - return 0; + return ret; } static int ov2680_set_fmt(struct v4l2_subdev *sd, @@ -478,35 +460,26 @@ static int ov2680_init_cfg(struct v4l2_subdev *sd, return ov2680_set_fmt(sd, sd_state, &fmt); } -static int ov2680_detect(struct i2c_client *client) +static int ov2680_detect(struct ov2680_dev *sensor) { - struct i2c_adapter *adapter = client->adapter; - u32 high = 0, low = 0; - int ret; - u16 id; - u8 revision; - - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) - return -ENODEV; + u64 chip_id, rev; + int ret = 0; - ret = ov_read_reg8(client, OV2680_SC_CMMN_CHIP_ID_H, &high); - if (ret) { - dev_err(&client->dev, "sensor_id_high read failed (%d)\n", ret); + cci_read(sensor->regmap, OV2680_REG_CHIP_ID, &chip_id, &ret); + cci_read(sensor->regmap, OV2680_REG_SC_CMMN_SUB_ID, &rev, &ret); + if (ret < 0) { + dev_err(sensor->dev, "failed to read chip id\n"); return -ENODEV; } - ret = ov_read_reg8(client, OV2680_SC_CMMN_CHIP_ID_L, &low); - id = ((((u16)high) << 8) | (u16)low); - if (id != OV2680_ID) { - dev_err(&client->dev, "sensor ID error 0x%x\n", id); + if (chip_id != OV2680_CHIP_ID) { + dev_err(sensor->dev, "chip id: 0x%04llx does not match expected 0x%04x\n", + chip_id, OV2680_CHIP_ID); return -ENODEV; } - ret = ov_read_reg8(client, OV2680_SC_CMMN_SUB_ID, &high); - revision = (u8)high & 0x0f; - - dev_info(&client->dev, "sensor_revision id = 0x%x, rev= %d\n", - id, revision); + dev_info(sensor->dev, "sensor_revision id = 0x%llx, rev= %lld\n", + chip_id, rev & 0x0f); return 0; } @@ -538,11 +511,12 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) if (ret) goto error_power_down; - ret = ov_write_reg8(client, OV2680_SW_STREAM, OV2680_START_STREAMING); + ret = cci_write(sensor->regmap, OV2680_REG_STREAM_CTRL, 1, + NULL); if (ret) goto error_power_down; } else { - ov_write_reg8(client, OV2680_SW_STREAM, OV2680_STOP_STREAMING); + cci_write(sensor->regmap, OV2680_REG_STREAM_CTRL, 0, NULL); pm_runtime_put(sensor->sd.dev); } @@ -563,6 +537,7 @@ error_unlock: static int ov2680_s_config(struct v4l2_subdev *sd) { + struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; @@ -573,7 +548,7 @@ static int ov2680_s_config(struct v4l2_subdev *sd) } /* config & detect sensor */ - ret = ov2680_detect(client); + ret = ov2680_detect(sensor); if (ret) dev_err(&client->dev, "ov2680_detect err s_config.\n"); @@ -586,7 +561,7 @@ static int ov2680_g_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *interval) { interval->interval.numerator = 1; - interval->interval.denominator = OV2680_FPS; + interval->interval.denominator = OV2680_FRAME_RATE; return 0; } @@ -638,7 +613,7 @@ static int ov2680_enum_frame_interval(struct v4l2_subdev *sd, return -EINVAL; fie->interval.numerator = 1; - fie->interval.denominator = OV2680_FPS; + fie->interval.denominator = OV2680_FRAME_RATE; return 0; } @@ -738,9 +713,13 @@ static int ov2680_probe(struct i2c_client *client) if (!sensor) return -ENOMEM; + sensor->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(sensor->regmap)) + return PTR_ERR(sensor->regmap); + mutex_init(&sensor->lock); - sensor->client = client; + sensor->dev = &client->dev; v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_ops); /* diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index d032af245674..7815522724f7 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -44,75 +45,12 @@ /* 1704 * 1294 * 30fps = 66MHz pixel clock */ #define OV2680_PIXELS_PER_LINE 1704 #define OV2680_LINES_PER_FRAME 1294 -#define OV2680_FPS 30 + #define OV2680_SKIP_FRAMES 3 /* If possible send 16 extra rows / lines to the ISP as padding */ #define OV2680_END_MARGIN 16 -#define OV2680_FOCAL_LENGTH_NUM 334 /*3.34mm*/ - -#define OV2680_INTEGRATION_TIME_MARGIN 8 -#define OV2680_ID 0x2680 - -/* - * OV2680 System control registers - */ -#define OV2680_SW_SLEEP 0x0100 -#define OV2680_SW_RESET 0x0103 -#define OV2680_SW_STREAM 0x0100 - -#define OV2680_SC_CMMN_CHIP_ID_H 0x300A -#define OV2680_SC_CMMN_CHIP_ID_L 0x300B -#define OV2680_SC_CMMN_SCCB_ID 0x302B /* 0x300C*/ -#define OV2680_SC_CMMN_SUB_ID 0x302A /* process, version*/ - -#define OV2680_GROUP_ACCESS 0x3208 /*Bit[7:4] Group control, Bit[3:0] Group ID*/ - -#define OV2680_REG_EXPOSURE_PK_HIGH 0x3500 -#define OV2680_REG_GAIN_PK 0x350a - -#define OV2680_REG_SENSOR_CTRL_0A 0x370a - -#define OV2680_HORIZONTAL_START_H 0x3800 /* Bit[11:8] */ -#define OV2680_HORIZONTAL_START_L 0x3801 /* Bit[7:0] */ -#define OV2680_VERTICAL_START_H 0x3802 /* Bit[11:8] */ -#define OV2680_VERTICAL_START_L 0x3803 /* Bit[7:0] */ -#define OV2680_HORIZONTAL_END_H 0x3804 /* Bit[11:8] */ -#define OV2680_HORIZONTAL_END_L 0x3805 /* Bit[7:0] */ -#define OV2680_VERTICAL_END_H 0x3806 /* Bit[11:8] */ -#define OV2680_VERTICAL_END_L 0x3807 /* Bit[7:0] */ -#define OV2680_HORIZONTAL_OUTPUT_SIZE_H 0x3808 /* Bit[11:8] */ -#define OV2680_HORIZONTAL_OUTPUT_SIZE_L 0x3809 /* Bit[7:0] */ -#define OV2680_VERTICAL_OUTPUT_SIZE_H 0x380a /* Bit[11:8] */ -#define OV2680_VERTICAL_OUTPUT_SIZE_L 0x380b /* Bit[7:0] */ -#define OV2680_HTS 0x380c -#define OV2680_VTS 0x380e -#define OV2680_ISP_X_WIN 0x3810 -#define OV2680_ISP_Y_WIN 0x3812 -#define OV2680_X_INC 0x3814 -#define OV2680_Y_INC 0x3815 - -#define OV2680_FRAME_OFF_NUM 0x4202 - -/*Flip/Mirror*/ -#define OV2680_REG_FORMAT1 0x3820 -#define OV2680_REG_FORMAT2 0x3821 - -#define OV2680_MWB_RED_GAIN_H 0x5004/*0x3400*/ -#define OV2680_MWB_GREEN_GAIN_H 0x5006/*0x3402*/ -#define OV2680_MWB_BLUE_GAIN_H 0x5008/*0x3404*/ -#define OV2680_MWB_GAIN_MAX 0x0fff - -#define OV2680_REG_ISP_CTRL00 0x5080 - -#define OV2680_X_WIN 0x5704 -#define OV2680_Y_WIN 0x5706 -#define OV2680_WIN_CONTROL 0x5708 - -#define OV2680_START_STREAMING 0x01 -#define OV2680_STOP_STREAMING 0x00 - /* * ov2680 device structure. */ @@ -121,7 +59,8 @@ struct ov2680_dev { struct media_pad pad; /* Protect against concurrent changes to controls */ struct mutex lock; - struct i2c_client *client; + struct device *dev; + struct regmap *regmap; struct gpio_desc *powerdown; struct fwnode_handle *ep_fwnode; bool is_streaming; @@ -150,19 +89,6 @@ struct ov2680_dev { } ctrls; }; -/** - * struct ov2680_reg - MI sensor register format - * @type: type of the register - * @reg: 16-bit offset to register - * @val: 8/16/32-bit register value - * - * Define a structure for sensor register initialization values - */ -struct ov2680_reg { - u16 reg; - u32 val; /* @set value for read/mod/write, @mask */ -}; - #define to_ov2680_sensor(x) container_of(x, struct ov2680_dev, sd) static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) @@ -173,7 +99,7 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) return &sensor->sd; } -static struct ov2680_reg const ov2680_global_setting[] = { +static const struct reg_sequence ov2680_global_setting[] = { /* MIPI PHY, 0x10 -> 0x1c enable bp_c_hs_en_lat and bp_d_hs_en_lat */ {0x3016, 0x1c}, @@ -242,8 +168,6 @@ static struct ov2680_reg const ov2680_global_setting[] = { /* DPC THRE RATIO 0x04 (4) -> 0x00 (0) */ {0x5792, 0x00}, - - {} }; #endif -- cgit v1.2.3 From f04eedb9424b8359fa788ce6b01ac3b90eedbea2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 5 Jul 2023 23:30:08 +0200 Subject: media: atomisp: csi2-bridge: Switch to new common ipu_bridge_init() Remove the duplicate IPU ACPI bridge code and use the new shared ipu_bridge_init() functionality. Note this will also use / assume v4l2-async device instantiation for ov5693 sensors on atomisp devices since ipu_supported_sensors[] already contains a match for this. This is fine since recent atomisp improvements allow the atomisp code to work with generic v4l2 sensor drivers and using an unmodified drivers/media/i2c/ov5693.c has been successfully tested on an Acer Iconia W4 820 tablet with an ISP2400 + OV5693 sensor. Reviewed-by: Andy Shevchenko Reviewed-by: Daniel Scally Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/Kconfig | 3 + drivers/staging/media/atomisp/pci/atomisp_csi2.h | 67 ----- .../media/atomisp/pci/atomisp_csi2_bridge.c | 333 ++++----------------- drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 1 + 4 files changed, 63 insertions(+), 341 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/Kconfig b/drivers/staging/media/atomisp/Kconfig index e9b168ba97bf..5d8917160d41 100644 --- a/drivers/staging/media/atomisp/Kconfig +++ b/drivers/staging/media/atomisp/Kconfig @@ -12,9 +12,12 @@ menuconfig INTEL_ATOMISP config VIDEO_ATOMISP tristate "Intel Atom Image Signal Processor Driver" depends on VIDEO_DEV && INTEL_ATOMISP + depends on MEDIA_PCI_SUPPORT depends on PMIC_OPREGION + depends on I2C select V4L2_FWNODE select IOSF_MBI + select IPU_BRIDGE select VIDEOBUF2_VMALLOC select VIDEO_V4L2_SUBDEV_API help diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h b/drivers/staging/media/atomisp/pci/atomisp_csi2.h index 16ddb3ab2963..8a112acba1e0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h @@ -30,9 +30,6 @@ #define CSI2_PAD_SOURCE 1 #define CSI2_PADS_NUM 2 -#define CSI2_MAX_LANES 4 -#define CSI2_MAX_LINK_FREQS 3 - #define CSI2_MAX_ACPI_GPIOS 2u struct acpi_device; @@ -55,70 +52,6 @@ struct atomisp_csi2_acpi_gpio_parsing_data { unsigned int map_count; }; -enum atomisp_csi2_sensor_swnodes { - SWNODE_SENSOR, - SWNODE_SENSOR_PORT, - SWNODE_SENSOR_ENDPOINT, - SWNODE_CSI2_PORT, - SWNODE_CSI2_ENDPOINT, - SWNODE_COUNT -}; - -struct atomisp_csi2_property_names { - char clock_frequency[16]; - char rotation[9]; - char bus_type[9]; - char data_lanes[11]; - char remote_endpoint[16]; - char link_frequencies[17]; -}; - -struct atomisp_csi2_node_names { - char port[7]; - char endpoint[11]; - char remote_port[7]; -}; - -struct atomisp_csi2_sensor_config { - const char *hid; - int lanes; - int nr_link_freqs; - u64 link_freqs[CSI2_MAX_LINK_FREQS]; -}; - -struct atomisp_csi2_sensor { - /* Append port in "-%u" format as suffix of HID */ - char name[ACPI_ID_LEN + 4]; - struct acpi_device *adev; - int port; - int lanes; - - /* SWNODE_COUNT + 1 for terminating NULL */ - const struct software_node *group[SWNODE_COUNT + 1]; - struct software_node swnodes[SWNODE_COUNT]; - struct atomisp_csi2_node_names node_names; - struct atomisp_csi2_property_names prop_names; - /* "clock-frequency", "rotation" + terminating entry */ - struct property_entry dev_properties[3]; - /* "bus-type", "data-lanes", "remote-endpoint" + "link-freq" + terminating entry */ - struct property_entry ep_properties[5]; - /* "data-lanes", "remote-endpoint" + terminating entry */ - struct property_entry csi2_properties[3]; - struct software_node_ref_args local_ref[1]; - struct software_node_ref_args remote_ref[1]; - struct software_node_ref_args vcm_ref[1]; - /* GPIO mappings storage */ - struct atomisp_csi2_acpi_gpio_map gpio_map; -}; - -struct atomisp_csi2_bridge { - struct software_node csi2_node; - char csi2_node_name[14]; - u32 data_lanes[CSI2_MAX_LANES]; - unsigned int n_sensors; - struct atomisp_csi2_sensor sensors[ATOMISP_CAMERA_NR_PORTS]; -}; - struct atomisp_mipi_csi2_device { struct v4l2_subdev subdev; struct media_pad pads[CSI2_PADS_NUM]; diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index 46d9f31986c9..df625ac2c779 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -14,31 +14,14 @@ #include #include #include + +#include #include #include "atomisp_cmd.h" #include "atomisp_csi2.h" #include "atomisp_internal.h" -#define NODE_SENSOR(_HID, _PROPS) \ - ((const struct software_node) { \ - .name = _HID, \ - .properties = _PROPS, \ - }) - -#define NODE_PORT(_PORT, _SENSOR_NODE) \ - ((const struct software_node) { \ - .name = _PORT, \ - .parent = _SENSOR_NODE, \ - }) - -#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ - ((const struct software_node) { \ - .name = _EP, \ - .parent = _PORT, \ - .properties = _PROPS, \ - }) - #define PMC_CLK_RATE_19_2MHZ 19200000 /* @@ -83,21 +66,18 @@ static const guid_t atomisp_dsm_guid = GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d, 0x97, 0xb9, 0x88, 0x2a, 0x68, 0x60, 0xa4, 0xbe); -/* - * Extend this array with ACPI Hardware IDs of sensors known to be working - * plus the default number of links + link-frequencies. - * - * Do not add an entry for a sensor that is not actually supported, - * or which have not yet been converted to work without atomisp_gmin - * power-management and with v4l2-async probing. - */ -static const struct atomisp_csi2_sensor_config supported_sensors[] = { - /* GalaxyCore GC0310 */ - { "INT0310", 1 }, - /* Omnivision OV2680 */ - { "OVTI2680", 1 }, +struct atomisp_sensor_config { + int lanes; }; +#define ATOMISP_SENSOR_CONFIG(_HID, _LANES) \ +{ \ + .id = _HID, \ + .driver_data = (long)&((const struct atomisp_sensor_config) { \ + .lanes = _LANES, \ + }) \ +} + /* * gmin_cfg parsing code. This is a cleaned up version of the gmin_cfg parsing * code from atomisp_gmin_platform.c. @@ -400,8 +380,7 @@ static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_ * the INT3472 discrete.c code and there is some overlap, but there are * enough differences that it is difficult to share the code. */ -static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, - struct acpi_device *adev) +static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) { struct atomisp_csi2_acpi_gpio_parsing_data data = { }; LIST_HEAD(resource_list); @@ -469,9 +448,12 @@ static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, } } + data.map = kzalloc(sizeof(*data.map), GFP_KERNEL); + if (!data.map) + return -ENOMEM; + /* Now parse the ACPI resources and build the lookup table */ data.adev = adev; - data.map = &sensor->gpio_map; ret = acpi_dev_get_resources(adev, &resource_list, atomisp_csi2_handle_acpi_gpio_res, &data); if (ret < 0) @@ -491,220 +473,68 @@ static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, return ret; } -static const struct atomisp_csi2_property_names prop_names = { - .clock_frequency = "clock-frequency", - .rotation = "rotation", - .bus_type = "bus-type", - .data_lanes = "data-lanes", - .remote_endpoint = "remote-endpoint", - .link_frequencies = "link-frequencies", +static const struct acpi_device_id atomisp_sensor_configs[] = { + ATOMISP_SENSOR_CONFIG("INT33BE", 2), /* OV5693 */ + {} }; -static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *sensor, - struct atomisp_csi2_bridge *bridge, - const struct atomisp_csi2_sensor_config *cfg) -{ - sensor->prop_names = prop_names; - - sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CSI2_ENDPOINT]); - sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]); - - sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency, - PMC_CLK_RATE_19_2MHZ); - sensor->dev_properties[1] = PROPERTY_ENTRY_U32(sensor->prop_names.rotation, 0); - - sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, - V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); - sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->lanes); - sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, - sensor->local_ref); - if (cfg->nr_link_freqs > 0) - sensor->ep_properties[3] = - PROPERTY_ENTRY_U64_ARRAY_LEN(sensor->prop_names.link_frequencies, - cfg->link_freqs, cfg->nr_link_freqs); - - sensor->csi2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->lanes); - sensor->csi2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, - sensor->remote_ref); -} - -static void atomisp_csi2_init_swnode_names(struct atomisp_csi2_sensor *sensor) -{ - snprintf(sensor->node_names.remote_port, - sizeof(sensor->node_names.remote_port), - SWNODE_GRAPH_PORT_NAME_FMT, sensor->port); - snprintf(sensor->node_names.port, - sizeof(sensor->node_names.port), - SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */ - snprintf(sensor->node_names.endpoint, - sizeof(sensor->node_names.endpoint), - SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ -} - -static void atomisp_csi2_init_swnode_group(struct atomisp_csi2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - - sensor->group[SWNODE_SENSOR] = &nodes[SWNODE_SENSOR]; - sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; - sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; - sensor->group[SWNODE_CSI2_PORT] = &nodes[SWNODE_CSI2_PORT]; - sensor->group[SWNODE_CSI2_ENDPOINT] = &nodes[SWNODE_CSI2_ENDPOINT]; -} - -static void atomisp_csi2_create_connection_swnodes(struct atomisp_csi2_bridge *bridge, - struct atomisp_csi2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - - atomisp_csi2_init_swnode_names(sensor); - - nodes[SWNODE_SENSOR] = NODE_SENSOR(sensor->name, - sensor->dev_properties); - nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port, - &nodes[SWNODE_SENSOR]); - nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, - &nodes[SWNODE_SENSOR_PORT], - sensor->ep_properties); - nodes[SWNODE_CSI2_PORT] = NODE_PORT(sensor->node_names.remote_port, - &bridge->csi2_node); - nodes[SWNODE_CSI2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, - &nodes[SWNODE_CSI2_PORT], - sensor->csi2_properties); - - atomisp_csi2_init_swnode_group(sensor); -} - -static void atomisp_csi2_unregister_sensors(struct atomisp_csi2_bridge *bridge) +static int atomisp_csi2_parse_sensor_fwnode(struct acpi_device *adev, + struct ipu_sensor *sensor) { - struct atomisp_csi2_sensor *sensor; - unsigned int i; - - for (i = 0; i < bridge->n_sensors; i++) { - sensor = &bridge->sensors[i]; - software_node_unregister_node_group(sensor->group); - acpi_dev_remove_driver_gpios(sensor->adev); - acpi_dev_put(sensor->adev); - } -} - -static int atomisp_csi2_connect_sensor(const struct atomisp_csi2_sensor_config *cfg, - struct atomisp_csi2_bridge *bridge, - struct atomisp_device *isp) -{ - struct fwnode_handle *fwnode, *primary; - struct atomisp_csi2_sensor *sensor; - struct acpi_device *adev; + const struct acpi_device_id *id; int ret, clock_num; + int lanes = 1; - for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) - continue; - - if (bridge->n_sensors >= ATOMISP_CAMERA_NR_PORTS) { - dev_err(isp->dev, "Exceeded available CSI2 ports\n"); - ret = -EOVERFLOW; - goto err_put_adev; - } - - sensor = &bridge->sensors[bridge->n_sensors]; - - /* - * ACPI takes care of turning the PMC clock on and off, but on BYT - * the clock defaults to 25 MHz instead of the expected 19.2 MHz. - * Get the PMC-clock number from ACPI _PR0 method and set it to 19.2 MHz. - * The PMC-clock number is also used to determine the default CSI port. - */ - clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); - - ret = atomisp_csi2_set_pmc_clk_freq(adev, clock_num); - if (ret) - goto err_put_adev; - - sensor->port = atomisp_csi2_get_port(adev, clock_num); - if (sensor->port >= ATOMISP_CAMERA_NR_PORTS) { - acpi_handle_err(adev->handle, "Invalid port: %d\n", sensor->port); - ret = -EINVAL; - goto err_put_adev; - } - - sensor->lanes = gmin_cfg_get_int(adev, "CsiLanes", cfg->lanes); - if (sensor->lanes > CSI2_MAX_LANES) { - acpi_handle_err(adev->handle, "Invalid number of lanes: %d\n", sensor->lanes); - ret = -EINVAL; - goto err_put_adev; - } + id = acpi_match_acpi_device(atomisp_sensor_configs, adev); + if (id) { + struct atomisp_sensor_config *cfg = + (struct atomisp_sensor_config *)id->driver_data; - ret = atomisp_csi2_add_gpio_mappings(sensor, adev); - if (ret) - goto err_put_adev; - - snprintf(sensor->name, sizeof(sensor->name), "%s-%u", - cfg->hid, sensor->port); - - atomisp_csi2_create_fwnode_properties(sensor, bridge, cfg); - atomisp_csi2_create_connection_swnodes(bridge, sensor); - - ret = software_node_register_node_group(sensor->group); - if (ret) - goto err_remove_mappings; - - fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR]); - if (!fwnode) { - ret = -ENODEV; - goto err_free_swnodes; - } + lanes = cfg->lanes; + } - sensor->adev = acpi_dev_get(adev); + /* + * ACPI takes care of turning the PMC clock on and off, but on BYT + * the clock defaults to 25 MHz instead of the expected 19.2 MHz. + * Get the PMC-clock number from ACPI PR0 method and set it to 19.2 MHz. + * The PMC-clock number is also used to determine the default CSI port. + */ + clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); - primary = acpi_fwnode_handle(adev); - primary->secondary = fwnode; + ret = atomisp_csi2_set_pmc_clk_freq(adev, clock_num); + if (ret) + return ret; - bridge->n_sensors++; + sensor->link = atomisp_csi2_get_port(adev, clock_num); + if (sensor->link >= ATOMISP_CAMERA_NR_PORTS) { + acpi_handle_err(adev->handle, "%s: Invalid port: %u\n", + dev_name(&adev->dev), sensor->link); + return -EINVAL; } - return 0; - -err_free_swnodes: - software_node_unregister_node_group(sensor->group); -err_remove_mappings: - acpi_dev_remove_driver_gpios(adev); -err_put_adev: - acpi_dev_put(adev); - return ret; -} - -static int atomisp_csi2_connect_sensors(struct atomisp_csi2_bridge *bridge, - struct atomisp_device *isp) -{ - unsigned int i; - int ret; + sensor->lanes = gmin_cfg_get_int(adev, "CsiLanes", lanes); + if (sensor->lanes > IPU_MAX_LANES) { + acpi_handle_err(adev->handle, "%s: Invalid lane-count: %d\n", + dev_name(&adev->dev), sensor->lanes); + return -EINVAL; + } - for (i = 0; i < ARRAY_SIZE(supported_sensors); i++) { - const struct atomisp_csi2_sensor_config *cfg = &supported_sensors[i]; + ret = atomisp_csi2_add_gpio_mappings(adev); + if (ret) + return ret; - ret = atomisp_csi2_connect_sensor(cfg, bridge, isp); - if (ret) - goto err_unregister_sensors; - } + sensor->mclkspeed = PMC_CLK_RATE_19_2MHZ; + sensor->rotation = 0; + sensor->orientation = (sensor->link == 1) ? + V4L2_FWNODE_ORIENTATION_BACK : V4L2_FWNODE_ORIENTATION_FRONT; return 0; - -err_unregister_sensors: - atomisp_csi2_unregister_sensors(bridge); - return ret; } int atomisp_csi2_bridge_init(struct atomisp_device *isp) { - struct atomisp_csi2_bridge *bridge; struct device *dev = isp->dev; struct fwnode_handle *fwnode; - int i, ret; /* * This function is intended to run only once and then leave @@ -716,52 +546,7 @@ int atomisp_csi2_bridge_init(struct atomisp_device *isp) if (fwnode && fwnode->secondary) return 0; - bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); - if (!bridge) - return -ENOMEM; - - strscpy(bridge->csi2_node_name, "atomisp-csi2", sizeof(bridge->csi2_node_name)); - bridge->csi2_node.name = bridge->csi2_node_name; - - ret = software_node_register(&bridge->csi2_node); - if (ret < 0) { - dev_err(dev, "Failed to register the CSI2 HID node\n"); - goto err_free_bridge; - } - - /* - * Map the lane arrangement, which is fixed for the ISP2 (meaning we - * only need one, rather than one per sensor). We include it as a - * member of the bridge struct rather than a global variable so - * that it survives if the module is unloaded along with the rest of - * the struct. - */ - for (i = 0; i < CSI2_MAX_LANES; i++) - bridge->data_lanes[i] = i + 1; - - ret = atomisp_csi2_connect_sensors(bridge, isp); - if (ret || bridge->n_sensors == 0) - goto err_unregister_csi2; - - fwnode = software_node_fwnode(&bridge->csi2_node); - if (!fwnode) { - dev_err(dev, "Error getting fwnode from csi2 software_node\n"); - ret = -ENODEV; - goto err_unregister_sensors; - } - - set_secondary_fwnode(dev, fwnode); - - return 0; - -err_unregister_sensors: - atomisp_csi2_unregister_sensors(bridge); -err_unregister_csi2: - software_node_unregister(&bridge->csi2_node); -err_free_bridge: - kfree(bridge); - - return ret; + return ipu_bridge_init(dev, atomisp_csi2_parse_sensor_fwnode); } /******* V4L2 sub-device asynchronous registration callbacks***********/ diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 21233e68b1e1..0d0329f5e4ad 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1615,3 +1615,4 @@ MODULE_AUTHOR("Wen Wang "); MODULE_AUTHOR("Xiaolin Zhang "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Intel ATOM Platform ISP Driver"); +MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); -- cgit v1.2.3 From fc0f5b59adf5170f0f4c2dc20c13f558e2baf64a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 5 Jul 2023 23:30:09 +0200 Subject: media: atomisp: csi2-bridge: Add dev_name() to acpi_handle_info() logging acpi_handle_info() uses the ACPI path to the handle as prefix for messages e.g. : "\_SB_.I2C2.CAM8". This makes it hard for users to figure out which csi2-bridge messages belong to which sensor since the actual sensor drivers uses the ACPI device name (typically "HID:00") for logging. Extend the acpi_handle_info() (and err and warn) logging to also log the device name to make it easier to match csi2-bridge messages with sensor driver log messages. Suggested-by: Sakari Ailus Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_csi2_bridge.c | 51 ++++++++++++++-------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index df625ac2c779..e362cc9ba985 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -131,7 +131,8 @@ static char *gmin_cfg_get_dsm(struct acpi_device *adev, const char *key) if (!val) break; - acpi_handle_info(adev->handle, "Using DSM entry %s=%s\n", key, val); + acpi_handle_info(adev->handle, "%s: Using DSM entry %s=%s\n", + dev_name(&adev->dev), key, val); break; } } @@ -156,7 +157,8 @@ static char *gmin_cfg_get_dmi_override(struct acpi_device *adev, const char *key if (strcmp(key, gv->key)) continue; - acpi_handle_info(adev->handle, "Using DMI entry %s=%s\n", key, gv->val); + acpi_handle_info(adev->handle, "%s: Using DMI entry %s=%s\n", + dev_name(&adev->dev), key, gv->val); return kstrdup(gv->val, GFP_KERNEL); } @@ -192,7 +194,8 @@ static int gmin_cfg_get_int(struct acpi_device *adev, const char *key, int defau return int_val; out_use_default: - acpi_handle_info(adev->handle, "Using default %s=%d\n", key, default_val); + acpi_handle_info(adev->handle, "%s: Using default %s=%d\n", + dev_name(&adev->dev), key, default_val); return default_val; } @@ -235,7 +238,8 @@ static int atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(struct acpi_device *adev) ACPI_FREE(buffer.pointer); if (ret < 0) - acpi_handle_warn(adev->handle, "Could not find PMC clk in _PR0\n"); + acpi_handle_warn(adev->handle, "%s: Could not find PMC clk in _PR0\n", + dev_name(&adev->dev)); return ret; } @@ -254,7 +258,8 @@ static int atomisp_csi2_set_pmc_clk_freq(struct acpi_device *adev, int clock_num clk = clk_get(NULL, name); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - acpi_handle_err(adev->handle, "Error getting clk %s:%d\n", name, ret); + acpi_handle_err(adev->handle, "%s: Error getting clk %s: %d\n", + dev_name(&adev->dev), name, ret); return ret; } @@ -268,7 +273,8 @@ static int atomisp_csi2_set_pmc_clk_freq(struct acpi_device *adev, int clock_num if (!ret) ret = clk_set_rate(clk, PMC_CLK_RATE_19_2MHZ); if (ret) - acpi_handle_err(adev->handle, "Error setting clk-rate for %s:%d\n", name, ret); + acpi_handle_err(adev->handle, "%s: Error setting clk-rate for %s: %d\n", + dev_name(&adev->dev), name, ret); clk_put(clk); return ret; @@ -317,7 +323,8 @@ static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_ if (i == data->settings_count) { acpi_handle_warn(data->adev->handle, - "Could not find DSM GPIO settings for pin %u\n", pin); + "%s: Could not find DSM GPIO settings for pin %u\n", + dev_name(&data->adev->dev), pin); return 1; } @@ -329,7 +336,8 @@ static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_ name = "powerdown-gpios"; break; default: - acpi_handle_warn(data->adev->handle, "Unknown GPIO type 0x%02lx for pin %u\n", + acpi_handle_warn(data->adev->handle, "%s: Unknown GPIO type 0x%02lx for pin %u\n", + dev_name(&data->adev->dev), INTEL_GPIO_DSM_TYPE(settings), pin); return 1; } @@ -354,7 +362,8 @@ static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_ data->map->mapping[i].size = 1; data->map_count++; - acpi_handle_info(data->adev->handle, "%s crs %d %s pin %u active-%s\n", name, + acpi_handle_info(data->adev->handle, "%s: %s crs %d %s pin %u active-%s\n", + dev_name(&data->adev->dev), name, data->res_count - 1, agpio->resource_source.string_ptr, pin, active_low ? "low" : "high"); @@ -391,7 +400,8 @@ static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid, 0x00, 1, NULL, ACPI_TYPE_STRING); if (obj) { - acpi_handle_info(adev->handle, "Sensor module id: '%s'\n", obj->string.pointer); + acpi_handle_info(adev->handle, "%s: Sensor module id: '%s'\n", + dev_name(&adev->dev), obj->string.pointer); ACPI_FREE(obj); } @@ -405,7 +415,8 @@ static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) &intel_sensor_gpio_info_guid, 0x00, 1, NULL, ACPI_TYPE_INTEGER); if (!obj) { - acpi_handle_err(adev->handle, "No _DSM entry for GPIO pin count\n"); + acpi_handle_err(adev->handle, "%s: No _DSM entry for GPIO pin count\n", + dev_name(&adev->dev)); return -EIO; } @@ -413,7 +424,9 @@ static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) ACPI_FREE(obj); if (data.settings_count > CSI2_MAX_ACPI_GPIOS) { - acpi_handle_err(adev->handle, "Too many GPIOs %u > %u\n", data.settings_count, CSI2_MAX_ACPI_GPIOS); + acpi_handle_err(adev->handle, "%s: Too many GPIOs %u > %u\n", + dev_name(&adev->dev), data.settings_count, + CSI2_MAX_ACPI_GPIOS); return -EOVERFLOW; } @@ -427,7 +440,8 @@ static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) 0x00, i + 2, NULL, ACPI_TYPE_INTEGER); if (!obj) { - acpi_handle_err(adev->handle, "No _DSM entry for pin %u\n", i); + acpi_handle_err(adev->handle, "%s: No _DSM entry for pin %u\n", + dev_name(&adev->dev), i); return -EIO; } @@ -442,7 +456,8 @@ static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) INTEL_GPIO_DSM_PIN(data.settings[j])) continue; - acpi_handle_err(adev->handle, "Duplicate pin number %lu\n", + acpi_handle_err(adev->handle, "%s: Duplicate pin number %lu\n", + dev_name(&adev->dev), INTEL_GPIO_DSM_PIN(data.settings[i])); return -EIO; } @@ -463,12 +478,14 @@ static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) if (data.map_count != data.settings_count || data.res_count != data.settings_count) - acpi_handle_warn(adev->handle, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n", - data.settings_count, data.res_count, data.map_count); + acpi_handle_warn(adev->handle, "%s: ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n", + dev_name(&adev->dev), data.settings_count, + data.res_count, data.map_count); ret = acpi_dev_add_driver_gpios(adev, data.map->mapping); if (ret) - acpi_handle_err(adev->handle, "Error adding driver GPIOs: %d\n", ret); + acpi_handle_err(adev->handle, "%s: Error adding driver GPIOs: %d\n", + dev_name(&adev->dev), ret); return ret; } -- cgit v1.2.3 From f663fb4967b0e428f80f7850090ed3ba3bff0e3b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 5 Jul 2023 23:30:10 +0200 Subject: media: atomisp: csi2-bridge: Add support for VCM I2C-client instantiation Fill sensor->vcm_type and call intel_cio2_bridge_instantiate_vcm() from the v4l2-async bound op so that an I2C-client will be instatiated for the VCM. Note unfortunately on atomisp the _DSM to get the VCM type sometimes returns a VCM even though there is none. Since VCMs are typically only used together with certain sensors, work around this by adding a vcm field to atomisp_sensor_config and only check for a VCM when that is set. Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_csi2_bridge.c | 44 +++++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index e362cc9ba985..03940c11505f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -66,15 +66,25 @@ static const guid_t atomisp_dsm_guid = GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d, 0x97, 0xb9, 0x88, 0x2a, 0x68, 0x60, 0xa4, 0xbe); +/* + * 75c9a639-5c8a-4a00-9f48-a9c3b5da789f + * This _DSM GUID returns a string giving the VCM type e.g. "AD5823". + */ +static const guid_t vcm_dsm_guid = + GUID_INIT(0x75c9a639, 0x5c8a, 0x4a00, + 0x9f, 0x48, 0xa9, 0xc3, 0xb5, 0xda, 0x78, 0x9f); + struct atomisp_sensor_config { int lanes; + bool vcm; }; -#define ATOMISP_SENSOR_CONFIG(_HID, _LANES) \ +#define ATOMISP_SENSOR_CONFIG(_HID, _LANES, _VCM) \ { \ .id = _HID, \ .driver_data = (long)&((const struct atomisp_sensor_config) { \ .lanes = _LANES, \ + .vcm = _VCM, \ }) \ } @@ -490,8 +500,28 @@ static int atomisp_csi2_add_gpio_mappings(struct acpi_device *adev) return ret; } +static char *atomisp_csi2_get_vcm_type(struct acpi_device *adev) +{ + union acpi_object *obj; + char *vcm_type; + + obj = acpi_evaluate_dsm_typed(adev->handle, &vcm_dsm_guid, 0, 0, + NULL, ACPI_TYPE_STRING); + if (!obj) + return NULL; + + vcm_type = kstrdup(obj->string.pointer, GFP_KERNEL); + ACPI_FREE(obj); + + if (!vcm_type) + return NULL; + + string_lower(vcm_type, vcm_type); + return vcm_type; +} + static const struct acpi_device_id atomisp_sensor_configs[] = { - ATOMISP_SENSOR_CONFIG("INT33BE", 2), /* OV5693 */ + ATOMISP_SENSOR_CONFIG("INT33BE", 2, true), /* OV5693 */ {} }; @@ -500,6 +530,7 @@ static int atomisp_csi2_parse_sensor_fwnode(struct acpi_device *adev, { const struct acpi_device_id *id; int ret, clock_num; + bool vcm = false; int lanes = 1; id = acpi_match_acpi_device(atomisp_sensor_configs, adev); @@ -508,6 +539,7 @@ static int atomisp_csi2_parse_sensor_fwnode(struct acpi_device *adev, (struct atomisp_sensor_config *)id->driver_data; lanes = cfg->lanes; + vcm = cfg->vcm; } /* @@ -545,6 +577,9 @@ static int atomisp_csi2_parse_sensor_fwnode(struct acpi_device *adev, sensor->orientation = (sensor->link == 1) ? V4L2_FWNODE_ORIENTATION_BACK : V4L2_FWNODE_ORIENTATION_FRONT; + if (vcm) + sensor->vcm_type = atomisp_csi2_get_vcm_type(adev); + return 0; } @@ -583,6 +618,7 @@ static int atomisp_notifier_bound(struct v4l2_async_notifier *notifier, { struct atomisp_device *isp = notifier_to_atomisp(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); + int ret; if (s_asd->port >= ATOMISP_CAMERA_NR_PORTS) { dev_err(isp->dev, "port %d not supported\n", s_asd->port); @@ -594,6 +630,10 @@ static int atomisp_notifier_bound(struct v4l2_async_notifier *notifier, return -EBUSY; } + ret = ipu_bridge_instantiate_vcm(sd->dev); + if (ret) + return ret; + isp->sensor_subdevs[s_asd->port] = sd; return 0; } -- cgit v1.2.3 From b8e277b1dbe66262615c57f2eb2ecdd5d1bd9054 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 3 Aug 2023 11:33:47 +0200 Subject: media: atomisp: Drop atomisp-ov2680 sensor driver After recent improvements to atomisp and the standard ov2680 sensor driver, the atomisp driver now works fine with the standard ov2680 driver. Drop the no longer necessary atomisp specific atomisp-ov2680 sensor driver. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/Kconfig | 13 - drivers/staging/media/atomisp/i2c/Makefile | 1 - drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 828 --------------------- drivers/staging/media/atomisp/i2c/ov2680.h | 173 ----- 4 files changed, 1015 deletions(-) delete mode 100644 drivers/staging/media/atomisp/i2c/atomisp-ov2680.c delete mode 100644 drivers/staging/media/atomisp/i2c/ov2680.h (limited to 'drivers/staging') diff --git a/drivers/staging/media/atomisp/i2c/Kconfig b/drivers/staging/media/atomisp/i2c/Kconfig index e34646d7dadc..2d4165cda2f1 100644 --- a/drivers/staging/media/atomisp/i2c/Kconfig +++ b/drivers/staging/media/atomisp/i2c/Kconfig @@ -57,19 +57,6 @@ config VIDEO_ATOMISP_GC0310 This is a Video4Linux2 sensor-level driver for the Galaxycore GC0310 0.3MP sensor. -config VIDEO_ATOMISP_OV2680 - tristate "Omnivision OV2680 sensor support" - depends on ACPI - depends on I2C && VIDEO_DEV - select V4L2_CCI_I2C - help - This is a Video4Linux2 sensor-level driver for the Omnivision - OV2680 raw camera. - - ov2680 is a 2M raw sensor. - - It currently only works with the atomisp driver. - config VIDEO_ATOMISP_OV5693 tristate "Omnivision ov5693 sensor support" depends on ACPI diff --git a/drivers/staging/media/atomisp/i2c/Makefile b/drivers/staging/media/atomisp/i2c/Makefile index 8d022986e199..fc55af5f3422 100644 --- a/drivers/staging/media/atomisp/i2c/Makefile +++ b/drivers/staging/media/atomisp/i2c/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_VIDEO_ATOMISP_OV5693) += ov5693/ obj-$(CONFIG_VIDEO_ATOMISP_MT9M114) += atomisp-mt9m114.o obj-$(CONFIG_VIDEO_ATOMISP_GC2235) += atomisp-gc2235.o obj-$(CONFIG_VIDEO_ATOMISP_OV2722) += atomisp-ov2722.o -obj-$(CONFIG_VIDEO_ATOMISP_OV2680) += atomisp-ov2680.o obj-$(CONFIG_VIDEO_ATOMISP_GC0310) += atomisp-gc0310.o obj-$(CONFIG_VIDEO_ATOMISP_MSRLIST_HELPER) += atomisp-libmsrlisthelper.o diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c deleted file mode 100644 index f933a65ac8d4..000000000000 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ /dev/null @@ -1,828 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Support for OmniVision OV2680 1080p HD camera sensor. - * - * Copyright (c) 2013 Intel Corporation. All Rights Reserved. - * Copyright (c) 2023 Hans de Goede - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ov2680.h" - -#define OV2680_CHIP_ID 0x2680 - -#define OV2680_REG_STREAM_CTRL CCI_REG8(0x0100) -#define OV2680_REG_SOFT_RESET CCI_REG8(0x0103) - -#define OV2680_REG_CHIP_ID CCI_REG16(0x300a) -#define OV2680_REG_SC_CMMN_SUB_ID CCI_REG8(0x302a) - -#define OV2680_REG_EXPOSURE_PK CCI_REG24(0x3500) -#define OV2680_REG_R_MANUAL CCI_REG8(0x3503) -#define OV2680_REG_GAIN_PK CCI_REG16(0x350a) - -#define OV2680_REG_SENSOR_CTRL_0A CCI_REG8(0x370a) - -#define OV2680_REG_HORIZONTAL_START CCI_REG16(0x3800) -#define OV2680_REG_VERTICAL_START CCI_REG16(0x3802) -#define OV2680_REG_HORIZONTAL_END CCI_REG16(0x3804) -#define OV2680_REG_VERTICAL_END CCI_REG16(0x3806) -#define OV2680_REG_HORIZONTAL_OUTPUT_SIZE CCI_REG16(0x3808) -#define OV2680_REG_VERTICAL_OUTPUT_SIZE CCI_REG16(0x380a) -#define OV2680_REG_TIMING_HTS CCI_REG16(0x380c) -#define OV2680_REG_TIMING_VTS CCI_REG16(0x380e) -#define OV2680_REG_ISP_X_WIN CCI_REG16(0x3810) -#define OV2680_REG_ISP_Y_WIN CCI_REG16(0x3812) -#define OV2680_REG_X_INC CCI_REG8(0x3814) -#define OV2680_REG_Y_INC CCI_REG8(0x3815) -#define OV2680_REG_FORMAT1 CCI_REG8(0x3820) -#define OV2680_REG_FORMAT2 CCI_REG8(0x3821) - -#define OV2680_REG_ISP_CTRL00 CCI_REG8(0x5080) - -#define OV2680_REG_X_WIN CCI_REG16(0x5704) -#define OV2680_REG_Y_WIN CCI_REG16(0x5706) - -#define OV2680_FRAME_RATE 30 -#define OV2680_INTEGRATION_TIME_MARGIN 8 - -static const struct v4l2_rect ov2680_default_crop = { - .left = OV2680_ACTIVE_START_LEFT, - .top = OV2680_ACTIVE_START_TOP, - .width = OV2680_ACTIVE_WIDTH, - .height = OV2680_ACTIVE_HEIGHT, -}; - -static void ov2680_set_bayer_order(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt) -{ - static const int ov2680_hv_flip_bayer_order[] = { - MEDIA_BUS_FMT_SBGGR10_1X10, - MEDIA_BUS_FMT_SGRBG10_1X10, - MEDIA_BUS_FMT_SGBRG10_1X10, - MEDIA_BUS_FMT_SRGGB10_1X10, - }; - int hv_flip = 0; - - if (sensor->ctrls.vflip->val) - hv_flip += 1; - - if (sensor->ctrls.hflip->val) - hv_flip += 2; - - fmt->code = ov2680_hv_flip_bayer_order[hv_flip]; -} - -static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val) -{ - int ret; - - if (sensor->is_streaming) - return -EBUSY; - - ret = cci_update_bits(sensor->regmap, OV2680_REG_FORMAT1, BIT(2), - val ? BIT(2) : 0, NULL); - if (ret < 0) - return ret; - - ov2680_set_bayer_order(sensor, &sensor->mode.fmt); - return 0; -} - -static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val) -{ - int ret; - - if (sensor->is_streaming) - return -EBUSY; - - ret = cci_update_bits(sensor->regmap, OV2680_REG_FORMAT2, BIT(2), - val ? BIT(2) : 0, NULL); - if (ret < 0) - return ret; - - ov2680_set_bayer_order(sensor, &sensor->mode.fmt); - return 0; -} - -static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp) -{ - return cci_write(sensor->regmap, OV2680_REG_EXPOSURE_PK, exp << 4, - NULL); -} - -static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain) -{ - return cci_write(sensor->regmap, OV2680_REG_GAIN_PK, gain, NULL); -} - -static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value) -{ - int ret = 0; - - if (!value) - return cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, - BIT(7), 0, NULL); - - cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, 0x03, value - 1, - &ret); - cci_update_bits(sensor->regmap, OV2680_REG_ISP_CTRL00, BIT(7), BIT(7), - &ret); - - return ret; -} - -static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = ctrl_to_sd(ctrl); - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - int ret; - - /* Only apply changes to the controls if the device is powered up */ - if (!pm_runtime_get_if_in_use(sensor->sd.dev)) { - ov2680_set_bayer_order(sensor, &sensor->mode.fmt); - return 0; - } - - switch (ctrl->id) { - case V4L2_CID_VFLIP: - ret = ov2680_set_vflip(sensor, ctrl->val); - break; - case V4L2_CID_HFLIP: - ret = ov2680_set_hflip(sensor, ctrl->val); - break; - case V4L2_CID_EXPOSURE: - ret = ov2680_exposure_set(sensor, ctrl->val); - break; - case V4L2_CID_GAIN: - ret = ov2680_gain_set(sensor, ctrl->val); - break; - case V4L2_CID_TEST_PATTERN: - ret = ov2680_test_pattern_set(sensor, ctrl->val); - break; - default: - ret = -EINVAL; - } - - pm_runtime_put(sensor->sd.dev); - return ret; -} - -static const struct v4l2_ctrl_ops ov2680_ctrl_ops = { - .s_ctrl = ov2680_s_ctrl, -}; - -static int ov2680_init_registers(struct v4l2_subdev *sd) -{ - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - int ret; - - ret = cci_write(sensor->regmap, OV2680_REG_SOFT_RESET, 0x01, NULL); - if (ret < 0) - return ret; - - /* Wait for sensor reset */ - usleep_range(1000, 2000); - - return regmap_multi_reg_write(sensor->regmap, ov2680_global_setting, - ARRAY_SIZE(ov2680_global_setting)); -} - -static struct v4l2_mbus_framefmt * -__ov2680_get_pad_format(struct ov2680_dev *sensor, struct v4l2_subdev_state *state, - unsigned int pad, enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_format(&sensor->sd, state, pad); - - return &sensor->mode.fmt; -} - -static struct v4l2_rect * -__ov2680_get_pad_crop(struct ov2680_dev *sensor, struct v4l2_subdev_state *state, - unsigned int pad, enum v4l2_subdev_format_whence which) -{ - if (which == V4L2_SUBDEV_FORMAT_TRY) - return v4l2_subdev_get_try_crop(&sensor->sd, state, pad); - - return &sensor->mode.crop; -} - -static void ov2680_fill_format(struct ov2680_dev *sensor, - struct v4l2_mbus_framefmt *fmt, - unsigned int width, unsigned int height) -{ - memset(fmt, 0, sizeof(*fmt)); - fmt->width = width; - fmt->height = height; - fmt->field = V4L2_FIELD_NONE; - ov2680_set_bayer_order(sensor, fmt); -} - -static void ov2680_calc_mode(struct ov2680_dev *sensor) -{ - int width = sensor->mode.fmt.width; - int height = sensor->mode.fmt.height; - int orig_width = width; - int orig_height = height; - - if (width <= (sensor->mode.crop.width / 2) && - height <= (sensor->mode.crop.height / 2)) { - sensor->mode.binning = true; - width *= 2; - height *= 2; - } else { - sensor->mode.binning = false; - } - - sensor->mode.h_start = - (sensor->mode.crop.left + (sensor->mode.crop.width - width) / 2) & ~1; - sensor->mode.v_start = - (sensor->mode.crop.top + (sensor->mode.crop.height - height) / 2) & ~1; - sensor->mode.h_end = min(sensor->mode.h_start + width + OV2680_END_MARGIN - 1, - OV2680_NATIVE_WIDTH - 1); - sensor->mode.v_end = min(sensor->mode.v_start + height + OV2680_END_MARGIN - 1, - OV2680_NATIVE_HEIGHT - 1); - sensor->mode.h_output_size = orig_width; - sensor->mode.v_output_size = orig_height; - sensor->mode.hts = OV2680_PIXELS_PER_LINE; - sensor->mode.vts = OV2680_LINES_PER_FRAME; -} - -static int ov2680_set_mode(struct ov2680_dev *sensor) -{ - u8 sensor_ctrl_0a, inc, fmt1, fmt2; - int ret = 0; - - if (sensor->mode.binning) { - sensor_ctrl_0a = 0x23; - inc = 0x31; - fmt1 = 0xc2; - fmt2 = 0x01; - } else { - sensor_ctrl_0a = 0x21; - inc = 0x11; - fmt1 = 0xc0; - fmt2 = 0x00; - } - - cci_write(sensor->regmap, OV2680_REG_SENSOR_CTRL_0A, - sensor_ctrl_0a, &ret); - cci_write(sensor->regmap, OV2680_REG_HORIZONTAL_START, - sensor->mode.h_start, &ret); - cci_write(sensor->regmap, OV2680_REG_VERTICAL_START, - sensor->mode.v_start, &ret); - cci_write(sensor->regmap, OV2680_REG_HORIZONTAL_END, - sensor->mode.h_end, &ret); - cci_write(sensor->regmap, OV2680_REG_VERTICAL_END, - sensor->mode.v_end, &ret); - cci_write(sensor->regmap, OV2680_REG_HORIZONTAL_OUTPUT_SIZE, - sensor->mode.h_output_size, &ret); - cci_write(sensor->regmap, OV2680_REG_VERTICAL_OUTPUT_SIZE, - sensor->mode.v_output_size, &ret); - cci_write(sensor->regmap, OV2680_REG_TIMING_HTS, - sensor->mode.hts, &ret); - cci_write(sensor->regmap, OV2680_REG_TIMING_VTS, - sensor->mode.vts, &ret); - cci_write(sensor->regmap, OV2680_REG_ISP_X_WIN, 0, &ret); - cci_write(sensor->regmap, OV2680_REG_ISP_Y_WIN, 0, &ret); - cci_write(sensor->regmap, OV2680_REG_X_INC, inc, &ret); - cci_write(sensor->regmap, OV2680_REG_Y_INC, inc, &ret); - cci_write(sensor->regmap, OV2680_REG_X_WIN, - sensor->mode.h_output_size, &ret); - cci_write(sensor->regmap, OV2680_REG_Y_WIN, - sensor->mode.v_output_size, &ret); - cci_write(sensor->regmap, OV2680_REG_FORMAT1, fmt1, &ret); - cci_write(sensor->regmap, OV2680_REG_FORMAT2, fmt2, &ret); - - return ret; -} - -static int ov2680_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - struct v4l2_mbus_framefmt *fmt; - const struct v4l2_rect *crop; - unsigned int width, height; - - crop = __ov2680_get_pad_crop(sensor, sd_state, format->pad, format->which); - - /* Limit set_fmt max size to crop width / height */ - width = clamp_t(unsigned int, ALIGN(format->format.width, 2), - OV2680_MIN_CROP_WIDTH, crop->width); - height = clamp_t(unsigned int, ALIGN(format->format.height, 2), - OV2680_MIN_CROP_HEIGHT, crop->height); - - fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which); - ov2680_fill_format(sensor, fmt, width, height); - - format->format = *fmt; - - if (format->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - - mutex_lock(&sensor->lock); - ov2680_calc_mode(sensor); - mutex_unlock(&sensor->lock); - return 0; -} - -static int ov2680_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - struct v4l2_mbus_framefmt *fmt; - - fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which); - format->format = *fmt; - return 0; -} - -static int ov2680_get_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - struct v4l2_subdev_selection *sel) -{ - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - mutex_lock(&sensor->lock); - sel->r = *__ov2680_get_pad_crop(sensor, state, sel->pad, sel->which); - mutex_unlock(&sensor->lock); - break; - case V4L2_SEL_TGT_NATIVE_SIZE: - case V4L2_SEL_TGT_CROP_BOUNDS: - sel->r.top = 0; - sel->r.left = 0; - sel->r.width = OV2680_NATIVE_WIDTH; - sel->r.height = OV2680_NATIVE_HEIGHT; - break; - case V4L2_SEL_TGT_CROP_DEFAULT: - sel->r.top = OV2680_ACTIVE_START_TOP; - sel->r.left = OV2680_ACTIVE_START_LEFT; - sel->r.width = OV2680_ACTIVE_WIDTH; - sel->r.height = OV2680_ACTIVE_HEIGHT; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ov2680_set_selection(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - struct v4l2_subdev_selection *sel) -{ - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - struct v4l2_mbus_framefmt *format; - struct v4l2_rect *__crop; - struct v4l2_rect rect; - - if (sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - /* - * Clamp the boundaries of the crop rectangle to the size of the sensor - * pixel array. Align to multiples of 2 to ensure Bayer pattern isn't - * disrupted. - */ - rect.left = clamp(ALIGN(sel->r.left, 2), OV2680_NATIVE_START_LEFT, - OV2680_NATIVE_WIDTH); - rect.top = clamp(ALIGN(sel->r.top, 2), OV2680_NATIVE_START_TOP, - OV2680_NATIVE_HEIGHT); - rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), - OV2680_MIN_CROP_WIDTH, OV2680_NATIVE_WIDTH); - rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), - OV2680_MIN_CROP_HEIGHT, OV2680_NATIVE_HEIGHT); - - /* Make sure the crop rectangle isn't outside the bounds of the array */ - rect.width = min_t(unsigned int, rect.width, - OV2680_NATIVE_WIDTH - rect.left); - rect.height = min_t(unsigned int, rect.height, - OV2680_NATIVE_HEIGHT - rect.top); - - __crop = __ov2680_get_pad_crop(sensor, state, sel->pad, sel->which); - - if (rect.width != __crop->width || rect.height != __crop->height) { - /* - * Reset the output image size if the crop rectangle size has - * been modified. - */ - format = __ov2680_get_pad_format(sensor, state, sel->pad, sel->which); - format->width = rect.width; - format->height = rect.height; - } - - *__crop = rect; - sel->r = rect; - - return 0; -} - -static int ov2680_init_cfg(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state) -{ - struct v4l2_subdev_format fmt = { - .which = sd_state ? V4L2_SUBDEV_FORMAT_TRY - : V4L2_SUBDEV_FORMAT_ACTIVE, - .format = { - .width = 800, - .height = 600, - }, - }; - - sd_state->pads[0].try_crop = ov2680_default_crop; - - return ov2680_set_fmt(sd, sd_state, &fmt); -} - -static int ov2680_detect(struct ov2680_dev *sensor) -{ - u64 chip_id, rev; - int ret = 0; - - cci_read(sensor->regmap, OV2680_REG_CHIP_ID, &chip_id, &ret); - cci_read(sensor->regmap, OV2680_REG_SC_CMMN_SUB_ID, &rev, &ret); - if (ret < 0) { - dev_err(sensor->dev, "failed to read chip id\n"); - return -ENODEV; - } - - if (chip_id != OV2680_CHIP_ID) { - dev_err(sensor->dev, "chip id: 0x%04llx does not match expected 0x%04x\n", - chip_id, OV2680_CHIP_ID); - return -ENODEV; - } - - dev_info(sensor->dev, "sensor_revision id = 0x%llx, rev= %lld\n", - chip_id, rev & 0x0f); - - return 0; -} - -static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret = 0; - - mutex_lock(&sensor->lock); - - if (sensor->is_streaming == enable) { - dev_warn(&client->dev, "stream already %s\n", enable ? "started" : "stopped"); - goto error_unlock; - } - - if (enable) { - ret = pm_runtime_get_sync(sensor->sd.dev); - if (ret < 0) - goto error_power_down; - - ret = ov2680_set_mode(sensor); - if (ret) - goto error_power_down; - - /* Restore value of all ctrls */ - ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler); - if (ret) - goto error_power_down; - - ret = cci_write(sensor->regmap, OV2680_REG_STREAM_CTRL, 1, - NULL); - if (ret) - goto error_power_down; - } else { - cci_write(sensor->regmap, OV2680_REG_STREAM_CTRL, 0, NULL); - pm_runtime_put(sensor->sd.dev); - } - - sensor->is_streaming = enable; - v4l2_ctrl_activate(sensor->ctrls.vflip, !enable); - v4l2_ctrl_activate(sensor->ctrls.hflip, !enable); - - mutex_unlock(&sensor->lock); - return 0; - -error_power_down: - pm_runtime_put(sensor->sd.dev); - sensor->is_streaming = false; -error_unlock: - mutex_unlock(&sensor->lock); - return ret; -} - -static int ov2680_s_config(struct v4l2_subdev *sd) -{ - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; - - ret = pm_runtime_get_sync(&client->dev); - if (ret < 0) { - dev_err(&client->dev, "ov2680 power-up err.\n"); - goto fail_power_on; - } - - /* config & detect sensor */ - ret = ov2680_detect(sensor); - if (ret) - dev_err(&client->dev, "ov2680_detect err s_config.\n"); - -fail_power_on: - pm_runtime_put(&client->dev); - return ret; -} - -static int ov2680_g_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_frame_interval *interval) -{ - interval->interval.numerator = 1; - interval->interval.denominator = OV2680_FRAME_RATE; - return 0; -} - -static int ov2680_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_mbus_code_enum *code) -{ - /* We support only a single format */ - if (code->index) - return -EINVAL; - - code->code = MEDIA_BUS_FMT_SBGGR10_1X10; - return 0; -} - -static int ov2680_enum_frame_size(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_size_enum *fse) -{ - static const struct v4l2_frmsize_discrete ov2680_frame_sizes[] = { - { 1616, 1216 }, - { 1616, 1096 }, - { 1616, 916 }, - { 1456, 1096 }, - { 1296, 976 }, - { 1296, 736 }, - { 784, 592 }, - { 656, 496 }, - }; - int index = fse->index; - - if (index >= ARRAY_SIZE(ov2680_frame_sizes)) - return -EINVAL; - - fse->min_width = ov2680_frame_sizes[index].width; - fse->min_height = ov2680_frame_sizes[index].height; - fse->max_width = ov2680_frame_sizes[index].width; - fse->max_height = ov2680_frame_sizes[index].height; - - return 0; -} - -static int ov2680_enum_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_interval_enum *fie) -{ - /* Only 1 framerate */ - if (fie->index) - return -EINVAL; - - fie->interval.numerator = 1; - fie->interval.denominator = OV2680_FRAME_RATE; - return 0; -} - -static int ov2680_g_skip_frames(struct v4l2_subdev *sd, u32 *frames) -{ - *frames = OV2680_SKIP_FRAMES; - return 0; -} - -static const struct v4l2_subdev_video_ops ov2680_video_ops = { - .s_stream = ov2680_s_stream, - .g_frame_interval = ov2680_g_frame_interval, -}; - -static const struct v4l2_subdev_sensor_ops ov2680_sensor_ops = { - .g_skip_frames = ov2680_g_skip_frames, -}; - -static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { - .init_cfg = ov2680_init_cfg, - .enum_mbus_code = ov2680_enum_mbus_code, - .enum_frame_size = ov2680_enum_frame_size, - .enum_frame_interval = ov2680_enum_frame_interval, - .get_fmt = ov2680_get_fmt, - .set_fmt = ov2680_set_fmt, - .get_selection = ov2680_get_selection, - .set_selection = ov2680_set_selection, -}; - -static const struct v4l2_subdev_ops ov2680_ops = { - .video = &ov2680_video_ops, - .pad = &ov2680_pad_ops, - .sensor = &ov2680_sensor_ops, -}; - -static int ov2680_init_controls(struct ov2680_dev *sensor) -{ - static const char * const test_pattern_menu[] = { - "Disabled", - "Color Bars", - "Random Data", - "Square", - "Black Image", - }; - const struct v4l2_ctrl_ops *ops = &ov2680_ctrl_ops; - struct ov2680_ctrls *ctrls = &sensor->ctrls; - struct v4l2_ctrl_handler *hdl = &ctrls->handler; - int exp_max = OV2680_LINES_PER_FRAME - OV2680_INTEGRATION_TIME_MARGIN; - - v4l2_ctrl_handler_init(hdl, 4); - - hdl->lock = &sensor->lock; - - ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); - ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); - ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, - 0, exp_max, 1, exp_max); - ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, 0, 1023, 1, 250); - ctrls->test_pattern = - v4l2_ctrl_new_std_menu_items(hdl, - &ov2680_ctrl_ops, V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(test_pattern_menu) - 1, - 0, 0, test_pattern_menu); - - ctrls->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; - ctrls->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; - - if (hdl->error) - return hdl->error; - - sensor->sd.ctrl_handler = hdl; - return 0; -} - -static void ov2680_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - - dev_dbg(&client->dev, "ov2680_remove...\n"); - - v4l2_async_unregister_subdev(&sensor->sd); - media_entity_cleanup(&sensor->sd.entity); - v4l2_ctrl_handler_free(&sensor->ctrls.handler); - mutex_destroy(&sensor->lock); - fwnode_handle_put(sensor->ep_fwnode); - pm_runtime_disable(&client->dev); -} - -static int ov2680_probe(struct i2c_client *client) -{ - struct device *dev = &client->dev; - struct ov2680_dev *sensor; - int ret; - - sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); - if (!sensor) - return -ENOMEM; - - sensor->regmap = devm_cci_regmap_init_i2c(client, 16); - if (IS_ERR(sensor->regmap)) - return PTR_ERR(sensor->regmap); - - mutex_init(&sensor->lock); - - sensor->dev = &client->dev; - v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_ops); - - /* - * Sometimes the fwnode graph is initialized by the bridge driver. - * Bridge drivers doing this may also add GPIO mappings, wait for this. - */ - sensor->ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); - if (!sensor->ep_fwnode) - return dev_err_probe(dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); - - sensor->powerdown = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(sensor->powerdown)) { - fwnode_handle_put(sensor->ep_fwnode); - return dev_err_probe(dev, PTR_ERR(sensor->powerdown), "getting powerdown GPIO\n"); - } - - pm_runtime_set_suspended(dev); - pm_runtime_enable(dev); - pm_runtime_set_autosuspend_delay(dev, 1000); - pm_runtime_use_autosuspend(dev); - - ret = ov2680_s_config(&sensor->sd); - if (ret) { - ov2680_remove(client); - return ret; - } - - sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - sensor->pad.flags = MEDIA_PAD_FL_SOURCE; - sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; - sensor->sd.fwnode = sensor->ep_fwnode; - - ret = ov2680_init_controls(sensor); - if (ret) { - ov2680_remove(client); - return ret; - } - - ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad); - if (ret) { - ov2680_remove(client); - return ret; - } - - sensor->mode.crop = ov2680_default_crop; - ov2680_fill_format(sensor, &sensor->mode.fmt, OV2680_NATIVE_WIDTH, OV2680_NATIVE_HEIGHT); - ov2680_calc_mode(sensor); - - ret = v4l2_async_register_subdev_sensor(&sensor->sd); - if (ret) { - ov2680_remove(client); - return ret; - } - - return 0; -} - -static int ov2680_suspend(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - - gpiod_set_value_cansleep(sensor->powerdown, 1); - return 0; -} - -static int ov2680_resume(struct device *dev) -{ - struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov2680_dev *sensor = to_ov2680_sensor(sd); - - /* according to DS, at least 5ms is needed after DOVDD (enabled by ACPI) */ - usleep_range(5000, 6000); - - gpiod_set_value_cansleep(sensor->powerdown, 0); - - /* according to DS, 20ms is needed between PWDN and i2c access */ - msleep(20); - - ov2680_init_registers(sd); - return 0; -} - -static DEFINE_RUNTIME_DEV_PM_OPS(ov2680_pm_ops, ov2680_suspend, ov2680_resume, NULL); - -static const struct acpi_device_id ov2680_acpi_match[] = { - {"XXOV2680"}, - {"OVTI2680"}, - {}, -}; -MODULE_DEVICE_TABLE(acpi, ov2680_acpi_match); - -static struct i2c_driver ov2680_driver = { - .driver = { - .name = "ov2680", - .pm = pm_sleep_ptr(&ov2680_pm_ops), - .acpi_match_table = ov2680_acpi_match, - }, - .probe = ov2680_probe, - .remove = ov2680_remove, -}; -module_i2c_driver(ov2680_driver); - -MODULE_AUTHOR("Jacky Wang "); -MODULE_DESCRIPTION("A low-level driver for OmniVision 2680 sensors"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h deleted file mode 100644 index 7815522724f7..000000000000 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ /dev/null @@ -1,173 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Support for OmniVision OV2680 5M camera sensor. - * - * Copyright (c) 2013 Intel Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * - */ - -#ifndef __OV2680_H__ -#define __OV2680_H__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define OV2680_NATIVE_WIDTH 1616 -#define OV2680_NATIVE_HEIGHT 1216 -#define OV2680_NATIVE_START_LEFT 0 -#define OV2680_NATIVE_START_TOP 0 -#define OV2680_ACTIVE_WIDTH 1600 -#define OV2680_ACTIVE_HEIGHT 1200 -#define OV2680_ACTIVE_START_LEFT 8 -#define OV2680_ACTIVE_START_TOP 8 -#define OV2680_MIN_CROP_WIDTH 2 -#define OV2680_MIN_CROP_HEIGHT 2 - -/* 1704 * 1294 * 30fps = 66MHz pixel clock */ -#define OV2680_PIXELS_PER_LINE 1704 -#define OV2680_LINES_PER_FRAME 1294 - -#define OV2680_SKIP_FRAMES 3 - -/* If possible send 16 extra rows / lines to the ISP as padding */ -#define OV2680_END_MARGIN 16 - -/* - * ov2680 device structure. - */ -struct ov2680_dev { - struct v4l2_subdev sd; - struct media_pad pad; - /* Protect against concurrent changes to controls */ - struct mutex lock; - struct device *dev; - struct regmap *regmap; - struct gpio_desc *powerdown; - struct fwnode_handle *ep_fwnode; - bool is_streaming; - - struct ov2680_mode { - struct v4l2_rect crop; - struct v4l2_mbus_framefmt fmt; - bool binning; - u16 h_start; - u16 v_start; - u16 h_end; - u16 v_end; - u16 h_output_size; - u16 v_output_size; - u16 hts; - u16 vts; - } mode; - - struct ov2680_ctrls { - struct v4l2_ctrl_handler handler; - struct v4l2_ctrl *hflip; - struct v4l2_ctrl *vflip; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *gain; - struct v4l2_ctrl *test_pattern; - } ctrls; -}; - -#define to_ov2680_sensor(x) container_of(x, struct ov2680_dev, sd) - -static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) -{ - struct ov2680_dev *sensor = - container_of(ctrl->handler, struct ov2680_dev, ctrls.handler); - - return &sensor->sd; -} - -static const struct reg_sequence ov2680_global_setting[] = { - /* MIPI PHY, 0x10 -> 0x1c enable bp_c_hs_en_lat and bp_d_hs_en_lat */ - {0x3016, 0x1c}, - - /* PLL MULT bits 0-7, datasheet default 0x37 for 24MHz extclk, use 0x45 for 19.2 Mhz extclk */ - {0x3082, 0x45}, - - /* R MANUAL set exposure (0x01) and gain (0x02) to manual (hw does not do auto) */ - {0x3503, 0x03}, - - /* Analog control register tweaks */ - {0x3603, 0x39}, /* Reset value 0x99 */ - {0x3604, 0x24}, /* Reset value 0x74 */ - {0x3621, 0x37}, /* Reset value 0x44 */ - - /* Sensor control register tweaks */ - {0x3701, 0x64}, /* Reset value 0x61 */ - {0x3705, 0x3c}, /* Reset value 0x21 */ - {0x370c, 0x50}, /* Reset value 0x10 */ - {0x370d, 0xc0}, /* Reset value 0x00 */ - {0x3718, 0x88}, /* Reset value 0x80 */ - - /* PSRAM tweaks */ - {0x3781, 0x80}, /* Reset value 0x00 */ - {0x3784, 0x0c}, /* Reset value 0x00, based on OV2680_R1A_AM10.ovt */ - {0x3789, 0x60}, /* Reset value 0x50 */ - - /* BLC CTRL00 0x01 -> 0x81 set avg_weight to 8 */ - {0x4000, 0x81}, - - /* Set black level compensation range to 0 - 3 (default 0 - 11) */ - {0x4008, 0x00}, - {0x4009, 0x03}, - - /* VFIFO R2 0x00 -> 0x02 set Frame reset enable */ - {0x4602, 0x02}, - - /* MIPI ctrl CLK PREPARE MIN change from 0x26 (38) -> 0x36 (54) */ - {0x481f, 0x36}, - - /* MIPI ctrl CLK LPX P MIN change from 0x32 (50) -> 0x36 (54) */ - {0x4825, 0x36}, - - /* R ISP CTRL2 0x20 -> 0x30, set sof_sel bit */ - {0x5002, 0x30}, - - /* - * Window CONTROL 0x00 -> 0x01, enable manual window control, - * this is necessary for full size flip and mirror support. - */ - {0x5708, 0x01}, - - /* - * DPC CTRL0 0x14 -> 0x3e, set enable_tail, enable_3x3_cluster - * and enable_general_tail bits based OV2680_R1A_AM10.ovt. - */ - {0x5780, 0x3e}, - - /* DPC MORE CONNECTION CASE THRE 0x0c (12) -> 0x02 (2) */ - {0x5788, 0x02}, - - /* DPC GAIN LIST1 0x0f (15) -> 0x08 (8) */ - {0x578e, 0x08}, - - /* DPC GAIN LIST2 0x3f (63) -> 0x0c (12) */ - {0x578f, 0x0c}, - - /* DPC THRE RATIO 0x04 (4) -> 0x00 (0) */ - {0x5792, 0x00}, -}; - -#endif -- cgit v1.2.3