unsigned int mfc_mem_hole_size(void) { if (mfc_mem_data_size(1)) return mfc_mem_data_base(1) - (mfc_mem_data_base(0) + mfc_mem_data_size(0)); else return 0; }
unsigned long mfc_mem_data_ofs(unsigned long addr, int contig) { unsigned int offset; int i; int port; port = mfc_mem_addr_port(addr); if (port < 0) return 0; offset = addr - mfc_mem_data_base(port); if (contig) { for (i = 0; i < port; i++) offset += mfc_mem_data_size(i); } return offset; }
unsigned int mfc_mem_data_ofs(unsigned int addr, int contig) { unsigned int offset; int i; int port; #ifdef CONFIG_EXYNOS4_CONTENT_PATH_PROTECTION port = 0; #else port = mfc_mem_addr_port(addr); #endif if (port < 0) return 0; offset = addr - mfc_mem_data_base(port); if (contig) { for (i = 0; i < port; i++) offset += mfc_mem_data_size(i); } return offset; }
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; }
/* FIXME: add request firmware ioctl */ static long mfc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct mfc_inst_ctx *mfc_ctx; int ret, ex_ret; struct mfc_common_args in_param; struct mfc_buf_alloc_arg buf_arg; int port; struct mfc_dev *dev; int i; struct mfc_set_config_arg *set_cnf_arg; mfc_ctx = (struct mfc_inst_ctx *)file->private_data; if (!mfc_ctx) return -EINVAL; dev = mfc_ctx->dev; mutex_lock(&dev->lock); ret = copy_from_user(&in_param, (struct mfc_common_args *)arg, sizeof(struct mfc_common_args)); if (ret < 0) { mfc_err("failed to copy parameters\n"); ret = -EIO; in_param.ret_code = MFC_INVALID_PARAM_FAIL; goto out_ioctl; } mutex_unlock(&dev->lock); /* FIXME: add locking */ mfc_dbg("cmd: 0x%08x\n", cmd); switch (cmd) { case IOCTL_MFC_DEC_INIT: mutex_lock(&dev->lock); if (mfc_chk_inst_state(mfc_ctx, INST_STATE_CREATE) < 0) { mfc_err("IOCTL_MFC_DEC_INIT invalid state: 0x%08x\n", mfc_ctx->state); in_param.ret_code = MFC_STATE_INVALID; ret = -EINVAL; break; } mfc_clock_on(); in_param.ret_code = mfc_init_decoding(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mfc_clock_off(); mutex_unlock(&dev->lock); break; case IOCTL_MFC_ENC_INIT: mutex_lock(&dev->lock); if (mfc_chk_inst_state(mfc_ctx, INST_STATE_CREATE) < 0) { mfc_err("IOCTL_MFC_ENC_INIT invalid state: 0x%08x\n", mfc_ctx->state); in_param.ret_code = MFC_STATE_INVALID; ret = -EINVAL; break; } mfc_clock_on(); in_param.ret_code = mfc_init_encoding(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mfc_clock_off(); mutex_unlock(&dev->lock); break; case IOCTL_MFC_DEC_EXE: mutex_lock(&dev->lock); mfc_clock_on(); in_param.ret_code = mfc_exec_decoding(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mfc_clock_off(); mutex_unlock(&dev->lock); break; case IOCTL_MFC_ENC_EXE: mutex_lock(&dev->lock); mfc_clock_on(); in_param.ret_code = mfc_exec_encoding(mfc_ctx, &(in_param.args)); ret = in_param.ret_code; mfc_clock_off(); mutex_unlock(&dev->lock); break; case IOCTL_MFC_GET_IN_BUF: if (in_param.args.mem_alloc.type == ENCODER) { buf_arg.type = ENCODER; port = 1; } else { buf_arg.type = DECODER; port = 0; } /* FIXME: consider the size */ buf_arg.size = in_param.args.mem_alloc.buff_size; /* buf_arg.mapped = in_param.args.mem_alloc.mapped_addr; */ /* FIXME: encodeing linear: 2KB, tile: 8KB */ buf_arg.align = ALIGN_2KB; if (buf_arg.type == ENCODER) in_param.ret_code = mfc_alloc_buf(mfc_ctx, &buf_arg, MBT_DPB | port); else in_param.ret_code = mfc_alloc_buf(mfc_ctx, &buf_arg, MBT_CPB | port); #if defined(CONFIG_VIDEO_MFC_VCM_UMP) in_param.args.mem_alloc.secure_id = buf_arg.secure_id; #elif defined(CONFIG_S5P_VMEM) in_param.args.mem_alloc.cookie = buf_arg.cookie; #else in_param.args.mem_alloc.offset = buf_arg.offset; #endif ret = in_param.ret_code; break; case IOCTL_MFC_FREE_BUF: in_param.ret_code = mfc_free_buf(mfc_ctx, in_param.args.mem_free.key); ret = in_param.ret_code; break; case IOCTL_MFC_GET_REAL_ADDR: in_param.args.real_addr.addr = mfc_get_buf_real(mfc_ctx->id, in_param.args.real_addr.key); mfc_dbg("real addr: 0x%08x", in_param.args.real_addr.addr); if (in_param.args.real_addr.addr) in_param.ret_code = MFC_OK; else in_param.ret_code = MFC_MEM_INVALID_ADDR_FAIL; ret = in_param.ret_code; break; case IOCTL_MFC_GET_MMAP_SIZE: if (mfc_chk_inst_state(mfc_ctx, INST_STATE_CREATE) < 0) { mfc_err("IOCTL_MFC_GET_MMAP_SIZE invalid state: \ 0x%08x\n", mfc_ctx->state); in_param.ret_code = MFC_STATE_INVALID; ret = -EINVAL; break; } in_param.ret_code = MFC_OK; ret = 0; for (i = 0; i < dev->mem_ports; i++) ret += mfc_mem_data_size(i); break; #if defined(CONFIG_VIDEO_MFC_VCM_UMP) case IOCTL_MFC_SET_IN_BUF: if (in_param.args.mem_alloc.type == ENCODER) { buf_arg.secure_id = in_param.args.mem_alloc.secure_id; buf_arg.align = ALIGN_2KB; port = 1; ret = mfc_vcm_bind_from_others(mfc_ctx, &buf_arg, MBT_OTHER | port); } else { in_param.args.real_addr.addr = mfc_ump_get_virt(in_param.args.real_addr.key); mfc_dbg("real addr: 0x%08x", in_param.args.real_addr.addr); if (in_param.args.real_addr.addr) in_param.ret_code = MFC_OK; else in_param.ret_code = MFC_MEM_INVALID_ADDR_FAIL; ret = in_param.ret_code; } break; #endif case IOCTL_MFC_SET_CONFIG: /* FIXME: mfc_chk_inst_state*/ /* RMVME: need locking ? */ mutex_lock(&dev->lock); /* in_param.ret_code = mfc_set_config(mfc_ctx, &(in_param.args)); */ set_cnf_arg = (struct mfc_set_config_arg *)&in_param.args; in_param.ret_code = mfc_set_inst_cfg(mfc_ctx, set_cnf_arg->in_config_param, set_cnf_arg->in_config_value); ret = in_param.ret_code; mutex_unlock(&dev->lock); break; case IOCTL_MFC_GET_CONFIG: /* FIXME: */ /* FIXME: mfc_chk_inst_state */ /* RMVME: need locking ? */ in_param.ret_code = MFC_OK; ret = MFC_OK; break; case IOCTL_MFC_SET_BUF_CACHE: mfc_ctx->buf_cache_type = in_param.args.mem_alloc.buf_cache_type; in_param.ret_code = MFC_OK; break; default: mfc_err("failed to execute ioctl cmd: 0x%08x\n", cmd); in_param.ret_code = MFC_INVALID_PARAM_FAIL; ret = -EINVAL; }
unsigned int mfc_mem_hole_size(void) { return mfc_mem_data_base(1) - (mfc_mem_data_base(0) + mfc_mem_data_size(0)); }