summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/vidc/msm_vdec.c2
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c4
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c33
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_dcvs.c247
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_dcvs.h5
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_internal.h3
6 files changed, 130 insertions, 164 deletions
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 05232f862e55..fdf6e1b1c5d0 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -2290,6 +2290,8 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
rc = -ENOTSUPP;
break;
}
+
+ msm_dcvs_try_enable(inst);
msm_comm_scale_clocks_and_bus(inst);
break;
case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_INPUT:
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 5eb287a28bbd..99f30d9cb97b 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1665,7 +1665,6 @@ static inline int msm_venc_power_save_mode_enable(struct msm_vidc_inst *inst)
goto fail_power_mode_set;
}
inst->flags |= VIDC_LOW_POWER;
- msm_dcvs_enc_set_power_save_mode(inst, true);
dprintk(VIDC_INFO, "Power Save Mode set for inst: %pK\n", inst);
}
@@ -2939,6 +2938,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
break;
}
+ msm_dcvs_try_enable(inst);
msm_comm_scale_clocks_and_bus(inst);
break;
case V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_BITSTREAM_RESTRICT:
@@ -3052,8 +3052,6 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
}
pdata = &venc_mode;
- msm_dcvs_enc_set_power_save_mode(inst,
- ctrl->val == V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE);
break;
case V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS:
if (inst->fmts[CAPTURE_PORT]->fourcc != V4L2_PIX_FMT_HEVC) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 10dcc30f4aaa..566441e9c546 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1239,8 +1239,6 @@ static void handle_event_change(enum hal_command_response cmd, void *data)
inst->prop.width[OUTPUT_PORT] = event_notify->width;
}
- inst->seqchanged_count++;
-
if (inst->session_type == MSM_VIDC_DECODER)
msm_dcvs_init_load(inst);
@@ -2227,11 +2225,32 @@ void handle_cmd_response(enum hal_command_response cmd, void *data)
int msm_comm_scale_clocks(struct msm_vidc_core *core)
{
- int num_mbs_per_sec =
- msm_comm_get_load(core, MSM_VIDC_ENCODER, LOAD_CALC_NO_QUIRKS) +
+ int num_mbs_per_sec, enc_mbs_per_sec, dec_mbs_per_sec;
+
+ enc_mbs_per_sec =
+ msm_comm_get_load(core, MSM_VIDC_ENCODER, LOAD_CALC_NO_QUIRKS);
+ dec_mbs_per_sec =
msm_comm_get_load(core, MSM_VIDC_DECODER, LOAD_CALC_NO_QUIRKS);
+
+ if (enc_mbs_per_sec >= dec_mbs_per_sec) {
+ /*
+ * If Encoder load is higher, use that load. Encoder votes for higher
+ * clock. Since Encoder and Deocder run on parallel cores, this clock
+ * should suffice decoder usecases.
+ */
+ num_mbs_per_sec = enc_mbs_per_sec;
+ } else {
+ /*
+ * If Decoder load is higher, it's tricky to decide clock. Decoder
+ * higher load might results less clocks than Encoder smaller load.
+ * At this point driver doesn't know which clock to vote. Hence use
+ * total load.
+ */
+ num_mbs_per_sec = enc_mbs_per_sec + dec_mbs_per_sec;
+ }
+
return msm_comm_scale_clocks_load(core, num_mbs_per_sec,
- LOAD_CALC_NO_QUIRKS);
+ LOAD_CALC_NO_QUIRKS);
}
int msm_comm_scale_clocks_load(struct msm_vidc_core *core,
@@ -4896,6 +4915,9 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
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] <
@@ -5205,6 +5227,7 @@ int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
msm_dcvs_init_load(inst);
}
msm_comm_scale_clocks_and_bus(inst);
+ msm_dcvs_try_enable(inst);
}
exit:
return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c
index c03f887be6f6..9e67ef096c63 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.c
@@ -20,10 +20,19 @@
((__cur_mbpf) >= (__min_mbpf))
static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst);
-static bool msm_dcvs_enc_check(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_dcvs_try_enable(struct msm_vidc_inst *inst)
+{
+ if (!inst) {
+ 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_get_mbs_per_frame(struct msm_vidc_inst *inst)
{
int height, width;
@@ -41,20 +50,27 @@ static inline int msm_dcvs_get_mbs_per_frame(struct msm_vidc_inst *inst)
return NUM_MBS_PER_FRAME(height, width);
}
-static inline int msm_dcvs_count_active_instances(struct msm_vidc_core *core)
+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 *inst = NULL;
+ struct msm_vidc_inst *temp = NULL;
if (!core) {
dprintk(VIDC_ERR, "%s: Invalid args: %pK\n", __func__, core);
return -EINVAL;
}
+ /* 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(inst, &core->instances, list) {
- if (inst->state >= MSM_VIDC_OPEN_DONE &&
- inst->state < MSM_VIDC_STOP_DONE)
+ 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);
@@ -112,17 +128,12 @@ 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) {
- inst->dcvs_mode = msm_dcvs_check_supported(inst);
- dprintk(VIDC_DBG, "%s: session DCVS %s supported\n",
- __func__, inst->dcvs_mode ? "" : "not");
-
- if (inst->dcvs_mode) {
- rc = msm_dcvs_enc_scale_clocks(inst);
- if (rc) {
- dprintk(VIDC_DBG,
+ 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");
- }
}
}
}
@@ -131,28 +142,14 @@ 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)
- return;
-
- if (msm_dcvs_check_supported(inst)) {
- inst->dcvs_mode = true;
- dprintk(VIDC_DBG,
- "%s: session DCVS supported, decode_dcvs_mode = %d\n",
- __func__, inst->dcvs_mode);
- } else {
- inst->dcvs_mode = false;
- dprintk(VIDC_DBG,
- "%s: session DCVS not supported, decode_dcvs_mode = %d\n",
- __func__, inst->dcvs_mode);
- }
-
- if (msm_vidc_dec_dcvs_mode && inst->dcvs_mode) {
+ 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);
+ "%s: Failed to scale clocks in DCVS: %d\n",
+ __func__, rc);
}
}
}
@@ -163,6 +160,11 @@ void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb)
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);
@@ -531,48 +533,6 @@ static int msm_dcvs_dec_scale_clocks(struct msm_vidc_inst *inst, bool fbd)
return rc;
}
-static bool msm_dcvs_enc_check(struct msm_vidc_inst *inst)
-{
- int num_mbs_per_frame = 0;
- long int instance_load = 0;
- long int dcvs_limit = 0;
- bool dcvs_check_passed = false, is_codec_supported = false;
- struct msm_vidc_platform_resources *res = NULL;
-
- if (!inst || !inst->core) {
- dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
- return dcvs_check_passed;
- }
-
- res = &inst->core->resources;
- if (!res->dcvs_limit) {
- dprintk(VIDC_ERR,
- "%s Dcvs limit table uninitialized\n", __func__);
- return false;
- }
-
- is_codec_supported =
- msm_dcvs_check_codec_supported(
- inst->fmts[CAPTURE_PORT]->fourcc,
- inst->dcvs.supported_codecs,
- 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;
-
- if (msm_vidc_enc_dcvs_mode && is_codec_supported &&
- inst->dcvs.is_power_save_mode &&
- IS_VALID_DCVS_SESSION(num_mbs_per_frame,
- res->dcvs_limit[inst->session_type].min_mbpf) &&
- IS_VALID_DCVS_SESSION(instance_load, dcvs_limit)) {
- dcvs_check_passed = true;
- }
- return dcvs_check_passed;
-}
-
static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst)
{
int num_mbs_per_frame = 0, instance_count = 0;
@@ -583,6 +543,7 @@ static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst)
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) {
@@ -599,104 +560,88 @@ static bool msm_dcvs_check_supported(struct msm_vidc_inst *inst)
"%s: dcvs limit table not found\n", __func__);
return false;
}
- instance_count = msm_dcvs_count_active_instances(core);
+ 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 (instance_count == 1 && inst->session_type == MSM_VIDC_DECODER &&
- !msm_comm_turbo_session(inst)) {
- num_mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
- instance_load = msm_comm_get_inst_load(inst,
- LOAD_CALC_NO_QUIRKS);
- output_buf_req = get_buff_req_buffer(inst,
- msm_comm_get_hal_output_buffer(inst));
- dcvs_limit =
- (long int)res->dcvs_limit[inst->session_type].min_mbpf *
- res->dcvs_limit[inst->session_type].fps;
- is_codec_supported =
- msm_dcvs_check_codec_supported(
- inst->fmts[OUTPUT_PORT]->fourcc,
- inst->dcvs.supported_codecs,
- inst->session_type);
- if (!is_codec_supported ||
- !IS_VALID_DCVS_SESSION(num_mbs_per_frame,
- res->dcvs_limit[inst->session_type].min_mbpf) ||
- !IS_VALID_DCVS_SESSION(instance_load, dcvs_limit) ||
- inst->seqchanged_count > 1)
- return false;
+ 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);
+ "%s: No buffer requirement for buffer type %x\n",
+ __func__, HAL_BUFFER_OUTPUT);
return false;
}
- } else if (instance_count == 1 &&
- inst->session_type == MSM_VIDC_ENCODER &&
- !msm_comm_turbo_session(inst)) {
- if (!msm_dcvs_enc_check(inst))
- return false;
- } else {
- /*
- * For multiple instance use case with 4K, clocks will be scaled
- * as per load in streamon, but the clocks may be scaled
- * down as DCVS is running for first playback instance
- * Rescaling the core clock for multiple instance use case
- */
- if (!dcvs->is_clock_scaled) {
- if (!msm_comm_scale_clocks(core)) {
- dcvs->is_clock_scaled = true;
- dprintk(VIDC_DBG,
- "%s: Scaled clocks = %d\n",
- __func__, dcvs->is_clock_scaled);
- } else {
- dprintk(VIDC_DBG,
- "%s: Failed to Scale clocks. Perf might be impacted\n",
- __func__);
- }
+ 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;
}
- /*
- * For multiple instance use case turn OFF DCVS algorithm
- * immediately
- */
+ if (msm_comm_turbo_session(inst) ||
+ !IS_VALID_DCVS_SESSION(instance_load, dcvs_limit ||
+ instance_count > 1))
+ is_dcvs_supported = false;
+ }
+ 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;
+ }
+dcvs_decision_done:
+ if (!is_dcvs_supported) {
+ msm_comm_scale_clocks(core);
if (instance_count > 1) {
mutex_lock(&core->lock);
list_for_each_entry(temp, &core->instances, list)
temp->dcvs_mode = false;
mutex_unlock(&core->lock);
}
-
- return false;
}
-
- return true;
+ return is_dcvs_supported;
}
int msm_dcvs_get_extra_buff_count(struct msm_vidc_inst *inst)
{
- int extra_buffer = 0;
-
if (!inst) {
dprintk(VIDC_ERR, "%s Invalid args\n", __func__);
return 0;
}
- if (inst->session_type == MSM_VIDC_ENCODER) {
- if (msm_dcvs_enc_check(inst))
- extra_buffer = DCVS_ENC_EXTRA_OUTPUT_BUFFERS;
- } else if (inst->session_type == MSM_VIDC_DECODER) {
- if (msm_dcvs_check_supported(inst))
- extra_buffer = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
- }
- return extra_buffer;
+ return inst->dcvs.extra_buffer_count;
}
-void msm_dcvs_enc_set_power_save_mode(struct msm_vidc_inst *inst,
- bool is_power_save_mode)
-{
- if (!inst) {
- dprintk(VIDC_ERR, "%s Invalid args\n", __func__);
- return;
- }
-
- inst->dcvs.is_power_save_mode = is_power_save_mode;
-}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.h b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.h
index 17040166b1e4..d40473976ebb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_dcvs.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_dcvs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -36,6 +36,5 @@ void msm_dcvs_init_load(struct msm_vidc_inst *inst);
void msm_dcvs_monitor_buffer(struct msm_vidc_inst *inst);
void msm_dcvs_check_and_scale_clocks(struct msm_vidc_inst *inst, bool is_etb);
int msm_dcvs_get_extra_buff_count(struct msm_vidc_inst *inst);
-void msm_dcvs_enc_set_power_save_mode(struct msm_vidc_inst *inst,
- bool is_power_save_mode);
+int msm_dcvs_try_enable(struct msm_vidc_inst *inst);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 72c1ddcf3a70..b6e74715ad07 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -204,9 +204,9 @@ struct dcvs_stats {
int load_high;
int min_threshold;
int max_threshold;
- bool is_clock_scaled;
int etb_counter;
bool is_power_save_mode;
+ unsigned int extra_buffer_count;
u32 supported_codecs;
};
@@ -279,7 +279,6 @@ struct msm_vidc_inst {
bool in_reconfig;
u32 reconfig_width;
u32 reconfig_height;
- u32 seqchanged_count;
struct dentry *debugfs_root;
void *priv;
struct msm_vidc_debug debug;