hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/sound/soc/meson/axg-tdm-formatter.c
....@@ -30,27 +30,32 @@
3030 struct axg_tdm_stream *ts,
3131 unsigned int offset)
3232 {
33
- unsigned int val, ch = ts->channels;
34
- unsigned long mask;
35
- int i, j;
33
+ unsigned int ch = ts->channels;
34
+ u32 val[AXG_TDM_NUM_LANES];
35
+ int i, j, k;
36
+
37
+ /*
38
+ * We need to mimick the slot distribution used by the HW to keep the
39
+ * channel placement consistent regardless of the number of channel
40
+ * in the stream. This is why the odd algorithm below is used.
41
+ */
42
+ memset(val, 0, sizeof(*val) * AXG_TDM_NUM_LANES);
3643
3744 /*
3845 * Distribute the channels of the stream over the available slots
39
- * of each TDM lane
46
+ * of each TDM lane. We need to go over the 32 slots ...
4047 */
41
- for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
42
- val = 0;
43
- mask = ts->mask[i];
44
-
45
- for (j = find_first_bit(&mask, 32);
46
- (j < 32) && ch;
47
- j = find_next_bit(&mask, 32, j + 1)) {
48
- val |= 1 << j;
49
- ch -= 1;
48
+ for (i = 0; (i < 32) && ch; i += 2) {
49
+ /* ... of all the lanes ... */
50
+ for (j = 0; j < AXG_TDM_NUM_LANES; j++) {
51
+ /* ... then distribute the channels in pairs */
52
+ for (k = 0; k < 2; k++) {
53
+ if ((BIT(i + k) & ts->mask[j]) && ch) {
54
+ val[j] |= BIT(i + k);
55
+ ch -= 1;
56
+ }
57
+ }
5058 }
51
-
52
- regmap_write(map, offset, val);
53
- offset += regmap_get_reg_stride(map);
5459 }
5560
5661 /*
....@@ -63,6 +68,11 @@
6368 return -EINVAL;
6469 }
6570
71
+ for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
72
+ regmap_write(map, offset, val[i]);
73
+ offset += regmap_get_reg_stride(map);
74
+ }
75
+
6676 return 0;
6777 }
6878 EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks);