diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index c483b1dfc12e..09d2deb3734a 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -127,50 +128,6 @@ out: return imxsd; } -/* - * Adds an imx-media link to a subdev pad's link list. This is called - * during driver load when forming the links between subdevs. - * - * @pad: the local pad - * @remote_node: the device node of the remote subdev - * @remote_devname: the device name of the remote subdev - * @local_pad: local pad index - * @remote_pad: remote pad index - */ -int imx_media_add_pad_link(struct imx_media_dev *imxmd, - struct imx_media_pad *pad, - struct device_node *remote_node, - const char *remote_devname, - int local_pad, int remote_pad) -{ - struct imx_media_link *link; - int link_idx, ret = 0; - - mutex_lock(&imxmd->mutex); - - link_idx = pad->num_links; - if (link_idx >= IMX_MEDIA_MAX_LINKS) { - dev_err(imxmd->md.dev, "%s: too many links!\n", __func__); - ret = -ENOSPC; - goto out; - } - - link = &pad->link[link_idx]; - - link->remote_sd_node = remote_node; - if (remote_devname) - strncpy(link->remote_devname, remote_devname, - sizeof(link->remote_devname)); - - link->local_pad = local_pad; - link->remote_pad = remote_pad; - - pad->num_links++; -out: - mutex_unlock(&imxmd->mutex); - return ret; -} - /* * get IPU from this CSI and add it to the list of IPUs * the media driver will control. @@ -240,76 +197,38 @@ out_unlock: } /* - * Create a single source->sink media link given a subdev and a single - * link from one of its source pads. Called after all subdevs have - * registered. - */ -static int imx_media_create_link(struct imx_media_dev *imxmd, - struct imx_media_subdev *src, - struct imx_media_link *link) -{ - struct imx_media_subdev *sink; - u16 source_pad, sink_pad; - int ret; - - sink = imx_media_find_async_subdev(imxmd, link->remote_sd_node, - link->remote_devname); - if (!sink) { - v4l2_warn(&imxmd->v4l2_dev, "%s: no sink for %s:%d\n", - __func__, src->sd->name, link->local_pad); - return 0; - } - - source_pad = link->local_pad; - sink_pad = link->remote_pad; - - v4l2_info(&imxmd->v4l2_dev, "%s: %s:%d -> %s:%d\n", __func__, - src->sd->name, source_pad, sink->sd->name, sink_pad); - - ret = media_create_pad_link(&src->sd->entity, source_pad, - &sink->sd->entity, sink_pad, 0); - if (ret) - v4l2_err(&imxmd->v4l2_dev, - "create_pad_link failed: %d\n", ret); - - return ret; -} - -/* - * create the media links from all imx-media pads and their links. + * create the media links from all pads and their links. * Called after all subdevs have registered. */ static int imx_media_create_links(struct imx_media_dev *imxmd) { struct imx_media_subdev *imxsd; - struct imx_media_link *link; - struct imx_media_pad *pad; - int num_pads, i, j, k; - int ret = 0; + struct v4l2_subdev *sd; + int i, ret; for (i = 0; i < imxmd->num_subdevs; i++) { imxsd = &imxmd->subdev[i]; - num_pads = imxsd->num_sink_pads + imxsd->num_src_pads; + sd = imxsd->sd; - for (j = 0; j < num_pads; j++) { - pad = &imxsd->pad[j]; - - /* only create the source->sink links */ - if (!(pad->pad.flags & MEDIA_PAD_FL_SOURCE)) - continue; - - for (k = 0; k < pad->num_links; k++) { - link = &pad->link[k]; - - ret = imx_media_create_link(imxmd, imxsd, link); - if (ret) - goto out; - } + if (((sd->grp_id & IMX_MEDIA_GRP_ID_CSI) || imxsd->pdev)) { + /* this is an internal subdev or a CSI */ + ret = imx_media_create_internal_links(imxmd, imxsd); + if (ret) + return ret; + /* + * the CSIs straddle between the external and the IPU + * internal entities, so create the external links + * to the CSI sink pads. + */ + if (sd->grp_id & IMX_MEDIA_GRP_ID_CSI) + imx_media_create_csi_of_links(imxmd, imxsd); + } else { + /* this is an external fwnode subdev */ + imx_media_create_of_links(imxmd, imxsd); } } -out: - return ret; + return 0; } /* @@ -550,7 +469,6 @@ static int imx_media_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; - struct imx_media_subdev *csi[4] = {0}; struct imx_media_dev *imxmd; int ret; @@ -581,14 +499,14 @@ static int imx_media_probe(struct platform_device *pdev) dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd); - ret = imx_media_of_parse(imxmd, &csi, node); + ret = imx_media_add_of_subdevs(imxmd, node); if (ret) { v4l2_err(&imxmd->v4l2_dev, - "imx_media_of_parse failed with %d\n", ret); + "add_of_subdevs failed with %d\n", ret); goto unreg_dev; } - ret = imx_media_add_internal_subdevs(imxmd, csi); + ret = imx_media_add_internal_subdevs(imxmd); if (ret) { v4l2_err(&imxmd->v4l2_dev, "add_internal_subdevs failed with %d\n", ret); diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c b/drivers/staging/media/imx/imx-media-internal-sd.c index cdfbf40dfcbe..3e60df5f12d6 100644 --- a/drivers/staging/media/imx/imx-media-internal-sd.c +++ b/drivers/staging/media/imx/imx-media-internal-sd.c @@ -60,14 +60,19 @@ static const struct internal_subdev_id { }, }; +struct internal_subdev; + struct internal_link { - const struct internal_subdev_id *remote_id; + const struct internal_subdev *remote; + int local_pad; int remote_pad; }; +/* max links per internal-sd pad */ +#define MAX_INTERNAL_LINKS 8 + struct internal_pad { - bool devnode; /* does this pad link to a device node */ - struct internal_link link[IMX_MEDIA_MAX_LINKS]; + struct internal_link link[MAX_INTERNAL_LINKS]; }; static const struct internal_subdev { @@ -75,7 +80,7 @@ static const struct internal_subdev { struct internal_pad pad[IMX_MEDIA_MAX_PADS]; int num_sink_pads; int num_src_pads; -} internal_subdev[num_isd] = { +} int_subdev[num_isd] = { [isd_csi0] = { .id = &isd_id[isd_csi0], .num_sink_pads = CSI_NUM_SINK_PADS, @@ -83,17 +88,16 @@ static const struct internal_subdev { .pad[CSI_SRC_PAD_DIRECT] = { .link = { { - .remote_id = &isd_id[isd_ic_prp], + .local_pad = CSI_SRC_PAD_DIRECT, + .remote = &int_subdev[isd_ic_prp], .remote_pad = PRP_SINK_PAD, }, { - .remote_id = &isd_id[isd_vdic], + .local_pad = CSI_SRC_PAD_DIRECT, + .remote = &int_subdev[isd_vdic], .remote_pad = VDIC_SINK_PAD_DIRECT, }, }, }, - .pad[CSI_SRC_PAD_IDMAC] = { - .devnode = true, - }, }, [isd_csi1] = { @@ -103,30 +107,27 @@ static const struct internal_subdev { .pad[CSI_SRC_PAD_DIRECT] = { .link = { { - .remote_id = &isd_id[isd_ic_prp], + .local_pad = CSI_SRC_PAD_DIRECT, + .remote = &int_subdev[isd_ic_prp], .remote_pad = PRP_SINK_PAD, }, { - .remote_id = &isd_id[isd_vdic], + .local_pad = CSI_SRC_PAD_DIRECT, + .remote = &int_subdev[isd_vdic], .remote_pad = VDIC_SINK_PAD_DIRECT, }, }, }, - .pad[CSI_SRC_PAD_IDMAC] = { - .devnode = true, - }, }, [isd_vdic] = { .id = &isd_id[isd_vdic], .num_sink_pads = VDIC_NUM_SINK_PADS, .num_src_pads = VDIC_NUM_SRC_PADS, - .pad[VDIC_SINK_PAD_IDMAC] = { - .devnode = true, - }, .pad[VDIC_SRC_PAD_DIRECT] = { .link = { { - .remote_id = &isd_id[isd_ic_prp], + .local_pad = VDIC_SRC_PAD_DIRECT, + .remote = &int_subdev[isd_ic_prp], .remote_pad = PRP_SINK_PAD, }, }, @@ -140,7 +141,8 @@ static const struct internal_subdev { .pad[PRP_SRC_PAD_PRPENC] = { .link = { { - .remote_id = &isd_id[isd_ic_prpenc], + .local_pad = PRP_SRC_PAD_PRPENC, + .remote = &int_subdev[isd_ic_prpenc], .remote_pad = 0, }, }, @@ -148,7 +150,8 @@ static const struct internal_subdev { .pad[PRP_SRC_PAD_PRPVF] = { .link = { { - .remote_id = &isd_id[isd_ic_prpvf], + .local_pad = PRP_SRC_PAD_PRPVF, + .remote = &int_subdev[isd_ic_prpvf], .remote_pad = 0, }, }, @@ -159,68 +162,114 @@ static const struct internal_subdev { .id = &isd_id[isd_ic_prpenc], .num_sink_pads = PRPENCVF_NUM_SINK_PADS, .num_src_pads = PRPENCVF_NUM_SRC_PADS, - .pad[PRPENCVF_SRC_PAD] = { - .devnode = true, - }, }, [isd_ic_prpvf] = { .id = &isd_id[isd_ic_prpvf], .num_sink_pads = PRPENCVF_NUM_SINK_PADS, .num_src_pads = PRPENCVF_NUM_SRC_PADS, - .pad[PRPENCVF_SRC_PAD] = { - .devnode = true, - }, }, }; -/* form a device name given a group id and ipu id */ -static inline void isd_id_to_devname(char *devname, int sz, - const struct internal_subdev_id *id, - int ipu_id) +/* form a device name given an internal subdev and ipu id */ +static inline void isd_to_devname(char *devname, int sz, + const struct internal_subdev *isd, + int ipu_id) { - int pdev_id = ipu_id * num_isd + id->index; + int pdev_id = ipu_id * num_isd + isd->id->index; - snprintf(devname, sz, "%s.%d", id->name, pdev_id); + snprintf(devname, sz, "%s.%d", isd->id->name, pdev_id); } -/* adds the links from given internal subdev */ -static int add_internal_links(struct imx_media_dev *imxmd, - const struct internal_subdev *isd, - struct imx_media_subdev *imxsd, - int ipu_id) +static const struct internal_subdev *find_intsd_by_grp_id(u32 grp_id) { - int i, num_pads, ret; + enum isd_enum i; - num_pads = isd->num_sink_pads + isd->num_src_pads; + for (i = 0; i < num_isd; i++) { + const struct internal_subdev *isd = &int_subdev[i]; - for (i = 0; i < num_pads; i++) { - const struct internal_pad *intpad = &isd->pad[i]; - struct imx_media_pad *pad = &imxsd->pad[i]; - int j; + if (isd->id->grp_id == grp_id) + return isd; + } - /* init the pad flags for this internal subdev */ - pad->pad.flags = (i < isd->num_sink_pads) ? - MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; - /* export devnode pad flag to the subdevs */ - pad->devnode = intpad->devnode; + return NULL; +} + +static struct imx_media_subdev *find_sink(struct imx_media_dev *imxmd, + struct imx_media_subdev *src, + const struct internal_link *link) +{ + char sink_devname[32]; + int ipu_id; + + /* + * retrieve IPU id from subdev name, note: can't get this from + * struct imx_media_internal_sd_platformdata because if src is + * a CSI, it has different struct ipu_client_platformdata which + * does not contain IPU id. + */ + if (sscanf(src->sd->name, "ipu%d", &ipu_id) != 1) + return NULL; + + isd_to_devname(sink_devname, sizeof(sink_devname), + link->remote, ipu_id - 1); + + return imx_media_find_async_subdev(imxmd, NULL, sink_devname); +} + +static int create_ipu_internal_link(struct imx_media_dev *imxmd, + struct imx_media_subdev *src, + const struct internal_link *link) +{ + struct imx_media_subdev *sink; + int ret; + + sink = find_sink(imxmd, src, link); + if (!sink) + return -ENODEV; + + v4l2_info(&imxmd->v4l2_dev, "%s:%d -> %s:%d\n", + src->sd->name, link->local_pad, + sink->sd->name, link->remote_pad); + + ret = media_create_pad_link(&src->sd->entity, link->local_pad, + &sink->sd->entity, link->remote_pad, 0); + if (ret) + v4l2_err(&imxmd->v4l2_dev, + "create_pad_link failed: %d\n", ret); + + return ret; +} + +int imx_media_create_internal_links(struct imx_media_dev *imxmd, + struct imx_media_subdev *imxsd) +{ + struct v4l2_subdev *sd = imxsd->sd; + const struct internal_subdev *intsd; + const struct internal_pad *intpad; + const struct internal_link *link; + struct media_pad *pad; + int i, j, ret; + + intsd = find_intsd_by_grp_id(imxsd->sd->grp_id); + if (!intsd) + return -ENODEV; + + /* create the source->sink links */ + for (i = 0; i < sd->entity.num_pads; i++) { + intpad = &intsd->pad[i]; + pad = &sd->entity.pads[i]; + + if (!(pad->flags & MEDIA_PAD_FL_SOURCE)) + continue; for (j = 0; ; j++) { - const struct internal_link *link; - char remote_devname[32]; - link = &intpad->link[j]; - if (!link->remote_id) + if (!link->remote) break; - isd_id_to_devname(remote_devname, - sizeof(remote_devname), - link->remote_id, ipu_id); - - ret = imx_media_add_pad_link(imxmd, pad, - NULL, remote_devname, - i, link->remote_pad); + ret = create_ipu_internal_link(imxmd, imxsd, link); if (ret) return ret; } @@ -230,10 +279,9 @@ static int add_internal_links(struct imx_media_dev *imxmd, } /* register an internal subdev as a platform device */ -static struct imx_media_subdev * -add_internal_subdev(struct imx_media_dev *imxmd, - const struct internal_subdev *isd, - int ipu_id) +static int add_internal_subdev(struct imx_media_dev *imxmd, + const struct internal_subdev *isd, + int ipu_id) { struct imx_media_internal_sd_platformdata pdata; struct platform_device_info pdevinfo = {0}; @@ -258,73 +306,58 @@ add_internal_subdev(struct imx_media_dev *imxmd, pdev = platform_device_register_full(&pdevinfo); if (IS_ERR(pdev)) - return ERR_CAST(pdev); + return PTR_ERR(pdev); imxsd = imx_media_add_async_subdev(imxmd, NULL, pdev); if (IS_ERR(imxsd)) - return imxsd; + return PTR_ERR(imxsd); imxsd->num_sink_pads = isd->num_sink_pads; imxsd->num_src_pads = isd->num_src_pads; - return imxsd; + return 0; } /* adds the internal subdevs in one ipu */ -static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, - struct imx_media_subdev *csi0, - struct imx_media_subdev *csi1, - int ipu_id) +static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id) { enum isd_enum i; - int ret; for (i = 0; i < num_isd; i++) { - const struct internal_subdev *isd = &internal_subdev[i]; - struct imx_media_subdev *imxsd; + const struct internal_subdev *isd = &int_subdev[i]; + int ret; /* * the CSIs are represented in the device-tree, so those - * devices are added already, and are added to the async - * subdev list by of_parse_subdev(), so we are given those - * subdevs as csi0 and csi1. + * devices are already added to the async subdev list by + * of_parse_subdev(). */ switch (isd->id->grp_id) { case IMX_MEDIA_GRP_ID_CSI0: - imxsd = csi0; - break; case IMX_MEDIA_GRP_ID_CSI1: - imxsd = csi1; + ret = 0; break; default: - imxsd = add_internal_subdev(imxmd, isd, ipu_id); + ret = add_internal_subdev(imxmd, isd, ipu_id); break; } - if (IS_ERR(imxsd)) - return PTR_ERR(imxsd); - - /* add the links from this subdev */ - if (imxsd) { - ret = add_internal_links(imxmd, isd, imxsd, ipu_id); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } -int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd, - struct imx_media_subdev *csi[4]) +int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd) { int ret; - ret = add_ipu_internal_subdevs(imxmd, csi[0], csi[1], 0); + ret = add_ipu_internal_subdevs(imxmd, 0); if (ret) goto remove; - ret = add_ipu_internal_subdevs(imxmd, csi[2], csi[3], 1); + ret = add_ipu_internal_subdevs(imxmd, 1); if (ret) goto remove; diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c index 883ad8595c85..d35c99e9f049 100644 --- a/drivers/staging/media/imx/imx-media-of.c +++ b/drivers/staging/media/imx/imx-media-of.c @@ -20,20 +20,6 @@ #include