/* * _sysfs_support_fbc_show() - Return 1 if FBC/FBDC supported, else 0. * @kdev - Pointer to struct device * @attr - pointer to struct device_attribute * @buf - Pointer to output buffer to receive character string. * The buffer length is PAGE_SIZE bytes. */ static ssize_t _sysfs_support_fbc_show(struct device *kdev, struct device_attribute *attr, char *buf) { const int buflen = PAGE_SIZE; int support_fbc; /* Supported for Anniedale, but not for ANN A0 and ANN B0. */ if (!IS_ANN() || IS_ANN_A0() || IS_ANN_B0()) support_fbc = 0; else support_fbc = 1; return scnprintf(buf, buflen, "%d\n", support_fbc); }
static void intel_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output) { struct mdfld_dsi_pkg_sender *sender; 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; int pipe = dbi_output->channel_num ? 2 : 0; u32 dpll_reg = MRST_DPLL_A; u32 dspcntr_reg = DSPACNTR; u32 pipeconf_reg = PIPEACONF; u32 dsplinoff_reg = DSPALINOFF; u32 dspsurf_reg = DSPASURF; sender = mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); if (!sender) { DRM_ERROR("pkg sender is NULL\n"); return; } /* if mode setting on-going, back off */ if (!IS_ANN_A0(dev)) { 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; } /* check DBI FIFO status */ if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) { if (!(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) return; } else if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) return; if (!IS_ANN_A0(dev)) { /* 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; mdfld_dsi_cmds_kick_out(sender); }
/** * Power on sequence for command mode MIPI panel. * NOTE: do NOT modify this function */ static int __dbi_panel_power_on(struct mdfld_dsi_config *dsi_config, struct panel_funcs *p_funcs) { struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int reset_count = 10; int err = 0; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); struct mdfld_dbi_dsr_info *dsr_info; struct mdfld_dsi_dbi_output **dbi_outputs; struct mdfld_dsi_dbi_output *dbi_output; if (!sender) { DRM_ERROR("pkg sender is NULL\n"); return -EINVAL; } PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; mdfld_dsi_dsr_forbid_locked(dsi_config); reset_recovery: --reset_count; err = 0; /*after entering dstb mode, need reset*/ if (p_funcs && p_funcs->exit_deep_standby) p_funcs->exit_deep_standby(dsi_config); if (__dbi_power_on(dsi_config)) { DRM_ERROR("Failed to init display controller!\n"); err = -EAGAIN; goto power_on_err; } /** * Different panel may have different ways to have * drvIC initialized. Support it! */ if (p_funcs && p_funcs->drv_ic_init) { if (p_funcs->drv_ic_init(dsi_config)) { DRM_ERROR("Failed to init dsi controller!\n"); err = -EAGAIN; goto power_on_err; } } /* Issue "write_mem_start" DSI command during power on. */ dsr_info = dev_priv->dbi_dsr_info; dbi_outputs = dsr_info->dbi_outputs; dbi_output = dsi_config->pipe ? dbi_outputs[1] : dbi_outputs[0]; if (!IS_ANN_A0(dev)) intel_dsi_dbi_update_fb(dbi_output); /** * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } if (p_funcs && p_funcs->set_brightness) if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); /*wait for all FIFOs empty*/ mdfld_dsi_wait_for_fifos_empty(sender); if (is_dual_dsi(dev)) { sender->work_for_slave_panel = true; mdfld_dsi_wait_for_fifos_empty(sender); sender->work_for_slave_panel = false; } if (IS_ANN_A0(dev)) intel_dsi_dbi_update_fb(dbi_output); power_on_err: if (err && reset_count) { DRM_ERROR("Failed to init panel, try reset it again!\n"); goto reset_recovery; } mdfld_dsi_dsr_allow_locked(dsi_config); return err; }
/* dbi interface power on*/ int __dbi_power_on(struct mdfld_dsi_config *dsi_config) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int retry; int err = 0; u32 guit_val = 0; u32 power_island = 0; u32 sprite_reg_offset = 0; int i = 0; int offset = 0; PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; power_island = pipe_to_island(dsi_config->pipe); if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C)) power_island |= OSPM_DISPLAY_MIO; if (is_dual_dsi(dev)) power_island |= OSPM_DISPLAY_C; if (!power_island_get(power_island)) return -EAGAIN; /* * Wait for DSI PLL locked on pipe, and only need to poll status of pipe * A as both MIPI pipes share the same DSI PLL. */ if (dsi_config->pipe == 0) { retry = 20000; while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) && --retry) udelay(150); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } } if (IS_ANN_A0(dev)) { /* FIXME: reset the DC registers for ANN A0 */ power_island_get(OSPM_DISPLAY_B | OSPM_DISPLAY_C); REG_WRITE(DSPCLK_GATE_D, 0xFFFFFFFF); /* 0x10000000 */ REG_WRITE(RAMCLK_GATE_D, 0xFFFFFFFF); /* 0x0 */ REG_WRITE(PFIT_CONTROL, 0x20000000); REG_WRITE(DSPIEDCFGSHDW, 0x0); REG_WRITE(DSPARB2, 0x000A0200); REG_WRITE(DSPARB, 0x18040080); REG_WRITE(DSPFW1, 0x0F0F3F3F); REG_WRITE(DSPFW2, 0x5F2F0F3F); REG_WRITE(DSPFW3, 0x0); REG_WRITE(DSPFW4, 0x07071F1F); REG_WRITE(DSPFW5, 0x2F17071F); REG_WRITE(DSPFW6, 0x00001F3F); REG_WRITE(DSPFW7, 0x1F3F1F3F); REG_WRITE(DSPSRCTRL, 0x00080100); REG_WRITE(DSPCHICKENBIT, 0x0); REG_WRITE(FBDC_CHICKEN, 0x0C0C0C0C); REG_WRITE(CURACNTR, 0x0); REG_WRITE(CURBCNTR, 0x0); REG_WRITE(CURCCNTR, 0x0); REG_WRITE(IEP_OVA_CTRL, 0x0); REG_WRITE(IEP_OVA_CTRL, 0x0); REG_WRITE(DSPACNTR, 0x0); REG_WRITE(DSPBCNTR, 0x0); REG_WRITE(DSPCCNTR, 0x0); REG_WRITE(DSPDCNTR, 0x0); REG_WRITE(DSPECNTR, 0x0); REG_WRITE(DSPFCNTR, 0x0); power_island_put(OSPM_DISPLAY_B | OSPM_DISPLAY_C); } /*exit ULPS*/ if (__dbi_exit_ulps_locked(dsi_config, 0)) { DRM_ERROR("Failed to exit ULPS\n"); goto power_on_err; } /*update MIPI port config*/ REG_WRITE(regs->mipi_reg, ctx->mipi | REG_READ(regs->mipi_reg)); /*unready dsi adapter for re-programming*/ REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) & ~(DSI_DEVICE_READY)); if (is_dual_dsi(dev)) { if (__dbi_exit_ulps_locked(dsi_config, 0x800)) { DRM_ERROR("Failed to exit ULPS\n"); goto power_on_err; } offset = 0x1000; REG_WRITE(regs->mipi_reg + offset, ctx->mipi | REG_READ(regs->mipi_reg + offset)); /*unready dsi adapter for re-programming*/ offset = 0x800; REG_WRITE(regs->device_ready_reg + offset, REG_READ(regs->device_ready_reg + offset) & ~(DSI_DEVICE_READY)); } /* * According to MIPI D-PHY spec, if clock stop feature is enabled (EOT * Disable), un-ready MIPI adapter needs to wait for 20 cycles from HS * to LP mode. Per calculation 1us is enough. */ if (ctx->eot_disable & CLOCK_STOP) udelay(1); __dbi_set_properties(dsi_config, PORT_A); /*Setup pipe timing*/ REG_WRITE(regs->htotal_reg, ctx->htotal); REG_WRITE(regs->hblank_reg, ctx->hblank); REG_WRITE(regs->hsync_reg, ctx->hsync); REG_WRITE(regs->vtotal_reg, ctx->vtotal); REG_WRITE(regs->vblank_reg, ctx->vblank); REG_WRITE(regs->vsync_reg, ctx->vsync); REG_WRITE(regs->pipesrc_reg, ctx->pipesrc); REG_WRITE(regs->dsppos_reg, ctx->dsppos); REG_WRITE(regs->dspstride_reg, ctx->dspstride); if (!IS_ANN_A0(dev)) { /*restore color_coef (chrome) */ for (i = 0; i < 6; i++) REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]); /* restore palette (gamma) */ for (i = 0; i < 256; i++) REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]); /* restore dpst setting */ if (dev_priv->psb_dpst_state) { dpstmgr_reg_restore_locked(dev, dsi_config); psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); } } /*Setup plane*/ REG_WRITE(regs->dspsize_reg, ctx->dspsize); REG_WRITE(regs->dspsurf_reg, ctx->dspsurf); REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); if (is_dual_dsi(dev)) __dbi_set_properties(dsi_config, PORT_C); /*enable plane*/ val = ctx->dspcntr | BIT31; REG_WRITE(regs->dspcntr_reg, val); if (ctx->sprite_dspcntr & BIT31) { if (dsi_config->pipe == 0) sprite_reg_offset = 0x3000; else if (dsi_config->pipe == 2) sprite_reg_offset = 0x1000; /* Set up Sprite Plane */ REG_WRITE(regs->dspsize_reg + sprite_reg_offset, ctx->sprite_dspsize); REG_WRITE(regs->dspsurf_reg + sprite_reg_offset, ctx->sprite_dspsurf); REG_WRITE(regs->dsplinoff_reg + sprite_reg_offset, ctx->sprite_dsplinoff); REG_WRITE(regs->dsppos_reg + sprite_reg_offset, ctx->sprite_dsppos); REG_WRITE(regs->dspstride_reg + sprite_reg_offset, ctx->sprite_dspstride); /* enable plane */ REG_WRITE(regs->dspcntr_reg + sprite_reg_offset, ctx->sprite_dspcntr); } /* Set up Overlay Plane */ if (ctx->ovaadd) PSB_WVDC32(ctx->ovaadd, OV_OVADD); if (ctx->ovcadd) PSB_WVDC32(ctx->ovcadd, OVC_OVADD); /*ready dsi adapter*/ REG_WRITE(regs->device_ready_reg, REG_READ(regs->device_ready_reg) | DSI_DEVICE_READY); mdelay(1); if (is_dual_dsi(dev)) { REG_WRITE(regs->device_ready_reg + offset, REG_READ(regs->device_ready_reg + offset) | DSI_DEVICE_READY); } if (IS_ANN_A0(dev)) { REG_WRITE(regs->ddl1_reg, ctx->ddl1); REG_WRITE(regs->ddl2_reg, ctx->ddl2); REG_WRITE(regs->ddl3_reg, ctx->ddl3); REG_WRITE(regs->ddl4_reg, ctx->ddl4); } /*Enable pipe*/ val = ctx->pipeconf; val &= ~0x000c0000; val |= BIT31 | PIPEACONF_DSR; REG_WRITE(regs->pipeconf_reg, val); /*Wait for pipe enabling,when timing generator is working */ retry = 10000; while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30)) udelay(3); if (!retry) { DRM_ERROR("Failed to enable pipe\n"); err = -EAGAIN; goto power_on_err; } /* * Enable TE to trigger "write_mem_start" issuing * in non-normal boot modes. */ mdfld_enable_te(dev, dsi_config->pipe); return err; power_on_err: power_island_put(power_island); return err; }
/** * Power on sequence for video mode MIPI panel. * NOTE: do NOT modify this function */ static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config, struct panel_funcs *p_funcs) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int retry, reset_count = 10; int i; int err = 0; u32 guit_val = 0; u32 power_island = 0; int offset = 0; PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; power_island = pipe_to_island(dsi_config->pipe); if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C)) power_island |= OSPM_DISPLAY_MIO; if (is_dual_dsi(dev)) power_island |= OSPM_DISPLAY_C; if (!power_island_get(power_island)) return -EAGAIN; reset_recovery: --reset_count; /*HW-Reset*/ if (p_funcs && p_funcs->reset) p_funcs->reset(dsi_config); if (!is_dual_dsi(dev)) { /* Disable PLL*/ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, _DSI_LDO_EN); /* Program PLL */ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ((guit_val & ~_P1_POST_DIV_MASK) | (ctx->dpll & _P1_POST_DIV_MASK))); ctx->dpll |= DPLL_VCO_ENABLE; ctx->dpll &= ~_DSI_LDO_EN; intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ctx->dpll); } else { intel_mid_msgbus_write32(CCK_PORT, 0x68, 0x682); /* Disable PLL*/ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, 0); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, _DSI_LDO_EN); /* Program PLL */ intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_DIV_REG, ctx->fp); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ((guit_val & ~_P1_POST_DIV_MASK) | (ctx->dpll & _P1_POST_DIV_MASK))); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); ctx->dpll |= DPLL_VCO_ENABLE; ctx->dpll &= ~(_DSI_LDO_EN | _CLK_EN_CCK_DSI0 | _CLK_EN_CCK_DSI1 | _DSI_MUX_SEL_CCK_DSI1 | _DSI_MUX_SEL_CCK_DSI0); ctx->dpll |= _CLK_EN_PLL_DSI0 | _CLK_EN_PLL_DSI1; intel_mid_msgbus_write32(CCK_PORT, DSI_PLL_CTRL_REG, ctx->dpll); } /* Wait for DSI PLL lock */ retry = 10000; guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); while (((guit_val & _DSI_PLL_LOCK) != _DSI_PLL_LOCK) && (--retry)) { udelay(3); guit_val = intel_mid_msgbus_read32(CCK_PORT, DSI_PLL_CTRL_REG); if (retry == 0) { DRM_ERROR("DSI PLL fails to lock\n"); err = -EAGAIN; goto power_on_err; } } /* * Wait for DSI PLL locked on pipe, and only need to poll status of pipe * A as both MIPI pipes share the same DSI PLL. */ if (dsi_config->pipe == 0) { retry = 20000; while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) && --retry) udelay(150); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } } __dpi_set_properties(dsi_config, PORT_A); /*Setup pipe timing*/ REG_WRITE(regs->htotal_reg, ctx->htotal); REG_WRITE(regs->hblank_reg, ctx->hblank); REG_WRITE(regs->hsync_reg, ctx->hsync); REG_WRITE(regs->vtotal_reg, ctx->vtotal); REG_WRITE(regs->vblank_reg, ctx->vblank); REG_WRITE(regs->vsync_reg, ctx->vsync); REG_WRITE(regs->pipesrc_reg, ctx->pipesrc); REG_WRITE(regs->dsppos_reg, ctx->dsppos); REG_WRITE(regs->dspstride_reg, ctx->dspstride); if (IS_ANN_A0(dev)) { /*reset registers*/ REG_WRITE(0x7002C, 0x000A0200); REG_WRITE(0x70508, 0x0c0c0c0c); REG_WRITE(0x70504, 0xffffffff); REG_WRITE(0x70500, 0xffffffff); DRM_DEBUG("LOADING: 0x70504 %#x\n", REG_READ(0x70504)); } /*Setup plane*/ REG_WRITE(regs->dspsize_reg, ctx->dspsize); REG_WRITE(regs->dspsurf_reg, ctx->dspsurf); REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); /*restore color_coef (chrome) */ for (i = 0; i < 6; i++) REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]); /* restore palette (gamma) */ for (i = 0; i < 256; i++) REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]); /* restore dpst setting */ if (dev_priv->psb_dpst_state) { dpstmgr_reg_restore_locked(dev, dsi_config); psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); } if (__dpi_config_port(dsi_config, p_funcs, PORT_A) != 0) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } if (is_dual_dsi(dev)) { __dpi_set_properties(dsi_config, PORT_C); __dpi_config_port(dsi_config, p_funcs, PORT_C); } /** * Different panel may have different ways to have * drvIC initialized. Support it! */ if (p_funcs && p_funcs->drv_ic_init) { if (p_funcs->drv_ic_init(dsi_config)) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } } /*Enable MIPI Port A*/ offset = 0x0; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); REG_WRITE(regs->dpi_control_reg + offset, BIT1); if (is_dual_dsi(dev)) { /*Enable MIPI Port C*/ offset = 0x1000; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); offset = 0x800; REG_WRITE(regs->dpi_control_reg + offset, BIT1); } /** * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } /*Enable pipe*/ val = ctx->pipeconf; val &= ~0x000c0000; val |= BIT31; REG_WRITE(regs->pipeconf_reg, val); /*Wait for pipe enabling,when timing generator is wroking */ if (REG_READ(regs->mipi_reg) & BIT31) { retry = 10000; while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30)) udelay(3); if (!retry) { DRM_ERROR("Failed to enable pipe\n"); err = -EAGAIN; goto power_on_err; } } /*enable plane*/ val = ctx->dspcntr | BIT31; REG_WRITE(regs->dspcntr_reg, val); if (p_funcs && p_funcs->set_brightness) { if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); } else { DRM_ERROR("Failed to set panel brightness\n"); } if (p_funcs && p_funcs->drv_set_panel_mode) p_funcs->drv_set_panel_mode(dsi_config); psb_enable_vblank(dev, dsi_config->pipe); return err; power_on_err: power_island_put(power_island); return err; }
int vsp_init_fw(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; struct vsp_private *vsp_priv = dev_priv->vsp_private; int ret = 0; const struct firmware *raw; unsigned char *ptr, *ma_ptr; struct vsp_secure_boot_header *boot_header; struct vsp_multi_app_blob_data *ma_header; unsigned long imr_addr; int imr_size; unsigned char *imr_ptr; unsigned int vrl_header_size = 736; const unsigned long vsp_magic_num = 0x50535624; const int FW_NAME_LEN = 30; char fw_name[FW_NAME_LEN]; int name_ret; PSB_DEBUG_GENERAL("read firmware into buffer\n"); name_ret = snprintf(fw_name, FW_NAME_LEN, "vsp.bin.%04x.%04x", (int)spid.platform_family_id, (int)spid.hardware_id); if (name_ret > FW_NAME_LEN) { DRM_ERROR("failed to get fw name, ret %d vs expect %d\n", name_ret, FW_NAME_LEN); /* no way */ return -1; } /* try load with spid first */ ret = request_firmware(&raw, fw_name, &dev->pdev->dev); if (ret < 0 || raw == NULL) { VSP_DEBUG("failed to load fw: %s, try to load different fw\n", fw_name); /* read firmware img */ VSP_DEBUG("load vsp fw\n"); if (IS_ANN_A0(dev)) ret = request_firmware(&raw, FW_NAME_ANN, &dev->pdev->dev); else if (IS_TNG_B0(dev)) ret = request_firmware(&raw, FW_NAME_B0, &dev->pdev->dev); else { DRM_ERROR("VSP secure fw: bad platform\n"); raw = NULL; } } if (ret < 0 || raw == NULL) { DRM_ERROR("VSP: request_firmware failed: reason %d\n", ret); return -1; } if (raw->size < sizeof(struct vsp_secure_boot_header)) { DRM_ERROR("VSP: %s is not a correct firmware (size %d)\n", FW_NAME, raw->size); ret = -1; goto out; } ptr = (void *)raw->data; ma_ptr = (void *) raw->data + vrl_header_size; boot_header = (struct vsp_secure_boot_header *) (ptr + vrl_header_size); ma_header = (struct vsp_multi_app_blob_data *) (ma_ptr + boot_header->ma_header_offset); /* get firmware header */ memcpy(&vsp_priv->boot_header, boot_header, sizeof(vsp_priv->boot_header)); if (vsp_priv->boot_header.magic_number != VSP_SECURE_BOOT_MAGIC_NR) { DRM_ERROR("VSP: failed to load correct vsp firmware\n" "FW magic number is wrong %x (should be %x)\n", vsp_priv->boot_header.magic_number, VSP_SECURE_BOOT_MAGIC_NR); ret = -1; goto out; } /* read application firmware image data (for state-buffer size, etc) */ /* load the multi-app blob header */ memcpy(&vsp_priv->ma_header, ma_header, sizeof(vsp_priv->ma_header)); if (vsp_priv->ma_header.magic_number != VSP_MULTI_APP_MAGIC_NR) { DRM_ERROR("VSP: failed to load correct vsp firmware\n" "FW magic number is wrong %x (should be %x)\n", vsp_priv->ma_header.magic_number, VSP_MULTI_APP_MAGIC_NR); ret = -1; goto out; } VSP_DEBUG("firmware secure header:\n"); VSP_DEBUG("boot_header magic number %x\n", boot_header->magic_number); VSP_DEBUG("boot_text_offset %x\n", boot_header->boot_text_offset); VSP_DEBUG("boot_text_reg %x\n", boot_header->boot_text_reg); VSP_DEBUG("boot_icache_value %x\n", boot_header->boot_icache_value); VSP_DEBUG("boot_icache_reg %x\n", boot_header->boot_icache_reg); VSP_DEBUG("boot_pc_value %x\n", boot_header->boot_pc_value); VSP_DEBUG("boot_pc_reg %x\n", boot_header->boot_pc_reg); VSP_DEBUG("ma_header_offset %x\n", boot_header->ma_header_offset); VSP_DEBUG("ma_header_reg %x\n", boot_header->ma_header_reg); VSP_DEBUG("boot_start_value %x\n", boot_header->boot_start_value); VSP_DEBUG("boot_start_reg %x\n", boot_header->boot_start_reg); VSP_DEBUG("firmware ma_blob header:\n"); VSP_DEBUG("ma_header magic number %x\n", ma_header->magic_number); VSP_DEBUG("offset_from_start %x\n", ma_header->offset_from_start); VSP_DEBUG("imr_state_buffer_addr %x\n", ma_header->imr_state_buffer_addr); VSP_DEBUG("imr_state_buffer_size %x\n", ma_header->imr_state_buffer_size); VSP_DEBUG("apps_default_context_buffer_size %x\n", ma_header->apps_default_context_buffer_size); /* get imr 11 region start address and size */ imr_addr = intel_mid_msgbus_read32(PNW_IMR_MSG_PORT, TNG_IMR11L_MSG_REGADDR); imr_addr <<= 10; VSP_DEBUG("IMR11 base address %p\n", imr_addr); imr_size = raw->size; /* map imr 11 */ /* check if raw size is smaller than */ /* ioremap the region */ imr_ptr = ioremap(imr_addr, imr_size); if (!imr_ptr) { DRM_ERROR("failed to map imr_addr\n"); ret = -1; goto out; } /* copy the firmware to imr 11 */ memcpy(imr_ptr, ptr, raw->size); /* unmap the region */ iounmap(imr_ptr); #ifdef CONFIG_DX_SEP54 ret = sepapp_image_verify(imr_addr, imr_size, 15, vsp_magic_num); if (ret) { DRM_ERROR("failed to verify vsp firmware, ret %x\n", ret); ret = -1; goto out; } #endif vsp_priv->fw_loaded = VSP_FW_LOADED; vsp_priv->vsp_state = VSP_STATE_DOWN; vsp_priv->ctrl = (struct vsp_ctrl_reg *) (dev_priv->vsp_reg + VSP_CONFIG_REG_SDRAM_BASE + VSP_CONFIG_REG_START); out: release_firmware(raw); return ret; }
/** * Power on sequence for video mode MIPI panel. * NOTE: do NOT modify this function */ static int __dpi_panel_power_on(struct mdfld_dsi_config *dsi_config, struct panel_funcs *p_funcs) { u32 val = 0; struct mdfld_dsi_hw_registers *regs; struct mdfld_dsi_hw_context *ctx; struct drm_psb_private *dev_priv; struct drm_device *dev; int retry, reset_count = 10; int i; int err = 0; u32 guit_val = 0; u32 power_island = 0; int offset = 0; PSB_DEBUG_ENTRY("\n"); if (!dsi_config) return -EINVAL; regs = &dsi_config->regs; ctx = &dsi_config->dsi_hw_context; dev = dsi_config->dev; dev_priv = dev->dev_private; power_island = pipe_to_island(dsi_config->pipe); if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C)) power_island |= OSPM_DISPLAY_MIO; if (is_dual_dsi(dev)) power_island |= OSPM_DISPLAY_C; if (!power_island_get(power_island)) return -EAGAIN; reset_recovery: --reset_count; /*HW-Reset*/ if (p_funcs && p_funcs->reset) p_funcs->reset(dsi_config); /* * Wait for DSI PLL locked on pipe, and only need to poll status of pipe * A as both MIPI pipes share the same DSI PLL. */ if (dsi_config->pipe == 0) { retry = 20000; while (!(REG_READ(regs->pipeconf_reg) & PIPECONF_DSIPLL_LOCK) && --retry) udelay(150); if (!retry) { DRM_ERROR("PLL failed to lock on pipe\n"); err = -EAGAIN; goto power_on_err; } } if (IS_ANN_A0(dev)) { /* FIXME: reset the DC registers for ANN A0 */ power_island_get(OSPM_DISPLAY_B | OSPM_DISPLAY_C); REG_WRITE(DSPCLK_GATE_D, 0xFFFFFFFF); /* 0x10000000 */ REG_WRITE(RAMCLK_GATE_D, 0xFFFFFFFF); /* 0x0 */ REG_WRITE(PFIT_CONTROL, 0x20000000); REG_WRITE(DSPIEDCFGSHDW, 0x0); REG_WRITE(DSPARB2, 0x000A0200); REG_WRITE(DSPARB, 0x18040080); REG_WRITE(DSPFW1, 0x0F0F3F3F); REG_WRITE(DSPFW2, 0x5F2F0F3F); REG_WRITE(DSPFW3, 0x0); REG_WRITE(DSPFW4, 0x07071F1F); REG_WRITE(DSPFW5, 0x2F17071F); REG_WRITE(DSPFW6, 0x00001F3F); REG_WRITE(DSPFW7, 0x1F3F1F3F); REG_WRITE(DSPSRCTRL, 0x00080100); REG_WRITE(DSPCHICKENBIT, 0x0); REG_WRITE(FBDC_CHICKEN, 0x0C0C0C0C); REG_WRITE(CURACNTR, 0x0); REG_WRITE(CURBCNTR, 0x0); REG_WRITE(CURCCNTR, 0x0); REG_WRITE(IEP_OVA_CTRL, 0x0); REG_WRITE(IEP_OVA_CTRL, 0x0); REG_WRITE(DSPACNTR, 0x0); REG_WRITE(DSPBCNTR, 0x0); REG_WRITE(DSPCCNTR, 0x0); REG_WRITE(DSPDCNTR, 0x0); REG_WRITE(DSPECNTR, 0x0); REG_WRITE(DSPFCNTR, 0x0); power_island_put(OSPM_DISPLAY_B | OSPM_DISPLAY_C); } __dpi_set_properties(dsi_config, PORT_A); /*Setup pipe timing*/ REG_WRITE(regs->htotal_reg, ctx->htotal); REG_WRITE(regs->hblank_reg, ctx->hblank); REG_WRITE(regs->hsync_reg, ctx->hsync); REG_WRITE(regs->vtotal_reg, ctx->vtotal); REG_WRITE(regs->vblank_reg, ctx->vblank); REG_WRITE(regs->vsync_reg, ctx->vsync); REG_WRITE(regs->pipesrc_reg, ctx->pipesrc); REG_WRITE(regs->dsppos_reg, ctx->dsppos); REG_WRITE(regs->dspstride_reg, ctx->dspstride); /*Setup plane*/ REG_WRITE(regs->dspsize_reg, ctx->dspsize); REG_WRITE(regs->dspsurf_reg, ctx->dspsurf); REG_WRITE(regs->dsplinoff_reg, ctx->dsplinoff); REG_WRITE(regs->vgacntr_reg, ctx->vgacntr); /*restore color_coef (chrome) */ for (i = 0; i < 6; i++) REG_WRITE(regs->color_coef_reg + (i<<2), ctx->color_coef[i]); /* restore palette (gamma) */ for (i = 0; i < 256; i++) REG_WRITE(regs->palette_reg + (i<<2), ctx->palette[i]); /* restore dpst setting */ if (dev_priv->psb_dpst_state) { dpstmgr_reg_restore_locked(dev, dsi_config); psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); } if (__dpi_config_port(dsi_config, p_funcs, PORT_A) != 0) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } if (is_dual_dsi(dev)) { __dpi_set_properties(dsi_config, PORT_C); __dpi_config_port(dsi_config, p_funcs, PORT_C); } /** * Different panel may have different ways to have * drvIC initialized. Support it! */ if (p_funcs && p_funcs->drv_ic_init) { if (p_funcs->drv_ic_init(dsi_config)) { if (!reset_count) { err = -EAGAIN; goto power_on_err; } DRM_ERROR("Failed to init dsi controller, reset it!\n"); goto reset_recovery; } } /*Enable MIPI Port A*/ offset = 0x0; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); REG_WRITE(regs->dpi_control_reg + offset, BIT1); if (is_dual_dsi(dev)) { /*Enable MIPI Port C*/ offset = 0x1000; REG_WRITE(regs->mipi_reg + offset, (ctx->mipi | BIT31)); offset = 0x800; REG_WRITE(regs->dpi_control_reg + offset, BIT1); } /** * Different panel may have different ways to have * panel turned on. Support it! */ if (p_funcs && p_funcs->power_on) if (p_funcs->power_on(dsi_config)) { DRM_ERROR("Failed to power on panel\n"); err = -EAGAIN; goto power_on_err; } if (IS_ANN_A0(dev)) { REG_WRITE(regs->ddl1_reg, ctx->ddl1); REG_WRITE(regs->ddl2_reg, ctx->ddl2); REG_WRITE(regs->ddl3_reg, ctx->ddl3); REG_WRITE(regs->ddl4_reg, ctx->ddl4); } /*Enable pipe*/ val = ctx->pipeconf; val &= ~0x000c0000; /** * Frame Start occurs on third HBLANK * after the start of VBLANK */ val |= BIT31 | BIT28; REG_WRITE(regs->pipeconf_reg, val); /*Wait for pipe enabling,when timing generator is wroking */ if (REG_READ(regs->mipi_reg) & BIT31) { retry = 10000; while (--retry && !(REG_READ(regs->pipeconf_reg) & BIT30)) udelay(3); if (!retry) { DRM_ERROR("Failed to enable pipe\n"); err = -EAGAIN; goto power_on_err; } } /*enable plane*/ val = ctx->dspcntr | BIT31; REG_WRITE(regs->dspcntr_reg, val); if (p_funcs && p_funcs->set_brightness) { if (p_funcs->set_brightness(dsi_config, ctx->lastbrightnesslevel)) DRM_ERROR("Failed to set panel brightness\n"); } else { DRM_ERROR("Failed to set panel brightness\n"); } if (p_funcs && p_funcs->drv_set_panel_mode) p_funcs->drv_set_panel_mode(dsi_config); psb_enable_vblank(dev, dsi_config->pipe); return err; power_on_err: power_island_put(power_island); return err; }
/** * Set up the display clock * */ void mrfld_setup_pll(struct drm_device *dev, int pipe, int clk) { DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private; int refclk = 0; int clk_n = 0, clk_p2 = 0, clk_byte = 1, m_conv = 0, clk_tmp = 0; struct mrst_clock_t clock; bool ok; u32 pll = 0, fp = 0; bool is_mipi = false, is_mipi2 = false, is_hdmi = false; struct mdfld_dsi_config *dsi_config = NULL; struct mdfld_dsi_hw_context *ctx = NULL; PSB_DEBUG_ENTRY("pipe = 0x%x\n", pipe); if (pipe == 0) dsi_config = dev_priv->dsi_configs[0]; else if (pipe == 2) dsi_config = dev_priv->dsi_configs[1]; if ((pipe != 1) && !dsi_config) { DRM_ERROR("Invalid DSI config\n"); return; } if (pipe != 1) { ctx = &dsi_config->dsi_hw_context; mutex_lock(&dsi_config->context_lock); } switch (pipe) { case 0: is_mipi = true; break; case 1: is_hdmi = true; break; case 2: is_mipi2 = true; break; } if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19)) { refclk = 19200; if (is_mipi || is_mipi2) { clk_n = 1, clk_p2 = 8; } else if (is_hdmi) { clk_n = 1, clk_p2 = 10; } } else if (dev_priv->ksel == KSEL_BYPASS_25) { refclk = 25000; if (is_mipi || is_mipi2) { clk_n = 1, clk_p2 = 8; } else if (is_hdmi) { clk_n = 1, clk_p2 = 10; } } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) { refclk = 83000; if (is_mipi || is_mipi2) { clk_n = 4, clk_p2 = 8; } else if (is_hdmi) { clk_n = 4, clk_p2 = 10; } } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) { refclk = 100000; if (is_mipi || is_mipi2) { clk_n = 4, clk_p2 = 8; } else if (is_hdmi) { clk_n = 4, clk_p2 = 10; } } if (is_mipi || is_mipi2) clk_byte = 3; clk_tmp = clk * clk_n * clk_p2 * clk_byte; PSB_DEBUG_ENTRY("clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2); PSB_DEBUG_ENTRY("clk = %d, clk_tmp = %d, clk_byte = %d. \n", clk, clk_tmp, clk_byte); ok = mrfld_find_best_PLL(dev, pipe, clk_tmp, refclk, &clock); dev_priv->tmds_clock_khz = clock.dot / (clk_n * clk_p2 * clk_byte); /* * FIXME: Hard code the divisors' value for JDI panel, and need to * calculate them according to the DSI PLL HAS spec. */ if (pipe != 1) { if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) { if (get_panel_type(dev, pipe) == JDI_7x12_CMD) { clock.p1 = 4; clk_n = 1; clock.m = 142; } else if ((get_panel_type(dev, pipe) == SHARP_10x19_CMD) || (get_panel_type(dev, pipe) == SHARP_25x16_CMD)) { clock.p1 = 3; clk_n = 1; clock.m = 137; } else { clock.p1 = 4; clk_n = 1; clock.m = 120; } } else if (is_dual_dsi(dev)) { clock.p1 = 2; clk_n = 1; clock.m = 104; } else { clock.p1 = 5; clk_n = 1; clock.m = 130; } } if (!ok) { DRM_ERROR("mdfldFindBestPLL fail in mrfld_crtc_mode_set.\n"); } else { m_conv = mrfld_m_converts[(clock.m - MRFLD_M_MIN)]; PSB_DEBUG_ENTRY("dot clock = %d," "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m, clock.p1, m_conv); } /* Write the N1 & M1 parameters into DSI_PLL_DIV_REG */ fp = (clk_n / 2) << 16; fp |= m_conv; /*TODO:vcheeram - Remove the hardcoding of fp for JDI_7x12_CMD panel * on ANN for fp. */ if (IS_ANN_A0(dev) && dsi_config != NULL && (get_panel_type(dev, dsi_config->pipe) == JDI_7x12_CMD)) fp = 0x177; if (is_mipi) { /* Enable DSI PLL clocks for DSI0 rather than CCK. */ pll |= _CLK_EN_PLL_DSI0; pll &= ~_CLK_EN_CCK_DSI0; /* Select DSI PLL as the source of the mux input clocks. */ pll &= ~_DSI_MUX_SEL_CCK_DSI0; } if (is_mipi2 || is_dual_dsi(dev)) { /* Enable DSI PLL clocks for DSI1 rather than CCK. */ pll |= _CLK_EN_PLL_DSI1; pll &= ~_CLK_EN_CCK_DSI1; /* Select DSI PLL as the source of the mux input clocks. */ pll &= ~_DSI_MUX_SEL_CCK_DSI1; } if (is_hdmi) pll |= MDFLD_VCO_SEL; /* compute bitmask from p1 value */ pll |= (1 << (clock.p1 - 2)) << 17; if (pipe != 1) { ctx->dpll = pll; ctx->fp = fp; mutex_unlock(&dsi_config->context_lock); } }