static int _ipu_pixel_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
			    unsigned long parent_clk_rate)
{
	struct clk_di_div *di_div = to_clk_di_div(hw);
	struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
	u64 div, parent_rate;
	u64 remainder;

	parent_rate = (unsigned long long)parent_clk_rate * 16;
	div = parent_rate;
	div = do_udiv64(div, rate, &remainder);
	/* Round the divider value */
	if (remainder > (rate/2))
		div++;

	/* Round up divider if it gets us closer to desired pix clk */
	if ((div & 0xC) == 0xC) {
		div += 0x10;
		div &= ~0xF;
	}
	if (div > 0x1000)
		pr_err("Overflow, di:%d, DI_BS_CLKGEN0 div:0x%x\n",
				di_div->di_id, (u32)div);
	_ipu_get(ipu);
	ipu_di_write(ipu, di_div->di_id, (u32)div, DI_BS_CLKGEN0);

	/* Setup pixel clock timing */
	/* FIXME: needs to be more flexible */
	/* Down time is half of period */
	ipu_di_write(ipu, di_div->di_id, ((u32)div / 16) << 16, DI_BS_CLKGEN1);
	_ipu_put(ipu);

	return 0;
}
Пример #2
0
static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
		int set, int up, int down)
{
	u32 reg;

	reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
	reg &= ~(0x3 << (di_pin * 2));
	reg |= set << (di_pin * 2);
	ipu_di_write(di, reg, DI_DW_GEN(wave_gen));

	ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
}
Пример #3
0
static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
		int start, int count)
{
	u32 reg;
	int i;

	for (i = 0; i < count; i++) {
		struct di_sync_config *c = &config[i];
		int wave_gen = start + i + 1;

		if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
				(c->repeat_count >= 0x1000) ||
				(c->cnt_up >= 0x400) ||
				(c->cnt_down >= 0x400)) {
			dev_err(di->ipu->dev, "DI%d counters out of range.\n",
					di->id);
			return;
		}

		reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
			DI_SW_GEN0_RUN_SRC(c->run_src) |
			DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
			DI_SW_GEN0_OFFSET_SRC(c->offset_src);
		ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));

		reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
			DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
			DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
					c->cnt_polarity_trigger_src) |
			DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
			DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
			DI_SW_GEN1_CNT_UP(c->cnt_up);

		/* Enable auto reload */
		if (c->repeat_count == 0)
			reg |= DI_SW_GEN1_AUTO_RELOAD;

		ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));

		reg = ipu_di_read(di, DI_STP_REP(wave_gen));
		reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
		reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
		ipu_di_write(di, reg, DI_STP_REP(wave_gen));
	}
}
Пример #4
0
static void ipu_di_data_wave_config(struct ipu_di *di,
				     int wave_gen,
				     int access_size, int component_size)
{
	u32 reg;
	reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
	    (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
	ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
}
Пример #5
0
static int clk_di_set_parent(struct clk *clk, u8 index)
{
	struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel);
	u32 val;

	val = ipu_di_read(di, DI_GENERAL);

	if (index)
		val |= DI_GEN_DI_CLK_EXT;
	else
		val &= ~DI_GEN_DI_CLK_EXT;

	ipu_di_write(di, val, DI_GENERAL);

	return 0;
}
Пример #6
0
static int clk_di_set_rate(struct clk *clk, unsigned long rate,
				unsigned long parent_rate)
{
	struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel);
	int div;
	u32 clkgen0;

	clkgen0 = ipu_di_read(di, DI_BS_CLKGEN0) & ~0xfff;

	div = ipu_di_clk_calc_div(parent_rate, rate);

	ipu_di_write(di, clkgen0 | div, DI_BS_CLKGEN0);

	dev_dbg(di->ipu->dev, "%s: inrate: %ld desired: %ld div: 0x%08x\n",
			__func__, parent_rate, rate, div);
	return 0;
}
static int _ipu_pixel_clk_set_parent(struct clk_hw *hw, u8 index)
{
	struct clk_di_mux *mux = to_clk_di_mux(hw);
	struct ipu_soc *ipu = ipu_get_soc(mux->ipu_id);
	u32 di_gen;

	di_gen = ipu_di_read(ipu, mux->di_id, DI_GENERAL);
	if (index == 0)
		/* ipu1_clk or ipu2_clk internal clk */
		di_gen &= ~DI_GEN_DI_CLK_EXT;
	else
		di_gen |= DI_GEN_DI_CLK_EXT;

	ipu_di_write(ipu, mux->di_id, di_gen, DI_GENERAL);
	mux->index = index;
	pr_debug("ipu_pixel_clk: di_clk_ext:0x%x, di_gen reg:0x%x.\n",
			!(di_gen & DI_GEN_DI_CLK_EXT), di_gen);
	return 0;
}