Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: staging/imx: remove static subdev arrays

For more complex OF graphs, there will be more async subdevices
registered. Remove the static subdev[IMX_MEDIA_MAX_SUBDEVS] array,
so that imx-media places no limits on the number of async subdevs
that can be added and registered.

There were two uses for 'struct imx_media_subdev'. First was to act
as the async subdev list to be passed to v4l2_async_notifier_register().

Second was to aid in inheriting subdev controls to the capture devices,
and this is done by creating a list of capture devices that can be reached
from a subdev's source pad. So 'struct imx_media_subdev' also contained
a static array of 'struct imx_media_pad' for placing the capture device
lists at each pad.

'struct imx_media_subdev' has been completely removed. Instead, at async
completion, allocate an array of 'struct imx_media_pad' and attach it to
the subdev's host_priv pointer, in order to support subdev controls
inheritance.

Likewise, remove static async_ptrs[IMX_MEDIA_MAX_SUBDEVS] array.
Instead, allocate a 'struct imx_media_async_subdev' when forming
the async list, and add it to an asd_list list_head in
imx_media_add_async_subdev(). At async completion, allocate the
asd pointer list and pull the asd's off asd_list for
v4l2_async_notifier_register().

Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Steve Longerbeam and committed by
Mauro Carvalho Chehab
9f6a0c59 4eef678d

