/*
 * _sysfs_support_fbc_show() - Return 1 if FBC/FBDC supported, else 0.
 * @kdev - Pointer to struct device
 * @attr - pointer to struct device_attribute
 * @buf - Pointer to output buffer to receive character string.
 * The buffer length is PAGE_SIZE bytes.
 */
static ssize_t _sysfs_support_fbc_show(struct device *kdev,
	struct device_attribute *attr, char *buf)
{
	const int buflen = PAGE_SIZE;
	int support_fbc;

	/* Supported for Anniedale, but not for ANN A0 and ANN B0. */
	if (!IS_ANN() || IS_ANN_A0() || IS_ANN_B0())
		support_fbc = 0;
	else
		support_fbc = 1;

	return scnprintf(buf, buflen, "%d\n", support_fbc);
}
static
void intel_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output)
{
	struct mdfld_dsi_pkg_sender *sender;
	struct drm_device *dev = dbi_output->dev;
	struct drm_crtc *crtc = dbi_output->base.base.crtc;
	struct psb_intel_crtc *psb_crtc =
		(crtc) ? to_psb_intel_crtc(crtc) : NULL;
	int pipe = dbi_output->channel_num ? 2 : 0;
	u32 dpll_reg = MRST_DPLL_A;
	u32 dspcntr_reg = DSPACNTR;
	u32 pipeconf_reg = PIPEACONF;
	u32 dsplinoff_reg = DSPALINOFF;
	u32 dspsurf_reg = DSPASURF;

	sender = mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
	if (!sender) {
		DRM_ERROR("pkg sender is NULL\n");
		return;
	}

	/* if mode setting on-going, back off */

	if (!IS_ANN_A0(dev)) {
		if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
				(psb_crtc && (psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) ||
				!(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
			return;
	}

	if (pipe == 2) {
		dspcntr_reg = DSPCCNTR;
		pipeconf_reg = PIPECCONF;
		dsplinoff_reg = DSPCLINOFF;
		dspsurf_reg = DSPCSURF;
	}

	/* check DBI FIFO status */
	if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) {
		if (!(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
		   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
			return;
	} else if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
	   !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
	   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
		return;

	if (!IS_ANN_A0(dev)) {
		/* refresh plane changes */

		REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
		REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
		REG_READ(dspsurf_reg);
	}

	mdfld_dsi_send_dcs(sender,
			   write_mem_start,
			   NULL,
			   0,
			   CMD_DATA_SRC_PIPE,
			   MDFLD_DSI_SEND_PACKAGE);
	dbi_output->dsr_fb_update_done = true;
	mdfld_dsi_cmds_kick_out(sender);
}
/**
 * Power on sequence for command mode MIPI panel.
 * NOTE: do NOT modify this function
 */
static int __dbi_panel_power_on(struct mdfld_dsi_config *dsi_config,
			struct panel_funcs *p_funcs)
{
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_psb_private *dev_priv;
	struct drm_device *dev;
	int reset_count = 10;
	int err = 0;
	struct mdfld_dsi_pkg_sender *sender
			= mdfld_dsi_get_pkg_sender(dsi_config);
	struct mdfld_dbi_dsr_info *dsr_info;
	struct mdfld_dsi_dbi_output **dbi_outputs;
	struct mdfld_dsi_dbi_output *dbi_output;

	if (!sender) {
		DRM_ERROR("pkg sender is NULL\n");
		return -EINVAL;
	}

	PSB_DEBUG_ENTRY("\n");

	if (!dsi_config)
		return -EINVAL;

	regs = &dsi_config->regs;
	ctx = &dsi_config->dsi_hw_context;
	dev = dsi_config->dev;
	dev_priv = dev->dev_private;

	mdfld_dsi_dsr_forbid_locked(dsi_config);
reset_recovery:
	--reset_count;
	err = 0;
	/*after entering dstb mode, need reset*/
	if (p_funcs && p_funcs->exit_deep_standby)
		p_funcs->exit_deep_standby(dsi_config);

	if (__dbi_power_on(dsi_config)) {
		DRM_ERROR("Failed to init display controller!\n");
		err = -EAGAIN;
		goto power_on_err;
	}

	/**
	 * Different panel may have different ways to have
	 * drvIC initialized. Support it!
	 */
	if (p_funcs && p_funcs->drv_ic_init) {
		if (p_funcs->drv_ic_init(dsi_config)) {
			DRM_ERROR("Failed to init dsi controller!\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}
	/* Issue "write_mem_start" DSI command during power on. */
	dsr_info = dev_priv->dbi_dsr_info;
	dbi_outputs = dsr_info->dbi_outputs;
	dbi_output = dsi_config->pipe ? dbi_outputs[1] : dbi_outputs[0];

	if (!IS_ANN_A0(dev))
		intel_dsi_dbi_update_fb(dbi_output);

	/**
	 * Different panel may have different ways to have
	 * panel turned on. Support it!
	 */
	if (p_funcs && p_funcs->power_on)
		if (p_funcs->power_on(dsi_config)) {
			DRM_ERROR("Failed to power on panel\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	if (p_funcs && p_funcs->set_brightness)
		if (p_funcs->set_brightness(dsi_config,
					ctx->lastbrightnesslevel))
			DRM_ERROR("Failed to set panel brightness\n");

	/*wait for all FIFOs empty*/
	mdfld_dsi_wait_for_fifos_empty(sender);
	if (is_dual_dsi(dev)) {
		sender->work_for_slave_panel = true;
		mdfld_dsi_wait_for_fifos_empty(sender);
		sender->work_for_slave_panel = false;
	}

	if (IS_ANN_A0(dev))
		intel_dsi_dbi_update_fb(dbi_output);

power_on_err:
	if (err && reset_count) {
		DRM_ERROR("Failed to init panel, try  reset it again!\n");
		goto reset_recovery;
	}
	mdfld_dsi_dsr_allow_locked(dsi_config);
	return err;
}
/* dbi interface power on*/
int __dbi_power_on(struct mdfld_dsi_config *dsi_config)
{
	u32 val = 0;
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_psb_private *dev_priv;
	struct drm_device *dev;
	int retry;
	int err = 0;
	u32 guit_val = 0;
	u32 power_island = 0;
	u32 sprite_reg_offset = 0;
	int i = 0;
	int offset = 0;

	PSB_DEBUG_ENTRY("\n");

	if (!dsi_config)
		return -EINVAL;

	regs = &dsi_config->regs;
	ctx = &dsi_config->dsi_hw_context;
	dev = dsi_config->dev;
	dev_priv = dev->dev_private;

	power_island = pipe_to_island(dsi_config->pipe);

	if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C))
		power_island |= OSPM_DISPLAY_MIO;

	if (is_dual_dsi(dev))
	power_island |= OSPM_DISPLAY_C;

	if (!power_island_get(power_island))
		return -EAGAIN;

	/*
	 * Wait for DSI PLL locked on pipe, and only need to poll status of pipe
	 * A as both MIPI pipes share the same DSI PLL.
	 */
	if (dsi_config->pipe == 0) {
		retry = 20000;
		while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) &&
				--retry)
			udelay(150);
		if (!retry) {
			DRM_ERROR("PLL failed to lock on pipe\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}

	if (IS_ANN_A0(dev)) {
		/* FIXME: reset the DC registers for ANN A0 */
		power_island_get(OSPM_DISPLAY_B | OSPM_DISPLAY_C);

		REG_WRITE(DSPCLK_GATE_D, 0xFFFFFFFF); /* 0x10000000 */
		REG_WRITE(RAMCLK_GATE_D, 0xFFFFFFFF); /* 0x0 */
		REG_WRITE(PFIT_CONTROL, 0x20000000);
		REG_WRITE(DSPIEDCFGSHDW, 0x0);
		REG_WRITE(DSPARB2, 0x000A0200);
		REG_WRITE(DSPARB, 0x18040080);
		REG_WRITE(DSPFW1, 0x0F0F3F3F);
		REG_WRITE(DSPFW2, 0x5F2F0F3F);
		REG_WRITE(DSPFW3, 0x0);
		REG_WRITE(DSPFW4, 0x07071F1F);
		REG_WRITE(DSPFW5, 0x2F17071F);
		REG_WRITE(DSPFW6, 0x00001F3F);
		REG_WRITE(DSPFW7, 0x1F3F1F3F);
		REG_WRITE(DSPSRCTRL, 0x00080100);
		REG_WRITE(DSPCHICKENBIT, 0x0);
		REG_WRITE(FBDC_CHICKEN, 0x0C0C0C0C);
		REG_WRITE(CURACNTR, 0x0);
		REG_WRITE(CURBCNTR, 0x0);
		REG_WRITE(CURCCNTR, 0x0);
		REG_WRITE(IEP_OVA_CTRL, 0x0);
		REG_WRITE(IEP_OVA_CTRL, 0x0);
		REG_WRITE(DSPACNTR, 0x0);
		REG_WRITE(DSPBCNTR, 0x0);
		REG_WRITE(DSPCCNTR, 0x0);
		REG_WRITE(DSPDCNTR, 0x0);
		REG_WRITE(DSPECNTR, 0x0);
		REG_WRITE(DSPFCNTR, 0x0);

		power_island_put(OSPM_DISPLAY_B | OSPM_DISPLAY_C);
	}

	/*exit ULPS*/
	if (__dbi_exit_ulps_locked(dsi_config, 0)) {
		DRM_ERROR("Failed to exit ULPS\n");
		goto power_on_err;
	}
	/*update MIPI port config*/
	REG_WRITE(regs->mipi_reg, ctx->mipi |
			 REG_READ(regs->mipi_reg));

	/*unready dsi adapter for re-programming*/
	REG_WRITE(regs->device_ready_reg,
		REG_READ(regs->device_ready_reg) & ~(DSI_DEVICE_READY));

	if (is_dual_dsi(dev)) {
		if (__dbi_exit_ulps_locked(dsi_config, 0x800)) {
			DRM_ERROR("Failed to exit ULPS\n");
			goto power_on_err;
		}
		offset = 0x1000;
		REG_WRITE(regs->mipi_reg + offset, ctx->mipi |
				 REG_READ(regs->mipi_reg + offset));
		/*unready dsi adapter for re-programming*/
		offset = 0x800;
		REG_WRITE(regs->device_ready_reg + offset,
			REG_READ(regs->device_ready_reg + offset) & ~(DSI_DEVICE_READY));
	}

	/*
	 * According to MIPI D-PHY spec, if clock stop feature is enabled (EOT
	 * Disable), un-ready MIPI adapter needs to wait for 20 cycles from HS
	 * to LP mode. Per calculation 1us is enough.
	 */
	if (ctx->eot_disable & CLOCK_STOP)
		udelay(1);

	__dbi_set_properties(dsi_config, PORT_A);

	/*Setup pipe timing*/
	REG_WRITE(regs->htotal_reg, ctx->htotal);
	REG_WRITE(regs->hblank_reg, ctx->hblank);
	REG_WRITE(regs->hsync_reg, ctx->hsync);
	REG_WRITE(regs->vtotal_reg, ctx->vtotal);
	REG_WRITE(regs->vblank_reg, ctx->vblank);
	REG_WRITE(regs->vsync_reg, ctx->vsync);
	REG_WRITE(regs->pipesrc_reg, ctx->pipesrc);
	REG_WRITE(regs->dsppos_reg, ctx->dsppos);
	REG_WRITE(regs->dspstride_reg, ctx->dspstride);

	if (!IS_ANN_A0(dev)) {
		/*restore color_coef (chrome) */
		for (i = 0; i < 6; i++)
			REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]);


		/* restore palette (gamma) */
		for (i = 0; i < 256; i++)
			REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]);

		/* restore dpst setting */
		if (dev_priv->psb_dpst_state) {
			dpstmgr_reg_restore_locked(dev, dsi_config);
			psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
		}
	}

	/*Setup plane*/
	REG_WRITE(regs->dspsize_reg, ctx->dspsize);
	REG_WRITE(regs->dspsurf_reg, ctx->dspsurf);
	REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff);
	REG_WRITE(regs->vgacntr_reg, ctx->vgacntr);

	if (is_dual_dsi(dev))
		__dbi_set_properties(dsi_config, PORT_C);

	/*enable plane*/
	val = ctx->dspcntr | BIT31;
	REG_WRITE(regs->dspcntr_reg, val);

	if (ctx->sprite_dspcntr & BIT31) {
		if (dsi_config->pipe == 0)
			sprite_reg_offset = 0x3000;
		else if (dsi_config->pipe == 2)
			sprite_reg_offset = 0x1000;

		/* Set up Sprite Plane */
		REG_WRITE(regs->dspsize_reg + sprite_reg_offset,
				ctx->sprite_dspsize);
		REG_WRITE(regs->dspsurf_reg + sprite_reg_offset,
				ctx->sprite_dspsurf);
		REG_WRITE(regs->dsplinoff_reg + sprite_reg_offset,
				ctx->sprite_dsplinoff);
		REG_WRITE(regs->dsppos_reg + sprite_reg_offset,
				ctx->sprite_dsppos);
		REG_WRITE(regs->dspstride_reg + sprite_reg_offset,
				ctx->sprite_dspstride);

		/* enable plane */
		REG_WRITE(regs->dspcntr_reg + sprite_reg_offset,
				ctx->sprite_dspcntr);
	}

	/* Set up Overlay Plane */
	if (ctx->ovaadd)
		PSB_WVDC32(ctx->ovaadd, OV_OVADD);

	if (ctx->ovcadd)
		PSB_WVDC32(ctx->ovcadd, OVC_OVADD);

	/*ready dsi adapter*/
	REG_WRITE(regs->device_ready_reg,
		REG_READ(regs->device_ready_reg) | DSI_DEVICE_READY);
	mdelay(1);
	if (is_dual_dsi(dev)) {
		REG_WRITE(regs->device_ready_reg + offset,
			REG_READ(regs->device_ready_reg + offset) | DSI_DEVICE_READY);
	}

	if (IS_ANN_A0(dev)) {
		REG_WRITE(regs->ddl1_reg, ctx->ddl1);
		REG_WRITE(regs->ddl2_reg, ctx->ddl2);
		REG_WRITE(regs->ddl3_reg, ctx->ddl3);
		REG_WRITE(regs->ddl4_reg, ctx->ddl4);
	}

	/*Enable pipe*/
	val = ctx->pipeconf;
	val &= ~0x000c0000;
	val |= BIT31 | PIPEACONF_DSR;
	REG_WRITE(regs->pipeconf_reg, val);

	/*Wait for pipe enabling,when timing generator is working */
	retry = 10000;
	while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30))
		udelay(3);

	if (!retry) {
		DRM_ERROR("Failed to enable pipe\n");
		err = -EAGAIN;
		goto power_on_err;
	}

	/*
	 * Enable TE to trigger "write_mem_start" issuing
	 * in non-normal boot modes.
	 */
	mdfld_enable_te(dev, dsi_config->pipe);
	return err;

power_on_err:
	power_island_put(power_island);
	return err;
}
/**
 * Power on sequence for video mode MIPI panel.
 * NOTE: do NOT modify this function
 */
