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