static int mfc_resume(struct platform_device *pdev) { int ret = 0; unsigned int mc_status; #if ENABLE_MONITORING_MFC_DD mfc_info("mfc_resume......#1\n"); #endif mutex_lock(&mfc_mutex); if (!mfc_is_running()) { #if ENABLE_MONITORING_MFC_DD mfc_info("mfc_resume......#2-0\n"); #endif mutex_unlock(&mfc_mutex); return 0; } #if ENABLE_MONITORING_MFC_DD mfc_info("mfc_resume......#2-1\n"); #endif #if Frame_Base_Power_CTR_ON clk_enable(mfc_clk); #endif /* * 1. MFC reset */ do { mc_status = READL(MFC_MC_STATUS); } while(mc_status != 0); mfc_cmd_reset(); WRITEL(mfc_port0_base_paddr, MFC_MC_DRAMBASE_ADDR_A); WRITEL(mfc_port1_base_paddr, MFC_MC_DRAMBASE_ADDR_B); WRITEL(1, MFC_NUM_MASTER); ret = mfc_set_wakeup(); if(ret != MFCINST_RET_OK){ mutex_unlock(&mfc_mutex); return ret; } #if Frame_Base_Power_CTR_ON clk_disable(mfc_clk); #endif mutex_unlock(&mfc_mutex); return 0; }
/* Deinitialize hardware */ void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev) { mfc_info("mfc deinit start\n"); if (!dev) { mfc_err("no mfc device to run\n"); return; } s5p_mfc_clock_on(); s5p_mfc_reset(dev); s5p_mfc_clock_off(); mfc_info("mfc deinit completed\n"); }
static int mfc_remove(struct platform_device *pdev) { #if ENABLE_MONITORING_MFC_DD mfc_info("remove mfc memory region, register\n"); #endif iounmap(mfc_sfr_base_vaddr); iounmap(mfc_port0_base_vaddr); /* remove memory region */ if (mfc_mem != NULL) { release_resource(mfc_mem); kfree(mfc_mem); mfc_mem = NULL; } free_irq(IRQ_MFC, pdev); mutex_destroy(&mfc_mutex); clk_put(mfc_clk); misc_deregister(&mfc_miscdev); return 0; }
static int mfc_suspend(struct platform_device *pdev, pm_message_t state) { int ret = 0; #if ENABLE_MONITORING_MFC_DD mfc_info("mfc_suspend......#1\n"); #endif mutex_lock(&mfc_mutex); if (!mfc_is_running()) { #if ENABLE_MONITORING_MFC_DD mfc_info("mfc_suspend......#2-0\n"); #endif mutex_unlock(&mfc_mutex); return 0; } #if Frame_Base_Power_CTR_ON if (s5pv210_pd_enable("mfc_pd") < 0) { printk(KERN_ERR "[Error]The power is not on for mfc\n"); return -1; } clk_enable(mfc_clk); #endif #if ENABLE_MONITORING_MFC_DD mfc_info("mfc_suspend......#2-1\n"); #endif ret = mfc_set_sleep(); if(ret != MFCINST_RET_OK){ mutex_unlock(&mfc_mutex); return ret; } #if Frame_Base_Power_CTR_ON clk_disable(mfc_clk); #endif mutex_unlock(&mfc_mutex); return 0; }
static int __init s3c_mfc_init(void) { printk(banner); #ifdef CONFIG_S3C6400_PDFW pd_register_dev(&s3c_mfc_pmdev, "domain_v"); mfc_info("mfc devid = %d\n", s3c_mfc_pmdev.devid); #endif if (platform_driver_register(&s3c_mfc_driver) != 0) { mfc_err("fail to register platform device\n"); return -EPERM; } mfc_info("%s", banner); return 0; }
static int mfc_release(struct inode *inode, struct file *file) { mfc_inst_ctx *mfc_ctx; int ret; #if ENABLE_MONITORING_MFC_DD mfc_info("MFC Release..\n"); #endif mutex_lock(&mfc_mutex); #if Frame_Base_Power_CTR_ON clk_enable(mfc_clk); #endif mfc_ctx = (mfc_inst_ctx *)file->private_data; if (mfc_ctx == NULL) { mfc_err("MFCINST_ERR_INVALID_PARAM\n"); ret = -EIO; goto out_release; } mfc_release_all_buffer(mfc_ctx->mem_inst_no); mfc_merge_fragment(mfc_ctx->mem_inst_no); mfc_return_mem_inst_no(mfc_ctx->mem_inst_no); /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); kfree(mfc_ctx); ret = 0; out_release: if (!mfc_is_running()) { #ifdef CONFIG_CPU_FREQ s5pc110_unlock_dvfs_high_level(DVFS_LOCK_TOKEN_1); #endif #ifdef CONFIG_PM_PWR_GATING s5pc110_unlock_power_domain(MFC_DOMAIN_LOCK_TOKEN); #endif #ifdef CONFIG_S5PC11X_LPAUDIO s5pc110_set_lpaudio_lock(0); #endif /* CONFIG_S5PC11X_LPAUDIO */ } clk_disable(mfc_clk); mutex_unlock(&mfc_mutex); return ret; }
/* Load firmware to MFC */ int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev) { struct firmware *fw_blob; unsigned int firmware_size; int err; if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } firmware_size = dev->variant->buf_size->firmware_code; /* Firmare has to be present as a separate file or compiled * into kernel. */ mfc_debug_enter(); mfc_info("Requesting fw\n"); err = request_firmware((const struct firmware **)&fw_blob, MFC_FW_NAME, dev->v4l2_dev.dev); if (err != 0) { mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel.\n"); return -EINVAL; } mfc_debug(2, "Ret of request_firmware: %d Size: %d\n", err, fw_blob->size); if (fw_blob->size > firmware_size) { mfc_err("MFC firmware is too big to be loaded.\n"); release_firmware(fw_blob); return -ENOMEM; } if (s5p_mfc_bitproc_buf == 0 || s5p_mfc_bitproc_phys == 0) { mfc_err("MFC firmware is not allocated or was not mapped correctly.\n"); release_firmware(fw_blob); return -EINVAL; } memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size); /* s5p_mfc_bitproc_dma = dma_map_single(dev->v4l2_dev.dev, s5p_mfc_bitproc_virt, FIRMWARE_CODE_SIZE, DMA_TO_DEVICE); */ s5p_mfc_mem_clean_priv(s5p_mfc_bitproc_buf, s5p_mfc_bitproc_virt, 0, fw_blob->size); dev->fw.dva = s5p_mfc_bitproc_phys; dev->fw.kva = s5p_mfc_bitproc_virt; dev->fw.ctx = s5p_mfc_bitproc_buf; dev->fw.size = fw_blob->size; release_firmware(fw_blob); mfc_debug_leave(); return 0; }
static int __init mfc_init(void) { mfc_info("%s\n", banner); if (platform_driver_register(&mfc_driver) != 0) { mfc_err(KERN_ERR "platform device registration failed..\n"); return -1; } return 0; }
int s5p_mfc_init_pm(struct s5p_mfc_dev *dev) { int ret = 0; pm = &dev->pm; p_dev = dev; pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME); if (IS_ERR(pm->clock_gate)) { mfc_err("Failed to get clock-gating control\n"); ret = PTR_ERR(pm->clock_gate); goto err_g_ip_clk; } ret = clk_prepare(pm->clock_gate); if (ret) { mfc_err("Failed to prepare clock-gating control\n"); goto err_p_ip_clk; } if (dev->variant->version != MFC_VERSION_V6) { pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME); if (IS_ERR(pm->clock)) { mfc_info("Failed to get MFC special clock control\n"); pm->clock = NULL; } else { clk_set_rate(pm->clock, MFC_SCLK_RATE); ret = clk_prepare_enable(pm->clock); if (ret) { mfc_err("Failed to enable MFC special clock\n"); goto err_s_clk; } } } atomic_set(&pm->power, 0); #ifdef CONFIG_PM pm->device = &dev->plat_dev->dev; pm_runtime_enable(pm->device); #endif #ifdef CLK_DEBUG atomic_set(&clk_ref, 0); #endif return 0; err_s_clk: clk_put(pm->clock); pm->clock = NULL; err_p_ip_clk: clk_put(pm->clock_gate); pm->clock_gate = NULL; err_g_ip_clk: return ret; }
irqreturn_t mfc_irq(int irq, void *dev_id) { struct mfc_dev *dev = (struct mfc_dev *)dev_id; r2h_cmd = read_reg(MFC_RISC2HOST_CMD); mfc_dbg("MFC IRQ: 0x%02x\n", r2h_cmd); if (((r2h_cmd >= OPEN_CH_RET) && (r2h_cmd <= CLOSE_CH_RET)) || ((r2h_cmd >= SEQ_DONE_RET) && (r2h_cmd <= EDFU_INIT_RET)) || ( r2h_cmd == ERR_RET)) { memset(&r2h_args, 0, sizeof(struct mfc_cmd_args)); r2h_args.arg[0] = read_reg(MFC_RISC2HOST_ARG1); r2h_args.arg[1] = read_reg(MFC_RISC2HOST_ARG2); r2h_args.arg[2] = read_reg(MFC_RISC2HOST_ARG3); r2h_args.arg[3] = read_reg(MFC_RISC2HOST_ARG4); if (r2h_cmd == ERR_RET) //mfc_dbg("F/W error code: %d", r2h_args.arg[1] & 0xFFFF); mfc_dbg("F/W error code: 0x%08x", r2h_args.arg[1]); } else { mfc_err("Unknown R2H return value: 0x%02x\n", r2h_cmd); } #ifdef MFC_PERF if (framecnt > 0) { do_gettimeofday(&tv2); mfc_info("%d, %ld", framecnt, (long)(((tv2.tv_sec * 1000000) + tv2.tv_usec) - ((tv1.tv_sec * 1000000) + tv1.tv_usec))); framecnt++; } #endif /* FIXME: codec wait_queue processing */ dev->irq_sys = 1; wake_up(&dev->wait_sys); /* * FIXME: check is codec command return or error * move to mfc_wait_codec() ? */ write_reg(0xFFFF, MFC_SI_RTN_CHID); write_reg(0, MFC_RISC2HOST_CMD); write_reg(0, MFC_RISC_HOST_INT); return IRQ_HANDLED; }
irqreturn_t mfc_irq(int irq, void *dev_id) { unsigned int int_reason; unsigned int err_status; int_reason = READL(MFC_RISC2HOST_COMMAND) & 0x1FFFF; err_status = READL(MFC_RISC2HOST_ARG2); mfc_disp_err_status = err_status >> 16; mfc_dec_err_status = err_status & 0xFFFF; mfc_debug_L0("mfc_irq() : Interrupt !! : %d\n", int_reason); if( ((int_reason & R2H_CMD_EMPTY) == R2H_CMD_EMPTY) || ((int_reason & R2H_CMD_OPEN_INSTANCE_RET) == R2H_CMD_OPEN_INSTANCE_RET) || ((int_reason & R2H_CMD_CLOSE_INSTANCE_RET) == R2H_CMD_CLOSE_INSTANCE_RET) || ((int_reason & R2H_CMD_ERROR_RET) == R2H_CMD_ERROR_RET) || ((int_reason & R2H_CMD_SEQ_DONE_RET) == R2H_CMD_SEQ_DONE_RET) || ((int_reason & R2H_CMD_FRAME_DONE_RET) == R2H_CMD_FRAME_DONE_RET) || ((int_reason & R2H_CMD_SLICE_DONE_RET) == R2H_CMD_SLICE_DONE_RET) || ((int_reason & R2H_CMD_ENC_COMPLETE_RET) == R2H_CMD_ENC_COMPLETE_RET) || ((int_reason & R2H_CMD_SYS_INIT_RET) == R2H_CMD_SYS_INIT_RET) || ((int_reason & R2H_CMD_FW_STATUS_RET) == R2H_CMD_FW_STATUS_RET) || ((int_reason & R2H_CMD_SLEEP_RET) == R2H_CMD_SLEEP_RET) || ((int_reason & R2H_CMD_WAKEUP_RET) == R2H_CMD_WAKEUP_RET) || ((int_reason & R2H_CMD_FLUSH_COMMAND_RET) == R2H_CMD_FLUSH_COMMAND_RET) || ((int_reason & R2H_CMD_CMD_ABORT_RET) == R2H_CMD_CMD_ABORT_RET) || ((int_reason & R2H_CMD_CMD_BATCH_ENC_RET) == R2H_CMD_CMD_BATCH_ENC_RET) || ((int_reason & R2H_CMD_INIT_BUFFERS_RET) == R2H_CMD_INIT_BUFFERS_RET) || ((int_reason & R2H_CMD_EDFU_INT_RET) == R2H_CMD_EDFU_INT_RET) || ((int_reason & R2H_CMD_DECODE_ERR_RET) == R2H_CMD_DECODE_ERR_RET)) { mfc_int_type = int_reason; wake_up_interruptible(&mfc_wait_queue); } else mfc_info("Strange Interrupt !! : %d\n", int_reason); WRITEL(0, MFC_RISC_HOST_INT); WRITEL(0, MFC_RISC2HOST_COMMAND); WRITEL(0xffff, MFC_SI_RTN_CHID); return IRQ_HANDLED; }
static void s3c_mfc_del_node_from_alloc_list(s3c_mfc_alloc_mem_t *node, int inst_no) { mfc_debug("[%d]instance (uncached_p_addr : 0x%08x cached_p_addr : 0x%08x size:%d cacheflag : %d)\n", inst_no, node->uncached_p_addr, node->cached_p_addr, node->size, node->cache_flag); if(node == s3c_mfc_alloc_mem_tail){ mfc_info("InValid node\n"); return; } if(node == s3c_mfc_alloc_mem_head) s3c_mfc_alloc_mem_head = node->next; node->prev->next = node->next; node->next->prev = node->prev; kfree(node); }
static int mfc_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long user_size = vma->vm_end - vma->vm_start; unsigned long real_size; struct mfc_inst_ctx *mfc_ctx; #if !(defined(CONFIG_VIDEO_MFC_VCM_UMP) || defined(CONFIG_S5P_VMEM)) /* mmap support */ unsigned long pfn; unsigned long remap_offset, remap_size; struct mfc_dev *dev; #ifdef SYSMMU_MFC_ON /* kernel virtual memory allocator */ char *ptr; unsigned long start, size; #endif #endif mfc_ctx = (struct mfc_inst_ctx *)file->private_data; if (!mfc_ctx) return -EINVAL; #if !(defined(CONFIG_VIDEO_MFC_VCM_UMP) || defined(CONFIG_S5P_VMEM)) dev = mfc_ctx->dev; #endif mfc_dbg("vm_start: 0x%08lx, vm_end: 0x%08lx, size: %ld(%ldMB)\n", vma->vm_start, vma->vm_end, user_size, (user_size >> 20)); real_size = (unsigned long)(mfc_mem_data_size(0) + mfc_mem_data_size(1)); mfc_dbg("port 0 size: %d, port 1 size: %d, total: %ld\n", mfc_mem_data_size(0), mfc_mem_data_size(1), real_size); /* * if memory size required from appl. mmap() is bigger than max data memory * size allocated in the driver. */ if (user_size > real_size) { mfc_err("user requeste mem(%ld) is bigger than available mem(%ld)\n", user_size, real_size); return -EINVAL; } #ifdef SYSMMU_MFC_ON #if (defined(CONFIG_VIDEO_MFC_VCM_UMP) || defined(CONFIG_S5P_VMEM)) vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_ops = &mfc_vm_ops; vma->vm_private_data = mfc_ctx; mfc_ctx->userbase = vma->vm_start; #else /* not CONFIG_VIDEO_MFC_VCM_UMP && not CONFIG_S5P_VMEM */ /* kernel virtual memory allocator */ if (dev->mem_ports == 1) { remap_offset = 0; remap_size = user_size; vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* * Port 0 mapping for stream buf & frame buf (chroma + MV + luma) */ ptr = (char *)mfc_mem_data_base(0); start = remap_offset; size = remap_size; while (size > 0) { pfn = vmalloc_to_pfn(ptr); if (remap_pfn_range(vma, vma->vm_start + start, pfn, PAGE_SIZE, vma->vm_page_prot)) { mfc_err("failed to remap port 0\n"); return -EAGAIN; } start += PAGE_SIZE; ptr += PAGE_SIZE; size -= PAGE_SIZE; } } else { remap_offset = 0; remap_size = min((unsigned long)mfc_mem_data_size(0), user_size); vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* * Port 0 mapping for stream buf & frame buf (chroma + MV) */ ptr = (char *)mfc_mem_data_base(0); start = remap_offset; size = remap_size; while (size > 0) { pfn = vmalloc_to_pfn(ptr); if (remap_pfn_range(vma, vma->vm_start + start, pfn, PAGE_SIZE, vma->vm_page_prot)) { mfc_err("failed to remap port 0\n"); return -EAGAIN; } start += PAGE_SIZE; ptr += PAGE_SIZE; size -= PAGE_SIZE; } remap_offset = remap_size; remap_size = min((unsigned long)mfc_mem_data_size(1), user_size - remap_offset); vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* * Port 1 mapping for frame buf (luma) */ ptr = (void *)mfc_mem_data_base(1); start = remap_offset; size = remap_size; while (size > 0) { pfn = vmalloc_to_pfn(ptr); if (remap_pfn_range(vma, vma->vm_start + start, pfn, PAGE_SIZE, vma->vm_page_prot)) { mfc_err("failed to remap port 1\n"); return -EAGAIN; } start += PAGE_SIZE; ptr += PAGE_SIZE; size -= PAGE_SIZE; } } mfc_ctx->userbase = vma->vm_start; mfc_dbg("user request mem = %ld, available data mem = %ld\n", user_size, real_size); if ((remap_offset + remap_size) < real_size) mfc_warn("The MFC reserved memory dose not mmap fully [%ld: %ld]\n", real_size, (remap_offset + remap_size)); #endif /* end of CONFIG_VIDEO_MFC_VCM_UMP */ #else /* not SYSMMU_MFC_ON */ /* early allocator */ /* CMA or bootmem(memblock) */ if (dev->mem_ports == 1) { remap_offset = 0; remap_size = user_size; vma->vm_flags |= VM_RESERVED | VM_IO; if(mfc_ctx->buf_cache_type == NO_CACHE){ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); mfc_info("CONFIG_VIDEO_MFC_CACHE is not enabled\n"); }else mfc_info("CONFIG_VIDEO_MFC_CACHE is enabled\n"); /* * Port 0 mapping for stream buf & frame buf (chroma + MV + luma) */ pfn = __phys_to_pfn(mfc_mem_data_base(0)); if (remap_pfn_range(vma, vma->vm_start + remap_offset, pfn, remap_size, vma->vm_page_prot)) { mfc_err("failed to remap port 0\n"); return -EINVAL; } } else { remap_offset = 0; remap_size = min((unsigned long)mfc_mem_data_size(0), user_size); vma->vm_flags |= VM_RESERVED | VM_IO; if(mfc_ctx->buf_cache_type == NO_CACHE){ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); mfc_info("CONFIG_VIDEO_MFC_CACHE is not enabled\n"); }else mfc_info("CONFIG_VIDEO_MFC_CACHE is enabled\n"); /* * Port 0 mapping for stream buf & frame buf (chroma + MV) */ pfn = __phys_to_pfn(mfc_mem_data_base(0)); if (remap_pfn_range(vma, vma->vm_start + remap_offset, pfn, remap_size, vma->vm_page_prot)) { mfc_err("failed to remap port 0\n"); return -EINVAL; } remap_offset = remap_size; remap_size = min((unsigned long)mfc_mem_data_size(1), user_size - remap_offset); vma->vm_flags |= VM_RESERVED | VM_IO; if(mfc_ctx->buf_cache_type == NO_CACHE) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* * Port 1 mapping for frame buf (luma) */ pfn = __phys_to_pfn(mfc_mem_data_base(1)); if (remap_pfn_range(vma, vma->vm_start + remap_offset, pfn, remap_size, vma->vm_page_prot)) { mfc_err("failed to remap port 1\n"); return -EINVAL; } } mfc_ctx->userbase = vma->vm_start; mfc_dbg("user request mem = %ld, available data mem = %ld\n", user_size, real_size); if ((remap_offset + remap_size) < real_size) mfc_warn("The MFC reserved memory dose not mmap fully [%ld: %ld]\n", real_size, (remap_offset + remap_size)); #endif /* end of SYSMMU_MFC_ON */ return 0; }
static void __exit mfc_exit(void) { platform_driver_unregister(&mfc_driver); mfc_info("FIMV MFC(Multi Function Codec) V5.x exit\n"); }
int s5p_mfc_sleep(struct s5p_mfc_dev *dev) { struct s5p_mfc_ctx *ctx; int new_ctx; int ret; mfc_debug_enter(); if (!dev) { mfc_info("No mfc device to run\n"); ret = 0; return ret; } spin_lock_irq(&dev->condlock); new_ctx = s5p_mfc_get_new_ctx(dev); spin_unlock_irq(&dev->condlock); if (new_ctx < 0) { mfc_info("No ctx is scheduled to be run\n"); ret = 0; return ret; } ctx = dev->ctx[new_ctx]; if (!ctx) { mfc_info("No ctx: not need to enter suspend\n"); ret = 0; return ret; } ret = wait_event_interruptible_timeout(ctx->queue, (test_bit(ctx->num, &dev->hw_lock) == 0), msecs_to_jiffies(MFC_INT_TIMEOUT)); if (ret == 0) { mfc_err("Waiting for hardware to finish timed out\n"); ret = -EIO; return ret; } spin_lock(&dev->condlock); set_bit(ctx->num, &dev->hw_lock); spin_unlock(&dev->condlock); s5p_mfc_clock_on(); s5p_mfc_clean_dev_int_flags(dev); ret = s5p_mfc_sleep_cmd(dev); if (ret) { mfc_err("Failed to send command to MFC - timeout.\n"); goto err_mfc_sleep; } if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) { mfc_err("Failed to sleep\n"); ret = -EIO; goto err_mfc_sleep; } dev->int_cond = 0; if (dev->int_err != 0 || dev->int_type != S5P_FIMV_R2H_CMD_SLEEP_RET) { /* Failure. */ mfc_err("Failed to sleep - error: %d" " int: %d.\n", dev->int_err, dev->int_type); ret = -EIO; goto err_mfc_sleep; } err_mfc_sleep: s5p_mfc_clock_off(); mfc_debug_leave(); return ret; }
static int mfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret, ex_ret; mfc_inst_ctx *mfc_ctx = NULL; mfc_common_args in_param; mutex_lock(&mfc_mutex); #if Frame_Base_Power_CTR_ON if (s5pv210_pd_enable("mfc_pd") < 0) { printk(KERN_ERR "[Error]The power is not on for mfc\n"); return -1; } clk_enable(mfc_clk); #endif ret = copy_from_user(&in_param, (mfc_common_args *)arg, sizeof(mfc_common_args)); if (ret < 0) { mfc_err("Inparm copy error\n"); ret = -EIO; in_param.ret_code = MFCINST_ERR_INVALID_PARAM; goto out_ioctl; } mfc_ctx = (mfc_inst_ctx *)file->private_data; mutex_unlock(&mfc_mutex); switch (cmd) { case IOCTL_MFC_ENC_INIT: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_info("IOCTL_MFC_ENC_INIT\n"); #endif if (mfc_set_state(mfc_ctx, MFCINST_STATE_ENC_INITIALIZE) < 0) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } /* MFC encode init */ in_param.ret_code = mfc_init_encode(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_ENC_EXE: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_info("IOCTL_MFC_ENC_EXE\n"); #endif if (mfc_ctx->MfcState < MFCINST_STATE_ENC_INITIALIZE) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } if (mfc_set_state(mfc_ctx, MFCINST_STATE_ENC_EXE) < 0) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } in_param.ret_code = mfc_exe_encode(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_DEC_INIT: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_info("IOCTL_MFC_DEC_INIT\n"); #endif if (mfc_set_state(mfc_ctx, MFCINST_STATE_DEC_INITIALIZE) < 0) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } /* MFC decode init */ in_param.ret_code = mfc_init_decode(mfc_ctx, &(in_param.args)); if (in_param.ret_code < 0) { mfc_err("MFC_DEC_INIT ERROR ............. ret(%d)\n",in_param.ret_code); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; } if (in_param.args.dec_init.out_dpb_cnt <= 0) { mfc_err("MFC out_dpb_cnt error\n"); mutex_unlock(&mfc_mutex); break; } mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_DEC_EXE: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_debug_L0("IOCTL_MFC_DEC_EXE\n"); #endif if (mfc_ctx->MfcState < MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } if (mfc_set_state(mfc_ctx, MFCINST_STATE_DEC_EXE) < 0) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } in_param.ret_code = mfc_exe_decode(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_GET_CONFIG: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_info("IOCTL_MFC_GET_CONFIG\n"); #endif if (mfc_ctx->MfcState < MFCINST_STATE_DEC_INITIALIZE) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } in_param.ret_code = mfc_get_config(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_SET_CONFIG: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_info("IOCTL_MFC_SET_CONFIG\n"); #endif in_param.ret_code = mfc_set_config(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_GET_IN_BUF: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_info("IOCTL_MFC_GET_IN_BUF\n"); #endif if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } if (in_param.args.mem_alloc.buff_size <= 0) { mfc_err("MFCINST_ERR_INVALID_PARAM\n"); in_param.ret_code = MFCINST_ERR_INVALID_PARAM; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } if ((is_dec_codec(in_param.args.mem_alloc.codec_type)) && (in_param.args.mem_alloc.buff_size < (CPB_BUF_SIZE + DESC_BUF_SIZE))) { in_param.args.mem_alloc.buff_size = CPB_BUF_SIZE + DESC_BUF_SIZE; } /* Buffer manager should have 64KB alignment for MFC base addresses */ in_param.args.mem_alloc.buff_size = ALIGN_TO_8KB(in_param.args.mem_alloc.buff_size); /* allocate stream buf for decoder & current YC buf for encoder */ if (is_dec_codec(in_param.args.mem_alloc.codec_type)) { in_param.ret_code = mfc_allocate_buffer(mfc_ctx, &in_param.args, 0); } else { in_param.ret_code = mfc_allocate_buffer(mfc_ctx, &in_param.args, 1); } ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_FREE_BUF: mutex_lock(&mfc_mutex); #if ENABLE_MONITORING_MFC_DD mfc_info("IOCTL_MFC_FREE_BUF\n"); #endif if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } in_param.ret_code = mfc_release_buffer((unsigned char *)in_param.args.mem_free.u_addr); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; case IOCTL_MFC_GET_PHYS_ADDR: mutex_lock(&mfc_mutex); mfc_debug("IOCTL_MFC_GET_PHYS_ADDR\n"); if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); in_param.ret_code = MFCINST_ERR_STATE_INVALID; ret = -EINVAL; mutex_unlock(&mfc_mutex); break; } in_param.ret_code = mfc_get_phys_addr(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mutex_unlock(&mfc_mutex); break; default: mfc_err("Requested ioctl command is not defined. (ioctl cmd=0x%08x)\n", cmd); in_param.ret_code = MFCINST_ERR_INVALID_PARAM; ret = -EINVAL; } out_ioctl: #if Frame_Base_Power_CTR_ON clk_disable(mfc_clk); if (s5pv210_pd_disable("mfc_pd") < 0) { printk(KERN_ERR "[Error]The power is not off for mfc\n"); return -1; } #endif ex_ret = copy_to_user((mfc_common_args *)arg, &in_param, sizeof(mfc_common_args)); if (ex_ret < 0) { mfc_err("Outparm copy to user error\n"); ret = -EIO; } mfc_debug_L0("---------------IOCTL return = %d ---------------\n", ret); return ret; }
/* Allocate firmware */ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { #if defined(CONFIG_VIDEOBUF2_CMA_PHYS) int err; struct cma_info mem_info_f, mem_info_a, mem_info_b; #endif unsigned int base_align; unsigned int firmware_size; void *alloc_ctx; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } base_align = dev->variant->buf_align->mfc_base_align; firmware_size = dev->variant->buf_size->firmware_code; alloc_ctx = dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX]; #if !defined(CONFIG_VIDEOBUF2_ION) if (s5p_mfc_bitproc_buf) { mfc_err("Attempting to allocate firmware when it seems that it is already loaded.\n"); return -ENOMEM; } #else if (s5p_mfc_bitproc_buf) return 0; #endif /* Get memory region information and check if it is correct */ #if defined(CONFIG_VIDEOBUF2_CMA_PHYS) err = cma_info(&mem_info_f, dev->v4l2_dev.dev, MFC_CMA_FW); mfc_debug(3, "Area \"%s\" is from %08x to %08x and has size %08x", "f", mem_info_f.lower_bound, mem_info_f.upper_bound, mem_info_f.total_size); if (err) { mfc_err("Couldn't get memory information from CMA.\n"); return -EINVAL; } err = cma_info(&mem_info_a, dev->v4l2_dev.dev, MFC_CMA_BANK1); mfc_debug(3, "Area \"%s\" is from %08x to %08x and has size %08x", "a", mem_info_a.lower_bound, mem_info_a.upper_bound, mem_info_a.total_size); if (err) { mfc_err("Couldn't get memory information from CMA.\n"); return -EINVAL; } if (mem_info_f.upper_bound > mem_info_a.lower_bound) { mfc_err("Firmware has to be " "allocated before memory for buffers (bank A).\n"); return -EINVAL; } #endif mfc_info("Allocating memory for firmware.\n"); #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION if (dev->num_drm_inst) alloc_ctx = dev->alloc_ctx_fw; #endif s5p_mfc_bitproc_buf = s5p_mfc_mem_alloc_priv(alloc_ctx, firmware_size); if (IS_ERR(s5p_mfc_bitproc_buf)) { s5p_mfc_bitproc_buf = 0; printk(KERN_ERR "Allocating bitprocessor buffer failed\n"); return -ENOMEM; } s5p_mfc_bitproc_phys = s5p_mfc_mem_daddr_priv(s5p_mfc_bitproc_buf); if (s5p_mfc_bitproc_phys & ((1 << base_align) - 1)) { mfc_err("The base memory is not aligned to %dBytes.\n", (1 << base_align)); s5p_mfc_mem_free_priv(s5p_mfc_bitproc_buf); s5p_mfc_bitproc_phys = 0; s5p_mfc_bitproc_buf = 0; return -EIO; } if (!dev->num_drm_inst) { s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr_priv(s5p_mfc_bitproc_buf); mfc_debug(2, "Virtual address for FW: %08lx\n", (long unsigned int)s5p_mfc_bitproc_virt); if (!s5p_mfc_bitproc_virt) { mfc_err("Bitprocessor memory remap failed\n"); s5p_mfc_mem_free_priv(s5p_mfc_bitproc_buf); s5p_mfc_bitproc_phys = 0; s5p_mfc_bitproc_buf = 0; return -EIO; } } dev->port_a = s5p_mfc_bitproc_phys; #if defined(CONFIG_VIDEOBUF2_CMA_PHYS) if (IS_TWOPORT(dev)) { err = cma_info(&mem_info_b, dev->v4l2_dev.dev, MFC_CMA_BANK2); mfc_debug(3, "Area \"%s\" is from %08x to %08x and has size %08x", "b", mem_info_b.lower_bound, mem_info_b.upper_bound, mem_info_b.total_size); if (err) { mfc_err("Couldn't get memory information from CMA.\n"); return -EINVAL; } dev->port_b = mem_info_b.lower_bound; mfc_debug(2, "Port A: %08x Port B: %08x (FW: %08x size: %08x)\n", dev->port_a, dev->port_b, s5p_mfc_bitproc_phys, firmware_size); } else { mfc_debug(2, "Port : %08x (FW: %08x size: %08x)\n", dev->port_a, s5p_mfc_bitproc_phys, firmware_size); } #elif defined(CONFIG_VIDEOBUF2_ION) dev->port_b = s5p_mfc_bitproc_phys; mfc_info("Port A: %08x Port B: %08x (FW: %08x size: %08x)\n", dev->port_a, dev->port_b, s5p_mfc_bitproc_phys, firmware_size); #endif mfc_debug_leave(); return 0; }
static int mfc_probe(struct platform_device *pdev) { struct resource *res; size_t size; int ret; #if ENABLE_MONITORING_MFC_DD mfc_info("MFC mfc_probe..dev_id(%d)\n",S5P_MDEV_MFC); #endif /* mfc clock enable should be here */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "failed to get memory region resource\n"); ret = -ENOENT; goto probe_out; } // 60K is required for mfc register (0x0 ~ 0xe008) size = (res->end - res->start) + 1; mfc_mem = request_mem_region(res->start, size, pdev->name); if (mfc_mem == NULL) { dev_err(&pdev->dev, "failed to get memory region\n"); ret = -ENOENT; goto probe_out; } mfc_sfr_base_vaddr = ioremap(mfc_mem->start, mfc_mem->end - mfc_mem->start + 1); if (mfc_sfr_base_vaddr == NULL) { dev_err(&pdev->dev, "failed to ioremap address region\n"); ret = -ENOENT; goto probe_out; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(&pdev->dev, "failed to get irq resource\n"); ret = -ENOENT; goto probe_out; } #if !defined(MFC_POLLING) ret = request_irq(res->start, mfc_irq, IRQF_DISABLED, pdev->name, pdev); if (ret != 0) { dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); goto probe_out; } #endif mutex_init(&mfc_mutex); /* * buffer memory secure */ mfc_port0_base_paddr = s5p_get_media_memory_bank(S5P_MDEV_MFC, 0); mfc_port0_base_paddr = ALIGN_TO_128KB(mfc_port0_base_paddr); mfc_port0_base_vaddr = phys_to_virt(mfc_port0_base_paddr); if (mfc_port0_base_vaddr == NULL) { mfc_err("fail to mapping port0 buffer\n"); ret = -EPERM; goto probe_out; } mfc_port1_base_paddr = s5p_get_media_memory_bank(S5P_MDEV_MFC, 1); mfc_port1_base_paddr = ALIGN_TO_128KB(mfc_port1_base_paddr); mfc_port1_base_vaddr = phys_to_virt(mfc_port1_base_paddr); if (mfc_port1_base_vaddr == NULL) { mfc_err("fail to mapping port1 buffer\n"); ret = -EPERM; goto probe_out; } // mfc_debug("mfc_port0_base_paddr = 0x%08x, mfc_port1_base_paddr = 0x%08x <<\n", // (unsigned int)mfc_port0_base_paddr, (unsigned int)mfc_port1_base_paddr); // mfc_debug("mfc_port0_base_vaddr = 0x%08x, mfc_port1_base_vaddr = 0x%08x <<\n", // (unsigned int)mfc_port0_base_vaddr, (unsigned int)mfc_port1_base_vaddr); /* * MFC FW downloading */ if (mfc_load_firmware() < 0) { mfc_err("MFCINST_ERR_FW_INIT_FAIL\n"); ret = -EPERM; goto probe_out; } mfc_init_mem_inst_no(); mfc_init_buffer(); mfc_clk = clk_get(&pdev->dev, "mfc"); if (mfc_clk == NULL) { printk(KERN_ERR "failed to find mfc clock source\n"); return -ENOENT; } ret = misc_register(&mfc_miscdev); return 0; probe_out: dev_err(&pdev->dev, "not found (%d). \n", ret); return ret; }
static void __exit mfc_exit(void) { platform_driver_unregister(&mfc_driver); mfc_info("S5PC110 MFC Driver exit.\n"); }
static int mfc_mmap(struct file *filp, struct vm_area_struct *vma) { unsigned long vir_size = vma->vm_end - vma->vm_start; unsigned long phy_size, firmware_size; unsigned long page_frame_no = 0; mfc_inst_ctx *mfc_ctx; #if ENABLE_MONITORING_MFC_DD mfc_info("MFC mfc_mmap..dev_id(%d)\n",S5P_MDEV_MFC); #endif mfc_debug("vma->vm_start = 0x%08x, vma->vm_end = 0x%08x\n", (unsigned int)vma->vm_start, (unsigned int)vma->vm_end); mfc_debug("vma->vm_end - vma->vm_start = %ld\n", vir_size); mfc_ctx = (mfc_inst_ctx *)filp->private_data; firmware_size = mfc_get_port0_buff_paddr() - mfc_get_fw_buff_paddr(); phy_size = (unsigned long)(s5p_get_media_memory_bank(S5P_MDEV_MFC, 0) - firmware_size + s5p_get_media_memory_bank(S5P_MDEV_MFC, 1)); /* if memory size required from appl. mmap() is bigger than max data memory * size allocated in the driver */ if (vir_size > phy_size) { mfc_err("virtual requested mem(%ld) is bigger than physical mem(%ld)\n", vir_size, phy_size); return -EINVAL; } mfc_ctx->port0_mmap_size = (vir_size / 2); vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* * port0 mapping for stream buf & frame buf (chroma + MV) */ page_frame_no = __phys_to_pfn(mfc_get_port0_buff_paddr()); if (remap_pfn_range(vma, vma->vm_start, page_frame_no, mfc_ctx->port0_mmap_size, vma->vm_page_prot)) { mfc_err("mfc remap port0 error\n"); return -EAGAIN; } vma->vm_flags |= VM_RESERVED | VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); /* * port1 mapping for frame buf (luma) */ page_frame_no = __phys_to_pfn(mfc_get_port1_buff_paddr()); if (remap_pfn_range(vma, vma->vm_start + mfc_ctx->port0_mmap_size, page_frame_no, vir_size - mfc_ctx->port0_mmap_size, vma->vm_page_prot)) { mfc_err("mfc remap port1 error\n"); return -EAGAIN; } mfc_debug("virtual requested mem = %ld, physical reserved data mem = %ld\n", vir_size, phy_size); return 0; }
static int mfc_open(struct inode *inode, struct file *file) { struct mfc_inst_ctx *mfc_ctx; int ret; enum mfc_ret_code retcode; int inst_id; #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION struct mfc_alloc_buffer *alloc; #endif /* prevent invalid reference */ file->private_data = NULL; mutex_lock(&mfcdev->lock); #if SUPPORT_SLICE_ENCODING mfcdev->frame_working_flag = 1; mfcdev->frame_sys = 0; #endif if (!mfcdev->fw.state) { if (mfcdev->fw.requesting) { printk(KERN_INFO "MFC F/W request is on-going, try again\n"); ret = -ENODEV; goto err_fw_state; } printk(KERN_INFO "MFC F/W is not existing, requesting...\n"); ret = request_firmware(&mfcdev->fw.info, MFC_FW_NAME, mfcdev->device); if (ret < 0) { printk(KERN_INFO "failed to copy MFC F/W during open\n"); ret = -ENODEV; goto err_fw_state; } if (soc_is_exynos4212() || soc_is_exynos4412()) { mfcdev->fw.state = mfc_load_firmware(mfcdev->fw.info->data, mfcdev->fw.info->size); if (!mfcdev->fw.state) { printk(KERN_ERR "failed to load MFC F/W, MFC will not working\n"); ret = -ENODEV; goto err_fw_state; } else { printk(KERN_INFO "MFC F/W loaded successfully (size: %d)\n", mfcdev->fw.info->size); } } } if (atomic_read(&mfcdev->inst_cnt) == 0) { /* reload F/W for first instance again */ if (soc_is_exynos4210()) { mfcdev->fw.state = mfc_load_firmware(mfcdev->fw.info->data, mfcdev->fw.info->size); if (!mfcdev->fw.state) { printk(KERN_ERR "failed to reload MFC F/W, MFC will not working\n"); ret = -ENODEV; goto err_fw_state; } else { printk(KERN_INFO "MFC F/W reloaded successfully (size: %d)\n", mfcdev->fw.info->size); } } #if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER) dev_lock(mfcdev->bus_dev, mfcdev->device, 133133); #endif #ifdef CONFIG_BUSFREQ pm_qos_add_request(&bus_qos_pm_qos_req, PM_QOS_BUS_QOS, 1); #endif ret = mfc_power_on(); if (ret < 0) { mfc_err("power enable failed\n"); goto err_pwr_enable; } #ifndef CONFIG_PM_RUNTIME #ifdef SYSMMU_MFC_ON mfc_clock_on(mfcdev); s5p_sysmmu_enable(mfcdev->device); #ifdef CONFIG_VIDEO_MFC_VCM_UMP vcm_set_pgtable_base(VCM_DEV_MFC); #else /* CONFIG_S5P_VMEM or kernel virtual memory allocator */ s5p_sysmmu_set_tablebase_pgd(mfcdev->device, __pa(swapper_pg_dir)); /* * RMVME: the power-gating work really (on <-> off), * all TBL entry was invalidated already when the power off */ s5p_sysmmu_tlb_invalidate(mfcdev->device, SYSMMU_MFC_R); #endif mfc_clock_off(mfcdev); #endif #endif /* MFC hardware initialization */ retcode = mfc_start(mfcdev); if (retcode != MFC_OK) { mfc_err("MFC H/W init failed: %d\n", retcode); ret = -ENODEV; goto err_start_hw; } } if (atomic_read(&mfcdev->inst_cnt) >= MFC_MAX_INSTANCE_NUM) { mfc_err("exceed max instance number, too many instance opened already\n"); ret = -EINVAL; goto err_inst_cnt; } inst_id = get_free_inst_id(mfcdev); if (inst_id < 0) { mfc_err("failed to get instance ID\n"); ret = -EINVAL; goto err_inst_id; } mfc_ctx = mfc_create_inst(); if (!mfc_ctx) { mfc_err("failed to create instance context\n"); ret = -ENOMEM; goto err_inst_ctx; } atomic_inc(&mfcdev->inst_cnt); mfcdev->inst_ctx[inst_id] = mfc_ctx; #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION if (check_magic(mfcdev->drm_info.addr) >= 0) { mfc_info("DRM instance starting\n"); clear_magic(mfcdev->drm_info.addr + check_magic(mfcdev->drm_info.addr)); mfc_ctx->drm_flag = 1; mfc_set_buf_alloc_scheme(MBS_FIRST_FIT); } else { mfc_ctx->drm_flag = 0; } #endif mfc_ctx->id = inst_id; mfc_ctx->dev = mfcdev; #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION if (mfc_ctx->drm_flag) { alloc = _mfc_alloc_buf(mfc_ctx, MFC_CTX_SIZE_L, ALIGN_2KB, MBT_CTX | PORT_A); if (alloc == NULL) { mfc_err("failed to alloc context buffer\n"); ret = -ENOMEM; goto err_drm_ctx; } mfc_ctx->ctxbufofs = mfc_mem_base_ofs(alloc->real) >> 11; mfc_ctx->ctxbufsize = alloc->size; memset((void *)alloc->addr, 0, alloc->size); mfc_mem_cache_clean((void *)alloc->addr, alloc->size); }
static int mfc_open(struct inode *inode, struct file *file) { mfc_inst_ctx *mfc_ctx; int ret; //struct sched_param param = { .sched_priority = 1 }; printk("%s(%d)\n", __func__, __LINE__); mutex_lock(&mfc_mutex); if (!mfc_is_running()) { #ifdef CONFIG_CPU_FREQ #if defined(CONFIG_MACH_S5PC110_P1) s5pc110_lock_dvfs_high_level(DVFS_LOCK_TOKEN_1, 2); // DVFS Limit 200Mhz when mfc is running #endif #if defined(CONFIG_MACH_S5PC110_ARIES) #if MAXIMUM_FREQ == 1200000 s5pc110_lock_dvfs_high_level(DVFS_LOCK_TOKEN_1, LEV_400MHZ); #else s5pc110_lock_dvfs_high_level(DVFS_LOCK_TOKEN_1, LEV_416MHZ); #endif #endif // CONFIG_MACH_S5PC110_P1 #endif #ifdef CONFIG_S5PC11X_LPAUDIO s5pc110_set_lpaudio_lock(1); #endif /* CONFIG_S5PC11X_LPAUDIO */ clk_enable(mfc_clk); #ifdef CONFIG_PM_PWR_GATING s5pc110_lock_power_domain(MFC_DOMAIN_LOCK_TOKEN); #endif if (mfc_init_hw() != TRUE) { #if Frame_Base_Power_CTR_ON clk_disable(mfc_clk); #endif ret = -ENODEV; goto out_open; } #if Frame_Base_Power_CTR_ON clk_disable(mfc_clk); #endif } mfc_ctx = (mfc_inst_ctx *)kmalloc(sizeof(mfc_inst_ctx), GFP_KERNEL); if (mfc_ctx == NULL) { mfc_err("MFCINST_MEMORY_ALLOC_FAIL\n"); ret = -ENOMEM; goto out_open; } memset(mfc_ctx, 0, sizeof(mfc_inst_ctx)); /* get the inst no allocating some part of memory among reserved memory */ mfc_ctx->mem_inst_no = mfc_get_mem_inst_no(); mfc_ctx->InstNo = -1; if (mfc_ctx->mem_inst_no < 0) { mfc_err("MFCINST_INST_NUM_EXCEEDED\n"); kfree(mfc_ctx); ret = -EPERM; goto out_open; } if (mfc_set_state(mfc_ctx, MFCINST_STATE_OPENED) < 0) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); kfree(mfc_ctx); ret = -ENODEV; goto out_open; } /* Decoder only */ mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB; mfc_ctx->FrameType = MFC_RET_FRAME_NOT_SET; file->private_data = (mfc_inst_ctx *)mfc_ctx; //sched_setscheduler(current, SCHED_FIFO, ¶m); ret = 0; out_open: mutex_unlock(&mfc_mutex); if(ret != 0) { mfc_err("MFC_OEPN_FAIL..... ret(%d) \n", ret); return ret; } #if ENABLE_MFC_DD_MONITOR mfc_info("MFC_OEPN_OK..... ret(%d) \n", ret); #endif return ret; }
int mfc_wait_for_done(mfc_wait_done_type command) { unsigned int nwait_time = 100; unsigned int ret_val = 1; if((command == R2H_CMD_CLOSE_INSTANCE_RET) || (command == R2H_CMD_OPEN_INSTANCE_RET) || (command == R2H_CMD_FW_STATUS_RET)) nwait_time = MFC_WAIT_4_TIME; else nwait_time = MFC_WAIT_2_TIME; #if defined(MFC_REQUEST_TIME) long sec, msec; #endif #if defined(MFC_POLLING) unsigned long timeo = jiffies; timeo += 20; /* waiting for 100ms */ #endif //set_user_nice(current, -20); #if defined(MFC_REQUEST_TIME) do_gettimeofday(&mfc_wakeup_before); if (mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec < 0) { msec = 1000000 + mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec; sec = mfc_wakeup_before.tv_sec - mfc_wakeup_after.tv_sec - 1; } else { msec = mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec; sec = mfc_wakeup_before.tv_sec - mfc_wakeup_after.tv_sec; } #endif #if defined(MFC_POLLING) while (time_before(jiffies, timeo)) { ret_val = READL(MFC_RISC2HOST_COMMAND) & 0x1ffff; if (ret_val != 0) { WRITEL(0, MFC_RISC_HOST_INT); WRITEL(0, MFC_RISC2HOST_COMMAND); WRITEL(0xffff, MFC_SI_RTN_CHID); mfc_int_type = ret_val; break; } msleep_interruptible(2); } if (ret_val == 0) printk("MFC timeouted!\n"); #else if (interruptible_sleep_on_timeout(&mfc_wait_queue, nwait_time) == 0) { ret_val = R2H_CMD_TIMEOUT; mfc_err("Interrupt Time Out(Cmd: %d) (Ver: 0x%08x) (0x64: 0x%08x) (0xF4: 0x%08x) (0x80: 0x%08x)\n", command, READL(0x58), READL(0x64), READL(0xF4),READL(0x80)); #if ENABLE_MFC_INTERRUPT_DEBUG // For MFC Interrupt Debugging. mfc_interrupt_debug(10); #endif mfc_int_type = ret_val; return ret_val; } else if (mfc_int_type == R2H_CMD_DECODE_ERR_RET) { mfc_err("MFC Error Returned Disp Error Status(%d), Dec Error Status(%d)\n", mfc_disp_err_status, mfc_dec_err_status ); } else if (command != mfc_int_type) { mfc_err("Interrupt Error Returned (%d) waiting for (%d)\n", mfc_int_type, command); } #endif #if defined(MFC_REQUEST_TIME) do_gettimeofday(&mfc_wakeup_after); if (mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec < 0) { msec = 1000000 + mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec; sec = mfc_wakeup_after.tv_sec - mfc_wakeup_before.tv_sec - 1; } else { msec = mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec; sec = mfc_wakeup_after.tv_sec - mfc_wakeup_before.tv_sec; } mfc_info("mfc_wait_for_done: mfc request interval time is %ld(sec), %ld(msec)\n", sec, msec); #endif ret_val = mfc_int_type; mfc_int_type = 0; return ret_val; }
int mfc_init_mem_mgr(struct mfc_dev *dev) { int i; #if !defined(CONFIG_VIDEO_MFC_VCM_UMP) dma_addr_t base[MAX_ALLOCATION]; #else /* FIXME: for support user-side allocation. it's temporary solution */ struct vcm_res *hole; #endif #ifndef SYSMMU_MFC_ON size_t size; #endif #ifdef CONFIG_S5P_MEM_CMA struct cma_info cma_infos[2]; #ifdef CONFIG_EXYNOS4_CONTENT_PATH_PROTECTION size_t bound_size; size_t available_size; size_t hole_size; #else int cma_index = 0; #endif #else unsigned int align_margin; #endif dev->mem_ports = MFC_MAX_MEM_PORT_NUM; memset(dev->mem_infos, 0, sizeof(dev->mem_infos)); #ifdef SYSMMU_MFC_ON #if defined(CONFIG_VIDEO_MFC_VCM_UMP) dev->vcm_info.sysmmu_vcm = vcm_create_unified( SZ_256M * dev->mem_ports, VCM_DEV_MFC, &mfc_vcm_driver); memcpy(&vcm_info, &dev->vcm_info, sizeof(struct mfc_vcm)); dev->mem_infos[0].vcm_s = vcm_reserve(dev->vcm_info.sysmmu_vcm, MFC_MEMSIZE_PORT_A, 0); if (IS_ERR(dev->mem_infos[0].vcm_s)) return PTR_ERR(dev->mem_infos[0].vcm_s); dev->mem_infos[0].base = ALIGN(dev->mem_infos[0].vcm_s->start, ALIGN_128KB); align_margin = dev->mem_infos[0].base - dev->mem_infos[0].vcm_s->start; /* FIXME: for offset operation. it's temporary solution */ /* dev->mem_infos[0].size = MFC_MEMSIZE_PORT_A - align_margin; */ dev->mem_infos[0].size = SZ_256M - align_margin; dev->mem_infos[0].addr = NULL; /* FIXME: for support user-side allocation. it's temporary solution */ if (MFC_MEMSIZE_PORT_A < SZ_256M) hole = vcm_reserve(dev->vcm_info.sysmmu_vcm, SZ_256M - MFC_MEMSIZE_PORT_A, 0); if (dev->mem_ports == 2) { dev->mem_infos[1].vcm_s = vcm_reserve(dev->vcm_info.sysmmu_vcm, MFC_MEMSIZE_PORT_B, 0); if (IS_ERR(dev->mem_infos[1].vcm_s)) { vcm_unreserve(dev->mem_infos[0].vcm_s); return PTR_ERR(dev->mem_infos[1].vcm_s); } dev->mem_infos[1].base = ALIGN(dev->mem_infos[1].vcm_s->start, ALIGN_128KB); align_margin = dev->mem_infos[1].base - dev->mem_infos[1].vcm_s->start; dev->mem_infos[1].size = MFC_MEMSIZE_PORT_B - align_margin; dev->mem_infos[1].addr = NULL; } /* FIXME: for support user-side allocation. it's temporary solution */ vcm_unreserve(hole); dev->fw.vcm_s = mfc_vcm_bind(dev->mem_infos[0].base, MFC_FW_SYSTEM_SIZE); if (IS_ERR(dev->fw.vcm_s)) return PTR_ERR(dev->fw.vcm_s); dev->fw.vcm_k = mfc_vcm_map(dev->fw.vcm_s->res.phys); if (IS_ERR(dev->fw.vcm_k)) { mfc_vcm_unbind(dev->fw.vcm_s, 0); return PTR_ERR(dev->fw.vcm_k); } /* FIXME: it's very tricky! MUST BE FIX */ dev->mem_infos[0].addr = (unsigned char *)dev->fw.vcm_k->start; #elif defined(CONFIG_S5P_VMEM) base[0] = MFC_FREEBASE; dev->mem_infos[0].base = ALIGN(base[0], ALIGN_128KB); align_margin = dev->mem_infos[0].base - base[0]; dev->mem_infos[0].size = MFC_MEMSIZE_PORT_A - align_margin; dev->mem_infos[0].addr = (unsigned char *)dev->mem_infos[0].base; if (dev->mem_ports == 2) { base[1] = dev->mem_infos[0].base + dev->mem_infos[0].size; dev->mem_infos[1].base = ALIGN(base[1], ALIGN_128KB); align_margin = dev->mem_infos[1].base - base[1]; dev->mem_infos[1].size = MFC_MEMSIZE_PORT_B - align_margin; dev->mem_infos[1].addr = (unsigned char *)dev->mem_infos[1].base; } dev->fw.vmem_cookie = s5p_vmem_vmemmap(MFC_FW_SYSTEM_SIZE, dev->mem_infos[0].base, dev->mem_infos[0].base + MFC_FW_SYSTEM_SIZE); if (!dev->fw.vmem_cookie) return -ENOMEM; #else /* not CONFIG_VIDEO_MFC_VCM_UMP && not CONFIG_S5P_VMEM */ /* kernel virtual memory allocator */ dev->mem_infos[0].vmalloc_addr = vmalloc(MFC_MEMSIZE_PORT_A); if (dev->mem_infos[0].vmalloc_addr == NULL) return -ENOMEM; base[0] = (unsigned long)dev->mem_infos[0].vmalloc_addr; dev->mem_infos[0].base = ALIGN(base[0], ALIGN_128KB); align_margin = dev->mem_infos[0].base - base[0]; dev->mem_infos[0].size = MFC_MEMSIZE_PORT_A - align_margin; dev->mem_infos[0].addr = (unsigned char *)dev->mem_infos[0].base; if (dev->mem_ports == 2) { dev->mem_infos[1].vmalloc_addr = vmalloc(MFC_MEMSIZE_PORT_B); if (dev->mem_infos[1].vmalloc_addr == NULL) { vfree(dev->mem_infos[0].vmalloc_addr); return -ENOMEM; } base[1] = (unsigned long)dev->mem_infos[1].vmalloc_addr; dev->mem_infos[1].base = ALIGN(base[1], ALIGN_128KB); align_margin = dev->mem_infos[1].base - base[1]; dev->mem_infos[1].size = MFC_MEMSIZE_PORT_B - align_margin; dev->mem_infos[1].addr = (unsigned char *)dev->mem_infos[1].base; } #endif /* end of CONFIG_VIDEO_MFC_VCM_UMP */ #else /* not SYSMMU_MFC_ON */ /* early allocator */ #if defined(CONFIG_S5P_MEM_CMA) #ifdef CONFIG_EXYNOS4_CONTENT_PATH_PROTECTION if (cma_info(&cma_infos[0], dev->device, "A")) { mfc_info("failed to get CMA info of 'mfc-secure'\n"); return -ENOMEM; } if (cma_info(&cma_infos[1], dev->device, "B")) { mfc_info("failed to get CMA info of 'mfc-normal'\n"); return -ENOMEM; } if (cma_infos[0].lower_bound > cma_infos[1].lower_bound) { mfc_info("'mfc-secure' region must be lower than 'mfc-normal' region\n"); return -ENOMEM; } /* * available = secure + normal * bound = secure + hole + normal * hole = bound - available */ available_size = cma_infos[0].free_size + cma_infos[1].free_size; bound_size = cma_infos[1].upper_bound - cma_infos[0].lower_bound; hole_size = bound_size - available_size; mfc_dbg("avail: 0x%08x, bound: 0x%08x offset: 0x%08x, hole: 0x%08x\n", available_size, bound_size, MAX_MEM_OFFSET, hole_size); /* re-assign actually available size */ if (bound_size > MAX_MEM_OFFSET) { if (cma_infos[0].free_size > MAX_MEM_OFFSET) /* it will be return error */ available_size = MAX_MEM_OFFSET; else if ((cma_infos[0].free_size + hole_size) >= MAX_MEM_OFFSET) /* it will be return error */ available_size = cma_infos[0].free_size; else available_size -= (bound_size - MAX_MEM_OFFSET); } mfc_dbg("avail: 0x%08x\n", available_size); size = cma_infos[0].free_size; if (size > available_size) { mfc_info("'mfc-secure' region is too large (%d:%d)", size >> 10, MAX_MEM_OFFSET >> 10); return -ENOMEM; }
/* FIXME: check every exception case (goto) */ static int __devinit mfc_probe(struct platform_device *pdev) { struct resource *res; int ret; mfcdev = kzalloc(sizeof(struct mfc_dev), GFP_KERNEL); if (unlikely(mfcdev == NULL)) { dev_err(&pdev->dev, "failed to allocate control memory\n"); return -ENOMEM; } /* init. control structure */ sprintf(mfcdev->name, "%s", MFC_DEV_NAME); mutex_init(&mfcdev->lock); init_waitqueue_head(&mfcdev->wait_sys); init_waitqueue_head(&mfcdev->wait_codec[0]); init_waitqueue_head(&mfcdev->wait_codec[1]); atomic_set(&mfcdev->inst_cnt, 0); #ifdef CONFIG_CPU_FREQ atomic_set(&mfcdev->busfreq_lock_cnt, 0); atomic_set(&mfcdev->cpufreq_lock_cnt, 0); #endif mfcdev->device = &pdev->dev; platform_set_drvdata(pdev, mfcdev); /* get the memory region */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(res == NULL)) { dev_err(&pdev->dev, "no memory resource specified\n"); ret = -ENOENT; goto err_mem_res; } mfcdev->reg.rsrc_start = res->start; mfcdev->reg.rsrc_len = resource_size(res); /* request mem region for MFC register (0x0000 ~ 0xE008) */ res = request_mem_region(mfcdev->reg.rsrc_start, mfcdev->reg.rsrc_len, pdev->name); if (unlikely(res == NULL)) { dev_err(&pdev->dev, "failed to get memory region\n"); ret = -ENOENT; goto err_mem_req; } /* ioremap for MFC register */ mfcdev->reg.base = ioremap(mfcdev->reg.rsrc_start, mfcdev->reg.rsrc_len); if (unlikely(!mfcdev->reg.base)) { dev_err(&pdev->dev, "failed to ioremap memory region\n"); ret = -EINVAL; goto err_mem_map; } init_reg(mfcdev->reg.base); mfcdev->irq = platform_get_irq(pdev, 0); if (unlikely(mfcdev->irq < 0)) { dev_err(&pdev->dev, "no irq resource specified\n"); ret = -ENOENT; goto err_irq_res; } ret = request_irq(mfcdev->irq, mfc_irq, IRQF_DISABLED, mfcdev->name, mfcdev); if (ret) { dev_err(&pdev->dev, "failed to allocate irq (%d)\n", ret); goto err_irq_req; } /* * initialize PM(power, clock) interface */ ret = mfc_init_pm(mfcdev); if (ret < 0) { printk(KERN_ERR "failed to init. MFC PM interface\n"); goto err_pm_if; } /* * initialize memory manager */ ret = mfc_init_mem_mgr(mfcdev); if (ret < 0) { printk(KERN_ERR "failed to init. MFC memory manager\n"); goto err_mem_mgr; } /* * loading firmware */ mfcdev->fw.requesting = 1; ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, MFC_FW_NAME, &pdev->dev, GFP_KERNEL, pdev, mfc_firmware_request_complete_handler); if (ret) { mfcdev->fw.requesting = 0; dev_err(&pdev->dev, "could not load firmware (err=%d)\n", ret); goto err_fw_req; } #if defined(SYSMMU_MFC_ON) && defined(CONFIG_VIDEO_MFC_VCM_UMP) ret = vcm_activate(mfcdev->vcm_info.sysmmu_vcm); if (ret < 0) { mfc_err("failed to activate VCM: %d", ret); goto err_act_vcm; } #endif /* * initialize buffer manager */ mfc_init_buf(); /* FIXME: final dec & enc */ mfc_init_decoders(); mfc_init_encoders(); ret = misc_register(&mfc_miscdev); if (ret) { mfc_err("MFC can't misc register on minor=%d\n", MFC_MINOR); goto err_misc_reg; } mfc_info("MFC(Multi Function Codec - FIMV v5.x) registered successfully\n"); return 0; err_misc_reg: mfc_final_buf(); #ifdef SYSMMU_MFC_ON #ifdef CONFIG_VIDEO_MFC_VCM_UMP mfc_clock_on(); vcm_deactivate(mfcdev->vcm_info.sysmmu_vcm); mfc_clock_off(); err_act_vcm: #endif mfc_clock_on(); sysmmu_off(SYSMMU_MFC_L); sysmmu_off(SYSMMU_MFC_R); mfc_clock_off(); #endif if (mfcdev->fw.info) release_firmware(mfcdev->fw.info); err_fw_req: /* FIXME: make kenel dump when probe fail */ mfc_clock_on(); mfc_final_mem_mgr(mfcdev); mfc_clock_off(); err_mem_mgr: mfc_final_pm(mfcdev); err_pm_if: free_irq(mfcdev->irq, mfcdev); err_irq_req: err_irq_res: iounmap(mfcdev->reg.base); err_mem_map: release_mem_region(mfcdev->reg.rsrc_start, mfcdev->reg.rsrc_len); err_mem_req: err_mem_res: platform_set_drvdata(pdev, NULL); mutex_destroy(&mfcdev->lock); kfree(mfcdev); 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; }
static int mfc_release(struct inode *inode, struct file *file) { mfc_inst_ctx *mfc_ctx; int ret; #if ENABLE_MONITORING_MFC_DD mfc_info("MFC Release..\n"); #endif mutex_lock(&mfc_mutex); #if Frame_Base_Power_CTR_ON /*if (s5pv210_pd_enable("mfc_pd") < 0) { printk(KERN_ERR "[Error]The power is not on for mfc\n"); return -1; }*/ clk_enable(mfc_clk); #endif mfc_ctx = (mfc_inst_ctx *)file->private_data; if (mfc_ctx == NULL) { mfc_err("MFCINST_ERR_INVALID_PARAM\n"); ret = -EIO; goto out_release; } mfc_release_all_buffer(mfc_ctx->mem_inst_no); mfc_merge_fragment(mfc_ctx->mem_inst_no); mfc_return_mem_inst_no(mfc_ctx->mem_inst_no); /* In case of no instance, we should not release codec instance */ if (mfc_ctx->InstNo >= 0) mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType); kfree(mfc_ctx); ret = 0; out_release: if (!mfc_is_running()) { #ifdef CONFIG_CPU_FREQ_S5PV210 s5pv210_set_cpufreq_level(NORMAL_TABLE); #endif /* CONFIG_CPU_FREQ_S5PV210 */ #ifdef CONFIG_PM_PWR_GATING s5pc110_unlock_power_domain(MFC_DOMAIN_LOCK_TOKEN); #endif #ifdef CONFIG_S5P_LPAUDIO s5p_set_lpaudio_lock(0); #endif /* CONFIG_S5P_LPAUDIO */ } clk_disable(mfc_clk); if (s5pv210_pd_disable("mfc_pd") < 0) { printk(KERN_ERR "[Error]The power is not off for mfc\n"); return -1; } mutex_unlock(&mfc_mutex); return ret; }
void mfc_print_shared_mem(unsigned int host_wr_addr) { mfc_info("set_frame_tag = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, SET_FRAME_TAG)); mfc_info("start_byte_num = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM)); mfc_info("ext_enc_control = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, EXT_ENC_CONTROL)); mfc_info("enc_param_change = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, ENC_PARAM_CHANGE)); mfc_info("vop_timing = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, VOP_TIMING)); mfc_info("hec_period = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, HEC_PERIOD)); mfc_info("p_b_frame_qp = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, P_B_FRAME_QP)); mfc_info("metadata_enable = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, METADATA_ENABLE)); mfc_info("ext_metadata_start_addr= 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, EXT_METADATA_START_ADDR)); mfc_info("put_extradata = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, PUT_EXTRADATA)); mfc_info("dbg_info_input0 = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_INPUT0)); mfc_info("dbg_info_input1 = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_INPUT1)); mfc_info("luma_dpb_size = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_LUMA_DPB_SIZE)); mfc_info("chroma_dpb_size = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_CHROMA_DPB_SIZE)); mfc_info("mv_size = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_MV_SIZE)); mfc_info("extended_decode_status = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, EXTENEDED_DECODE_STATUS)); mfc_info("get_frame_tag_top = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_TOP)); mfc_info("get_frame_tag_bot = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_BOT)); mfc_info("pic_time_top = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_TOP)); mfc_info("pic_time_bot = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_BOT)); mfc_info("start_byte_num = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM)); mfc_info("dec_frm_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DEC_FRM_SIZE)); mfc_info("crop_info1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, CROP_INFO1)); mfc_info("crop_info2 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, CROP_INFO2)); mfc_info("metadata_status = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_STATUS)); mfc_info("metadata_display_index = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_DISPLAY_INDEX)); mfc_info("dbg_info_output0 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT0)); mfc_info("dbg_info_output1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT1)); mfc_info("720p_limit_enable = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, P720_LIMIT_ENABLE)); mfc_info("RC_CONTROL_ENABLE = 0x%08x\n" ,mfc_read_shared_mem_item(host_wr_addr, RC_CONTROL_ENABLE)); }
/* 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; }
static int mfc_open(struct inode *inode, struct file *file) { mfc_inst_ctx *mfc_ctx; int ret; //struct sched_param param = { .sched_priority = 1 }; #if ENABLE_MONITORING_MFC_DD mfc_info("MFC mfc_open..\n"); #endif mutex_lock(&mfc_mutex); if (!mfc_is_running()) { #ifdef CONFIG_CPU_FREQ_S5PV210 s5pv210_set_cpufreq_level(RESTRICT_TABLE); #endif /* CONFIG_CPU_FREQ_S5PV210 */ #ifdef CONFIG_S5P_LPAUDIO s5p_set_lpaudio_lock(1); #endif /* CONFIG_S5P_LPAUDIO */ if (s5pv210_pd_enable("mfc_pd") < 0){ printk(KERN_ERR "[Error]The power is not on for mfc\n"); return -1; } clk_enable(mfc_clk); #ifdef CONFIG_PM_PWR_GATING s5pc110_lock_power_domain(MFC_DOMAIN_LOCK_TOKEN); #endif if (mfc_init_hw() != TRUE) { #if Frame_Base_Power_CTR_ON clk_disable(mfc_clk); if (s5pv210_pd_disable("mfc_pd") < 0) { printk(KERN_ERR "[Error]The power is not off for mfc\n"); return -1; } #endif ret = -ENODEV; goto out_open; } #if Frame_Base_Power_CTR_ON clk_disable(mfc_clk); /*if (s5pv210_pd_disable("mfc_pd") < 0) { printk(KERN_ERR "[Error]The power is not off for mfc\n"); return -1; }*/ #endif } mfc_ctx = (mfc_inst_ctx *)kmalloc(sizeof(mfc_inst_ctx), GFP_KERNEL); if (mfc_ctx == NULL) { mfc_err("MFCINST_MEMORY_ALLOC_FAIL\n"); ret = -ENOMEM; goto out_open; } memset(mfc_ctx, 0, sizeof(mfc_inst_ctx)); /* get the inst no allocating some part of memory among reserved memory */ mfc_ctx->mem_inst_no = mfc_get_mem_inst_no(); mfc_ctx->InstNo = -1; if (mfc_ctx->mem_inst_no < 0) { mfc_err("MFCINST_INST_NUM_EXCEEDED\n"); kfree(mfc_ctx); ret = -EPERM; goto out_open; } if (mfc_set_state(mfc_ctx, MFCINST_STATE_OPENED) < 0) { mfc_err("MFCINST_ERR_STATE_INVALID\n"); kfree(mfc_ctx); ret = -ENODEV; goto out_open; } /* Decoder only */ mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB; mfc_ctx->FrameType = MFC_RET_FRAME_NOT_SET; file->private_data = (mfc_inst_ctx *)mfc_ctx; //sched_setscheduler(current, SCHED_FIFO, ¶m); ret = 0; out_open: mutex_unlock(&mfc_mutex); if(ret != 0) { mfc_err("MFC_OEPN_FAIL..... ret(%d) \n", ret); return ret; } #if ENABLE_MONITORING_MFC_DD mfc_info("MFC_OEPN_OK..... ret(%d) \n", ret); #endif return ret; }