/* 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;
}
/**
 * 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;

    if (!dsi_config)
        return -EINVAL;

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

    if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
                                   OSPM_UHB_FORCE_POWER_ON))
        return -EAGAIN;
reset_recovery:
    --reset_count;
    /*HW-Reset*/
    if (p_funcs && p_funcs->reset)
        p_funcs->reset(dsi_config);

    /*Enable DSI PLL*/
    if (!(REG_READ(regs->dpll_reg) & BIT31)) {
        if(ctx->pll_bypass_mode) {
            uint32_t dpll = 0;

            REG_WRITE(regs->dpll_reg, dpll);
            if (ctx->cck_div) {
                dpll = dpll | BIT11;
                REG_WRITE(regs->dpll_reg, dpll);
                udelay(1);
            }
            dpll = dpll | BIT12;
            REG_WRITE(regs->dpll_reg, dpll);
            mdelay(1);
            dpll = dpll | BIT13;
            REG_WRITE(regs->dpll_reg, dpll);
            mdelay(1);
        } else {
            REG_WRITE(regs->dpll_reg, 0x0);
            REG_WRITE(regs->fp_reg, 0x0);
            REG_WRITE(regs->fp_reg, ctx->fp);
            REG_WRITE(regs->dpll_reg, ((ctx->dpll) & ~BIT30));

            udelay(2);
            val = REG_READ(regs->dpll_reg);
            REG_WRITE(regs->dpll_reg, (val | BIT31));

            /*wait for PLL lock on pipe*/
            retry = 10000;
            while (--retry && !(REG_READ(PIPEACONF) & BIT29))
                udelay(3);
            if (!retry) {
                DRM_ERROR("PLL failed to lock on pipe\n");
                err = -EAGAIN;
                goto power_on_err;
            }
        }
    }

    REG_WRITE(regs->eot_disable_reg,
              (REG_READ(regs->eot_disable_reg) & ~BIT1));
    REG_WRITE(regs->device_ready_reg, ~BIT0);
    REG_WRITE(regs->device_ready_reg, BIT0);
    mdelay(1);

    /*exit ULPS*/
    if (__dpi_exit_ulps_locked(dsi_config)) {
        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));

    /*D-PHY parameter*/
    REG_WRITE(regs->dphy_param_reg, ctx->dphy_param);

    /*Configure DSI controller*/
    REG_WRITE(regs->mipi_control_reg, ctx->mipi_control);
    REG_WRITE(regs->intr_en_reg, ctx->intr_en);
    REG_WRITE(regs->hs_tx_timeout_reg, ctx->hs_tx_timeout);
    REG_WRITE(regs->lp_rx_timeout_reg, ctx->lp_rx_timeout);
    REG_WRITE(regs->turn_around_timeout_reg,
              ctx->turn_around_timeout);
    REG_WRITE(regs->device_reset_timer_reg,
              ctx->device_reset_timer);
    REG_WRITE(regs->high_low_switch_count_reg,
              ctx->high_low_switch_count);
    REG_WRITE(regs->init_count_reg, ctx->init_count);
    REG_WRITE(regs->eot_disable_reg, ctx->eot_disable);
    REG_WRITE(regs->lp_byteclk_reg, ctx->lp_byteclk);
    REG_WRITE(regs->clk_lane_switch_time_cnt_reg,
              ctx->clk_lane_switch_time_cnt);
    if (ctx->pll_bypass_mode) {
        /*Force using non-burst pulse event mode here*/
        REG_WRITE(regs->video_mode_format_reg, 0x1);
    } else {
        REG_WRITE(regs->video_mode_format_reg, ctx->video_mode_format);
    }
    REG_WRITE(regs->dsi_func_prg_reg, ctx->dsi_func_prg);

    /*DSI timing*/
    REG_WRITE(regs->dpi_resolution_reg, ctx->dpi_resolution);
    REG_WRITE(regs->hsync_count_reg, ctx->hsync_count);
    REG_WRITE(regs->hbp_count_reg, ctx->hbp_count);
    REG_WRITE(regs->hfp_count_reg, ctx->hfp_count);
    REG_WRITE(regs->hactive_count_reg, ctx->hactive_count);
    REG_WRITE(regs->vsync_count_reg, ctx->vsync_count);
    REG_WRITE(regs->vbp_count_reg, ctx->vbp_count);
    REG_WRITE(regs->vfp_count_reg, ctx->vfp_count);

    /*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 gamma correction max (RGB) */
    REG_WRITE(regs->gamma_red_max_reg, ctx->gamma_red_max);
    REG_WRITE(regs->gamma_green_max_reg, ctx->gamma_green_max);
    REG_WRITE(regs->gamma_blue_max_reg, ctx->gamma_blue_max);

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

    /*Enable DSI Controller*/
    REG_WRITE(regs->device_ready_reg, (REG_READ(regs->device_ready_reg) | BIT0));

    /**
     * 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) {
                goto reset_err_bypass;
            }
            pmu_nc_set_power_state(OSPM_MIPI_ISLAND,
                                   OSPM_ISLAND_DOWN, OSPM_REG_TYPE);

            pmu_nc_set_power_state(OSPM_MIPI_ISLAND,
                                   OSPM_ISLAND_UP, OSPM_REG_TYPE);

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

reset_err_bypass:

    if (ctx->pll_bypass_mode) {
        /*Reprogram to use pll clock*/
        REG_WRITE(regs->dpll_reg, 0x0);
        REG_WRITE(regs->fp_reg, 0x0);
        REG_WRITE(regs->fp_reg, ctx->fp);
        REG_WRITE(regs->dpll_reg, ((ctx->dpll) & ~BIT30));

        udelay(2);
        REG_WRITE(regs->dpll_reg, 0x2 << 17);
        mdelay(1);
        REG_WRITE(regs->dpll_reg, (0x2 << 17 | BIT31));

        /*wait for PLL lock on pipe*/
        retry = 10000;
        while (--retry && !(REG_READ(PIPEACONF) & BIT29))
            udelay(3);
        if (!retry) {
            DRM_ERROR("PLL failed to lock on pipe\n");
            err = -EAGAIN;
            goto power_on_err;
        }

        /*Switch back to burst mode*/
        REG_WRITE(regs->video_mode_format_reg, ctx->video_mode_format);

        /*Clear device ready reg*/
        REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) & ~DSI_DEVICE_READY);
        msleep(1);
        /*Enable DSI Controller*/
        REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) | DSI_DEVICE_READY);
        msleep(1);
    }

    /**
     * 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 MIPI Port*/
    REG_WRITE(regs->mipi_reg, (ctx->mipi | BIT31));

    /*Enable pipe*/
    val = ctx->pipeconf;
    val &= ~0x000c0000;
    val |= BIT31;

    /* disable gamma if needed */
    if (drm_psb_enable_color_conversion == 0)
        val &= ~(PIPEACONF_COLOR_MATRIX_ENABLE);


    REG_WRITE(regs->pipeconf_reg, val);
    REG_WRITE(regs->pipestat_reg, ctx->pipestat |
              PIPE_VBLANK_INTERRUPT_ENABLE);

    /*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;

    /* disable gamma if needed */
    if (drm_psb_enable_gamma == 0)
        val &= ~(PIPEACONF_GAMMA);

    REG_WRITE(regs->dspcntr_reg, val);

    /*Notify PVR module that screen is on*/
    if (dev_priv->pvr_screen_event_handler)
        dev_priv->pvr_screen_event_handler(dev, 1);

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

power_on_err:
    ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
    return err;
}
Exemple #4
0
/**
 * 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, bool first_boot)
{
	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 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;
	if (android_hdmi_is_connected(dev) && first_boot)
			otm_hdmi_power_islands_on();

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(dev)) {
		/* FIXME: reset the DC registers for ANN A0 */
		ann_dc_setup(dsi_config);
	}

	__dpi_set_properties(dsi_config, PORT_A);

	/* update 0x650c[0] = 1 to fixed arbitration pattern
	 * it is found display TLB request be blocked by display plane
	 * memory requests, never goes out. This causes display controller
	 * uses stale TLB data to do memory translation, getting wrong
	 * memory address for data, and causing the flickering issue.
	 */
	REG_WRITE(GCI_CTRL, REG_READ(GCI_CTRL) | 1);

	/*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), csc_setting_save[i]);

	/* restore palette (gamma) */
	for (i = 0; i < 256; i++)
		REG_WRITE(regs->palette_reg + (i<<2), gamma_setting_save[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(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);

		REG_WRITE(DSPARB2, ctx->dsparb2);
		REG_WRITE(DSPARB, ctx->dsparb);
	}

	/*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;
}
/**
 * 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;
}