void psb_intel_opregion_enable_asle(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; struct opregion_asle *asle = dev_priv->opregion.asle; if (asle && system_opregion ) { /* Don't do this on Medfield or other non PC like devices, they use the bit for something different altogether */ psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); psb_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE); asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN | ASLE_PFMB_EN; asle->ardy = 1; } }
/** * Exit from DSR */ void mdfld_dsi_dpi_exit_idle(struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only) { struct drm_psb_private * dev_priv = dev->dev_private; unsigned long irqflags; /* PSB_DEBUG_ENTRY("\n"); */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) { DRM_ERROR("display island is in off state\n"); return; } spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); /* update the surface base address. */ if (p_surfaceAddr) { REG_WRITE(DSPASURF, *((u32 *)p_surfaceAddr)); #if defined(CONFIG_MDFD_DUAL_MIPI) REG_WRITE(DSPCSURF, *((u32 *)p_surfaceAddr)); #endif } mid_enable_pipe_event(dev_priv, 0); psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); }
/* dbi interface power on*/ int __dbi_power_on(struct mdfld_dsi_config *dsi_config) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int retry; int err = 0; u32 guit_val = 0; u32 power_island = 0; u32 sprite_reg_offset = 0; int i = 0; int offset = 0; PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; power_island = pipe_to_island(dsi_config->pipe); if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C)) power_island |= OSPM_DISPLAY_MIO; if (is_dual_dsi(dev)) power_island |= OSPM_DISPLAY_C; if (!power_island_get(power_island)) return -EAGAIN; /* * Wait for DSI PLL locked on pipe, and only need to poll status of pipe * A as both MIPI pipes share the same DSI PLL. */ if (dsi_config->pipe == 0) { retry = 20000; while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) && --retry) udelay(150); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } } if (IS_ANN_A0(dev)) { /* FIXME: reset the DC registers for ANN A0 */ power_island_get(OSPM_DISPLAY_B | OSPM_DISPLAY_C); REG_WRITE(DSPCLK_GATE_D, 0xFFFFFFFF); /* 0x10000000 */ REG_WRITE(RAMCLK_GATE_D, 0xFFFFFFFF); /* 0x0 */ REG_WRITE(PFIT_CONTROL, 0x20000000); REG_WRITE(DSPIEDCFGSHDW, 0x0); REG_WRITE(DSPARB2, 0x000A0200); REG_WRITE(DSPARB, 0x18040080); REG_WRITE(DSPFW1, 0x0F0F3F3F); REG_WRITE(DSPFW2, 0x5F2F0F3F); REG_WRITE(DSPFW3, 0x0); REG_WRITE(DSPFW4, 0x07071F1F); REG_WRITE(DSPFW5, 0x2F17071F); REG_WRITE(DSPFW6, 0x00001F3F); REG_WRITE(DSPFW7, 0x1F3F1F3F); REG_WRITE(DSPSRCTRL, 0x00080100); REG_WRITE(DSPCHICKENBIT, 0x0); REG_WRITE(FBDC_CHICKEN, 0x0C0C0C0C); REG_WRITE(CURACNTR, 0x0); REG_WRITE(CURBCNTR, 0x0); REG_WRITE(CURCCNTR, 0x0); REG_WRITE(IEP_OVA_CTRL, 0x0); REG_WRITE(IEP_OVA_CTRL, 0x0); REG_WRITE(DSPACNTR, 0x0); REG_WRITE(DSPBCNTR, 0x0); REG_WRITE(DSPCCNTR, 0x0); REG_WRITE(DSPDCNTR, 0x0); REG_WRITE(DSPECNTR, 0x0); REG_WRITE(DSPFCNTR, 0x0); power_island_put(OSPM_DISPLAY_B | OSPM_DISPLAY_C); } /*exit ULPS*/ if (__dbi_exit_ulps_locked(dsi_config, 0)) { DRM_ERROR("Failed to exit ULPS\n"); goto power_on_err; } /*update MIPI port config*/ REG_WRITE(regs->mipi_reg, ctx->mipi | REG_READ(regs->mipi_reg)); /*unready dsi adapter for re-programming*/ REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) & ~(DSI_DEVICE_READY)); if (is_dual_dsi(dev)) { if (__dbi_exit_ulps_locked(dsi_config, 0x800)) { DRM_ERROR("Failed to exit ULPS\n"); goto power_on_err; } offset = 0x1000; REG_WRITE(regs->mipi_reg + offset, ctx->mipi | REG_READ(regs->mipi_reg + offset)); /*unready dsi adapter for re-programming*/ offset = 0x800; REG_WRITE(regs->device_ready_reg + offset, REG_READ(regs->device_ready_reg + offset) & ~(DSI_DEVICE_READY)); } /* * According to MIPI D-PHY spec, if clock stop feature is enabled (EOT * Disable), un-ready MIPI adapter needs to wait for 20 cycles from HS * to LP mode. Per calculation 1us is enough. */ if (ctx->eot_disable & CLOCK_STOP) udelay(1); __dbi_set_properties(dsi_config, PORT_A); /*Setup pipe timing*/ REG_WRITE(regs->htotal_reg, ctx->htotal); REG_WRITE(regs->hblank_reg, ctx->hblank); REG_WRITE(regs->hsync_reg, ctx->hsync); REG_WRITE(regs->vtotal_reg, ctx->vtotal); REG_WRITE(regs->vblank_reg, ctx->vblank); REG_WRITE(regs->vsync_reg, ctx->vsync); REG_WRITE(regs->pipesrc_reg, ctx->pipesrc); REG_WRITE(regs->dsppos_reg, ctx->dsppos); REG_WRITE(regs->dspstride_reg, ctx->dspstride); if (!IS_ANN_A0(dev)) { /*restore color_coef (chrome) */ for (i = 0; i < 6; i++) REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]); /* restore palette (gamma) */ for (i = 0; i < 256; i++) REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]); /* restore dpst setting */ if (dev_priv->psb_dpst_state) { dpstmgr_reg_restore_locked(dev, dsi_config); psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); } } /*Setup plane*/ REG_WRITE(regs->dspsize_reg, ctx->dspsize); REG_WRITE(regs->dspsurf_reg, ctx->dspsurf); REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); if (is_dual_dsi(dev)) __dbi_set_properties(dsi_config, PORT_C); /*enable plane*/ val = ctx->dspcntr | BIT31; REG_WRITE(regs->dspcntr_reg, val); if (ctx->sprite_dspcntr & BIT31) { if (dsi_config->pipe == 0) sprite_reg_offset = 0x3000; else if (dsi_config->pipe == 2) sprite_reg_offset = 0x1000; /* Set up Sprite Plane */ REG_WRITE(regs->dspsize_reg + sprite_reg_offset, ctx->sprite_dspsize); REG_WRITE(regs->dspsurf_reg + sprite_reg_offset, ctx->sprite_dspsurf); REG_WRITE(regs->dsplinoff_reg + sprite_reg_offset, ctx->sprite_dsplinoff); REG_WRITE(regs->dsppos_reg + sprite_reg_offset, ctx->sprite_dsppos); REG_WRITE(regs->dspstride_reg + sprite_reg_offset, ctx->sprite_dspstride); /* enable plane */ REG_WRITE(regs->dspcntr_reg + sprite_reg_offset, ctx->sprite_dspcntr); } /* Set up Overlay Plane */ if (ctx->ovaadd) PSB_WVDC32(ctx->ovaadd, OV_OVADD); if (ctx->ovcadd) PSB_WVDC32(ctx->ovcadd, OVC_OVADD); /*ready dsi adapter*/ REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) | DSI_DEVICE_READY); mdelay(1); if (is_dual_dsi(dev)) { REG_WRITE(regs->device_ready_reg + offset, REG_READ(regs->device_ready_reg + offset) | DSI_DEVICE_READY); } if (IS_ANN_A0(dev)) { REG_WRITE(regs->ddl1_reg, ctx->ddl1); REG_WRITE(regs->ddl2_reg, ctx->ddl2); REG_WRITE(regs->ddl3_reg, ctx->ddl3); REG_WRITE(regs->ddl4_reg, ctx->ddl4); } /*Enable pipe*/ val = ctx->pipeconf; val &= ~0x000c0000; val |= BIT31 | PIPEACONF_DSR; REG_WRITE(regs->pipeconf_reg, val); /*Wait for pipe enabling,when timing generator is working */ retry = 10000; while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30)) udelay(3); if (!retry) { DRM_ERROR("Failed to enable pipe\n"); err = -EAGAIN; goto power_on_err; } /* * Enable TE to trigger "write_mem_start" issuing * in non-normal boot modes. */ mdfld_enable_te(dev, dsi_config->pipe); return err; power_on_err: power_island_put(power_island); return err; }
/** * Power on sequence for video mode MIPI panel. * NOTE: do NOT modify this function */ static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config, struct panel_funcs *p_funcs) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int retry, reset_count = 10; int i; int err = 0; u32 guit_val = 0; u32 power_island = 0; int offset = 0; PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; power_island = pipe_to_island(dsi_config->pipe); if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C)) power_island |= OSPM_DISPLAY_MIO; if (is_dual_dsi(dev)) power_island |= OSPM_DISPLAY_C; if (!power_island_get(power_island)) return -EAGAIN; reset_recovery: --reset_count; /*HW-Reset*/ if (p_funcs && p_funcs->reset) p_funcs->reset(dsi_config); if (!is_dual_dsi(dev)) { /* Disable PLL*/ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, _DSI_LDO_EN); /* Program PLL */ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ((guit_val & ~_P1_POST_DIV_MASK) | (ctx->dpll & _P1_POST_DIV_MASK))); ctx->dpll |= DPLL_VCO_ENABLE; ctx->dpll &= ~_DSI_LDO_EN; intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ctx->dpll); } else { intel_mid_msgbus_write32(CCK_PORT, 0x68, 0x682); /* Disable PLL*/ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, _DSI_LDO_EN); /* Program PLL */ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ((guit_val & ~_P1_POST_DIV_MASK) | (ctx->dpll & _P1_POST_DIV_MASK))); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); ctx->dpll |= DPLL_VCO_ENABLE; ctx->dpll &= ~(_DSI_LDO_EN | _CLK_EN_CCK_DSI0 | _CLK_EN_CCK_DSI1 | _DSI_MUX_SEL_CCK_DSI1 | _DSI_MUX_SEL_CCK_DSI0); ctx->dpll |= _CLK_EN_PLL_DSI0 | _CLK_EN_PLL_DSI1; intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ctx->dpll); } /* Wait for DSI PLL lock */ retry = 10000; guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); while (((guit_val & _DSI_PLL_LOCK) != _DSI_PLL_LOCK) && (--retry)) { udelay(3); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); if (retry == 0) { DRM_ERROR("DSI PLL fails to lock\n"); err = -EAGAIN; goto power_on_err; } } /* * Wait for DSI PLL locked on pipe, and only need to poll status of pipe * A as both MIPI pipes share the same DSI PLL. */ if (dsi_config->pipe == 0) { retry = 20000; while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) && --retry) udelay(150); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } } __dpi_set_properties(dsi_config, PORT_A); /*Setup pipe timing*/ REG_WRITE(regs->htotal_reg, ctx->htotal); REG_WRITE(regs->hblank_reg, ctx->hblank); REG_WRITE(regs->hsync_reg, ctx->hsync); REG_WRITE(regs->vtotal_reg, ctx->vtotal); REG_WRITE(regs->vblank_reg, ctx->vblank); REG_WRITE(regs->vsync_reg, ctx->vsync); REG_WRITE(regs->pipesrc_reg, ctx->pipesrc); REG_WRITE(regs->dsppos_reg, ctx->dsppos); REG_WRITE(regs->dspstride_reg, ctx->dspstride); if (IS_ANN_A0(dev)) { /*reset registers*/ REG_WRITE(0x7002C, 0x000A0200); REG_WRITE(0x70508, 0x0c0c0c0c); REG_WRITE(0x70504, 0xffffffff); REG_WRITE(0x70500, 0xffffffff); DRM_DEBUG("LOADING: 0x70504 %#x\n", REG_READ(0x70504)); } /*Setup plane*/ REG_WRITE(regs->dspsize_reg, ctx->dspsize); REG_WRITE(regs->dspsurf_reg, ctx->dspsurf); REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); /*restore color_coef (chrome) */ for (i = 0; i < 6; i++) REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]); /* restore palette (gamma) */ for (i = 0; i < 256; i++) REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]); /* restore dpst setting */ if (dev_priv->psb_dpst_state) { dpstmgr_reg_restore_locked(dev, dsi_config); psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); } if (__dpi_config_port(dsi_config, p_funcs, PORT_A) != 0) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } if (is_dual_dsi(dev)) { __dpi_set_properties(dsi_config, PORT_C); __dpi_config_port(dsi_config, p_funcs, PORT_C); } /** * Different panel may have different ways to have * drvIC initialized. Support it! */ if (p_funcs && p_funcs->drv_ic_init) { if (p_funcs->drv_ic_init(dsi_config)) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } } /*Enable MIPI Port A*/ offset = 0x0; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); REG_WRITE(regs->dpi_control_reg + offset, BIT1); if (is_dual_dsi(dev)) { /*Enable MIPI Port C*/ offset = 0x1000; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); offset = 0x800; REG_WRITE(regs->dpi_control_reg + offset, BIT1); } /** * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } /*Enable pipe*/ val = ctx->pipeconf; val &= ~0x000c0000; val |= BIT31; REG_WRITE(regs->pipeconf_reg, val); /*Wait for pipe enabling,when timing generator is wroking */ if (REG_READ(regs->mipi_reg) & BIT31) { retry = 10000; while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30)) udelay(3); if (!retry) { DRM_ERROR("Failed to enable pipe\n"); err = -EAGAIN; goto power_on_err; } } /*enable plane*/ val = ctx->dspcntr | BIT31; REG_WRITE(regs->dspcntr_reg, val); if (p_funcs && p_funcs->set_brightness) { if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); } else { DRM_ERROR("Failed to set panel brightness\n"); } if (p_funcs && p_funcs->drv_set_panel_mode) p_funcs->drv_set_panel_mode(dsi_config); psb_enable_vblank(dev, dsi_config->pipe); return err; power_on_err: power_island_put(power_island); return err; }
/** * Power on sequence for video mode MIPI panel. * NOTE: do NOT modify this function */ static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config, struct panel_funcs *p_funcs, bool first_boot) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int retry, reset_count = 10; int i; int err = 0; u32 power_island = 0; int offset = 0; PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; power_island = pipe_to_island(dsi_config->pipe); if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C)) power_island |= OSPM_DISPLAY_MIO; if (is_dual_dsi(dev)) power_island |= OSPM_DISPLAY_C; if (!power_island_get(power_island)) return -EAGAIN; if (android_hdmi_is_connected(dev) && first_boot) otm_hdmi_power_islands_on(); reset_recovery: --reset_count; /*HW-Reset*/ if (p_funcs && p_funcs->reset) p_funcs->reset(dsi_config); /* * Wait for DSI PLL locked on pipe, and only need to poll status of pipe * A as both MIPI pipes share the same DSI PLL. */ if (dsi_config->pipe == 0) { retry = 20000; while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) && --retry) udelay(150); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } } if (IS_ANN(dev)) { /* FIXME: reset the DC registers for ANN A0 */ ann_dc_setup(dsi_config); } __dpi_set_properties(dsi_config, PORT_A); /* update 0x650c[0] = 1 to fixed arbitration pattern * it is found display TLB request be blocked by display plane * memory requests, never goes out. This causes display controller * uses stale TLB data to do memory translation, getting wrong * memory address for data, and causing the flickering issue. */ REG_WRITE(GCI_CTRL, REG_READ(GCI_CTRL) | 1); /*Setup pipe timing*/ REG_WRITE(regs->htotal_reg, ctx->htotal); REG_WRITE(regs->hblank_reg, ctx->hblank); REG_WRITE(regs->hsync_reg, ctx->hsync); REG_WRITE(regs->vtotal_reg, ctx->vtotal); REG_WRITE(regs->vblank_reg, ctx->vblank); REG_WRITE(regs->vsync_reg, ctx->vsync); REG_WRITE(regs->pipesrc_reg, ctx->pipesrc); REG_WRITE(regs->dsppos_reg, ctx->dsppos); REG_WRITE(regs->dspstride_reg, ctx->dspstride); /*Setup plane*/ REG_WRITE(regs->dspsize_reg, ctx->dspsize); REG_WRITE(regs->dspsurf_reg, ctx->dspsurf); REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); /*restore color_coef (chrome) */ for (i = 0; i < 6; i++) REG_WRITE(regs->color_coef_reg + (i<<2), csc_setting_save[i]); /* restore palette (gamma) */ for (i = 0; i < 256; i++) REG_WRITE(regs->palette_reg + (i<<2), gamma_setting_save[i]); /* restore dpst setting */ if (dev_priv->psb_dpst_state) { dpstmgr_reg_restore_locked(dev, dsi_config); psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); } if (__dpi_config_port(dsi_config, p_funcs, PORT_A) != 0) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } if (is_dual_dsi(dev)) { __dpi_set_properties(dsi_config, PORT_C); __dpi_config_port(dsi_config, p_funcs, PORT_C); } /** * Different panel may have different ways to have * drvIC initialized. Support it! */ if (p_funcs && p_funcs->drv_ic_init) { if (p_funcs->drv_ic_init(dsi_config)) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } } /*Enable MIPI Port A*/ offset = 0x0; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); REG_WRITE(regs->dpi_control_reg + offset, BIT1); if (is_dual_dsi(dev)) { /*Enable MIPI Port C*/ offset = 0x1000; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); offset = 0x800; REG_WRITE(regs->dpi_control_reg + offset, BIT1); } /** * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } if (IS_ANN(dev)) { REG_WRITE(regs->ddl1_reg, ctx->ddl1); REG_WRITE(regs->ddl2_reg, ctx->ddl2); REG_WRITE(regs->ddl3_reg, ctx->ddl3); REG_WRITE(regs->ddl4_reg, ctx->ddl4); REG_WRITE(DSPARB2, ctx->dsparb2); REG_WRITE(DSPARB, ctx->dsparb); } /*Enable pipe*/ val = ctx->pipeconf; val &= ~0x000c0000; /** * Frame Start occurs on third HBLANK * after the start of VBLANK */ val |= BIT31 | BIT28; REG_WRITE(regs->pipeconf_reg, val); /*Wait for pipe enabling,when timing generator is wroking */ if (REG_READ(regs->mipi_reg) & BIT31) { retry = 10000; while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30)) udelay(3); if (!retry) { DRM_ERROR("Failed to enable pipe\n"); err = -EAGAIN; goto power_on_err; } } /*enable plane*/ val = ctx->dspcntr | BIT31; REG_WRITE(regs->dspcntr_reg, val); if (p_funcs && p_funcs->set_brightness) { if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); } else { DRM_ERROR("Failed to set panel brightness\n"); } if (p_funcs && p_funcs->drv_set_panel_mode) p_funcs->drv_set_panel_mode(dsi_config); psb_enable_vblank(dev, dsi_config->pipe); return err; power_on_err: power_island_put(power_island); return err; }
/** * Power on sequence for video mode MIPI panel. * NOTE: do NOT modify this function */ static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config, struct panel_funcs *p_funcs) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int retry, reset_count = 10; int i; int err = 0; if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return -EAGAIN; reset_recovery: --reset_count; /*HW-Reset*/ if (p_funcs && p_funcs->reset) p_funcs->reset(dsi_config); /*Enable DSI PLL*/ if (!(REG_READ(regs->dpll_reg) & BIT31)) { if(ctx->pll_bypass_mode) { uint32_t dpll = 0; REG_WRITE(regs->dpll_reg, dpll); if (ctx->cck_div) { dpll = dpll | BIT11; REG_WRITE(regs->dpll_reg, dpll); udelay(1); } dpll = dpll | BIT12; REG_WRITE(regs->dpll_reg, dpll); mdelay(1); dpll = dpll | BIT13; REG_WRITE(regs->dpll_reg, dpll); mdelay(1); } else { REG_WRITE(regs->dpll_reg, 0x0); REG_WRITE(regs->fp_reg, 0x0); REG_WRITE(regs->fp_reg, ctx->fp); REG_WRITE(regs->dpll_reg, ((ctx->dpll) & ~BIT30)); udelay(2); val = REG_READ(regs->dpll_reg); REG_WRITE(regs->dpll_reg, (val | BIT31)); /*wait for PLL lock on pipe*/ retry = 10000; while (--retry && !(REG_READ(PIPEACONF) & BIT29)) udelay(3); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } } } REG_WRITE(regs->eot_disable_reg, (REG_READ(regs->eot_disable_reg) & ~BIT1)); REG_WRITE(regs->device_ready_reg, ~BIT0); REG_WRITE(regs->device_ready_reg, BIT0); mdelay(1); /*exit ULPS*/ if (__dpi_exit_ulps_locked(dsi_config)) { DRM_ERROR("Failed to exit ULPS\n"); goto power_on_err; } /*update MIPI port config*/ REG_WRITE(regs->mipi_reg, (ctx->mipi | REG_READ(regs->mipi_reg))); /*unready dsi adapter for re-programming*/ REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) & ~(DSI_DEVICE_READY)); /*D-PHY parameter*/ REG_WRITE(regs->dphy_param_reg, ctx->dphy_param); /*Configure DSI controller*/ REG_WRITE(regs->mipi_control_reg, ctx->mipi_control); REG_WRITE(regs->intr_en_reg, ctx->intr_en); REG_WRITE(regs->hs_tx_timeout_reg, ctx->hs_tx_timeout); REG_WRITE(regs->lp_rx_timeout_reg, ctx->lp_rx_timeout); REG_WRITE(regs->turn_around_timeout_reg, ctx->turn_around_timeout); REG_WRITE(regs->device_reset_timer_reg, ctx->device_reset_timer); REG_WRITE(regs->high_low_switch_count_reg, ctx->high_low_switch_count); REG_WRITE(regs->init_count_reg, ctx->init_count); REG_WRITE(regs->eot_disable_reg, ctx->eot_disable); REG_WRITE(regs->lp_byteclk_reg, ctx->lp_byteclk); REG_WRITE(regs->clk_lane_switch_time_cnt_reg, ctx->clk_lane_switch_time_cnt); if (ctx->pll_bypass_mode) { /*Force using non-burst pulse event mode here*/ REG_WRITE(regs->video_mode_format_reg, 0x1); } else { REG_WRITE(regs->video_mode_format_reg, ctx->video_mode_format); } REG_WRITE(regs->dsi_func_prg_reg, ctx->dsi_func_prg); /*DSI timing*/ REG_WRITE(regs->dpi_resolution_reg, ctx->dpi_resolution); REG_WRITE(regs->hsync_count_reg, ctx->hsync_count); REG_WRITE(regs->hbp_count_reg, ctx->hbp_count); REG_WRITE(regs->hfp_count_reg, ctx->hfp_count); REG_WRITE(regs->hactive_count_reg, ctx->hactive_count); REG_WRITE(regs->vsync_count_reg, ctx->vsync_count); REG_WRITE(regs->vbp_count_reg, ctx->vbp_count); REG_WRITE(regs->vfp_count_reg, ctx->vfp_count); /*Setup pipe timing*/ REG_WRITE(regs->htotal_reg, ctx->htotal); REG_WRITE(regs->hblank_reg, ctx->hblank); REG_WRITE(regs->hsync_reg, ctx->hsync); REG_WRITE(regs->vtotal_reg, ctx->vtotal); REG_WRITE(regs->vblank_reg, ctx->vblank); REG_WRITE(regs->vsync_reg, ctx->vsync); REG_WRITE(regs->pipesrc_reg, ctx->pipesrc); REG_WRITE(regs->dsppos_reg, ctx->dsppos); REG_WRITE(regs->dspstride_reg, ctx->dspstride); /*Setup plane*/ REG_WRITE(regs->dspsize_reg, ctx->dspsize); REG_WRITE(regs->dspsurf_reg, ctx->dspsurf); REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); /*restore color_coef (chrome) */ for (i = 0; i < 6; i++) { REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]); } /* restore palette (gamma) */ for (i = 0; i < 256; i++) REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]); /* restore gamma correction max (RGB) */ REG_WRITE(regs->gamma_red_max_reg, ctx->gamma_red_max); REG_WRITE(regs->gamma_green_max_reg, ctx->gamma_green_max); REG_WRITE(regs->gamma_blue_max_reg, ctx->gamma_blue_max); #ifdef CONFIG_CTP_DPST /* restore dpst setting */ if (dev_priv->psb_dpst_state) { dpstmgr_reg_restore_locked(dsi_config); psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); } #endif /*Enable DSI Controller*/ REG_WRITE(regs->device_ready_reg, (REG_READ(regs->device_ready_reg) | BIT0)); /** * Different panel may have different ways to have * drvIC initialized. Support it! */ if (p_funcs && p_funcs->drv_ic_init) { if (p_funcs->drv_ic_init(dsi_config)) { if (!reset_count) { goto reset_err_bypass; } pmu_nc_set_power_state(OSPM_MIPI_ISLAND, OSPM_ISLAND_DOWN, OSPM_REG_TYPE); pmu_nc_set_power_state(OSPM_MIPI_ISLAND, OSPM_ISLAND_UP, OSPM_REG_TYPE); DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } } reset_err_bypass: if (ctx->pll_bypass_mode) { /*Reprogram to use pll clock*/ REG_WRITE(regs->dpll_reg, 0x0); REG_WRITE(regs->fp_reg, 0x0); REG_WRITE(regs->fp_reg, ctx->fp); REG_WRITE(regs->dpll_reg, ((ctx->dpll) & ~BIT30)); udelay(2); REG_WRITE(regs->dpll_reg, 0x2 << 17); mdelay(1); REG_WRITE(regs->dpll_reg, (0x2 << 17 | BIT31)); /*wait for PLL lock on pipe*/ retry = 10000; while (--retry && !(REG_READ(PIPEACONF) & BIT29)) udelay(3); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } /*Switch back to burst mode*/ REG_WRITE(regs->video_mode_format_reg, ctx->video_mode_format); /*Clear device ready reg*/ REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) & ~DSI_DEVICE_READY); msleep(1); /*Enable DSI Controller*/ REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) | DSI_DEVICE_READY); msleep(1); } /** * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } /*Enable MIPI Port*/ REG_WRITE(regs->mipi_reg, (ctx->mipi | BIT31)); /*Enable pipe*/ val = ctx->pipeconf; val &= ~0x000c0000; val |= BIT31; /* disable gamma if needed */ if (drm_psb_enable_color_conversion == 0) val &= ~(PIPEACONF_COLOR_MATRIX_ENABLE); REG_WRITE(regs->pipeconf_reg, val); REG_WRITE(regs->pipestat_reg, ctx->pipestat | PIPE_VBLANK_INTERRUPT_ENABLE); /*Wait for pipe enabling,when timing generator is wroking */ if (REG_READ(regs->mipi_reg) & BIT31) { retry = 10000; while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30)) udelay(3); if (!retry) { DRM_ERROR("Failed to enable pipe\n"); err = -EAGAIN; goto power_on_err; } } /*enable plane*/ val = ctx->dspcntr | BIT31; /* disable gamma if needed */ if (drm_psb_enable_gamma == 0) val &= ~(PIPEACONF_GAMMA); REG_WRITE(regs->dspcntr_reg, val); /*Notify PVR module that screen is on*/ if (dev_priv->pvr_screen_event_handler) dev_priv->pvr_screen_event_handler(dev, 1); if (p_funcs && p_funcs->set_brightness) if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); power_on_err: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; }
/** * 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; }