static int mdp3_dmap_lut_config(struct mdp3_dma *dma,
			struct mdp3_dma_lut_config *config,
			struct mdp3_dma_lut *lut)
{
	u32 addr, color;
	int i;

	if (config->lut_enable && lut) {
		addr = MDP3_REG_DMA_P_CSC_LUT1;
		if (config->lut_sel)
			addr = MDP3_REG_DMA_P_CSC_LUT2;

		for (i = 0; i < MDP_LUT_SIZE; i++) {
			color = lut->color0_lut[i] & 0xff;
			color |= (lut->color1_lut[i] & 0xff) << 8;
			color |= (lut->color2_lut[i] & 0xff) << 16;
			MDP3_REG_WRITE(addr, color);
			addr += 4;
		}
	}

	dma->lut_config = *config;

	if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
		mdp3_ccs_update(dma);

	return 0;
}
static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
			struct mdp3_dma_color_correct_config *config,
			struct mdp3_dma_ccs *ccs)
{
	int i;
	u32 addr;

	if (!ccs)
		return -EINVAL;

	if (config->ccs_enable) {
		addr = MDP3_REG_DMA_P_CSC_MV1;
		if (config->ccs_sel)
			addr = MDP3_REG_DMA_P_CSC_MV2;
		for (i = 0; i < 9; i++) {
			MDP3_REG_WRITE(addr, ccs->mv[i]);
			addr += 4;
		}

		addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
		if (config->pre_bias_sel)
			addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
		for (i = 0; i < 3; i++) {
			MDP3_REG_WRITE(addr, ccs->pre_bv[i]);
			addr += 4;
		}

		addr = MDP3_REG_DMA_P_CSC_POST_BV1;
		if (config->post_bias_sel)
			addr = MDP3_REG_DMA_P_CSC_POST_BV2;
		for (i = 0; i < 3; i++) {
			MDP3_REG_WRITE(addr, ccs->post_bv[i]);
			addr += 4;
		}

		addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
		if (config->pre_limit_sel)
			addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
		for (i = 0; i < 6; i++) {
			MDP3_REG_WRITE(addr, ccs->pre_lv[i]);
			addr += 4;
		}

		addr = MDP3_REG_DMA_P_CSC_POST_LV1;
		if (config->post_limit_sel)
			addr = MDP3_REG_DMA_P_CSC_POST_LV2;
		for (i = 0; i < 6; i++) {
			MDP3_REG_WRITE(addr, ccs->post_lv[i]);
			addr += 4;
		}
	}
	dma->ccs_config = *config;

	if (dma->output_config.out_sel != MDP3_DMA_OUTPUT_SEL_DSI_CMD)
		mdp3_ccs_update(dma);

	return 0;
}
static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf,
				struct mdp3_intf *intf)
{
	unsigned long flag;
	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
	int rc = 0;

	pr_debug("mdp3_dmap_update\n");

	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
		cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
		if (intf->active) {
			rc = wait_for_completion_timeout(&dma->dma_comp,
				KOFF_TIMEOUT);
			if (rc <= 0) {
				WARN(1, "cmd kickoff timed out (%d)\n", rc);
				rc = -1;
			}
		}
	}
	if (dma->update_src_cfg) {
		if (dma->output_config.out_sel ==
				 MDP3_DMA_OUTPUT_SEL_DSI_VIDEO && intf->active)
			pr_err("configuring dma source while dma is active\n");
		dma->dma_config_source(dma);
		dma->update_src_cfg = false;
	}
	spin_lock_irqsave(&dma->dma_lock, flag);
	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
	dma->source_config.buf = buf;
	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
		mdp3_ccs_update(dma);
		MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
	}

	if (!intf->active) {
		pr_debug("mdp3_dmap_update start interface\n");
		intf->start(intf);
	}

	mb();
	dma->vsync_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS) &
		(1 << MDP3_INTR_LCDC_START_OF_FRAME);
	init_completion(&dma->vsync_comp);
	spin_unlock_irqrestore(&dma->dma_lock, flag);

	mdp3_dma_callback_enable(dma, cb_type);
	pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
		rc = wait_for_completion_timeout(&dma->vsync_comp,
			KOFF_TIMEOUT);
		if (rc <= 0)
			rc = -1;
	}
	pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
	return rc;
}
static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf,
				struct mdp3_intf *intf)
{
	unsigned long flag;
	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;

	pr_debug("mdp3_dmap_update\n");

	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
		cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
		if (intf->active)
			wait_for_completion_killable(&dma->dma_comp);
	}
	spin_lock_irqsave(&dma->dma_lock, flag);
	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
	dma->source_config.buf = buf;
	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
		mdp3_ccs_update(dma);
		MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
	}

	if (!intf->active) {
		pr_debug("mdp3_dmap_update start interface\n");
		intf->start(intf);
	}

	wmb();
	init_completion(&dma->vsync_comp);
	spin_unlock_irqrestore(&dma->dma_lock, flag);

	mdp3_dma_callback_enable(dma, cb_type);
	pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
		wait_for_completion_killable(&dma->vsync_comp);
	pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
	return 0;
}