/* Called with the state.lock mutex held */
static void __s5pcsis_set_format(unsigned long __iomem *base_reg,
	struct fimc_is_image *image)
{
	u32 val;

	BUG_ON(!image);

	/* Color format */
	val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG));

	if (image->format.pixelformat == V4L2_PIX_FMT_SGRBG8)
		val = (val & ~S5PCSIS_CFG_FMT_MASK) | S5PCSIS_CFG_FMT_RAW8;
	else
		val = (val & ~S5PCSIS_CFG_FMT_MASK) | S5PCSIS_CFG_FMT_RAW10;

#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5422)
	val |= S5PCSIS_CFG_END_INTERVAL(1);
#endif
	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG));

	/* Pixel resolution */
	val = (image->window.o_width << 16) | image->window.o_height;
	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_RESOL));

	/* Output channel2 for DT */
	if (image->format.field == V4L2_FIELD_INTERLACED) {
		val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG_CH2));
		val |= S5PCSIS_CFG_VIRTUAL_CH(2);
		val |= S5PCSIS_CFG_END_INTERVAL(1);
		val = (val & ~S5PCSIS_CFG_FMT_MASK) | S5PCSIS_CFG_FMT_USER(1);
		writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG_CH2));
	}
}
static void s5pcsis_set_params(unsigned long __iomem *base_reg,
	struct fimc_is_image *image)
{
	u32 val;
	u32 num_lanes = 0x3;

	if (image->num_lanes)
		num_lanes = image->num_lanes - 1;

#if defined(CONFIG_SOC_EXYNOS3470)
	writel(0x000000AC, base_reg + TO_WORD_OFFSET(S5PCSIS_CONFIG)); /* only for carmen */
#endif
	__s5pcsis_set_format(base_reg, image);

	val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
	val &= ~S5PCSIS_CTRL_ALIGN_32BIT;

	val |= S5PCSIS_CTRL_NUMOFDATALANE(num_lanes);

	/* Interleaved data */
	if (image->format.field == V4L2_FIELD_INTERLACED) {
		pr_info("set DT only\n");
		val |= S5PCSIS_CTRL_INTERLEAVE_MODE(1); /* DT only */
		val |= S5PCSIS_CTRL_UPDATE_SHADOW(2); /* ch2 shadow reg */
	}

	/* Not using external clock. */
	val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;

	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));

	/* Update the shadow register. */
	val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
	writel(val | S5PCSIS_CTRL_UPDATE_SHADOW(0), base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
}
static void s5pcsis_reset(unsigned long __iomem *base_reg)
{
	u32 val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));

	writel(val | S5PCSIS_CTRL_RESET, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
	udelay(10);
}
static void flite_hw_set_unuse_buffer(u32 __iomem *base_reg, u32 number)
{
	u32 buffer;
	buffer = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1FCNTSEQ));
	buffer &= ~(1<<number);
	writel(buffer, base_reg + TO_WORD_OFFSET(FLITE_REG_CH1FCNTSEQ));
}
static void s5pcsis_enable_interrupts(unsigned long __iomem *base_reg,
	struct fimc_is_image *image, bool on)
{
	u32 val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_INTMSK));

	val = on ? val | S5PCSIS_INTMSK_EN_ALL :
		   val & ~S5PCSIS_INTMSK_EN_ALL;

	if (image->format.field == V4L2_FIELD_INTERLACED) {
		if (on) {
			val |= S5PCSIS_INTMSK_FRAME_START_CH2;
			val |= S5PCSIS_INTMSK_FRAME_END_CH2;
		} else {
			val &= ~S5PCSIS_INTMSK_FRAME_START_CH2;
			val &= ~S5PCSIS_INTMSK_FRAME_END_CH2;
		}
	}

#if defined(CONFIG_SOC_EXYNOS5260)
	/* FIXME: hard coded, only for rhea */
	writel(0xFFF01037, base_reg + TO_WORD_OFFSET(S5PCSIS_INTMSK));
#else
	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_INTMSK));