static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config,
		struct panel_funcs *p_funcs)
{
	u32 val = 0;
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_psb_private *dev_priv;
	struct drm_device *dev;
	int retry, reset_count = 10;
	int i;
	int err = 0;
	u32 guit_val = 0;
	u32 power_island = 0;
	int offset = 0;

	PSB_DEBUG_ENTRY("\n");

	if (!dsi_config)
		return -EINVAL;

	regs = &dsi_config->regs;
	ctx = &dsi_config->dsi_hw_context;
	dev = dsi_config->dev;
	dev_priv = dev->dev_private;
	power_island = pipe_to_island(dsi_config->pipe);

	if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C))
		power_island |= OSPM_DISPLAY_MIO;
	if (is_dual_dsi(dev))
		power_island |= OSPM_DISPLAY_C;

	if (!power_island_get(power_island))
		return -EAGAIN;

reset_recovery:
	--reset_count;
	/*HW-Reset*/
	if (p_funcs && p_funcs->reset)
		p_funcs->reset(dsi_config);

	if (!is_dual_dsi(dev)) {
		/* Disable PLL*/
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0);
		guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, _DSI_LDO_EN);

		/* Program PLL */
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp);

		guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG,
		                ((guit_val & ~_P1_POST_DIV_MASK) |
		                 (ctx->dpll & _P1_POST_DIV_MASK)));
		ctx->dpll |= DPLL_VCO_ENABLE;
		ctx->dpll &= ~_DSI_LDO_EN;
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ctx->dpll);
	} else {
		intel_mid_msgbus_write32(CCK_PORT, 0x68, 0x682);
		/* Disable PLL*/
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0);
		guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
		intel_mid_msgbus_write32(CCK_PORT,
					DSI_PLL_CTRL_REG,
					_DSI_LDO_EN);
		/* Program PLL */
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp);
		guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG,
				((guit_val & ~_P1_POST_DIV_MASK) |
				 (ctx->dpll & _P1_POST_DIV_MASK)));
		guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
		ctx->dpll |= DPLL_VCO_ENABLE;
		ctx->dpll &= ~(_DSI_LDO_EN |
			       _CLK_EN_CCK_DSI0 | _CLK_EN_CCK_DSI1 |
			       _DSI_MUX_SEL_CCK_DSI1 | _DSI_MUX_SEL_CCK_DSI0);
		ctx->dpll |= _CLK_EN_PLL_DSI0 | _CLK_EN_PLL_DSI1;
		intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ctx->dpll);
	}
	/* Wait for DSI PLL lock */
	retry = 10000;
	guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
	while (((guit_val & _DSI_PLL_LOCK) != _DSI_PLL_LOCK) && (--retry)) {
		udelay(3);
		guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG);
		if (retry == 0) {
			DRM_ERROR("DSI PLL fails to lock\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}

	/*
	 * Wait for DSI PLL locked on pipe, and only need to poll status of pipe
	 * A as both MIPI pipes share the same DSI PLL.
	 */
	if (dsi_config->pipe == 0) {
		retry = 20000;
		while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) &&
				--retry)
			udelay(150);
		if (!retry) {
			DRM_ERROR("PLL failed to lock on pipe\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}
	__dpi_set_properties(dsi_config, PORT_A);

	/*Setup pipe timing*/
	REG_WRITE(regs->htotal_reg, ctx->htotal);
	REG_WRITE(regs->hblank_reg, ctx->hblank);
	REG_WRITE(regs->hsync_reg, ctx->hsync);
	REG_WRITE(regs->vtotal_reg, ctx->vtotal);
	REG_WRITE(regs->vblank_reg, ctx->vblank);
	REG_WRITE(regs->vsync_reg, ctx->vsync);
	REG_WRITE(regs->pipesrc_reg, ctx->pipesrc);

	REG_WRITE(regs->dsppos_reg, ctx->dsppos);
	REG_WRITE(regs->dspstride_reg, ctx->dspstride);

	if (IS_ANN_A0(dev)) {
		/*reset registers*/
		REG_WRITE(0x7002C, 0x000A0200);
		REG_WRITE(0x70508, 0x0c0c0c0c);
		REG_WRITE(0x70504, 0xffffffff);
		REG_WRITE(0x70500, 0xffffffff);
		DRM_DEBUG("LOADING: 0x70504 %#x\n", REG_READ(0x70504));
	}

	/*Setup plane*/
	REG_WRITE(regs->dspsize_reg, ctx->dspsize);
	REG_WRITE(regs->dspsurf_reg, ctx->dspsurf);
	REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff);
	REG_WRITE(regs->vgacntr_reg, ctx->vgacntr);

	/*restore color_coef (chrome) */
	for (i = 0; i < 6; i++)
		REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]);

	/* restore palette (gamma) */
	for (i = 0; i < 256; i++)
		REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]);

	/* restore dpst setting */
	if (dev_priv->psb_dpst_state) {
		dpstmgr_reg_restore_locked(dev, dsi_config);
		psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
	}

	if (__dpi_config_port(dsi_config, p_funcs, PORT_A) != 0) {
		if (!reset_count) {
				err = -EAGAIN;
				goto power_on_err;
			}
			DRM_ERROR("Failed to init dsi controller, reset it!\n");
			goto reset_recovery;
	}
	if (is_dual_dsi(dev)) {
		__dpi_set_properties(dsi_config, PORT_C);
		__dpi_config_port(dsi_config, p_funcs, PORT_C);
	}

	/**
	 * Different panel may have different ways to have
	 * drvIC initialized. Support it!
	 */
	if (p_funcs && p_funcs->drv_ic_init) {
		if (p_funcs->drv_ic_init(dsi_config)) {
			if (!reset_count) {
				err = -EAGAIN;
				goto power_on_err;
			}

			DRM_ERROR("Failed to init dsi controller, reset it!\n");
			goto reset_recovery;
		}
	}

	/*Enable MIPI Port A*/
	offset = 0x0;
	REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31));

	REG_WRITE(regs->dpi_control_reg + offset, BIT1);
	if (is_dual_dsi(dev)) {
		/*Enable MIPI Port C*/
		offset = 0x1000;
		REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31));
		offset = 0x800;
		REG_WRITE(regs->dpi_control_reg + offset, BIT1);
	}
	/**
	 * Different panel may have different ways to have
	 * panel turned on. Support it!
	 */
	if (p_funcs && p_funcs->power_on)
		if (p_funcs->power_on(dsi_config)) {
			DRM_ERROR("Failed to power on panel\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	/*Enable pipe*/
	val = ctx->pipeconf;
	val &= ~0x000c0000;
	val |= BIT31;
	REG_WRITE(regs->pipeconf_reg, val);
	/*Wait for pipe enabling,when timing generator
	  is wroking */
	if (REG_READ(regs->mipi_reg) & BIT31) {
		retry = 10000;
		while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30))
			udelay(3);

		if (!retry) {
			DRM_ERROR("Failed to enable pipe\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}
	/*enable plane*/
	val = ctx->dspcntr | BIT31;
	REG_WRITE(regs->dspcntr_reg, val);

	if (p_funcs && p_funcs->set_brightness) {
		if (p_funcs->set_brightness(dsi_config,
				ctx->lastbrightnesslevel))
			DRM_ERROR("Failed to set panel brightness\n");
	} else {
		DRM_ERROR("Failed to set panel brightness\n");
	}
	if (p_funcs && p_funcs->drv_set_panel_mode)
		p_funcs->drv_set_panel_mode(dsi_config);

	psb_enable_vblank(dev, dsi_config->pipe);
	return err;

power_on_err:
	power_island_put(power_island);
	return err;
}
int vsp_init_fw(struct drm_device *dev)
{
	struct drm_psb_private *dev_priv = dev->dev_private;
	struct vsp_private *vsp_priv = dev_priv->vsp_private;
	int ret = 0;
	const struct firmware *raw;
	unsigned char *ptr, *ma_ptr;
	struct vsp_secure_boot_header *boot_header;
	struct vsp_multi_app_blob_data *ma_header;
	unsigned long imr_addr;
	int imr_size;
	unsigned char *imr_ptr;
	unsigned int vrl_header_size = 736;
	const unsigned long vsp_magic_num = 0x50535624;
	const int FW_NAME_LEN = 30;
	char fw_name[FW_NAME_LEN];
	int name_ret;

	PSB_DEBUG_GENERAL("read firmware into buffer\n");

	name_ret = snprintf(fw_name, FW_NAME_LEN, "vsp.bin.%04x.%04x",
		 (int)spid.platform_family_id, (int)spid.hardware_id);
	if (name_ret > FW_NAME_LEN) {
		DRM_ERROR("failed to get fw name, ret %d vs expect %d\n",
			  name_ret, FW_NAME_LEN);
		/* no way */
		return -1;
	}

	/* try load with spid first */
	ret = request_firmware(&raw, fw_name, &dev->pdev->dev);
	if (ret < 0 || raw == NULL) {
		VSP_DEBUG("failed to load fw: %s, try to load different fw\n",
			fw_name);

		/* read firmware img */
		VSP_DEBUG("load vsp fw\n");
		if (IS_ANN_A0(dev))
			ret = request_firmware(&raw, FW_NAME_ANN,
					       &dev->pdev->dev);
		else if (IS_TNG_B0(dev))
			ret = request_firmware(&raw, FW_NAME_B0,
					       &dev->pdev->dev);
		else {
			DRM_ERROR("VSP secure fw: bad platform\n");
			raw = NULL;
		}
	}

	if (ret < 0 || raw == NULL) {
		DRM_ERROR("VSP: request_firmware failed: reason %d\n", ret);
		return -1;
	}

	if (raw->size < sizeof(struct vsp_secure_boot_header)) {
		DRM_ERROR("VSP: %s is not a correct firmware (size %d)\n",
				FW_NAME, raw->size);
		ret = -1;
		goto out;
	}

	ptr = (void *)raw->data;
	ma_ptr = (void *) raw->data + vrl_header_size;
	boot_header = (struct vsp_secure_boot_header *)
		(ptr + vrl_header_size);
	ma_header = (struct vsp_multi_app_blob_data *)
		(ma_ptr + boot_header->ma_header_offset);

	/* get firmware header */
	memcpy(&vsp_priv->boot_header, boot_header, sizeof(vsp_priv->boot_header));

	if (vsp_priv->boot_header.magic_number != VSP_SECURE_BOOT_MAGIC_NR) {
		DRM_ERROR("VSP: failed to load correct vsp firmware\n"
			  "FW magic number is wrong %x (should be %x)\n",
			  vsp_priv->boot_header.magic_number,
			  VSP_SECURE_BOOT_MAGIC_NR);
		ret = -1;
		goto out;
	}

	/* read application firmware image data (for state-buffer size, etc) */
	/* load the multi-app blob header */
	memcpy(&vsp_priv->ma_header, ma_header, sizeof(vsp_priv->ma_header));
	if (vsp_priv->ma_header.magic_number != VSP_MULTI_APP_MAGIC_NR) {
		DRM_ERROR("VSP: failed to load correct vsp firmware\n"
			  "FW magic number is wrong %x (should be %x)\n",
			  vsp_priv->ma_header.magic_number,
			  VSP_MULTI_APP_MAGIC_NR);
		ret = -1;
		goto out;
	}

	VSP_DEBUG("firmware secure header:\n");
	VSP_DEBUG("boot_header magic number %x\n", boot_header->magic_number);
	VSP_DEBUG("boot_text_offset %x\n", boot_header->boot_text_offset);
	VSP_DEBUG("boot_text_reg %x\n", boot_header->boot_text_reg);
	VSP_DEBUG("boot_icache_value %x\n", boot_header->boot_icache_value);
	VSP_DEBUG("boot_icache_reg %x\n", boot_header->boot_icache_reg);
	VSP_DEBUG("boot_pc_value %x\n", boot_header->boot_pc_value);
	VSP_DEBUG("boot_pc_reg %x\n", boot_header->boot_pc_reg);
	VSP_DEBUG("ma_header_offset %x\n", boot_header->ma_header_offset);
	VSP_DEBUG("ma_header_reg %x\n", boot_header->ma_header_reg);
	VSP_DEBUG("boot_start_value %x\n", boot_header->boot_start_value);
	VSP_DEBUG("boot_start_reg %x\n", boot_header->boot_start_reg);
	VSP_DEBUG("firmware ma_blob header:\n");
	VSP_DEBUG("ma_header magic number %x\n", ma_header->magic_number);
	VSP_DEBUG("offset_from_start %x\n", ma_header->offset_from_start);
	VSP_DEBUG("imr_state_buffer_addr %x\n", ma_header->imr_state_buffer_addr);
	VSP_DEBUG("imr_state_buffer_size %x\n", ma_header->imr_state_buffer_size);
	VSP_DEBUG("apps_default_context_buffer_size %x\n",
			ma_header->apps_default_context_buffer_size);

	/* get imr 11 region start address and size */
	imr_addr = intel_mid_msgbus_read32(PNW_IMR_MSG_PORT,
					   TNG_IMR11L_MSG_REGADDR);
	imr_addr <<= 10;
	VSP_DEBUG("IMR11 base address %p\n", imr_addr);

	imr_size = raw->size;

	/* map imr 11 */
	/* check if raw size is smaller than */
	/* ioremap the region */
	imr_ptr = ioremap(imr_addr, imr_size);
	if (!imr_ptr) {
		DRM_ERROR("failed to map imr_addr\n");
		ret = -1;
		goto out;
	}

	/* copy the firmware to imr 11 */
	memcpy(imr_ptr, ptr, raw->size);

	/* unmap the region */
	iounmap(imr_ptr);
#ifdef CONFIG_DX_SEP54
	ret = sepapp_image_verify(imr_addr, imr_size, 15, vsp_magic_num);
	if (ret) {
		DRM_ERROR("failed to verify vsp firmware, ret %x\n", ret);
		ret = -1;
		goto out;
	}
#endif

	vsp_priv->fw_loaded = VSP_FW_LOADED;
	vsp_priv->vsp_state = VSP_STATE_DOWN;

	vsp_priv->ctrl = (struct vsp_ctrl_reg *) (dev_priv->vsp_reg +
						  VSP_CONFIG_REG_SDRAM_BASE +
						  VSP_CONFIG_REG_START);
out:
	release_firmware(raw);

	return ret;
}
/**
 * Power on sequence for video mode MIPI panel.
 * NOTE: do NOT modify this function
 */
static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config,
		struct panel_funcs *p_funcs)
{
	u32 val = 0;
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_psb_private *dev_priv;
	struct drm_device *dev;
	int retry, reset_count = 10;
	int i;
	int err = 0;
	u32 guit_val = 0;
	u32 power_island = 0;
	int offset = 0;

	PSB_DEBUG_ENTRY("\n");

	if (!dsi_config)
		return -EINVAL;

	regs = &dsi_config->regs;
	ctx = &dsi_config->dsi_hw_context;
	dev = dsi_config->dev;
	dev_priv = dev->dev_private;
	power_island = pipe_to_island(dsi_config->pipe);

	if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C))
		power_island |= OSPM_DISPLAY_MIO;
	if (is_dual_dsi(dev))
		power_island |= OSPM_DISPLAY_C;

	if (!power_island_get(power_island))
		return -EAGAIN;

