Unverified Commit aaf7a668 authored by Venkata Prasad Potturu's avatar Venkata Prasad Potturu Committed by Mark Brown
Browse files

ASoC: amd: acp: Add new interrupt handle callbacks in acp_common_hw_ops



Add new interrupt handle callbacks in acp_common_hw_ops.
Refactor and move interrupt handler registration form platform
driver to pci driver.

Signed-off-by: default avatarVenkata Prasad Potturu <venkataprasad.potturu@amd.com>
Link: https://patch.msgid.link/20250310183201.11979-7-venkataprasad.potturu@amd.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6e60db74
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -617,7 +617,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
	writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
	writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);

	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
			BIT(BT_RX_THRESHOLD(rsrc->offset)) |
			BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
@@ -625,7 +625,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
			BIT(HS_RX_THRESHOLD(rsrc->offset)) |
			BIT(HS_TX_THRESHOLD(rsrc->offset));

	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));

	return 0;
}
+67 −12
Original line number Diff line number Diff line
@@ -27,26 +27,76 @@ const struct snd_acp_hw_ops acp_common_hw_ops = {
	/* ACP hardware initilizations */
	.acp_init = acp_init,
	.acp_deinit = acp_deinit,

	/* ACP Interrupts*/
	.irq = acp_irq_handler,
	.en_interrupts = acp_enable_interrupts,
	.dis_interrupts = acp_disable_interrupts,
};
EXPORT_SYMBOL_NS_GPL(acp_common_hw_ops, "SND_SOC_ACP_COMMON");
void acp_enable_interrupts(struct acp_dev_data *adata)

irqreturn_t acp_irq_handler(int irq, void *data)
{
	struct acp_chip_info *chip = data;
	struct acp_dev_data *adata = chip->adata;
	struct acp_resource *rsrc = adata->rsrc;
	struct acp_stream *stream;
	u16 i2s_flag = 0;
	u32 ext_intr_stat, ext_intr_stat1;

	if (adata->rsrc->no_of_ctrls == 2)
		ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(chip, (rsrc->irqp_used - 1)));

	ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used));

	spin_lock(&adata->acp_lock);
	list_for_each_entry(stream, &adata->stream_list, list) {
		if (ext_intr_stat & stream->irq_bit) {
			writel(stream->irq_bit,
			       ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used));
			snd_pcm_period_elapsed(stream->substream);
			i2s_flag = 1;
		}
		if (adata->rsrc->no_of_ctrls == 2) {
			if (ext_intr_stat1 & stream->irq_bit) {
				writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(chip,
				       (rsrc->irqp_used - 1)));
				snd_pcm_period_elapsed(stream->substream);
				i2s_flag = 1;
			}
		}
	}
	spin_unlock(&adata->acp_lock);
	if (i2s_flag)
		return IRQ_HANDLED;

	return IRQ_NONE;
}

int acp_enable_interrupts(struct acp_chip_info *chip)
{
	struct acp_resource *rsrc;
	u32 ext_intr_ctrl;

	writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
	ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
	rsrc = chip->rsrc;
	writel(0x01, ACP_EXTERNAL_INTR_ENB(chip));
	ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
	ext_intr_ctrl |= ACP_ERROR_MASK;
	writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
	writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));

	return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON");

void acp_disable_interrupts(struct acp_dev_data *adata)
int acp_disable_interrupts(struct acp_chip_info *chip)
{
	struct acp_resource *rsrc = adata->rsrc;
	struct acp_resource *rsrc;

	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
	writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
	rsrc = chip->rsrc;
	writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used));
	writel(0x00, ACP_EXTERNAL_INTR_ENB(chip));

	return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, "SND_SOC_ACP_COMMON");

@@ -90,19 +140,23 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
			    struct acp_dev_data *adata)
{
	struct snd_soc_dai *dai;
	struct device *dev;
	struct acp_chip_info *chip;
	struct snd_soc_pcm_runtime *soc_runtime;
	u32 ext_int_ctrl;

	soc_runtime = snd_soc_substream_to_rtd(substream);
	dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
	dev = dai->component->dev;
	chip = dev_get_platdata(dev);
	/* Programming channel mask and sampling rate */
	writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
	writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);

	/* Enabling ACP Pdm interuppts */
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0));
	ext_int_ctrl |= PDM_DMA_INTR_MASK;
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0));
	set_acp_pdm_clk(substream, dai);
}
EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON");
@@ -113,6 +167,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
	struct device *dev = dai->component->dev;
	struct acp_dev_data *adata = dev_get_drvdata(dev);
	struct acp_resource *rsrc = adata->rsrc;
	struct acp_chip_info *chip = dev_get_platdata(dev);
	struct acp_stream *stream = substream->runtime->private_data;
	u32 reg_dma_size, reg_fifo_size, reg_fifo_addr;
	u32 phy_addr, acp_fifo_addr, ext_int_ctrl;
@@ -185,7 +240,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
	writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
	writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);

	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
			BIT(BT_RX_THRESHOLD(rsrc->offset)) |
			BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
@@ -193,7 +248,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
			BIT(HS_RX_THRESHOLD(rsrc->offset)) |
			BIT(HS_TX_THRESHOLD(rsrc->offset));

	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
	return 0;
}

+21 −8
Original line number Diff line number Diff line
@@ -26,6 +26,15 @@
#define ACP3x_REG_START	0x1240000
#define ACP3x_REG_END	0x125C000

