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; }
/** * 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); }
static void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) { struct mdfld_dsi_encoder *dsi_encoder; struct mdfld_dsi_dpi_output *dpi_output; struct mdfld_dsi_hw_context *ctx; struct mdfld_dsi_config *dsi_config; struct drm_device *dev; u32 temp_val = 0; PSB_DEBUG_ENTRY("\n"); dsi_encoder = MDFLD_DSI_ENCODER(encoder); dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); dev = dsi_config->dev; ctx = &dsi_config->dsi_hw_context; if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return; temp_val = REG_READ(PIPEACONF); temp_val &= ~(BIT27 | BIT28); /* Setup pipe configuration for different panels*/ REG_WRITE(PIPEACONF, temp_val | (ctx->pipeconf & (BIT27 | BIT28))); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); /*Everything is ready, commit DSI hw context to HW*/ __mdfld_dsi_dpi_set_power(encoder, true); dpi_output->first_boot = 0; }
static void dpst_restore_gamma_settings(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_config *dsi_config; struct mdfld_dsi_hw_context *ctx; struct drm_connector *connector; struct drm_crtc *crtc; struct psb_intel_crtc *psb_intel_crtc; int i = 0; if (!dev_priv) return; connector = dev_priv->dpst_lvds_connector; dsi_config = dev_priv->dsi_configs[0]; ctx = &dsi_config->dsi_hw_context; crtc = connector->encoder->crtc; psb_intel_crtc = to_psb_intel_crtc(crtc); if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return; mdfld_dsi_dsr_forbid(dsi_config); for (i = 0; i < 256; i++) { ctx->palette[i] = lut_adj[i]; REG_WRITE((PALETTE_A + 4 * i), lut_adj[i]); } mdfld_dsi_dsr_allow(dsi_config); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); }
inline int had_get_hwstate(struct snd_intelhad *intelhaddata) { /* Check for device presence -SW state */ if (intelhaddata->drv_status == HAD_DRV_DISCONNECTED) { pr_debug("%s:Device not connected:%d\n", __func__, intelhaddata->drv_status); return -ENODEV; } /* Check for device presence -HW state */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) { pr_err("%s:Device not connected\n", __func__); dump_stack(); /* HOT_UNPLUG event can be sent to * maintain correct state within HAD * had_event_handler(HAD_EVENT_HOT_UNPLUG, intelhaddata); * Drop all acuired locks before executing this. */ return -ENODEV; } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); 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; 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; MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr); if (dev_priv->b_async_flip_enable && dev_priv->async_flip_update_fb) if (dev_priv->async_flip_update_fb( dev, 0) == IMG_FALSE) return IMG_FALSE; } #if defined(CONFIG_MDFD_DUAL_MIPI) if (psCurrentSwapChain->ui32SwapChainPropertyFlag & PVRSRV_SWAPCHAIN_ATTACHED_PLANE_C) { dspsurf = DSPCSURF; MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr); if (dev_priv->b_async_flip_enable && dev_priv->async_flip_update_fb) if (dev_priv->async_flip_update_fb( dev, 2) == IMG_FALSE) return IMG_FALSE; } #endif #ifdef CONFIG_MDFD_HDMI /* To avoid Plane B still fetches data from original frame * buffer. */ if (psCurrentSwapChain->ui32SwapChainPropertyFlag & PVRSRV_SWAPCHAIN_ATTACHED_PLANE_B) { dspsurf = DSPBSURF; 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 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 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; }
void gl3_disable(void) { struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private; PSB_DEBUG_ENTRY("gl3_disable called on platform %x\n", dev_priv->platform_rev_id); if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true)) return; MDFLD_GL3_WRITE(MDFLD_GL3_DISABLE_CACHE, MDFLD_GL3_CONTROL); PSB_DEBUG_GENERAL("gl3 cache disabled with mask %x\n", MDFLD_GL3_DISABLE_CACHE); ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND); }
void gl3_reset(void) { struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private; PSB_DEBUG_ENTRY("gl3_reset called on platform %x\n", dev_priv->platform_rev_id); if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true)) return; // Reset the cache MDFLD_GL3_WRITE(MDFLD_GL3_SOFT_RESET_ENABLE, MDFLD_GL3_G_CONTROL); PSB_DEBUG_GENERAL("gl3 cache soft reset with mas %x\n", MDFLD_GL3_SOFT_RESET_ENABLE); ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND); }
int mdfld_panel_generic_dsi_dbi_power_on(struct drm_encoder *encoder) { 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 panel_funcs *p_funcs = dbi_output->p_funcs; struct mdfld_dsi_hw_registers *regs = NULL; struct mdfld_dsi_hw_context *ctx = NULL; struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = dev->dev_private; int err = 0; if (!dev_priv->dsi_init_done) return 0; if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return -EAGAIN; /* * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) { p_funcs->dsi_controller_init(dsi_config, dsi_config->pipe, true); if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } } power_on_err: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; }
int mdfld_panel_generic_dsi_dbi_power_off(struct drm_encoder *encoder) { 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 panel_funcs *p_funcs = dbi_output->p_funcs; struct mdfld_dsi_hw_context *ctx; struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = dev->dev_private; int err = 0; if (!dev_priv->dsi_init_done) return 0; if (!dsi_config) return -EINVAL; ctx = &dsi_config->dsi_hw_context; if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return -EAGAIN; ctx->lastbrightnesslevel = psb_brightness; /* * Different panel may have different ways to have * panel turned off. Support it! */ if (p_funcs && p_funcs->power_off) { if (p_funcs->power_off(dsi_config)) { DRM_ERROR("Failed to power off panel\n"); err = -EAGAIN; goto power_off_err; } } power_off_err: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return err; }
static int mdfld_dsi_pr2_detect(struct mdfld_dsi_config *dsi_config) { int status; struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; u32 dpll_val, device_ready_val; int pipe = dsi_config->pipe; PSB_DEBUG_ENTRY("\n"); if (pipe == 0) { /* * FIXME: WA to detect the panel connection status, and need to * implement detection feature with get_power_mode DSI command. */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return -EAGAIN; } dpll_val = REG_READ(regs->dpll_reg); device_ready_val = REG_READ(regs->device_ready_reg); if ((device_ready_val & DSI_DEVICE_READY) && (dpll_val & DPLL_VCO_ENABLE)) { dsi_config->dsi_hw_context.panel_on = true; } else { dsi_config->dsi_hw_context.panel_on = false; DRM_INFO("%s: panel is not detected!\n", __func__); } status = MDFLD_DSI_PANEL_CONNECTED; ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } else { DRM_INFO("%s: do NOT support dual panel\n", __func__); status = MDFLD_DSI_PANEL_DISCONNECTED; } return status; }
PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex, PVRSRV_DEV_POWER_STATE eNewPowerState, PVRSRV_DEV_POWER_STATE eCurrentPowerState) { if ((eNewPowerState != eCurrentPowerState) && (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)) { if (ui32DeviceIndex == gui32SGXDeviceID) { PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore SGX power")); #if defined(SUPPORT_DRI_DRM_EXT) ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true); #endif } else if (ui32DeviceIndex == gui32MRSTMSVDXDeviceID) { PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore MSVDX power")); if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) { ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND); } else { ospm_power_island_up(OSPM_DISPLAY_ISLAND); ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND); ospm_power_island_down(OSPM_DISPLAY_ISLAND); } } else if (ui32DeviceIndex == gui32MRSTTOPAZDeviceID) { PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore TOPAZ power")); if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) { ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND); } else { ospm_power_island_up(OSPM_DISPLAY_ISLAND); ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND); ospm_power_island_down(OSPM_DISPLAY_ISLAND); } } } return PVRSRV_OK; }
void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) { struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_dpi_output *dpi_output = NULL; u32 mipi_reg = MIPI; u32 pipeconf_reg = PIPEACONF; PSB_DEBUG_ENTRY("set power %s on pipe %d\n", on ? "On" : "Off", pipe); dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); if (pipe) if (!(dev_priv->panel_desc & DISPLAY_B) || !(dev_priv->panel_desc & DISPLAY_C)) return; if (pipe) { mipi_reg = MIPI_C; pipeconf_reg = PIPECCONF; } /*start up display island if it was shutdown*/ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) return; /** * if TMD panel call new power on/off sequences instead. * NOTE: refine TOSHIBA panel code later */ __mdfld_dsi_dpi_set_power(encoder, on); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); }
int psb_dpst_mode(struct drm_device *dev, void *data) { struct drm_psb_private *dev_priv = psb_priv(dev); struct mdfld_dsi_config *dsi_config = NULL; uint32_t *arg = data; uint32_t x = 0; uint32_t y = 0; uint32_t reg; if (!dev_priv) return 0; dsi_config = dev_priv->dsi_configs[0]; if (!dsi_config) return 0; mdfld_dsi_dsr_forbid(dsi_config); if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) return 0; reg = PSB_RVDC32(PIPEASRC); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); mdfld_dsi_dsr_allow(dsi_config); /* horizontal is the left 16 bits */ x = reg >> 16; /* vertical is the right 16 bits */ y = reg & 0x0000ffff; /* the values are the image size minus one */ x += 1; y += 1; *arg = (x << 16) | y; return 0; }
/* 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); }
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 int __mdfld_dbi_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 = PSB_DSI_PLL_CTRL; u32 pipeconf_reg = PSB_PIPECONF(PSB_PIPE_A); u32 dspcntr_reg = PSB_DSPCNTR(PSB_PIPE_A); u32 dspbase_reg = PSB_DSPBASE(PSB_PIPE_A); u32 dspsurf_reg = PSB_DSPSURF(PSB_PIPE_A); PSB_DEBUG_ENTRY("\n"); if(!dbi_output) { return 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 -EAGAIN; if(pipe == 2) { dpll_reg = PSB_DSI_PLL_CTRL; pipeconf_reg = PSB_PIPECONF(PSB_PIPE_C); dspcntr_reg = PSB_DSPCNTR(PSB_PIPE_C); dspbase_reg = MDFLD_DSPCBASE; dspsurf_reg = PSB_DSPSURF(PSB_PIPE_C); } if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true)) return -EAGAIN; /*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); /*FIXME: add timeout*/ while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)); } /*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); } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); /*clean IN_DSR flag*/ dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; return 0; }
static int mdfld_dpu_update_fb(struct drm_device * dev) { struct drm_crtc * crtc; struct psb_intel_crtc * psb_crtc; 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; bool pipe_updated[2]; unsigned long irq_flags; u32 dpll_reg = PSB_DSI_PLL_CTRL; u32 dspcntr_reg = PSB_DSPCNTR(PSB_PIPE_A); u32 pipeconf_reg = PSB_PIPECONF(PSB_PIPE_A); u32 dsplinoff_reg = PSB_DSPLINOFF(PSB_PIPE_A); u32 dspsurf_reg = PSB_DSPSURF(PSB_PIPE_A); int pipe; int i; int ret; dbi_output = dpu_info->dbi_outputs; pipe_updated[0] = pipe_updated[1] = false; if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true)) return -EAGAIN; /*try to prevent any new damage reports*/ if(!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) { return -EAGAIN; } for(i=0; i<dpu_info->dbi_output_num; i++) { crtc = dbi_output[i]->base.base.crtc; psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; pipe = dbi_output[i]->channel_num ? 2 : 0; if(pipe == 2) { dspcntr_reg = PSB_DSPCNTR(PSB_PIPE_C); pipeconf_reg = PSB_PIPECONF(PSB_PIPE_C); dsplinoff_reg = PSB_DSPLINOFF(PSB_PIPE_C); dspsurf_reg = PSB_DSPSURF(PSB_PIPE_C); } if (!(REG_READ(MIPI_GEN_FIFO_STAT_REG(pipe)) & BIT(27)) || !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) { PSB_DEBUG_ENTRY("DBI FIFO is busy, DSI %d state %x\n", pipe, REG_READ(MIPI_INTR_STAT_REG(pipe))); continue; } /*if dbi output is in a exclusive state, pipe change won't be updated*/ if(dbi_output[i]->dbi_panel_on && !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) && !(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) && !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) { ret = mdfld_dpu_update_pipe(dbi_output[i], dpu_info, dbi_output[i]->channel_num ? 2 : 0); if(!ret) { pipe_updated[i] = true; } } } for(i=0; i<dpu_info->dbi_output_num; i++) { if(pipe_updated[i]) { mdfld_dbi_flush_cb(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0); } } spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return 0; }
/** * Update the DBI MIPI Panel Frame Buffer. */ static void pyr_dsi_dbi_update_fb (struct mdfld_dsi_dbi_output * dbi_output, int pipe) { struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); 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 dpll_reg = MRST_DPLL_A; u32 dspcntr_reg = DSPACNTR; u32 pipeconf_reg = PIPEACONF; u32 dsplinoff_reg = DSPALINOFF; u32 dspsurf_reg = DSPASURF; /*u32 mipi_state_reg = MIPIA_INTR_STAT_REG;*/ u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG; u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; u32 reg_offset = 0; u32 intr_status; u32 fifo_stat_reg_val; u32 dpll_reg_val; u32 dspcntr_reg_val; u32 pipeconf_reg_val; /*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) || !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) return; /* * Look for errors here. In particular we're checking for whatever * error status might have appeared during the last frame transmit * (memory write). * * Normally, the bits we're testing here would be set infrequently, * if at all. However, the Pyrenees panel (at least) returns * at least one error bit on most frames. So we've disabled the * kernel message for now. * * Still clear whatever error bits are set, except don't clear the * ones that would make the Penwell DSI controller reset if we * cleared them. */ intr_status = REG_READ(INTR_STAT_REG); if ((intr_status & 0x26FFFFFF) != 0) { /* DRM_ERROR("DSI status: 0x%08X\n", intr_status); */ intr_status &= 0x26F3FFFF; REG_WRITE(INTR_STAT_REG, intr_status); } if(pipe == 2) { dspcntr_reg = DSPCCNTR; pipeconf_reg = PIPECCONF; dsplinoff_reg = DSPCLINOFF; dspsurf_reg = DSPCSURF; hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET, reg_offset = MIPIC_REG_OFFSET; } if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return; } fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset); dpll_reg_val = REG_READ(dpll_reg); dspcntr_reg_val = REG_READ(dspcntr_reg); pipeconf_reg_val = REG_READ(pipeconf_reg); if(!(fifo_stat_reg_val & BIT27) || !(dpll_reg_val & DPLL_VCO_ENABLE) || !(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) || !(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) { goto update_fb_out0; } /*refresh plane changes*/ REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); REG_READ(dspsurf_reg); mdfld_dsi_send_dcs(sender, write_mem_start, NULL, 0, CMD_DATA_SRC_PIPE, MDFLD_DSI_SEND_PACKAGE); /* * The idea here is to transmit a Generic Read command after the * Write Memory Start/Continue commands finish. This asks for * the panel to return an "ACK No Errors," or (if it has errors * to report) an Error Report. This allows us to monitor the * panel's perception of the health of the DSI. */ mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0); dbi_output->dsr_fb_update_done = true; update_fb_out0: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); }
static void pyr_dsi_dbi_mode_set(struct drm_encoder * encoder, struct drm_display_mode * mode, struct drm_display_mode * adjusted_mode) { int ret = 0; struct drm_device * dev = encoder->dev; struct drm_psb_private * dev_priv = (struct drm_psb_private*)dev->dev_private; struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_dbi_output * dsi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct mdfld_dsi_connector * dsi_connector = dsi_config->connector; int pipe = dsi_connector->pipe; u8 param = 0; /*regs*/ u32 mipi_reg = MIPI; u32 dspcntr_reg = DSPACNTR; u32 pipeconf_reg = PIPEACONF; u32 reg_offset = 0; /*values*/ u32 dspcntr_val = dev_priv->dspcntr; u32 pipeconf_val = dev_priv->pipeconf; u32 h_active_area = mode->hdisplay; u32 v_active_area = mode->vdisplay; u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX); if (dev_priv->platform_rev_id != MDFLD_PNW_A0) mipi_val = (PASS_FROM_SPHY_TO_AFE | TE_TRIGGER_GPIO_PIN); PSB_DEBUG_ENTRY("mipi_val =0x%x\n", mipi_val); PSB_DEBUG_ENTRY("type %s\n", (pipe == 2) ? "MIPI2" : "MIPI"); PSB_DEBUG_ENTRY("h %d v %d\n", mode->hdisplay, mode->vdisplay); if(pipe == 2) { mipi_reg = MIPI_C; dspcntr_reg = DSPCCNTR; pipeconf_reg = PIPECCONF; reg_offset = MIPIC_REG_OFFSET; dspcntr_val = dev_priv->dspcntr2; pipeconf_val = dev_priv->pipeconf2; } else { mipi_val |= 0x2; /*two lanes for port A and C respectively*/ } if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return; } /*set up pipe related registers*/ REG_WRITE(mipi_reg, mipi_val); REG_READ(mipi_reg); pyr_dsi_controller_dbi_init(dsi_config, pipe); msleep(20); REG_WRITE(dspcntr_reg, dspcntr_val); REG_READ(dspcntr_reg); /*20ms delay before sending exit_sleep_mode*/ msleep(20); /*send exit_sleep_mode DCS*/ ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM); if(ret) { DRM_ERROR("sent exit_sleep_mode faild\n"); goto out_err; } if (dev_priv->platform_rev_id != MDFLD_PNW_A0) { /*send set_tear_on DCS*/ ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on, ¶m, 1, CMD_DATA_SRC_SYSTEM_MEM); if(ret) { DRM_ERROR("%s - sent set_tear_on faild\n", __func__); goto out_err; } } /*do some init stuff*/ mdfld_dsi_brightness_init(dsi_config, pipe); mdfld_dsi_gen_fifo_ready (dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset), HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR); REG_READ(pipeconf_reg); /*TODO: this looks ugly, try to move it to CRTC mode setting*/ if(pipe == 2) { dev_priv->pipeconf2 |= PIPEACONF_DSR; } else { dev_priv->pipeconf |= PIPEACONF_DSR; } PSB_DEBUG_ENTRY("pipeconf %x\n", REG_READ(pipeconf_reg)); ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, h_active_area - 1, v_active_area - 1); if(ret) { DRM_ERROR("update area failed\n"); goto out_err; } out_err: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); if(ret) { DRM_ERROR("mode set failed\n"); } else { PSB_DEBUG_ENTRY("mode set done successfully\n"); } }
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"); }
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; }
/** * snd_intelhad_init_audio_ctrl - to initialize audio channel status * registers and confgiuration registers * * @substream:substream for which the prepare function is called * @intelhaddata:substream private data * * This function is called in the prepare callback */ int snd_intelhad_init_audio_ctrl(struct snd_pcm_substream *substream, struct snd_intelhad *intelhaddata, int flag_silence) { union aud_cfg cfg_val = {.cfg_regval = 0}; union aud_ch_status_0 ch_stat0 = {.status_0_regval = 0}; union aud_ch_status_1 ch_stat1 = {.status_1_regval = 0}; union aud_buf_config buf_cfg = {.buf_cfgval = 0}; u8 channels; int format, retval; u32 data; ch_stat0.status_0_regx.lpcm_id = (intelhaddata->aes_bits & IEC958_AES0_NONAUDIO)>>1; ch_stat0.status_0_regx.clk_acc = (intelhaddata->aes_bits & IEC958_AES3_CON_CLOCK)>>4; switch (substream->runtime->rate) { case AUD_SAMPLE_RATE_32: ch_stat0.status_0_regx.samp_freq = CH_STATUS_MAP_32KHZ; break; case AUD_SAMPLE_RATE_44_1: case AUD_SAMPLE_RATE_88_2: case AUD_SAMPLE_RATE_176_4: ch_stat0.status_0_regx.samp_freq = CH_STATUS_MAP_44KHZ; break; case AUD_SAMPLE_RATE_48: case AUD_SAMPLE_RATE_96: case HAD_MAX_RATE: ch_stat0.status_0_regx.samp_freq = CH_STATUS_MAP_48KHZ; break; default: return -EINVAL; break; } had_write_register(AUD_CH_STATUS_0, ch_stat0.status_0_regval); format = substream->runtime->format; if (format == SNDRV_PCM_FORMAT_S16_LE) { ch_stat1.status_1_regx.max_wrd_len = MAX_SMPL_WIDTH_20; ch_stat1.status_1_regx.wrd_len = SMPL_WIDTH_16BITS; } else if (format == SNDRV_PCM_FORMAT_S24_LE) { ch_stat1.status_1_regx.max_wrd_len = MAX_SMPL_WIDTH_24; ch_stat1.status_1_regx.wrd_len = SMPL_WIDTH_24BITS; } else { ch_stat1.status_1_regx.max_wrd_len = 0; ch_stat1.status_1_regx.wrd_len = 0; } had_write_register(AUD_CH_STATUS_1, ch_stat1.status_1_regval); buf_cfg.buf_cfg_regx.fifo_width = FIFO_THRESHOLD; buf_cfg.buf_cfg_regx.aud_delay = 0; had_write_register(AUD_BUF_CONFIG, buf_cfg.buf_cfgval); channels = substream->runtime->channels; switch (channels) { case 1: case 2: cfg_val.cfg_regx.num_ch = CH_STEREO; cfg_val.cfg_regx.layout = LAYOUT0; break; case 3: case 4: cfg_val.cfg_regx.num_ch = CH_THREE_FOUR; cfg_val.cfg_regx.layout = LAYOUT1; break; case 5: case 6: cfg_val.cfg_regx.num_ch = CH_FIVE_SIX; cfg_val.cfg_regx.layout = LAYOUT1; break; case 7: case 8: cfg_val.cfg_regx.num_ch = CH_SEVEN_EIGHT; cfg_val.cfg_regx.layout = LAYOUT1; break; } cfg_val.cfg_regx.val_bit = 1; had_write_register(AUD_CONFIG, cfg_val.cfg_regval); return 0; } /** * snd_intelhad_prog_dip - to initialize Data Island Packets registers * * @substream:substream for which the prepare function is called * @intelhaddata:substream private data * * This function is called in the prepare callback */ static void snd_intelhad_prog_dip(struct snd_pcm_substream *substream, struct snd_intelhad *intelhaddata, int flag_silence) { int i; union aud_ctrl_st ctrl_state = {.ctrl_val = 0}; union aud_info_frame2 frame2 = {.fr2_val = 0}; union aud_info_frame3 frame3 = {.fr3_val = 0}; u8 checksum = 0; had_write_register(AUD_CNTL_ST, ctrl_state.ctrl_val); frame2.fr2_regx.chnl_cnt = substream->runtime->channels - 1; /*TODO: Read from intelhaddata->eeld.speaker_allocation_block;*/ frame3.fr3_regx.chnl_alloc = CHANNEL_ALLOCATION; /*Calculte the byte wide checksum for all valid DIP words*/ for (i = 0; i < BYTES_PER_WORD; i++) checksum += (INFO_FRAME_WORD1 >> i*BITS_PER_BYTE) & MASK_BYTE0; for (i = 0; i < BYTES_PER_WORD; i++) checksum += (frame2.fr2_val >> i*BITS_PER_BYTE) & MASK_BYTE0; for (i = 0; i < BYTES_PER_WORD; i++) checksum += (frame3.fr3_val >> i*BITS_PER_BYTE) & MASK_BYTE0; frame2.fr2_regx.chksum = -(checksum); had_write_register(AUD_HDMIW_INFOFR, INFO_FRAME_WORD1); had_write_register(AUD_HDMIW_INFOFR, frame2.fr2_val); had_write_register(AUD_HDMIW_INFOFR, frame3.fr3_val); /* program remaining DIP words with zero */ for (i = 0; i < HAD_MAX_DIP_WORDS-VALID_DIP_WORDS; i++) had_write_register(AUD_HDMIW_INFOFR, 0x0); ctrl_state.ctrl_regx.dip_freq = 1; ctrl_state.ctrl_regx.dip_en_sta = 1; had_write_register(AUD_CNTL_ST, ctrl_state.ctrl_val); } /** * snd_intelhad_prog_buffer - programs buffer * address and length registers * * @substream:substream for which the prepare function is called * @intelhaddata:substream private data * * This function programs ring buffer address and length into registers. */ int snd_intelhad_prog_buffer(struct snd_intelhad *intelhaddata, int start, int end) { u32 ring_buf_addr, ring_buf_size, period_bytes; u8 i, num_periods; struct snd_pcm_substream *substream; substream = intelhaddata->stream_info.had_substream; if (!substream) { pr_err("substream is NULL\n"); dump_stack(); return 0; } ring_buf_addr = substream->runtime->dma_addr; ring_buf_size = snd_pcm_lib_buffer_bytes(substream); intelhaddata->stream_info.ring_buf_size = ring_buf_size; period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size); num_periods = substream->runtime->periods; /* buffer addr should be 64 byte aligned, period bytes will be used to calculate addr offset*/ period_bytes &= ~0x3F; /* Hardware supports MAX_PERIODS buffers */ if (end >= HAD_MAX_PERIODS) return -EINVAL; for (i = start; i <= end; i++) { /* Program the buf registers with addr and len */ intelhaddata->buf_info[i].buf_addr = ring_buf_addr + (i * period_bytes); if (i < num_periods-1) intelhaddata->buf_info[i].buf_size = period_bytes; else intelhaddata->buf_info[i].buf_size = ring_buf_size - (period_bytes*i); had_write_register(AUD_BUF_A_ADDR + (i * HAD_REG_WIDTH), intelhaddata->buf_info[i].buf_addr | BIT(0) | BIT(1)); had_write_register(AUD_BUF_A_LENGTH + (i * HAD_REG_WIDTH), period_bytes); intelhaddata->buf_info[i].is_valid = true; } pr_debug("%s:buf[%d-%d] addr=%#x and size=%d\n", __func__, start, end, intelhaddata->buf_info[start].buf_addr, intelhaddata->buf_info[start].buf_size); intelhaddata->valid_buf_cnt = num_periods; return 0; } inline int snd_intelhad_read_len(struct snd_intelhad *intelhaddata) { int i, retval = 0; u32 len[4]; for (i = 0; i < 4 ; i++) { had_read_register(AUD_BUF_A_LENGTH + (i * HAD_REG_WIDTH), &len[i]); if (!len[i]) retval++; } if (retval != 1) { for (i = 0; i < 4 ; i++) pr_debug("buf[%d] size=%d\n", i, len[i]); } return retval; } /** * snd_intelhad_prog_cts - Program HDMI audio CTS value * * @aud_samp_freq: sampling frequency of audio data * @tmds: sampling frequency of the display data * @n_param: N value, depends on aud_samp_freq * @intelhaddata:substream private data * * Program CTS register based on the audio and display sampling frequency */ static void snd_intelhad_prog_cts(u32 aud_samp_freq, u32 tmds, u32 n_param, struct snd_intelhad *intelhaddata) { u32 cts_val; u64 dividend, divisor; /* Calculate CTS according to HDMI 1.3a spec*/ dividend = (u64)tmds * n_param*1000; divisor = 128 * aud_samp_freq; cts_val = div64_u64(dividend, divisor); pr_debug("TMDS value=%d, N value=%d, CTS Value=%d\n", tmds, n_param, cts_val); had_write_register(AUD_HDMI_CTS, (BIT(20) | cts_val)); } /** * snd_intelhad_prog_n - Program HDMI audio N value * * @aud_samp_freq: sampling frequency of audio data * @n_param: N value, depends on aud_samp_freq * @intelhaddata:substream private data * * This function is called in the prepare callback. * It programs based on the audio and display sampling frequency */ static int snd_intelhad_prog_n(u32 aud_samp_freq, u32 *n_param, struct snd_intelhad *intelhaddata) { u32 n_val; int retval = 0; /* Select N according to HDMI 1.3a spec*/ switch (aud_samp_freq) { case AUD_SAMPLE_RATE_32: n_val = 4096; break; case AUD_SAMPLE_RATE_44_1: n_val = 6272; break; case AUD_SAMPLE_RATE_48: n_val = 6144; break; case AUD_SAMPLE_RATE_88_2: n_val = 12544; break; case AUD_SAMPLE_RATE_96: n_val = 12288; break; case AUD_SAMPLE_RATE_176_4: n_val = 25088; break; case HAD_MAX_RATE: n_val = 24576; break; default: retval = -EINVAL; break; } if (retval) return retval; had_write_register(AUD_N_ENABLE, (BIT(20) | n_val)); *n_param = n_val; return retval; } /** * snd_intelhad_open - stream initializations are done here * @substream:substream for which the stream function is called * * This function is called whenever a PCM stream is opened */ static int snd_intelhad_open(struct snd_pcm_substream *substream) { struct snd_intelhad *intelhaddata; struct snd_pcm_runtime *runtime; struct had_stream_pvt *stream; struct had_pvt_data *had_stream; int retval; pr_debug("snd_intelhad_open called\n"); intelhaddata = snd_pcm_substream_chip(substream); had_stream = intelhaddata->private_data; /* * HDMI driver might suspend the device already, * so we return it on */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { pr_err("HDMI device can't be turned on\n"); return -ENODEV; } if (had_get_hwstate(intelhaddata)) { pr_err("%s: HDMI cable plugged-out\n", __func__); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return -ENODEV; } runtime = substream->runtime; /* Check, if device already in use */ if (runtime->private_data) { pr_err("Device already in use\n"); ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); return -EBUSY; } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); /* set the runtime hw parameter with local snd_pcm_hardware struct */ runtime->hw = snd_intel_hadstream; stream = kzalloc(sizeof(*stream), GFP_KERNEL); if (!stream) { retval = -ENOMEM; goto exit_err; } stream->stream_status = STREAM_INIT; runtime->private_data = stream; retval = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (retval < 0) { kfree(stream); goto exit_err; } /* Make sure, that the period size is always aligned * 64byte boundary */ retval = snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64); if (retval < 0) { pr_err("%s:step_size=64 failed,err=%d\n", __func__, retval); kfree(stream); goto exit_err; } return retval; exit_err: runtime->private_data = NULL; return retval; } /** * had_period_elapsed - updates the hardware pointer status * @had_substream:substream for which the stream function is called * */ static void had_period_elapsed(void *had_substream) { struct snd_pcm_substream *substream = had_substream; struct had_stream_pvt *stream; if (!substream || !substream->runtime) return; stream = substream->runtime->private_data; if (!stream) return; if (stream->stream_status != STREAM_RUNNING) return; snd_pcm_period_elapsed(substream); return; } /** * snd_intelhad_init_stream - internal function to initialize stream info * @substream:substream for which the stream function is called * */ static int snd_intelhad_init_stream(struct snd_pcm_substream *substream) { struct snd_intelhad *intelhaddata = snd_pcm_substream_chip(substream); pr_debug("setting buffer ptr param\n"); intelhaddata->stream_info.period_elapsed = had_period_elapsed; intelhaddata->stream_info.had_substream = substream; intelhaddata->stream_info.buffer_ptr = 0; intelhaddata->stream_info.buffer_rendered = 0; intelhaddata->stream_info.sfreq = substream->runtime->rate; return 0; } /** * snd_intelhad_close- to free parameteres when stream is stopped * * @substream: substream for which the function is called * * This function is called by ALSA framework when stream is stopped */ static int snd_intelhad_close(struct snd_pcm_substream *substream) { struct snd_intelhad *intelhaddata; struct snd_pcm_runtime *runtime; pr_debug("snd_intelhad_close called\n"); intelhaddata = snd_pcm_substream_chip(substream); runtime = substream->runtime; intelhaddata->stream_info.buffer_rendered = 0; intelhaddata->stream_info.buffer_ptr = 0; intelhaddata->stream_info.str_id = 0; intelhaddata->stream_info.had_substream = NULL; /* Check if following drv_status modification is required - VA */ if (intelhaddata->drv_status != HAD_DRV_DISCONNECTED) intelhaddata->drv_status = HAD_DRV_CONNECTED; kfree(runtime->private_data); runtime->private_data = NULL; return 0; } /** * snd_intelhad_hw_params- to setup the hardware parameters * like allocating the buffers * * @substream: substream for which the function is called * @hw_params: hardware parameters * * This function is called by ALSA framework when hardware params are set */ static int snd_intelhad_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { unsigned long addr; int pages, buf_size, retval; BUG_ON(!hw_params); buf_size = params_buffer_bytes(hw_params); retval = snd_pcm_lib_malloc_pages(substream, buf_size); if (retval < 0) return retval; pr_debug("%s:allocated memory = %d\n", __func__, buf_size); /* mark the pages as uncached region */ addr = (unsigned long) substream->runtime->dma_area; pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / PAGE_SIZE; retval = set_memory_uc(addr, pages); if (retval) { pr_err("set_memory_uc failed.Error:%d\n", retval); return retval; } memset(substream->runtime->dma_area, 0, buf_size); return retval; } /** * snd_intelhad_hw_free- to release the resources allocated during * hardware params setup * * @substream: substream for which the function is called * * This function is called by ALSA framework before close callback. * */ static int snd_intelhad_hw_free(struct snd_pcm_substream *substream) { unsigned long addr; u32 pages; pr_debug("snd_intelhad_hw_free called\n"); /* mark back the pages as cached/writeback region before the free */ addr = (unsigned long) substream->runtime->dma_area; pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / PAGE_SIZE; set_memory_wb(addr, pages); return snd_pcm_lib_free_pages(substream); }
void mdfld_panel_generic_dsi_dbi_update_fb( struct mdfld_dsi_dbi_output *dbi_output, int pipe) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); struct drm_device *dev = dbi_output->dev; struct drm_psb_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = dbi_output->base.base.crtc; struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; u32 dpll_reg = MRST_DPLL_A; u32 dspcntr_reg = DSPACNTR; u32 pipeconf_reg = PIPEACONF; u32 dsplinoff_reg = DSPALINOFF; u32 dspsurf_reg = DSPASURF; if (!dev_priv->dsi_init_done) return; /* 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)) || !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) return; if (pipe == 2) { dspcntr_reg = DSPCCNTR; pipeconf_reg = PIPECCONF; dsplinoff_reg = DSPCLINOFF; dspsurf_reg = DSPCSURF; } if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return; } /* check DBI FIFO status */ if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) { goto update_fb_out0; } /* refresh plane changes */ REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); REG_READ(dspsurf_reg); mdfld_dsi_send_dcs(sender, write_mem_start, NULL, 0, CMD_DATA_SRC_PIPE, MDFLD_DSI_SEND_PACKAGE); dbi_output->dsr_fb_update_done = true; update_fb_out0: ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); }
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; }
bool ps_hdmi_power_islands_on() { return ospm_power_using_hw_begin( OSPM_DISPLAY_B | OSPM_DISPLAY_HDMI, OSPM_UHB_FORCE_POWER_ON); }
static void mdfld_h8c7_dsi_controller_init(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_hw_context *hw_ctx = &dsi_config->dsi_hw_context; struct drm_device *dev = dsi_config->dev; struct csc_setting csc = { .pipe = 0, .type = CSC_REG_SETTING, .enable_state = true, .data_len = CSC_REG_COUNT, .data.csc_reg_data = { 0xFFB0424, 0xFDF, 0x4320FF1, 0xFDC, 0xFF50FF5, 0x415} }; struct gamma_setting gamma = { .pipe = 0, .type = GAMMA_REG_SETTING, .enable_state = true, .data_len = GAMMA_10_BIT_TABLE_COUNT, .gamma_tableX100 = { 0x000000, 0x030303, 0x050505, 0x070707, 0x090909, 0x0C0C0C, 0x0E0E0E, 0x101010, 0x121212, 0x141414, 0x171717, 0x191919, 0x1B1B1B, 0x1D1D1D, 0x1F1F1F, 0x212121, 0x232323, 0x252525, 0x282828, 0x2A2A2A, 0x2C2C2C, 0x2E2E2E, 0x303030, 0x323232, 0x343434, 0x363636, 0x383838, 0x3A3A3A, 0x3C3C3C, 0x3E3E3E, 0x404040, 0x424242, 0x444444, 0x464646, 0x484848, 0x4A4A4A, 0x4C4C4C, 0x4E4E4E, 0x505050, 0x525252, 0x545454, 0x565656, 0x585858, 0x5A5A5A, 0x5C5C5C, 0x5E5E5E, 0x606060, 0x626262, 0x646464, 0x666666, 0x686868, 0x6A6A6A, 0x6C6C6C, 0x6E6E6E, 0x707070, 0x727272, 0x747474, 0x767676, 0x787878, 0x7A7A7A, 0x7C7C7C, 0x7E7E7E, 0x808080, 0x828282, 0x848484, 0x868686, 0x888888, 0x8A8A8A, 0x8C8C8C, 0x8E8E8E, 0x909090, 0x929292, 0x949494, 0x969696, 0x989898, 0x999999, 0x9B9B9B, 0x9D9D9D, 0x9F9F9F, 0xA1A1A1, 0xA3A3A3, 0xA5A5A5, 0xA7A7A7, 0xA9A9A9, 0xABABAB, 0xADADAD, 0xAFAFAF, 0xB1B1B1, 0xB3B3B3, 0xB5B5B5, 0xB6B6B6, 0xB8B8B8, 0xBABABA, 0xBCBCBC, 0xBEBEBE, 0xC0C0C0, 0xC2C2C2, 0xC4C4C4, 0xC6C6C6, 0xC8C8C8, 0xCACACA, 0xCCCCCC, 0xCECECE, 0xCFCFCF, 0xD1D1D1, 0xD3D3D3, 0xD5D5D5, 0xD7D7D7, 0xD9D9D9, 0xDBDBDB, 0xDDDDDD, 0xDFDFDF, 0xE1E1E1, 0xE3E3E3, 0xE4E4E4, 0xE6E6E6, 0xE8E8E8, 0xEAEAEA, 0xECECEC, 0xEEEEEE, 0xF0F0F0, 0xF2F2F2, 0xF4F4F4, 0xF6F6F6, 0xF7F7F7, 0xF9F9F9, 0xFBFBFB, 0xFDFDFD} }; PSB_DEBUG_ENTRY("\n"); /*reconfig lane configuration*/ dsi_config->lane_count = 3; dsi_config->lane_config = MDFLD_DSI_DATA_LANE_3_1; dsi_config->enable_gamma_csc = ENABLE_GAMMA | ENABLE_CSC; /* This is for 400 mhz. Set it to 0 for 800mhz */ hw_ctx->cck_div = 1; hw_ctx->pll_bypass_mode = 0; hw_ctx->mipi_control = 0x00; hw_ctx->intr_en = 0xffffffff; hw_ctx->hs_tx_timeout = 0xffffff; hw_ctx->lp_rx_timeout = 0xffffff; hw_ctx->turn_around_timeout = 0x1f; hw_ctx->device_reset_timer = 0xffff; hw_ctx->high_low_switch_count = 0x20; hw_ctx->init_count = 0xf0; hw_ctx->eot_disable = 0x3; hw_ctx->lp_byteclk = 0x4; hw_ctx->clk_lane_switch_time_cnt = 0x20000E; hw_ctx->hs_ls_dbi_enable = 0x0; /* HW team suggested 1390 for bandwidth setting */ hw_ctx->dbi_bw_ctrl = 1390; hw_ctx->dphy_param = 0x20124E1A; hw_ctx->dsi_func_prg = (0xa000 | dsi_config->lane_count); hw_ctx->mipi = TE_TRIGGER_GPIO_PIN; hw_ctx->mipi |= dsi_config->lane_config; if (dsi_config->enable_gamma_csc & ENABLE_CSC) { /* setting the tuned csc setting */ drm_psb_enable_color_conversion = 1; mdfld_intel_crtc_set_color_conversion(dev, &csc); } if (dsi_config->enable_gamma_csc & ENABLE_GAMMA) { /* setting the tuned gamma setting */ drm_psb_enable_gamma = 1; mdfld_intel_crtc_set_gamma(dev, &gamma); } } static struct drm_display_mode *h8c7_cmd_get_config_mode(void) { struct drm_display_mode *mode; PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; mode->htotal = 920; mode->hdisplay = 720; mode->hsync_start = 816; mode->hsync_end = 824; mode->vtotal = 1300; mode->vdisplay = 1280; mode->vsync_start = 1294; mode->vsync_end = 1296; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; mode->type |= DRM_MODE_TYPE_PREFERRED; PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay); PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay); PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start); PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end); PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal); PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start); PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end); PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal); PSB_DEBUG_ENTRY("clock is %d\n", mode->clock); drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); return mode; } static int mdfld_dsi_h8c7_cmd_power_on(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; int enable_err, enabled = 0; PSB_DEBUG_ENTRY("\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } if (!IS_ERR(h8c7_regulator_status.regulator)) { if (!h8c7_regulator_status.h8c7_mmc2_on) { PSB_DEBUG_ENTRY("Before power on, regulator is %d\n", regulator_is_enabled(h8c7_regulator_status.regulator)); PSB_DEBUG_ENTRY("Begin to power on\n"); h8c7_regulator_status.h8c7_mmc2_on = true; } else { DRM_ERROR("power on several times without off\n"); } enabled = regulator_is_enabled(h8c7_regulator_status.regulator); enable_err = regulator_enable(h8c7_regulator_status.regulator); if (enable_err < 0) { regulator_put(h8c7_regulator_status.regulator); DRM_ERROR("FATAL:enable h8c7 regulator error\n"); } /* vemmc2 need 50ms delay due to stability ** If already enabled, no need to wait for this delay. ** This code isn't race proof but since in addition to ** this panel driver only touch driver is enabling this ** regulator and does it after this function has been ** finished, this code works well enough for now. */ if (!enabled) msleep(50); PSB_DEBUG_ENTRY("After power on, regulator is %d\n", regulator_is_enabled(h8c7_regulator_status.regulator)); } /*exit sleep */ err = mdfld_dsi_send_dcs(sender, exit_sleep_mode, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("faild to exit_sleep mode\n"); goto power_err; } msleep(120); /*set tear on*/ err = mdfld_dsi_send_dcs(sender, set_tear_on, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("faild to set_tear_on mode\n"); goto power_err; } /*turn on display*/ err = mdfld_dsi_send_dcs(sender, set_display_on, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("faild to set_display_on mode\n"); goto power_err; } if (drm_psb_enable_cabc) { /* turn on cabc */ h8c7_disable_cabc[1] = 0x2; mdfld_dsi_send_mcs_long_hs(sender, h8c7_disable_cabc, sizeof(h8c7_disable_cabc), 0); mdelay(5); mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_off, 4, 0); mdfld_dsi_send_mcs_long_hs(sender, h8c7_set_cabc_gain, 10, 0); mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_on, 4, 0); DRM_INFO("%s enable h8c7 cabc\n", __func__); } power_err: return err; } static int mdfld_dsi_h8c7_cmd_power_off(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; PSB_DEBUG_ENTRY("\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } /* turn off cabc */ h8c7_disable_cabc[1] = 0x0; mdfld_dsi_send_mcs_long_lp(sender, h8c7_disable_cabc, sizeof(h8c7_disable_cabc), 0); /*turn off backlight*/ err = mdfld_dsi_send_mcs_long_lp(sender, h8c7_turn_off_backlight, sizeof(h8c7_turn_off_backlight), 0); if (err) { DRM_ERROR("%s: failed to turn off backlight\n", __func__); goto out; } mdelay(1); /*turn off display */ err = mdfld_dsi_send_dcs(sender, set_display_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("sent set_display_off faild\n"); goto out; } /*set tear off */ err = mdfld_dsi_send_dcs(sender, set_tear_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("sent set_tear_off faild\n"); goto out; } /*Enter sleep mode */ err = mdfld_dsi_send_dcs(sender, enter_sleep_mode, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("DCS 0x%x sent failed\n", enter_sleep_mode); goto out; } /** * MIPI spec shows it must wait 5ms * before sneding next command */ mdelay(5); /*enter deep standby mode*/ err = mdfld_dsi_send_mcs_long_lp(sender, h8c7_mcs_protect_off, 4, 0); if (err) { DRM_ERROR("Failed to turn off protection\n"); goto out; } err = mdfld_dsi_send_mcs_long_lp(sender, h8c7_set_power_dstb, 14, 0); if (err) DRM_ERROR("Failed to enter DSTB\n"); mdelay(5); mdfld_dsi_send_mcs_long_lp(sender, h8c7_mcs_protect_on, 4, 0); out: if (!IS_ERR(h8c7_regulator_status.regulator)) { if (h8c7_regulator_status.h8c7_mmc2_on) { h8c7_regulator_status.h8c7_mmc2_on = false; PSB_DEBUG_GENERAL("Begin to power off\n"); } else DRM_ERROR("power off several times without on\n"); regulator_disable(h8c7_regulator_status.regulator); PSB_DEBUG_GENERAL("After power off, regulator is %d\n", regulator_is_enabled(h8c7_regulator_status.regulator)); } return err; } static void h8c7_cmd_get_panel_info(int pipe, struct panel_info *pi) { PSB_DEBUG_ENTRY("\n"); if (pipe == 0) { pi->width_mm = PANEL_4DOT3_WIDTH; pi->height_mm = PANEL_4DOT3_HEIGHT; } } static int mdfld_dsi_h8c7_cmd_detect(struct mdfld_dsi_config *dsi_config) { int status; struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; u32 dpll_val, device_ready_val; int pipe = dsi_config->pipe; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); PSB_DEBUG_ENTRY("\n"); if (pipe == 0) { /* * FIXME: WA to detect the panel connection status, and need to * implement detection feature with get_power_mode DSI command. */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return -EAGAIN; } dpll_val = REG_READ(regs->dpll_reg); device_ready_val = REG_READ(regs->device_ready_reg); if ((device_ready_val & DSI_DEVICE_READY) && (dpll_val & DPLL_VCO_ENABLE)) { dsi_config->dsi_hw_context.panel_on = true; mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_off, 4, 0); mdfld_dsi_send_gen_long_hs(sender, h8c7_set_disp_reg, 13, 0); mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_on, 4, 0); } else { dsi_config->dsi_hw_context.panel_on = false; DRM_INFO("%s: panel is not initialized!\n", __func__); } status = MDFLD_DSI_PANEL_CONNECTED; ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } else { DRM_INFO("%s: do NOT support dual panel\n", __func__); status = MDFLD_DSI_PANEL_DISCONNECTED; } return status; }
static void gi_renesas_dsi_controller_init(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_hw_context *hw_ctx = &dsi_config->dsi_hw_context; struct drm_device *dev = dsi_config->dev; struct csc_setting csc = { .pipe = 0, .type = CSC_REG_SETTING, .enable_state = true, .data_len = CSC_REG_COUNT, .data.csc_reg_data = { 0xF510486, 0x27, 0x3F10FD0, 0x3E, 0x51000F, 0x39F} }; struct gamma_setting gamma = { .pipe = 0, .type = GAMMA_REG_SETTING, .enable_state = true, .data_len = GAMMA_10_BIT_TABLE_COUNT, .gamma_tableX100 = { 0x000000, 0x010101, 0x020202, 0x030303, 0x040404, 0x050505, 0x060606, 0x070807, 0x080908, 0x0A0B0A, 0x0B0C0B, 0x0D0D0D, 0x0E0F0E, 0x0F100F, 0x111211, 0x121312, 0x141514, 0x151715, 0x171817, 0x191A19, 0x1A1C1A, 0x1C1D1C, 0x1D1F1D, 0x1F211F, 0x212221, 0x222422, 0x242624, 0x262726, 0x272928, 0x292B29, 0x2B2D2B, 0x2D2F2D, 0x2E302F, 0x303230, 0x323432, 0x343634, 0x363836, 0x383A38, 0x393B39, 0x3B3D3B, 0x3D3F3D, 0x3F413F, 0x414341, 0x434543, 0x454745, 0x474947, 0x494B49, 0x4B4D4B, 0x4C4F4D, 0x4E514F, 0x505351, 0x525552, 0x545754, 0x565956, 0x585B58, 0x5A5D5A, 0x5C5F5D, 0x5E615F, 0x606361, 0x636563, 0x656765, 0x676967, 0x696B69, 0x6B6D6B, 0x6D6F6D, 0x6F716F, 0x717371, 0x737573, 0x757775, 0x777A78, 0x7A7C7A, 0x7C7E7C, 0x7E807E, 0x808280, 0x828482, 0x848684, 0x868887, 0x898B89, 0x8B8D8B, 0x8D8F8D, 0x8F918F, 0x919391, 0x949594, 0x969896, 0x989A98, 0x9A9C9A, 0x9D9E9D, 0x9FA09F, 0xA1A3A1, 0xA3A5A3, 0xA5A7A6, 0xA8A9A8, 0xAAACAA, 0xACAEAC, 0xAFB0AF, 0xB1B2B1, 0xB3B5B3, 0xB5B7B5, 0xB8B9B8, 0xBABBBA, 0xBCBEBC, 0xBFC0BF, 0xC1C2C1, 0xC3C5C3, 0xC6C7C6, 0xC8C9C8, 0xCACBCA, 0xCDCECD, 0xCFD0CF, 0xD1D2D1, 0xD4D5D4, 0xD6D7D6, 0xD8D9D8, 0xDBDCDB, 0xDDDEDD, 0xE0E0E0, 0xE2E3E2, 0xE4E5E4, 0xE7E7E7, 0xE9EAE9, 0xECECEC, 0xEEEEEE, 0xF0F1F0, 0xF3F3F3, 0xF5F5F5, 0xF8F8F8, 0xFAFAFA, 0xFDFDFD} }; PSB_DEBUG_ENTRY("\n"); dsi_config->lane_count = 1; dsi_config->lane_config = MDFLD_DSI_DATA_LANE_2_2; dsi_config->enable_gamma_csc = ENABLE_GAMMA | ENABLE_CSC; hw_ctx->pll_bypass_mode = 1; hw_ctx->cck_div = 1; hw_ctx->mipi_control = 0x00; hw_ctx->intr_en = 0xffffffff; hw_ctx->hs_tx_timeout = 0xffffff; hw_ctx->lp_rx_timeout = 0xffffff; hw_ctx->turn_around_timeout = 0x14; hw_ctx->device_reset_timer = 0xffff; hw_ctx->high_low_switch_count = 0x28; hw_ctx->init_count = 0xf0; hw_ctx->eot_disable = 0x2; hw_ctx->hs_ls_dbi_enable = 0x0; hw_ctx->lp_byteclk = 0x0; hw_ctx->clk_lane_switch_time_cnt = 0xa0014; hw_ctx->dphy_param = 0x150a600f; hw_ctx->dbi_bw_ctrl = 0x820; hw_ctx->mipi = PASS_FROM_SPHY_TO_AFE | TE_TRIGGER_GPIO_PIN; hw_ctx->mipi |= dsi_config->lane_config; /*set up func_prg*/ hw_ctx->dsi_func_prg = (0xa000 | dsi_config->lane_count); if (dsi_config->enable_gamma_csc & ENABLE_CSC) { /* setting the tuned csc setting */ drm_psb_enable_color_conversion = 1; mdfld_intel_crtc_set_color_conversion(dev, &csc); } if (dsi_config->enable_gamma_csc & ENABLE_GAMMA) { /* setting the tuned gamma setting */ drm_psb_enable_gamma = 1; mdfld_intel_crtc_set_gamma(dev, &gamma); } } static struct drm_display_mode *gi_renesas_cmd_get_config_mode(void) { struct drm_display_mode *mode; PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; mode->hdisplay = 320; mode->vdisplay = 480; /* HFP = 10, HSYNC = 10, HBP = 20 */ mode->hsync_start = mode->hdisplay + 10; mode->hsync_end = mode->hsync_start + 10; mode->htotal = mode->hsync_end + 20; /* VFP = 10, VSYNC = 2, VBP = 20 */ mode->vsync_start = mode->vdisplay + 10; mode->vsync_end = mode->vsync_start + 2; mode->vtotal = mode->vsync_end + 10; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); mode->type |= DRM_MODE_TYPE_PREFERRED; return mode; } static int __gi_renesas_dsi_power_on(struct mdfld_dsi_config *dsi_config) { struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; PSB_DEBUG_ENTRY("\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } if (drm_psb_enable_cabc) { /* enable cabc */ gi_er61529_backlight_cntr_1[1] = 0x01; mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_backlight_cntr_1, 21, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); } mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_backlight_cntr, 5, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_exit_sleep_mode, 1, 0); mdelay(120); mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_set_tear_on, 2, 0); mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_dcs_set_display_on, 1, 0); return err; } static int __gi_renesas_dsi_power_off(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; PSB_DEBUG_ENTRY("Turn off video mode TMD panel...\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } /* turn off display */ err = mdfld_dsi_send_dcs(sender, set_display_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("%s - sent set_display_off faild\n", __func__); goto power_err; } mdelay(70); /* set tear off display */ err = mdfld_dsi_send_dcs(sender, set_tear_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("%s - sent set_tear_off faild\n", __func__); goto power_err; } /* disable CABC */ gi_er61529_backlight_cntr_1[1] = 0x00; mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_backlight_cntr_1, 21, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); err = mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_enter_sleep_mode, 1, 0); if (err) { DRM_ERROR("Enter sleep mode error\n"); goto power_err; } mdelay(120); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_lp_mode_cntr, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); power_err: return err; } static void gi_renesas_cmd_get_panel_info(int pipe, struct panel_info *pi) { if (pipe == 0) { pi->width_mm = PANEL_3DOT47_WIDTH; pi->height_mm = PANEL_3DOT47_HEIGHT; } } static int gi_renesas_dsi_cmd_detect(struct mdfld_dsi_config *dsi_config) { struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; int status; int pipe = dsi_config->pipe; uint32_t dpll_val, device_ready_val; PSB_DEBUG_ENTRY("\n"); if (pipe == 0) { if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return -EAGAIN; } dpll_val = REG_READ(regs->dpll_reg); device_ready_val = REG_READ(regs->device_ready_reg); if ((device_ready_val & DSI_DEVICE_READY) && (dpll_val & DPLL_VCO_ENABLE)) { dsi_config->dsi_hw_context.panel_on = true; status = MDFLD_DSI_PANEL_CONNECTED; } else { dsi_config->dsi_hw_context.panel_on = false; status = MDFLD_DSI_PANEL_DISCONNECTED; DRM_INFO("%s: do NOT support dual panel\n", __func__); } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } else { PSB_DEBUG_ENTRY("Only support single panel\n"); status = MDFLD_DSI_PANEL_DISCONNECTED; dsi_config->dsi_hw_context.panel_on = 0; } return 0; } static int gi_renesas_dsi_cmd_set_brightness(struct mdfld_dsi_config *dsi_config, int level) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); u8 backlight_val; PSB_DEBUG_ENTRY("Set brightness level %d...\n", level); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } backlight_val = level * 255 / 100; gi_er61529_set_backlight[2] = backlight_val; mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_set_backlight, 5, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); return 0; } static int gi_renesas_dsi_panel_reset(struct mdfld_dsi_config *dsi_config) { static int mipi_reset_gpio; int ret = 0; PSB_DEBUG_ENTRY("\n"); if (mipi_reset_gpio == 0) { ret = get_gpio_by_name("mipi-reset"); if (ret < 0) { DRM_ERROR("Faild to get panel reset gpio, " \ "use default reset pin\n"); ret = 128; } mipi_reset_gpio = ret; ret = gpio_request(mipi_reset_gpio, "mipi_display"); if (ret) { DRM_ERROR("Faild to request panel reset gpio\n"); return -EINVAL; } gpio_direction_output(mipi_reset_gpio, 0); } gpio_set_value_cansleep(mipi_reset_gpio, 0); mdelay(11); gpio_set_value_cansleep(mipi_reset_gpio, 1); mdelay(20); return 0; } void gi_renesas_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) { p_funcs->get_config_mode = gi_renesas_cmd_get_config_mode; p_funcs->get_panel_info = gi_renesas_cmd_get_panel_info; p_funcs->reset = gi_renesas_dsi_panel_reset; p_funcs->drv_ic_init = gi_renesas_dbi_ic_init; p_funcs->dsi_controller_init = gi_renesas_dsi_controller_init; p_funcs->detect = gi_renesas_dsi_cmd_detect; p_funcs->set_brightness = gi_renesas_dsi_cmd_set_brightness; p_funcs->power_on = __gi_renesas_dsi_power_on; p_funcs->power_off = __gi_renesas_dsi_power_off; }