staging: msvdx: support for non-DO firmware
authorTopi Pohjolainen <topi.pohjolainen@intel.com>
Fri, 27 Apr 2012 14:24:28 +0000 (17:24 +0300)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:31:07 +0000 (12:31 +0300)
Part of video hw driver update from UMG.

Signed-off-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
drivers/staging/mrst/imgv/psb_msvdx.c
drivers/staging/mrst/imgv/psb_msvdxinit.c

index a4b67c9..454b4ea 100644 (file)
@@ -381,6 +381,14 @@ static int psb_submit_video_cmdbuf(struct drm_device *dev,
        if (msvdx_priv->msvdx_needs_reset) {
                spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
 
+               PSB_DEBUG_GENERAL("MSVDX: will reset msvdx\n");
+               if (!IS_D0(dev)) {
+                       if (psb_msvdx_reset(dev_priv)) {
+                               ret = -EBUSY;
+                               DRM_ERROR("MSVDX: Reset failed\n");
+                               return ret;
+                       }
+               }
                msvdx_priv->msvdx_needs_reset = 0;
                msvdx_priv->msvdx_busy = 0;
 
@@ -840,8 +848,11 @@ loop: /* just for coding style check */
                                          " - resetting and ignoring error\n",
                                          fence);
 
-               msvdx_priv->msvdx_needs_reset |= MSVDX_RESET_NEEDS_REUPLOAD_FW |
+               if (IS_D0(dev))
+                       msvdx_priv->msvdx_needs_reset |= MSVDX_RESET_NEEDS_REUPLOAD_FW |
                                MSVDX_RESET_NEEDS_INIT_FW;
+               else
+                       msvdx_priv->msvdx_needs_reset = 1;
 
                if (msg_id == VA_MSGID_CMD_HW_PANIC) {
                        diff = msvdx_priv->msvdx_current_sequence
@@ -1083,8 +1094,13 @@ done:
                goto loop;
        }
        /* we get a frame/slice done, try to save some power*/
-       if (drm_msvdx_pmpolicy == PSB_PMPOLICY_POWERDOWN)
-               schedule_delayed_work(&dev_priv->scheduler.msvdx_suspend_wq, 0);
+       if (IS_D0(dev)) {
+               if (drm_msvdx_pmpolicy == PSB_PMPOLICY_POWERDOWN)
+                       schedule_delayed_work(&dev_priv->scheduler.msvdx_suspend_wq, 0);
+       } else {
+               if (drm_msvdx_pmpolicy != PSB_PMPOLICY_NOPM)
+                       schedule_delayed_work(&dev_priv->scheduler.msvdx_suspend_wq, 0);
+       }
 
        DRM_MEMORYBARRIER();    /* TBD check this... */
 }
@@ -1119,14 +1135,34 @@ IMG_BOOL psb_msvdx_interrupt(IMG_VOID *pvData)
         * if HW/FW is totally hang, the lockup function will handle
         * the reseting when firmware is loaded w/o the driver
         */
+       if (!IS_D0(dev) &&
+           (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK)) {
+               /*Ideally we should we should never get to this */
+               PSB_DEBUG_IRQ("MSVDX:MMU Fault:0x%x\n", msvdx_stat);
+
+               /* 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();
 
-       if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK) {
+               msvdx_priv->msvdx_needs_reset = 1;
+       } else if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK) {
                PSB_DEBUG_IRQ
-               ("MSVDX: msvdx_stat: 0x%x(MTX)\n", msvdx_stat);
+                       ("MSVDX: msvdx_stat: 0x%x(MTX)\n", msvdx_stat);
+
+               /* Clear all interupt bits */
+               if (IS_D0(dev))
+                       PSB_WMSVDX32(MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK,
+                                    MSVDX_INTERRUPT_CLEAR);
+               else
+                       PSB_WMSVDX32(0xffff, MSVDX_INTERRUPT_CLEAR);
 
-               /* Clear this interupt bit */
-               PSB_WMSVDX32(MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK,
-                               MSVDX_INTERRUPT_CLEAR);
                PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
                DRM_READMEMORYBARRIER();
 
@@ -1188,12 +1224,12 @@ int psb_check_msvdx_idle(struct drm_device *dev)
                return -EBUSY;
        }
 