#endif
}
static void flite_hw_set_capture_stop(u32 __iomem *base_reg)
{
	u32 cfg;

	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIIMGCPT));
	cfg &= ~FLITE_REG_CIIMGCPT_IMGCPTEN;
	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIIMGCPT));
}
static void flite_hw_set_last_capture_end_clear(u32 __iomem *base_reg)
{
	u32 cfg = 0;

	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS2));
	cfg &= ~FLITE_REG_CISTATUS2_LASTCAPEND;

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS2));
}
static int flite_hw_set_source_format(u32 __iomem *base_reg, struct fimc_is_image *image)
{
	int ret = 0;
	u32 pixelformat, format, cfg;

	BUG_ON(!image);

	pixelformat = image->format.pixelformat;
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	switch (pixelformat) {
	case V4L2_PIX_FMT_SBGGR8:
	case V4L2_PIX_FMT_SGBRG8:
	case V4L2_PIX_FMT_SGRBG8:
	case V4L2_PIX_FMT_SRGGB8:
		format = HW_FORMAT_RAW8;
		break;
	case V4L2_PIX_FMT_SBGGR10:
	case V4L2_PIX_FMT_SGBRG10:
	case V4L2_PIX_FMT_SGRBG10:
	case V4L2_PIX_FMT_SRGGB10:
		format = HW_FORMAT_RAW10;
		break;
	case V4L2_PIX_FMT_SBGGR12:
	case V4L2_PIX_FMT_SGBRG12:
	case V4L2_PIX_FMT_SGRBG12:
	case V4L2_PIX_FMT_SRGGB12:
	case V4L2_PIX_FMT_SBGGR16:
		format = HW_FORMAT_RAW10;
		/*
		 * HACK : hal send RAW10 for RAW12
		 * formt = HW_FORMAT_RAW12 << 24;
		 */
		break;
	case V4L2_PIX_FMT_YUYV:
		format = HW_FORMAT_YUV422_8BIT;
		break;
	case V4L2_PIX_FMT_JPEG:
		format = HW_FORMAT_USER;
		break;
	default:
		err("unsupported format(%X)", pixelformat);
		format = HW_FORMAT_RAW10;
		ret = -EINVAL;
		break;
	}

#ifdef COLORBAR_MODE
	cfg |= (HW_FORMAT_YUV422_8BIT << 24);
#else
	cfg |= (format << 24);
#endif

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	return ret;
}
static void flite_hw_set_test_pattern_enable(u32 __iomem *base_reg)
{
	u32 cfg = 0;

	/* will use for pattern generation testing */
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
	cfg |= FLITE_REG_CIGCTRL_TEST_PATTERN_COLORBAR;

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
}
static void flite_hw_enable_bns(u32 __iomem *base_reg, bool enable)
{
	u32 cfg = 0;

	/* enable */
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGON));
	cfg |= FLITE_REG_BINNINGON_CLKGATE_ON(enable);
	cfg |= FLITE_REG_BINNINGON_EN(enable);
	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGON));
}
void flite_hw_set_output_otf(u32 __iomem *base_reg, bool enable)
{
	u32 cfg = 0;
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	if (enable)
		cfg &= ~FLITE_REG_CIGCTRL_OLOCAL_DISABLE;
	else
		cfg |= FLITE_REG_CIGCTRL_OLOCAL_DISABLE;

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
}
static void flite_hw_set_start_addr(u32 __iomem *base_reg, u32 number, u32 addr)
{
	u32 __iomem *target_reg;

	if (number == 0) {
		target_reg = base_reg + TO_WORD_OFFSET(0x30);
	} else {
		number--;
		target_reg = base_reg + TO_WORD_OFFSET(0x200 + (0x4*number));
	}

	writel(addr, target_reg);
}
static void flite_hw_s_size_bns(u32 __iomem *base_reg,
	u32 width, u32 height, u32 otf_width, u32 otf_height)
{
	u32 cfg = 0;

	/* size */
	cfg = FLITE_REG_BINNINGTOTAL_HEIGHT(height);
	cfg |= FLITE_REG_BINNINGTOTAL_WIDTH(width);
	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGTOTAL));

	cfg = FLITE_REG_BINNINGOUTPUT_HEIGHT(otf_height);
	cfg |= FLITE_REG_BINNINGOUTPUT_WIDTH(otf_width);
	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGOUTPUT));
}
void flite_hw_set_interrupt_mask(u32 __iomem *base_reg, bool enable, u32 irq_ids)
{
	u32 cfg = 0;
	u32 i = 0;
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	for (i = 0; i < FLITE_MASK_IRQ_ALL; i++) {
		if (!((1 << i) & irq_ids))
			continue;

		switch (i) {
		case FLITE_MASK_IRQ_START:
			if (enable)
				cfg &= ~FLITE_REG_CIGCTRL_IRQ_STARTEN0_DISABLE;
			else
				cfg |= FLITE_REG_CIGCTRL_IRQ_STARTEN0_DISABLE;
			break;
		case FLITE_MASK_IRQ_END:
			if (enable)
				cfg &= ~FLITE_REG_CIGCTRL_IRQ_ENDEN0_DISABLE;
			else
				cfg |= FLITE_REG_CIGCTRL_IRQ_ENDEN0_DISABLE;
			break;
		case FLITE_MASK_IRQ_OVERFLOW:
			if (enable)
				cfg &= ~FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE;
			else
				cfg |= FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE;
			break;
		case FLITE_MASK_IRQ_LAST_CAPTURE:
			if (enable)
				cfg &= ~FLITE_REG_CIGCTRL_IRQ_LASTEN0_DISABLE;
			else
				cfg |= FLITE_REG_CIGCTRL_IRQ_LASTEN0_DISABLE;
			break;
		case FLITE_MASK_IRQ_LINE:
			if (enable)
				cfg &= ~FLITE_REG_CIGCTRL_IRQ_LINEEN0_DISABLE;
			else
				cfg |= FLITE_REG_CIGCTRL_IRQ_LINEEN0_DISABLE;
			break;
		}
	}

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
}
static int flite_hw_get_status1(u32 __iomem *base_reg)
{
	u32 status = 0;

	status = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS));

	return status;
}
static void s5pcsis_set_hsync_settle(unsigned long __iomem *base_reg, u32 settle)
{
	u32 val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));

	val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (settle << 24);

