diff options
| -rw-r--r-- | drivers/media/platform/rockchip/rkvdec/rkvdec.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c b/drivers/media/platform/rockchip/rkvdec/rkvdec.c index ce96a0470d4d..af2eced90026 100644 --- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c +++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c @@ -1269,6 +1269,49 @@ static void rkvdec_watchdog_func(struct work_struct *work) } } +/* + * Some SoCs, like RK3588 have multiple identical VDPU cores, but the + * kernel is currently missing support for multi-core handling. Exposing + * separate devices for each core to userspace is bad, since that does + * not allow scheduling tasks properly (and creates ABI). With this workaround + * the driver will only probe for the first core and early exit for the other + * cores. Once the driver gains multi-core support, the same technique + * for detecting the first core can be used to cluster all cores together. + */ +static int rkvdec_disable_multicore(struct rkvdec_dev *rkvdec) +{ + struct device_node *node = NULL; + const char *compatible; + bool is_first_core; + int ret; + + /* Intentionally ignores the fallback strings */ + ret = of_property_read_string(rkvdec->dev->of_node, "compatible", &compatible); + if (ret) + return ret; + + /* The first compatible and available node found is considered the main core */ + do { + node = of_find_compatible_node(node, NULL, compatible); + if (of_device_is_available(node)) + break; + } while (node); + + if (!node) + return -EINVAL; + + is_first_core = (rkvdec->dev->of_node == node); + + of_node_put(node); + + if (!is_first_core) { + dev_info(rkvdec->dev, "missing multi-core support, ignoring this instance\n"); + return -ENODEV; + } + + return 0; +} + static const struct rkvdec_variant_ops rk3399_variant_ops = { .irq_handler = rk3399_irq_handler, }; @@ -1332,6 +1375,10 @@ static int rkvdec_probe(struct platform_device *pdev) mutex_init(&rkvdec->vdev_lock); INIT_DELAYED_WORK(&rkvdec->watchdog_work, rkvdec_watchdog_func); + ret = rkvdec_disable_multicore(rkvdec); + if (ret) + return ret; + ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &rkvdec->clocks); if (ret < 0) return ret; |
