Пример #1
0
int mfc_wakeup(struct mfc_dev *dev)
{
	int ret;

	/* FIXME: add mfc_power_on()? */

	//mfc_clock_on();
	mfc_clock_on(dev);

	if (mfc_reset() == false) {
		//mfc_clock_off();
		mfc_clock_off(dev);
		return MFC_FAIL;
	}

	mfc_init_memctrl();
	mfc_clear_cmds();

	ret = mfc_cmd_sys_wakeup(dev);

	//mfc_clock_off();
	mfc_clock_off(dev);

	/* FIXME: ret = 0 */
	return ret;
}
Пример #2
0
int mfc_start(struct mfc_dev *dev)
{
	int ret;

	/* FIXME: when MFC start, load firmware again */
	/*
	dev->fw.state = mfc_load_firmware(dev->fw.info->data, dev->fw.info->size);
	*/

	mfc_clock_on(dev);

	if (mfc_reset() == false) {
		mfc_clock_off(dev);
		return MFC_FAIL;
	}

	mfc_init_memctrl();
	mfc_clear_cmds();

	ret = mfc_cmd_fw_start(dev);
	if (ret < 0) {
		mfc_clock_off(dev);
		return ret;
	}

	ret = mfc_cmd_sys_init(dev);

	mfc_clock_off(dev);

	return ret;
}
Пример #3
0
static int mfc_runtime_resume(struct device *dev)
{
	struct mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev));
	int pre_power;

	pre_power = atomic_read(&m_dev->pm.power);
	atomic_set(&m_dev->pm.power, 1);

#ifdef SYSMMU_MFC_ON
	if (pre_power == 0) {
		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));
#endif

		mfc_clock_off();
	}
#endif

	return 0;
}
Пример #4
0
/* FIXME: check mfc_remove funtionalilty */
static int __devexit mfc_remove(struct platform_device *pdev)
{
	struct mfc_dev *dev = platform_get_drvdata(pdev);

	/* FIXME: close all instance? or check active instance? */

	misc_deregister(&mfc_miscdev);

	mfc_final_buf();
#ifdef SYSMMU_MFC_ON
	mfc_clock_on();

#ifdef CONFIG_VIDEO_MFC_VCM_UMP
	vcm_deactivate(mfcdev->vcm_info.sysmmu_vcm);
#endif

	sysmmu_off(SYSMMU_MFC_L);
	sysmmu_off(SYSMMU_MFC_R);

	mfc_clock_off();
#endif
	if (dev->fw.info)
		release_firmware(dev->fw.info);
	mfc_final_mem_mgr(dev);
	mfc_final_pm(dev);
	free_irq(dev->irq, dev);
	iounmap(dev->reg.base);
	release_mem_region(dev->reg.rsrc_start, dev->reg.rsrc_len);
	platform_set_drvdata(pdev, NULL);
	mutex_destroy(&dev->lock);
	kfree(dev);

	return 0;
}
Пример #5
0
static int mfc_release(struct inode *inode, struct file *file)
{
	struct mfc_inst_ctx *mfc_ctx;
	struct mfc_dev *dev;
	int ret;

	mfc_ctx = (struct mfc_inst_ctx *)file->private_data;
	if (!mfc_ctx)
		return -EINVAL;

	dev = mfc_ctx->dev;

	mutex_lock(&dev->lock);

#ifdef CONFIG_CPU_FREQ
	/* Release MFC & Bus Frequency lock for High resolution */
	if (mfc_ctx->busfreq_flag == true){
		atomic_dec(&dev->busfreq_lock_cnt);
		mfc_ctx->busfreq_flag = false;
		if (atomic_read(&dev->busfreq_lock_cnt) == 0){
			/* release Freq lock back to normal */
			s5pv310_busfreq_lock_free(DVFS_LOCK_ID_MFC);
			mfc_dbg("[%s] Bus Freq lock Released Normal !!\n",__func__);
		}
	}
#endif

	file->private_data = NULL;

	printk(KERN_INFO"[%s]Released Instance id %d \n",__func__,mfc_ctx->id);
	dev->inst_ctx[mfc_ctx->id] = NULL;
	atomic_dec(&dev->inst_cnt);

	mfc_destroy_inst(mfc_ctx);

	if (atomic_read(&dev->inst_cnt) == 0) {
		ret = mfc_power_off();
		if (ret < 0) {
			mfc_err("power disable failed.\n");
			goto err_pwr_disable;
		}
	} else {
#if defined(SYSMMU_MFC_ON) && !defined(CONFIG_VIDEO_MFC_VCM_UMP)
	mfc_clock_on();

	sysmmu_tlb_invalidate(SYSMMU_MFC_L);
	sysmmu_tlb_invalidate(SYSMMU_MFC_R);

	mfc_clock_off();
#endif
	}

	ret = 0;

err_pwr_disable:
	mutex_unlock(&dev->lock);

	return ret;
}
Пример #6
0
static void mfc_set_pagetable(enum vcm_dev_id id, unsigned long base)
{
	if (mfc_power_chk()) {
		mfc_clock_on();

		s5p_sysmmu_set_tablebase_pgd(NULL, base);

		mfc_clock_off();
	}
}
Пример #7
0
static void mfc_tlb_invalidate(enum vcm_dev_id id)
{
	if (mfc_power_chk()) {
		mfc_clock_on();

		s5p_sysmmu_tlb_invalidate(NULL);

		mfc_clock_off();
	}
}
Пример #8
0
static int mfc_resume(struct device *dev)
{
	struct mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev));
	int ret;
	u32 timeout;

	if (atomic_read(&m_dev->inst_cnt) == 0)
		return 0;

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

	mfc_clock_off();
