Il 10/01/24 15:14, Julien Stephan ha scritto:
From: Phi-bang Nguyen <pnguyen@xxxxxxxxxxxx> This driver provides a path to bypass the SoC ISP so that image data coming from the SENINF can go directly into memory without any image processing. This allows the use of an external ISP. Signed-off-by: Phi-bang Nguyen <pnguyen@xxxxxxxxxxxx> Signed-off-by: Florian Sylvestre <fsylvestre@xxxxxxxxxxxx> [Paul Elder fix irq locking] Signed-off-by: Paul Elder <paul.elder@xxxxxxxxxxxxxxxx> Co-developed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> Co-developed-by: Julien Stephan <jstephan@xxxxxxxxxxxx> Signed-off-by: Julien Stephan <jstephan@xxxxxxxxxxxx> --- MAINTAINERS | 1 + .../platform/mediatek/isp/isp_30/Kconfig | 19 + .../platform/mediatek/isp/isp_30/Makefile | 1 + .../mediatek/isp/isp_30/camsv/Makefile | 7 + .../mediatek/isp/isp_30/camsv/mtk_camsv.c | 328 ++++++++ .../mediatek/isp/isp_30/camsv/mtk_camsv.h | 199 +++++ .../isp/isp_30/camsv/mtk_camsv30_hw.c | 427 ++++++++++ .../isp/isp_30/camsv/mtk_camsv30_regs.h | 60 ++ .../isp/isp_30/camsv/mtk_camsv_video.c | 774 ++++++++++++++++++ 9 files changed, 1816 insertions(+) create mode 100644 drivers/media/platform/mediatek/isp/isp_30/camsv/Makefile create mode 100644 drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv.c create mode 100644 drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv.h create mode 100644 drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv30_hw.c create mode 100644 drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv30_regs.h create mode 100644 drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv_video.c
..snip..
diff --git a/drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv30_hw.c b/drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv30_hw.c new file mode 100644 index 000000000000..3b8ccdab2af0 --- /dev/null +++ b/drivers/media/platform/mediatek/isp/isp_30/camsv/mtk_camsv30_hw.c @@ -0,0 +1,427 @@
..snip..
+ +static int mtk_camsv30_probe(struct platform_device *pdev) +{ + static const char * const clk_names[] = { "cam", "camtg", "camsv"}; + + struct mtk_cam_dev *cam_dev; + struct device *dev = &pdev->dev; + int ret; + int i; + + if (!iommu_present(&platform_bus_type)) + return -EPROBE_DEFER; + + cam_dev = devm_kzalloc(dev, sizeof(*cam_dev), GFP_KERNEL); + if (!cam_dev) + return -ENOMEM; + + cam_dev->conf = of_device_get_match_data(dev); + if (!cam_dev->conf) + return -ENODEV; + + cam_dev->dev = dev; + dev_set_drvdata(dev, cam_dev); + + cam_dev->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(cam_dev->regs)) + return dev_err_probe(dev, PTR_ERR(cam_dev->regs), + "failed to map register base\n"); + + + cam_dev->regs_img0 = devm_platform_ioremap_resource(pdev, 1); + + if (IS_ERR(cam_dev->regs_img0)) + return dev_err_probe(dev, PTR_ERR(cam_dev->regs_img0), + "failed to map img0 register base\n"); + + + cam_dev->regs_tg = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(cam_dev->regs_tg)) + return dev_err_probe(dev, PTR_ERR(cam_dev->regs_tg), + "failed to map TG register base\n"); + + + cam_dev->num_clks = ARRAY_SIZE(clk_names); + cam_dev->clks = devm_kcalloc(dev, cam_dev->num_clks, + sizeof(*cam_dev->clks), GFP_KERNEL); + if (!cam_dev->clks) + return -ENOMEM; + + for (i = 0; i < cam_dev->num_clks; ++i) + cam_dev->clks[i].id = clk_names[i]; + + ret = devm_clk_bulk_get(dev, cam_dev->num_clks, cam_dev->clks); + if (ret) + return dev_err_probe(dev, ret, "failed to get clocks: %i\n", ret); + + + cam_dev->irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(dev, cam_dev->irq, + isp_irq_camsv30, 0, + dev_name(dev), cam_dev); + if (ret != 0) + return dev_err_probe(dev, -ENODEV, "failed to request irq=%d\n", + cam_dev->irq); + + cam_dev->hw_functions = &mtk_camsv30_hw_functions; + + spin_lock_init(&cam_dev->irqlock); + + /* initialise runtime power management */ + pm_runtime_set_autosuspend_delay(dev, MTK_CAMSV30_AUTOSUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_suspended(dev); + pm_runtime_enable(dev);
devm_pm_runtime_enable() ?
+ + /* Initialize the v4l2 common part */ + return mtk_cam_dev_init(cam_dev); +} + +static int mtk_camsv30_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mtk_cam_dev *cam_dev = dev_get_drvdata(dev); + + mtk_cam_dev_cleanup(cam_dev); + pm_runtime_put_autosuspend(dev); + pm_runtime_disable(dev); + + return 0; +} + +static const struct dev_pm_ops mtk_camsv30_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(mtk_camsv30_runtime_suspend, + mtk_camsv30_runtime_resume, NULL) +}; + +static const struct of_device_id mtk_camsv30_of_ids[] = { + { .compatible = "mediatek,mt8365-camsv", .data = &camsv30_conf }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mtk_camsv30_of_ids); + +static struct platform_driver mtk_camsv30_driver = { + .probe = mtk_camsv30_probe, + .remove = mtk_camsv30_remove,
You definitely want to use void .remove_new() here Cheers, Angelo