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