void psb_irq_uninstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; unsigned long irqflags; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); dev_priv->sgx_irq_mask = 0x00000000; dev_priv->sgx2_irq_mask = 0x00000000; dev_priv->vdc_irq_mask = 0x00000000; PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); PSB_WSGX32(dev_priv->sgx_irq_mask, PSB_CR_EVENT_HOST_ENABLE); PSB_WSGX32(dev_priv->sgx2_irq_mask, PSB_CR_EVENT_HOST_ENABLE2); wmb(); PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); PSB_WSGX32(PSB_RSGX32(PSB_CR_EVENT_STATUS), PSB_CR_EVENT_HOST_CLEAR); PSB_WSGX32(PSB_RSGX32(PSB_CR_EVENT_STATUS2), PSB_CR_EVENT_HOST_CLEAR2); /****MSVDX IRQ Setup...*****/ /* Clear interrupt enabled flag */ PSB_WMSVDX32(0, MSVDX_HOST_INTERRUPT_ENABLE); dev_priv->irq_enabled = 0; spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); }
void psb_irq_postinstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; unsigned long irqflags; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); PSB_WSGX32(dev_priv->sgx2_irq_mask, PSB_CR_EVENT_HOST_ENABLE2); PSB_WSGX32(dev_priv->sgx_irq_mask, PSB_CR_EVENT_HOST_ENABLE); (void)PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); /****MSVDX IRQ Setup...*****/ /* Enable Mtx Interupt to host */ { unsigned long enables = 0; PSB_DEBUG_GENERAL("Setting up MSVDX IRQs.....\n"); REGIO_WRITE_FIELD_LITE(enables, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ, 1); PSB_WMSVDX32(enables, MSVDX_HOST_INTERRUPT_ENABLE); } dev_priv->irq_enabled = 1; uint32_t hotplug_stat = PSB_RVDC32(PORT_HOTPLUG_ENABLE_REG); PSB_WVDC32(hotplug_stat | SDVOB_HOTPLUG_DETECT_ENABLE, PORT_HOTPLUG_ENABLE_REG); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); }
/* 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 (!ospm_power_using_hw_begin (OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) return 0; mdfld_dsi_dsr_forbid(dsi_config); 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; } mdfld_dsi_dsr_allow(dsi_config); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return 0; }
static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) { struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; uint32_t pipestat; int wake = 0; int vsync_a = 0; int vsync_b = 0; static int pipe_a_on = 0; static int pipe_b_on = 0; int trigger_2d_blit = 0; pipestat = PSB_RVDC32(PSB_PIPEASTAT); if (pipestat & (1<<31)) { printk("buffer underrun 0x%x\n",underrun++); PSB_WVDC32(1<<31 | 1<<15, PSB_PIPEASTAT); } if ((!drm_psb_disable_vsync) && (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)) { atomic_inc(&dev->vbl_received); wake = 1; PSB_WVDC32(_PSB_VBLANK_INTERRUPT_ENABLE | _PSB_VBLANK_CLEAR, PSB_PIPEASTAT); } if ((!drm_psb_disable_vsync) && (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)) { atomic_inc(&dev->vbl_received2); wake = 1; PSB_WVDC32(_PSB_VBLANK_INTERRUPT_ENABLE | _PSB_VBLANK_CLEAR, PSB_PIPEBSTAT); } if (vdc_stat & _PSB_HOTPLUG_INTERRUPT_FLAG) { // Clear 2nd status register spin_lock(&dev_priv->irqmask_lock); uint32_t hotplugstat = PSB_RVDC32(PORT_HOTPLUG_STATUS_REG); PSB_WVDC32(hotplugstat, PORT_HOTPLUG_STATUS_REG); spin_unlock(&dev_priv->irqmask_lock); hotplug_env = '1'; wake_up_interruptible(&hotplug_queue); } PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); (void)PSB_RVDC32(PSB_INT_IDENTITY_R); DRM_READMEMORYBARRIER(); if (wake) { DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); } }
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; if (!dev_priv) return 0; dsi_config = dev_priv->dsi_configs[0]; if (!dsi_config) return 0; if (!ospm_power_using_hw_begin (OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { return 0; } mdfld_dsi_dsr_forbid(dsi_config); 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); } } mdfld_dsi_dsr_allow(dsi_config); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); 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; }
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; if (!ospm_power_using_hw_begin (OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return 0; mdfld_dsi_dsr_forbid(dsi_config); reg_data.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL); reg_data.guardband = input->guardband; reg_data.guardband_interrupt_delay = input->guardband_interrupt_delay; PSB_WVDC32(reg_data.data, HISTOGRAM_INT_CONTROL); ctx->histogram_intr_ctrl = reg_data.data; mdfld_dsi_dsr_allow(dsi_config); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return 0; }
/* dsr lock and power island lock should be hold before calling this function */ int psb_dpst_diet_save(struct drm_device *dev) { struct drm_psb_private *dev_priv = NULL; struct dpst_ie_histogram_control ie_hist_cont_reg; uint32_t blm_hist_ctl = HISTOGRAM_LOGIC_CONTROL; uint32_t iebdr_reg = HISTOGRAM_BIN_DATA; int dpst3_bin_count = 32; u32 i; if (!dev) return 0; dev_priv = psb_priv(dev); if (!dev_priv || !dev_priv->psb_dpst_state) return 0; ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl); ie_hist_cont_reg.bin_reg_func_select = 1; 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++) diet_saved[i] = PSB_RVDC32(iebdr_reg); dpst_print("diet saved\n"); diet_saved[0] = 0x200; return 0; }
void psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) { if ((dev_priv->pipestat[pipe] & mask) != mask) { u32 reg = psb_pipestat(pipe); u32 writeVal = PSB_RVDC32(reg); dev_priv->pipestat[pipe] |= mask; /* Enable the interrupt, clear any pending status */ writeVal |= (mask | (mask >> 16)); PSB_WVDC32(writeVal, reg); (void) PSB_RVDC32(reg); }
/* this function is only called by dpms on or late resume function */ void dpstmgr_reg_restore_locked(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 (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) return; 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); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); }
/* 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 psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) { if ((dev_priv->pipestat[pipe] & mask) != mask) { u32 reg = psb_pipestat(pipe); dev_priv->pipestat[pipe] |= mask; /* Enable the interrupt, clear any pending status */ if (ospm_power_using_hw_begin (OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) { u32 writeVal = PSB_RVDC32(reg); writeVal |= (mask | (mask >> 16)); PSB_WVDC32(writeVal, reg); (void)PSB_RVDC32(reg); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } }
void psb_irq_preinstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; spin_lock(&dev_priv->irqmask_lock); PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); PSB_WVDC32(0x00000000, PSB_INT_MASK_R); PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE); (void)PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); dev_priv->sgx_irq_mask = _PSB_CE_PIXELBE_END_RENDER | _PSB_CE_DPM_3D_MEM_FREE | _PSB_CE_TA_FINISHED | _PSB_CE_DPM_REACHED_MEM_THRESH | _PSB_CE_DPM_OUT_OF_MEMORY_GBL | _PSB_CE_DPM_OUT_OF_MEMORY_MT | _PSB_CE_TA_TERMINATE | _PSB_CE_SW_EVENT; dev_priv->sgx2_irq_mask = _PSB_CE2_BIF_REQUESTER_FAULT; dev_priv->vdc_irq_mask = _PSB_IRQ_SGX_FLAG | _PSB_IRQ_MSVDX_FLAG | _PSB_HOTPLUG_INTERRUPT_ENABLE; if (!drm_psb_disable_vsync || drm_psb_detear) dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG | _PSB_VSYNC_PIPEB_FLAG; /*Clear MTX interrupt */ { unsigned long mtx_int = 0; REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ, 1); PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR); } spin_unlock(&dev_priv->irqmask_lock); }
/** * gma_resume_display - resume display side logic * * Resume the display hardware restoring state and enabling * as necessary. */ static void gma_resume_display(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); struct drm_psb_private *dev_priv = dev->dev_private; /* turn on the display power island */ dev_priv->ops->power_up(dev); dev_priv->suspended = false; dev_priv->display_power = true; PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); psb_gtt_restore(dev); /* Rebuild our GTT mappings */ dev_priv->ops->restore_regs(dev); }
static void set_clock(void *data, int state_high) { struct intel_i2c_chan *chan = data; struct drm_psb_private *dev_priv = chan->drm_dev->dev_private; uint32_t reserved = 0, clock_bits; /* On most chips, these bits must be preserved in software. */ reserved = PSB_RVDC32(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE); if (state_high) clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; else clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK; PSB_WVDC32(reserved | clock_bits, chan->reg); udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ }
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; }
/* dsr lock and power island lock should be hold before calling this function */ int psb_dpst_diet_restore(struct drm_device *dev) { struct drm_psb_private *dev_priv = NULL; struct mdfld_dsi_config *dsi_config = NULL; struct mdfld_dsi_hw_context *ctx = NULL; 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) return 0; dev_priv = psb_priv(dev); if (!dev_priv || !dev_priv->psb_dpst_state) return 0; dsi_config = dev_priv->dsi_configs[0]; if (!dsi_config) return 0; ctx = &dsi_config->dsi_hw_context; PSB_WVDC32(ctx->histogram_intr_ctrl, HISTOGRAM_INT_CONTROL); ie_hist_cont_reg.data = ctx->histogram_logic_ctrl; 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("before restore: "); for (i = 0; i <= dpst3_bin_count; i++) { printk(" 0x%x ", PSB_RVDC32(iebdr_reg)); } printk("\n"); } for (i = 0; i <= dpst3_bin_count; i++) { PSB_WVDC32(diet_saved[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; return 0; }
IMG_BOOL MRSTLFBFlipToSurface(MRSTLFB_DEVINFO *psDevInfo, unsigned long uiAddr) { int dspbase = (psDevInfo->ui32MainPipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (psDevInfo->ui32MainPipe == 0 ? DSPASURF : DSPBSURF); struct drm_device * dev = psDevInfo->psDrmDevice; struct drm_psb_private *dev_priv = (struct drm_psb_private *) psDevInfo->psDrmDevice->dev_private; MRSTLFB_SWAPCHAIN *psCurrentSwapChain = psDevInfo->psCurrentSwapChain; struct mdfld_dsi_config *dsi_config; struct mdfld_dsi_hw_context *ctx; unsigned int tmp; if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false)) { if (IS_MRST(dev)) { MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr); } else if (IS_MDFLD(dev)) { if (psCurrentSwapChain != NULL) { if (psCurrentSwapChain->ui32SwapChainPropertyFlag & PVRSRV_SWAPCHAIN_ATTACHED_PLANE_A) { dspsurf = DSPASURF; tmp = PSB_RVDC32(DSPACNTR); if (!(tmp & DISPLAY_PLANE_ENABLE)) PSB_WVDC32(tmp | DISPLAY_PLANE_ENABLE, DSPACNTR); MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr); dsi_config = dev_priv->dsi_configs[0]; if (dsi_config) { ctx = &dsi_config->dsi_hw_context; ctx->dspsurf = uiAddr; } if (mdfld_dsi_dsr_update_panel_fb(dsi_config)) { ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return IMG_FALSE; } } #if defined(CONFIG_MDFD_DUAL_MIPI) if (psCurrentSwapChain->ui32SwapChainPropertyFlag & PVRSRV_SWAPCHAIN_ATTACHED_PLANE_C) { dspsurf = DSPCSURF; tmp = PSB_RVDC32(DSPACNTR + 0x2000); if (!(tmp & DISPLAY_PLANE_ENABLE)) PSB_WVDC32(tmp | DISPLAY_PLANE_ENABLE, DSPACNTR + 0x2000); MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr); dsi_config = dev_priv->dsi_configs[1]; if (dsi_config) { ctx = &dsi_config->dsi_hw_context; ctx->dspsurf = uiAddr; } if (mdfld_dsi_dsr_update_panel_fb(dsi_config)) { ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return IMG_FALSE; } } #endif #ifdef CONFIG_SUPPORT_HDMI /* To avoid Plane B still fetches data from original frame * buffer. */ if (psCurrentSwapChain->ui32SwapChainPropertyFlag & PVRSRV_SWAPCHAIN_ATTACHED_PLANE_B) { dspsurf = DSPBSURF; tmp = PSB_RVDC32(DSPACNTR + 0x1000); if (!(tmp & DISPLAY_PLANE_ENABLE)) PSB_WVDC32(tmp | DISPLAY_PLANE_ENABLE, DSPACNTR + 0x1000); MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr); } #endif } else { printk(KERN_WARNING "Current Swapchain is null, no attached plane info\ available, omit address update\n"); if (drm_psb_debug & PSB_D_GENERAL) dump_stack(); } } else { MRSTLFBVSyncWriteReg(psDevInfo, dspbase, uiAddr); } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); }
// 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; }
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; }
/* 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; }
/* * mdfld_restore_display_registers * * Description: We are going to resume so restore display register state. * * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio */ static int mdfld_restore_display_registers(struct drm_device *dev, int pipenum) { /* To get panel out of ULPS mode. */ u32 temp = 0; u32 device_ready_reg = DEVICE_READY_REG; struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_config *dsi_config = NULL; struct medfield_state *regs = &dev_priv->regs.mdfld; struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum]; const struct psb_offset *map = &dev_priv->regmap[pipenum]; u32 i; u32 dpll; u32 timeout = 0; /* register */ u32 mipi_reg = MIPI; /* values */ u32 dpll_val = pipe->dpll; u32 mipi_val = regs->saveMIPI; switch (pipenum) { case 0: dpll_val &= ~DPLL_VCO_ENABLE; dsi_config = dev_priv->dsi_configs[0]; break; case 1: dpll_val &= ~DPLL_VCO_ENABLE; break; case 2: mipi_reg = MIPI_C; mipi_val = regs->saveMIPI_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 (pipenum == 1) { PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, map->dpll); PSB_RVDC32(map->dpll); PSB_WVDC32(pipe->fp0, map->fp0); } else { dpll = PSB_RVDC32(map->dpll); 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, map->dpll); /* FIXME_MDFLD PO - change 500 to 1 after PO */ udelay(500); } PSB_WVDC32(pipe->fp0, map->fp0); PSB_WVDC32(dpll_val, map->dpll); /* FIXME_MDFLD PO - change 500 to 1 after PO */ udelay(500); dpll_val |= DPLL_VCO_ENABLE; PSB_WVDC32(dpll_val, map->dpll); PSB_RVDC32(map->dpll); /* wait for DSI PLL to lock */ while (timeout < 20000 && !(PSB_RVDC32(map->conf) & PIPECONF_DSIPLL_LOCK)) { udelay(150); timeout++; } if (timeout == 20000) { DRM_ERROR("%s, can't lock DSIPLL.\n", __func__); return -EINVAL; } } } /* Restore mode */ PSB_WVDC32(pipe->htotal, map->htotal); PSB_WVDC32(pipe->hblank, map->hblank); PSB_WVDC32(pipe->hsync, map->hsync); PSB_WVDC32(pipe->vtotal, map->vtotal); PSB_WVDC32(pipe->vblank, map->vblank); PSB_WVDC32(pipe->vsync, map->vsync); PSB_WVDC32(pipe->src, map->src); PSB_WVDC32(pipe->status, map->status); /*set up the plane*/ PSB_WVDC32(pipe->stride, map->stride); PSB_WVDC32(pipe->linoff, map->linoff); PSB_WVDC32(pipe->tileoff, map->tileoff); PSB_WVDC32(pipe->size, map->size); PSB_WVDC32(pipe->pos, map->pos); PSB_WVDC32(pipe->surf, map->surf); if (pipenum == 1) { /* restore palette (gamma) */ /*DRM_UDELAY(50000); */ for (i = 0; i < 256; i++) PSB_WVDC32(pipe->palette[i], map->palette + (i << 2)); PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL); PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); /*TODO: resume HDMI port */ /*TODO: resume pipe*/ /*enable the plane*/ PSB_WVDC32(pipe->cntr & ~DISPLAY_PLANE_ENABLE, map->cntr); return 0; } /*set up pipe related registers*/ PSB_WVDC32(mipi_val, mipi_reg); /*setup MIPI adapter + MIPI IP registers*/ if (dsi_config) mdfld_dsi_controller_init(dsi_config, pipenum); if (in_atomic() || in_interrupt()) mdelay(20); else msleep(20); /*enable the plane*/ PSB_WVDC32(pipe->cntr, map->cntr); if (in_atomic() || in_interrupt()) mdelay(20); else msleep(20); /* LP Hold Release */ temp = REG_READ(mipi_reg); temp |= LP_OUTPUT_HOLD_RELEASE; REG_WRITE(mipi_reg, temp); mdelay(1); /* Set DSI host to exit from Utra Low Power State */ temp = REG_READ(device_ready_reg); temp &= ~ULPS_MASK; temp |= 0x3; temp |= EXIT_ULPS_DEV_READY; REG_WRITE(device_ready_reg, temp); mdelay(1); temp = REG_READ(device_ready_reg); temp &= ~ULPS_MASK; temp |= EXITING_ULPS; REG_WRITE(device_ready_reg, temp); mdelay(1); /*enable the pipe*/ PSB_WVDC32(pipe->conf, map->conf); /* restore palette (gamma) */ /*DRM_UDELAY(50000); */ for (i = 0; i < 256; i++) PSB_WVDC32(pipe->palette[i], map->palette + (i << 2)); return 0; }
/* 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_cursor_overlay_registers - restore cursor * @dev: our device * * Restore the cursor and overlay state that was saved earlier */ static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; /* Enable Cursor A */ PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR); PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS); PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE); PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR); PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS); PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE); PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR); PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS); PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE); /* Restore HW overlay */ PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD); PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0); PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1); PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2); PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3); PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4); PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5); PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET); PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET); PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET); PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET); PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET); PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET); PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET); return 0; }
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; if (!ospm_power_using_hw_begin (OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { return 0; } 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.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); } 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); } mdfld_dsi_dsr_allow(dsi_config); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return 0; }
/* 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; }
/* * 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; }