3ea53da658a6b77ebb91a4b88e68805824f1673f
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.10 / 950-0633-snd-iec958-split-status-creation-and-fill.patch
1 From 5dea9e48e2a2bd39524e21c1a743f08edd8e4ef6 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Wed, 28 Apr 2021 15:29:13 +0200
4 Subject: [PATCH] snd: iec958: split status creation and fill
5
6 In some situations, like a codec probe, we need to provide an IEC status
7 default but don't have access to the sampling rate and width yet since
8 no stream has been configured yet.
9
10 Each and every driver has its own default, whereas the core iec958 code
11 also has some buried in the snd_pcm_create_iec958_consumer functions.
12
13 Let's split these functions in two to provide a default that doesn't
14 rely on the sampling rate and width, and another function to fill them
15 when available.
16
17 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
18 ---
19 include/sound/pcm_iec958.h | 8 +++
20 sound/core/pcm_iec958.c | 129 +++++++++++++++++++++++++------------
21 2 files changed, 95 insertions(+), 42 deletions(-)
22
23 --- a/include/sound/pcm_iec958.h
24 +++ b/include/sound/pcm_iec958.h
25 @@ -4,6 +4,14 @@
26
27 #include <linux/types.h>
28
29 +int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len);
30 +
31 +int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
32 + size_t len);
33 +
34 +int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
35 + u8 *cs, size_t len);
36 +
37 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
38 size_t len);
39
40 --- a/sound/core/pcm_iec958.c
41 +++ b/sound/core/pcm_iec958.c
42 @@ -9,41 +9,68 @@
43 #include <sound/pcm_params.h>
44 #include <sound/pcm_iec958.h>
45
46 -static int create_iec958_consumer(uint rate, uint sample_width,
47 - u8 *cs, size_t len)
48 +int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len)
49 {
50 - unsigned int fs, ws;
51 -
52 if (len < 4)
53 return -EINVAL;
54
55 - switch (rate) {
56 - case 32000:
57 - fs = IEC958_AES3_CON_FS_32000;
58 - break;
59 - case 44100:
60 - fs = IEC958_AES3_CON_FS_44100;
61 - break;
62 - case 48000:
63 - fs = IEC958_AES3_CON_FS_48000;
64 - break;
65 - case 88200:
66 - fs = IEC958_AES3_CON_FS_88200;
67 - break;
68 - case 96000:
69 - fs = IEC958_AES3_CON_FS_96000;
70 - break;
71 - case 176400:
72 - fs = IEC958_AES3_CON_FS_176400;
73 - break;
74 - case 192000:
75 - fs = IEC958_AES3_CON_FS_192000;
76 - break;
77 - default:
78 + memset(cs, 0, len);
79 +
80 + cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
81 + cs[1] = IEC958_AES1_CON_GENERAL;
82 + cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
83 + cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | IEC958_AES3_CON_FS_NOTID;
84 +
85 + if (len > 4)
86 + cs[4] = IEC958_AES4_CON_WORDLEN_NOTID;
87 +
88 + return len;
89 +}
90 +EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_default);
91 +
92 +static int fill_iec958_consumer(uint rate, uint sample_width,
93 + u8 *cs, size_t len)
94 +{
95 + if (len < 4)
96 return -EINVAL;
97 +
98 + if ((cs[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) {
99 + unsigned int fs;
100 +
101 + switch (rate) {
102 + case 32000:
103 + fs = IEC958_AES3_CON_FS_32000;
104 + break;
105 + case 44100:
106 + fs = IEC958_AES3_CON_FS_44100;
107 + break;
108 + case 48000:
109 + fs = IEC958_AES3_CON_FS_48000;
110 + break;
111 + case 88200:
112 + fs = IEC958_AES3_CON_FS_88200;
113 + break;
114 + case 96000:
115 + fs = IEC958_AES3_CON_FS_96000;
116 + break;
117 + case 176400:
118 + fs = IEC958_AES3_CON_FS_176400;
119 + break;
120 + case 192000:
121 + fs = IEC958_AES3_CON_FS_192000;
122 + break;
123 + default:
124 + return -EINVAL;
125 + }
126 +
127 + cs[3] &= ~IEC958_AES3_CON_FS;
128 + cs[3] |= fs;
129 }
130
131 - if (len > 4) {
132 + if (len > 4 &&
133 + (cs[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) {
134 + unsigned int ws;
135 +
136 switch (sample_width) {
137 case 16:
138 ws = IEC958_AES4_CON_WORDLEN_20_16;
139 @@ -64,20 +91,29 @@ static int create_iec958_consumer(uint r
140 default:
141 return -EINVAL;
142 }
143 - }
144
145 - memset(cs, 0, len);
146 + cs[4] &= ~IEC958_AES4_CON_WORDLEN;
147 + cs[4] |= ws;
148 + }
149
150 - cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
151 - cs[1] = IEC958_AES1_CON_GENERAL;
152 - cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC | IEC958_AES2_CON_CHANNEL_UNSPEC;
153 - cs[3] = IEC958_AES3_CON_CLOCK_1000PPM | fs;
154 + return len;
155 +}
156
157 - if (len > 4)
158 - cs[4] = ws;
159 +int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
160 + u8 *cs, size_t len)
161 +{
162 + return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
163 +}
164 +EXPORT_SYMBOL(snd_pcm_fill_iec958_consumer_hw_params);
165
166 - return len;
167 +int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime,
168 + u8 *cs, size_t len)
169 +{
170 + return fill_iec958_consumer(runtime->rate,
171 + snd_pcm_format_width(runtime->format),
172 + cs, len);
173 }
174 +EXPORT_SYMBOL(snd_pcm_fill_iec958_consumer);
175
176 /**
177 * snd_pcm_create_iec958_consumer - create consumer format IEC958 channel status
178 @@ -95,9 +131,13 @@ static int create_iec958_consumer(uint r
179 int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs,
180 size_t len)
181 {
182 - return create_iec958_consumer(runtime->rate,
183 - snd_pcm_format_width(runtime->format),
184 - cs, len);
185 + int ret;
186 +
187 + ret = snd_pcm_create_iec958_consumer_default(cs, len);
188 + if (ret < 0)
189 + return ret;
190 +
191 + return snd_pcm_fill_iec958_consumer(runtime, cs, len);
192 }
193 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer);
194
195 @@ -117,7 +157,12 @@ EXPORT_SYMBOL(snd_pcm_create_iec958_cons
196 int snd_pcm_create_iec958_consumer_hw_params(struct snd_pcm_hw_params *params,
197 u8 *cs, size_t len)
198 {
199 - return create_iec958_consumer(params_rate(params), params_width(params),
200 - cs, len);
201 + int ret;
202 +
203 + ret = snd_pcm_create_iec958_consumer_default(cs, len);
204 + if (ret < 0)
205 + return ret;
206 +
207 + return fill_iec958_consumer(params_rate(params), params_width(params), cs, len);
208 }
209 EXPORT_SYMBOL(snd_pcm_create_iec958_consumer_hw_params);