diff --git a/driver/variant/iris2/src/msm_vidc_buffer_iris2.c b/driver/variant/iris2/src/msm_vidc_buffer_iris2.c index 13563c2c1a..f0bfa3a3b8 100644 --- a/driver/variant/iris2/src/msm_vidc_buffer_iris2.c +++ b/driver/variant/iris2/src/msm_vidc_buffer_iris2.c @@ -575,6 +575,7 @@ static u32 calculate_enc_scratch_size(struct msm_vidc_inst *inst, bitstream_size = ALIGN(bitstream_size, VENUS_DMA_ALIGNMENT); if (1) { // TODO: work_mode == HFI_WORKMODE_2) { + s_vpr_e(inst->sid, "work mode 2\n"); total_bitbin_buffers = 3; bitbin_size = bitstream_size * 17 / 10; bitbin_size = ALIGN(bitbin_size, VENUS_DMA_ALIGNMENT); @@ -1288,7 +1289,8 @@ int msm_buffer_size_iris2(struct msm_vidc_inst *inst, case MSM_VIDC_BUF_DPB: size = msm_vidc_encoder_dpb_size_iris2(inst); break; - case MSM_VIDC_BUF_PERSIST: + //case MSM_VIDC_BUF_PERSIST: + case MSM_VIDC_BUF_ARP: size = msm_vidc_encoder_persist_size_iris2(inst); break; default: @@ -1344,7 +1346,8 @@ int msm_buffer_min_count_iris2(struct msm_vidc_inst *inst, case MSM_VIDC_BUF_NON_COMV: case MSM_VIDC_BUF_LINE: case MSM_VIDC_BUF_DPB: - case MSM_VIDC_BUF_PERSIST: + //case MSM_VIDC_BUF_PERSIST: + case MSM_VIDC_BUF_ARP: count = 1; break; default: diff --git a/driver/vidc/inc/msm_venc.h b/driver/vidc/inc/msm_venc.h index 1d1f41e921..11d5c2df67 100644 --- a/driver/vidc/inc/msm_venc.h +++ b/driver/vidc/inc/msm_venc.h @@ -9,6 +9,10 @@ #include "msm_vidc_core.h" #include "msm_vidc_inst.h" +int msm_venc_stop_input(struct msm_vidc_inst *inst); +int msm_venc_start_input(struct msm_vidc_inst *inst); +int msm_venc_stop_output(struct msm_vidc_inst *inst); +int msm_venc_start_output(struct msm_vidc_inst *inst); int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f); diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 9b562d6223..a41ba4ba3c 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -50,6 +50,7 @@ static inline is_output_meta_buffer(enum msm_vidc_buffer_type buffer_type) static inline is_internal_buffer(enum msm_vidc_buffer_type buffer_type) { return buffer_type == MSM_VIDC_BUF_BIN || + buffer_type == MSM_VIDC_BUF_ARP || buffer_type == MSM_VIDC_BUF_COMV || buffer_type == MSM_VIDC_BUF_NON_COMV || buffer_type == MSM_VIDC_BUF_LINE || diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index 1045100f48..e312d8de52 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -27,6 +27,7 @@ struct msm_vidc_session_ops { struct msm_vidc_allocations_info { struct msm_vidc_allocations bin; + struct msm_vidc_allocations arp; struct msm_vidc_allocations comv; struct msm_vidc_allocations non_comv; struct msm_vidc_allocations line; @@ -40,6 +41,7 @@ struct msm_vidc_mappings_info { struct msm_vidc_mappings input_meta; struct msm_vidc_mappings output_meta; struct msm_vidc_mappings bin; + struct msm_vidc_mappings arp; struct msm_vidc_mappings comv; struct msm_vidc_mappings non_comv; struct msm_vidc_mappings line; @@ -53,6 +55,7 @@ struct msm_vidc_buffers_info { struct msm_vidc_buffers input_meta; struct msm_vidc_buffers output_meta; struct msm_vidc_buffers bin; + struct msm_vidc_buffers arp; struct msm_vidc_buffers comv; struct msm_vidc_buffers non_comv; struct msm_vidc_buffers line; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 987cdb12b8..6022a67fb8 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -68,6 +68,10 @@ (V4L2_CTRL_ID2WHICH(idx) == V4L2_CTRL_CLASS_MPEG) && \ V4L2_CTRL_DRIVER_PRIV(idx)) +#define BUFFER_ALIGNMENT_SIZE(x) x +#define NUM_MBS_720P (((1280 + 15) >> 4) * ((720 + 15) >> 4)) +#define NUM_MBS_4k (((4096 + 15) >> 4) * ((2304 + 15) >> 4)) + /* * Convert Q16 number into Integer and Fractional part upto 2 places. * Ex : 105752 / 65536 = 1.61; 1.61 in Q16 = 105752; @@ -110,6 +114,7 @@ enum msm_vidc_buffer_type { MSM_VIDC_BUF_OUTPUT_META, MSM_VIDC_BUF_QUEUE, MSM_VIDC_BUF_BIN, + MSM_VIDC_BUF_ARP, MSM_VIDC_BUF_COMV, MSM_VIDC_BUF_NON_COMV, MSM_VIDC_BUF_LINE, diff --git a/driver/vidc/src/hfi_packet.c b/driver/vidc/src/hfi_packet.c index 021d43759e..c20fbac758 100644 --- a/driver/vidc/src/hfi_packet.c +++ b/driver/vidc/src/hfi_packet.c @@ -86,6 +86,7 @@ u32 get_hfi_port_from_buffer_type(struct msm_vidc_inst *inst, case MSM_VIDC_BUF_INPUT: case MSM_VIDC_BUF_INPUT_META: case MSM_VIDC_BUF_BIN: + case MSM_VIDC_BUF_ARP: case MSM_VIDC_BUF_COMV: case MSM_VIDC_BUF_NON_COMV: case MSM_VIDC_BUF_LINE: @@ -131,6 +132,8 @@ u32 get_hfi_buffer_type(enum msm_vidc_domain_type domain, return HFI_BUFFER_METADATA; case MSM_VIDC_BUF_BIN: return HFI_BUFFER_BIN; + case MSM_VIDC_BUF_ARP: + return HFI_BUFFER_ARP; case MSM_VIDC_BUF_COMV: return HFI_BUFFER_COMV; case MSM_VIDC_BUF_NON_COMV: diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index feb948f034..2d19b5b2ff 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -13,6 +13,47 @@ #include "msm_vidc_internal.h" #include "msm_vidc_platform.h" #include "msm_vidc_debug.h" +#include "venus_hfi.h" +#include "hfi_packet.h" + +u32 msm_venc_input_set_prop[] = { + HFI_PROP_COLOR_FORMAT, + HFI_PROP_ALIGN_RESOLUTION, + HFI_PROP_CROP_COORDINATE_TOP_LEFT, + HFI_PROP_CROP_RESOLUTION, +}; + +u32 msm_venc_output_set_prop[] = { + HFI_PROP_ALIGN_RESOLUTION, + HFI_PROP_CROP_COORDINATE_TOP_LEFT, + HFI_PROP_CROP_RESOLUTION, +}; + +u32 msm_venc_input_subscribe_for_properties[] = { + HFI_PROP_TAG_NOT_PROPAGATED_TO_OUTPUT, +}; + +u32 msm_venc_deliver_as_metadata[] = { + HFI_PROP_BUFFER_TAG, + HFI_PROP_SEI_MASTERING_DISPLAY_COLOUR, + HFI_PROP_SEI_CONTENT_LIGHT_LEVEL, + HFI_PROP_SEI_HDR10PLUS_USERDATA, + HFI_PROP_CVP_STAT_INFO, +}; + +u32 msm_venc_subscribe_for_metadata[] = { + HFI_PROP_BUFFER_TAG, + HFI_PROP_METADATA_SEQ_HEADER_NAL, + HFI_PROP_TIMESTAMP, + HFI_PROP_LTR_MARK_USE_DETAILS, + HFI_PROP_SUBFRAME_OUTPUT, + HFI_PROP_ENC_QP_METADATA, +}; + +u32 msm_venc_output_subscribe_for_properties[] = { + HFI_PROP_PICTURE_TYPE, + HFI_PROP_BUFFER_MARK, +}; static int msm_venc_codec_change(struct msm_vidc_inst *inst, u32 codec) { @@ -25,6 +66,617 @@ static int msm_venc_codec_change(struct msm_vidc_inst *inst, u32 codec) return rc; } +static int msm_venc_set_colorformat(struct msm_vidc_inst *inst, + enum msm_vidc_port_type port) +{ + int rc = 0; + u32 pixelformat; + enum msm_vidc_colorformat_type colorformat; + u32 hfi_colorformat; + + if (port != INPUT_PORT && port != OUTPUT_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_NV12_UBWC && + pixelformat != V4L2_PIX_FMT_NV12_TP10_UBWC) { + s_vpr_e(inst->sid, "%s: invalid pixelformat %#x\n", + __func__, pixelformat); + return -EINVAL; + } + colorformat = v4l2_colorformat_to_driver(pixelformat, __func__); + hfi_colorformat = get_hfi_colorformat(inst, colorformat); + rc = venus_hfi_session_property(inst, + HFI_PROP_COLOR_FORMAT, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, port), + HFI_PAYLOAD_U32_ENUM, + &hfi_colorformat, + sizeof(u32)); + if (rc) + return rc; + return 0; +} + +static int msm_venc_set_resolution(struct msm_vidc_inst *inst, + enum msm_vidc_port_type port) +{ + int rc = 0; + u32 resolution; + + if (port != INPUT_PORT && 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; + rc = venus_hfi_session_property(inst, + HFI_PROP_ALIGN_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_crop_top_left(struct msm_vidc_inst *inst, + enum msm_vidc_port_type port) +{ + int rc = 0; + u32 crop_top_left; + + if (port != INPUT_PORT && port != OUTPUT_PORT) { + s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port); + return -EINVAL; + } + + crop_top_left = 0; + rc = venus_hfi_session_property(inst, + HFI_PROP_CROP_COORDINATE_TOP_LEFT, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, port), + HFI_PAYLOAD_32_PACKED, + &crop_top_left, + sizeof(u32)); + if (rc) + return rc; + return 0; +} + +static int msm_venc_set_crop_resolution(struct msm_vidc_inst *inst, + enum msm_vidc_port_type port) +{ + int rc = 0; + u32 crop; + + if (port != INPUT_PORT && port != OUTPUT_PORT) { + s_vpr_e(inst->sid, "%s: invalid port %d\n", __func__, port); + return -EINVAL; + } + + /* output buffer resolution is nothing but crop */ + crop = inst->fmts[INPUT_PORT].fmt.pix_mp.width << 16 | + inst->fmts[INPUT_PORT].fmt.pix_mp.height; + rc = venus_hfi_session_property(inst, + HFI_PROP_CROP_RESOLUTION, + HFI_HOST_FLAGS_NONE, + get_hfi_port(inst, port), + HFI_PAYLOAD_32_PACKED, + &crop, + sizeof(u32)); + if (rc) + return rc; + return 0; +} + +static int msm_venc_set_stage(struct msm_vidc_inst *inst) +{ + int rc = 0; + struct msm_vidc_core *core = inst->core; + + rc = call_session_op(core, decide_work_mode, inst); + if (rc) { + s_vpr_e(inst->sid, "%s: decide_work_mode failed\n", + __func__); + return -EINVAL; + } + + rc = venus_hfi_session_property(inst, + HFI_PROP_STAGE, + HFI_HOST_FLAGS_NONE, + HFI_PORT_NONE, + HFI_PAYLOAD_U32, + &inst->stage, + sizeof(u32)); + if (rc) + return rc; + return 0; +} + +static int msm_venc_set_pipe(struct msm_vidc_inst *inst) +{ + int rc = 0; + struct msm_vidc_core *core = inst->core; + + rc = call_session_op(core, decide_work_route, inst); + if (rc) { + s_vpr_e(inst->sid, "%s: decide_work_route failed\n", + __func__); + return -EINVAL; + } + + rc = venus_hfi_session_property(inst, + HFI_PROP_PIPE, + HFI_HOST_FLAGS_NONE, + HFI_PORT_NONE, + HFI_PAYLOAD_U32, + &inst->pipe, + sizeof(u32)); + if (rc) + return rc; + return 0; +} + +static int msm_venc_set_input_properties(struct msm_vidc_inst *inst) +{ + int rc = 0; + int i = 0; + + d_vpr_h("%s()\n", __func__); + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(msm_venc_input_set_prop); + i++) { + switch (msm_venc_input_set_prop[i]) { + case HFI_PROP_COLOR_FORMAT: + rc = msm_venc_set_colorformat(inst, INPUT_PORT); + break; + case HFI_PROP_ALIGN_RESOLUTION: + rc = msm_venc_set_resolution(inst, INPUT_PORT); + break; + case HFI_PROP_CROP_COORDINATE_TOP_LEFT: + rc = msm_venc_set_crop_top_left(inst, INPUT_PORT); + break; + case HFI_PROP_CROP_RESOLUTION: + rc = msm_venc_set_crop_resolution(inst, INPUT_PORT); + break; + default: + d_vpr_e("%s: unknown property %#x\n", __func__, + msm_venc_input_set_prop[i]); + rc = -EINVAL; + break; + } + } + + return rc; +} + +static int msm_venc_set_output_properties(struct msm_vidc_inst *inst) +{ + int rc = 0; + int i = 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) + return rc; + + rc = msm_venc_set_pipe(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_ALIGN_RESOLUTION: + rc = msm_venc_set_resolution(inst, OUTPUT_PORT); + break; + case HFI_PROP_CROP_COORDINATE_TOP_LEFT: + rc = msm_venc_set_crop_top_left(inst, OUTPUT_PORT); + break; + case HFI_PROP_CROP_RESOLUTION: + rc = msm_venc_set_crop_resolution(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_get_input_internal_buffers(struct msm_vidc_inst *inst) +{ + int rc = 0; + struct msm_vidc_core *core; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + + inst->buffers.arp.size = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_ARP); + inst->buffers.bin.size = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_BIN); + /* inst->buffers.comv.size = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_COMV); + inst->buffers.non_comv.size = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_NON_COMV); */ + inst->buffers.line.size = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_LINE); + inst->buffers.dpb.size = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_DPB); + /* inst->buffers.persist.size = call_session_op(core, buffer_size, + inst, MSM_VIDC_BUF_PERSIST); */ + + inst->buffers.arp.min_count = call_session_op(core, min_count, + inst, MSM_VIDC_BUF_ARP); + inst->buffers.bin.min_count = call_session_op(core, min_count, + inst, MSM_VIDC_BUF_BIN); + /* inst->buffers.comv.min_count = call_session_op(core, min_count, + inst, MSM_VIDC_BUF_COMV); + inst->buffers.non_comv.min_count = call_session_op(core, min_count, + inst, MSM_VIDC_BUF_NON_COMV); */ + inst->buffers.line.min_count = call_session_op(core, min_count, + inst, MSM_VIDC_BUF_LINE); + inst->buffers.dpb.min_count = call_session_op(core, min_count, + inst, MSM_VIDC_BUF_DPB); + /* inst->buffers.persist.min_count = call_session_op(core, min_count, + inst, MSM_VIDC_BUF_PERSIST); */ + + s_vpr_h(inst->sid, "internal buffer: min size\n"); + s_vpr_h(inst->sid, "arp buffer: %d %d\n", + inst->buffers.arp.min_count, + inst->buffers.arp.size); + s_vpr_h(inst->sid, "bin buffer: %d %d\n", + inst->buffers.bin.min_count, + inst->buffers.bin.size); + /* s_vpr_h(inst->sid, "comv buffer: %d %d\n", + inst->buffers.comv.min_count, + inst->buffers.comv.size); + s_vpr_h(inst->sid, "non_comv buffer: %d %d\n", + inst->buffers.non_comv.min_count, + inst->buffers.non_comv.size); */ + s_vpr_h(inst->sid, "line buffer: %d %d\n", + inst->buffers.line.min_count, + inst->buffers.line.size); + s_vpr_h(inst->sid, "dpb buffer: %d %d\n", + inst->buffers.dpb.min_count, + inst->buffers.dpb.size); + /* s_vpr_h(inst->sid, "persist buffer: %d %d\n", + inst->buffers.persist.min_count, + inst->buffers.persist.size); */ + + return rc; +} + +static int msm_venc_create_input_internal_buffers(struct msm_vidc_inst *inst) +{ + int rc = 0; + + d_vpr_h("%s()\n", __func__); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_ARP); + if (rc) + return rc; + rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_BIN); + if (rc) + return rc; + /* rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_COMV); + if (rc) + return rc; + rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV); + if (rc) + return rc; */ + rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_LINE); + if (rc) + return rc; + rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_DPB); + if (rc) + return rc; + /* rc = msm_vidc_create_internal_buffers(inst, MSM_VIDC_BUF_PERSIST); + if (rc) + return rc; */ + + return 0; +} + +static int msm_venc_queue_input_internal_buffers(struct msm_vidc_inst *inst) +{ + int rc = 0; + + d_vpr_h("%s()\n", __func__); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_ARP); + if (rc) + return rc; + rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_BIN); + if (rc) + return rc; + /* rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_COMV); + if (rc) + return rc; + rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV); + if (rc) + return rc; */ + rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_LINE); + if (rc) + return rc; + rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_DPB); + if (rc) + return rc; + // TODO: fw is not accepting persist buffer and returning session error. + //rc = msm_vidc_queue_internal_buffers(inst, MSM_VIDC_BUF_PERSIST); + if (rc) + return rc; + + return 0; +} + +static int msm_venc_property_subscription(struct msm_vidc_inst *inst, + enum msm_vidc_port_type port) +{ + int rc = 0; + struct msm_vidc_core *core; + u32 payload[32] = {0}; + u32 i; + u32 payload_size = 0; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + d_vpr_h("%s()\n", __func__); + + payload[0] = HFI_MODE_PROPERTY; + if (port == INPUT_PORT) { + for (i = 0; i < ARRAY_SIZE(msm_venc_input_subscribe_for_properties); i++) + payload[i + 1] = msm_venc_input_subscribe_for_properties[i]; + payload_size = (ARRAY_SIZE(msm_venc_input_subscribe_for_properties) + 1) * + sizeof(u32); + } else if (port == OUTPUT_PORT) { + for (i = 0; i < ARRAY_SIZE(msm_venc_output_subscribe_for_properties); i++) + payload[i + 1] = msm_venc_output_subscribe_for_properties[i]; + payload_size = (ARRAY_SIZE(msm_venc_output_subscribe_for_properties) + 1) * + sizeof(u32); + } else { + s_vpr_e(inst->sid, "%s: invalid port: %d\n", __func__, port); + return -EINVAL; + } + + rc = venus_hfi_session_command(inst, + HFI_CMD_SUBSCRIBE_MODE, + port, + HFI_PAYLOAD_U32_ARRAY, + &payload[0], + payload_size); + + return rc; +} + +static int msm_venc_metadata_delivery(struct msm_vidc_inst *inst, + enum msm_vidc_port_type port) +{ + int rc = 0; + struct msm_vidc_core *core; + u32 payload[32] = {0}; + u32 i; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + d_vpr_h("%s()\n", __func__); + + payload[0] = HFI_MODE_METADATA; + for (i = 0; i < ARRAY_SIZE(msm_venc_deliver_as_metadata); i++) + payload[i + 1] = msm_venc_deliver_as_metadata[i]; + + rc = venus_hfi_session_command(inst, + HFI_CMD_DELIVERY_MODE, + port, + HFI_PAYLOAD_U32_ARRAY, + &payload[0], + (ARRAY_SIZE(msm_venc_deliver_as_metadata) + 1) * + sizeof(u32)); + + return rc; +} + +static int msm_venc_metadata_subscription(struct msm_vidc_inst *inst, + enum msm_vidc_port_type port) +{ + int rc = 0; + struct msm_vidc_core *core; + u32 payload[32] = {0}; + u32 i; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + d_vpr_h("%s()\n", __func__); + + payload[0] = HFI_MODE_METADATA; + for (i = 0; i < ARRAY_SIZE(msm_venc_subscribe_for_metadata); i++) + payload[i + 1] = msm_venc_subscribe_for_metadata[i]; + + rc = venus_hfi_session_command(inst, + HFI_CMD_SUBSCRIBE_MODE, + port, + HFI_PAYLOAD_U32_ARRAY, + &payload[0], + (ARRAY_SIZE(msm_venc_subscribe_for_metadata) + 1) * + sizeof(u32)); + + return rc; +} + +int msm_venc_stop_input(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + rc = msm_vidc_session_stop(inst, INPUT_PORT); + if (rc) + return rc; + + return 0; +} + +int msm_venc_start_input(struct msm_vidc_inst *inst) +{ + int rc = 0; + struct msm_vidc_core *core; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + core = inst->core; + s_vpr_h(inst->sid, "%s()\n", __func__); + + //rc = msm_vidc_check_session_supported(inst); + if (rc) + goto error; + //rc = msm_vidc_check_scaling_supported(inst); + if (rc) + goto error; + + rc = msm_venc_set_input_properties(inst); + if (rc) + goto error; + + /* Decide bse vpp delay after work mode */ + //msm_vidc_set_bse_vpp_delay(inst); + + rc = msm_venc_get_input_internal_buffers(inst); + if (rc) + goto error; + /* check for memory after all buffers calculation */ + //rc = msm_vidc_check_memory_supported(inst); + if (rc) + goto error; + + //msm_vidc_update_dcvs(inst); + //msm_vidc_update_batching(inst); + //msm_vidc_scale_power(inst); + + rc = msm_venc_create_input_internal_buffers(inst); + rc = 0; // TODO + if (rc) + goto error; + rc = msm_venc_queue_input_internal_buffers(inst); + rc = 0; // TODO + if (rc) + goto error; + + rc = msm_venc_property_subscription(inst, INPUT_PORT); + if (rc) + return rc; + + rc = msm_venc_metadata_delivery(inst, INPUT_PORT); + if (rc) + return rc; + + rc = venus_hfi_start(inst, INPUT_PORT); + if (rc) + goto error; + + s_vpr_h(inst->sid, "%s: done\n", __func__); + return 0; + +error: + s_vpr_e(inst->sid, "%s: failed\n", __func__); + msm_venc_stop_input(inst); + return rc; +} + +int msm_venc_stop_output(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + rc = msm_vidc_session_stop(inst, OUTPUT_PORT); + if (rc) + return rc; + + return 0; +} + +int msm_venc_start_output(struct msm_vidc_inst *inst) +{ + int rc = 0; + + d_vpr_h("%s()\n", __func__); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + rc = msm_venc_set_output_properties(inst); + if (rc) + goto error; + + rc = msm_venc_property_subscription(inst, OUTPUT_PORT); + if (rc) + return rc; + + rc = msm_venc_metadata_subscription(inst, OUTPUT_PORT); + if (rc) + return rc; + + rc = venus_hfi_start(inst, OUTPUT_PORT); + if (rc) + goto error; + + d_vpr_h("%s: done\n", __func__); + return 0; + +error: + msm_venc_stop_output(inst); + return rc; +} + int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) { int rc = 0; diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index d45151234e..84d8e84725 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -760,12 +760,14 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->buffers.output.list); INIT_LIST_HEAD(&inst->buffers.output_meta.list); INIT_LIST_HEAD(&inst->buffers.bin.list); + INIT_LIST_HEAD(&inst->buffers.arp.list); INIT_LIST_HEAD(&inst->buffers.comv.list); INIT_LIST_HEAD(&inst->buffers.non_comv.list); INIT_LIST_HEAD(&inst->buffers.line.list); INIT_LIST_HEAD(&inst->buffers.dpb.list); INIT_LIST_HEAD(&inst->buffers.persist.list); INIT_LIST_HEAD(&inst->allocations.bin.list); + INIT_LIST_HEAD(&inst->allocations.arp.list); INIT_LIST_HEAD(&inst->allocations.comv.list); INIT_LIST_HEAD(&inst->allocations.non_comv.list); INIT_LIST_HEAD(&inst->allocations.line.list); @@ -776,6 +778,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->mappings.output.list); INIT_LIST_HEAD(&inst->mappings.output_meta.list); INIT_LIST_HEAD(&inst->mappings.bin.list); + INIT_LIST_HEAD(&inst->mappings.arp.list); INIT_LIST_HEAD(&inst->mappings.comv.list); INIT_LIST_HEAD(&inst->mappings.non_comv.list); INIT_LIST_HEAD(&inst->mappings.line.list); diff --git a/driver/vidc/src/msm_vidc_buffer.c b/driver/vidc/src/msm_vidc_buffer.c index 5332c7aa06..fc3d7f0858 100644 --- a/driver/vidc/src/msm_vidc_buffer.c +++ b/driver/vidc/src/msm_vidc_buffer.c @@ -9,6 +9,7 @@ #include "msm_vidc_core.h" #include "msm_vidc_driver.h" #include "msm_vidc_debug.h" +#include "msm_vidc_internal.h" #define MIN_INPUT_BUFFERS 4 #define MIN_ENC_OUTPUT_BUFFERS 4 @@ -182,9 +183,47 @@ u32 msm_vidc_encoder_input_size(struct msm_vidc_inst *inst) u32 msm_vidc_encoder_output_size(struct msm_vidc_inst *inst) { - u32 size = ALIGN(15 * 1024 * 1024, SZ_4K); - size = 4; // TODO - return size; + u32 frame_size; + u32 mbs_per_frame; + u32 width, height; + struct v4l2_format *f; + + f = &inst->fmts[OUTPUT_PORT]; + /* + * Encoder output size calculation: 32 Align width/height + * For resolution < 720p : YUVsize * 4 + * For resolution > 720p & <= 4K : YUVsize / 2 + * For resolution > 4k : YUVsize / 4 + * Initially frame_size = YUVsize * 2; + */ + + /* if (is_grid_session(inst)) { + f->fmt.pix_mp.width = f->fmt.pix_mp.height = HEIC_GRID_DIMENSION; + } */ + width = ALIGN(f->fmt.pix_mp.width, BUFFER_ALIGNMENT_SIZE(32)); + height = ALIGN(f->fmt.pix_mp.height, BUFFER_ALIGNMENT_SIZE(32)); + mbs_per_frame = NUM_MBS_PER_FRAME(width, height); + frame_size = (width * height * 3); + + if (mbs_per_frame < NUM_MBS_720P) + frame_size = frame_size << 1; + else if (mbs_per_frame <= NUM_MBS_4k) + frame_size = frame_size >> 2; + else + frame_size = frame_size >> 3; + + /*if ((inst->rc_type == RATE_CONTROL_OFF) || + (inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)) + frame_size = frame_size << 1; + + if (inst->rc_type == RATE_CONTROL_LOSSLESS) + frame_size = (width * height * 9) >> 2; */ + + /* multiply by 10/8 (1.25) to get size for 10 bit case */ + if (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_HEVC) + frame_size = frame_size + (frame_size >> 2); + + return ALIGN(frame_size, SZ_4K); } u32 msm_vidc_encoder_input_meta_size(struct msm_vidc_inst *inst) diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 6c4e9f8c75..e873c6ad92 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -308,6 +308,8 @@ u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst, region = MSM_VIDC_SECURE_PIXEL; break; case MSM_VIDC_BUF_PERSIST: + // TODO: Need to revisit for ARP + case MSM_VIDC_BUF_ARP: region = MSM_VIDC_SECURE_NONPIXEL; break; default: @@ -332,6 +334,8 @@ struct msm_vidc_buffers *msm_vidc_get_buffers( return &inst->buffers.output_meta; case MSM_VIDC_BUF_BIN: return &inst->buffers.bin; + case MSM_VIDC_BUF_ARP: + return &inst->buffers.arp; case MSM_VIDC_BUF_COMV: return &inst->buffers.comv; case MSM_VIDC_BUF_NON_COMV: @@ -364,6 +368,8 @@ struct msm_vidc_mappings *msm_vidc_get_mappings( return &inst->mappings.output_meta; case MSM_VIDC_BUF_BIN: return &inst->mappings.bin; + case MSM_VIDC_BUF_ARP: + return &inst->mappings.arp; case MSM_VIDC_BUF_COMV: return &inst->mappings.comv; case MSM_VIDC_BUF_NON_COMV: @@ -388,6 +394,8 @@ struct msm_vidc_allocations *msm_vidc_get_allocations( switch (buffer_type) { case MSM_VIDC_BUF_BIN: return &inst->allocations.bin; + case MSM_VIDC_BUF_ARP: + return &inst->allocations.arp; case MSM_VIDC_BUF_COMV: return &inst->allocations.comv; case MSM_VIDC_BUF_NON_COMV: diff --git a/driver/vidc/src/msm_vidc_vb2.c b/driver/vidc/src/msm_vidc_vb2.c index d746d570cb..9f96d7bc59 100644 --- a/driver/vidc/src/msm_vidc_vb2.c +++ b/driver/vidc/src/msm_vidc_vb2.c @@ -171,19 +171,26 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count) if (q->type == INPUT_MPLANE) { if (is_decode_session(inst)) rc = msm_vdec_start_input(inst); - //else if (is_encode_session(inst)) - // rc = msm_venc_start_input(inst); + else if (is_encode_session(inst)) + rc = msm_venc_start_input(inst); + else + goto error; } else if (q->type == OUTPUT_MPLANE) { if (is_decode_session(inst)) rc = msm_vdec_start_output(inst); - //else if (is_encode_session(inst)) - // rc = msm_venc_start_output(inst); + else if (is_encode_session(inst)) + rc = msm_venc_start_output(inst); + else + goto error; } else { - s_vpr_e(inst->sid, "%s: invalid type %d\n", __func__, q->type); - rc = -EINVAL; + goto error; } return rc; + +error: + s_vpr_e(inst->sid, "%s: invalid session/qtype, qtype %d\n", __func__, q->type); + return -EINVAL; } void msm_vidc_stop_streaming(struct vb2_queue *q) @@ -215,21 +222,29 @@ void msm_vidc_stop_streaming(struct vb2_queue *q) if (q->type == INPUT_MPLANE) { if (is_decode_session(inst)) rc = msm_vdec_stop_input(inst); - //else if (is_encode_session(inst)) - // rc = msm_venc_start_input(inst); + else if (is_encode_session(inst)) + rc = msm_venc_stop_input(inst); + else + goto error; } else if (q->type == OUTPUT_MPLANE) { if (is_decode_session(inst)) rc = msm_vdec_stop_output(inst); - //else if (is_encode_session(inst)) - // rc = msm_venc_start_output(inst); + else if (is_encode_session(inst)) + rc = msm_venc_stop_output(inst); + else + goto error; } else { - s_vpr_e(inst->sid, "%s: invalid type %d\n", __func__, q->type); + goto error; } if (rc) s_vpr_e(inst->sid, "%s: stop failed for qtype: %d\n", __func__, q->type); + return; +error: + s_vpr_e(inst->sid, "%s: invalid session/qtype, qtype: %d\n", + __func__, q->type); return; } diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index b31bbd7a29..6b7096c8b3 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -36,6 +36,7 @@ bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst, buffer_type != HFI_BUFFER_RAW && buffer_type != HFI_BUFFER_METADATA && buffer_type != HFI_BUFFER_BIN && + buffer_type != HFI_BUFFER_ARP && buffer_type != HFI_BUFFER_COMV && buffer_type != HFI_BUFFER_NON_COMV && buffer_type != HFI_BUFFER_LINE &&