Esempio n. 1
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;
	}
Esempio n. 2
0
/* Allocate firmware */
int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
{
#if defined(CONFIG_S5P_MFC_VB2_CMA)
	int err;
	struct cma_info mem_info_f, mem_info_a, mem_info_b;
#endif
	unsigned int base_align = dev->variant->buf_align->mfc_base_align;
	unsigned int firmware_size = dev->variant->buf_size->firmware_code;

	mfc_debug_enter();

#if !defined(CONFIG_S5P_MFC_VB2_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_S5P_MFC_VB2_CMA)
	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;
	}
	mfc_debug(2, "Allocating memory for firmware.\n");
	s5p_mfc_bitproc_buf = s5p_mfc_mem_allocate(
		dev->alloc_ctx[MFC_CMA_FW_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_dma_addr(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(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}
	dev->port_a = s5p_mfc_bitproc_phys;

	s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr(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(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	if (HAS_PORTNUM(dev) && 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_S5P_MFC_VB2_SDVMM)
	mfc_debug(2, "Allocating memory for firmware.\n");
	s5p_mfc_bitproc_buf = s5p_mfc_mem_alloc(
		dev->alloc_ctx[MFC_CMA_FW_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_cookie(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	dev->port_a = s5p_mfc_bitproc_phys;
	dev->port_b = s5p_mfc_bitproc_phys;

	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);
#elif defined(CONFIG_S5P_MFC_VB2_ION)
	mfc_debug(2, "Allocating memory for firmware.\n");
	s5p_mfc_bitproc_buf = s5p_mfc_mem_allocate(
		dev->alloc_ctx[MFC_CMA_FW_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_dma_addr(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(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr(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(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	dev->port_a = s5p_mfc_bitproc_phys;
	dev->port_b = s5p_mfc_bitproc_phys;

	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);

#endif
	mfc_debug_leave();

	return 0;
}
Esempio n. 3
0
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
{
	int ret;

	mfc_debug_enter();

	/* 0. MFC reset */
	mfc_debug(2, "MFC reset...\n");

	s5p_mfc_clock_on();

	ret = s5p_mfc_reset(dev);
	if (ret) {
		mfc_err("Failed to reset MFC - timeout.\n");
		goto err_mfc_wakeup;
	}
	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");
		goto err_mfc_wakeup;
	}

	/* 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");
		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("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();
	mfc_debug_leave();

	return 0;
}
Esempio n. 4
0
static int mfc_probe(struct platform_device *pdev)
{
	struct s3c_platform_mfc *pdata;
	struct resource *res;
	size_t size;
	int ret;

	if (!pdev || !pdev->dev.platform_data) {
		dev_err(&pdev->dev, "Unable to probe mfc!\n");
		return -1;
	}

	pdata = pdev->dev.platform_data;

	/* 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 err_mem_req;
	}

	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 err_mem_map;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "failed to get irq resource\n");
		ret = -ENOENT;
		goto err_irq_res;
	}

#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 err_irq_req;
	}
#endif

	mutex_init(&mfc_mutex);

	/*
	 * buffer memory secure
	 */
	mfc_port0_base_paddr =(unsigned int)pdata->buf_phy_base[0];
	mfc_port0_memsize =  (unsigned int)pdata->buf_phy_size[0];

	mfc_debug(" mfc_port0_base_paddr= 0x%x \n", mfc_port0_base_paddr);
	mfc_debug(" mfc_port0_memsize = 0x%x \n", mfc_port0_memsize);

	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 err_vaddr_map;
	}

	mfc_port1_base_paddr = (unsigned int)pdata->buf_phy_base[1];
	mfc_port1_memsize =  (unsigned int)pdata->buf_phy_size[1];

	mfc_debug(" mfc_port1_base_paddr= 0x%x \n", mfc_port1_base_paddr);
	mfc_debug(" mfc_port1_memsize = 0x%x \n", mfc_port1_memsize);

	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 err_vaddr_map;
	}

	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);

	/* Get mfc power domain regulator */
	mfc_pd_regulator = regulator_get(&pdev->dev, "pd");
	if (IS_ERR(mfc_pd_regulator)) {
		mfc_err("failed to find mfc power domain\n");
		ret = PTR_ERR(mfc_pd_regulator);
		goto err_regulator_get;
	}

	mfc_sclk = clk_get(&pdev->dev, "sclk_mfc");
	if (IS_ERR(mfc_sclk)) {
		mfc_err("failed to find mfc clock source\n");
		ret = PTR_ERR(mfc_sclk);
		goto err_clk_get;
	}

	mfc_init_mem_inst_no();
	mfc_init_buffer();

	ret = misc_register(&mfc_miscdev);
	if (ret) {
		mfc_err("MFC can't misc register on minor\n");
		goto err_misc_reg;
	}

	/*
	 * MFC FW downloading
	 */
	ret = request_firmware_nowait(THIS_MODULE,
				      FW_ACTION_HOTPLUG,
				      MFC_FW_NAME,
				      &pdev->dev,
				      GFP_KERNEL,
				      pdev,
				      mfc_firmware_request_complete_handler);
	if (ret) {
		mfc_err("MFCINST_ERR_FW_INIT_FAIL\n");
		ret = -EPERM;
		goto err_req_fw;
	}

	return 0;

err_req_fw:
	misc_deregister(&mfc_miscdev);
err_misc_reg:
	clk_put(mfc_sclk);
err_clk_get:
	regulator_put(mfc_pd_regulator);
err_regulator_get:
err_vaddr_map:
	free_irq(res->start, pdev);
	mutex_destroy(&mfc_mutex);
err_irq_req:
err_irq_res:
	iounmap(mfc_sfr_base_vaddr);
err_mem_map:
	release_mem_region((unsigned int)mfc_mem, size);
err_mem_req:
probe_out:
	dev_err(&pdev->dev, "not found (%d).\n", ret);
	return ret;
}
Esempio n. 5
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);

#ifdef CONFIG_USE_MFC_CMA
	if (atomic_read(&mfcdev->inst_cnt) == 0) {
#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_GC1)
		size_t size = 0x02800000;
		mfcdev->cma_vaddr = dma_alloc_coherent(mfcdev->device, size,
						&mfcdev->cma_dma_addr, 0);
		if (!mfcdev->cma_vaddr) {
			printk(KERN_ERR "%s: dma_alloc_coherent returns "
						"-ENOMEM\n", __func__);
			mutex_unlock(&mfcdev->lock);
			return -ENOMEM;
		}
		printk(KERN_INFO "%s[%d] size 0x%x, vaddr 0x%x, base 0x%x\n",
					 __func__, __LINE__, (int)size,
						(int)mfcdev->cma_vaddr,
						(int)mfcdev->cma_dma_addr);
#endif
	}
#endif

#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);
	}
Esempio n. 6
0
/* Initialize hardware */
int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
{
    unsigned int ver;
    int ret;

    mfc_debug_enter();
    if (!dev->fw_virt_addr) {
        mfc_err("Firmware memory is not allocated.\n");
        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 */
    s5p_mfc_clean_dev_int_flags(dev);
    if (IS_MFCV6_PLUS(dev))
        mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
    else
        mfc_write(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_MFC_R2H_CMD_FW_STATUS_RET)) {
        mfc_err("Failed to load firmware\n");
        s5p_mfc_reset(dev);
        s5p_mfc_clock_off();
        return -EIO;
    }
    s5p_mfc_clean_dev_int_flags(dev);
    /* 4. Initialize firmware */
    ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
    if (ret) {
        mfc_err("Failed to send command to MFC - timeout\n");
        s5p_mfc_reset(dev);
        s5p_mfc_clock_off();
        return ret;
    }
    mfc_debug(2, "Ok, now will wait for completion of hardware init\n");
    if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
        mfc_err("Failed to init hardware\n");
        s5p_mfc_reset(dev);
        s5p_mfc_clock_off();
        return -EIO;
    }
    dev->int_cond = 0;
    if (dev->int_err != 0 || dev->int_type !=
            S5P_MFC_R2H_CMD_SYS_INIT_RET) {
        /* Failure. */
        mfc_err("Failed to init firmware - error: %d int: %d\n",
                dev->int_err, dev->int_type);
        s5p_mfc_reset(dev);
        s5p_mfc_clock_off();
        return -EIO;
    }
    if (IS_MFCV6_PLUS(dev))
        ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
    else
        ver = mfc_read(dev, S5P_FIMV_FW_VERSION);

    mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
              (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
    s5p_mfc_clock_off();
    mfc_debug_leave();
    return 0;
}
/* Reqeust buffers */
static int vidioc_reqbufs(struct file *file, void *priv,
					  struct v4l2_requestbuffers *reqbufs)
{
	struct s5p_mfc_dev *dev = video_drvdata(file);
	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
	int ret = 0;
	unsigned long flags;

	if (reqbufs->memory != V4L2_MEMORY_MMAP) {
		mfc_err("Only V4L2_MEMORY_MAP is supported\n");
		return -EINVAL;
	}
	if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		/* Can only request buffers after an instance has been opened.*/
		if (ctx->state == MFCINST_INIT) {
			ctx->src_bufs_cnt = 0;
			if (reqbufs->count == 0) {
				mfc_debug(2, "Freeing buffers\n");
				s5p_mfc_clock_on();
				ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
				s5p_mfc_clock_off();
				return ret;
			}
			/* Decoding */
			if (ctx->output_state != QUEUE_FREE) {
				mfc_err("Bufs have already been requested\n");
				return -EINVAL;
			}
			s5p_mfc_clock_on();
			ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
			s5p_mfc_clock_off();
			if (ret) {
				mfc_err("vb2_reqbufs on output failed\n");
				return ret;
			}
			mfc_debug(2, "vb2_reqbufs: %d\n", ret);
			ctx->output_state = QUEUE_BUFS_REQUESTED;
		}
	} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
		ctx->dst_bufs_cnt = 0;
		if (reqbufs->count == 0) {
			mfc_debug(2, "Freeing buffers\n");
			s5p_mfc_clock_on();
			ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
			s5p_mfc_clock_off();
			return ret;
		}
		if (ctx->capture_state != QUEUE_FREE) {
			mfc_err("Bufs have already been requested\n");
			return -EINVAL;
		}
		ctx->capture_state = QUEUE_BUFS_REQUESTED;
		s5p_mfc_clock_on();
		ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
		s5p_mfc_clock_off();
		if (ret) {
			mfc_err("vb2_reqbufs on capture failed\n");
			return ret;
		}
		if (reqbufs->count < ctx->dpb_count) {
			mfc_err("Not enough buffers allocated\n");
			reqbufs->count = 0;
			s5p_mfc_clock_on();
			ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
			s5p_mfc_clock_off();
			return -ENOMEM;
		}
		ctx->total_dpb_count = reqbufs->count;
		ret = s5p_mfc_alloc_codec_buffers(ctx);
		if (ret) {
			mfc_err("Failed to allocate decoding buffers\n");
			reqbufs->count = 0;
			s5p_mfc_clock_on();
			ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
			s5p_mfc_clock_off();
			return -ENOMEM;
		}
		if (ctx->dst_bufs_cnt == ctx->total_dpb_count) {
			ctx->capture_state = QUEUE_BUFS_MMAPED;
		} else {
			mfc_err("Not all buffers passed to buf_init\n");
			reqbufs->count = 0;
			s5p_mfc_clock_on();
			ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
			s5p_mfc_release_codec_buffers(ctx);
			s5p_mfc_clock_off();
			return -ENOMEM;
		}
		if (s5p_mfc_ctx_ready(ctx)) {
			spin_lock_irqsave(&dev->condlock, flags);
			set_bit(ctx->num, &dev->ctx_work_bits);
			spin_unlock_irqrestore(&dev->condlock, flags);
		}
		s5p_mfc_try_run(dev);
		s5p_mfc_wait_for_done_ctx(ctx,
					 S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
	}
	return ret;
}
Esempio n. 8
0
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;
}
Esempio n. 9
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;
}
Esempio n. 10
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
/* 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);
	atomic_set(&mfcdev->busfreq_lock_cnt, 0);

	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
	 */
	ret = request_firmware_nowait(THIS_MODULE,
				      FW_ACTION_HOTPLUG,
				      MFC_FW_NAME,
				      &pdev->dev,
				      GFP_KERNEL,
				      pdev,
				      mfc_firmware_request_complete_handler);
	if (ret) {
		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;
}
Esempio n. 13
0
static int mfc_open(struct inode *inode, struct file *file)
{
	struct mfc_inst_ctx *mfc_ctx;
	int ret;
	enum mfc_ret_code retcode;

	/* prevent invalid reference */
	file->private_data = NULL;

	mutex_lock(&mfcdev->lock);

	if (atomic_read(&mfcdev->inst_cnt) == 0) {
		/* reload F/W for first instance again */
		mfcdev->fw.state = mfc_load_firmware(mfcdev->fw.info->data, mfcdev->fw.info->size);
		if (!mfcdev->fw.state) {
			mfc_err("MFC F/W not load yet\n");
			ret = -ENODEV;
			goto err_fw_state;
		}
		printk(KERN_INFO "MFC F/W reloaded for first Instance successfully (size: %d)\n", mfcdev->fw.info->size);

		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();

		sysmmu_on(SYSMMU_MFC_L);
		sysmmu_on(SYSMMU_MFC_R);

#ifdef CONFIG_VIDEO_MFC_VCM_UMP
		vcm_set_pgtable_base(VCM_DEV_MFC);
#else /* CONFIG_S5P_VMEM or kernel virtual memory allocator */
		sysmmu_set_tablebase_pgd(SYSMMU_MFC_L, __pa(swapper_pg_dir));
		sysmmu_set_tablebase_pgd(SYSMMU_MFC_R, __pa(swapper_pg_dir));

		/*
		 * RMVME: the power-gating work really (on <-> off),
		 * all TBL entry was invalidated already when the power off
		 */
		sysmmu_tlb_invalidate(SYSMMU_MFC_L);
		sysmmu_tlb_invalidate(SYSMMU_MFC_R);
#endif
		mfc_clock_off();
#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;
		}
	}

	mfc_ctx = mfc_create_inst();
	if (!mfc_ctx) {
		mfc_err("failed to create instance context\n");
		ret = -ENOMEM;
		goto err_inst_ctx;
	}

	mfc_ctx->id = get_free_inst_id(mfcdev);
	if (mfc_ctx->id < 0) {
		ret = -EINVAL;
		goto err_inst_ctx;
	}

	printk(KERN_INFO"[%s]Opened Instance id %d \n",__func__,mfc_ctx->id);
	mfc_ctx->dev = mfcdev;

	atomic_inc(&mfcdev->inst_cnt);
	mfcdev->inst_ctx[mfc_ctx->id] = mfc_ctx;

	file->private_data = (struct mfc_inst_ctx *)mfc_ctx;

	mutex_unlock(&mfcdev->lock);

	return 0;

err_inst_ctx:
err_start_hw:
	if (atomic_read(&mfcdev->inst_cnt) == 0) {
		if (mfc_power_off() < 0)
			mfc_err("power disable failed\n");
	}

err_pwr_enable:
err_fw_state:
	mutex_unlock(&mfcdev->lock);

	return ret;
}
Esempio n. 14
0
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;
}
int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
{
    struct s5p_mfc_ctx *ctx;
    int ret;
    int old_state;

    mfc_debug_enter();

    if (!dev) {
        mfc_err("no mfc device to run\n");
        return -EINVAL;
    }

    ctx = dev->ctx[dev->curr_ctx];
    if (!ctx) {
        mfc_err("no mfc context to run\n");
        return -EINVAL;
    }
    old_state = ctx->state;
    ctx->state = MFCINST_ABORT;
    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_dev("Waiting for hardware to finish timed out\n");
        ret = -EIO;
        return ret;
    }

    spin_lock_irq(&dev->condlock);
    mfc_info_dev("curr_ctx_drm:%d, hw_lock:%lu\n", dev->curr_ctx_drm, dev->hw_lock);
    set_bit(ctx->num, &dev->hw_lock);
    spin_unlock_irq(&dev->condlock);

    ctx->state = old_state;
    s5p_mfc_clock_on(dev);
    s5p_mfc_clean_dev_int_flags(dev);
    ret = s5p_mfc_sleep_cmd(dev);
    if (ret) {
        mfc_err_dev("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_dev("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_dev("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(dev);

    /* release system pgtable */
    if (dev->curr_ctx_drm) {
        ret = s5p_mfc_release_sec_pgtable(dev);
        if (ret < 0) {
            mfc_err("Fail to release MFC secure sysmmu page tables. ret = %d\n", ret);
        }
    }

    mfc_debug_leave();

    return ret;
}
Esempio n. 16
0
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, &param);

	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;
}
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);
    /* Set clock source again after wake up */
    s5p_mfc_set_clock_parent(dev);

    /* setup system pgtable */
    if (dev->curr_ctx_drm) {
        ret = s5p_mfc_request_sec_pgtable(dev);
        if (ret < 0) {
            mfc_err("Fail to make MFC secure sysmmu page tables. ret = %d\n", ret);
        }
    }

    /* 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");
    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;
}
Esempio n. 18
0
/* Input arguments for S3C_MFC_IOCTL_MFC_SET_CONFIG */
int s3c_mfc_set_config_params(s3c_mfc_inst_context_t *mfc_inst, s3c_mfc_args_t *args)		
{   __D("\n");
	int             ret, size;
	unsigned int    param_change_enable = 0, param_change_val;
	unsigned char	*start;
	unsigned int	offset;
	
	switch (args->set_config.in_config_param) {
	case S3C_MFC_SET_CONFIG_DEC_ROTATE:
#if (S3C_MFC_ROTATE_ENABLE == 1)
		args->set_config.out_config_value_old[0]
			= s3c_mfc_inst_set_post_rotate(mfc_inst, args->set_config.in_config_value[0]);
#else
		mfc_err("S3C_MFC_IOCTL_MFC_SET_CONFIG with S3C_MFC_SET_CONFIG_DEC_ROTATE is not supported\n");
		mfc_err("please check if S3C_MFC_ROTATE_ENABLE is defined as 1 in MfcConfig.h file\n");
#endif
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CONFIG_ENC_H263_PARAM:
		args->set_config.out_config_value_old[0] = mfc_inst->h263_annex;
		mfc_inst->h263_annex = args->set_config.in_config_value[0];
		mfc_debug("parameter = 0x%x\n", mfc_inst->h263_annex);
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CONFIG_ENC_SLICE_MODE:
		if (mfc_inst->enc_num_slices) {
			args->set_config.out_config_value_old[0] = 1;
			args->set_config.out_config_value_old[1] = mfc_inst->enc_num_slices;
		} else {
			args->set_config.out_config_value_old[0] = 0;
			args->set_config.out_config_value_old[1] = 0;
		}

		if (args->set_config.in_config_value[0])
			mfc_inst->enc_num_slices = args->set_config.in_config_value[1];
		else
			mfc_inst->enc_num_slices = 0;

		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CONFIG_ENC_PARAM_CHANGE:

		switch (args->set_config.in_config_value[0]) {
		case S3C_ENC_PARAM_GOP_NUM:
			param_change_enable = (1 << 0);
			break;

		case S3C_ENC_PARAM_INTRA_QP:
			param_change_enable = (1 << 1);
			break;

		case S3C_ENC_PARAM_BITRATE:
			param_change_enable = (1 << 2);
			break;

		case S3C_ENC_PARAM_F_RATE:
			param_change_enable = (1 << 3);
			break;

		case S3C_ENC_PARAM_INTRA_REF:
			param_change_enable = (1 << 4);
			break;

		case S3C_ENC_PARAM_SLICE_MODE:
			param_change_enable = (1 << 5);
			break;

		default:
			break;
		}

		param_change_val  = args->set_config.in_config_value[1];
		ret = s3c_mfc_inst_enc_param_change(mfc_inst, param_change_enable, param_change_val);

		break;

	case S3C_MFC_SET_CONFIG_ENC_CUR_PIC_OPT:

		switch (args->set_config.in_config_value[0]) {
		case S3C_ENC_PIC_OPT_IDR:
			mfc_inst->enc_pic_option ^= (args->set_config.in_config_value[1] << 1);
			break;

		case S3C_ENC_PIC_OPT_SKIP:
			mfc_inst->enc_pic_option ^= (args->set_config.in_config_value[1] << 0);
			break;

		case S3C_ENC_PIC_OPT_RECOVERY:
			mfc_inst->enc_pic_option ^= (args->set_config.in_config_value[1] << 24);
			break;

		default:
			break;
		}

		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CACHE_CLEAN:
		/* 
		 * in_config_value[0] : start address in user layer 
		 * in_config_value[1] : offset 
		 * in_config_value[2] : start address of stream buffer in user layer
		 */
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = mfc_inst->stream_buffer + offset;
		size = args->set_config.in_config_value[1];
		dma_cache_maint(start, size, DMA_TO_DEVICE);
		/*
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = (unsigned int)mfc_inst->stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		dmac_clean_range((void *)start, (void *)end);

		start = (unsigned int)mfc_inst->phys_addr_stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		outer_clean_range((unsigned long)start, (unsigned long)end);
		*/
		
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CACHE_INVALIDATE:
		/* 
		 * in_config_value[0] : start address in user layer 
		 * in_config_value[1] : offset 
		 * in_config_value[2] : start address of stream buffer in user layer
		 */
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = mfc_inst->stream_buffer + offset;
		size = args->set_config.in_config_value[1];
		dma_cache_maint(start, size, DMA_FROM_DEVICE);

		/*
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = (unsigned int)mfc_inst->stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		dmac_inv_range((void *)start, (void *)end);

		start = (unsigned int)mfc_inst->phys_addr_stream_buffer + offset;
		end = start + args->set_config.in_config_value[1];
		outer_inv_range((unsigned long)start, (unsigned long)end);
		*/
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CACHE_CLEAN_INVALIDATE:
		/* 
		 * in_config_value[0] : start address in user layer 
		 * in_config_value[1] : offset 
		 * in_config_value[2] : start address of stream buffer in user layer
		 */
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = mfc_inst->stream_buffer + offset;
		size = args->set_config.in_config_value[1];
		dma_cache_maint(start, size, DMA_BIDIRECTIONAL);

		/*
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = (unsigned int)mfc_inst->stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		dmac_flush_range((void *)start, (void *)end);

		start = (unsigned int)mfc_inst->phys_addr_stream_buffer + offset;
		end = start + args->set_config.in_config_value[1];
		outer_flush_range((unsigned long)start, (unsigned long)end);
		*/
		ret = S3C_MFC_INST_RET_OK;
		break;

#if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1))
	case S3C_MFC_SET_PADDING_SIZE:
		mfc_debug("padding size = %d\n", 		\
			args->set_config.in_config_value[0]);
		mfc_inst->padding_size = args->set_config.in_config_value[0];
		ret = S3C_MFC_INST_RET_OK;
		break;
#endif

	default:
		ret = -1;
	}

	/* Output arguments for S3C_MFC_IOCTL_MFC_SET_CONFIG */
	args->set_config.ret_code = ret;

	return S3C_MFC_INST_RET_OK;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
/* Set format */
static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
	struct s5p_mfc_dev *dev = video_drvdata(file);
	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
	int ret = 0;
	struct s5p_mfc_fmt *fmt;
	struct v4l2_pix_format_mplane *pix_mp;

	mfc_debug_enter();
	ret = vidioc_try_fmt(file, priv, f);
	pix_mp = &f->fmt.pix_mp;
	if (ret)
		return ret;
	if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
		v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
		ret = -EBUSY;
		goto out;
	}
	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
		fmt = find_format(f, MFC_FMT_RAW);
		if (!fmt) {
			mfc_err("Unsupported format for source.\n");
			return -EINVAL;
		}
		if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
			mfc_err("Not supported format.\n");
			return -EINVAL;
		} else if (IS_MFCV6(dev) &&
				(fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
			mfc_err("Not supported format.\n");
			return -EINVAL;
		}
		ctx->dst_fmt = fmt;
		mfc_debug_leave();
		return ret;
	} else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		mfc_err("Wrong type error for S_FMT : %d", f->type);
		return -EINVAL;
	}
	fmt = find_format(f, MFC_FMT_DEC);
	if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) {
		mfc_err("Unknown codec\n");
		ret = -EINVAL;
		goto out;
	}
	if (fmt->type != MFC_FMT_DEC) {
		mfc_err("Wrong format selected, you should choose "
					"format for decoding\n");
		ret = -EINVAL;
		goto out;
	}
	if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
		mfc_err("Not supported format.\n");
		return -EINVAL;
	}
	ctx->src_fmt = fmt;
	ctx->codec_mode = fmt->codec_mode;
	mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
	pix_mp->height = 0;
	pix_mp->width = 0;
	if (pix_mp->plane_fmt[0].sizeimage)
		ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
	else
		pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
								DEF_CPB_SIZE;
	pix_mp->plane_fmt[0].bytesperline = 0;
	ctx->state = MFCINST_INIT;