#if defined(CONFIG_SOC_EXYNOS5260)
	/* FIXME: hard coded, only for rhea */
	writel(0x0E00001F, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
#elif defined(CONFIG_SOC_EXYNOS3470)
	val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
	val = (val & ~S5PCSIS_DPHYCTRL_HSS_MASK) | (0x6 << 28);
	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
#else
	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
#endif
}
static void flite_hw_set_dma_fmt(u32 __iomem *base_reg,
	u32 pixelformat)
{
	u32 cfg = 0;

	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1CTRL));

	if (pixelformat == V4L2_PIX_FMT_SBGGR10 || pixelformat == V4L2_PIX_FMT_SBGGR12)
		cfg |= FLITE_REG_CH1CTRL_CH1_PACK12;
	else
		cfg &= (~FLITE_REG_CH1CTRL_CH1_PACK12); /* Normal */

	if (pixelformat == V4L2_PIX_FMT_SGRBG8)
		cfg |= FLITE_REG_CH1CTRL_CH1_RAW_CON; /* 1D DMA */
	else
		cfg &= (~FLITE_REG_CH1CTRL_CH1_RAW_CON); /* 2D DMA */

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CH1CTRL));
}
static int init_fimc_lite(u32 __iomem *base_reg)
{
	int i;

	writel(0, base_reg + TO_WORD_OFFSET(FLITE_REG_CH1FCNTSEQ));

	for (i = 0; i < 32; i++)
		flite_hw_set_start_addr(base_reg , i, 0xffffffff);

	return 0;
}
static void flite_hw_force_reset(u32 __iomem *base_reg)
{
	u32 cfg = 0, retry = 100;
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	/* request sw reset */
	cfg |= FLITE_REG_CIGCTRL_SWRST_REQ;
	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	/* checking reset ready */
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
	while (retry-- && !(cfg & FLITE_REG_CIGCTRL_SWRST_RDY))
		cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	if (!(cfg & FLITE_REG_CIGCTRL_SWRST_RDY))
		warn("[CamIF] sw reset is not read but forcelly");

	/* sw reset */
	cfg |= FLITE_REG_CIGCTRL_SWRST;
	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));
}
static void s5pcsis_system_enable(unsigned long __iomem *base_reg, int on)
{
	u32 val;

	val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));

