summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorBryan Wu <pengw@nvidia.com>2013-06-03 14:40:25 -0700
committerMatthew Pedro <mapedro@nvidia.com>2013-10-16 15:21:30 -0700
commitf2054ae01c96275abdc7c323c8adb03795e11c7d (patch)
tree5ec9807087e7e45f6a7a88a66393e3eb653b3092 /drivers
parent38b37d811fc6f0c705b36b51d74f62673b6c915e (diff)
media: tegra_v4l2: pass platform_data via soc_camera_link
soc_camera_link supports passing power on/off control callback to soc_camera stack. So the power control can be handled by soc_camera stack instead of our Tegra V4L2 host driver. Also pass other platform_data fields via soc_camera_link instead of a hacking nvhost_device_data struct. Bug 1240806 Bug 1369083 Change-Id: I443a7d28196cc8292805da70d2d5ff1c3cd50a5d Signed-off-by: Bryan Wu <pengw@nvidia.com> Reviewed-on: http://git-master/r/246267 (cherry picked from commit 9083d270bf93b583cd5bf5151a52ea250f8541a3) Reviewed-on: http://git-master/r/279986 Reviewed-by: Matthew Pedro <mapedro@nvidia.com> Tested-by: Matthew Pedro <mapedro@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/tegra_v4l2_camera.c84
1 files changed, 66 insertions, 18 deletions
diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c
index 739a56b85f3a..678e765512d4 100644
--- a/drivers/media/video/tegra_v4l2_camera.c
+++ b/drivers/media/video/tegra_v4l2_camera.c
@@ -960,6 +960,60 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev)
return err;
}
+static void tegra_camera_activate(struct tegra_camera_dev *pcdev)
+{
+ nvhost_module_busy_ext(pcdev->ndev);
+
+ /* Enable external power */
+ regulator_enable(pcdev->reg);
+
+ /*
+ * Powergating DIS must powergate VE partition. Camera
+ * module needs to increase the ref-count of disa to
+ * avoid itself powergated by DIS inadvertently.
+ */
+ tegra_unpowergate_partition(TEGRA_POWERGATE_DISA);
+ /* Unpowergate VE */
+ tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
+
+ /* Turn on relevant clocks. */
+ clk_set_rate(pcdev->clk_vi, 150000000);
+ clk_prepare_enable(pcdev->clk_vi);
+ clk_set_rate(pcdev->clk_vi_sensor, 24000000);
+ clk_prepare_enable(pcdev->clk_vi_sensor);
+ clk_prepare_enable(pcdev->clk_csi);
+ clk_prepare_enable(pcdev->clk_isp);
+ clk_prepare_enable(pcdev->clk_csus);
+ clk_set_rate(pcdev->clk_sclk, 80000000);
+ clk_prepare_enable(pcdev->clk_sclk);
+ clk_set_rate(pcdev->clk_sclk, 375000000);
+ clk_prepare_enable(pcdev->clk_emc);
+
+ /* Save current syncpt values. */
+ tegra_camera_save_syncpts(pcdev);
+}
+
+static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev)
+{
+ /* Turn off relevant clocks. */
+ clk_disable_unprepare(pcdev->clk_vi);
+ clk_disable_unprepare(pcdev->clk_vi_sensor);
+ clk_disable_unprepare(pcdev->clk_csi);
+ clk_disable_unprepare(pcdev->clk_isp);
+ clk_disable_unprepare(pcdev->clk_csus);
+ clk_disable_unprepare(pcdev->clk_sclk);
+ clk_disable_unprepare(pcdev->clk_emc);
+
+ /* Powergate VE */
+ tegra_powergate_partition(TEGRA_POWERGATE_VENC);
+ tegra_powergate_partition(TEGRA_POWERGATE_DISA);
+
+ /* Disable external power */
+ regulator_disable(pcdev->reg);
+
+ nvhost_module_idle_ext(pcdev->ndev);
+}
+
static int tegra_camera_capture_frame(struct tegra_camera_dev *pcdev)
{
struct vb2_buffer *vb;
@@ -1404,8 +1458,18 @@ static int tegra_camera_add_device(struct soc_camera_device *icd)
struct tegra_camera_dev *pcdev = ici->priv;
int err;
- if (pcdev->icd)
- return -EBUSY;
+ pcdev->pdata = icd->link->priv;
+ if (!pcdev->pdata) {
+ dev_err(icd->parent, "No platform data!\n");
+ return -EINVAL;
+ }
+
+ if (!tegra_camera_port_is_valid(pcdev->pdata->port)) {
+ dev_err(icd->parent,
+ "Invalid camera port %d in platform data\n",
+ pcdev->pdata->port);
+ return -EINVAL;
+ }
pm_runtime_get_sync(ici->v4l2_dev.dev);
@@ -1693,12 +1757,6 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev,
nvhost_set_drvdata(ndev, pcdev);
- if (!tegra_camera_port_is_valid(pcdev->pdata->port)) {
- dev_err(&ndev->dev, "Invalid camera port %d in platform data\n",
- pcdev->pdata->port);
- goto exit_free_pcdev;
- }
-
pcdev->clk_vi = clk_get_sys("tegra_camera", "vi");
if (IS_ERR_OR_NULL(pcdev->clk_vi)) {
dev_err(&ndev->dev, "Failed to get vi clock.\n");
@@ -1825,11 +1883,6 @@ static int tegra_camera_suspend(struct nvhost_device *ndev, pm_message_t state)
/* Suspend the camera sensor. */
WARN_ON(!pcdev->icd->ops->suspend);
pcdev->icd->ops->suspend(pcdev->icd, state);
-
- /* Power off the camera subsystem. */
- pcdev->pdata->disable_camera(pcdev->ndev);
-
- nvhost_module_idle_ext(nvhost_get_parent(ndev));
}
return 0;
@@ -1843,11 +1896,6 @@ static int tegra_camera_resume(struct nvhost_device *ndev)
/* We only need to do something if a camera sensor is attached. */
if (pcdev->icd) {
- nvhost_module_busy_ext(nvhost_get_parent(ndev));
-
- /* Power on the camera subsystem. */
- pcdev->pdata->enable_camera(pcdev->ndev);
-
/* Resume the camera host. */
tegra_camera_save_syncpts(pcdev);
tegra_camera_capture_setup(pcdev);