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