@@ -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;
@@ -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;
@@ -2039,11 +2039,18 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
}
list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+ struct isp_bus_cfg *bus_cfg;
+
if (sd->notifier != &isp->notifier)
continue;
- ret = isp_link_entity(isp, &sd->entity,
- v4l2_subdev_to_bus_cfg(sd)->interface);
+ bus_cfg = v4l2_subdev_to_bus_cfg(sd);
+ if (!bus_cfg) {
+ mutex_unlock(&isp->media_dev.graph_mutex);
+ return -EINVAL;
+ }
+
+ ret = isp_link_entity(isp, &sd->entity, bus_cfg->interface);
if (ret < 0) {
mutex_unlock(&isp->media_dev.graph_mutex);
return ret;
@@ -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)
@@ -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 {
@@ -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)
@@ -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);
@@ -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);
@@ -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;
@@ -209,6 +209,17 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier,
((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \
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
*
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> --- .../media/platform/rockchip/rkisp1/rkisp1-csi.c | 7 ++++++- .../media/platform/rockchip/rkisp1/rkisp1-isp.c | 8 ++++++-- drivers/media/platform/ti/omap3isp/isp.c | 11 +++++++++-- drivers/media/platform/ti/omap3isp/isp.h | 13 +++++++++++-- drivers/media/platform/ti/omap3isp/ispccdc.c | 13 +++++++++++-- drivers/media/platform/ti/omap3isp/ispccp2.c | 2 ++ drivers/media/platform/ti/omap3isp/ispcsi2.c | 2 ++ drivers/media/platform/ti/omap3isp/ispcsiphy.c | 15 ++++++++++++--- drivers/media/v4l2-core/v4l2-async.c | 7 +++++++ include/media/v4l2-async.h | 11 +++++++++++ 10 files changed, 77 insertions(+), 12 deletions(-)