|
@@ -800,7 +800,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
|
|
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
|
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
|
};
|
|
};
|
|
|
|
|
|
-static int coda_start_decoding(struct coda_ctx *ctx);
|
|
|
|
|
|
+static int __coda_start_decoding(struct coda_ctx *ctx);
|
|
|
|
|
|
static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
|
|
static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
|
|
{
|
|
{
|
|
@@ -976,7 +976,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
|
|
|
|
|
|
/* Run coda_start_decoding (again) if not yet initialized */
|
|
/* Run coda_start_decoding (again) if not yet initialized */
|
|
if (!ctx->initialized) {
|
|
if (!ctx->initialized) {
|
|
- int ret = coda_start_decoding(ctx);
|
|
|
|
|
|
+ int ret = __coda_start_decoding(ctx);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
|
|
v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
|
|
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
|
|
v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
|
|
@@ -1041,7 +1041,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static void coda_prepare_encode(struct coda_ctx *ctx)
|
|
|
|
|
|
+static int coda_prepare_encode(struct coda_ctx *ctx)
|
|
{
|
|
{
|
|
struct coda_q_data *q_data_src, *q_data_dst;
|
|
struct coda_q_data *q_data_src, *q_data_dst;
|
|
struct vb2_buffer *src_buf, *dst_buf;
|
|
struct vb2_buffer *src_buf, *dst_buf;
|
|
@@ -1183,6 +1183,8 @@ static void coda_prepare_encode(struct coda_ctx *ctx)
|
|
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
|
|
ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
|
|
coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
|
|
coda_write(dev, ctx->bit_stream_param, CODA_REG_BIT_BIT_STREAM_PARAM);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void coda_device_run(void *m2m_priv)
|
|
static void coda_device_run(void *m2m_priv)
|
|
@@ -1233,16 +1235,12 @@ static void coda_pic_run_work(struct work_struct *work)
|
|
mutex_lock(&ctx->buffer_mutex);
|
|
mutex_lock(&ctx->buffer_mutex);
|
|
mutex_lock(&dev->coda_mutex);
|
|
mutex_lock(&dev->coda_mutex);
|
|
|
|
|
|
- if (ctx->inst_type == CODA_INST_DECODER) {
|
|
|
|
- ret = coda_prepare_decode(ctx);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- mutex_unlock(&dev->coda_mutex);
|
|
|
|
- mutex_unlock(&ctx->buffer_mutex);
|
|
|
|
- /* job_finish scheduled by prepare_decode */
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- coda_prepare_encode(ctx);
|
|
|
|
|
|
+ ret = ctx->ops->prepare_run(ctx);
|
|
|
|
+ if (ret < 0 && ctx->inst_type == CODA_INST_DECODER) {
|
|
|
|
+ mutex_unlock(&dev->coda_mutex);
|
|
|
|
+ mutex_unlock(&ctx->buffer_mutex);
|
|
|
|
+ /* job_finish scheduled by prepare_decode */
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
if (dev->devtype->product != CODA_DX6)
|
|
if (dev->devtype->product != CODA_DX6)
|
|
@@ -1260,10 +1258,7 @@ static void coda_pic_run_work(struct work_struct *work)
|
|
|
|
|
|
coda_hw_reset(ctx);
|
|
coda_hw_reset(ctx);
|
|
} else if (!ctx->aborting) {
|
|
} else if (!ctx->aborting) {
|
|
- if (ctx->inst_type == CODA_INST_DECODER)
|
|
|
|
- coda_finish_decode(ctx);
|
|
|
|
- else
|
|
|
|
- coda_finish_encode(ctx);
|
|
|
|
|
|
+ ctx->ops->finish_run(ctx);
|
|
}
|
|
}
|
|
|
|
|
|
if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out))
|
|
if (ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out))
|
|
@@ -1846,7 +1841,7 @@ err:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-static int coda_start_decoding(struct coda_ctx *ctx)
|
|
|
|
|
|
+static int __coda_start_decoding(struct coda_ctx *ctx)
|
|
{
|
|
{
|
|
struct coda_q_data *q_data_src, *q_data_dst;
|
|
struct coda_q_data *q_data_src, *q_data_dst;
|
|
u32 bitstream_buf, bitstream_size;
|
|
u32 bitstream_buf, bitstream_size;
|
|
@@ -2037,6 +2032,18 @@ static int coda_start_decoding(struct coda_ctx *ctx)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int coda_start_decoding(struct coda_ctx *ctx)
|
|
|
|
+{
|
|
|
|
+ struct coda_dev *dev = ctx->dev;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ mutex_lock(&dev->coda_mutex);
|
|
|
|
+ ret = __coda_start_decoding(ctx);
|
|
|
|
+ mutex_unlock(&dev->coda_mutex);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf,
|
|
static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf,
|
|
int header_code, u8 *header, int *size)
|
|
int header_code, u8 *header, int *size)
|
|
{
|
|
{
|
|
@@ -2081,7 +2088,6 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
|
|
{
|
|
{
|
|
struct coda_ctx *ctx = vb2_get_drv_priv(q);
|
|
struct coda_ctx *ctx = vb2_get_drv_priv(q);
|
|
struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
|
|
struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
|
|
- struct coda_dev *dev = ctx->dev;
|
|
|
|
struct coda_q_data *q_data_src, *q_data_dst;
|
|
struct coda_q_data *q_data_src, *q_data_dst;
|
|
u32 dst_fourcc;
|
|
u32 dst_fourcc;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
@@ -2133,16 +2139,12 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
|
|
+ ret = ctx->ops->start_streaming(ctx);
|
|
if (ctx->inst_type == CODA_INST_DECODER) {
|
|
if (ctx->inst_type == CODA_INST_DECODER) {
|
|
- mutex_lock(&dev->coda_mutex);
|
|
|
|
- ret = coda_start_decoding(ctx);
|
|
|
|
- mutex_unlock(&dev->coda_mutex);
|
|
|
|
if (ret == -EAGAIN)
|
|
if (ret == -EAGAIN)
|
|
return 0;
|
|
return 0;
|
|
else if (ret < 0)
|
|
else if (ret < 0)
|
|
return ret;
|
|
return ret;
|
|
- } else {
|
|
|
|
- ret = coda_start_encoding(ctx);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
ctx->initialized = 1;
|
|
ctx->initialized = 1;
|
|
@@ -2737,10 +2739,9 @@ static int coda_next_free_instance(struct coda_dev *dev)
|
|
return idx;
|
|
return idx;
|
|
}
|
|
}
|
|
|
|
|
|
-static int coda_open(struct file *file, enum coda_inst_type inst_type)
|
|
|
|
|
|
+static int coda_open(struct file *file, enum coda_inst_type inst_type,
|
|
|
|
+ const struct coda_context_ops *ctx_ops)
|
|
{
|
|
{
|
|
- int (*queue_init)(void *priv, struct vb2_queue *src_vq,
|
|
|
|
- struct vb2_queue *dst_vq);
|
|
|
|
struct coda_dev *dev = video_drvdata(file);
|
|
struct coda_dev *dev = video_drvdata(file);
|
|
struct coda_ctx *ctx = NULL;
|
|
struct coda_ctx *ctx = NULL;
|
|
char *name;
|
|
char *name;
|
|
@@ -2763,9 +2764,10 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type)
|
|
kfree(name);
|
|
kfree(name);
|
|
|
|
|
|
ctx->inst_type = inst_type;
|
|
ctx->inst_type = inst_type;
|
|
|
|
+ ctx->ops = ctx_ops;
|
|
init_completion(&ctx->completion);
|
|
init_completion(&ctx->completion);
|
|
INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
|
|
INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
|
|
- INIT_WORK(&ctx->seq_end_work, coda_seq_end_work);
|
|
|
|
|
|
+ INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
|
|
v4l2_fh_init(&ctx->fh, video_devdata(file));
|
|
v4l2_fh_init(&ctx->fh, video_devdata(file));
|
|
file->private_data = &ctx->fh;
|
|
file->private_data = &ctx->fh;
|
|
v4l2_fh_add(&ctx->fh);
|
|
v4l2_fh_add(&ctx->fh);
|
|
@@ -2796,11 +2798,8 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type)
|
|
goto err_clk_ahb;
|
|
goto err_clk_ahb;
|
|
|
|
|
|
set_default_params(ctx);
|
|
set_default_params(ctx);
|
|
- if (inst_type == CODA_INST_ENCODER)
|
|
|
|
- queue_init = coda_encoder_queue_init;
|
|
|
|
- else
|
|
|
|
- queue_init = coda_decoder_queue_init;
|
|
|
|
- ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, queue_init);
|
|
|
|
|
|
+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
|
|
|
|
+ ctx->ops->queue_init);
|
|
if (IS_ERR(ctx->fh.m2m_ctx)) {
|
|
if (IS_ERR(ctx->fh.m2m_ctx)) {
|
|
ret = PTR_ERR(ctx->fh.m2m_ctx);
|
|
ret = PTR_ERR(ctx->fh.m2m_ctx);
|
|
|
|
|
|
@@ -2871,14 +2870,30 @@ err_coda_max:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct coda_context_ops coda_encode_ops = {
|
|
|
|
+ .queue_init = coda_encoder_queue_init,
|
|
|
|
+ .start_streaming = coda_start_encoding,
|
|
|
|
+ .prepare_run = coda_prepare_encode,
|
|
|
|
+ .finish_run = coda_finish_encode,
|
|
|
|
+ .seq_end_work = coda_seq_end_work,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+struct coda_context_ops coda_decode_ops = {
|
|
|
|
+ .queue_init = coda_decoder_queue_init,
|
|
|
|
+ .start_streaming = coda_start_decoding,
|
|
|
|
+ .prepare_run = coda_prepare_decode,
|
|
|
|
+ .finish_run = coda_finish_decode,
|
|
|
|
+ .seq_end_work = coda_seq_end_work
|
|
|
|
+};
|
|
|
|
+
|
|
static int coda_encoder_open(struct file *file)
|
|
static int coda_encoder_open(struct file *file)
|
|
{
|
|
{
|
|
- return coda_open(file, CODA_INST_ENCODER);
|
|
|
|
|
|
+ return coda_open(file, CODA_INST_ENCODER, &coda_encode_ops);
|
|
}
|
|
}
|
|
|
|
|
|
static int coda_decoder_open(struct file *file)
|
|
static int coda_decoder_open(struct file *file)
|
|
{
|
|
{
|
|
- return coda_open(file, CODA_INST_DECODER);
|
|
|
|
|
|
+ return coda_open(file, CODA_INST_DECODER, &coda_decode_ops);
|
|
}
|
|
}
|
|
|
|
|
|
static int coda_release(struct file *file)
|
|
static int coda_release(struct file *file)
|