diff options
author | Ruofei Ma <ruofeim@google.com> | 2022-08-19 01:32:28 +0000 |
---|---|---|
committer | Jason Chiu <jasoncschiu@google.com> | 2022-08-24 16:19:14 +0000 |
commit | 94a11b80719b79a2cd34a671096cad9986ffa800 (patch) | |
tree | 918613bba4165a94434e2254c65ff24a1f72dace | |
parent | f5dffbcb1a0c188baae150e69a530740b3d466cd (diff) | |
download | gchips-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.c | 41 | ||||
-rw-r--r-- | bigo_pm.c | 35 | ||||
-rw-r--r-- | bigo_pm.h | 2 | ||||
-rw-r--r-- | bigo_priv.h | 2 |
4 files changed, 68 insertions, 12 deletions
@@ -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); @@ -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); } @@ -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); |