diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index 55c3081bcf..5288b91cd8 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/driver/platform/waipio/src/msm_vidc_waipio.c @@ -82,9 +82,23 @@ static struct msm_platform_core_capability core_data_waipio[] = { }; static struct msm_platform_inst_capability instance_data_waipio[] = { - /* {type, domains, codecs, min, max, step_or_menu, value} */ + /* {type, domains, codecs, min, max, step_or_mask, value} */ {FRAME_WIDTH, ENC|DEC, CODECS_ALL, 128, 8192, 1, 1920}, {FRAME_HEIGHT, ENC|DEC, CODECS_ALL, 128, 8192, 1, 1080}, + {PIX_FMTS, ENC, CODECS_ALL, + MSM_VIDC_FMT_NV12, + MSM_VIDC_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, + MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12_UBWC | + MSM_VIDC_FMT_NV12_P010_UBWC | MSM_VIDC_FMT_NV12_TP10_UBWC | + MSM_VIDC_FMT_RGBA8888_UBWC | MSM_VIDC_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, + MSM_VIDC_FMT_NV12_UBWC}, + {PIX_FMTS, DEC, CODECS_ALL, + MSM_VIDC_FMT_NV12, + MSM_VIDC_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, + MSM_VIDC_FMT_NV12 | MSM_VIDC_FMT_NV21 | MSM_VIDC_FMT_NV12_UBWC | + MSM_VIDC_FMT_NV12_P010_UBWC | MSM_VIDC_FMT_NV12_TP10_UBWC | + MSM_VIDC_FMT_RGBA8888_UBWC | MSM_VIDC_FMT_SDE_Y_CBCR_H2V2_P010_VENUS, + MSM_VIDC_FMT_NV12_UBWC}, /* (8192 * 4320) / 256 */ {MBPF, ENC|DEC, CODECS_ALL, 64, 138240, 1, 138240}, /* ((1920 * 1088) / 256) * 960 fps */ diff --git a/driver/vidc/inc/msm_vdec.h b/driver/vidc/inc/msm_vdec.h index b3b8f5bb4d..71abfc0ef8 100644 --- a/driver/vidc/inc/msm_vdec.h +++ b/driver/vidc/inc/msm_vdec.h @@ -15,6 +15,7 @@ int msm_vdec_stop_output(struct msm_vidc_inst *inst); int msm_vdec_start_output(struct msm_vidc_inst *inst); int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); +int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f); int msm_vdec_inst_init(struct msm_vidc_inst *inst); int msm_vdec_ctrl_init(struct msm_vidc_inst *inst); diff --git a/driver/vidc/inc/msm_venc.h b/driver/vidc/inc/msm_venc.h index e1810d950a..8af066db14 100644 --- a/driver/vidc/inc/msm_venc.h +++ b/driver/vidc/inc/msm_venc.h @@ -9,6 +9,9 @@ #include "msm_vidc_core.h" #include "msm_vidc_inst.h" +int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); +int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); +int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f); int msm_venc_inst_init(struct msm_vidc_inst *inst); int msm_venc_ctrl_init(struct msm_vidc_inst *inst); diff --git a/driver/vidc/inc/msm_vidc_core.h b/driver/vidc/inc/msm_vidc_core.h index 450c68cd87..044d466b88 100644 --- a/driver/vidc/inc/msm_vidc_core.h +++ b/driver/vidc/inc/msm_vidc_core.h @@ -76,6 +76,7 @@ struct msm_vidc_core { u32 spur_count; u32 reg_count; bool power_enabled; + u32 codecs_count; struct msm_vidc_core_capability *capabilities; struct msm_vidc_inst_capability *inst_caps; struct msm_vidc_mem_addr sfr; diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index f414b7e736..b6cc9633cc 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -66,6 +66,11 @@ static inline bool is_thumbnail_session(struct msm_vidc_inst *inst) return false; // TODO: fix it } +u32 get_v4l2_codec_from_vidc(enum msm_vidc_codec_type codec); +enum msm_vidc_codec_type get_vidc_codec_from_v4l2(u32 v4l2_codec); +u32 get_v4l2_colorformat_from_vidc(enum msm_vidc_colorformat_type colorformat); +enum msm_vidc_colorformat_type get_vidc_colorformat_from_v4l2(u32 colorformat); +u32 get_media_colorformat_from_v4l2(u32 v4l2_fmt); int msm_vidc_change_inst_state(struct msm_vidc_inst *inst, enum msm_vidc_inst_state state); int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst, @@ -87,7 +92,6 @@ void msm_vidc_fw_unload_handler(struct work_struct *work); void msm_vidc_batch_handler(struct work_struct *work); int msm_vidc_setup_event_queue(struct msm_vidc_inst *inst); int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst); -u32 msm_vidc_convert_color_fmt(u32 v4l2_fmt); int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl); int msm_vidc_get_port_from_v4l2_type(u32 type); u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst, diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index e49581d44d..5e298913c7 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -169,6 +169,7 @@ enum msm_vidc_inst_capability_type { INST_CAP_NONE = 0, FRAME_WIDTH, FRAME_HEIGHT, + PIX_FMTS, MBPF, MBPS, FRAME_RATE, @@ -223,7 +224,7 @@ struct msm_vidc_inst_cap { enum msm_vidc_inst_capability_type cap; s32 min; s32 max; - u32 step_or_menu; + u32 step_or_mask; s32 value; enum msm_vidc_inst_capability_flags flags; u32 v4l2_id; diff --git a/driver/vidc/inc/msm_vidc_platform.h b/driver/vidc/inc/msm_vidc_platform.h index 87f2cdb57f..ecef436290 100644 --- a/driver/vidc/inc/msm_vidc_platform.h +++ b/driver/vidc/inc/msm_vidc_platform.h @@ -21,7 +21,7 @@ struct msm_platform_inst_capability { enum msm_vidc_codec_type codec; s32 min; s32 max; - u32 step_or_menu; + u32 step_or_mask; s32 value; enum msm_vidc_inst_capability_flags flags; u32 v4l2_id; diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index 4dd04f5103..36125a5ede 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -18,6 +18,7 @@ static int msm_vdec_codec_change(struct msm_vidc_inst *inst, u32 codec) { int rc = 0; + int i; struct msm_vidc_core *core; d_vpr_h("%s()\n", __func__); @@ -27,6 +28,20 @@ static int msm_vdec_codec_change(struct msm_vidc_inst *inst, u32 codec) } core = inst->core; + inst->capabilities = NULL; + for (i = 0; i < core->codecs_count; i++) { + if (core->inst_caps[i].domain == MSM_VIDC_DECODER && + core->inst_caps[i].codec == get_vidc_codec_from_v4l2( + inst->fmts[INPUT_PORT].fmt.pix.pixelformat)) { + s_vpr_h(inst->sid, "%s: changed capabilities to %#x caps\n", + __func__, inst->fmts[INPUT_PORT].fmt.pix.pixelformat); + inst->capabilities = &core->inst_caps[i]; + } + } + if (!inst->capabilities) { + s_vpr_e(inst->sid, "%s: capabilities not found\n", __func__); + return -EINVAL; + } return rc; } @@ -300,7 +315,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) } inst->buffers.input.size = fmt->fmt.pix.sizeimage; - // update crop dimensions + /* update crop dimensions */ inst->crop.x = inst->crop.y = 0; inst->crop.width = f->fmt.pix.width; inst->crop.height = f->fmt.pix.height; @@ -351,10 +366,10 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) fmt->type = OUTPUT_PLANE; fmt->fmt.pix.pixelformat = f->fmt.pix.pixelformat; fmt->fmt.pix.width = VENUS_Y_STRIDE( - msm_vidc_convert_color_fmt(fmt->fmt.pix.pixelformat), + get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat), f->fmt.pix.width); fmt->fmt.pix.height = VENUS_Y_SCANLINES( - msm_vidc_convert_color_fmt(fmt->fmt.pix.pixelformat), + get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat), f->fmt.pix.height); fmt->fmt.pix.bytesperline = fmt->fmt.pix.width; fmt->fmt.pix.sizeimage = call_session_op(core, buffer_size, @@ -416,7 +431,7 @@ err_invalid_fmt: int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) { int rc = 0; - u32 index; + int port; d_vpr_h("%s()\n", __func__); if (!inst) { @@ -424,19 +439,58 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) return -EINVAL; } - if (f->type == OUTPUT_PLANE) { - index = OUTPUT_PORT; - } else if (f->type == INPUT_PLANE) { - index = OUTPUT_PORT; - } else if (f->type == OUTPUT_META_PLANE) { - index = OUTPUT_PORT; - } else if (f->type == OUTPUT_META_PLANE) { - index = OUTPUT_PORT; - } else { - d_vpr_e("%s: invalid type %d\n", __func__, f->type); + port = msm_vidc_get_port_from_v4l2_type(f->type); + if (port < 0) { + d_vpr_e("%s: invalid format type %d\n", __func__, f->type); return -EINVAL; } - memcpy(f, &inst->fmts[index], sizeof(struct v4l2_format)); + memcpy(f, &inst->fmts[port], sizeof(struct v4l2_format)); + + return rc; +} + +int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) +{ + int rc = 0; + enum msm_vidc_codec_type codec; + enum msm_vidc_colorformat_type colorformat; + struct msm_vidc_core *core; + + if (!inst || !inst->core || !inst->capabilities || !f) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + if (f->index >= + sizeof(inst->capabilities->cap[PIX_FMTS].step_or_mask) * 8) { + d_vpr_e("%s: invalid index %d\n", __func__, f->index); + return -EINVAL; + } + memset(f->reserved, 0, sizeof(f->reserved)); + + if (f->type == INPUT_PLANE) { + codec = core->capabilities[DEC_CODECS].value & f->index; + f->pixelformat = get_v4l2_codec_from_vidc(codec); + if (!f->pixelformat) + return -EINVAL; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strlcpy(f->description, "codec", sizeof(f->description)); + } else if (f->type == OUTPUT_PLANE) { + colorformat = f->index & + inst->capabilities->cap[PIX_FMTS].step_or_mask; + f->pixelformat = get_v4l2_colorformat_from_vidc(colorformat); + if (!f->pixelformat) + return -EINVAL; + strlcpy(f->description, "colorformat", sizeof(f->description)); + } else if (f->type == INPUT_META_PLANE || f->type == OUTPUT_META_PLANE) { + if (!f->index) { + f->pixelformat = V4L2_PIX_FMT_VIDC_META; + strlcpy(f->description, "metadata", sizeof(f->description)); + } else { + return -EINVAL; + } + } return rc; } @@ -444,6 +498,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) int msm_vdec_inst_init(struct msm_vidc_inst *inst) { int rc = 0; + int i; struct msm_vidc_core *core; struct v4l2_format *f; @@ -473,6 +528,10 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->buffers.input.extra_count; inst->buffers.input.size = f->fmt.pix.sizeimage; + inst->crop.x = inst->crop.y = 0; + inst->crop.width = f->fmt.pix.width; + inst->crop.height = f->fmt.pix.height; + f = &inst->fmts[INPUT_META_PORT]; f->type = INPUT_META_PLANE; f->fmt.meta.dataformat = V4L2_PIX_FMT_VIDC_META; @@ -487,9 +546,9 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) f->type = OUTPUT_PLANE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12_UBWC; f->fmt.pix.width = VENUS_Y_STRIDE( - msm_vidc_convert_color_fmt(f->fmt.pix.pixelformat), DEFAULT_WIDTH); + get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_WIDTH); f->fmt.pix.height = VENUS_Y_SCANLINES( - msm_vidc_convert_color_fmt(f->fmt.pix.pixelformat), DEFAULT_HEIGHT); + get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_HEIGHT); f->fmt.pix.bytesperline = f->fmt.pix.width; f->fmt.pix.sizeimage = call_session_op(core, buffer_size, inst, MSM_VIDC_BUF_OUTPUT); @@ -515,6 +574,21 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->prop.frame_rate = DEFAULT_FPS << 16; inst->prop.operating_rate = DEFAULT_FPS << 16; + inst->capabilities = NULL; + for (i = 0; i < core->codecs_count; i++) { + if (core->inst_caps[i].domain == MSM_VIDC_DECODER && + core->inst_caps[i].codec == get_vidc_codec_from_v4l2( + inst->fmts[INPUT_PORT].fmt.pix.pixelformat)) { + s_vpr_h(inst->sid, "%s: assigned capabilities with %#x caps\n", + __func__, inst->fmts[INPUT_PORT].fmt.pix.pixelformat); + inst->capabilities = &core->inst_caps[i]; + } + } + if (!inst->capabilities) { + s_vpr_e(inst->sid, "%s: capabilities not found\n", __func__); + return -EINVAL; + } + return rc; } diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index 7ee0c4f633..f98f3e4695 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -14,10 +14,277 @@ #include "msm_vidc_platform.h" #include "msm_vidc_debug.h" +static int msm_venc_codec_change(struct msm_vidc_inst *inst, u32 codec) +{ + int rc = 0; + int i; + struct msm_vidc_core *core; + + d_vpr_h("%s()\n", __func__); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + inst->capabilities = NULL; + for (i = 0; i < core->codecs_count; i++) { + if (core->inst_caps[i].domain == MSM_VIDC_ENCODER && + core->inst_caps[i].codec == get_vidc_codec_from_v4l2( + inst->fmts[OUTPUT_PORT].fmt.pix.pixelformat)) { + s_vpr_h(inst->sid, "%s: assigned capabilities with %#x caps\n", + __func__, inst->fmts[OUTPUT_PORT].fmt.pix.pixelformat); + inst->capabilities = &core->inst_caps[i]; + } + } + if (!inst->capabilities) { + s_vpr_e(inst->sid, "%s: capabilities not found\n", __func__); + return -EINVAL; + } + + return rc; +} + +int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) +{ + int rc = 0; + struct msm_vidc_core *core; + struct v4l2_format *fmt; + + d_vpr_h("%s()\n", __func__); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + if (inst->state == MSM_VIDC_START) { + d_vpr_e("%s: invalid state %d\n", __func__, inst->state); + return -EINVAL; + } + + if (f->type == INPUT_PLANE) { + if (inst->state == MSM_VIDC_START_INPUT) { + d_vpr_e("%s: invalid state %d\n", __func__, inst->state); + return -EINVAL; + } + fmt = &inst->fmts[INPUT_PORT]; + fmt->type = INPUT_PLANE; + fmt->fmt.pix.pixelformat = f->fmt.pix.pixelformat; + fmt->fmt.pix.width = VENUS_Y_STRIDE( + get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat), + f->fmt.pix.width); + fmt->fmt.pix.height = VENUS_Y_SCANLINES( + get_media_colorformat_from_v4l2(fmt->fmt.pix.pixelformat), + f->fmt.pix.height); + fmt->fmt.pix.bytesperline = fmt->fmt.pix.width; + fmt->fmt.pix.sizeimage = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_INPUT); + inst->buffers.input.min_count = + call_session_op(core, min_count, inst, MSM_VIDC_BUF_INPUT); + inst->buffers.input.extra_count = + call_session_op(core, extra_count, inst, MSM_VIDC_BUF_INPUT); + if (inst->buffers.input.actual_count < + inst->buffers.input.min_count + + inst->buffers.input.extra_count) { + inst->buffers.input.actual_count = + inst->buffers.input.min_count + + inst->buffers.input.extra_count; + } + inst->buffers.input.size = fmt->fmt.pix.sizeimage; + + //rc = msm_vidc_check_session_supported(inst); + if (rc) + goto err_invalid_fmt; + //update_log_ctxt(inst->sid, inst->session_type, + // mplane->pixelformat); + s_vpr_h(inst->sid, + "%s: input: codec %#x width %d height %d size %d min_count %d extra_count %d\n", + __func__, f->fmt.pix.pixelformat, f->fmt.pix.width, + f->fmt.pix.height, fmt->fmt.pix.sizeimage, + inst->buffers.input.min_count, + inst->buffers.input.extra_count); + + //msm_vidc_update_dcvs(inst); + //msm_vidc_update_batching(inst); + + } else if (f->type == INPUT_META_PLANE) { + if (inst->state == MSM_VIDC_START_INPUT) { + d_vpr_e("%s: invalid state %d\n", __func__, inst->state); + return -EINVAL; + } + fmt = &inst->fmts[INPUT_META_PORT]; + fmt->type = INPUT_META_PLANE; + fmt->fmt.meta.dataformat = V4L2_PIX_FMT_VIDC_META; + fmt->fmt.meta.buffersize = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_INPUT_META); + inst->buffers.input_meta.min_count = + inst->buffers.input.min_count; + inst->buffers.input_meta.extra_count = + inst->buffers.input.extra_count; + inst->buffers.input_meta.actual_count = + inst->buffers.input.actual_count; + inst->buffers.input_meta.size = fmt->fmt.meta.buffersize; + s_vpr_h(inst->sid, + "%s: input meta: size %d min_count %d extra_count %d\n", + __func__, fmt->fmt.meta.buffersize, + inst->buffers.input_meta.min_count, + inst->buffers.input_meta.extra_count); + } else if (f->type == OUTPUT_PLANE) { + if (inst->state == MSM_VIDC_START_OUTPUT) { + d_vpr_e("%s: invalid state %d\n", __func__, inst->state); + return -EINVAL; + } + fmt = &inst->fmts[OUTPUT_PORT]; + if (fmt->fmt.pix.pixelformat != f->fmt.pix.pixelformat) { + s_vpr_e(inst->sid, + "%s: codec changed from %#x to %#x\n", __func__, + fmt->fmt.pix.pixelformat, f->fmt.pix.pixelformat); + rc = msm_venc_codec_change(inst, f->fmt.pix.pixelformat); + if (rc) + goto err_invalid_fmt; + } + fmt->type = OUTPUT_PLANE; + fmt->fmt.pix.width = ALIGN(f->fmt.pix.width, 16); + fmt->fmt.pix.height = ALIGN(f->fmt.pix.height, 16); + fmt->fmt.pix.pixelformat = f->fmt.pix.pixelformat; + fmt->fmt.pix.bytesperline = 0; + fmt->fmt.pix.sizeimage = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_OUTPUT); + inst->buffers.output.min_count = + call_session_op(core, min_count, inst, MSM_VIDC_BUF_OUTPUT); + inst->buffers.output.extra_count = + call_session_op(core, extra_count, inst, MSM_VIDC_BUF_OUTPUT); + if (inst->buffers.output.actual_count < + inst->buffers.output.min_count + + inst->buffers.output.extra_count) { + inst->buffers.output.actual_count = + inst->buffers.output.min_count + + inst->buffers.output.extra_count; + } + inst->buffers.output.size = fmt->fmt.pix.sizeimage; + + //rc = msm_vidc_check_session_supported(inst); + if (rc) + goto err_invalid_fmt; + + /* update crop dimensions */ + inst->crop.x = inst->crop.y = 0; + inst->crop.width = f->fmt.pix.width; + inst->crop.height = f->fmt.pix.height; + + //update_log_ctxt(inst->sid, inst->session_type, + // mplane->pixelformat); + + s_vpr_h(inst->sid, + "%s: output: format %#x width %d height %d size %d min_count %d extra_count %d\n", + __func__, fmt->fmt.pix.pixelformat, fmt->fmt.pix.width, + fmt->fmt.pix.height, fmt->fmt.pix.sizeimage, + inst->buffers.output.min_count, + inst->buffers.output.extra_count); + } else if (f->type == OUTPUT_META_PLANE) { + if (inst->state == MSM_VIDC_START_OUTPUT) { + d_vpr_e("%s: invalid state %d\n", __func__, inst->state); + return -EINVAL; + } + fmt = &inst->fmts[OUTPUT_META_PORT]; + fmt->type = OUTPUT_META_PLANE; + fmt->fmt.meta.dataformat = V4L2_PIX_FMT_VIDC_META; + fmt->fmt.meta.buffersize = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_OUTPUT_META); + inst->buffers.output_meta.min_count = + inst->buffers.output.min_count; + inst->buffers.output_meta.extra_count = + inst->buffers.output.extra_count; + inst->buffers.output_meta.actual_count = + inst->buffers.output.actual_count; + inst->buffers.output_meta.size = fmt->fmt.meta.buffersize; + s_vpr_h(inst->sid, + "%s: input meta: size %d min_count %d extra_count %d\n", + __func__, fmt->fmt.meta.buffersize, + inst->buffers.output_meta.min_count, + inst->buffers.output_meta.extra_count); + } else { + s_vpr_e(inst->sid, "%s: invalid type %d\n", __func__, f->type); + goto err_invalid_fmt; + } + memcpy(f, fmt, sizeof(struct v4l2_format)); + +err_invalid_fmt: + return rc; +} + +int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) +{ + int rc = 0; + int port; + + d_vpr_h("%s()\n", __func__); + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + port = msm_vidc_get_port_from_v4l2_type(f->type); + if (port < 0) { + d_vpr_e("%s: invalid format type %d\n", __func__, f->type); + return -EINVAL; + } + memcpy(f, &inst->fmts[port], sizeof(struct v4l2_format)); + + return rc; +} + +int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) +{ + int rc = 0; + enum msm_vidc_codec_type codec; + enum msm_vidc_colorformat_type colorformat; + struct msm_vidc_core *core; + + if (!inst || !inst->core || !inst->capabilities || !f) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + if (f->index >= + sizeof(inst->capabilities->cap[PIX_FMTS].step_or_mask) * 8) { + d_vpr_e("%s: invalid index %d\n", __func__, f->index); + return -EINVAL; + } + memset(f->reserved, 0, sizeof(f->reserved)); + + if (f->type == OUTPUT_PLANE) { + codec = core->capabilities[DEC_CODECS].value & f->index; + f->pixelformat = get_v4l2_codec_from_vidc(codec); + if (!f->pixelformat) + return -EINVAL; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strlcpy(f->description, "codec", sizeof(f->description)); + } else if (f->type == INPUT_PLANE) { + colorformat = f->index & + inst->capabilities->cap[PIX_FMTS].step_or_mask; + f->pixelformat = get_v4l2_colorformat_from_vidc(colorformat); + if (!f->pixelformat) + return -EINVAL; + strlcpy(f->description, "colorformat", sizeof(f->description)); + } else if (f->type == INPUT_META_PLANE || f->type == OUTPUT_META_PLANE) { + if (!f->index) { + f->pixelformat = V4L2_PIX_FMT_VIDC_META; + strlcpy(f->description, "metadata", sizeof(f->description)); + } else { + return -EINVAL; + } + } + + return rc; +} int msm_venc_inst_init(struct msm_vidc_inst *inst) { int rc = 0; + int i; struct msm_vidc_core *core; struct v4l2_format *f; @@ -45,6 +312,10 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) inst->buffers.output.extra_count; inst->buffers.output.size = f->fmt.pix.sizeimage; + inst->crop.x = inst->crop.y = 0; + inst->crop.width = f->fmt.pix.width; + inst->crop.height = f->fmt.pix.height; + f = &inst->fmts[OUTPUT_META_PORT]; f->type = OUTPUT_META_PLANE; f->fmt.meta.dataformat = V4L2_PIX_FMT_VIDC_META; @@ -59,9 +330,9 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) f->type = INPUT_PLANE; f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12_UBWC; f->fmt.pix.width = VENUS_Y_STRIDE( - msm_vidc_convert_color_fmt(f->fmt.pix.pixelformat), DEFAULT_WIDTH); + get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_WIDTH); f->fmt.pix.height = VENUS_Y_SCANLINES( - msm_vidc_convert_color_fmt(f->fmt.pix.pixelformat), DEFAULT_HEIGHT); + get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat), DEFAULT_HEIGHT); f->fmt.pix.bytesperline = f->fmt.pix.width; f->fmt.pix.sizeimage = call_session_op(core, buffer_size, inst, MSM_VIDC_BUF_INPUT); @@ -87,6 +358,21 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) inst->prop.frame_rate = DEFAULT_FPS << 16; inst->prop.operating_rate = DEFAULT_FPS << 16; + inst->capabilities = NULL; + for (i = 0; i < core->codecs_count; i++) { + if (core->inst_caps[i].domain == MSM_VIDC_ENCODER && + core->inst_caps[i].codec == get_vidc_codec_from_v4l2( + inst->fmts[OUTPUT_PORT].fmt.pix.pixelformat)) { + s_vpr_h(inst->sid, "%s: assigned capabilities with %#x caps\n", + __func__, inst->fmts[OUTPUT_PORT].fmt.pix.pixelformat); + inst->capabilities = &core->inst_caps[i]; + } + } + if (!inst->capabilities) { + s_vpr_e(inst->sid, "%s: capabilities not found\n", __func__); + return -EINVAL; + } + return rc; } diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index 1725dfccc6..c8b5a95551 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -25,61 +25,63 @@ bool valid_v4l2_buffer(struct v4l2_buffer *b, { return true; } -/* -static int get_poll_flags(struct msm_vidc_inst *inst) + +static int get_poll_flags(struct msm_vidc_inst *inst, u32 port) { - int rc = 0; - struct vb2_queue *outq = &inst->bufq[PORT_INPUT].vb2_bufq; - struct vb2_queue *capq = &inst->bufq[PORT_OUTPUT].vb2_bufq; - struct vb2_buffer *out_vb = NULL; - struct vb2_buffer *cap_vb = NULL; + int poll = 0; + struct vb2_queue *q = NULL; + struct vb2_buffer *vb = NULL; unsigned long flags = 0; - if (v4l2_event_pending(&inst->event_handler)) - rc |= POLLPRI; + if (!inst || port >= MAX_PORT) { + d_vpr_e("%s: invalid params, inst %pK, port %d\n", + __func__, inst, port); + return poll; + } + q = &inst->vb2q[port]; - spin_lock_irqsave(&capq->done_lock, flags); - if (!list_empty(&capq->done_list)) - cap_vb = list_first_entry(&capq->done_list, struct vb2_buffer, - done_entry); - if (cap_vb && (cap_vb->state == VB2_BUF_STATE_DONE - || cap_vb->state == VB2_BUF_STATE_ERROR)) - rc |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&capq->done_lock, flags); + spin_lock_irqsave(&q->done_lock, flags); + if (!list_empty(&q->done_list)) + vb = list_first_entry(&q->done_list, struct vb2_buffer, + done_entry); + if (vb && (vb->state == VB2_BUF_STATE_DONE || + vb->state == VB2_BUF_STATE_ERROR)) { + if (port == OUTPUT_PORT || port == OUTPUT_META_PORT) + poll |= POLLIN | POLLRDNORM; + else if (port == INPUT_PORT || port == INPUT_META_PORT) + poll |= POLLOUT | POLLWRNORM; + } + spin_unlock_irqrestore(&q->done_lock, flags); - spin_lock_irqsave(&outq->done_lock, flags); - if (!list_empty(&outq->done_list)) - out_vb = list_first_entry(&outq->done_list, struct vb2_buffer, - done_entry); - if (out_vb && (out_vb->state == VB2_BUF_STATE_DONE - || out_vb->state == VB2_BUF_STATE_ERROR)) - rc |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&outq->done_lock, flags); - - return rc; + return poll; } -*/ int msm_vidc_poll(void *instance, struct file *filp, struct poll_table_struct *wait) { -/* + int poll = 0; struct msm_vidc_inst *inst = instance; - struct vb2_queue *outq = NULL; - struct vb2_queue *capq = NULL; - if (!inst) + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; - - outq = &inst->bufq[PORT_INPUT].vb2_bufq; - capq = &inst->bufq[PORT_OUTPUT].vb2_bufq; + } poll_wait(filp, &inst->event_handler.wait, wait); - poll_wait(filp, &capq->done_wq, wait); - poll_wait(filp, &outq->done_wq, wait); - return get_poll_flags(inst); -*/ - return 0; + poll_wait(filp, &inst->vb2q[INPUT_META_PORT].done_wq, wait); + poll_wait(filp, &inst->vb2q[OUTPUT_META_PORT].done_wq, wait); + poll_wait(filp, &inst->vb2q[INPUT_PORT].done_wq, wait); + poll_wait(filp, &inst->vb2q[OUTPUT_PORT].done_wq, wait); + + if (v4l2_event_pending(&inst->event_handler)) + poll |= POLLPRI; + + poll |= get_poll_flags(inst, INPUT_META_PORT); + poll |= get_poll_flags(inst, OUTPUT_META_PORT); + poll |= get_poll_flags(inst, INPUT_PORT); + poll |= get_poll_flags(inst, OUTPUT_PORT); + + return poll; } EXPORT_SYMBOL(msm_vidc_poll); @@ -87,14 +89,16 @@ int msm_vidc_querycap(void *instance, struct v4l2_capability *cap) { struct msm_vidc_inst *inst = instance; - if (!inst || !cap) + if (!inst || !cap) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; + } strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver)); cap->bus_info[0] = 0; cap->version = MSM_VIDC_VERSION; - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | - V4L2_CAP_VIDEO_OUTPUT_MPLANE | + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE | + V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -115,13 +119,16 @@ int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f) { struct msm_vidc_inst *inst = instance; - if (!inst || !f) + if (!inst || !f) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; + } if (inst->domain == MSM_VIDC_DECODER) - return -EINVAL;//msm_vdec_enum_fmt(instance, f); - else if (inst->domain == MSM_VIDC_ENCODER) - return -EINVAL;//msm_venc_enum_fmt(instance, f); + return msm_vdec_enum_fmt(inst, f); + if (inst->domain == MSM_VIDC_ENCODER) + return msm_venc_enum_fmt(inst, f); + return -EINVAL; } EXPORT_SYMBOL(msm_vidc_enum_fmt); @@ -200,8 +207,10 @@ int msm_vidc_s_fmt(void *instance, struct v4l2_format *f) int rc = 0; struct msm_vidc_inst *inst = instance; - if (!inst || !f) + if (!inst || !f) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; + } if (f->type == INPUT_PLANE) { if (inst->state != MSM_VIDC_OPEN && @@ -225,7 +234,7 @@ int msm_vidc_s_fmt(void *instance, struct v4l2_format *f) if (inst->domain == MSM_VIDC_DECODER) rc = msm_vdec_s_fmt(inst, f); if (inst->domain == MSM_VIDC_ENCODER) - rc = 0;//msm_venc_s_fmt(instance, f); + rc = msm_venc_s_fmt(inst, f); return rc; } @@ -236,13 +245,15 @@ int msm_vidc_g_fmt(void *instance, struct v4l2_format *f) int rc = 0; struct msm_vidc_inst *inst = instance; - if (!inst || !f) + if (!inst || !f) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; + } if (inst->domain == MSM_VIDC_DECODER) rc = msm_vdec_g_fmt(inst, f); if (inst->domain == MSM_VIDC_ENCODER) - rc = 0;//msm_venc_g_fmt(instance, f); + rc = msm_venc_g_fmt(inst, f); return rc; } @@ -265,9 +276,10 @@ int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control) struct v4l2_ctrl *ctrl = NULL; int rc = 0; - if (!inst || !control) + if (!inst || !control) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; - + } ctrl = v4l2_ctrl_find(&inst->ctrl_handler, control->id); if (ctrl) { rc = msm_vidc_get_control(inst, ctrl); @@ -285,8 +297,10 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b) struct msm_vidc_inst *inst = instance; int port; - if (!inst || !b) + if (!inst || !b) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; + } mutex_lock(&inst->lock); @@ -347,8 +361,10 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type) enum msm_vidc_inst_state new_state = 0; int port; - if (!inst) + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; + } mutex_lock(&inst->lock); @@ -425,8 +441,10 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type) enum msm_vidc_inst_state new_state = 0; int port; - if (!inst) + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; + } mutex_lock(&inst->lock); @@ -524,10 +542,11 @@ int msm_vidc_subscribe_event(void *instance, int rc = 0; struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - if (!inst || !sub) + if (!inst || !sub) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; - - s_vpr_e(inst->sid, "%s: type %d id %d\n", __func__, sub->type, sub->id); + } + s_vpr_h(inst->sid, "%s: type %d id %d\n", __func__, sub->type, sub->id); rc = v4l2_event_subscribe(&inst->event_handler, sub, MAX_EVENTS, NULL); return rc; @@ -540,10 +559,11 @@ int msm_vidc_unsubscribe_event(void *instance, int rc = 0; struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - if (!inst || !sub) + if (!inst || !sub) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; - - s_vpr_e(inst->sid, "%s: type %d id %d\n", __func__, sub->type, sub->id); + } + s_vpr_h(inst->sid, "%s: type %d id %d\n", __func__, sub->type, sub->id); rc = v4l2_event_unsubscribe(&inst->event_handler, sub); return rc; } @@ -554,9 +574,10 @@ int msm_vidc_dqevent(void *instance, struct v4l2_event *event) int rc = 0; struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance; - if (!inst || !event) + if (!inst || !event) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; - + } rc = v4l2_event_dequeue(&inst->event_handler, event, false); return rc; } diff --git a/driver/vidc/src/msm_vidc_buffer.c b/driver/vidc/src/msm_vidc_buffer.c index c2e9ec9943..7b31c89e9b 100644 --- a/driver/vidc/src/msm_vidc_buffer.c +++ b/driver/vidc/src/msm_vidc_buffer.c @@ -148,7 +148,7 @@ u32 msm_vidc_decoder_output_size(struct msm_vidc_inst *inst) struct v4l2_format *f; f = &inst->fmts[OUTPUT_PORT]; - format = msm_vidc_convert_color_fmt(f->fmt.pix.pixelformat); + format = get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat); return VENUS_BUFFER_SIZE(format, f->fmt.pix.width, f->fmt.pix.height); } @@ -169,7 +169,7 @@ u32 msm_vidc_encoder_input_size(struct msm_vidc_inst *inst) struct v4l2_format *f; f = &inst->fmts[INPUT_PORT]; - format = msm_vidc_convert_color_fmt(f->fmt.pix.pixelformat); + format = get_media_colorformat_from_v4l2(f->fmt.pix.pixelformat); return VENUS_BUFFER_SIZE(format, f->fmt.pix.width, f->fmt.pix.height); } diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 00729b0e22..6f1d5ae7a7 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -26,6 +26,145 @@ void print_vidc_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *b) { } +enum msm_vidc_codec_type get_vidc_codec_from_v4l2(u32 v4l2_codec) +{ + enum msm_vidc_codec_type codec = 0; + + switch (v4l2_codec) { + case V4L2_PIX_FMT_H264: + codec = MSM_VIDC_H264; + break; + case V4L2_PIX_FMT_HEVC: + codec = MSM_VIDC_HEVC; + break; + case V4L2_PIX_FMT_VP9: + codec = MSM_VIDC_VP9; + break; + case V4L2_PIX_FMT_MPEG2: + codec = MSM_VIDC_MPEG2; + break; + default: + d_vpr_e("%s: vidc codec not found for %#x\n", __func__, v4l2_codec); + break; + } + return codec; +} + +u32 get_v4l2_codec_from_vidc(enum msm_vidc_codec_type codec) +{ + u32 v4l2_codec = 0; + + switch (codec) { + case MSM_VIDC_H264: + v4l2_codec = V4L2_PIX_FMT_H264; + break; + case MSM_VIDC_HEVC: + v4l2_codec = V4L2_PIX_FMT_HEVC; + break; + case MSM_VIDC_VP9: + v4l2_codec = V4L2_PIX_FMT_VP9; + break; + case MSM_VIDC_MPEG2: + v4l2_codec = V4L2_PIX_FMT_MPEG2; + break; + default: + d_vpr_e("%s: v4l2 codec not found for %#x\n", __func__, codec); + break; + } + return v4l2_codec; +} + +enum msm_vidc_colorformat_type get_vidc_colorformat_from_v4l2(u32 v4l2_colorformat) +{ + enum msm_vidc_colorformat_type colorformat = 0; + + switch (v4l2_colorformat) { + case V4L2_PIX_FMT_NV12: + colorformat = MSM_VIDC_FMT_NV12; + break; + case V4L2_PIX_FMT_NV21: + colorformat = MSM_VIDC_FMT_NV21; + break; + case V4L2_PIX_FMT_NV12_UBWC: + colorformat = MSM_VIDC_FMT_NV12_UBWC; + break; + case V4L2_PIX_FMT_NV12_TP10_UBWC: + colorformat = MSM_VIDC_FMT_NV12_TP10_UBWC; + break; + case V4L2_PIX_FMT_RGBA8888_UBWC: + colorformat = MSM_VIDC_FMT_RGBA8888_UBWC; + break; + case V4L2_PIX_FMT_NV12_P010_UBWC: + colorformat = MSM_VIDC_FMT_SDE_Y_CBCR_H2V2_P010_VENUS; + break; + case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS: + colorformat = MSM_VIDC_FMT_SDE_Y_CBCR_H2V2_P010_VENUS; + break; + default: + d_vpr_e("%s: vidc format not found for %#x\n", __func__, v4l2_colorformat); + break; + } + return colorformat; +} + +u32 get_v4l2_colorformat_from_vidc(enum msm_vidc_colorformat_type colorformat) +{ + u32 v4l2_colorformat = 0; + + switch (colorformat) { + case MSM_VIDC_FMT_NV12: + v4l2_colorformat = V4L2_PIX_FMT_NV12; + break; + case MSM_VIDC_FMT_NV21: + v4l2_colorformat = V4L2_PIX_FMT_NV21; + break; + case MSM_VIDC_FMT_NV12_UBWC: + v4l2_colorformat = V4L2_PIX_FMT_NV12_UBWC; + break; + case MSM_VIDC_FMT_NV12_TP10_UBWC: + v4l2_colorformat = V4L2_PIX_FMT_NV12_TP10_UBWC; + break; + case MSM_VIDC_FMT_RGBA8888_UBWC: + v4l2_colorformat = V4L2_PIX_FMT_RGBA8888_UBWC; + break; + case MSM_VIDC_FMT_NV12_P010_UBWC: + v4l2_colorformat = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS; + break; + case MSM_VIDC_FMT_SDE_Y_CBCR_H2V2_P010_VENUS: + v4l2_colorformat = V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS; + break; + default: + d_vpr_e("%s: v4l2 format not found for %#x\n", __func__, colorformat); + break; + } + return v4l2_colorformat; +} + +u32 get_media_colorformat_from_v4l2(u32 v4l2_fmt) +{ + switch (v4l2_fmt) { + case V4L2_PIX_FMT_NV12: + return COLOR_FMT_NV12; + case V4L2_PIX_FMT_NV21: + return COLOR_FMT_NV21; + case V4L2_PIX_FMT_NV12_512: + return COLOR_FMT_NV12_512; + case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS: + return COLOR_FMT_P010; + case V4L2_PIX_FMT_NV12_UBWC: + return COLOR_FMT_NV12_UBWC; + case V4L2_PIX_FMT_NV12_TP10_UBWC: + return COLOR_FMT_NV12_BPP10_UBWC; + case V4L2_PIX_FMT_RGBA8888_UBWC: + return COLOR_FMT_RGBA8888_UBWC; + default: + d_vpr_e( + "Invalid v4l2 color fmt FMT : %x, Set default(NV12)", + v4l2_fmt); + return COLOR_FMT_NV12; + } +} + int msm_vidc_get_port_from_v4l2_type(u32 type) { int port; @@ -227,31 +366,6 @@ int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) return rc; } -u32 msm_vidc_convert_color_fmt(u32 v4l2_fmt) -{ - switch (v4l2_fmt) { - case V4L2_PIX_FMT_NV12: - return COLOR_FMT_NV12; - case V4L2_PIX_FMT_NV21: - return COLOR_FMT_NV21; - case V4L2_PIX_FMT_NV12_512: - return COLOR_FMT_NV12_512; - case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010_VENUS: - return COLOR_FMT_P010; - case V4L2_PIX_FMT_NV12_UBWC: - return COLOR_FMT_NV12_UBWC; - case V4L2_PIX_FMT_NV12_TP10_UBWC: - return COLOR_FMT_NV12_BPP10_UBWC; - case V4L2_PIX_FMT_RGBA8888_UBWC: - return COLOR_FMT_RGBA8888_UBWC; - default: - d_vpr_e( - "Invalid v4l2 color fmt FMT : %x, Set default(NV12)", - v4l2_fmt); - return COLOR_FMT_NV12; - } -} - int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buffer_type) { @@ -609,7 +723,7 @@ static void update_inst_capability(struct msm_platform_inst_capability *in, capability->cap[in->cap].cap = in->cap; capability->cap[in->cap].min = in->min; capability->cap[in->cap].max = in->max; - capability->cap[in->cap].step_or_menu = in->step_or_menu; + capability->cap[in->cap].step_or_mask = in->step_or_mask; capability->cap[in->cap].value = in->value; capability->cap[in->cap].flags = in->flags; capability->cap[in->cap].v4l2_id = in->v4l2_id; @@ -658,6 +772,8 @@ static int msm_vidc_init_instance_caps(struct msm_vidc_core *core) count_bits = dec_valid_codecs; COUNT_BITS(count_bits, codecs_count); + core->codecs_count = codecs_count; + if (!core->inst_caps) { core->inst_caps = kcalloc(codecs_count, sizeof(struct msm_vidc_inst_capability), diff --git a/driver/vidc/src/msm_vidc_probe.c b/driver/vidc/src/msm_vidc_probe.c index f55a82010d..dc7eadce1e 100644 --- a/driver/vidc/src/msm_vidc_probe.c +++ b/driver/vidc/src/msm_vidc_probe.c @@ -118,7 +118,8 @@ static int msm_vidc_register_video_device(struct msm_vidc_core *core, core->vdev[index].type = type; core->vdev[index].vdev.v4l2_dev = &core->v4l2_dev; core->vdev[index].vdev.device_caps = - V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_META_CAPTURE | + V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_META_OUTPUT | V4L2_CAP_STREAMING; rc = video_register_device(&core->vdev[index].vdev, VFL_TYPE_GRABBER, nr);