static void dpst_save_gamma_settings(struct drm_device *dev)
{
    struct drm_psb_private *dev_priv = dev->dev_private;
    struct drm_connector *connector;
    struct mdfld_dsi_config *dsi_config;
    struct drm_crtc *crtc;
    struct psb_intel_crtc *psb_intel_crtc;
    int i = 0;

    if (!dev_priv)
        return;

    connector = dev_priv->dpst_connector;
    dsi_config = dev_priv->dsi_configs[0];

    crtc = connector->encoder->crtc;
    psb_intel_crtc = to_psb_intel_crtc(crtc);

    /*
    * FIXME: We need to force the Display to
    * turn on but on TNG OSPM how we can force PIPEA to do it?
    */
    if (!power_island_get(OSPM_DISPLAY_A))
    {
	return;
    }

    for (i = 0; i < 256; i++)
        lut_adj[i] = REG_READ((PALETTE_A + 4 * i));

    power_island_put(OSPM_DISPLAY_A);
}
// SH START DIET
// SH TODO This doesn't work yet.
int psb_diet_enable(struct drm_device *dev, void *data)
{
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct mdfld_dsi_config *dsi_config = NULL;
	struct mdfld_dsi_hw_context *ctx = NULL;
	uint32_t * arg = data;
	struct dpst_ie_histogram_control ie_hist_cont_reg;
	u32 i;
	int dpst3_bin_threshold_count = 1;
	int dpst_hsv_multiplier = 2;
	uint32_t blm_hist_ctl = HISTOGRAM_LOGIC_CONTROL;
	uint32_t iebdr_reg = HISTOGRAM_BIN_DATA;
	int dpst3_bin_count = 32;

	if (!dev_priv)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if (!dsi_config)
		return 0;
	ctx = &dsi_config->dsi_hw_context;

	if (power_island_get(OSPM_DISPLAY_A))
        {
		if (data) {
			ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
			ie_hist_cont_reg.bin_reg_func_select =
				dpst3_bin_threshold_count;
			ie_hist_cont_reg.bin_reg_index = 0;
			PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
			for (i = 0; i < dpst3_bin_count; i++)
			{
				PSB_WVDC32(arg[i], iebdr_reg);
			}
			ctx->aimg_enhance_bin = PSB_RVDC32(iebdr_reg);

			ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
			ie_hist_cont_reg.ie_mode_table_enabled = 1;
			ie_hist_cont_reg.alt_enhancement_mode = dpst_hsv_multiplier;
			PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;

		} else {
			ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
			ie_hist_cont_reg.ie_mode_table_enabled = 0;
			PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;
		}

		power_island_put(OSPM_DISPLAY_A);
	}

	return 0;
}
 static int psb_hist_status(struct drm_device *dev, void *data)
{
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct drm_psb_hist_status_arg *hist_status = data;
	uint32_t * arg = hist_status->buf;
	struct mdfld_dsi_config *dsi_config = NULL;
	u32 iedbr_reg_data = 0;
	struct dpst_ie_histogram_control ie_hist_cont_reg;
	u32 i;
	int dpst3_bin_threshold_count = 0;
	uint32_t blm_hist_ctl = HISTOGRAM_LOGIC_CONTROL;
	uint32_t iebdr_reg = HISTOGRAM_BIN_DATA;
	uint32_t segvalue_max_22_bit = 0x3fffff;
	uint32_t iedbr_busy_bit = 0x80000000;
	int dpst3_bin_count = 32; //Different DPST Algs has different Values?

	if (!dev_priv)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if (!dsi_config)
		return 0;

	/*
        * FIXME: We need to force the Display to
        * turn on but on TNG OSPM how we can force PIPEA to do it?
        */
        if (power_island_get(OSPM_DISPLAY_A))
	{
		ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
		ie_hist_cont_reg.bin_reg_func_select = dpst3_bin_threshold_count;
		ie_hist_cont_reg.bin_reg_index = 0;

		PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
		for (i = 0; i < dpst3_bin_count; i++) {
			iedbr_reg_data = PSB_RVDC32(iebdr_reg);
			if (!(iedbr_reg_data & iedbr_busy_bit)) {
				arg[i] = iedbr_reg_data & segvalue_max_22_bit;
			} else {
				i = 0;
				ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
				ie_hist_cont_reg.bin_reg_index = 0;
				PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
			}
		}

		power_island_put(OSPM_DISPLAY_A);
	}

	return 0;
}
Beispiel #4
0
static PVRSRV_ERROR SysDevicePrePowerState(
		PVRSRV_DEV_POWER_STATE eNewPowerState,
		PVRSRV_DEV_POWER_STATE eCurrentPowerState,
		IMG_BOOL bForced)
{
	if ((eNewPowerState != eCurrentPowerState) &&
		(eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)) {
		PVR_DPF((PVR_DBG_MESSAGE, "Remove SGX power"));
		if (!power_island_put(OSPM_GRAPHICS_ISLAND))
			return PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE;
	}

	return PVRSRV_OK;
}
Beispiel #5
0
static void ann_dc_setup(struct mdfld_dsi_config *dsi_config)
{
	struct drm_device *dev = dsi_config->dev;
	struct mdfld_dsi_hw_registers *regs = &dsi_config->regs;
	struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context;


	DRM_INFO("restore some registers to default value\n");

	power_island_get(OSPM_DISPLAY_B | OSPM_DISPLAY_C);

	REG_WRITE(DSPCLK_GATE_D, 0x0);
	REG_WRITE(RAMCLK_GATE_D, 0xc0000 | (1 << 11)); // FIXME: delay 1us for RDB done signal
	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, 0x20);
	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(DSPBCNTR, 0x0);
	REG_WRITE(DSPCCNTR, 0x0);
	REG_WRITE(DSPDCNTR, 0x0);
	REG_WRITE(DSPECNTR, 0x0);
	REG_WRITE(DSPFCNTR, 0x0);
	REG_WRITE(GCI_CTRL, REG_READ(GCI_CTRL) | 1);

	power_island_put(OSPM_DISPLAY_B | OSPM_DISPLAY_C);

	DRM_INFO("setup drain latency\n");

	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);
}
 int psb_dpst_mode(struct drm_device *dev, void *data)
{
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct mdfld_dsi_config *dsi_config = NULL;
	uint32_t * arg = data;
	uint32_t x = 0;
	uint32_t y = 0;
	uint32_t reg;

	if (!dev_priv)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if (!dsi_config)
		return 0;

	if (!power_island_get(OSPM_DISPLAY_A))
		return 0;

	reg = PSB_RVDC32(PIPEASRC);

	power_island_put(OSPM_DISPLAY_A);

	/* horizontal is the left 16 bits */
	x = reg >> 16;

	/* vertical is the right 16 bits */
	y = reg & 0x0000ffff;

	/* the values are the image size minus one */
	x += 1;
	y += 1;
	*arg = (x << 16) | y;

	if (x*y <= 1280*800)
		dpst_hist_fake = dpst_hist_720p;
	else if (x*y <= 1920*1200)
		dpst_hist_fake = dpst_hist_1080p;
	else
		dpst_hist_fake = dpst_hist_25x16;

	return 0;
}
static int mdfld_dsi_jdi_detect(struct mdfld_dsi_config *dsi_config)
{
	int status;
	struct drm_device *dev = dsi_config->dev;
	struct mdfld_dsi_hw_registers *regs = &dsi_config->regs;
	u32 dpll_val, device_ready_val;
	int pipe = dsi_config->pipe;
	u32 power_island = 0;

	PSB_DEBUG_ENTRY("\n");

	if (pipe == 0) {
		/*
		 * FIXME: WA to detect the panel connection status, and need to
		 * implement detection feature with get_power_mode DSI command.
		 */
		power_island = pipe_to_island(pipe);

		if (!power_island_get(power_island)) {
			DRM_ERROR("Failed to turn on power island\n");
			return -EAGAIN;
		}

		dpll_val = REG_READ(regs->dpll_reg);
		device_ready_val = REG_READ(regs->device_ready_reg);
		if ((device_ready_val & DSI_DEVICE_READY) &&
				(dpll_val & DPLL_VCO_ENABLE)) {
			dsi_config->dsi_hw_context.panel_on = true;
		} else {
			dsi_config->dsi_hw_context.panel_on = false;
			DRM_INFO("%s: panel is not detected!\n", __func__);
		}

		status = MDFLD_DSI_PANEL_CONNECTED;

		power_island_put(power_island);
	} else {
		DRM_INFO("%s: do NOT support dual panel\n", __func__);
		status = MDFLD_DSI_PANEL_DISCONNECTED;
	}

	return status;
}
 int psb_update_guard(struct drm_device *dev, void *data)
{
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct dpst_guardband *input = (struct dpst_guardband *)data;
	struct mdfld_dsi_config *dsi_config = NULL;
	struct mdfld_dsi_hw_context *ctx = NULL;
	struct dpst_guardband reg_data;

	if (!dev_priv)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if (!dsi_config)
		return 0;
	ctx = &dsi_config->dsi_hw_context;

	/*
        * FIXME: We need to force the Display to
        * turn on but on TNG OSPM how we can force PIPEA to do it?
        */
        if (!power_island_get(OSPM_DISPLAY_A))
        {
		return 0;
	}

	reg_data.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
	reg_data.guardband = input->guardband;
	reg_data.guardband_interrupt_delay = input->guardband_interrupt_delay;

	/* printk(KERN_ALERT "guardband = %u\ninterrupt delay = %u\n",
		reg_data.guardband, reg_data.guardband_interrupt_delay); */
	PSB_WVDC32(reg_data.data, HISTOGRAM_INT_CONTROL);
	ctx->histogram_intr_ctrl = reg_data.data;
	dpst_print("guardband 0x%x\n", reg_data.data);

	power_island_put(OSPM_DISPLAY_A);

	return 0;
}
/* this function is only called by dpms on or late resume function */
void dpstmgr_reg_restore_locked(struct drm_device *dev, struct mdfld_dsi_config *dsi_config)
{
	struct mdfld_dsi_hw_context *ctx = NULL;
	struct drm_psb_private *dev_priv = NULL;
	struct mdfld_dsi_hw_registers *regs = NULL;

	if (!dsi_config || !dsi_config->dev)
		return;

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

	if (power_island_get(OSPM_DISPLAY_A))
	{

		PSB_WVDC32(ctx->histogram_intr_ctrl, regs->histogram_intr_ctrl_reg);
		PSB_WVDC32(ctx->histogram_logic_ctrl, regs->histogram_logic_ctrl_reg);
		PSB_WVDC32(ctx->aimg_enhance_bin, regs->aimg_enhance_bin_reg);
		PSB_WVDC32(ctx->lvds_port_ctrl, regs->lvds_port_ctrl_reg);

		power_island_put(OSPM_DISPLAY_A);
	}
}
void mdfld_reset_panel_handler_work(struct work_struct *work)
{
	struct drm_psb_private *dev_priv =
		container_of(work, struct drm_psb_private, reset_panel_work);
	struct mdfld_dsi_config *dsi_config = NULL;
	struct mdfld_dsi_dbi_output *dbi_output = NULL;
	struct panel_funcs *p_funcs  = NULL;
	struct drm_device *dev;

	dbi_output = dev_priv->dbi_output;
	dsi_config = dev_priv->dsi_configs[0];

	if (!dsi_config || !dbi_output)
		return;
	dev = dsi_config->dev;

	/*disable ESD when HDMI connected*/
	if (hdmi_state)
		return;

	PSB_DEBUG_ENTRY("\n");

	p_funcs = dbi_output->p_funcs;
	if (p_funcs) {
		mutex_lock(&dsi_config->context_lock);

		if (!dsi_config->dsi_hw_context.panel_on) {
			DRM_INFO("don't reset panel when panel is off\n");
			mutex_unlock(&dsi_config->context_lock);
			return;
		}

		DRM_INFO("Starts ESD panel reset\n");
		/*
		 * since panel is in abnormal state,
		 * we do a power off/on first
		 */
		power_island_put(OSPM_DISPLAY_A |
				 OSPM_DISPLAY_C |
				 OSPM_DISPLAY_MIO);
		power_island_get(OSPM_DISPLAY_A |
				 OSPM_DISPLAY_C |
				 OSPM_DISPLAY_MIO);

		if (__dbi_panel_power_off(dsi_config, p_funcs))
			DRM_INFO("failed to power off dbi panel\n");

		if (get_panel_type(dev, 0) == JDI_7x12_CMD)
			if (p_funcs && p_funcs->reset)
				p_funcs->reset(dsi_config);

		if (__dbi_panel_power_on(dsi_config, p_funcs)) {
			DRM_ERROR("failed to power on dbi panel\n");
			mutex_unlock(&dsi_config->context_lock);
			return;
		}

		mutex_unlock(&dsi_config->context_lock);

		/*recover pipestat in case island once been poweroff and pipestat was reset to default*/
		mdfld_recover_te(dev, dsi_config->pipe);

		DRM_INFO("%s: End panel reset\n", __func__);
	} else {
		DRM_INFO("%s invalid panel init\n", __func__);
	}
}
Beispiel #11
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;
}
Beispiel #12
0
/* generic dbi function */
static
int mdfld_generic_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
{
    struct mdfld_dsi_encoder *dsi_encoder;
    struct mdfld_dsi_dbi_output *dbi_output;
    struct mdfld_dsi_connector *dsi_connector;
    struct mdfld_dsi_config *dsi_config;
    struct panel_funcs *p_funcs;
    struct drm_device *dev;
    struct drm_psb_private *dev_priv;
    int pipe = 0;

    if (!encoder) {
        DRM_ERROR("Invalid encoder\n");
        return -EINVAL;
    }

    PSB_DEBUG_ENTRY("%s\n", (on ? "on" : "off"));

    dsi_encoder = MDFLD_DSI_ENCODER(encoder);
    dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
    dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
    dsi_connector = mdfld_dsi_encoder_get_connector(dsi_encoder);
    if (!dsi_connector) {
        DRM_ERROR("dsi_connector is NULL\n");
        return -EINVAL;
    }

    p_funcs = dbi_output->p_funcs;
    dev = encoder->dev;
    dev_priv = dev->dev_private;
    pipe = dsi_config->pipe;

    mutex_lock(&dsi_config->context_lock);

    if (dsi_connector->status != connector_status_connected)
        goto set_power_err;

    if (dbi_output->first_boot && on) {
        if (dsi_config->dsi_hw_context.panel_on) {
            /* When using smooth transition,
             * wake up ESD detection thread.
             */
            mdfld_dsi_error_detector_wakeup(dsi_connector);

            DRM_INFO("skip panle power setting for first boot!");
            goto fun_exit;
        }

        /* power down islands turned on by firmware */
        power_island_put(OSPM_DISPLAY_A |
                         OSPM_DISPLAY_C | OSPM_DISPLAY_MIO);
    }

    switch (on) {
    case true:
        /* panel is already on */
        if (dsi_config->dsi_hw_context.panel_on)
            goto fun_exit;

        if (__dbi_panel_power_on(dsi_config, p_funcs)) {
            DRM_ERROR("Faild to turn on panel\n");
            goto set_power_err;
        }

        dsi_config->dsi_hw_context.panel_on = 1;
        dbi_output->dbi_panel_on = 1;
        mdfld_dsi_error_detector_wakeup(dsi_connector);

        break;
    case false:
        if (!dsi_config->dsi_hw_context.panel_on &&
                !dbi_output->first_boot)
            goto fun_exit;
        if (__dbi_panel_power_off(dsi_config, p_funcs)) {
            DRM_ERROR("Faild to turn off panel\n");
            goto set_power_err;
        }

        dsi_config->dsi_hw_context.panel_on = 0;
        dbi_output->dbi_panel_on = 0;
        break;
    default:
        break;
    }

fun_exit:
    mutex_unlock(&dsi_config->context_lock);
    PSB_DEBUG_ENTRY("successfully\n");
    return 0;

set_power_err:
    mutex_unlock(&dsi_config->context_lock);
    PSB_DEBUG_ENTRY("unsuccessfully!\n");
    return -EAGAIN;
}
// SH START DIET
int psb_diet_enable(struct drm_device *dev, void *data)
{
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct mdfld_dsi_config *dsi_config = NULL;
	struct mdfld_dsi_hw_context *ctx = NULL;
	uint32_t * arg = data;
	struct dpst_ie_histogram_control ie_hist_cont_reg;
	u32 i;
	uint32_t blm_hist_ctl = HISTOGRAM_LOGIC_CONTROL;
	uint32_t iebdr_reg = HISTOGRAM_BIN_DATA;
	int dpst3_bin_count = 32;
	 u32 temp =0;

	if (!dev_priv)
		return 0;

	if(dev_priv->early_suspended)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if (!dsi_config)
		return 0;
	ctx = &dsi_config->dsi_hw_context;

	mutex_lock(&dpst_mutex);

	if (power_island_get(OSPM_DISPLAY_A))
	{
		mdfld_dsi_dsr_forbid(dsi_config);
		if (data) {
			ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
			dpst_print("hist_ctl: 0x%x\n", ie_hist_cont_reg.data);
			ie_hist_cont_reg.bin_reg_func_select = 1;
			ie_hist_cont_reg.bin_reg_index = 0;
			ie_hist_cont_reg.ie_histogram_enable = 1;
			ie_hist_cont_reg.ie_mode_table_enabled = 1;
			ie_hist_cont_reg.ie_pipe_assignment = 0;
#ifdef HSV
			ie_hist_cont_reg.histogram_mode_select = 1;//HSV
			ie_hist_cont_reg.alt_enhancement_mode = 2;//dpst_hsv_multiplier;
#else
			ie_hist_cont_reg.histogram_mode_select = 0;//YUV
			ie_hist_cont_reg.alt_enhancement_mode = 1; //additive
#endif
			PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
			if (drm_psb_debug & PSB_D_DPST) {
				printk("previous corr: ");
				for (i = 0; i <= dpst3_bin_count; i++)
				{
					printk(" 0x%x ", PSB_RVDC32(iebdr_reg));
				}
				printk("\n");
			}
			PSB_WVDC32(0x200, iebdr_reg);
			for (i = 1; i <= dpst3_bin_count; i++)
			{
				PSB_WVDC32(arg[i], iebdr_reg);
			}
			ctx->aimg_enhance_bin = PSB_RVDC32(iebdr_reg);

			ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);

			temp = ie_hist_cont_reg.data;
			temp|=(1<<27);
			temp&=~0x7f;
			ie_hist_cont_reg.data = temp;
			PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);

			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;
		} else {
			ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
			ie_hist_cont_reg.ie_mode_table_enabled = 0;
			PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;
		}

		mdfld_dsi_dsr_allow(dsi_config);
		power_island_put(OSPM_DISPLAY_A);
	}

	mutex_unlock(&dpst_mutex);

	return 0;
}
Beispiel #14
0
/**
 * Setup Display Controller to turn on/off a video mode panel.
 * Most of the video mode MIPI panel should follow the power on/off
 * sequence in this function.
 * NOTE: do NOT modify this function for new panel Enabling. Register
 * new panel function callbacks to make this function available for a
 * new video mode panel
 */
