Commit ee8b1ef9 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'amd-drm-next-5.20-2022-07-26' of...

Merge tag 'amd-drm-next-5.20-2022-07-26' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amdgpu:
- VCN4 fixes
- RAS support for UMC 8.10
- ACP support for jadeite platforms
- NBIO HDP flush fixes
- Misc spelling and grammar fixes
- Runtime PM fixes
- Non-DC HPD fix
- Clean up amdgpu DM code
- DSC fixes
- Expose some additional GFXOFF data via debugfs
- More FP clean up for new DCN blocks
- PPC DC FP fixes
- DCN 3.1.4 fixes
- DC DML stack usage fixes
- GMC fixes
- SPM fixes for RDNA2

amdkfd:
- MMU notifier fix
- Mutex fix

UAPI:
- Add a comment about VCN4 unified queues
- IP version information for UMDs
  Proposed mesa change: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17411/diffs?commit_id=c8a63590dfd0d64e6e6a634dcfed993f135dd075



Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220726181536.5759-1-alexander.deucher@amd.com
parents 417c1c19 1b54a012
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -63,3 +63,44 @@ gpu_metrics

.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c
   :doc: gpu_metrics

GFXOFF
======

GFXOFF is a feature found in most recent GPUs that saves power at runtime. The
card's RLC (RunList Controller) firmware powers off the gfx engine
dynamically when there is no workload on gfx or compute pipes. GFXOFF is on by
default on supported GPUs.

Userspace can interact with GFXOFF through a debugfs interface:

``amdgpu_gfxoff``
-----------------

Use it to enable/disable GFXOFF, and to check if it's current enabled/disabled::

  $ xxd -l1 -p /sys/kernel/debug/dri/0/amdgpu_gfxoff
  01

- Write 0 to disable it, and 1 to enable it.
- Read 0 means it's disabled, 1 it's enabled.

If it's enabled, that means that the GPU is free to enter into GFXOFF mode as
needed. Disabled means that it will never enter GFXOFF mode.

``amdgpu_gfxoff_status``
------------------------

Read it to check current GFXOFF's status of a GPU::

  $ xxd -l1 -p /sys/kernel/debug/dri/0/amdgpu_gfxoff_status
  02

- 0: GPU is in GFXOFF state, the gfx engine is powered down.
- 1: Transition out of GFXOFF state
- 2: Not in GFXOFF state
- 3: Transition into GFXOFF state

If GFXOFF is enabled, the value will be transitioning around [0, 3], always
getting into 0 when possible. When it's disabled, it's always at 2. Returns
``-EINVAL`` if it's not supported.
+3 −2
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ config DRM_AMDGPU_SI
	depends on DRM_AMDGPU
	help
	  Choose this option if you want to enable experimental support
	  for SI asics.
	  for SI (Southern Islands) asics.

	  SI is already supported in radeon. Experimental support for SI
	  in amdgpu will be disabled by default and is still provided by
@@ -16,7 +16,8 @@ config DRM_AMDGPU_CIK
	bool "Enable amdgpu support for CIK parts"
	depends on DRM_AMDGPU
	help
	  Choose this option if you want to enable support for CIK asics.
	  Choose this option if you want to enable support for CIK (Sea
	  Islands) asics.

	  CIK is already supported in radeon. Support for CIK in amdgpu
	  will be disabled by default and is still provided by radeon.
+1 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ amdgpu-y += \

# add UMC block
amdgpu-y += \
	umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o
	umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o umc_v8_10.o

