Loading drivers/gpu/msm/Kconfig +19 −0 Original line number Diff line number Diff line Loading @@ -10,8 +10,27 @@ config QCOM_KGSL on QTI targets. This includes power management, memory management, and scheduling for the Adreno GPUs. config DEVFREQ_GOV_QCOM_ADRENO_TZ tristate "Qualcomm Technologies, Inc. GPU frequency governor" depends on PM_DEVFREQ && QCOM_KGSL help GPU frequency governor for the Adreno GPU. Sets the frequency using an "on demand" algorithm in conjunction with other components on Adreno platforms. This is not useful for non-Adreno devices. config DEVFREQ_GOV_QCOM_GPUBW_MON tristate "Qualcomm Technologies, Inc. GPU bandwidth governor" depends on DEVFREQ_GOV_QCOM_ADRENO_TZ help This governor works together with the Adreno GPU governor to select bus frequency votes using an "on-demand" algorithm. This governor will not be useful for non-Adreno based targets. config QCOM_ADRENO_DEFAULT_GOVERNOR string "devfreq governor for the adreno core" default "msm-adreno-tz" if DEVFREQ_GOV_QCOM_ADRENO_TZ default "simple_ondemand" depends on QCOM_KGSL Loading drivers/gpu/msm/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -52,3 +52,6 @@ msm_kgsl-$(CONFIG_COMPAT) += adreno_compat.o msm_kgsl-$(CONFIG_QCOM_KGSL_CORESIGHT) += adreno_coresight.o msm_kgsl-$(CONFIG_DEBUG_FS) += adreno_debugfs.o adreno_profile.o msm_kgsl-$(CONFIG_ARM_SMMU) += adreno_iommu.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_ADRENO_TZ) += governor_msm_adreno_tz.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_GPUBW_MON) += governor_gpubw_mon.o drivers/gpu/msm/adreno.c +59 −14 Original line number Diff line number Diff line Loading @@ -842,7 +842,7 @@ static void adreno_of_get_ca_target_pwrlevel(struct adreno_device *adreno_dev, of_property_read_u32(node, "qcom,ca-target-pwrlevel", &ca_target_pwrlevel); if (ca_target_pwrlevel > device->pwrctrl.num_pwrlevels - 2) if (ca_target_pwrlevel >= device->pwrctrl.num_pwrlevels) ca_target_pwrlevel = 1; device->pwrscale.ctxt_aware_target_pwrlevel = ca_target_pwrlevel; Loading Loading @@ -907,15 +907,27 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, pwr->num_pwrlevels = 0; for_each_child_of_node(node, child) { unsigned int index; unsigned int index, freq = 0; struct kgsl_pwrlevel *level; if (of_property_read_u32(child, "reg", &index)) { dev_err(device->dev, "%pOF: powerlevel index not found\n", child); of_node_put(child); return -EINVAL; } if (of_property_read_u32(child, "qcom,gpu-freq", &freq)) { dev_err(device->dev, "%pOF: Unable to read qcom,gpu-freq\n", child); of_node_put(child); return -EINVAL; } /* Ignore "zero" powerlevels */ if (!freq) continue; if (index >= KGSL_MAX_PWRLEVELS) { dev_err(device->dev, "%pOF: Pwrlevel index %d is out of range\n", Loading @@ -928,12 +940,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, level = &pwr->pwrlevels[index]; if (of_property_read_u32(child, "qcom,gpu-freq", &level->gpu_freq)) { dev_err(device->dev, "%pOF: Unable to read qcom,gpu-freq\n", child); return -EINVAL; } level->gpu_freq = freq; of_property_read_u32(child, "qcom,acd-level", &level->acd_level); Loading @@ -944,6 +951,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, dev_err(device->dev, "%pOF: Couldn't read the bus frequency for power level %d\n", child, index); of_node_put(child); return ret; } Loading @@ -968,7 +976,7 @@ static void adreno_of_get_initial_pwrlevel(struct adreno_device *adreno_dev, of_property_read_u32(node, "qcom,initial-pwrlevel", &init_level); if (init_level < 0 || init_level > pwr->num_pwrlevels) if (init_level < 0 || init_level >= pwr->num_pwrlevels) init_level = 1; pwr->active_pwrlevel = init_level; Loading Loading @@ -1613,6 +1621,43 @@ static int adreno_remove(struct platform_device *pdev) return 0; } static int adreno_pm_resume(struct device *dev) { struct kgsl_device *device = dev_get_drvdata(dev); mutex_lock(&device->mutex); if (device->state == KGSL_STATE_SUSPEND) { adreno_dispatcher_unhalt(device); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); } else if (device->state != KGSL_STATE_INIT) { /* * This is an error situation so wait for the device to idle and * then put the device in SLUMBER state. This will get us to * the right place when we resume. */ if (device->state == KGSL_STATE_ACTIVE) adreno_idle(device); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); dev_err(device->dev, "resume invoked without a suspend\n"); } mutex_unlock(&device->mutex); return 0; } static int adreno_pm_suspend(struct device *dev) { struct kgsl_device *device = dev_get_drvdata(dev); int status; mutex_lock(&device->mutex); status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); if (!status && device->state == KGSL_STATE_SUSPEND) adreno_dispatcher_halt(device); mutex_unlock(&device->mutex); return status; } static void adreno_fault_detect_init(struct adreno_device *adreno_dev) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); Loading Loading @@ -3741,21 +3786,21 @@ static const struct kgsl_functable adreno_functable = { .clk_set_options = adreno_clk_set_options, .gpu_model = adreno_gpu_model, .stop_fault_timer = adreno_dispatcher_stop_fault_timer, .dispatcher_halt = adreno_dispatcher_halt, .dispatcher_unhalt = adreno_dispatcher_unhalt, .query_property_list = adreno_query_property_list, .is_hwcg_on = adreno_is_hwcg_on, }; static const struct dev_pm_ops adreno_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(adreno_pm_suspend, adreno_pm_resume) }; static struct platform_driver adreno_platform_driver = { .probe = adreno_probe, .remove = adreno_remove, .suspend = kgsl_suspend_driver, .resume = kgsl_resume_driver, .id_table = adreno_id_table, .driver = { .name = "kgsl-3d", .pm = &kgsl_pm_ops, .pm = &adreno_pm_ops, .of_match_table = adreno_match_table, } }; Loading drivers/gpu/msm/adreno_a5xx.c +3 −4 Original line number Diff line number Diff line Loading @@ -934,14 +934,13 @@ static uint32_t _write_voltage_table(struct adreno_device *adreno_dev, const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); int i; struct dev_pm_opp *opp; int levels = pwr->num_pwrlevels - 1; unsigned int mvolt = 0; kgsl_regwrite(device, addr++, a5xx_core->max_power); kgsl_regwrite(device, addr++, levels); kgsl_regwrite(device, addr++, pwr->num_pwrlevels); /* Write voltage in mV and frequency in MHz */ for (i = 0; i < levels; i++) { for (i = 0; i < pwr->num_pwrlevels; i++) { opp = dev_pm_opp_find_freq_exact(&device->pdev->dev, pwr->pwrlevels[i].gpu_freq, true); /* _opp_get returns uV, convert to mV */ Loading @@ -953,7 +952,7 @@ static uint32_t _write_voltage_table(struct adreno_device *adreno_dev, kgsl_regwrite(device, addr++, pwr->pwrlevels[i].gpu_freq / 1000000); } return (levels * 2 + 2); return (pwr->num_pwrlevels * 2 + 2); } static uint32_t lm_limit(struct adreno_device *adreno_dev) Loading drivers/gpu/msm/adreno_a6xx_gmu.c +2 −1 Original line number Diff line number Diff line Loading @@ -830,7 +830,8 @@ static int a6xx_gmu_gfx_rail_on(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); unsigned int perf_idx = pwr->num_pwrlevels - pwr->default_pwrlevel - 1; unsigned int perf_idx = gmu->num_gpupwrlevels - pwr->default_pwrlevel - 1; uint32_t default_opp = gmu->rpmh_votes.gx_votes[perf_idx]; gmu_core_regwrite(device, A6XX_GMU_BOOT_SLUMBER_OPTION, Loading Loading
drivers/gpu/msm/Kconfig +19 −0 Original line number Diff line number Diff line Loading @@ -10,8 +10,27 @@ config QCOM_KGSL on QTI targets. This includes power management, memory management, and scheduling for the Adreno GPUs. config DEVFREQ_GOV_QCOM_ADRENO_TZ tristate "Qualcomm Technologies, Inc. GPU frequency governor" depends on PM_DEVFREQ && QCOM_KGSL help GPU frequency governor for the Adreno GPU. Sets the frequency using an "on demand" algorithm in conjunction with other components on Adreno platforms. This is not useful for non-Adreno devices. config DEVFREQ_GOV_QCOM_GPUBW_MON tristate "Qualcomm Technologies, Inc. GPU bandwidth governor" depends on DEVFREQ_GOV_QCOM_ADRENO_TZ help This governor works together with the Adreno GPU governor to select bus frequency votes using an "on-demand" algorithm. This governor will not be useful for non-Adreno based targets. config QCOM_ADRENO_DEFAULT_GOVERNOR string "devfreq governor for the adreno core" default "msm-adreno-tz" if DEVFREQ_GOV_QCOM_ADRENO_TZ default "simple_ondemand" depends on QCOM_KGSL Loading
drivers/gpu/msm/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -52,3 +52,6 @@ msm_kgsl-$(CONFIG_COMPAT) += adreno_compat.o msm_kgsl-$(CONFIG_QCOM_KGSL_CORESIGHT) += adreno_coresight.o msm_kgsl-$(CONFIG_DEBUG_FS) += adreno_debugfs.o adreno_profile.o msm_kgsl-$(CONFIG_ARM_SMMU) += adreno_iommu.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_ADRENO_TZ) += governor_msm_adreno_tz.o obj-$(CONFIG_DEVFREQ_GOV_QCOM_GPUBW_MON) += governor_gpubw_mon.o
drivers/gpu/msm/adreno.c +59 −14 Original line number Diff line number Diff line Loading @@ -842,7 +842,7 @@ static void adreno_of_get_ca_target_pwrlevel(struct adreno_device *adreno_dev, of_property_read_u32(node, "qcom,ca-target-pwrlevel", &ca_target_pwrlevel); if (ca_target_pwrlevel > device->pwrctrl.num_pwrlevels - 2) if (ca_target_pwrlevel >= device->pwrctrl.num_pwrlevels) ca_target_pwrlevel = 1; device->pwrscale.ctxt_aware_target_pwrlevel = ca_target_pwrlevel; Loading Loading @@ -907,15 +907,27 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, pwr->num_pwrlevels = 0; for_each_child_of_node(node, child) { unsigned int index; unsigned int index, freq = 0; struct kgsl_pwrlevel *level; if (of_property_read_u32(child, "reg", &index)) { dev_err(device->dev, "%pOF: powerlevel index not found\n", child); of_node_put(child); return -EINVAL; } if (of_property_read_u32(child, "qcom,gpu-freq", &freq)) { dev_err(device->dev, "%pOF: Unable to read qcom,gpu-freq\n", child); of_node_put(child); return -EINVAL; } /* Ignore "zero" powerlevels */ if (!freq) continue; if (index >= KGSL_MAX_PWRLEVELS) { dev_err(device->dev, "%pOF: Pwrlevel index %d is out of range\n", Loading @@ -928,12 +940,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, level = &pwr->pwrlevels[index]; if (of_property_read_u32(child, "qcom,gpu-freq", &level->gpu_freq)) { dev_err(device->dev, "%pOF: Unable to read qcom,gpu-freq\n", child); return -EINVAL; } level->gpu_freq = freq; of_property_read_u32(child, "qcom,acd-level", &level->acd_level); Loading @@ -944,6 +951,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev, dev_err(device->dev, "%pOF: Couldn't read the bus frequency for power level %d\n", child, index); of_node_put(child); return ret; } Loading @@ -968,7 +976,7 @@ static void adreno_of_get_initial_pwrlevel(struct adreno_device *adreno_dev, of_property_read_u32(node, "qcom,initial-pwrlevel", &init_level); if (init_level < 0 || init_level > pwr->num_pwrlevels) if (init_level < 0 || init_level >= pwr->num_pwrlevels) init_level = 1; pwr->active_pwrlevel = init_level; Loading Loading @@ -1613,6 +1621,43 @@ static int adreno_remove(struct platform_device *pdev) return 0; } static int adreno_pm_resume(struct device *dev) { struct kgsl_device *device = dev_get_drvdata(dev); mutex_lock(&device->mutex); if (device->state == KGSL_STATE_SUSPEND) { adreno_dispatcher_unhalt(device); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); } else if (device->state != KGSL_STATE_INIT) { /* * This is an error situation so wait for the device to idle and * then put the device in SLUMBER state. This will get us to * the right place when we resume. */ if (device->state == KGSL_STATE_ACTIVE) adreno_idle(device); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); dev_err(device->dev, "resume invoked without a suspend\n"); } mutex_unlock(&device->mutex); return 0; } static int adreno_pm_suspend(struct device *dev) { struct kgsl_device *device = dev_get_drvdata(dev); int status; mutex_lock(&device->mutex); status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); if (!status && device->state == KGSL_STATE_SUSPEND) adreno_dispatcher_halt(device); mutex_unlock(&device->mutex); return status; } static void adreno_fault_detect_init(struct adreno_device *adreno_dev) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); Loading Loading @@ -3741,21 +3786,21 @@ static const struct kgsl_functable adreno_functable = { .clk_set_options = adreno_clk_set_options, .gpu_model = adreno_gpu_model, .stop_fault_timer = adreno_dispatcher_stop_fault_timer, .dispatcher_halt = adreno_dispatcher_halt, .dispatcher_unhalt = adreno_dispatcher_unhalt, .query_property_list = adreno_query_property_list, .is_hwcg_on = adreno_is_hwcg_on, }; static const struct dev_pm_ops adreno_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(adreno_pm_suspend, adreno_pm_resume) }; static struct platform_driver adreno_platform_driver = { .probe = adreno_probe, .remove = adreno_remove, .suspend = kgsl_suspend_driver, .resume = kgsl_resume_driver, .id_table = adreno_id_table, .driver = { .name = "kgsl-3d", .pm = &kgsl_pm_ops, .pm = &adreno_pm_ops, .of_match_table = adreno_match_table, } }; Loading
drivers/gpu/msm/adreno_a5xx.c +3 −4 Original line number Diff line number Diff line Loading @@ -934,14 +934,13 @@ static uint32_t _write_voltage_table(struct adreno_device *adreno_dev, const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev); int i; struct dev_pm_opp *opp; int levels = pwr->num_pwrlevels - 1; unsigned int mvolt = 0; kgsl_regwrite(device, addr++, a5xx_core->max_power); kgsl_regwrite(device, addr++, levels); kgsl_regwrite(device, addr++, pwr->num_pwrlevels); /* Write voltage in mV and frequency in MHz */ for (i = 0; i < levels; i++) { for (i = 0; i < pwr->num_pwrlevels; i++) { opp = dev_pm_opp_find_freq_exact(&device->pdev->dev, pwr->pwrlevels[i].gpu_freq, true); /* _opp_get returns uV, convert to mV */ Loading @@ -953,7 +952,7 @@ static uint32_t _write_voltage_table(struct adreno_device *adreno_dev, kgsl_regwrite(device, addr++, pwr->pwrlevels[i].gpu_freq / 1000000); } return (levels * 2 + 2); return (pwr->num_pwrlevels * 2 + 2); } static uint32_t lm_limit(struct adreno_device *adreno_dev) Loading
drivers/gpu/msm/adreno_a6xx_gmu.c +2 −1 Original line number Diff line number Diff line Loading @@ -830,7 +830,8 @@ static int a6xx_gmu_gfx_rail_on(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); unsigned int perf_idx = pwr->num_pwrlevels - pwr->default_pwrlevel - 1; unsigned int perf_idx = gmu->num_gpupwrlevels - pwr->default_pwrlevel - 1; uint32_t default_opp = gmu->rpmh_votes.gx_votes[perf_idx]; gmu_core_regwrite(device, A6XX_GMU_BOOT_SLUMBER_OPTION, Loading