reset_recovery:
	--reset_count;
	/*HW-Reset*/
	if (p_funcs && p_funcs->reset)
		p_funcs->reset(dsi_config);

	/*
	 * Wait for DSI PLL locked on pipe, and only need to poll status of pipe
	 * A as both MIPI pipes share the same DSI PLL.
	 */
	if (dsi_config->pipe == 0) {
		retry = 20000;
		while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) &&
				--retry)
			udelay(150);
		if (!retry) {
			DRM_ERROR("PLL failed to lock on pipe\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}

	if (IS_ANN_A0(dev)) {
		/* FIXME: reset the DC registers for ANN A0 */
		power_island_get(OSPM_DISPLAY_B | OSPM_DISPLAY_C);

		REG_WRITE(DSPCLK_GATE_D, 0xFFFFFFFF); /* 0x10000000 */
		REG_WRITE(RAMCLK_GATE_D, 0xFFFFFFFF); /* 0x0 */
		REG_WRITE(PFIT_CONTROL, 0x20000000);
		REG_WRITE(DSPIEDCFGSHDW, 0x0);
		REG_WRITE(DSPARB2, 0x000A0200);
		REG_WRITE(DSPARB, 0x18040080);
		REG_WRITE(DSPFW1, 0x0F0F3F3F);
		REG_WRITE(DSPFW2, 0x5F2F0F3F);
		REG_WRITE(DSPFW3, 0x0);
		REG_WRITE(DSPFW4, 0x07071F1F);
		REG_WRITE(DSPFW5, 0x2F17071F);
		REG_WRITE(DSPFW6, 0x00001F3F);
		REG_WRITE(DSPFW7, 0x1F3F1F3F);
		REG_WRITE(DSPSRCTRL, 0x00080100);
		REG_WRITE(DSPCHICKENBIT, 0x0);
		REG_WRITE(FBDC_CHICKEN, 0x0C0C0C0C);
		REG_WRITE(CURACNTR, 0x0);
		REG_WRITE(CURBCNTR, 0x0);
		REG_WRITE(CURCCNTR, 0x0);
		REG_WRITE(IEP_OVA_CTRL, 0x0);
		REG_WRITE(IEP_OVA_CTRL, 0x0);
		REG_WRITE(DSPACNTR, 0x0);
		REG_WRITE(DSPBCNTR, 0x0);
		REG_WRITE(DSPCCNTR, 0x0);
		REG_WRITE(DSPDCNTR, 0x0);
		REG_WRITE(DSPECNTR, 0x0);
		REG_WRITE(DSPFCNTR, 0x0);

		power_island_put(OSPM_DISPLAY_B | OSPM_DISPLAY_C);
	}

	__dpi_set_properties(dsi_config, PORT_A);

	/*Setup pipe timing*/
	REG_WRITE(regs->htotal_reg, ctx->htotal);
	REG_WRITE(regs->hblank_reg, ctx->hblank);
	REG_WRITE(regs->hsync_reg, ctx->hsync);
	REG_WRITE(regs->vtotal_reg, ctx->vtotal);
	REG_WRITE(regs->vblank_reg, ctx->vblank);
	REG_WRITE(regs->vsync_reg, ctx->vsync);
	REG_WRITE(regs->pipesrc_reg, ctx->pipesrc);

	REG_WRITE(regs->dsppos_reg, ctx->dsppos);
	REG_WRITE(regs->dspstride_reg, ctx->dspstride);

	/*Setup plane*/
	REG_WRITE(regs->dspsize_reg, ctx->dspsize);
	REG_WRITE(regs->dspsurf_reg, ctx->dspsurf);
	REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff);
	REG_WRITE(regs->vgacntr_reg, ctx->vgacntr);

	/*restore color_coef (chrome) */
	for (i = 0; i < 6; i++)
		REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]);

	/* restore palette (gamma) */
	for (i = 0; i < 256; i++)
		REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]);

	/* restore dpst setting */
	if (dev_priv->psb_dpst_state) {
		dpstmgr_reg_restore_locked(dev, dsi_config);
		psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
	}

	if (__dpi_config_port(dsi_config, p_funcs, PORT_A) != 0) {
		if (!reset_count) {
				err = -EAGAIN;
				goto power_on_err;
			}
			DRM_ERROR("Failed to init dsi controller, reset it!\n");
			goto reset_recovery;
	}
	if (is_dual_dsi(dev)) {
		__dpi_set_properties(dsi_config, PORT_C);
		__dpi_config_port(dsi_config, p_funcs, PORT_C);
	}

	/**
	 * Different panel may have different ways to have
	 * drvIC initialized. Support it!
	 */
	if (p_funcs && p_funcs->drv_ic_init) {
		if (p_funcs->drv_ic_init(dsi_config)) {
			if (!reset_count) {
				err = -EAGAIN;
				goto power_on_err;
			}

			DRM_ERROR("Failed to init dsi controller, reset it!\n");
			goto reset_recovery;
		}
	}

	/*Enable MIPI Port A*/
	offset = 0x0;
	REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31));

	REG_WRITE(regs->dpi_control_reg + offset, BIT1);
	if (is_dual_dsi(dev)) {
		/*Enable MIPI Port C*/
		offset = 0x1000;
		REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31));
		offset = 0x800;
		REG_WRITE(regs->dpi_control_reg + offset, BIT1);
	}
	/**
	 * Different panel may have different ways to have
	 * panel turned on. Support it!
	 */
	if (p_funcs && p_funcs->power_on)
		if (p_funcs->power_on(dsi_config)) {
			DRM_ERROR("Failed to power on panel\n");
			err = -EAGAIN;
			goto power_on_err;
		}

	if (IS_ANN_A0(dev)) {
		REG_WRITE(regs->ddl1_reg, ctx->ddl1);
		REG_WRITE(regs->ddl2_reg, ctx->ddl2);
		REG_WRITE(regs->ddl3_reg, ctx->ddl3);
		REG_WRITE(regs->ddl4_reg, ctx->ddl4);
	}

	/*Enable pipe*/
	val = ctx->pipeconf;
	val &= ~0x000c0000;
	/**
	 * Frame Start occurs on third HBLANK
	 * after the start of VBLANK
	 */
	val |= BIT31 | BIT28;
	REG_WRITE(regs->pipeconf_reg, val);
	/*Wait for pipe enabling,when timing generator
	  is wroking */
	if (REG_READ(regs->mipi_reg) & BIT31) {
		retry = 10000;
		while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30))
			udelay(3);

		if (!retry) {
			DRM_ERROR("Failed to enable pipe\n");
			err = -EAGAIN;
			goto power_on_err;
		}
	}
	/*enable plane*/
	val = ctx->dspcntr | BIT31;
	REG_WRITE(regs->dspcntr_reg, val);

	if (p_funcs && p_funcs->set_brightness) {
		if (p_funcs->set_brightness(dsi_config,
				ctx->lastbrightnesslevel))
			DRM_ERROR("Failed to set panel brightness\n");
	} else {
		DRM_ERROR("Failed to set panel brightness\n");
	}
	if (p_funcs && p_funcs->drv_set_panel_mode)
		p_funcs->drv_set_panel_mode(dsi_config);

	psb_enable_vblank(dev, dsi_config->pipe);
	return err;

