162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// AMD ALSA SoC PCM Driver
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/platform_device.h>
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/err.h>
1062306a36Sopenharmony_ci#include <linux/io.h>
1162306a36Sopenharmony_ci#include <sound/pcm_params.h>
1262306a36Sopenharmony_ci#include <sound/soc.h>
1362306a36Sopenharmony_ci#include <sound/soc-dai.h>
1462306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "acp5x.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define DRV_NAME "acp5x_i2s_playcap"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic int acp5x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
2162306a36Sopenharmony_ci			     unsigned int fmt)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	struct i2s_dev_data *adata;
2462306a36Sopenharmony_ci	int mode;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	adata = snd_soc_dai_get_drvdata(cpu_dai);
2762306a36Sopenharmony_ci	mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
2862306a36Sopenharmony_ci	switch (mode) {
2962306a36Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
3062306a36Sopenharmony_ci		adata->tdm_mode = TDM_DISABLE;
3162306a36Sopenharmony_ci		break;
3262306a36Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_A:
3362306a36Sopenharmony_ci		adata->tdm_mode = TDM_ENABLE;
3462306a36Sopenharmony_ci		break;
3562306a36Sopenharmony_ci	default:
3662306a36Sopenharmony_ci		return -EINVAL;
3762306a36Sopenharmony_ci	}
3862306a36Sopenharmony_ci	mode = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
3962306a36Sopenharmony_ci	switch (mode) {
4062306a36Sopenharmony_ci	case SND_SOC_DAIFMT_BP_FP:
4162306a36Sopenharmony_ci		adata->master_mode = I2S_MASTER_MODE_ENABLE;
4262306a36Sopenharmony_ci		break;
4362306a36Sopenharmony_ci	case SND_SOC_DAIFMT_BC_FC:
4462306a36Sopenharmony_ci		adata->master_mode = I2S_MASTER_MODE_DISABLE;
4562306a36Sopenharmony_ci		break;
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci	return 0;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic int acp5x_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
5162306a36Sopenharmony_ci				  u32 tx_mask, u32 rx_mask,
5262306a36Sopenharmony_ci				  int slots, int slot_width)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	struct i2s_dev_data *adata;
5562306a36Sopenharmony_ci	u32 frm_len;
5662306a36Sopenharmony_ci	u16 slot_len;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	adata = snd_soc_dai_get_drvdata(cpu_dai);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/* These values are as per Hardware Spec */
6162306a36Sopenharmony_ci	switch (slot_width) {
6262306a36Sopenharmony_ci	case SLOT_WIDTH_8:
6362306a36Sopenharmony_ci		slot_len = 8;
6462306a36Sopenharmony_ci		break;
6562306a36Sopenharmony_ci	case SLOT_WIDTH_16:
6662306a36Sopenharmony_ci		slot_len = 16;
6762306a36Sopenharmony_ci		break;
6862306a36Sopenharmony_ci	case SLOT_WIDTH_24:
6962306a36Sopenharmony_ci		slot_len = 24;
7062306a36Sopenharmony_ci		break;
7162306a36Sopenharmony_ci	case SLOT_WIDTH_32:
7262306a36Sopenharmony_ci		slot_len = 0;
7362306a36Sopenharmony_ci		break;
7462306a36Sopenharmony_ci	default:
7562306a36Sopenharmony_ci		return -EINVAL;
7662306a36Sopenharmony_ci	}
7762306a36Sopenharmony_ci	frm_len = FRM_LEN | (slots << 15) | (slot_len << 18);
7862306a36Sopenharmony_ci	adata->tdm_fmt = frm_len;
7962306a36Sopenharmony_ci	return 0;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic int acp5x_i2s_hwparams(struct snd_pcm_substream *substream,
8362306a36Sopenharmony_ci			      struct snd_pcm_hw_params *params,
8462306a36Sopenharmony_ci			      struct snd_soc_dai *dai)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	struct i2s_stream_instance *rtd;
8762306a36Sopenharmony_ci	struct snd_soc_pcm_runtime *prtd;
8862306a36Sopenharmony_ci	struct snd_soc_card *card;
8962306a36Sopenharmony_ci	struct acp5x_platform_info *pinfo;
9062306a36Sopenharmony_ci	struct i2s_dev_data *adata;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	u32 val;
9362306a36Sopenharmony_ci	u32 reg_val, frmt_reg;
9462306a36Sopenharmony_ci	u32 lrclk_div_val, bclk_div_val;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	lrclk_div_val = 0;
9762306a36Sopenharmony_ci	bclk_div_val = 0;
9862306a36Sopenharmony_ci	prtd = asoc_substream_to_rtd(substream);
9962306a36Sopenharmony_ci	rtd = substream->runtime->private_data;
10062306a36Sopenharmony_ci	card = prtd->card;
10162306a36Sopenharmony_ci	adata = snd_soc_dai_get_drvdata(dai);
10262306a36Sopenharmony_ci	pinfo = snd_soc_card_get_drvdata(card);
10362306a36Sopenharmony_ci	if (pinfo) {
10462306a36Sopenharmony_ci		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
10562306a36Sopenharmony_ci			rtd->i2s_instance = pinfo->play_i2s_instance;
10662306a36Sopenharmony_ci		else
10762306a36Sopenharmony_ci			rtd->i2s_instance = pinfo->cap_i2s_instance;
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	/* These values are as per Hardware Spec */
11162306a36Sopenharmony_ci	switch (params_format(params)) {
11262306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_U8:
11362306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S8:
11462306a36Sopenharmony_ci		rtd->xfer_resolution = 0x0;
11562306a36Sopenharmony_ci		break;
11662306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S16_LE:
11762306a36Sopenharmony_ci		rtd->xfer_resolution = 0x02;
11862306a36Sopenharmony_ci		break;
11962306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S24_LE:
12062306a36Sopenharmony_ci		rtd->xfer_resolution = 0x04;
12162306a36Sopenharmony_ci		break;
12262306a36Sopenharmony_ci	case SNDRV_PCM_FORMAT_S32_LE:
12362306a36Sopenharmony_ci		rtd->xfer_resolution = 0x05;
12462306a36Sopenharmony_ci		break;
12562306a36Sopenharmony_ci	default:
12662306a36Sopenharmony_ci		return -EINVAL;
12762306a36Sopenharmony_ci	}
12862306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
12962306a36Sopenharmony_ci		switch (rtd->i2s_instance) {
13062306a36Sopenharmony_ci		case I2S_HS_INSTANCE:
13162306a36Sopenharmony_ci			reg_val = ACP_HSTDM_ITER;
13262306a36Sopenharmony_ci			frmt_reg = ACP_HSTDM_TXFRMT;
13362306a36Sopenharmony_ci			break;
13462306a36Sopenharmony_ci		case I2S_SP_INSTANCE:
13562306a36Sopenharmony_ci		default:
13662306a36Sopenharmony_ci			reg_val = ACP_I2STDM_ITER;
13762306a36Sopenharmony_ci			frmt_reg = ACP_I2STDM_TXFRMT;
13862306a36Sopenharmony_ci		}
13962306a36Sopenharmony_ci	} else {
14062306a36Sopenharmony_ci		switch (rtd->i2s_instance) {
14162306a36Sopenharmony_ci		case I2S_HS_INSTANCE:
14262306a36Sopenharmony_ci			reg_val = ACP_HSTDM_IRER;
14362306a36Sopenharmony_ci			frmt_reg = ACP_HSTDM_RXFRMT;
14462306a36Sopenharmony_ci			break;
14562306a36Sopenharmony_ci		case I2S_SP_INSTANCE:
14662306a36Sopenharmony_ci		default:
14762306a36Sopenharmony_ci			reg_val = ACP_I2STDM_IRER;
14862306a36Sopenharmony_ci			frmt_reg = ACP_I2STDM_RXFRMT;
14962306a36Sopenharmony_ci		}
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci	if (adata->tdm_mode) {
15262306a36Sopenharmony_ci		val = acp_readl(rtd->acp5x_base + reg_val);
15362306a36Sopenharmony_ci		acp_writel(val | 0x2, rtd->acp5x_base + reg_val);
15462306a36Sopenharmony_ci		acp_writel(adata->tdm_fmt, rtd->acp5x_base + frmt_reg);
15562306a36Sopenharmony_ci	}
15662306a36Sopenharmony_ci	val = acp_readl(rtd->acp5x_base + reg_val);
15762306a36Sopenharmony_ci	val &= ~ACP5x_ITER_IRER_SAMP_LEN_MASK;
15862306a36Sopenharmony_ci	val = val | (rtd->xfer_resolution  << 3);
15962306a36Sopenharmony_ci	acp_writel(val, rtd->acp5x_base + reg_val);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	if (adata->master_mode) {
16262306a36Sopenharmony_ci		switch (params_format(params)) {
16362306a36Sopenharmony_ci		case SNDRV_PCM_FORMAT_S16_LE:
16462306a36Sopenharmony_ci			switch (params_rate(params)) {
16562306a36Sopenharmony_ci			case 8000:
16662306a36Sopenharmony_ci				bclk_div_val = 768;
16762306a36Sopenharmony_ci				break;
16862306a36Sopenharmony_ci			case 16000:
16962306a36Sopenharmony_ci				bclk_div_val = 384;
17062306a36Sopenharmony_ci				break;
17162306a36Sopenharmony_ci			case 24000:
17262306a36Sopenharmony_ci				bclk_div_val = 256;
17362306a36Sopenharmony_ci				break;
17462306a36Sopenharmony_ci			case 32000:
17562306a36Sopenharmony_ci				bclk_div_val = 192;
17662306a36Sopenharmony_ci				break;
17762306a36Sopenharmony_ci			case 44100:
17862306a36Sopenharmony_ci			case 48000:
17962306a36Sopenharmony_ci				bclk_div_val = 128;
18062306a36Sopenharmony_ci				break;
18162306a36Sopenharmony_ci			case 88200:
18262306a36Sopenharmony_ci			case 96000:
18362306a36Sopenharmony_ci				bclk_div_val = 64;
18462306a36Sopenharmony_ci				break;
18562306a36Sopenharmony_ci			case 192000:
18662306a36Sopenharmony_ci				bclk_div_val = 32;
18762306a36Sopenharmony_ci				break;
18862306a36Sopenharmony_ci			default:
18962306a36Sopenharmony_ci				return -EINVAL;
19062306a36Sopenharmony_ci			}
19162306a36Sopenharmony_ci			lrclk_div_val = 32;
19262306a36Sopenharmony_ci			break;
19362306a36Sopenharmony_ci		case SNDRV_PCM_FORMAT_S32_LE:
19462306a36Sopenharmony_ci			switch (params_rate(params)) {
19562306a36Sopenharmony_ci			case 8000:
19662306a36Sopenharmony_ci				bclk_div_val = 384;
19762306a36Sopenharmony_ci				break;
19862306a36Sopenharmony_ci			case 16000:
19962306a36Sopenharmony_ci				bclk_div_val = 192;
20062306a36Sopenharmony_ci				break;
20162306a36Sopenharmony_ci			case 24000:
20262306a36Sopenharmony_ci				bclk_div_val = 128;
20362306a36Sopenharmony_ci				break;
20462306a36Sopenharmony_ci			case 32000:
20562306a36Sopenharmony_ci				bclk_div_val = 96;
20662306a36Sopenharmony_ci				break;
20762306a36Sopenharmony_ci			case 44100:
20862306a36Sopenharmony_ci			case 48000:
20962306a36Sopenharmony_ci				bclk_div_val = 64;
21062306a36Sopenharmony_ci				break;
21162306a36Sopenharmony_ci			case 88200:
21262306a36Sopenharmony_ci			case 96000:
21362306a36Sopenharmony_ci				bclk_div_val = 32;
21462306a36Sopenharmony_ci				break;
21562306a36Sopenharmony_ci			case 192000:
21662306a36Sopenharmony_ci				bclk_div_val = 16;
21762306a36Sopenharmony_ci				break;
21862306a36Sopenharmony_ci			default:
21962306a36Sopenharmony_ci				return -EINVAL;
22062306a36Sopenharmony_ci			}
22162306a36Sopenharmony_ci			lrclk_div_val = 64;
22262306a36Sopenharmony_ci			break;
22362306a36Sopenharmony_ci		default:
22462306a36Sopenharmony_ci			return -EINVAL;
22562306a36Sopenharmony_ci		}
22662306a36Sopenharmony_ci		rtd->lrclk_div = lrclk_div_val;
22762306a36Sopenharmony_ci		rtd->bclk_div = bclk_div_val;
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci	return 0;
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic int acp5x_i2s_trigger(struct snd_pcm_substream *substream,
23362306a36Sopenharmony_ci			     int cmd, struct snd_soc_dai *dai)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct i2s_stream_instance *rtd;
23662306a36Sopenharmony_ci	struct i2s_dev_data *adata;
23762306a36Sopenharmony_ci	u32 ret, val, period_bytes, reg_val, ier_val, water_val;
23862306a36Sopenharmony_ci	u32 buf_size, buf_reg;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	adata = snd_soc_dai_get_drvdata(dai);
24162306a36Sopenharmony_ci	rtd = substream->runtime->private_data;
24262306a36Sopenharmony_ci	period_bytes = frames_to_bytes(substream->runtime,
24362306a36Sopenharmony_ci				       substream->runtime->period_size);
24462306a36Sopenharmony_ci	buf_size = frames_to_bytes(substream->runtime,
24562306a36Sopenharmony_ci				   substream->runtime->buffer_size);
24662306a36Sopenharmony_ci	switch (cmd) {
24762306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
24862306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
24962306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
25062306a36Sopenharmony_ci		rtd->bytescount = acp_get_byte_count(rtd,
25162306a36Sopenharmony_ci						     substream->stream);
25262306a36Sopenharmony_ci		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
25362306a36Sopenharmony_ci			switch (rtd->i2s_instance) {
25462306a36Sopenharmony_ci			case I2S_HS_INSTANCE:
25562306a36Sopenharmony_ci				water_val =
25662306a36Sopenharmony_ci					ACP_HS_TX_INTR_WATERMARK_SIZE;
25762306a36Sopenharmony_ci				reg_val = ACP_HSTDM_ITER;
25862306a36Sopenharmony_ci				ier_val = ACP_HSTDM_IER;
25962306a36Sopenharmony_ci				buf_reg = ACP_HS_TX_RINGBUFSIZE;
26062306a36Sopenharmony_ci				break;
26162306a36Sopenharmony_ci			case I2S_SP_INSTANCE:
26262306a36Sopenharmony_ci			default:
26362306a36Sopenharmony_ci				water_val =
26462306a36Sopenharmony_ci					ACP_I2S_TX_INTR_WATERMARK_SIZE;
26562306a36Sopenharmony_ci				reg_val = ACP_I2STDM_ITER;
26662306a36Sopenharmony_ci				ier_val = ACP_I2STDM_IER;
26762306a36Sopenharmony_ci				buf_reg = ACP_I2S_TX_RINGBUFSIZE;
26862306a36Sopenharmony_ci			}
26962306a36Sopenharmony_ci		} else {
27062306a36Sopenharmony_ci			switch (rtd->i2s_instance) {
27162306a36Sopenharmony_ci			case I2S_HS_INSTANCE:
27262306a36Sopenharmony_ci				water_val =
27362306a36Sopenharmony_ci					ACP_HS_RX_INTR_WATERMARK_SIZE;
27462306a36Sopenharmony_ci				reg_val = ACP_HSTDM_IRER;
27562306a36Sopenharmony_ci				ier_val = ACP_HSTDM_IER;
27662306a36Sopenharmony_ci				buf_reg = ACP_HS_RX_RINGBUFSIZE;
27762306a36Sopenharmony_ci				break;
27862306a36Sopenharmony_ci			case I2S_SP_INSTANCE:
27962306a36Sopenharmony_ci			default:
28062306a36Sopenharmony_ci				water_val =
28162306a36Sopenharmony_ci					ACP_I2S_RX_INTR_WATERMARK_SIZE;
28262306a36Sopenharmony_ci				reg_val = ACP_I2STDM_IRER;
28362306a36Sopenharmony_ci				ier_val = ACP_I2STDM_IER;
28462306a36Sopenharmony_ci				buf_reg = ACP_I2S_RX_RINGBUFSIZE;
28562306a36Sopenharmony_ci			}
28662306a36Sopenharmony_ci		}
28762306a36Sopenharmony_ci		acp_writel(period_bytes, rtd->acp5x_base + water_val);
28862306a36Sopenharmony_ci		acp_writel(buf_size, rtd->acp5x_base + buf_reg);
28962306a36Sopenharmony_ci		if (adata->master_mode)
29062306a36Sopenharmony_ci			acp5x_set_i2s_clk(adata, rtd);
29162306a36Sopenharmony_ci		val = acp_readl(rtd->acp5x_base + reg_val);
29262306a36Sopenharmony_ci		val = val | BIT(0);
29362306a36Sopenharmony_ci		acp_writel(val, rtd->acp5x_base + reg_val);
29462306a36Sopenharmony_ci		acp_writel(1, rtd->acp5x_base + ier_val);
29562306a36Sopenharmony_ci		ret = 0;
29662306a36Sopenharmony_ci		break;
29762306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
29862306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
29962306a36Sopenharmony_ci	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
30062306a36Sopenharmony_ci		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
30162306a36Sopenharmony_ci			switch (rtd->i2s_instance) {
30262306a36Sopenharmony_ci			case I2S_HS_INSTANCE:
30362306a36Sopenharmony_ci				reg_val = ACP_HSTDM_ITER;
30462306a36Sopenharmony_ci				break;
30562306a36Sopenharmony_ci			case I2S_SP_INSTANCE:
30662306a36Sopenharmony_ci			default:
30762306a36Sopenharmony_ci				reg_val = ACP_I2STDM_ITER;
30862306a36Sopenharmony_ci			}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci		} else {
31162306a36Sopenharmony_ci			switch (rtd->i2s_instance) {
31262306a36Sopenharmony_ci			case I2S_HS_INSTANCE:
31362306a36Sopenharmony_ci				reg_val = ACP_HSTDM_IRER;
31462306a36Sopenharmony_ci				break;
31562306a36Sopenharmony_ci			case I2S_SP_INSTANCE:
31662306a36Sopenharmony_ci			default:
31762306a36Sopenharmony_ci				reg_val = ACP_I2STDM_IRER;
31862306a36Sopenharmony_ci			}
31962306a36Sopenharmony_ci		}
32062306a36Sopenharmony_ci		val = acp_readl(rtd->acp5x_base + reg_val);
32162306a36Sopenharmony_ci		val = val & ~BIT(0);
32262306a36Sopenharmony_ci		acp_writel(val, rtd->acp5x_base + reg_val);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		if (!(acp_readl(rtd->acp5x_base + ACP_HSTDM_ITER) & BIT(0)) &&
32562306a36Sopenharmony_ci		    !(acp_readl(rtd->acp5x_base + ACP_HSTDM_IRER) & BIT(0)))
32662306a36Sopenharmony_ci			acp_writel(0, rtd->acp5x_base + ACP_HSTDM_IER);
32762306a36Sopenharmony_ci		if (!(acp_readl(rtd->acp5x_base + ACP_I2STDM_ITER) & BIT(0)) &&
32862306a36Sopenharmony_ci		    !(acp_readl(rtd->acp5x_base + ACP_I2STDM_IRER) & BIT(0)))
32962306a36Sopenharmony_ci			acp_writel(0, rtd->acp5x_base + ACP_I2STDM_IER);
33062306a36Sopenharmony_ci		ret = 0;
33162306a36Sopenharmony_ci		break;
33262306a36Sopenharmony_ci	default:
33362306a36Sopenharmony_ci		ret = -EINVAL;
33462306a36Sopenharmony_ci		break;
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci	return ret;
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistatic const struct snd_soc_dai_ops acp5x_i2s_dai_ops = {
34062306a36Sopenharmony_ci	.hw_params = acp5x_i2s_hwparams,
34162306a36Sopenharmony_ci	.trigger = acp5x_i2s_trigger,
34262306a36Sopenharmony_ci	.set_fmt = acp5x_i2s_set_fmt,
34362306a36Sopenharmony_ci	.set_tdm_slot = acp5x_i2s_set_tdm_slot,
34462306a36Sopenharmony_ci};
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic const struct snd_soc_component_driver acp5x_dai_component = {
34762306a36Sopenharmony_ci	.name = "acp5x-i2s",
34862306a36Sopenharmony_ci	.legacy_dai_naming = 1,
34962306a36Sopenharmony_ci};
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_cistatic struct snd_soc_dai_driver acp5x_i2s_dai = {
35262306a36Sopenharmony_ci	.playback = {
35362306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_96000,
35462306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
35562306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
35662306a36Sopenharmony_ci		.channels_min = 2,
35762306a36Sopenharmony_ci		.channels_max = 2,
35862306a36Sopenharmony_ci		.rate_min = 8000,
35962306a36Sopenharmony_ci		.rate_max = 96000,
36062306a36Sopenharmony_ci	},
36162306a36Sopenharmony_ci	.capture = {
36262306a36Sopenharmony_ci		.rates = SNDRV_PCM_RATE_8000_96000,
36362306a36Sopenharmony_ci		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
36462306a36Sopenharmony_ci			SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
36562306a36Sopenharmony_ci		.channels_min = 2,
36662306a36Sopenharmony_ci		.channels_max = 2,
36762306a36Sopenharmony_ci		.rate_min = 8000,
36862306a36Sopenharmony_ci		.rate_max = 96000,
36962306a36Sopenharmony_ci	},
37062306a36Sopenharmony_ci	.ops = &acp5x_i2s_dai_ops,
37162306a36Sopenharmony_ci};
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic int acp5x_dai_probe(struct platform_device *pdev)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	struct resource *res;
37662306a36Sopenharmony_ci	struct i2s_dev_data *adata;
37762306a36Sopenharmony_ci	int ret;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
38062306a36Sopenharmony_ci			     GFP_KERNEL);
38162306a36Sopenharmony_ci	if (!adata)
38262306a36Sopenharmony_ci		return -ENOMEM;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
38562306a36Sopenharmony_ci	if (!res) {
38662306a36Sopenharmony_ci		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
38762306a36Sopenharmony_ci		return -ENOMEM;
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci	adata->acp5x_base = devm_ioremap(&pdev->dev, res->start,
39062306a36Sopenharmony_ci					 resource_size(res));
39162306a36Sopenharmony_ci	if (!adata->acp5x_base)
39262306a36Sopenharmony_ci		return -ENOMEM;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	adata->master_mode = I2S_MASTER_MODE_ENABLE;
39562306a36Sopenharmony_ci	dev_set_drvdata(&pdev->dev, adata);
39662306a36Sopenharmony_ci	ret = devm_snd_soc_register_component(&pdev->dev,
39762306a36Sopenharmony_ci					      &acp5x_dai_component,
39862306a36Sopenharmony_ci					      &acp5x_i2s_dai, 1);
39962306a36Sopenharmony_ci	if (ret)
40062306a36Sopenharmony_ci		dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
40162306a36Sopenharmony_ci	return ret;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic struct platform_driver acp5x_dai_driver = {
40562306a36Sopenharmony_ci	.probe = acp5x_dai_probe,
40662306a36Sopenharmony_ci	.driver = {
40762306a36Sopenharmony_ci		.name = "acp5x_i2s_playcap",
40862306a36Sopenharmony_ci	},
40962306a36Sopenharmony_ci};
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_cimodule_platform_driver(acp5x_dai_driver);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ciMODULE_AUTHOR("Vijendar.Mukunda@amd.com");
41462306a36Sopenharmony_ciMODULE_DESCRIPTION("AMD ACP5.x CPU DAI Driver");
41562306a36Sopenharmony_ciMODULE_ALIAS("platform:" DRV_NAME);
41662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
417