1
use bitfield::Bit;
2

            
3
use super::Info;
4
use crate::i2s::master::{
5
    Alignment,
6
    BitOrder,
7
    Config,
8
    ConfigError,
9
    Endianness,
10
    Polarity,
11
    UnitConfig,
12
};
13

            
14
impl Info {
15
    pub(crate) fn set_tx_bclk(&self, bclk_divider: u32) {
16
        self.regs()
17
            .tx_conf1()
18
24
            .modify(|_, w| unsafe { w.tx_bck_div_num().bits((bclk_divider - 1) as u8) });
19
    }
20

            
21
    pub(crate) fn set_rx_bclk(&self, bclk_divider: u32) {
22
        self.regs()
23
            .rx_conf1()
24
24
            .modify(|_, w| unsafe { w.rx_bck_div_num().bits((bclk_divider - 1) as u8) });
25
    }
26

            
27
25
    pub(crate) fn update_tx(&self) {
28
        self.regs().tx_conf().modify(|_, w| w.tx_update().set_bit());
29
390337581
        while self.regs().tx_conf().read().tx_update().bit_is_set() {
30
            // wait
31
        }
32
    }
33

            
34
1
    pub(crate) fn update_rx(&self) {
35
        self.regs().rx_conf().modify(|_, w| w.rx_update().set_bit());
36
15675276
        while self.regs().rx_conf().read().rx_update().bit_is_set() {
37
            // wait
38
        }
39
    }
40

            
41
26
    pub(crate) fn configure(&self, config: &Config) -> Result<(), ConfigError> {
42
        config.validate(self)?;
43

            
44
        match config {
45
            Config::Tdm(c) => {
46
24
                self.configure_tx(&c.tx_config)?;
47
24
                self.configure_rx(&c.rx_config)?;
48
24
                self.configure_mclk_pad(c.mclk_out);
49

            
50
24
                self.regs()
51
                    .tx_conf()
52
                    .modify(|_, w| w.sig_loopback().bit(c.signal_loopback));
53
                self.regs()
54
                    .rx_conf()
55
                    .modify(|_, w| w.rx_slave_mod().bit(c.signal_loopback));
56
            }
57
            #[cfg(any(i2s_supports_pdm_tx, i2s_supports_pdm_rx))]
58
            Config::Pdm(c) => {
59
                crate::i2s::pdm::configure_pdm(self, c)?;
60
            }
61
        }
62

            
63
        Ok(())
64
26
    }
65

            
66
24
    pub(crate) fn configure_tx(&self, config: &UnitConfig) -> Result<(), ConfigError> {
67
        let ws_width = config.calculate_ws_width()?;
68
        let clocks = config.calculate_clock();
69
24
        self.configure_tx_mclk(config.clock_source, &clocks);
70
24
        self.set_tx_bclk(clocks.bclk_divider);
71

            
72
        self.regs().tx_conf1().modify(|_, w| unsafe {
73
24
            w.tx_msb_shift().bit(config.msb_shift);
74
            #[allow(clippy::useless_conversion)]
75
24
            w.tx_tdm_ws_width().bits((ws_width - 1).try_into().unwrap());
76
            w.tx_bits_mod().bits(config.data_format.channel_bits() - 1);
77
            w.tx_tdm_chan_bits()
78
                .bits(config.data_format.data_bits() - 1);
79
            w.tx_half_sample_bits()
80
24
                .bits((config.data_format.data_bits() * config.channels.count) / 2 - 1)
81
        });
82

            
83
        self.regs().tx_conf().modify(|_, w| unsafe {
84
            w.tx_mono().clear_bit();
85
            w.tx_mono_fst_vld().set_bit();
86
            w.tx_stop_en().set_bit();
87
            w.tx_chan_equal().bit(config.channels.fill.is_none());
88
            w.tx_tdm_en().set_bit();
89
            w.tx_pdm_en().clear_bit();
90
            w.tx_pcm_bypass().set_bit();
91
            w.tx_big_endian()
92
                .bit(config.endianness == Endianness::BigEndian);
93
            w.tx_bit_order().bit(config.bit_order == BitOrder::LsbFirst);
94
            w.tx_ws_idle_pol()
95
                .bit(config.ws_polarity == Polarity::ActiveHigh);
96
            w.tx_chan_mod().bits(0);
97
            w.tx_left_align().bit(config.alignment() == Alignment::Left)
98
        });
99

            
100
        self.regs().tx_tdm_ctrl().modify(|_, w| unsafe {
101
24
            w.tx_tdm_tot_chan_num().bits(config.channels.count - 1);
102
            w.tx_tdm_chan0_en().bit(config.channels.mask.bit(0));
103
            w.tx_tdm_chan1_en().bit(config.channels.mask.bit(1));
104
            w.tx_tdm_chan2_en().bit(config.channels.mask.bit(2));
105
            w.tx_tdm_chan3_en().bit(config.channels.mask.bit(3));
106
            w.tx_tdm_chan4_en().bit(config.channels.mask.bit(4));
107
            w.tx_tdm_chan5_en().bit(config.channels.mask.bit(5));
108
            w.tx_tdm_chan6_en().bit(config.channels.mask.bit(6));
109
            w.tx_tdm_chan7_en().bit(config.channels.mask.bit(7));
110
            w.tx_tdm_chan8_en().bit(config.channels.mask.bit(8));
111
            w.tx_tdm_chan9_en().bit(config.channels.mask.bit(9));
112
            w.tx_tdm_chan10_en().bit(config.channels.mask.bit(10));
113
            w.tx_tdm_chan11_en().bit(config.channels.mask.bit(11));
114
            w.tx_tdm_chan12_en().bit(config.channels.mask.bit(12));
115
            w.tx_tdm_chan13_en().bit(config.channels.mask.bit(13));
116
            w.tx_tdm_chan14_en().bit(config.channels.mask.bit(14));
117
            w.tx_tdm_chan15_en().bit(config.channels.mask.bit(15));
118
            w.tx_tdm_skip_msk_en().clear_bit()
119
        });
120

            
121
        self.regs()
122
            .conf_sigle_data()
123
            .modify(|_, w| unsafe { w.single_data().bits(config.channels.fill.unwrap_or(0)) });
124

            
125
        Ok(())
126
24
    }
127

            
128
24
    pub(crate) fn configure_rx(&self, config: &UnitConfig) -> Result<(), ConfigError> {
129
        let ws_width = config.calculate_ws_width()?;
130
        let clocks = config.calculate_clock();
131
24
        self.configure_rx_mclk(config.clock_source, &clocks);
132
24
        self.set_rx_bclk(clocks.bclk_divider);
133

            
134
        self.regs().rx_conf1().modify(|_, w| unsafe {
135
24
            w.rx_msb_shift().bit(config.msb_shift);
136
            #[allow(clippy::useless_conversion)]
137
24
            w.rx_tdm_ws_width().bits((ws_width - 1).try_into().unwrap());
138
            w.rx_bits_mod().bits(config.data_format.channel_bits() - 1);
139
            w.rx_tdm_chan_bits()
140
                .bits(config.data_format.data_bits() - 1);
141
            w.rx_half_sample_bits()
142
24
                .bits((config.data_format.data_bits() * config.channels.count) / 2 - 1)
143
        });
144

            
145
        self.regs().rx_conf().modify(|_, w| unsafe {
146
            w.rx_mono().clear_bit();
147
            w.rx_mono_fst_vld().set_bit();
148
            w.rx_stop_mode().bits(2);
149
            w.rx_tdm_en().set_bit();
150
            w.rx_pdm_en().clear_bit();
151
            w.rx_pcm_bypass().set_bit();
152
            w.rx_big_endian()
153
                .bit(config.endianness == Endianness::BigEndian);
154
            w.rx_bit_order().bit(config.bit_order == BitOrder::LsbFirst);
155
            w.rx_ws_idle_pol()
156
                .bit(config.ws_polarity == Polarity::ActiveHigh);
157
            w.rx_left_align().bit(config.alignment() == Alignment::Left)
158
        });
159

            
160
        self.regs().rx_tdm_ctrl().modify(|_, w| unsafe {
161
24
            w.rx_tdm_tot_chan_num().bits(config.channels.count - 1);
162
            w.rx_tdm_pdm_chan0_en().bit(config.channels.mask.bit(0));
163
            w.rx_tdm_pdm_chan1_en().bit(config.channels.mask.bit(1));
164
            w.rx_tdm_pdm_chan2_en().bit(config.channels.mask.bit(2));
165
            w.rx_tdm_pdm_chan3_en().bit(config.channels.mask.bit(3));
166
            w.rx_tdm_pdm_chan4_en().bit(config.channels.mask.bit(4));
167
            w.rx_tdm_pdm_chan5_en().bit(config.channels.mask.bit(5));
168
            w.rx_tdm_pdm_chan6_en().bit(config.channels.mask.bit(6));
169
            w.rx_tdm_pdm_chan7_en().bit(config.channels.mask.bit(7));
170
            w.rx_tdm_chan8_en().bit(config.channels.mask.bit(8));
171
            w.rx_tdm_chan9_en().bit(config.channels.mask.bit(9));
172
            w.rx_tdm_chan10_en().bit(config.channels.mask.bit(10));
173
            w.rx_tdm_chan11_en().bit(config.channels.mask.bit(11));
174
            w.rx_tdm_chan12_en().bit(config.channels.mask.bit(12));
175
            w.rx_tdm_chan13_en().bit(config.channels.mask.bit(13));
176
            w.rx_tdm_chan14_en().bit(config.channels.mask.bit(14));
177
            w.rx_tdm_chan15_en().bit(config.channels.mask.bit(15))
178
        });
179

            
180
        Ok(())
181
24
    }
182

            
183
    pub(crate) fn set_master(&self) {
184
        self.regs()
185
            .tx_conf()
186
            .modify(|_, w| w.tx_slave_mod().clear_bit());
187
        self.regs()
188
            .rx_conf()
189
            .modify(|_, w| w.rx_slave_mod().clear_bit());
190
26
    }
191

            
192
    pub(crate) fn reset_tx(&self) {
193
        // I2S v2/v3: reset fields are write-to-trigger (WT); writing 0 has no effect.
194
        self.regs().tx_conf().modify(|_, w| {
195
            w.tx_reset().set_bit();
196
            w.tx_fifo_reset().set_bit()
197
        });
198

            
199
        self.regs().int_clr().write(|w| {
200
            w.tx_done().clear_bit_by_one();
201
            w.tx_hung().clear_bit_by_one()
202
        });
203
    }
204

            
205
    pub(crate) fn tx_start(&self) {
206
        self.regs().tx_conf().modify(|_, w| w.tx_start().set_bit());
207
    }
208

            
209
    pub(crate) fn tx_stop(&self) {
210
        self.regs()
211
            .tx_conf()
212
            .modify(|_, w| w.tx_start().clear_bit());
213
    }
214

            
215
    pub(crate) fn is_tx_done(&self) -> bool {
216
        self.regs().state().read().tx_idle().bit_is_set()
217
    }
218

            
219
    pub(crate) fn reset_rx(&self) {
220
        self.regs()
221
            .rx_conf()
222
            .modify(|_, w| w.rx_start().clear_bit());
223

            
224
        // I2S v2/v3: reset fields are write-to-trigger (WT); writing 0 has no effect.
225
        self.regs().rx_conf().modify(|_, w| {
226
            w.rx_reset().set_bit();
227
            w.rx_fifo_reset().set_bit()
228
        });
229

            
230
        self.regs().int_clr().write(|w| {
231
            w.rx_done().clear_bit_by_one();
232
            w.rx_hung().clear_bit_by_one()
233
        });
234
    }
235

            
236
    pub(crate) fn rx_start(&self, len: usize) {
237
        let len = len - 1;
238

            
239
        self.regs()
240
            .rxeof_num()
241
            .write(|w| unsafe { w.rx_eof_num().bits(len as u16) });
242
        // Sync configuration into the I2S clock domain before starting RX.
243
        self.update_rx();
244
        self.regs().rx_conf().modify(|_, w| w.rx_start().set_bit());
245
    }
246

            
247
    pub(crate) fn rx_stop(&self) {
248
        self.regs()
249
            .rx_conf()
250
            .modify(|_, w| w.rx_start().clear_bit());
251
    }
252

            
253
    pub(crate) fn is_rx_done(&self) -> bool {
254
        self.regs().int_raw().read().rx_done().bit_is_set()
255
    }
256
}