162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// This file is provided under a dual BSD/GPLv2 license. When using or
462306a36Sopenharmony_ci// redistributing this file, you may do so under either license.
562306a36Sopenharmony_ci//
662306a36Sopenharmony_ci// Copyright(c) 2023 Advanced Micro Devices, Inc.
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci// Authors: Syed Saba Kareem <Syed.SabaKareem@amd.com>
962306a36Sopenharmony_ci//
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * Common file to be used by amd platforms
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "amd.h"
1662306a36Sopenharmony_ci#include <linux/pci.h>
1762306a36Sopenharmony_ci#include <linux/export.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_civoid acp_enable_interrupts(struct acp_dev_data *adata)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	struct acp_resource *rsrc = adata->rsrc;
2262306a36Sopenharmony_ci	u32 ext_intr_ctrl;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
2562306a36Sopenharmony_ci	ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
2662306a36Sopenharmony_ci	ext_intr_ctrl |= ACP_ERROR_MASK;
2762306a36Sopenharmony_ci	writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, SND_SOC_ACP_COMMON);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_civoid acp_disable_interrupts(struct acp_dev_data *adata)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	struct acp_resource *rsrc = adata->rsrc;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
3662306a36Sopenharmony_ci	writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, SND_SOC_ACP_COMMON);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream,
4162306a36Sopenharmony_ci				    struct snd_soc_dai *dai)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	struct snd_pcm_runtime *runtime = substream->runtime;
4462306a36Sopenharmony_ci	struct acp_stream *stream = runtime->private_data;
4562306a36Sopenharmony_ci	struct device *dev = dai->component->dev;
4662306a36Sopenharmony_ci	struct acp_dev_data *adata = dev_get_drvdata(dev);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	u32 physical_addr, pdm_size, period_bytes;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	period_bytes = frames_to_bytes(runtime, runtime->period_size);
5162306a36Sopenharmony_ci	pdm_size = frames_to_bytes(runtime, runtime->buffer_size);
5262306a36Sopenharmony_ci	physical_addr = stream->reg_offset + MEM_WINDOW_START;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	/* Init ACP PDM Ring buffer */
5562306a36Sopenharmony_ci	writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
5662306a36Sopenharmony_ci	writel(pdm_size, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
5762306a36Sopenharmony_ci	writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
5862306a36Sopenharmony_ci	writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic void set_acp_pdm_clk(struct snd_pcm_substream *substream,
6262306a36Sopenharmony_ci			    struct snd_soc_dai *dai)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	struct device *dev = dai->component->dev;
6562306a36Sopenharmony_ci	struct acp_dev_data *adata = dev_get_drvdata(dev);
6662306a36Sopenharmony_ci	unsigned int pdm_ctrl;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	/* Enable default ACP PDM clk */
6962306a36Sopenharmony_ci	writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
7062306a36Sopenharmony_ci	pdm_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
7162306a36Sopenharmony_ci	pdm_ctrl |= PDM_MISC_CTRL_MASK;
7262306a36Sopenharmony_ci	writel(pdm_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
7362306a36Sopenharmony_ci	set_acp_pdm_ring_buffer(substream, dai);
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_civoid restore_acp_pdm_params(struct snd_pcm_substream *substream,
7762306a36Sopenharmony_ci			    struct acp_dev_data *adata)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	struct snd_soc_dai *dai;
8062306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *soc_runtime;
8162306a36Sopenharmony_ci	u32 ext_int_ctrl;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	soc_runtime = asoc_substream_to_rtd(substream);
8462306a36Sopenharmony_ci	dai = asoc_rtd_to_cpu(soc_runtime, 0);
8562306a36Sopenharmony_ci	/* Programming channel mask and sampling rate */
8662306a36Sopenharmony_ci	writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
8762306a36Sopenharmony_ci	writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	/* Enabling ACP Pdm interuppts */
9062306a36Sopenharmony_ci	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
9162306a36Sopenharmony_ci	ext_int_ctrl |= PDM_DMA_INTR_MASK;
9262306a36Sopenharmony_ci	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
9362306a36Sopenharmony_ci	set_acp_pdm_clk(substream, dai);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, SND_SOC_ACP_COMMON);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistatic int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
9862306a36Sopenharmony_ci				struct snd_soc_dai *dai)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct device *dev = dai->component->dev;
10162306a36Sopenharmony_ci	struct acp_dev_data *adata = dev_get_drvdata(dev);
10262306a36Sopenharmony_ci	struct acp_resource *rsrc = adata->rsrc;
10362306a36Sopenharmony_ci	struct acp_stream *stream = substream->runtime->private_data;
10462306a36Sopenharmony_ci	u32 reg_dma_size, reg_fifo_size, reg_fifo_addr;
10562306a36Sopenharmony_ci	u32 phy_addr, acp_fifo_addr, ext_int_ctrl;
10662306a36Sopenharmony_ci	unsigned int dir = substream->stream;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	switch (dai->driver->id) {
10962306a36Sopenharmony_ci	case I2S_SP_INSTANCE:
11062306a36Sopenharmony_ci		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
11162306a36Sopenharmony_ci			reg_dma_size = ACP_I2S_TX_DMA_SIZE;
11262306a36Sopenharmony_ci			acp_fifo_addr = rsrc->sram_pte_offset +
11362306a36Sopenharmony_ci					SP_PB_FIFO_ADDR_OFFSET;
11462306a36Sopenharmony_ci			reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
11562306a36Sopenharmony_ci			reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
11662306a36Sopenharmony_ci			phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
11762306a36Sopenharmony_ci			writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
11862306a36Sopenharmony_ci		} else {
11962306a36Sopenharmony_ci			reg_dma_size = ACP_I2S_RX_DMA_SIZE;
12062306a36Sopenharmony_ci			acp_fifo_addr = rsrc->sram_pte_offset +
12162306a36Sopenharmony_ci					SP_CAPT_FIFO_ADDR_OFFSET;
12262306a36Sopenharmony_ci			reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
12362306a36Sopenharmony_ci			reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
12462306a36Sopenharmony_ci			phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
12562306a36Sopenharmony_ci			writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR);
12662306a36Sopenharmony_ci		}
12762306a36Sopenharmony_ci		break;
12862306a36Sopenharmony_ci	case I2S_BT_INSTANCE:
12962306a36Sopenharmony_ci		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
13062306a36Sopenharmony_ci			reg_dma_size = ACP_BT_TX_DMA_SIZE;
13162306a36Sopenharmony_ci			acp_fifo_addr = rsrc->sram_pte_offset +
13262306a36Sopenharmony_ci					BT_PB_FIFO_ADDR_OFFSET;
13362306a36Sopenharmony_ci			reg_fifo_addr = ACP_BT_TX_FIFOADDR;
13462306a36Sopenharmony_ci			reg_fifo_size = ACP_BT_TX_FIFOSIZE;
13562306a36Sopenharmony_ci			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
13662306a36Sopenharmony_ci			writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
13762306a36Sopenharmony_ci		} else {
13862306a36Sopenharmony_ci			reg_dma_size = ACP_BT_RX_DMA_SIZE;
13962306a36Sopenharmony_ci			acp_fifo_addr = rsrc->sram_pte_offset +
14062306a36Sopenharmony_ci					BT_CAPT_FIFO_ADDR_OFFSET;
14162306a36Sopenharmony_ci			reg_fifo_addr = ACP_BT_RX_FIFOADDR;
14262306a36Sopenharmony_ci			reg_fifo_size = ACP_BT_RX_FIFOSIZE;
14362306a36Sopenharmony_ci			phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
14462306a36Sopenharmony_ci			writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
14562306a36Sopenharmony_ci		}
14662306a36Sopenharmony_ci		break;
14762306a36Sopenharmony_ci	case I2S_HS_INSTANCE:
14862306a36Sopenharmony_ci		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
14962306a36Sopenharmony_ci			reg_dma_size = ACP_HS_TX_DMA_SIZE;
15062306a36Sopenharmony_ci			acp_fifo_addr = rsrc->sram_pte_offset +
15162306a36Sopenharmony_ci					HS_PB_FIFO_ADDR_OFFSET;
15262306a36Sopenharmony_ci			reg_fifo_addr = ACP_HS_TX_FIFOADDR;
15362306a36Sopenharmony_ci			reg_fifo_size = ACP_HS_TX_FIFOSIZE;
15462306a36Sopenharmony_ci			phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
15562306a36Sopenharmony_ci			writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
15662306a36Sopenharmony_ci		} else {
15762306a36Sopenharmony_ci			reg_dma_size = ACP_HS_RX_DMA_SIZE;
15862306a36Sopenharmony_ci			acp_fifo_addr = rsrc->sram_pte_offset +
15962306a36Sopenharmony_ci					HS_CAPT_FIFO_ADDR_OFFSET;
16062306a36Sopenharmony_ci			reg_fifo_addr = ACP_HS_RX_FIFOADDR;
16162306a36Sopenharmony_ci			reg_fifo_size = ACP_HS_RX_FIFOSIZE;
16262306a36Sopenharmony_ci			phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
16362306a36Sopenharmony_ci			writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
16462306a36Sopenharmony_ci		}
16562306a36Sopenharmony_ci		break;
16662306a36Sopenharmony_ci	default:
16762306a36Sopenharmony_ci		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
16862306a36Sopenharmony_ci		return -EINVAL;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	writel(DMA_SIZE, adata->acp_base + reg_dma_size);
17262306a36Sopenharmony_ci	writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
17362306a36Sopenharmony_ci	writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
17662306a36Sopenharmony_ci	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
17762306a36Sopenharmony_ci			BIT(BT_RX_THRESHOLD(rsrc->offset)) |
17862306a36Sopenharmony_ci			BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
17962306a36Sopenharmony_ci			BIT(BT_TX_THRESHOLD(rsrc->offset)) |
18062306a36Sopenharmony_ci			BIT(HS_RX_THRESHOLD(rsrc->offset)) |
18162306a36Sopenharmony_ci			BIT(HS_TX_THRESHOLD(rsrc->offset));
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
18462306a36Sopenharmony_ci	return 0;
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ciint restore_acp_i2s_params(struct snd_pcm_substream *substream,
18862306a36Sopenharmony_ci			   struct acp_dev_data *adata,
18962306a36Sopenharmony_ci			   struct acp_stream *stream)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci	struct snd_soc_dai *dai;
19262306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *soc_runtime;
19362306a36Sopenharmony_ci	u32 tdm_fmt, reg_val, fmt_reg, val;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	soc_runtime = asoc_substream_to_rtd(substream);
19662306a36Sopenharmony_ci	dai = asoc_rtd_to_cpu(soc_runtime, 0);
19762306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
19862306a36Sopenharmony_ci		tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1];
19962306a36Sopenharmony_ci		switch (stream->dai_id) {
20062306a36Sopenharmony_ci		case I2S_BT_INSTANCE:
20162306a36Sopenharmony_ci			reg_val = ACP_BTTDM_ITER;
20262306a36Sopenharmony_ci			fmt_reg = ACP_BTTDM_TXFRMT;
20362306a36Sopenharmony_ci			break;
20462306a36Sopenharmony_ci		case I2S_SP_INSTANCE:
20562306a36Sopenharmony_ci			reg_val = ACP_I2STDM_ITER;
20662306a36Sopenharmony_ci			fmt_reg = ACP_I2STDM_TXFRMT;
20762306a36Sopenharmony_ci			break;
20862306a36Sopenharmony_ci		case I2S_HS_INSTANCE:
20962306a36Sopenharmony_ci			reg_val = ACP_HSTDM_ITER;
21062306a36Sopenharmony_ci			fmt_reg = ACP_HSTDM_TXFRMT;
21162306a36Sopenharmony_ci			break;
21262306a36Sopenharmony_ci		default:
21362306a36Sopenharmony_ci			pr_err("Invalid dai id %x\n", stream->dai_id);
21462306a36Sopenharmony_ci			return -EINVAL;
21562306a36Sopenharmony_ci		}
21662306a36Sopenharmony_ci		val = adata->xfer_tx_resolution[stream->dai_id - 1] << 3;
21762306a36Sopenharmony_ci	} else {
21862306a36Sopenharmony_ci		tdm_fmt = adata->tdm_rx_fmt[stream->dai_id - 1];
21962306a36Sopenharmony_ci		switch (stream->dai_id) {
22062306a36Sopenharmony_ci		case I2S_BT_INSTANCE:
22162306a36Sopenharmony_ci			reg_val = ACP_BTTDM_IRER;
22262306a36Sopenharmony_ci			fmt_reg = ACP_BTTDM_RXFRMT;
22362306a36Sopenharmony_ci			break;
22462306a36Sopenharmony_ci		case I2S_SP_INSTANCE:
22562306a36Sopenharmony_ci			reg_val = ACP_I2STDM_IRER;
22662306a36Sopenharmony_ci			fmt_reg = ACP_I2STDM_RXFRMT;
22762306a36Sopenharmony_ci			break;
22862306a36Sopenharmony_ci		case I2S_HS_INSTANCE:
22962306a36Sopenharmony_ci			reg_val = ACP_HSTDM_IRER;
23062306a36Sopenharmony_ci			fmt_reg = ACP_HSTDM_RXFRMT;
23162306a36Sopenharmony_ci			break;
23262306a36Sopenharmony_ci		default:
23362306a36Sopenharmony_ci			pr_err("Invalid dai id %x\n", stream->dai_id);
23462306a36Sopenharmony_ci			return -EINVAL;
23562306a36Sopenharmony_ci		}
23662306a36Sopenharmony_ci		val = adata->xfer_rx_resolution[stream->dai_id - 1] << 3;
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci	writel(val, adata->acp_base + reg_val);
23962306a36Sopenharmony_ci	if (adata->tdm_mode == TDM_ENABLE) {
24062306a36Sopenharmony_ci		writel(tdm_fmt, adata->acp_base + fmt_reg);
24162306a36Sopenharmony_ci		val = readl(adata->acp_base + reg_val);
24262306a36Sopenharmony_ci		writel(val | 0x2, adata->acp_base + reg_val);
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci	return set_acp_i2s_dma_fifo(substream, dai);
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, SND_SOC_ACP_COMMON);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic int acp_power_on(struct acp_chip_info *chip)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	u32 val, acp_pgfsm_stat_reg, acp_pgfsm_ctrl_reg;
25162306a36Sopenharmony_ci	void __iomem *base;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	base = chip->base;
25462306a36Sopenharmony_ci	switch (chip->acp_rev) {
25562306a36Sopenharmony_ci	case ACP3X_DEV:
25662306a36Sopenharmony_ci		acp_pgfsm_stat_reg = ACP_PGFSM_STATUS;
25762306a36Sopenharmony_ci		acp_pgfsm_ctrl_reg = ACP_PGFSM_CONTROL;
25862306a36Sopenharmony_ci		break;
25962306a36Sopenharmony_ci	case ACP6X_DEV:
26062306a36Sopenharmony_ci		acp_pgfsm_stat_reg = ACP6X_PGFSM_STATUS;
26162306a36Sopenharmony_ci		acp_pgfsm_ctrl_reg = ACP6X_PGFSM_CONTROL;
26262306a36Sopenharmony_ci		break;
26362306a36Sopenharmony_ci	default:
26462306a36Sopenharmony_ci		return -EINVAL;
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	val = readl(base + acp_pgfsm_stat_reg);
26862306a36Sopenharmony_ci	if (val == ACP_POWERED_ON)
26962306a36Sopenharmony_ci		return 0;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS)
27262306a36Sopenharmony_ci		writel(ACP_PGFSM_CNTL_POWER_ON_MASK, base + acp_pgfsm_ctrl_reg);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	return readl_poll_timeout(base + acp_pgfsm_stat_reg, val,
27562306a36Sopenharmony_ci				  !val, DELAY_US, ACP_TIMEOUT);
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic int acp_reset(void __iomem *base)
27962306a36Sopenharmony_ci{
28062306a36Sopenharmony_ci	u32 val;
28162306a36Sopenharmony_ci	int ret;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	writel(1, base + ACP_SOFT_RESET);
28462306a36Sopenharmony_ci	ret = readl_poll_timeout(base + ACP_SOFT_RESET, val, val & ACP_SOFT_RST_DONE_MASK,
28562306a36Sopenharmony_ci				 DELAY_US, ACP_TIMEOUT);
28662306a36Sopenharmony_ci	if (ret)
28762306a36Sopenharmony_ci		return ret;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	writel(0, base + ACP_SOFT_RESET);
29062306a36Sopenharmony_ci	return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ciint acp_init(struct acp_chip_info *chip)
29462306a36Sopenharmony_ci{
29562306a36Sopenharmony_ci	int ret;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	/* power on */
29862306a36Sopenharmony_ci	ret = acp_power_on(chip);
29962306a36Sopenharmony_ci	if (ret) {
30062306a36Sopenharmony_ci		pr_err("ACP power on failed\n");
30162306a36Sopenharmony_ci		return ret;
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci	writel(0x01, chip->base + ACP_CONTROL);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	/* Reset */
30662306a36Sopenharmony_ci	ret = acp_reset(chip->base);
30762306a36Sopenharmony_ci	if (ret) {
30862306a36Sopenharmony_ci		pr_err("ACP reset failed\n");
30962306a36Sopenharmony_ci		return ret;
31062306a36Sopenharmony_ci	}
31162306a36Sopenharmony_ci	return 0;
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(acp_init, SND_SOC_ACP_COMMON);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ciint acp_deinit(void __iomem *base)
31662306a36Sopenharmony_ci{
31762306a36Sopenharmony_ci	int ret;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/* Reset */
32062306a36Sopenharmony_ci	ret = acp_reset(base);
32162306a36Sopenharmony_ci	if (ret)
32262306a36Sopenharmony_ci		return ret;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	writel(0, base + ACP_CONTROL);
32562306a36Sopenharmony_ci	return 0;
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ciint smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	pci_write_config_dword(dev, 0x60, smn_addr);
33262306a36Sopenharmony_ci	pci_write_config_dword(dev, 0x64, data);
33362306a36Sopenharmony_ci	return 0;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(smn_write, SND_SOC_ACP_COMMON);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ciint smn_read(struct pci_dev *dev, u32 smn_addr)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	u32 data;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	pci_write_config_dword(dev, 0x60, smn_addr);
34262306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x64, &data);
34362306a36Sopenharmony_ci	return data;
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ciEXPORT_SYMBOL_NS_GPL(smn_read, SND_SOC_ACP_COMMON);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
348