1 /* 2 * Arm PrimeCell PL041 Advanced Audio Codec Interface 3 * 4 * Copyright (c) 2011 5 * Written by Mathieu Sonet - www.elasticsheep.com 6 * 7 * This code is licensed under the GPL. 8 * 9 * ***************************************************************** 10 * 11 * This driver emulates the ARM AACI interface 12 * connected to a LM4549 codec. 13 * 14 * Limitations: 15 * - Supports only a playback on one channel (Versatile/Vexpress) 16 * - Supports only one TX FIFO in compact-mode or non-compact mode. 17 * - Supports playback of 12, 16, 18 and 20 bits samples. 18 * - Record is not supported. 19 * - The PL041 is hardwired to a LM4549 codec. 20 * 21 */ 22 23 #include "qemu/osdep.h" 24 #include "hw/irq.h" 25 #include "hw/qdev-properties.h" 26 #include "hw/sysbus.h" 27 #include "qemu/log.h" 28 #include "qemu/module.h" 29 30 #include "pl041.h" 31 #include "lm4549.h" 32 #include "migration/vmstate.h" 33 #include "qom/object.h" 34 35 #if 0 36 #define PL041_DEBUG_LEVEL 1 37 #endif 38 39 #if defined(PL041_DEBUG_LEVEL) && (PL041_DEBUG_LEVEL >= 1) 40 #define DBG_L1(fmt, ...) \ 41 do { printf("pl041: " fmt , ## __VA_ARGS__); } while (0) 42 #else 43 #define DBG_L1(fmt, ...) \ 44 do { } while (0) 45 #endif 46 47 #if defined(PL041_DEBUG_LEVEL) && (PL041_DEBUG_LEVEL >= 2) 48 #define DBG_L2(fmt, ...) \ 49 do { printf("pl041: " fmt , ## __VA_ARGS__); } while (0) 50 #else 51 #define DBG_L2(fmt, ...) \ 52 do { } while (0) 53 #endif 54 55 56 #define MAX_FIFO_DEPTH (1024) 57 #define DEFAULT_FIFO_DEPTH (8) 58 59 #define SLOT1_RW (1 << 19) 60 61 /* This FIFO only stores 20-bit samples on 32-bit words. 62 So its level is independent of the selected mode */ 63 typedef struct { 64 uint32_t level; 65 uint32_t data[MAX_FIFO_DEPTH]; 66 } pl041_fifo; 67 68 typedef struct { 69 pl041_fifo tx_fifo; 70 uint8_t tx_enabled; 71 uint8_t tx_compact_mode; 72 uint8_t tx_sample_size; 73 74 pl041_fifo rx_fifo; 75 uint8_t rx_enabled; 76 uint8_t rx_compact_mode; 77 uint8_t rx_sample_size; 78 } pl041_channel; 79 80 #define TYPE_PL041 "pl041" 81 typedef struct PL041State PL041State; 82 DECLARE_INSTANCE_CHECKER(PL041State, PL041, 83 TYPE_PL041) 84 85 struct PL041State { 86 SysBusDevice parent_obj; 87 88 MemoryRegion iomem; 89 qemu_irq irq; 90 91 uint32_t fifo_depth; /* FIFO depth in non-compact mode */ 92 93 pl041_regfile regs; 94 pl041_channel fifo1; 95 lm4549_state codec; 96 }; 97 98 99 static const unsigned char pl041_default_id[8] = { 100 0x41, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 101 }; 102 103 #if defined(PL041_DEBUG_LEVEL) 104 #define REGISTER(name, offset) #name, 105 static const char *pl041_regs_name[] = { 106 #include "pl041.hx" 107 }; 108 #undef REGISTER 109 #endif 110 111 112 #if defined(PL041_DEBUG_LEVEL) 113 static const char *get_reg_name(hwaddr offset) 114 { 115 if (offset <= PL041_dr1_7) { 116 return pl041_regs_name[offset >> 2]; 117 } 118 119 return "unknown"; 120 } 121 #endif 122 123 static uint8_t pl041_compute_periphid3(PL041State *s) 124 { 125 uint8_t id3 = 1; /* One channel */ 126 127 /* Add the fifo depth information */ 128 switch (s->fifo_depth) { 129 case 8: 130 id3 |= 0 << 3; 131 break; 132 case 32: 133 id3 |= 1 << 3; 134 break; 135 case 64: 136 id3 |= 2 << 3; 137 break; 138 case 128: 139 id3 |= 3 << 3; 140 break; 141 case 256: 142 id3 |= 4 << 3; 143 break; 144 case 512: 145 id3 |= 5 << 3; 146 break; 147 case 1024: 148 id3 |= 6 << 3; 149 break; 150 case 2048: 151 id3 |= 7 << 3; 152 break; 153 } 154 155 return id3; 156 } 157 158 static void pl041_reset(PL041State *s) 159 { 160 DBG_L1("pl041_reset\n"); 161 162 memset(&s->regs, 0x00, sizeof(pl041_regfile)); 163 164 s->regs.slfr = SL1TXEMPTY | SL2TXEMPTY | SL12TXEMPTY; 165 s->regs.sr1 = TXFE | RXFE | TXHE; 166 s->regs.isr1 = 0; 167 168 memset(&s->fifo1, 0x00, sizeof(s->fifo1)); 169 } 170 171 172 static void pl041_fifo1_write(PL041State *s, uint32_t value) 173 { 174 pl041_channel *channel = &s->fifo1; 175 pl041_fifo *fifo = &s->fifo1.tx_fifo; 176 177 /* Push the value in the FIFO */ 178 if (channel->tx_compact_mode == 0) { 179 /* Non-compact mode */ 180 181 if (fifo->level < s->fifo_depth) { 182 /* Pad the value with 0 to obtain a 20-bit sample */ 183 switch (channel->tx_sample_size) { 184 case 12: 185 value = (value << 8) & 0xFFFFF; 186 break; 187 case 16: 188 value = (value << 4) & 0xFFFFF; 189 break; 190 case 18: 191 value = (value << 2) & 0xFFFFF; 192 break; 193 case 20: 194 default: 195 break; 196 } 197 198 /* Store the sample in the FIFO */ 199 fifo->data[fifo->level++] = value; 200 } 201 #if defined(PL041_DEBUG_LEVEL) 202 else { 203 DBG_L1("fifo1 write: overrun\n"); 204 } 205 #endif 206 } else { 207 /* Compact mode */ 208 209 if ((fifo->level + 2) < s->fifo_depth) { 210 uint32_t i = 0; 211 uint32_t sample = 0; 212 213 for (i = 0; i < 2; i++) { 214 sample = value & 0xFFFF; 215 value = value >> 16; 216 217 /* Pad each sample with 0 to obtain a 20-bit sample */ 218 switch (channel->tx_sample_size) { 219 case 12: 220 sample = sample << 8; 221 break; 222 case 16: 223 default: 224 sample = sample << 4; 225 break; 226 } 227 228 /* Store the sample in the FIFO */ 229 fifo->data[fifo->level++] = sample; 230 } 231 } 232 #if defined(PL041_DEBUG_LEVEL) 233 else { 234 DBG_L1("fifo1 write: overrun\n"); 235 } 236 #endif 237 } 238 239 /* Update the status register */ 240 if (fifo->level > 0) { 241 s->regs.sr1 &= ~(TXUNDERRUN | TXFE); 242 } 243 244 if (fifo->level >= (s->fifo_depth / 2)) { 245 s->regs.sr1 &= ~TXHE; 246 } 247 248 if (fifo->level >= s->fifo_depth) { 249 s->regs.sr1 |= TXFF; 250 } 251 252 DBG_L2("fifo1_push sr1 = 0x%08x\n", s->regs.sr1); 253 } 254 255 static void pl041_fifo1_transmit(PL041State *s) 256 { 257 pl041_channel *channel = &s->fifo1; 258 pl041_fifo *fifo = &s->fifo1.tx_fifo; 259 uint32_t slots = s->regs.txcr1 & TXSLOT_MASK; 260 uint32_t written_samples; 261 262 /* Check if FIFO1 transmit is enabled */ 263 if ((channel->tx_enabled) && (slots & (TXSLOT3 | TXSLOT4))) { 264 if (fifo->level >= (s->fifo_depth / 2)) { 265 int i; 266 267 DBG_L1("Transfer FIFO level = %i\n", fifo->level); 268 269 /* Try to transfer the whole FIFO */ 270 for (i = 0; i < (fifo->level / 2); i++) { 271 uint32_t left = fifo->data[i * 2]; 272 uint32_t right = fifo->data[i * 2 + 1]; 273 274 /* Transmit two 20-bit samples to the codec */ 275 if (lm4549_write_samples(&s->codec, left, right) == 0) { 276 DBG_L1("Codec buffer full\n"); 277 break; 278 } 279 } 280 281 written_samples = i * 2; 282 if (written_samples > 0) { 283 /* Update the FIFO level */ 284 fifo->level -= written_samples; 285 286 /* Move back the pending samples to the start of the FIFO */ 287 for (i = 0; i < fifo->level; i++) { 288 fifo->data[i] = fifo->data[written_samples + i]; 289 } 290 291 /* Update the status register */ 292 s->regs.sr1 &= ~TXFF; 293 294 if (fifo->level <= (s->fifo_depth / 2)) { 295 s->regs.sr1 |= TXHE; 296 } 297 298 if (fifo->level == 0) { 299 s->regs.sr1 |= TXFE | TXUNDERRUN; 300 DBG_L1("Empty FIFO\n"); 301 } 302 } 303 } 304 } 305 } 306 307 static void pl041_isr1_update(PL041State *s) 308 { 309 /* Update ISR1 */ 310 if (s->regs.sr1 & TXUNDERRUN) { 311 s->regs.isr1 |= URINTR; 312 } else { 313 s->regs.isr1 &= ~URINTR; 314 } 315 316 if (s->regs.sr1 & TXHE) { 317 s->regs.isr1 |= TXINTR; 318 } else { 319 s->regs.isr1 &= ~TXINTR; 320 } 321 322 if (!(s->regs.sr1 & TXBUSY) && (s->regs.sr1 & TXFE)) { 323 s->regs.isr1 |= TXCINTR; 324 } else { 325 s->regs.isr1 &= ~TXCINTR; 326 } 327 328 /* Update the irq state */ 329 qemu_set_irq(s->irq, ((s->regs.isr1 & s->regs.ie1) > 0) ? 1 : 0); 330 DBG_L2("Set interrupt sr1 = 0x%08x isr1 = 0x%08x masked = 0x%08x\n", 331 s->regs.sr1, s->regs.isr1, s->regs.isr1 & s->regs.ie1); 332 } 333 334 static void pl041_request_data(void *opaque) 335 { 336 PL041State *s = (PL041State *)opaque; 337 338 /* Trigger pending transfers */ 339 pl041_fifo1_transmit(s); 340 pl041_isr1_update(s); 341 } 342 343 static uint64_t pl041_read(void *opaque, hwaddr offset, 344 unsigned size) 345 { 346 PL041State *s = (PL041State *)opaque; 347 int value; 348 349 if ((offset >= PL041_periphid0) && (offset <= PL041_pcellid3)) { 350 if (offset == PL041_periphid3) { 351 value = pl041_compute_periphid3(s); 352 } else { 353 value = pl041_default_id[(offset - PL041_periphid0) >> 2]; 354 } 355 356 DBG_L1("pl041_read [0x%08x] => 0x%08x\n", offset, value); 357 return value; 358 } else if (offset <= PL041_dr4_7) { 359 value = *((uint32_t *)&s->regs + (offset >> 2)); 360 } else { 361 DBG_L1("pl041_read: Reserved offset %x\n", (int)offset); 362 return 0; 363 } 364 365 switch (offset) { 366 case PL041_allints: 367 value = s->regs.isr1 & 0x7F; 368 break; 369 } 370 371 DBG_L1("pl041_read [0x%08x] %s => 0x%08x\n", offset, 372 get_reg_name(offset), value); 373 374 return value; 375 } 376 377 static void pl041_write(void *opaque, hwaddr offset, 378 uint64_t value, unsigned size) 379 { 380 PL041State *s = (PL041State *)opaque; 381 uint16_t control, data; 382 uint32_t result; 383 384 DBG_L1("pl041_write [0x%08x] %s <= 0x%08x\n", offset, 385 get_reg_name(offset), (unsigned int)value); 386 387 /* Write the register */ 388 if (offset <= PL041_dr4_7) { 389 *((uint32_t *)&s->regs + (offset >> 2)) = value; 390 } else { 391 DBG_L1("pl041_write: Reserved offset %x\n", (int)offset); 392 return; 393 } 394 395 /* Execute the actions */ 396 switch (offset) { 397 case PL041_txcr1: 398 { 399 pl041_channel *channel = &s->fifo1; 400 401 uint32_t txen = s->regs.txcr1 & TXEN; 402 uint32_t tsize = (s->regs.txcr1 & TSIZE_MASK) >> TSIZE_MASK_BIT; 403 uint32_t compact_mode = (s->regs.txcr1 & TXCOMPACT) ? 1 : 0; 404 #if defined(PL041_DEBUG_LEVEL) 405 uint32_t slots = (s->regs.txcr1 & TXSLOT_MASK) >> TXSLOT_MASK_BIT; 406 uint32_t txfen = (s->regs.txcr1 & TXFEN) > 0 ? 1 : 0; 407 #endif 408 409 DBG_L1("=> txen = %i slots = 0x%01x tsize = %i compact = %i " 410 "txfen = %i\n", txen, slots, tsize, compact_mode, txfen); 411 412 channel->tx_enabled = txen; 413 channel->tx_compact_mode = compact_mode; 414 415 switch (tsize) { 416 case 0: 417 channel->tx_sample_size = 16; 418 break; 419 case 1: 420 channel->tx_sample_size = 18; 421 break; 422 case 2: 423 channel->tx_sample_size = 20; 424 break; 425 case 3: 426 channel->tx_sample_size = 12; 427 break; 428 } 429 430 DBG_L1("TX enabled = %i\n", channel->tx_enabled); 431 DBG_L1("TX compact mode = %i\n", channel->tx_compact_mode); 432 DBG_L1("TX sample width = %i\n", channel->tx_sample_size); 433 434 /* Check if compact mode is allowed with selected tsize */ 435 if (channel->tx_compact_mode == 1) { 436 if ((channel->tx_sample_size == 18) || 437 (channel->tx_sample_size == 20)) { 438 channel->tx_compact_mode = 0; 439 DBG_L1("Compact mode not allowed with 18/20-bit sample size\n"); 440 } 441 } 442 443 break; 444 } 445 case PL041_sl1tx: 446 s->regs.slfr &= ~SL1TXEMPTY; 447 448 control = (s->regs.sl1tx >> 12) & 0x7F; 449 data = (s->regs.sl2tx >> 4) & 0xFFFF; 450 451 if ((s->regs.sl1tx & SLOT1_RW) == 0) { 452 /* Write operation */ 453 lm4549_write(&s->codec, control, data); 454 } else { 455 /* Read operation */ 456 result = lm4549_read(&s->codec, control); 457 458 /* Store the returned value */ 459 s->regs.sl1rx = s->regs.sl1tx & ~SLOT1_RW; 460 s->regs.sl2rx = result << 4; 461 462 s->regs.slfr &= ~(SL1RXBUSY | SL2RXBUSY); 463 s->regs.slfr |= SL1RXVALID | SL2RXVALID; 464 } 465 break; 466 467 case PL041_sl2tx: 468 s->regs.sl2tx = value; 469 s->regs.slfr &= ~SL2TXEMPTY; 470 break; 471 472 case PL041_intclr: 473 DBG_L1("=> Clear interrupt intclr = 0x%08x isr1 = 0x%08x\n", 474 s->regs.intclr, s->regs.isr1); 475 476 if (s->regs.intclr & TXUEC1) { 477 s->regs.sr1 &= ~TXUNDERRUN; 478 } 479 break; 480 481 case PL041_maincr: 482 { 483 #if defined(PL041_DEBUG_LEVEL) 484 char debug[] = " AACIFE SL1RXEN SL1TXEN"; 485 if (!(value & AACIFE)) { 486 debug[0] = '!'; 487 } 488 if (!(value & SL1RXEN)) { 489 debug[8] = '!'; 490 } 491 if (!(value & SL1TXEN)) { 492 debug[17] = '!'; 493 } 494 DBG_L1("%s\n", debug); 495 #endif 496 497 if ((s->regs.maincr & AACIFE) == 0) { 498 pl041_reset(s); 499 } 500 break; 501 } 502 503 case PL041_dr1_0: 504 case PL041_dr1_1: 505 case PL041_dr1_2: 506 case PL041_dr1_3: 507 pl041_fifo1_write(s, value); 508 break; 509 } 510 511 /* Transmit the FIFO content */ 512 pl041_fifo1_transmit(s); 513 514 /* Update the ISR1 register */ 515 pl041_isr1_update(s); 516 } 517 518 static void pl041_device_reset(DeviceState *d) 519 { 520 PL041State *s = PL041(d); 521 522 pl041_reset(s); 523 } 524 525 static const MemoryRegionOps pl041_ops = { 526 .read = pl041_read, 527 .write = pl041_write, 528 .endianness = DEVICE_NATIVE_ENDIAN, 529 }; 530 531 static void pl041_init(Object *obj) 532 { 533 SysBusDevice *dev = SYS_BUS_DEVICE(obj); 534 PL041State *s = PL041(dev); 535 536 DBG_L1("pl041_init 0x%08x\n", (uint32_t)s); 537 538 /* Connect the device to the sysbus */ 539 memory_region_init_io(&s->iomem, obj, &pl041_ops, s, "pl041", 0x1000); 540 sysbus_init_mmio(dev, &s->iomem); 541 sysbus_init_irq(dev, &s->irq); 542 } 543 544 static void pl041_realize(DeviceState *dev, Error **errp) 545 { 546 PL041State *s = PL041(dev); 547 548 /* Check the device properties */ 549 switch (s->fifo_depth) { 550 case 8: 551 case 32: 552 case 64: 553 case 128: 554 case 256: 555 case 512: 556 case 1024: 557 case 2048: 558 break; 559 case 16: 560 default: 561 /* NC FIFO depth of 16 is not allowed because its id bits in 562 AACIPERIPHID3 overlap with the id for the default NC FIFO depth */ 563 qemu_log_mask(LOG_UNIMP, 564 "pl041: unsupported non-compact fifo depth [%i]\n", 565 s->fifo_depth); 566 } 567 568 /* Init the codec */ 569 lm4549_init(&s->codec, &pl041_request_data, (void *)s); 570 } 571 572 static const VMStateDescription vmstate_pl041_regfile = { 573 .name = "pl041_regfile", 574 .version_id = 1, 575 .minimum_version_id = 1, 576 .fields = (VMStateField[]) { 577 #define REGISTER(name, offset) VMSTATE_UINT32(name, pl041_regfile), 578 #include "pl041.hx" 579 #undef REGISTER 580 VMSTATE_END_OF_LIST() 581 } 582 }; 583 584 static const VMStateDescription vmstate_pl041_fifo = { 585 .name = "pl041_fifo", 586 .version_id = 1, 587 .minimum_version_id = 1, 588 .fields = (VMStateField[]) { 589 VMSTATE_UINT32(level, pl041_fifo), 590 VMSTATE_UINT32_ARRAY(data, pl041_fifo, MAX_FIFO_DEPTH), 591 VMSTATE_END_OF_LIST() 592 } 593 }; 594 595 static const VMStateDescription vmstate_pl041_channel = { 596 .name = "pl041_channel", 597 .version_id = 1, 598 .minimum_version_id = 1, 599 .fields = (VMStateField[]) { 600 VMSTATE_STRUCT(tx_fifo, pl041_channel, 0, 601 vmstate_pl041_fifo, pl041_fifo), 602 VMSTATE_UINT8(tx_enabled, pl041_channel), 603 VMSTATE_UINT8(tx_compact_mode, pl041_channel), 604 VMSTATE_UINT8(tx_sample_size, pl041_channel), 605 VMSTATE_STRUCT(rx_fifo, pl041_channel, 0, 606 vmstate_pl041_fifo, pl041_fifo), 607 VMSTATE_UINT8(rx_enabled, pl041_channel), 608 VMSTATE_UINT8(rx_compact_mode, pl041_channel), 609 VMSTATE_UINT8(rx_sample_size, pl041_channel), 610 VMSTATE_END_OF_LIST() 611 } 612 }; 613 614 static const VMStateDescription vmstate_pl041 = { 615 .name = "pl041", 616 .version_id = 1, 617 .minimum_version_id = 1, 618 .fields = (VMStateField[]) { 619 VMSTATE_UINT32(fifo_depth, PL041State), 620 VMSTATE_STRUCT(regs, PL041State, 0, 621 vmstate_pl041_regfile, pl041_regfile), 622 VMSTATE_STRUCT(fifo1, PL041State, 0, 623 vmstate_pl041_channel, pl041_channel), 624 VMSTATE_STRUCT(codec, PL041State, 0, 625 vmstate_lm4549_state, lm4549_state), 626 VMSTATE_END_OF_LIST() 627 } 628 }; 629 630 static Property pl041_device_properties[] = { 631 DEFINE_AUDIO_PROPERTIES(PL041State, codec.card), 632 /* Non-compact FIFO depth property */ 633 DEFINE_PROP_UINT32("nc_fifo_depth", PL041State, fifo_depth, 634 DEFAULT_FIFO_DEPTH), 635 DEFINE_PROP_END_OF_LIST(), 636 }; 637 638 static void pl041_device_class_init(ObjectClass *klass, void *data) 639 { 640 DeviceClass *dc = DEVICE_CLASS(klass); 641 642 dc->realize = pl041_realize; 643 set_bit(DEVICE_CATEGORY_SOUND, dc->categories); 644 dc->reset = pl041_device_reset; 645 dc->vmsd = &vmstate_pl041; 646 device_class_set_props(dc, pl041_device_properties); 647 } 648 649 static const TypeInfo pl041_device_info = { 650 .name = TYPE_PL041, 651 .parent = TYPE_SYS_BUS_DEVICE, 652 .instance_size = sizeof(PL041State), 653 .instance_init = pl041_init, 654 .class_init = pl041_device_class_init, 655 }; 656 657 static void pl041_register_types(void) 658 { 659 type_register_static(&pl041_device_info); 660 } 661 662 type_init(pl041_register_types) 663