Beispiel #1
0
/* Try format */
static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
{
	struct s5p_mfc_dev *dev = video_drvdata(file);
	struct s5p_mfc_fmt *fmt;

	mfc_debug(2, "Type is %d\n", f->type);
	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
		fmt = find_format(f, MFC_FMT_DEC);
		if (!fmt) {
			mfc_err("Unsupported format for source.\n");
			return -EINVAL;
		}
		if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
			mfc_err("Not supported format.\n");
			return -EINVAL;
		}
	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
		fmt = find_format(f, MFC_FMT_RAW);
		if (!fmt) {
			mfc_err("Unsupported format for destination.\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;
		}
	}

	return 0;
}
void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev,
					enum mfc_buf_usage_type buf_type)
{
	struct s5p_mfc_extra_buf *fw_info;

	fw_info = &dev->fw_info;

	if (IS_MFCV6(dev)) {
#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
		if (buf_type == MFCBUF_DRM)
			fw_info = &dev->drm_fw_info;

		s5p_mfc_write_reg(dev, fw_info->ofs, S5P_FIMV_RISC_BASE_ADDRESS);
		mfc_info_dev("[%d] Base Address : %08lx\n", buf_type, fw_info->ofs);
#else
		s5p_mfc_write_reg(dev, dev->port_a, S5P_FIMV_RISC_BASE_ADDRESS);
		mfc_debug(2, "Base Address : %08zu\n", dev->port_a);
#endif
	} else {
		/* channelA, port0 */
		s5p_mfc_write_reg(dev, dev->port_a, S5P_FIMV_MC_DRAMBASE_ADR_A);
		/* channelB, port1 */
		s5p_mfc_write_reg(dev, dev->port_b, S5P_FIMV_MC_DRAMBASE_ADR_B);

		mfc_debug(2, "Port A: %08zu, Port B: %08zu\n", dev->port_a, dev->port_b);
	}
}
int s5p_mfc_clock_on(struct s5p_mfc_dev *dev)
{
	int ret = 0;
	int state, val;
	unsigned long flags;

	dev->pm.clock_on_steps = 1;
	MFC_TRACE_DEV("++ clock_on: Set clock rate(%d)\n", dev->curr_rate);
	ret = clk_enable(dev->pm.clock);
	if (ret < 0)
		return ret;

	if (dev->pm.base_type != MFCBUF_INVALID)
		s5p_mfc_init_memctrl(dev, dev->pm.base_type);

	dev->pm.clock_on_steps |= 0x1 << 1;
	if (dev->curr_ctx_drm && dev->is_support_smc) {
		spin_lock_irqsave(&dev->pm.clklock, flags);
		mfc_debug(3, "Begin: enable protection\n");
		ret = exynos_smc(SMC_PROTECTION_SET, 0,
					dev->id, SMC_PROTECTION_ENABLE);
		dev->pm.clock_on_steps |= 0x1 << 2;
		if (!ret) {
			printk("Protection Enable failed! ret(%u)\n", ret);
			spin_unlock_irqrestore(&dev->pm.clklock, flags);
			clk_disable(dev->pm.clock);
			return -EACCES;
		}
		mfc_debug(3, "End: enable protection\n");
		spin_unlock_irqrestore(&dev->pm.clklock, flags);
	} else {
		ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]);
		if (ret < 0) {
			dev->pm.clock_on_steps |= 0x1 << 3;
			clk_disable(dev->pm.clock);
			return ret;
		}
	}

	dev->pm.clock_on_steps |= 0x1 << 4;
	if (IS_MFCV6(dev)) {
		spin_lock_irqsave(&dev->pm.clklock, flags);
		if ((atomic_inc_return(&dev->clk_ref) == 1) &&
				FW_HAS_BUS_RESET(dev)) {
			val = s5p_mfc_read_reg(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
			val &= ~(0x1);
			s5p_mfc_write_reg(dev, val, S5P_FIMV_MFC_BUS_RESET_CTRL);
		}
		spin_unlock_irqrestore(&dev->pm.clklock, flags);
	} else {
		atomic_inc_return(&dev->clk_ref);
	}

	dev->pm.clock_on_steps |= 0x1 << 5;
	state = atomic_read(&dev->clk_ref);
	mfc_debug(2, "+ %d\n", state);
	MFC_TRACE_DEV("-- clock_on : ref state(%d)\n", state);

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

	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");
		return ret;
	}

	/* 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");
		return -EIO;
	}

	s5p_mfc_clock_off();

	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);
		return -EIO;
	}

	mfc_debug_leave();

	return 0;
}
/* Reset the device */
static int s5p_mfc_reset(struct s5p_mfc_dev *dev)
{
	int i;
	unsigned int mc_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(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;
			}

			mc_status = s5p_mfc_read_reg(S5P_FIMV_MC_STATUS);

		} while (mc_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;
}
void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
{
	if (IS_MFCV6(dev))
		s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
	else
		s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();

	dev->mfc_cmds = s5p_mfc_cmds;
}
int s5p_mfc_clock_on(struct s5p_mfc_dev *dev)
{
	int ret = 0;
	int state, val;
	unsigned long flags;

#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
	MFC_TRACE_DEV("++ clock_on: Set clock rate(%d)\n", dev->curr_rate);
	mutex_lock(&dev->curr_rate_lock);
	s5p_mfc_clock_set_rate(dev, dev->curr_rate);
	mutex_unlock(&dev->curr_rate_lock);
#endif
	ret = clk_enable(dev->pm.clock);
	if (ret < 0)
		return ret;

	if (dev->curr_ctx_drm && dev->is_support_smc) {
		spin_lock_irqsave(&dev->pm.clklock, flags);
		mfc_debug(3, "Begin: enable protection\n");
		ret = exynos_smc(SMC_PROTECTION_SET, 0,
					dev->id, SMC_PROTECTION_ENABLE);
		if (!ret) {
			printk("Protection Enable failed! ret(%u)\n", ret);
			spin_unlock_irqrestore(&dev->pm.clklock, flags);
			clk_disable(dev->pm.clock);
			return ret;
		}
		mfc_debug(3, "End: enable protection\n");
		spin_unlock_irqrestore(&dev->pm.clklock, flags);
	} else {
		ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]);
		if (ret < 0) {
			clk_disable(dev->pm.clock);
			return ret;
		}
	}

	if (IS_MFCV6(dev)) {
		spin_lock_irqsave(&dev->pm.clklock, flags);
		if ((atomic_inc_return(&dev->clk_ref) == 1) &&
				FW_HAS_BUS_RESET(dev)) {
			val = s5p_mfc_read_reg(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
			val &= ~(0x1);
			s5p_mfc_write_reg(dev, val, S5P_FIMV_MFC_BUS_RESET_CTRL);
		}
		spin_unlock_irqrestore(&dev->pm.clklock, flags);
	} else {
		atomic_inc_return(&dev->clk_ref);
	}

	state = atomic_read(&dev->clk_ref);
	mfc_debug(2, "+ %d\n", state);
	MFC_TRACE_DEV("-- clock_on : ref state(%d)\n", state);

	return 0;
}
/* Deinitialize hardware */
void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
{
	s5p_mfc_clock_on();

	s5p_mfc_reset(dev);
	if (IS_MFCV6(dev))
		s5p_mfc_release_dev_context_buffer(dev);

	s5p_mfc_clock_off();
}
void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
{
    if (IS_MFCV6(dev)) {
        s5p_mfc_ops = s5p_mfc_init_hw_ops_v6();
        dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6;
    } else {
        s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
        dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
    }
    dev->mfc_ops = s5p_mfc_ops;
}
void s5p_mfc_clock_off(struct s5p_mfc_dev *dev)
{
	int state, val;
	unsigned long timeout, flags;
	int ret = 0;

	if (IS_MFCV6(dev)) {
		spin_lock_irqsave(&dev->pm.clklock, flags);
		if ((atomic_dec_return(&dev->clk_ref) == 0) &&
				FW_HAS_BUS_RESET(dev)) {
			s5p_mfc_write_reg(dev, 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_dev("Timeout while resetting MFC.\n");
					break;
				}
				val = s5p_mfc_read_reg(dev,
						S5P_FIMV_MFC_BUS_RESET_CTRL);
			} while ((val & 0x2) == 0);
		}
		spin_unlock_irqrestore(&dev->pm.clklock, flags);
	} else {
		atomic_dec_return(&dev->clk_ref);
	}

	state = atomic_read(&dev->clk_ref);
	if (state < 0) {
		mfc_err_dev("Clock state is wrong(%d)\n", state);
		atomic_set(&dev->clk_ref, 0);
	} else {
		if (dev->curr_ctx_drm && dev->is_support_smc) {
			mfc_debug(3, "Begin: disable protection\n");
			spin_lock_irqsave(&dev->pm.clklock, flags);
			ret = exynos_smc(SMC_PROTECTION_SET, 0,
					dev->id, SMC_PROTECTION_DISABLE);
			if (!ret) {
				printk("Protection Disable failed! ret(%u)\n", ret);
				spin_unlock_irqrestore(&dev->pm.clklock, flags);
				clk_disable(dev->pm.clock);
				return;
			}
			mfc_debug(3, "End: disable protection\n");
			spin_unlock_irqrestore(&dev->pm.clklock, flags);
		} else {
			s5p_mfc_mem_suspend(dev->alloc_ctx[0]);
		}
		clk_disable(dev->pm.clock);
	}
	mfc_debug(2, "- %d\n", state);
}
static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
{
	if (IS_MFCV6(dev)) {
		/* Zero initialization should be done before RESET.
		 * Nothing to do here. */
	} else {
		s5p_mfc_write_reg(0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
		s5p_mfc_write_reg(0xffffffff, S5P_FIMV_SI_CH1_INST_ID);

		s5p_mfc_write_reg(0, S5P_FIMV_RISC2HOST_CMD);
		s5p_mfc_write_reg(0, S5P_FIMV_HOST2RISC_CMD);
	}
}
static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
{
	if (IS_MFCV6(dev)) {
		s5p_mfc_write_reg(dev->port_a, S5P_FIMV_RISC_BASE_ADDRESS);
		mfc_debug(2, "Base Address : %08x\n", dev->port_a);
	} else {
		/* channelA, port0 */
		s5p_mfc_write_reg(dev->port_a, S5P_FIMV_MC_DRAMBASE_ADR_A);
		/* channelB, port1 */
		s5p_mfc_write_reg(dev->port_b, S5P_FIMV_MC_DRAMBASE_ADR_B);

		mfc_debug(2, "Port A: %08x, Port B: %08x\n", dev->port_a, dev->port_b);
	}
}
Beispiel #13
0
int s5p_mfc_clock_on(void)
{
	int ret = 0;
	int state, val;
	struct s5p_mfc_dev *dev = platform_get_drvdata(to_platform_device(pm->device));
	unsigned long flags;

#ifdef CONFIG_ARM_EXYNOS5410_BUS_DEVFREQ
	s5p_mfc_clock_set_rate(dev, dev->curr_rate);
#endif
	ret = clk_enable(pm->clock);
	if (ret < 0)
		return ret;

	if (!dev->curr_ctx_drm) {
		ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]);
		if (ret < 0) {
			clk_disable(pm->clock);
			return ret;
		}
	}

	if (IS_MFCV6(dev)) {
		spin_lock_irqsave(&pm->clklock, flags);
		if ((atomic_inc_return(&clk_ref) == 1) &&
				FW_HAS_BUS_RESET(dev)) {
			val = s5p_mfc_read_reg(S5P_FIMV_MFC_BUS_RESET_CTRL);
			val &= ~(0x1);
			s5p_mfc_write_reg(val, S5P_FIMV_MFC_BUS_RESET_CTRL);
		}
		spin_unlock_irqrestore(&pm->clklock, flags);
	} else {
		atomic_inc_return(&clk_ref);
	}

	state = atomic_read(&clk_ref);
	mfc_debug(3, "+ %d", state);

	return 0;
}
Beispiel #14
0
void s5p_mfc_clock_off(void)
{
	int state, val;
	unsigned long timeout, flags;
	struct s5p_mfc_dev *dev = platform_get_drvdata(to_platform_device(pm->device));

	if (IS_MFCV6(dev)) {
		spin_lock_irqsave(&pm->clklock, flags);
		if ((atomic_dec_return(&clk_ref) == 0) &&
				FW_HAS_BUS_RESET(dev)) {
			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");
					break;
				}
				val = s5p_mfc_read_reg(
						S5P_FIMV_MFC_BUS_RESET_CTRL);
			} while ((val & 0x2) == 0);
		}
		spin_unlock_irqrestore(&pm->clklock, flags);
	} else {
		atomic_dec_return(&clk_ref);
	}

	state = atomic_read(&clk_ref);
	if (state < 0) {
		mfc_err("Clock state is wrong(%d)\n", state);
		atomic_set(&clk_ref, 0);
	} else {
		if (!dev->curr_ctx_drm)
			s5p_mfc_mem_suspend(dev->alloc_ctx[0]);
		clk_disable(pm->clock);
	}
}
/* Initialize hardware */
int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
{
	char fimv_info;
	int fw_ver;
	int ret = 0;

	mfc_debug_enter();

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

	/* RMVME: */
	if (!s5p_mfc_bitproc_buf)
		return -EINVAL;

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

	s5p_mfc_clock_on();

	ret = s5p_mfc_reset(dev);
	if (ret) {
		mfc_err("Failed to reset MFC - timeout.\n");
		goto err_init_hw;
	}
	mfc_debug(2, "Done MFC reset...\n");

	/* 1. Set DRAM base Addr */
	s5p_mfc_init_memctrl(dev);

	/* 2. Initialize registers of channel I/F */
	s5p_mfc_clear_cmds(dev);
	s5p_mfc_clean_dev_int_flags(dev);

	/* 3. Release reset signal to the RISC */
	if (IS_MFCV6(dev))
		s5p_mfc_write_reg(0x1, S5P_FIMV_RISC_ON);
	else
		s5p_mfc_write_reg(0x3ff, S5P_FIMV_SW_RESET);

	mfc_debug(2, "Will now wait for completion of firmware transfer.\n");
	if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
		mfc_err("Failed to load firmware.\n");
		s5p_mfc_clean_dev_int_flags(dev);
		ret = -EIO;
		goto err_init_hw;
	}

	s5p_mfc_clean_dev_int_flags(dev);
	/* 4. Initialize firmware */
	ret = s5p_mfc_sys_init_cmd(dev);
	if (ret) {
		mfc_err("Failed to send command to MFC - timeout.\n");
		goto err_init_hw;
	}
	mfc_debug(2, "Ok, now will write a command to init the system\n");
	if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
		mfc_err("Failed to load firmware\n");
		ret = -EIO;
		goto err_init_hw;
	}

	dev->int_cond = 0;
	if (dev->int_err != 0 || dev->int_type !=
						S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
		/* Failure. */
		mfc_err("Failed to init firmware - error: %d"
				" int: %d.\n", dev->int_err, dev->int_type);
		ret = -EIO;
		goto err_init_hw;
	}

	fimv_info = MFC_GET_REG(SYS_FW_FIMV_INFO);
	if (fimv_info != 'D' && fimv_info != 'E')
		fimv_info = 'N';

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

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

