summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/camera
diff options
context:
space:
mode:
authorJihoon Bang <jbang@nvidia.com>2013-01-17 10:19:29 -0800
committerRiham Haidar <rhaidar@nvidia.com>2013-01-25 15:40:02 -0800
commitb526c6cbed623f86b0c7ddba2796c40ffb489826 (patch)
treeb44e469c5e8c76aa5097a9efa072e5fd68f1f7cb /drivers/video/tegra/camera
parent09a59de211cf1409a79e912d23b311e867e9710f (diff)
video: tegra: camera: squash changes for pll_d2_clk
Squash following changes. These changes are about handling pll_d2_clk which is used to test pattern generator in VI/CSI. 08c492d1d7d13: fix test pattern generator 60817b5005851: enable/disable pll_d2 in balance Fix build error related for T148. 3beca1de87b49: fix build error Fix uneven clk_enable/clk_disable. Bug 1189789 Bug 1168336 Bug 1214620 Change-Id: I105d422578141002753c05a2f4579180873f832c Signed-off-by: Jihoon Bang <jbang@nvidia.com> Reviewed-on: http://git-master/r/192115 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Krishna Reddy <vdumpa@nvidia.com> Reviewed-by: Jon Mayo <jmayo@nvidia.com> GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/video/tegra/camera')
-rw-r--r--drivers/video/tegra/camera/camera.c37
-rw-r--r--drivers/video/tegra/camera/camera_clk.c77
-rw-r--r--drivers/video/tegra/camera/camera_clk.h2
-rw-r--r--drivers/video/tegra/camera/camera_emc.c6
-rw-r--r--drivers/video/tegra/camera/camera_priv_defs.h12
5 files changed, 96 insertions, 38 deletions
diff --git a/drivers/video/tegra/camera/camera.c b/drivers/video/tegra/camera/camera.c
index 9264d8fd0e5c..67080a8cb707 100644
--- a/drivers/video/tegra/camera/camera.c
+++ b/drivers/video/tegra/camera/camera.c
@@ -21,18 +21,18 @@
#define TEGRA_CAMERA_NAME "tegra_camera"
-static struct camera_clk tegra_camera_clk[] = {
- { CAMERA_ISP_CLK, "isp"},
- { CAMERA_VI_CLK, "vi"},
- { CAMERA_VI_SENSOR_CLK, "vi_sensor"},
- { CAMERA_CSUS_CLK, "csus"},
- { CAMERA_CSI_CLK, "csi"},
- { CAMERA_EMC_CLK, "emc"},
+static struct clock_data clock_init[] = {
+ { CAMERA_ISP_CLK, "isp", true},
+ { CAMERA_VI_CLK, "vi", true},
+ { CAMERA_VI_SENSOR_CLK, "vi_sensor", true},
+ { CAMERA_CSUS_CLK, "csus", true},
+ { CAMERA_CSI_CLK, "csi", true},
+ { CAMERA_EMC_CLK, "emc", true},
#ifdef CONFIG_ARCH_TEGRA_11x_SOC
- { CAMERA_CILAB_CLK, "cilab"},
- { CAMERA_CILCD_CLK, "cilcd"},
- { CAMERA_CILE_CLK, "cile"},
- { CAMERA_PLL_D2_CLK, "pll_d2"}
+ { CAMERA_CILAB_CLK, "cilab", true},
+ { CAMERA_CILCD_CLK, "cilcd", true},
+ { CAMERA_CILE_CLK, "cile", true},
+ { CAMERA_PLL_D2_CLK, "pll_d2", false}
#endif
};
@@ -120,6 +120,10 @@ static int tegra_camera_open(struct inode *inode, struct file *file)
ret = tegra_camera_enable_emc(camera);
if (ret)
goto enable_emc_fail;
+
+ /* read initial clock info */
+ tegra_camera_init_clk(camera, clock_init);
+
/* enable camera HW clock */
ret = tegra_camera_enable_clk(camera);
if (ret)
@@ -245,8 +249,8 @@ struct tegra_camera *tegra_camera_register(struct platform_device *ndev)
}
for (i = 0; i < CAMERA_CLK_MAX; i++) {
- ret = tegra_camera_clk_get(ndev, tegra_camera_clk[i].name,
- &camera->clk[tegra_camera_clk[i].index]);
+ ret = tegra_camera_clk_get(ndev, clock_init[i].name,
+ &camera->clock[clock_init[i].index].clk);
if (ret)
goto clk_get_fail;
}
@@ -275,7 +279,7 @@ struct tegra_camera *tegra_camera_register(struct platform_device *ndev)
clk_get_fail:
for (; i > 0; i--)
- clk_put(camera->clk[i-1]);
+ clk_put(camera->clock[clock_init[i].index].clk);
misc_deregister(&camera->misc_dev);
misc_register_fail:
regulator_put(camera->reg);
@@ -287,8 +291,13 @@ regulator_fail:
int tegra_camera_unregister(struct tegra_camera *camera)
{
+ int i;
+
dev_info(camera->dev, "%s: ++\n", __func__);
+ for (i = 0; i < CAMERA_CLK_MAX; i++)
+ clk_put(camera->clock[i].clk);
+
#ifdef CONFIG_ARCH_TEGRA_11x_SOC
/*
* Return memory bandwidth to isomgr.
diff --git a/drivers/video/tegra/camera/camera_clk.c b/drivers/video/tegra/camera/camera_clk.c
index d3668c9a8356..e6e75fb99bac 100644
--- a/drivers/video/tegra/camera/camera_clk.c
+++ b/drivers/video/tegra/camera/camera_clk.c
@@ -20,7 +20,9 @@ int tegra_camera_enable_clk(struct tegra_camera *camera)
{
int i;
for (i = 0; i < CAMERA_CLK_MAX; i++)
- clk_prepare_enable(camera->clk[i]);
+ if (camera->clock[i].on)
+ clk_prepare_enable(camera->clock[i].clk);
+
return 0;
}
@@ -28,7 +30,18 @@ int tegra_camera_disable_clk(struct tegra_camera *camera)
{
int i;
for (i = CAMERA_CLK_MAX; i > 0; i--)
- clk_prepare_enable(camera->clk[i-1]);
+ if (camera->clock[i-1].on)
+ clk_disable_unprepare(camera->clock[i-1].clk);
+
+ return 0;
+}
+
+int tegra_camera_init_clk(struct tegra_camera *camera,
+ struct clock_data *clock_init)
+{
+ int i;
+ for (i = 0; i < CAMERA_CLK_MAX; i++)
+ camera->clock[clock_init[i].index].on = clock_init[i].init;
return 0;
}
@@ -55,13 +68,32 @@ int tegra_camera_clk_set_rate(struct tegra_camera *camera)
switch (info->clk_id) {
case TEGRA_CAMERA_VI_CLK:
- clk = camera->clk[CAMERA_VI_CLK];
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+ if (info->flag == TEGRA_CAMERA_ENABLE_PD2VI_CLK) {
+ if (camera->clock[CAMERA_PLL_D2_CLK].clk) {
+ clk_prepare_enable(
+ camera->clock[CAMERA_PLL_D2_CLK].clk);
+ clk = camera->clock[CAMERA_PLL_D2_CLK].clk;
+ camera->clock[CAMERA_PLL_D2_CLK].on = true;
+ } else {
+ /*
+ * PowerSaving: enable pll_d2 for camera only
+ * when required. pll_d2 will be disabled when
+ * camera will be released.
+ */
+ return -EINVAL;
+ }
+ } else
+#endif
+ {
+ clk = camera->clock[CAMERA_VI_CLK].clk;
+ }
break;
case TEGRA_CAMERA_VI_SENSOR_CLK:
- clk = camera->clk[CAMERA_VI_SENSOR_CLK];
+ clk = camera->clock[CAMERA_VI_SENSOR_CLK].clk;
break;
case TEGRA_CAMERA_EMC_CLK:
- clk = camera->clk[CAMERA_EMC_CLK];
+ clk = camera->clock[CAMERA_EMC_CLK].clk;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
{
/*
@@ -117,16 +149,21 @@ int tegra_camera_clk_set_rate(struct tegra_camera *camera)
parent_div_rate = parent_rate;
parent_div_rate_pre = parent_rate;
- /*
- * The requested clock rate from user space should be respected.
- * This loop is to search the clock rate that is higher than requested
- * clock.
- */
- while (parent_div_rate >= info->rate) {
- parent_div_rate_pre = parent_div_rate;
- parent_div_rate = clk_round_rate(clk, parent_div_rate-1);
+ if (info->flag != TEGRA_CAMERA_ENABLE_PD2VI_CLK) {
+ /*
+ * The requested clock rate from user space should be respected.
+ * This loop is to search the clock rate that is higher than
+ * requested clock.
+ * However, for camera pattern generator, since we share the
+ * clk source with display, we would not want to change the
+ * display clock.
+ */
+ while (parent_div_rate >= info->rate) {
+ parent_div_rate_pre = parent_div_rate;
+ parent_div_rate = clk_round_rate(clk,
+ parent_div_rate-1);
+ }
}
-
dev_dbg(camera->dev, "%s: set_rate=%lu",
__func__, parent_div_rate_pre);
@@ -143,9 +180,11 @@ int tegra_camera_clk_set_rate(struct tegra_camera *camera)
}
#endif
if (info->flag == TEGRA_CAMERA_ENABLE_PD2VI_CLK) {
-#ifdef CONFIG_ARCH_TEGRA_11x_SOC
- tegra_clk_cfg_ex(camera->clk[CAMERA_PLL_D2_CLK],
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+ tegra_clk_cfg_ex(camera->clock[CAMERA_PLL_D2_CLK].clk,
TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
+ tegra_clk_cfg_ex(camera->clock[CAMERA_PLL_D2_CLK].clk,
+ TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
#else
/*
* bit 25: 0 = pd2vi_Clk, 1 = vi_sensor_clk
@@ -154,10 +193,12 @@ int tegra_camera_clk_set_rate(struct tegra_camera *camera)
tegra_clk_cfg_ex(clk, TEGRA_CLK_VI_INP_SEL, 2);
#endif
}
-#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
else {
- tegra_clk_cfg_ex(camera->clk[CAMERA_PLL_D2_CLK],
+ tegra_clk_cfg_ex(camera->clock[CAMERA_PLL_D2_CLK].clk,
TEGRA_CLK_PLLD_CSI_OUT_ENB, 0);
+ tegra_clk_cfg_ex(camera->clock[CAMERA_PLL_D2_CLK].clk,
+ TEGRA_CLK_PLLD_DSI_OUT_ENB, 0);
}
#endif
}
diff --git a/drivers/video/tegra/camera/camera_clk.h b/drivers/video/tegra/camera/camera_clk.h
index 19fc9db47f47..a912eeeedb79 100644
--- a/drivers/video/tegra/camera/camera_clk.h
+++ b/drivers/video/tegra/camera/camera_clk.h
@@ -21,5 +21,7 @@
int tegra_camera_enable_clk(struct tegra_camera *camera);
int tegra_camera_disable_clk(struct tegra_camera *camera);
int tegra_camera_clk_set_rate(struct tegra_camera *camera);
+int tegra_camera_init_clk(struct tegra_camera *camera,
+ struct clock_data *clock_init);
#endif
diff --git a/drivers/video/tegra/camera/camera_emc.c b/drivers/video/tegra/camera/camera_emc.c
index 44208c104193..ad28fc3495f0 100644
--- a/drivers/video/tegra/camera/camera_emc.c
+++ b/drivers/video/tegra/camera/camera_emc.c
@@ -21,9 +21,9 @@ int tegra_camera_enable_emc(struct tegra_camera *camera)
int ret = tegra_emc_disable_eack();
dev_dbg(camera->dev, "%s++\n", __func__);
- clk_prepare_enable(camera->clk[CAMERA_EMC_CLK]);
+ clk_prepare_enable(camera->clock[CAMERA_EMC_CLK].clk);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- clk_set_rate(camera->clk[TEGRA_CAMERA_EMC_CLK], 300000000);
+ clk_set_rate(camera->clock[TEGRA_CAMERA_EMC_CLK].clk, 300000000);
#endif
return ret;
}
@@ -31,6 +31,6 @@ int tegra_camera_enable_emc(struct tegra_camera *camera)
int tegra_camera_disable_emc(struct tegra_camera *camera)
{
dev_dbg(camera->dev, "%s++\n", __func__);
- clk_disable_unprepare(camera->clk[CAMERA_EMC_CLK]);
+ clk_disable_unprepare(camera->clock[CAMERA_EMC_CLK].clk);
return tegra_emc_enable_eack();
}
diff --git a/drivers/video/tegra/camera/camera_priv_defs.h b/drivers/video/tegra/camera/camera_priv_defs.h
index 7e4ecefdf199..0a1f37cee751 100644
--- a/drivers/video/tegra/camera/camera_priv_defs.h
+++ b/drivers/video/tegra/camera/camera_priv_defs.h
@@ -53,7 +53,7 @@ enum {
CAMERA_ISP_CLK,
CAMERA_CSUS_CLK,
CAMERA_CSI_CLK,
-#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
CAMERA_CILAB_CLK,
CAMERA_CILCD_CLK,
CAMERA_CILE_CLK,
@@ -62,10 +62,15 @@ enum {
CAMERA_CLK_MAX,
};
+struct clock {
+ struct clk *clk;
+ bool on;
+};
+
struct tegra_camera {
struct device *dev;
struct miscdevice misc_dev;
- struct clk *clk[CAMERA_CLK_MAX];
+ struct clock clock[CAMERA_CLK_MAX];
struct regulator *reg;
struct tegra_camera_clk_info info;
struct mutex tegra_camera_lock;
@@ -76,9 +81,10 @@ struct tegra_camera {
#endif
};
-struct camera_clk {
+struct clock_data {
int index;
char *name;
+ bool init;
};
struct tegra_camera *tegra_camera_register(struct platform_device *ndev);