media: v4l: async: Obtain async connection based on sub-device

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>
This commit is contained in:
Sakari Ailus 2023-05-15 11:06:50 +02:00 committed by Mauro Carvalho Chehab
parent 9bf19fbf0c
commit c91fd7b7a8
9 changed files with 68 additions and 10 deletions

View 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;

View 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;

View 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)

View 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 {

View 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)

View 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);

View 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);

View 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;

View file

@ -210,6 +210,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
*