-       PSB_DEBUG_MSVDX("SIGNATURE is %x\n",
-                       PSB_RMSVDX32(MSVDX_COMMS_SIGNATURE));
+       if (IS_D0(dev)) {
+               PSB_DEBUG_MSVDX("   SIGNITURE is %x\n", PSB_RMSVDX32(MSVDX_COMMS_SIGNATURE));
 
-       if (!(PSB_RMSVDX32(MSVDX_COMMS_FW_STATUS) &
-                               MSVDX_FW_STATUS_HW_IDLE))
-               return -EBUSY;
+               if (!(PSB_RMSVDX32(MSVDX_COMMS_FW_STATUS) & MSVDX_FW_STATUS_HW_IDLE))
+                       return -EBUSY;
+       }
        /*
                if (msvdx_priv->msvdx_hw_busy) {
                        PSB_DEBUG_PM("MSVDX: %s, HW is busy\n", __func__);
@@ -1388,7 +1424,10 @@ int psb_msvdx_save_context(struct drm_device *dev)
        struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
        int offset = 0;
 
-       msvdx_priv->msvdx_needs_reset = MSVDX_RESET_NEEDS_INIT_FW;
+       if (IS_D0(dev))
+               msvdx_priv->msvdx_needs_reset = MSVDX_RESET_NEEDS_INIT_FW;
+       else
+               msvdx_priv->msvdx_needs_reset = 1;
 
        for (offset = 0; offset < VEC_LOCAL_MEM_BYTE_SIZE / 4; ++offset)
                msvdx_priv->vec_local_mem_data[offset] =
@@ -1396,9 +1435,12 @@ int psb_msvdx_save_context(struct drm_device *dev)
 
        msvdx_priv->vec_local_mem_saved = 1;
 
-       PSB_WMSVDX32(0, MSVDX_MTX_ENABLE);
-       psb_msvdx_reset(dev_priv);
-       PSB_WMSVDX32(0, MSVDX_MAN_CLK_ENABLE);
+       if (IS_D0(dev)) {
+               PSB_WMSVDX32(0, MSVDX_MTX_ENABLE);
+               psb_msvdx_reset(dev_priv);
+               PSB_WMSVDX32(0, MSVDX_MAN_CLK_ENABLE);
+       }
+
        return 0;
 }
 
index 9acfd22..4a15c37 100644 (file)
@@ -509,19 +509,19 @@ int psb_setup_fw(struct drm_device *dev)
 {
        struct drm_psb_private *dev_priv = dev->dev_private;
        uint32_t ram_bank_size;
-       struct msvdx_fw *fw;
-       uint32_t *fw_ptr = NULL;
-       uint32_t *text_ptr = NULL;
-       uint32_t *data_ptr = NULL;
-       const struct firmware *raw = NULL;
        struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
-       int ec_firmware = 0, ret = 0;
-       uint32_t init_msg[FW_DEVA_INIT_SIZE];
+       int ret = 0;
 
        /* todo : Assert the clock is on - if not turn it on to upload code */
        PSB_DEBUG_GENERAL("MSVDX: psb_setup_fw\n");
        PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
 
