.. | .. |
---|
30 | 30 | struct axg_tdm_stream *ts, |
---|
31 | 31 | unsigned int offset) |
---|
32 | 32 | { |
---|
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); |
---|
36 | 43 | |
---|
37 | 44 | /* |
---|
38 | 45 | * 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 ... |
---|
40 | 47 | */ |
---|
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 | + } |
---|
50 | 58 | } |
---|
51 | | - |
---|
52 | | - regmap_write(map, offset, val); |
---|
53 | | - offset += regmap_get_reg_stride(map); |
---|
54 | 59 | } |
---|
55 | 60 | |
---|
56 | 61 | /* |
---|
.. | .. |
---|
63 | 68 | return -EINVAL; |
---|
64 | 69 | } |
---|
65 | 70 | |
---|
| 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 | + |
---|
66 | 76 | return 0; |
---|
67 | 77 | } |
---|
68 | 78 | EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks); |
---|