blob: 92de8196ee991875fdd334fea38e3269040f9703 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From 599235bd9d22c8cad90b0a7621b46d70cca94d31 Mon Sep 17 00:00:00 2001
2From: Viorel Suman <viorel.suman@nxp.com>
3Date: Wed, 5 Jun 2019 13:46:32 +0000
4Subject: [PATCH] MLK-21957-3: ASoC: fsl_sai: add bitcount and timestamp
5 controls
6
7Bitcount and timestamp support added in SAI IP recently.
8Add the related controls in SAI driver.
9
10Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
11---
12 sound/soc/fsl/fsl_sai.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++-
13 sound/soc/fsl/fsl_sai.h | 6 +++
14 2 files changed, 102 insertions(+), 1 deletion(-)
15
16--- a/sound/soc/fsl/fsl_sai.c
17+++ b/sound/soc/fsl/fsl_sai.c
18@@ -992,6 +992,90 @@ static const struct snd_soc_dai_ops fsl_
19 .shutdown = fsl_sai_shutdown,
20 };
21
22+static const char
23+ *en_sl[] = { "Disabled", "Enabled", },
24+ *inc_sl[] = { "On enabled and bitcount increment", "On enabled", };
25+
26+static const struct soc_enum tstmp_enum[] = {
27+SOC_ENUM_SINGLE(FSL_SAI_TTCTL, 0, ARRAY_SIZE(en_sl), en_sl),
28+SOC_ENUM_SINGLE(FSL_SAI_RTCTL, 0, ARRAY_SIZE(en_sl), en_sl),
29+SOC_ENUM_SINGLE(FSL_SAI_TTCTL, 1, ARRAY_SIZE(inc_sl), inc_sl),
30+SOC_ENUM_SINGLE(FSL_SAI_RTCTL, 1, ARRAY_SIZE(inc_sl), inc_sl),
31+};
32+
33+int fsl_sai_get_reg(struct snd_kcontrol *kcontrol,
34+ struct snd_ctl_elem_value *ucontrol)
35+{
36+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
37+ struct soc_mreg_control *mc =
38+ (struct soc_mreg_control *)kcontrol->private_value;
39+ bool pm_active = pm_runtime_active(component->dev);
40+ unsigned int regval;
41+ int ret;
42+
43+ if (pm_active)
44+ regcache_cache_bypass(component->regmap, true);
45+
46+ ret = snd_soc_component_read(component, mc->regbase, &regval);
47+
48+ if (pm_active)
49+ regcache_cache_bypass(component->regmap, false);
50+
51+ if (ret < 0)
52+ return ret;
53+
54+ ucontrol->value.integer.value[0] = regval;
55+
56+ return 0;
57+}
58+
59+#define SOC_SINGLE_REG_RO(xname, xreg) \
60+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \
61+ .access = SNDRV_CTL_ELEM_ACCESS_READ | \
62+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
63+ .info = snd_soc_info_xr_sx, .get = fsl_sai_get_reg, \
64+ .private_value = (unsigned long)&(struct soc_mreg_control) \
65+ { .regbase = xreg, .regcount = 1, .nbits = 32, \
66+ .invert = 0, .min = 0, .max = 0xffffffff, } }
67+
68+static const struct snd_kcontrol_new fsl_sai_pb_ctrls[] = {
69+ SOC_ENUM("Playback Timestamp Control", tstmp_enum[0]),
70+ SOC_ENUM("Playback Timestamp Increment", tstmp_enum[2]),
71+ SOC_SINGLE("Playback Timestamp Reset", FSL_SAI_TTCTL, 8, 1, 0),
72+ SOC_SINGLE("Playback Bit Counter Reset", FSL_SAI_TTCTL, 9, 1, 0),
73+ SOC_SINGLE_REG_RO("Playback Timestamp Counter", FSL_SAI_TTCTN),
74+ SOC_SINGLE_REG_RO("Playback Bit Counter", FSL_SAI_TBCTN),
75+ SOC_SINGLE_REG_RO("Playback Latched Timestamp Counter", FSL_SAI_TTCAP),
76+};
77+
78+static const struct snd_kcontrol_new fsl_sai_cp_ctrls[] = {
79+ SOC_ENUM("Capture Timestamp Control", tstmp_enum[1]),
80+ SOC_ENUM("Capture Timestamp Increment", tstmp_enum[3]),
81+ SOC_SINGLE("Capture Timestamp Reset", FSL_SAI_RTCTL, 8, 1, 0),
82+ SOC_SINGLE("Capture Bit Counter Reset", FSL_SAI_RTCTL, 9, 1, 0),
83+ SOC_SINGLE_REG_RO("Capture Timestamp Counter", FSL_SAI_RTCTN),
84+ SOC_SINGLE_REG_RO("Capture Bit Counter", FSL_SAI_RBCTN),
85+ SOC_SINGLE_REG_RO("Capture Latched Timestamp Counter", FSL_SAI_RTCAP),
86+};
87+
88+static int fsl_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
89+ struct snd_soc_dai *dai)
90+{
91+ struct fsl_sai *sai = dev_get_drvdata(dai->dev);
92+ struct snd_pcm *pcm = rtd->pcm;
93+ bool ts_enabled = sai->verid.timestamp_en;
94+ struct snd_soc_component *comp = dai->component;
95+
96+ if (ts_enabled && pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
97+ snd_soc_add_component_controls(comp, fsl_sai_pb_ctrls,
98+ ARRAY_SIZE(fsl_sai_pb_ctrls));
99+
100+ if (ts_enabled && pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
101+ snd_soc_add_component_controls(comp, fsl_sai_cp_ctrls,
102+ ARRAY_SIZE(fsl_sai_cp_ctrls));
103+ return 0;
104+}
105+
106 static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
107 {
108 struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
109@@ -1030,6 +1114,7 @@ static int fsl_sai_dai_resume(struct snd
110 }
111
112 static struct snd_soc_dai_driver fsl_sai_dai_template = {
113+ .pcm_new = fsl_sai_pcm_new,
114 .probe = fsl_sai_dai_probe,
115 .playback = {
116 .stream_name = "CPU-Playback",
117@@ -1054,7 +1139,7 @@ static struct snd_soc_dai_driver fsl_sai
118 };
119
120 static const struct snd_soc_component_driver fsl_component = {
121- .name = "fsl-sai",
122+ .name = "fsl-sai",
123 };
124
125 static struct reg_default fsl_sai_v2_reg_defaults[] = {
126@@ -1141,6 +1226,14 @@ static bool fsl_sai_readable_reg(struct
127 case FSL_SAI_MDIV:
128 case FSL_SAI_VERID:
129 case FSL_SAI_PARAM:
130+ case FSL_SAI_TTCTN:
131+ case FSL_SAI_RTCTN:
132+ case FSL_SAI_TTCTL:
133+ case FSL_SAI_TBCTN:
134+ case FSL_SAI_TTCAP:
135+ case FSL_SAI_RTCTL:
136+ case FSL_SAI_RBCTN:
137+ case FSL_SAI_RTCAP:
138 return true;
139 default:
140 return false;
141@@ -1214,6 +1307,8 @@ static bool fsl_sai_writeable_reg(struct
142 case FSL_SAI_RMR:
143 case FSL_SAI_MCTL:
144 case FSL_SAI_MDIV:
145+ case FSL_SAI_TTCTL:
146+ case FSL_SAI_RTCTL:
147 return true;
148 default:
149 return false;
150--- a/sound/soc/fsl/fsl_sai.h
151+++ b/sound/soc/fsl/fsl_sai.h
152@@ -210,6 +210,12 @@
153
154 #define SAI_FLAG_PMQOS BIT(0)
155
156+/* SAI timestamp and bitcounter */
157+#define FSL_SAI_xTCTL_TSEN BIT(0)
158+#define FSL_SAI_xTCTL_TSINC BIT(1)
159+#define FSL_SAI_xTCTL_RTSC BIT(8)
160+#define FSL_SAI_xTCTL_RBC BIT(9)
161+
162 struct fsl_sai_soc_data {
163 unsigned int fifo_depth;
164 unsigned int fifos;