out:
	mfc_debug_leave();
	return ret;
}
Esempio n. 21
0
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;
	struct mfc_inst_ctx *mfc_ctx;

	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 = (struct mfc_inst_ctx *)filp->private_data;

	firmware_size = mfc_get_port0_buff_paddr() - mfc_get_fw_buff_paddr();
	phy_size = (unsigned long)(mfc_port0_memsize - firmware_size + mfc_port1_memsize);

	/* 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);

	if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
		vma->vm_flags |= VM_RESERVED | VM_IO;
	 	/*
 	  	* 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;
		/*
	 	* 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;
		 }
	} else {
	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;
}
Esempio n. 22
0
/* Allocate and load firmware */
int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
{
	struct firmware *fw_blob;
	size_t bank2_base_phys;
	void *b_base;
	int err;

	/* Firmare has to be present as a separate file or compiled
	 * into kernel. */
	mfc_debug_enter();
	err = request_firmware((const struct firmware **)&fw_blob,
				     "s5p-mfc.fw", 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;
	}
	dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
	if (s5p_mfc_bitproc_buf) {
		mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
		release_firmware(fw_blob);
		return -ENOMEM;
	}
	s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc(
		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size);
	if (IS_ERR(s5p_mfc_bitproc_buf)) {
		s5p_mfc_bitproc_buf = NULL;
		mfc_err("Allocating bitprocessor buffer failed\n");
		release_firmware(fw_blob);
		return -ENOMEM;
	}
	s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie(
		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf);
	if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
		mfc_err("The base memory for bank 1 is not aligned to 128KB\n");
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = NULL;
		release_firmware(fw_blob);
		return -EIO;
	}
	s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf);
	if (!s5p_mfc_bitproc_virt) {
		mfc_err("Bitprocessor memory remap failed\n");
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = NULL;
		release_firmware(fw_blob);
		return -EIO;
	}
	dev->bank1 = s5p_mfc_bitproc_phys;
	b_base = vb2_dma_contig_memops.alloc(
		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
	if (IS_ERR(b_base)) {
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = NULL;
		mfc_err("Allocating bank2 base failed\n");
	release_firmware(fw_blob);
		return -ENOMEM;
	}
	bank2_base_phys = s5p_mfc_mem_cookie(
		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
	vb2_dma_contig_memops.put(b_base);
	if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
		mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = NULL;
		release_firmware(fw_blob);
		return -EIO;
	}
	dev->bank2 = bank2_base_phys;
	memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
	wmb();
	release_firmware(fw_blob);
	mfc_debug_leave();
	return 0;
}
Esempio n. 23
0
static int mfc_open(struct inode *inode, struct file *file)
{
	struct mfc_inst_ctx *mfc_ctx;
	int ret;

	mutex_lock(&mfc_mutex);

	if (!mfc_is_running()) {
		/* Turn on mfc power domain regulator */
		ret = regulator_enable(mfc_pd_regulator);
		if (ret < 0) {
			mfc_err("MFC_RET_POWER_ENABLE_FAIL\n");
			ret = -EINVAL;
			goto err_open;
		}

#ifdef CONFIG_DVFS_LIMIT
		s5pv210_lock_dvfs_high_level(DVFS_LOCK_TOKEN_1, L4);
#endif
		clk_enable(mfc_sclk);

		mfc_load_firmware(mfc_fw_info->data, mfc_fw_info->size);

		if (mfc_init_hw() != true) {
			clk_disable(mfc_sclk);
			ret =  -ENODEV;
			goto err_regulator;
		}
		clk_disable(mfc_sclk);
	}

	mfc_ctx = (struct mfc_inst_ctx *)kmalloc(sizeof(struct mfc_inst_ctx), GFP_KERNEL);
	if (mfc_ctx == NULL) {
		mfc_err("MFCINST_MEMORY_ALLOC_FAIL\n");
		ret = -ENOMEM;
		goto err_regulator;
	}

	memset(mfc_ctx, 0, sizeof(struct 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");
		ret = -EPERM;
		goto err_mem_inst;
	}

	if (mfc_set_state(mfc_ctx, MFCINST_STATE_OPENED) < 0) {
		mfc_err("MFCINST_ERR_STATE_INVALID\n");
		ret = -ENODEV;
		goto err_set_state;
	}

	/* Decoder only */
	mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB;
	mfc_ctx->FrameType = MFC_RET_FRAME_NOT_SET;

	file->private_data = mfc_ctx;

	mutex_unlock(&mfc_mutex);

	return 0;

err_set_state:
	mfc_return_mem_inst_no(mfc_ctx->mem_inst_no);
err_mem_inst:
	kfree(mfc_ctx);
err_regulator:
	if (!mfc_is_running()) {
#ifdef CONFIG_DVFS_LIMIT
		s5pv210_unlock_dvfs_high_level(DVFS_LOCK_TOKEN_1);
#endif
		/* Turn off mfc power domain regulator */
		ret = regulator_disable(mfc_pd_regulator);
		if (ret < 0)
			mfc_err("MFC_RET_POWER_DISABLE_FAIL\n");
	}
err_open:
	mutex_unlock(&mfc_mutex);

	return ret;
}
/* Reset the device */
static int s5p_mfc_reset(struct s5p_mfc_dev *dev)
{
    int i;
    unsigned int status;
    unsigned long timeout;

    mfc_debug_enter();

    if (!dev) {
        mfc_err("no mfc device to run\n");
        return -EINVAL;
    }

    /* Stop procedure */
    /* Reset VI */
    /*
    s5p_mfc_write_reg(dev, 0x3f7, S5P_FIMV_SW_RESET);
    */

    if (IS_MFCV6(dev)) {
        /* Zero Initialization of MFC registers */
        s5p_mfc_write_reg(dev, 0, S5P_FIMV_RISC2HOST_CMD);
        s5p_mfc_write_reg(dev, 0, S5P_FIMV_HOST2RISC_CMD);
        s5p_mfc_write_reg(dev, 0, S5P_FIMV_FW_VERSION);

        for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++)
            s5p_mfc_write_reg(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4));

        if (IS_MFCv6X(dev))
            if (s5p_mfc_bus_reset(dev))
                return -EIO;

        s5p_mfc_write_reg(dev, 0, S5P_FIMV_RISC_ON);
        s5p_mfc_write_reg(dev, 0x1FFF, S5P_FIMV_MFC_RESET);
        s5p_mfc_write_reg(dev, 0, S5P_FIMV_MFC_RESET);
    } else {
        s5p_mfc_write_reg(dev, 0x3f6, S5P_FIMV_SW_RESET);	/*  reset RISC */
        s5p_mfc_write_reg(dev, 0x3e2, S5P_FIMV_SW_RESET);	/*  All reset except for MC */
        mdelay(10);

        timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);

        /* Check MC status */
        do {
            if (time_after(jiffies, timeout)) {
                mfc_err_dev("Timeout while resetting MFC.\n");
                return -EIO;
            }

            status = s5p_mfc_read_reg(dev, S5P_FIMV_MC_STATUS);

        } while (status & 0x3);

        s5p_mfc_write_reg(dev, 0x0, S5P_FIMV_SW_RESET);
        s5p_mfc_write_reg(dev, 0x3fe, S5P_FIMV_SW_RESET);
    }

    mfc_debug_leave();

    return 0;
}
Esempio n. 25
0
/* 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;
}
/* 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;

    /* 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;
    }

    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;
}
Esempio n. 27
0
/* Initialize hardware */
int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
{
	char dvx_info;
	int mfc_info;
	int ret = 0;

	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");
		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);

	/* 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;
		/* Disable the clock that enabled in s5p_mfc_sys_init_cmd() */
		s5p_mfc_clock_off();
		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;
	}

	dvx_info = MFC_GET_REG(SYS_FW_DVX_INFO);
	if (dvx_info != 'D' && dvx_info != 'E')
		dvx_info = 'N';

	mfc_info("MFC v%x.%x, F/W : (%c) %02xyy, %02xmm, %02xdd\n",
		 MFC_VER_MAJOR(dev->fw.ver),
		 MFC_VER_MINOR(dev->fw.ver),
		 dvx_info,
		 MFC_GET_REG(SYS_FW_VER_YEAR),
		 MFC_GET_REG(SYS_FW_VER_MONTH),
		 MFC_GET_REG(SYS_FW_VER_DATE));

	dev->fw.date = MFC_GET_REG(SYS_FW_VER_ALL);
	/* Check MFC version and F/W version */
	if (dev->fw.date >= 0x120328) {
		mfc_info = MFC_GET_REG(SYS_MFC_VER);
		if (mfc_info != dev->fw.ver) {
			mfc_err("Invalid F/W version(0x%x) for MFC H/W(0x%x)\n",
					mfc_info, dev->fw.ver);
			ret = -EIO;
			goto err_init_hw;
		}
	}

