cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

acp3x-pcm-dma.c (14442B)


      1// SPDX-License-Identifier: GPL-2.0+
      2//
      3// AMD ALSA SoC PCM Driver
      4//
      5//Copyright 2016 Advanced Micro Devices, Inc.
      6
      7#include <linux/platform_device.h>
      8#include <linux/module.h>
      9#include <linux/err.h>
     10#include <linux/io.h>
     11#include <linux/pm_runtime.h>
     12#include <sound/pcm_params.h>
     13#include <sound/soc.h>
     14#include <sound/soc-dai.h>
     15
     16#include "acp3x.h"
     17
     18#define DRV_NAME "acp3x_rv_i2s_dma"
     19
     20static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
     21	.info = SNDRV_PCM_INFO_INTERLEAVED |
     22		SNDRV_PCM_INFO_BLOCK_TRANSFER |
     23		SNDRV_PCM_INFO_BATCH |
     24		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
     25		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
     26	.formats = SNDRV_PCM_FMTBIT_S16_LE |  SNDRV_PCM_FMTBIT_S8 |
     27		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
     28	.channels_min = 2,
     29	.channels_max = 8,
     30	.rates = SNDRV_PCM_RATE_8000_96000,
     31	.rate_min = 8000,
     32	.rate_max = 96000,
     33	.buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
     34	.period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
     35	.period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
     36	.periods_min = PLAYBACK_MIN_NUM_PERIODS,
     37	.periods_max = PLAYBACK_MAX_NUM_PERIODS,
     38};
     39
     40static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = {
     41	.info = SNDRV_PCM_INFO_INTERLEAVED |
     42		SNDRV_PCM_INFO_BLOCK_TRANSFER |
     43		SNDRV_PCM_INFO_BATCH |
     44		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
     45		SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
     46	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
     47		   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
     48	.channels_min = 2,
     49	.channels_max = 2,
     50	.rates = SNDRV_PCM_RATE_8000_48000,
     51	.rate_min = 8000,
     52	.rate_max = 48000,
     53	.buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
     54	.period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
     55	.period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
     56	.periods_min = CAPTURE_MIN_NUM_PERIODS,
     57	.periods_max = CAPTURE_MAX_NUM_PERIODS,
     58};
     59
     60static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
     61{
     62	struct i2s_dev_data *rv_i2s_data;
     63	u16 play_flag, cap_flag;
     64	u32 val;
     65
     66	rv_i2s_data = dev_id;
     67	if (!rv_i2s_data)
     68		return IRQ_NONE;
     69
     70	play_flag = 0;
     71	cap_flag = 0;
     72	val = rv_readl(rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
     73	if ((val & BIT(BT_TX_THRESHOLD)) && rv_i2s_data->play_stream) {
     74		rv_writel(BIT(BT_TX_THRESHOLD), rv_i2s_data->acp3x_base +
     75			  mmACP_EXTERNAL_INTR_STAT);
     76		snd_pcm_period_elapsed(rv_i2s_data->play_stream);
     77		play_flag = 1;
     78	}
     79	if ((val & BIT(I2S_TX_THRESHOLD)) &&
     80				rv_i2s_data->i2ssp_play_stream) {
     81		rv_writel(BIT(I2S_TX_THRESHOLD),
     82			rv_i2s_data->acp3x_base	+ mmACP_EXTERNAL_INTR_STAT);
     83		snd_pcm_period_elapsed(rv_i2s_data->i2ssp_play_stream);
     84		play_flag = 1;
     85	}
     86
     87	if ((val & BIT(BT_RX_THRESHOLD)) && rv_i2s_data->capture_stream) {
     88		rv_writel(BIT(BT_RX_THRESHOLD), rv_i2s_data->acp3x_base +
     89			  mmACP_EXTERNAL_INTR_STAT);
     90		snd_pcm_period_elapsed(rv_i2s_data->capture_stream);
     91		cap_flag = 1;
     92	}
     93	if ((val & BIT(I2S_RX_THRESHOLD)) &&
     94				rv_i2s_data->i2ssp_capture_stream) {
     95		rv_writel(BIT(I2S_RX_THRESHOLD),
     96			 rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
     97		snd_pcm_period_elapsed(rv_i2s_data->i2ssp_capture_stream);
     98		cap_flag = 1;
     99	}
    100
    101	if (play_flag | cap_flag)
    102		return IRQ_HANDLED;
    103	else
    104		return IRQ_NONE;
    105}
    106
    107static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
    108{
    109	u16 page_idx;
    110	u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
    111	u32 reg_dma_size, reg_fifo_size;
    112	dma_addr_t addr;
    113
    114	addr = rtd->dma_addr;
    115
    116	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
    117		switch (rtd->i2s_instance) {
    118		case I2S_BT_INSTANCE:
    119			val = ACP_SRAM_BT_PB_PTE_OFFSET;
    120			break;
    121		case I2S_SP_INSTANCE:
    122		default:
    123			val = ACP_SRAM_SP_PB_PTE_OFFSET;
    124		}
    125	} else {
    126		switch (rtd->i2s_instance) {
    127		case I2S_BT_INSTANCE:
    128			val = ACP_SRAM_BT_CP_PTE_OFFSET;
    129			break;
    130		case I2S_SP_INSTANCE:
    131		default:
    132			val = ACP_SRAM_SP_CP_PTE_OFFSET;
    133		}
    134	}
    135	/* Group Enable */
    136	rv_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp3x_base +
    137		  mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
    138	rv_writel(PAGE_SIZE_4K_ENABLE, rtd->acp3x_base +
    139		  mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
    140
    141	for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
    142		/* Load the low address of page int ACP SRAM through SRBM */
    143		low = lower_32_bits(addr);
    144		high = upper_32_bits(addr);
    145
    146		rv_writel(low, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val);
    147		high |= BIT(31);
    148		rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
    149				+ 4);
    150		/* Move to next physically contiguous page */
    151		val += 8;
    152		addr += PAGE_SIZE;
    153	}
    154
    155	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
    156		switch (rtd->i2s_instance) {
    157		case I2S_BT_INSTANCE:
    158			reg_dma_size = mmACP_BT_TX_DMA_SIZE;
    159			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
    160						BT_PB_FIFO_ADDR_OFFSET;
    161			reg_fifo_addr = mmACP_BT_TX_FIFOADDR;
    162			reg_fifo_size = mmACP_BT_TX_FIFOSIZE;
    163			rv_writel(I2S_BT_TX_MEM_WINDOW_START,
    164				rtd->acp3x_base + mmACP_BT_TX_RINGBUFADDR);
    165			break;
    166
    167		case I2S_SP_INSTANCE:
    168		default:
    169			reg_dma_size = mmACP_I2S_TX_DMA_SIZE;
    170			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
    171						SP_PB_FIFO_ADDR_OFFSET;
    172			reg_fifo_addr =	mmACP_I2S_TX_FIFOADDR;
    173			reg_fifo_size = mmACP_I2S_TX_FIFOSIZE;
    174			rv_writel(I2S_SP_TX_MEM_WINDOW_START,
    175				rtd->acp3x_base + mmACP_I2S_TX_RINGBUFADDR);
    176		}
    177	} else {
    178		switch (rtd->i2s_instance) {
    179		case I2S_BT_INSTANCE:
    180			reg_dma_size = mmACP_BT_RX_DMA_SIZE;
    181			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
    182						BT_CAPT_FIFO_ADDR_OFFSET;
    183			reg_fifo_addr = mmACP_BT_RX_FIFOADDR;
    184			reg_fifo_size = mmACP_BT_RX_FIFOSIZE;
    185			rv_writel(I2S_BT_RX_MEM_WINDOW_START,
    186				rtd->acp3x_base + mmACP_BT_RX_RINGBUFADDR);
    187			break;
    188
    189		case I2S_SP_INSTANCE:
    190		default:
    191			reg_dma_size = mmACP_I2S_RX_DMA_SIZE;
    192			acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
    193						SP_CAPT_FIFO_ADDR_OFFSET;
    194			reg_fifo_addr = mmACP_I2S_RX_FIFOADDR;
    195			reg_fifo_size = mmACP_I2S_RX_FIFOSIZE;
    196			rv_writel(I2S_SP_RX_MEM_WINDOW_START,
    197				rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
    198		}
    199	}
    200	rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size);
    201	rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr);
    202	rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size);
    203	rv_writel(BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
    204		| BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD),
    205		rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
    206}
    207
    208static int acp3x_dma_open(struct snd_soc_component *component,
    209			  struct snd_pcm_substream *substream)
    210{
    211	struct snd_pcm_runtime *runtime;
    212	struct snd_soc_pcm_runtime *prtd;
    213	struct i2s_dev_data *adata;
    214	struct i2s_stream_instance *i2s_data;
    215	int ret;
    216
    217	runtime = substream->runtime;
    218	prtd = asoc_substream_to_rtd(substream);
    219	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
    220	adata = dev_get_drvdata(component->dev);
    221	i2s_data = kzalloc(sizeof(*i2s_data), GFP_KERNEL);
    222	if (!i2s_data)
    223		return -EINVAL;
    224
    225	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    226		runtime->hw = acp3x_pcm_hardware_playback;
    227	else
    228		runtime->hw = acp3x_pcm_hardware_capture;
    229
    230	ret = snd_pcm_hw_constraint_integer(runtime,
    231					    SNDRV_PCM_HW_PARAM_PERIODS);
    232	if (ret < 0) {
    233		dev_err(component->dev, "set integer constraint failed\n");
    234		kfree(i2s_data);
    235		return ret;
    236	}
    237
    238	i2s_data->acp3x_base = adata->acp3x_base;
    239	runtime->private_data = i2s_data;
    240	return ret;
    241}
    242
    243
    244static int acp3x_dma_hw_params(struct snd_soc_component *component,
    245			       struct snd_pcm_substream *substream,
    246			       struct snd_pcm_hw_params *params)
    247{
    248	struct i2s_stream_instance *rtd;
    249	struct snd_soc_pcm_runtime *prtd;
    250	struct snd_soc_card *card;
    251	struct acp3x_platform_info *pinfo;
    252	struct i2s_dev_data *adata;
    253	u64 size;
    254
    255	prtd = asoc_substream_to_rtd(substream);
    256	card = prtd->card;
    257	pinfo = snd_soc_card_get_drvdata(card);
    258	adata = dev_get_drvdata(component->dev);
    259	rtd = substream->runtime->private_data;
    260	if (!rtd)
    261		return -EINVAL;
    262
    263	if (pinfo) {
    264		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    265			rtd->i2s_instance = pinfo->play_i2s_instance;
    266			switch (rtd->i2s_instance) {
    267			case I2S_BT_INSTANCE:
    268				adata->play_stream = substream;
    269				break;
    270			case I2S_SP_INSTANCE:
    271			default:
    272				adata->i2ssp_play_stream = substream;
    273			}
    274		} else {
    275			rtd->i2s_instance = pinfo->cap_i2s_instance;
    276			switch (rtd->i2s_instance) {
    277			case I2S_BT_INSTANCE:
    278				adata->capture_stream = substream;
    279				break;
    280			case I2S_SP_INSTANCE:
    281			default:
    282				adata->i2ssp_capture_stream = substream;
    283			}
    284		}
    285	} else {
    286		pr_err("pinfo failed\n");
    287	}
    288	size = params_buffer_bytes(params);
    289	rtd->dma_addr = substream->runtime->dma_addr;
    290	rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
    291	config_acp3x_dma(rtd, substream->stream);
    292	return 0;
    293}
    294
    295static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component,
    296					   struct snd_pcm_substream *substream)
    297{
    298	struct i2s_stream_instance *rtd;
    299	u32 pos;
    300	u32 buffersize;
    301	u64 bytescount;
    302
    303	rtd = substream->runtime->private_data;
    304
    305	buffersize = frames_to_bytes(substream->runtime,
    306				     substream->runtime->buffer_size);
    307	bytescount = acp_get_byte_count(rtd, substream->stream);
    308	if (bytescount > rtd->bytescount)
    309		bytescount -= rtd->bytescount;
    310	pos = do_div(bytescount, buffersize);
    311	return bytes_to_frames(substream->runtime, pos);
    312}
    313
    314static int acp3x_dma_new(struct snd_soc_component *component,
    315			 struct snd_soc_pcm_runtime *rtd)
    316{
    317	struct device *parent = component->dev->parent;
    318	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
    319				       parent, MIN_BUFFER, MAX_BUFFER);
    320	return 0;
    321}
    322
    323static int acp3x_dma_close(struct snd_soc_component *component,
    324			   struct snd_pcm_substream *substream)
    325{
    326	struct snd_soc_pcm_runtime *prtd;
    327	struct i2s_dev_data *adata;
    328	struct i2s_stream_instance *ins;
    329
    330	prtd = asoc_substream_to_rtd(substream);
    331	component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
    332	adata = dev_get_drvdata(component->dev);
    333	ins = substream->runtime->private_data;
    334	if (!ins)
    335		return -EINVAL;
    336
    337	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    338		switch (ins->i2s_instance) {
    339		case I2S_BT_INSTANCE:
    340			adata->play_stream = NULL;
    341			break;
    342		case I2S_SP_INSTANCE:
    343		default:
    344			adata->i2ssp_play_stream = NULL;
    345		}
    346	} else {
    347		switch (ins->i2s_instance) {
    348		case I2S_BT_INSTANCE:
    349			adata->capture_stream = NULL;
    350			break;
    351		case I2S_SP_INSTANCE:
    352		default:
    353			adata->i2ssp_capture_stream = NULL;
    354		}
    355	}
    356
    357	return 0;
    358}
    359
    360static const struct snd_soc_component_driver acp3x_i2s_component = {
    361	.name		= DRV_NAME,
    362	.open		= acp3x_dma_open,
    363	.close		= acp3x_dma_close,
    364	.hw_params	= acp3x_dma_hw_params,
    365	.pointer	= acp3x_dma_pointer,
    366	.pcm_construct	= acp3x_dma_new,
    367};
    368
    369static int acp3x_audio_probe(struct platform_device *pdev)
    370{
    371	struct resource *res;
    372	struct i2s_dev_data *adata;
    373	unsigned int irqflags;
    374	int status;
    375
    376	if (!pdev->dev.platform_data) {
    377		dev_err(&pdev->dev, "platform_data not retrieved\n");
    378		return -ENODEV;
    379	}
    380	irqflags = *((unsigned int *)(pdev->dev.platform_data));
    381
    382	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    383	if (!res) {
    384		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
    385		return -ENODEV;
    386	}
    387
    388	adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
    389	if (!adata)
    390		return -ENOMEM;
    391
    392	adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
    393					 resource_size(res));
    394	if (!adata->acp3x_base)
    395		return -ENOMEM;
    396
    397	status = platform_get_irq(pdev, 0);
    398	if (status < 0)
    399		return status;
    400	adata->i2s_irq = status;
    401
    402	dev_set_drvdata(&pdev->dev, adata);
    403	status = devm_snd_soc_register_component(&pdev->dev,
    404						 &acp3x_i2s_component,
    405						 NULL, 0);
    406	if (status) {
    407		dev_err(&pdev->dev, "Fail to register acp i2s component\n");
    408		return -ENODEV;
    409	}
    410	status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
    411				  irqflags, "ACP3x_I2S_IRQ", adata);
    412	if (status) {
    413		dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
    414		return -ENODEV;
    415	}
    416
    417	pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
    418	pm_runtime_use_autosuspend(&pdev->dev);
    419	pm_runtime_enable(&pdev->dev);
    420	pm_runtime_allow(&pdev->dev);
    421	return 0;
    422}
    423
    424static int acp3x_audio_remove(struct platform_device *pdev)
    425{
    426	pm_runtime_disable(&pdev->dev);
    427	return 0;
    428}
    429
    430static int acp3x_resume(struct device *dev)
    431{
    432	struct i2s_dev_data *adata;
    433	u32 val, reg_val, frmt_val;
    434
    435	reg_val = 0;
    436	frmt_val = 0;
    437	adata = dev_get_drvdata(dev);
    438
    439	if (adata->play_stream && adata->play_stream->runtime) {
    440		struct i2s_stream_instance *rtd =
    441			adata->play_stream->runtime->private_data;
    442		config_acp3x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
    443		switch (rtd->i2s_instance) {
    444		case I2S_BT_INSTANCE:
    445			reg_val = mmACP_BTTDM_ITER;
    446			frmt_val = mmACP_BTTDM_TXFRMT;
    447			break;
    448		case I2S_SP_INSTANCE:
    449		default:
    450			reg_val = mmACP_I2STDM_ITER;
    451			frmt_val = mmACP_I2STDM_TXFRMT;
    452		}
    453		rv_writel((rtd->xfer_resolution  << 3),
    454			  rtd->acp3x_base + reg_val);
    455	}
    456	if (adata->capture_stream && adata->capture_stream->runtime) {
    457		struct i2s_stream_instance *rtd =
    458			adata->capture_stream->runtime->private_data;
    459		config_acp3x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
    460		switch (rtd->i2s_instance) {
    461		case I2S_BT_INSTANCE:
    462			reg_val = mmACP_BTTDM_IRER;
    463			frmt_val = mmACP_BTTDM_RXFRMT;
    464			break;
    465		case I2S_SP_INSTANCE:
    466		default:
    467			reg_val = mmACP_I2STDM_IRER;
    468			frmt_val = mmACP_I2STDM_RXFRMT;
    469		}
    470		rv_writel((rtd->xfer_resolution  << 3),
    471			  rtd->acp3x_base + reg_val);
    472	}
    473	if (adata->tdm_mode == TDM_ENABLE) {
    474		rv_writel(adata->tdm_fmt, adata->acp3x_base + frmt_val);
    475		val = rv_readl(adata->acp3x_base + reg_val);
    476		rv_writel(val | 0x2, adata->acp3x_base + reg_val);
    477	}
    478	rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
    479	return 0;
    480}
    481
    482
    483static int acp3x_pcm_runtime_suspend(struct device *dev)
    484{
    485	struct i2s_dev_data *adata;
    486
    487	adata = dev_get_drvdata(dev);
    488
    489	rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
    490
    491	return 0;
    492}
    493
    494static int acp3x_pcm_runtime_resume(struct device *dev)
    495{
    496	struct i2s_dev_data *adata;
    497
    498	adata = dev_get_drvdata(dev);
    499
    500	rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
    501	return 0;
    502}
    503
    504static const struct dev_pm_ops acp3x_pm_ops = {
    505	.runtime_suspend = acp3x_pcm_runtime_suspend,
    506	.runtime_resume = acp3x_pcm_runtime_resume,
    507	.resume = acp3x_resume,
    508};
    509
    510static struct platform_driver acp3x_dma_driver = {
    511	.probe = acp3x_audio_probe,
    512	.remove = acp3x_audio_remove,
    513	.driver = {
    514		.name = "acp3x_rv_i2s_dma",
    515		.pm = &acp3x_pm_ops,
    516	},
    517};
    518
    519module_platform_driver(acp3x_dma_driver);
    520
    521MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com");
    522MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
    523MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
    524MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
    525MODULE_LICENSE("GPL v2");
    526MODULE_ALIAS("platform:"DRV_NAME);