aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amdfalconx86/recipes-kernel/linux/files/1131-drm-amd-Adding-ACP-driver-support-for-AMDGPU.patch
diff options
context:
space:
mode:
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.patch383
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
+