brintos

brintos / linux-shallow public Read only

0
0
Text · 5.4 KiB · 6f40ef7 Raw
188 lines · 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 or4// 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 IP12 */13 14#include "../ops.h"15#include "acp-dsp-offset.h"16#include "acp.h"17 18#define PTE_GRP1_OFFSET		0x0000000019#define PTE_GRP2_OFFSET		0x0080000020#define PTE_GRP3_OFFSET		0x0100000021#define PTE_GRP4_OFFSET		0x0180000022#define PTE_GRP5_OFFSET		0x0200000023#define PTE_GRP6_OFFSET		0x0280000024#define PTE_GRP7_OFFSET		0x0300000025#define PTE_GRP8_OFFSET		0x0380000026 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);188