#endif

	mutex_lock(&m_dev->lock);

	__raw_writel(S5P_INT_LOCAL_PWR_EN, S5P_PMU_MFC_CONF);

	/* Wait max 1ms */
	timeout = 10;
	while ((__raw_readl(S5P_PMU_MFC_CONF + 0x4) & S5P_INT_LOCAL_PWR_EN)
		!= S5P_INT_LOCAL_PWR_EN) {
		if (timeout == 0) {
			printk(KERN_ERR "Power domain MFC enable failed.\n");
			break;
		}
		timeout--;
		udelay(100);
	}

	ret = mfc_wakeup(m_dev);

	mutex_unlock(&m_dev->lock);

	if (ret != MFC_OK)
		return ret;

	return 0;
}
Пример #9
0
void mfc_destroy_inst(struct mfc_inst_ctx* ctx)
{
	struct mfc_dec_ctx *dec_ctx;
	struct mfc_enc_ctx *enc_ctx;
	struct mfc_pre_cfg *precfg;

	if (ctx) {
		if (ctx->state < INST_STATE_SETUP) {
			while (!list_empty(&ctx->presetcfgs)) {
				precfg = list_entry((&ctx->presetcfgs)->next,
						struct mfc_pre_cfg, list);

				mfc_dbg("remove unused preset config [0x%08x]\n",
					precfg->type);

				list_del(&precfg->list);
				kfree(precfg);
			}
		} else {
			/* free (decoder/encoder & context) private memory */
			if (ctx->type == DECODER) {
				dec_ctx = ctx->c_priv;
				if (dec_ctx->d_priv)
					kfree(dec_ctx->d_priv);

				kfree(dec_ctx);
			} else if (ctx->type == ENCODER) {
				enc_ctx = ctx->c_priv;
				if (enc_ctx->e_priv)
					kfree(enc_ctx->e_priv);

				kfree(enc_ctx);
			}
		}

		if (ctx->state >= INST_STATE_OPEN) {
			mfc_clock_on(ctx->dev);
			mfc_cmd_inst_close(ctx);
			mfc_clock_off(ctx->dev);
		}

		mfc_free_buf_inst(ctx->id);

		/* free instance context memory */
		kfree(ctx);
	}
Пример #10
0
int mfc_sleep(struct mfc_dev *dev)
{
	int ret;

	mfc_clock_on(dev);

	/* FIXME: add SFR backup? */

	ret = mfc_cmd_sys_sleep(dev);

	mfc_clock_off(dev);

	/* FIXME: add mfc_power_off()? */

	/* FIXME: ret = 0 */
	return ret;
}
Пример #11
0
void mfc_destroy_inst(struct mfc_inst_ctx* ctx)
{
	int ret = 0;

	if (ctx) {
		if (ctx->state >= INST_STATE_OPENED) {
			mfc_clock_on();
			/* FIXME: meaningless return value */
			ret = mfc_cmd_inst_close(ctx);
			mfc_clock_off();
		}

		mfc_free_buf_inst(ctx->id);

		/* FIXME: free ctx->c_priv */

		kfree(ctx);
	}
}
Пример #12
0
static int mfc_open(struct inode *inode, struct file *file)
{
	struct mfc_inst_ctx *mfc_ctx;
	int ret;
	enum mfc_ret_code retcode;
	int inst_id;
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
	struct mfc_alloc_buffer *alloc;
#endif

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

	mutex_lock(&mfcdev->lock);

#if defined(CONFIG_USE_MFC_CMA) && defined(CONFIG_MACH_MEHMET)
	if (atomic_read(&mfcdev->inst_cnt) == 0) {
		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

#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
	if (mfcdev->drm_playback) {
		mfc_err("DRM playback was activated, cannot open no more instance\n");
		ret = -EINVAL;
		goto err_drm_playback;
	}
#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) {
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
		if (check_magic(mfcdev->drm_info.addr)) {
			mfc_dbg("DRM playback starting\n");

			clear_magic(mfcdev->drm_info.addr);

			mfcdev->drm_playback = 1;

			mfc_set_buf_alloc_scheme(MBS_FIRST_FIT);
		} else {
			/* 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);
				}
			}
		}
#else
		/* 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);
			}
		}
#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();

		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();
#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;
		}
	}
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
	else {
		if (check_magic(mfcdev->drm_info.addr)) {
			clear_magic(mfcdev->drm_info.addr);
			mfc_err("MFC instances are not cleared before DRM playback!\n");
			ret = -EINVAL;
			goto err_drm_start;
		}
	}
#endif
	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;

	mfc_ctx->id = inst_id;
	mfc_ctx->dev = mfcdev;

#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
	if (mfcdev->drm_playback) {
		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);
	}
Пример #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 (!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 exist, 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");
			goto err_fw_state;
		}
	}

	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) {
			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 reloaded 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;
		}
		
		/*
		 * Indicate that MFC is running
		 */
		mfc_is_running = 1;
	}

	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) {
		mfc_destroy_inst(mfc_ctx);
		ret = -EINVAL;
		goto err_inst_ctx;
	}

	printk(KERN_INFO "MFC instance [%d] opened", 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;
}
Пример #14
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);
#ifdef CONFIG_CPU_FREQ
	atomic_set(&mfcdev->busfreq_lock_cnt, 0);
	atomic_set(&mfcdev->cpufreq_lock_cnt, 0);
#endif

	mfcdev->device = &pdev->dev;

	platform_set_drvdata(pdev, mfcdev);

	/* get the memory region */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (unlikely(res == NULL)) {
		dev_err(&pdev->dev, "no memory resource specified\n");
		ret = -ENOENT;
		goto err_mem_res;
	}

	mfcdev->reg.rsrc_start = res->start;
	mfcdev->reg.rsrc_len = resource_size(res);

	/* request mem region for MFC register (0x0000 ~ 0xE008) */
	res = request_mem_region(mfcdev->reg.rsrc_start,
			mfcdev->reg.rsrc_len, pdev->name);
	if (unlikely(res == NULL)) {
		dev_err(&pdev->dev, "failed to get memory region\n");
		ret = -ENOENT;
		goto err_mem_req;
	}

	/* ioremap for MFC register */
	mfcdev->reg.base = ioremap(mfcdev->reg.rsrc_start, mfcdev->reg.rsrc_len);

	if (unlikely(!mfcdev->reg.base)) {
		dev_err(&pdev->dev, "failed to ioremap memory region\n");
		ret = -EINVAL;
		goto err_mem_map;
	}

	init_reg(mfcdev->reg.base);

	mfcdev->irq = platform_get_irq(pdev, 0);
	if (unlikely(mfcdev->irq < 0)) {
		dev_err(&pdev->dev, "no irq resource specified\n");
		ret = -ENOENT;
		goto err_irq_res;
	}

	ret = request_irq(mfcdev->irq, mfc_irq, IRQF_DISABLED, mfcdev->name, mfcdev);
	if (ret) {
		dev_err(&pdev->dev, "failed to allocate irq (%d)\n", ret);
		goto err_irq_req;
	}

	/*
	 * initialize PM(power, clock) interface
	 */
	ret = mfc_init_pm(mfcdev);
	if (ret < 0) {
		printk(KERN_ERR "failed to init. MFC PM interface\n");
		goto err_pm_if;
	}

	/*
	 * initialize memory manager
	 */
	ret = mfc_init_mem_mgr(mfcdev);
	if (ret < 0) {
		printk(KERN_ERR "failed to init. MFC memory manager\n");
		goto err_mem_mgr;
	}

	/*
	 * loading firmware
	 */
	mfcdev->fw.requesting = 1;
	ret = request_firmware_nowait(THIS_MODULE,
				      FW_ACTION_HOTPLUG,
				      MFC_FW_NAME,
				      &pdev->dev,
				      GFP_KERNEL,
				      pdev,
				      mfc_firmware_request_complete_handler);
	if (ret) {
		mfcdev->fw.requesting = 0;
		dev_err(&pdev->dev, "could not load firmware (err=%d)\n", ret);
		goto err_fw_req;
	}

#if defined(SYSMMU_MFC_ON) && defined(CONFIG_VIDEO_MFC_VCM_UMP)
	ret = vcm_activate(mfcdev->vcm_info.sysmmu_vcm);
	if (ret < 0) {
		mfc_err("failed to activate VCM: %d", ret);

		goto err_act_vcm;
	}
#endif

	/*
	 * initialize buffer manager
	 */
	mfc_init_buf();

	/* FIXME: final dec & enc */
	mfc_init_decoders();
	mfc_init_encoders();

	ret = misc_register(&mfc_miscdev);

	if (ret) {
		mfc_err("MFC can't misc register on minor=%d\n", MFC_MINOR);
		goto err_misc_reg;
	}

	mfc_info("MFC(Multi Function Codec - FIMV v5.x) registered successfully\n");

	return 0;

err_misc_reg:
	mfc_final_buf();

#ifdef SYSMMU_MFC_ON
#ifdef CONFIG_VIDEO_MFC_VCM_UMP
	mfc_clock_on();

	vcm_deactivate(mfcdev->vcm_info.sysmmu_vcm);

	mfc_clock_off();

err_act_vcm:
#endif
	mfc_clock_on();

	sysmmu_off(SYSMMU_MFC_L);
	sysmmu_off(SYSMMU_MFC_R);

	mfc_clock_off();
#endif
	if (mfcdev->fw.info)
		release_firmware(mfcdev->fw.info);

err_fw_req:
	/* FIXME: make kenel dump when probe fail */
	mfc_clock_on();

	mfc_final_mem_mgr(mfcdev);

	mfc_clock_off();

err_mem_mgr:
	mfc_final_pm(mfcdev);

err_pm_if:
	free_irq(mfcdev->irq, mfcdev);

err_irq_req:
err_irq_res:
	iounmap(mfcdev->reg.base);

err_mem_map:
	release_mem_region(mfcdev->reg.rsrc_start, mfcdev->reg.rsrc_len);

err_mem_req:
err_mem_res:
	platform_set_drvdata(pdev, NULL);
	mutex_destroy(&mfcdev->lock);
	kfree(mfcdev);

	return ret;
}
Пример #15
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;
	}
