video: driver: Add support to update buffer flags

Add support to added buf flags in dequeued buffers based
on HFI_PROP_NO_OUTPUT and HFI_PROP_PICTURE_TYPE property
values received from video fw.

Change-Id: Icf285ab7feb88daf8991705964ed0d3214c99870
Signed-off-by: Akshata Sahukar <asahukar@codeaurora.org>
Этот коммит содержится в:
Akshata Sahukar
2021-02-05 16:32:06 -08:00
родитель f8e6c60909
Коммит 508102a802
3 изменённых файлов: 205 добавлений и 112 удалений

Просмотреть файл

@@ -386,6 +386,40 @@ static int handle_session_drain(struct msm_vidc_inst *inst,
return 0;
}
static int get_driver_buffer_flags(struct msm_vidc_inst *inst, u32 hfi_flags)
{
u32 driver_flags = 0;
if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_IDR) {
driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_P) {
driver_flags |= MSM_VIDC_BUF_FLAG_PFRAME;
} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_B) {
driver_flags |= MSM_VIDC_BUF_FLAG_BFRAME;
} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_I) {
if (inst->codec == MSM_VIDC_VP9)
driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_CRA) {
driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
} else if (inst->frame_prop.hfi_picture_type & HFI_PICTURE_BLA) {
driver_flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;
}
if (inst->capabilities->cap[META_BUF_TAG].value) {
if (inst->frame_prop.hfi_no_output &&
!(hfi_flags & HFI_BUF_FW_FLAG_CODEC_CONFIG))
driver_flags |= MSM_VIDC_BUF_FLAG_ERROR;
}
if (hfi_flags & HFI_BUF_FW_FLAG_CODEC_CONFIG)
driver_flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG;
if (hfi_flags & HFI_BUF_FW_FLAG_LAST)
driver_flags |= MSM_VIDC_BUF_FLAG_LAST;
return driver_flags;
}
static int handle_input_buffer(struct msm_vidc_inst *inst,
struct hfi_buffer *buffer)
{
@@ -414,17 +448,9 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
buf->data_size = buffer->data_size;
buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
buf->attr |= MSM_VIDC_ATTR_DEQUEUED;
buf->flags = 0;
//todo:
/*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT) {
i_vpr_h(inst, "%s: data corrupted\n", __func__);
buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;
}
if (buffer->flags & HFI_BUF_FW_FLAG_UNSUPPORTED) {
i_vpr_e(inst, "%s: unsupported input\n", __func__);
buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;
// TODO: move inst->state to error state
}*/
buf->flags = get_driver_buffer_flags(inst, buffer->flags);
print_vidc_buffer(VIDC_HIGH, "EBD", inst, buf);
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD);
@@ -467,21 +493,10 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
else
buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY;
buf->flags = 0;
//todo: moved to HFI_PROP_PICTURE_TYPE
/*if (buffer->flags & HFI_BUF_FW_FLAG_KEYFRAME)
buf->flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;*/
//moved to HFI_INFO_DATA_CORRUPT
/*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT)
buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;*/
if (buffer->flags & HFI_BUF_FW_FLAG_CODEC_CONFIG)
buf->flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG;
//moved to HFI_PROP_SUBFRAME_OUTPUT
/*if (buffer->flags & HFI_BUF_FW_FLAG_SUBFRAME)
buf->flags |= MSM_VIDC_BUF_FLAG_SUBFRAME;*/
if (buffer->flags & HFI_BUF_FW_FLAG_LAST)
buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
buf->flags = 0;
buf->flags = get_driver_buffer_flags(inst, buffer->flags);
print_vidc_buffer(VIDC_HIGH, "FBD", inst, buf);
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD);
@@ -894,9 +909,26 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
static int handle_port_settings_change(struct msm_vidc_inst *inst,
struct hfi_packet *pkt)
{
int rc = 0;
i_vpr_h(inst, "%s: Received port settings change, type %d\n",
__func__, pkt->port);
return 0;
if (pkt->port == HFI_PORT_RAW) {
print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
inst->subcr_params[OUTPUT_PORT]);
rc = msm_vdec_output_port_settings_change(inst);
} else if (pkt->port == HFI_PORT_BITSTREAM) {
print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
inst->subcr_params[INPUT_PORT]);
rc = msm_vdec_input_port_settings_change(inst);
} else {
i_vpr_e(inst, "%s: invalid port type: %#x\n",
__func__, pkt->port);
rc = -EINVAL;
}
return rc;
}
static int handle_session_subscribe_mode(struct msm_vidc_inst *inst,
@@ -958,6 +990,7 @@ static int handle_session_command(struct msm_vidc_inst *inst,
static int handle_session_property(struct msm_vidc_inst *inst,
struct hfi_packet *pkt)
{
int rc = 0;
u32 port;
u32 *payload_ptr;
@@ -998,12 +1031,33 @@ static int handle_session_property(struct msm_vidc_inst *inst,
case HFI_PROP_TIER:
inst->subcr_params[port].tier = payload_ptr[0];
break;
case HFI_PROP_PICTURE_TYPE:
if (is_encode_session(inst) && port == INPUT_PORT) {
rc = -EINVAL;
i_vpr_e(inst,
"%s: invalid port: %d for property %#x\n",
__func__, pkt->port, pkt->type);
break;
}
inst->frame_prop.hfi_picture_type = payload_ptr[0];
break;
case HFI_PROP_NO_OUTPUT:
if (port != INPUT_PORT) {
rc = -EINVAL;
i_vpr_e(inst,
"%s: invalid port: %d for property %#x\n",
__func__, pkt->port, pkt->type);
break;
}
inst->frame_prop.hfi_no_output = 1;
break;
default:
i_vpr_e(inst, "%s: invalid port settings property %#x\n",
__func__, pkt->type);
return -EINVAL;
}
return 0;
return rc;
}
static int handle_image_version_property(struct msm_vidc_core *core,
@@ -1096,16 +1150,48 @@ exit:
return rc;
}
static int process_response_packet(struct msm_vidc_inst *inst,
struct hfi_packet *packet)
{
int rc = 0;
if (packet->type > HFI_CMD_BEGIN &&
packet->type < HFI_CMD_END) {
rc = handle_session_command(inst, packet);
} else if (packet->type > HFI_PROP_BEGIN &&
packet->type < HFI_PROP_END) {
rc = handle_session_property(inst, packet);
} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
packet->type < HFI_SESSION_ERROR_END) {
rc = handle_session_error(inst, packet);
} else if (packet->type > HFI_INFORMATION_BEGIN &&
packet->type < HFI_INFORMATION_END) {
rc = handle_session_info(inst, packet);
} else {
i_vpr_e(inst, "%s: Unknown packet type: %#x\n",
__func__, packet->type);
rc = -EINVAL;
}
return rc;
}
int handle_session_response_work(struct msm_vidc_inst *inst,
struct response_work *resp_work)
{
int rc = 0;
struct hfi_header *hdr = NULL;
struct hfi_packet *packet;
u8 *pkt, *temp_pkt;
u8 *pkt, *start_pkt;
u32 hfi_cmd_type = 0;
u32 hfi_port = 0;
int i;
int i, j;
struct msm_vidc_cmd_range be[5] = {
{HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END},
{HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END},
{HFI_PROP_BEGIN, HFI_PROP_END},
{HFI_CMD_BEGIN, HFI_CMD_END},
{HFI_INFORMATION_BEGIN, HFI_INFORMATION_END},
};
if (!inst || !resp_work) {
d_vpr_e("%s: invalid params\n", __func__);
@@ -1119,47 +1205,42 @@ int handle_session_response_work(struct msm_vidc_inst *inst,
}
hfi_cmd_type = 0;
hfi_port = 0;
pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
temp_pkt = pkt;
start_pkt = pkt;
/* validate all packets */
for (i = 0; i < hdr->num_packets; i++) {
packet = (struct hfi_packet * ) pkt;
if (validate_packet(pkt, resp_work->data,
resp_work->data_size, __func__)) {
rc = -EINVAL;
goto exit;
}
packet = (struct hfi_packet *)pkt;
if (packet->type > HFI_CMD_BEGIN &&
packet->type < HFI_CMD_END) {
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
i_vpr_e(inst,
"%s: invalid packet type %d in port settings change\n",
__func__, packet->type);
rc = -EINVAL;
goto exit;
}
hfi_cmd_type = packet->type;
hfi_port = packet->port;
rc = handle_session_command(inst, packet);
} else if (packet->type > HFI_PROP_BEGIN &&
packet->type < HFI_PROP_END) {
rc = handle_session_property(inst, packet);
} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
packet->type < HFI_SESSION_ERROR_END) {
rc = handle_session_error(inst, packet);
} else if (packet->type > HFI_INFORMATION_BEGIN &&
packet->type < HFI_INFORMATION_END) {
rc = handle_session_info(inst, packet);
} else {
i_vpr_e(inst, "%s: Unknown packet type: %#x\n",
__func__, packet->type);
rc = -EINVAL;
goto exit;
}
pkt += packet->size;
}
memset(&inst->frame_prop, 0,
sizeof(struct msm_vidc_frame_properties));
for (i = 0; i < ARRAY_SIZE(be); i++) {
pkt = start_pkt;
for (j = 0; j < hdr->num_packets; j++) {
packet = (struct hfi_packet * ) pkt;
if (packet->type > be[i].begin
&& packet->type < be[i].end) {
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
i_vpr_e(inst,
"%s: invalid packet type %d in port settings change\n",
__func__, packet->type);
rc = -EINVAL;
}
hfi_cmd_type = packet->type;
rc = process_response_packet(inst, packet);
if (rc)
goto exit;
}
pkt += packet->size;
}
}
if (hfi_cmd_type == HFI_CMD_BUFFER) {
rc = handle_dequeue_buffers(inst);
@@ -1167,24 +1248,8 @@ int handle_session_response_work(struct msm_vidc_inst *inst,
goto exit;
}
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
if (hfi_port == HFI_PORT_RAW) {
print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
inst->subcr_params[OUTPUT_PORT]);
rc = msm_vdec_output_port_settings_change(inst);
if (rc)
goto exit;
} else if (hfi_port == HFI_PORT_BITSTREAM) {
print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
inst->subcr_params[INPUT_PORT]);
rc = msm_vdec_input_port_settings_change(inst);
if (rc)
goto exit;
} else {
i_vpr_e(inst, "%s: invalid port type: %#x\n",
__func__, hfi_port);
}
}
memset(&inst->frame_prop, 0,
sizeof(struct msm_vidc_frame_properties));
exit:
return rc;
@@ -1283,10 +1348,17 @@ static int handle_session_response(struct msm_vidc_core *core,
int rc = 0;
struct msm_vidc_inst *inst;
struct hfi_packet *packet;
u8 *pkt;
u8 *pkt, *start_pkt;
u32 hfi_cmd_type = 0;
u32 hfi_port = 0;
int i;
int i, j;
struct msm_vidc_cmd_range be[5] = {
{HFI_SYSTEM_ERROR_BEGIN, HFI_SYSTEM_ERROR_END},
{HFI_SESSION_ERROR_BEGIN, HFI_SESSION_ERROR_END},
{HFI_PROP_BEGIN, HFI_PROP_END},
{HFI_CMD_BEGIN, HFI_CMD_END},
{HFI_INFORMATION_BEGIN, HFI_INFORMATION_END},
};
inst = get_inst(core, hdr->session_id);
if (!inst) {
@@ -1298,58 +1370,66 @@ static int handle_session_response(struct msm_vidc_core *core,
hfi_cmd_type = 0;
hfi_port = 0;
pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
start_pkt = pkt;
/* validate all packets */
for (i = 0; i < hdr->num_packets; i++) {
packet = (struct hfi_packet * ) pkt;
if (validate_packet(pkt, core->response_packet,
core->packet_size, __func__)) {
rc = -EINVAL;
goto exit;
}
packet = (struct hfi_packet *)pkt;
if (packet->type > HFI_CMD_BEGIN &&
packet->type < HFI_CMD_END) {
if (packet->type == HFI_CMD_SETTINGS_CHANGE) {
if (packet->port == HFI_PORT_BITSTREAM)
rc = queue_response_work(inst, RESP_WORK_INPUT_PSC,
(void *)hdr, hdr->size);
else if (packet->port == HFI_PORT_RAW)
rc = queue_response_work(inst, RESP_WORK_OUTPUT_PSC,
(void *)hdr, hdr->size);
goto exit;
} else if (packet->type == HFI_CMD_BUFFER &&
packet->port == HFI_PORT_RAW &&
check_last_flag(inst, packet)) {
rc = queue_response_work(inst, RESP_WORK_LAST_FLAG,
pkt += packet->size;
}
pkt = start_pkt;
for (j = 0; j < hdr->num_packets; j++) {
packet = (struct hfi_packet * ) pkt;
if (packet->type == HFI_CMD_SETTINGS_CHANGE) {
if (packet->port == HFI_PORT_BITSTREAM)
rc = queue_response_work(inst,
RESP_WORK_INPUT_PSC,
(void *)hdr, hdr->size);
goto exit;
}
hfi_cmd_type = packet->type;
hfi_port = packet->port;
rc = handle_session_command(inst, packet);
} else if (packet->type > HFI_PROP_BEGIN &&
packet->type < HFI_PROP_END) {
rc = handle_session_property(inst, packet);
} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
packet->type < HFI_SESSION_ERROR_END) {
rc = handle_session_error(inst, packet);
} else if (packet->type > HFI_INFORMATION_BEGIN &&
packet->type < HFI_INFORMATION_END) {
rc = handle_session_info(inst, packet);
} else {
i_vpr_e(inst, "%s: Unknown packet type: %#x\n",
__func__, packet->type);
rc = -EINVAL;
else if (packet->port == HFI_PORT_RAW)
rc = queue_response_work(inst,
RESP_WORK_OUTPUT_PSC,
(void *)hdr, hdr->size);
goto exit;
} else if (packet->type == HFI_CMD_BUFFER &&
packet->port == HFI_PORT_RAW &&
check_last_flag(inst, packet)) {
rc = queue_response_work(inst,
RESP_WORK_LAST_FLAG,
(void *)hdr, hdr->size);
goto exit;
}
pkt += packet->size;
}
memset(&inst->frame_prop, 0, sizeof(struct msm_vidc_frame_properties));
for (i = 0; i < ARRAY_SIZE(be); i++) {
pkt = start_pkt;
for (j = 0; j < hdr->num_packets; j++) {
packet = (struct hfi_packet * ) pkt;
if (packet->type > be[i].begin && packet->type < be[i].end) {
hfi_cmd_type = packet->type;
rc = process_response_packet(inst, packet);
if (rc)
goto exit;
}
pkt += packet->size;
}
}
if (hfi_cmd_type == HFI_CMD_BUFFER) {
rc = handle_dequeue_buffers(inst);
if (rc)
goto exit;
}
memset(&inst->frame_prop, 0, sizeof(struct msm_vidc_frame_properties));
exit:
mutex_unlock(&inst->lock);
put_inst(inst);