paul@206 | 1 | /* |
paul@206 | 2 | * AIC support for the X1600. |
paul@206 | 3 | * |
paul@302 | 4 | * Copyright (C) 2023, 2024 Paul Boddie <paul@boddie.org.uk> |
paul@206 | 5 | * |
paul@206 | 6 | * This program is free software; you can redistribute it and/or |
paul@206 | 7 | * modify it under the terms of the GNU General Public License as |
paul@206 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@206 | 9 | * the License, or (at your option) any later version. |
paul@206 | 10 | * |
paul@206 | 11 | * This program is distributed in the hope that it will be useful, |
paul@206 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@206 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@206 | 14 | * GNU General Public License for more details. |
paul@206 | 15 | * |
paul@206 | 16 | * You should have received a copy of the GNU General Public License |
paul@206 | 17 | * along with this program; if not, write to the Free Software |
paul@206 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@206 | 19 | * Boston, MA 02110-1301, USA |
paul@206 | 20 | */ |
paul@206 | 21 | |
paul@206 | 22 | #include <l4/devices/aic-x1600.h> |
paul@206 | 23 | #include <l4/devices/dma.h> |
paul@220 | 24 | #include <l4/sys/err.h> |
paul@220 | 25 | |
paul@206 | 26 | |
paul@206 | 27 | |
paul@220 | 28 | /* Register definitions. */ |
paul@206 | 29 | |
paul@206 | 30 | enum Regs |
paul@206 | 31 | { |
paul@206 | 32 | Aic_config = 0x000, // AICFR |
paul@206 | 33 | Aic_control = 0x004, // AICCR |
paul@206 | 34 | Aic_i2s_msb_control = 0x010, // I2SCR |
paul@206 | 35 | Aic_fifo_status = 0x014, // AICSR |
paul@206 | 36 | Aic_i2s_msb_status = 0x01c, // I2SSR |
paul@206 | 37 | Aic_i2s_msb_divider = 0x030, // I2SDIV |
paul@206 | 38 | Aic_fifo_data = 0x034, // AICDR |
paul@206 | 39 | Aic_loop_data = 0x038, // AICLR |
paul@206 | 40 | Aic_tfifo_loop = 0x03c, // AICTFLR |
paul@206 | 41 | }; |
paul@206 | 42 | |
paul@206 | 43 | enum Aic_config_bits : unsigned |
paul@206 | 44 | { |
paul@206 | 45 | Aic_enable_big_endian = 0x1000, // MSB |
paul@206 | 46 | Aic_independent_clock = 0x0100, // DMODE |
paul@206 | 47 | Aic_shared_clock = 0x0000, // DMODE |
paul@206 | 48 | Aic_last_sample_uflow = 0x0040, // LSMP |
paul@206 | 49 | Aic_select_i2s_msb = 0x0010, // AUSEL |
paul@206 | 50 | Aic_reset = 0x0008, // RST |
paul@206 | 51 | Aic_tmaster = 0x0004, // TMASTER |
paul@206 | 52 | Aic_rmaster = 0x0002, // RMASTER |
paul@206 | 53 | Aic_enable = 0x0001, // ENB |
paul@220 | 54 | }; |
paul@206 | 55 | |
paul@220 | 56 | enum Aic_config_shifts : unsigned |
paul@220 | 57 | { |
paul@220 | 58 | Aic_rfifo_thold_shift = 24, // RFTH |
paul@220 | 59 | Aic_tfifo_thold_shift = 16, // TFTH |
paul@206 | 60 | }; |
paul@206 | 61 | |
paul@206 | 62 | enum Aic_fifo_limits : unsigned |
paul@206 | 63 | { |
paul@206 | 64 | Aic_rfifo_max = 15, |
paul@206 | 65 | Aic_tfifo_max = 31, |
paul@206 | 66 | }; |
paul@206 | 67 | |
paul@206 | 68 | enum Aic_control_bits : unsigned |
paul@206 | 69 | { |
paul@206 | 70 | Aic_enable_tfifo_loop_overrun = 0x80000000, // ETFLOR |
paul@206 | 71 | Aic_enable_tfifo_loop_request = 0x40000000, // ETFLS |
paul@206 | 72 | Aic_packed_data = 0x10000000, // PACK16 |
paul@206 | 73 | |
paul@206 | 74 | Aic_channel_number_mask = 0x07000000, // CHANNEL |
paul@206 | 75 | Aic_channel_mono = 0x00000000, |
paul@206 | 76 | Aic_channel_stereo = 0x01000000, |
paul@206 | 77 | |
paul@206 | 78 | Aic_enable_tfifo_loop = 0x00800000, // ETFL |
paul@206 | 79 | Aic_enable_tfifo_loop_dma = 0x00400000, // TLDMS |
paul@206 | 80 | |
paul@206 | 81 | Aic_output_size_mask = 0x00380000, // OSS |
paul@206 | 82 | Aic_output_size_8bit = 0x00000000, // 0 |
paul@206 | 83 | Aic_output_size_16bit = 0x00080000, // 1 |
paul@206 | 84 | Aic_output_size_18bit = 0x00100000, // 2 |
paul@206 | 85 | Aic_output_size_20bit = 0x00180000, // 3 |
paul@206 | 86 | Aic_output_size_24bit = 0x00200000, // 4 |
paul@206 | 87 | |
paul@206 | 88 | Aic_input_size_mask = 0x00070000, // ISS |
paul@206 | 89 | Aic_input_size_8bit = 0x00000000, // 0 |
paul@206 | 90 | Aic_input_size_16bit = 0x00010000, // 1 |
paul@206 | 91 | Aic_input_size_18bit = 0x00020000, // 2 |
paul@206 | 92 | Aic_input_size_20bit = 0x00030000, // 3 |
paul@206 | 93 | Aic_input_size_24bit = 0x00040000, // 4 |
paul@206 | 94 | |
paul@206 | 95 | Aic_enable_recv_dma = 0x00008000, // RDMS |
paul@206 | 96 | Aic_enable_trans_dma = 0x00004000, // TDMS |
paul@206 | 97 | |
paul@206 | 98 | Aic_mono_control_mask = 0x00003000, // MONOCTR |
paul@206 | 99 | Aic_mono_control_both = 0x00000000, // 0 |
paul@206 | 100 | Aic_mono_control_right = 0x00001000, // 1 |
paul@206 | 101 | Aic_mono_control_left = 0x00002000, // 2 |
paul@206 | 102 | |
paul@206 | 103 | Aic_trans_byte_swap = 0x00000400, // ENDSW |
paul@206 | 104 | Aic_tfifo_flush = 0x00000100, // TFLUSH |
paul@206 | 105 | Aic_rfifo_flush = 0x00000080, // RFLUSH |
paul@206 | 106 | Aic_enable_rfifo_overrun = 0x00000040, // EROR |
paul@206 | 107 | Aic_enable_tfifo_underrun = 0x00000020, // ETUR |
paul@206 | 108 | Aic_enable_rfifo_request = 0x00000010, // ERFS |
paul@206 | 109 | Aic_enable_tfifo_request = 0x00000008, // ETFS |
paul@206 | 110 | Aic_enable_loopback = 0x00000004, // ENLBF |
paul@206 | 111 | Aic_enable_playback = 0x00000002, // ERPL |
paul@206 | 112 | Aic_enable_record = 0x00000001, // EREC |
paul@206 | 113 | }; |
paul@206 | 114 | |
paul@206 | 115 | enum Aic_i2s_msb_control_bits : unsigned |
paul@206 | 116 | { |
paul@206 | 117 | Aic_i2s_msb_right_first = 0x20000, // RFIRST |
paul@206 | 118 | Aic_i2s_msb_switch_lr = 0x10000, // SWLH |
paul@206 | 119 | Aic_select_msb_justified = 0x00001, // AMSL |
paul@206 | 120 | Aic_select_i2s = 0x00000, // AMSL |
paul@206 | 121 | }; |
paul@206 | 122 | |
paul@206 | 123 | enum Aic_fifo_status_bits : unsigned |
paul@206 | 124 | { |
paul@206 | 125 | Aic_rfifo_overrun = 0x40, // ROR |
paul@206 | 126 | Aic_tfifo_underrun = 0x20, // TUR |
paul@206 | 127 | Aic_rfifo_request = 0x10, // RFS |
paul@206 | 128 | Aic_tfifo_request = 0x08, // TFS |
paul@206 | 129 | Aic_tfifo_loop_overrun = 0x04, // TFLOR |
paul@206 | 130 | Aic_tfifo_loop_request = 0x02, // TFLS |
paul@220 | 131 | }; |
paul@206 | 132 | |
paul@220 | 133 | enum Aic_fifo_status_shifts : unsigned |
paul@220 | 134 | { |
paul@220 | 135 | Aic_rfifo_level_shift = 24, // RFL |
paul@220 | 136 | Aic_tfifo_loop_level_shift = 15, // TFLL |
paul@220 | 137 | Aic_tfifo_level_shift = 8, // TFL |
paul@206 | 138 | }; |
paul@206 | 139 | |
paul@206 | 140 | enum Aic_i2s_msb_status_bits : unsigned |
paul@206 | 141 | { |
paul@206 | 142 | Aic_trans_channel_busy = 0x20, // CHBSY |
paul@206 | 143 | Aic_trans_busy = 0x10, // TBSY |
paul@206 | 144 | Aic_recv_busy = 0x08, // RBSY |
paul@206 | 145 | Aic_busy = 0x04, // BSY |
paul@206 | 146 | }; |
paul@206 | 147 | |
paul@206 | 148 | enum Aic_i2s_msb_divider_bits : unsigned |
paul@206 | 149 | { |
paul@206 | 150 | Aic_recv_divider_mask = 0x1ff0000, // RDIV |
paul@206 | 151 | Aic_trans_divider_mask = 0x00001ff, // TDIV |
paul@220 | 152 | }; |
paul@206 | 153 | |
paul@220 | 154 | enum Aic_i2s_msb_divider_shifts : unsigned |
paul@220 | 155 | { |
paul@220 | 156 | Aic_recv_divider_shift = 16, // RDIV |
paul@220 | 157 | Aic_trans_divider_shift = 0, // TDIV |
paul@206 | 158 | }; |
paul@206 | 159 | |
paul@206 | 160 | enum Aic_i2s_msb_divider_limits : unsigned |
paul@206 | 161 | { |
paul@206 | 162 | Aic_recv_divider_limit = 0x1ff, // RDIV |
paul@206 | 163 | Aic_trans_divider_limit = 0x1ff, // TDIV |
paul@206 | 164 | }; |
paul@206 | 165 | |
paul@206 | 166 | enum Aic_fifo_data_limits : unsigned |
paul@206 | 167 | { |
paul@206 | 168 | Aic_fifo_data_limit = 0xffffff, // DATA |
paul@206 | 169 | }; |
paul@206 | 170 | |
paul@206 | 171 | enum Aic_loop_data_limits : unsigned |
paul@206 | 172 | { |
paul@206 | 173 | Aic_loop_data_limit = 0xffffff, // DATALP |
paul@206 | 174 | }; |
paul@206 | 175 | |
paul@206 | 176 | enum Aic_tfifo_loop_limits : unsigned |
paul@206 | 177 | { |
paul@206 | 178 | Aic_tfifo_loop_limit = 0xf, // TFLTH |
paul@206 | 179 | }; |
paul@206 | 180 | |
paul@206 | 181 | |
paul@206 | 182 | |
paul@220 | 183 | /* Initialise a channel. */ |
paul@206 | 184 | |
paul@206 | 185 | Aic_x1600_channel::Aic_x1600_channel(l4_addr_t aic_start, l4_addr_t start, |
paul@206 | 186 | enum Clock_identifiers clock_rx, |
paul@206 | 187 | enum Clock_identifiers clock_tx, |
paul@206 | 188 | Cpm_x1600_chip *cpm, |
paul@206 | 189 | Dma_x1600_channel *dma) |
paul@206 | 190 | : _aic_start(aic_start), _clock_rx(clock_rx), _clock_tx(clock_tx), _cpm(cpm), _dma(dma) |
paul@206 | 191 | { |
paul@206 | 192 | _regs = new Hw::Mmio_register_block<32>(start); |
paul@206 | 193 | _cpm->start_clock(clock_rx); |
paul@206 | 194 | _cpm->start_clock(clock_tx); |
paul@206 | 195 | config(); |
paul@206 | 196 | } |
paul@206 | 197 | |
paul@206 | 198 | /* |
paul@206 | 199 | I2S configuration. |
paul@206 | 200 | |
paul@206 | 201 | The system clock (SYS_CLK) for I2S in the X1600 is issued by the X1600 as the |
paul@206 | 202 | master/system clock (MCLK) externally to the DAC/codec. |
paul@206 | 203 | |
paul@206 | 204 | SYS_CLK is divided to obtain BIT_CLK which is issued by the X1600 as BCLK. |
paul@206 | 205 | This is dependent on the actual sample rate. |
paul@206 | 206 | |
paul@206 | 207 | LRCLK indicates the left/right channel for the issued data. |
paul@206 | 208 | |
paul@206 | 209 | Where clocks (MCLK, BCLK, LRCLK) are issued only by the X1600, share mode |
paul@206 | 210 | is used. Otherwise, independent (6-line) mode is used. |
paul@206 | 211 | |
paul@302 | 212 | To drive the MAX98357A, no MCLK is needed. |
paul@206 | 213 | |
paul@206 | 214 | Initialisation involves the following: |
paul@206 | 215 | |
paul@206 | 216 | - Configure MCLK, BCLK, LRCLK as outputs |
paul@206 | 217 | - Select I2S in Aic_i2s_msb_control (deselecting Aic_select_msb_justified) |
paul@206 | 218 | - Set master mode in Aic_config (Aic_tmaster, also Aic_rmaster if independent |
paul@206 | 219 | mode is used) |
paul@206 | 220 | - Set the dividers in Aic_i2s_msb_divider for BCLK using the configured I2S |
paul@206 | 221 | clock frequency |
paul@206 | 222 | - Perform a reset by writing to Aic_reset in Aic_config, if necessary |
paul@302 | 223 | - The MAX98357A may not need any configuration using I2C or some other bus |
paul@206 | 224 | */ |
paul@206 | 225 | |
paul@206 | 226 | void |
paul@206 | 227 | Aic_x1600_channel::config() |
paul@206 | 228 | { |
paul@206 | 229 | // NOTE: Setting transmit request threshold to 31 (15 * 2 + 1). |
paul@206 | 230 | |
paul@206 | 231 | _regs[Aic_config] = Aic_shared_clock | Aic_select_i2s_msb | Aic_reset | |
paul@220 | 232 | Aic_tmaster | Aic_enable | (15 << Aic_tfifo_thold_shift); |
paul@206 | 233 | |
paul@206 | 234 | _regs[Aic_i2s_msb_control] = Aic_select_i2s; |
paul@206 | 235 | } |
paul@206 | 236 | |
paul@206 | 237 | /* |
paul@206 | 238 | Clock configuration: |
paul@206 | 239 | |
paul@206 | 240 | - SYS_CLK (MCLK) is Clock_i2s0_tx (or Clock_i2s0_rx) |
paul@206 | 241 | - BIT_CLK (BCLK) is MCLK divided by the appropriate AIC/I2S divider |
paul@206 | 242 | - BCLK should be 64 times the sample rate according to the manual |
paul@206 | 243 | |
paul@206 | 244 | This suggests that the X1600 always produces data for two 32-bit channels |
paul@206 | 245 | regardless of the input data characteristics. |
paul@206 | 246 | */ |
paul@206 | 247 | |
paul@206 | 248 | void |
paul@206 | 249 | Aic_x1600_channel::set_divider(uint32_t divider, uint32_t mask, uint32_t limit, |
paul@206 | 250 | int bit) |
paul@206 | 251 | { |
paul@206 | 252 | if (divider <= limit) |
paul@206 | 253 | _regs[Aic_i2s_msb_divider] = (_regs[Aic_i2s_msb_divider] & ~mask) | |
paul@206 | 254 | (divider << bit); |
paul@206 | 255 | } |
paul@206 | 256 | |
paul@206 | 257 | void |
paul@206 | 258 | Aic_x1600_channel::set_recv_frequency(uint32_t sample_rate) |
paul@206 | 259 | { |
paul@206 | 260 | set_divider(_cpm->get_frequency(_clock_rx) / (sample_rate * 32 * 2), |
paul@220 | 261 | Aic_recv_divider_mask, Aic_recv_divider_limit, Aic_recv_divider_shift); |
paul@206 | 262 | } |
paul@206 | 263 | |
paul@206 | 264 | void |
paul@206 | 265 | Aic_x1600_channel::set_trans_frequency(uint32_t sample_rate) |
paul@206 | 266 | { |
paul@206 | 267 | set_divider(_cpm->get_frequency(_clock_tx) / (sample_rate * 32 * 2), |
paul@220 | 268 | Aic_trans_divider_mask, Aic_trans_divider_limit, Aic_trans_divider_shift); |
paul@206 | 269 | } |
paul@206 | 270 | |
paul@206 | 271 | uint32_t |
paul@206 | 272 | Aic_x1600_channel::encode_input_size(uint8_t sample_size) |
paul@206 | 273 | { |
paul@206 | 274 | switch (sample_size) |
paul@206 | 275 | { |
paul@206 | 276 | case 16: |
paul@206 | 277 | return Aic_input_size_16bit; |
paul@206 | 278 | |
paul@206 | 279 | case 18: |
paul@206 | 280 | return Aic_input_size_18bit; |
paul@206 | 281 | |
paul@206 | 282 | case 20: |
paul@206 | 283 | return Aic_input_size_20bit; |
paul@206 | 284 | |
paul@206 | 285 | case 24: |
paul@206 | 286 | return Aic_input_size_24bit; |
paul@206 | 287 | |
paul@206 | 288 | default: |
paul@206 | 289 | return Aic_input_size_8bit; |
paul@206 | 290 | } |
paul@206 | 291 | } |
paul@206 | 292 | |
paul@206 | 293 | uint32_t |
paul@206 | 294 | Aic_x1600_channel::encode_output_size(uint8_t sample_size) |
paul@206 | 295 | { |
paul@206 | 296 | switch (sample_size) |
paul@206 | 297 | { |
paul@206 | 298 | case 16: |
paul@206 | 299 | return Aic_output_size_16bit; |
paul@206 | 300 | |
paul@206 | 301 | case 18: |
paul@206 | 302 | return Aic_output_size_18bit; |
paul@206 | 303 | |
paul@206 | 304 | case 20: |
paul@206 | 305 | return Aic_output_size_20bit; |
paul@206 | 306 | |
paul@206 | 307 | case 24: |
paul@206 | 308 | return Aic_output_size_24bit; |
paul@206 | 309 | |
paul@206 | 310 | default: |
paul@206 | 311 | return Aic_output_size_8bit; |
paul@206 | 312 | } |
paul@206 | 313 | } |
paul@206 | 314 | |
paul@220 | 315 | /* Transfer a sample using the given byte count (total sample size), sample rate |
paul@220 | 316 | (or frequency), sample unit size (or resolution, width). */ |
paul@206 | 317 | |
paul@220 | 318 | uint32_t |
paul@221 | 319 | Aic_x1600_channel::transfer(l4re_dma_space_dma_addr_t paddr, uint32_t count, |
paul@221 | 320 | uint32_t sample_rate, uint8_t sample_size) |
paul@206 | 321 | { |
paul@206 | 322 | /* To play a sample: |
paul@206 | 323 | |
paul@206 | 324 | - Configure the sample size using the Aic_output_size settings in Aic_control |
paul@302 | 325 | - The sample size will be 16- or 24-bit for the MAX98357A, with the X1600 not |
paul@206 | 326 | supporting 32-bit samples |
paul@206 | 327 | - Configure the number of channels in Aic_control (Aic_channel_mono or |
paul@206 | 328 | Aic_channel_stereo) |
paul@206 | 329 | - For 16-bit samples, select Aic_packed_data in Aic_control if appropriate, |
paul@206 | 330 | possibly not for the MAX983A |
paul@206 | 331 | - If two channels are used, select Aic_i2s_msb_right_first in |
paul@206 | 332 | Aic_i2s_msb_control if appropriate, as well as Aic_i2s_msb_switch_lr if |
paul@206 | 333 | switching the channels |
paul@206 | 334 | - Reconfigure the dividers if appropriate |
paul@206 | 335 | - For DMA, set Aic_enable_trans_dma in Aic_control and the transmit FIFO |
paul@206 | 336 | threshold value |
paul@206 | 337 | */ |
paul@206 | 338 | |
paul@206 | 339 | // NOTE: Introduce sample size. |
paul@206 | 340 | |
paul@206 | 341 | set_trans_frequency(sample_rate); |
paul@206 | 342 | |
paul@206 | 343 | /* NOTE: The MAX98357A might require stereo input data, but perhaps the |
paul@206 | 344 | peripheral can generate the appropriate LRCLK to make it accept mono |
paul@206 | 345 | data. */ |
paul@206 | 346 | |
paul@206 | 347 | _regs[Aic_control] = encode_output_size(sample_size) | |
paul@206 | 348 | Aic_channel_mono | |
paul@206 | 349 | Aic_enable_trans_dma | |
paul@206 | 350 | Aic_enable_playback; |
paul@206 | 351 | |
paul@220 | 352 | /* Transfer from the allocated region to the FIFO. Use an incrementing source |
paul@220 | 353 | address with source width, destination width and transfer unit reflecting |
paul@220 | 354 | the sample size, and with transfers initiated by an empty AIC transmit |
paul@220 | 355 | FIFO. */ |
paul@206 | 356 | |
paul@220 | 357 | uint32_t sample_unit = (sample_size == 8) ? 1 : (sample_size == 16) ? 2 : 4; |
paul@220 | 358 | uint32_t unit_count = count / sample_unit; |
paul@221 | 359 | uint32_t to_transfer = _dma->transfer(paddr, |
paul@220 | 360 | _aic_start + Aic_fifo_data, |
paul@220 | 361 | unit_count, |
paul@220 | 362 | true, |
paul@220 | 363 | false, |
paul@220 | 364 | sample_unit, |
paul@220 | 365 | sample_unit, |
paul@220 | 366 | sample_unit, |
paul@220 | 367 | Dma_request_aic_out); |
paul@206 | 368 | |
paul@220 | 369 | uint32_t transferred = 0; |
paul@206 | 370 | |
paul@206 | 371 | if (to_transfer) |
paul@206 | 372 | transferred = to_transfer ? (unit_count - _dma->wait()) * sample_unit : 0; |
paul@206 | 373 | |
paul@206 | 374 | #if 0 |
paul@206 | 375 | if (transferred) |
paul@206 | 376 | while (_regs[Aic_fifo_status]); |
paul@206 | 377 | |
paul@206 | 378 | _regs[Aic_control] = _regs[Aic_control] & ~Aic_enable_playback; |
paul@206 | 379 | #endif |
paul@206 | 380 | |
paul@206 | 381 | return transferred; |
paul@206 | 382 | } |
paul@206 | 383 | |
paul@206 | 384 | |
paul@206 | 385 | |
paul@206 | 386 | // Initialise the AIC/I2S controller. |
paul@206 | 387 | |
paul@206 | 388 | Aic_x1600_chip::Aic_x1600_chip(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, |
paul@206 | 389 | Cpm_x1600_chip *cpm) |
paul@206 | 390 | : _aic_start(aic_start), _start(start), _end(end), _cpm(cpm) |
paul@206 | 391 | { |
paul@206 | 392 | } |
paul@206 | 393 | |
paul@206 | 394 | // Obtain a channel object. |
paul@206 | 395 | |
paul@206 | 396 | Aic_x1600_channel * |
paul@206 | 397 | Aic_x1600_chip::get_channel(uint8_t channel, Dma_x1600_channel *dma) |
paul@206 | 398 | { |
paul@206 | 399 | if (channel < 1) |
paul@206 | 400 | return new Aic_x1600_channel(_aic_start, _start, Clock_i2s0_rx, Clock_i2s0_tx, _cpm, dma); |
paul@206 | 401 | else |
paul@206 | 402 | throw -L4_EINVAL; |
paul@206 | 403 | } |
paul@206 | 404 | |
paul@206 | 405 | |
paul@206 | 406 | |
paul@206 | 407 | // C language interface functions. |
paul@206 | 408 | |
paul@206 | 409 | void *x1600_aic_init(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, void *cpm) |
paul@206 | 410 | { |
paul@206 | 411 | return (void *) new Aic_x1600_chip(aic_start, start, end, static_cast<Cpm_x1600_chip *>(cpm)); |
paul@206 | 412 | } |
paul@206 | 413 | |
paul@206 | 414 | void *x1600_aic_get_channel(void *aic, uint8_t channel, void *dma) |
paul@206 | 415 | { |
paul@206 | 416 | return static_cast<Aic_x1600_chip *>(aic)->get_channel(channel, |
paul@206 | 417 | static_cast<Dma_x1600_channel *>(dma)); |
paul@206 | 418 | } |
paul@206 | 419 | |
paul@221 | 420 | uint32_t x1600_aic_transfer(void *channel, l4re_dma_space_dma_addr_t paddr, |
paul@221 | 421 | uint32_t count, uint32_t sample_rate, |
paul@221 | 422 | uint8_t sample_size) |
paul@206 | 423 | { |
paul@221 | 424 | return static_cast<Aic_x1600_channel *>(channel)->transfer(paddr, count, |
paul@221 | 425 | sample_rate, sample_size); |
paul@206 | 426 | } |