void psb_irq_postinstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; unsigned long irqflags; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); PSB_WSGX32(dev_priv->sgx2_irq_mask, PSB_CR_EVENT_HOST_ENABLE2); PSB_WSGX32(dev_priv->sgx_irq_mask, PSB_CR_EVENT_HOST_ENABLE); (void)PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); /****MSVDX IRQ Setup...*****/ /* Enable Mtx Interupt to host */ { unsigned long enables = 0; PSB_DEBUG_GENERAL("Setting up MSVDX IRQs.....\n"); REGIO_WRITE_FIELD_LITE(enables, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ, 1); PSB_WMSVDX32(enables, MSVDX_HOST_INTERRUPT_ENABLE); } dev_priv->irq_enabled = 1; uint32_t hotplug_stat = PSB_RVDC32(PORT_HOTPLUG_ENABLE_REG); PSB_WVDC32(hotplug_stat | SDVOB_HOTPLUG_DETECT_ENABLE, PORT_HOTPLUG_ENABLE_REG); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); }
static int ls04x_drv_ic_init(struct mdfld_dsi_config *dsi_config) { int r = 0; u8 data[16]; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); PSB_DEBUG_ENTRY("\n"); if (!sender) return -EINVAL; sender->status = MDFLD_DSI_PKG_SENDER_FREE; memset(data, 0, sizeof(data)); mdfld_dsi_send_gen_short_hs(sender, ls04x_mcap[0], ls04x_mcap[1], 2, MDFLD_DSI_SEND_PACKAGE); r = mdfld_dsi_read_gen_hs(sender, ls04x_device_code_read[0], 0, 1, data, 5); PSB_DEBUG_GENERAL("device code read: %d %02x %02x %02x %02x %02x\n", r, data[0], data[1], data[2], data[3], data[4]); if ((data[2] == 0x14) && (data[3] == 0x13)) r = ls04x_igzo_drv_ic_init(dsi_config); else if ((data[2] == 0x34) && (data[3] == 0x15)) r = ls04x_cgs_drv_ic_init(dsi_config); else if ((data[2] == 0x94) && (data[3] == 0x31)) r = ls04x_igzo_g8_drv_ic_init(dsi_config); else DRM_INFO("unknown device code: %02x %02x\n", data[2], data[3]); return r; }
void psb_msvdx_irq_postinstall(struct drm_psb_private *dev_priv) { /* Enable Mtx Interupt to host */ unsigned long enables = 0; PSB_DEBUG_GENERAL("Setting up MSVDX IRQs.....\n"); REGIO_WRITE_FIELD_LITE(enables, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ, 1); PSB_WMSVDX32(enables, MSVDX_HOST_INTERRUPT_ENABLE); }
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 psb_poll_mtx_irq (struct drm_psb_private *dev_priv) { int ret = 0; uint32_t MtxInt = 0; REGIO_WRITE_FIELD_LITE (MtxInt, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ, 1); ret = psb_wait_for_register (dev_priv, MSVDX_INTERRUPT_STATUS, MtxInt, /* Required value */ MtxInt /* Enabled bits */ ); if (ret) { PSB_DEBUG_GENERAL ("MSVDX: Error Mtx did not return int within a resonable time\n"); return ret; } PSB_DEBUG_GENERAL ("MSVDX: Got MTX Int\n"); /* Got it so clear the bit */ PSB_WMSVDX32 (MtxInt, MSVDX_INTERRUPT_CLEAR); return ret; }
/* * MSVDX interrupt. */ static void psb_msvdx_interrupt(struct drm_device *dev, uint32_t msvdx_stat) { struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK) { /*Ideally we should we should never get to this */ PSB_DEBUG_GENERAL ("******MSVDX: msvdx_stat: 0x%x fence2_irq_on=%d ***** (MMU FAULT)\n", msvdx_stat, dev_priv->fence2_irq_on); /* Pause MMU */ PSB_WMSVDX32(MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK, MSVDX_MMU_CONTROL0); DRM_WRITEMEMORYBARRIER(); /* Clear this interupt bit only */ PSB_WMSVDX32(MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK, MSVDX_INTERRUPT_CLEAR); PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR); DRM_READMEMORYBARRIER(); dev_priv->msvdx_needs_reset = 1; } else if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK) { PSB_DEBUG_GENERAL ("******MSVDX: msvdx_stat: 0x%x fence2_irq_on=%d ***** (MTX)\n", msvdx_stat, dev_priv->fence2_irq_on); /* Clear all interupt bits */ PSB_WMSVDX32(0xffff, MSVDX_INTERRUPT_CLEAR); PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR); DRM_READMEMORYBARRIER(); psb_msvdx_mtx_interrupt(dev); } }
static void msvdx_upload_fw(struct drm_psb_private *dev_priv, const uint32_t data_mem, uint32_t ram_bank_size, uint32_t address, const unsigned int words, const uint32_t * const data) { uint32_t loop, ctrl, ram_id, addr, cur_bank = (uint32_t) ~0; uint32_t access_ctrl; PSB_DEBUG_GENERAL("MSVDX: Upload firmware by register interface\n"); /* Save the access control register... */ access_ctrl = PSB_RMSVDX32(MTX_RAM_ACCESS_CONTROL_OFFSET); /* Wait for MCMSTAT to become be idle 1 */ psb_wait_for_register(dev_priv, MTX_RAM_ACCESS_STATUS_OFFSET, 1, /* Required Value */ 0xffffffff, /* Enables */ 2000000, 5); for (loop = 0; loop < words; loop++) { ram_id = data_mem + (address / ram_bank_size); if (ram_id != cur_bank) { addr = address >> 2; ctrl = 0; REGIO_WRITE_FIELD_LITE(ctrl, MTX_RAM_ACCESS_CONTROL, MTX_MCMID, ram_id); REGIO_WRITE_FIELD_LITE(ctrl, MTX_RAM_ACCESS_CONTROL, MTX_MCM_ADDR, addr); REGIO_WRITE_FIELD_LITE(ctrl, MTX_RAM_ACCESS_CONTROL, MTX_MCMAI, 1); PSB_WMSVDX32(ctrl, MTX_RAM_ACCESS_CONTROL_OFFSET); cur_bank = ram_id; } address += 4; PSB_WMSVDX32(data[loop], MTX_RAM_ACCESS_DATA_TRANSFER_OFFSET); /* Wait for MCMSTAT to become be idle 1 */ psb_wait_for_register(dev_priv, MTX_RAM_ACCESS_STATUS_OFFSET, 1, /* Required Value */ 0xffffffff, /* Enables */ 2000000, 5); }
static void msvdx_get_mtx_control_from_dash(struct drm_psb_private *dev_priv) { struct msvdx_private *msvdx_priv = dev_priv->msvdx_private; int count = 0; uint32_t reg_val = 0; REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_IS_SLAVE, 1); REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_GPIO_IN, 0x02); PSB_WMSVDX32(reg_val, MSVDX_MTX_DEBUG_OFFSET); do { reg_val = PSB_RMSVDX32(MSVDX_MTX_DEBUG_OFFSET); count++; } while (((reg_val & 0x18) != 0) && count < 50000); if (count >= 50000) PSB_DEBUG_GENERAL("MAVDX: timeout in get_mtx_control_from_dash\n"); /* Save the access control register...*/ msvdx_priv->psb_dash_access_ctrl = PSB_RMSVDX32(MTX_RAM_ACCESS_CONTROL_OFFSET); }
int psb_wait_for_register (struct drm_psb_private *dev_priv, uint32_t ui32Offset, uint32_t ui32Value, uint32_t ui32Enable) { uint32_t ui32Temp; uint32_t ui32PollCount = 1000; while (ui32PollCount) { ui32Temp = PSB_RMSVDX32 (ui32Offset); if (ui32Value == (ui32Temp & ui32Enable)) /* All the bits are reset */ return 0; /* So exit */ /* Wait a bit */ DRM_UDELAY (100); ui32PollCount--; } PSB_DEBUG_GENERAL ("MSVDX: Timeout while waiting for register %08x: expecting %08x (mask %08x), got %08x\n", ui32Offset, ui32Value, ui32Enable, ui32Temp); return 1; }
static void msvdx_upload_fw(struct drm_psb_private *dev_priv, uint32_t address, const unsigned int words, int fw_sel) { uint32_t reg_val = 0; uint32_t cmd; uint32_t uCountReg, offset, mmu_ptd; uint32_t size = (words * 4); /* byte count */ uint32_t dma_channel = 0; /* Setup a Simple DMA for Ch0 */ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private; PSB_DEBUG_GENERAL("MSVDX: Upload firmware by DMA\n"); msvdx_get_mtx_control_from_dash(dev_priv); /* dma transfers to/from the mtx have to be 32-bit aligned and in multiples of 32 bits */ PSB_WMSVDX32(address, MTX_SYSC_CDMAA_OFFSET); REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, BURSTSIZE, 4); /* burst size in multiples of 64 bits (allowed values are 2 or 4) */ REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, RNW, 0); /* false means write to mtx mem, true means read from mtx mem */ REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, ENABLE, 1); /* begin transfer */ REGIO_WRITE_FIELD_LITE(reg_val, MTX_SYSC_CDMAC, LENGTH, words); /* This specifies the transfer size of the DMA operation in terms of 32-bit words */ PSB_WMSVDX32(reg_val, MTX_SYSC_CDMAC_OFFSET); /* toggle channel 0 usage between mtx and other msvdx peripherals */ { reg_val = PSB_RMSVDX32(MSVDX_CONTROL_OFFSET); REGIO_WRITE_FIELD(reg_val, MSVDX_CONTROL, DMAC_CH0_SELECT, 0); PSB_WMSVDX32(reg_val, MSVDX_CONTROL_OFFSET); } /* Clear the DMAC Stats */ PSB_WMSVDX32(0 , DMAC_DMAC_IRQ_STAT_OFFSET + dma_channel); offset = msvdx_priv->fw->offset; if (fw_sel) offset += ((msvdx_priv->mtx_mem_size + 8192) & ~0xfff); /* use bank 0 */ cmd = 0; PSB_WMSVDX32(cmd, MSVDX_MMU_BANK_INDEX_OFFSET); /* Write PTD to mmu base 0*/ mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu); PSB_WMSVDX32(mmu_ptd, MSVDX_MMU_DIR_LIST_BASE_OFFSET + 0); /* Invalidate */ reg_val = PSB_RMSVDX32(MSVDX_MMU_CONTROL0_OFFSET); reg_val &= ~0xf; REGIO_WRITE_FIELD(reg_val, MSVDX_MMU_CONTROL0, MMU_INVALDC, 1); PSB_WMSVDX32(reg_val, MSVDX_MMU_CONTROL0_OFFSET); PSB_WMSVDX32(offset, DMAC_DMAC_SETUP_OFFSET + dma_channel); /* Only use a single dma - assert that this is valid */ if ((size / 4) >= (1 << 15)) { DRM_ERROR("psb: DMA size beyond limited, aboart firmware uploading\n"); return; } uCountReg = PSB_DMAC_VALUE_COUNT(PSB_DMAC_BSWAP_NO_SWAP, 0, /* 32 bits */ PSB_DMAC_DIR_MEM_TO_PERIPH, 0, (size / 4)); /* Set the number of bytes to dma*/ PSB_WMSVDX32(uCountReg, DMAC_DMAC_COUNT_OFFSET + dma_channel); cmd = PSB_DMAC_VALUE_PERIPH_PARAM(PSB_DMAC_ACC_DEL_0, PSB_DMAC_INCR_OFF, PSB_DMAC_BURST_2); PSB_WMSVDX32(cmd, DMAC_DMAC_PERIPH_OFFSET + dma_channel); /* Set destination port for dma */ cmd = 0; REGIO_WRITE_FIELD(cmd, DMAC_DMAC_PERIPHERAL_ADDR, ADDR, MTX_SYSC_CDMAT_OFFSET); PSB_WMSVDX32(cmd, DMAC_DMAC_PERIPHERAL_ADDR_OFFSET + dma_channel); /* Finally, rewrite the count register with the enable bit set*/ PSB_WMSVDX32(uCountReg | DMAC_DMAC_COUNT_EN_MASK, DMAC_DMAC_COUNT_OFFSET + dma_channel); /* Wait for all to be done */ if (psb_wait_for_register(dev_priv, DMAC_DMAC_IRQ_STAT_OFFSET + dma_channel, DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK, DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK, 2000000, 5)) { psb_setup_fw_dump(dev_priv, dma_channel); msvdx_release_mtx_control_from_dash(dev_priv); return; } /* Assert that the MTX DMA port is all done aswell */ if (psb_wait_for_register(dev_priv, MTX_SYSC_CDMAS0_OFFSET, 1, 1, 2000000, 5)) { msvdx_release_mtx_control_from_dash(dev_priv); return; } msvdx_release_mtx_control_from_dash(dev_priv); PSB_DEBUG_GENERAL("MSVDX: Upload done\n"); }
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; }
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; }