From 4a29b70907496aa9da79112ec31cf9cf2b972c3f Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Mon, 19 Jun 2017 14:00:18 -0300 Subject: [media] vimc: Subdevices as modules Change the core structure for adding subdevices in the topology. Instead of calling the specific create function for each subdevice, inject a child platform_device with the driver's name. Each type of node in the topology (sensor, capture, debayer, scaler) will register a platform_driver with the corresponding name through the component subsystem. Implementing a new subdevice type doesn't require vimc-core to be altered. This facilitates future implementation of dynamic entities, where hotpluging an entity in the topology is just a matter of registering/unregistering a platform_device in the system. It also facilitates other implementations of different nodes without touching the core code and remove the need of a header file for each type of node. Signed-off-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-sensor.c | 93 ++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 25 deletions(-) (limited to 'drivers/media/platform/vimc/vimc-sensor.c') diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index d4f97050b544..5ea7b0853936 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c @@ -15,18 +15,24 @@ * */ +#include #include #include +#include +#include #include #include #include #include -#include "vimc-sensor.h" +#include "vimc-common.h" + +#define VIMC_SEN_DRV_NAME "vimc-sensor" struct vimc_sen_device { struct vimc_ent_device ved; struct v4l2_subdev sd; + struct device *dev; struct tpg_data tpg; struct task_struct *kthread_sen; u8 *frame; @@ -166,7 +172,7 @@ static int vimc_sen_set_fmt(struct v4l2_subdev *sd, /* Set the new format */ vimc_sen_adjust_fmt(&fmt->format); - dev_dbg(vsen->sd.v4l2_dev->mdev->dev, "%s: format update: " + dev_dbg(vsen->dev, "%s: format update: " "old:%dx%d (0x%x, %d, %d, %d, %d) " "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vsen->sd.name, /* old */ @@ -252,8 +258,8 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable) vsen->kthread_sen = kthread_run(vimc_sen_tpg_thread, vsen, "%s-sen", vsen->sd.v4l2_dev->name); if (IS_ERR(vsen->kthread_sen)) { - dev_err(vsen->sd.v4l2_dev->dev, - "%s: kernel_thread() failed\n", vsen->sd.name); + dev_err(vsen->dev, "%s: kernel_thread() failed\n", + vsen->sd.name); vfree(vsen->frame); vsen->frame = NULL; return PTR_ERR(vsen->kthread_sen); @@ -285,8 +291,10 @@ static const struct v4l2_subdev_ops vimc_sen_ops = { .video = &vimc_sen_video_ops, }; -static void vimc_sen_destroy(struct vimc_ent_device *ved) +static void vimc_sen_comp_unbind(struct device *comp, struct device *master, + void *master_data) { + struct vimc_ent_device *ved = dev_get_drvdata(comp); struct vimc_sen_device *vsen = container_of(ved, struct vimc_sen_device, ved); @@ -295,36 +303,31 @@ static void vimc_sen_destroy(struct vimc_ent_device *ved) kfree(vsen); } -struct vimc_ent_device *vimc_sen_create(struct v4l2_device *v4l2_dev, - const char *const name, - u16 num_pads, - const unsigned long *pads_flag) +static int vimc_sen_comp_bind(struct device *comp, struct device *master, + void *master_data) { + struct v4l2_device *v4l2_dev = master_data; + struct vimc_platform_data *pdata = comp->platform_data; struct vimc_sen_device *vsen; - unsigned int i; int ret; - /* NOTE: a sensor node may be created with more then one pad */ - if (!name || !num_pads || !pads_flag) - return ERR_PTR(-EINVAL); - - /* check if all pads are sources */ - for (i = 0; i < num_pads; i++) - if (!(pads_flag[i] & MEDIA_PAD_FL_SOURCE)) - return ERR_PTR(-EINVAL); - /* Allocate the vsen struct */ vsen = kzalloc(sizeof(*vsen), GFP_KERNEL); if (!vsen) - return ERR_PTR(-ENOMEM); + return -ENOMEM; /* Initialize ved and sd */ - ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev, name, - MEDIA_ENT_F_CAM_SENSOR, num_pads, pads_flag, - &vimc_sen_ops, vimc_sen_destroy); + ret = vimc_ent_sd_register(&vsen->ved, &vsen->sd, v4l2_dev, + pdata->entity_name, + MEDIA_ENT_F_ATV_DECODER, 1, + (const unsigned long[1]) {MEDIA_PAD_FL_SOURCE}, + &vimc_sen_ops); if (ret) goto err_free_vsen; + dev_set_drvdata(comp, &vsen->ved); + vsen->dev = comp; + /* Initialize the frame format */ vsen->mbus_format = fmt_default; @@ -335,12 +338,52 @@ struct vimc_ent_device *vimc_sen_create(struct v4l2_device *v4l2_dev, if (ret) goto err_unregister_ent_sd; - return &vsen->ved; + return 0; err_unregister_ent_sd: vimc_ent_sd_unregister(&vsen->ved, &vsen->sd); err_free_vsen: kfree(vsen); - return ERR_PTR(ret); + return ret; } + +static const struct component_ops vimc_sen_comp_ops = { + .bind = vimc_sen_comp_bind, + .unbind = vimc_sen_comp_unbind, +}; + +static int vimc_sen_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &vimc_sen_comp_ops); +} + +static int vimc_sen_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &vimc_sen_comp_ops); + + return 0; +} + +static struct platform_driver vimc_sen_pdrv = { + .probe = vimc_sen_probe, + .remove = vimc_sen_remove, + .driver = { + .name = VIMC_SEN_DRV_NAME, + }, +}; + +static const struct platform_device_id vimc_sen_driver_ids[] = { + { + .name = VIMC_SEN_DRV_NAME, + }, + { } +}; + +module_platform_driver(vimc_sen_pdrv); + +MODULE_DEVICE_TABLE(platform, vimc_sen_driver_ids); + +MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Sensor"); +MODULE_AUTHOR("Helen Mae Koike Fornazier "); +MODULE_LICENSE("GPL"); -- cgit v1.2.2