mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-29 11:42:36 +00:00
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: Venkata Prasad Potturu <venkataprasad.potturu@amd.com> Link: https://patch.msgid.link/20250310183201.11979-7-venkataprasad.potturu@amd.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
6e60db74b6
commit
aaf7a668bb
@ -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(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
|
||||||
writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
|
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)) |
|
ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
|
||||||
BIT(BT_RX_THRESHOLD(rsrc->offset)) |
|
BIT(BT_RX_THRESHOLD(rsrc->offset)) |
|
||||||
BIT(I2S_TX_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_RX_THRESHOLD(rsrc->offset)) |
|
||||||
BIT(HS_TX_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -27,26 +27,76 @@ const struct snd_acp_hw_ops acp_common_hw_ops = {
|
|||||||
/* ACP hardware initilizations */
|
/* ACP hardware initilizations */
|
||||||
.acp_init = acp_init,
|
.acp_init = acp_init,
|
||||||
.acp_deinit = acp_deinit,
|
.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");
|
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_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;
|
u32 ext_intr_ctrl;
|
||||||
|
|
||||||
writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
|
rsrc = chip->rsrc;
|
||||||
ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
|
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;
|
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");
|
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));
|
rsrc = chip->rsrc;
|
||||||
writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
|
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");
|
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 acp_dev_data *adata)
|
||||||
{
|
{
|
||||||
struct snd_soc_dai *dai;
|
struct snd_soc_dai *dai;
|
||||||
|
struct device *dev;
|
||||||
|
struct acp_chip_info *chip;
|
||||||
struct snd_soc_pcm_runtime *soc_runtime;
|
struct snd_soc_pcm_runtime *soc_runtime;
|
||||||
u32 ext_int_ctrl;
|
u32 ext_int_ctrl;
|
||||||
|
|
||||||
soc_runtime = snd_soc_substream_to_rtd(substream);
|
soc_runtime = snd_soc_substream_to_rtd(substream);
|
||||||
dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
|
dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
|
||||||
|
dev = dai->component->dev;
|
||||||
|
chip = dev_get_platdata(dev);
|
||||||
/* Programming channel mask and sampling rate */
|
/* Programming channel mask and sampling rate */
|
||||||
writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
|
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);
|
writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
|
||||||
|
|
||||||
/* Enabling ACP Pdm interuppts */
|
/* 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;
|
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);
|
set_acp_pdm_clk(substream, dai);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON");
|
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 device *dev = dai->component->dev;
|
||||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
||||||
struct acp_resource *rsrc = adata->rsrc;
|
struct acp_resource *rsrc = adata->rsrc;
|
||||||
|
struct acp_chip_info *chip = dev_get_platdata(dev);
|
||||||
struct acp_stream *stream = substream->runtime->private_data;
|
struct acp_stream *stream = substream->runtime->private_data;
|
||||||
u32 reg_dma_size, reg_fifo_size, reg_fifo_addr;
|
u32 reg_dma_size, reg_fifo_size, reg_fifo_addr;
|
||||||
u32 phy_addr, acp_fifo_addr, ext_int_ctrl;
|
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(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
|
||||||
writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
|
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)) |
|
ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
|
||||||
BIT(BT_RX_THRESHOLD(rsrc->offset)) |
|
BIT(BT_RX_THRESHOLD(rsrc->offset)) |
|
||||||
BIT(I2S_TX_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_RX_THRESHOLD(rsrc->offset)) |
|
||||||
BIT(HS_TX_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,15 @@
|
|||||||
#define ACP3x_REG_START 0x1240000
|
#define ACP3x_REG_START 0x1240000
|
||||||
#define ACP3x_REG_END 0x125C000
|
#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,
|
static void acp_fill_platform_dev_info(struct platform_device_info *pdevinfo,
|
||||||
struct device *parent,
|
struct device *parent,
|
||||||
struct fwnode_handle *fw_node,
|
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)
|
if (ret)
|
||||||
goto release_regions;
|
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);
|
check_acp_config(pci, chip);
|
||||||
if (!chip->is_pdm_dev && !chip->is_i2s_config)
|
if (!chip->is_pdm_dev && !chip->is_i2s_config)
|
||||||
goto skip_pdev_creation;
|
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)
|
static int __maybe_unused snd_acp_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct acp_chip_info *chip;
|
struct acp_chip_info *chip;
|
||||||
struct acp_dev_data *adata;
|
|
||||||
struct device child;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
chip = dev_get_drvdata(dev);
|
chip = dev_get_drvdata(dev);
|
||||||
ret = acp_hw_init(chip);
|
ret = acp_hw_init(chip);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(dev, "ACP init failed\n");
|
dev_err(dev, "ACP init failed\n");
|
||||||
if (chip->chip_pdev) {
|
|
||||||
child = chip->chip_pdev->dev;
|
ret = acp_hw_en_interrupts(chip);
|
||||||
adata = dev_get_drvdata(&child);
|
if (ret)
|
||||||
if (adata)
|
dev_err(dev, "ACP en-interrupts failed\n");
|
||||||
acp_enable_interrupts(adata);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
|
|||||||
{
|
{
|
||||||
struct acp_stream *stream = substream->runtime->private_data;
|
struct acp_stream *stream = substream->runtime->private_data;
|
||||||
struct device *dev = dai->component->dev;
|
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;
|
u32 ext_int_ctrl;
|
||||||
|
|
||||||
stream->dai_id = DMIC_INSTANCE;
|
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;
|
stream->reg_offset = ACP_REGION2_OFFSET;
|
||||||
|
|
||||||
/* Enable DMIC Interrupts */
|
/* 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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -165,13 +165,13 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
|
|||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct device *dev = dai->component->dev;
|
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;
|
u32 ext_int_ctrl;
|
||||||
|
|
||||||
/* Disable DMIC interrupts */
|
/* 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;
|
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 = {
|
const struct snd_soc_dai_ops acp_dmic_dai_ops = {
|
||||||
|
@ -107,43 +107,6 @@ static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = {
|
|||||||
.periods_max = CAPTURE_MAX_NUM_PERIODS,
|
.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)
|
void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
|
||||||
{
|
{
|
||||||
struct acp_resource *rsrc = adata->rsrc;
|
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;
|
runtime->private_data = stream;
|
||||||
|
|
||||||
writel(1, ACP_EXTERNAL_INTR_ENB(adata));
|
writel(1, ACP_EXTERNAL_INTR_ENB(chip));
|
||||||
|
|
||||||
spin_lock_irq(&adata->acp_lock);
|
spin_lock_irq(&adata->acp_lock);
|
||||||
list_add_tail(&stream->list, &adata->stream_list);
|
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)
|
int acp_platform_register(struct device *dev)
|
||||||
{
|
{
|
||||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
||||||
|
struct acp_chip_info *chip;
|
||||||
struct snd_soc_dai_driver;
|
struct snd_soc_dai_driver;
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
status = devm_request_irq(dev, adata->i2s_irq, i2s_irq_handler,
|
chip = dev_get_platdata(dev);
|
||||||
IRQF_SHARED, "ACP_I2S_IRQ", adata);
|
if (!chip || !chip->base) {
|
||||||
if (status) {
|
dev_err(dev, "ACP chip data is NULL\n");
|
||||||
dev_err(dev, "ACP I2S IRQ request failed\n");
|
return -ENODEV;
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chip->adata = adata;
|
||||||
status = devm_snd_soc_register_component(dev, &acp_pcm_component,
|
status = devm_snd_soc_register_component(dev, &acp_pcm_component,
|
||||||
adata->dai_driver,
|
adata->dai_driver,
|
||||||
adata->num_dai);
|
adata->num_dai);
|
||||||
|
@ -192,6 +192,7 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chip->rsrc = &rsrc;
|
||||||
adata->i2s_irq = res->start;
|
adata->i2s_irq = res->start;
|
||||||
adata->dev = dev;
|
adata->dev = dev;
|
||||||
adata->dai_driver = acp_rmb_dai;
|
adata->dai_driver = acp_rmb_dai;
|
||||||
@ -208,7 +209,11 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
acp_enable_interrupts(adata);
|
ret = acp_hw_en_interrupts(chip);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "ACP en-interrupts failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
acp_platform_register(dev);
|
acp_platform_register(dev);
|
||||||
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
||||||
pm_runtime_use_autosuspend(&pdev->dev);
|
pm_runtime_use_autosuspend(&pdev->dev);
|
||||||
@ -221,9 +226,13 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
|
|||||||
static void rembrandt_audio_remove(struct platform_device *pdev)
|
static void rembrandt_audio_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
struct acp_chip_info *chip = dev_get_platdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = acp_hw_dis_interrupts(chip);
|
||||||
|
if (ret)
|
||||||
|
dev_err(dev, "ACP dis-interrupts failed\n");
|
||||||
|
|
||||||
acp_disable_interrupts(adata);
|
|
||||||
acp_platform_unregister(dev);
|
acp_platform_unregister(dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,7 @@ static int renoir_audio_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
adata->i2s_irq = ret;
|
adata->i2s_irq = ret;
|
||||||
|
|
||||||
|
chip->rsrc = &rsrc;
|
||||||
adata->dev = dev;
|
adata->dev = dev;
|
||||||
adata->dai_driver = acp_renoir_dai;
|
adata->dai_driver = acp_renoir_dai;
|
||||||
adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
|
adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
|
||||||
@ -150,7 +151,11 @@ static int renoir_audio_probe(struct platform_device *pdev)
|
|||||||
adata->flag = chip->flag;
|
adata->flag = chip->flag;
|
||||||
|
|
||||||
dev_set_drvdata(dev, adata);
|
dev_set_drvdata(dev, adata);
|
||||||
acp_enable_interrupts(adata);
|
ret = acp_hw_en_interrupts(chip);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "ACP en-interrupts failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
acp_platform_register(dev);
|
acp_platform_register(dev);
|
||||||
|
|
||||||
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
||||||
@ -164,9 +169,13 @@ static int renoir_audio_probe(struct platform_device *pdev)
|
|||||||
static void renoir_audio_remove(struct platform_device *pdev)
|
static void renoir_audio_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
struct acp_chip_info *chip = dev_get_platdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = acp_hw_dis_interrupts(chip);
|
||||||
|
if (ret)
|
||||||
|
dev_err(dev, "ACP dis-interrupts failed\n");
|
||||||
|
|
||||||
acp_disable_interrupts(adata);
|
|
||||||
acp_platform_unregister(dev);
|
acp_platform_unregister(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +243,7 @@ static int acp63_audio_probe(struct platform_device *pdev)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chip->rsrc = &rsrc;
|
||||||
adata->i2s_irq = res->start;
|
adata->i2s_irq = res->start;
|
||||||
adata->dev = dev;
|
adata->dev = dev;
|
||||||
adata->dai_driver = acp63_dai;
|
adata->dai_driver = acp63_dai;
|
||||||
@ -258,7 +259,11 @@ static int acp63_audio_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
acp_enable_interrupts(adata);
|
ret = acp_hw_en_interrupts(chip);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "ACP en-interrupts failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
acp_platform_register(dev);
|
acp_platform_register(dev);
|
||||||
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
||||||
pm_runtime_use_autosuspend(&pdev->dev);
|
pm_runtime_use_autosuspend(&pdev->dev);
|
||||||
@ -271,9 +276,13 @@ static int acp63_audio_probe(struct platform_device *pdev)
|
|||||||
static void acp63_audio_remove(struct platform_device *pdev)
|
static void acp63_audio_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
struct acp_chip_info *chip = dev_get_platdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = acp_hw_dis_interrupts(chip);
|
||||||
|
if (ret)
|
||||||
|
dev_err(dev, "ACP dis-interrupts failed\n");
|
||||||
|
|
||||||
acp_disable_interrupts(adata);
|
|
||||||
acp_platform_unregister(dev);
|
acp_platform_unregister(dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
}
|
}
|
||||||
|
@ -174,6 +174,7 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chip->rsrc = &rsrc;
|
||||||
adata->i2s_irq = res->start;
|
adata->i2s_irq = res->start;
|
||||||
adata->dev = dev;
|
adata->dev = dev;
|
||||||
adata->dai_driver = acp70_dai;
|
adata->dai_driver = acp70_dai;
|
||||||
@ -190,7 +191,11 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
|
|||||||
dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n");
|
dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
acp_enable_interrupts(adata);
|
ret = acp_hw_en_interrupts(chip);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "ACP en-interrupts failed\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
acp_platform_register(dev);
|
acp_platform_register(dev);
|
||||||
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
|
||||||
pm_runtime_use_autosuspend(&pdev->dev);
|
pm_runtime_use_autosuspend(&pdev->dev);
|
||||||
@ -203,9 +208,13 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
|
|||||||
static void acp_acp70_audio_remove(struct platform_device *pdev)
|
static void acp_acp70_audio_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
struct acp_chip_info *chip = dev_get_platdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = acp_hw_dis_interrupts(chip);
|
||||||
|
if (ret)
|
||||||
|
dev_err(dev, "ACP dis-interrupts failed\n");
|
||||||
|
|
||||||
acp_disable_interrupts(adata);
|
|
||||||
acp_platform_unregister(dev);
|
acp_platform_unregister(dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
}
|
}
|
||||||
|
@ -147,10 +147,12 @@ struct acp_chip_info {
|
|||||||
struct snd_acp_hw_ops *acp_hw_ops;
|
struct snd_acp_hw_ops *acp_hw_ops;
|
||||||
int (*acp_hw_ops_init)(struct acp_chip_info *chip);
|
int (*acp_hw_ops_init)(struct acp_chip_info *chip);
|
||||||
struct platform_device *chip_pdev;
|
struct platform_device *chip_pdev;
|
||||||
|
struct acp_resource *rsrc; /* Platform specific resources*/
|
||||||
struct platform_device *dmic_codec_dev;
|
struct platform_device *dmic_codec_dev;
|
||||||
struct platform_device *acp_plat_dev;
|
struct platform_device *acp_plat_dev;
|
||||||
struct platform_device *mach_dev;
|
struct platform_device *mach_dev;
|
||||||
struct snd_soc_acpi_mach *machines;
|
struct snd_soc_acpi_mach *machines;
|
||||||
|
struct acp_dev_data *adata;
|
||||||
u32 addr;
|
u32 addr;
|
||||||
unsigned int flag; /* Distinguish b/w Legacy or Only PDM */
|
unsigned int flag; /* Distinguish b/w Legacy or Only PDM */
|
||||||
bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */
|
bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */
|
||||||
@ -215,11 +217,19 @@ struct acp_dev_data {
|
|||||||
* struct snd_acp_hw_ops - ACP PCI driver platform specific ops
|
* struct snd_acp_hw_ops - ACP PCI driver platform specific ops
|
||||||
* @acp_init: ACP initialization
|
* @acp_init: ACP initialization
|
||||||
* @acp_deinit: ACP de-initialization
|
* @acp_deinit: ACP de-initialization
|
||||||
|
* @irq: ACP irq handler
|
||||||
|
* @en_interrupts: ACP enable interrupts
|
||||||
|
* @dis_interrupts: ACP disable interrupts
|
||||||
*/
|
*/
|
||||||
struct snd_acp_hw_ops {
|
struct snd_acp_hw_ops {
|
||||||
/* ACP hardware initilizations */
|
/* ACP hardware initilizations */
|
||||||
int (*acp_init)(struct acp_chip_info *chip);
|
int (*acp_init)(struct acp_chip_info *chip);
|
||||||
int (*acp_deinit)(struct acp_chip_info *chip);
|
int (*acp_deinit)(struct acp_chip_info *chip);
|
||||||
|
|
||||||
|
/* ACP Interrupts*/
|
||||||
|
irqreturn_t (*irq)(int irq, void *data);
|
||||||
|
int (*en_interrupts)(struct acp_chip_info *chip);
|
||||||
|
int (*dis_interrupts)(struct acp_chip_info *chip);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum acp_config {
|
enum acp_config {
|
||||||
@ -332,8 +342,9 @@ int acp_machine_select(struct acp_chip_info *chip);
|
|||||||
|
|
||||||
int acp_init(struct acp_chip_info *chip);
|
int acp_init(struct acp_chip_info *chip);
|
||||||
int acp_deinit(struct acp_chip_info *chip);
|
int acp_deinit(struct acp_chip_info *chip);
|
||||||
void acp_enable_interrupts(struct acp_dev_data *adata);
|
int acp_enable_interrupts(struct acp_chip_info *chip);
|
||||||
void acp_disable_interrupts(struct acp_dev_data *adata);
|
int acp_disable_interrupts(struct acp_chip_info *chip);
|
||||||
|
irqreturn_t acp_irq_handler(int irq, void *data);
|
||||||
|
|
||||||
extern struct snd_acp_hw_ops acp31_common_hw_ops;
|
extern struct snd_acp_hw_ops acp31_common_hw_ops;
|
||||||
extern struct snd_acp_hw_ops acp6x_common_hw_ops;
|
extern struct snd_acp_hw_ops acp6x_common_hw_ops;
|
||||||
@ -370,6 +381,20 @@ static inline int acp_hw_deinit(struct acp_chip_info *chip)
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int acp_hw_en_interrupts(struct acp_chip_info *chip)
|
||||||
|
{
|
||||||
|
if (chip && chip->acp_hw_ops && chip->acp_hw_ops->en_interrupts)
|
||||||
|
return chip->acp_hw_ops->en_interrupts(chip);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int acp_hw_dis_interrupts(struct acp_chip_info *chip)
|
||||||
|
{
|
||||||
|
if (chip && chip->acp_hw_ops && chip->acp_hw_ops->dis_interrupts)
|
||||||
|
chip->acp_hw_ops->dis_interrupts(chip);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
|
static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
|
||||||
{
|
{
|
||||||
u64 byte_count = 0, low = 0, high = 0;
|
u64 byte_count = 0, low = 0, high = 0;
|
||||||
|
@ -29,13 +29,13 @@
|
|||||||
#define ACP_PIN_CONFIG 0x1440
|
#define ACP_PIN_CONFIG 0x1440
|
||||||
#define ACP3X_PIN_CONFIG 0x1400
|
#define ACP3X_PIN_CONFIG 0x1400
|
||||||
|
|
||||||
#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
|
#define ACP_EXTERNAL_INTR_REG_ADDR(chip, offset, ctrl) \
|
||||||
(adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
|
(chip->base + chip->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
|
||||||
|
|
||||||
#define ACP_EXTERNAL_INTR_ENB(adata) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x0, 0x0)
|
#define ACP_EXTERNAL_INTR_ENB(chip) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x0, 0x0)
|
||||||
#define ACP_EXTERNAL_INTR_CNTL(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x4, ctrl)
|
#define ACP_EXTERNAL_INTR_CNTL(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x4, ctrl)
|
||||||
#define ACP_EXTERNAL_INTR_STAT(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, \
|
#define ACP_EXTERNAL_INTR_STAT(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, \
|
||||||
(0x4 + (adata->rsrc->no_of_ctrls * 0x04)), ctrl)
|
(0x4 + (chip->rsrc->no_of_ctrls * 0x04)), ctrl)
|
||||||
|
|
||||||
/* Registers from ACP_AUDIO_BUFFERS block */
|
/* Registers from ACP_AUDIO_BUFFERS block */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user