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>
This commit is contained in:
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
* 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},

查看文件

@@ -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,

查看文件

@@ -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 ||

查看文件

@@ -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);

查看文件

@@ -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 {

查看文件

@@ -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;
}

查看文件

@@ -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;

查看文件

@@ -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 */

查看文件

@@ -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;
}

查看文件

@@ -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",

查看文件

@@ -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 */