video: driver: enc fix to run sample HEVC NV12C testcase

Allocate ARP buffer in CB4 to avoid HW hang issue.
Add support to set HFI_PROP_RAW_RESOLUTION at enc INPUT port
and did necessary changes to set HFI_PROP_CROP_OFFSETS at
OUTPUT port only for encoder. Also added support to set
missing basic control properties to video firmware.

Change-Id: If5bc2940d37ac20c1889cd4de466be09f1e1f28b
Signed-off-by: Akshata Sahukar <asahukar@codeaurora.org>
This commit is contained in:
Akshata Sahukar
2020-12-15 15:57:19 -08:00
parent a2f47ddf00
commit 38b9dd655f
10 changed files with 346 additions and 92 deletions

View File

@@ -211,6 +211,26 @@ u32 get_hfi_colorformat(struct msm_vidc_inst *inst,
return hfi_colorformat;
}
u32 get_hfi_quality_mode(struct msm_vidc_inst *inst)
{
u32 hfi_mode = HFI_MODE_POWER_SAVE;
switch(inst->quality_mode) {
case MSM_VIDC_MAX_QUALITY_MODE:
hfi_mode = HFI_MODE_MAX_QUALITY;
break;
case MSM_VIDC_POWER_SAVE_MODE:
hfi_mode = HFI_MODE_POWER_SAVE;
break;
default:
s_vpr_e(inst->sid, "%s: invalid qulity mode %d\n",
__func__, inst->quality_mode);
break;
}
return hfi_mode;
}
int get_hfi_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer, struct hfi_buffer *buf)
{

View File

@@ -19,13 +19,15 @@
u32 msm_venc_input_set_prop[] = {
HFI_PROP_COLOR_FORMAT,
HFI_PROP_BITSTREAM_RESOLUTION,
HFI_PROP_CROP_OFFSETS,
HFI_PROP_RAW_RESOLUTION,
HFI_PROP_LINEAR_STRIDE_SCANLINE,
HFI_PROP_BUFFER_HOST_MAX_COUNT,
};
u32 msm_venc_output_set_prop[] = {
HFI_PROP_BITSTREAM_RESOLUTION,
HFI_PROP_CROP_OFFSETS,
HFI_PROP_BUFFER_HOST_MAX_COUNT,
};
u32 msm_venc_input_subscribe_for_properties[] = {
@@ -116,13 +118,65 @@ static int msm_venc_set_colorformat(struct msm_vidc_inst *inst,
return 0;
}
static int msm_venc_set_resolution(struct msm_vidc_inst *inst,
/* TODO: Enable when NV12 support is required */
static int msm_venc_set_linear_alignment_factor(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
/* int rc = 0;
u32 pixelformat;
u32 alignment_factor[2];
if (port != INPUT_PORT) {
s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port);
return -EINVAL;
}
pixelformat = inst->fmts[INPUT_PORT].fmt.pix_mp.pixelformat;
if (pixelformat == V4L2_PIX_FMT_VIDC_NV12C ||
pixelformat == V4L2_PIX_FMT_VIDC_TP10C ||
pixelformat == V4L2_PIX_FMT_VIDC_ARGB32C) {
s_vpr_e(inst->sid,
"%s: not a linear color fmt, property is not set\n",
__func__);
return 0;
}
if (pixelformat == V4L2_PIX_FMT_ARGB32) {
alignment_factor[0] =
(rgb_stride_alignment(pixelformat, __func__) << 16) |
rgb_scanline_alignment(pixelformat, __func__);
alignment_factor[1] = 0;
} else {
alignment_factor[0] =
(y_stride_alignment(pixelformat, __func__) << 16) |
y_scanline_alignment(pixelformat, __func__);
alignment_factor[1] =
(uv_stride_alignment(pixelformat, __func__) << 16) |
uv_scanline_alignment(pixelformat, __func__);
}
s_vpr_h(inst->sid, "%s: payload[0]: %u payload[1]: %u\n", __func__,
alignment_factor[0], alignment_factor[1]);
rc = venus_hfi_session_property(inst,
HFI_PROP_LINEAR_STRIDE_SCANLINE,
HFI_HOST_FLAGS_NONE,
get_hfi_port(inst, port),
HFI_PAYLOAD_64_PACKED,
&alignment_factor,
sizeof(u64));
if (rc)
return rc;
*/
return 0;
}
static int msm_venc_set_raw_resolution(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
u32 resolution;
if (port != INPUT_PORT && port != OUTPUT_PORT) {
if (port != INPUT_PORT) {
s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port);
return -EINVAL;
}
@@ -132,6 +186,34 @@ static int msm_venc_set_resolution(struct msm_vidc_inst *inst,
s_vpr_h(inst->sid, "%s: width: %d height: %d\n", __func__,
inst->fmts[port].fmt.pix_mp.width,
inst->fmts[port].fmt.pix_mp.height);
rc = venus_hfi_session_property(inst,
HFI_PROP_RAW_RESOLUTION,
HFI_HOST_FLAGS_NONE,
get_hfi_port(inst, port),
HFI_PAYLOAD_32_PACKED,
&resolution,
sizeof(u32));
if (rc)
return rc;
return 0;
}
static int msm_venc_set_bitstream_resolution(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
u32 resolution;
if (port != OUTPUT_PORT) {
s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port);
return -EINVAL;
}
resolution = (inst->fmts[port].fmt.pix_mp.width << 16) |
inst->fmts[port].fmt.pix_mp.height;
s_vpr_h(inst->sid, "%s: width: %d height: %d\n", __func__,
inst->fmts[port].fmt.pix_mp.width,
inst->fmts[port].fmt.pix_mp.height);
rc = venus_hfi_session_property(inst,
HFI_PROP_BITSTREAM_RESOLUTION,
HFI_HOST_FLAGS_NONE,
@@ -148,25 +230,57 @@ static int msm_venc_set_crop_offsets(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
u32 crop;
u32 left_offset, top_offset, right_offset, bottom_offset;
u64 crop;
if (port != INPUT_PORT && port != OUTPUT_PORT) {
if (port != OUTPUT_PORT) {
s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port);
return -EINVAL;
}
/* TODO: recheck later */
crop = inst->fmts[INPUT_PORT].fmt.pix_mp.width << 16 |
inst->fmts[INPUT_PORT].fmt.pix_mp.height;
s_vpr_h(inst->sid, "%s: width: %d height: %d\n", __func__,
inst->fmts[INPUT_PORT].fmt.pix_mp.width,
inst->fmts[INPUT_PORT].fmt.pix_mp.height);
left_offset = inst->crop.left;
top_offset = inst->crop.top;
right_offset = (inst->fmts[port].fmt.pix_mp.width -
inst->crop.width);
bottom_offset = (inst->fmts[port].fmt.pix_mp.height -
inst->crop.height);
crop = (u64)right_offset << 48 | (u64)bottom_offset << 32 |
(u64)left_offset << 16 | top_offset;
s_vpr_h(inst->sid, "%s: left_offset: %d top_offset: %d "
"right_offset: %d bottom_offset: %d", __func__,
left_offset, top_offset, right_offset, bottom_offset);
rc = venus_hfi_session_property(inst,
HFI_PROP_CROP_OFFSETS,
HFI_HOST_FLAGS_NONE,
get_hfi_port(inst, port),
HFI_PAYLOAD_64_PACKED,
&crop,
sizeof(u64));
if (rc)
return rc;
return 0;
}
static int msm_venc_set_host_max_buf_count(struct msm_vidc_inst *inst,
enum msm_vidc_port_type port)
{
int rc = 0;
u32 count = DEFAULT_MAX_HOST_BUF_COUNT;
if (port != INPUT_PORT && port != OUTPUT_PORT) {
s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port);
return -EINVAL;
}
s_vpr_h(inst->sid, "%s: count: %u port: %u\n", __func__, count, port);
rc = venus_hfi_session_property(inst,
HFI_PROP_BUFFER_HOST_MAX_COUNT,
HFI_HOST_FLAGS_NONE,
get_hfi_port(inst, port),
HFI_PAYLOAD_U32,
&count,
sizeof(u32));
if (rc)
return rc;
@@ -185,6 +299,7 @@ static int msm_venc_set_stage(struct msm_vidc_inst *inst)
return -EINVAL;
}
s_vpr_h(inst->sid, "%s: stage: %u\n", __func__, inst->stage);
rc = venus_hfi_session_property(inst,
HFI_PROP_STAGE,
HFI_HOST_FLAGS_NONE,
@@ -209,6 +324,7 @@ static int msm_venc_set_pipe(struct msm_vidc_inst *inst)
return -EINVAL;
}
s_vpr_h(inst->sid, "%s: pipe: %u\n", __func__, inst->pipe);
rc = venus_hfi_session_property(inst,
HFI_PROP_PIPE,
HFI_HOST_FLAGS_NONE,
@@ -221,6 +337,29 @@ static int msm_venc_set_pipe(struct msm_vidc_inst *inst)
return 0;
}
static int msm_venc_set_quality_mode(struct msm_vidc_inst *inst)
{
int rc = 0;
if (!inst->quality_mode) {
s_vpr_e(inst->sid, "%s: invalid mode: %u\n",
__func__, inst->quality_mode);
return -EINVAL;
}
s_vpr_h(inst->sid, "%s: quality_mode: %u\n", __func__, inst->quality_mode);
rc = venus_hfi_session_property(inst,
HFI_PROP_QUALITY_MODE,
HFI_HOST_FLAGS_NONE,
HFI_PORT_BITSTREAM,
HFI_PAYLOAD_U32_ENUM,
&inst->quality_mode,
sizeof(u32));
if (rc)
return rc;
return 0;
}
static int msm_venc_set_input_properties(struct msm_vidc_inst *inst)
{
int rc = 0;
@@ -238,11 +377,14 @@ static int msm_venc_set_input_properties(struct msm_vidc_inst *inst)
case HFI_PROP_COLOR_FORMAT:
rc = msm_venc_set_colorformat(inst, INPUT_PORT);
break;
case HFI_PROP_BITSTREAM_RESOLUTION:
rc = msm_venc_set_resolution(inst, INPUT_PORT);
case HFI_PROP_RAW_RESOLUTION:
rc = msm_venc_set_raw_resolution(inst, INPUT_PORT);
break;
case HFI_PROP_CROP_OFFSETS:
rc = msm_venc_set_crop_offsets(inst, INPUT_PORT);
case HFI_PROP_LINEAR_STRIDE_SCANLINE:
rc = msm_venc_set_linear_alignment_factor(inst, INPUT_PORT);
break;
case HFI_PROP_BUFFER_HOST_MAX_COUNT:
rc = msm_venc_set_host_max_buf_count(inst, INPUT_PORT);
break;
default:
d_vpr_e("%s: unknown property %#x\n", __func__,
@@ -266,6 +408,39 @@ static int msm_venc_set_output_properties(struct msm_vidc_inst *inst)
return -EINVAL;
}
for (i = 0; i < ARRAY_SIZE(msm_venc_output_set_prop);
i++) {
switch (msm_venc_output_set_prop[i]) {
case HFI_PROP_BITSTREAM_RESOLUTION:
rc = msm_venc_set_bitstream_resolution(inst, OUTPUT_PORT);
break;
case HFI_PROP_CROP_OFFSETS:
rc = msm_venc_set_crop_offsets(inst, OUTPUT_PORT);
break;
case HFI_PROP_BUFFER_HOST_MAX_COUNT:
rc = msm_venc_set_host_max_buf_count(inst, OUTPUT_PORT);
break;
default:
d_vpr_e("%s: unknown property %#x\n", __func__,
msm_venc_output_set_prop[i]);
rc = -EINVAL;
break;
}
}
return rc;
}
static int msm_venc_set_internal_properties(struct msm_vidc_inst *inst)
{
int rc = 0;
d_vpr_h("%s()\n", __func__);
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
//TODO: set HFI_PORT_NONE properties at master port streamon.
rc = msm_venc_set_stage(inst);
if (rc)
@@ -275,22 +450,9 @@ static int msm_venc_set_output_properties(struct msm_vidc_inst *inst)
if (rc)
return rc;
for (i = 0; i < ARRAY_SIZE(msm_venc_output_set_prop);
i++) {
switch (msm_venc_output_set_prop[i]) {
case HFI_PROP_BITSTREAM_RESOLUTION:
rc = msm_venc_set_resolution(inst, OUTPUT_PORT);
break;
case HFI_PROP_CROP_OFFSETS:
rc = msm_venc_set_crop_offsets(inst, OUTPUT_PORT);
break;
default:
d_vpr_e("%s: unknown property %#x\n", __func__,
msm_venc_output_set_prop[i]);
rc = -EINVAL;
break;
}
}
rc = msm_venc_set_quality_mode(inst);
if (rc)
return rc;
return rc;
}
@@ -678,6 +840,18 @@ int msm_venc_start_output(struct msm_vidc_inst *inst)
if (rc)
goto error;
rc = msm_vidc_adjust_v4l2_properties(inst);
if (rc)
return -EINVAL;
rc = msm_vidc_set_v4l2_properties(inst);
if (rc)
return -EINVAL;
rc = msm_venc_set_internal_properties(inst);
if (rc)
goto error;
rc = msm_venc_property_subscription(inst, OUTPUT_PORT);
if (rc)
return rc;
@@ -732,6 +906,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
v4l2_colorformat_to_media(fmt->fmt.pix_mp.pixelformat,
__func__),
f->fmt.pix_mp.height);
fmt->fmt.pix_mp.num_planes = 1;
fmt->fmt.pix_mp.plane_fmt[0].bytesperline =
fmt->fmt.pix_mp.width;
@@ -804,8 +979,17 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
goto err_invalid_fmt;
}
fmt->type = OUTPUT_MPLANE;
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 16);
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 16);
if (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_HEVC) {
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width,
H265_BITSTREM_ALIGNMENT);
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height,
H265_BITSTREM_ALIGNMENT);
} else {
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width,
DEFAULT_BITSTREM_ALIGNMENT);
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height,
DEFAULT_BITSTREM_ALIGNMENT);
}
fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
fmt->fmt.pix_mp.num_planes = 1;
fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
@@ -1042,6 +1226,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst)
inst->prop.operating_rate = DEFAULT_FPS << 16;
inst->stage = MSM_VIDC_STAGE_2;
inst->pipe = MSM_VIDC_PIPE_4;
inst->quality_mode = MSM_VIDC_MAX_QUALITY_MODE;
rc = msm_venc_codec_change(inst,
inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat);

