diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 3faa5aaf9d03..89c7590ad121 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2675,11 +2675,11 @@ static void adreno_pwrlevel_change_settings(struct kgsl_device *device, } static void adreno_clk_set_options(struct kgsl_device *device, const char *name, - struct clk *clk) + struct clk *clk, bool on) { if (ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options) ADRENO_GPU_DEVICE(ADRENO_DEVICE(device))->clk_set_options( - ADRENO_DEVICE(device), name, clk); + ADRENO_DEVICE(device), name, clk, on); } static void adreno_iommu_sync(struct kgsl_device *device, bool sync) diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 33fdb9ae11fa..218d08e6dfc3 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -789,7 +789,7 @@ struct adreno_gpudev { void (*preemption_schedule)(struct adreno_device *); void (*enable_64bit)(struct adreno_device *); void (*clk_set_options)(struct adreno_device *, - const char *, struct clk *); + const char *, struct clk *, bool on); }; /** diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 87300096fbf1..0715022be6e3 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1640,11 +1640,15 @@ static void a5xx_pwrlevel_change_settings(struct adreno_device *adreno_dev, } static void a5xx_clk_set_options(struct adreno_device *adreno_dev, - const char *name, struct clk *clk) + const char *name, struct clk *clk, bool on) { + + if (!adreno_is_a540(adreno_dev) && !adreno_is_a512(adreno_dev) && + !adreno_is_a508(adreno_dev)) + return; + /* Handle clock settings for GFX PSCBCs */ - if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev) || - adreno_is_a508(adreno_dev)) { + if (on) { if (!strcmp(name, "mem_iface_clk")) { clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); @@ -1652,6 +1656,11 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev, clk_set_flags(clk, CLKFLAG_RETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_RETAIN_MEM); } + } else { + if (!strcmp(name, "core_clk")) { + clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); + clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); + } } } diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index aca484618268..177b283a2dda 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -166,7 +166,7 @@ struct kgsl_functable { unsigned int prelevel, unsigned int postlevel, bool post); void (*regulator_disable_poll)(struct kgsl_device *device); void (*clk_set_options)(struct kgsl_device *device, - const char *name, struct clk *clk); + const char *name, struct clk *clk, bool on); void (*gpu_model)(struct kgsl_device *device, char *str, size_t bufsz); void (*stop_fault_timer)(struct kgsl_device *device); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index e4c431546d2a..9a2864bfd811 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -2003,10 +2003,6 @@ static int _get_clocks(struct kgsl_device *device) if (!strcmp(name, "isense_clk")) pwr->isense_clk_indx = i; - - if (device->ftbl->clk_set_options) - device->ftbl->clk_set_options(device, name, - pwr->grp_clks[i]); break; } } @@ -2453,6 +2449,22 @@ static void kgsl_pwrctrl_disable(struct kgsl_device *device) kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_OFF); } +static void +kgsl_pwrctrl_clk_set_options(struct kgsl_device *device, bool on) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + int i; + + for (i = 0; i < KGSL_MAX_CLKS; i++) { + if (pwr->grp_clks[i] == NULL) + continue; + + if (device->ftbl->clk_set_options) + device->ftbl->clk_set_options(device, clocks[i], + pwr->grp_clks[i], on); + } +} + /** * _init() - Get the GPU ready to start, but don't turn anything on * @device - Pointer to the kgsl_device struct @@ -2499,6 +2511,7 @@ static int _wake(struct kgsl_device *device) device->ftbl->resume(device); /* fall through */ case KGSL_STATE_SLUMBER: + kgsl_pwrctrl_clk_set_options(device, true); status = device->ftbl->start(device, device->pwrctrl.superfast); device->pwrctrl.superfast = false; @@ -2535,6 +2548,7 @@ static int _wake(struct kgsl_device *device) device->pwrctrl.interval_timeout); break; case KGSL_STATE_AWARE: + kgsl_pwrctrl_clk_set_options(device, true); /* Enable state before turning on irq */ kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); @@ -2649,6 +2663,7 @@ _slumber(struct kgsl_device *device) status = kgsl_pwrctrl_enable(device); device->ftbl->suspend_context(device); device->ftbl->stop(device); + kgsl_pwrctrl_clk_set_options(device, false); kgsl_pwrctrl_disable(device); kgsl_pwrscale_sleep(device); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);