Ejemplo n.º 1
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);
	}
Ejemplo n.º 2
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);
	}