media: v4l: async: Obtain async connection based on sub-device
authorSakari Ailus <sakari.ailus@linux.intel.com>
Mon, 15 May 2023 09:06:50 +0000 (11:06 +0200)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 28 Jul 2023 08:47:56 +0000 (10:47 +0200)
Add v4l2_async_connection_unique() function for obtaining a struct
v4l2_async_connection, typically allocated by drivers together with their
own information on an external sub-device.

The relation between connections and sub-devices still remains 1:1 but
this code becomes more complex when the relation soon changes.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de> # imx6qp
Tested-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> # rcar + adv746x
Tested-by: Aishwarya Kothari <aishwarya.kothari@toradex.com> # Apalis i.MX6Q with TC358743
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> # Renesas RZ/G2L SMARC
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/platform/rockchip/rkisp1/rkisp1-csi.c
drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
drivers/media/platform/ti/omap3isp/isp.h
drivers/media/platform/ti/omap3isp/ispccdc.c
drivers/media/platform/ti/omap3isp/ispccp2.c
drivers/media/platform/ti/omap3isp/ispcsi2.c
drivers/media/platform/ti/omap3isp/ispcsiphy.c
drivers/media/v4l2-core/v4l2-async.c
include/media/v4l2-async.h

index d7acc94..fdff3d0 100644 (file)
@@ -381,6 +381,7 @@ static int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable)
        struct rkisp1_csi *csi = to_rkisp1_csi(sd);
        struct rkisp1_device *rkisp1 = csi->rkisp1;
        struct rkisp1_sensor_async *source_asd;
+       struct v4l2_async_connection *asc;
        struct media_pad *source_pad;
        struct v4l2_subdev *source;
        int ret;
@@ -406,7 +407,11 @@ static int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable)
                return -EPIPE;
        }
 
-       source_asd = container_of(source->asd, struct rkisp1_sensor_async, asd);
+       asc = v4l2_async_connection_unique(source);
+       if (!asc)
+               return -EPIPE;
+
+       source_asd = container_of(asc, struct rkisp1_sensor_async, asd);
        if (source_asd->mbus_type != V4L2_MBUS_CSI2_DPHY)
                return -EINVAL;
 