#if defined(CONFIG_SOC_EXYNOS5430) || defined(CONFIG_SOC_EXYNOS5422)
	val |= S5PCSIS_CTRL_WCLK_EXTCLK;
#endif

	if (on) {
		val |= S5PCSIS_CTRL_ENABLE;
		val |= S5PCSIS_CTRL_WCLK_EXTCLK;
	} else
		val &= ~S5PCSIS_CTRL_ENABLE;
#if defined(CONFIG_SOC_EXYNOS3470) || defined(CONFIG_SOC_EXYNOS5260)
	/* FIXME: hard coded, only for rhea */
	writel(0x0000010D, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
#else
	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_CTRL));
#endif

	val = readl(base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
	if (on)
		val |= S5PCSIS_DPHYCTRL_ENABLE;
	else
		val &= ~S5PCSIS_DPHYCTRL_ENABLE;
#if defined(CONFIG_SOC_EXYNOS3470) || defined(CONFIG_SOC_EXYNOS5260)
	/* FIXME: hard coded, only for rhea */
	writel(0x0E00001F, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
#else
	writel(val, base_reg + TO_WORD_OFFSET(S5PCSIS_DPHYCTRL));
#endif
}
static void flite_hw_s_coeff_bns(u32 __iomem *base_reg,
	u32 factor_x, u32 factor_y)
{
	int i;
	int index;
	u32 cfg = 0;
	u32 x_cfg = 0;
	u32 y_cfg = 0;
	u32 unity_size;
	u32 unity;
	u32 weight_x[16] = {0, }, weight_y[16] = {0, };

	if (factor_x != factor_y)
		err("x y factor is not the same (%d, %d)", factor_x, factor_y);

	/* control */
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGCTRL));
	cfg |= FLITE_REG_BINNINGCTRL_FACTOR_Y(factor_y);
	cfg |= FLITE_REG_BINNINGCTRL_FACTOR_X(factor_x);
	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGCTRL));

	unity_size = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGCTRL)) & 0xF;
	unity = 1 << unity_size;

	for(i = 0; bns_scales[factor_x][i] != 0; i++)
		weight_x[i] = bns_scales[factor_x][i] * unity / 1000;

	for(i = 0; bns_scales[factor_y][i] != 0; i++)
		weight_y[i] = bns_scales[factor_y][i] * unity / 1000;

	for (i = 0; i < 8; i++) {
		index = i * 2;
		x_cfg = (weight_x[index + 1] << 16) | (weight_x[index] << 0);
		y_cfg = (weight_y[index + 1] << 16) | (weight_y[index] << 0);

		writel(x_cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX01) + i);
		writel(y_cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY01) + i);
	}
}
static void flite_hw_set_window_offset(u32 __iomem *base_reg,
	struct fimc_is_image *image)
{
	u32 cfg = 0;
	u32 hoff2, voff2;

	BUG_ON(!image);

	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST));
	cfg &= ~(FLITE_REG_CIWDOFST_HOROFF_MASK |
		FLITE_REG_CIWDOFST_VEROFF_MASK);
	cfg |= FLITE_REG_CIWDOFST_WINOFSEN |
		FLITE_REG_CIWDOFST_WINHOROFST(image->window.offs_h) |
		FLITE_REG_CIWDOFST_WINVEROFST(image->window.offs_v);

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST));

	hoff2 = image->window.o_width - image->window.width - image->window.offs_h;
	voff2 = image->window.o_height - image->window.height - image->window.offs_v;
	cfg = FLITE_REG_CIWDOFST2_WINHOROFST2(hoff2) |
		FLITE_REG_CIWDOFST2_WINVEROFST2(voff2);

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST2));
}
static void flite_hw_set_cam_source_size(u32 __iomem *base_reg,
	struct fimc_is_image *image)
{
	u32 cfg = 0;

