video: driver: add restrictions for dec fence enablement

- Allow dec sw fence enablement only if decode order is set and
 non interlace type session.
- Enable low latency mode if sw fence is enabled.
- Signal fence if FBD length > 0.

Change-Id: Ib59c2de51f621b796e68fe2aba68d9fca3ff4272
Signed-off-by: Akshata Sahukar <quic_asahukar@quicinc.com>
这个提交包含在:
Akshata Sahukar
2022-04-20 12:01:18 -07:00
父节点 3cbfc66709
当前提交 047ed11bf7
修改 11 个文件,包含 167 行新增48 行删除

查看文件

@@ -330,7 +330,7 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = {
* Client will enable V4L2_CID_MPEG_VIDC_METADATA_OUTBUF_FENCE * Client will enable V4L2_CID_MPEG_VIDC_METADATA_OUTBUF_FENCE
* to get fence_id in input metadata buffer done. * 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_DISABLE,
V4L2_MPEG_VIDC_META_ENABLE | V4L2_MPEG_VIDC_META_RX_INPUT, V4L2_MPEG_VIDC_META_ENABLE | V4L2_MPEG_VIDC_META_RX_INPUT,
0, V4L2_MPEG_VIDC_META_DISABLE, 0, V4L2_MPEG_VIDC_META_DISABLE,
@@ -1327,7 +1327,10 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = {
0, 0,
HFI_PROP_PIPE}, 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, {QUALITY_MODE, ENC, CODECS_ALL,
MSM_VIDC_MAX_QUALITY_MODE, MSM_VIDC_MAX_QUALITY_MODE,
@@ -1729,6 +1732,12 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala
NULL, NULL,
msm_vidc_set_u32}, 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, {HFLIP, ENC, CODECS_ALL,
{0}, {0},
{0}, {0},
@@ -1860,7 +1869,13 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala
{LOWLATENCY_MODE, ENC, H264 | HEVC, {LOWLATENCY_MODE, ENC, H264 | HEVC,
{BITRATE_MODE}, {BITRATE_MODE},
{STAGE}, {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}, NULL},
{LTR_COUNT, ENC, H264|HEVC, {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, {OUTPUT_ORDER, DEC, H264|HEVC|VP9|AV1,
{THUMBNAIL_MODE, DISPLAY_DELAY, DISPLAY_DELAY_ENABLE}, {THUMBNAIL_MODE, DISPLAY_DELAY, DISPLAY_DELAY_ENABLE},
{0}, {META_OUTBUF_FENCE},
msm_vidc_adjust_output_order, msm_vidc_adjust_output_order,
msm_vidc_set_u32}, msm_vidc_set_u32},
@@ -2190,7 +2205,7 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala
NULL, NULL,
msm_vidc_set_u32_packed}, msm_vidc_set_u32_packed},
{STAGE, DEC|ENC, CODECS_ALL, {STAGE, ENC | DEC, CODECS_ALL,
{0}, {0},
{0}, {0},
NULL, NULL,
@@ -2202,6 +2217,12 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala
NULL, NULL,
msm_vidc_set_stage}, msm_vidc_set_stage},
{STAGE, DEC, H264|HEVC|VP9|AV1,
{LOWLATENCY_MODE},
{0},
NULL,
msm_vidc_set_stage},
{PIPE, DEC|ENC, CODECS_ALL, {PIPE, DEC|ENC, CODECS_ALL,
{0}, {0},
{0}, {0},

查看文件

@@ -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_brs(void *instance, struct v4l2_ctrl *ctrl);
int msm_vidc_adjust_bitrate_boost(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_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_adjust_set_v4l2_properties(struct msm_vidc_inst *inst);
int msm_vidc_prepare_dependency_list(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); 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_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_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_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_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl);
int msm_vidc_set_header_mode(void *instance, int msm_vidc_set_header_mode(void *instance,

查看文件

@@ -197,6 +197,11 @@ static inline bool is_meta_enabled(struct msm_vidc_inst *inst, unsigned int type
return enabled; 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) static inline bool is_linear_yuv_colorformat(enum msm_vidc_colorformat_type colorformat)
{ {
return colorformat == MSM_VIDC_FMT_NV12 || return colorformat == MSM_VIDC_FMT_NV12 ||

查看文件

@@ -13,10 +13,12 @@ struct msm_vidc_fence *msm_vidc_fence_create(
struct msm_vidc_inst *inst); struct msm_vidc_inst *inst);
int msm_vidc_create_fence_fd(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 *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, int msm_vidc_fence_signal(struct msm_vidc_inst *inst,
u32 fence_id); u32 fence_id);
void msm_vidc_fence_destroy(struct msm_vidc_inst *inst, 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); int msm_vidc_fence_init(struct msm_vidc_inst *inst);
void msm_vidc_fence_deinit(struct msm_vidc_inst *inst); void msm_vidc_fence_deinit(struct msm_vidc_inst *inst);

查看文件

@@ -762,6 +762,7 @@ struct msm_vidc_hfi_frame_info {
u32 cf; u32 cf;
u32 data_corrupt; u32 data_corrupt;
u32 overflow; u32 overflow;
u32 fence_id;
}; };
struct msm_vidc_decode_vpp_delay { struct msm_vidc_decode_vpp_delay {

查看文件

@@ -1190,7 +1190,7 @@ static int msm_vdec_read_input_subcr_params(struct msm_vidc_inst *inst)
u32 colour_description_present_flag = 0; u32 colour_description_present_flag = 0;
u32 video_signal_type_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__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; 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__); 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; return 0;
} }

查看文件

@@ -443,7 +443,6 @@ int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap_id,
s32 adjusted_val, const char *func) s32 adjusted_val, const char *func)
{ {
int prev_value = 0; int prev_value = 0;
bool is_updated = false;
if (!inst || !inst->capabilities) { if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__); 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 */ /* disable metadata */
inst->capabilities->cap[cap_id].value &= ~adjusted_val; inst->capabilities->cap[cap_id].value &= ~adjusted_val;
} }
if (prev_value != (prev_value | adjusted_val))
is_updated = true;
} else { } else {
inst->capabilities->cap[cap_id].value = adjusted_val; 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, i_vpr_h(inst,
"%s: updated database: name: %s, value: %#x -> %#x\n", "%s: updated database: name: %s, value: %#x -> %#x\n",
func, cap_name(cap_id), func, cap_name(cap_id),
prev_value, adjusted_val); prev_value, inst->capabilities->cap[cap_id].value);
} }
return 0; return 0;
@@ -2743,7 +2738,7 @@ int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl)
return 0; 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; struct msm_vidc_inst_capability *capability;
s32 adjusted_value; s32 adjusted_value;
@@ -2773,6 +2768,36 @@ int msm_vidc_adjust_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl)
return 0; 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 msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl)
{ {
int adjusted_value; int adjusted_value;
@@ -2893,6 +2918,37 @@ int msm_vidc_adjust_dec_operating_rate(void *instance, struct v4l2_ctrl *ctrl)
return 0; 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) int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst)
{ {
struct list_head root_list, opt_list; struct list_head root_list, opt_list;

查看文件

@@ -3481,7 +3481,7 @@ exit:
if (rc) { if (rc) {
i_vpr_e(inst, "%s: qbuf failed\n", __func__); i_vpr_e(inst, "%s: qbuf failed\n", __func__);
if (fence) if (fence)
msm_vidc_fence_destroy(inst, fence); msm_vidc_fence_destroy(inst, (u32)fence->dma_fence.seqno);
} }
return rc; 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) { list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) {
i_vpr_e(inst, "%s: destroying fence id: %llu\n", i_vpr_e(inst, "%s: destroying fence id: %llu\n",
__func__, fence->dma_fence.seqno); __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 */ /* destroy buffers from pool */

查看文件

@@ -117,15 +117,15 @@ err_fd:
return rc; 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; struct msm_vidc_fence *fence, *dummy_fence;
bool found = false; bool found = false;
if (!inst) { if (!inst) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return NULL;
} }
list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) { 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", i_vpr_e(inst, "%s: no fence available to signal with id: %u",
__func__, fence_id); __func__, fence_id);
rc = -EINVAL; rc = -EINVAL;
goto exit; goto exit;
} }
i_vpr_l(inst, "%s: fence %s\n", __func__, fence->name); i_vpr_l(inst, "%s: fence %s\n", __func__, fence->name);
dma_fence_signal(&fence->dma_fence); dma_fence_signal(&fence->dma_fence);
dma_fence_put(&fence->dma_fence); dma_fence_put(&fence->dma_fence);
@@ -150,28 +168,18 @@ exit:
return rc; 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__); d_vpr_e("%s: invalid params\n", __func__);
return; return;
} }
list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) { fence = msm_vidc_get_fence_from_id(inst, fence_id);
if (fence->dma_fence.seqno == if (!fence) {
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);
return; return;
} }

