diff options
Diffstat (limited to 'drivers/media/platform/vimc/vimc-core.c')
-rw-r--r-- | drivers/media/platform/vimc/vimc-core.c | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/drivers/media/platform/vimc/vimc-core.c b/drivers/media/platform/vimc/vimc-core.c index 64ac0e6ef29c..339126e565dc 100644 --- a/drivers/media/platform/vimc/vimc-core.c +++ b/drivers/media/platform/vimc/vimc-core.c @@ -48,48 +48,51 @@ static struct vimc_ent_config ent_config[] = { { .name = "Sensor A", .add = vimc_sen_add, - .rm = vimc_sen_rm, + .release = vimc_sen_release, }, { .name = "Sensor B", .add = vimc_sen_add, - .rm = vimc_sen_rm, + .release = vimc_sen_release, }, { .name = "Debayer A", .add = vimc_deb_add, - .rm = vimc_deb_rm, + .release = vimc_deb_release, }, { .name = "Debayer B", .add = vimc_deb_add, - .rm = vimc_deb_rm, + .release = vimc_deb_release, }, { .name = "Raw Capture 0", .add = vimc_cap_add, - .rm = vimc_cap_rm, + .unregister = vimc_cap_unregister, + .release = vimc_cap_release, }, { .name = "Raw Capture 1", .add = vimc_cap_add, - .rm = vimc_cap_rm, + .unregister = vimc_cap_unregister, + .release = vimc_cap_release, }, { /* TODO: change this to vimc-input when it is implemented */ .name = "RGB/YUV Input", .add = vimc_sen_add, - .rm = vimc_sen_rm, + .release = vimc_sen_release, }, { .name = "Scaler", .add = vimc_sca_add, - .rm = vimc_sca_rm, + .release = vimc_sca_release, }, { .name = "RGB/YUV Capture", .add = vimc_cap_add, - .rm = vimc_cap_rm, + .unregister = vimc_cap_unregister, + .release = vimc_cap_release, }, }; @@ -175,13 +178,33 @@ static int vimc_add_subdevs(struct vimc_device *vimc) return 0; } -static void vimc_rm_subdevs(struct vimc_device *vimc) +static void vimc_release_subdevs(struct vimc_device *vimc) { unsigned int i; for (i = 0; i < vimc->pipe_cfg->num_ents; i++) if (vimc->ent_devs[i]) - vimc->pipe_cfg->ents[i].rm(vimc, vimc->ent_devs[i]); + vimc->pipe_cfg->ents[i].release(vimc->ent_devs[i]); +} + +static void vimc_unregister_subdevs(struct vimc_device *vimc) +{ + unsigned int i; + + for (i = 0; i < vimc->pipe_cfg->num_ents; i++) + if (vimc->ent_devs[i] && vimc->pipe_cfg->ents[i].unregister) + vimc->pipe_cfg->ents[i].unregister(vimc->ent_devs[i]); +} + +static void vimc_v4l2_dev_release(struct v4l2_device *v4l2_dev) +{ + struct vimc_device *vimc = + container_of(v4l2_dev, struct vimc_device, v4l2_dev); + + vimc_release_subdevs(vimc); + media_device_cleanup(&vimc->mdev); + kfree(vimc->ent_devs); + kfree(vimc); } static int vimc_register_devices(struct vimc_device *vimc) @@ -195,7 +218,6 @@ static int vimc_register_devices(struct vimc_device *vimc) "v4l2 device register failed (err=%d)\n", ret); return ret; } - /* allocate ent_devs */ vimc->ent_devs = kcalloc(vimc->pipe_cfg->num_ents, sizeof(*vimc->ent_devs), GFP_KERNEL); @@ -236,9 +258,9 @@ static int vimc_register_devices(struct vimc_device *vimc) err_mdev_unregister: media_device_unregister(&vimc->mdev); - media_device_cleanup(&vimc->mdev); err_rm_subdevs: - vimc_rm_subdevs(vimc); + vimc_unregister_subdevs(vimc); + vimc_release_subdevs(vimc); kfree(vimc->ent_devs); err_v4l2_unregister: v4l2_device_unregister(&vimc->v4l2_dev); @@ -248,11 +270,9 @@ err_v4l2_unregister: static void vimc_unregister(struct vimc_device *vimc) { + vimc_unregister_subdevs(vimc); media_device_unregister(&vimc->mdev); - media_device_cleanup(&vimc->mdev); v4l2_device_unregister(&vimc->v4l2_dev); - kfree(vimc->ent_devs); - kfree(vimc); } static int vimc_probe(struct platform_device *pdev) @@ -285,7 +305,12 @@ static int vimc_probe(struct platform_device *pdev) kfree(vimc); return ret; } + /* + * the release cb is set only after successful registration. + * if the registration fails, we release directly from probe + */ + vimc->v4l2_dev.release = vimc_v4l2_dev_release; platform_set_drvdata(pdev, vimc); return 0; } @@ -296,8 +321,8 @@ static int vimc_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "remove"); - vimc_rm_subdevs(vimc); vimc_unregister(vimc); + v4l2_device_put(&vimc->v4l2_dev); return 0; } |