コード例 #1
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static void hva_device_run(void *priv)
{
	struct hva_ctx *ctx = priv;
	struct hva_dev *hva = ctx_to_hdev(ctx);

	queue_work(hva->work_queue, &ctx->run_work);
}
コード例 #2
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static int hva_release(struct file *file)
{
	struct hva_ctx *ctx = fh_to_ctx(file->private_data);
	struct hva_dev *hva = ctx_to_hdev(ctx);
	struct device *dev = ctx_to_dev(ctx);
	const struct hva_enc *enc = ctx->enc;

	if (enc) {
		dev_dbg(dev, "%s %s encoder closed\n", ctx->name, enc->name);
		enc->close(ctx);
		ctx->enc = NULL;

		/* clear instance context in instances array */
		hva->instances[ctx->id] = NULL;
		hva->nb_of_instances--;
	}

	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);

	v4l2_ctrl_handler_free(&ctx->ctrl_handler);

	v4l2_fh_del(&ctx->fh);
	v4l2_fh_exit(&ctx->fh);

	dev_info(dev, "%s encoder instance released\n", ctx->name);

	kfree(ctx);

	return 0;
}
コード例 #3
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static int hva_enum_fmt_frame(struct file *file, void *priv,
			      struct v4l2_fmtdesc *f)
{
	struct hva_ctx *ctx = fh_to_ctx(file->private_data);
	struct hva_dev *hva = ctx_to_hdev(ctx);

	if (unlikely(f->index >= hva->nb_of_pixelformats))
		return -EINVAL;

	f->pixelformat = hva->pixelformats[f->index];

	return 0;
}
コード例 #4
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static int hva_querycap(struct file *file, void *priv,
			struct v4l2_capability *cap)
{
	struct hva_ctx *ctx = fh_to_ctx(file->private_data);
	struct hva_dev *hva = ctx_to_hdev(ctx);

	strlcpy(cap->driver, HVA_NAME, sizeof(cap->driver));
	strlcpy(cap->card, hva->vdev->name, sizeof(cap->card));
	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
		 hva->pdev->name);

	return 0;
}
コード例 #5
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static void hva_stop_streaming(struct vb2_queue *vq)
{
	struct hva_ctx *ctx = vb2_get_drv_priv(vq);
	struct hva_dev *hva = ctx_to_hdev(ctx);
	struct device *dev = ctx_to_dev(ctx);
	const struct hva_enc *enc = ctx->enc;
	struct vb2_v4l2_buffer *vbuf;

	dev_dbg(dev, "%s %s stop streaming\n", ctx->name,
		to_type_str(vq->type));

	if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		/* return of all pending buffers to vb2 (in error state) */
		ctx->frame_num = 0;
		while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
	} else {
		/* return of all pending buffers to vb2 (in error state) */
		ctx->stream_num = 0;
		while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
	}

	if ((V4L2_TYPE_IS_OUTPUT(vq->type) &&
	     vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q)) ||
	    (!V4L2_TYPE_IS_OUTPUT(vq->type) &&
	     vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))) {
		dev_dbg(dev, "%s %s out=%d cap=%d\n",
			ctx->name, to_type_str(vq->type),
			vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q),
			vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q));
		return;
	}

	/* close encoder when both stop_streaming have been called */
	if (enc) {
		dev_dbg(dev, "%s %s encoder closed\n", ctx->name, enc->name);
		enc->close(ctx);
		ctx->enc = NULL;

		/* clear instance context in instances array */
		hva->instances[ctx->id] = NULL;
		hva->nb_of_instances--;
	}

	ctx->aborting = false;
}
コード例 #6
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static const struct hva_enc *hva_find_encoder(struct hva_ctx *ctx,
					      u32 pixelformat,
					      u32 streamformat)
{
	struct hva_dev *hva = ctx_to_hdev(ctx);
	const struct hva_enc *enc;
	unsigned int i;

	for (i = 0; i < hva->nb_of_encoders; i++) {
		enc = hva->encoders[i];
		if ((enc->pixelformat == pixelformat) &&
		    (enc->streamformat == streamformat))
			return enc;
	}

	return NULL;
}
コード例 #7
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static int hva_open_encoder(struct hva_ctx *ctx, u32 streamformat,
			    u32 pixelformat, struct hva_enc **penc)
{
	struct hva_dev *hva = ctx_to_hdev(ctx);
	struct device *dev = ctx_to_dev(ctx);
	struct hva_enc *enc;
	int ret;

	/* find an encoder which can deal with these formats */
	enc = (struct hva_enc *)hva_find_encoder(ctx, pixelformat,
						 streamformat);
	if (!enc) {
		dev_err(dev, "%s no encoder found matching %4.4s => %4.4s\n",
			ctx->name, (char *)&pixelformat, (char *)&streamformat);
		return -EINVAL;
	}

	dev_dbg(dev, "%s one encoder matching %4.4s => %4.4s\n",
		ctx->name, (char *)&pixelformat, (char *)&streamformat);

	/* update instance name */
	snprintf(ctx->name, sizeof(ctx->name), "[%3d:%4.4s]",
		 hva->instance_id, (char *)&streamformat);

	/* open encoder instance */
	ret = enc->open(ctx);
	if (ret) {
		dev_err(dev, "%s failed to open encoder instance (%d)\n",
			ctx->name, ret);
		return ret;
	}

	dev_dbg(dev, "%s %s encoder opened\n", ctx->name, enc->name);

	*penc = enc;

	return ret;
}
コード例 #8
0
ファイル: hva-v4l2.c プロジェクト: ReneNyffenegger/linux
static int hva_release(struct file *file)
{
	struct hva_ctx *ctx = fh_to_ctx(file->private_data);
	struct hva_dev *hva = ctx_to_hdev(ctx);
	struct device *dev = ctx_to_dev(ctx);
	const struct hva_enc *enc = ctx->enc;

	if (enc) {
		dev_dbg(dev, "%s %s encoder closed\n", ctx->name, enc->name);
		enc->close(ctx);
		ctx->enc = NULL;

		/* clear instance context in instances array */
		hva->instances[ctx->id] = NULL;
		hva->nb_of_instances--;
	}

	/* trace a summary of instance before closing (debug purpose) */
	hva_dbg_summary(ctx);

	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);

	v4l2_ctrl_handler_free(&ctx->ctrl_handler);

	v4l2_fh_del(&ctx->fh);
	v4l2_fh_exit(&ctx->fh);

