File Index
Files and directories
Sign in
FILE

acp-stream.c

File preview with syntax highlighting.

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