+216 -218
+2 -2
drivers/staging/media/imx/imx-ic-prp.c
··· 300 300 { 301 301 struct imx_ic_priv *ic_priv = v4l2_get_subdevdata(sd); 302 302 struct prp_priv *priv = ic_priv->prp_priv; 303 - struct imx_media_subdev *csi; 303 + struct v4l2_subdev *csi; 304 304 int ret; 305 305 306 306 ret = v4l2_subdev_link_validate_default(sd, link, ··· 333 333 } 334 334 335 335 if (csi) { 336 - switch (csi->sd->grp_id) { 336 + switch (csi->grp_id) { 337 337 case IMX_MEDIA_GRP_ID_CSI0: 338 338 priv->csi_id = 0; 339 339 break;
+4 -5
drivers/staging/media/imx/imx-media-csi.c
··· 138 138 struct v4l2_fwnode_endpoint *ep) 139 139 { 140 140 struct device_node *endpoint, *port; 141 - struct imx_media_subdev *imxsd; 142 141 struct media_entity *src; 143 142 struct v4l2_subdev *sd; 144 143 struct media_pad *pad; ··· 153 154 * CSI-2 receiver if it is in the path, otherwise stay 154 155 * with video mux. 155 156 */ 156 - imxsd = imx_media_find_upstream_subdev(priv->md, src, 157 - IMX_MEDIA_GRP_ID_CSI2); 158 - if (!IS_ERR(imxsd)) 159 - src = &imxsd->sd->entity; 157 + sd = imx_media_find_upstream_subdev(priv->md, src, 158 + IMX_MEDIA_GRP_ID_CSI2); 159 + if (!IS_ERR(sd)) 160 + src = &sd->entity; 160 161 } 161 162 162 163 /* get source pad of entity directly upstream from src */
+120 -95
drivers/staging/media/imx/imx-media-dev.c
··· 33 33 } 34 34 35 35 /* 36 - * Find a subdev by fwnode or device name. This is called during 36 + * Find an asd by fwnode or device name. This is called during 37 37 * driver load to form the async subdev list and bind them. 38 38 */ 39 - struct imx_media_subdev * 40 - imx_media_find_async_subdev(struct imx_media_dev *imxmd, 41 - struct fwnode_handle *fwnode, 42 - const char *devname) 39 + static struct v4l2_async_subdev * 40 + find_async_subdev(struct imx_media_dev *imxmd, 41 + struct fwnode_handle *fwnode, 42 + const char *devname) 43 43 { 44 - struct imx_media_subdev *imxsd; 45 - int i; 44 + struct imx_media_async_subdev *imxasd; 45 + struct v4l2_async_subdev *asd; 46 46 47 - for (i = 0; i < imxmd->subdev_notifier.num_subdevs; i++) { 48 - imxsd = &imxmd->subdev[i]; 49 - switch (imxsd->asd.match_type) { 47 + list_for_each_entry(imxasd, &imxmd->asd_list, list) { 48 + asd = &imxasd->asd; 49 + switch (asd->match_type) { 50 50 case V4L2_ASYNC_MATCH_FWNODE: 51 - if (fwnode && imxsd->asd.match.fwnode.fwnode == fwnode) 52 - return imxsd; 51 + if (fwnode && asd->match.fwnode.fwnode == fwnode) 52 + return asd; 53 53 break; 54 54 case V4L2_ASYNC_MATCH_DEVNAME: 55 - if (devname && 56 - !strcmp(imxsd->asd.match.device_name.name, devname)) 57 - return imxsd; 55 + if (devname && !strcmp(asd->match.device_name.name, 56 + devname)) 57 + return asd; 58 58 break; 59 59 default: 60 60 break; ··· 72 72 * given platform_device. This is called during driver load when 73 73 * forming the async subdev list. 74 74 */ 75 - struct imx_media_subdev * 76 - imx_media_add_async_subdev(struct imx_media_dev *imxmd, 77 - struct fwnode_handle *fwnode, 78 - struct platform_device *pdev) 75 + int imx_media_add_async_subdev(struct imx_media_dev *imxmd, 76 + struct fwnode_handle *fwnode, 77 + struct platform_device *pdev) 79 78 { 80 79 struct device_node *np = to_of_node(fwnode); 81 - struct imx_media_subdev *imxsd; 80 + struct imx_media_async_subdev *imxasd; 82 81 struct v4l2_async_subdev *asd; 83 82 const char *devname = NULL; 84 - int sd_idx; 83 + int ret = 0; 85 84 86 85 mutex_lock(&imxmd->mutex); 87 86 88 87 if (pdev) 89 88 devname = dev_name(&pdev->dev); 90 89 91 - /* return -EEXIST if this subdev already added */ 92 - if (imx_media_find_async_subdev(imxmd, fwnode, devname)) { 90 + /* return -EEXIST if this asd already added */ 91 + if (find_async_subdev(imxmd, fwnode, devname)) { 93 92 dev_dbg(imxmd->md.dev, "%s: already added %s\n", 94 93 __func__, np ? np->name : devname); 95 - imxsd = ERR_PTR(-EEXIST); 94 + ret = -EEXIST; 96 95 goto out; 97 96 } 98 97 99 - sd_idx = imxmd->subdev_notifier.num_subdevs; 100 - if (sd_idx >= IMX_MEDIA_MAX_SUBDEVS) { 101 - dev_err(imxmd->md.dev, "%s: too many subdevs! can't add %s\n", 102 - __func__, np ? np->name : devname); 103 - imxsd = ERR_PTR(-ENOSPC); 98 + imxasd = devm_kzalloc(imxmd->md.dev, sizeof(*imxasd), GFP_KERNEL); 99 + if (!imxasd) { 100 + ret = -ENOMEM; 104 101 goto out; 105 102 } 103 + asd = &imxasd->asd; 106 104 107 - imxsd = &imxmd->subdev[sd_idx]; 108 - 109 - asd = &imxsd->asd; 110 105 if (fwnode) { 111 106 asd->match_type = V4L2_ASYNC_MATCH_FWNODE; 112 107 asd->match.fwnode.fwnode = fwnode; 113 108 } else { 114 109 asd->match_type = V4L2_ASYNC_MATCH_DEVNAME; 115 110 asd->match.device_name.name = devname; 116 - imxsd->pdev = pdev; 111 + imxasd->pdev = pdev; 117 112 } 118 113 119 - imxmd->async_ptrs[sd_idx] = asd; 114 + list_add_tail(&imxasd->list, &imxmd->asd_list); 115 + 120 116 imxmd->subdev_notifier.num_subdevs++; 121 117 122 118 dev_dbg(imxmd->md.dev, "%s: added %s, match type %s\n", ··· 120 124 121 125 out: 122 126 mutex_unlock(&imxmd->mutex); 123 - return imxsd; 127 + return ret; 124 128 } 125 129 126 130 /* ··· 158 162 struct v4l2_async_subdev *asd) 159 163 { 160 164 struct imx_media_dev *imxmd = notifier2dev(notifier); 161 - struct imx_media_subdev *imxsd; 162 165 int ret = 0; 163 166 164 167 mutex_lock(&imxmd->mutex); 165 168 166 - imxsd = imx_media_find_async_subdev(imxmd, sd->fwnode, 167 - dev_name(sd->dev)); 168 - if (!imxsd) { 169 - ret = -EINVAL; 170 - goto out; 171 - } 172 - 173 169 if (sd->grp_id & IMX_MEDIA_GRP_ID_CSI) { 174 170 ret = imx_media_get_ipu(imxmd, sd); 175 171 if (ret) 176 - goto out_unlock; 172 + goto out; 177 173 } 178 174 179 - /* attach the subdev */ 180 - imxsd->sd = sd; 175 + v4l2_info(&imxmd->v4l2_dev, "subdev %s bound\n", sd->name); 181 176 out: 182 - if (ret) 183 - v4l2_warn(&imxmd->v4l2_dev, 184 - "Received unknown subdev %s\n", sd->name); 185 - else 186 - v4l2_info(&imxmd->v4l2_dev, 187 - "Registered subdev %s\n", sd->name); 188 - 189 - out_unlock: 190 177 mutex_unlock(&imxmd->mutex); 191 178 return ret; 192 179 } 193 180 194 181 /* 195 - * create the media links from all pads and their links. 196 - * Called after all subdevs have registered. 182 + * create the media links for all subdevs that registered async. 183 + * Called after all async subdevs have bound. 197 184 */ 198 - static int imx_media_create_links(struct imx_media_dev *imxmd) 185 + static int imx_media_create_links(struct v4l2_async_notifier *notifier) 199 186 { 200 - struct imx_media_subdev *imxsd; 187 + struct imx_media_dev *imxmd = notifier2dev(notifier); 201 188 struct v4l2_subdev *sd; 202 - int i, ret; 189 + int ret; 203 190 204 - for (i = 0; i < imxmd->num_subdevs; i++) { 205 - imxsd = &imxmd->subdev[i]; 206 - sd = imxsd->sd; 207 - 208 - if (((sd->grp_id & IMX_MEDIA_GRP_ID_CSI) || imxsd->pdev)) { 209 - /* this is an internal subdev or a CSI */ 210 - ret = imx_media_create_internal_links(imxmd, imxsd); 191 + /* 192 + * Only links are created between subdevices that are known 193 + * to the async notifier. If there are other non-async subdevices, 194 + * they were created internally by some subdevice (smiapp is one 195 + * example). In those cases it is expected the subdevice is 196 + * responsible for creating those internal links. 197 + */ 198 + list_for_each_entry(sd, &notifier->done, async_list) { 199 + switch (sd->grp_id) { 200 + case IMX_MEDIA_GRP_ID_VDIC: 201 + case IMX_MEDIA_GRP_ID_IC_PRP: 202 + case IMX_MEDIA_GRP_ID_IC_PRPENC: 203 + case IMX_MEDIA_GRP_ID_IC_PRPVF: 204 + case IMX_MEDIA_GRP_ID_CSI0: 205 + case IMX_MEDIA_GRP_ID_CSI1: 206 + ret = imx_media_create_internal_links(imxmd, sd); 211 207 if (ret) 212 208 return ret; 213 209 /* ··· 208 220 * to the CSI sink pads. 209 221 */ 210 222 if (sd->grp_id & IMX_MEDIA_GRP_ID_CSI) 211 - imx_media_create_csi_of_links(imxmd, imxsd); 212 - } else { 223 + imx_media_create_csi_of_links(imxmd, sd); 224 + break; 225 + default: 213 226 /* this is an external fwnode subdev */ 214 - imx_media_create_of_links(imxmd, imxsd); 227 + imx_media_create_of_links(imxmd, sd); 228 + break; 215 229 } 216 230 } 217 231 ··· 229 239 struct media_pad *srcpad) 230 240 { 231 241 struct media_entity *entity = srcpad->entity; 232 - struct imx_media_subdev *imxsd; 233 242 struct imx_media_pad *imxpad; 234 243 struct media_link *link; 235 244 struct v4l2_subdev *sd; ··· 239 250 return 0; 240 251 241 252 sd = media_entity_to_v4l2_subdev(entity); 242 - imxsd = imx_media_find_subdev_by_sd(imxmd, sd); 243 - if (IS_ERR(imxsd)) { 244 - v4l2_err(&imxmd->v4l2_dev, "failed to find subdev for entity %s, sd %p err %ld\n", 245 - entity->name, sd, PTR_ERR(imxsd)); 253 + 254 + imxpad = to_imx_media_pad(sd, srcpad->index); 255 + if (!imxpad) { 256 + v4l2_warn(&imxmd->v4l2_dev, "%s:%u has no vdev list!\n", 257 + entity->name, srcpad->index); 258 + /* 259 + * shouldn't happen, but no reason to fail driver load, 260 + * just skip this entity. 261 + */ 246 262 return 0; 247 263 } 248 264 249 - imxpad = &imxsd->pad[srcpad->index]; 250 265 vdev_idx = imxpad->num_vdevs; 251 266 252 267 /* just return if we've been here before */ ··· 289 296 return 0; 290 297 } 291 298 299 + static int imx_media_alloc_pad_vdev_lists(struct imx_media_dev *imxmd) 300 + { 301 + struct imx_media_pad *imxpads; 302 + struct media_entity *entity; 303 + struct v4l2_subdev *sd; 304 + 305 + list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { 306 + entity = &sd->entity; 307 + imxpads = devm_kzalloc(imxmd->md.dev, 308 + entity->num_pads * sizeof(*imxpads), 309 + GFP_KERNEL); 310 + if (!imxpads) 311 + return -ENOMEM; 312 + 313 + /* attach imxpads to the subdev's host private pointer */ 314 + sd->host_priv = imxpads; 315 + } 316 + 317 + return 0; 318 + } 319 + 292 320 /* form the vdev lists in all imx-media source pads */ 293 321 static int imx_media_create_pad_vdev_lists(struct imx_media_dev *imxmd) 294 322 { 295 323 struct imx_media_video_dev *vdev; 296 324 struct media_link *link; 297 325 int i, ret; 326 + 327 + ret = imx_media_alloc_pad_vdev_lists(imxmd); 328 + if (ret) 329 + return ret; 298 330 299 331 for (i = 0; i < imxmd->num_vdevs; i++) { 300 332 vdev = imxmd->vdev[i]; ··· 337 319 static int imx_media_probe_complete(struct v4l2_async_notifier *notifier) 338 320 { 339 321 struct imx_media_dev *imxmd = notifier2dev(notifier); 340 - int i, ret; 322 + int ret; 341 323 342 324 mutex_lock(&imxmd->mutex); 343 325 344 - /* make sure all subdevs were bound */ 345 - for (i = 0; i < imxmd->num_subdevs; i++) { 346 - if (!imxmd->subdev[i].sd) { 347 - v4l2_err(&imxmd->v4l2_dev, "unbound subdev!\n"); 348 - ret = -ENODEV; 349 - goto unlock; 350 - } 351 - } 352 - 353 - ret = imx_media_create_links(imxmd); 326 + ret = imx_media_create_links(notifier); 354 327 if (ret) 355 328 goto unlock; 356 329 ··· 410 401 unsigned int notification) 411 402 { 412 403 struct media_entity *source = link->source->entity; 413 - struct imx_media_subdev *imxsd; 414 404 struct imx_media_pad *imxpad; 415 405 struct imx_media_dev *imxmd; 416 406 struct video_device *vfd; ··· 429 421 430 422 imxmd = dev_get_drvdata(sd->v4l2_dev->dev); 431 423 432 - imxsd = imx_media_find_subdev_by_sd(imxmd, sd); 433 - if (IS_ERR(imxsd)) 434 - return PTR_ERR(imxsd); 435 - imxpad = &imxsd->pad[pad_idx]; 424 + imxpad = to_imx_media_pad(sd, pad_idx); 425 + if (!imxpad) { 426 + /* shouldn't happen, but no reason to fail link setup */ 427 + return 0; 428 + } 436 429 437 430 /* 438 431 * Before disabling a link, reset controls for all video ··· 477 468 { 478 469 struct device *dev = &pdev->dev; 479 470 struct device_node *node = dev->of_node; 471 + struct imx_media_async_subdev *imxasd; 472 + struct v4l2_async_subdev **subdevs; 480 473 struct imx_media_dev *imxmd; 481 - int ret; 474 + int num_subdevs, i, ret; 482 475 483 476 imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL); 484 477 if (!imxmd) ··· 509 498 510 499 dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd); 511 500 501 + INIT_LIST_HEAD(&imxmd->asd_list); 502 + 512 503 ret = imx_media_add_of_subdevs(imxmd, node); 513 504 if (ret) { 514 505 v4l2_err(&imxmd->v4l2_dev, ··· 525 512 goto unreg_dev; 526 513 } 527 514 515 + num_subdevs = imxmd->subdev_notifier.num_subdevs; 516 + 528 517 /* no subdevs? just bail */ 529 - imxmd->num_subdevs = imxmd->subdev_notifier.num_subdevs; 530 - if (imxmd->num_subdevs == 0) { 518 + if (num_subdevs == 0) { 531 519 ret = -ENODEV; 532 520 goto unreg_dev; 533 521 } 534 522 523 + subdevs = devm_kzalloc(imxmd->md.dev, sizeof(*subdevs) * num_subdevs, 524 + GFP_KERNEL); 525 + if (!subdevs) { 526 + ret = -ENOMEM; 527 + goto unreg_dev; 528 + } 529 + 530 + i = 0; 531 + list_for_each_entry(imxasd, &imxmd->asd_list, list) 532 + subdevs[i++] = &imxasd->asd; 533 + 535 534 /* prepare the async subdev notifier and register it */ 536 - imxmd->subdev_notifier.subdevs = imxmd->async_ptrs; 535 + imxmd->subdev_notifier.subdevs = subdevs; 537 536 imxmd->subdev_notifier.ops = &imx_media_subdev_ops; 538 537 ret = v4l2_async_notifier_register(&imxmd->v4l2_dev, 539 538 &imxmd->subdev_notifier);
+23 -28
drivers/staging/media/imx/imx-media-internal-sd.c
··· 68 68 int remote_pad; 69 69 }; 70 70 71 + /* max pads per internal-sd */ 72 + #define MAX_INTERNAL_PADS 8 71 73 /* max links per internal-sd pad */ 72 74 #define MAX_INTERNAL_LINKS 8 73 75 ··· 79 77 80 78 static const struct internal_subdev { 81 79 const struct internal_subdev_id *id; 82 - struct internal_pad pad[IMX_MEDIA_MAX_PADS]; 80 + struct internal_pad pad[MAX_INTERNAL_PADS]; 83 81 } int_subdev[num_isd] = { 84 82 [isd_csi0] = { 85 83 .id = &isd_id[isd_csi0], ··· 183 181 return NULL; 184 182 } 185 183 186 - static struct imx_media_subdev *find_sink(struct imx_media_dev *imxmd, 187 - struct imx_media_subdev *src, 188 - const struct internal_link *link) 184 + static struct v4l2_subdev *find_sink(struct imx_media_dev *imxmd, 185 + struct v4l2_subdev *src, 186 + const struct internal_link *link) 189 187 { 190 188 char sink_devname[32]; 191 189 int ipu_id; ··· 196 194 * a CSI, it has different struct ipu_client_platformdata which 197 195 * does not contain IPU id. 198 196 */ 199 - if (sscanf(src->sd->name, "ipu%d", &ipu_id) != 1) 197 + if (sscanf(src->name, "ipu%d", &ipu_id) != 1) 200 198 return NULL; 201 199 202 200 isd_to_devname(sink_devname, sizeof(sink_devname), 203 201 link->remote, ipu_id - 1); 204 202 205 - return imx_media_find_async_subdev(imxmd, NULL, sink_devname); 203 + return imx_media_find_subdev_by_devname(imxmd, sink_devname); 206 204 } 207 205 208 206 static int create_ipu_internal_link(struct imx_media_dev *imxmd, 209 - struct imx_media_subdev *src, 207 + struct v4l2_subdev *src, 210 208 const struct internal_link *link) 211 209 { 212 - struct imx_media_subdev *sink; 210 + struct v4l2_subdev *sink; 213 211 int ret; 214 212 215 213 sink = find_sink(imxmd, src, link); ··· 217 215 return -ENODEV; 218 216 219 217 v4l2_info(&imxmd->v4l2_dev, "%s:%d -> %s:%d\n", 220 - src->sd->name, link->local_pad, 221 - sink->sd->name, link->remote_pad); 218 + src->name, link->local_pad, 219 + sink->name, link->remote_pad); 222 220 223 - ret = media_create_pad_link(&src->sd->entity, link->local_pad, 224 - &sink->sd->entity, link->remote_pad, 0); 221 + ret = media_create_pad_link(&src->entity, link->local_pad, 222 + &sink->entity, link->remote_pad, 0); 225 223 if (ret) 226 224 v4l2_err(&imxmd->v4l2_dev, 227 225 "create_pad_link failed: %d\n", ret); ··· 230 228 } 231 229 232 230 int imx_media_create_internal_links(struct imx_media_dev *imxmd, 233 - struct imx_media_subdev *imxsd) 231 + struct v4l2_subdev *sd) 234 232 { 235 - struct v4l2_subdev *sd = imxsd->sd; 236 233 const struct internal_subdev *intsd; 237 234 const struct internal_pad *intpad; 238 235 const struct internal_link *link; 239 236 struct media_pad *pad; 240 237 int i, j, ret; 241 238 242 - intsd = find_intsd_by_grp_id(imxsd->sd->grp_id); 239 + intsd = find_intsd_by_grp_id(sd->grp_id); 243 240 if (!intsd) 244 241 return -ENODEV; 245 242 ··· 256 255 if (!link->remote) 257 256 break; 258 257 259 - ret = create_ipu_internal_link(imxmd, imxsd, link); 258 + ret = create_ipu_internal_link(imxmd, sd, link); 260 259 if (ret) 261 260 return ret; 262 261 } ··· 272 271 { 273 272 struct imx_media_internal_sd_platformdata pdata; 274 273 struct platform_device_info pdevinfo = {0}; 275 - struct imx_media_subdev *imxsd; 276 274 struct platform_device *pdev; 277 275 278 276 pdata.grp_id = isd->id->grp_id; ··· 294 294 if (IS_ERR(pdev)) 295 295 return PTR_ERR(pdev); 296 296 297 - imxsd = imx_media_add_async_subdev(imxmd, NULL, pdev); 298 - if (IS_ERR(imxsd)) 299 - return PTR_ERR(imxsd); 300 - 301 - return 0; 297 + return imx_media_add_async_subdev(imxmd, NULL, pdev); 302 298 } 303 299 304 300 /* adds the internal subdevs in one ipu */ ··· 349 353 350 354 void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd) 351 355 { 352 - struct imx_media_subdev *imxsd; 353 - int i; 356 + struct imx_media_async_subdev *imxasd; 354 357 355 - for (i = 0; i < imxmd->subdev_notifier.num_subdevs; i++) { 356 - imxsd = &imxmd->subdev[i]; 357 - if (!imxsd->pdev) 358 + list_for_each_entry(imxasd, &imxmd->asd_list, list) { 359 + if (!imxasd->pdev) 358 360 continue; 359 - platform_device_unregister(imxsd->pdev); 361 + 362 + platform_device_unregister(imxasd->pdev); 360 363 } 361 364 }
+13 -18
drivers/staging/media/imx/imx-media-of.c
··· 76 76 of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np, 77 77 bool is_csi_port) 78 78 { 79 - struct imx_media_subdev *imxsd; 80 79 int i, num_ports, ret; 81 80 82 81 if (!of_device_is_available(sd_np)) { ··· 86 87 } 87 88 88 89 /* register this subdev with async notifier */ 89 - imxsd = imx_media_add_async_subdev(imxmd, of_fwnode_handle(sd_np), 90 - NULL); 91 - ret = PTR_ERR_OR_ZERO(imxsd); 90 + ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(sd_np), 91 + NULL); 92 92 if (ret) { 93 93 if (ret == -EEXIST) { 94 94 /* already added, everything is fine */ ··· 157 159 } 158 160 159 161 /* 160 - * Create a single media link to/from imxsd using a fwnode link. 162 + * Create a single media link to/from sd using a fwnode link. 161 163 * 162 164 * NOTE: this function assumes an OF port node is equivalent to 163 165 * a media pad (port id equal to media pad index), and that an 164 166 * OF endpoint node is equivalent to a media link. 165 167 */ 166 168 static int create_of_link(struct imx_media_dev *imxmd, 167 - struct imx_media_subdev *imxsd, 169 + struct v4l2_subdev *sd, 168 170 struct v4l2_fwnode_link *link) 169 171 { 170 - struct v4l2_subdev *sd = imxsd->sd; 171 - struct imx_media_subdev *remote; 172 - struct v4l2_subdev *src, *sink; 172 + struct v4l2_subdev *remote, *src, *sink; 173 173 int src_pad, sink_pad; 174 174 175 175 if (link->local_port >= sd->entity.num_pads) 176 176 return -EINVAL; 177 177 178 - remote = imx_media_find_async_subdev(imxmd, link->remote_node, NULL); 178 + remote = imx_media_find_subdev_by_fwnode(imxmd, link->remote_node); 179 179 if (!remote) 180 180 return 0; 181 181 182 182 if (sd->entity.pads[link->local_port].flags & MEDIA_PAD_FL_SINK) { 183 - src = remote->sd; 183 + src = remote; 184 184 src_pad = link->remote_port; 185 185 sink = sd; 186 186 sink_pad = link->local_port; 187 187 } else { 188 188 src = sd; 189 189 src_pad = link->local_port; 190 - sink = remote->sd; 190 + sink = remote; 191 191 sink_pad = link->remote_port; 192 192 } 193 193 ··· 202 206 } 203 207 204 208 /* 205 - * Create media links to/from imxsd using its device-tree endpoints. 209 + * Create media links to/from sd using its device-tree endpoints. 206 210 */ 207 211 int imx_media_create_of_links(struct imx_media_dev *imxmd, 208 - struct imx_media_subdev *imxsd) 212 + struct v4l2_subdev *sd) 209 213 { 210 - struct v4l2_subdev *sd = imxsd->sd; 211 214 struct v4l2_fwnode_link link; 212 215 struct device_node *ep; 213 216 int ret; ··· 216 221 if (ret) 217 222 continue; 218 223 219 - ret = create_of_link(imxmd, imxsd, &link); 224 + ret = create_of_link(imxmd, sd, &link); 220 225 v4l2_fwnode_put_link(&link); 221 226 if (ret) 222 227 return ret; ··· 230 235 * using its device-tree endpoints. 231 236 */ 232 237 int imx_media_create_csi_of_links(struct imx_media_dev *imxmd, 233 - struct imx_media_subdev *csi) 238 + struct v4l2_subdev *csi) 234 239 { 235 - struct device_node *csi_np = csi->sd->dev->of_node; 240 + struct device_node *csi_np = csi->dev->of_node; 236 241 struct fwnode_handle *fwnode, *csi_ep; 237 242 struct v4l2_fwnode_link link; 238 243 struct device_node *ep;
+20 -23
drivers/staging/media/imx/imx-media-utils.c
··· 668 668 } 669 669 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name); 670 670 671 - struct imx_media_subdev * 672 - imx_media_find_subdev_by_sd(struct imx_media_dev *imxmd, 673 - struct v4l2_subdev *sd) 671 + struct v4l2_subdev * 672 + imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd, 673 + struct fwnode_handle *fwnode) 674 674 { 675 - struct imx_media_subdev *imxsd; 676 - int i; 675 + struct v4l2_subdev *sd; 677 676 678 - for (i = 0; i < imxmd->num_subdevs; i++) { 679 - imxsd = &imxmd->subdev[i]; 680 - if (sd == imxsd->sd) 681 - return imxsd; 677 + list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { 678 + if (sd->fwnode == fwnode) 679 + return sd; 682 680 } 683 681 684 - return ERR_PTR(-ENODEV); 682 + return NULL; 685 683 } 686 - EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_sd); 684 + EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_fwnode); 687 685 688 - struct imx_media_subdev * 689 - imx_media_find_subdev_by_id(struct imx_media_dev *imxmd, u32 grp_id) 686 + struct v4l2_subdev * 687 + imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd, 688 + const char *devname) 690 689 { 691 - struct imx_media_subdev *imxsd; 692 - int i; 690 + struct v4l2_subdev *sd; 693 691 694 - for (i = 0; i < imxmd->num_subdevs; i++) { 695 - imxsd = &imxmd->subdev[i]; 696 - if (imxsd->sd && imxsd->sd->grp_id == grp_id) 697 - return imxsd; 692 + list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { 693 + if (!strcmp(devname, dev_name(sd->dev))) 694 + return sd; 698 695 } 699 696 700 - return ERR_PTR(-ENODEV); 697 + return NULL; 701 698 } 702 - EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_id); 699 + EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname); 703 700 704 701 /* 705 702 * Adds a video device to the master video device list. This is called by ··· 839 842 * the current pipeline. 840 843 * Must be called with mdev->graph_mutex held. 841 844 */ 842 - struct imx_media_subdev * 845 + struct v4l2_subdev * 843 846 imx_media_find_upstream_subdev(struct imx_media_dev *imxmd, 844 847 struct media_entity *start_entity, 845 848 u32 grp_id) ··· 850 853 if (!sd) 851 854 return ERR_PTR(-ENODEV); 852 855 853 - return imx_media_find_subdev_by_sd(imxmd, sd); 856 + return sd; 854 857 } 855 858 EXPORT_SYMBOL_GPL(imx_media_find_upstream_subdev); 856 859
+34 -47
drivers/staging/media/imx/imx-media.h
··· 11 11 #ifndef _IMX_MEDIA_H 12 12 #define _IMX_MEDIA_H 13 13 14 + #include <linux/platform_device.h> 14 15 #include <media/v4l2-ctrls.h> 15 16 #include <media/v4l2-device.h> 16 17 #include <media/v4l2-fwnode.h> ··· 19 18 #include <media/videobuf2-dma-contig.h> 20 19 #include <video/imx-ipu-v3.h> 21 20 22 - /* 23 - * This is somewhat arbitrary, but we need at least: 24 - * - 4 video devices per IPU 25 - * - 3 IC subdevs per IPU 26 - * - 1 VDIC subdev per IPU 27 - * - 2 CSI subdevs per IPU 28 - * - 1 mipi-csi2 receiver subdev 29 - * - 2 video-mux subdevs 30 - * - 2 camera sensor subdevs per IPU (1 parallel, 1 mipi-csi2) 31 - * 32 - */ 33 21 /* max video devices */ 34 22 #define IMX_MEDIA_MAX_VDEVS 8 35 - /* max subdevices */ 36 - #define IMX_MEDIA_MAX_SUBDEVS 32 37 - /* max pads per subdev */ 38 - #define IMX_MEDIA_MAX_PADS 16 39 23 40 24 /* 41 25 * Pad definitions for the subdevs with multiple source or ··· 91 105 return container_of(vbuf, struct imx_media_buffer, vbuf); 92 106 } 93 107 108 + /* to support control inheritance to video devices */ 94 109 struct imx_media_pad { 95 110 /* 96 111 * list of video devices that can be reached from this pad, ··· 101 114 int num_vdevs; 102 115 }; 103 116 117 + static inline struct imx_media_pad * 118 + to_imx_media_pad(struct v4l2_subdev *sd, int pad_index) 119 + { 120 + struct imx_media_pad *imxpads = sd->host_priv; 121 + 122 + return imxpads ? &imxpads[pad_index] : NULL; 123 + } 124 + 104 125 struct imx_media_internal_sd_platformdata { 105 126 char sd_name[V4L2_SUBDEV_NAME_SIZE]; 106 127 u32 grp_id; 107 128 int ipu_id; 108 129 }; 109 130 110 - struct imx_media_subdev { 131 + 132 + struct imx_media_async_subdev { 111 133 struct v4l2_async_subdev asd; 112 - struct v4l2_subdev *sd; /* set when bound */ 113 - 114 - struct imx_media_pad pad[IMX_MEDIA_MAX_PADS]; 115 - 116 - /* the platform device if this is an IPU-internal subdev */ 134 + /* the platform device of IPU-internal subdevs */ 117 135 struct platform_device *pdev; 136 + struct list_head list; 118 137 }; 138 + 139 + static inline struct imx_media_async_subdev * 140 + to_imx_media_asd(struct v4l2_async_subdev *asd) 141 + { 142 + return container_of(asd, struct imx_media_async_subdev, asd); 143 + } 119 144 120 145 struct imx_media_dev { 121 146 struct media_device md; ··· 138 139 139 140 struct mutex mutex; /* protect elements below */ 140 141 141 - /* master subdevice list */ 142 - struct imx_media_subdev subdev[IMX_MEDIA_MAX_SUBDEVS]; 143 - int num_subdevs; 144 - 145 142 /* master video device list */ 146 143 struct imx_media_video_dev *vdev[IMX_MEDIA_MAX_VDEVS]; 147 144 int num_vdevs; ··· 146 151 struct ipu_soc *ipu[2]; 147 152 148 153 /* for async subdev registration */ 149 - struct v4l2_async_subdev *async_ptrs[IMX_MEDIA_MAX_SUBDEVS]; 154 + struct list_head asd_list; 150 155 struct v4l2_async_notifier subdev_notifier; 151 156 }; 152 157 ··· 167 172 const struct imx_media_pixfmt * 168 173 imx_media_find_ipu_format(u32 code, enum codespace_sel cs_sel); 169 174 int imx_media_enum_ipu_format(u32 *code, u32 index, enum codespace_sel cs_sel); 170 - 171 175 int imx_media_init_mbus_fmt(struct v4l2_mbus_framefmt *mbus, 172 176 u32 width, u32 height, u32 code, u32 field, 173 177 const struct imx_media_pixfmt **cc); ··· 180 186 struct v4l2_mbus_framefmt *mbus); 181 187 int imx_media_ipu_image_to_mbus_fmt(struct v4l2_mbus_framefmt *mbus, 182 188 struct ipu_image *image); 183 - 184 - struct imx_media_subdev * 185 - imx_media_find_async_subdev(struct imx_media_dev *imxmd, 186 - struct fwnode_handle *fwnode, 187 - const char *devname); 188 - struct imx_media_subdev * 189 - imx_media_add_async_subdev(struct imx_media_dev *imxmd, 190 - struct fwnode_handle *fwnode, 191 - struct platform_device *pdev); 192 - 189 + int imx_media_add_async_subdev(struct imx_media_dev *imxmd, 190 + struct fwnode_handle *fwnode, 191 + struct platform_device *pdev); 193 192 void imx_media_grp_id_to_sd_name(char *sd_name, int sz, 194 193 u32 grp_id, int ipu_id); 195 194 196 195 int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd); 197 196 int imx_media_create_internal_links(struct imx_media_dev *imxmd, 198 - struct imx_media_subdev *imxsd); 197 + struct v4l2_subdev *sd); 199 198 void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd); 200 199 201 - struct imx_media_subdev * 202 - imx_media_find_subdev_by_sd(struct imx_media_dev *imxmd, 203 - struct v4l2_subdev *sd); 204 - struct imx_media_subdev * 205 - imx_media_find_subdev_by_id(struct imx_media_dev *imxmd, 206 - u32 grp_id); 200 + struct v4l2_subdev * 201 + imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd, 202 + struct fwnode_handle *fwnode); 203 + struct v4l2_subdev * 204 + imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd, 205 + const char *devname); 207 206 int imx_media_add_video_device(struct imx_media_dev *imxmd, 208 207 struct imx_media_video_dev *vdev); 209 208 int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd, ··· 205 218 imx_media_find_upstream_pad(struct imx_media_dev *imxmd, 206 219 struct media_entity *start_entity, 207 220 u32 grp_id); 208 - struct imx_media_subdev * 221 + struct v4l2_subdev * 209 222 imx_media_find_upstream_subdev(struct imx_media_dev *imxmd, 210 223 struct media_entity *start_entity, 211 224 u32 grp_id); ··· 240 253 int imx_media_add_of_subdevs(struct imx_media_dev *dev, 241 254 struct device_node *np); 242 255 int imx_media_create_of_links(struct imx_media_dev *imxmd, 243 - struct imx_media_subdev *imxsd); 256 + struct v4l2_subdev *sd); 244 257 int imx_media_create_csi_of_links(struct imx_media_dev *imxmd, 245 - struct imx_media_subdev *csi); 258 + struct v4l2_subdev *csi); 246 259 247 260 /* imx-media-capture.c */ 248 261 struct imx_media_video_dev *