diff options
Diffstat (limited to 'drivers/media/platform/am437x/am437x-vpfe.c')
-rw-r--r-- | drivers/media/platform/am437x/am437x-vpfe.c | 82 |
1 files changed, 43 insertions, 39 deletions
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index cac6aec0ffa7..0b1a03b64b19 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -2423,30 +2423,32 @@ static const struct v4l2_async_notifier_operations vpfe_async_ops = { }; static struct vpfe_config * -vpfe_get_pdata(struct platform_device *pdev) +vpfe_get_pdata(struct vpfe_device *vpfe) { struct device_node *endpoint = NULL; struct v4l2_fwnode_endpoint bus_cfg; + struct device *dev = vpfe->pdev; struct vpfe_subdev_info *sdinfo; struct vpfe_config *pdata; unsigned int flags; unsigned int i; int err; - dev_dbg(&pdev->dev, "vpfe_get_pdata\n"); + dev_dbg(dev, "vpfe_get_pdata\n"); - if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) - return pdev->dev.platform_data; + v4l2_async_notifier_init(&vpfe->notifier); - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) + return dev->platform_data; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; for (i = 0; ; i++) { struct device_node *rem; - endpoint = of_graph_get_next_endpoint(pdev->dev.of_node, - endpoint); + endpoint = of_graph_get_next_endpoint(dev->of_node, endpoint); if (!endpoint) break; @@ -2474,16 +2476,16 @@ vpfe_get_pdata(struct platform_device *pdev) err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg); if (err) { - dev_err(&pdev->dev, "Could not parse the endpoint\n"); - goto done; + dev_err(dev, "Could not parse the endpoint\n"); + goto cleanup; } sdinfo->vpfe_param.bus_width = bus_cfg.bus.parallel.bus_width; if (sdinfo->vpfe_param.bus_width < 8 || sdinfo->vpfe_param.bus_width > 16) { - dev_err(&pdev->dev, "Invalid bus width.\n"); - goto done; + dev_err(dev, "Invalid bus width.\n"); + goto cleanup; } flags = bus_cfg.bus.parallel.flags; @@ -2496,29 +2498,25 @@ vpfe_get_pdata(struct platform_device *pdev) rem = of_graph_get_remote_port_parent(endpoint); if (!rem) { - dev_err(&pdev->dev, "Remote device at %pOF not found\n", + dev_err(dev, "Remote device at %pOF not found\n", endpoint); - goto done; + goto cleanup; } - pdata->asd[i] = devm_kzalloc(&pdev->dev, - sizeof(struct v4l2_async_subdev), - GFP_KERNEL); - if (!pdata->asd[i]) { + pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( + &vpfe->notifier, of_fwnode_handle(rem), + sizeof(struct v4l2_async_subdev)); + if (IS_ERR(pdata->asd[i])) { of_node_put(rem); - pdata = NULL; - goto done; + goto cleanup; } - - pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE; - pdata->asd[i]->match.fwnode = of_fwnode_handle(rem); - of_node_put(rem); } of_node_put(endpoint); return pdata; -done: +cleanup: + v4l2_async_notifier_cleanup(&vpfe->notifier); of_node_put(endpoint); return NULL; } @@ -2530,34 +2528,39 @@ done: */ static int vpfe_probe(struct platform_device *pdev) { - struct vpfe_config *vpfe_cfg = vpfe_get_pdata(pdev); + struct vpfe_config *vpfe_cfg; struct vpfe_device *vpfe; struct vpfe_ccdc *ccdc; struct resource *res; int ret; - if (!vpfe_cfg) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - } - vpfe = devm_kzalloc(&pdev->dev, sizeof(*vpfe), GFP_KERNEL); if (!vpfe) return -ENOMEM; vpfe->pdev = &pdev->dev; + + vpfe_cfg = vpfe_get_pdata(vpfe); + if (!vpfe_cfg) { + dev_err(&pdev->dev, "No platform data\n"); + return -EINVAL; + } + vpfe->cfg = vpfe_cfg; ccdc = &vpfe->ccdc; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ccdc->ccdc_cfg.base_addr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ccdc->ccdc_cfg.base_addr)) - return PTR_ERR(ccdc->ccdc_cfg.base_addr); + if (IS_ERR(ccdc->ccdc_cfg.base_addr)) { + ret = PTR_ERR(ccdc->ccdc_cfg.base_addr); + goto probe_out_cleanup; + } ret = platform_get_irq(pdev, 0); if (ret <= 0) { dev_err(&pdev->dev, "No IRQ resource\n"); - return -ENODEV; + ret = -ENODEV; + goto probe_out_cleanup; } vpfe->irq = ret; @@ -2565,14 +2568,15 @@ static int vpfe_probe(struct platform_device *pdev) "vpfe_capture0", vpfe); if (ret) { dev_err(&pdev->dev, "Unable to request interrupt\n"); - return -EINVAL; + ret = -EINVAL; + goto probe_out_cleanup; } ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev); if (ret) { vpfe_err(vpfe, "Unable to register v4l2 device.\n"); - return ret; + goto probe_out_cleanup; } /* set the driver data in platform device */ @@ -2596,11 +2600,8 @@ static int vpfe_probe(struct platform_device *pdev) goto probe_out_v4l2_unregister; } - vpfe->notifier.subdevs = vpfe->cfg->asd; - vpfe->notifier.num_subdevs = ARRAY_SIZE(vpfe->cfg->asd); vpfe->notifier.ops = &vpfe_async_ops; - ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, - &vpfe->notifier); + ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, &vpfe->notifier); if (ret) { vpfe_err(vpfe, "Error registering async notifier\n"); ret = -EINVAL; @@ -2611,6 +2612,8 @@ static int vpfe_probe(struct platform_device *pdev) probe_out_v4l2_unregister: v4l2_device_unregister(&vpfe->v4l2_dev); +probe_out_cleanup: + v4l2_async_notifier_cleanup(&vpfe->notifier); return ret; } @@ -2626,6 +2629,7 @@ static int vpfe_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); v4l2_async_notifier_unregister(&vpfe->notifier); + v4l2_async_notifier_cleanup(&vpfe->notifier); v4l2_device_unregister(&vpfe->v4l2_dev); video_unregister_device(&vpfe->video_dev); |