+       if (!IS_D0(dev)) {
+               /* Reset MTX */
+               PSB_WMSVDX32(MSVDX_MTX_SOFT_RESET_MTX_RESET_MASK,
+                               MSVDX_MTX_SOFT_RESET);
+       }
+
        /* Initialses Communication controll area to 0 */
        /*
          if (psb_rev_id >= POULSBO_D1) {
@@ -539,8 +539,27 @@ int psb_setup_fw(struct drm_device *dev)
 
        PSB_WMSVDX32(FIRMWAREID, MSVDX_COMMS_FIRMWARE_ID);
 
-       PSB_WMSVDX32(0, MSVDX_EXT_FW_ERROR_STATE); /* EXT_FW_ERROR_STATE */
-
+       if (!IS_D0(dev)) {
+               PSB_WMSVDX32(0, MSVDX_COMMS_ERROR_TRIG);
+               PSB_WMSVDX32(199, MSVDX_MTX_SYSC_TIMERDIV); /* MTX_SYSC_TIMERDIV */
+               PSB_WMSVDX32(0, MSVDX_EXT_FW_ERROR_STATE); /* EXT_FW_ERROR_STATE */
+               PSB_WMSVDX32(0, MSVDX_COMMS_MSG_COUNTER);
+               PSB_WMSVDX32(0, MSVDX_COMMS_SIGNATURE);
+               PSB_WMSVDX32(0, MSVDX_COMMS_TO_HOST_RD_INDEX);
+               PSB_WMSVDX32(0, MSVDX_COMMS_TO_HOST_WRT_INDEX);
+               PSB_WMSVDX32(0, MSVDX_COMMS_TO_MTX_RD_INDEX);
+               PSB_WMSVDX32(0, MSVDX_COMMS_TO_MTX_WRT_INDEX);
+               PSB_WMSVDX32(0, MSVDX_COMMS_FW_STATUS);
+               PSB_WMSVDX32(DSIABLE_IDLE_GPIO_SIG
+                       | DSIABLE_Auto_CLOCK_GATING
+                       | RETURN_VDEB_DATA_IN_COMPLETION,
+                               MSVDX_COMMS_OFFSET_FLAGS);
+               PSB_WMSVDX32(0, MSVDX_COMMS_SIGNATURE);
+       } else {
+               /* we should restore the state, if we power down/up
+                * during EC */
+               PSB_WMSVDX32(0, MSVDX_EXT_FW_ERROR_STATE); /* EXT_FW_ERROR_STATE */
+       }
        /* read register bank size */
        {
                uint32_t bank_size, reg;
@@ -554,6 +573,14 @@ int psb_setup_fw(struct drm_device *dev)
        PSB_DEBUG_GENERAL("MSVDX: RAM bank size = %d bytes\n",
                          ram_bank_size);
 
+    if (!IS_D0(dev)) {
+        struct msvdx_fw *fw;
+        uint32_t *fw_ptr = NULL;
+        uint32_t *text_ptr = NULL;
+        uint32_t *data_ptr = NULL;
+        const struct firmware *raw = NULL;
+        int ec_firmware = 0;
+
        /* if FW already loaded from storage */
        if (msvdx_priv->msvdx_fw)
                fw_ptr = msvdx_priv->msvdx_fw;
@@ -655,6 +682,7 @@ int psb_setup_fw(struct drm_device *dev)
 
                /*      -- Turn on the thread   */
                PSB_WMSVDX32(MSVDX_MTX_ENABLE_MTX_ENABLE_MASK, MSVDX_MTX_ENABLE);
+       }
 
        /* Wait for the signature value to be written back */
        ret = psb_wait_for_register(dev_priv, MSVDX_COMMS_SIGNATURE,
@@ -668,29 +696,29 @@ int psb_setup_fw(struct drm_device *dev)
        PSB_DEBUG_GENERAL("MSVDX: MTX Initial indications OK\n");
        PSB_DEBUG_GENERAL("MSVDX: MSVDX_COMMS_AREA_ADDR = %08x\n",
                          MSVDX_COMMS_AREA_ADDR);
-       /*
-        * at this stage, FW is uplaoded successfully, can send rendec
-        * init message
-        */
-       /* send INIT cmd for RENDEC init */
-       PSB_WMSVDX32(DSIABLE_IDLE_GPIO_SIG | DSIABLE_Auto_CLOCK_GATING
-                    | RETURN_VDEB_DATA_IN_COMPLETION,
-                    MSVDX_COMMS_OFFSET_FLAGS);
-
-       MEMIO_WRITE_FIELD(init_msg, FWRK_GENMSG_SIZE,
-                       FW_DEVA_INIT_SIZE);
-       MEMIO_WRITE_FIELD(init_msg, FWRK_GENMSG_ID,
-                       FW_DEVA_INIT_ID);
-
-       MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_ADDR0,
-                       msvdx_priv->base_addr0);
-       MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_ADDR1,
-                       msvdx_priv->base_addr1);
-       MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_SIZE0,
-                       RENDEC_A_SIZE / (4*1024));
-       MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_SIZE1,
-                       RENDEC_B_SIZE / (4*1024));
-       psb_mtx_send(dev_priv, init_msg);
+       if (IS_D0(dev)) {
+               /*
+                * at this stage, FW is uplaoded successfully, can send rendec
+                * init message
+                */
+               uint32_t init_msg[FW_DEVA_INIT_SIZE];
+
+               /* send INIT cmd for RENDEC init */
+               PSB_WMSVDX32(DSIABLE_IDLE_GPIO_SIG | DSIABLE_Auto_CLOCK_GATING
+                            | RETURN_VDEB_DATA_IN_COMPLETION,
+                            MSVDX_COMMS_OFFSET_FLAGS);
+
+               MEMIO_WRITE_FIELD(init_msg, FWRK_GENMSG_SIZE,
+                                 FW_DEVA_INIT_SIZE);
+               MEMIO_WRITE_FIELD(init_msg, FWRK_GENMSG_ID,
+                                 FW_DEVA_INIT_ID);
+
+               MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_ADDR0, msvdx_priv->base_addr0);
+               MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_ADDR1, msvdx_priv->base_addr1);
+               MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_SIZE0, RENDEC_A_SIZE / (4*1024));
+               MEMIO_WRITE_FIELD(init_msg, FW_DEVA_INIT_RENDEC_SIZE1, RENDEC_B_SIZE / (4*1024));
+               psb_mtx_send(dev_priv, init_msg);
+       }
 
 #if 0
 
