Пример #1
0
int tegra_camera_clk_set_rate(struct tegra_camera *camera)
{
	struct clk *clk, *clk_parent;
	struct tegra_camera_clk_info *info = &camera->info;
	unsigned long parent_rate, parent_div_rate, parent_div_rate_pre;

	if (!info) {
		dev_err(camera->dev,
				"%s: no clock info %d\n",
				__func__, info->id);
		return -EINVAL;
	}

	if (info->id != TEGRA_CAMERA_MODULE_VI &&
		info->id != TEGRA_CAMERA_MODULE_EMC) {
		dev_err(camera->dev,
				"%s: set rate only aplies to vi module %d\n",
				__func__, info->id);
		return -EINVAL;
	}

	switch (info->clk_id) {
	case TEGRA_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:
		return 0; /* legacy, ignore */
	case TEGRA_CAMERA_EMC_CLK:
		clk = camera->clock[CAMERA_EMC_CLK].clk;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
		{
			/*
			 * When emc_clock is set through TEGRA_CAMERA_EMC_CLK,
			 * info->rate has peak memory bandwidth in Bps.
			 */
			unsigned long bw = info->rate / 1000;
#if defined(CONFIG_TEGRA_ISOMGR)
			int ret = 0;
#endif

			dev_dbg(camera->dev, "%s: bw=%lu KBps\n",
				__func__, bw);

#ifdef CONFIG_ARCH_TEGRA_11x_SOC
			/*
			 * Take into account iso client efficiency here until
			 * isomgr is alive. It's 35%.
			 */
			clk_set_rate(clk,
			((100*tegra_emc_bw_to_freq_req(bw)) / 35) * 1000);
#else
			clk_set_rate(clk, tegra_emc_bw_to_freq_req(bw) * 1000);
#endif

#if defined(CONFIG_TEGRA_ISOMGR)
			/*
			 * There is no way to figure out what latency
			 * can be tolerated in VI without reading VI
			 * registers for now. 3 usec is minimum time
			 * to switch PLL source. Let's put 4 usec as
			 * latency for now.
			 */
			ret = tegra_camera_isomgr_request(camera, bw, 4);
			if (ret) {
				dev_err(camera->dev,
				"%s: failed to reserve %lu KBps\n",
				__func__, bw);
				return -ENOMEM;
			}
#endif
		}
#endif
		goto set_rate_end;
	default:
		dev_err(camera->dev,
				"%s: invalid clk id for set rate %d\n",
				__func__, info->clk_id);
		return -EINVAL;
	}

	clk_parent = clk_get_parent(clk);
	parent_rate = clk_get_rate(clk_parent);
	dev_dbg(camera->dev, "%s: clk_id=%d, parent_rate=%lu, clk_rate=%lu\n",
			__func__, info->clk_id, parent_rate, info->rate);
	parent_div_rate = parent_rate;
	parent_div_rate_pre = parent_rate;

	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);

	clk_set_rate(clk, parent_div_rate_pre);

	if (info->clk_id == TEGRA_CAMERA_VI_CLK) {
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
		{
			u32 val;
			void __iomem *apb_misc =
				IO_ADDRESS(TEGRA_APB_MISC_BASE);
			val = readl(apb_misc + 0x42c);
			writel(val | 0x1, apb_misc + 0x42c);
		}
#endif
		if (info->flag == TEGRA_CAMERA_ENABLE_PD2VI_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
		 * bit 24: 0 = internal clock, 1 = external clock(pd2vi_clk)
		 */
			tegra_clk_cfg_ex(clk, TEGRA_CLK_VI_INP_SEL, 2);
#endif
		}
#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
		else {
			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);
		}
		tegra_camera_set_latency_allowance(camera, parent_div_rate_pre);
#endif
	}

