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