summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuofei Ma <ruofeim@google.com>2022-08-19 01:32:28 +0000
committerJason Chiu <jasoncschiu@google.com>2022-08-24 16:19:14 +0000
commit94a11b80719b79a2cd34a671096cad9986ffa800 (patch)
tree918613bba4165a94434e2254c65ff24a1f72dace
parentf5dffbcb1a0c188baae150e69a530740b3d466cd (diff)
downloadgchips-94a11b80719b79a2cd34a671096cad9986ffa800.tar.gz
bigocean turn off clocks in idle state
Turn off bigocean clocks when it is idle for predefined timout. This change is to save the power when user holds onto bigocean instance but are not actually playing any video. This can happen with video pause or app bug. Bug: 242975531 Bug: 243650406 Signed-off-by: Ruofei Ma <ruofeim@google.com> Change-Id: Ie4fa8ac0e3b5dcc9d552b257b8c32649a43d873c (cherry picked from commit 51480d7d5ad2fbe2b18624ad266c390dded132ce)
-rw-r--r--bigo.c41
-rw-r--r--bigo_pm.c35
-rw-r--r--bigo_pm.h2
-rw-r--r--bigo_priv.h2
4 files changed, 68 insertions, 12 deletions
diff --git a/bigo.c b/bigo.c
index 99e8558..0d9ac36 100644
--- a/bigo.c
+++ b/bigo.c
@@ -38,6 +38,8 @@
#define BIGO_MAX_INST_NUM 16
#define BIGO_HBD_BIT BIT(17)
+#define BIGO_IDLE_TIMEOUT_MS 1000
+
static int bigo_worker_thread(void *data);
static struct sscd_platform_data bigo_sscd_platdata;
@@ -174,7 +176,7 @@ static int bigo_open(struct inode *inode, struct file *file)
}
list_add_tail(&inst->list, &core->instances);
mutex_unlock(&core->lock);
- bigo_update_qos(core);
+ bigo_mark_qos_dirty(core);
pr_info("opened instance\n");
return rc;
@@ -193,6 +195,7 @@ static void bigo_close(struct kref *ref)
if (inst && inst->core) {
clear_job_from_prioq(inst->core, inst);
bigo_unmap_all(inst);
+ bigo_mark_qos_dirty(inst->core);
bigo_update_qos(inst->core);
kfree(inst->job.regs);
kfree(inst);
@@ -268,7 +271,7 @@ inline void bigo_config_frmrate(struct bigo_inst *inst, __u32 frmrate)
mutex_lock(&inst->lock);
inst->fps = frmrate;
mutex_unlock(&inst->lock);
- bigo_update_qos(inst->core);
+ bigo_mark_qos_dirty(inst->core);
}
inline void bigo_config_frmsize(struct bigo_inst *inst,
@@ -278,7 +281,7 @@ inline void bigo_config_frmsize(struct bigo_inst *inst,
inst->height = frmsize->height;
inst->width = frmsize->width;
mutex_unlock(&inst->lock);
- bigo_update_qos(inst->core);
+ bigo_mark_qos_dirty(inst->core);
}
inline void bigo_config_secure(struct bigo_inst *inst, __u32 is_secure)
@@ -391,7 +394,7 @@ static long bigo_unlocked_ioctl(struct file *file, unsigned int cmd,
bpp = hbd ? 2:1;
if (bpp != inst->bpp) {
inst->bpp = bpp;
- bigo_update_qos(core);
+ bigo_mark_qos_dirty(core);
}
if(enqueue_prioq(core, inst)) {
@@ -570,11 +573,20 @@ static void deinit_chardev(struct bigo_core *core)
unregister_chrdev_region(core->devno, 1);
}
+static inline void mark_instances_idle(struct bigo_core *core)
+{
+ struct bigo_inst *curr_inst;
+ mutex_lock(&core->lock);
+ list_for_each_entry(curr_inst, &core->instances, list)
+ curr_inst->idle = true;
+ mutex_unlock(&core->lock);
+}
+
static int bigo_worker_thread(void *data)
{
struct bigo_core *core = (struct bigo_core *)data;
struct bigo_inst *inst;
- struct bigo_job *job;
+ struct bigo_job *job = NULL;
bool should_stop;
int rc;
@@ -582,8 +594,21 @@ static int bigo_worker_thread(void *data)
return -ENOMEM;
while(1) {
- wait_event(core->worker,
- dequeue_prioq(core, &job, &should_stop));
+ rc = wait_event_timeout(core->worker,
+ dequeue_prioq(core, &job, &should_stop),
+ msecs_to_jiffies(BIGO_IDLE_TIMEOUT_MS));
+ if (!rc && !should_stop) {
+ /* Mark all instances as IDLE since none of these
+ * instances queued a job for BIGO_IDLE_TIMEOUT_MS
+ */
+ mark_instances_idle(core);
+ bigo_clocks_off(core);
+ bigo_mark_qos_dirty(core);
+ pr_info("bigocean entered idle state\n");
+ wait_event(core->worker,
+ dequeue_prioq(core, &job, &should_stop));
+ pr_info("bigocean resumed to work\n");
+ }
if(should_stop) {
pr_info("worker thread received stop signal, exit\n");
return 0;
@@ -592,6 +617,8 @@ static int bigo_worker_thread(void *data)
continue;
inst = container_of(job, struct bigo_inst, job);
+ inst->idle = false;
+ bigo_update_qos(core);
if (inst->is_secure) {
rc = exynos_smc(SMC_PROTECTION_SET, 0, BIGO_SMC_ID,
SMC_PROTECTION_ENABLE);
diff --git a/bigo_pm.c b/bigo_pm.c
index 8bd0e2a..ff98fb1 100644
--- a/bigo_pm.c
+++ b/bigo_pm.c
@@ -29,6 +29,8 @@ static inline u32 bigo_get_total_load(struct bigo_core *core)
return 0;
list_for_each_entry(inst, &core->instances, list) {
+ if (inst->idle)
+ continue;
curr_load = inst->width * inst->height * inst->fps / 1024;
if (curr_load < core->pm.max_load - load) {
load += curr_load;
@@ -51,6 +53,8 @@ static inline void update_mif_floor(struct bigo_core *core)
if (!list_empty(&core->instances)) {
list_for_each_entry(inst, &core->instances, list) {
+ if (inst->idle)
+ continue;
curr_load = inst->width * inst->height * inst->fps * inst->bpp / 1024;
load += curr_load;
}
@@ -129,18 +133,39 @@ static int bigo_scale_bw(struct bigo_core *core)
return bts_update_bw(core->pm.bwindex, bw);
}
+void bigo_mark_qos_dirty(struct bigo_core *core)
+{
+ mutex_lock(&core->lock);
+ core->qos_dirty = true;
+ mutex_unlock(&core->lock);
+}
+
void bigo_update_qos(struct bigo_core *core)
{
int rc;
mutex_lock(&core->lock);
- rc = bigo_scale_bw(core);
+ if (core->qos_dirty) {
+ rc = bigo_scale_bw(core);
+ if (rc)
+ pr_warn("%s: failed to scale bandwidth: %d\n", __func__, rc);
+
+ update_mif_floor(core);
+ bigo_scale_freq(core);
+ core->qos_dirty = false;
+ }
+ mutex_unlock(&core->lock);
+}
+
+void bigo_clocks_off(struct bigo_core *core)
+{
+ struct bts_bw bw;
- if (rc)
- pr_warn("%s: failed to scale bandwidth: %d\n", __func__, rc);
+ memset(&bw, 0, sizeof(struct bts_bw));
- update_mif_floor(core);
- bigo_scale_freq(core);
+ mutex_lock(&core->lock);
+ bts_update_bw(core->pm.bwindex, bw);
+ bigo_set_freq(core, bigo_get_target_freq(core, 0));
mutex_unlock(&core->lock);
}
diff --git a/bigo_pm.h b/bigo_pm.h
index c571b87..50064a5 100644
--- a/bigo_pm.h
+++ b/bigo_pm.h
@@ -21,5 +21,7 @@ int bigo_runtime_suspend(struct device *dev);
int bigo_runtime_resume(struct device *dev);
#endif
void bigo_update_qos(struct bigo_core *core);
+void bigo_clocks_off(struct bigo_core *core);
+void bigo_mark_qos_dirty(struct bigo_core *core);
#endif //_BIGO_PM_H_
diff --git a/bigo_priv.h b/bigo_priv.h
index e951229..ee3d59e 100644
--- a/bigo_priv.h
+++ b/bigo_priv.h
@@ -113,6 +113,7 @@ struct bigo_core {
struct task_struct *worker_thread;
wait_queue_head_t worker;
struct bigo_prio_array prioq;
+ u32 qos_dirty;
};
struct bigo_inst {
@@ -135,6 +136,7 @@ struct bigo_inst {
struct bigo_job job;
/* bytes per pixel */
u32 bpp;
+ bool idle;
};
inline void set_curr_inst(struct bigo_core *core, struct bigo_inst *inst);