	BUG_ON(!image);

#ifdef COLORBAR_MODE
	cfg |= FLITE_REG_CISRCSIZE_SIZE_H(640);
	cfg |= FLITE_REG_CISRCSIZE_SIZE_V(480);
#else
	cfg |= FLITE_REG_CISRCSIZE_SIZE_H(image->window.o_width);
	cfg |= FLITE_REG_CISRCSIZE_SIZE_V(image->window.o_height);
#endif

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CISRCSIZE));
}
static void flite_hw_set_dma_offset(u32 __iomem *base_reg,
	struct fimc_is_image *image)
{
	u32 cfg = 0;

	BUG_ON(!image);

	switch (image->format.pixelformat) {
	case V4L2_PIX_FMT_SBGGR8:
	case V4L2_PIX_FMT_SGBRG8:
	case V4L2_PIX_FMT_SGRBG8:
	case V4L2_PIX_FMT_SRGGB8:
		cfg |= FLITE_REG_CH1OCAN_OCAN_H(roundup(image->window.o_width, 16));
		break;
	case V4L2_PIX_FMT_SBGGR10:
	case V4L2_PIX_FMT_SGBRG10:
	case V4L2_PIX_FMT_SGRBG10:
	case V4L2_PIX_FMT_SRGGB10:
	case V4L2_PIX_FMT_SBGGR12:
	case V4L2_PIX_FMT_SGBRG12:
	case V4L2_PIX_FMT_SGRBG12:
	case V4L2_PIX_FMT_SRGGB12:
		/* always input format is raw10 but this means padding bit */
		cfg |= FLITE_REG_CH1OCAN_OCAN_H(roundup((image->window.o_width * 3) / 2, 16));
		break;
	case V4L2_PIX_FMT_SBGGR16:
	case V4L2_PIX_FMT_YUYV:
		cfg |= FLITE_REG_CH1OCAN_OCAN_H(roundup(image->window.o_width * 2, 16));
		break;
	default:
		warn("unsupprted format(%d)", image->format.pixelformat);
		break;
	}

	cfg |= FLITE_REG_CH1OCAN_OCAN_V(image->window.o_height);

