* ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
*/
struct ceu_subdev {
- struct v4l2_subdev *v4l2_sd;
struct v4l2_async_subdev asd;
+ struct v4l2_subdev *v4l2_sd;
/* per-subdevice mbus configuration options */
unsigned int mbus_flags;
struct v4l2_device v4l2_dev;
/* subdevices descriptors */
- struct ceu_subdev *subdevs;
+ struct ceu_subdev **subdevs;
/* the subdevice currently in use */
struct ceu_subdev *sd;
unsigned int sd_index;
if (inp->index >= ceudev->num_sd)
return -EINVAL;
- ceusd = &ceudev->subdevs[inp->index];
+ ceusd = ceudev->subdevs[inp->index];
inp->type = V4L2_INPUT_TYPE_CAMERA;
inp->std = 0;
return 0;
ceu_sd_old = ceudev->sd;
- ceudev->sd = &ceudev->subdevs[i];
+ ceudev->sd = ceudev->subdevs[i];
/*
* Make sure we can generate output image formats and apply
* ceu formats.
*/
if (!ceudev->sd) {
- ceudev->sd = &ceudev->subdevs[0];
+ ceudev->sd = ceudev->subdevs[0];
ceudev->sd_index = 0;
}
/*
* ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
- * ceu device. Both DT and platform data parsing use
- * this routine.
+ * ceu device. Both DT and platform data parsing use
+ * this routine.
*
* Returns 0 for success, -ENOMEM for failure.
*/
const struct ceu_platform_data *pdata)
{
const struct ceu_async_subdev *async_sd;
+ struct v4l2_async_subdev *asd;
struct ceu_subdev *ceu_sd;
unsigned int i;
int ret;
/* Setup the ceu subdevice and the async subdevice. */
async_sd = &pdata->subdevs[i];
- ceu_sd = &ceudev->subdevs[i];
-
- INIT_LIST_HEAD(&ceu_sd->asd.list);
-
- ceu_sd->mbus_flags = async_sd->flags;
- ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_I2C;
- ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id;
- ceu_sd->asd.match.i2c.address = async_sd->i2c_address;
-
- ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
- &ceu_sd->asd);
- if (ret) {
+ asd = v4l2_async_notifier_add_i2c_subdev(&ceudev->notifier,
+ async_sd->i2c_adapter_id,
+ async_sd->i2c_address,
+ sizeof(*ceu_sd));
+ if (IS_ERR(asd)) {
v4l2_async_notifier_cleanup(&ceudev->notifier);
- return ret;
+ return PTR_ERR(asd);
}
+ ceu_sd = to_ceu_subdev(asd);
+ ceu_sd->mbus_flags = async_sd->flags;
+ ceudev->subdevs[i] = ceu_sd;
}
return pdata->num_subdevs;
static int ceu_parse_dt(struct ceu_device *ceudev)
{
struct device_node *of = ceudev->dev->of_node;
- struct device_node *ep, *remote;
+ struct device_node *ep;
+ struct v4l2_async_subdev *asd;
struct ceu_subdev *ceu_sd;
unsigned int i;
int num_ep;
}
/* Setup the ceu subdevice and the async subdevice. */
- ceu_sd = &ceudev->subdevs[i];
- INIT_LIST_HEAD(&ceu_sd->asd.list);
-
- remote = of_graph_get_remote_port_parent(ep);
- ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
- ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
- ceu_sd->asd.match.fwnode = of_fwnode_handle(remote);
-
- ret = v4l2_async_notifier_add_subdev(&ceudev->notifier,
- &ceu_sd->asd);
- if (ret) {
- of_node_put(remote);
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
+ &ceudev->notifier, of_fwnode_handle(ep),
+ sizeof(*ceu_sd));
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
goto error_cleanup;
}
+ ceu_sd = to_ceu_subdev(asd);
+ ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;
+ ceudev->subdevs[i] = ceu_sd;
of_node_put(ep);
}