power_on_err:
	power_island_put(power_island);
	return err;
}
/**
 * Set up the display clock 
 *
 */
void mrfld_setup_pll(struct drm_device *dev, int pipe, int clk)
{
	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
	int refclk = 0;
	int clk_n = 0, clk_p2 = 0, clk_byte = 1, m_conv = 0, clk_tmp = 0;
	struct mrst_clock_t clock;
	bool ok;
	u32 pll = 0, fp = 0;
	bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
	struct mdfld_dsi_config *dsi_config = NULL;
	struct mdfld_dsi_hw_context *ctx = NULL;

	PSB_DEBUG_ENTRY("pipe = 0x%x\n", pipe);

	if (pipe == 0)
		dsi_config = dev_priv->dsi_configs[0];
	else if (pipe == 2)
		dsi_config = dev_priv->dsi_configs[1];

	if ((pipe != 1) && !dsi_config) {
		DRM_ERROR("Invalid DSI config\n");
		return;
	}

	if (pipe != 1) {
		ctx = &dsi_config->dsi_hw_context;

		mutex_lock(&dsi_config->context_lock);
	}

	switch (pipe) {
	case 0:
		is_mipi = true;
		break;
	case 1:
		is_hdmi = true;
		break;
	case 2:
		is_mipi2 = true;
		break;
	}

	if ((dev_priv->ksel == KSEL_CRYSTAL_19)
	    || (dev_priv->ksel == KSEL_BYPASS_19)) {
		refclk = 19200;

		if (is_mipi || is_mipi2) {
			clk_n = 1, clk_p2 = 8;
		} else if (is_hdmi) {
			clk_n = 1, clk_p2 = 10;
		}
	} else if (dev_priv->ksel == KSEL_BYPASS_25) {
		refclk = 25000;

		if (is_mipi || is_mipi2) {
			clk_n = 1, clk_p2 = 8;
		} else if (is_hdmi) {
			clk_n = 1, clk_p2 = 10;
		}
	} else if ((dev_priv->ksel == KSEL_BYPASS_83_100)
		   && (dev_priv->core_freq == 166)) {
		refclk = 83000;

		if (is_mipi || is_mipi2) {
			clk_n = 4, clk_p2 = 8;
		} else if (is_hdmi) {
			clk_n = 4, clk_p2 = 10;
		}
	} else if ((dev_priv->ksel == KSEL_BYPASS_83_100) &&
		   (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
		refclk = 100000;
		if (is_mipi || is_mipi2) {
			clk_n = 4, clk_p2 = 8;
		} else if (is_hdmi) {
			clk_n = 4, clk_p2 = 10;
		}
	}

	if (is_mipi || is_mipi2)
		clk_byte = 3;

	clk_tmp = clk * clk_n * clk_p2 * clk_byte;

	PSB_DEBUG_ENTRY("clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n,
			clk_p2);
	PSB_DEBUG_ENTRY("clk = %d, clk_tmp = %d, clk_byte = %d. \n", clk,
			clk_tmp, clk_byte);

	ok = mrfld_find_best_PLL(dev, pipe, clk_tmp, refclk, &clock);
	dev_priv->tmds_clock_khz = clock.dot / (clk_n * clk_p2 * clk_byte);

	/*
	 * FIXME: Hard code the divisors' value for JDI panel, and need to
	 * calculate them according to the DSI PLL HAS spec.
	 */
	if (pipe != 1) {
		if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) {
			if (get_panel_type(dev, pipe) == JDI_7x12_CMD) {
				clock.p1 = 4;
				clk_n = 1;
				clock.m = 142;
			} else if ((get_panel_type(dev, pipe) == SHARP_10x19_CMD) ||
				(get_panel_type(dev, pipe) == SHARP_25x16_CMD))
			{
				clock.p1 = 3;
				clk_n = 1;
				clock.m = 137;
			} else {
				clock.p1 = 4;
				clk_n = 1;
				clock.m = 120;
			}
		} else if (is_dual_dsi(dev)) {
			clock.p1 = 2;
			clk_n = 1;
			clock.m = 104;
		} else {
			clock.p1 = 5;
			clk_n = 1;
			clock.m = 130;
		}
	}

	if (!ok) {
		DRM_ERROR("mdfldFindBestPLL fail in mrfld_crtc_mode_set.\n");
	} else {
		m_conv = mrfld_m_converts[(clock.m - MRFLD_M_MIN)];

		PSB_DEBUG_ENTRY("dot clock = %d,"
				"m = %d, p1 = %d, m_conv = %d. \n", clock.dot,
				clock.m, clock.p1, m_conv);
	}

	/* Write the N1 & M1 parameters into DSI_PLL_DIV_REG */
	fp = (clk_n / 2) << 16;
	fp |= m_conv;
	/*TODO:vcheeram - Remove the hardcoding of fp for JDI_7x12_CMD panel
	 * on ANN for fp.
	 */
	if (IS_ANN_A0(dev) && dsi_config != NULL && (get_panel_type(dev, dsi_config->pipe) == JDI_7x12_CMD))
		fp = 0x177;

	if (is_mipi) {
		/* Enable DSI PLL clocks for DSI0 rather than CCK. */
		pll |= _CLK_EN_PLL_DSI0;
		pll &= ~_CLK_EN_CCK_DSI0;
		/* Select DSI PLL as the source of the mux input clocks. */
		pll &= ~_DSI_MUX_SEL_CCK_DSI0;
	}

	if (is_mipi2 || is_dual_dsi(dev)) {
		/* Enable DSI PLL clocks for DSI1 rather than CCK. */
		pll |= _CLK_EN_PLL_DSI1;
		pll &= ~_CLK_EN_CCK_DSI1;
		/* Select DSI PLL as the source of the mux input clocks. */
		pll &= ~_DSI_MUX_SEL_CCK_DSI1;
	}

	if (is_hdmi)
		pll |= MDFLD_VCO_SEL;

	/* compute bitmask from p1 value */
	pll |= (1 << (clock.p1 - 2)) << 17;

	if (pipe != 1) {
		ctx->dpll = pll;
		ctx->fp = fp;
		mutex_unlock(&dsi_config->context_lock);
	}
}