Пример #16
0
static int mfc_open(struct inode *inode, struct file *file)
{
	struct mfc_inst_ctx *mfc_ctx;
	int ret;
	enum mfc_ret_code retcode;
	int inst_id;
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
	struct mfc_alloc_buffer *alloc;
#endif

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

	mutex_lock(&mfcdev->lock);
#if SUPPORT_SLICE_ENCODING
	mfcdev->frame_working_flag = 1;
	mfcdev->frame_sys = 0;
#endif

	if (!mfcdev->fw.state) {
		if (mfcdev->fw.requesting) {
			printk(KERN_INFO "MFC F/W request is on-going, try again\n");
			ret = -ENODEV;
			goto err_fw_state;
		}

		printk(KERN_INFO "MFC F/W is not existing, requesting...\n");
		ret = request_firmware(&mfcdev->fw.info, MFC_FW_NAME, mfcdev->device);

		if (ret < 0) {
			printk(KERN_INFO "failed to copy MFC F/W during open\n");
			ret = -ENODEV;
			goto err_fw_state;
		}

		if (soc_is_exynos4212() || soc_is_exynos4412()) {
			mfcdev->fw.state = mfc_load_firmware(mfcdev->fw.info->data, mfcdev->fw.info->size);
			if (!mfcdev->fw.state) {
				printk(KERN_ERR "failed to load MFC F/W, MFC will not working\n");
				ret = -ENODEV;
				goto err_fw_state;
			} else {
				printk(KERN_INFO "MFC F/W loaded successfully (size: %d)\n", mfcdev->fw.info->size);
			}
		}
	}

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

#if defined(CONFIG_BUSFREQ_OPP) || defined(CONFIG_BUSFREQ_LOCK_WRAPPER)
		dev_lock(mfcdev->bus_dev, mfcdev->device, 133133);
#endif
#ifdef CONFIG_BUSFREQ
		pm_qos_add_request(&bus_qos_pm_qos_req, PM_QOS_BUS_QOS, 1);
#endif

		ret = mfc_power_on();
		if (ret < 0) {
			mfc_err("power enable failed\n");
			goto err_pwr_enable;
		}

#ifndef CONFIG_PM_RUNTIME
#ifdef SYSMMU_MFC_ON
		mfc_clock_on(mfcdev);

		s5p_sysmmu_enable(mfcdev->device);

#ifdef CONFIG_VIDEO_MFC_VCM_UMP
		vcm_set_pgtable_base(VCM_DEV_MFC);
#else /* CONFIG_S5P_VMEM or kernel virtual memory allocator */
		s5p_sysmmu_set_tablebase_pgd(mfcdev->device,
							__pa(swapper_pg_dir));

		/*
		 * RMVME: the power-gating work really (on <-> off),
		 * all TBL entry was invalidated already when the power off
		 */
		s5p_sysmmu_tlb_invalidate(mfcdev->device, SYSMMU_MFC_R);
#endif
		mfc_clock_off(mfcdev);
#endif
#endif
		/* MFC hardware initialization */
		retcode = mfc_start(mfcdev);
		if (retcode != MFC_OK) {
			mfc_err("MFC H/W init failed: %d\n", retcode);
			ret = -ENODEV;
			goto err_start_hw;
		}
	}

	if (atomic_read(&mfcdev->inst_cnt) >= MFC_MAX_INSTANCE_NUM) {
		mfc_err("exceed max instance number, too many instance opened already\n");
		ret = -EINVAL;
		goto err_inst_cnt;
	}

	inst_id = get_free_inst_id(mfcdev);
	if (inst_id < 0) {
		mfc_err("failed to get instance ID\n");
		ret = -EINVAL;
		goto err_inst_id;
	}

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

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

#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
	if (check_magic(mfcdev->drm_info.addr) >= 0) {
		mfc_info("DRM instance starting\n");
		clear_magic(mfcdev->drm_info.addr + check_magic(mfcdev->drm_info.addr));
		mfc_ctx->drm_flag = 1;
		mfc_set_buf_alloc_scheme(MBS_FIRST_FIT);
	} else {
		mfc_ctx->drm_flag = 0;
	}
#endif

	mfc_ctx->id = inst_id;
	mfc_ctx->dev = mfcdev;

#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
	if (mfc_ctx->drm_flag) {
		alloc = _mfc_alloc_buf(mfc_ctx, MFC_CTX_SIZE_L, ALIGN_2KB, MBT_CTX | PORT_A);
		if (alloc == NULL) {
			mfc_err("failed to alloc context buffer\n");
			ret = -ENOMEM;
			goto err_drm_ctx;
		}

		mfc_ctx->ctxbufofs = mfc_mem_base_ofs(alloc->real) >> 11;
		mfc_ctx->ctxbufsize = alloc->size;
		memset((void *)alloc->addr, 0, alloc->size);
		mfc_mem_cache_clean((void *)alloc->addr, alloc->size);
	}