err_init_hw:
	s5p_mfc_clock_off();
	mfc_debug_leave();

	return ret;
}
/* Allocate firmware */
int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
{
    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_FW_ALLOC_CTX];

    if (dev->fw_info.alloc)
        return 0;

    mfc_debug(2, "Allocating memory for firmware.\n");

    alloc_ctx = dev->alloc_ctx_fw;

    dev->fw_info.alloc = s5p_mfc_mem_alloc_priv(alloc_ctx, firmware_size);
    if (IS_ERR(dev->fw_info.alloc)) {
        dev->fw_info.alloc = 0;
        printk(KERN_ERR "Allocating bitprocessor buffer failed\n");
        return -ENOMEM;
    }

    dev->fw_info.ofs = s5p_mfc_mem_daddr_priv(dev->fw_info.alloc);
    if (dev->fw_info.ofs & ((1 << base_align) - 1)) {
        mfc_err_dev("The base memory is not aligned to %dBytes.\n",
                    (1 << base_align));
        s5p_mfc_mem_free_priv(dev->fw_info.alloc);
        dev->fw_info.ofs = 0;
        dev->fw_info.alloc = 0;
        return -EIO;
    }

    dev->fw_info.virt =
        s5p_mfc_mem_vaddr_priv(dev->fw_info.alloc);
    mfc_debug(2, "Virtual address for FW: %08lx\n",
              (long unsigned int)dev->fw_info.virt);
    if (!dev->fw_info.virt) {
        mfc_err_dev("Bitprocessor memory remap failed\n");
        s5p_mfc_mem_free_priv(dev->fw_info.alloc);
        dev->fw_info.ofs = 0;
        dev->fw_info.alloc = 0;
        return -EIO;
    }

    dev->port_a = dev->fw_info.ofs;
    dev->port_b = dev->fw_info.ofs;

    mfc_debug(2, "Port A: %08x Port B: %08x (FW: %08lx size: %08x)\n",
              dev->port_a, dev->port_b,
              dev->fw_info.ofs,
              firmware_size);
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
    alloc_ctx = dev->alloc_ctx_drm_fw;

    dev->drm_fw_info.alloc = s5p_mfc_mem_alloc_priv(alloc_ctx, firmware_size);
    if (IS_ERR(dev->drm_fw_info.alloc)) {
        /* Release normal F/W buffer */
        s5p_mfc_mem_free_priv(dev->fw_info.alloc);
        dev->fw_info.ofs = 0;
        dev->fw_info.alloc = 0;
        printk(KERN_ERR "Allocating bitprocessor buffer failed\n");
        return -ENOMEM;
    }

    dev->drm_fw_info.ofs = s5p_mfc_mem_daddr_priv(dev->drm_fw_info.alloc);
    if (dev->drm_fw_info.ofs & ((1 << base_align) - 1)) {
        mfc_err_dev("The base memory is not aligned to %dBytes.\n",
                    (1 << base_align));
        s5p_mfc_mem_free_priv(dev->drm_fw_info.alloc);
        /* Release normal F/W buffer */
        s5p_mfc_mem_free_priv(dev->fw_info.alloc);
        dev->fw_info.ofs = 0;
        dev->fw_info.alloc = 0;
        return -EIO;
    }

    mfc_info_dev("Port for DRM F/W : 0x%lx\n", dev->drm_fw_info.ofs);
