diff --git a/drivers/video/tegra/host/isp/isp5.c b/drivers/video/tegra/host/isp/isp5.c index a2083c07..ad3d6624 100644 --- a/drivers/video/tegra/host/isp/isp5.c +++ b/drivers/video/tegra/host/isp/isp5.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -167,6 +168,77 @@ static uint32_t isp5_get_gos_table(struct platform_device *pdev, return count; } +static int isp5_module_init(struct platform_device *pdev) +{ + struct nvhost_device_data *pdata = platform_get_drvdata(pdev); + unsigned int i; + int err; + + err = devm_clk_bulk_get_all(&pdev->dev, &pdata->clks); + if (err < 0) { + dev_err(&pdev->dev, "failed to get clocks %d\n", err); + return err; + } + pdata->num_clks = err; + + for (i = 0; i < pdata->num_clks; i++) { + err = clk_set_rate(pdata->clks[i].clk, ULONG_MAX); + if (err < 0) { + dev_err(&pdev->dev, "failed to set clock rate!\n"); + return err; + } + } + + pdata->reset_control = devm_reset_control_get_exclusive_released( + &pdev->dev, NULL); + if (IS_ERR(pdata->reset_control)) { + dev_err(&pdev->dev, "failed to get reset\n"); + return PTR_ERR(pdata->reset_control); + } + + reset_control_acquire(pdata->reset_control); + if (err < 0) { + dev_err(&pdev->dev, "failed to acquire reset: %d\n", err); + return err; + } + + err = clk_bulk_prepare_enable(pdata->num_clks, pdata->clks); + if (err < 0) { + reset_control_release(pdata->reset_control); + dev_err(&pdev->dev, "failed to enabled clocks: %d\n", err); + return err; + } + + reset_control_reset(pdata->reset_control); + clk_bulk_disable_unprepare(pdata->num_clks, pdata->clks); + reset_control_release(pdata->reset_control); + + if (pdata->autosuspend_delay) { + pm_runtime_set_autosuspend_delay(&pdev->dev, + pdata->autosuspend_delay); + pm_runtime_use_autosuspend(&pdev->dev); + } + + pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) + return -EOPNOTSUPP; + + pdata->debugfs = debugfs_create_dir(pdev->dev.of_node->name, + NULL); + + return 0; + +} + +static void isp5_module_deinit(struct platform_device *pdev) +{ + struct nvhost_device_data *pdata = platform_get_drvdata(pdev); + + pm_runtime_disable(&pdev->dev); + + debugfs_remove_recursive(pdata->debugfs); +} + static struct isp_channel_drv_ops isp5_channel_drv_ops = { .alloc_syncpt = isp5_alloc_syncpt, .release_syncpt = isp5_release_syncpt, @@ -364,7 +436,7 @@ static int isp5_probe(struct platform_device *pdev) goto error; } - err = nvhost_module_init(pdev); + err = isp5_module_init(pdev); if (err) goto deinit; @@ -401,6 +473,8 @@ static int isp5_probe(struct platform_device *pdev) release_client: isp5_client_device_release(pdev); +deinit: + isp5_module_deinit(pdev); error: if (err != -EPROBE_DEFER) dev_err(&pdev->dev, "probe failed: %d\n", err);