Prepare to move Gen2 and earlier models to media controller by generating a unique VIN group id for each VIN instance. On Gen3 and Gen4 it is important to have a specific id in the group as media graph routes depend on this. On Gen2 and earlier models all that will matter is to have a unique id in the range. Break out the id generation to a own function keeping the logic for Gen3 and Gen4 while generating a sequential id for Gen2 models. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@xxxxxxxxxxxx> --- * Changes since v1 - Move ID allocation to probe. - Use ida_alloc_range() instead of implementing our own schema by counting DT nodes. --- .../platform/renesas/rcar-vin/rcar-core.c | 76 ++++++++++++++----- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index 91e871580e70..7a7cf54ae7ec 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -10,6 +10,7 @@ * Based on the soc-camera rcar_vin driver */ +#include <linux/idr.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_graph.h> @@ -55,6 +56,7 @@ * be only one group for all instances. */ +static DEFINE_IDA(rvin_ida); static DEFINE_MUTEX(rvin_group_lock); static struct rvin_group *rvin_group_data; @@ -119,23 +121,8 @@ static int rvin_group_get(struct rvin_dev *vin, const struct media_device_ops *ops) { struct rvin_group *group; - u32 id; int ret; - /* Make sure VIN id is present and sane */ - ret = of_property_read_u32(vin->dev->of_node, "renesas,id", &id); - if (ret) { - vin_err(vin, "%pOF: No renesas,id property found\n", - vin->dev->of_node); - return -EINVAL; - } - - if (id >= RCAR_VIN_NUM) { - vin_err(vin, "%pOF: Invalid renesas,id '%u'\n", - vin->dev->of_node, id); - return -EINVAL; - } - /* Join or create a VIN group */ mutex_lock(&rvin_group_lock); if (rvin_group_data) { @@ -164,16 +151,15 @@ static int rvin_group_get(struct rvin_dev *vin, /* Add VIN to group */ mutex_lock(&group->lock); - if (group->vin[id]) { - vin_err(vin, "Duplicate renesas,id property value %u\n", id); + if (group->vin[vin->id]) { + vin_err(vin, "Duplicate renesas,id property value %u\n", vin->id); mutex_unlock(&group->lock); kref_put(&group->refcount, rvin_group_release); return -EINVAL; } - group->vin[id] = vin; + group->vin[vin->id] = vin; - vin->id = id; vin->group = group; vin->v4l2_dev.mdev = &group->mdev; @@ -1377,6 +1363,52 @@ static const struct of_device_id rvin_of_id_table[] = { }; MODULE_DEVICE_TABLE(of, rvin_of_id_table); +static int rvin_id_get(struct rvin_dev *vin) +{ + u32 oid; + int id; + + switch (vin->info->model) { + case RCAR_GEN3: + if (of_property_read_u32(vin->dev->of_node, "renesas,id", &oid)) + break; + + if (oid < 0 || oid >= RCAR_VIN_NUM) { + vin_err(vin, "%pOF: Invalid renesas,id '%u'\n", + vin->dev->of_node, oid); + return -EINVAL; + } + + vin->id = oid; + + return 0; + default: + id = ida_alloc_range(&rvin_ida, 0, RCAR_VIN_NUM - 1, + GFP_KERNEL); + if (id < 0) + break; + + vin->id = id; + + return 0; + } + + vin_err(vin, "Can't figure out VIN id\n"); + + return -EINVAL; +} + +static void rvin_id_put(struct rvin_dev *vin) +{ + switch (vin->info->model) { + case RCAR_GEN3: + break; + default: + ida_free(&rvin_ida, vin->id); + break; + } +} + static int rcar_vin_probe(struct platform_device *pdev) { struct rvin_dev *vin; @@ -1404,6 +1436,9 @@ static int rcar_vin_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vin); + if (rvin_id_get(vin)) + return -EINVAL; + if (vin->info->use_isp) { ret = rvin_isp_init(vin); } else if (vin->info->use_mc) { @@ -1421,6 +1456,7 @@ static int rcar_vin_probe(struct platform_device *pdev) if (ret) { rvin_dma_unregister(vin); + rvin_id_put(vin); return ret; } @@ -1445,6 +1481,8 @@ static void rcar_vin_remove(struct platform_device *pdev) else rvin_parallel_cleanup(vin); + rvin_id_put(vin); + rvin_dma_unregister(vin); } -- 2.48.1