diff --git a/driver/platform/kalama/src/msm_vidc_kalama.c b/driver/platform/kalama/src/msm_vidc_kalama.c index 5d2ed29cf3..a12290dffd 100644 --- a/driver/platform/kalama/src/msm_vidc_kalama.c +++ b/driver/platform/kalama/src/msm_vidc_kalama.c @@ -330,7 +330,7 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = { * Client will enable V4L2_CID_MPEG_VIDC_METADATA_OUTBUF_FENCE * to get fence_id in input metadata buffer done. */ - {META_OUTBUF_FENCE, DEC, CODECS_ALL, + {META_OUTBUF_FENCE, DEC, H264|HEVC|VP9|AV1, V4L2_MPEG_VIDC_META_DISABLE, V4L2_MPEG_VIDC_META_ENABLE | V4L2_MPEG_VIDC_META_RX_INPUT, 0, V4L2_MPEG_VIDC_META_DISABLE, @@ -1327,7 +1327,10 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = { 0, HFI_PROP_PIPE}, - {POC, DEC, H264, 0, 18, 1, 1}, + {POC, DEC, H264, + 0, 18, 1, 1, + 0, + HFI_PROP_PIC_ORDER_CNT_TYPE}, {QUALITY_MODE, ENC, CODECS_ALL, MSM_VIDC_MAX_QUALITY_MODE, @@ -1729,6 +1732,12 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala NULL, msm_vidc_set_u32}, + {META_OUTBUF_FENCE, DEC, H264|HEVC|VP9|AV1, + {OUTPUT_ORDER}, + {LOWLATENCY_MODE}, + msm_vidc_adjust_dec_outbuf_fence, + NULL}, + {HFLIP, ENC, CODECS_ALL, {0}, {0}, @@ -1860,7 +1869,13 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala {LOWLATENCY_MODE, ENC, H264 | HEVC, {BITRATE_MODE}, {STAGE}, - msm_vidc_adjust_lowlatency_mode, + msm_vidc_adjust_enc_lowlatency_mode, + NULL}, + + {LOWLATENCY_MODE, DEC, H264|HEVC|VP9|AV1, + {META_OUTBUF_FENCE}, + {STAGE}, + msm_vidc_adjust_dec_lowlatency_mode, NULL}, {LTR_COUNT, ENC, H264|HEVC, @@ -2150,7 +2165,7 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala {OUTPUT_ORDER, DEC, H264|HEVC|VP9|AV1, {THUMBNAIL_MODE, DISPLAY_DELAY, DISPLAY_DELAY_ENABLE}, - {0}, + {META_OUTBUF_FENCE}, msm_vidc_adjust_output_order, msm_vidc_set_u32}, @@ -2190,7 +2205,7 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala NULL, msm_vidc_set_u32_packed}, - {STAGE, DEC|ENC, CODECS_ALL, + {STAGE, ENC | DEC, CODECS_ALL, {0}, {0}, NULL, @@ -2202,6 +2217,12 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala NULL, msm_vidc_set_stage}, + {STAGE, DEC, H264|HEVC|VP9|AV1, + {LOWLATENCY_MODE}, + {0}, + NULL, + msm_vidc_set_stage}, + {PIPE, DEC|ENC, CODECS_ALL, {0}, {0}, diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index 8ff65837b5..99342c2912 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/driver/vidc/inc/msm_vidc_control.h @@ -46,7 +46,8 @@ int msm_vidc_adjust_blur_resolution(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_brs(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_bitrate_boost(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_min_quality(void *instance, struct v4l2_ctrl *ctrl); -int msm_vidc_adjust_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_enc_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_dec_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_set_v4l2_properties(struct msm_vidc_inst *inst); int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst); int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl); @@ -54,6 +55,7 @@ int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_all_intra(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_dec_frame_rate(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_dec_operating_rate(void *instance, struct v4l2_ctrl *ctrl); +int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl); int msm_vidc_set_header_mode(void *instance, diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 22b7c8246c..22a19c33ed 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -197,6 +197,11 @@ static inline bool is_meta_enabled(struct msm_vidc_inst *inst, unsigned int type return enabled; } +static inline bool is_outbuf_fence_enabled(struct msm_vidc_inst *inst) +{ + return is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE); +} + static inline bool is_linear_yuv_colorformat(enum msm_vidc_colorformat_type colorformat) { return colorformat == MSM_VIDC_FMT_NV12 || diff --git a/driver/vidc/inc/msm_vidc_fence.h b/driver/vidc/inc/msm_vidc_fence.h index 58999899e2..21f9cf481d 100644 --- a/driver/vidc/inc/msm_vidc_fence.h +++ b/driver/vidc/inc/msm_vidc_fence.h @@ -13,10 +13,12 @@ struct msm_vidc_fence *msm_vidc_fence_create( struct msm_vidc_inst *inst); int msm_vidc_create_fence_fd(struct msm_vidc_inst *inst, struct msm_vidc_fence *fence); +struct msm_vidc_fence *msm_vidc_get_fence_from_id( + struct msm_vidc_inst *inst, u32 fence_id); int msm_vidc_fence_signal(struct msm_vidc_inst *inst, u32 fence_id); void msm_vidc_fence_destroy(struct msm_vidc_inst *inst, - struct msm_vidc_fence *fence); + u32 fence_id); int msm_vidc_fence_init(struct msm_vidc_inst *inst); void msm_vidc_fence_deinit(struct msm_vidc_inst *inst); diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 7d14691092..1f6cd571a8 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -762,6 +762,7 @@ struct msm_vidc_hfi_frame_info { u32 cf; u32 data_corrupt; u32 overflow; + u32 fence_id; }; struct msm_vidc_decode_vpp_delay { diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index f59cdaba53..2c4da109e5 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -1190,7 +1190,7 @@ static int msm_vdec_read_input_subcr_params(struct msm_vidc_inst *inst) u32 colour_description_present_flag = 0; u32 video_signal_type_present_flag = 0; - if (!inst || !inst->core) { + if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } @@ -1298,6 +1298,14 @@ static int msm_vdec_read_input_subcr_params(struct msm_vidc_inst *inst) subsc_params.av1_super_block_enabled, __func__); } + /* disable META_OUTBUF_FENCE if session is Interlace type */ + if (inst->capabilities->cap[CODED_FRAMES].value == + CODED_FRAMES_INTERLACE) { + msm_vidc_update_cap_value(inst, META_OUTBUF_FENCE, + V4L2_MPEG_VIDC_META_RX_INPUT | + V4L2_MPEG_VIDC_META_DISABLE, __func__); + } + return 0; } diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 8de3d9d65a..0c41dc141c 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -443,7 +443,6 @@ int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap_id, s32 adjusted_val, const char *func) { int prev_value = 0; - bool is_updated = false; if (!inst || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); @@ -464,19 +463,15 @@ int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap_id, /* disable metadata */ inst->capabilities->cap[cap_id].value &= ~adjusted_val; } - if (prev_value != (prev_value | adjusted_val)) - is_updated = true; } else { inst->capabilities->cap[cap_id].value = adjusted_val; - if (prev_value != adjusted_val) - is_updated = true; } - if (is_updated) { + if (prev_value != inst->capabilities->cap[cap_id].value) { i_vpr_h(inst, "%s: updated database: name: %s, value: %#x -> %#x\n", func, cap_name(cap_id), - prev_value, adjusted_val); + prev_value, inst->capabilities->cap[cap_id].value); } return 0; @@ -2743,7 +2738,7 @@ int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl) return 0; } -int msm_vidc_adjust_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) +int msm_vidc_adjust_enc_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) { struct msm_vidc_inst_capability *capability; s32 adjusted_value; @@ -2773,6 +2768,36 @@ int msm_vidc_adjust_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) return 0; } +int msm_vidc_adjust_dec_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + s32 adjusted_value; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + s32 outbuf_fence = V4L2_MPEG_VIDC_META_DISABLE; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : + capability->cap[LOWLATENCY_MODE].value; + + if (msm_vidc_get_parent_value(inst, LOWLATENCY_MODE, META_OUTBUF_FENCE, + &outbuf_fence, __func__)) + return -EINVAL; + + if (outbuf_fence & V4L2_MPEG_VIDC_META_ENABLE && + outbuf_fence & V4L2_MPEG_VIDC_META_RX_INPUT) + adjusted_value = 1; + + msm_vidc_update_cap_value(inst, LOWLATENCY_MODE, + adjusted_value, __func__); + + return 0; +} + int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl) { int adjusted_value; @@ -2893,6 +2918,37 @@ int msm_vidc_adjust_dec_operating_rate(void *instance, struct v4l2_ctrl *ctrl) return 0; } +int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl) +{ + struct msm_vidc_inst_capability *capability; + struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance; + u32 adjusted_value = 0; + s32 picture_order = -1; + + if (!inst || !inst->capabilities) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + capability = inst->capabilities; + + adjusted_value = ctrl ? ctrl->val : capability->cap[META_OUTBUF_FENCE].value; + + if (msm_vidc_get_parent_value(inst, META_OUTBUF_FENCE, OUTPUT_ORDER, + &picture_order, __func__)) + return -EINVAL; + + if (picture_order == V4L2_MPEG_MSM_VIDC_DISABLE) { + /* disable outbuf fence */ + adjusted_value = V4L2_MPEG_VIDC_META_DISABLE | + V4L2_MPEG_VIDC_META_RX_INPUT; + } + + msm_vidc_update_cap_value(inst, META_OUTBUF_FENCE, + adjusted_value, __func__); + + return 0; +} + int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst) { struct list_head root_list, opt_list; diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index cd1e301710..96b0cad991 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -3481,7 +3481,7 @@ exit: if (rc) { i_vpr_e(inst, "%s: qbuf failed\n", __func__); if (fence) - msm_vidc_fence_destroy(inst, fence); + msm_vidc_fence_destroy(inst, (u32)fence->dma_fence.seqno); } return rc; } @@ -5569,7 +5569,7 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst) list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) { i_vpr_e(inst, "%s: destroying fence id: %llu\n", __func__, fence->dma_fence.seqno); - msm_vidc_fence_destroy(inst, fence); + msm_vidc_fence_destroy(inst, (u32)fence->dma_fence.seqno); } /* destroy buffers from pool */ diff --git a/driver/vidc/src/msm_vidc_fence.c b/driver/vidc/src/msm_vidc_fence.c index 23b0f1bd0e..f85053e939 100644 --- a/driver/vidc/src/msm_vidc_fence.c +++ b/driver/vidc/src/msm_vidc_fence.c @@ -117,15 +117,15 @@ err_fd: return rc; } -int msm_vidc_fence_signal(struct msm_vidc_inst *inst, u32 fence_id) +struct msm_vidc_fence *msm_vidc_get_fence_from_id( + struct msm_vidc_inst *inst, u32 fence_id) { - int rc = 0; struct msm_vidc_fence *fence, *dummy_fence; bool found = false; if (!inst) { d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; + return NULL; } list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) { @@ -135,12 +135,30 @@ int msm_vidc_fence_signal(struct msm_vidc_inst *inst, u32 fence_id) } } - if (!found) { + if (!found) + return NULL; + + return fence; +} + +int msm_vidc_fence_signal(struct msm_vidc_inst *inst, u32 fence_id) +{ + int rc = 0; + struct msm_vidc_fence *fence; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + fence = msm_vidc_get_fence_from_id(inst, fence_id); + if (!fence) { i_vpr_e(inst, "%s: no fence available to signal with id: %u", __func__, fence_id); rc = -EINVAL; goto exit; } + i_vpr_l(inst, "%s: fence %s\n", __func__, fence->name); dma_fence_signal(&fence->dma_fence); dma_fence_put(&fence->dma_fence); @@ -150,28 +168,18 @@ exit: return rc; } -void msm_vidc_fence_destroy(struct msm_vidc_inst *inst, - struct msm_vidc_fence *fence_to_destroy) -{ - struct msm_vidc_fence *fence, *dummy_fence; - bool found = false; - if (!inst || !fence_to_destroy) { +void msm_vidc_fence_destroy(struct msm_vidc_inst *inst, u32 fence_id) +{ + struct msm_vidc_fence *fence; + + if (!inst) { d_vpr_e("%s: invalid params\n", __func__); return; } - list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) { - if (fence->dma_fence.seqno == - fence_to_destroy->dma_fence.seqno) { - found = true; - break; - } - } - - if (!found) { - i_vpr_e(inst, "%s: no fence available to destroy with id: %llu", - __func__, fence_to_destroy->dma_fence.seqno); + fence = msm_vidc_get_fence_from_id(inst, fence_id); + if (!fence) { return; } diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index d592d370ac..c483e63b3c 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -864,7 +864,7 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, if (buffer->data_size) { i_vpr_e(inst, "%s: reset data size to zero for last flag buffer\n", __func__); - buffer->data_size = 0; + buf->data_size = 0; } if (buffer->flags & HFI_BUF_FW_FLAG_READONLY) { i_vpr_e(inst, "%s: reset RO flag for last flag buffer\n", @@ -895,6 +895,19 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, buf->flags = 0; buf->flags = get_driver_buffer_flags(inst, buffer->flags); + /* fence signalling */ + if (inst->hfi_frame_info.fence_id) { + if (buf->data_size) { + /* signal fence */ + msm_vidc_fence_signal(inst, + inst->hfi_frame_info.fence_id); + } else { + /* destroy fence */ + msm_vidc_fence_destroy(inst, + inst->hfi_frame_info.fence_id); + } + } + if (is_decode_session(inst)) { inst->power.fw_cr = inst->hfi_frame_info.cr; inst->power.fw_cf = inst->hfi_frame_info.cf; @@ -1435,7 +1448,6 @@ static int handle_property_with_payload(struct msm_vidc_inst *inst, { int rc = 0; u32 *payload_ptr = NULL; - u32 fence_id = 0; payload_ptr = (u32 *)((u8 *)pkt + sizeof(struct hfi_packet)); if (!payload_ptr) { @@ -1536,13 +1548,7 @@ static int handle_property_with_payload(struct msm_vidc_inst *inst, __func__, payload_ptr[0], inst->capabilities->cap[PIPE].value); break; case HFI_PROP_FENCE: - if (is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE)) { - fence_id = payload_ptr[0]; - rc = msm_vidc_fence_signal(inst, fence_id); - } else { - i_vpr_e(inst, "%s: fence is not enabled for this session\n", - __func__); - } + inst->hfi_frame_info.fence_id = payload_ptr[0]; break; default: i_vpr_e(inst, "%s: invalid property %#x\n", diff --git a/include/uapi/vidc/media/v4l2_vidc_extensions.h b/include/uapi/vidc/media/v4l2_vidc_extensions.h index b5ee13460c..41d2507a4c 100644 --- a/include/uapi/vidc/media/v4l2_vidc_extensions.h +++ b/include/uapi/vidc/media/v4l2_vidc_extensions.h @@ -389,6 +389,16 @@ enum meta_interlace_info { META_INTERLACE_FRAME_INTERLACE_BOTTOMFIELD_FIRST = 0x00000020, }; +enum meta_picture_type { + META_PICTURE_TYPE_IDR = 0x00000001, + META_PICTURE_TYPE_P = 0x00000002, + META_PICTURE_TYPE_B = 0x00000004, + META_PICTURE_TYPE_I = 0x00000008, + META_PICTURE_TYPE_CRA = 0x00000010, + META_PICTURE_TYPE_BLA = 0x00000020, + META_PICTURE_TYPE_NOSHOW = 0x00000040, +}; + /* vendor controls end */ /* vendor events start */