static int s5p_mfc_cmd_host2risc(int cmd, struct s5p_mfc_cmd_args *args) { int cur_cmd; unsigned long timeout; timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */ do { if (time_after(jiffies, timeout)) { mfc_err("Timeout while waiting for hardware.\n"); return -EIO; } cur_cmd = s5p_mfc_read_reg(S5P_FIMV_HOST2RISC_CMD); } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY); s5p_mfc_write_reg(args->arg[0], S5P_FIMV_HOST2RISC_ARG1); s5p_mfc_write_reg(args->arg[1], S5P_FIMV_HOST2RISC_ARG2); s5p_mfc_write_reg(args->arg[2], S5P_FIMV_HOST2RISC_ARG3); s5p_mfc_write_reg(args->arg[3], S5P_FIMV_HOST2RISC_ARG4); /* Issue the command */ s5p_mfc_write_reg(cmd, S5P_FIMV_HOST2RISC_CMD); 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); } }
/* Open a new instance and get its number */ int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev; int ret; mfc_debug_enter(); if (!ctx) { mfc_err("no mfc context to run\n"); return -EINVAL; } dev = ctx->dev; mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode); s5p_mfc_write_reg(dev, ctx->codec_mode, S5P_FIMV_CODEC_TYPE); s5p_mfc_write_reg(dev, ctx->ctx.ofs, S5P_FIMV_CONTEXT_MEM_ADDR); s5p_mfc_write_reg(dev, ctx->ctx_buf_size, S5P_FIMV_CONTEXT_MEM_SIZE); if (ctx->type == MFCINST_DECODER) s5p_mfc_write_reg(dev, ctx->dec_priv->crc_enable, S5P_FIMV_D_CRC_CTRL); ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE, NULL); mfc_debug_leave(); return ret; }
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; }
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); } }
int s5p_mfc_cmd_host2risc(int cmd, struct s5p_mfc_cmd_args *args) { mfc_debug(2, "Issue the command: %d\n", cmd); /* Reset RISC2HOST command */ s5p_mfc_write_reg(0x0, S5P_FIMV_RISC2HOST_CMD); /* Issue the command */ s5p_mfc_write_reg(cmd, S5P_FIMV_HOST2RISC_CMD); s5p_mfc_write_reg(0x1, S5P_FIMV_HOST2RISC_INT); return 0; }
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_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd, struct s5p_mfc_cmd_args *args) { mfc_debug(2, "Issue the command: %d\n", cmd); MFC_TRACE_DEV(">> Issue cmd : %d\n", cmd); /* Reset RISC2HOST command */ s5p_mfc_write_reg(dev, 0x0, S5P_FIMV_RISC2HOST_CMD); /* Issue the command */ s5p_mfc_write_reg(dev, cmd, S5P_FIMV_HOST2RISC_CMD); s5p_mfc_write_reg(dev, 0x1, S5P_FIMV_HOST2RISC_INT); return 0; }
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_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; }
int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev) { struct s5p_mfc_cmd_args h2r_args; struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->buf; int ret; mfc_debug_enter(); s5p_mfc_alloc_dev_context_buffer(dev); s5p_mfc_write_reg(dev->ctx_buf.ofs, S5P_FIMV_CONTEXT_MEM_ADDR); s5p_mfc_write_reg(buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE); ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args); mfc_debug_leave(); return ret; }
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); }
/* Open a new instance and get its number */ int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_cmd_args h2r_args; struct s5p_mfc_dec *dec = ctx->dec_priv; int ret; mfc_debug_enter(); mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode); s5p_mfc_write_reg(ctx->codec_mode, S5P_FIMV_CODEC_TYPE); s5p_mfc_write_reg(ctx->ctx.ofs, S5P_FIMV_CONTEXT_MEM_ADDR); s5p_mfc_write_reg(ctx->ctx_buf_size, S5P_FIMV_CONTEXT_MEM_SIZE); if (ctx->type == MFCINST_DECODER) s5p_mfc_write_reg(dec->crc_enable, S5P_FIMV_D_CRC_CTRL); ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_OPEN_INSTANCE, &h2r_args); mfc_debug_leave(); return ret; }
int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev, enum mfc_buf_usage_type buf_type) { struct s5p_mfc_buf_size_v6 *buf_size; struct s5p_mfc_extra_buf *ctx_buf, *dis_shm_buf; int ret; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } buf_size = dev->variant->buf_size->buf; ctx_buf = &dev->ctx_buf; dis_shm_buf = &dev->dis_shm_buf; #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION if (buf_type == MFCBUF_DRM) { ctx_buf = &dev->ctx_buf_drm; dis_shm_buf = &dev->dis_shm_buf_drm; } #endif s5p_mfc_write_reg(dev, ctx_buf->ofs, S5P_FIMV_CONTEXT_MEM_ADDR); s5p_mfc_write_reg(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE); if (IS_MFCv7X(dev)) { s5p_mfc_write_reg(dev, dis_shm_buf->ofs, S5P_FIMV_DIS_SHARED_MEM_ADDR); mfc_debug(2, "Setting shared memory = 0x%x\n", (unsigned int)dis_shm_buf->ofs); } ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, NULL); mfc_debug_leave(); return ret; }
/* Close instance */ int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_dev *dev = ctx->dev; int ret; mfc_debug_enter(); s5p_mfc_write_reg(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID); ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE, NULL); mfc_debug_leave(); return ret; }
/* Close instance */ int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx) { struct s5p_mfc_cmd_args h2r_args; int ret = 0; mfc_debug_enter(); if (ctx->state != MFCINST_FREE) { s5p_mfc_write_reg(ctx->inst_no, S5P_FIMV_INSTANCE_ID); ret = s5p_mfc_cmd_host2risc(S5P_FIMV_H2R_CMD_CLOSE_INSTANCE, &h2r_args); } else { ret = -EINVAL; } mfc_debug_leave(); return ret; }
static inline int s5p_mfc_bus_reset(struct s5p_mfc_dev *dev) { unsigned int status; unsigned long timeout; /* Reset */ 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"); return -EIO; } status = s5p_mfc_read_reg(S5P_FIMV_MFC_BUS_RESET_CTRL); } while ((status & 0x2) == 0); return 0; }
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); } }
/* 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(0x3f7, S5P_FIMV_SW_RESET); */ if (IS_MFCV6(dev)) { /* 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)); if (IS_MFCv6X(dev)) if (s5p_mfc_bus_reset(dev)) return -EIO; 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; } status = s5p_mfc_read_reg(S5P_FIMV_MC_STATUS); } while (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; }
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; }
/* 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; }
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) { 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; }
/* Reset the device */ static int s5p_mfc_reset(struct s5p_mfc_dev *dev) { int i; unsigned int 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(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"); return -EIO; } status = s5p_mfc_read_reg(S5P_FIMV_MFC_BUS_RESET_CTRL); } while ((status & 0x2) == 0); 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; } status = s5p_mfc_read_reg(S5P_FIMV_MC_STATUS); } while (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; }