msm: vidc: Update clock selection algorithm
- Update operating rate for each session based on current
snapshot of all concurrent instances.
- Move clock related variables to single struct.
- Misc bug fixes in quality mode.
- Add\Remove NULL checks in clock scaling code.
- Update debugfs support according to new design.
- Fix issue in clock calculation.
- Init clock states at instance state transistions so
that they finish faster.
CRs-Fixed: 2012520
Change-Id: I7fd167d91b96d70e582d1f353ae68ff30439849f
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 3d3b7e9..a7f728d 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -23,7 +23,6 @@
#define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS MIN_NUM_CAPTURE_BUFFERS
#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8010
#define MB_SIZE_IN_PIXEL (16 * 16)
-#define MAX_OPERATING_FRAME_RATE (300 << 16)
#define OPERATING_FRAME_RATE_STEP (1 << 16)
static const char *const mpeg_video_stream_format[] = {
@@ -360,7 +359,7 @@
.name = "Set Decoder Operating rate",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 0,
- .maximum = MAX_OPERATING_FRAME_RATE,
+ .maximum = INT_MAX,
.default_value = 0,
.step = OPERATING_FRAME_RATE_STEP,
},
@@ -681,7 +680,7 @@
inst->bufq[OUTPUT_PORT].num_planes = 1;
inst->bufq[CAPTURE_PORT].num_planes = 1;
inst->prop.fps = DEFAULT_FPS;
- inst->operating_rate = 0;
+ inst->clk_data.operating_rate = 0;
memcpy(&inst->fmts[OUTPUT_PORT], &vdec_formats[2],
sizeof(struct msm_vidc_format));
memcpy(&inst->fmts[CAPTURE_PORT], &vdec_formats[0],
@@ -968,8 +967,12 @@
case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
dprintk(VIDC_DBG,
"inst(%pK) operating rate changed from %d to %d\n",
- inst, inst->operating_rate >> 16, ctrl->val >> 16);
- inst->operating_rate = ctrl->val;
+ inst, inst->clk_data.operating_rate >> 16,
+ ctrl->val >> 16);
+ inst->clk_data.operating_rate = ctrl->val;
+
+ msm_vidc_update_operating_rate(inst);
+
break;
default:
break;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 91d657d..3189072 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -23,7 +23,6 @@
#define DEFAULT_BIT_RATE 64000
#define BIT_RATE_STEP 100
#define DEFAULT_FRAME_RATE 15
-#define MAX_OPERATING_FRAME_RATE (300 << 16)
#define OPERATING_FRAME_RATE_STEP (1 << 16)
#define MAX_SLICE_BYTE_SIZE ((MAX_BIT_RATE)>>3)
#define MIN_SLICE_BYTE_SIZE 512
@@ -878,7 +877,7 @@
.name = "Set Encoder Operating rate",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 0,
- .maximum = MAX_OPERATING_FRAME_RATE,
+ .maximum = INT_MAX,
.default_value = 0,
.step = OPERATING_FRAME_RATE_STEP,
},
@@ -1235,7 +1234,7 @@
bitrate.bit_rate = ctrl->val;
bitrate.layer_id = 0;
pdata = &bitrate;
- inst->bitrate = ctrl->val;
+ inst->clk_data.bitrate = ctrl->val;
break;
}
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
@@ -1747,8 +1746,12 @@
case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
dprintk(VIDC_DBG,
"inst(%pK) operating rate changed from %d to %d\n",
- inst, inst->operating_rate >> 16, ctrl->val >> 16);
- inst->operating_rate = ctrl->val;
+ inst, inst->clk_data.operating_rate >> 16,
+ ctrl->val >> 16);
+ inst->clk_data.operating_rate = ctrl->val;
+
+ msm_vidc_update_operating_rate(inst);
+
break;
case V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE:
{
@@ -1831,6 +1834,7 @@
else
enable.enable = 0;
pdata = &enable;
+ inst->clk_data.low_latency_mode = (bool) enable.enable;
break;
}
case V4L2_CID_MPEG_VIDC_VIDEO_H264_TRANSFORM_8x8:
@@ -2083,7 +2087,7 @@
/* To start with, both ports are 1 plane each */
inst->bufq[OUTPUT_PORT].num_planes = 1;
inst->bufq[CAPTURE_PORT].num_planes = 1;
- inst->operating_rate = 0;
+ inst->clk_data.operating_rate = 0;
memcpy(&inst->fmts[CAPTURE_PORT], &venc_formats[4],
sizeof(struct msm_vidc_format));
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index e071037..8f97b15 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1433,7 +1433,9 @@
"Failed to move inst: %pK to start done state\n", inst);
goto fail_start;
}
- msm_dcvs_init(inst);
+
+ msm_clock_data_reset(inst);
+
if (msm_comm_get_stream_output_mode(inst) ==
HAL_VIDEO_DECODER_SECONDARY) {
rc = msm_comm_queue_output_buffers(inst);
@@ -1519,6 +1521,9 @@
dprintk(VIDC_ERR,
"Failed to move inst: %pK to state %d\n",
inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
+
+ msm_clock_data_reset(inst);
+
return rc;
}
@@ -1971,10 +1976,11 @@
inst->session_type = session_type;
inst->state = MSM_VIDC_CORE_UNINIT_DONE;
inst->core = core;
- inst->freq = 0;
- inst->core_id = VIDC_CORE_ID_DEFAULT;
+ inst->clk_data.min_freq = 0;
+ inst->clk_data.curr_freq = 0;
+ inst->clk_data.bitrate = 0;
+ inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
inst->bit_depth = MSM_VIDC_BIT_DEPTH_8;
- inst->bitrate = 0;
inst->pic_struct = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
inst->colour_space = MSM_VIDC_BT601_6_525;
inst->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
@@ -2037,6 +2043,8 @@
goto fail_init;
}
+ msm_comm_scale_clocks_and_bus(inst);
+
inst->debugfs_root =
msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index d43ae5a..cd518fb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -23,17 +23,12 @@
struct msm_vidc_inst *inst = NULL;
struct vidc_bus_vote_data *vote_data = NULL;
- if (!core) {
+ if (!core || !core->device) {
dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, core);
return -EINVAL;
}
hdev = core->device;
- if (!hdev) {
- dprintk(VIDC_ERR, "%s Invalid device handle: %pK\n",
- __func__, hdev);
- return -EINVAL;
- }
mutex_lock(&core->lock);
list_for_each_entry(inst, &core->instances, list)
@@ -65,12 +60,17 @@
vote_data[i].height = max(inst->prop.height[CAPTURE_PORT],
inst->prop.height[OUTPUT_PORT]);
- if (inst->operating_rate)
- vote_data[i].fps = (inst->operating_rate >> 16) ?
- inst->operating_rate >> 16 : 1;
+ if (inst->clk_data.operating_rate)
+ vote_data[i].fps =
+ (inst->clk_data.operating_rate >> 16) ?
+ inst->clk_data.operating_rate >> 16 : 1;
else
vote_data[i].fps = inst->prop.fps;
+ if (!msm_vidc_clock_scaling ||
+ inst->clk_data.buffer_counter < DCVS_FTB_WINDOW)
+ vote_data[i].power_mode = VIDC_POWER_TURBO;
+
/*
* TODO: support for OBP-DBP split mode hasn't been yet
* implemented, once it is, this part of code needs to be
@@ -126,18 +126,19 @@
int buffers_outside_fw = 0;
struct msm_vidc_core *core;
struct hal_buffer_requirements *output_buf_req;
- struct dcvs_stats *dcvs;
+ struct clock_data *dcvs;
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s Invalid params\n", __func__);
return -EINVAL;
}
- if (!inst->dcvs_mode) {
+
+ if (!inst->clk_data.dcvs_mode) {
dprintk(VIDC_DBG, "DCVS is not enabled\n");
return 0;
}
- dcvs = &inst->dcvs;
+ dcvs = &inst->clk_data;
core = inst->core;
mutex_lock(&inst->lock);
@@ -210,7 +211,7 @@
}
mutex_unlock(&inst->freqs.lock);
- inst->dcvs.buffer_counter++;
+ inst->clk_data.buffer_counter++;
}
@@ -227,12 +228,13 @@
/* If current requirement is within DCVS limits, try DCVS. */
- if (freq < inst->dcvs.load_high) {
+ if (freq < inst->clk_data.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;
+ freq = inst->clk_data.load;
}
+ dprintk(VIDC_PROF, "%s Inst %pK : Freq = %lu\n", __func__, inst, freq);
return freq;
}
@@ -274,9 +276,10 @@
unsigned long freq = 0;
unsigned long vpp_cycles = 0, vsp_cycles = 0;
u32 vpp_cycles_per_mb;
- u32 mbs_per_frame;
+ u32 mbs_per_second;
- mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
+ mbs_per_second = msm_comm_get_inst_load(inst,
+ LOAD_CALC_NO_QUIRKS);
/*
* Calculate vpp, vsp cycles separately for encoder and decoder.
@@ -286,17 +289,17 @@
if (inst->session_type == MSM_VIDC_ENCODER) {
vpp_cycles_per_mb = inst->flags & VIDC_LOW_POWER ?
- inst->entry->low_power_cycles :
- inst->entry->vpp_cycles;
+ inst->clk_data.entry->low_power_cycles :
+ inst->clk_data.entry->vpp_cycles;
- vsp_cycles = mbs_per_frame * inst->entry->vsp_cycles;
+ vsp_cycles = mbs_per_second * inst->clk_data.entry->vsp_cycles;
/* 10 / 7 is overhead factor */
- vsp_cycles += (inst->bitrate * 10) / 7;
+ vsp_cycles += (inst->clk_data.bitrate * 10) / 7;
} else if (inst->session_type == MSM_VIDC_DECODER) {
- vpp_cycles = mbs_per_frame * inst->entry->vpp_cycles;
+ vpp_cycles = mbs_per_second * inst->clk_data.entry->vpp_cycles;
- vsp_cycles = mbs_per_frame * inst->entry->vsp_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;
@@ -306,6 +309,8 @@
return freq;
}
+ dprintk(VIDC_PROF, "%s Inst %pK : Freq = %lu\n", __func__, inst, freq);
+
freq = max(vpp_cycles, vsp_cycles);
return freq;
@@ -321,7 +326,7 @@
hdev = core->device;
allowed_clks_tbl = core->resources.allowed_clks_tbl;
- if (!hdev || !allowed_clks_tbl) {
+ if (!allowed_clks_tbl) {
dprintk(VIDC_ERR,
"%s Invalid parameters\n", __func__);
return -EINVAL;
@@ -329,35 +334,104 @@
mutex_lock(&core->lock);
list_for_each_entry(temp, &core->instances, list) {
- freq += temp->freq;
+ freq += temp->clk_data.curr_freq;
}
for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) {
rate = allowed_clks_tbl[i].clock_rate;
if (rate >= freq)
break;
}
+ core->min_freq = freq;
+ core->curr_freq = rate;
mutex_unlock(&core->lock);
- core->freq = rate;
- dprintk(VIDC_PROF, "Voting for freq = %lu", freq);
+ dprintk(VIDC_PROF, "Min freq = %lu Current Freq = %lu\n",
+ core->min_freq, core->curr_freq);
rc = call_hfi_op(hdev, scale_clocks,
- hdev->hfi_device_data, rate);
+ hdev->hfi_device_data, core->curr_freq);
return rc;
}
-static unsigned long msm_vidc_max_freq(struct msm_vidc_inst *inst)
+static unsigned long msm_vidc_max_freq(struct msm_vidc_core *core)
{
struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
unsigned long freq = 0;
- allowed_clks_tbl = inst->core->resources.allowed_clks_tbl;
+ allowed_clks_tbl = core->resources.allowed_clks_tbl;
freq = allowed_clks_tbl[0].clock_rate;
dprintk(VIDC_PROF, "Max rate = %lu", freq);
return freq;
}
+int msm_vidc_update_operating_rate(struct msm_vidc_inst *inst)
+{
+ struct v4l2_ctrl *ctrl = NULL;
+ struct msm_vidc_inst *temp;
+ struct msm_vidc_core *core;
+ unsigned long max_freq, freq_left, ops_left, load, cycles, freq = 0;
+ unsigned long mbs_per_frame;
+
+ if (!inst || !inst->core) {
+ dprintk(VIDC_ERR, "%s Invalid args\n", __func__);
+ return -EINVAL;
+ }
+ core = inst->core;
+
+ mutex_lock(&core->lock);
+ max_freq = msm_vidc_max_freq(core);
+ list_for_each_entry(temp, &core->instances, list) {
+ if (temp == inst ||
+ temp->state < MSM_VIDC_START_DONE ||
+ temp->state >= MSM_VIDC_RELEASE_RESOURCES_DONE)
+ continue;
+
+ freq += temp->clk_data.min_freq;
+ }
+
+ freq_left = max_freq - freq;
+
+ list_for_each_entry(temp, &core->instances, list) {
+
+ mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
+ cycles = temp->clk_data.entry->vpp_cycles;
+ if (inst->session_type == MSM_VIDC_ENCODER)
+ cycles = temp->flags & VIDC_LOW_POWER ?
+ inst->clk_data.entry->low_power_cycles :
+ cycles;
+
+ load = cycles * mbs_per_frame;
+
+ ops_left = load ? (freq_left / load) : 0;
+ /* Convert remaining operating rate to Q16 format */
+ ops_left = ops_left << 16;
+
+ ctrl = v4l2_ctrl_find(&temp->ctrl_handler,
+ V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE);
+ if (ctrl) {
+ dprintk(VIDC_DBG,
+ "%s: Before Range = %lld --> %lld\n",
+ ctrl->name, ctrl->minimum, ctrl->maximum);
+ dprintk(VIDC_DBG,
+ "%s: Before Def value = %lld Cur val = %d\n",
+ ctrl->name, ctrl->default_value, ctrl->val);
+ v4l2_ctrl_modify_range(ctrl, ctrl->minimum,
+ ctrl->val + ops_left, ctrl->step,
+ ctrl->minimum);
+ dprintk(VIDC_DBG,
+ "%s: Updated Range = %lld --> %lld\n",
+ ctrl->name, ctrl->minimum, ctrl->maximum);
+ dprintk(VIDC_DBG,
+ "%s: Updated Def value = %lld Cur val = %d\n",
+ ctrl->name, ctrl->default_value, ctrl->val);
+ }
+ }
+ mutex_unlock(&core->lock);
+
+ return 0;
+}
+
int msm_comm_scale_clocks(struct msm_vidc_inst *inst)
{
struct vb2_buf_entry *temp, *next;
@@ -365,9 +439,10 @@
u32 filled_len = 0;
ion_phys_addr_t device_addr = 0;
- if (inst->dcvs.buffer_counter < DCVS_FTB_WINDOW) {
- freq = msm_vidc_max_freq(inst);
- goto decision_done;
+ if (!inst || !inst->core) {
+ dprintk(VIDC_ERR, "%s Invalid args: Inst = %pK\n",
+ __func__, inst);
+ return -EINVAL;
}
mutex_lock(&inst->pendingq.lock);
@@ -381,7 +456,7 @@
mutex_unlock(&inst->pendingq.lock);
if (!filled_len || !device_addr) {
- freq = inst->freq;
+ dprintk(VIDC_PROF, "No Change in frequency\n");
goto decision_done;
}
@@ -391,8 +466,15 @@
freq = msm_vidc_adjust_freq(inst);
+ inst->clk_data.min_freq = freq;
+
+ if (inst->clk_data.buffer_counter < DCVS_FTB_WINDOW ||
+ !msm_vidc_clock_scaling)
+ inst->clk_data.curr_freq = msm_vidc_max_freq(inst->core);
+ else
+ inst->clk_data.curr_freq = freq;
+
decision_done:
- inst->freq = freq;
msm_vidc_set_clocks(inst->core);
return 0;
}
@@ -422,29 +504,29 @@
int msm_dcvs_try_enable(struct msm_vidc_inst *inst)
{
- bool force_disable = false;
-
if (!inst) {
dprintk(VIDC_ERR, "%s: Invalid args: %p\n", __func__, inst);
return -EINVAL;
}
- force_disable = inst->session_type == MSM_VIDC_ENCODER ?
- !msm_vidc_enc_dcvs_mode :
- !msm_vidc_dec_dcvs_mode;
-
- if (force_disable || inst->flags & VIDC_THUMBNAIL) {
- dprintk(VIDC_PROF, "Thumbnail sessions don't need DCVS : %pK\n",
- inst);
- inst->dcvs.extra_capture_buffer_count = 0;
- inst->dcvs.extra_output_buffer_count = 0;
+ if (!msm_vidc_clock_scaling ||
+ inst->flags & VIDC_THUMBNAIL ||
+ inst->clk_data.low_latency_mode) {
+ dprintk(VIDC_PROF,
+ "This session doesn't need DCVS : %pK\n",
+ inst);
+ inst->clk_data.extra_capture_buffer_count = 0;
+ inst->clk_data.extra_output_buffer_count = 0;
+ inst->clk_data.dcvs_mode = false;
return false;
}
- inst->dcvs_mode = true;
+ inst->clk_data.dcvs_mode = true;
// TODO : Update with proper number based on on-target tuning.
- inst->dcvs.extra_capture_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
- inst->dcvs.extra_output_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
+ inst->clk_data.extra_capture_buffer_count =
+ DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
+ inst->clk_data.extra_output_buffer_count =
+ DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
return true;
}
@@ -482,6 +564,12 @@
struct clock_profile_entry *entry = NULL;
int fourcc;
+ if (!inst || !inst->core) {
+ dprintk(VIDC_ERR, "%s Invalid args: Inst = %pK\n",
+ __func__, inst);
+ return -EINVAL;
+ }
+
clk_freq_tbl = &inst->core->resources.clock_freq_tbl;
fourcc = inst->session_type == MSM_VIDC_DECODER ?
inst->fmts[OUTPUT_PORT].fourcc :
@@ -498,7 +586,7 @@
inst->session_type);
if (matched) {
- inst->entry = entry;
+ inst->clk_data.entry = entry;
break;
}
}
@@ -512,7 +600,7 @@
return rc;
}
-static inline void msm_dcvs_print_dcvs_stats(struct dcvs_stats *dcvs)
+static inline void msm_dcvs_print_dcvs_stats(struct clock_data *dcvs)
{
dprintk(VIDC_DBG,
"DCVS: Load_Low %d, Load High %d\n",
@@ -524,31 +612,31 @@
dcvs->min_threshold, dcvs->max_threshold);
}
-void msm_dcvs_init(struct msm_vidc_inst *inst)
+void msm_clock_data_reset(struct msm_vidc_inst *inst)
{
struct msm_vidc_core *core;
- int i = 0;
+ int i = 0, rc = 0;
struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
u64 total_freq = 0, rate = 0, load;
int cycles;
- struct dcvs_stats *dcvs;
+ struct clock_data *dcvs;
dprintk(VIDC_DBG, "Init DCVS Load\n");
if (!inst || !inst->core) {
- dprintk(VIDC_ERR, "%s Invalid args: %pK\n", __func__, inst);
+ dprintk(VIDC_ERR, "%s Invalid args: Inst = %pK\n",
+ __func__, inst);
return;
}
core = inst->core;
- dcvs = &inst->dcvs;
- inst->dcvs = (struct dcvs_stats){0};
+ dcvs = &inst->clk_data;
load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS);
- cycles = inst->entry->vpp_cycles;
+ cycles = inst->clk_data.entry->vpp_cycles;
allowed_clks_tbl = core->resources.allowed_clks_tbl;
if (inst->session_type == MSM_VIDC_ENCODER) {
cycles = inst->flags & VIDC_LOW_POWER ?
- inst->entry->low_power_cycles :
+ inst->clk_data.entry->low_power_cycles :
cycles;
dcvs->buffer_type = HAL_BUFFER_INPUT;
@@ -573,7 +661,17 @@
dcvs->load = dcvs->load_high = rate;
dcvs->load_low = allowed_clks_tbl[i+1].clock_rate;
+ inst->clk_data.buffer_counter = 0;
+
msm_dcvs_print_dcvs_stats(dcvs);
+
+ msm_vidc_update_operating_rate(inst);
+
+ rc = msm_comm_scale_clocks_and_bus(inst);
+
+ if (rc)
+ dprintk(VIDC_ERR, "%s Failed to scale Clocks and Bus\n",
+ __func__);
}
int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst,
@@ -585,23 +683,26 @@
}
return buffer_type == HAL_BUFFER_INPUT ?
- inst->dcvs.extra_output_buffer_count :
- inst->dcvs.extra_capture_buffer_count;
+ inst->clk_data.extra_output_buffer_count :
+ inst->clk_data.extra_capture_buffer_count;
}
int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst)
{
int rc = 0;
- bool low_latency_mode;
struct hfi_device *hdev;
struct hal_video_work_mode pdata;
struct hal_enable latency;
- hdev = inst->core->device;
+ if (!inst || !inst->core || !inst->core->device) {
+ dprintk(VIDC_ERR,
+ "%s Invalid args: Inst = %pK\n",
+ __func__, inst);
+ return -EINVAL;
+ }
- low_latency_mode = msm_comm_g_ctrl_for_id(inst,
- V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE);
- if (low_latency_mode) {
+ hdev = inst->core->device;
+ if (inst->clk_data.low_latency_mode) {
pdata.video_work_mode = VIDC_WORK_MODE_1;
goto decision_done;
}
@@ -636,7 +737,7 @@
decision_done:
- inst->work_mode = pdata.video_work_mode;
+ 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);
@@ -646,7 +747,8 @@
/* For WORK_MODE_1, set Low Latency mode by default to HW. */
- if (inst->work_mode == VIDC_WORK_MODE_1) {
+ 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,
@@ -675,8 +777,8 @@
return 0;
}
mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
- if (inst->core->resources.max_hq_mbs_per_frame > mbs_per_frame ||
- inst->core->resources.max_hq_fps > inst->prop.fps) {
+ if (mbs_per_frame >= inst->core->resources.max_hq_mbs_per_frame ||
+ inst->prop.fps >= inst->core->resources.max_hq_fps) {
enable = true;
}
@@ -692,9 +794,12 @@
__func__, inst);
goto fail_power_mode_set;
}
- inst->flags |= VIDC_LOW_POWER;
- dprintk(VIDC_PROF, "Power Save Mode set for inst: %pK\n", inst);
+ inst->flags = enable ?
+ inst->flags | VIDC_LOW_POWER :
+ inst->flags & ~VIDC_LOW_POWER;
+ dprintk(VIDC_PROF,
+ "Power Save Mode for inst: %pK Enable = %d\n", inst, enable);
fail_power_mode_set:
return rc;
}
@@ -704,15 +809,10 @@
{
struct msm_vidc_inst *inst = NULL;
- if (!core) {
- dprintk(VIDC_ERR, "Invalid args: %pK\n", core);
- return -EINVAL;
- }
-
dprintk(VIDC_PROF, "Core %d : Moving all inst to LP mode\n", core_id);
mutex_lock(&core->lock);
list_for_each_entry(inst, &core->instances, list) {
- if (inst->core_id == core_id &&
+ if (inst->clk_data.core_id == core_id &&
inst->session_type == MSM_VIDC_ENCODER)
msm_vidc_power_save_mode_enable(inst, true);
}
@@ -731,19 +831,19 @@
list_for_each_entry(inst, &core->instances, list) {
u32 cycles, lp_cycles;
- if (!inst->core_id && core_id)
+ if (!(inst->clk_data.core_id && core_id))
continue;
if (inst->session_type == MSM_VIDC_DECODER) {
- cycles = lp_cycles = inst->entry->vpp_cycles;
+ cycles = lp_cycles = inst->clk_data.entry->vpp_cycles;
} else if (inst->session_type == MSM_VIDC_ENCODER) {
lp_mode |= inst->flags & VIDC_LOW_POWER;
cycles = lp_mode ?
- inst->entry->low_power_cycles :
- inst->entry->vpp_cycles;
+ inst->clk_data.entry->low_power_cycles :
+ inst->clk_data.entry->vpp_cycles;
} else {
continue;
}
- if (inst->core_id == 3)
+ if (inst->clk_data.core_id == 3)
cycles = cycles / 2;
current_inst_mbs_per_sec = msm_comm_get_inst_load(inst,
@@ -768,10 +868,17 @@
min_load = 0, min_lp_load = 0;
u32 min_core_id, min_lp_core_id;
+ if (!inst || !inst->core || !inst->core->device) {
+ dprintk(VIDC_ERR,
+ "%s Invalid args: Inst = %pK\n",
+ __func__, inst);
+ return -EINVAL;
+ }
+
core = inst->core;
hdev = core->device;
- max_freq = msm_vidc_max_freq(inst);
- inst->core_id = 0;
+ max_freq = msm_vidc_max_freq(inst->core);
+ inst->clk_data.core_id = 0;
core0_load = get_core_load(core, VIDC_CORE_ID_1, false);
core1_load = get_core_load(core, VIDC_CORE_ID_2, false);
@@ -786,11 +893,11 @@
VIDC_CORE_ID_1 : VIDC_CORE_ID_2;
lp_cycles = inst->session_type == MSM_VIDC_ENCODER ?
- inst->entry->low_power_cycles :
- inst->entry->vpp_cycles;
+ inst->clk_data.entry->low_power_cycles :
+ inst->clk_data.entry->vpp_cycles;
current_inst_load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS) *
- inst->entry->vpp_cycles;
+ inst->clk_data.entry->vpp_cycles;
current_inst_lp_load = msm_comm_get_inst_load(inst,
LOAD_CALC_NO_QUIRKS) * lp_cycles;
@@ -814,7 +921,7 @@
if (inst->session_type == MSM_VIDC_ENCODER && hier_mode) {
if (current_inst_load / 2 + core0_load <= max_freq &&
current_inst_load / 2 + core1_load <= max_freq) {
- inst->core_id = VIDC_CORE_ID_3;
+ inst->clk_data.core_id = VIDC_CORE_ID_3;
msm_vidc_power_save_mode_enable(inst, false);
goto decision_done;
}
@@ -825,32 +932,32 @@
core0_lp_load <= max_freq &&
current_inst_lp_load / 2 +
core1_lp_load <= max_freq) {
- inst->core_id = VIDC_CORE_ID_3;
+ inst->clk_data.core_id = VIDC_CORE_ID_3;
msm_vidc_power_save_mode_enable(inst, true);
goto decision_done;
}
}
if (current_inst_load + min_load < max_freq) {
- inst->core_id = min_core_id;
+ inst->clk_data.core_id = min_core_id;
dprintk(VIDC_DBG,
"Selected normally : Core ID = %d\n",
- inst->core_id);
+ inst->clk_data.core_id);
msm_vidc_power_save_mode_enable(inst, false);
} else if (current_inst_lp_load + min_load < max_freq) {
/* Move current instance to LP and return */
- inst->core_id = min_core_id;
+ inst->clk_data.core_id = min_core_id;
dprintk(VIDC_DBG,
"Selected by moving current to LP : Core ID = %d\n",
- inst->core_id);
+ inst->clk_data.core_id);
msm_vidc_power_save_mode_enable(inst, true);
} else if (current_inst_lp_load + min_lp_load < max_freq) {
/* Move all instances to LP mode and return */
- inst->core_id = min_lp_core_id;
+ inst->clk_data.core_id = min_lp_core_id;
dprintk(VIDC_DBG,
"Moved all inst's to LP: Core ID = %d\n",
- inst->core_id);
+ inst->clk_data.core_id);
msm_vidc_move_core_to_power_save_mode(core, min_lp_core_id);
} else {
rc = -EINVAL;
@@ -860,7 +967,7 @@
}
decision_done:
- core_info.video_core_enable_mask = inst->core_id;
+ core_info.video_core_enable_mask = inst->clk_data.core_id;
rc = call_hfi_op(hdev, session_set_property,
(void *)inst->session,
@@ -874,3 +981,4 @@
return rc;
}
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
index d01f074..fe4822b 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
@@ -31,7 +31,8 @@
/* Considering one safeguard buffer */
#define DCVS_BUFFER_SAFEGUARD (DCVS_DEC_EXTRA_OUTPUT_BUFFERS - 1)
-void msm_dcvs_init(struct msm_vidc_inst *inst);
+void msm_clock_data_reset(struct msm_vidc_inst *inst);
+int msm_vidc_update_operating_rate(struct msm_vidc_inst *inst);
int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst,
enum hal_buffer buffer_type);
int msm_dcvs_try_enable(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 853edf5..0920339 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -584,9 +584,9 @@
capture_port_mbs = NUM_MBS_PER_FRAME(inst->prop.width[CAPTURE_PORT],
inst->prop.height[CAPTURE_PORT]);
- if (inst->operating_rate) {
- fps = (inst->operating_rate >> 16) ?
- inst->operating_rate >> 16 : 1;
+ if (inst->clk_data.operating_rate) {
+ fps = (inst->clk_data.operating_rate >> 16) ?
+ inst->clk_data.operating_rate >> 16 : 1;
/*
* Check if operating rate is less than fps.
* If Yes, then use fps to scale clocks
@@ -2510,7 +2510,7 @@
}
tl = msm_comm_vidc_thermal_level(vidc_driver->thermal_level);
- freq = core->freq;
+ freq = core->curr_freq;
is_turbo = is_core_turbo(core, freq);
dprintk(VIDC_DBG,
@@ -4738,9 +4738,9 @@
return 0;
}
- // Finish FLUSH As Soon As Possible.
- inst->dcvs.buffer_counter = 0;
- msm_comm_scale_clocks_and_bus(inst);
+ /* Finish FLUSH As Soon As Possible. */
+
+ msm_clock_data_reset(inst);
msm_comm_flush_dynamic_buffers(inst);
@@ -5474,7 +5474,7 @@
}
core = inst->core;
- dprintk(VIDC_ERR, "Venus core frequency = %lu", core->freq);
+ dprintk(VIDC_ERR, "Venus core frequency = %lu", core->curr_freq);
mutex_lock(&core->lock);
dprintk(VIDC_ERR, "Printing instance info that caused Error\n");
msm_comm_print_inst_info(inst);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 15ee8a8..f62c132 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -26,12 +26,10 @@
int msm_vidc_fw_low_power_mode = 1;
int msm_vidc_hw_rsp_timeout = 2000;
bool msm_vidc_fw_coverage = !true;
-bool msm_vidc_dec_dcvs_mode = true;
-bool msm_vidc_enc_dcvs_mode = true;
bool msm_vidc_sys_idle_indicator = !true;
int msm_vidc_firmware_unload_delay = 15000;
bool msm_vidc_thermal_mitigation_disabled = !true;
-bool msm_vidc_bitrate_clock_scaling = true;
+bool msm_vidc_clock_scaling = true;
bool msm_vidc_debug_timeout = !true;
#define MAX_DBG_BUF_SIZE 4096
@@ -174,8 +172,6 @@
__debugfs_create(x32, "fw_level", &msm_vidc_fw_debug) &&
__debugfs_create(u32, "fw_debug_mode", &msm_vidc_fw_debug_mode) &&
__debugfs_create(bool, "fw_coverage", &msm_vidc_fw_coverage) &&
- __debugfs_create(bool, "dcvs_dec_mode", &msm_vidc_dec_dcvs_mode) &&
- __debugfs_create(bool, "dcvs_enc_mode", &msm_vidc_enc_dcvs_mode) &&
__debugfs_create(u32, "fw_low_power_mode",
&msm_vidc_fw_low_power_mode) &&
__debugfs_create(u32, "debug_output", &msm_vidc_debug_out) &&
@@ -186,8 +182,8 @@
&msm_vidc_firmware_unload_delay) &&
__debugfs_create(bool, "disable_thermal_mitigation",
&msm_vidc_thermal_mitigation_disabled) &&
- __debugfs_create(bool, "bitrate_clock_scaling",
- &msm_vidc_bitrate_clock_scaling) &&
+ __debugfs_create(bool, "clock_scaling",
+ &msm_vidc_clock_scaling) &&
__debugfs_create(bool, "debug_timeout",
&msm_vidc_debug_timeout);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index cf5ce22..f5c8e5a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -59,12 +59,10 @@
extern int msm_vidc_fw_low_power_mode;
extern int msm_vidc_hw_rsp_timeout;
extern bool msm_vidc_fw_coverage;
-extern bool msm_vidc_dec_dcvs_mode;
-extern bool msm_vidc_enc_dcvs_mode;
extern bool msm_vidc_sys_idle_indicator;
extern int msm_vidc_firmware_unload_delay;
extern bool msm_vidc_thermal_mitigation_disabled;
-extern bool msm_vidc_bitrate_clock_scaling;
+extern bool msm_vidc_clock_scaling;
extern bool msm_vidc_debug_timeout;
#define VIDC_MSG_PRIO2STRING(__level) ({ \
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 53bc068..37bccbd 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -52,7 +52,7 @@
/* Maintains the number of FTB's between each FBD over a window */
-#define DCVS_FTB_WINDOW 32
+#define DCVS_FTB_WINDOW 16
#define V4L2_EVENT_VIDC_BASE 10
@@ -205,7 +205,7 @@
int ebd;
};
-struct dcvs_stats {
+struct clock_data {
int buffer_counter;
int load;
int load_low;
@@ -215,6 +215,15 @@
unsigned int extra_capture_buffer_count;
unsigned int extra_output_buffer_count;
enum hal_buffer buffer_type;
+ bool dcvs_mode;
+ unsigned long bitrate;
+ unsigned long min_freq;
+ unsigned long curr_freq;
+ u32 operating_rate;
+ struct clock_profile_entry *entry;
+ u32 core_id;
+ enum hal_work_mode work_mode;
+ bool low_latency_mode;
};
struct profile_data {
@@ -259,7 +268,8 @@
struct msm_vidc_capability *capabilities;
struct delayed_work fw_unload_work;
bool smmu_fault_handled;
- unsigned long freq;
+ unsigned long min_freq;
+ unsigned long curr_freq;
};
struct msm_vidc_inst {
@@ -293,28 +303,21 @@
void *priv;
struct msm_vidc_debug debug;
struct buf_count count;
- struct dcvs_stats dcvs;
+ struct clock_data clk_data;
enum msm_vidc_modes flags;
struct msm_vidc_capability capability;
u32 buffer_size_limit;
enum buffer_mode_type buffer_mode_set[MAX_PORT_NUM];
struct v4l2_ctrl **ctrls;
- bool dcvs_mode;
enum msm_vidc_pixel_depth bit_depth;
struct kref kref;
- unsigned long bitrate;
- unsigned long freq;
u32 buffers_held_in_driver;
atomic_t in_flush;
u32 pic_struct;
u32 colour_space;
- u32 operating_rate;
u32 profile;
u32 level;
u32 entropy_mode;
- struct clock_profile_entry *entry;
- u32 core_id;
- enum hal_work_mode work_mode;
};
extern struct msm_vidc_drv *vidc_driver;