# add IH block
amdgpu-y += \
+1 −1
Original line number Diff line number Diff line
@@ -197,6 +197,7 @@ extern uint amdgpu_smu_memory_pool_size;
extern int amdgpu_smu_pptable_id;
extern uint amdgpu_dc_feature_mask;
extern uint amdgpu_dc_debug_mask;
extern uint amdgpu_dc_visual_confirm;
extern uint amdgpu_dm_abm_level;
extern int amdgpu_backlight;
extern struct amdgpu_mgpu_info mgpu_info;
@@ -1011,7 +1012,6 @@ struct amdgpu_device {
	uint64_t	df_perfmon_config_assign_mask[AMDGPU_MAX_DF_PERFMONS];

	/* enable runtime pm on the device */
	bool                            runpm;
	bool                            in_runpm;
	bool                            has_pr3;

+227 −127
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
#include <linux/platform_device.h>
#include <sound/designware_i2s.h>
#include <sound/pcm.h>
#include <linux/acpi.h>
#include <linux/dmi.h>

#include "amdgpu.h"
#include "atom.h"
@@ -36,6 +38,7 @@

#include "acp_gfx_if.h"

#define ST_JADEITE 1
#define ACP_TILE_ON_MASK			0x03
#define ACP_TILE_OFF_MASK			0x02
#define ACP_TILE_ON_RETAIN_REG_MASK		0x1f
@@ -85,6 +88,8 @@
#define ACP_DEVS				4
#define ACP_SRC_ID				162

static unsigned long acp_machine_id;

enum {
	ACP_TILE_P1 = 0,
	ACP_TILE_P2,
@@ -128,7 +133,6 @@ static int acp_poweroff(struct generic_pm_domain *genpd)
	struct amdgpu_device *adev;

	apd = container_of(genpd, struct acp_pm_domain, gpd);
	if (apd != NULL) {
	adev = apd->adev;
	/* call smu to POWER GATE ACP block
	 * smu will
@@ -137,7 +141,6 @@ static int acp_poweroff(struct generic_pm_domain *genpd)
	 * 3. check and enter ulv state
	 */
	amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
	}
	return 0;
}

@@ -147,7 +150,6 @@ static int acp_poweron(struct generic_pm_domain *genpd)
	struct amdgpu_device *adev;

	apd = container_of(genpd, struct acp_pm_domain, gpd);
	if (apd != NULL) {
	adev = apd->adev;
	/* call smu to UNGATE ACP block
	 * smu will
@@ -156,7 +158,6 @@ static int acp_poweron(struct generic_pm_domain *genpd)
	 * 3. power on acp tiles
	 */
	amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
	}
	return 0;
}

@@ -184,6 +185,37 @@ static int acp_genpd_remove_device(struct device *dev, void *data)
	return 0;
}

static int acp_quirk_cb(const struct dmi_system_id *id)
{
	acp_machine_id = ST_JADEITE;
	return 1;
}

static const struct dmi_system_id acp_quirk_table[] = {
	{
		.callback = acp_quirk_cb,
		.matches = {
			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMD"),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jadeite"),
		}
	},
	{
		.callback = acp_quirk_cb,
		.matches = {
			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "IP3 Technology CO.,Ltd."),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN1D"),
		},
	},
	{
		.callback = acp_quirk_cb,
		.matches = {
			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Standard"),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN10"),
		},
	},
	{}
};