#ifdef CONFIG_VIDEO_STI_HVA_DEBUGFS
	hva_dbg_ctx_remove(ctx);
#endif

	dev_info(dev, "%s encoder instance released\n", ctx->name);

	kfree(ctx);

	return 0;
}
コード例 #9
0
ファイル: hva-v4l2.c プロジェクト: acton393/linux
static int hva_start_streaming(struct vb2_queue *vq, unsigned int count)
{
	struct hva_ctx *ctx = vb2_get_drv_priv(vq);
	struct hva_dev *hva = ctx_to_hdev(ctx);
	struct device *dev = ctx_to_dev(ctx);
	struct vb2_v4l2_buffer *vbuf;
	int ret;
	unsigned int i;
	bool found = false;

	dev_dbg(dev, "%s %s start streaming\n", ctx->name,
		to_type_str(vq->type));

	/* open encoder when both start_streaming have been called */
	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
		if (!vb2_start_streaming_called(&ctx->fh.m2m_ctx->cap_q_ctx.q))
			return 0;
	} else {
		if (!vb2_start_streaming_called(&ctx->fh.m2m_ctx->out_q_ctx.q))
			return 0;
	}

	/* store the instance context in the instances array */
	for (i = 0; i < HVA_MAX_INSTANCES; i++) {
		if (!hva->instances[i]) {
			hva->instances[i] = ctx;
			/* save the context identifier in the context */
			ctx->id = i;
			found = true;
			break;
		}
	}

	if (!found) {
		dev_err(dev, "%s maximum instances reached\n", ctx->name);
		ret = -ENOMEM;
		goto err;
	}

	hva->nb_of_instances++;

	if (!ctx->enc) {
		ret = hva_open_encoder(ctx,
				       ctx->streaminfo.streamformat,
				       ctx->frameinfo.pixelformat,
				       &ctx->enc);
		if (ret < 0)
			goto err_ctx;
	}

	return 0;

err_ctx:
	hva->instances[ctx->id] = NULL;
	hva->nb_of_instances--;
err:
	if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
		/* return of all pending buffers to vb2 (in queued state) */
		while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED);
	} else {
		/* return of all pending buffers to vb2 (in queued state) */
		while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_QUEUED);
	}

	return ret;
}