/* Try format */ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_fmt *fmt; mfc_debug(2, "Type is %d\n", f->type); if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { fmt = find_format(f, MFC_FMT_DEC); if (!fmt) { mfc_err("Unsupported format for source.\n"); return -EINVAL; } if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { mfc_err("Not supported format.\n"); return -EINVAL; } } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { fmt = find_format(f, MFC_FMT_RAW); if (!fmt) { mfc_err("Unsupported format for destination.\n"); return -EINVAL; } if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { mfc_err("Not supported format.\n"); return -EINVAL; } else if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { mfc_err("Not supported format.\n"); return -EINVAL; } } return 0; }
void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev, enum mfc_buf_usage_type buf_type) { struct s5p_mfc_extra_buf *fw_info; fw_info = &dev->fw_info; if (IS_MFCV6(dev)) { #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION if (buf_type == MFCBUF_DRM) fw_info = &dev->drm_fw_info; s5p_mfc_write_reg(dev, fw_info->ofs, S5P_FIMV_RISC_BASE_ADDRESS); mfc_info_dev("[%d] Base Address : %08lx\n", buf_type, fw_info->ofs); #else s5p_mfc_write_reg(dev, dev->port_a, S5P_FIMV_RISC_BASE_ADDRESS); mfc_debug(2, "Base Address : %08zu\n", dev->port_a); #endif } else { /* channelA, port0 */ s5p_mfc_write_reg(dev, dev->port_a, S5P_FIMV_MC_DRAMBASE_ADR_A); /* channelB, port1 */ s5p_mfc_write_reg(dev, dev->port_b, S5P_FIMV_MC_DRAMBASE_ADR_B); mfc_debug(2, "Port A: %08zu, Port B: %08zu\n", dev->port_a, dev->port_b); } }
int s5p_mfc_clock_on(struct s5p_mfc_dev *dev) { int ret = 0; int state, val; unsigned long flags; dev->pm.clock_on_steps = 1; MFC_TRACE_DEV("++ clock_on: Set clock rate(%d)\n", dev->curr_rate); ret = clk_enable(dev->pm.clock); if (ret < 0) return ret; if (dev->pm.base_type != MFCBUF_INVALID) s5p_mfc_init_memctrl(dev, dev->pm.base_type); dev->pm.clock_on_steps |= 0x1 << 1; if (dev->curr_ctx_drm && dev->is_support_smc) { spin_lock_irqsave(&dev->pm.clklock, flags); mfc_debug(3, "Begin: enable protection\n"); ret = exynos_smc(SMC_PROTECTION_SET, 0, dev->id, SMC_PROTECTION_ENABLE); dev->pm.clock_on_steps |= 0x1 << 2; if (!ret) { printk("Protection Enable failed! ret(%u)\n", ret); spin_unlock_irqrestore(&dev->pm.clklock, flags); clk_disable(dev->pm.clock); return -EACCES; } mfc_debug(3, "End: enable protection\n"); spin_unlock_irqrestore(&dev->pm.clklock, flags); } else { ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]); if (ret < 0) { dev->pm.clock_on_steps |= 0x1 << 3; clk_disable(dev->pm.clock); return ret; } } dev->pm.clock_on_steps |= 0x1 << 4; if (IS_MFCV6(dev)) { spin_lock_irqsave(&dev->pm.clklock, flags); if ((atomic_inc_return(&dev->clk_ref) == 1) && FW_HAS_BUS_RESET(dev)) { val = s5p_mfc_read_reg(dev, S5P_FIMV_MFC_BUS_RESET_CTRL); val &= ~(0x1); s5p_mfc_write_reg(dev, val, S5P_FIMV_MFC_BUS_RESET_CTRL); } spin_unlock_irqrestore(&dev->pm.clklock, flags); } else { atomic_inc_return(&dev->clk_ref); } dev->pm.clock_on_steps |= 0x1 << 5; state = atomic_read(&dev->clk_ref); mfc_debug(2, "+ %d\n", state); MFC_TRACE_DEV("-- clock_on : ref state(%d)\n", state); return 0; }
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) { int ret; mfc_debug_enter(); /* 0. MFC reset */ mfc_debug(2, "MFC reset...\n"); s5p_mfc_clock_on(); ret = s5p_mfc_reset(dev); if (ret) { mfc_err("Failed to reset MFC - timeout.\n"); return ret; } mfc_debug(2, "Done MFC reset...\n"); /* 1. Set DRAM base Addr */ s5p_mfc_init_memctrl(dev); /* 2. Initialize registers of channel I/F */ s5p_mfc_clear_cmds(dev); s5p_mfc_clean_dev_int_flags(dev); /* 3. Initialize firmware */ ret = s5p_mfc_wakeup_cmd(dev); if (ret) { mfc_err("Failed to send command to MFC - timeout.\n"); return ret; } /* 4. Release reset signal to the RISC */ if (IS_MFCV6(dev)) s5p_mfc_write_reg(0x1, S5P_FIMV_RISC_ON); else s5p_mfc_write_reg(0x3ff, S5P_FIMV_SW_RESET); mfc_debug(2, "Ok, now will write a command to wakeup the system\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) { mfc_err("Failed to load firmware\n"); return -EIO; } s5p_mfc_clock_off(); dev->int_cond = 0; if (dev->int_err != 0 || dev->int_type != S5P_FIMV_R2H_CMD_WAKEUP_RET) { /* Failure. */ mfc_err("Failed to wakeup - error: %d" " int: %d.\n",dev->int_err, dev->int_type); return -EIO; } mfc_debug_leave(); return 0; }
/* Reset the device */ static int s5p_mfc_reset(struct s5p_mfc_dev *dev) { int i; unsigned int mc_status; unsigned long timeout; mfc_debug_enter(); /* Stop procedure */ /* FIXME: F/W can be access invalid address */ /* Reset VI */ /* s5p_mfc_write_reg(0x3f7, S5P_FIMV_SW_RESET); */ if (IS_MFCV6(dev)) { /* Reset IP */ s5p_mfc_write_reg(0xFEE, S5P_FIMV_MFC_RESET); /* except RISC, reset */ s5p_mfc_write_reg(0x0, S5P_FIMV_MFC_RESET); /* reset release */ /* Zero Initialization of MFC registers */ s5p_mfc_write_reg(0, S5P_FIMV_RISC2HOST_CMD); s5p_mfc_write_reg(0, S5P_FIMV_HOST2RISC_CMD); s5p_mfc_write_reg(0, S5P_FIMV_FW_VERSION); for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++) s5p_mfc_write_reg(0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4)); /* Reset */ s5p_mfc_write_reg(0, S5P_FIMV_RISC_ON); s5p_mfc_write_reg(0x1FFF, S5P_FIMV_MFC_RESET); s5p_mfc_write_reg(0, S5P_FIMV_MFC_RESET); } else { s5p_mfc_write_reg(0x3f6, S5P_FIMV_SW_RESET); /* reset RISC */ s5p_mfc_write_reg(0x3e2, S5P_FIMV_SW_RESET); /* All reset except for MC */ mdelay(10); timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); /* Check MC status */ do { if (time_after(jiffies, timeout)) { mfc_err("Timeout while resetting MFC.\n"); return -EIO; } mc_status = s5p_mfc_read_reg(S5P_FIMV_MC_STATUS); } while (mc_status & 0x3); s5p_mfc_write_reg(0x0, S5P_FIMV_SW_RESET); s5p_mfc_write_reg(0x3fe, S5P_FIMV_SW_RESET); } mfc_debug_leave(); return 0; }
void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev) { if (IS_MFCV6(dev)) s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6(); else s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5(); dev->mfc_cmds = s5p_mfc_cmds; }
int s5p_mfc_clock_on(struct s5p_mfc_dev *dev) { int ret = 0; int state, val; unsigned long flags; #ifdef CONFIG_MFC_USE_BUS_DEVFREQ MFC_TRACE_DEV("++ clock_on: Set clock rate(%d)\n", dev->curr_rate); mutex_lock(&dev->curr_rate_lock); s5p_mfc_clock_set_rate(dev, dev->curr_rate); mutex_unlock(&dev->curr_rate_lock); #endif ret = clk_enable(dev->pm.clock); if (ret < 0) return ret; if (dev->curr_ctx_drm && dev->is_support_smc) { spin_lock_irqsave(&dev->pm.clklock, flags); mfc_debug(3, "Begin: enable protection\n"); ret = exynos_smc(SMC_PROTECTION_SET, 0, dev->id, SMC_PROTECTION_ENABLE); if (!ret) { printk("Protection Enable failed! ret(%u)\n", ret); spin_unlock_irqrestore(&dev->pm.clklock, flags); clk_disable(dev->pm.clock); return ret; } mfc_debug(3, "End: enable protection\n"); spin_unlock_irqrestore(&dev->pm.clklock, flags); } else { ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]); if (ret < 0) { clk_disable(dev->pm.clock); return ret; } } if (IS_MFCV6(dev)) { spin_lock_irqsave(&dev->pm.clklock, flags); if ((atomic_inc_return(&dev->clk_ref) == 1) && FW_HAS_BUS_RESET(dev)) { val = s5p_mfc_read_reg(dev, S5P_FIMV_MFC_BUS_RESET_CTRL); val &= ~(0x1); s5p_mfc_write_reg(dev, val, S5P_FIMV_MFC_BUS_RESET_CTRL); } spin_unlock_irqrestore(&dev->pm.clklock, flags); } else { atomic_inc_return(&dev->clk_ref); } state = atomic_read(&dev->clk_ref); mfc_debug(2, "+ %d\n", state); MFC_TRACE_DEV("-- clock_on : ref state(%d)\n", state); return 0; }
/* Deinitialize hardware */ void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev) { s5p_mfc_clock_on(); s5p_mfc_reset(dev); if (IS_MFCV6(dev)) s5p_mfc_release_dev_context_buffer(dev); s5p_mfc_clock_off(); }
void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev) { if (IS_MFCV6(dev)) { s5p_mfc_ops = s5p_mfc_init_hw_ops_v6(); dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6; } else { s5p_mfc_ops = s5p_mfc_init_hw_ops_v5(); dev->warn_start = S5P_FIMV_ERR_WARNINGS_START; } dev->mfc_ops = s5p_mfc_ops; }
void s5p_mfc_clock_off(struct s5p_mfc_dev *dev) { int state, val; unsigned long timeout, flags; int ret = 0; if (IS_MFCV6(dev)) { spin_lock_irqsave(&dev->pm.clklock, flags); if ((atomic_dec_return(&dev->clk_ref) == 0) && FW_HAS_BUS_RESET(dev)) { s5p_mfc_write_reg(dev, 0x1, S5P_FIMV_MFC_BUS_RESET_CTRL); timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); /* Check bus status */ do { if (time_after(jiffies, timeout)) { mfc_err_dev("Timeout while resetting MFC.\n"); break; } val = s5p_mfc_read_reg(dev, S5P_FIMV_MFC_BUS_RESET_CTRL); } while ((val & 0x2) == 0); } spin_unlock_irqrestore(&dev->pm.clklock, flags); } else { atomic_dec_return(&dev->clk_ref); } state = atomic_read(&dev->clk_ref); if (state < 0) { mfc_err_dev("Clock state is wrong(%d)\n", state); atomic_set(&dev->clk_ref, 0); } else { if (dev->curr_ctx_drm && dev->is_support_smc) { mfc_debug(3, "Begin: disable protection\n"); spin_lock_irqsave(&dev->pm.clklock, flags); ret = exynos_smc(SMC_PROTECTION_SET, 0, dev->id, SMC_PROTECTION_DISABLE); if (!ret) { printk("Protection Disable failed! ret(%u)\n", ret); spin_unlock_irqrestore(&dev->pm.clklock, flags); clk_disable(dev->pm.clock); return; } mfc_debug(3, "End: disable protection\n"); spin_unlock_irqrestore(&dev->pm.clklock, flags); } else { s5p_mfc_mem_suspend(dev->alloc_ctx[0]); } clk_disable(dev->pm.clock); } mfc_debug(2, "- %d\n", state); }
static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev) { if (IS_MFCV6(dev)) { /* Zero initialization should be done before RESET. * Nothing to do here. */ } else { s5p_mfc_write_reg(0xffffffff, S5P_FIMV_SI_CH0_INST_ID); s5p_mfc_write_reg(0xffffffff, S5P_FIMV_SI_CH1_INST_ID); s5p_mfc_write_reg(0, S5P_FIMV_RISC2HOST_CMD); s5p_mfc_write_reg(0, S5P_FIMV_HOST2RISC_CMD); } }
static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev) { if (IS_MFCV6(dev)) { s5p_mfc_write_reg(dev->port_a, S5P_FIMV_RISC_BASE_ADDRESS); mfc_debug(2, "Base Address : %08x\n", dev->port_a); } else { /* channelA, port0 */ s5p_mfc_write_reg(dev->port_a, S5P_FIMV_MC_DRAMBASE_ADR_A); /* channelB, port1 */ s5p_mfc_write_reg(dev->port_b, S5P_FIMV_MC_DRAMBASE_ADR_B); mfc_debug(2, "Port A: %08x, Port B: %08x\n", dev->port_a, dev->port_b); } }
int s5p_mfc_clock_on(void) { int ret = 0; int state, val; struct s5p_mfc_dev *dev = platform_get_drvdata(to_platform_device(pm->device)); unsigned long flags; #ifdef CONFIG_ARM_EXYNOS5410_BUS_DEVFREQ s5p_mfc_clock_set_rate(dev, dev->curr_rate); #endif ret = clk_enable(pm->clock); if (ret < 0) return ret; if (!dev->curr_ctx_drm) { ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]); if (ret < 0) { clk_disable(pm->clock); return ret; } } if (IS_MFCV6(dev)) { spin_lock_irqsave(&pm->clklock, flags); if ((atomic_inc_return(&clk_ref) == 1) && FW_HAS_BUS_RESET(dev)) { val = s5p_mfc_read_reg(S5P_FIMV_MFC_BUS_RESET_CTRL); val &= ~(0x1); s5p_mfc_write_reg(val, S5P_FIMV_MFC_BUS_RESET_CTRL); } spin_unlock_irqrestore(&pm->clklock, flags); } else { atomic_inc_return(&clk_ref); } state = atomic_read(&clk_ref); mfc_debug(3, "+ %d", state); return 0; }
void s5p_mfc_clock_off(void) { int state, val; unsigned long timeout, flags; struct s5p_mfc_dev *dev = platform_get_drvdata(to_platform_device(pm->device)); if (IS_MFCV6(dev)) { spin_lock_irqsave(&pm->clklock, flags); if ((atomic_dec_return(&clk_ref) == 0) && FW_HAS_BUS_RESET(dev)) { s5p_mfc_write_reg(0x1, S5P_FIMV_MFC_BUS_RESET_CTRL); timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); /* Check bus status */ do { if (time_after(jiffies, timeout)) { mfc_err("Timeout while resetting MFC.\n"); break; } val = s5p_mfc_read_reg( S5P_FIMV_MFC_BUS_RESET_CTRL); } while ((val & 0x2) == 0); } spin_unlock_irqrestore(&pm->clklock, flags); } else { atomic_dec_return(&clk_ref); } state = atomic_read(&clk_ref); if (state < 0) { mfc_err("Clock state is wrong(%d)\n", state); atomic_set(&clk_ref, 0); } else { if (!dev->curr_ctx_drm) s5p_mfc_mem_suspend(dev->alloc_ctx[0]); clk_disable(pm->clock); } }
/* Initialize hardware */ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) { char fimv_info; int fw_ver; int ret = 0; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } /* RMVME: */ if (!s5p_mfc_bitproc_buf) return -EINVAL; /* 0. MFC reset */ mfc_debug(2, "MFC reset...\n"); s5p_mfc_clock_on(); ret = s5p_mfc_reset(dev); if (ret) { mfc_err("Failed to reset MFC - timeout.\n"); goto err_init_hw; } mfc_debug(2, "Done MFC reset...\n"); /* 1. Set DRAM base Addr */ s5p_mfc_init_memctrl(dev); /* 2. Initialize registers of channel I/F */ s5p_mfc_clear_cmds(dev); s5p_mfc_clean_dev_int_flags(dev); /* 3. Release reset signal to the RISC */ if (IS_MFCV6(dev)) s5p_mfc_write_reg(0x1, S5P_FIMV_RISC_ON); else s5p_mfc_write_reg(0x3ff, S5P_FIMV_SW_RESET); mfc_debug(2, "Will now wait for completion of firmware transfer.\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) { mfc_err("Failed to load firmware.\n"); s5p_mfc_clean_dev_int_flags(dev); ret = -EIO; goto err_init_hw; } s5p_mfc_clean_dev_int_flags(dev); /* 4. Initialize firmware */ ret = s5p_mfc_sys_init_cmd(dev); if (ret) { mfc_err("Failed to send command to MFC - timeout.\n"); goto err_init_hw; } mfc_debug(2, "Ok, now will write a command to init the system\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) { mfc_err("Failed to load firmware\n"); ret = -EIO; goto err_init_hw; } dev->int_cond = 0; if (dev->int_err != 0 || dev->int_type != S5P_FIMV_R2H_CMD_SYS_INIT_RET) { /* Failure. */ mfc_err("Failed to init firmware - error: %d" " int: %d.\n", dev->int_err, dev->int_type); ret = -EIO; goto err_init_hw; } fimv_info = MFC_GET_REG(SYS_FW_FIMV_INFO); if (fimv_info != 'D' && fimv_info != 'E') fimv_info = 'N'; mfc_info("MFC v%x.%x, F/W: %02xyy, %02xmm, %02xdd (%c)\n", MFC_VER_MAJOR(dev), MFC_VER_MINOR(dev), MFC_GET_REG(SYS_FW_VER_YEAR), MFC_GET_REG(SYS_FW_VER_MONTH), MFC_GET_REG(SYS_FW_VER_DATE), fimv_info); dev->fw.date = MFC_GET_REG(SYS_FW_VER_ALL); /* Check MFC version and F/W version */ if (IS_MFCV6(dev) && FW_HAS_VER_INFO(dev)) { fw_ver = MFC_GET_REG(SYS_MFC_VER); if (fw_ver != mfc_version(dev)) { mfc_err("Invalid F/W version(0x%x) for MFC H/W(0x%x)\n", fw_ver, mfc_version(dev)); ret = -EIO; goto err_init_hw; } } err_init_hw: s5p_mfc_clock_off(); mfc_debug_leave(); return ret; }
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) { enum mfc_buf_usage_type buf_type; int ret; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } mfc_info_dev("curr_ctx_drm:%d\n", dev->curr_ctx_drm); dev->wakeup_status = 1; /* Set clock source again after wake up */ s5p_mfc_set_clock_parent(dev); /* 0. MFC reset */ mfc_debug(2, "MFC reset...\n"); s5p_mfc_clock_on(dev); dev->wakeup_status = 0; /* SYSMMU default block mode (not enalble/disable) */ if (dev->curr_ctx_drm) { ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]); if (ret < 0) mfc_err_dev("Failed to attach iommu\n"); s5p_mfc_mem_suspend(dev->alloc_ctx[0]); } ret = s5p_mfc_reset(dev); if (ret) { mfc_err_dev("Failed to reset MFC - timeout.\n"); goto err_mfc_wakeup; } mfc_debug(2, "Done MFC reset...\n"); if (dev->curr_ctx_drm) buf_type = MFCBUF_DRM; else buf_type = MFCBUF_NORMAL; /* 1. Set DRAM base Addr */ s5p_mfc_init_memctrl(dev, buf_type); /* 2. Initialize registers of channel I/F */ s5p_mfc_clear_cmds(dev); s5p_mfc_clean_dev_int_flags(dev); /* 3. Initialize firmware */ if (!FW_WAKEUP_AFTER_RISC_ON(dev)) ret = s5p_mfc_wakeup_cmd(dev); if (ret) { mfc_err_dev("Failed to send command to MFC - timeout.\n"); goto err_mfc_wakeup; } /* 4. Release reset signal to the RISC */ if (IS_MFCV6(dev)) s5p_mfc_write_reg(dev, 0x1, S5P_FIMV_RISC_ON); else s5p_mfc_write_reg(dev, 0x3ff, S5P_FIMV_SW_RESET); mfc_debug(2, "Will now wait for completion of firmware transfer.\n"); if (FW_WAKEUP_AFTER_RISC_ON(dev)) { if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) { mfc_err_dev("Failed to load firmware.\n"); s5p_mfc_clean_dev_int_flags(dev); ret = -EIO; goto err_mfc_wakeup; } } if (FW_WAKEUP_AFTER_RISC_ON(dev)) ret = s5p_mfc_wakeup_cmd(dev); mfc_debug(2, "Ok, now will write a command to wakeup the system\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) { mfc_err_dev("Failed to load firmware\n"); ret = -EIO; goto err_mfc_wakeup; } dev->int_cond = 0; if (dev->int_err != 0 || dev->int_type != S5P_FIMV_R2H_CMD_WAKEUP_RET) { /* Failure. */ mfc_err_dev("Failed to wakeup - error: %d" " int: %d.\n", dev->int_err, dev->int_type); ret = -EIO; goto err_mfc_wakeup; } err_mfc_wakeup: s5p_mfc_clock_off(dev); mfc_debug_leave(); return 0; }
/* Initialize hardware */ int mfc_init_hw(struct s5p_mfc_dev *dev, enum mfc_buf_usage_type buf_type) { char fimv_info; int fw_ver; int ret = 0; int curr_ctx_backup; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } curr_ctx_backup = dev->curr_ctx_drm; dev->sys_init_status = 0; /* RMVME: */ if (!dev->fw_info.alloc) return -EINVAL; /* 0. MFC reset */ mfc_debug(2, "MFC reset...\n"); /* At init time, do not call secure API */ if (buf_type == MFCBUF_NORMAL) dev->curr_ctx_drm = 0; else if (buf_type == MFCBUF_DRM) dev->curr_ctx_drm = 1; ret = s5p_mfc_clock_on(dev); if (ret) { mfc_err_dev("Failed to enable clock before reset(%d)\n", ret); dev->curr_ctx_drm = curr_ctx_backup; return ret; } dev->sys_init_status = 1; ret = s5p_mfc_reset(dev); if (ret) { mfc_err_dev("Failed to reset MFC - timeout.\n"); goto err_init_hw; } mfc_debug(2, "Done MFC reset...\n"); /* 1. Set DRAM base Addr */ s5p_mfc_init_memctrl(dev, buf_type); /* 2. Initialize registers of channel I/F */ s5p_mfc_clear_cmds(dev); s5p_mfc_clean_dev_int_flags(dev); /* 3. Release reset signal to the RISC */ if (IS_MFCV6(dev)) s5p_mfc_write_reg(dev, 0x1, S5P_FIMV_RISC_ON); else s5p_mfc_write_reg(dev, 0x3ff, S5P_FIMV_SW_RESET); mfc_debug(2, "Will now wait for completion of firmware transfer.\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) { mfc_err_dev("Failed to load firmware.\n"); s5p_mfc_clean_dev_int_flags(dev); ret = -EIO; goto err_init_hw; } s5p_mfc_clean_dev_int_flags(dev); /* 4. Initialize firmware */ ret = s5p_mfc_sys_init_cmd(dev, buf_type); if (ret) { mfc_err_dev("Failed to send command to MFC - timeout.\n"); goto err_init_hw; } mfc_debug(2, "Ok, now will write a command to init the system\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) { mfc_err_dev("Failed to load firmware\n"); ret = -EIO; goto err_init_hw; } dev->int_cond = 0; if (dev->int_err != 0 || dev->int_type != S5P_FIMV_R2H_CMD_SYS_INIT_RET) { /* Failure. */ mfc_err_dev("Failed to init firmware - error: %d" " int: %d.\n", dev->int_err, dev->int_type); ret = -EIO; goto err_init_hw; } fimv_info = MFC_GET_REG(SYS_FW_FIMV_INFO); if (fimv_info != 'D' && fimv_info != 'E') fimv_info = 'N'; mfc_info_dev("MFC v%x.%x, F/W: %02xyy, %02xmm, %02xdd (%c)\n", MFC_VER_MAJOR(dev), MFC_VER_MINOR(dev), MFC_GET_REG(SYS_FW_VER_YEAR), MFC_GET_REG(SYS_FW_VER_MONTH), MFC_GET_REG(SYS_FW_VER_DATE), fimv_info); dev->fw.date = MFC_GET_REG(SYS_FW_VER_ALL); /* Check MFC version and F/W version */ if (IS_MFCV6(dev) && FW_HAS_VER_INFO(dev)) { fw_ver = MFC_GET_REG(SYS_MFC_VER); if (fw_ver != mfc_version(dev)) { mfc_err_dev("Invalid F/W version(0x%x) for MFC H/W(0x%x)\n", fw_ver, mfc_version(dev)); ret = -EIO; goto err_init_hw; } } #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION /* Cache flush for base address change */ if (FW_HAS_BASE_CHANGE(dev)) { s5p_mfc_clean_dev_int_flags(dev); s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_CACHE_FLUSH, NULL); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET)) { mfc_err_dev("Failed to flush cache\n"); ret = -EIO; goto err_init_hw; } if (buf_type == MFCBUF_DRM && !curr_ctx_backup) { s5p_mfc_clock_off(dev); dev->curr_ctx_drm = curr_ctx_backup; s5p_mfc_clock_on_with_base(dev, MFCBUF_NORMAL); } else if (buf_type == MFCBUF_NORMAL && curr_ctx_backup) { s5p_mfc_init_memctrl(dev, MFCBUF_DRM); } } #endif err_init_hw: s5p_mfc_clock_off(dev); dev->curr_ctx_drm = curr_ctx_backup; mfc_debug_leave(); return ret; }
/* Set format */ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; struct s5p_mfc_fmt *fmt; struct v4l2_pix_format_mplane *pix_mp; mfc_debug_enter(); ret = vidioc_try_fmt(file, priv, f); pix_mp = &f->fmt.pix_mp; if (ret) return ret; if (ctx->vq_src.streaming || ctx->vq_dst.streaming) { v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__); ret = -EBUSY; goto out; } if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { fmt = find_format(f, MFC_FMT_RAW); if (!fmt) { mfc_err("Unsupported format for source.\n"); return -EINVAL; } if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { mfc_err("Not supported format.\n"); return -EINVAL; } else if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { mfc_err("Not supported format.\n"); return -EINVAL; } ctx->dst_fmt = fmt; mfc_debug_leave(); return ret; } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { mfc_err("Wrong type error for S_FMT : %d", f->type); return -EINVAL; } fmt = find_format(f, MFC_FMT_DEC); if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) { mfc_err("Unknown codec\n"); ret = -EINVAL; goto out; } if (fmt->type != MFC_FMT_DEC) { mfc_err("Wrong format selected, you should choose " "format for decoding\n"); ret = -EINVAL; goto out; } if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { mfc_err("Not supported format.\n"); return -EINVAL; } ctx->src_fmt = fmt; ctx->codec_mode = fmt->codec_mode; mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); pix_mp->height = 0; pix_mp->width = 0; if (pix_mp->plane_fmt[0].sizeimage) ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; else pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = DEF_CPB_SIZE; pix_mp->plane_fmt[0].bytesperline = 0; ctx->state = MFCINST_INIT; out: mfc_debug_leave(); return ret; }
/* Reset the device */ static int s5p_mfc_reset(struct s5p_mfc_dev *dev) { int i; unsigned int status; unsigned long timeout; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } /* Stop procedure */ /* Reset VI */ /* s5p_mfc_write_reg(dev, 0x3f7, S5P_FIMV_SW_RESET); */ if (IS_MFCV6(dev)) { /* Zero Initialization of MFC registers */ s5p_mfc_write_reg(dev, 0, S5P_FIMV_RISC2HOST_CMD); s5p_mfc_write_reg(dev, 0, S5P_FIMV_HOST2RISC_CMD); s5p_mfc_write_reg(dev, 0, S5P_FIMV_FW_VERSION); for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++) s5p_mfc_write_reg(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4)); if (IS_MFCv6X(dev)) if (s5p_mfc_bus_reset(dev)) return -EIO; if (!IS_MFCV8(dev)) s5p_mfc_write_reg(dev, 0, S5P_FIMV_RISC_ON); s5p_mfc_write_reg(dev, 0x1FFF, S5P_FIMV_MFC_RESET); s5p_mfc_write_reg(dev, 0, S5P_FIMV_MFC_RESET); } else { s5p_mfc_write_reg(dev, 0x3f6, S5P_FIMV_SW_RESET); /* reset RISC */ s5p_mfc_write_reg(dev, 0x3e2, S5P_FIMV_SW_RESET); /* All reset except for MC */ mdelay(10); timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); /* Check MC status */ do { if (time_after(jiffies, timeout)) { mfc_err_dev("Timeout while resetting MFC.\n"); return -EIO; } status = s5p_mfc_read_reg(dev, S5P_FIMV_MC_STATUS); } while (status & 0x3); s5p_mfc_write_reg(dev, 0x0, S5P_FIMV_SW_RESET); s5p_mfc_write_reg(dev, 0x3fe, S5P_FIMV_SW_RESET); } mfc_debug_leave(); return 0; }
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev) { int ret; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } /* 0. MFC reset */ mfc_debug(2, "MFC reset...\n"); s5p_mfc_clock_on(dev); ret = s5p_mfc_reset(dev); if (ret) { mfc_err_dev("Failed to reset MFC - timeout.\n"); goto err_mfc_wakeup; } mfc_debug(2, "Done MFC reset...\n"); /* 1. Set DRAM base Addr */ s5p_mfc_init_memctrl(dev, MFCBUF_NORMAL); /* 2. Initialize registers of channel I/F */ s5p_mfc_clear_cmds(dev); s5p_mfc_clean_dev_int_flags(dev); /* 3. Initialize firmware */ if (!IS_OVER_MFCv78(dev)) ret = s5p_mfc_wakeup_cmd(dev); if (ret) { mfc_err_dev("Failed to send command to MFC - timeout.\n"); goto err_mfc_wakeup; } /* 4. Release reset signal to the RISC */ if (IS_MFCV6(dev)) s5p_mfc_write_reg(dev, 0x1, S5P_FIMV_RISC_ON); else s5p_mfc_write_reg(dev, 0x3ff, S5P_FIMV_SW_RESET); mfc_debug(2, "Will now wait for completion of firmware transfer.\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) { mfc_err_dev("Failed to load firmware.\n"); s5p_mfc_clean_dev_int_flags(dev); ret = -EIO; goto err_mfc_wakeup; } if (IS_OVER_MFCv78(dev)) ret = s5p_mfc_wakeup_cmd(dev); mfc_debug(2, "Ok, now will write a command to wakeup the system\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) { mfc_err_dev("Failed to load firmware\n"); ret = -EIO; goto err_mfc_wakeup; } dev->int_cond = 0; if (dev->int_err != 0 || dev->int_type != S5P_FIMV_R2H_CMD_WAKEUP_RET) { /* Failure. */ mfc_err_dev("Failed to wakeup - error: %d" " int: %d.\n", dev->int_err, dev->int_type); ret = -EIO; goto err_mfc_wakeup; } err_mfc_wakeup: s5p_mfc_clock_off(dev); mfc_debug_leave(); return 0; }
/* Initialize hardware */ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev) { int ret; mfc_debug_enter(); /* RMVME: */ if (!s5p_mfc_bitproc_buf) return -EINVAL; /* 0. MFC reset */ mfc_debug(2, "MFC reset...\n"); s5p_mfc_clock_on(); ret = s5p_mfc_reset(dev); if (ret) { mfc_err("Failed to reset MFC - timeout.\n"); return ret; } mfc_debug(2, "Done MFC reset...\n"); /* 1. Set DRAM base Addr */ s5p_mfc_init_memctrl(dev); /* 2. Initialize registers of channel I/F */ s5p_mfc_clear_cmds(dev); /* 3. Release reset signal to the RISC */ if (IS_MFCV6(dev)) s5p_mfc_write_reg(0x1, S5P_FIMV_RISC_ON); else s5p_mfc_write_reg(0x3ff, S5P_FIMV_SW_RESET); mfc_debug(2, "Will now wait for completion of firmware transfer.\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) { mfc_err("Failed to load firmware.\n"); s5p_mfc_clean_dev_int_flags(dev); return -EIO; } s5p_mfc_clean_dev_int_flags(dev); /* 4. Initialize firmware */ ret = s5p_mfc_sys_init_cmd(dev); if (ret) { mfc_err("Failed to send command to MFC - timeout.\n"); return ret; } mfc_debug(2, "Ok, now will write a command to init the system\n"); if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) { mfc_err("Failed to load firmware\n"); return -EIO; } dev->int_cond = 0; if (dev->int_err != 0 || dev->int_type != S5P_FIMV_R2H_CMD_SYS_INIT_RET) { /* Failure. */ mfc_err("Failed to init firmware - error: %d" " int: %d.\n",dev->int_err, dev->int_type); return -EIO; } mfc_info("MFC F/W version : %02xyy, %02xmm, %02xdd\n", MFC_GET_REG(SYS_FW_VER_YEAR), MFC_GET_REG(SYS_FW_VER_MONTH), MFC_GET_REG(SYS_FW_VER_DATE)); s5p_mfc_clock_off(); mfc_debug_leave(); return 0; }