查看文件

@@ -864,7 +864,7 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
if (buffer->data_size) { if (buffer->data_size) {
i_vpr_e(inst, "%s: reset data size to zero for last flag buffer\n", i_vpr_e(inst, "%s: reset data size to zero for last flag buffer\n",
__func__); __func__);
buffer->data_size = 0; buf->data_size = 0;
} }
if (buffer->flags & HFI_BUF_FW_FLAG_READONLY) { if (buffer->flags & HFI_BUF_FW_FLAG_READONLY) {
i_vpr_e(inst, "%s: reset RO flag for last flag buffer\n", 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 = 0;
buf->flags = get_driver_buffer_flags(inst, buffer->flags); 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)) { if (is_decode_session(inst)) {
inst->power.fw_cr = inst->hfi_frame_info.cr; inst->power.fw_cr = inst->hfi_frame_info.cr;
inst->power.fw_cf = inst->hfi_frame_info.cf; 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; int rc = 0;
u32 *payload_ptr = NULL; u32 *payload_ptr = NULL;
u32 fence_id = 0;
payload_ptr = (u32 *)((u8 *)pkt + sizeof(struct hfi_packet)); payload_ptr = (u32 *)((u8 *)pkt + sizeof(struct hfi_packet));
if (!payload_ptr) { 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); __func__, payload_ptr[0], inst->capabilities->cap[PIPE].value);
break; break;
case HFI_PROP_FENCE: case HFI_PROP_FENCE:
if (is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE)) { inst->hfi_frame_info.fence_id = payload_ptr[0];
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__);
}
break; break;
default: default:
i_vpr_e(inst, "%s: invalid property %#x\n", i_vpr_e(inst, "%s: invalid property %#x\n",

查看文件

@@ -389,6 +389,16 @@ enum meta_interlace_info {
META_INTERLACE_FRAME_INTERLACE_BOTTOMFIELD_FIRST = 0x00000020, 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 controls end */
/* vendor events start */ /* vendor events start */