static irqreturn_t irq_handler(int irq, void *data)
{
	struct acp_chip_info *chip = data;

	if (chip && chip->acp_hw_ops && chip->acp_hw_ops->irq)
		return chip->acp_hw_ops->irq(irq, chip);

	return IRQ_NONE;
}
static void acp_fill_platform_dev_info(struct platform_device_info *pdevinfo,
				       struct device *parent,
				       struct fwnode_handle *fw_node,
@@ -166,6 +175,13 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
	if (ret)
		goto release_regions;

	ret = devm_request_irq(dev, pci->irq, irq_handler,
			       IRQF_SHARED, "ACP_I2S_IRQ", chip);
	if (ret) {
		dev_err(&pci->dev, "ACP I2S IRQ request failed %d\n", ret);
		return ret;
	}

	check_acp_config(pci, chip);
	if (!chip->is_pdm_dev && !chip->is_i2s_config)
		goto skip_pdev_creation;
@@ -213,20 +229,17 @@ static int __maybe_unused snd_acp_suspend(struct device *dev)
static int __maybe_unused snd_acp_resume(struct device *dev)
{
	struct acp_chip_info *chip;
	struct acp_dev_data *adata;
	struct device child;
	int ret;

	chip = dev_get_drvdata(dev);
	ret = acp_hw_init(chip);
	if (ret)
		dev_err(dev, "ACP init failed\n");
	if (chip->chip_pdev) {
		child = chip->chip_pdev->dev;
		adata = dev_get_drvdata(&child);
		if (adata)
			acp_enable_interrupts(adata);
	}

	ret = acp_hw_en_interrupts(chip);
	if (ret)
		dev_err(dev, "ACP en-interrupts failed\n");

	return ret;
}

+6 −6
Original line number Diff line number Diff line
@@ -145,7 +145,7 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
{
	struct acp_stream *stream = substream->runtime->private_data;
	struct device *dev = dai->component->dev;
	struct acp_dev_data *adata = dev_get_drvdata(dev);
	struct acp_chip_info *chip = dev_get_platdata(dev);
	u32 ext_int_ctrl;

	stream->dai_id = DMIC_INSTANCE;
@@ -154,9 +154,9 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
	stream->reg_offset = ACP_REGION2_OFFSET;

	/* Enable DMIC Interrupts */
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0));
	ext_int_ctrl |= PDM_DMA_INTR_MASK;
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0));

	return 0;
}
@@ -165,13 +165,13 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{
	struct device *dev = dai->component->dev;
	struct acp_dev_data *adata = dev_get_drvdata(dev);
	struct acp_chip_info *chip = dev_get_platdata(dev);
	u32 ext_int_ctrl;

	/* Disable DMIC interrupts */
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0));
	ext_int_ctrl &= ~PDM_DMA_INTR_MASK;
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0));
}

const struct snd_soc_dai_ops acp_dmic_dai_ops = {
+7 −43
Original line number Diff line number Diff line
@@ -107,43 +107,6 @@ static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = {
	.periods_max = CAPTURE_MAX_NUM_PERIODS,
};

static irqreturn_t i2s_irq_handler(int irq, void *data)
{
	struct acp_dev_data *adata = data;
	struct acp_resource *rsrc = adata->rsrc;
	struct acp_stream *stream;
	u16 i2s_flag = 0;
	u32 ext_intr_stat, ext_intr_stat1;

	if (adata->rsrc->no_of_ctrls == 2)
		ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));

	ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));

	spin_lock(&adata->acp_lock);
	list_for_each_entry(stream, &adata->stream_list, list) {
		if (ext_intr_stat & stream->irq_bit) {
			writel(stream->irq_bit,
			       ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
			snd_pcm_period_elapsed(stream->substream);
			i2s_flag = 1;
		}
		if (adata->rsrc->no_of_ctrls == 2) {
			if (ext_intr_stat1 & stream->irq_bit) {
				writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
				       (rsrc->irqp_used - 1)));
				snd_pcm_period_elapsed(stream->substream);
				i2s_flag = 1;
			}
		}
	}
	spin_unlock(&adata->acp_lock);
	if (i2s_flag)
		return IRQ_HANDLED;

	return IRQ_NONE;
}

void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
{
	struct acp_resource *rsrc = adata->rsrc;
@@ -278,7 +241,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
	}
	runtime->private_data = stream;

	writel(1, ACP_EXTERNAL_INTR_ENB(adata));
	writel(1, ACP_EXTERNAL_INTR_ENB(chip));

	spin_lock_irq(&adata->acp_lock);
	list_add_tail(&stream->list, &adata->stream_list);
@@ -363,16 +326,17 @@ static const struct snd_soc_component_driver acp_pcm_component = {
int acp_platform_register(struct device *dev)
{
	struct acp_dev_data *adata = dev_get_drvdata(dev);
	struct acp_chip_info *chip;
	struct snd_soc_dai_driver;
	unsigned int status;

	status = devm_request_irq(dev, adata->i2s_irq, i2s_irq_handler,
				  IRQF_SHARED, "ACP_I2S_IRQ", adata);
	if (status) {
		dev_err(dev, "ACP I2S IRQ request failed\n");
		return status;
	chip = dev_get_platdata(dev);
	if (!chip || !chip->base) {
		dev_err(dev, "ACP chip data is NULL\n");
		return -ENODEV;
	}

	chip->adata = adata;
	status = devm_snd_soc_register_component(dev, &acp_pcm_component,
						 adata->dai_driver,
						 adata->num_dai);
Loading