View File

@@ -551,7 +551,7 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
/* Dynamic set control ASAP */
rc = msm_vidc_set_fw_list(inst);
rc = msm_vidc_set_v4l2_properties(inst);
if (rc) {
s_vpr_e(inst->sid, "%s: setting %s failed\n",
__func__, ctrl->name);
@@ -695,7 +695,7 @@ int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl)
* - update instance firmware list with current capability id
* Now, loop over child list and call its adjust function
*/
int msm_vidc_adjust_properties(struct msm_vidc_inst *inst)
int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst)
{
int rc = 0;
int i;
@@ -742,6 +742,38 @@ exit:
return rc;
}
int msm_vidc_set_q16(void *instance,
enum msm_vidc_inst_capability_type cap_id)
{
int rc = 0;
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
u32 hfi_value = 0;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
hfi_value = inst->capabilities->cap[cap_id].value;
s_vpr_h(inst->sid,
"%s: hfi_id: %#x, value: %#x\n", __func__,
inst->capabilities->cap[cap_id].hfi_id,
hfi_value);
rc = venus_hfi_session_property(inst,
inst->capabilities->cap[cap_id].hfi_id,
HFI_HOST_FLAGS_NONE,
msm_vidc_get_port_info(inst, cap_id),
HFI_PAYLOAD_Q16,
&hfi_value,
sizeof(u32));
if (rc)
s_vpr_e(inst->sid,
"%s: failed to set cap_id: %d to fw\n",
__func__, cap_id);
return rc;
}
int msm_vidc_set_u32(void *instance,
enum msm_vidc_inst_capability_type cap_id)
{
@@ -764,6 +796,10 @@ int msm_vidc_set_u32(void *instance,
hfi_payload = HFI_PAYLOAD_U32;
}
s_vpr_h(inst->sid,
"%s: hfi_id: %#x, value: %u\n", __func__,
inst->capabilities->cap[cap_id].hfi_id,
hfi_value);
rc = venus_hfi_session_property(inst,
inst->capabilities->cap[cap_id].hfi_id,
HFI_HOST_FLAGS_NONE,
@@ -790,6 +826,10 @@ int msm_vidc_set_s32(void *instance,
return -EINVAL;
}
s_vpr_h(inst->sid,
"%s: hfi_id: %#x, value: %d\n", __func__,
inst->capabilities->cap[cap_id].hfi_id,
inst->capabilities->cap[cap_id].value);
rc = venus_hfi_session_property(inst,
inst->capabilities->cap[cap_id].hfi_id,
HFI_HOST_FLAGS_NONE, HFI_PORT_NONE,
@@ -851,7 +891,7 @@ int msm_vidc_set_array(void *instance,
return rc;
}
int msm_vidc_set_fw_list(struct msm_vidc_inst *inst)
int msm_vidc_set_v4l2_properties(struct msm_vidc_inst *inst)
{
int rc = 0;
struct msm_vidc_inst_capability *capability;
@@ -942,10 +982,10 @@ int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst,
case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
switch (capability->cap[cap_id].value) {
case V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE:
*value = BIT(HFI_SEQ_HEADER_SEPERATE_FRAME);
*value = HFI_SEQ_HEADER_SEPERATE_FRAME;
break;
case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME:
*value = BIT(HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME);
*value = HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME;
break;
/*
* TODO (AS): other HFI values are missing corresponding

View File

@@ -272,8 +272,10 @@ u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst,
{
u32 region = MSM_VIDC_NON_SECURE;
if (!is_secure_session(inst))
if (!is_secure_session(inst) &&
buffer_type != MSM_VIDC_BUF_ARP) {
return region;
}
switch (buffer_type) {
case MSM_VIDC_BUF_INPUT:
@@ -906,6 +908,7 @@ int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
alloc->region = msm_vidc_get_buffer_region(inst,
buffer_type, __func__);
alloc->size = buffer->buffer_size;
alloc->secure = (alloc->region > MSM_VIDC_NON_SECURE) ? 1 : 0;
rc = msm_vidc_memory_alloc(inst->core, alloc);
if (rc)
return -ENOMEM;

View File

@@ -171,47 +171,6 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
return rc;
}
/*
if ((inst->state == MSM_VIDC_OPEN && q->type == OUTPUT_MPLANE) ||
inst->state == MSM_VIDC_START_INPUT) {
s_vpr_h(inst->sid, "$s: msm_vidc_adjust_properties\n");
rc = msm_vidc_adjust_properties(inst);
if (rc)
return -EINVAL;
s_vpr_h(inst->sid, "$s: msm_vidc_set_fw_list\n");
rc = msm_vidc_set_fw_list(inst);
if (rc)
return -EINVAL;
}
if (inst->state == MSM_VIDC_START_INPUT ||
inst->state == MSM_VIDC_START_OUTPUT) {
rc = msm_vidc_adjust_properties(inst);
if (rc)
return -EINVAL;
}
if ((inst->state == MSM_VIDC_START_OUTPUT) ||
(inst->state == MSM_VIDC_OPEN &&
q->type == INPUT_MPLANE)) {
rc = msm_vidc_set_fw_list(inst);
if (rc)
return -EINVAL;
}
*/
if (inst->state == MSM_VIDC_START_INPUT ||
inst->state == MSM_VIDC_START_OUTPUT) {
rc = msm_vidc_adjust_properties(inst);
if (rc)
return -EINVAL;
rc = msm_vidc_set_fw_list(inst);
if (rc)
return -EINVAL;
}
if (q->type == INPUT_MPLANE) {
if (is_decode_session(inst))
rc = msm_vdec_start_input(inst);