static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) { struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl); struct s5p_mfc_dev *dev = ctx->dev; switch (ctrl->id) { case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: if (ctx->state >= MFCINST_HEAD_PARSED && ctx->state < MFCINST_ABORT) { ctrl->val = ctx->dpb_count; break; } else if (ctx->state != MFCINST_INIT) { v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); return -EINVAL; } /* Should wait for the header to be parsed */ s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); if (ctx->state >= MFCINST_HEAD_PARSED && ctx->state < MFCINST_ABORT) { ctrl->val = ctx->dpb_count; } else { v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n"); return -EINVAL; } break; } return 0; }
/* Get format */ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct v4l2_pix_format_mplane *pix_mp; mfc_debug_enter(); pix_mp = &f->fmt.pix_mp; if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && (ctx->state == MFCINST_GOT_INST || ctx->state == MFCINST_RES_CHANGE_END)) { /* If the MFC is parsing the header, * so wait until it is finished */ s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); } if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && ctx->state >= MFCINST_HEAD_PARSED && ctx->state < MFCINST_ABORT) { /* This is run on CAPTURE (decode output) */ /* Width and height are set to the dimensions of the movie, the buffer is bigger and further processing stages should crop to this rectangle. */ pix_mp->width = ctx->buf_width; pix_mp->height = ctx->buf_height; pix_mp->field = V4L2_FIELD_NONE; pix_mp->num_planes = 2; /* Set pixelformat to the format in which MFC outputs the decoded frame */ pix_mp->pixelformat = ctx->dst_fmt->fourcc; pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size; } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { /* This is run on OUTPUT The buffer contains compressed image so width and height have no meaning */ pix_mp->width = 0; pix_mp->height = 0; pix_mp->field = V4L2_FIELD_NONE; pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size; pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size; pix_mp->pixelformat = ctx->src_fmt->fourcc; pix_mp->num_planes = ctx->src_fmt->num_planes; } else { mfc_err("Format could not be read\n"); mfc_debug(2, "%s-- with error\n", __func__); return -EINVAL; } mfc_debug_leave(); return 0; }
static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, struct v4l2_requestbuffers *reqbufs) { int ret = 0; s5p_mfc_clock_on(); if (reqbufs->count == 0) { mfc_debug(2, "Freeing buffers\n"); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); if (ret) goto out; s5p_mfc_hw_call_void(dev->mfc_ops, release_codec_buffers, ctx); ctx->dst_bufs_cnt = 0; } else if (ctx->capture_state == QUEUE_FREE) { WARN_ON(ctx->dst_bufs_cnt != 0); mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n", reqbufs->count); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); if (ret) goto out; ctx->capture_state = QUEUE_BUFS_REQUESTED; ctx->total_dpb_count = reqbufs->count; ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx); if (ret) { mfc_err("Failed to allocate decoding buffers\n"); reqbufs->count = 0; vb2_reqbufs(&ctx->vq_dst, reqbufs); ret = -ENOMEM; ctx->capture_state = QUEUE_FREE; goto out; } WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count); ctx->capture_state = QUEUE_BUFS_MMAPED; if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); } else { mfc_err("Buffers have already been requested\n"); ret = -EINVAL; } out: s5p_mfc_clock_off(); if (ret) mfc_err("Failed allocating buffers for CAPTURE queue\n"); return ret; }
void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) { ctx->state = MFCINST_RETURN_INST; set_work_bit_irqsave(ctx); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); /* Wait until instance is returned or timeout occurred */ if (s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)) mfc_err("Err returning instance\n"); /* Free resources */ s5p_mfc_hw_call_void(dev->mfc_ops, release_codec_buffers, ctx); s5p_mfc_hw_call_void(dev->mfc_ops, release_instance_buffer, ctx); if (ctx->type == MFCINST_DECODER) s5p_mfc_hw_call_void(dev->mfc_ops, release_dec_desc_buffer, ctx); ctx->inst_no = MFC_NO_INSTANCE_SET; ctx->state = MFCINST_FREE; }
/* Stream on */ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct s5p_mfc_dev *dev = ctx->dev; int ret = -EINVAL; mfc_debug_enter(); if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (ctx->state == MFCINST_INIT) { ctx->dst_bufs_cnt = 0; ctx->src_bufs_cnt = 0; ctx->capture_state = QUEUE_FREE; ctx->output_state = QUEUE_FREE; s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers, ctx); set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); if (s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { /* Error or timeout */ mfc_err("Error getting instance from hardware\n"); s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx); s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); return -EIO; } mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); } ret = vb2_streamon(&ctx->vq_src, type); } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ret = vb2_streamon(&ctx->vq_dst, type); mfc_debug_leave(); return ret; }
int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) { int ret = 0; ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx); if (ret) { mfc_err("Failed allocating instance buffer\n"); goto err; } if (ctx->type == MFCINST_DECODER) { ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_dec_temp_buffers, ctx); if (ret) { mfc_err("Failed allocating temporary buffers\n"); goto err_free_inst_buf; } } set_work_bit_irqsave(ctx); s5p_mfc_clean_ctx_int_flags(ctx); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); if (s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { /* Error or timeout */ mfc_err("Error getting instance from hardware\n"); ret = -EIO; goto err_free_desc_buf; } mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); return ret; err_free_desc_buf: if (ctx->type == MFCINST_DECODER) s5p_mfc_hw_call_void(dev->mfc_ops, release_dec_desc_buffer, ctx); err_free_inst_buf: s5p_mfc_hw_call_void(dev->mfc_ops, release_instance_buffer, ctx); err: return ret; }
/* Reqeust buffers */ static int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) { struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; if (reqbufs->memory != V4L2_MEMORY_MMAP) { mfc_err("Only V4L2_MEMORY_MAP is supported\n"); return -EINVAL; } if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { /* Can only request buffers after an instance has been opened.*/ if (ctx->state == MFCINST_INIT) { ctx->src_bufs_cnt = 0; if (reqbufs->count == 0) { mfc_debug(2, "Freeing buffers\n"); s5p_mfc_clock_on(); ret = vb2_reqbufs(&ctx->vq_src, reqbufs); s5p_mfc_clock_off(); return ret; } /* Decoding */ if (ctx->output_state != QUEUE_FREE) { mfc_err("Bufs have already been requested\n"); return -EINVAL; } s5p_mfc_clock_on(); ret = vb2_reqbufs(&ctx->vq_src, reqbufs); s5p_mfc_clock_off(); if (ret) { mfc_err("vb2_reqbufs on output failed\n"); return ret; } mfc_debug(2, "vb2_reqbufs: %d\n", ret); ctx->output_state = QUEUE_BUFS_REQUESTED; } } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { ctx->dst_bufs_cnt = 0; if (reqbufs->count == 0) { mfc_debug(2, "Freeing buffers\n"); s5p_mfc_clock_on(); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); s5p_mfc_clock_off(); return ret; } if (ctx->capture_state != QUEUE_FREE) { mfc_err("Bufs have already been requested\n"); return -EINVAL; } ctx->capture_state = QUEUE_BUFS_REQUESTED; s5p_mfc_clock_on(); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); s5p_mfc_clock_off(); if (ret) { mfc_err("vb2_reqbufs on capture failed\n"); return ret; } if (reqbufs->count < ctx->dpb_count) { mfc_err("Not enough buffers allocated\n"); reqbufs->count = 0; s5p_mfc_clock_on(); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); s5p_mfc_clock_off(); return -ENOMEM; } ctx->total_dpb_count = reqbufs->count; ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx); if (ret) { mfc_err("Failed to allocate decoding buffers\n"); reqbufs->count = 0; s5p_mfc_clock_on(); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); s5p_mfc_clock_off(); return -ENOMEM; } if (ctx->dst_bufs_cnt == ctx->total_dpb_count) { ctx->capture_state = QUEUE_BUFS_MMAPED; } else { mfc_err("Not all buffers passed to buf_init\n"); reqbufs->count = 0; s5p_mfc_clock_on(); ret = vb2_reqbufs(&ctx->vq_dst, reqbufs); s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx); s5p_mfc_clock_off(); return -ENOMEM; } if (s5p_mfc_ctx_ready(ctx)) set_work_bit_irqsave(ctx); s5p_mfc_hw_call(dev->mfc_ops, try_run, dev); s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET, 0); } return ret; }