/**
 * acp_hw_init - start and test ACP block
 *
@@ -193,7 +225,7 @@ static int acp_genpd_remove_device(struct device *dev, void *data)
static int acp_hw_init(void *handle)
{
	int r;
	uint64_t acp_base;
	u64 acp_base;
	u32 val = 0;
	u32 count = 0;
	struct i2s_platform_data *i2s_pdata = NULL;
@@ -220,37 +252,98 @@ static int acp_hw_init(void *handle)
		return -EINVAL;

	acp_base = adev->rmmio_base;


	adev->acp.acp_genpd = kzalloc(sizeof(struct acp_pm_domain), GFP_KERNEL);
	if (adev->acp.acp_genpd == NULL)
	if (!adev->acp.acp_genpd)
		return -ENOMEM;

	adev->acp.acp_genpd->gpd.name = "ACP_AUDIO";
	adev->acp.acp_genpd->gpd.power_off = acp_poweroff;
	adev->acp.acp_genpd->gpd.power_on = acp_poweron;


	adev->acp.acp_genpd->adev = adev;

	pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false);
	dmi_check_system(acp_quirk_table);
	switch (acp_machine_id) {
	case ST_JADEITE:
	{
		adev->acp.acp_cell = kcalloc(2, sizeof(struct mfd_cell),
					     GFP_KERNEL);
		if (!adev->acp.acp_cell) {
			r = -ENOMEM;
			goto failure;
		}

		adev->acp.acp_res = kcalloc(3, sizeof(struct resource), GFP_KERNEL);
		if (!adev->acp.acp_res) {
			r = -ENOMEM;
			goto failure;
		}

		i2s_pdata = kcalloc(1, sizeof(struct i2s_platform_data), GFP_KERNEL);
		if (!i2s_pdata) {
			r = -ENOMEM;
			goto failure;
		}

		i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
				      DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
		i2s_pdata[0].cap = DWC_I2S_PLAY | DWC_I2S_RECORD;
		i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000;
		i2s_pdata[0].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
		i2s_pdata[0].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;

		adev->acp.acp_res[0].name = "acp2x_dma";
		adev->acp.acp_res[0].flags = IORESOURCE_MEM;
		adev->acp.acp_res[0].start = acp_base;
		adev->acp.acp_res[0].end = acp_base + ACP_DMA_REGS_END;

		adev->acp.acp_res[1].name = "acp2x_dw_i2s_play_cap";
		adev->acp.acp_res[1].flags = IORESOURCE_MEM;
		adev->acp.acp_res[1].start = acp_base + ACP_I2S_CAP_REGS_START;
		adev->acp.acp_res[1].end = acp_base + ACP_I2S_CAP_REGS_END;

		adev->acp.acp_res[2].name = "acp2x_dma_irq";
		adev->acp.acp_res[2].flags = IORESOURCE_IRQ;
		adev->acp.acp_res[2].start = amdgpu_irq_create_mapping(adev, 162);
		adev->acp.acp_res[2].end = adev->acp.acp_res[2].start;

		adev->acp.acp_cell[0].name = "acp_audio_dma";
		adev->acp.acp_cell[0].num_resources = 3;
		adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
		adev->acp.acp_cell[0].platform_data = &adev->asic_type;
		adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);

		adev->acp.acp_cell[1].name = "designware-i2s";
		adev->acp.acp_cell[1].num_resources = 1;
		adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1];
		adev->acp.acp_cell[1].platform_data = &i2s_pdata[0];
		adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data);
		r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, 2);
		if (r)
			goto failure;
		r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
					  acp_genpd_add_device);
		if (r)
			goto failure;
		break;
	}
	default:
		adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell),
					     GFP_KERNEL);

	if (adev->acp.acp_cell == NULL) {
		if (!adev->acp.acp_cell) {
			r = -ENOMEM;
			goto failure;
		}

		adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL);
	if (adev->acp.acp_res == NULL) {
		if (!adev->acp.acp_res) {
			r = -ENOMEM;
			goto failure;
		}

		i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL);
	if (i2s_pdata == NULL) {
		if (!i2s_pdata) {
			r = -ENOMEM;
			goto failure;
		}
@@ -297,6 +390,14 @@ static int acp_hw_init(void *handle)
		i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET;
		i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET;

		i2s_pdata[3].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
		switch (adev->asic_type) {
		case CHIP_STONEY:
			i2s_pdata[3].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
			break;
		default:
			break;
		}
		adev->acp.acp_res[0].name = "acp2x_dma";
		adev->acp.acp_res[0].flags = IORESOURCE_MEM;
		adev->acp.acp_res[0].start = acp_base;
@@ -346,8 +447,7 @@ static int acp_hw_init(void *handle)
		adev->acp.acp_cell[3].platform_data = &i2s_pdata[2];
		adev->acp.acp_cell[3].pdata_size = sizeof(struct i2s_platform_data);

	r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell,
								ACP_DEVS);
		r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, ACP_DEVS);
		if (r)
			goto failure;

@@ -355,6 +455,7 @@ static int acp_hw_init(void *handle)
					  acp_genpd_add_device);
		if (r)
			goto failure;
	}

	/* Assert Soft reset of ACP */
	val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
@@ -546,8 +647,7 @@ static const struct amd_ip_funcs acp_ip_funcs = {
	.set_powergating_state = acp_set_powergating_state,
};

const struct amdgpu_ip_block_version acp_ip_block =
{
const struct amdgpu_ip_block_version acp_ip_block = {
	.type = AMD_IP_BLOCK_TYPE_ACP,
	.major = 2,
	.minor = 2,
Loading