Exemplo n.º 1
0
static void s5p_mfc_watchdog_worker(struct work_struct *work)
{
	struct s5p_mfc_dev *dev;
	struct s5p_mfc_ctx *ctx;
	int i, ret;
	int mutex_locked;
	unsigned long flags;

	dev = container_of(work, struct s5p_mfc_dev, watchdog_work);

	mfc_err("Driver timeout error handling.\n");
	/* Lock the mutex that protects open and release.
	 * This is necessary as they may load and unload firmware. */
	mutex_locked = mutex_trylock(&dev->mfc_mutex);
	if (!mutex_locked)
		mfc_err("This is not good. Some instance may be "
							"closing/opening.\n");

	s5p_mfc_clock_off();

	spin_lock_irqsave(&dev->irqlock, flags);

	for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
		ctx = dev->ctx[i];
		if (ctx) {
			ctx->state = MFCINST_ERROR;
			s5p_mfc_cleanup_queue(&ctx->dst_queue,
				&ctx->vq_dst);
			s5p_mfc_cleanup_queue(&ctx->src_queue,
				&ctx->vq_src);
			clear_work_bit(ctx);
			wake_up_ctx(ctx, S5P_FIMV_R2H_CMD_ERR_RET, 0);
		}
	}
	dev->hw_lock = 0;
	spin_unlock_irqrestore(&dev->irqlock, flags);
	/* Double check if there is at least one instance running.
	 * If no instance is in memory than no firmware should be present */
	if (dev->num_inst > 0) {
		ret = s5p_mfc_load_firmware(dev);
		if (ret != 0) {
			mfc_err("Failed to reload FW.\n");
			if (mutex_locked)
				mutex_unlock(&dev->mfc_mutex);
			return;
		}

		ret = s5p_mfc_init_hw(dev);
		if (ret != 0) {
			mfc_err("Failed to reinit FW.\n");
			if (mutex_locked)
				mutex_unlock(&dev->mfc_mutex);
			return;
		}
	}
	if (mutex_locked)
		mutex_unlock(&dev->mfc_mutex);
}
/* Initialize MFC V6 hardware */
static int s5p_mfc_init_hw_v6(struct s5p_mfc_dev *dev)
{
	unsigned int ver;
	int ret;

	mfc_debug_enter();
	ret = s5p_mfc_load_firmware(dev);
	if (ret) {
		mfc_err("Failed to reload FW\n");
		return ret;
	}

	/* 0. MFC reset */
	mfc_debug(2, "MFC reset..\n");
	WARN_ON(dev->risc_on);
	s5p_mfc_clock_on(dev);
	ret = s5p_mfc_ctrl_ops_call(dev, reset, dev);
	if (ret) {
		mfc_err("Failed to reset MFC - timeout\n");
		s5p_mfc_clock_off(dev);
		return ret;
	}
	mfc_debug(2, "Done MFC reset..\n");
	/* 1. Set DRAM base Addr */
	s5p_mfc_init_memctrl_v6(dev);
	/* 2. Release reset signal to the RISC */
	s5p_mfc_clean_dev_int_flags(dev);
	mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);

	ret = s5p_mfc_init_fw(dev);
	if (ret) {
		s5p_mfc_clock_off(dev);
		return ret;
	}

	ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
	mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
		(ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
	s5p_mfc_clock_off(dev);
	dev->risc_on = 1;
	mfc_debug_leave();
	return ret;
}