Loading Documentation/devicetree/bindings/media/video/msm-vidc.txt +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ Required properties: - compatible : one of: - "qcom,msm-vidc" - "qcom,sm8150-vidc" : Invokes driver specific data for SM8150. - "qcom,sm6150-vidc" : Invokes driver specific data for SM6150. - "qcom,sdm845-vidc" : Invokes driver specific data for SDM845. - "qcom,sdm670-vidc" : Invokes driver specific data for SDM670. Loading drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +2 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include "venus_boot.h" #include "vidc_hfi_api.h" #include "msm_v4l2_private.h" #include "msm_vidc_clocks.h" #define BASE_DEVICE_NUMBER 32 Loading Loading @@ -369,6 +370,7 @@ static int msm_vidc_initialize_core(struct platform_device *pdev, dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__); mutex_unlock(&core->lock); msm_vidc_init_core_clk_ops(core); return rc; } Loading drivers/media/platform/msm/vidc/msm_vidc.c +2 −2 Original line number Diff line number Diff line Loading @@ -1001,7 +1001,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) } /* Decide work route for current session */ rc = msm_vidc_decide_work_route(inst); rc = call_core_op(inst->core, decide_work_route, inst); if (rc) { dprintk(VIDC_ERR, "Failed to decide work route for session %pK\n", inst); Loading @@ -1009,7 +1009,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) } /* Decide work mode for current session */ rc = msm_vidc_decide_work_mode(inst); rc = call_core_op(inst->core, decide_work_mode, inst); if (rc) { dprintk(VIDC_ERR, "Failed to decide work mode for session %pK\n", inst); Loading drivers/media/platform/msm/vidc/msm_vidc_clocks.c +164 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,24 @@ #define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 16) #define MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO (5 << 16) static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst, u32 filled_len); static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst); static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst, u32 filled_len); struct msm_vidc_core_ops core_ops_vpu4 = { .calc_freq = msm_vidc_calc_freq_ar50, .decide_work_route = NULL, .decide_work_mode = msm_vidc_decide_work_mode_ar50, }; struct msm_vidc_core_ops core_ops_vpu5 = { .calc_freq = msm_vidc_calc_freq, .decide_work_route = msm_vidc_decide_work_route, .decide_work_mode = msm_vidc_decide_work_mode, }; static inline void msm_dcvs_print_dcvs_stats(struct clock_data *dcvs) { dprintk(VIDC_PROF, Loading Loading @@ -576,8 +594,77 @@ void msm_comm_update_input_cr(struct msm_vidc_inst *inst, mutex_unlock(&inst->input_crs.lock); } static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst, u32 filled_len) { unsigned long freq = 0; unsigned long vpp_cycles = 0, vsp_cycles = 0; u32 vpp_cycles_per_mb; u32 mbs_per_second; struct msm_vidc_core *core = NULL; int i = 0; struct allowed_clock_rates_table *allowed_clks_tbl = NULL; u64 rate = 0; struct clock_data *dcvs = NULL; core = inst->core; dcvs = &inst->clk_data; mbs_per_second = msm_comm_get_inst_load_per_core(inst, LOAD_CALC_NO_QUIRKS); /* * Calculate vpp, vsp cycles separately for encoder and decoder. * Even though, most part is common now, in future it may change * between them. */ if (inst->session_type == MSM_VIDC_ENCODER) { vpp_cycles_per_mb = inst->flags & VIDC_LOW_POWER ? inst->clk_data.entry->low_power_cycles : inst->clk_data.entry->vpp_cycles; vpp_cycles = mbs_per_second * vpp_cycles_per_mb; vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles; /* 10 / 7 is overhead factor */ vsp_cycles += (inst->clk_data.bitrate * 10) / 7; } else if (inst->session_type == MSM_VIDC_DECODER) { vpp_cycles = mbs_per_second * inst->clk_data.entry->vpp_cycles; vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles; /* 10 / 7 is overhead factor */ vsp_cycles += ((inst->prop.fps * filled_len * 8) * 10) / 7; } else { dprintk(VIDC_ERR, "Unknown session type = %s\n", __func__); return msm_vidc_max_freq(inst->core); } freq = max(vpp_cycles, vsp_cycles); dprintk(VIDC_DBG, "Update DCVS Load\n"); allowed_clks_tbl = core->resources.allowed_clks_tbl; for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) { rate = allowed_clks_tbl[i].clock_rate; if (rate >= freq) break; } dcvs->load_norm = rate; dcvs->load_low = i < (core->resources.allowed_clks_tbl_size - 1) ? allowed_clks_tbl[i+1].clock_rate : dcvs->load_norm; dcvs->load_high = i > 0 ? allowed_clks_tbl[i-1].clock_rate : dcvs->load_norm; msm_dcvs_print_dcvs_stats(dcvs); dprintk(VIDC_PROF, "%s Inst %pK : Filled Len = %d Freq = %lu\n", __func__, inst, filled_len, freq); return freq; } static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst, u32 filled_len) Loading Loading @@ -829,7 +916,7 @@ int msm_comm_scale_clocks(struct msm_vidc_inst *inst) goto no_clock_change; } freq = msm_vidc_calc_freq(inst, filled_len); freq = call_core_op(inst->core, calc_freq, inst, filled_len); msm_vidc_update_freq_entry(inst, freq, device_addr, is_turbo); Loading Loading @@ -1097,6 +1184,71 @@ int msm_vidc_decide_work_route(struct msm_vidc_inst *inst) return rc; } static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct hal_video_work_mode pdata; struct hal_enable latency; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s Invalid args: Inst = %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; if (inst->clk_data.low_latency_mode) { pdata.video_work_mode = VIDC_WORK_MODE_1; goto decision_done; } if (inst->session_type == MSM_VIDC_DECODER) { pdata.video_work_mode = VIDC_WORK_MODE_2; switch (inst->fmts[OUTPUT_PORT].fourcc) { case V4L2_PIX_FMT_MPEG2: pdata.video_work_mode = VIDC_WORK_MODE_1; break; case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_HEVC: if (inst->prop.height[OUTPUT_PORT] * inst->prop.width[OUTPUT_PORT] <= 1280 * 720) pdata.video_work_mode = VIDC_WORK_MODE_1; break; } } else if (inst->session_type == MSM_VIDC_ENCODER) pdata.video_work_mode = VIDC_WORK_MODE_1; else { return -EINVAL; } decision_done: inst->clk_data.work_mode = pdata.video_work_mode; rc = call_hfi_op(hdev, session_set_property, (void *)inst->session, HAL_PARAM_VIDEO_WORK_MODE, (void *)&pdata); if (rc) dprintk(VIDC_WARN, " Failed to configure Work Mode %pK\n", inst); /* For WORK_MODE_1, set Low Latency mode by default to HW. */ if (inst->session_type == MSM_VIDC_ENCODER && inst->clk_data.work_mode == VIDC_WORK_MODE_1) { latency.enable = 1; rc = call_hfi_op(hdev, session_set_property, (void *)inst->session, HAL_PARAM_VENC_LOW_LATENCY, (void *)&latency); } rc = msm_comm_scale_clocks_and_bus(inst); return rc; } int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst) { int rc = 0; Loading Loading @@ -1429,6 +1581,17 @@ int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst) return rc; } void msm_vidc_init_core_clk_ops(struct msm_vidc_core *core) { if (!core) return; if (core->platform_data->vpu_ver == VPU_VERSION_4) core->core_ops = &core_ops_vpu4; else core->core_ops = &core_ops_vpu5; } void msm_print_core_status(struct msm_vidc_core *core, u32 core_id) { struct msm_vidc_inst *inst = NULL; Loading drivers/media/platform/msm/vidc/msm_vidc_clocks.h +1 −0 Original line number Diff line number Diff line Loading @@ -44,4 +44,5 @@ void msm_comm_update_input_cr(struct msm_vidc_inst *inst, u32 index, u32 cr); void update_recon_stats(struct msm_vidc_inst *inst, struct recon_stats_type *recon_stats); void msm_vidc_init_core_clk_ops(struct msm_vidc_core *core); #endif Loading
Documentation/devicetree/bindings/media/video/msm-vidc.txt +1 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ Required properties: - compatible : one of: - "qcom,msm-vidc" - "qcom,sm8150-vidc" : Invokes driver specific data for SM8150. - "qcom,sm6150-vidc" : Invokes driver specific data for SM6150. - "qcom,sdm845-vidc" : Invokes driver specific data for SDM845. - "qcom,sdm670-vidc" : Invokes driver specific data for SDM670. Loading
drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +2 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include "venus_boot.h" #include "vidc_hfi_api.h" #include "msm_v4l2_private.h" #include "msm_vidc_clocks.h" #define BASE_DEVICE_NUMBER 32 Loading Loading @@ -369,6 +370,7 @@ static int msm_vidc_initialize_core(struct platform_device *pdev, dprintk(VIDC_ERR, "%s: failed to allocate memory\n", __func__); mutex_unlock(&core->lock); msm_vidc_init_core_clk_ops(core); return rc; } Loading
drivers/media/platform/msm/vidc/msm_vidc.c +2 −2 Original line number Diff line number Diff line Loading @@ -1001,7 +1001,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) } /* Decide work route for current session */ rc = msm_vidc_decide_work_route(inst); rc = call_core_op(inst->core, decide_work_route, inst); if (rc) { dprintk(VIDC_ERR, "Failed to decide work route for session %pK\n", inst); Loading @@ -1009,7 +1009,7 @@ static inline int start_streaming(struct msm_vidc_inst *inst) } /* Decide work mode for current session */ rc = msm_vidc_decide_work_mode(inst); rc = call_core_op(inst->core, decide_work_mode, inst); if (rc) { dprintk(VIDC_ERR, "Failed to decide work mode for session %pK\n", inst); Loading
drivers/media/platform/msm/vidc/msm_vidc_clocks.c +164 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,24 @@ #define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 16) #define MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO (5 << 16) static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst, u32 filled_len); static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst); static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst, u32 filled_len); struct msm_vidc_core_ops core_ops_vpu4 = { .calc_freq = msm_vidc_calc_freq_ar50, .decide_work_route = NULL, .decide_work_mode = msm_vidc_decide_work_mode_ar50, }; struct msm_vidc_core_ops core_ops_vpu5 = { .calc_freq = msm_vidc_calc_freq, .decide_work_route = msm_vidc_decide_work_route, .decide_work_mode = msm_vidc_decide_work_mode, }; static inline void msm_dcvs_print_dcvs_stats(struct clock_data *dcvs) { dprintk(VIDC_PROF, Loading Loading @@ -576,8 +594,77 @@ void msm_comm_update_input_cr(struct msm_vidc_inst *inst, mutex_unlock(&inst->input_crs.lock); } static unsigned long msm_vidc_calc_freq_ar50(struct msm_vidc_inst *inst, u32 filled_len) { unsigned long freq = 0; unsigned long vpp_cycles = 0, vsp_cycles = 0; u32 vpp_cycles_per_mb; u32 mbs_per_second; struct msm_vidc_core *core = NULL; int i = 0; struct allowed_clock_rates_table *allowed_clks_tbl = NULL; u64 rate = 0; struct clock_data *dcvs = NULL; core = inst->core; dcvs = &inst->clk_data; mbs_per_second = msm_comm_get_inst_load_per_core(inst, LOAD_CALC_NO_QUIRKS); /* * Calculate vpp, vsp cycles separately for encoder and decoder. * Even though, most part is common now, in future it may change * between them. */ if (inst->session_type == MSM_VIDC_ENCODER) { vpp_cycles_per_mb = inst->flags & VIDC_LOW_POWER ? inst->clk_data.entry->low_power_cycles : inst->clk_data.entry->vpp_cycles; vpp_cycles = mbs_per_second * vpp_cycles_per_mb; vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles; /* 10 / 7 is overhead factor */ vsp_cycles += (inst->clk_data.bitrate * 10) / 7; } else if (inst->session_type == MSM_VIDC_DECODER) { vpp_cycles = mbs_per_second * inst->clk_data.entry->vpp_cycles; vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles; /* 10 / 7 is overhead factor */ vsp_cycles += ((inst->prop.fps * filled_len * 8) * 10) / 7; } else { dprintk(VIDC_ERR, "Unknown session type = %s\n", __func__); return msm_vidc_max_freq(inst->core); } freq = max(vpp_cycles, vsp_cycles); dprintk(VIDC_DBG, "Update DCVS Load\n"); allowed_clks_tbl = core->resources.allowed_clks_tbl; for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) { rate = allowed_clks_tbl[i].clock_rate; if (rate >= freq) break; } dcvs->load_norm = rate; dcvs->load_low = i < (core->resources.allowed_clks_tbl_size - 1) ? allowed_clks_tbl[i+1].clock_rate : dcvs->load_norm; dcvs->load_high = i > 0 ? allowed_clks_tbl[i-1].clock_rate : dcvs->load_norm; msm_dcvs_print_dcvs_stats(dcvs); dprintk(VIDC_PROF, "%s Inst %pK : Filled Len = %d Freq = %lu\n", __func__, inst, filled_len, freq); return freq; } static unsigned long msm_vidc_calc_freq(struct msm_vidc_inst *inst, u32 filled_len) Loading Loading @@ -829,7 +916,7 @@ int msm_comm_scale_clocks(struct msm_vidc_inst *inst) goto no_clock_change; } freq = msm_vidc_calc_freq(inst, filled_len); freq = call_core_op(inst->core, calc_freq, inst, filled_len); msm_vidc_update_freq_entry(inst, freq, device_addr, is_turbo); Loading Loading @@ -1097,6 +1184,71 @@ int msm_vidc_decide_work_route(struct msm_vidc_inst *inst) return rc; } static int msm_vidc_decide_work_mode_ar50(struct msm_vidc_inst *inst) { int rc = 0; struct hfi_device *hdev; struct hal_video_work_mode pdata; struct hal_enable latency; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s Invalid args: Inst = %pK\n", __func__, inst); return -EINVAL; } hdev = inst->core->device; if (inst->clk_data.low_latency_mode) { pdata.video_work_mode = VIDC_WORK_MODE_1; goto decision_done; } if (inst->session_type == MSM_VIDC_DECODER) { pdata.video_work_mode = VIDC_WORK_MODE_2; switch (inst->fmts[OUTPUT_PORT].fourcc) { case V4L2_PIX_FMT_MPEG2: pdata.video_work_mode = VIDC_WORK_MODE_1; break; case V4L2_PIX_FMT_H264: case V4L2_PIX_FMT_HEVC: if (inst->prop.height[OUTPUT_PORT] * inst->prop.width[OUTPUT_PORT] <= 1280 * 720) pdata.video_work_mode = VIDC_WORK_MODE_1; break; } } else if (inst->session_type == MSM_VIDC_ENCODER) pdata.video_work_mode = VIDC_WORK_MODE_1; else { return -EINVAL; } decision_done: inst->clk_data.work_mode = pdata.video_work_mode; rc = call_hfi_op(hdev, session_set_property, (void *)inst->session, HAL_PARAM_VIDEO_WORK_MODE, (void *)&pdata); if (rc) dprintk(VIDC_WARN, " Failed to configure Work Mode %pK\n", inst); /* For WORK_MODE_1, set Low Latency mode by default to HW. */ if (inst->session_type == MSM_VIDC_ENCODER && inst->clk_data.work_mode == VIDC_WORK_MODE_1) { latency.enable = 1; rc = call_hfi_op(hdev, session_set_property, (void *)inst->session, HAL_PARAM_VENC_LOW_LATENCY, (void *)&latency); } rc = msm_comm_scale_clocks_and_bus(inst); return rc; } int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst) { int rc = 0; Loading Loading @@ -1429,6 +1581,17 @@ int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst) return rc; } void msm_vidc_init_core_clk_ops(struct msm_vidc_core *core) { if (!core) return; if (core->platform_data->vpu_ver == VPU_VERSION_4) core->core_ops = &core_ops_vpu4; else core->core_ops = &core_ops_vpu5; } void msm_print_core_status(struct msm_vidc_core *core, u32 core_id) { struct msm_vidc_inst *inst = NULL; Loading
drivers/media/platform/msm/vidc/msm_vidc_clocks.h +1 −0 Original line number Diff line number Diff line Loading @@ -44,4 +44,5 @@ void msm_comm_update_input_cr(struct msm_vidc_inst *inst, u32 index, u32 cr); void update_recon_stats(struct msm_vidc_inst *inst, struct recon_stats_type *recon_stats); void msm_vidc_init_core_clk_ops(struct msm_vidc_core *core); #endif