	writel(cfg, base_reg + TO_WORD_OFFSET(FLITE_REG_CH1OCAN));
}
u32 flite_hw_get_interrupt_mask(u32 __iomem *base_reg, u32 irq_ids)
{
	u32 cfg = 0;
	u32 ret = 0;
	u32 i = 0;
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL));

	for (i = 0; i < FLITE_MASK_IRQ_ALL; i++) {
		if (!((1 << i) & irq_ids))
			continue;

		switch (i) {
		case FLITE_MASK_IRQ_START:
			if (cfg & FLITE_REG_CIGCTRL_IRQ_STARTEN0_DISABLE)
				ret |= (1 << i);
			break;
		case FLITE_MASK_IRQ_END:
			if (cfg & FLITE_REG_CIGCTRL_IRQ_ENDEN0_DISABLE)
				ret |= (1 << i);
			break;
		case FLITE_MASK_IRQ_OVERFLOW:
			if (cfg & FLITE_REG_CIGCTRL_IRQ_OVFEN0_DISABLE)
				ret |= (1 << i);
			break;
		case FLITE_MASK_IRQ_LAST_CAPTURE:
			if (cfg & FLITE_REG_CIGCTRL_IRQ_LASTEN0_DISABLE)
				ret |= (1 << i);
			break;
		case FLITE_MASK_IRQ_LINE:
			if (cfg & FLITE_REG_CIGCTRL_IRQ_LINEEN0_DISABLE)
				ret |= (1 << i);
			break;
		}
	}

	return ret;
}
static void flite_hw_set_status1(u32 __iomem *base_reg, u32 val)
{
	writel(val, base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS));
}
static void flite_hw_set_lineint_ratio(u32 __iomem *base_reg, u32 ratio)
{
	writel(ratio, base_reg + TO_WORD_OFFSET(FLITE_REG_LINEINT));
}
void flite_hw_dump(u32 __iomem *base_reg)
{
	info("BNS 4.0 DUMP\n");
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISRCSIZE, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISRCSIZE)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CIGCTRL, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIGCTRL)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CIIMGCPT, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIIMGCPT)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CIWDOFST, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CIWDOFST2, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CIWDOFST2)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CH1CTRL, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1CTRL)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CH1OCAN, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1OCAN)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CH1OOFF, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1OOFF)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CH1OSA1, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1OSA1)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISTATUS, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISTATUS2, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS2)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISTATUS4, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS4)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISTATUS5, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS5)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISTATUS6, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS6)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISTATUS7, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS7)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CISTATUS8, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CISTATUS8)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_LINEINT, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_LINEINT)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CH1THOLD, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1THOLD)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_CH1FCNTSEQ, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1FCNTSEQ)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_BINNINGON, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGON)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_BINNINGCTRL, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGCTRL)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_BINNINGTOTAL, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGTOTAL)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_BINNINGOUTPUT, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_BINNINGOUTPUT)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_WEIGHTX01, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX01)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_WEIGHTX23, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTX23)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_WEIGHTY01, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY01)));
	info("[0x%04X] : 0x%08X\n", FLITE_REG_WEIGHTY23, readl(base_reg + TO_WORD_OFFSET(FLITE_REG_WEIGHTY23)));
}
u32 flite_hw_get_status(u32 __iomem *base_reg, u32 status_ids, bool clear)
{
	u32 i = 0;
	u32 ret = 0;
	u32 status1;
	u32 clear_status1 = 0;
	u32 ch1ctrl;

	status1 = flite_hw_get_status1(base_reg);

	for (i = 0; i < FLITE_STATUS_ALL; i++) {
		if (!((1 << i) & status_ids))
			continue;

		switch (i) {
		case FLITE_STATUS_IRQ_SRC_START:
			if (status1 & (1 << 5)) {
				ret |= (1 << i);
				clear_status1 |= (1 << 5);
			}
			break;
		case FLITE_STATUS_IRQ_SRC_END:
			if (status1 & (1 << 4)) {
				ret |= (1 << i);
				clear_status1 |= (1 << 4);
			}
			break;
		case FLITE_STATUS_IRQ_SRC_OVERFLOW:
			if (status1 & (1 << 7)) {
				ret |= (1 << i);
				clear_status1 |= (1 << 7);
			}
			break;
		case FLITE_STATUS_IRQ_SRC_LAST_CAPTURE:
			if (status1 & (1 << 6)) {
				ret |= (1 << i);
				clear_status1 |= (1 << 6);
			}
			break;
		case FLITE_STATUS_IRQ_SRC_LINE:
			if (status1 & (1 << 8)) {
				ret |= (1 << i);
				clear_status1 |= (1 << 8);
			}
			break;
		case FLITE_STATUS_OFY:
			if (status1 & (1 << 10)) {
				ret |= (1 << i);
				if (clear) {
					ch1ctrl = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1CTRL));
					ch1ctrl  |= (FLITE_REG_CH1CTRL_CLR_OVERFLOW_FIFO_CH1);
					writel(ch1ctrl, base_reg + TO_WORD_OFFSET(FLITE_REG_CH1CTRL));
					ch1ctrl  &= ~(FLITE_REG_CH1CTRL_CLR_OVERFLOW_FIFO_CH1);
					writel(ch1ctrl, base_reg + TO_WORD_OFFSET(FLITE_REG_CH1CTRL));
				}
			}
			break;
		case FLITE_STATUS_MIPI_VALID:
			if (status1 & (7 << 20))
				ret |= (1 << i);
			break;
		default:
			break;
		}
	}

	if (clear && (clear_status1 > 0))
		flite_hw_set_status1(base_reg, clear_status1);

	return ret;
}
bool flite_hw_get_output_dma(u32 __iomem *base_reg)
{
	u32 cfg = 0;
	cfg = readl(base_reg + TO_WORD_OFFSET(FLITE_REG_CH1CTRL));
	return (cfg & FLITE_REG_CH1CTRL_CH1_ODMA_DISABLE) ? false : true;
}