diff --git a/drivers/mxc/vpu-decoder-b0/Makefile b/drivers/mxc/vpu-decoder-b0/Makefile index 99505578b2c3..f0de32973ee7 100644 --- a/drivers/mxc/vpu-decoder-b0/Makefile +++ b/drivers/mxc/vpu-decoder-b0/Makefile @@ -2,7 +2,7 @@ ## Makefile for the VPU and M0 driver ## DEFINES += -D REBOOT=1 \ - -D BOOT_ARCH=0 + -D BOOT_ARCH=1 EXTRA_CFLAGS += $(DEFINES) diff --git a/drivers/mxc/vpu-decoder-b0/mediasys_types.h b/drivers/mxc/vpu-decoder-b0/mediasys_types.h index 047ac507f8fc..137f6f95316a 100644 --- a/drivers/mxc/vpu-decoder-b0/mediasys_types.h +++ b/drivers/mxc/vpu-decoder-b0/mediasys_types.h @@ -212,6 +212,7 @@ typedef enum { VID_API_EVENT_DBG_FIFO_DUMP = 0x23, VID_API_EVENT_DEC_CHECK_RES = 0x24, VID_API_EVENT_DEC_CFG_INFO = 0x25, + VID_API_EVENT_SNAPSHOT_DONE = 0x40, VID_API_EVENT_INVALID = 0xFF } TB_API_DEC_EVENT; diff --git a/drivers/mxc/vpu-decoder-b0/vpu_b0.c b/drivers/mxc/vpu-decoder-b0/vpu_b0.c index 6678286c81e0..8a817ea03298 100644 --- a/drivers/mxc/vpu-decoder-b0/vpu_b0.c +++ b/drivers/mxc/vpu-decoder-b0/vpu_b0.c @@ -1862,6 +1862,9 @@ static irqreturn_t fsl_vpu_mu_isr(int irq, void *This) } else if (msg == 0x55) { dev->firmware_started = true; complete(&dev->start_cmp); + } else if (msg == 0xA5) { + /*receive snapshot done msg and wakeup complete to suspend*/ + complete(&dev->snap_done_cmp); } else schedule_work(&dev->msg_work); @@ -2843,6 +2846,7 @@ static int vpu_probe(struct platform_device *pdev) mutex_init(&dev->dev_mutex); mutex_init(&dev->cmd_mutex); init_completion(&dev->start_cmp); + init_completion(&dev->snap_done_cmp); dev->firmware_started = false; dev->hang_mask = 0; dev->instance_mask = 0; @@ -2941,13 +2945,67 @@ static int vpu_runtime_resume(struct device *dev) return 0; } +#define CHECK_BIT(var, pos) (((var) >> (pos)) & 1) + +static void v4l2_vpu_send_snapshot(struct vpu_dev *dev) +{ + int i = 0; + int strIdx = (~dev->hang_mask) & (dev->instance_mask); + /*figure out the first available instance*/ + for (i = 0; i < VPU_MAX_NUM_STREAMS; i++) { + if (CHECK_BIT(strIdx, i)) + break; + } + + strIdx = i; + v4l2_vpu_send_cmd(dev->ctx[strIdx], strIdx, VID_API_CMD_SNAPSHOT, 0, NULL); +} + static int vpu_suspend(struct device *dev) { + struct vpu_dev *vpudev = (struct vpu_dev *)dev_get_drvdata(dev); + + if (vpudev->hang_mask != vpudev->instance_mask) { + + /*if there is an available device, send snapshot command to firmware*/ + v4l2_vpu_send_snapshot(vpudev); + + if (!wait_for_completion_timeout(&vpudev->snap_done_cmp, msecs_to_jiffies(1000))) { + vpu_dbg(LVL_ERR, "error: wait for snapdone event timeouti\n"); + return -1; + } + } + + vpu_set_power(vpudev, false); + return 0; } static int vpu_resume(struct device *dev) { + struct vpu_dev *vpudev = (struct vpu_dev *)dev_get_drvdata(dev); + void *csr_offset, *csr_cpuwait; + + vpu_set_power(vpudev, true); + vpu_enable_hw(vpudev); + + MU_Init(vpudev->mu_base_virtaddr); + MU_EnableRxFullInt(vpudev->mu_base_virtaddr, 0); + + if (vpudev->hang_mask == vpudev->instance_mask) { + /*no instance is active before suspend, do reset*/ + vpudev->fw_is_ready = false; + vpudev->firmware_started = false; + + rpc_init_shared_memory(&vpudev->shared_mem, vpudev->m0_rpc_phy - vpudev->m0_p_fw_space_phy, vpudev->m0_rpc_virt, SHARED_SIZE); + rpc_set_system_cfg_value(vpudev->shared_mem.pSharedInterface, VPU_REG_BASE); + } else { + /*resume*/ + csr_offset = ioremap(0x2d040000, 4); + writel(vpudev->m0_p_fw_space_phy, csr_offset); + csr_cpuwait = ioremap(0x2d040004, 4); + writel(0x0, csr_cpuwait); + } return 0; } diff --git a/drivers/mxc/vpu-decoder-b0/vpu_b0.h b/drivers/mxc/vpu-decoder-b0/vpu_b0.h index b8c041f23eed..7fcf58ad8fe4 100644 --- a/drivers/mxc/vpu-decoder-b0/vpu_b0.h +++ b/drivers/mxc/vpu-decoder-b0/vpu_b0.h @@ -191,6 +191,7 @@ struct vpu_dev { bool fw_is_ready; bool firmware_started; struct completion start_cmp; + struct completion snap_done_cmp; struct workqueue_struct *workqueue; struct work_struct msg_work; unsigned long instance_mask;