diff options
author | Jihoon Bang <jbang@nvidia.com> | 2013-01-17 10:19:29 -0800 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2013-01-25 15:40:02 -0800 |
commit | b526c6cbed623f86b0c7ddba2796c40ffb489826 (patch) | |
tree | b44e469c5e8c76aa5097a9efa072e5fd68f1f7cb /drivers/video/tegra/camera | |
parent | 09a59de211cf1409a79e912d23b311e867e9710f (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.c | 37 | ||||
-rw-r--r-- | drivers/video/tegra/camera/camera_clk.c | 77 | ||||
-rw-r--r-- | drivers/video/tegra/camera/camera_clk.h | 2 | ||||
-rw-r--r-- | drivers/video/tegra/camera/camera_emc.c | 6 | ||||
-rw-r--r-- | drivers/video/tegra/camera/camera_priv_defs.h | 12 |
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); |