static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
{
	struct mdfld_dsi_encoder *dsi_encoder;
	struct mdfld_dsi_connector *dsi_connector;
	struct mdfld_dsi_dpi_output *dpi_output;
	struct mdfld_dsi_config *dsi_config;
	struct panel_funcs *p_funcs;
	int pipe;
	struct drm_device *dev;
	struct drm_psb_private *dev_priv;

	if (!encoder) {
		DRM_ERROR("Invalid encoder\n");
		return -EINVAL;
	}

	dsi_encoder = MDFLD_DSI_ENCODER(encoder);
	dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
	dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
	p_funcs = dpi_output->p_funcs;
	pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
	dsi_connector = mdfld_dsi_encoder_get_connector(dsi_encoder);
	if (!dsi_connector) {
		DRM_ERROR("dsi_connector is NULL\n");
		return -EINVAL;
	}

	dev = dsi_config->dev;
	dev_priv = dev->dev_private;

	if (dsi_connector->status != connector_status_connected)
		return 0;

	mutex_lock(&dsi_config->context_lock);

	if (dpi_output->first_boot && on) {
		if (dsi_config->dsi_hw_context.panel_on) {
			if (IS_ANN(dev))
				ann_dc_setup(dsi_config);

			psb_enable_vblank(dev, dsi_config->pipe);

			/* don't need ISLAND c for non dual-dsi panel */
			if (!is_dual_dsi(dev))
				power_island_put(OSPM_DISPLAY_C);

			DRM_INFO("skip panle power setting for first boot! "
				 "panel is already powered on\n");
			goto fun_exit;
		}
		if (android_hdmi_is_connected(dev))
			otm_hdmi_power_islands_off();
		/* power down islands turned on by firmware */
		power_island_put(OSPM_DISPLAY_A | OSPM_DISPLAY_C |
				 OSPM_DISPLAY_MIO);
	}

	switch (on) {
	case true:
		/* panel is already on */
		if (dsi_config->dsi_hw_context.panel_on)
			goto fun_exit;
		if (__dpi_panel_power_on(dsi_config, p_funcs, dpi_output->first_boot)) {
			DRM_ERROR("Faild to turn on panel\n");
			goto set_power_err;
		}
		dsi_config->dsi_hw_context.panel_on = 1;

		/* for every dpi panel power on, clear the dpi underrun count */
		dev_priv->pipea_dpi_underrun_count = 0;
		dev_priv->pipec_dpi_underrun_count = 0;

		break;
	case false:
		if (!dsi_config->dsi_hw_context.panel_on &&
			!dpi_output->first_boot)
			goto fun_exit;
		if (__dpi_panel_power_off(dsi_config, p_funcs)) {
			DRM_ERROR("Faild to turn off panel\n");
			goto set_power_err;
		}
		dsi_config->dsi_hw_context.panel_on = 0;
		break;
	default:
		break;
	}

fun_exit:
	mutex_unlock(&dsi_config->context_lock);
	PSB_DEBUG_ENTRY("successfully\n");
	return 0;
set_power_err:
	mutex_unlock(&dsi_config->context_lock);
	PSB_DEBUG_ENTRY("unsuccessfully!!!!\n");
	return -EAGAIN;
}
/* IOCTL - moved to standard calls for Kernel Integration */
int psb_hist_enable(struct drm_device *dev, void *data)
{
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct dpst_guardband guardband_reg;
	struct dpst_ie_histogram_control ie_hist_cont_reg;
	struct mdfld_dsi_hw_context *ctx = NULL;
	uint32_t * enable = data;
	struct mdfld_dsi_config *dsi_config = NULL;

	if (!dev_priv)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if(!dsi_config)
		return 0;
	ctx = &dsi_config->dsi_hw_context;

	mutex_lock(&dpst_mutex);
	/*
	* FIXME: We need to force the Display to
	* turn on but on TNG OSPM how we can force PIPEA to do it?
	*/
	if (power_island_get(OSPM_DISPLAY_A)) {

		mdfld_dsi_dsr_forbid(dsi_config);

		if (*enable == 1) {
			ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
			ie_hist_cont_reg.ie_pipe_assignment = 0;
			ie_hist_cont_reg.bin_reg_func_select = 1;
			ie_hist_cont_reg.bin_reg_index = 0;
			ie_hist_cont_reg.ie_histogram_enable = 1;
			ie_hist_cont_reg.ie_mode_table_enabled = 1;
#ifdef HSV
			ie_hist_cont_reg.histogram_mode_select = 1;//HSV
			ie_hist_cont_reg.alt_enhancement_mode = 2;//dpst_hsv_multiplier;
#else
			ie_hist_cont_reg.histogram_mode_select = 0;//YUV
			ie_hist_cont_reg.alt_enhancement_mode = 1; //additive
#endif
			PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;
			dpst_print("hist_ctl 0x%x\n", ie_hist_cont_reg.data);

			guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
			guardband_reg.interrupt_enable = 1;
			guardband_reg.interrupt_status = 1;

			PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
			ctx->histogram_intr_ctrl = guardband_reg.data;
			dpst_print("guardband 0x%x\n", guardband_reg.data);

			/* Wait for two vblanks */
		} else {
			guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
			guardband_reg.interrupt_enable = 0;
			guardband_reg.interrupt_status = 1;
			PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
			ctx->histogram_intr_ctrl = guardband_reg.data;
			dpst_print("guardband 0x%x\n", guardband_reg.data);

			ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
			ie_hist_cont_reg.ie_histogram_enable = 0;
			PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;
			dpst_print("disabled: hist_ctl 0x%x\n", ie_hist_cont_reg.data);

			dpst_disable_post_process(g_dev);
		}

		mdfld_dsi_dsr_allow(dsi_config);
		power_island_put(OSPM_DISPLAY_A);
	}

	mutex_unlock(&dpst_mutex);

	return 0;
}
 static int psb_hist_status(struct drm_device *dev, void *data)
{
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct drm_psb_hist_status_arg *hist_status = data;
	uint32_t * arg = hist_status->buf;
	struct mdfld_dsi_config *dsi_config = NULL;
	u32 iedbr_reg_data = 0;
	struct dpst_ie_histogram_control ie_hist_cont_reg;
	u32 i;
	uint32_t blm_hist_ctl = HISTOGRAM_LOGIC_CONTROL;
	uint32_t iebdr_reg = HISTOGRAM_BIN_DATA;
	uint32_t segvalue_max_22_bit = 0x3fffff;
	uint32_t iedbr_busy_bit = 0x80000000;
	int dpst3_bin_count = 32; //Different DPST Algs has different Values?

	if (!dev_priv)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if (!dsi_config)
		return 0;

	/* Use a fake hist status to avoid enhancement is adapted to black
	 * content during suspend, while make content too bright on resume.
	*/
	if(dev_priv->early_suspended) {
		memcpy(arg, dpst_hist_fake, 32*sizeof(uint32_t));
		return 0;
	}

	mutex_lock(&dpst_mutex);
	/*
	 * FIXME: We need to force the Display to
	 * turn on but on TNG OSPM how we can force PIPEA to do it?
	 */
	if (power_island_get(OSPM_DISPLAY_A))
	{
		mdfld_dsi_dsr_forbid(dsi_config);

		ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
		dpst_print("hist_ctl: 0x%x\n", ie_hist_cont_reg.data);
		ie_hist_cont_reg.bin_reg_func_select = 0;
		ie_hist_cont_reg.bin_reg_index = 0;
		ie_hist_cont_reg.ie_histogram_enable = 1;
		ie_hist_cont_reg.ie_mode_table_enabled = 1;
		ie_hist_cont_reg.ie_pipe_assignment = 0;
#ifdef HSV
		ie_hist_cont_reg.histogram_mode_select = 1;//HSV
		ie_hist_cont_reg.alt_enhancement_mode = 2;//dpst_hsv_multiplier;
#else
		ie_hist_cont_reg.histogram_mode_select = 0;//YUV
		ie_hist_cont_reg.alt_enhancement_mode = 1; //additive
#endif

		PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
		dpst_print("hist static: \n");
		for (i = 0; i < dpst3_bin_count; i++) {
			iedbr_reg_data = PSB_RVDC32(iebdr_reg);
			if (!(iedbr_reg_data & iedbr_busy_bit)) {
				arg[i] = iedbr_reg_data & segvalue_max_22_bit;
				dpst_print("hist_ctl 0x%d 0x%x\n", 0x3ff & PSB_RVDC32(blm_hist_ctl), arg[i]);
			} else {
				i = -1;
				ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
				ie_hist_cont_reg.bin_reg_index = 0;
				PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
			}
		}
		mdfld_dsi_dsr_allow(dsi_config);
		power_island_put(OSPM_DISPLAY_A);
	}

	mutex_unlock(&dpst_mutex);

	return 0;
}
/**
 * Power off sequence for DBI interface
*/
int __dbi_power_off(struct mdfld_dsi_config *dsi_config)
{
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_device *dev;
	struct drm_psb_private *dev_priv;
	int pipe0_enabled;
	int pipe2_enabled;
	int err = 0;
	u32 guit_val = 0;
	u32 power_island = 0;
	int retry;
	int offset = 0;

	if (!dsi_config)
		return -EINVAL;

	PSB_DEBUG_ENTRY("\n");

	regs = &dsi_config->regs;
	ctx = &dsi_config->dsi_hw_context;
	dev = dsi_config->dev;
	dev_priv = dev->dev_private;
	/*Disable plane*/
	REG_WRITE(regs->dspcntr_reg, 0);

	/*Disable pipe*/
	/* Don't disable DSR mode. */
	REG_WRITE(regs->pipeconf_reg, (REG_READ(regs->pipeconf_reg) & ~BIT31));
	/*wait for pipe disabling,
	  pipe synchronization plus , only avaiable when
	  timer generator is working*/
	if (REG_READ(regs->mipi_reg) & BIT31) {
		retry = 100000;
		while (--retry && (REG_READ(regs->pipeconf_reg) & BIT30))
			udelay(5);

		if (!retry) {
			DRM_ERROR("Failed to disable pipe\n");
			err = -EAGAIN;
			goto power_off_err;
		}
	}
	if (!is_dual_dsi(dev)) {
		/*enter ULPS*/
		__dbi_enter_ulps_locked(dsi_config, offset);
	} else {
		/*Disable MIPI port*/
		REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31));
		/*clear Low power output hold*/
		REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16));
		/*Disable DSI controller*/
		REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0));
		/*enter ULPS*/
		__dbi_enter_ulps_locked(dsi_config, offset);

		offset = 0x1000;
		/*Disable MIPI port*/
		REG_WRITE(regs->mipi_reg +offset,
		(REG_READ(regs->mipi_reg + offset) & ~BIT31));
		/*clear Low power output hold*/
		REG_WRITE(regs->mipi_reg + offset,
		(REG_READ(regs->mipi_reg + offset) & ~BIT16));

		offset = 0x800;
		/*Disable DSI controller*/
		REG_WRITE(regs->device_ready_reg + offset, (ctx->device_ready & ~BIT0));
		/*enter ULPS*/
		__dbi_enter_ulps_locked(dsi_config, offset);
		offset = 0x0;

	}
