diff options
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/files/1131-drm-amd-Adding-ACP-driver-support-for-AMDGPU.patch')
-rw-r--r-- | meta-amdfalconx86/recipes-kernel/linux/files/1131-drm-amd-Adding-ACP-driver-support-for-AMDGPU.patch | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/files/1131-drm-amd-Adding-ACP-driver-support-for-AMDGPU.patch b/meta-amdfalconx86/recipes-kernel/linux/files/1131-drm-amd-Adding-ACP-driver-support-for-AMDGPU.patch new file mode 100644 index 00000000..5ae2536d --- /dev/null +++ b/meta-amdfalconx86/recipes-kernel/linux/files/1131-drm-amd-Adding-ACP-driver-support-for-AMDGPU.patch @@ -0,0 +1,383 @@ +From 58e6e67a2e65c339cbb6803463b19aaab92303c5 Mon Sep 17 00:00:00 2001 +From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com> +Date: Sat, 24 Sep 2016 12:57:36 +0530 +Subject: [PATCH 06/17] drm/amd: Adding ACP driver support for AMDGPU + +Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com> +Signed-off-by: Kalyan Alle <kalyan.alle@amd.com> +--- + drivers/gpu/drm/amd/acp/Kconfig | 1 + + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 216 ++----------------------------- + drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h | 2 +- + drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 4 +- + drivers/gpu/drm/amd/include/amd_shared.h | 2 + + 6 files changed, 18 insertions(+), 212 deletions(-) + +diff --git a/drivers/gpu/drm/amd/acp/Kconfig b/drivers/gpu/drm/amd/acp/Kconfig +index ca77ec1..b8a0605 100644 +--- a/drivers/gpu/drm/amd/acp/Kconfig ++++ b/drivers/gpu/drm/amd/acp/Kconfig +@@ -2,6 +2,7 @@ menu "ACP (Audio CoProcessor) Configuration" + + config DRM_AMD_ACP + bool "Enable AMD Audio CoProcessor IP support" ++ default y + select MFD_CORE + select PM_GENERIC_DOMAINS if PM + help +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index 551f763..86894ec 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1928,8 +1928,9 @@ struct amdgpu_atcs { + /* + * CGS + */ +-struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev); +-void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device); ++void *amdgpu_cgs_create_device(struct amdgpu_device *adev); ++void amdgpu_cgs_destroy_device(void *cgs_device); ++ + + + /* GPU virtualization */ +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +index 043ba60..cbbc31a8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +@@ -24,7 +24,6 @@ + */ + + #include <linux/irqdomain.h> +-#include <linux/pm_domain.h> + #include <linux/platform_device.h> + #include <sound/designware_i2s.h> + #include <sound/pcm.h> +@@ -103,153 +102,6 @@ static int acp_sw_fini(void *handle) + return 0; + } + +-/* power off a tile/block within ACP */ +-static int acp_suspend_tile(void *cgs_dev, int tile) +-{ +- u32 val = 0; +- u32 count = 0; +- +- if ((tile < ACP_TILE_P1) || (tile > ACP_TILE_DSP2)) { +- pr_err("Invalid ACP tile : %d to suspend\n", tile); +- return -1; +- } +- +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 + tile); +- val &= ACP_TILE_ON_MASK; +- +- if (val == 0x0) { +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG); +- val = val | (1 << tile); +- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val); +- cgs_write_register(cgs_dev, mmACP_PGFSM_CONFIG_REG, +- 0x500 + tile); +- +- count = ACP_TIMEOUT_LOOP; +- while (true) { +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 +- + tile); +- val = val & ACP_TILE_ON_MASK; +- if (val == ACP_TILE_OFF_MASK) +- break; +- if (--count == 0) { +- pr_err("Timeout reading ACP PGFSM status\n"); +- return -ETIMEDOUT; +- } +- udelay(100); +- } +- +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG); +- +- val |= ACP_TILE_OFF_RETAIN_REG_MASK; +- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val); +- } +- return 0; +-} +- +-/* power on a tile/block within ACP */ +-static int acp_resume_tile(void *cgs_dev, int tile) +-{ +- u32 val = 0; +- u32 count = 0; +- +- if ((tile < ACP_TILE_P1) || (tile > ACP_TILE_DSP2)) { +- pr_err("Invalid ACP tile to resume\n"); +- return -1; +- } +- +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 + tile); +- val = val & ACP_TILE_ON_MASK; +- +- if (val != 0x0) { +- cgs_write_register(cgs_dev, mmACP_PGFSM_CONFIG_REG, +- 0x600 + tile); +- count = ACP_TIMEOUT_LOOP; +- while (true) { +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 +- + tile); +- val = val & ACP_TILE_ON_MASK; +- if (val == 0x0) +- break; +- if (--count == 0) { +- pr_err("Timeout reading ACP PGFSM status\n"); +- return -ETIMEDOUT; +- } +- udelay(100); +- } +- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG); +- if (tile == ACP_TILE_P1) +- val = val & (ACP_TILE_P1_MASK); +- else if (tile == ACP_TILE_P2) +- val = val & (ACP_TILE_P2_MASK); +- +- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val); +- } +- return 0; +-} +- +-struct acp_pm_domain { +- void *cgs_dev; +- struct generic_pm_domain gpd; +-}; +- +-static int acp_poweroff(struct generic_pm_domain *genpd) +-{ +- int i, ret; +- struct acp_pm_domain *apd; +- +- apd = container_of(genpd, struct acp_pm_domain, gpd); +- if (apd != NULL) { +- /* Donot return abruptly if any of power tile fails to suspend. +- * Log it and continue powering off other tile +- */ +- for (i = 4; i >= 0 ; i--) { +- ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_P1 + i); +- if (ret) +- pr_err("ACP tile %d tile suspend failed\n", i); +- } +- } +- return 0; +-} +- +-static int acp_poweron(struct generic_pm_domain *genpd) +-{ +- int i, ret; +- struct acp_pm_domain *apd; +- +- apd = container_of(genpd, struct acp_pm_domain, gpd); +- if (apd != NULL) { +- for (i = 0; i < 2; i++) { +- ret = acp_resume_tile(apd->cgs_dev, ACP_TILE_P1 + i); +- if (ret) { +- pr_err("ACP tile %d resume failed\n", i); +- break; +- } +- } +- +- /* Disable DSPs which are not going to be used */ +- for (i = 0; i < 3; i++) { +- ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_DSP0 + i); +- /* Continue suspending other DSP, even if one fails */ +- if (ret) +- pr_err("ACP DSP %d suspend failed\n", i); +- } +- } +- return 0; +-} +- +-static struct device *get_mfd_cell_dev(const char *device_name, int r) +-{ +- char auto_dev_name[25]; +- struct device *dev; +- +- snprintf(auto_dev_name, sizeof(auto_dev_name), +- "%s.%d.auto", device_name, r); +- dev = bus_find_device_by_name(&platform_bus_type, NULL, auto_dev_name); +- dev_info(dev, "device %s added to pm domain\n", auto_dev_name); +- +- return dev; +-} +- + /** + * acp_hw_init - start and test ACP block + * +@@ -258,9 +110,8 @@ static struct device *get_mfd_cell_dev(const char *device_name, int r) + */ + static int acp_hw_init(void *handle) + { +- int r, i; ++ int r; + uint64_t acp_base; +- struct device *dev; + struct i2s_platform_data *i2s_pdata; + + struct amdgpu_device *adev = (struct amdgpu_device *)handle; +@@ -286,19 +137,6 @@ static int acp_hw_init(void *handle) + else if (r) + return r; + +- adev->acp.acp_genpd = kzalloc(sizeof(struct acp_pm_domain), GFP_KERNEL); +- if (adev->acp.acp_genpd == NULL) +- 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->cgs_dev = adev->acp.cgs_device; +- +- pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false); +- + adev->acp.acp_cell = kzalloc(sizeof(struct mfd_cell) * ACP_DEVS, + GFP_KERNEL); + +@@ -373,15 +211,6 @@ static int acp_hw_init(void *handle) + if (r) + return r; + +- for (i = 0; i < ACP_DEVS ; i++) { +- dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); +- r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev); +- if (r) { +- dev_err(dev, "Failed to add dev to genpd\n"); +- return r; +- } +- } +- + return 0; + } + +@@ -393,22 +222,10 @@ static int acp_hw_init(void *handle) + */ + static int acp_hw_fini(void *handle) + { +- int i, ret; +- struct device *dev; +- + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +- for (i = 0; i < ACP_DEVS ; i++) { +- dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); +- ret = pm_genpd_remove_device(&adev->acp.acp_genpd->gpd, dev); +- /* If removal fails, dont giveup and try rest */ +- if (ret) +- dev_err(dev, "remove dev from genpd failed\n"); +- } +- + mfd_remove_devices(adev->acp.parent); + kfree(adev->acp.acp_res); +- kfree(adev->acp.acp_genpd); + kfree(adev->acp.acp_cell); + + return 0; +@@ -421,29 +238,6 @@ static int acp_suspend(void *handle) + + static int acp_resume(void *handle) + { +- int i, ret; +- struct acp_pm_domain *apd; +- struct amdgpu_device *adev = (struct amdgpu_device *)handle; +- +- /* return early if no ACP */ +- if (!adev->acp.acp_genpd) +- return 0; +- +- /* SMU block will power on ACP irrespective of ACP runtime status. +- * Power off explicitly based on genpd ACP runtime status so that ACP +- * hw and ACP-genpd status are in sync. +- * 'suspend_power_off' represents "Power status before system suspend" +- */ +- if (adev->acp.acp_genpd->gpd.suspend_power_off == true) { +- apd = container_of(&adev->acp.acp_genpd->gpd, +- struct acp_pm_domain, gpd); +- +- for (i = 4; i >= 0 ; i--) { +- ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_P1 + i); +- if (ret) +- pr_err("ACP tile %d tile suspend failed\n", i); +- } +- } + return 0; + } + +@@ -467,6 +261,13 @@ static int acp_soft_reset(void *handle) + return 0; + } + ++static void acp_print_status(void *handle) ++{ ++ struct amdgpu_device *adev = (struct amdgpu_device *)handle; ++ ++ dev_info(adev->dev, "ACP STATUS\n"); ++} ++ + static int acp_set_clockgating_state(void *handle, + enum amd_clockgating_state state) + { +@@ -492,6 +293,7 @@ const struct amd_ip_funcs acp_ip_funcs = { + .is_idle = acp_is_idle, + .wait_for_idle = acp_wait_for_idle, + .soft_reset = acp_soft_reset, ++ .print_status = acp_print_status, + .set_clockgating_state = acp_set_clockgating_state, + .set_powergating_state = acp_set_powergating_state, + }; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h +index 8a39631..f6e32a6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h +@@ -30,7 +30,7 @@ + + struct amdgpu_acp { + struct device *parent; +- struct cgs_device *cgs_device; ++ void *cgs_device; + struct amd_acp_private *private; + struct mfd_cell *acp_cell; + struct resource *acp_res; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +index 490464e..88625b5 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +@@ -1141,7 +1141,7 @@ static const struct cgs_os_ops amdgpu_cgs_os_ops = { + amdgpu_cgs_irq_put + }; + +-struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev) ++void *amdgpu_cgs_create_device(struct amdgpu_device *adev) + { + struct amdgpu_cgs_device *cgs_device = + kmalloc(sizeof(*cgs_device), GFP_KERNEL); +@@ -1158,7 +1158,7 @@ struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev) + return (struct cgs_device *)cgs_device; + } + +-void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device) ++void amdgpu_cgs_destroy_device(void *cgs_device) + { + kfree(cgs_device); + } +diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h +index afce1ed..d83baf3 100644 +--- a/drivers/gpu/drm/amd/include/amd_shared.h ++++ b/drivers/gpu/drm/amd/include/amd_shared.h +@@ -168,6 +168,8 @@ struct amd_ip_funcs { + int (*wait_for_idle)(void *handle); + /* soft reset the IP block */ + int (*soft_reset)(void *handle); ++ /* dump the IP block status registers */ ++ void (*print_status)(void *handle); + /* enable/disable cg for the IP block */ + int (*set_clockgating_state)(void *handle, + enum amd_clockgating_state state); +-- +2.7.4 + |