1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
From 913e9b53a6d75fcb5e65ed5e5a219bc852c1a09c Mon Sep 17 00:00:00 2001
From: Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com>
Date: Wed, 29 Mar 2017 19:12:20 +0530
Subject: [PATCH 1105/4131] ASoC: AMD: add ACP3x i2s ops
ACP3x has a i2s controller block for playback and capture. This patch
adds ACP3x i2s operations.
Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
sound/soc/amd/raven/acp3x-pcm-dma.c | 85 +++++++++++++++++++++++++++++++++++--
1 file changed, 82 insertions(+), 3 deletions(-)
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
index 346ebcb..5e589dc 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -436,10 +436,89 @@ static struct snd_soc_platform_driver acp3x_asoc_platform = {
.pcm_new = acp3x_dma_new,
};
+static int acp3x_dai_i2s_hwparams(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ 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;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ rv_writel((rtd->xfer_resolution << 3),
+ rtd->acp3x_base + mmACP_BTTDM_ITER);
+ else
+ rv_writel((rtd->xfer_resolution << 3),
+ 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;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ 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(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;
+}
+
struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
- .hw_params = NULL,
- .trigger = NULL,
- .set_fmt = NULL,
+ .hw_params = acp3x_dai_i2s_hwparams,
+ .trigger = acp3x_dai_i2s_trigger,
};
static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {
--
2.7.4
|