power_off_err:

	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_put(power_island))
		return -EINVAL;

	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;
}
Beispiel #19
0
/**
 * Power off sequence for DBI interface
*/
int __dbi_power_off(struct mdfld_dsi_config *dsi_config)
{
    struct mdfld_dsi_hw_registers *regs;
    struct mdfld_dsi_hw_context *ctx;
    struct drm_device *dev;
    struct drm_psb_private *dev_priv;
    int err = 0;
    u32 power_island = 0;
    int retry,i;
    int offset = 0;
    u32 val;

    if (!dsi_config)
        return -EINVAL;

    PSB_DEBUG_ENTRY("\n");

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

    ctx->dspcntr    = REG_READ(regs->dspcntr_reg);
    ctx->pipeconf   = REG_READ(regs->pipeconf_reg);

    ctx->dsparb = REG_READ(DSPARB);
    ctx->dsparb2 = REG_READ(DSPARB2);

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

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

    /*Disable plane*/
    val = ctx->dspcntr;
    REG_WRITE(regs->dspcntr_reg, (val & ~BIT31));

    /*Disable pipe*/
    /* Don't disable DSR mode. */
    REG_WRITE(regs->pipeconf_reg, (REG_READ(regs->pipeconf_reg) & ~BIT31));
    /*wait for pipe disabling,
      pipe synchronization plus , only avaiable when
      timer generator is working*/
    if (REG_READ(regs->mipi_reg) & BIT31) {
        retry = 100000;
        while (--retry && (REG_READ(regs->pipeconf_reg) & BIT30))
            udelay(5);

        if (!retry) {
            DRM_ERROR("Failed to disable pipe\n");
            if (IS_MOFD(dev)) {
                /*
                 * FIXME: turn off the power island directly
                 * although failed to disable pipe.
                 */
                err = 0;
            } else
                err = -EAGAIN;
            goto power_off_err;
        }
    }
    if (!is_dual_dsi(dev)) {
        /*enter ULPS*/
        __dbi_enter_ulps_locked(dsi_config, offset);
    } else {
        /*Disable MIPI port*/
        REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31));
        /*clear Low power output hold*/
        REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16));
        /*Disable DSI controller*/
        REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0));
        /*enter ULPS*/
        __dbi_enter_ulps_locked(dsi_config, offset);

        offset = 0x1000;
        /*Disable MIPI port*/
        REG_WRITE(regs->mipi_reg +offset,
                  (REG_READ(regs->mipi_reg + offset) & ~BIT31));
        /*clear Low power output hold*/
        REG_WRITE(regs->mipi_reg + offset,
                  (REG_READ(regs->mipi_reg + offset) & ~BIT16));

        offset = 0x800;
        /*Disable DSI controller*/
        REG_WRITE(regs->device_ready_reg + offset, (ctx->device_ready & ~BIT0));
        /*enter ULPS*/
        __dbi_enter_ulps_locked(dsi_config, offset);
        offset = 0x0;

    }
