diff options
-rw-r--r-- | drivers/staging/media/imx/imx-media-capture.c | 2 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media-dev.c | 77 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media-utils.c | 16 | ||||
-rw-r--r-- | drivers/staging/media/imx/imx-media.h | 39 |
4 files changed, 68 insertions, 66 deletions
diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c index 7b6763802db8..576bdc7e9c42 100644 --- a/drivers/staging/media/imx/imx-media-capture.c +++ b/drivers/staging/media/imx/imx-media-capture.c @@ -748,6 +748,8 @@ imx_media_capture_device_init(struct v4l2_subdev *src_sd, int pad) vfd->queue = &priv->q; priv->vdev.vfd = vfd; + INIT_LIST_HEAD(&priv->vdev.list); + video_set_drvdata(vfd, priv); v4l2_ctrl_handler_init(&priv->ctrl_hdlr, 0); diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index 71586ae445a7..2800700482d6 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -229,10 +229,11 @@ static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd, struct media_pad *srcpad) { struct media_entity *entity = srcpad->entity; - struct imx_media_pad *imxpad; + struct imx_media_pad_vdev *pad_vdev; + struct list_head *pad_vdev_list; struct media_link *link; struct v4l2_subdev *sd; - int i, vdev_idx, ret; + int i, ret; /* skip this entity if not a v4l2_subdev */ if (!is_media_entity_v4l2_subdev(entity)) @@ -240,8 +241,8 @@ static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd, sd = media_entity_to_v4l2_subdev(entity); - imxpad = to_imx_media_pad(sd, srcpad->index); - if (!imxpad) { + pad_vdev_list = to_pad_vdev_list(sd, srcpad->index); + if (!pad_vdev_list) { v4l2_warn(&imxmd->v4l2_dev, "%s:%u has no vdev list!\n", entity->name, srcpad->index); /* @@ -251,23 +252,22 @@ static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd, return 0; } - vdev_idx = imxpad->num_vdevs; - /* just return if we've been here before */ - for (i = 0; i < vdev_idx; i++) - if (vdev == imxpad->vdev[i]) + list_for_each_entry(pad_vdev, pad_vdev_list, list) { + if (pad_vdev->vdev == vdev) return 0; - - if (vdev_idx >= IMX_MEDIA_MAX_VDEVS) { - dev_err(imxmd->md.dev, "can't add %s to pad %s:%u\n", - vdev->vfd->entity.name, entity->name, srcpad->index); - return -ENOSPC; } dev_dbg(imxmd->md.dev, "adding %s to pad %s:%u\n", vdev->vfd->entity.name, entity->name, srcpad->index); - imxpad->vdev[vdev_idx] = vdev; - imxpad->num_vdevs++; + + pad_vdev = devm_kzalloc(imxmd->md.dev, sizeof(*pad_vdev), GFP_KERNEL); + if (!pad_vdev) + return -ENOMEM; + + /* attach this vdev to this pad */ + pad_vdev->vdev = vdev; + list_add_tail(&pad_vdev->list, pad_vdev_list); /* move upstream from this entity's sink pads */ for (i = 0; i < entity->num_pads; i++) { @@ -289,22 +289,32 @@ static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd, return 0; } +/* + * For every subdevice, allocate an array of list_head's, one list_head + * for each pad, to hold the list of video devices reachable from that + * pad. + */ static int imx_media_alloc_pad_vdev_lists(struct imx_media_dev *imxmd) { - struct imx_media_pad *imxpads; + struct list_head *vdev_lists; struct media_entity *entity; struct v4l2_subdev *sd; + int i; list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { entity = &sd->entity; - imxpads = devm_kzalloc(imxmd->md.dev, - entity->num_pads * sizeof(*imxpads), - GFP_KERNEL); - if (!imxpads) + vdev_lists = devm_kzalloc( + imxmd->md.dev, + entity->num_pads * sizeof(*vdev_lists), + GFP_KERNEL); + if (!vdev_lists) return -ENOMEM; - /* attach imxpads to the subdev's host private pointer */ - sd->host_priv = imxpads; + /* attach to the subdev's host private pointer */ + sd->host_priv = vdev_lists; + + for (i = 0; i < entity->num_pads; i++) + INIT_LIST_HEAD(to_pad_vdev_list(sd, i)); } return 0; @@ -315,14 +325,13 @@ static int imx_media_create_pad_vdev_lists(struct imx_media_dev *imxmd) { struct imx_media_video_dev *vdev; struct media_link *link; - int i, ret; + int ret; ret = imx_media_alloc_pad_vdev_lists(imxmd); if (ret) return ret; - for (i = 0; i < imxmd->num_vdevs; i++) { - vdev = imxmd->vdev[i]; + list_for_each_entry(vdev, &imxmd->vdev_list, list) { link = list_first_entry(&vdev->vfd->entity.links, struct media_link, list); ret = imx_media_add_vdev_to_pad(imxmd, vdev, link->source); @@ -410,11 +419,12 @@ static int imx_media_link_notify(struct media_link *link, u32 flags, unsigned int notification) { struct media_entity *source = link->source->entity; - struct imx_media_pad *imxpad; + struct imx_media_pad_vdev *pad_vdev; + struct list_head *pad_vdev_list; struct imx_media_dev *imxmd; struct video_device *vfd; struct v4l2_subdev *sd; - int i, pad_idx, ret; + int pad_idx, ret; ret = v4l2_pipeline_link_notify(link, flags, notification); if (ret) @@ -429,8 +439,8 @@ static int imx_media_link_notify(struct media_link *link, u32 flags, imxmd = dev_get_drvdata(sd->v4l2_dev->dev); - imxpad = to_imx_media_pad(sd, pad_idx); - if (!imxpad) { + pad_vdev_list = to_pad_vdev_list(sd, pad_idx); + if (!pad_vdev_list) { /* shouldn't happen, but no reason to fail link setup */ return 0; } @@ -444,8 +454,8 @@ static int imx_media_link_notify(struct media_link *link, u32 flags, */ if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH && !(flags & MEDIA_LNK_FL_ENABLED)) { - for (i = 0; i < imxpad->num_vdevs; i++) { - vfd = imxpad->vdev[i]->vfd; + list_for_each_entry(pad_vdev, pad_vdev_list, list) { + vfd = pad_vdev->vdev->vfd; dev_dbg(imxmd->md.dev, "reset controls for %s\n", vfd->entity.name); @@ -454,8 +464,8 @@ static int imx_media_link_notify(struct media_link *link, u32 flags, } } else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && (link->flags & MEDIA_LNK_FL_ENABLED)) { - for (i = 0; i < imxpad->num_vdevs; i++) { - vfd = imxpad->vdev[i]->vfd; + list_for_each_entry(pad_vdev, pad_vdev_list, list) { + vfd = pad_vdev->vdev->vfd; dev_dbg(imxmd->md.dev, "refresh controls for %s\n", vfd->entity.name); @@ -510,6 +520,7 @@ static int imx_media_probe(struct platform_device *pdev) dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd); INIT_LIST_HEAD(&imxmd->asd_list); + INIT_LIST_HEAD(&imxmd->vdev_list); ret = imx_media_add_of_subdevs(imxmd, node); if (ret) { diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index e143a88d3317..13dafa77a2eb 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -705,24 +705,12 @@ EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname); int imx_media_add_video_device(struct imx_media_dev *imxmd, struct imx_media_video_dev *vdev) { - int vdev_idx, ret = 0; - mutex_lock(&imxmd->mutex); - vdev_idx = imxmd->num_vdevs; - if (vdev_idx >= IMX_MEDIA_MAX_VDEVS) { - dev_err(imxmd->md.dev, - "%s: too many video devices! can't add %s\n", - __func__, vdev->vfd->name); - ret = -ENOSPC; - goto out; - } + list_add_tail(&vdev->list, &imxmd->vdev_list); - imxmd->vdev[vdev_idx] = vdev; - imxmd->num_vdevs++; -out: mutex_unlock(&imxmd->mutex); - return ret; + return 0; } EXPORT_SYMBOL_GPL(imx_media_add_video_device); diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index 5089a0d88114..ebb24b165fff 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -19,9 +19,6 @@ #include <media/videobuf2-dma-contig.h> #include <video/imx-ipu-v3.h> -/* max video devices */ -#define IMX_MEDIA_MAX_VDEVS 8 - /* * Pad definitions for the subdevs with multiple source or * sink pads @@ -82,6 +79,9 @@ struct imx_media_video_dev { /* the user format */ struct v4l2_format fmt; const struct imx_media_pixfmt *cc; + + /* links this vdev to master list */ + struct list_head list; }; static inline struct imx_media_buffer *to_imx_media_vb(struct vb2_buffer *vb) @@ -91,24 +91,26 @@ static inline struct imx_media_buffer *to_imx_media_vb(struct vb2_buffer *vb) return container_of(vbuf, struct imx_media_buffer, vbuf); } -/* to support control inheritance to video devices */ -struct imx_media_pad { - /* - * list of video devices that can be reached from this pad, - * list is only valid for source pads. - */ - struct imx_media_video_dev *vdev[IMX_MEDIA_MAX_VDEVS]; - int num_vdevs; -}; - -static inline struct imx_media_pad * -to_imx_media_pad(struct v4l2_subdev *sd, int pad_index) +/* + * to support control inheritance to video devices, this + * retrieves a pad's list_head of video devices that can + * be reached from the pad. Note that only the lists in + * source pads get populated, sink pads have empty lists. + */ +static inline struct list_head * +to_pad_vdev_list(struct v4l2_subdev *sd, int pad_index) { - struct imx_media_pad *imxpads = sd->host_priv; + struct list_head *vdev_list = sd->host_priv; - return imxpads ? &imxpads[pad_index] : NULL; + return vdev_list ? &vdev_list[pad_index] : NULL; } +/* an entry in a pad's video device list */ +struct imx_media_pad_vdev { + struct imx_media_video_dev *vdev; + struct list_head list; +}; + struct imx_media_internal_sd_platformdata { char sd_name[V4L2_SUBDEV_NAME_SIZE]; u32 grp_id; @@ -139,8 +141,7 @@ struct imx_media_dev { struct mutex mutex; /* protect elements below */ /* master video device list */ - struct imx_media_video_dev *vdev[IMX_MEDIA_MAX_VDEVS]; - int num_vdevs; + struct list_head vdev_list; /* IPUs this media driver control, valid after subdevs bound */ struct ipu_soc *ipu[2]; |