int mdfld_dpu_exit_dsr(struct drm_device * dev) { struct mdfld_dsi_dbi_output ** dbi_output; struct drm_psb_private * dev_priv = dev->dev_private; struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info; int i; int pipe; dbi_output = dpu_info->dbi_outputs; for(i=0; i<dpu_info->dbi_output_num; i++) { /*if this output is not in DSR mode, don't call exit dsr*/ if(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) { __mdfld_dbi_exit_dsr(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0); } } /*enable te interrupt*/ for (i = 0; i < dpu_info->dbi_output_num; i++) { /*if this output is not in DSR mode, don't call exit dsr*/ pipe = dbi_output[i]->channel_num ? 2 : 0; if (dbi_output[i]->dbi_panel_on && pipe) { mdfld_disable_te(dev, 0); mdfld_enable_te(dev, 2); } else if (dbi_output[i]->dbi_panel_on && !pipe) { mdfld_disable_te(dev, 2); mdfld_enable_te(dev, 0); } } return 0; }
static int exit_dsr_locked(struct mdfld_dsi_config *dsi_config) { int err = 0; struct drm_device *dev; struct mdfld_dsi_pkg_sender *sender; if (!dsi_config) return -EINVAL; sender = mdfld_dsi_get_pkg_sender(dsi_config); if (!sender) { DRM_ERROR("Failed to get dsi sender\n"); return -EINVAL; } dev = dsi_config->dev; err = __dbi_power_on(dsi_config); if (!err) /*enable TE, will need it in panel power on*/ mdfld_enable_te(dev, dsi_config->pipe); mdfld_dsi_status_check(sender); 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; }
/* * mdfld_restore_display_registers - restore the state of a pipe * @dev: our device * @pipe: the pipe to restore * * Restore the state of a pipe to that which was saved by the register save * functions. */ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe) { /* To get panel out of ULPS mode */ struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_config *dsi_config = NULL; u32 i = 0; u32 dpll = 0; u32 timeout = 0; u32 reg_offset = 0; /* register */ u32 dpll_reg = MRST_DPLL_A; u32 fp_reg = MRST_FPA0; u32 pipeconf_reg = PIPEACONF; u32 htot_reg = HTOTAL_A; u32 hblank_reg = HBLANK_A; u32 hsync_reg = HSYNC_A; u32 vtot_reg = VTOTAL_A; u32 vblank_reg = VBLANK_A; u32 vsync_reg = VSYNC_A; u32 pipesrc_reg = PIPEASRC; u32 dspstride_reg = DSPASTRIDE; u32 dsplinoff_reg = DSPALINOFF; u32 dsptileoff_reg = DSPATILEOFF; u32 dspsize_reg = DSPASIZE; u32 dsppos_reg = DSPAPOS; u32 dspsurf_reg = DSPASURF; u32 dspstatus_reg = PIPEASTAT; u32 mipi_reg = MIPI; u32 dspcntr_reg = DSPACNTR; u32 palette_reg = PALETTE_A; /* values */ u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE; u32 fp_val = dev_priv->saveFPA0; u32 pipeconf_val = dev_priv->savePIPEACONF; u32 htot_val = dev_priv->saveHTOTAL_A; u32 hblank_val = dev_priv->saveHBLANK_A; u32 hsync_val = dev_priv->saveHSYNC_A; u32 vtot_val = dev_priv->saveVTOTAL_A; u32 vblank_val = dev_priv->saveVBLANK_A; u32 vsync_val = dev_priv->saveVSYNC_A; u32 pipesrc_val = dev_priv->savePIPEASRC; u32 dspstride_val = dev_priv->saveDSPASTRIDE; u32 dsplinoff_val = dev_priv->saveDSPALINOFF; u32 dsptileoff_val = dev_priv->saveDSPATILEOFF; u32 dspsize_val = dev_priv->saveDSPASIZE; u32 dsppos_val = dev_priv->saveDSPAPOS; u32 dspsurf_val = dev_priv->saveDSPASURF; u32 dspstatus_val = dev_priv->saveDSPASTATUS; u32 mipi_val = dev_priv->saveMIPI; u32 dspcntr_val = dev_priv->saveDSPACNTR; u32 *palette_val = dev_priv->save_palette_a; switch (pipe) { case 0: dsi_config = dev_priv->dsi_configs[0]; break; case 1: /* register */ dpll_reg = MDFLD_DPLL_B; fp_reg = MDFLD_DPLL_DIV0; pipeconf_reg = PIPEBCONF; htot_reg = HTOTAL_B; hblank_reg = HBLANK_B; hsync_reg = HSYNC_B; vtot_reg = VTOTAL_B; vblank_reg = VBLANK_B; vsync_reg = VSYNC_B; pipesrc_reg = PIPEBSRC; dspstride_reg = DSPBSTRIDE; dsplinoff_reg = DSPBLINOFF; dsptileoff_reg = DSPBTILEOFF; dspsize_reg = DSPBSIZE; dsppos_reg = DSPBPOS; dspsurf_reg = DSPBSURF; dspcntr_reg = DSPBCNTR; palette_reg = PALETTE_B; dspstatus_reg = PIPEBSTAT; /* values */ dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE; fp_val = dev_priv->saveFPB0; pipeconf_val = dev_priv->savePIPEBCONF; htot_val = dev_priv->saveHTOTAL_B; hblank_val = dev_priv->saveHBLANK_B; hsync_val = dev_priv->saveHSYNC_B; vtot_val = dev_priv->saveVTOTAL_B; vblank_val = dev_priv->saveVBLANK_B; vsync_val = dev_priv->saveVSYNC_B; pipesrc_val = dev_priv->savePIPEBSRC; dspstride_val = dev_priv->saveDSPBSTRIDE; dsplinoff_val = dev_priv->saveDSPBLINOFF; dsptileoff_val = dev_priv->saveDSPBTILEOFF; dspsize_val = dev_priv->saveDSPBSIZE; dsppos_val = dev_priv->saveDSPBPOS; dspsurf_val = dev_priv->saveDSPBSURF; dspcntr_val = dev_priv->saveDSPBCNTR; dspstatus_val = dev_priv->saveDSPBSTATUS; palette_val = dev_priv->save_palette_b; break; case 2: reg_offset = MIPIC_REG_OFFSET; /* register */ pipeconf_reg = PIPECCONF; htot_reg = HTOTAL_C; hblank_reg = HBLANK_C; hsync_reg = HSYNC_C; vtot_reg = VTOTAL_C; vblank_reg = VBLANK_C; vsync_reg = VSYNC_C; pipesrc_reg = PIPECSRC; dspstride_reg = DSPCSTRIDE; dsplinoff_reg = DSPCLINOFF; dsptileoff_reg = DSPCTILEOFF; dspsize_reg = DSPCSIZE; dsppos_reg = DSPCPOS; dspsurf_reg = DSPCSURF; mipi_reg = MIPI_C; dspcntr_reg = DSPCCNTR; palette_reg = PALETTE_C; dspstatus_reg = PIPECSTAT; /* values */ pipeconf_val = dev_priv->savePIPECCONF; htot_val = dev_priv->saveHTOTAL_C; hblank_val = dev_priv->saveHBLANK_C; hsync_val = dev_priv->saveHSYNC_C; vtot_val = dev_priv->saveVTOTAL_C; vblank_val = dev_priv->saveVBLANK_C; vsync_val = dev_priv->saveVSYNC_C; pipesrc_val = dev_priv->savePIPECSRC; dspstride_val = dev_priv->saveDSPCSTRIDE; dsplinoff_val = dev_priv->saveDSPCLINOFF; dsptileoff_val = dev_priv->saveDSPCTILEOFF; dspsize_val = dev_priv->saveDSPCSIZE; dsppos_val = dev_priv->saveDSPCPOS; dspsurf_val = dev_priv->saveDSPCSURF; dspstatus_val = dev_priv->saveDSPCSTATUS; mipi_val = dev_priv->saveMIPI_C; dspcntr_val = dev_priv->saveDSPCCNTR; palette_val = dev_priv->save_palette_c; dsi_config = dev_priv->dsi_configs[1]; break; default: DRM_ERROR("%s, invalid pipe number.\n", __func__); return -EINVAL; } /* Make sure VGA plane is off. it initializes to on after reset!*/ PSB_WVDC32(0x80000000, VGACNTRL); if (pipe == 1) { PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg); PSB_RVDC32(dpll_reg); PSB_WVDC32(fp_val, fp_reg); } else { dpll = PSB_RVDC32(dpll_reg); if (!(dpll & DPLL_VCO_ENABLE)) { /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ if (dpll & MDFLD_PWR_GATE_EN) { dpll &= ~MDFLD_PWR_GATE_EN; PSB_WVDC32(dpll, dpll_reg); udelay(500); /* FIXME: 1 ? */ } PSB_WVDC32(fp_val, fp_reg); PSB_WVDC32(dpll_val, dpll_reg); /* FIXME_MDFLD PO - change 500 to 1 after PO */ udelay(500); dpll_val |= DPLL_VCO_ENABLE; PSB_WVDC32(dpll_val, dpll_reg); PSB_RVDC32(dpll_reg); /* wait for DSI PLL to lock */ while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { udelay(150); timeout++; } if (timeout == 20000) { DRM_ERROR("%s, can't lock DSIPLL.\n", __func__); return -EINVAL; } } } /* Restore mode */ PSB_WVDC32(htot_val, htot_reg); PSB_WVDC32(hblank_val, hblank_reg); PSB_WVDC32(hsync_val, hsync_reg); PSB_WVDC32(vtot_val, vtot_reg); PSB_WVDC32(vblank_val, vblank_reg); PSB_WVDC32(vsync_val, vsync_reg); PSB_WVDC32(pipesrc_val, pipesrc_reg); PSB_WVDC32(dspstatus_val, dspstatus_reg); /* Set up the plane */ PSB_WVDC32(dspstride_val, dspstride_reg); PSB_WVDC32(dsplinoff_val, dsplinoff_reg); PSB_WVDC32(dsptileoff_val, dsptileoff_reg); PSB_WVDC32(dspsize_val, dspsize_reg); PSB_WVDC32(dsppos_val, dsppos_reg); PSB_WVDC32(dspsurf_val, dspsurf_reg); if (pipe == 1) { PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL); PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL); PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL); } else { /* Set up pipe related registers */ PSB_WVDC32(mipi_val, mipi_reg); /* Setup MIPI adapter + MIPI IP registers */ mdfld_dsi_controller_init(dsi_config, pipe); msleep(20); } /* Enable the plane */ PSB_WVDC32(dspcntr_val, dspcntr_reg); msleep(20); /* Enable the pipe */ PSB_WVDC32(pipeconf_val, pipeconf_reg); for (i = 0; i < 256; i++) PSB_WVDC32(palette_val[i], palette_reg + (i<<2)); if (pipe == 1) return 0; if (!mdfld_panel_dpi(dev)) mdfld_enable_te(dev, pipe); return 0; }
static void pyr_dsi_dbi_set_power(struct drm_encoder * encoder, bool on) { int ret = 0; struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_dbi_output * dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); /*struct drm_device * dev = dbi_output->dev;*/ struct drm_device* dev = encoder->dev; struct drm_psb_private * dev_priv = dev->dev_private; u32 reg_offset = 0; int pipe = (dbi_output->channel_num == 0) ? 0 : 2; PSB_DEBUG_ENTRY("pipe %d : %s, panel on: %s\n",pipe, on ? "On" : "Off", dbi_output->dbi_panel_on ? "True" : "False"); if(pipe == 2) { if(on) dev_priv->dual_mipi = true; else dev_priv->dual_mipi = false; reg_offset = MIPIC_REG_OFFSET; } else { if (!on) dev_priv->dual_mipi = false; } if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return; } if(on) { if(dbi_output->dbi_panel_on) goto out_err; ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); if(ret) { DRM_ERROR("power on error\n"); goto out_err; } dbi_output->dbi_panel_on = true; if(pipe == 2) { dev_priv->dbi_panel_on2 = true; } else { dev_priv->dbi_panel_on = true; if (dev_priv->platform_rev_id != MDFLD_PNW_A0) mdfld_enable_te(dev, 0); } } else { if(!dbi_output->dbi_panel_on && !dbi_output->first_boot) goto out_err; dbi_output->dbi_panel_on = false; dbi_output->first_boot = false; if(pipe == 2) { dev_priv->dbi_panel_on2 = false; if (dev_priv->platform_rev_id != MDFLD_PNW_A0) mdfld_disable_te(dev, 2); } else { dev_priv->dbi_panel_on = false; if (dev_priv->platform_rev_id != MDFLD_PNW_A0) { mdfld_disable_te(dev, 0); if (dev_priv->dbi_panel_on2) mdfld_enable_te(dev, 2); } } ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); if(ret) { DRM_ERROR("power on error\n"); goto out_err; } } out_err: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); if(ret) DRM_ERROR("failed\n"); else PSB_DEBUG_ENTRY("successfully\n"); }
static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) { int ret = 0; struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_dbi_output *dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_encoder_get_pkg_sender(dsi_encoder); struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = dev->dev_private; u32 reg_offset = 0; int pipe = (dbi_output->channel_num == 0) ? 0 : 2; u32 data = 0; dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe, on ? "On" : "Off", dbi_output->dbi_panel_on ? "True" : "False"); if (pipe == 2) { if (on) dev_priv->dual_mipi = true; else dev_priv->dual_mipi = false; reg_offset = MIPIC_REG_OFFSET; } else { if (!on) dev_priv->dual_mipi = false; } if (!gma_power_begin(dev, true)) { dev_err(dev->dev, "hw begin failed\n"); return; } if (on) { if (dbi_output->dbi_panel_on) goto out_err; ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); if (ret) { dev_err(dev->dev, "power on error\n"); goto out_err; } dbi_output->dbi_panel_on = true; if (pipe == 2) dev_priv->dbi_panel_on2 = true; else dev_priv->dbi_panel_on = true; mdfld_enable_te(dev, pipe); } else { if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) goto out_err; dbi_output->dbi_panel_on = false; dbi_output->first_boot = false; if (pipe == 2) dev_priv->dbi_panel_on2 = false; else dev_priv->dbi_panel_on = false; mdfld_disable_te(dev, pipe); ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); if (ret) { dev_err(dev->dev, "power on error\n"); goto out_err; } } /* * FIXME: this is a WA for TPO panel crash on DPMS on & off around * 83 times. the root cause of this issue is that Booster in * drvIC crashed. Add this WA so that we can resume the driver IC * once we found that booster has a fault */ mdfld_dsi_get_power_mode(dsi_config, &data, MDFLD_DSI_HS_TRANSMISSION); if (on && data && !(data & (1 << 7))) { /* Soft reset */ mdfld_dsi_send_dcs(sender, DCS_SOFT_RESET, NULL, 0, CMD_DATA_SRC_PIPE, MDFLD_DSI_SEND_PACKAGE); /* Init drvIC */ if (dbi_output->p_funcs->drv_ic_init) dbi_output->p_funcs->drv_ic_init(dsi_config, pipe); } out_err: gma_power_end(dev); if (ret) dev_err(dev->dev, "failed\n"); }
static int enter_dsr_locked(struct mdfld_dsi_config *dsi_config, int level) { 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; struct mdfld_dsi_pkg_sender *sender; int err; pm_message_t state; int pipe0_enabled; int pipe2_enabled; PSB_DEBUG_ENTRY("mdfld_dsi_dsr: enter dsr\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; sender = mdfld_dsi_get_pkg_sender(dsi_config); if (!sender) { DRM_ERROR("Failed to get dsi sender\n"); return -EINVAL; } if (level < DSR_EXITED) { DRM_ERROR("Why to do this?"); return -EINVAL; } if (level > DSR_ENTERED_LEVEL0) { /** * TODO: require OSPM interfaces to tell OSPM module that * display controller is ready to be power gated. * OSPM module needs to response this request ASAP. * NOTE: it makes no sense to have display controller islands * & pci power gated here directly. OSPM module is the only one * who can power gate/ungate power islands. * FIXME: since there's no ospm interfaces for acquiring * suspending DSI related power islands, we have to call OSPM * interfaces to power gate display islands and pci right now, * which should NOT happen in this way!!! */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("Failed power on display island\n"); return -EINVAL; } PSB_DEBUG_ENTRY("mdfld_dsi_dsr: entering DSR level 1\n"); /*Disable TE, don't need it anymore*/ mdfld_disable_te(dev, dsi_config->pipe); err = mdfld_dsi_wait_for_fifos_empty(sender); if (err) { DRM_ERROR("mdfld_dsi_dsr: FIFO not empty\n"); mdfld_enable_te(dev, dsi_config->pipe); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); /*suspend whole PCI host and related islands ** if failed at this try, revive te for another chance */ state.event = 0; if (ospm_power_suspend(gpDrmDevice->pdev, state)) { /* Only display island is powered off then ** need revive the whole TE */ if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) exit_dsr_locked(dsi_config); else mdfld_enable_te(dev, dsi_config->pipe); return -EINVAL; } /* *suspend pci *FIXME: should I do it here? *how about decoder/encoder is working?? *OSPM should check the refcout of each islands before *actually power off PCI!!! *need invoke this in the same context, we need deal with *DSR lock later for suspend PCI may go to sleep!!! */ /*ospm_suspend_pci(dev->pdev);*/ PSB_DEBUG_ENTRY("mdfld_dsi_dsr: entered\n"); return 0; } /* * if DSR_EXITED < level < DSR_ENTERED_LEVEL1, we only have the display * controller components turned off instead of power gate them. * this is useful for HDMI & WIDI. */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("Failed power on display island\n"); return -EINVAL; } PSB_DEBUG_ENTRY("mdfld_dsi_dsr: entering DSR level 0\n"); /*Disable TE, don't need it anymore*/ mdfld_disable_te(dev, dsi_config->pipe); err = mdfld_dsi_wait_for_fifos_empty(sender); if (err) { DRM_ERROR("mdfld_dsi_dsr: FIFO not empty\n"); mdfld_enable_te(dev, dsi_config->pipe); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; } /*turn off dbi interface put in ulps*/ __dbi_power_off(dsi_config); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); PSB_DEBUG_ENTRY("entered\n"); return 0; }
int mdfld_panel_generic_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) { int ret = 0; struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_dbi_output *dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); struct panel_funcs *p_funcs = dbi_output->p_funcs; struct mdfld_dsi_connector *dsi_connector = mdfld_dsi_encoder_get_connector(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = dev->dev_private; u32 reg_offset = 0; int pipe = (dbi_output->channel_num == 0) ? 0 : 2; PSB_DEBUG_ENTRY("pipe %d : %s, panel on: %s\n", pipe, on ? "On" : "Off", dbi_output->dbi_panel_on ? "True" : "False"); if (pipe == 2) { if (on) dev_priv->dual_mipi = true; else dev_priv->dual_mipi = false; reg_offset = MIPIC_REG_OFFSET; } else { if (!on) dev_priv->dual_mipi = false; } if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return -EAGAIN; } mutex_lock(&dsi_config->context_lock); if (on) { if (dbi_output->dbi_panel_on) goto out_err; ret = mdfld_panel_generic_dsi_dbi_power_on(encoder); if (ret) { DRM_ERROR("power on error\n"); goto out_err; } dbi_output->dbi_panel_on = true; if (pipe == 2) dev_priv->dbi_panel_on2 = true; else dev_priv->dbi_panel_on = true; if (dev_priv->platform_rev_id != MDFLD_PNW_A0) mdfld_enable_te(dev, pipe); /* wake up error detector if ESD enabled */ if (p_funcs->esd_detection) mdfld_dsi_error_detector_wakeup(dsi_connector); else PSB_DEBUG_ENTRY("ESD detection disabled\n"); dsi_config->dsi_hw_context.panel_on = 1; } else { if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) goto out_err; dbi_output->dbi_panel_on = false; dbi_output->first_boot = false; if (pipe == 2) dev_priv->dbi_panel_on2 = false; else dev_priv->dbi_panel_on = false; if (dev_priv->platform_rev_id != MDFLD_PNW_A0) mdfld_disable_te(dev, pipe); ret = mdfld_panel_generic_dsi_dbi_power_off(encoder); if (ret) { DRM_ERROR("power on error\n"); goto out_err; } dsi_config->dsi_hw_context.panel_on = 0; } out_err: mutex_unlock(&dsi_config->context_lock); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); if (ret) DRM_ERROR("failed\n"); else PSB_DEBUG_ENTRY("successfully\n"); return ret; }
static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe) { struct drm_device *dev = dbi_output->dev; struct drm_crtc *crtc = dbi_output->base.base.crtc; struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; u32 reg_val; u32 dpll_reg = MRST_DPLL_A; u32 pipeconf_reg = PIPEACONF; u32 dspcntr_reg = DSPACNTR; u32 reg_offset = 0; /*if mode setting on-going, back off*/ if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) return; if (pipe == 2) { dpll_reg = MRST_DPLL_A; pipeconf_reg = PIPECCONF; dspcntr_reg = DSPCCNTR; reg_offset = MIPIC_REG_OFFSET; } if (!gma_power_begin(dev, true)) { dev_err(dev->dev, "hw begin failed\n"); return; } /* Enable DPLL */ reg_val = REG_READ(dpll_reg); if (!(reg_val & DPLL_VCO_ENABLE)) { if (reg_val & MDFLD_PWR_GATE_EN) { reg_val &= ~MDFLD_PWR_GATE_EN; REG_WRITE(dpll_reg, reg_val); REG_READ(dpll_reg); udelay(500); } reg_val |= DPLL_VCO_ENABLE; REG_WRITE(dpll_reg, reg_val); REG_READ(dpll_reg); udelay(500); /* Add timeout */ while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) cpu_relax(); } /* Enable pipe */ reg_val = REG_READ(pipeconf_reg); if (!(reg_val & PIPEACONF_ENABLE)) { reg_val |= PIPEACONF_ENABLE; REG_WRITE(pipeconf_reg, reg_val); REG_READ(pipeconf_reg); udelay(500); mdfldWaitForPipeEnable(dev, pipe); } /* Enable plane */ reg_val = REG_READ(dspcntr_reg); if (!(reg_val & DISPLAY_PLANE_ENABLE)) { reg_val |= DISPLAY_PLANE_ENABLE; REG_WRITE(dspcntr_reg, reg_val); REG_READ(dspcntr_reg); udelay(500); } /* Enable TE interrupt on this pipe */ mdfld_enable_te(dev, pipe); gma_power_end(dev); /*clean IN_DSR flag*/ dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; }