static struct panel_funcs *dsi_config_to_p_func( struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_encoder *encoder; struct mdfld_dsi_dpi_output *dpi_output; struct mdfld_dsi_dbi_output *dbi_output; struct panel_funcs *p_funcs = NULL; if (!dsi_config) return NULL; encoder = dsi_config->encoders[dsi_config->type]; if (!encoder) return NULL; if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) { dbi_output = MDFLD_DSI_DBI_OUTPUT(encoder); p_funcs = dbi_output ? dbi_output->p_funcs : NULL; } else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) { dpi_output = MDFLD_DSI_DPI_OUTPUT(encoder); p_funcs = dpi_output ? dpi_output->p_funcs : NULL; } return p_funcs; }
static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder *dsi_encoder, int pipe) { struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; if (dev_priv->dpi_panel_on[pipe]) { dev_err(dev->dev, "DPI panel is already on\n"); return; } /* For resume path sequence */ mdfld_dsi_dpi_shut_down(dpi_output, pipe); dsi_set_device_ready_state(dev, 0, pipe); dsi_set_device_ready_state(dev, 1, pipe); tc35876x_set_bridge_reset_state(dev, 0); tc35876x_configure_lvds_bridge(dev); mdfld_dsi_dpi_turn_on(dpi_output, pipe); /* Send turn on command */ dsi_set_pipe_plane_enable_state(dev, 1, pipe); }
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; }
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_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_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; u32 mipi_reg = MIPI; u32 pipeconf_reg = PIPEACONF; if(pipe) { mipi_reg = MIPI_C; pipeconf_reg = PIPECCONF; } /* Start up display island if it was shutdown */ if (!gma_power_begin(dev, true)) return; if(on) { if (mdfld_get_panel_type(dev, pipe) == TMD_VID){ mdfld_dsi_dpi_turn_on(dpi_output, pipe); } else { /* Enable mipi port */ REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31))); REG_READ(mipi_reg); mdfld_dsi_dpi_turn_on(dpi_output, pipe); mdfld_dsi_tpo_ic_init(dsi_config, pipe); } if(pipe == 2) { dev_priv->dpi_panel_on2 = true; } else { dev_priv->dpi_panel_on = true; } } else { if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { mdfld_dsi_dpi_shut_down(dpi_output, pipe); } else { mdfld_dsi_dpi_shut_down(dpi_output, pipe); /* Disable mipi port */ REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31))); REG_READ(mipi_reg); } if(pipe == 2) dev_priv->dpi_panel_on2 = false; else dev_priv->dpi_panel_on = false; } gma_power_end(dev); }
static void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) { struct mdfld_dsi_encoder *dsi_encoder; struct mdfld_dsi_dpi_output *dpi_output; PSB_DEBUG_ENTRY("\n"); dsi_encoder = MDFLD_DSI_ENCODER(encoder); dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); /*Everything is ready, commit DSI hw context to HW*/ __mdfld_dsi_dpi_set_power(encoder, true); dpi_output->first_boot = 0; }
static 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_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_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; /*start up display island if it was shutdown*/ if (!gma_power_begin(dev, true)) return; if (on) { if (mdfld_get_panel_type(dev, pipe) == TMD_VID) mdfld_dsi_dpi_turn_on(dpi_output, pipe); else if (mdfld_get_panel_type(dev, pipe) == TC35876X) mdfld_dsi_configure_up(dsi_encoder, pipe); else { /*enable mipi port*/ REG_WRITE(MIPI_PORT_CONTROL(pipe), REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31)); REG_READ(MIPI_PORT_CONTROL(pipe)); mdfld_dsi_dpi_turn_on(dpi_output, pipe); mdfld_dsi_tpo_ic_init(dsi_config, pipe); } dev_priv->dpi_panel_on[pipe] = true; } else { if (mdfld_get_panel_type(dev, pipe) == TMD_VID) mdfld_dsi_dpi_shut_down(dpi_output, pipe); else if (mdfld_get_panel_type(dev, pipe) == TC35876X) mdfld_dsi_configure_down(dsi_encoder, pipe); else { mdfld_dsi_dpi_shut_down(dpi_output, pipe); /*disable mipi port*/ REG_WRITE(MIPI_PORT_CONTROL(pipe), REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31)); REG_READ(MIPI_PORT_CONTROL(pipe)); } dev_priv->dpi_panel_on[pipe] = false; } gma_power_end(dev); }
static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder *dsi_encoder, int pipe) { struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; if (!dev_priv->dpi_panel_on[pipe]) { dev_err(dev->dev, "DPI panel is already off\n"); return; } tc35876x_toshiba_bridge_panel_off(dev); tc35876x_set_bridge_reset_state(dev, 1); dsi_set_pipe_plane_enable_state(dev, 0, pipe); mdfld_dsi_dpi_shut_down(dpi_output, pipe); dsi_set_device_ready_state(dev, 0, pipe); }
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); struct drm_device *dev; struct drm_psb_private *dev_priv; struct mdfld_dsi_dpi_output *dpi_output = NULL; u32 mipi_reg = MIPI; u32 pipeconf_reg = PIPEACONF; int pipe; if (!dsi_config) { DRM_ERROR("dsi_config is NULL\n"); return; } pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); dev = dsi_config->dev; dev_priv = dev->dev_private; 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; } /** * if TMD panel call new power on/off sequences instead. * NOTE: refine TOSHIBA panel code later */ __mdfld_dsi_dpi_set_power(encoder, on); }
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); }
void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); u32 pipeconf_reg = PIPEACONF; u32 dspcntr_reg = DSPACNTR; u32 pipeconf; u32 dspcntr; u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; if (pipe == -1) return; pipeconf = dev_priv->pipeconf[pipe]; dspcntr = dev_priv->dspcntr[pipe]; if (pipe) { pipeconf_reg = PIPECCONF; dspcntr_reg = DSPCCNTR; } else { if (mdfld_get_panel_type(dev, pipe) == TC35876X) mipi &= (~0x03); /* Use all four lanes */ else mipi |= 2; } /*start up display island if it was shutdown*/ if (!gma_power_begin(dev, true)) return; if (mdfld_get_panel_type(dev, pipe) == TC35876X) { /* * The following logic is required to reset the bridge and * configure. This also starts the DSI clock at 200MHz. */ tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ tc35876x_toshiba_bridge_panel_on(dev); udelay(100); /* Now start the DSI clock */ REG_WRITE(MRST_DPLL_A, 0x00); REG_WRITE(MRST_FPA0, 0xC1); REG_WRITE(MRST_DPLL_A, 0x00800000); udelay(500); REG_WRITE(MRST_DPLL_A, 0x80800000); if (REG_BIT_WAIT(pipeconf_reg, 1, 29)) dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n", __func__); REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); mipi_set_properties(dsi_config, pipe); mdfld_mipi_config(dsi_config, pipe); mdfld_set_pipe_timing(dsi_config, pipe); REG_WRITE(DSPABASE, 0x00); REG_WRITE(DSPASIZE, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); REG_WRITE(DSPACNTR, 0x98000000); REG_WRITE(DSPASURF, 0x00); REG_WRITE(VGACNTRL, 0x80000000); REG_WRITE(DEVICE_READY_REG, 0x00000001); REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000); } else { /*set up mipi port FIXME: do at init time */ REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi); } REG_READ(MIPI_PORT_CONTROL(pipe)); if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { /* NOP */ } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { /* set up DSI controller DPI interface */ mdfld_dsi_dpi_controller_init(dsi_config, pipe); /* Configure MIPI Bridge and Panel */ tc35876x_configure_lvds_bridge(dev); dev_priv->dpi_panel_on[pipe] = true; } else { /*turn on DPI interface*/ mdfld_dsi_dpi_turn_on(dpi_output, pipe); } /*set up pipe*/ REG_WRITE(pipeconf_reg, pipeconf); REG_READ(pipeconf_reg); /*set up display plane*/ REG_WRITE(dspcntr_reg, dspcntr); REG_READ(dspcntr_reg); msleep(20); /* FIXME: this should wait for vblank */ if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { /* NOP */ } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { mdfld_dsi_dpi_turn_on(dpi_output, pipe); } else { /* init driver ic */ mdfld_dsi_tpo_ic_init(dsi_config, pipe); /*init backlight*/ mdfld_dsi_brightness_init(dsi_config, pipe); } gma_power_end(dev); }
/** * Setup Display Controller to turn on/off a video mode panel. * Most of the video mode MIPI panel should follow the power on/off * sequence in this function. * NOTE: do NOT modify this function for new panel Enabling. Register * new panel function callbacks to make this function available for a * new video mode panel */ static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) { struct mdfld_dsi_encoder *dsi_encoder; struct mdfld_dsi_connector *dsi_connector; struct mdfld_dsi_dpi_output *dpi_output; struct mdfld_dsi_config *dsi_config; struct panel_funcs *p_funcs; int pipe; struct drm_device *dev; struct drm_psb_private *dev_priv; if (!encoder) { DRM_ERROR("Invalid encoder\n"); return -EINVAL; } dsi_encoder = MDFLD_DSI_ENCODER(encoder); dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); p_funcs = dpi_output->p_funcs; pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); dsi_connector = mdfld_dsi_encoder_get_connector(dsi_encoder); if (!dsi_connector) { DRM_ERROR("dsi_connector is NULL\n"); return -EINVAL; } dev = dsi_config->dev; dev_priv = dev->dev_private; if (dsi_connector->status != connector_status_connected) return 0; mutex_lock(&dsi_config->context_lock); if (dpi_output->first_boot && dsi_config->dsi_hw_context.panel_on) { printk(KERN_ALERT "skip panle power setting for first boot!" \ "panel is already powered on\n"); goto fun_exit; } switch (on) { case true: /* panel is already on */ if (dsi_config->dsi_hw_context.panel_on) goto fun_exit; if (__dpi_panel_power_on(dsi_config, p_funcs)) { DRM_ERROR("Faild to turn on panel\n"); goto set_power_err; } dsi_config->dsi_hw_context.panel_on = 1; break; case false: if (__dpi_panel_power_off(dsi_config, p_funcs)) { DRM_ERROR("Faild to turn off panel\n"); goto set_power_err; } dsi_config->dsi_hw_context.panel_on = 0; break; default: break; } fun_exit: mutex_unlock(&dsi_config->context_lock); PSB_DEBUG_ENTRY("successfully\n"); return 0; set_power_err: mutex_unlock(&dsi_config->context_lock); PSB_DEBUG_ENTRY("unsuccessfully!!!!\n"); return -EAGAIN; }
static void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) { struct mdfld_dsi_encoder *dsi_encoder; struct mdfld_dsi_config *dsi_config; struct drm_device *dev; struct drm_psb_private *dev_priv; struct mdfld_dsi_dpi_output *dpi_output; struct panel_funcs *p_funcs; dsi_encoder = MDFLD_DSI_ENCODER(encoder); dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); if (!dsi_config) { DRM_ERROR("dsi_config is NULL\n"); return; } dev = dsi_config->dev; dev_priv = dev->dev_private; dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); p_funcs = dpi_output->p_funcs; PSB_DEBUG_ENTRY("%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : DRM_MODE_DPMS_STANDBY == mode ? "standby" : "off")); mutex_lock(&dev_priv->dpms_mutex); DCLockMutex(); if (mode == DRM_MODE_DPMS_ON) { mdfld_dsi_dpi_set_power(encoder, true); DCAttachPipe(dsi_config->pipe); DC_MRFLD_onPowerOn(dsi_config->pipe); #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE { struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context; struct backlight_device bd; bd.props.brightness = ctx->lastbrightnesslevel; psb_set_brightness(&bd); } #endif } else if (mode == DRM_MODE_DPMS_STANDBY) { #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct mdfld_dsi_hw_context *ctx = &dsi_config->dsi_hw_context; struct backlight_device bd; ctx->lastbrightnesslevel = psb_get_brightness(&bd); bd.props.brightness = 0; psb_set_brightness(&bd); #endif /* Make the pending flip request as completed. */ DCUnAttachPipe(dsi_config->pipe); msleep(50); DC_MRFLD_onPowerOff(dsi_config->pipe); msleep(50); } else { mdfld_dsi_dpi_set_power(encoder, false); drm_handle_vblank(dev, dsi_config->pipe); /* Turn off TE interrupt. */ drm_vblank_off(dev, dsi_config->pipe); /* Make the pending flip request as completed. */ DCUnAttachPipe(dsi_config->pipe); DC_MRFLD_onPowerOff(dsi_config->pipe); } DCUnLockMutex(); mutex_unlock(&dev_priv->dpms_mutex); }
/** * Setup Display Controller to turn on/off a video mode panel. * Most of the video mode MIPI panel should follow the power on/off * sequence in this function. * NOTE: do NOT modify this function for new panel Enabling. Register * new panel function callbacks to make this function available for a * new video mode panel */ static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) { struct mdfld_dsi_encoder *dsi_encoder; struct mdfld_dsi_connector *dsi_connector; struct mdfld_dsi_dpi_output *dpi_output; struct mdfld_dsi_config *dsi_config; struct panel_funcs *p_funcs; int pipe; struct drm_device *dev; struct drm_psb_private *dev_priv; if (!encoder) { DRM_ERROR("Invalid encoder\n"); return -EINVAL; } dsi_encoder = MDFLD_DSI_ENCODER(encoder); dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); p_funcs = dpi_output->p_funcs; pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); dsi_connector = mdfld_dsi_encoder_get_connector(dsi_encoder); if (!dsi_connector) { DRM_ERROR("dsi_connector is NULL\n"); return -EINVAL; } dev = dsi_config->dev; dev_priv = dev->dev_private; if (dsi_connector->status != connector_status_connected) return 0; mutex_lock(&dsi_config->context_lock); if (dpi_output->first_boot && on) { if (dsi_config->dsi_hw_context.panel_on) { if (IS_ANN(dev)) ann_dc_setup(dsi_config); psb_enable_vblank(dev, dsi_config->pipe); /* don't need ISLAND c for non dual-dsi panel */ if (!is_dual_dsi(dev)) power_island_put(OSPM_DISPLAY_C); DRM_INFO("skip panle power setting for first boot! " "panel is already powered on\n"); goto fun_exit; } if (android_hdmi_is_connected(dev)) otm_hdmi_power_islands_off(); /* power down islands turned on by firmware */ power_island_put(OSPM_DISPLAY_A | OSPM_DISPLAY_C | OSPM_DISPLAY_MIO); } switch (on) { case true: /* panel is already on */ if (dsi_config->dsi_hw_context.panel_on) goto fun_exit; if (__dpi_panel_power_on(dsi_config, p_funcs, dpi_output->first_boot)) { DRM_ERROR("Faild to turn on panel\n"); goto set_power_err; } dsi_config->dsi_hw_context.panel_on = 1; /* for every dpi panel power on, clear the dpi underrun count */ dev_priv->pipea_dpi_underrun_count = 0; dev_priv->pipec_dpi_underrun_count = 0; break; case false: if (!dsi_config->dsi_hw_context.panel_on && !dpi_output->first_boot) goto fun_exit; if (__dpi_panel_power_off(dsi_config, p_funcs)) { DRM_ERROR("Faild to turn off panel\n"); goto set_power_err; } dsi_config->dsi_hw_context.panel_on = 0; break; default: break; } fun_exit: mutex_unlock(&dsi_config->context_lock); PSB_DEBUG_ENTRY("successfully\n"); return 0; set_power_err: mutex_unlock(&dsi_config->context_lock); PSB_DEBUG_ENTRY("unsuccessfully!!!!\n"); return -EAGAIN; }
void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); u32 pipeconf_reg = PIPEACONF; u32 dspcntr_reg = DSPACNTR; u32 mipi_reg = MIPI; u32 reg_offset = 0; u32 pipeconf = dev_priv->pipeconf; u32 dspcntr = dev_priv->dspcntr; u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n", mode->hdisplay, mode->vdisplay, pipe); if(pipe) { pipeconf_reg = PIPECCONF; dspcntr_reg = DSPCCNTR; mipi_reg = MIPI_C; reg_offset = MIPIC_REG_OFFSET; } else { mipi |= 2; } if (!gma_power_begin(dev, true)) return; /* Set up mipi port FIXME: do at init time */ REG_WRITE(mipi_reg, mipi); REG_READ(mipi_reg); /* Set up DSI controller DPI interface */ mdfld_dsi_dpi_controller_init(dsi_config, pipe); if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { /* Turn on DPI interface */ mdfld_dsi_dpi_turn_on(dpi_output, pipe); } /* Set up pipe */ REG_WRITE(pipeconf_reg, pipeconf); REG_READ(pipeconf_reg); /* Set up display plane */ REG_WRITE(dspcntr_reg, dspcntr); REG_READ(dspcntr_reg); msleep(20); /* FIXME: this should wait for vblank */ dev_dbg(dev->dev, "State %x, power %d\n", REG_READ(MIPIA_INTR_STAT_REG + reg_offset), dpi_output->panel_on); if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { /* Init driver ic */ mdfld_dsi_tpo_ic_init(dsi_config, pipe); /* Init backlight */ mdfld_dsi_brightness_init(dsi_config, pipe); } gma_power_end(dev); }
/** * Setup Display Controller to turn on/off a video mode panel. * Most of the video mode MIPI panel should follow the power on/off * sequence in this function. * NOTE: do NOT modify this function for new panel Enabling. Register * new panel function callbacks to make this function available for a * new video mode panel */ static int __mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) { struct mdfld_dsi_encoder *dsi_encoder; struct mdfld_dsi_connector *dsi_connector; struct mdfld_dsi_dpi_output *dpi_output; struct mdfld_dsi_config *dsi_config; struct panel_funcs *p_funcs; int pipe; struct drm_device *dev; struct drm_psb_private *dev_priv; static int last_ospm_suspend = -1; if (!encoder) { DRM_ERROR("Invalid encoder\n"); return -EINVAL; } PSB_DEBUG_ENTRY("%s, last_ospm_suspend = %s\n", (on ? "on" : "off"), (last_ospm_suspend ? "true" : "false")); dsi_encoder = MDFLD_DSI_ENCODER(encoder); dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); p_funcs = dpi_output->p_funcs; pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); dsi_connector = mdfld_dsi_encoder_get_connector(dsi_encoder); if (!dsi_connector) { DRM_ERROR("Invalid connector\n"); return -EINVAL; } dev = dsi_config->dev; dev_priv = dev->dev_private; if (dsi_connector->status != connector_status_connected) return 0; mutex_lock(&dsi_config->context_lock); if (last_ospm_suspend == -1) last_ospm_suspend = false; if (dpi_output->first_boot && dsi_config->dsi_hw_context.panel_on) { if (Check_fw_initilized_reusable(dsi_config, p_funcs)) { DRM_INFO("skip panle power setting for first boot!" " panel is already powered on\n"); goto fun_exit; } else dsi_config->dsi_hw_context.panel_on = 0; } /* ASUS_BSP: Louis +++*/ else if (dpi_output->first_boot && !dsi_config->dsi_hw_context.panel_on) { DRM_INFO("No display in ifwi, initialize panel in kernel\n"); psbfb_memclear(); } /* ASUS_BSP: Louis ---*/ /** * if ospm has turned panel off, but dpms tries to turn panel on, skip */ if (dev_priv->dpms_on_off && on && last_ospm_suspend) goto fun_exit; switch (on) { case true: /* panel is already on */ if (dsi_config->dsi_hw_context.panel_on) goto fun_exit; /* For DPMS case, just turn on/off panel */ if (dev_priv->dpms_on_off) { if (mdfld_dsi_dpi_panel_turn_on(dsi_config, p_funcs)) { DRM_ERROR("Faild to turn on panel\n"); goto set_power_err; } } else { if (__dpi_panel_power_on(dsi_config, p_funcs)) { DRM_ERROR("Faild to turn on panel\n"); goto set_power_err; } } /** * If power on, turn off color mode by default, * let panel in full color mode */ mdfld_dsi_dpi_set_color_mode(dsi_config, false); dsi_config->dsi_hw_context.panel_on = 1; last_ospm_suspend = false; break; case false: if (dev_priv->dpms_on_off && dsi_config->dsi_hw_context.panel_on) { if (mdfld_dsi_dpi_panel_shut_down(dsi_config, p_funcs)) DRM_ERROR("Faild to shutdown panel\n"); last_ospm_suspend = false; } else if (!dev_priv->dpms_on_off && !last_ospm_suspend) { if (__dpi_panel_power_off(dsi_config, p_funcs)) { DRM_ERROR("Faild to turn off panel\n"); goto set_power_err; } /* ospm suspend called? */ last_ospm_suspend = true; } dsi_config->dsi_hw_context.panel_on = 0; SetDisplayFrameUpdate(5); /* ASUS_BSP: Louis ++ */ break; default: break; } fun_exit: mutex_unlock(&dsi_config->context_lock); /*To optimize dpms with context lock, move panel sleep out of mutex*/ if (dev_priv->dpms_on_off) msleep(100); PSB_DEBUG_ENTRY("successfully\n"); return 0; set_power_err: mutex_unlock(&dsi_config->context_lock); PSB_DEBUG_ENTRY("unsuccessfully!!!!\n"); return -EAGAIN; }