ASoC: amd: Refactoring of DAI from DMA driver
ASoC: PCM DMA driver should only have dma ops. So Removed all DAI related functionality.Refactoring the PCM DMA diver code.Added new file containing only DAI ops Signed-off-by: Ravulapati Vishnu vardhan rao <Vishnuvardhanrao.Ravulapati@amd.com> Link: https://lore.kernel.org/r/1577540460-21438-2-git-send-email-Vishnuvardhanrao.Ravulapati@amd.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
		
							parent
							
								
									3863857dd5
								
							
						
					
					
						commit
						c9fe7db6e8
					
				| @ -2,5 +2,7 @@ | |||||||
| # Raven Ridge platform Support
 | # Raven Ridge platform Support
 | ||||||
| snd-pci-acp3x-objs	:= pci-acp3x.o | snd-pci-acp3x-objs	:= pci-acp3x.o | ||||||
| snd-acp3x-pcm-dma-objs	:= acp3x-pcm-dma.o | snd-acp3x-pcm-dma-objs	:= acp3x-pcm-dma.o | ||||||
|  | snd-acp3x-i2s-objs	:= acp3x-i2s.o | ||||||
| obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-pci-acp3x.o | obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-pci-acp3x.o | ||||||
| obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-acp3x-pcm-dma.o | obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-acp3x-pcm-dma.o | ||||||
|  | obj-$(CONFIG_SND_SOC_AMD_ACP3x)	 += snd-acp3x-i2s.o | ||||||
|  | |||||||
							
								
								
									
										261
									
								
								sound/soc/amd/raven/acp3x-i2s.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								sound/soc/amd/raven/acp3x-i2s.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,261 @@ | |||||||
|  | // SPDX-License-Identifier: GPL-2.0+
 | ||||||
|  | //
 | ||||||
|  | // AMD ALSA SoC PCM Driver
 | ||||||
|  | //
 | ||||||
|  | //Copyright 2016 Advanced Micro Devices, Inc.
 | ||||||
|  | 
 | ||||||
|  | #include <linux/platform_device.h> | ||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/err.h> | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <sound/pcm_params.h> | ||||||
|  | #include <sound/soc.h> | ||||||
|  | #include <sound/soc-dai.h> | ||||||
|  | #include <linux/dma-mapping.h> | ||||||
|  | 
 | ||||||
|  | #include "acp3x.h" | ||||||
|  | 
 | ||||||
|  | #define DRV_NAME "acp3x-i2s" | ||||||
|  | 
 | ||||||
