diff --git a/msm/vidc/msm_smem.c b/msm/vidc/msm_smem.c index 40871b70ff77..4d326ab0bea5 100644 --- a/msm/vidc/msm_smem.c +++ b/msm/vidc/msm_smem.c @@ -9,7 +9,6 @@ #include "msm_vidc_debug.h" #include "msm_vidc_resources.h" - static int msm_dma_get_device_address(struct dma_buf *dbuf, unsigned long align, dma_addr_t *iova, unsigned long *buffer_size, unsigned long flags, enum hal_buffer buffer_type, @@ -599,3 +598,73 @@ struct context_bank_info *msm_smem_get_context_bank(u32 session_type, return match; } +int msm_smem_memory_prefetch(struct msm_vidc_inst *inst) +{ + int i, rc = 0; + struct memory_regions *vidc_regions = NULL; + struct ion_prefetch_region ion_region[MEMORY_REGIONS_MAX]; + + if (!inst) { + d_vpr_e("%s: invalid parameters\n", __func__); + return -EINVAL; + } + + vidc_regions = &inst->regions; + if (vidc_regions->num_regions > MEMORY_REGIONS_MAX) { + s_vpr_e(inst->sid, "%s: invalid num_regions %d, max %d\n", + __func__, vidc_regions->num_regions, + MEMORY_REGIONS_MAX); + return -EINVAL; + } + + memset(ion_region, 0, sizeof(ion_region)); + for (i = 0; i < vidc_regions->num_regions; i++) { + ion_region[i].size = vidc_regions->region[i].size; + ion_region[i].vmid = vidc_regions->region[i].vmid; + } + + rc = msm_ion_heap_prefetch(ION_SECURE_HEAP_ID, ion_region, + vidc_regions->num_regions); + if (rc) + s_vpr_e(inst->sid, "%s: prefetch failed, ret: %d\n", + __func__, rc); + else + s_vpr_l(inst->sid, "%s: prefetch succeeded\n", __func__); + + return rc; +} + +int msm_smem_memory_drain(struct msm_vidc_inst *inst) +{ + int i, rc = 0; + struct memory_regions *vidc_regions = NULL; + struct ion_prefetch_region ion_region[MEMORY_REGIONS_MAX]; + + if (!inst) { + d_vpr_e("%s: invalid parameters\n", __func__); + return -EINVAL; + } + + vidc_regions = &inst->regions; + if (vidc_regions->num_regions > MEMORY_REGIONS_MAX) { + s_vpr_e(inst->sid, "%s: invalid num_regions %d, max %d\n", + __func__, vidc_regions->num_regions, + MEMORY_REGIONS_MAX); + return -EINVAL; + } + + memset(ion_region, 0, sizeof(ion_region)); + for (i = 0; i < vidc_regions->num_regions; i++) { + ion_region[i].size = vidc_regions->region[i].size; + ion_region[i].vmid = vidc_regions->region[i].vmid; + } + + rc = msm_ion_heap_drain(ION_SECURE_HEAP_ID, ion_region, + vidc_regions->num_regions); + if (rc) + s_vpr_e(inst->sid, "%s: drain failed, ret: %d\n", __func__, rc); + else + s_vpr_l(inst->sid, "%s: drain succeeded\n", __func__); + + return rc; +} diff --git a/msm/vidc/msm_vdec.c b/msm/vidc/msm_vdec.c index c535e3fe1347..37071bf5b1a8 100644 --- a/msm/vidc/msm_vdec.c +++ b/msm/vidc/msm_vdec.c @@ -883,6 +883,7 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) __func__); return -ENOTSUPP; } + msm_comm_memory_prefetch(inst); break; case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA: if (ctrl->val == EXTRADATA_NONE) diff --git a/msm/vidc/msm_vidc.c b/msm/vidc/msm_vidc.c index 0dc329929e9d..60fadec7452d 100644 --- a/msm/vidc/msm_vidc.c +++ b/msm/vidc/msm_vidc.c @@ -1415,6 +1415,8 @@ static const struct v4l2_ctrl_ops msm_vidc_ctrl_ops = { static struct msm_vidc_inst_smem_ops msm_vidc_smem_ops = { .smem_map_dma_buf = msm_smem_map_dma_buf, .smem_unmap_dma_buf = msm_smem_unmap_dma_buf, + .smem_prefetch = msm_smem_memory_prefetch, + .smem_drain = msm_smem_memory_drain, }; void *msm_vidc_open(int core_id, int session_type) @@ -1756,6 +1758,7 @@ int msm_vidc_close(void *instance) } msm_comm_session_clean(inst); + msm_comm_memory_drain(inst); kref_put(&inst->kref, close_helper); return 0; diff --git a/msm/vidc/msm_vidc.h b/msm/vidc/msm_vidc.h index d4d50a74f8fa..92bd06426747 100644 --- a/msm/vidc/msm_vidc.h +++ b/msm/vidc/msm_vidc.h @@ -13,6 +13,7 @@ #define HAL_BUFFER_MAX 0xe #define CVP_FRAME_RATE_MAX (60) +#define MEMORY_REGIONS_MAX 30 enum smem_type { SMEM_DMA = 1, @@ -75,6 +76,19 @@ enum smem_cache_ops { SMEM_CACHE_CLEAN_INVALIDATE, }; +struct memory_regions { + u32 num_regions; + struct { + u64 size; + u32 vmid; + } region[MEMORY_REGIONS_MAX]; +}; + +enum memory_ops { + MEMORY_PREFETCH = 1, + MEMORY_DRAIN, +}; + enum core_id { MSM_VIDC_CORE_VENUS = 0, MSM_VIDC_CORE_Q6, diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index e2be7fa36a57..7cb8a1ef7792 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -7351,3 +7351,94 @@ int msm_comm_fetch_framerate(struct msm_vidc_inst *inst, } return rc; } + +static int msm_comm_memory_regions_prepare(struct msm_vidc_inst *inst) +{ + u32 i = 0; + struct msm_vidc_platform_resources *res; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid parameters\n", __func__); + return -EINVAL; + } + res = &inst->core->resources; + + inst->regions.num_regions = res->prefetch_non_pix_buf_count + + res->prefetch_pix_buf_count; + if (inst->regions.num_regions > MEMORY_REGIONS_MAX) { + s_vpr_e(inst->sid, "%s: invalid num_regions: %d, max: %d\n", + __func__, inst->regions.num_regions, + MEMORY_REGIONS_MAX); + return -EINVAL; + } + + s_vpr_h(inst->sid, + "%s: preparing %d nonpixel memory regions of %ld bytes each and %d pixel memory regions of %ld bytes each\n", + __func__, res->prefetch_non_pix_buf_count, + res->prefetch_non_pix_buf_size, res->prefetch_pix_buf_count, + res->prefetch_pix_buf_size); + + for (i = 0; i < res->prefetch_non_pix_buf_count; i++) { + inst->regions.region[i].size = res->prefetch_non_pix_buf_size; + inst->regions.region[i].vmid = ION_FLAG_CP_NON_PIXEL; + } + + for (i = res->prefetch_non_pix_buf_count; + i < inst->regions.num_regions; i++) { + inst->regions.region[i].size = res->prefetch_pix_buf_size; + inst->regions.region[i].vmid = ION_FLAG_CP_PIXEL; + } + + return 0; +} + +int msm_comm_memory_prefetch(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst || !inst->smem_ops) { + d_vpr_e("%s: invalid parameters\n", __func__); + return -EINVAL; + } + + if (inst->memory_ops & MEMORY_PREFETCH) { + s_vpr_h(inst->sid, "%s: prefetch done already\n", __func__); + return 0; + } + + rc = msm_comm_memory_regions_prepare(inst); + if (rc) + return rc; + + if (inst->regions.num_regions == 0) + return 0; + + rc = inst->smem_ops->smem_prefetch(inst); + if (rc) + return rc; + + inst->memory_ops |= MEMORY_PREFETCH; + + return rc; +} + +int msm_comm_memory_drain(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst || !inst->smem_ops) { + d_vpr_e("%s: invalid parameters\n", __func__); + return -EINVAL; + } + + if (!(inst->memory_ops & MEMORY_PREFETCH)) + return 0; + + rc = inst->smem_ops->smem_drain(inst); + if (rc) + return rc; + + inst->memory_ops &= ~MEMORY_PREFETCH; + + return rc; +} diff --git a/msm/vidc/msm_vidc_common.h b/msm/vidc/msm_vidc_common.h index 49e666b98ca6..234d0c58be95 100644 --- a/msm/vidc/msm_vidc_common.h +++ b/msm/vidc/msm_vidc_common.h @@ -339,4 +339,6 @@ void msm_comm_release_timestamps(struct msm_vidc_inst *inst); u32 msm_comm_get_max_framerate(struct msm_vidc_inst *inst); u32 msm_comm_calc_framerate(struct msm_vidc_inst *inst, u64 timestamp_us, u64 prev_ts); +int msm_comm_memory_prefetch(struct msm_vidc_inst *inst); +int msm_comm_memory_drain(struct msm_vidc_inst *inst); #endif diff --git a/msm/vidc/msm_vidc_internal.h b/msm/vidc/msm_vidc_internal.h index cd2e27e156b7..1ecea42a6521 100644 --- a/msm/vidc/msm_vidc_internal.h +++ b/msm/vidc/msm_vidc_internal.h @@ -485,6 +485,8 @@ struct msm_vidc_inst_smem_ops { struct msm_smem *smem); int (*smem_unmap_dma_buf)(struct msm_vidc_inst *inst, struct msm_smem *smem); + int (*smem_prefetch)(struct msm_vidc_inst *inst); + int (*smem_drain)(struct msm_vidc_inst *inst); }; struct msm_vidc_inst { @@ -552,6 +554,8 @@ struct msm_vidc_inst { struct batch_mode batch; struct delayed_work batch_work; struct msm_vidc_inst_smem_ops *smem_ops; + enum memory_ops memory_ops; + struct memory_regions regions; int (*buffer_size_calculators)(struct msm_vidc_inst *inst); bool all_intra; bool is_perf_eligible_session; @@ -612,6 +616,8 @@ void msm_smem_put_dma_buf(void *dma_buf, u32 sid); int msm_smem_cache_operations(struct dma_buf *dbuf, enum smem_cache_ops cache_op, unsigned long offset, unsigned long size, u32 sid); +int msm_smem_memory_prefetch(struct msm_vidc_inst *inst); +int msm_smem_memory_drain(struct msm_vidc_inst *inst); void msm_vidc_fw_unload_handler(struct work_struct *work); void msm_vidc_ssr_handler(struct work_struct *work); /* diff --git a/msm/vidc/msm_vidc_platform.c b/msm/vidc/msm_vidc_platform.c index 244be41ac700..fea44112ab6f 100644 --- a/msm/vidc/msm_vidc_platform.c +++ b/msm/vidc/msm_vidc_platform.c @@ -431,6 +431,33 @@ static struct msm_vidc_common_data lahaina_common_data[] = { .key = "qcom,avsync-window-size", .value = 40, }, + { + .key = "qcom,prefetch_non_pix_buf_count", + .value = 1, + }, + { + .key = "qcom,prefetch_non_pix_buf_size", + /* + * Internal buffer size is calculated for secure decode session + * of resolution 4k (4096x2160) + * Internal buf size = calculate_scratch_size() + + * calculate_scratch1_size() + calculate_persist1_size() + * Take maximum between VP9 10bit, HEVC 10bit, AVC, MPEG2 secure + * decoder sessions + */ + .value = 209715200, + }, + { + .key = "qcom,prefetch_pix_buf_count", + .value = 18, + }, + { + .key = "qcom,prefetch_pix_buf_size", + /* + * Calculated by VENUS_BUFFER_SIZE for 4096x2160 UBWC + */ + .value = 13434880, + }, }; static struct msm_vidc_common_data bengal_common_data_v0[] = { diff --git a/msm/vidc/msm_vidc_res_parse.c b/msm/vidc/msm_vidc_res_parse.c index 95cf123ac8b1..809597fa4324 100644 --- a/msm/vidc/msm_vidc_res_parse.c +++ b/msm/vidc/msm_vidc_res_parse.c @@ -775,6 +775,15 @@ int read_platform_resources_from_drv_data( res->max_secure_inst_count = find_key_value(platform_data, "qcom,max-secure-instances"); + res->prefetch_pix_buf_count = find_key_value(platform_data, + "qcom,prefetch_pix_buf_count"); + res->prefetch_pix_buf_size = find_key_value(platform_data, + "qcom,prefetch_pix_buf_size"); + res->prefetch_non_pix_buf_count = find_key_value(platform_data, + "qcom,prefetch_non_pix_buf_count"); + res->prefetch_non_pix_buf_size = find_key_value(platform_data, + "qcom,prefetch_non_pix_buf_size"); + res->slave_side_cp = find_key_value(platform_data, "qcom,slave-side-cp"); res->thermal_mitigable = find_key_value(platform_data, diff --git a/msm/vidc/msm_vidc_resources.h b/msm/vidc/msm_vidc_resources.h index aa2fb29f16ce..9d296e33d63d 100644 --- a/msm/vidc/msm_vidc_resources.h +++ b/msm/vidc/msm_vidc_resources.h @@ -168,6 +168,10 @@ struct msm_vidc_platform_resources { uint32_t pm_qos_latency_us; uint32_t max_inst_count; uint32_t max_secure_inst_count; + uint32_t prefetch_pix_buf_count; + uint32_t prefetch_pix_buf_size; + uint32_t prefetch_non_pix_buf_count; + uint32_t prefetch_non_pix_buf_size; int msm_vidc_hw_rsp_timeout; int msm_vidc_firmware_unload_delay; uint32_t msm_vidc_pwr_collapse_delay;