From patchwork Mon Nov 11 14:49:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "RAVULAPATI, VISHNU VARDHAN RAO" X-Patchwork-Id: 11237207 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1ACDF1515 for ; Mon, 11 Nov 2019 14:56:28 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9DEE621D7F for ; Mon, 11 Nov 2019 14:56:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=alsa-project.org header.i=@alsa-project.org header.b="VknJAqqL"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=amdcloud.onmicrosoft.com header.i=@amdcloud.onmicrosoft.com header.b="kwLVSCRt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9DEE621D7F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=amd.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id BED811675; Mon, 11 Nov 2019 15:55:35 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz BED811675 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1573484185; bh=IboS5hfao1Zc3m5ydMjCY1GnSltrt5hQltYDR3Jd4lo=; h=From:To:Date:In-Reply-To:References:Cc:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=VknJAqqL87z+OepmVCp85HFkB/bZdiE5ZTmnLqT+7Uxin0iERQN9jkcda8+e6AlB2 JddxYSvu5hiBcdwmppi4zFKgsTOfeNH7VoPhIvJx2iA/QOr30ODR58dYf3PABdlQFq jSW0dTjaLgdtRtF7n/x3L5bdZJC5djf0hJ2awTLE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 83689F80659; Mon, 11 Nov 2019 15:52:38 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa1.perex.cz (Postfix, from userid 50401) id 4C305F8065A; Mon, 11 Nov 2019 15:52:37 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on alsa1.perex.cz X-Spam-Level: * X-Spam-Status: No, score=1.8 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, FORGED_SPF_HELO,SPF_HELO_PASS,SPF_NONE,SURBL_BLOCKED,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from NAM04-BN3-obe.outbound.protection.outlook.com (mail-eopbgr680066.outbound.protection.outlook.com [40.107.68.66]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id ACB05F80275 for ; Mon, 11 Nov 2019 15:52:33 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz ACB05F80275 Authentication-Results: alsa1.perex.cz; dkim=pass (1024-bit key) header.d=amdcloud.onmicrosoft.com header.i=@amdcloud.onmicrosoft.com header.b="kwLVSCRt" ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=WSOWxPYntIgVf2NCeIOM6gH5cotGRtdPfU6jsZZGAFBho2Hfa4F1+JcC6MRDv5YZxbgmpLJD5Mh1TpDCHRt6CsTcr9JIGU4hm2eFCY91zSuhxl82ytsKplq5sv6Xitmpil2ntbODCWoUi1OfQQgifL5X2ONTOAqycqXjwAZdHwm7bKX4oRuuhRIbVyrAuYdfQYixs9/0kzZRc65snABxW+7My9nDzRfl0/5SgcIYdfzYIXouFC5b82H8+NgMCp3vwFK/Wkgugnigz2V7c5y0lCYzkxZfnaDQa793HuJNr58N2oep7VGHIsxH4COSJzQ0ixY+5Vs+oUWVEKm/tPhyuw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=G5punGZLALh0dP3iTqbcjo+J7Xn4hNCMRbuB671IlmE=; b=DyW4kD1Q8qEyoswBgHikN0i77dQEmy1m+gADjI4QmxqGnIXc5X+ijeZvV5mNICubZstmrRLUKzivcH5WKc4dTr9QDjlYSdMlq5o6l3ZNrtzSSULeDyyI//v/RGndJ0BicooepAgjJljulk/C/173Wbxf7zJc5rWtfTFTjMPJ2XEYi5xGe5Pjblkuhl1PztGDrKLuz84lzigvqdBwSKSEozZam2j5gHcLHJ4ssl14iunAt7vNA56ksoHC6edVCtbyhduXb3w9szGwSxCix+CAmJngg6OgGePfPb1UQRiMvAN17fqDXwrdnS+J8yXtM1v9K1xSTqNlDko6YoAS/49A0w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none (sender ip is 165.204.84.17) smtp.rcpttodomain=google.com smtp.mailfrom=amd.com; dmarc=permerror action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=G5punGZLALh0dP3iTqbcjo+J7Xn4hNCMRbuB671IlmE=; b=kwLVSCRtiLTYEuEmp1wH4kjXK9Rs05TDXm7RfgVGzjj4A9WCz6EB2Mwjmbwf81Q8EC8I8BsJwXDx1ZDtzJYUxYG5sLtYFQHGduqnlBusaCwgj13pW1ANSrCZmbfKdezJWo+5kwPwJu7/xjOTYHcOI5Lxb0TsQgVbvvHXMh0yt9M= Received: from SN1PR12CA0110.namprd12.prod.outlook.com (2603:10b6:802:21::45) by DM6PR12MB4091.namprd12.prod.outlook.com (2603:10b6:5:222::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2430.20; Mon, 11 Nov 2019 14:52:29 +0000 Received: from CO1NAM03FT056.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e48::203) by SN1PR12CA0110.outlook.office365.com (2603:10b6:802:21::45) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2430.23 via Frontend Transport; Mon, 11 Nov 2019 14:52:29 +0000 Authentication-Results: spf=none (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; google.com; dkim=none (message not signed) header.d=none;google.com; dmarc=permerror action=none header.from=amd.com; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Received: from SATLEXMB02.amd.com (165.204.84.17) by CO1NAM03FT056.mail.protection.outlook.com (10.152.81.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.20.2430.20 via Frontend Transport; Mon, 11 Nov 2019 14:52:29 +0000 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB02.amd.com (10.181.40.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Mon, 11 Nov 2019 08:52:28 -0600 Received: from SATLEXMB02.amd.com (10.181.40.143) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Mon, 11 Nov 2019 08:52:27 -0600 Received: from vishnu-All-Series.amd.com (10.180.168.240) by SATLEXMB02.amd.com (10.181.40.143) with Microsoft SMTP Server id 15.1.1713.5 via Frontend Transport; Mon, 11 Nov 2019 08:52:18 -0600 From: Ravulapati Vishnu vardhan rao To: Date: Mon, 11 Nov 2019 20:19:54 +0530 Message-ID: <1573483794-8921-7-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1573483794-8921-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com> References: <1573483794-8921-1-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:165.204.84.17; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(4636009)(1496009)(396003)(136003)(39860400002)(376002)(346002)(428003)(23433003)(199004)(189003)(70586007)(305945005)(51416003)(53416004)(5660300002)(7416002)(2906002)(186003)(7696005)(70206006)(356004)(6666004)(478600001)(26005)(426003)(86362001)(316002)(76176011)(4326008)(36756003)(16586007)(486006)(109986005)(2616005)(8936002)(50226002)(11346002)(446003)(476003)(126002)(81156014)(81166006)(8676002)(47776003)(14444005)(1671002)(30864003)(336012)(48376002)(54906003)(50466002)(266003)(32563001); DIR:OUT; SFP:1101; SCL:1; SRVR:DM6PR12MB4091; H:SATLEXMB02.amd.com; FPR:; SPF:None; LANG:en; PTR:InfoDomainNonexistent; A:1; MX:1; X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5d845feb-227b-4b85-a6ea-08d766b6c643 X-MS-TrafficTypeDiagnostic: DM6PR12MB4091:|DM6PR12MB4091: X-Microsoft-Antispam-PRVS: X-MS-Exchange-Transport-Forked: True X-MS-Oob-TLC-OOBClassifiers: OLM:820; X-Forefront-PRVS: 0218A015FA X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: XBUFuA6Tjy8A/EVJ6WIRMz7Ee5dCllx6Q19bLjkIpLg8dCtsFdJsbDh/BwkaQZYynIaNG9lmOv0diTs337LT1ccfYD8TJ3q05Fd04YNAr6cBblnl942F+YqG6mlnjl1XSTQrhvfZKrZhIAaWITx4uyT1xcvybP+ja1mxBd1VIdpL2h7jydayCHkiplf6SvzNcwzngJWjf86SAa0R1T5c5lldn94pgDYD0HMWvJR1i1f3qsG1VynDYjfVbgcXAMhH2k3cvO4EKWFnQ7UQAjMmq0pquB3bM/k3b2EE3pigxj7BRuYVwL8bkKD4oOyHu2uNG1OTX+Y7OFyxlyMu3/AF57L248nqoReH9mmvJIVFZc5a4hwdddhGJ/mi4nN78QpvpeU7ueGFw8djwFD6LmJw96QGZr88jR1IdSKSOekxSXv/1rt4fJqgdNFlZGB6Fm2m X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Nov 2019 14:52:29.0986 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5d845feb-227b-4b85-a6ea-08d766b6c643 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB02.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4091 Cc: "moderated list:SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEM..." , Maruthi Bayyavarapu , Kuninori Morimoto , open list , Takashi Iwai , YueHaibing , Liam Girdwood , Akshu.Agrawal@amd.com, Sanju R Mehta , Ravulapati Vishnu vardhan rao , Mark Brown , djkurtz@google.com, Vijendar Mukunda , Alex Deucher , Colin Ian King , Dan Carpenter Subject: [alsa-devel] [PATCH v4 6/6] ASoC: amd: Added ACP3x system resume and runtime pm X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" When system wide suspend happens, ACP will be powered off and when system resumes,for audio usecase to continue,all the runtime configuration data needs to be programmed again. Added resume pm call back to ACP pm ops and also added runtime PM operations for ACP3x PCM platform device. Device will enter into D3 state when there is no activity on audio I2S lines. Signed-off-by: Ravulapati Vishnu vardhan rao --- sound/soc/amd/raven/acp3x-pcm-dma.c | 135 ----------------------------- sound/soc/amd/raven/acp3x.h | 8 ++ sound/soc/amd/raven/pci-acp3x.c | 168 +++++++++++++++++++++++++++++++++++- 3 files changed, 173 insertions(+), 138 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 8a8b135..00713eb 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -58,106 +58,6 @@ static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = { .periods_max = CAPTURE_MAX_NUM_PERIODS, }; -static int acp3x_power_on(void __iomem *acp3x_base, bool on) -{ - u16 val, mask; - u32 timeout; - - if (on == true) { - val = 1; - mask = ACP3x_POWER_ON; - } else { - val = 0; - mask = ACP3x_POWER_OFF; - } - - rv_writel(val, acp3x_base + mmACP_PGFSM_CONTROL); - timeout = 0; - while (true) { - val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); - if ((val & ACP3x_POWER_OFF_IN_PROGRESS) == mask) - break; - if (timeout > 100) { - pr_err("ACP3x power state change failure\n"); - return -ENODEV; - } - timeout++; - cpu_relax(); - } - return 0; -} - -static int acp3x_reset(void __iomem *acp3x_base) -{ - u32 val, timeout; - - rv_writel(1, acp3x_base + mmACP_SOFT_RESET); - timeout = 0; - while (true) { - val = rv_readl(acp3x_base + mmACP_SOFT_RESET); - if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) || - timeout > 100) { - if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) - break; - return -ENODEV; - } - timeout++; - cpu_relax(); - } - - rv_writel(0, acp3x_base + mmACP_SOFT_RESET); - timeout = 0; - while (true) { - val = rv_readl(acp3x_base + mmACP_SOFT_RESET); - if (!val || timeout > 100) { - if (!val) - break; - return -ENODEV; - } - timeout++; - cpu_relax(); - } - return 0; -} - -static int acp3x_init(void __iomem *acp3x_base) -{ - int ret; - - /* power on */ - ret = acp3x_power_on(acp3x_base, true); - if (ret) { - pr_err("ACP3x power on failed\n"); - return ret; - } - /* Reset */ - ret = acp3x_reset(acp3x_base); - if (ret) { - pr_err("ACP3x reset failed\n"); - return ret; - } - return 0; -} - -static int acp3x_deinit(void __iomem *acp3x_base) -{ - int ret; - - /* Reset */ - ret = acp3x_reset(acp3x_base); - if (ret) { - pr_err("ACP3x reset failed\n"); - return ret; - } - /* power off */ - ret = acp3x_power_on(acp3x_base, false); - if (ret) { - pr_err("ACP3x power off failed\n"); - return ret; - } - return 0; -} - static irqreturn_t i2s_irq_handler(int irq, void *dev_id) { u16 play_flag, cap_flag; @@ -520,10 +420,6 @@ static int acp3x_audio_probe(struct platform_device *pdev) adata->i2s_irq = res->start; dev_set_drvdata(&pdev->dev, adata); - /* Initialize ACP */ - status = acp3x_init(adata->acp3x_base); - if (status) - goto io_irq; status = devm_snd_soc_register_component(&pdev->dev, &acp3x_i2s_component, NULL, 0); @@ -560,40 +456,20 @@ static int acp3x_audio_probe(struct platform_device *pdev) kfree(res); kfree(adata->acp3x_base); kfree(adata); - status = acp3x_deinit(adata->acp3x_base); - if (status) - dev_err(&pdev->dev, "ACP de-init failed\n"); - else - dev_info(&pdev->dev, "ACP de-initialized\n"); - /*ignore device status and return driver probe error*/ return -ENODEV; } static int acp3x_audio_remove(struct platform_device *pdev) { - int ret; - struct i2s_dev_data *adata = dev_get_drvdata(&pdev->dev); - - ret = acp3x_deinit(adata->acp3x_base); - if (ret) - dev_err(&pdev->dev, "ACP de-init failed\n"); - else - dev_info(&pdev->dev, "ACP de-initialized\n"); - pm_runtime_disable(&pdev->dev); return 0; } static int acp3x_resume(struct device *dev) { - int status; u32 val; struct i2s_dev_data *adata = dev_get_drvdata(dev); - status = acp3x_init(adata->acp3x_base); - if (status) - return -ENODEV; - if (adata->play_stream && adata->play_stream->runtime) { struct i2s_stream_instance *rtd = adata->play_stream->runtime->private_data; @@ -638,15 +514,8 @@ static int acp3x_resume(struct device *dev) static int acp3x_pcm_runtime_suspend(struct device *dev) { - int status; struct i2s_dev_data *adata = dev_get_drvdata(dev); - status = acp3x_deinit(adata->acp3x_base); - if (status) - dev_err(dev, "ACP de-init failed\n"); - else - dev_info(dev, "ACP de-initialized\n"); - rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); return 0; @@ -654,12 +523,8 @@ static int acp3x_pcm_runtime_suspend(struct device *dev) static int acp3x_pcm_runtime_resume(struct device *dev) { - int status; struct i2s_dev_data *adata = dev_get_drvdata(dev); - status = acp3x_init(adata->acp3x_base); - if (status) - return -ENODEV; rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); return 0; } diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h index 01b283a..c40f960 100644 --- a/sound/soc/amd/raven/acp3x.h +++ b/sound/soc/amd/raven/acp3x.h @@ -7,6 +7,7 @@ #include "chip_offset_byte.h" +#define DELAY 600 #define I2S_SP_INSTANCE 0x01 #define I2S_BT_INSTANCE 0x02 @@ -65,6 +66,13 @@ #define SLOT_WIDTH_16 0x10 #define SLOT_WIDTH_24 0x18 #define SLOT_WIDTH_32 0x20 +#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 +#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 +#define ACP_PGFSM_STATUS_MASK 0x03 +#define ACP_POWERED_ON 0x00 +#define ACP_POWER_ON_IN_PROGRESS 0x01 +#define ACP_POWERED_OFF 0x02 +#define ACP_POWER_OFF_IN_PROGRESS 0x03 struct acp3x_platform_info { u16 play_i2s_instance; diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c index fe37160c..6b48baa 100644 --- a/sound/soc/amd/raven/pci-acp3x.c +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include "acp3x.h" @@ -19,6 +22,114 @@ struct acp3x_dev_data { struct platform_device *pdev[ACP3x_DEVS]; }; +static int acp3x_power_on(void __iomem *acp3x_base) +{ + u32 val; + u32 timeout = 0; + int ret = 0; + + val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); + + if (val == 0) + return val; + + if (!((val & ACP_PGFSM_STATUS_MASK) == + ACP_POWER_ON_IN_PROGRESS)) + rv_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, + acp3x_base + mmACP_PGFSM_CONTROL); + while (++timeout < DELAY) { + val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); + if (!val) + break; + udelay(1); + if (timeout > 500) { + pr_err("ACP is Not Powered ON\n"); + return -ETIMEDOUT; + } + } +} +static int acp3x_power_off(void __iomem *acp3x_base) +{ + u32 val; + u32 timeout = 0; + + rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK, + acp3x_base + mmACP_PGFSM_CONTROL); + while (++timeout < DELAY) { + val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS); + if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF) + return 0; + udelay(1); + if (timeout > 500) { + pr_err("ACP is Not Powered OFF\n"); + return -ETIMEDOUT; + } + } +} +static int acp3x_reset(void __iomem *acp3x_base) +{ + u32 val, timeout; + + rv_writel(1, acp3x_base + mmACP_SOFT_RESET); + timeout = 0; + while (++timeout < DELAY) { + val = rv_readl(acp3x_base + mmACP_SOFT_RESET); + if ((val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) || + timeout > 100) { + if (val & ACP3x_SOFT_RESET__SoftResetAudDone_MASK) + break; + return -ENODEV; + } + cpu_relax(); + } + rv_writel(0, acp3x_base + mmACP_SOFT_RESET); + timeout = 0; + while (++timeout < DELAY) { + val = rv_readl(acp3x_base + mmACP_SOFT_RESET); + if (!val) + break; + if (timeout > 100) + return -ENODEV; + cpu_relax(); + } + return 0; +} +static int acp3x_init(void __iomem *acp3x_base) +{ + int ret; + + /* power on */ + ret = acp3x_power_on(acp3x_base); + if (ret) { + pr_err("ACP3x power on failed\n"); + return ret; + } + /* Reset */ + ret = acp3x_reset(acp3x_base); + if (ret) { + pr_err("ACP3x reset failed\n"); + return ret; + } + return 0; +} +static int acp3x_deinit(void __iomem *acp3x_base) +{ + int ret; + + /* Reset */ + ret = acp3x_reset(acp3x_base); + if (ret) { + pr_err("ACP3x reset failed\n"); + return ret; + } + /* power off */ + ret = acp3x_power_off(acp3x_base); + if (ret) { + pr_err("ACP3x power off failed\n"); + return ret; + } + return 0; +} static int snd_acp3x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -63,6 +174,10 @@ static int snd_acp3x_probe(struct pci_dev *pci, } pci_set_master(pci); pci_set_drvdata(pci, adata); + ret = acp3x_init(adata->acp3x_base); + if (ret) + return -ENODEV; + val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG); switch (val) { @@ -133,9 +248,19 @@ static int snd_acp3x_probe(struct pci_dev *pci, ret = -ENODEV; goto unmap_mmio; } + pm_runtime_set_autosuspend_delay(&pci->dev, 10000); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_set_active(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_enable(&pci->dev); return 0; unmap_mmio: + ret = acp3x_deinit(adata->acp3x_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + else + dev_info(&pci->dev, "ACP de-initialized\n"); pci_disable_msi(pci); for (i = 0 ; i < ACP3x_DEVS ; i++) platform_device_unregister(adata->pdev[i]); @@ -148,23 +273,57 @@ static int snd_acp3x_probe(struct pci_dev *pci, return ret; } +static int snd_acp3x_suspend(struct device *dev) +{ + int status; + struct acp3x_dev_data *adata = dev_get_drvdata(dev); + + status = acp3x_deinit(adata->acp3x_base); + if (status) + dev_err(dev, "ACP de-init failed\n"); + else + dev_info(dev, "ACP de-initialized\n"); + return 0; +} +static int snd_acp3x_resume(struct device *dev) +{ + int status; + struct acp3x_dev_data *adata = dev_get_drvdata(dev); + + status = acp3x_init(adata->acp3x_base); + if (status) { + dev_err(dev, "ACP init failed\n"); + return status; + } + return 0; +} +static const struct dev_pm_ops acp3x_pm = { + .runtime_suspend = snd_acp3x_suspend, + .runtime_resume = snd_acp3x_resume, + .resume = snd_acp3x_resume, +}; static void snd_acp3x_remove(struct pci_dev *pci) { - int i; + int i, ret; struct acp3x_dev_data *adata = pci_get_drvdata(pci); if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) { for (i = 0 ; i < ACP3x_DEVS ; i++) platform_device_unregister(adata->pdev[i]); } + ret = acp3x_deinit(adata->acp3x_base); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + else + dev_info(&pci->dev, "ACP de-initialized\n"); iounmap(adata->acp3x_base); - + pm_runtime_disable(&pci->dev); + pm_runtime_get_noresume(&pci->dev); pci_disable_msi(pci); pci_release_regions(pci); pci_disable_device(pci); } - static const struct pci_device_id snd_acp3x_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2), .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, @@ -178,6 +337,9 @@ static struct pci_driver acp3x_driver = { .id_table = snd_acp3x_ids, .probe = snd_acp3x_probe, .remove = snd_acp3x_remove, + .driver = { + .pm = &acp3x_pm, + } }; module_pci_driver(acp3x_driver);