xref: /openbmc/linux/sound/soc/sof/amd/acp-stream.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1e8afccf8SAjit Kumar Pandey // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2e8afccf8SAjit Kumar Pandey //
3e8afccf8SAjit Kumar Pandey // This file is provided under a dual BSD/GPLv2 license. When using or
4e8afccf8SAjit Kumar Pandey // redistributing this file, you may do so under either license.
5e8afccf8SAjit Kumar Pandey //
6e8afccf8SAjit Kumar Pandey // Copyright(c) 2021 Advanced Micro Devices, Inc.
7e8afccf8SAjit Kumar Pandey //
8e8afccf8SAjit Kumar Pandey // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9e8afccf8SAjit Kumar Pandey 
10e8afccf8SAjit Kumar Pandey /*
11e8afccf8SAjit Kumar Pandey  * Hardware interface for generic AMD audio DSP ACP IP
12e8afccf8SAjit Kumar Pandey  */
13e8afccf8SAjit Kumar Pandey 
14e8afccf8SAjit Kumar Pandey #include "../ops.h"
15e8afccf8SAjit Kumar Pandey #include "acp-dsp-offset.h"
16e8afccf8SAjit Kumar Pandey #include "acp.h"
17e8afccf8SAjit Kumar Pandey 
18e8afccf8SAjit Kumar Pandey #define PTE_GRP1_OFFSET		0x00000000
19e8afccf8SAjit Kumar Pandey #define PTE_GRP2_OFFSET		0x00800000
20e8afccf8SAjit Kumar Pandey #define PTE_GRP3_OFFSET		0x01000000
21e8afccf8SAjit Kumar Pandey #define PTE_GRP4_OFFSET		0x01800000
22e8afccf8SAjit Kumar Pandey #define PTE_GRP5_OFFSET		0x02000000
23e8afccf8SAjit Kumar Pandey #define PTE_GRP6_OFFSET		0x02800000
24e8afccf8SAjit Kumar Pandey #define PTE_GRP7_OFFSET		0x03000000
25e8afccf8SAjit Kumar Pandey #define PTE_GRP8_OFFSET		0x03800000
26e8afccf8SAjit Kumar Pandey 
acp_dsp_stream_config(struct snd_sof_dev * sdev,struct acp_dsp_stream * stream)27e8afccf8SAjit Kumar Pandey int acp_dsp_stream_config(struct snd_sof_dev *sdev, struct acp_dsp_stream *stream)
28e8afccf8SAjit Kumar Pandey {
294da6b033SAjit Kumar Pandey 	const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
30e8afccf8SAjit Kumar Pandey 	unsigned int pte_reg, pte_size, phy_addr_offset, index;
31e8afccf8SAjit Kumar Pandey 	int stream_tag = stream->stream_tag;
32e8afccf8SAjit Kumar Pandey 	u32 low, high, offset, reg_val;
33e8afccf8SAjit Kumar Pandey 	dma_addr_t addr;
34e8afccf8SAjit Kumar Pandey 	int page_idx;
35e8afccf8SAjit Kumar Pandey 
36e8afccf8SAjit Kumar Pandey 	switch (stream_tag) {
37e8afccf8SAjit Kumar Pandey 	case 1:
38e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_1;
39e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1;
40e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp1_pte);
41e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP1_OFFSET;
42e8afccf8SAjit Kumar Pandey 		break;
43e8afccf8SAjit Kumar Pandey 	case 2:
44e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_2;
45e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2;
46e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp2_pte);
47e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP2_OFFSET;
48e8afccf8SAjit Kumar Pandey 		break;
49e8afccf8SAjit Kumar Pandey 	case 3:
50e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_3;
51e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3;
52e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp3_pte);
53e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP3_OFFSET;
54e8afccf8SAjit Kumar Pandey 		break;
55e8afccf8SAjit Kumar Pandey 	case 4:
56e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_4;
57e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4;
58e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp4_pte);
59e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP4_OFFSET;
60e8afccf8SAjit Kumar Pandey 		break;
61e8afccf8SAjit Kumar Pandey 	case 5:
62e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5;
63e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5;
64e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp5_pte);
65e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP5_OFFSET;
66e8afccf8SAjit Kumar Pandey 		break;
67e8afccf8SAjit Kumar Pandey 	case 6:
68e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_6;
69e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6;
70e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp6_pte);
71e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP6_OFFSET;
72e8afccf8SAjit Kumar Pandey 		break;
73e8afccf8SAjit Kumar Pandey 	case 7:
74e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_7;
75e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7;
76e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp7_pte);
77e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP7_OFFSET;
78e8afccf8SAjit Kumar Pandey 		break;
79e8afccf8SAjit Kumar Pandey 	case 8:
80e8afccf8SAjit Kumar Pandey 		pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_8;
81e8afccf8SAjit Kumar Pandey 		pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8;
82e8afccf8SAjit Kumar Pandey 		offset = offsetof(struct scratch_reg_conf, grp8_pte);
83e8afccf8SAjit Kumar Pandey 		stream->reg_offset = PTE_GRP8_OFFSET;
84e8afccf8SAjit Kumar Pandey 		break;
85e8afccf8SAjit Kumar Pandey 	default:
86e8afccf8SAjit Kumar Pandey 		dev_err(sdev->dev, "Invalid stream tag %d\n", stream_tag);
87e8afccf8SAjit Kumar Pandey 		return -EINVAL;
88e8afccf8SAjit Kumar Pandey 	}
89e8afccf8SAjit Kumar Pandey 
90e8afccf8SAjit Kumar Pandey 	/* write phy_addr in scratch memory */
91e8afccf8SAjit Kumar Pandey 
92*40d3c041SV sujith kumar Reddy 	phy_addr_offset = sdev->debug_box.offset +
93*40d3c041SV sujith kumar Reddy 			  offsetof(struct scratch_reg_conf, reg_offset);
94e8afccf8SAjit Kumar Pandey 	index = stream_tag - 1;
95e8afccf8SAjit Kumar Pandey 	phy_addr_offset = phy_addr_offset + index * 4;
96e8afccf8SAjit Kumar Pandey 
97e8afccf8SAjit Kumar Pandey 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 +
98e8afccf8SAjit Kumar Pandey 			  phy_addr_offset, stream->reg_offset);
99e8afccf8SAjit Kumar Pandey 
100e8afccf8SAjit Kumar Pandey 	/* Group Enable */
101*40d3c041SV sujith kumar Reddy 	offset = offset + sdev->debug_box.offset;
1024da6b033SAjit Kumar Pandey 	reg_val = desc->sram_pte_offset + offset;
103e8afccf8SAjit Kumar Pandey 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, pte_reg, reg_val | BIT(31));
104e8afccf8SAjit Kumar Pandey 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, pte_size, PAGE_SIZE_4K_ENABLE);
105e8afccf8SAjit Kumar Pandey 
106e8afccf8SAjit Kumar Pandey 	for (page_idx = 0; page_idx < stream->num_pages; page_idx++) {
107e8afccf8SAjit Kumar Pandey 		addr = snd_sgbuf_get_addr(stream->dmab, page_idx * PAGE_SIZE);
108e8afccf8SAjit Kumar Pandey 
109e8afccf8SAjit Kumar Pandey 		/* Load the low address of page int ACP SRAM through SRBM */
110e8afccf8SAjit Kumar Pandey 		low = lower_32_bits(addr);
111e8afccf8SAjit Kumar Pandey 		high = upper_32_bits(addr);
112e8afccf8SAjit Kumar Pandey 
113e8afccf8SAjit Kumar Pandey 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset, low);
114e8afccf8SAjit Kumar Pandey 
115e8afccf8SAjit Kumar Pandey 		high |= BIT(31);
116e8afccf8SAjit Kumar Pandey 		snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + offset + 4, high);
117e8afccf8SAjit Kumar Pandey 		/* Move to next physically contiguous page */
118e8afccf8SAjit Kumar Pandey 		offset += 8;
119e8afccf8SAjit Kumar Pandey 	}
120e8afccf8SAjit Kumar Pandey 
121b7485ec8SAjit Kumar Pandey 	/* Flush ATU Cache after PTE Update */
122b7485ec8SAjit Kumar Pandey 	snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACPAXI2AXI_ATU_CTRL, ACP_ATU_CACHE_INVALID);
123b7485ec8SAjit Kumar Pandey 
124e8afccf8SAjit Kumar Pandey 	return 0;
125e8afccf8SAjit Kumar Pandey }
126e8afccf8SAjit Kumar Pandey 
acp_dsp_stream_get(struct snd_sof_dev * sdev,int tag)127e8afccf8SAjit Kumar Pandey struct acp_dsp_stream *acp_dsp_stream_get(struct snd_sof_dev *sdev, int tag)
128e8afccf8SAjit Kumar Pandey {
129e8afccf8SAjit Kumar Pandey 	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
130e8afccf8SAjit Kumar Pandey 	struct acp_dsp_stream *stream = adata->stream_buf;
131e8afccf8SAjit Kumar Pandey 	int i;
132e8afccf8SAjit Kumar Pandey 
133e8afccf8SAjit Kumar Pandey 	for (i = 0; i < ACP_MAX_STREAM; i++, stream++) {
134e8afccf8SAjit Kumar Pandey 		if (stream->active)
135e8afccf8SAjit Kumar Pandey 			continue;
136e8afccf8SAjit Kumar Pandey 
137e8afccf8SAjit Kumar Pandey 		/* return stream if tag not specified*/
138e8afccf8SAjit Kumar Pandey 		if (!tag) {
139e8afccf8SAjit Kumar Pandey 			stream->active = 1;
140e8afccf8SAjit Kumar Pandey 			return stream;
141e8afccf8SAjit Kumar Pandey 		}
142e8afccf8SAjit Kumar Pandey 
143e8afccf8SAjit Kumar Pandey 		/* check if this is the requested stream tag */
144e8afccf8SAjit Kumar Pandey 		if (stream->stream_tag == tag) {
145e8afccf8SAjit Kumar Pandey 			stream->active = 1;
146e8afccf8SAjit Kumar Pandey 			return stream;
147e8afccf8SAjit Kumar Pandey 		}
148e8afccf8SAjit Kumar Pandey 	}
149e8afccf8SAjit Kumar Pandey 
150e8afccf8SAjit Kumar Pandey 	dev_err(sdev->dev, "stream %d active or no inactive stream\n", tag);
151e8afccf8SAjit Kumar Pandey 	return NULL;
152e8afccf8SAjit Kumar Pandey }
153e8afccf8SAjit Kumar Pandey EXPORT_SYMBOL_NS(acp_dsp_stream_get, SND_SOC_SOF_AMD_COMMON);
154e8afccf8SAjit Kumar Pandey 
acp_dsp_stream_put(struct snd_sof_dev * sdev,struct acp_dsp_stream * acp_stream)155e8afccf8SAjit Kumar Pandey int acp_dsp_stream_put(struct snd_sof_dev *sdev,
156e8afccf8SAjit Kumar Pandey 		       struct acp_dsp_stream *acp_stream)
157e8afccf8SAjit Kumar Pandey {
158e8afccf8SAjit Kumar Pandey 	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
159e8afccf8SAjit Kumar Pandey 	struct acp_dsp_stream *stream = adata->stream_buf;
160e8afccf8SAjit Kumar Pandey 	int i;
161e8afccf8SAjit Kumar Pandey 
162e8afccf8SAjit Kumar Pandey 	/* Free an active stream */
163e8afccf8SAjit Kumar Pandey 	for (i = 0; i < ACP_MAX_STREAM; i++, stream++) {
164e8afccf8SAjit Kumar Pandey 		if (stream == acp_stream) {
165e8afccf8SAjit Kumar Pandey 			stream->active = 0;
166e8afccf8SAjit Kumar Pandey 			return 0;
167e8afccf8SAjit Kumar Pandey 		}
168e8afccf8SAjit Kumar Pandey 	}
169e8afccf8SAjit Kumar Pandey 
170e8afccf8SAjit Kumar Pandey 	dev_err(sdev->dev, "Cannot find active stream tag %d\n", acp_stream->stream_tag);
171e8afccf8SAjit Kumar Pandey 	return -EINVAL;
172e8afccf8SAjit Kumar Pandey }
173e8afccf8SAjit Kumar Pandey EXPORT_SYMBOL_NS(acp_dsp_stream_put, SND_SOC_SOF_AMD_COMMON);
174e8afccf8SAjit Kumar Pandey 
acp_dsp_stream_init(struct snd_sof_dev * sdev)175e8afccf8SAjit Kumar Pandey int acp_dsp_stream_init(struct snd_sof_dev *sdev)
176e8afccf8SAjit Kumar Pandey {
177e8afccf8SAjit Kumar Pandey 	struct acp_dev_data *adata = sdev->pdata->hw_pdata;
178e8afccf8SAjit Kumar Pandey 	int i;
179e8afccf8SAjit Kumar Pandey 
180e8afccf8SAjit Kumar Pandey 	for (i = 0; i < ACP_MAX_STREAM; i++) {
181e8afccf8SAjit Kumar Pandey 		adata->stream_buf[i].sdev = sdev;
182e8afccf8SAjit Kumar Pandey 		adata->stream_buf[i].active = 0;
183e8afccf8SAjit Kumar Pandey 		adata->stream_buf[i].stream_tag = i + 1;
184e8afccf8SAjit Kumar Pandey 	}
185e8afccf8SAjit Kumar Pandey 	return 0;
186e8afccf8SAjit Kumar Pandey }
187e8afccf8SAjit Kumar Pandey EXPORT_SYMBOL_NS(acp_dsp_stream_init, SND_SOC_SOF_AMD_COMMON);
188