[PATCH 4/4] drm/amd/powerplay: support retrieving and adjusting dcefclock power levels
Alex Deucher
alexdeucher at gmail.com
Mon Jan 14 16:59:50 UTC 2019
On Mon, Jan 14, 2019 at 5:02 AM Evan Quan <evan.quan at amd.com> wrote:
>
> User can use "pp_dpm_dcefclk" to retrieve and adjust dcefclock power
> levels.
>
> Change-Id: Ia3f61558ca96104c88d129ba5194103b2fe702ec
> Signed-off-by: Evan Quan <evan.quan at amd.com>
We should probably find a way to hide these new files on asics which
don't support them. Other than that, the series looks good to me.
Alex
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 53 ++++++++++++++++++-
> .../gpu/drm/amd/include/kgd_pp_interface.h | 1 +
> .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 52 +++++++++++++++++-
> 3 files changed, 103 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> index f6646a522c06..b7b70f590236 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
> @@ -731,11 +731,13 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
> }
>
> /**
> - * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_pcie
> + * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk
> + * pp_dpm_pcie
> *
> * The amdgpu driver provides a sysfs API for adjusting what power levels
> * are enabled for a given power state. The files pp_dpm_sclk, pp_dpm_mclk,
> - * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
> + * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are used for
> + * this.
> *
> * Reading back the files will show you the available power levels within
> * the power state and the clock information for those levels.
> @@ -745,6 +747,8 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
> * Secondly,Enter a new value for each level by inputing a string that
> * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie"
> * E.g., echo 4 5 6 to > pp_dpm_sclk will enable sclk levels 4, 5, and 6.
> + *
> + * NOTE: change to the dcefclk max dpm level is not supported now
> */
>
> static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
> @@ -927,6 +931,42 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
> return count;
> }
>
> +static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct drm_device *ddev = dev_get_drvdata(dev);
> + struct amdgpu_device *adev = ddev->dev_private;
> +
> + if (adev->powerplay.pp_funcs->print_clock_levels)
> + return amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf);
> + else
> + return snprintf(buf, PAGE_SIZE, "\n");
> +}
> +
> +static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf,
> + size_t count)
> +{
> + struct drm_device *ddev = dev_get_drvdata(dev);
> + struct amdgpu_device *adev = ddev->dev_private;
> + int ret;
> + uint32_t mask = 0;
> +
> + ret = amdgpu_read_mask(buf, count, &mask);
> + if (ret)
> + return ret;
> +
> + if (adev->powerplay.pp_funcs->force_clock_level)
> + ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask);
> +
> + if (ret)
> + return -EINVAL;
> +
> + return count;
> +}
> +
> static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> @@ -1216,6 +1256,9 @@ static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
> static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
> amdgpu_get_pp_dpm_fclk,
> amdgpu_set_pp_dpm_fclk);
> +static DEVICE_ATTR(pp_dpm_dcefclk, S_IRUGO | S_IWUSR,
> + amdgpu_get_pp_dpm_dcefclk,
> + amdgpu_set_pp_dpm_dcefclk);
> static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
> amdgpu_get_pp_dpm_pcie,
> amdgpu_set_pp_dpm_pcie);
> @@ -2387,6 +2430,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
> DRM_ERROR("failed to create device file pp_dpm_fclk\n");
> return ret;
> }
> + ret = device_create_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> + if (ret) {
> + DRM_ERROR("failed to create device file pp_dpm_dcefclk\n");
> + return ret;
> + }
> ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
> if (ret) {
> DRM_ERROR("failed to create device file pp_dpm_pcie\n");
> @@ -2474,6 +2522,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
> device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
> device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
> device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
> + device_remove_file(adev->dev, &dev_attr_pp_dpm_dcefclk);
> device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
> device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
> device_remove_file(adev->dev,
> diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> index f82de14f6560..2b579ba9b685 100644
> --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
> @@ -94,6 +94,7 @@ enum pp_clock_type {
> PP_PCIE,
> PP_SOCCLK,
> PP_FCLK,
> + PP_DCEFCLK,
> OD_SCLK,
> OD_MCLK,
> OD_VDDC_CURVE,
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> index 1832dcb965b1..585046c24925 100644
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
> @@ -1746,6 +1746,17 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
> return ret);
> }
>
> + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled &&
> + (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) {
> + min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level;
> +
> + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
> + hwmgr, PPSMC_MSG_SetHardMinByFreq,
> + (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff))),
> + "Failed to set hard min dcefclk!",
> + return ret);
> + }
> +
> return ret;
> }
>
> @@ -2258,7 +2269,7 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
> enum pp_clock_type type, uint32_t mask)
> {
> struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
> - uint32_t soft_min_level, soft_max_level;
> + uint32_t soft_min_level, soft_max_level, hard_min_level;
> int ret = 0;
>
> switch (type) {
> @@ -2373,6 +2384,28 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
>
> break;
>
> + case PP_DCEFCLK:
> + hard_min_level = mask ? (ffs(mask) - 1) : 0;
> +
> + if (hard_min_level >= data->dpm_table.dcef_table.count) {
> + pr_err("Clock level specified %d is over max allowed %d\n",
> + hard_min_level,
> + data->dpm_table.dcef_table.count - 1);
> + return -EINVAL;
> + }
> +
> + data->dpm_table.dcef_table.dpm_state.hard_min_level =
> + data->dpm_table.dcef_table.dpm_levels[hard_min_level].value;
> +
> + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK);
> + PP_ASSERT_WITH_CODE(!ret,
> + "Failed to upload boot level to lowest!",
> + return ret);
> +
> + //TODO: Setting DCEFCLK max dpm level is not supported
> +
> + break;
> +
> case PP_PCIE:
> soft_min_level = mask ? (ffs(mask) - 1) : 0;
> soft_max_level = mask ? (fls(mask) - 1) : 0;
> @@ -3039,6 +3072,23 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
> fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
> break;
>
> + case PP_DCEFCLK:
> + ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now);
> + PP_ASSERT_WITH_CODE(!ret,
> + "Attempt to get current dcefclk freq Failed!",
> + return ret);
> +
> + ret = vega20_get_dcefclocks(hwmgr, &clocks);
> + PP_ASSERT_WITH_CODE(!ret,
> + "Attempt to get dcefclk levels Failed!",
> + return ret);
> +
> + for (i = 0; i < clocks.num_levels; i++)
> + size += sprintf(buf + size, "%d: %uMhz %s\n",
> + i, clocks.data[i].clocks_in_khz / 1000,
> + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
> + break;
> +
> case PP_PCIE:
> gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
> --
> 2.20.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list