@@ -735,14 +763,17 @@ int psb_msvdx_reset(struct drm_psb_private *dev_priv)
        int ret = 0;
 
        if (IS_PENWELL(dev_priv->dev)) {
-               uint32_t core_rev;
-               /* Enable Clocks */
-               PSB_DEBUG_GENERAL("Enabling clocks\n");
-               PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
-
-               /* Always pause the MMU as the core may be still active when resetting.  It is very bad to have memory
-                  activity at the same time as a reset - Very Very bad */
-               PSB_WMSVDX32(2, MSVDX_MMU_CONTROL0);
+               if (IS_D0(dev_priv->dev)) {
+                       uint32_t core_rev;
+                       /* Enable Clocks */
+                       PSB_DEBUG_GENERAL("Enabling clocks\n");
+                       PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+                       /* Always pause the MMU as the core may be still active
+                        * when resetting.  It is very bad to have memory
+                        * activity at the same time as a reset - Very Very bad
+                        */
+                       PSB_WMSVDX32(2, MSVDX_MMU_CONTROL0);
 
                        core_rev = PSB_RMSVDX32(MSVDX_CORE_REV);
                        if (core_rev < 0x00050502) {
@@ -819,6 +850,20 @@ int psb_msvdx_reset(struct drm_psb_private *dev_priv)
                                }
                        }
                        goto out;
+               } else {
+                       int loop;
+                       /* Enable Clocks */
+                       PSB_DEBUG_GENERAL("Enabling clocks\n");
+                       PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+                       /* Always pause the MMU as the core may be still active when resetting.  It is very bad to have memory
+                          activity at the same time as a reset - Very Very bad */
+                       PSB_WMSVDX32(2, MSVDX_MMU_CONTROL0);
+                       for (loop = 0; loop < 50; loop++)
+                               ret = psb_wait_for_register(dev_priv, MSVDX_MMU_MEM_REQ, 0,
+                                               0xff);
+                       if (ret)
+                               return ret;
+               }
 
        }
        /* Issue software reset */
@@ -983,6 +1028,10 @@ int psb_msvdx_init(struct drm_device *dev)
                PSB_WMSVDX32(8200, REGISTER(MSVDX_CORE, CR_BE_MSVDX_WDT_COMPAREMATCH));
                PSB_WMSVDX32(reg_val, REGISTER(MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL));
        */
