msm: vidc: Simplify DCVS algorithm
Unify Encoder and Decoder DCVS by removing complex buffer
tracking logic. DCVS is based on simple logic now.
- More YUV buffers with Venus --> Venus is Late -->
Increase Venus clock.
- Less YUV buffers with Venus --> Venus is not late -->
Decrease Venus clock.
CRs-Fixed: 2012520
Change-Id: I47870747dd73e20e1be1fd156ed8ae89ca4b824a
Signed-off-by: Praneeth Paladugu <ppaladug@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index fd6e681..abc6cc8 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -883,6 +883,7 @@
property_id = HAL_PARAM_VDEC_SYNC_FRAME_DECODE;
hal_property.enable = ctrl->val;
pdata = &hal_property;
+ msm_dcvs_try_enable(inst);
break;
case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
inst->flags |= VIDC_SECURE;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 475b696..2d803bb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1390,7 +1390,7 @@
"Failed to move inst: %pK to start done state\n", inst);
goto fail_start;
}
- msm_dcvs_init_load(inst);
+ msm_dcvs_init(inst);
if (msm_comm_get_stream_output_mode(inst) ==
HAL_VIDEO_DECODER_SECONDARY) {
rc = msm_comm_queue_output_buffers(inst);
@@ -1953,7 +1953,6 @@
if (rc)
goto fail_bufq_capture;
- msm_dcvs_init(inst);
rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
session_type);
if (rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 73a3967..70427d3 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -16,13 +16,6 @@
#include "msm_vidc_debug.h"
#include "msm_vidc_clocks.h"
-#define IS_VALID_DCVS_SESSION(__cur_mbpf, __min_mbpf) \
- ((__cur_mbpf) >= (__min_mbpf))
-
-static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst);
-static int msm_dcvs_enc_scale_clocks(struct msm_vidc_inst *inst);
-static int msm_dcvs_dec_scale_clocks(struct msm_vidc_inst *inst, bool fbd);
-
int msm_comm_vote_bus(struct msm_vidc_core *core)
{
int rc = 0, vote_data_count = 0, i = 0;
@@ -103,6 +96,82 @@
return rc;
}
+static inline int get_pending_bufs_fw(struct msm_vidc_inst *inst)
+{
+ int fw_out_qsize = 0, buffers_in_driver = 0;
+
+ /*
+ * DCVS always operates on Uncompressed buffers.
+ * For Decoders, FTB and Encoders, ETB.
+ */
+
+ if (inst->state >= MSM_VIDC_OPEN_DONE &&
+ inst->state < MSM_VIDC_STOP_DONE) {
+ if (inst->session_type == MSM_VIDC_DECODER)
+ fw_out_qsize = inst->count.ftb - inst->count.fbd;
+ else
+ fw_out_qsize = inst->count.etb - inst->count.ebd;
+
+ buffers_in_driver = inst->buffers_held_in_driver;
+ }
+
+ return fw_out_qsize + buffers_in_driver;
+}
+
+static int msm_dcvs_scale_clocks(struct msm_vidc_inst *inst)
+{
+ int rc = 0;
+ int fw_pending_bufs = 0;
+ int total_output_buf = 0;
+ int buffers_outside_fw = 0;
+ struct msm_vidc_core *core;
+ struct hal_buffer_requirements *output_buf_req;
+ struct dcvs_stats *dcvs;
+
+ if (!inst || !inst->core || !inst->core->device) {
+ dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
+ return -EINVAL;
+ }
+ if (!inst->dcvs_mode) {
+ dprintk(VIDC_DBG, "DCVS is not enabled\n");
+ return 0;
+ }
+
+ dcvs = &inst->dcvs;
+
+ core = inst->core;
+ mutex_lock(&inst->lock);
+ fw_pending_bufs = get_pending_bufs_fw(inst);
+
+ output_buf_req = get_buff_req_buffer(inst,
+ dcvs->buffer_type);
+ mutex_unlock(&inst->lock);
+ if (!output_buf_req) {
+ dprintk(VIDC_ERR,
+ "%s: No buffer requirement for buffer type %x\n",
+ __func__, dcvs->buffer_type);
+ return -EINVAL;
+ }
+
+ /* Total number of output buffers */
+ total_output_buf = output_buf_req->buffer_count_actual;
+
+ /* Buffers outside FW are with display */
+ buffers_outside_fw = total_output_buf - fw_pending_bufs;
+ dprintk(VIDC_DBG,
+ "Counts : total_output_buf = %d fw_pending_bufs = %d buffers_outside_fw = %d\n",
+ total_output_buf, fw_pending_bufs, buffers_outside_fw);
+
+ if (buffers_outside_fw >= dcvs->min_threshold &&
+ dcvs->load > dcvs->load_low) {
+ dcvs->load = dcvs->load_low;
+ } else if (buffers_outside_fw < dcvs->min_threshold &&
+ dcvs->load == dcvs->load_low) {
+ dcvs->load = dcvs->load_high;
+ }
+ return rc;
+}
+
static void msm_vidc_update_freq_entry(struct msm_vidc_inst *inst,
unsigned long freq, ion_phys_addr_t device_addr)
{
@@ -140,10 +209,12 @@
temp->freq = 0;
}
mutex_unlock(&inst->freqs.lock);
+
+ inst->dcvs.buffer_counter++;
}
-static unsigned long msm_vidc_get_highest_freq(struct msm_vidc_inst *inst)
+static unsigned long msm_vidc_adjust_freq(struct msm_vidc_inst *inst)
{
struct vidc_freq_data *temp;
unsigned long freq = 0;
@@ -154,6 +225,15 @@
}
mutex_unlock(&inst->freqs.lock);
+ /* If current requirement is within DCVS limits, try DCVS. */
+
+ if (freq < inst->dcvs.load_high) {
+ dprintk(VIDC_DBG, "Calling DCVS now\n");
+ // TODO calling DCVS here may reduce the residency. Re-visit.
+ msm_dcvs_scale_clocks(inst);
+ freq = inst->dcvs.load;
+ }
+
return freq;
}
@@ -285,7 +365,7 @@
u32 filled_len = 0;
ion_phys_addr_t device_addr = 0;
- if (inst->count.fbd < DCVS_FTB_WINDOW) {
+ if (inst->dcvs.buffer_counter < DCVS_FTB_WINDOW) {
freq = msm_vidc_max_freq(inst);
goto decision_done;
}
@@ -309,7 +389,7 @@
msm_vidc_update_freq_entry(inst, freq, device_addr);
- freq = msm_vidc_get_highest_freq(inst);
+ freq = msm_vidc_adjust_freq(inst);
decision_done:
inst->freq = freq;
@@ -346,35 +426,16 @@
dprintk(VIDC_ERR, "%s: Invalid args: %p\n", __func__, inst);
return -EINVAL;
}
- inst->dcvs_mode = msm_dcvs_check_supported(inst);
- return 0;
-}
-
-static inline int msm_dcvs_count_active_instances(struct msm_vidc_core *core,
- enum session_type session_type)
-{
- int active_instances = 0;
- struct msm_vidc_inst *temp = NULL;
-
- if (!core) {
- dprintk(VIDC_ERR, "%s: Invalid args: %pK\n", __func__, core);
- return -EINVAL;
+ if (inst->flags & VIDC_THUMBNAIL) {
+ dprintk(VIDC_PROF, "Thumbnail sessions don't need DCVS : %pK\n",
+ inst);
+ return false;
}
+ inst->dcvs_mode = true;
- /* DCVS condition is as following
- * Decoder DCVS : Only for ONE decoder session.
- * Encoder DCVS : Only for ONE encoder session + ONE decoder session
- */
- mutex_lock(&core->lock);
- list_for_each_entry(temp, &core->instances, list) {
- if (temp->state >= MSM_VIDC_OPEN_DONE &&
- temp->state < MSM_VIDC_STOP_DONE &&
- (temp->session_type == session_type ||
- temp->session_type == MSM_VIDC_ENCODER))
- active_instances++;
- }
- mutex_unlock(&core->lock);
- return active_instances;
+ // TODO : Update with proper number based on on-target tuning.
+ inst->dcvs.extra_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
+ return true;
}
static bool msm_dcvs_check_codec_supported(int fourcc,
@@ -406,7 +467,6 @@
int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst)
{
-
int rc = 0, j = 0;
struct clock_freq_table *clk_freq_tbl = NULL;
struct clock_profile_entry *entry = NULL;
@@ -442,92 +502,6 @@
return rc;
}
-static void msm_dcvs_update_dcvs_params(int idx, struct msm_vidc_inst *inst)
-{
- struct dcvs_stats *dcvs = NULL;
- struct msm_vidc_platform_resources *res = NULL;
- struct dcvs_table *table = NULL;
-
- if (!inst || !inst->core) {
- dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
- return;
- }
-
- dcvs = &inst->dcvs;
- res = &inst->core->resources;
- table = res->dcvs_tbl;
-
- dcvs->load_low = table[idx].load_low;
- dcvs->load_high = table[idx].load_high;
- dcvs->supported_codecs = table[idx].supported_codecs;
-}
-
-static void msm_dcvs_enc_check_and_scale_clocks(struct msm_vidc_inst *inst)
-{
- int rc = 0;
-
- if (inst->session_type == MSM_VIDC_ENCODER &&
- msm_vidc_enc_dcvs_mode) {
- rc = msm_dcvs_enc_scale_clocks(inst);
- if (rc) {
- dprintk(VIDC_DBG,
- "ENC_DCVS: error while scaling clocks\n");
- }
- }
-}
-
-static void msm_dcvs_dec_check_and_scale_clocks(struct msm_vidc_inst *inst)
-{
- int rc = 0;
-
- if (inst->session_type == MSM_VIDC_DECODER &&
- msm_vidc_dec_dcvs_mode) {
- msm_dcvs_monitor_buffer(inst);
- rc = msm_dcvs_dec_scale_clocks(inst, false);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s: Failed to scale clocks in DCVS: %d\n",
- __func__, rc);
- }
- }
-}
-
-void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb)
-{
- if (!inst) {
- dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
- return;
- }
- msm_dcvs_try_enable(inst);
- if (!inst->dcvs_mode) {
- dprintk(VIDC_DBG, "DCVS is not enabled\n");
- return;
- }
-
- if (is_etb)
- msm_dcvs_enc_check_and_scale_clocks(inst);
- else
- msm_dcvs_dec_check_and_scale_clocks(inst);
-}
-
-static inline int get_pending_bufs_fw(struct msm_vidc_inst *inst)
-{
- int fw_out_qsize = 0, buffers_in_driver = 0;
-
- if (!inst) {
- dprintk(VIDC_ERR, "%s Invalid args\n", __func__);
- return -EINVAL;
- }
-
- if (inst->state >= MSM_VIDC_OPEN_DONE &&
- inst->state < MSM_VIDC_STOP_DONE) {
- fw_out_qsize = inst->count.ftb - inst->count.fbd;
- buffers_in_driver = inst->buffers_held_in_driver;
- }
-
- return fw_out_qsize + buffers_in_driver;
-}
-
static inline void msm_dcvs_print_dcvs_stats(struct dcvs_stats *dcvs)
{
dprintk(VIDC_DBG,
@@ -536,23 +510,18 @@
dcvs->load_high);
dprintk(VIDC_DBG,
- "DCVS: ThrDispBufLow %d, ThrDispBufHigh %d\n",
- dcvs->threshold_disp_buf_low,
- dcvs->threshold_disp_buf_high);
-
- dprintk(VIDC_DBG,
"DCVS: min_threshold %d, max_threshold %d\n",
dcvs->min_threshold, dcvs->max_threshold);
}
-void msm_dcvs_init_load(struct msm_vidc_inst *inst)
+void msm_dcvs_init(struct msm_vidc_inst *inst)
{
struct msm_vidc_core *core;
- struct hal_buffer_requirements *output_buf_req;
+ int i = 0;
+ struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
+ u64 total_freq = 0, rate = 0, load;
+ int cycles;
struct dcvs_stats *dcvs;
- struct dcvs_table *table;
- struct msm_vidc_platform_resources *res = NULL;
- int i, num_rows, fourcc;
dprintk(VIDC_DBG, "Init DCVS Load\n");
@@ -563,410 +532,38 @@
core = inst->core;
dcvs = &inst->dcvs;
- res = &core->resources;
- dcvs->load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS);
-
- num_rows = res->dcvs_tbl_size;
- table = res->dcvs_tbl;
-
- if (!num_rows || !table) {
- dprintk(VIDC_ERR,
- "%s: Dcvs table entry not found.\n", __func__);
- return;
- }
-
- fourcc = inst->session_type == MSM_VIDC_DECODER ?
- inst->fmts[OUTPUT_PORT].fourcc :
- inst->fmts[CAPTURE_PORT].fourcc;
-
- for (i = 0; i < num_rows; i++) {
- bool matches = msm_dcvs_check_codec_supported(
- fourcc,
- table[i].supported_codecs,
- inst->session_type);
- if (!matches)
- continue;
-
- if (dcvs->load > table[i].load) {
- msm_dcvs_update_dcvs_params(i, inst);
- break;
- }
- }
-
- if (inst->session_type == MSM_VIDC_ENCODER)
- goto print_stats;
-
- output_buf_req = get_buff_req_buffer(inst,
- msm_comm_get_hal_output_buffer(inst));
-
- if (!output_buf_req) {
- dprintk(VIDC_ERR,
- "%s: No buffer requirement for buffer type %x\n",
- __func__, HAL_BUFFER_OUTPUT);
- return;
- }
-
- dcvs->transition_turbo = false;
-
- /* calculating the min and max threshold */
- if (output_buf_req->buffer_count_actual) {
- dcvs->min_threshold = output_buf_req->buffer_count_actual -
- output_buf_req->buffer_count_min -
- msm_dcvs_get_extra_buff_count(inst) + 1;
- dcvs->max_threshold = output_buf_req->buffer_count_actual;
- if (dcvs->max_threshold <= dcvs->min_threshold)
- dcvs->max_threshold =
- dcvs->min_threshold + DCVS_BUFFER_SAFEGUARD;
- dcvs->threshold_disp_buf_low = dcvs->min_threshold;
- dcvs->threshold_disp_buf_high = dcvs->max_threshold;
- }
-
-print_stats:
- msm_dcvs_print_dcvs_stats(dcvs);
-}
-
-void msm_dcvs_init(struct msm_vidc_inst *inst)
-{
- dprintk(VIDC_DBG, "Init DCVS Struct\n");
-
- if (!inst) {
- dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
- return;
- }
-
- inst->dcvs = (struct dcvs_stats){ {0} };
- inst->dcvs.threshold_disp_buf_high = DCVS_NOMINAL_THRESHOLD;
- inst->dcvs.threshold_disp_buf_low = DCVS_TURBO_THRESHOLD;
-}
-
-void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst)
-{
- int new_ftb, i, prev_buf_count;
- int fw_pending_bufs, total_output_buf, buffers_outside_fw;
- struct dcvs_stats *dcvs;
- struct hal_buffer_requirements *output_buf_req;
-
- if (!inst) {
- dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
- return;
- }
- dcvs = &inst->dcvs;
-
- mutex_lock(&inst->lock);
- output_buf_req = get_buff_req_buffer(inst,
- msm_comm_get_hal_output_buffer(inst));
- if (!output_buf_req) {
- dprintk(VIDC_ERR, "%s : Get output buffer req failed %pK\n",
- __func__, inst);
- mutex_unlock(&inst->lock);
- return;
- }
-
- total_output_buf = output_buf_req->buffer_count_actual;
- fw_pending_bufs = get_pending_bufs_fw(inst);
- mutex_unlock(&inst->lock);
-
- buffers_outside_fw = total_output_buf - fw_pending_bufs;
- dcvs->num_ftb[dcvs->ftb_index] = buffers_outside_fw;
- dcvs->ftb_index = (dcvs->ftb_index + 1) % DCVS_FTB_WINDOW;
-
- if (dcvs->ftb_counter < DCVS_FTB_WINDOW)
- dcvs->ftb_counter++;
-
- dprintk(VIDC_PROF,
- "DCVS: ftb_counter %d\n", dcvs->ftb_counter);
-
- if (dcvs->ftb_counter == DCVS_FTB_WINDOW) {
- new_ftb = 0;
- for (i = 0; i < dcvs->ftb_counter; i++) {
- if (dcvs->num_ftb[i] > new_ftb)
- new_ftb = dcvs->num_ftb[i];
- }
-
- dcvs->threshold_disp_buf_high = new_ftb;
- if (dcvs->threshold_disp_buf_high <=
- dcvs->threshold_disp_buf_low +
- DCVS_BUFFER_SAFEGUARD) {
- dcvs->threshold_disp_buf_high =
- dcvs->threshold_disp_buf_low +
- DCVS_BUFFER_SAFEGUARD
- + (DCVS_BUFFER_SAFEGUARD == 0);
- }
-
- dcvs->threshold_disp_buf_high =
- clamp(dcvs->threshold_disp_buf_high,
- dcvs->min_threshold,
- dcvs->max_threshold);
- }
-
- if (dcvs->ftb_counter == DCVS_FTB_WINDOW &&
- dcvs->load == dcvs->load_low) {
- prev_buf_count =
- dcvs->num_ftb[((dcvs->ftb_index - 2 +
- DCVS_FTB_WINDOW) % DCVS_FTB_WINDOW)];
- if (prev_buf_count == dcvs->threshold_disp_buf_low &&
- buffers_outside_fw <= dcvs->threshold_disp_buf_low) {
- dcvs->transition_turbo = true;
- } else if (buffers_outside_fw > dcvs->threshold_disp_buf_low &&
- (buffers_outside_fw -
- (prev_buf_count - buffers_outside_fw))
- < dcvs->threshold_disp_buf_low){
- dcvs->transition_turbo = true;
- }
- }
-
- dprintk(VIDC_PROF,
- "DCVS: total_output_buf %d buffers_outside_fw %d load %d transition_turbo %d\n",
- total_output_buf, buffers_outside_fw, dcvs->load_low,
- dcvs->transition_turbo);
-}
-
-static int msm_dcvs_enc_scale_clocks(struct msm_vidc_inst *inst)
-{
- int rc = 0, fw_pending_bufs = 0, total_input_buf = 0;
- struct msm_vidc_core *core;
- struct dcvs_stats *dcvs;
-
- if (!inst || !inst->core || !inst->core->device) {
- dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
- return -EINVAL;
- }
-
- core = inst->core;
- dcvs = &inst->dcvs;
-
- mutex_lock(&inst->lock);
- total_input_buf = inst->buff_req.buffer[0].buffer_count_actual;
- fw_pending_bufs = (inst->count.etb - inst->count.ebd);
- mutex_unlock(&inst->lock);
-
- dprintk(VIDC_PROF,
- "DCVS: total_input_buf %d, fw_pending_bufs %d\n",
- total_input_buf, fw_pending_bufs);
-
- if (dcvs->etb_counter < total_input_buf) {
- dcvs->etb_counter++;
- if (dcvs->etb_counter != total_input_buf)
- return rc;
- }
-
- dprintk(VIDC_PROF,
- "DCVS: total_input_buf %d, fw_pending_bufs %d etb_counter %d dcvs->load %d\n",
- total_input_buf, fw_pending_bufs,
- dcvs->etb_counter, dcvs->load);
-
- if (fw_pending_bufs <= DCVS_ENC_LOW_THR &&
- dcvs->load > dcvs->load_low) {
- dcvs->load = dcvs->load_low;
- dcvs->prev_freq_lowered = true;
- } else {
- dcvs->prev_freq_lowered = false;
- }
-
- if (fw_pending_bufs >= DCVS_ENC_HIGH_THR &&
- dcvs->load <= dcvs->load_low) {
- dcvs->load = dcvs->load_high;
- dcvs->prev_freq_increased = true;
- } else {
- dcvs->prev_freq_increased = false;
- }
-
- if (dcvs->prev_freq_lowered || dcvs->prev_freq_increased) {
- dprintk(VIDC_PROF,
- "DCVS: (Scaling Clock %s) etb clock set = %d total_input_buf = %d fw_pending_bufs %d\n",
- dcvs->prev_freq_lowered ? "Lower" : "Higher",
- dcvs->load, total_input_buf, fw_pending_bufs);
-
- if (rc) {
- dprintk(VIDC_PROF,
- "Failed to set clock rate in FBD: %d\n", rc);
- }
- } else {
- dprintk(VIDC_PROF,
- "DCVS: etb clock load_old = %d total_input_buf = %d fw_pending_bufs %d\n",
- dcvs->load, total_input_buf, fw_pending_bufs);
- }
-
- return rc;
-}
-
-
-/*
- * In DCVS scale_clocks will be done both in qbuf and FBD
- * 1 indicates call made from fbd that lowers clock
- * 0 indicates call made from qbuf that increases clock
- * based on DCVS algorithm
- */
-
-static int msm_dcvs_dec_scale_clocks(struct msm_vidc_inst *inst, bool fbd)
-{
- int rc = 0;
- int fw_pending_bufs = 0;
- int total_output_buf = 0;
- int buffers_outside_fw = 0;
- struct msm_vidc_core *core;
- struct hal_buffer_requirements *output_buf_req;
- struct dcvs_stats *dcvs;
-
- if (!inst || !inst->core || !inst->core->device) {
- dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
- return -EINVAL;
- }
- core = inst->core;
- dcvs = &inst->dcvs;
- mutex_lock(&inst->lock);
- fw_pending_bufs = get_pending_bufs_fw(inst);
-
- output_buf_req = get_buff_req_buffer(inst,
- msm_comm_get_hal_output_buffer(inst));
- mutex_unlock(&inst->lock);
- if (!output_buf_req) {
- dprintk(VIDC_ERR,
- "%s: No buffer requirement for buffer type %x\n",
- __func__, HAL_BUFFER_OUTPUT);
- return -EINVAL;
- }
-
- /* Total number of output buffers */
- total_output_buf = output_buf_req->buffer_count_actual;
-
- /* Buffers outside FW are with display */
- buffers_outside_fw = total_output_buf - fw_pending_bufs;
-
- if (buffers_outside_fw >= dcvs->threshold_disp_buf_high &&
- !dcvs->prev_freq_increased &&
- dcvs->load > dcvs->load_low) {
- dcvs->load = dcvs->load_low;
- dcvs->prev_freq_lowered = true;
- dcvs->prev_freq_increased = false;
- } else if (dcvs->transition_turbo && dcvs->load == dcvs->load_low) {
- dcvs->load = dcvs->load_high;
- dcvs->prev_freq_increased = true;
- dcvs->prev_freq_lowered = false;
- dcvs->transition_turbo = false;
- } else {
- dcvs->prev_freq_increased = false;
- dcvs->prev_freq_lowered = false;
- }
-
- if (dcvs->prev_freq_lowered || dcvs->prev_freq_increased) {
- dprintk(VIDC_PROF,
- "DCVS: clock set = %d tot_output_buf = %d buffers_outside_fw %d threshold_high %d transition_turbo %d\n",
- dcvs->load, total_output_buf, buffers_outside_fw,
- dcvs->threshold_disp_buf_high, dcvs->transition_turbo);
-
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to set clock rate in FBD: %d\n", rc);
- }
- } else {
- dprintk(VIDC_PROF,
- "DCVS: clock old = %d tot_output_buf = %d buffers_outside_fw %d threshold_high %d transition_turbo %d\n",
- dcvs->load, total_output_buf, buffers_outside_fw,
- dcvs->threshold_disp_buf_high, dcvs->transition_turbo);
- }
- return rc;
-}
-
-static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst)
-{
- int num_mbs_per_frame = 0, instance_count = 0;
- long int instance_load = 0;
- long int dcvs_limit = 0;
- struct msm_vidc_inst *temp = NULL;
- struct msm_vidc_core *core;
- struct hal_buffer_requirements *output_buf_req;
- struct dcvs_stats *dcvs;
- bool is_codec_supported = false;
- bool is_dcvs_supported = true;
- struct msm_vidc_platform_resources *res = NULL;
-
- if (!inst || !inst->core || !inst->core->device) {
- dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__);
- return -EINVAL;
- }
-
- core = inst->core;
- dcvs = &inst->dcvs;
- res = &core->resources;
-
- if (!res->dcvs_limit) {
- dprintk(VIDC_WARN,
- "%s: dcvs limit table not found\n", __func__);
- return false;
- }
- instance_count = msm_dcvs_count_active_instances(core,
- inst->session_type);
- num_mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
- instance_load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS);
- dcvs_limit =
- (long int)res->dcvs_limit[inst->session_type].min_mbpf *
- res->dcvs_limit[inst->session_type].fps;
- inst->dcvs.extra_buffer_count = 0;
-
- if (!IS_VALID_DCVS_SESSION(num_mbs_per_frame,
- res->dcvs_limit[inst->session_type].min_mbpf)) {
- inst->dcvs.extra_buffer_count = 0;
- is_dcvs_supported = false;
- goto dcvs_decision_done;
-
- }
-
- if (inst->session_type == MSM_VIDC_DECODER) {
- inst->dcvs.extra_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
- output_buf_req = get_buff_req_buffer(inst,
- msm_comm_get_hal_output_buffer(inst));
- if (!output_buf_req) {
- dprintk(VIDC_ERR,
- "%s: No buffer requirement for buffer type %x\n",
- __func__, HAL_BUFFER_OUTPUT);
- return false;
- }
- is_codec_supported =
- msm_dcvs_check_codec_supported(
- inst->fmts[OUTPUT_PORT].fourcc,
- inst->dcvs.supported_codecs,
- inst->session_type);
- if (!is_codec_supported ||
- !msm_vidc_dec_dcvs_mode) {
- inst->dcvs.extra_buffer_count = 0;
- is_dcvs_supported = false;
- goto dcvs_decision_done;
- }
- if (msm_comm_turbo_session(inst) ||
- !IS_VALID_DCVS_SESSION(instance_load, dcvs_limit) ||
- instance_count > 1)
- is_dcvs_supported = false;
- }
+ inst->dcvs = (struct dcvs_stats){0};
+ load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS);
+ cycles = inst->entry->vpp_cycles;
+ allowed_clks_tbl = core->resources.allowed_clks_tbl;
if (inst->session_type == MSM_VIDC_ENCODER) {
- inst->dcvs.extra_buffer_count = DCVS_ENC_EXTRA_OUTPUT_BUFFERS;
- is_codec_supported =
- msm_dcvs_check_codec_supported(
- inst->fmts[CAPTURE_PORT].fourcc,
- inst->dcvs.supported_codecs,
- inst->session_type);
- if (!is_codec_supported ||
- !msm_vidc_enc_dcvs_mode) {
- inst->dcvs.extra_buffer_count = 0;
- is_dcvs_supported = false;
- goto dcvs_decision_done;
- }
- if (msm_comm_turbo_session(inst) ||
- !IS_VALID_DCVS_SESSION(instance_load, dcvs_limit) ||
- instance_count > 1)
- is_dcvs_supported = false;
+ cycles = inst->flags & VIDC_LOW_POWER ?
+ inst->entry->low_power_cycles :
+ cycles;
+
+ dcvs->buffer_type = HAL_BUFFER_INPUT;
+ // TODO : Update with proper no based on Buffer counts change.
+ dcvs->min_threshold = 7;
+ } else if (inst->session_type == MSM_VIDC_DECODER) {
+ dcvs->buffer_type = msm_comm_get_hal_output_buffer(inst);
+ // TODO : Update with proper no based on Buffer counts change.
+ dcvs->min_threshold = 4;
+ } else {
+ return;
}
-dcvs_decision_done:
- if (!is_dcvs_supported) {
- msm_comm_scale_clocks(inst);
- if (instance_count > 1) {
- mutex_lock(&core->lock);
- list_for_each_entry(temp, &core->instances, list)
- temp->dcvs_mode = false;
- mutex_unlock(&core->lock);
- }
+
+ total_freq = cycles * load;
+
+ for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) {
+ rate = allowed_clks_tbl[i].clock_rate;
+ if (rate >= total_freq)
+ break;
}
- return is_dcvs_supported;
+
+ dcvs->load = dcvs->load_high = rate;
+ dcvs->load_low = allowed_clks_tbl[i+1].clock_rate;
+
+ msm_dcvs_print_dcvs_stats(dcvs);
}
int msm_dcvs_get_extra_buff_count(struct msm_vidc_inst *inst)
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
index 665aca8..0229ccbb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
@@ -32,10 +32,7 @@
#define DCVS_BUFFER_SAFEGUARD (DCVS_DEC_EXTRA_OUTPUT_BUFFERS - 1)
void msm_dcvs_init(struct msm_vidc_inst *inst);
-void msm_dcvs_init_load(struct msm_vidc_inst *inst);
-void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst);
int msm_dcvs_get_extra_buff_count(struct msm_vidc_inst *inst);
-void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb);
int msm_dcvs_try_enable(struct msm_vidc_inst *inst);
int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst);
int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 3a79f9a..4aaa525 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1525,9 +1525,6 @@
inst->prop.width[OUTPUT_PORT] = event_notify->width;
}
- if (inst->session_type == MSM_VIDC_DECODER)
- msm_dcvs_init_load(inst);
-
rc = msm_vidc_check_session_supported(inst);
if (!rc) {
seq_changed_event.type = event;
@@ -3850,7 +3847,6 @@
data->timestamp, data->flags);
msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FTB);
}
-
}
/*
@@ -4723,6 +4719,10 @@
return 0;
}
+ // Finish FLUSH As Soon As Possible.
+ inst->dcvs.buffer_counter = 0;
+ msm_comm_scale_clocks_and_bus(inst);
+
msm_comm_flush_dynamic_buffers(inst);
if (inst->state == MSM_VIDC_CORE_INVALID ||
@@ -5058,9 +5058,6 @@
return -ENOTSUPP;
}
- if (!rc)
- msm_dcvs_try_enable(inst);
-
if (!rc) {
if (inst->prop.width[CAPTURE_PORT] < capability->width.min ||
inst->prop.height[CAPTURE_PORT] <
@@ -5377,10 +5374,7 @@
if (rc)
dprintk(VIDC_WARN,
"Failed to set frame rate %d\n", rc);
- } else {
- msm_dcvs_init_load(inst);
}
- msm_dcvs_try_enable(inst);
}
exit:
return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 28612e3..8562e8f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -206,23 +206,14 @@
};
struct dcvs_stats {
- int num_ftb[DCVS_FTB_WINDOW];
- bool transition_turbo;
- int ftb_index;
- int ftb_counter;
- bool prev_freq_lowered;
- bool prev_freq_increased;
- int threshold_disp_buf_high;
- int threshold_disp_buf_low;
+ int buffer_counter;
int load;
int load_low;
int load_high;
int min_threshold;
int max_threshold;
- int etb_counter;
- bool is_power_save_mode;
unsigned int extra_buffer_count;
- u32 supported_codecs;
+ enum hal_buffer buffer_type;
};
struct profile_data {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index fbf4474..8b9018c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -90,18 +90,6 @@
res->pf_ver_tbl = NULL;
}
-static inline void msm_vidc_free_dcvs_table(
- struct msm_vidc_platform_resources *res)
-{
- res->dcvs_tbl = NULL;
-}
-
-static inline void msm_vidc_free_dcvs_limit(
- struct msm_vidc_platform_resources *res)
-{
- res->dcvs_limit = NULL;
-}
-
static inline void msm_vidc_free_imem_ab_table(
struct msm_vidc_platform_resources *res)
{
@@ -163,8 +151,6 @@
msm_vidc_free_clock_table(res);
msm_vidc_free_regulator_table(res);
msm_vidc_free_platform_version_table(res);
- msm_vidc_free_dcvs_table(res);
- msm_vidc_free_dcvs_limit(res);
msm_vidc_free_cycles_per_mb_table(res);
msm_vidc_free_allowed_clocks_table(res);
msm_vidc_free_reg_table(res);
@@ -547,94 +533,6 @@
return rc;
}
-static int msm_vidc_load_dcvs_table(struct msm_vidc_platform_resources *res)
-{
- int rc = 0;
- int num_elements = 0;
- struct platform_device *pdev = res->pdev;
-
- if (!of_find_property(pdev->dev.of_node, "qcom,dcvs-tbl", NULL)) {
- /*
- * qcom,dcvs-tbl is an optional property. Incase qcom,dcvs-limit
- * property is present, it becomes mandatory. It likely won't
- * be present on targets that does not support the feature
- */
- dprintk(VIDC_DBG, "qcom,dcvs-tbl not found\n");
- return 0;
- }
-
- num_elements = get_u32_array_num_elements(pdev->dev.of_node,
- "qcom,dcvs-tbl");
- num_elements /= sizeof(*res->dcvs_tbl) / sizeof(u32);
- if (!num_elements) {
- dprintk(VIDC_ERR, "no elements in dcvs table\n");
- return rc;
- }
-
- res->dcvs_tbl = devm_kzalloc(&pdev->dev, num_elements *
- sizeof(*res->dcvs_tbl), GFP_KERNEL);
- if (!res->dcvs_tbl) {
- dprintk(VIDC_ERR,
- "%s Failed to alloc dcvs_tbl\n",
- __func__);
- return -ENOMEM;
- }
-
- if (of_property_read_u32_array(pdev->dev.of_node,
- "qcom,dcvs-tbl", (u32 *)res->dcvs_tbl,
- num_elements * sizeof(*res->dcvs_tbl) / sizeof(u32))) {
- dprintk(VIDC_ERR, "Failed to read dcvs table\n");
- msm_vidc_free_dcvs_table(res);
- return -EINVAL;
- }
- res->dcvs_tbl_size = num_elements;
-
- return rc;
-}
-
-static int msm_vidc_load_dcvs_limit(struct msm_vidc_platform_resources *res)
-{
- int rc = 0;
- int num_elements = 0;
- struct platform_device *pdev = res->pdev;
-
- if (!of_find_property(pdev->dev.of_node, "qcom,dcvs-limit", NULL)) {
- /*
- * qcom,dcvs-limit is an optional property. Incase qcom,dcvs-tbl
- * property is present, it becomes mandatory. It likely won't
- * be present on targets that does not support the feature
- */
- dprintk(VIDC_DBG, "qcom,dcvs-limit not found\n");
- return 0;
- }
-
- num_elements = get_u32_array_num_elements(pdev->dev.of_node,
- "qcom,dcvs-limit");
- num_elements /= sizeof(*res->dcvs_limit) / sizeof(u32);
- if (!num_elements) {
- dprintk(VIDC_ERR, "no elements in dcvs limit\n");
- res->dcvs_limit = NULL;
- return rc;
- }
-
- res->dcvs_limit = devm_kzalloc(&pdev->dev, num_elements *
- sizeof(*res->dcvs_limit), GFP_KERNEL);
- if (!res->dcvs_limit) {
- dprintk(VIDC_ERR,
- "%s Failed to alloc dcvs_limit\n",
- __func__);
- return -ENOMEM;
- }
- if (of_property_read_u32_array(pdev->dev.of_node,
- "qcom,dcvs-limit", (u32 *)res->dcvs_limit,
- num_elements * sizeof(*res->dcvs_limit) / sizeof(u32))) {
- dprintk(VIDC_ERR, "Failed to read dcvs limit\n");
- msm_vidc_free_dcvs_limit(res);
- return -EINVAL;
- }
- return rc;
-}
-
static int msm_vidc_populate_bus(struct device *dev,
struct msm_vidc_platform_resources *res)
{
@@ -986,14 +884,6 @@
if (rc)
dprintk(VIDC_ERR, "Failed to load pf version table: %d\n", rc);
- rc = msm_vidc_load_dcvs_table(res);
- if (rc)
- dprintk(VIDC_WARN, "Failed to load dcvs table: %d\n", rc);
-
- rc = msm_vidc_load_dcvs_limit(res);
- if (rc)
- dprintk(VIDC_WARN, "Failed to load dcvs limit: %d\n", rc);
-
rc = msm_vidc_load_imem_ab_table(res);
if (rc)
dprintk(VIDC_WARN, "Failed to load freq table: %d\n", rc);