5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/pkg/devices/lib/aic/include/aic-x1600.h Tue Oct 24 17:34:51 2023 +0200
5.3 @@ -0,0 +1,106 @@
5.4 +/*
5.5 + * AIC support for the X1600.
5.6 + *
5.7 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software; you can redistribute it and/or
5.10 + * modify it under the terms of the GNU General Public License as
5.11 + * published by the Free Software Foundation; either version 2 of
5.12 + * the License, or (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program; if not, write to the Free Software
5.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
5.22 + * Boston, MA 02110-1301, USA
5.23 + */
5.24 +
5.25 +#pragma once
5.26 +
5.27 +#include <l4/re/c/dma_space.h>
5.28 +#include <l4/sys/types.h>
5.29 +#include <stdint.h>
5.30 +
5.31 +
5.32 +
5.33 +#ifdef __cplusplus
5.34 +
5.35 +#include <l4/devices/cpm-x1600.h>
5.36 +#include <l4/devices/dma-x1600.h>
5.37 +#include <l4/devices/hw_mmio_register_block.h>
5.38 +
5.39 +// AIC channel.
5.40 +
5.41 +class Aic_x1600_channel
5.42 +{
5.43 +private:
5.44 + l4_addr_t _aic_start;
5.45 + Hw::Register_block<32> _regs;
5.46 + enum Clock_identifiers _clock_rx, _clock_tx;
5.47 + Cpm_x1600_chip *_cpm;
5.48 + Dma_x1600_channel *_dma;
5.49 +
5.50 + // Buffer management.
5.51 +
5.52 + unsigned int _size = 0;
5.53 + l4_addr_t _vaddr = 0;
5.54 + l4re_dma_space_dma_addr_t _paddr = 0;
5.55 + l4_cap_idx_t _mem = L4_INVALID_CAP;
5.56 +
5.57 +public:
5.58 + Aic_x1600_channel(l4_addr_t aic_start, l4_addr_t start,
5.59 + enum Clock_identifiers clock_rx,
5.60 + enum Clock_identifiers clock_tx,
5.61 + Cpm_x1600_chip *cpm,
5.62 + Dma_x1600_channel *dma);
5.63 +
5.64 + long get_buffer(uint32_t count, l4_addr_t *addr);
5.65 + unsigned int transfer(uint32_t count, uint32_t sample_rate, uint8_t sample_size);
5.66 +
5.67 +private:
5.68 + void disable();
5.69 + void enable();
5.70 +
5.71 + void config();
5.72 + uint32_t encode_input_size(uint8_t sample_size);
5.73 + uint32_t encode_output_size(uint8_t sample_size);
5.74 + void set_divider(uint32_t divider, uint32_t mask, uint32_t limit, int bit);
5.75 + void set_recv_frequency(uint32_t sample_rate);
5.76 + void set_trans_frequency(uint32_t sample_rate);
5.77 +};
5.78 +
5.79 +// AIC device control.
5.80 +
5.81 +class Aic_x1600_chip
5.82 +{
5.83 +private:
5.84 + l4_addr_t _aic_start, _start, _end;
5.85 + Cpm_x1600_chip *_cpm;
5.86 +
5.87 +public:
5.88 + Aic_x1600_chip(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, Cpm_x1600_chip *cpm);
5.89 +
5.90 + Aic_x1600_channel *get_channel(uint8_t channel, Dma_x1600_channel *dma);
5.91 +};
5.92 +
5.93 +#endif /* __cplusplus */
5.94 +
5.95 +
5.96 +
5.97 +/* C language interface. */
5.98 +
5.99 +EXTERN_C_BEGIN
5.100 +
5.101 +void *x1600_aic_init(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, void *cpm);
5.102 +
5.103 +void *x1600_aic_get_channel(void *aic, uint8_t channel, void *dma);
5.104 +
5.105 +long x1600_aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr);
5.106 +
5.107 +unsigned int x1600_aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size);
5.108 +
5.109 +EXTERN_C_END
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/pkg/devices/lib/aic/src/x1600.cc Tue Oct 24 17:34:51 2023 +0200
7.3 @@ -0,0 +1,466 @@
7.4 +/*
7.5 + * AIC support for the X1600.
7.6 + *
7.7 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
7.8 + *
7.9 + * This program is free software; you can redistribute it and/or
7.10 + * modify it under the terms of the GNU General Public License as
7.11 + * published by the Free Software Foundation; either version 2 of
7.12 + * the License, or (at your option) any later version.
7.13 + *
7.14 + * This program is distributed in the hope that it will be useful,
7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.17 + * GNU General Public License for more details.
7.18 + *
7.19 + * You should have received a copy of the GNU General Public License
7.20 + * along with this program; if not, write to the Free Software
7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
7.22 + * Boston, MA 02110-1301, USA
7.23 + */
7.24 +
7.25 +#include <l4/devices/aic-x1600.h>
7.26 +#include <l4/devices/dma.h>
7.27 +#include <l4/devices/hw_mmio_register_block.h>
7.28 +
7.29 +#include <l4/sys/icu.h>
7.30 +#include <l4/util/util.h>
7.31 +
7.32 +#include <stdio.h>
7.33 +
7.34 +enum Regs
7.35 +{
7.36 + Aic_config = 0x000, // AICFR
7.37 + Aic_control = 0x004, // AICCR
7.38 + Aic_i2s_msb_control = 0x010, // I2SCR
7.39 + Aic_fifo_status = 0x014, // AICSR
7.40 + Aic_i2s_msb_status = 0x01c, // I2SSR
7.41 + Aic_i2s_msb_divider = 0x030, // I2SDIV
7.42 + Aic_fifo_data = 0x034, // AICDR
7.43 + Aic_loop_data = 0x038, // AICLR
7.44 + Aic_tfifo_loop = 0x03c, // AICTFLR
7.45 +};
7.46 +
7.47 +enum Aic_config_bits : unsigned
7.48 +{
7.49 + Aic_enable_big_endian = 0x1000, // MSB
7.50 + Aic_independent_clock = 0x0100, // DMODE
7.51 + Aic_shared_clock = 0x0000, // DMODE
7.52 + Aic_last_sample_uflow = 0x0040, // LSMP
7.53 + Aic_select_i2s_msb = 0x0010, // AUSEL
7.54 + Aic_reset = 0x0008, // RST
7.55 + Aic_tmaster = 0x0004, // TMASTER
7.56 + Aic_rmaster = 0x0002, // RMASTER
7.57 + Aic_enable = 0x0001, // ENB
7.58 +
7.59 + Aic_rfifo_thold_bit = 24, // RFTH
7.60 + Aic_tfifo_thold_bit = 16, // TFTH
7.61 +};
7.62 +
7.63 +enum Aic_fifo_limits : unsigned
7.64 +{
7.65 + Aic_rfifo_max = 15,
7.66 + Aic_tfifo_max = 31,
7.67 +};
7.68 +
7.69 +enum Aic_control_bits : unsigned
7.70 +{
7.71 + Aic_enable_tfifo_loop_overrun = 0x80000000, // ETFLOR
7.72 + Aic_enable_tfifo_loop_request = 0x40000000, // ETFLS
7.73 + Aic_packed_data = 0x10000000, // PACK16
7.74 +
7.75 + Aic_channel_number_mask = 0x07000000, // CHANNEL
7.76 + Aic_channel_mono = 0x00000000,
7.77 + Aic_channel_stereo = 0x01000000,
7.78 +
7.79 + Aic_enable_tfifo_loop = 0x00800000, // ETFL
7.80 + Aic_enable_tfifo_loop_dma = 0x00400000, // TLDMS
7.81 +
7.82 + Aic_output_size_mask = 0x00380000, // OSS
7.83 + Aic_output_size_8bit = 0x00000000, // 0
7.84 + Aic_output_size_16bit = 0x00080000, // 1
7.85 + Aic_output_size_18bit = 0x00100000, // 2
7.86 + Aic_output_size_20bit = 0x00180000, // 3
7.87 + Aic_output_size_24bit = 0x00200000, // 4
7.88 +
7.89 + Aic_input_size_mask = 0x00070000, // ISS
7.90 + Aic_input_size_8bit = 0x00000000, // 0
7.91 + Aic_input_size_16bit = 0x00010000, // 1
7.92 + Aic_input_size_18bit = 0x00020000, // 2
7.93 + Aic_input_size_20bit = 0x00030000, // 3
7.94 + Aic_input_size_24bit = 0x00040000, // 4
7.95 +
7.96 + Aic_enable_recv_dma = 0x00008000, // RDMS
7.97 + Aic_enable_trans_dma = 0x00004000, // TDMS
7.98 +
7.99 + Aic_mono_control_mask = 0x00003000, // MONOCTR
7.100 + Aic_mono_control_both = 0x00000000, // 0
7.101 + Aic_mono_control_right = 0x00001000, // 1
7.102 + Aic_mono_control_left = 0x00002000, // 2
7.103 +
7.104 + Aic_trans_byte_swap = 0x00000400, // ENDSW
7.105 + Aic_tfifo_flush = 0x00000100, // TFLUSH
7.106 + Aic_rfifo_flush = 0x00000080, // RFLUSH
7.107 + Aic_enable_rfifo_overrun = 0x00000040, // EROR
7.108 + Aic_enable_tfifo_underrun = 0x00000020, // ETUR
7.109 + Aic_enable_rfifo_request = 0x00000010, // ERFS
7.110 + Aic_enable_tfifo_request = 0x00000008, // ETFS
7.111 + Aic_enable_loopback = 0x00000004, // ENLBF
7.112 + Aic_enable_playback = 0x00000002, // ERPL
7.113 + Aic_enable_record = 0x00000001, // EREC
7.114 +};
7.115 +
7.116 +enum Aic_i2s_msb_control_bits : unsigned
7.117 +{
7.118 + Aic_i2s_msb_right_first = 0x20000, // RFIRST
7.119 + Aic_i2s_msb_switch_lr = 0x10000, // SWLH
7.120 + Aic_select_msb_justified = 0x00001, // AMSL
7.121 + Aic_select_i2s = 0x00000, // AMSL
7.122 +};
7.123 +
7.124 +enum Aic_fifo_status_bits : unsigned
7.125 +{
7.126 + Aic_rfifo_overrun = 0x40, // ROR
7.127 + Aic_tfifo_underrun = 0x20, // TUR
7.128 + Aic_rfifo_request = 0x10, // RFS
7.129 + Aic_tfifo_request = 0x08, // TFS
7.130 + Aic_tfifo_loop_overrun = 0x04, // TFLOR
7.131 + Aic_tfifo_loop_request = 0x02, // TFLS
7.132 +
7.133 + Aic_rfifo_level_bit = 24, // RFL
7.134 + Aic_tfifo_loop_level_bit = 15, // TFLL
7.135 + Aic_tfifo_level_bit = 8, // TFL
7.136 +};
7.137 +
7.138 +enum Aic_i2s_msb_status_bits : unsigned
7.139 +{
7.140 + Aic_trans_channel_busy = 0x20, // CHBSY
7.141 + Aic_trans_busy = 0x10, // TBSY
7.142 + Aic_recv_busy = 0x08, // RBSY
7.143 + Aic_busy = 0x04, // BSY
7.144 +};
7.145 +
7.146 +enum Aic_i2s_msb_divider_bits : unsigned
7.147 +{
7.148 + Aic_recv_divider_mask = 0x1ff0000, // RDIV
7.149 + Aic_trans_divider_mask = 0x00001ff, // TDIV
7.150 +
7.151 + Aic_recv_divider_bit = 16, // RDIV
7.152 + Aic_trans_divider_bit = 0, // TDIV
7.153 +};
7.154 +
7.155 +enum Aic_i2s_msb_divider_limits : unsigned
7.156 +{
7.157 + Aic_recv_divider_limit = 0x1ff, // RDIV
7.158 + Aic_trans_divider_limit = 0x1ff, // TDIV
7.159 +};
7.160 +
7.161 +enum Aic_fifo_data_limits : unsigned
7.162 +{
7.163 + Aic_fifo_data_limit = 0xffffff, // DATA
7.164 +};
7.165 +
7.166 +enum Aic_loop_data_limits : unsigned
7.167 +{
7.168 + Aic_loop_data_limit = 0xffffff, // DATALP
7.169 +};
7.170 +
7.171 +enum Aic_tfifo_loop_limits : unsigned
7.172 +{
7.173 + Aic_tfifo_loop_limit = 0xf, // TFLTH
7.174 +};
7.175 +
7.176 +
7.177 +
7.178 +// Initialise a channel.
7.179 +
7.180 +Aic_x1600_channel::Aic_x1600_channel(l4_addr_t aic_start, l4_addr_t start,
7.181 + enum Clock_identifiers clock_rx,
7.182 + enum Clock_identifiers clock_tx,
7.183 + Cpm_x1600_chip *cpm,
7.184 + Dma_x1600_channel *dma)
7.185 +: _aic_start(aic_start), _clock_rx(clock_rx), _clock_tx(clock_tx), _cpm(cpm), _dma(dma)
7.186 +{
7.187 + _regs = new Hw::Mmio_register_block<32>(start);
7.188 + _cpm->start_clock(clock_rx);
7.189 + _cpm->start_clock(clock_tx);
7.190 + config();
7.191 +}
7.192 +
7.193 +/*
7.194 +I2S configuration.
7.195 +
7.196 +The system clock (SYS_CLK) for I2S in the X1600 is issued by the X1600 as the
7.197 +master/system clock (MCLK) externally to the DAC/codec.
7.198 +
7.199 +SYS_CLK is divided to obtain BIT_CLK which is issued by the X1600 as BCLK.
7.200 +This is dependent on the actual sample rate.
7.201 +
7.202 +LRCLK indicates the left/right channel for the issued data.
7.203 +
7.204 +Where clocks (MCLK, BCLK, LRCLK) are issued only by the X1600, share mode
7.205 +is used. Otherwise, independent (6-line) mode is used.
7.206 +
7.207 +To drive the MAX9835A, no MCLK is needed.
7.208 +
7.209 +Initialisation involves the following:
7.210 +
7.211 +- Configure MCLK, BCLK, LRCLK as outputs
7.212 +- Select I2S in Aic_i2s_msb_control (deselecting Aic_select_msb_justified)
7.213 +- Set master mode in Aic_config (Aic_tmaster, also Aic_rmaster if independent
7.214 + mode is used)
7.215 +- Set the dividers in Aic_i2s_msb_divider for BCLK using the configured I2S
7.216 + clock frequency
7.217 +- Perform a reset by writing to Aic_reset in Aic_config, if necessary
7.218 +- The MAX9835A may not need any configuration using I2C or some other bus
7.219 +*/
7.220 +
7.221 +void
7.222 +Aic_x1600_channel::config()
7.223 +{
7.224 + // NOTE: Setting transmit request threshold to 31 (15 * 2 + 1).
7.225 +
7.226 + printf("config = %08x\n", (uint32_t) _regs[Aic_config]);
7.227 +
7.228 + _regs[Aic_config] = Aic_shared_clock | Aic_select_i2s_msb | Aic_reset |
7.229 + Aic_tmaster | Aic_enable | (15 << Aic_tfifo_thold_bit);
7.230 +
7.231 + _regs[Aic_i2s_msb_control] = Aic_select_i2s;
7.232 +
7.233 + printf("config = %08x\n", (uint32_t) _regs[Aic_config]);
7.234 +}
7.235 +
7.236 +/*
7.237 +Clock configuration:
7.238 +
7.239 +- SYS_CLK (MCLK) is Clock_i2s0_tx (or Clock_i2s0_rx)
7.240 +- BIT_CLK (BCLK) is MCLK divided by the appropriate AIC/I2S divider
7.241 +- BCLK should be 64 times the sample rate according to the manual
7.242 +
7.243 +This suggests that the X1600 always produces data for two 32-bit channels
7.244 +regardless of the input data characteristics.
7.245 +*/
7.246 +
7.247 +void
7.248 +Aic_x1600_channel::set_divider(uint32_t divider, uint32_t mask, uint32_t limit,
7.249 + int bit)
7.250 +{
7.251 + if (divider <= limit)
7.252 + _regs[Aic_i2s_msb_divider] = (_regs[Aic_i2s_msb_divider] & ~mask) |
7.253 + (divider << bit);
7.254 +}
7.255 +
7.256 +void
7.257 +Aic_x1600_channel::set_recv_frequency(uint32_t sample_rate)
7.258 +{
7.259 + set_divider(_cpm->get_frequency(_clock_rx) / (sample_rate * 32 * 2),
7.260 + Aic_recv_divider_mask, Aic_recv_divider_limit, Aic_recv_divider_bit);
7.261 +}
7.262 +
7.263 +void
7.264 +Aic_x1600_channel::set_trans_frequency(uint32_t sample_rate)
7.265 +{
7.266 + printf("tx %d / (freq %d * %d * 2) = %d vs. %d\n", _cpm->get_frequency(_clock_tx),
7.267 + sample_rate, 32,
7.268 + _cpm->get_frequency(_clock_tx) / (sample_rate * 32 * 2),
7.269 + Aic_trans_divider_limit);
7.270 +
7.271 + set_divider(_cpm->get_frequency(_clock_tx) / (sample_rate * 32 * 2),
7.272 + Aic_trans_divider_mask, Aic_trans_divider_limit, Aic_trans_divider_bit);
7.273 +}
7.274 +
7.275 +uint32_t
7.276 +Aic_x1600_channel::encode_input_size(uint8_t sample_size)
7.277 +{
7.278 + switch (sample_size)
7.279 + {
7.280 + case 16:
7.281 + return Aic_input_size_16bit;
7.282 +
7.283 + case 18:
7.284 + return Aic_input_size_18bit;
7.285 +
7.286 + case 20:
7.287 + return Aic_input_size_20bit;
7.288 +
7.289 + case 24:
7.290 + return Aic_input_size_24bit;
7.291 +
7.292 + default:
7.293 + return Aic_input_size_8bit;
7.294 + }
7.295 +}
7.296 +
7.297 +uint32_t
7.298 +Aic_x1600_channel::encode_output_size(uint8_t sample_size)
7.299 +{
7.300 + switch (sample_size)
7.301 + {
7.302 + case 16:
7.303 + return Aic_output_size_16bit;
7.304 +
7.305 + case 18:
7.306 + return Aic_output_size_18bit;
7.307 +
7.308 + case 20:
7.309 + return Aic_output_size_20bit;
7.310 +
7.311 + case 24:
7.312 + return Aic_output_size_24bit;
7.313 +
7.314 + default:
7.315 + return Aic_output_size_8bit;
7.316 + }
7.317 +}
7.318 +
7.319 +// Obtain a DMA-accessible buffer for sample transfers.
7.320 +
7.321 +long
7.322 +Aic_x1600_channel::get_buffer(uint32_t count, l4_addr_t *addr)
7.323 +{
7.324 + printf("get_buffer(%d)\n", count);
7.325 + long err = get_dma_region(count, 8, &_vaddr, &_paddr, &_mem);
7.326 +
7.327 + if (err)
7.328 + return err;
7.329 +
7.330 + // Set the region size as the requested size, not any allocated size.
7.331 +
7.332 + _size = count;
7.333 + *addr = _vaddr;
7.334 + printf("size = %d\n", _size);
7.335 + return L4_EOK;
7.336 +}
7.337 +
7.338 +// Transfer a sample using the given byte count (total sample size), sample rate
7.339 +// (or frequency), sample unit size (or resolution, width).
7.340 +
7.341 +unsigned int
7.342 +Aic_x1600_channel::transfer(uint32_t count, uint32_t sample_rate, uint8_t sample_size)
7.343 +{
7.344 + printf("transfer(%d, %d, %d)\n", count, sample_rate, sample_size);
7.345 +
7.346 + if (count > _size)
7.347 + return 0;
7.348 +
7.349 + /* To play a sample:
7.350 +
7.351 + - Configure the sample size using the Aic_output_size settings in Aic_control
7.352 + - The sample size will be 16- or 24-bit for the MAX9835A, with the X1600 not
7.353 + supporting 32-bit samples
7.354 + - Configure the number of channels in Aic_control (Aic_channel_mono or
7.355 + Aic_channel_stereo)
7.356 + - For 16-bit samples, select Aic_packed_data in Aic_control if appropriate,
7.357 + possibly not for the MAX983A
7.358 + - If two channels are used, select Aic_i2s_msb_right_first in
7.359 + Aic_i2s_msb_control if appropriate, as well as Aic_i2s_msb_switch_lr if
7.360 + switching the channels
7.361 + - Reconfigure the dividers if appropriate
7.362 + - For DMA, set Aic_enable_trans_dma in Aic_control and the transmit FIFO
7.363 + threshold value
7.364 + */
7.365 +
7.366 + // NOTE: Introduce sample size.
7.367 +
7.368 + set_trans_frequency(sample_rate);
7.369 +
7.370 + /* NOTE: The MAX98357A might require stereo input data, but perhaps the
7.371 + peripheral can generate the appropriate LRCLK to make it accept mono
7.372 + data. */
7.373 +
7.374 + _regs[Aic_control] = encode_output_size(sample_size) |
7.375 + Aic_channel_mono |
7.376 + Aic_enable_trans_dma |
7.377 + Aic_enable_playback;
7.378 +
7.379 + printf("control = %08x\n", (uint32_t) _regs[Aic_control]);
7.380 + printf("config = %08x\n", (uint32_t) _regs[Aic_config]);
7.381 + printf("divider = %d\n", (uint32_t) _regs[Aic_i2s_msb_divider]);
7.382 + printf("status = %08x\n", (uint32_t) _regs[Aic_i2s_msb_status]);
7.383 + printf("fifo = %08x\n", (uint32_t) _regs[Aic_fifo_status]);
7.384 +
7.385 + // Transfer from the allocated region to the FIFO. Use an incrementing source
7.386 + // address with source width, destination width and transfer unit reflecting
7.387 + // the sample size, and with transfers initiated by an empty AIC transmit
7.388 + // FIFO.
7.389 +
7.390 + printf("transfer from %llx to %lx\n", _paddr, _aic_start + Aic_fifo_data);
7.391 +
7.392 + unsigned int sample_unit = (sample_size == 8) ? 1 :
7.393 + (sample_size == 16) ? 2 :
7.394 + 4;
7.395 + unsigned int unit_count = count / sample_unit;
7.396 +
7.397 + unsigned int to_transfer = _dma->transfer(_paddr,
7.398 + _aic_start + Aic_fifo_data,
7.399 + unit_count,
7.400 + true,
7.401 + false,
7.402 + sample_unit,
7.403 + sample_unit,
7.404 + sample_unit,
7.405 + Dma_request_aic_out);
7.406 +
7.407 + printf("status = %08x\n", (uint32_t) _regs[Aic_i2s_msb_status]);
7.408 + printf("fifo = %08x\n", (uint32_t) _regs[Aic_fifo_status]);
7.409 +
7.410 + unsigned int transferred = 0;
7.411 +
7.412 + if (to_transfer)
7.413 + transferred = to_transfer ? (unit_count - _dma->wait()) * sample_unit : 0;
7.414 +
7.415 +#if 0
7.416 + if (transferred)
7.417 + while (_regs[Aic_fifo_status]);
7.418 +
7.419 + _regs[Aic_control] = _regs[Aic_control] & ~Aic_enable_playback;
7.420 +#endif
7.421 +
7.422 + return transferred;
7.423 +}
7.424 +
7.425 +
7.426 +
7.427 +// Initialise the AIC/I2S controller.
7.428 +
7.429 +Aic_x1600_chip::Aic_x1600_chip(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end,
7.430 + Cpm_x1600_chip *cpm)
7.431 +: _aic_start(aic_start), _start(start), _end(end), _cpm(cpm)
7.432 +{
7.433 +}
7.434 +
7.435 +// Obtain a channel object.
7.436 +
7.437 +Aic_x1600_channel *
7.438 +Aic_x1600_chip::get_channel(uint8_t channel, Dma_x1600_channel *dma)
7.439 +{
7.440 + if (channel < 1)
7.441 + return new Aic_x1600_channel(_aic_start, _start, Clock_i2s0_rx, Clock_i2s0_tx, _cpm, dma);
7.442 + else
7.443 + throw -L4_EINVAL;
7.444 +}
7.445 +
7.446 +
7.447 +
7.448 +// C language interface functions.
7.449 +
7.450 +void *x1600_aic_init(l4_addr_t aic_start, l4_addr_t start, l4_addr_t end, void *cpm)
7.451 +{
7.452 + return (void *) new Aic_x1600_chip(aic_start, start, end, static_cast<Cpm_x1600_chip *>(cpm));
7.453 +}
7.454 +
7.455 +void *x1600_aic_get_channel(void *aic, uint8_t channel, void *dma)
7.456 +{
7.457 + return static_cast<Aic_x1600_chip *>(aic)->get_channel(channel,
7.458 + static_cast<Dma_x1600_channel *>(dma));
7.459 +}
7.460 +
7.461 +long x1600_aic_get_buffer(void *channel, uint32_t count, l4_addr_t *addr)
7.462 +{
7.463 + return static_cast<Aic_x1600_channel *>(channel)->get_buffer(count, addr);
7.464 +}
7.465 +
7.466 +unsigned int x1600_aic_transfer(void *channel, uint32_t count, uint32_t sample_rate, uint8_t sample_size)
7.467 +{
7.468 + return static_cast<Aic_x1600_channel *>(channel)->transfer(count, sample_rate, sample_size);
7.469 +}