+       if (!IS_D0(dev)) {
+               /* Enable MMU by removing all bypass bits */
+               PSB_WMSVDX32(0, MSVDX_MMU_CONTROL0);
+       }
 
        /* move firmware loading to the place receiving first command buffer */
 
@@ -1036,6 +1085,17 @@ int psb_msvdx_init(struct drm_device *dev)
        PSB_DEBUG_GENERAL("MSVDX: RENDEC A: %08x RENDEC B: %08x\n",
                          msvdx_priv->base_addr0, msvdx_priv->base_addr1);
 
+       if (!IS_D0(dev)) {
+               PSB_WMSVDX32(msvdx_priv->base_addr0, MSVDX_RENDEC_BASE_ADDR0);
+               PSB_WMSVDX32(msvdx_priv->base_addr1, MSVDX_RENDEC_BASE_ADDR1);
+
+               cmd = 0;
+               REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_BUFFER_SIZE,
+                               RENDEC_BUFFER_SIZE0, RENDEC_A_SIZE / 4096);
+               REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_BUFFER_SIZE,
+                               RENDEC_BUFFER_SIZE1, RENDEC_B_SIZE / 4096);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_BUFFER_SIZE);
+       }
        if (!msvdx_priv->fw) {
                uint32_t core_rev;
 
@@ -1059,6 +1119,31 @@ int psb_msvdx_init(struct drm_device *dev)
                        goto err_exit;
                }
        }
+       if (!IS_D0(dev)) {
+               cmd = 0;
+               REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                               RENDEC_DECODE_START_SIZE, 0);
+               REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                               RENDEC_BURST_SIZE_W, 1);
+               REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                               RENDEC_BURST_SIZE_R, 1);
+               REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+                               RENDEC_EXTERNAL_MEMORY, 1);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTROL1);
+
+               cmd = 0x00101010;
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT0);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT1);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT2);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT3);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT4);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT5);
+
+               cmd = 0;
+               REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL0, RENDEC_INITIALISE,
+                               1);
+               PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTROL0);
+       }
 
        /* PSB_WMSVDX32(clk_enable_minimal, MSVDX_MAN_CLK_ENABLE); */
        PSB_DEBUG_INIT("MSVDX:defer firmware loading to the"
@@ -1066,8 +1151,18 @@ int psb_msvdx_init(struct drm_device *dev)
 
        msvdx_priv->msvdx_fw_loaded = 0; /* need to load firware */
 
-       PSB_WMSVDX32(0x334, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
-       PSB_WMSVDX32(0x2008, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+       if (!IS_D0(dev)) {
+               /* it should be set at punit post boot init phase */
+               PSB_WMSVDX32(820, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
+               PSB_WMSVDX32(8200, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+
+               PSB_WMSVDX32(820, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
+               PSB_WMSVDX32(8200, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+       } else {
+               /* for the other two, use the default value punit set */
+               PSB_WMSVDX32(0x334, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
+               PSB_WMSVDX32(0x2008, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+       }
 
        psb_msvdx_clearirq(dev);
        psb_msvdx_enableirq(dev);
@@ -1075,6 +1170,16 @@ int psb_msvdx_init(struct drm_device *dev)
        PSB_DEBUG_INIT("MSDVX:old clock gating disable = 0x%08x\n",
                PSB_RVDC32(PSB_MSVDX_CLOCKGATING));
 
+       if (!IS_D0(dev)) {
+               cmd = 0;
+               cmd = PSB_RMSVDX32(MSVDX_VEC_SHIFTREG_CONTROL); /* VEC_SHIFTREG_CONTROL */
+               REGIO_WRITE_FIELD(cmd,
+                                 VEC_SHIFTREG_CONTROL,
+                                 SR_MASTER_SELECT,
+                                 1);  /* Host */
+               PSB_WMSVDX32(cmd, MSVDX_VEC_SHIFTREG_CONTROL);
+       }
+
 #if 0
        ret = psb_setup_fw(dev);
        if (ret)