set_rate_end:
	info->rate = clk_get_rate(clk);
	dev_dbg(camera->dev, "%s: get_rate=%lu",
			__func__, info->rate);
	return 0;
}
Пример #2
0
static int tegra_camera_clk_set_rate(struct tegra_camera_dev *dev)
{
	struct clk *clk, *clk_parent;
	struct tegra_camera_clk_info *info = &dev->info;
	unsigned long parent_rate, parent_div_rate, parent_div_rate_pre;

	if (!info) {
		dev_err(dev->dev,
				"%s: no clock info %d\n",
				__func__, info->id);
		return -EINVAL;
	}

	if (info->id != TEGRA_CAMERA_MODULE_VI &&
		info->id != TEGRA_CAMERA_MODULE_EMC) {
		dev_err(dev->dev,
				"%s: set rate only aplies to vi module %d\n",
				__func__, info->id);
		return -EINVAL;
	}

	switch (info->clk_id) {
	case TEGRA_CAMERA_VI_CLK:
		clk = dev->vi_clk;
		break;
	case TEGRA_CAMERA_VI_SENSOR_CLK:
		clk = dev->vi_sensor_clk;
		break;
	case TEGRA_CAMERA_EMC_CLK:
		clk = dev->emc_clk;
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
		dev_dbg(dev->dev, "%s: emc_clk rate=%lu\n",
			__func__, info->rate);
		clk_set_rate(dev->emc_clk, info->rate);
#endif
		goto set_rate_end;
	default:
		dev_err(dev->dev,
				"%s: invalid clk id for set rate %d\n",
				__func__, info->clk_id);
		return -EINVAL;
	}

	clk_parent = clk_get_parent(clk);
	parent_rate = clk_get_rate(clk_parent);
	dev_dbg(dev->dev, "%s: clk_id=%d, parent_rate=%lu, clk_rate=%lu\n",
			__func__, info->clk_id, parent_rate, info->rate);
	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);
	}

	dev_dbg(dev->dev, "%s: set_rate=%lu",
			__func__, parent_div_rate_pre);

	clk_set_rate(clk, parent_div_rate_pre);

	if (info->clk_id == TEGRA_CAMERA_VI_CLK) {
		/*
		 * bit 25: 0 = pd2vi_Clk, 1 = vi_sensor_clk
		 * bit 24: 0 = internal clock, 1 = external clock(pd2vi_clk)
		 */
		if (info->flag == TEGRA_CAMERA_ENABLE_PD2VI_CLK)
			tegra_clk_cfg_ex(clk, TEGRA_CLK_VI_INP_SEL, 2);

#ifdef CONFIG_ARCH_TEGRA_2x_SOC
		{
			u32 val;
			void __iomem *apb_misc =
				IO_ADDRESS(TEGRA_APB_MISC_BASE);
			val = readl(apb_misc + 0x42c);
			writel(val | 0x1, apb_misc + 0x42c);
		}
#endif
	}

set_rate_end:
	info->rate = clk_get_rate(clk);
	dev_dbg(dev->dev, "%s: get_rate=%lu",
			__func__, info->rate);
	return 0;

}
Пример #3
0
static int tegra_camera_clk_set_rate(struct tegra_camera_dev *dev)
{
	struct clk *clk, *clk_parent;
	struct tegra_camera_clk_info *info = &dev->info;
	unsigned long parent_rate, parent_div_rate, parent_div_rate_pre;

	if (!info) {
		dev_err(dev->dev,
				"%s: no clock info %d\n",
				__func__, info->id);
		return -EINVAL;
	}

	if (info->id != TEGRA_CAMERA_MODULE_VI) {
		dev_err(dev->dev,
				"%s: set rate only aplies to vi module %d\n",
				__func__, info->id);
		return -EINVAL;
	}

	switch (info->clk_id) {
	case TEGRA_CAMERA_VI_CLK:
		clk = dev->vi_clk;
		break;
	case TEGRA_CAMERA_VI_SENSOR_CLK:
		clk = dev->vi_sensor_clk;
		break;
	default:
		dev_err(dev->dev,
				"%s: invalid clk id for set rate %d\n",
				__func__, info->clk_id);
		return -EINVAL;
	}

	clk_parent = clk_get_parent(clk);
	parent_rate = clk_get_rate(clk_parent);
	dev_dbg(dev->dev, "%s: clk_id=%d, parent_rate=%lu, clk_rate=%lu\n",
			__func__, info->clk_id, parent_rate, info->rate);
	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);
	}

	dev_dbg(dev->dev, "%s: set_rate=%lu",
			__func__, parent_div_rate_pre);

	clk_set_rate(clk, parent_div_rate_pre);

	if (info->clk_id == TEGRA_CAMERA_VI_CLK) {
		/*
		 * bit 25: 0 = pd2vi_Clk, 1 = vi_sensor_clk
		 * bit 24: 0 = internal clock, 1 = external clock(pd2vi_clk)
		 */
		if (info->flag == TEGRA_CAMERA_ENABLE_PD2VI_CLK)
			tegra_clk_cfg_ex(clk, TEGRA_CLK_VI_INP_SEL, 2);
	}

	info->rate = clk_get_rate(clk);
	dev_dbg(dev->dev, "%s: get_rate=%lu",
			__func__, info->rate);
	return 0;

}