power_off_err:

    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_put(power_island))
        return -EINVAL;

    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 off sequence for video mode MIPI panel.
 * NOTE: do NOT modify this function
 */
static int __dpi_panel_power_off(struct mdfld_dsi_config *dsi_config,
		struct panel_funcs *p_funcs)
{
	u32 val = 0;
	u32 tmp = 0;
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_device *dev;
	struct drm_psb_private *dev_priv;
	int retry;
	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;

	/* Don't reset brightness to 0.*/
	ctx->lastbrightnesslevel = psb_brightness;

	tmp = REG_READ(regs->pipeconf_reg);

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

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

	/*
	 * Couldn't disable the pipe until DRM_WAIT_ON signaled by last
	 * vblank event when playing video, otherwise the last vblank event
	 * will lost when pipe disabled before vblank interrupt coming
	 * sometimes.
	 */

	/*Disable panel*/
	val = ctx->dspcntr;
	REG_WRITE(regs->dspcntr_reg, (val & ~BIT31));
	/*Disable overlay & cursor panel assigned to this pipe*/
	REG_WRITE(regs->pipeconf_reg, (tmp | (0x000c0000)));

	/*Disable pipe*/
	val = REG_READ(regs->pipeconf_reg);
	ctx->pipeconf = val;
	REG_WRITE(regs->pipeconf_reg, (val & ~BIT31));