index 585cf3f..07fbb77 100644 (file)
@@ -868,9 +868,13 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
                mbus_flags = 0;
        } else {
                const struct rkisp1_sensor_async *asd;
+               struct v4l2_async_connection *asc;
 
-               asd = container_of(rkisp1->source->asd,
-                                  struct rkisp1_sensor_async, asd);
+               asc = v4l2_async_connection_unique(rkisp1->source);
+               if (!asc)
+                       return -EPIPE;
+
+               asd = container_of(asc, struct rkisp1_sensor_async, asd);
 
                mbus_type = asd->mbus_type;
                mbus_flags = asd->mbus_flags;
index 32ea70c..b479363 100644 (file)
@@ -224,8 +224,17 @@ struct isp_async_subdev {
        struct isp_bus_cfg bus;
 };
 
-#define v4l2_subdev_to_bus_cfg(sd) \
-       (&container_of((sd)->asd, struct isp_async_subdev, asd)->bus)
+static inline struct isp_bus_cfg *
+v4l2_subdev_to_bus_cfg(struct v4l2_subdev *sd)
+{
+       struct v4l2_async_connection *asc;
+
+       asc = v4l2_async_connection_unique(sd);
+       if (!asc)
+               return NULL;
+
+       return &container_of(asc, struct isp_async_subdev, asd)->bus;
+}
 
 #define v4l2_dev_to_isp_device(dev) \
        container_of(dev, struct isp_device, v4l2_dev)
index fdcdffe..2fe42aa 100644 (file)
@@ -1140,8 +1140,13 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        if (ccdc->input == CCDC_INPUT_PARALLEL) {
                struct v4l2_subdev *sd =
                        to_isp_pipeline(&ccdc->subdev.entity)->external;
+               struct isp_bus_cfg *bus_cfg;
 
-               parcfg = &v4l2_subdev_to_bus_cfg(sd)->bus.parallel;
+               bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+               if (WARN_ON(!bus_cfg))
+                       return;
+
+               parcfg = &bus_cfg->bus.parallel;
                ccdc->bt656 = parcfg->bt656;
        }
 
@@ -2436,7 +2441,11 @@ static int ccdc_link_validate(struct v4l2_subdev *sd,
        if (ccdc->input == CCDC_INPUT_PARALLEL) {
                struct v4l2_subdev *sd =
                        media_entity_to_v4l2_subdev(link->source->entity);
-               struct isp_bus_cfg *bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+               struct isp_bus_cfg *bus_cfg;
+
+               bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+               if (WARN_ON(!bus_cfg))
+                       return -EPIPE;
 
                parallel_shift = bus_cfg->bus.parallel.data_lane_shift;
        } else {
index fc90ff8..da5f017 100644 (file)
@@ -360,6 +360,8 @@ static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
        pad = media_pad_remote_pad_first(&ccp2->pads[CCP2_PAD_SINK]);
        sensor = media_entity_to_v4l2_subdev(pad->entity);
        buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+       if (WARN_ON(!buscfg))
+               return -EPIPE;
 
        ret = ccp2_phyif_config(ccp2, &buscfg->bus.ccp2);
        if (ret < 0)
index 6870980..0f9a54b 100644 (file)
@@ -564,6 +564,8 @@ static int csi2_configure(struct isp_csi2_device *csi2)
        pad = media_pad_remote_pad_first(&csi2->pads[CSI2_PAD_SINK]);
        sensor = media_entity_to_v4l2_subdev(pad->entity);
        buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+       if (WARN_ON(!buscfg))
+               return -EPIPE;
 
        csi2->frame_skip = 0;
        v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
index 1bde76c..29a84d8 100644 (file)
@@ -163,13 +163,17 @@ static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
 static int omap3isp_csiphy_config(struct isp_csiphy *phy)
 {
        struct isp_pipeline *pipe = to_isp_pipeline(phy->entity);
-       struct isp_bus_cfg *buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+       struct isp_bus_cfg *buscfg;
        struct isp_csiphy_lanes_cfg *lanes;
        int csi2_ddrclk_khz;
        unsigned int num_data_lanes, used_lanes = 0;
        unsigned int i;
        u32 reg;
 
+       buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+       if (WARN_ON(!buscfg))
+               return -EPIPE;
+
        if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1
            || buscfg->interface == ISP_INTERFACE_CCP2B_PHY2) {
                lanes = &buscfg->bus.ccp2.lanecfg;
@@ -306,8 +310,13 @@ void omap3isp_csiphy_release(struct isp_csiphy *phy)
        mutex_lock(&phy->mutex);
        if (phy->entity) {
                struct isp_pipeline *pipe = to_isp_pipeline(phy->entity);
-               struct isp_bus_cfg *buscfg =
-                       v4l2_subdev_to_bus_cfg(pipe->external);
+               struct isp_bus_cfg *buscfg;
+
+               buscfg = v4l2_subdev_to_bus_cfg(pipe->external);
+               if (WARN_ON(!buscfg)) {
+                       mutex_unlock(&phy->mutex);
+                       return;
+               }
 
                csiphy_routing_cfg(phy, buscfg->interface, false,
                                   buscfg->bus.ccp2.phy_layer);
index 95fecf3..cb962b0 100644 (file)
@@ -751,6 +751,13 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
 }
 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
 
+struct v4l2_async_connection *
+v4l2_async_connection_unique(struct v4l2_subdev *sd)
+{
+       return sd->asd;
+}
+EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
+
 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
 {
        struct v4l2_async_notifier *subdev_notifier;
index c06b3b8..5bc2efe 100644 (file)
@@ -211,6 +211,17 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
                                         sizeof(type)))
 
 /**
+ * v4l2_async_connection_unique - return a unique &struct v4l2_async_connection
+ *                               for a sub-device
+ * @sd: the sub-device
+ *
+ * Return an async connection for a sub-device, when there is a single
+ * one only.
+ */
+struct v4l2_async_connection *
+v4l2_async_connection_unique(struct v4l2_subdev *sd);
+
+/**
  * v4l2_async_nf_register - registers a subdevice asynchronous notifier
  *
  * @v4l2_dev: pointer to &struct v4l2_device