ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 801-audio-0059-MLK-20328-1-ASoC-fsl_sai-map-number-of-pins-to-datal.patch
1 From e62741891f6901b5219eacdf60835cac9beb7bae Mon Sep 17 00:00:00 2001
2 From: Viorel Suman <viorel.suman@nxp.com>
3 Date: Wed, 21 Nov 2018 16:09:44 +0200
4 Subject: [PATCH] MLK-20328-1: ASoC: fsl_sai: map number of pins to dataline
5  masks
6
7 The patch enable mapping the number of pins required to play or record
8 a specific number of channels to a specific dataline mask.
9
10 Three consequent elements in "fsl,dataline" and "fsl,dataline,dsd" defines a
11 particular mapping, for instance for: fsl,dataline = "0 0xff 0xff 2 0x11 0x11"
12 there are two mappings defined:
13
14 default (0 pins) "rx" and "tx" dataline masks: 0 0xff 0xff
15          2 pins  "rx" and "tx" dataline masks: 2 0x11 0x11
16
17 In case if property is missing, then default value "0 0x1 0x1" is considered.
18
19 Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
20 ---
21  sound/soc/fsl/fsl_sai.c | 227 ++++++++++++++++++++++++++++++------------------
22  sound/soc/fsl/fsl_sai.h |  16 +++-
23  2 files changed, 153 insertions(+), 90 deletions(-)
24
25 --- a/sound/soc/fsl/fsl_sai.c
26 +++ b/sound/soc/fsl/fsl_sai.c
27 @@ -621,17 +621,35 @@ static int fsl_sai_hw_params(struct snd_
28         u32 slots = (channels == 1) ? 2 : channels;
29         u32 slot_width = word_width;
30         u32 pins, bclk;
31 -       int ret;
32 -       int i;
33 -       int trce_mask = 0;
34 +       int ret, i, trce_mask = 0, dl_cfg_cnt, dl_cfg_idx = 0;
35 +       struct fsl_sai_dl_cfg *dl_cfg;
36  
37         if (sai->slots)
38                 slots = sai->slots;
39  
40         pins = DIV_ROUND_UP(channels, slots);
41         sai->is_dsd = fsl_is_dsd(params);
42 -       if (sai->is_dsd)
43 +       if (sai->is_dsd) {
44                 pins = channels;
45 +               dl_cfg = sai->dsd_dl_cfg;
46 +               dl_cfg_cnt = sai->dsd_dl_cfg_cnt;
47 +       } else {
48 +               dl_cfg = sai->pcm_dl_cfg;
49 +               dl_cfg_cnt = sai->pcm_dl_cfg_cnt;
50 +       }
51 +
52 +       for (i = 0; i < dl_cfg_cnt; i++) {
53 +               if (dl_cfg[i].pins == pins) {
54 +                       dl_cfg_idx = i;
55 +                       break;
56 +               }
57 +       }
58 +
59 +       if (dl_cfg_idx >= dl_cfg_cnt) {
60 +               dev_err(cpu_dai->dev, "fsl,dataline%s invalid or not provided.\n",
61 +                       sai->is_dsd ? ",dsd" : "");
62 +               return -EINVAL;
63 +       }
64  
65         if (sai->slot_width)
66                 slot_width = sai->slot_width;
67 @@ -713,7 +731,7 @@ static int fsl_sai_hw_params(struct snd_
68  
69         if (sai->soc->dataline != 0x1) {
70  
71 -               if (sai->dataline[tx] <= 1 || sai->is_multi_lane)
72 +               if (dl_cfg[dl_cfg_idx].mask[tx] <= 1 || sai->is_multi_lane)
73                         regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, offset),
74                                 FSL_SAI_CR4_FCOMB_MASK, 0);
75                 else
76 @@ -724,21 +742,13 @@ static int fsl_sai_hw_params(struct snd_
77                         if (tx) {
78                                 sai->dma_params_tx.maxburst =
79                                                 FSL_SAI_MAXBURST_TX * pins;
80 -                               if (sai->is_dsd)
81 -                                       sai->dma_params_tx.fifo_num = pins +
82 -                                          (sai->dataline_off_dsd[tx] << 4);
83 -                               else
84 -                                       sai->dma_params_tx.fifo_num = pins +
85 -                                               (sai->dataline_off[tx] << 4);
86 +                               sai->dma_params_tx.fifo_num = pins +
87 +                                          (dl_cfg[dl_cfg_idx].offset[tx] << 4);
88                         } else {
89                                 sai->dma_params_rx.maxburst =
90                                         FSL_SAI_MAXBURST_RX * pins;
91 -                               if (sai->is_dsd)
92 -                                       sai->dma_params_rx.fifo_num = pins +
93 -                                         (sai->dataline_off_dsd[tx] << 4);
94 -                               else
95 -                                       sai->dma_params_rx.fifo_num = pins +
96 -                                               (sai->dataline_off[tx] << 4);
97 +                               sai->dma_params_rx.fifo_num = pins +
98 +                                         (dl_cfg[dl_cfg_idx].offset[tx] << 4);
99                         }
100                 }
101  
102 @@ -746,38 +756,22 @@ static int fsl_sai_hw_params(struct snd_
103                                 &sai->dma_params_rx);
104         }
105  
106 -       if (sai->is_dsd) {
107 -               if (__sw_hweight8(sai->dataline_dsd[tx] & 0xFF) < pins) {
108 -                       dev_err(cpu_dai->dev, "channel not supported\n");
109 -                       return -EINVAL;
110 -               }
111 -               /*find a proper tcre setting*/
112 -               for (i = 0; i < 8; i++) {
113 -                       trce_mask = (1 << (i + 1)) - 1;
114 -                       if (__sw_hweight8(sai->dataline_dsd[tx] & trce_mask) == pins)
115 -                               break;
116 -               }
117 -
118 -               regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset),
119 -                          FSL_SAI_CR3_TRCE_MASK,
120 -                          FSL_SAI_CR3_TRCE((sai->dataline_dsd[tx] & trce_mask)));
121 -       } else {
122 -               if (__sw_hweight8(sai->dataline[tx] & 0xFF) < pins) {
123 -                       dev_err(cpu_dai->dev, "channel not supported\n");
124 -                       return -EINVAL;
125 -               }
126 -               /*find a proper tcre setting*/
127 -               for (i = 0; i < 8; i++) {
128 -                       trce_mask = (1 << (i + 1)) - 1;
129 -                       if (__sw_hweight8(sai->dataline[tx] & trce_mask) == pins)
130 -                               break;
131 -               }
132 +       if (__sw_hweight8(dl_cfg[dl_cfg_idx].mask[tx] & 0xFF) < pins) {
133 +               dev_err(cpu_dai->dev, "channel not supported\n");
134 +               return -EINVAL;
135 +       }
136  
137 -               regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset),
138 -                          FSL_SAI_CR3_TRCE_MASK,
139 -                          FSL_SAI_CR3_TRCE((sai->dataline[tx] & trce_mask)));
140 +       /*find a proper tcre setting*/
141 +       for (i = 0; i < 8; i++) {
142 +               trce_mask = (1 << (i + 1)) - 1;
143 +               if (__sw_hweight8(dl_cfg[dl_cfg_idx].mask[tx] & trce_mask) == pins)
144 +                       break;
145         }
146  
147 +       regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, offset),
148 +                  FSL_SAI_CR3_TRCE_MASK,
149 +                  FSL_SAI_CR3_TRCE((dl_cfg[dl_cfg_idx].mask[tx] & trce_mask)));
150 +
151         regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, offset),
152                            FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK |
153                            FSL_SAI_CR4_CHMOD_MASK,
154 @@ -820,15 +814,32 @@ static int fsl_sai_trigger(struct snd_pc
155         u32 slots = (channels == 1) ? 2 : channels;
156         u32 xcsr, count = 100;
157         u32 pins;
158 -       int i = 0, j = 0, k = 0;
159 +       int i = 0, j = 0, k = 0, dl_cfg_cnt, dl_cfg_idx = 0;
160 +       struct fsl_sai_dl_cfg *dl_cfg;
161  
162         if (sai->slots)
163                 slots = sai->slots;
164  
165         pins = DIV_ROUND_UP(channels, slots);
166  
167 -       if (sai->is_dsd)
168 +       if (sai->is_dsd) {
169                 pins = channels;
170 +               dl_cfg = sai->dsd_dl_cfg;
171 +               dl_cfg_cnt = sai->dsd_dl_cfg_cnt;
172 +       } else {
173 +               dl_cfg = sai->pcm_dl_cfg;
174 +               dl_cfg_cnt = sai->pcm_dl_cfg_cnt;
175 +       }
176 +
177 +       for (i = 0; i < dl_cfg_cnt; i++) {
178 +               if (dl_cfg[i].pins == pins) {
179 +                       dl_cfg_idx = i;
180 +                       break;
181 +               }
182 +       }
183 +
184 +       i = 0;
185 +
186         /*
187          * Asynchronous mode: Clear SYNC for both Tx and Rx.
188          * Rx sync with Tx clocks: Clear SYNC for Tx, set it for Rx.
189 @@ -849,7 +860,7 @@ static int fsl_sai_trigger(struct snd_pc
190         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
191  
192                 while (tx && i < channels) {
193 -                       if ((sai->is_dsd ? sai->dataline_dsd[tx] : sai->dataline[tx]) & (1 << j)) {
194 +                       if (dl_cfg[dl_cfg_idx].mask[tx] & (1 << j)) {
195                                 regmap_write(sai->regmap, FSL_SAI_TDR0 + j * 0x4, 0x0);
196                                 i++;
197                                 k++;
198 @@ -1262,6 +1273,77 @@ static const struct of_device_id fsl_sai
199  };
200  MODULE_DEVICE_TABLE(of, fsl_sai_ids);
201  
202 +static unsigned int fsl_sai_calc_dl_off(unsigned int* dl_mask)
203 +{
204 +       int fbidx, nbidx, offset;
205 +
206 +       fbidx = find_first_bit((const unsigned long *)dl_mask, 8);
207 +       nbidx = find_next_bit((const unsigned long *)dl_mask, 8, fbidx+1);
208 +       offset = nbidx - fbidx - 1;
209 +
210 +       return (offset < 0 || offset >= 7 ? 0 : offset);
211 +}
212 +
213 +static int fsl_sai_read_dlcfg(struct platform_device *pdev, char *pn,
214 +       struct fsl_sai_dl_cfg **rcfg, unsigned int soc_dl)
215 +{
216 +       int ret, elems, i, index, num_cfg;
217 +       struct device_node *np = pdev->dev.of_node;
218 +       struct fsl_sai_dl_cfg *cfg;
219 +       u32 rx, tx, pins;
220 +
221 +       *rcfg = NULL;
222 +
223 +       elems = of_property_count_u32_elems(np, pn);
224 +
225 +       /* consider default value "0 0x1 0x1" if property is missing */
226 +       if (elems <= 0)
227 +               elems = 3;
228 +
229 +       if (elems % 3) {
230 +               dev_err(&pdev->dev,
231 +                       "Number of elements in %s must be divisible to 3.\n", pn);
232 +               return -EINVAL;
233 +       }
234 +
235 +       num_cfg = elems / 3;
236 +       cfg = devm_kzalloc(&pdev->dev, num_cfg * sizeof(*cfg), GFP_KERNEL);
237 +       if (cfg == NULL) {
238 +               dev_err(&pdev->dev, "Cannot allocate memory for %s.\n", pn);
239 +               return -ENOMEM;
240 +       }
241 +
242 +       for (i = 0, index = 0; i < num_cfg; i++) {
243 +               ret = of_property_read_u32_index(np, pn, index++, &pins);
244 +               if (ret)
245 +                       pins = 0;
246 +
247 +               ret = of_property_read_u32_index(np, pn, index++, &rx);
248 +               if (ret)
249 +                       rx = 1;
250 +
251 +               ret = of_property_read_u32_index(np, pn, index++, &tx);
252 +               if (ret)
253 +                       tx = 1;
254 +
255 +               if ((rx & ~soc_dl) || (tx & ~soc_dl)) {
256 +                       dev_err(&pdev->dev,
257 +                               "%s: dataline cfg[%d] setting error, mask is 0x%x\n",
258 +                                pn, i, soc_dl);
259 +                       return -EINVAL;
260 +               }
261 +
262 +               cfg[i].pins = pins;
263 +               cfg[i].mask[0] = rx;
264 +               cfg[i].offset[0] = fsl_sai_calc_dl_off(&rx);
265 +               cfg[i].mask[1] = tx;
266 +               cfg[i].offset[1] = fsl_sai_calc_dl_off(&tx);
267 +       }
268 +
269 +       *rcfg = cfg;
270 +       return num_cfg;
271 +}
272 +
273  static int fsl_sai_probe(struct platform_device *pdev)
274  {
275         struct device_node *np = pdev->dev.of_node;
276 @@ -1273,7 +1355,6 @@ static int fsl_sai_probe(struct platform
277         char tmp[8];
278         int irq, ret, i;
279         int index;
280 -       int firstbitidx, nextbitidx, offset;
281         struct regmap_config fsl_sai_regmap_config = fsl_sai_v2_regmap_config;
282         unsigned long irqflags = 0;
283  
284 @@ -1340,45 +1421,19 @@ static int fsl_sai_probe(struct platform
285                 sai->is_multi_lane = true;
286  
287         /*dataline mask for rx and tx*/
288 -       ret = of_property_read_u32_index(np, "fsl,dataline", 0, &sai->dataline[0]);
289 -       if (ret)
290 -               sai->dataline[0] = 1;
291 -
292 -       ret = of_property_read_u32_index(np, "fsl,dataline", 1, &sai->dataline[1]);
293 -       if (ret)
294 -               sai->dataline[1] = 1;
295 -
296 -       if ((sai->dataline[0] & (~sai->soc->dataline)) || sai->dataline[1] & (~sai->soc->dataline)) {
297 -               dev_err(&pdev->dev, "dataline setting error, Mask is 0x%x\n", sai->soc->dataline);
298 -               return -EINVAL;
299 -       }
300 -
301 -       for (i = 0; i < 2; i++) {
302 -               firstbitidx = find_first_bit((const unsigned long *)&sai->dataline[i], 8);
303 -               nextbitidx = find_next_bit((const unsigned long *)&sai->dataline[i], 8, firstbitidx+1);
304 -               offset = nextbitidx - firstbitidx - 1;
305 -               sai->dataline_off[i] = (offset < 0 || offset >= 7 ? 0 : offset);
306 -       }
307 -
308 -       ret = of_property_read_u32_index(np, "fsl,dataline,dsd", 0, &sai->dataline_dsd[0]);
309 -       if (ret)
310 -               sai->dataline_dsd[0] = 1;
311 -
312 -       ret = of_property_read_u32_index(np, "fsl,dataline,dsd", 1, &sai->dataline_dsd[1]);
313 -       if (ret)
314 -               sai->dataline_dsd[1] = 1;
315 +       ret = fsl_sai_read_dlcfg(pdev, "fsl,dataline", &sai->pcm_dl_cfg,
316 +                                       sai->soc->dataline);
317 +       if (ret < 0)
318 +               return ret;
319 +
320 +       sai->pcm_dl_cfg_cnt = ret;
321 +
322 +       ret = fsl_sai_read_dlcfg(pdev, "fsl,dataline,dsd", &sai->dsd_dl_cfg,
323 +                                       sai->soc->dataline);
324 +       if (ret < 0)
325 +               return ret;
326  
327 -       if ((sai->dataline_dsd[0] & (~sai->soc->dataline)) || sai->dataline_dsd[1] & (~sai->soc->dataline)) {
328 -               dev_err(&pdev->dev, "dataline setting error, Mask is 0x%x\n", sai->soc->dataline);
329 -               return -EINVAL;
330 -       }
331 -
332 -       for (i = 0; i < 2; i++) {
333 -               firstbitidx = find_first_bit((const unsigned long *)&sai->dataline_dsd[i], 8);
334 -               nextbitidx = find_next_bit((const unsigned long *)&sai->dataline_dsd[i], 8, firstbitidx+1);
335 -               offset = nextbitidx - firstbitidx - 1;
336 -               sai->dataline_off_dsd[i] = (offset < 0 || offset >= 7 ? 0 : offset);
337 -       }
338 +       sai->dsd_dl_cfg_cnt = ret;
339  
340         if ((of_find_property(np, "fsl,i2s-xtor", NULL) != NULL) ||
341             (of_find_property(np, "fsl,txm-rxs", NULL) != NULL))
342 --- a/sound/soc/fsl/fsl_sai.h
343 +++ b/sound/soc/fsl/fsl_sai.h
344 @@ -234,6 +234,12 @@ struct fsl_sai_param {
345         u32 dln; /* number of datalines implemented */
346  };
347  
348 +struct fsl_sai_dl_cfg {
349 +       unsigned int pins;
350 +       unsigned int mask[2];
351 +       unsigned int offset[2];
352 +};
353 +
354  struct fsl_sai {
355         struct platform_device *pdev;
356         struct regmap *regmap;
357 @@ -249,10 +255,12 @@ struct fsl_sai {
358         bool synchronous[2];
359         bool is_stream_opened[2];
360         bool is_dsd;
361 -       unsigned int dataline[2];
362 -       unsigned int dataline_dsd[2];
363 -       unsigned int dataline_off[2];
364 -       unsigned int dataline_off_dsd[2];
365 +
366 +       int pcm_dl_cfg_cnt;
367 +       int dsd_dl_cfg_cnt;
368 +       struct fsl_sai_dl_cfg *pcm_dl_cfg;
369 +       struct fsl_sai_dl_cfg *dsd_dl_cfg;
370 +
371         unsigned int masterflag[2];
372  
373         unsigned int mclk_id[2];