	/*wait for pipe disabling,
	  pipe synchronization plus , only avaiable when
	  timer generator is working*/
	if (REG_READ(regs->mipi_reg) & BIT31) {
		retry = 100000;
		while (--retry && (REG_READ(regs->pipeconf_reg) & BIT30))
			udelay(5);

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

	/**
	 * Different panel may have different ways to have
	 * panel turned off. Support it!
	 */
	if (p_funcs && p_funcs->power_off) {
		if (p_funcs->power_off(dsi_config)) {
			DRM_ERROR("Failed to power off panel\n");
			err = -EAGAIN;
			goto power_off_err;
		}
	}

	/*Disable MIPI port*/
	REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31));

	/*clear Low power output hold*/
	REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16));

	/*Disable DSI controller*/
	REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0));

	/*enter ULPS*/
	__dpi_enter_ulps_locked(dsi_config, offset);

	if (is_dual_dsi(dev)) {
		offset = 0x1000;
		/*Disable MIPI port*/
		REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31));

		/*clear Low power output hold*/
		REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16));
		offset = 0x800;
		/*Disable DSI controller*/
		REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0));

		/*enter ULPS*/
		__dpi_enter_ulps_locked(dsi_config, offset);
		offset = 0x0;
	}

	/* Disable DSI 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);

power_off_err:
	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_put(power_island))
		return -EINVAL;

	return err;
}
/* IOCTL - moved to standard calls for Kernel Integration */
int psb_hist_enable(struct drm_device *dev, void *data)
{
	u32 irqCtrl = 0;
	struct drm_psb_private *dev_priv = psb_priv(dev);
	struct dpst_guardband guardband_reg;
	struct dpst_ie_histogram_control ie_hist_cont_reg;
	struct mdfld_dsi_hw_context *ctx = NULL;
	uint32_t * enable = data;
	struct mdfld_dsi_config *dsi_config = NULL;

	if (!dev_priv)
		return 0;

	dsi_config = dev_priv->dsi_configs[0];
	if(!dsi_config)
		return 0;
	ctx = &dsi_config->dsi_hw_context;

	/*
	* FIXME: We need to force the Display to
	* turn on but on TNG OSPM how we can force PIPEA to do it?
	*/
	if (power_island_get(OSPM_DISPLAY_A)) {

		if (*enable == 1) {
			ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
			ie_hist_cont_reg.ie_pipe_assignment = 0;
			ie_hist_cont_reg.histogram_mode_select = DPST_YUV_LUMA_MODE;
			ie_hist_cont_reg.ie_histogram_enable = 1;
			PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;

			guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
			guardband_reg.interrupt_enable = 1;
			guardband_reg.interrupt_status = 1;
			PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
			ctx->histogram_intr_ctrl = guardband_reg.data;

			irqCtrl = PSB_RVDC32(PIPEASTAT);
			ctx->pipestat = (irqCtrl | PIPE_DPST_EVENT_ENABLE);
			PSB_WVDC32(ctx->pipestat, PIPEASTAT);

			/* Wait for two vblanks */
		} else {
			guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
			guardband_reg.interrupt_enable = 0;
			guardband_reg.interrupt_status = 1;
			PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
			ctx->histogram_intr_ctrl = guardband_reg.data;

			ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
			ie_hist_cont_reg.ie_histogram_enable = 0;
			PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
			ctx->histogram_logic_ctrl = ie_hist_cont_reg.data;

			irqCtrl = PSB_RVDC32(PIPEASTAT);
			irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
			PSB_WVDC32(irqCtrl, PIPEASTAT);
			ctx->pipestat = irqCtrl;
			dpst_disable_post_process(g_dev);
		}

		power_island_put(OSPM_DISPLAY_A);
	}

	return 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)
{
	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;
}