|  | static int acp3x_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | ||||||
|  | 					unsigned int fmt) | ||||||
|  | { | ||||||
|  | 	struct i2s_dev_data *adata; | ||||||
|  | 	int mode; | ||||||
|  | 
 | ||||||
|  | 	adata = snd_soc_dai_get_drvdata(cpu_dai); | ||||||
|  | 	mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||||||
|  | 	switch (mode) { | ||||||
|  | 	case SND_SOC_DAIFMT_I2S: | ||||||
|  | 		adata->tdm_mode = false; | ||||||
|  | 		break; | ||||||
|  | 	case SND_SOC_DAIFMT_DSP_A: | ||||||
|  | 		adata->tdm_mode = true; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int acp3x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, | ||||||
|  | 		u32 tx_mask, u32 rx_mask, int slots, int slot_width) | ||||||
|  | { | ||||||
|  | 	struct i2s_dev_data *adata; | ||||||
|  | 	u32 val, reg_val, frmt_val, frm_len; | ||||||
|  | 	u16 slot_len; | ||||||
|  | 
 | ||||||
|  | 	adata = snd_soc_dai_get_drvdata(cpu_dai); | ||||||
|  | 
 | ||||||
|  | 	/* These values are as per Hardware Spec */ | ||||||
|  | 	switch (slot_width) { | ||||||
|  | 	case SLOT_WIDTH_8: | ||||||
|  | 		slot_len = 8; | ||||||
|  | 		break; | ||||||
|  | 	case SLOT_WIDTH_16: | ||||||
|  | 		slot_len = 16; | ||||||
|  | 		break; | ||||||
|  | 	case SLOT_WIDTH_24: | ||||||
|  | 		slot_len = 24; | ||||||
|  | 		break; | ||||||
|  | 	case SLOT_WIDTH_32: | ||||||
|  | 		slot_len = 0; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Enable I2S/BT channels TDM, respective TX/RX frame lengths.*/ | ||||||
|  | 
 | ||||||
|  | 	frm_len = FRM_LEN | (slots << 15) | (slot_len << 18); | ||||||
|  | 	if (adata->substream_type == SNDRV_PCM_STREAM_PLAYBACK) { | ||||||
|  | 		reg_val = mmACP_BTTDM_ITER; | ||||||
|  | 		frmt_val = mmACP_BTTDM_TXFRMT; | ||||||
|  | 	} else { | ||||||
|  | 		reg_val = mmACP_BTTDM_IRER; | ||||||
|  | 		frmt_val = mmACP_BTTDM_RXFRMT; | ||||||
|  | 	} | ||||||
|  | 	val = rv_readl(adata->acp3x_base + reg_val); | ||||||
|  | 	rv_writel(val | 0x2, adata->acp3x_base + reg_val); | ||||||
|  | 	rv_writel(frm_len, adata->acp3x_base + frmt_val); | ||||||
|  | 	adata->tdm_fmt = frm_len; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int acp3x_i2s_hwparams(struct snd_pcm_substream *substream, | ||||||
|  | 	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||||||
|  | { | ||||||
|  | 	struct i2s_stream_instance *rtd; | ||||||
|  | 	u32 val; | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	rtd = substream->runtime->private_data; | ||||||
|  | 
 | ||||||
|  | 	/* These values are as per Hardware Spec */ | ||||||
|  | 	switch (params_format(params)) { | ||||||
|  | 	case SNDRV_PCM_FORMAT_U8: | ||||||
|  | 	case SNDRV_PCM_FORMAT_S8: | ||||||
|  | 		rtd->xfer_resolution = 0x0; | ||||||
|  | 		break; | ||||||
|  | 	case SNDRV_PCM_FORMAT_S16_LE: | ||||||
|  | 		rtd->xfer_resolution = 0x02; | ||||||
|  | 		break; | ||||||
|  | 	case SNDRV_PCM_FORMAT_S24_LE: | ||||||
|  | 		rtd->xfer_resolution = 0x04; | ||||||
|  | 		break; | ||||||
|  | 	case SNDRV_PCM_FORMAT_S32_LE: | ||||||
|  | 		rtd->xfer_resolution = 0x05; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||||||
|  | 		reg_val = mmACP_BTTDM_ITER; | ||||||
|  | 	else | ||||||
|  | 		reg_val = mmACP_BTTDM_IRER; | ||||||
|  | 
 | ||||||
|  | 	val = rv_readl(rtd->acp3x_base + reg_val); | ||||||
|  | 	val = val | (rtd->xfer_resolution  << 3); | ||||||
|  | 	rv_writel(val, rtd->acp3x_base + reg_val); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, | ||||||
|  | 				int cmd, struct snd_soc_dai *dai) | ||||||
|  | { | ||||||
|  | 	struct i2s_stream_instance *rtd; | ||||||
|  | 	u32 val, period_bytes; | ||||||
|  | 	int ret, reg_val; | ||||||
|  | 
 | ||||||
|  | 	rtd = substream->runtime->private_data; | ||||||
|  | 	period_bytes = frames_to_bytes(substream->runtime, | ||||||
|  | 			substream->runtime->period_size); | ||||||
|  | 	switch (cmd) { | ||||||
|  | 	case SNDRV_PCM_TRIGGER_START: | ||||||
|  | 	case SNDRV_PCM_TRIGGER_RESUME: | ||||||
|  | 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||||||
|  | 		rtd->bytescount = acp_get_byte_count(rtd, | ||||||
|  | 						substream->stream); | ||||||
|  | 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||||||
|  | 			reg_val = mmACP_BTTDM_ITER; | ||||||
|  | 			rv_writel(period_bytes, rtd->acp3x_base + | ||||||
|  | 					mmACP_BT_TX_INTR_WATERMARK_SIZE); | ||||||
|  | 		} else { | ||||||
|  | 			reg_val = mmACP_BTTDM_IRER; | ||||||
|  | 			rv_writel(period_bytes, rtd->acp3x_base + | ||||||
|  | 					mmACP_BT_RX_INTR_WATERMARK_SIZE); | ||||||
|  | 		} | ||||||
|  | 		val = rv_readl(rtd->acp3x_base + reg_val); | ||||||
|  | 		val = val | BIT(0); | ||||||
|  | 		rv_writel(val, rtd->acp3x_base + reg_val); | ||||||
|  | 		rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER); | ||||||
|  | 		break; | ||||||
|  | 	case SNDRV_PCM_TRIGGER_STOP: | ||||||
|  | 	case SNDRV_PCM_TRIGGER_SUSPEND: | ||||||
|  | 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||||||
|  | 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||||||
|  | 			reg_val = mmACP_BTTDM_ITER; | ||||||
|  | 		else | ||||||
|  | 			reg_val = mmACP_BTTDM_IRER; | ||||||
|  | 
 | ||||||
|  | 		val = rv_readl(rtd->acp3x_base + reg_val); | ||||||
|  | 		val = val & ~BIT(0); | ||||||
|  | 		rv_writel(val, rtd->acp3x_base + reg_val); | ||||||
|  | 		rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER); | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		ret = -EINVAL; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct snd_soc_dai_ops acp3x_i2s_dai_ops = { | ||||||
|  | 	.hw_params = acp3x_i2s_hwparams, | ||||||
|  | 	.trigger = acp3x_i2s_trigger, | ||||||
|  | 	.set_fmt = acp3x_i2s_set_fmt, | ||||||
|  | 	.set_tdm_slot = acp3x_i2s_set_tdm_slot, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct snd_soc_component_driver acp3x_dai_component = { | ||||||
|  | 	.name           = "acp3x-i2s", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static struct snd_soc_dai_driver acp3x_i2s_dai = { | ||||||
|  | 	.playback = { | ||||||
|  | 		.rates = SNDRV_PCM_RATE_8000_96000, | ||||||
|  | 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | | ||||||
|  | 			SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | | ||||||
|  | 			SNDRV_PCM_FMTBIT_S32_LE, | ||||||
|  | 		.channels_min = 2, | ||||||
|  | 		.channels_max = 8, | ||||||
|  | 		.rate_min = 8000, | ||||||
|  | 		.rate_max = 96000, | ||||||
|  | 	}, | ||||||
|  | 	.capture = { | ||||||
|  | 		.rates = SNDRV_PCM_RATE_8000_48000, | ||||||
|  | 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | | ||||||
|  | 			SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | | ||||||
|  | 			SNDRV_PCM_FMTBIT_S32_LE, | ||||||
|  | 		.channels_min = 2, | ||||||
|  | 		.channels_max = 2, | ||||||
|  | 		.rate_min = 8000, | ||||||
|  | 		.rate_max = 48000, | ||||||
|  | 	}, | ||||||
|  | 	.ops = &acp3x_i2s_dai_ops, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int acp3x_dai_probe(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	struct resource *res; | ||||||
|  | 	struct i2s_dev_data *adata; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data), | ||||||
|  | 			GFP_KERNEL); | ||||||
|  | 	if (!adata) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | 	if (!res) { | ||||||
|  | 		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start, | ||||||
|  | 						resource_size(res)); | ||||||
|  | 	if (IS_ERR(adata->acp3x_base)) | ||||||
|  | 		return PTR_ERR(adata->acp3x_base); | ||||||
|  | 
 | ||||||
|  | 	adata->i2s_irq = res->start; | ||||||
|  | 	dev_set_drvdata(&pdev->dev, adata); | ||||||
|  | 	ret = devm_snd_soc_register_component(&pdev->dev, | ||||||
|  | 			&acp3x_dai_component, &acp3x_i2s_dai, 1); | ||||||
|  | 	if (ret) { | ||||||
|  | 		dev_err(&pdev->dev, "Fail to register acp i2s dai\n"); | ||||||
|  | 		return -ENODEV; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int acp3x_dai_remove(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	/* As we use devm_ memory alloc there is nothing TBD here */ | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct platform_driver acp3x_dai_driver = { | ||||||
|  | 	.probe = acp3x_dai_probe, | ||||||
|  | 	.remove = acp3x_dai_remove, | ||||||
|  | 	.driver = { | ||||||
|  | 		.name = "acp3x_i2s_playcap", | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | module_platform_driver(acp3x_dai_driver); | ||||||
|  | 
 | ||||||
|  | MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); | ||||||
|  | MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver"); | ||||||
|  | MODULE_LICENSE("GPL v2"); | ||||||
|  | MODULE_ALIAS("platform:" DRV_NAME); | ||||||
| @ -9,7 +9,6 @@ | |||||||
| #include <linux/err.h> | #include <linux/err.h> | ||||||
| #include <linux/io.h> | #include <linux/io.h> | ||||||
| #include <linux/pm_runtime.h> | #include <linux/pm_runtime.h> | ||||||
| #include <sound/pcm.h> |  | ||||||
| #include <sound/pcm_params.h> | #include <sound/pcm_params.h> | ||||||
| #include <sound/soc.h> | #include <sound/soc.h> | ||||||
| #include <sound/soc-dai.h> | #include <sound/soc-dai.h> | ||||||
| @ -18,24 +17,6 @@ | |||||||
| 
 | 
 | ||||||
| #define DRV_NAME "acp3x-i2s-audio" | #define DRV_NAME "acp3x-i2s-audio" | ||||||
| 
 | 
 | ||||||
| struct i2s_dev_data { |  | ||||||
| 	bool tdm_mode; |  | ||||||
| 	unsigned int i2s_irq; |  | ||||||
| 	u32 tdm_fmt; |  | ||||||
| 	void __iomem *acp3x_base; |  | ||||||
| 	struct snd_pcm_substream *play_stream; |  | ||||||
| 	struct snd_pcm_substream *capture_stream; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct i2s_stream_instance { |  | ||||||
| 	u16 num_pages; |  | ||||||
| 	u16 channels; |  | ||||||
| 	u32 xfer_resolution; |  | ||||||
| 	u64 bytescount; |  | ||||||
| 	dma_addr_t dma_addr; |  | ||||||
| 	void __iomem *acp3x_base; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = { | static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = { | ||||||
| 	.info = SNDRV_PCM_INFO_INTERLEAVED | | 	.info = SNDRV_PCM_INFO_INTERLEAVED | | ||||||
| 		SNDRV_PCM_INFO_BLOCK_TRANSFER | | 		SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||||||
| @ -178,10 +159,11 @@ static int acp3x_deinit(void __iomem *acp3x_base) | |||||||
| 
 | 
 | ||||||
| static irqreturn_t i2s_irq_handler(int irq, void *dev_id) | static irqreturn_t i2s_irq_handler(int irq, void *dev_id) | ||||||
| { | { | ||||||
|  | 	struct i2s_dev_data *rv_i2s_data; | ||||||
| 	u16 play_flag, cap_flag; | 	u16 play_flag, cap_flag; | ||||||
| 	u32 val; | 	u32 val; | ||||||
| 	struct i2s_dev_data *rv_i2s_data = dev_id; |  | ||||||
| 
 | 
 | ||||||
|  | 	rv_i2s_data = dev_id; | ||||||
| 	if (!rv_i2s_data) | 	if (!rv_i2s_data) | ||||||
| 		return IRQ_NONE; | 		return IRQ_NONE; | ||||||
| 
 | 
 | ||||||
| @ -278,11 +260,17 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction) | |||||||
| static int acp3x_dma_open(struct snd_soc_component *component, | static int acp3x_dma_open(struct snd_soc_component *component, | ||||||
| 			  struct snd_pcm_substream *substream) | 			  struct snd_pcm_substream *substream) | ||||||
| { | { | ||||||
| 	int ret = 0; | 	struct snd_pcm_runtime *runtime; | ||||||
| 	struct snd_pcm_runtime *runtime = substream->runtime; | 	struct snd_soc_pcm_runtime *prtd; | ||||||
| 	struct i2s_dev_data *adata = dev_get_drvdata(component->dev); | 	struct i2s_dev_data *adata; | ||||||
| 	struct i2s_stream_instance *i2s_data = kzalloc(sizeof(struct i2s_stream_instance), | 	struct i2s_stream_instance *i2s_data; | ||||||
| 						       GFP_KERNEL); | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	runtime = substream->runtime; | ||||||
|  | 	prtd = substream->private_data; | ||||||
|  | 	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); | ||||||
|  | 	adata = dev_get_drvdata(component->dev); | ||||||
|  | 	i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL); | ||||||
| 	if (!i2s_data) | 	if (!i2s_data) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| @ -312,23 +300,6 @@ static int acp3x_dma_open(struct snd_soc_component *component, | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction) |  | ||||||
| { |  | ||||||
| 	u64 byte_count; |  | ||||||
| 
 |  | ||||||
| 	if (direction == SNDRV_PCM_STREAM_PLAYBACK) { |  | ||||||
| 		byte_count = rv_readl(rtd->acp3x_base + |  | ||||||
| 				      mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH); |  | ||||||
| 		byte_count |= rv_readl(rtd->acp3x_base + |  | ||||||
| 				       mmACP_BT_TX_LINEARPOSITIONCNTR_LOW); |  | ||||||
| 	} else { |  | ||||||
| 		byte_count = rv_readl(rtd->acp3x_base + |  | ||||||
| 				      mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH); |  | ||||||
| 		byte_count |= rv_readl(rtd->acp3x_base + |  | ||||||
| 				       mmACP_BT_RX_LINEARPOSITIONCNTR_LOW); |  | ||||||
| 	} |  | ||||||
| 	return byte_count; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| static int acp3x_dma_hw_params(struct snd_soc_component *component, | static int acp3x_dma_hw_params(struct snd_soc_component *component, | ||||||
| 			       struct snd_pcm_substream *substream, | 			       struct snd_pcm_substream *substream, | ||||||
| @ -351,12 +322,12 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component, | |||||||
| static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component, | static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component, | ||||||
| 					   struct snd_pcm_substream *substream) | 					   struct snd_pcm_substream *substream) | ||||||
| { | { | ||||||
| 	u32 pos = 0; | 	struct i2s_stream_instance *rtd; | ||||||
| 	u32 buffersize = 0; | 	u32 pos; | ||||||
| 	u64 bytescount = 0; | 	u32 buffersize; | ||||||
| 	struct i2s_stream_instance *rtd = | 	u64 bytescount; | ||||||
| 		substream->runtime->private_data; |  | ||||||
| 
 | 
 | ||||||
|  | 	rtd = substream->runtime->private_data; | ||||||
| 	buffersize = frames_to_bytes(substream->runtime, | 	buffersize = frames_to_bytes(substream->runtime, | ||||||
| 				     substream->runtime->buffer_size); | 				     substream->runtime->buffer_size); | ||||||
| 	bytescount = acp_get_byte_count(rtd, substream->stream); | 	bytescount = acp_get_byte_count(rtd, substream->stream); | ||||||
| @ -385,8 +356,12 @@ static int acp3x_dma_mmap(struct snd_soc_component *component, | |||||||
| static int acp3x_dma_close(struct snd_soc_component *component, | static int acp3x_dma_close(struct snd_soc_component *component, | ||||||
| 			   struct snd_pcm_substream *substream) | 			   struct snd_pcm_substream *substream) | ||||||
| { | { | ||||||
| 	struct i2s_stream_instance *rtd = substream->runtime->private_data; | 	struct snd_soc_pcm_runtime *prtd; | ||||||
| 	struct i2s_dev_data *adata = dev_get_drvdata(component->dev); | 	struct i2s_dev_data *adata; | ||||||
|  | 
 | ||||||
|  | 	prtd = substream->private_data; | ||||||
|  | 	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); | ||||||
|  | 	adata = dev_get_drvdata(component->dev); | ||||||
| 
 | 
 | ||||||
| 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||||||
| 		adata->play_stream = NULL; | 		adata->play_stream = NULL; | ||||||
| @ -398,186 +373,9 @@ static int acp3x_dma_close(struct snd_soc_component *component, | |||||||
| 	 */ | 	 */ | ||||||
| 	if (!adata->play_stream && !adata->capture_stream) | 	if (!adata->play_stream && !adata->capture_stream) | ||||||
| 		rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); | 		rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); | ||||||
| 	kfree(rtd); |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int acp3x_dai_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| 	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai); |  | ||||||
| 
 |  | ||||||
| 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |  | ||||||
| 	case SND_SOC_DAIFMT_I2S: |  | ||||||
| 		adata->tdm_mode = false; |  | ||||||
| 		break; |  | ||||||
| 	case SND_SOC_DAIFMT_DSP_A: |  | ||||||
| 		adata->tdm_mode = true; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int acp3x_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask, |  | ||||||
| 				  u32 rx_mask, int slots, int slot_width) |  | ||||||
| { |  | ||||||
| 	u32 val = 0; |  | ||||||
| 	u16 slot_len; |  | ||||||
| 
 |  | ||||||
| 	struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai); |  | ||||||
| 
 |  | ||||||
| 	switch (slot_width) { |  | ||||||
| 	case SLOT_WIDTH_8: |  | ||||||
| 		slot_len = 8; |  | ||||||
| 		break; |  | ||||||
| 	case SLOT_WIDTH_16: |  | ||||||
| 		slot_len = 16; |  | ||||||
| 		break; |  | ||||||
| 	case SLOT_WIDTH_24: |  | ||||||
| 		slot_len = 24; |  | ||||||
| 		break; |  | ||||||
| 	case SLOT_WIDTH_32: |  | ||||||
| 		slot_len = 0; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 	val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER); |  | ||||||
| 	rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER); |  | ||||||
| 
 |  | ||||||
| 	val = (FRM_LEN | (slots << 15) | (slot_len << 18)); |  | ||||||
| 	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_TXFRMT); |  | ||||||
| 	rv_writel(val, adata->acp3x_base + mmACP_BTTDM_RXFRMT); |  | ||||||
| 
 |  | ||||||
| 	adata->tdm_fmt = val; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int acp3x_dai_i2s_hwparams(struct snd_pcm_substream *substream, |  | ||||||
| 				  struct snd_pcm_hw_params *params, |  | ||||||
| 				  struct snd_soc_dai *dai) |  | ||||||
| { |  | ||||||
| 	u32 val = 0; |  | ||||||
| 	struct i2s_stream_instance *rtd = substream->runtime->private_data; |  | ||||||
| 
 |  | ||||||
| 	switch (params_format(params)) { |  | ||||||
| 	case SNDRV_PCM_FORMAT_U8: |  | ||||||
| 	case SNDRV_PCM_FORMAT_S8: |  | ||||||
| 		rtd->xfer_resolution = 0x0; |  | ||||||
| 		break; |  | ||||||
| 	case SNDRV_PCM_FORMAT_S16_LE: |  | ||||||
| 		rtd->xfer_resolution = 0x02; |  | ||||||
| 		break; |  | ||||||
| 	case SNDRV_PCM_FORMAT_S24_LE: |  | ||||||
| 		rtd->xfer_resolution = 0x04; |  | ||||||
| 		break; |  | ||||||
| 	case SNDRV_PCM_FORMAT_S32_LE: |  | ||||||
| 		rtd->xfer_resolution = 0x05; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	} |  | ||||||
| 	val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 	val = val | (rtd->xfer_resolution  << 3); |  | ||||||
| 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |  | ||||||
| 		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 	else |  | ||||||
| 		rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER); |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream, |  | ||||||
| 				 int cmd, struct snd_soc_dai *dai) |  | ||||||
| { |  | ||||||
| 	int ret = 0; |  | ||||||
| 	struct i2s_stream_instance *rtd = substream->runtime->private_data; |  | ||||||
| 	u32 val, period_bytes; |  | ||||||
| 
 |  | ||||||
| 	period_bytes = frames_to_bytes(substream->runtime, |  | ||||||
| 				       substream->runtime->period_size); |  | ||||||
| 	switch (cmd) { |  | ||||||
| 	case SNDRV_PCM_TRIGGER_START: |  | ||||||
| 	case SNDRV_PCM_TRIGGER_RESUME: |  | ||||||
| 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |  | ||||||
| 		rtd->bytescount = acp_get_byte_count(rtd, substream->stream); |  | ||||||
| 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |  | ||||||
| 			rv_writel(period_bytes, rtd->acp3x_base + |  | ||||||
| 				  mmACP_BT_TX_INTR_WATERMARK_SIZE); |  | ||||||
| 			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 			val = val | BIT(0); |  | ||||||
| 			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 		} else { |  | ||||||
| 			rv_writel(period_bytes, rtd->acp3x_base + |  | ||||||
| 				  mmACP_BT_RX_INTR_WATERMARK_SIZE); |  | ||||||
| 			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER); |  | ||||||
| 			val = val | BIT(0); |  | ||||||
| 			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER); |  | ||||||
| 		} |  | ||||||
| 		rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER); |  | ||||||
| 		break; |  | ||||||
| 	case SNDRV_PCM_TRIGGER_STOP: |  | ||||||
| 	case SNDRV_PCM_TRIGGER_SUSPEND: |  | ||||||
| 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |  | ||||||
| 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |  | ||||||
| 			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 			val = val & ~BIT(0); |  | ||||||
| 			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER); |  | ||||||
| 		} else { |  | ||||||
| 			val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER); |  | ||||||
| 			val = val & ~BIT(0); |  | ||||||
| 			rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER); |  | ||||||
| 		} |  | ||||||
| 		rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER); |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		ret = -EINVAL; |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct snd_soc_dai_ops acp3x_dai_i2s_ops = { |  | ||||||
| 	.hw_params = acp3x_dai_i2s_hwparams, |  | ||||||
| 	.trigger   = acp3x_dai_i2s_trigger, |  | ||||||
| 	.set_fmt = acp3x_dai_i2s_set_fmt, |  | ||||||
| 	.set_tdm_slot = acp3x_dai_set_tdm_slot, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static struct snd_soc_dai_driver acp3x_i2s_dai_driver = { |  | ||||||
| 	.playback = { |  | ||||||
| 		.rates = SNDRV_PCM_RATE_8000_96000, |  | ||||||
| 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | |  | ||||||
| 					SNDRV_PCM_FMTBIT_U8 | |  | ||||||
| 					SNDRV_PCM_FMTBIT_S24_LE | |  | ||||||
| 					SNDRV_PCM_FMTBIT_S32_LE, |  | ||||||
| 		.channels_min = 2, |  | ||||||
| 		.channels_max = 8, |  | ||||||
| 
 |  | ||||||
| 		.rate_min = 8000, |  | ||||||
| 		.rate_max = 96000, |  | ||||||
| 	}, |  | ||||||
| 	.capture = { |  | ||||||
| 		.rates = SNDRV_PCM_RATE_8000_48000, |  | ||||||
| 		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | |  | ||||||
| 					SNDRV_PCM_FMTBIT_U8 | |  | ||||||
| 					SNDRV_PCM_FMTBIT_S24_LE | |  | ||||||
| 					SNDRV_PCM_FMTBIT_S32_LE, |  | ||||||
| 		.channels_min = 2, |  | ||||||
| 		.channels_max = 2, |  | ||||||
| 		.rate_min = 8000, |  | ||||||
| 		.rate_max = 48000, |  | ||||||
| 	}, |  | ||||||
| 	.ops = &acp3x_dai_i2s_ops, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const struct snd_soc_component_driver acp3x_i2s_component = { | static const struct snd_soc_component_driver acp3x_i2s_component = { | ||||||
| 	.name		= DRV_NAME, | 	.name		= DRV_NAME, | ||||||
| 	.open		= acp3x_dma_open, | 	.open		= acp3x_dma_open, | ||||||
| @ -590,10 +388,10 @@ static const struct snd_soc_component_driver acp3x_i2s_component = { | |||||||
| 
 | 
 | ||||||
| static int acp3x_audio_probe(struct platform_device *pdev) | static int acp3x_audio_probe(struct platform_device *pdev) | ||||||
| { | { | ||||||
| 	int status; |  | ||||||
| 	struct resource *res; | 	struct resource *res; | ||||||
| 	struct i2s_dev_data *adata; | 	struct i2s_dev_data *adata; | ||||||
| 	unsigned int irqflags; | 	unsigned int irqflags; | ||||||
|  | 	int status, ret; | ||||||
| 
 | 
 | ||||||
| 	if (!pdev->dev.platform_data) { | 	if (!pdev->dev.platform_data) { | ||||||
| 		dev_err(&pdev->dev, "platform_data not retrieved\n"); | 		dev_err(&pdev->dev, "platform_data not retrieved\n"); | ||||||
| @ -603,7 +401,7 @@ static int acp3x_audio_probe(struct platform_device *pdev) | |||||||
| 
 | 
 | ||||||
| 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
| 	if (!res) { | 	if (!res) { | ||||||
| 		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n"); | 		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -613,6 +411,8 @@ static int acp3x_audio_probe(struct platform_device *pdev) | |||||||
| 
 | 
 | ||||||
| 	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start, | 	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start, | ||||||
| 					 resource_size(res)); | 					 resource_size(res)); | ||||||
|  | 	if (!adata->acp3x_base) | ||||||
|  | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||||||
| 	if (!res) { | 	if (!res) { | ||||||
| @ -621,52 +421,54 @@ static int acp3x_audio_probe(struct platform_device *pdev) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	adata->i2s_irq = res->start; | 	adata->i2s_irq = res->start; | ||||||
| 	adata->play_stream = NULL; |  | ||||||
| 	adata->capture_stream = NULL; |  | ||||||
| 
 | 
 | ||||||
| 	dev_set_drvdata(&pdev->dev, adata); | 	dev_set_drvdata(&pdev->dev, adata); | ||||||
| 	/* Initialize ACP */ | 	/* Initialize ACP */ | ||||||
| 	status = acp3x_init(adata->acp3x_base); | 	status = acp3x_init(adata->acp3x_base); | ||||||
| 	if (status) | 	if (status) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
|  | 
 | ||||||
| 	status = devm_snd_soc_register_component(&pdev->dev, | 	status = devm_snd_soc_register_component(&pdev->dev, | ||||||
| 						 &acp3x_i2s_component, | 						 &acp3x_i2s_component, | ||||||
| 						 &acp3x_i2s_dai_driver, 1); | 						 NULL, 0); | ||||||
| 	if (status) { | 	if (status) { | ||||||
| 		dev_err(&pdev->dev, "Fail to register acp i2s dai\n"); | 		dev_err(&pdev->dev, "Fail to register acp i2s component\n"); | ||||||
|  | 		ret = -ENODEV; | ||||||
| 		goto dev_err; | 		goto dev_err; | ||||||
| 	} | 	} | ||||||
| 	status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler, | 	status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler, | ||||||
| 				  irqflags, "ACP3x_I2S_IRQ", adata); | 				  irqflags, "ACP3x_I2S_IRQ", adata); | ||||||
| 	if (status) { | 	if (status) { | ||||||
| 		dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n"); | 		dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n"); | ||||||
|  | 		ret = -ENODEV; | ||||||
| 		goto dev_err; | 		goto dev_err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	pm_runtime_set_autosuspend_delay(&pdev->dev, 10000); | 	pm_runtime_set_autosuspend_delay(&pdev->dev, 5000); | ||||||
| 	pm_runtime_use_autosuspend(&pdev->dev); | 	pm_runtime_use_autosuspend(&pdev->dev); | ||||||
| 	pm_runtime_enable(&pdev->dev); | 	pm_runtime_enable(&pdev->dev); | ||||||
| 	return 0; | 	return 0; | ||||||
|  | 
 | ||||||
| dev_err: | dev_err: | ||||||
| 	status = acp3x_deinit(adata->acp3x_base); | 	status = acp3x_deinit(adata->acp3x_base); | ||||||
| 	if (status) | 	if (status) | ||||||
| 		dev_err(&pdev->dev, "ACP de-init failed\n"); | 		dev_err(&pdev->dev, "ACP de-init failed\n"); | ||||||
| 	else | 	else | ||||||
| 		dev_info(&pdev->dev, "ACP de-initialized\n"); | 		dev_dbg(&pdev->dev, "ACP de-initialized\n"); | ||||||
| 	/*ignore device status and return driver probe error*/ | 	return ret; | ||||||
| 	return -ENODEV; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int acp3x_audio_remove(struct platform_device *pdev) | static int acp3x_audio_remove(struct platform_device *pdev) | ||||||
| { | { | ||||||
|  | 	struct i2s_dev_data *adata; | ||||||
| 	int ret; | 	int ret; | ||||||
| 	struct i2s_dev_data *adata = dev_get_drvdata(&pdev->dev); |  | ||||||
| 
 | 
 | ||||||
|  | 	adata = dev_get_drvdata(&pdev->dev); | ||||||
| 	ret = acp3x_deinit(adata->acp3x_base); | 	ret = acp3x_deinit(adata->acp3x_base); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		dev_err(&pdev->dev, "ACP de-init failed\n"); | 		dev_err(&pdev->dev, "ACP de-init failed\n"); | ||||||
| 	else | 	else | ||||||
| 		dev_info(&pdev->dev, "ACP de-initialized\n"); | 		dev_dbg(&pdev->dev, "ACP de-initialized\n"); | ||||||
| 
 | 
 | ||||||
| 	pm_runtime_disable(&pdev->dev); | 	pm_runtime_disable(&pdev->dev); | ||||||
| 	return 0; | 	return 0; | ||||||
| @ -674,10 +476,11 @@ static int acp3x_audio_remove(struct platform_device *pdev) | |||||||
| 
 | 
 | ||||||
| static int acp3x_resume(struct device *dev) | static int acp3x_resume(struct device *dev) | ||||||
| { | { | ||||||
|  | 	struct i2s_dev_data *adata; | ||||||
| 	int status; | 	int status; | ||||||
| 	u32 val; | 	u32 val; | ||||||
| 	struct i2s_dev_data *adata = dev_get_drvdata(dev); |  | ||||||
| 
 | 
 | ||||||
|  | 	adata = dev_get_drvdata(dev); | ||||||
| 	status = acp3x_init(adata->acp3x_base); | 	status = acp3x_init(adata->acp3x_base); | ||||||
| 	if (status) | 	if (status) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| @ -719,14 +522,15 @@ static int acp3x_resume(struct device *dev) | |||||||
| 
 | 
 | ||||||
| static int acp3x_pcm_runtime_suspend(struct device *dev) | static int acp3x_pcm_runtime_suspend(struct device *dev) | ||||||
| { | { | ||||||
|  | 	struct i2s_dev_data *adata; | ||||||
| 	int status; | 	int status; | ||||||
| 	struct i2s_dev_data *adata = dev_get_drvdata(dev); | 	adata = dev_get_drvdata(dev); | ||||||
| 
 | 
 | ||||||
| 	status = acp3x_deinit(adata->acp3x_base); | 	status = acp3x_deinit(adata->acp3x_base); | ||||||
| 	if (status) | 	if (status) | ||||||
| 		dev_err(dev, "ACP de-init failed\n"); | 		dev_err(dev, "ACP de-init failed\n"); | ||||||
| 	else | 	else | ||||||
| 		dev_info(dev, "ACP de-initialized\n"); | 		dev_dbg(dev, "ACP de-initialized\n"); | ||||||
| 
 | 
 | ||||||
| 	rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); | 	rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); | ||||||
| 
 | 
 | ||||||
| @ -735,8 +539,9 @@ static int acp3x_pcm_runtime_suspend(struct device *dev) | |||||||
| 
 | 
 | ||||||
| static int acp3x_pcm_runtime_resume(struct device *dev) | static int acp3x_pcm_runtime_resume(struct device *dev) | ||||||
| { | { | ||||||
|  | 	struct i2s_dev_data *adata; | ||||||
| 	int status; | 	int status; | ||||||
| 	struct i2s_dev_data *adata = dev_get_drvdata(dev); | 	adata = dev_get_drvdata(dev); | ||||||
| 
 | 
 | ||||||
| 	status = acp3x_init(adata->acp3x_base); | 	status = acp3x_init(adata->acp3x_base); | ||||||
| 	if (status) | 	if (status) | ||||||
| @ -755,13 +560,14 @@ static struct platform_driver acp3x_dma_driver = { | |||||||
| 	.probe = acp3x_audio_probe, | 	.probe = acp3x_audio_probe, | ||||||
| 	.remove = acp3x_audio_remove, | 	.remove = acp3x_audio_remove, | ||||||
| 	.driver = { | 	.driver = { | ||||||
| 		.name = "acp3x_rv_i2s", | 		.name = "acp3x_rv_i2s_dma", | ||||||
| 		.pm = &acp3x_pm_ops, | 		.pm = &acp3x_pm_ops, | ||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| module_platform_driver(acp3x_dma_driver); | module_platform_driver(acp3x_dma_driver); | ||||||
| 
 | 
 | ||||||
|  | MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); | ||||||
| MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com"); | MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com"); | ||||||
| MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); | MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); | ||||||
| MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver"); | MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver"); | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "chip_offset_byte.h" | #include "chip_offset_byte.h" | ||||||
|  | #include <sound/pcm.h> | ||||||
| 
 | 
 | ||||||
| #define ACP3x_DEVS		3 | #define ACP3x_DEVS		3 | ||||||
| #define ACP3x_PHY_BASE_ADDRESS 0x1240000 | #define ACP3x_PHY_BASE_ADDRESS 0x1240000 | ||||||
| @ -51,6 +52,30 @@ | |||||||
| #define SLOT_WIDTH_24 0x18 | #define SLOT_WIDTH_24 0x18 | ||||||
| #define SLOT_WIDTH_32 0x20 | #define SLOT_WIDTH_32 0x20 | ||||||
| 
 | 
 | ||||||
|  | struct acp3x_platform_info { | ||||||
|  | 	u16 play_i2s_instance; | ||||||
|  | 	u16 cap_i2s_instance; | ||||||
|  | 	u16 capture_channel; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct i2s_dev_data { | ||||||
|  | 	bool tdm_mode; | ||||||
|  | 	unsigned int i2s_irq; | ||||||
|  | 	u32 tdm_fmt; | ||||||
|  | 	u32 substream_type; | ||||||
|  | 	void __iomem *acp3x_base; | ||||||
|  | 	struct snd_pcm_substream *play_stream; | ||||||
|  | 	struct snd_pcm_substream *capture_stream; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct i2s_stream_instance { | ||||||
|  | 	u16 num_pages; | ||||||
|  | 	u16 channels; | ||||||
|  | 	u32 xfer_resolution; | ||||||
|  | 	u64 bytescount; | ||||||
|  | 	dma_addr_t dma_addr; | ||||||
|  | 	void __iomem *acp3x_base; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| static inline u32 rv_readl(void __iomem *base_addr) | static inline u32 rv_readl(void __iomem *base_addr) | ||||||
| { | { | ||||||
| @ -61,3 +86,22 @@ static inline void rv_writel(u32 val, void __iomem *base_addr) | |||||||
| { | { | ||||||
| 	writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS); | 	writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, | ||||||
|  | 							int direction) | ||||||
|  | { | ||||||
|  | 	u64 byte_count; | ||||||
|  | 
 | ||||||
|  | 	if (direction == SNDRV_PCM_STREAM_PLAYBACK) { | ||||||
|  | 		byte_count = rv_readl(rtd->acp3x_base + | ||||||
|  | 				mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH); | ||||||
|  | 		byte_count |= rv_readl(rtd->acp3x_base + | ||||||
|  | 				mmACP_BT_TX_LINEARPOSITIONCNTR_LOW); | ||||||
|  | 	} else { | ||||||
|  | 		byte_count = rv_readl(rtd->acp3x_base + | ||||||
|  | 				mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH); | ||||||
|  | 		byte_count |= rv_readl(rtd->acp3x_base + | ||||||
|  | 				mmACP_BT_RX_LINEARPOSITIONCNTR_LOW); | ||||||
|  | 	} | ||||||
|  | 	return byte_count; | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user