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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
From 599235bd9d22c8cad90b0a7621b46d70cca94d31 Mon Sep 17 00:00:00 2001
From: Viorel Suman <viorel.suman@nxp.com>
Date: Wed, 5 Jun 2019 13:46:32 +0000
Subject: [PATCH] MLK-21957-3: ASoC: fsl_sai: add bitcount and timestamp
controls
Bitcount and timestamp support added in SAI IP recently.
Add the related controls in SAI driver.
Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
---
sound/soc/fsl/fsl_sai.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++-
sound/soc/fsl/fsl_sai.h | 6 +++
2 files changed, 102 insertions(+), 1 deletion(-)
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -992,6 +992,90 @@ static const struct snd_soc_dai_ops fsl_
.shutdown = fsl_sai_shutdown,
};
+static const char
+ *en_sl[] = { "Disabled", "Enabled", },
+ *inc_sl[] = { "On enabled and bitcount increment", "On enabled", };
+
+static const struct soc_enum tstmp_enum[] = {
+SOC_ENUM_SINGLE(FSL_SAI_TTCTL, 0, ARRAY_SIZE(en_sl), en_sl),
+SOC_ENUM_SINGLE(FSL_SAI_RTCTL, 0, ARRAY_SIZE(en_sl), en_sl),
+SOC_ENUM_SINGLE(FSL_SAI_TTCTL, 1, ARRAY_SIZE(inc_sl), inc_sl),
+SOC_ENUM_SINGLE(FSL_SAI_RTCTL, 1, ARRAY_SIZE(inc_sl), inc_sl),
+};
+
+int fsl_sai_get_reg(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct soc_mreg_control *mc =
+ (struct soc_mreg_control *)kcontrol->private_value;
+ bool pm_active = pm_runtime_active(component->dev);
+ unsigned int regval;
+ int ret;
+
+ if (pm_active)
+ regcache_cache_bypass(component->regmap, true);
+
+ ret = snd_soc_component_read(component, mc->regbase, ®val);
+
+ if (pm_active)
+ regcache_cache_bypass(component->regmap, false);
+
+ if (ret < 0)
+ return ret;
+
+ ucontrol->value.integer.value[0] = regval;
+
+ return 0;
+}
+
+#define SOC_SINGLE_REG_RO(xname, xreg) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | \
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = snd_soc_info_xr_sx, .get = fsl_sai_get_reg, \
+ .private_value = (unsigned long)&(struct soc_mreg_control) \
+ { .regbase = xreg, .regcount = 1, .nbits = 32, \
+ .invert = 0, .min = 0, .max = 0xffffffff, } }
+
+static const struct snd_kcontrol_new fsl_sai_pb_ctrls[] = {
+ SOC_ENUM("Playback Timestamp Control", tstmp_enum[0]),
+ SOC_ENUM("Playback Timestamp Increment", tstmp_enum[2]),
+ SOC_SINGLE("Playback Timestamp Reset", FSL_SAI_TTCTL, 8, 1, 0),
+ SOC_SINGLE("Playback Bit Counter Reset", FSL_SAI_TTCTL, 9, 1, 0),
+ SOC_SINGLE_REG_RO("Playback Timestamp Counter", FSL_SAI_TTCTN),
+ SOC_SINGLE_REG_RO("Playback Bit Counter", FSL_SAI_TBCTN),
+ SOC_SINGLE_REG_RO("Playback Latched Timestamp Counter", FSL_SAI_TTCAP),
+};
+
+static const struct snd_kcontrol_new fsl_sai_cp_ctrls[] = {
+ SOC_ENUM("Capture Timestamp Control", tstmp_enum[1]),
+ SOC_ENUM("Capture Timestamp Increment", tstmp_enum[3]),
+ SOC_SINGLE("Capture Timestamp Reset", FSL_SAI_RTCTL, 8, 1, 0),
+ SOC_SINGLE("Capture Bit Counter Reset", FSL_SAI_RTCTL, 9, 1, 0),
+ SOC_SINGLE_REG_RO("Capture Timestamp Counter", FSL_SAI_RTCTN),
+ SOC_SINGLE_REG_RO("Capture Bit Counter", FSL_SAI_RBCTN),
+ SOC_SINGLE_REG_RO("Capture Latched Timestamp Counter", FSL_SAI_RTCAP),
+};
+
+static int fsl_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai)
+{
+ struct fsl_sai *sai = dev_get_drvdata(dai->dev);
+ struct snd_pcm *pcm = rtd->pcm;
+ bool ts_enabled = sai->verid.timestamp_en;
+ struct snd_soc_component *comp = dai->component;
+
+ if (ts_enabled && pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
+ snd_soc_add_component_controls(comp, fsl_sai_pb_ctrls,
+ ARRAY_SIZE(fsl_sai_pb_ctrls));
+
+ if (ts_enabled && pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
+ snd_soc_add_component_controls(comp, fsl_sai_cp_ctrls,
+ ARRAY_SIZE(fsl_sai_cp_ctrls));
+ return 0;
+}
+
static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
{
struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
@@ -1030,6 +1114,7 @@ static int fsl_sai_dai_resume(struct snd
}
static struct snd_soc_dai_driver fsl_sai_dai = {
+ .pcm_new = fsl_sai_pcm_new,
.probe = fsl_sai_dai_probe,
.playback = {
.stream_name = "CPU-Playback",
@@ -1054,7 +1139,7 @@ static struct snd_soc_dai_driver fsl_sai
};
static const struct snd_soc_component_driver fsl_component = {
- .name = "fsl-sai",
+ .name = "fsl-sai",
};
static struct reg_default fsl_sai_v2_reg_defaults[] = {
@@ -1141,6 +1226,14 @@ static bool fsl_sai_readable_reg(struct
case FSL_SAI_MDIV:
case FSL_SAI_VERID:
case FSL_SAI_PARAM:
+ case FSL_SAI_TTCTN:
+ case FSL_SAI_RTCTN:
+ case FSL_SAI_TTCTL:
+ case FSL_SAI_TBCTN:
+ case FSL_SAI_TTCAP:
+ case FSL_SAI_RTCTL:
+ case FSL_SAI_RBCTN:
+ case FSL_SAI_RTCAP:
return true;
default:
return false;
@@ -1214,6 +1307,8 @@ static bool fsl_sai_writeable_reg(struct
case FSL_SAI_RMR:
case FSL_SAI_MCTL:
case FSL_SAI_MDIV:
+ case FSL_SAI_TTCTL:
+ case FSL_SAI_RTCTL:
return true;
default:
return false;
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -210,6 +210,12 @@
#define SAI_FLAG_PMQOS BIT(0)
+/* SAI timestamp and bitcounter */
+#define FSL_SAI_xTCTL_TSEN BIT(0)
+#define FSL_SAI_xTCTL_TSINC BIT(1)
+#define FSL_SAI_xTCTL_RTSC BIT(8)
+#define FSL_SAI_xTCTL_RBC BIT(9)
+
struct fsl_sai_soc_data {
unsigned int fifo_depth;
unsigned int fifos;
|