err_init_hw:
	s5p_mfc_clock_off();
	mfc_debug_leave();

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

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

	s5p_mfc_clock_on(dev);

	dev->wakeup_status = 0;
	/* SYSMMU default block mode (not enalble/disable) */
	if (dev->curr_ctx_drm) {
		ret = s5p_mfc_mem_resume(dev->alloc_ctx[0]);
		if (ret < 0)
			mfc_err_dev("Failed to attach iommu\n");
		s5p_mfc_mem_suspend(dev->alloc_ctx[0]);
	}

	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;
}
/* 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;
	dev->sys_init_status = 0;
	/* 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;
	}

	dev->sys_init_status = 1;
	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;
}
Beispiel #18
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;
}
/* 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;
		if (!IS_MFCV8(dev))
			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;
}
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
{
	int ret;

	mfc_debug_enter();

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

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

	/* 1. Set DRAM base Addr */
	s5p_mfc_init_memctrl(dev, MFCBUF_NORMAL);

	/* 2. Initialize registers of channel I/F */
	s5p_mfc_clear_cmds(dev);

	s5p_mfc_clean_dev_int_flags(dev);
	/* 3. Initialize firmware */
	if (!IS_OVER_MFCv78(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 (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 (IS_OVER_MFCv78(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;
}
/* Initialize hardware */
int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
{
	int ret;

	mfc_debug_enter();

	/* RMVME: */
	if (!s5p_mfc_bitproc_buf)
		return -EINVAL;

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

	s5p_mfc_clock_on();

	ret = s5p_mfc_reset(dev);
	if (ret) {
		mfc_err("Failed to reset MFC - timeout.\n");
		return ret;
	}
	mfc_debug(2, "Done MFC reset...\n");

	/* 1. Set DRAM base Addr */
	s5p_mfc_init_memctrl(dev);

	/* 2. Initialize registers of channel I/F */
	s5p_mfc_clear_cmds(dev);

	/* 3. Release reset signal to the RISC */
	if (IS_MFCV6(dev))
		s5p_mfc_write_reg(0x1, S5P_FIMV_RISC_ON);
	else
		s5p_mfc_write_reg(0x3ff, S5P_FIMV_SW_RESET);

	mfc_debug(2, "Will now wait for completion of firmware transfer.\n");
	if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
		mfc_err("Failed to load firmware.\n");
		s5p_mfc_clean_dev_int_flags(dev);
		return -EIO;
	}

	s5p_mfc_clean_dev_int_flags(dev);
	/* 4. Initialize firmware */
	ret = s5p_mfc_sys_init_cmd(dev);
	if (ret) {
		mfc_err("Failed to send command to MFC - timeout.\n");
		return ret;
	}
	mfc_debug(2, "Ok, now will write a command to init the system\n");
	if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
		mfc_err("Failed to load firmware\n");
		return -EIO;
	}

	dev->int_cond = 0;
	if (dev->int_err != 0 || dev->int_type !=
						S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
		/* Failure. */
		mfc_err("Failed to init firmware - error: %d"
				" int: %d.\n",dev->int_err, dev->int_type);
		return -EIO;
	}

	mfc_info("MFC F/W version : %02xyy, %02xmm, %02xdd\n",
		 MFC_GET_REG(SYS_FW_VER_YEAR),
		 MFC_GET_REG(SYS_FW_VER_MONTH),
		 MFC_GET_REG(SYS_FW_VER_DATE));

	s5p_mfc_clock_off();

	mfc_debug_leave();

	return 0;
}