#endif

    mfc_debug_leave();

    return 0;
}
Esempio n. 29
0
static long mfc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int ret, ex_ret;
	struct mfc_inst_ctx *mfc_ctx = NULL;
	struct mfc_common_args in_param;

	mutex_lock(&mfc_mutex);
	clk_enable(mfc_sclk);

	ret = copy_from_user(&in_param, (struct mfc_common_args *)arg, sizeof(struct 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 = (struct mfc_inst_ctx *)file->private_data;
	mutex_unlock(&mfc_mutex);

	switch (cmd) {
	case IOCTL_MFC_ENC_INIT:
		mutex_lock(&mfc_mutex);

		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 (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 (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) {
			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 (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 (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);
		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 (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);

		mfc_ctx->desc_buff_paddr = in_param.args.mem_alloc.out_paddr + CPB_BUF_SIZE;

		ret = in_param.ret_code;
		mutex_unlock(&mfc_mutex);
		break;

	case IOCTL_MFC_FREE_BUF:
		mutex_lock(&mfc_mutex);
		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;

	case IOCTL_MFC_GET_MMAP_SIZE:

		if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
			mfc_err("MFC_RET_STATE_INVALID\n");
			in_param.ret_code = MFCINST_ERR_STATE_INVALID;
			ret = -EINVAL;

			break;
		}

		in_param.ret_code = MFCINST_RET_OK;
		ret = mfc_ctx->port0_mmap_size;

		break;

	case IOCTL_MFC_BUF_CACHE:
		mutex_lock(&mfc_mutex);

		in_param.ret_code = MFCINST_RET_OK;
		mfc_ctx->buf_type = in_param.args.buf_type;

		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:
	clk_disable(mfc_sclk);

	ex_ret = copy_to_user((struct mfc_common_args *)arg, &in_param, sizeof(struct 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;
}
Esempio n. 30
0
static int s3c_mfc_probe(struct platform_device *pdev)
{
	int	size;
	int	ret;
	struct resource *res;	
	unsigned int mfc_clk;

	/* mfc clock enable  */
	s3c_mfc_hclk = clk_get(&pdev->dev, "hclk_mfc");
	if (!s3c_mfc_hclk || IS_ERR(s3c_mfc_hclk)) {
		mfc_err("failed to get mfc hclk source\n");
		return -ENOENT;
	}	
	clk_enable(s3c_mfc_hclk);

	s3c_mfc_sclk = clk_get(&pdev->dev, "sclk_mfc");
	if (!s3c_mfc_sclk || IS_ERR(s3c_mfc_sclk)) {
		mfc_err("failed to get mfc sclk source\n");
		return -ENOENT;
	}
	clk_enable(s3c_mfc_sclk);

	s3c_mfc_pclk = clk_get(&pdev->dev, "pclk_mfc");
	if (!s3c_mfc_pclk || IS_ERR(s3c_mfc_pclk)) {
		mfc_err("failed to get mfc pclk source\n");
		return -ENOENT;
	}
	clk_enable(s3c_mfc_pclk);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		mfc_err("failed to get memory region resouce\n");
		return -ENOENT;
	}

	size = (res->end-res->start)+1;
	s3c_mfc_mem = request_mem_region(res->start, size, pdev->name);
	if (s3c_mfc_mem == NULL) {
		mfc_err("failed to get memory region\n");
		return -ENOENT;
	}

	s3c_mfc_sfr_base_virt_addr = ioremap_nocache(res->start, size);
	if (s3c_mfc_sfr_base_virt_addr == 0) {
		mfc_err("failed to ioremap() region\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res == NULL) {
		mfc_err("failed to get irq resource\n");
		return -ENOENT;
	}

	ret = request_irq(res->start, s3c_mfc_irq, IRQF_DISABLED, pdev->name, pdev);
	if (ret != 0) {
		mfc_err("failed to install irq (%d)\n", ret);
		return ret;
	}

	s3c_mfc_phys_buffer = s3c_get_media_memory(S3C_MDEV_MFC);

	/* mutex creation and initialization */
	s3c_mfc_mutex = (struct mutex *)kmalloc(sizeof(struct mutex), GFP_KERNEL);
	if (s3c_mfc_mutex == NULL)
		return -ENOMEM;

	mutex_init(s3c_mfc_mutex);

	/* mfc clock set 133 Mhz */
	if (s3c_mfc_setup_clock() == FALSE)
		return -ENODEV;
	
	/*
	 * 2. MFC Memory Setup
	 */
	if (s3c_mfc_setup_memory() == FALSE)
		return -ENOMEM;

	/*
	 * 3. MFC Hardware Initialization
	 */
	if (s3c_mfc_init_hw() == FALSE)
		return -ENODEV;

	ret = misc_register(&s3c_mfc_miscdev);

	clk_disable(s3c_mfc_hclk);
	clk_disable(s3c_mfc_sclk);
	clk_disable(s3c_mfc_pclk);

	return 0;
}