26 |
26 |
#include "qemu-timer.h"
|
27 |
27 |
#include "qemu-char.h"
|
28 |
28 |
#include "flash.h"
|
|
29 |
#include "audio/audio.h"
|
29 |
30 |
|
30 |
31 |
/* GP timers */
|
31 |
32 |
struct omap_gp_timer_s {
|
... | ... | |
1420 |
1421 |
s->ch[chipselect].opaque = opaque;
|
1421 |
1422 |
}
|
1422 |
1423 |
|
|
1424 |
/* Enhanced Audio Controller (CODEC only) */
|
|
1425 |
struct omap_eac_s {
|
|
1426 |
target_phys_addr_t base;
|
|
1427 |
qemu_irq irq;
|
|
1428 |
|
|
1429 |
uint16_t sysconfig;
|
|
1430 |
uint8_t config[4];
|
|
1431 |
uint8_t control;
|
|
1432 |
uint8_t address;
|
|
1433 |
uint16_t data;
|
|
1434 |
uint8_t vtol;
|
|
1435 |
uint8_t vtsl;
|
|
1436 |
uint16_t mixer;
|
|
1437 |
uint16_t gain[4];
|
|
1438 |
uint8_t att;
|
|
1439 |
uint16_t max[7];
|
|
1440 |
|
|
1441 |
struct {
|
|
1442 |
qemu_irq txdrq;
|
|
1443 |
qemu_irq rxdrq;
|
|
1444 |
uint32_t (*txrx)(void *opaque, uint32_t, int);
|
|
1445 |
void *opaque;
|
|
1446 |
|
|
1447 |
#define EAC_BUF_LEN 1024
|
|
1448 |
uint32_t rxbuf[EAC_BUF_LEN];
|
|
1449 |
int rxlen;
|
|
1450 |
int rxavail;
|
|
1451 |
uint32_t txbuf[EAC_BUF_LEN];
|
|
1452 |
int txlen;
|
|
1453 |
int txavail;
|
|
1454 |
|
|
1455 |
int enable;
|
|
1456 |
int rate;
|
|
1457 |
|
|
1458 |
uint16_t config[4];
|
|
1459 |
|
|
1460 |
/* These need to be moved to the actual codec */
|
|
1461 |
QEMUSoundCard card;
|
|
1462 |
SWVoiceIn *in_voice;
|
|
1463 |
SWVoiceOut *out_voice;
|
|
1464 |
int hw_enable;
|
|
1465 |
} codec;
|
|
1466 |
|
|
1467 |
struct {
|
|
1468 |
uint8_t control;
|
|
1469 |
uint16_t config;
|
|
1470 |
} modem, bt;
|
|
1471 |
};
|
|
1472 |
|
|
1473 |
static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
|
|
1474 |
{
|
|
1475 |
qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1); /* AURDI */
|
|
1476 |
}
|
|
1477 |
|
|
1478 |
static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
|
|
1479 |
{
|
|
1480 |
qemu_set_irq(s->codec.rxdrq, s->codec.rxavail + s->codec.rxlen &&
|
|
1481 |
((s->codec.config[1] >> 12) & 1)); /* DMAREN */
|
|
1482 |
}
|
|
1483 |
|
|
1484 |
static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
|
|
1485 |
{
|
|
1486 |
qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
|
|
1487 |
((s->codec.config[1] >> 11) & 1)); /* DMAWEN */
|
|
1488 |
}
|
|
1489 |
|
|
1490 |
static inline void omap_eac_in_refill(struct omap_eac_s *s)
|
|
1491 |
{
|
|
1492 |
int left, start = 0;
|
|
1493 |
|
|
1494 |
s->codec.rxlen = MIN(s->codec.rxavail, EAC_BUF_LEN);
|
|
1495 |
s->codec.rxavail -= s->codec.rxlen;
|
|
1496 |
|
|
1497 |
for (left = s->codec.rxlen << 2; left; start = (EAC_BUF_LEN << 2) - left)
|
|
1498 |
left -= AUD_read(s->codec.in_voice,
|
|
1499 |
(uint8_t *) s->codec.rxbuf + start, left);
|
|
1500 |
}
|
|
1501 |
|
|
1502 |
static inline void omap_eac_out_empty(struct omap_eac_s *s)
|
|
1503 |
{
|
|
1504 |
int left, start = 0;
|
|
1505 |
|
|
1506 |
for (left = s->codec.txlen << 2; left; start = (s->codec.txlen << 2) - left)
|
|
1507 |
left -= AUD_write(s->codec.out_voice,
|
|
1508 |
(uint8_t *) s->codec.txbuf + start, left);
|
|
1509 |
|
|
1510 |
s->codec.txavail -= s->codec.txlen;
|
|
1511 |
s->codec.txlen = 0;
|
|
1512 |
}
|
|
1513 |
|
|
1514 |
static void omap_eac_in_cb(void *opaque, int avail_b)
|
|
1515 |
{
|
|
1516 |
struct omap_eac_s *s = (struct omap_eac_s *) opaque;
|
|
1517 |
|
|
1518 |
s->codec.rxavail = avail_b >> 2;
|
|
1519 |
omap_eac_in_dmarequest_update(s);
|
|
1520 |
/* TODO: possibly discard current buffer if overrun */
|
|
1521 |
}
|
|
1522 |
|
|
1523 |
static void omap_eac_out_cb(void *opaque, int free_b)
|
|
1524 |
{
|
|
1525 |
struct omap_eac_s *s = (struct omap_eac_s *) opaque;
|
|
1526 |
|
|
1527 |
s->codec.txavail = free_b >> 2;
|
|
1528 |
if (s->codec.txlen > s->codec.txavail)
|
|
1529 |
s->codec.txlen = s->codec.txavail;
|
|
1530 |
omap_eac_out_empty(s);
|
|
1531 |
omap_eac_out_dmarequest_update(s);
|
|
1532 |
}
|
|
1533 |
|
|
1534 |
static void omap_eac_enable_update(struct omap_eac_s *s)
|
|
1535 |
{
|
|
1536 |
s->codec.enable = !(s->codec.config[1] & 1) && /* EACPWD */
|
|
1537 |
(s->codec.config[1] & 2) && /* AUDEN */
|
|
1538 |
s->codec.hw_enable;
|
|
1539 |
}
|
|
1540 |
|
|
1541 |
static const int omap_eac_fsint[4] = {
|
|
1542 |
8000,
|
|
1543 |
11025,
|
|
1544 |
22050,
|
|
1545 |
44100,
|
|
1546 |
};
|
|
1547 |
|
|
1548 |
static const int omap_eac_fsint2[8] = {
|
|
1549 |
8000,
|
|
1550 |
11025,
|
|
1551 |
22050,
|
|
1552 |
44100,
|
|
1553 |
48000,
|
|
1554 |
0, 0, 0,
|
|
1555 |
};
|
|
1556 |
|
|
1557 |
static const int omap_eac_fsint3[16] = {
|
|
1558 |
8000,
|
|
1559 |
11025,
|
|
1560 |
16000,
|
|
1561 |
22050,
|
|
1562 |
24000,
|
|
1563 |
32000,
|
|
1564 |
44100,
|
|
1565 |
48000,
|
|
1566 |
0, 0, 0, 0, 0, 0, 0, 0,
|
|
1567 |
};
|
|
1568 |
|
|
1569 |
static void omap_eac_rate_update(struct omap_eac_s *s)
|
|
1570 |
{
|
|
1571 |
int fsint[3];
|
|
1572 |
|
|
1573 |
fsint[2] = (s->codec.config[3] >> 9) & 0xf;
|
|
1574 |
fsint[1] = (s->codec.config[2] >> 0) & 0x7;
|
|
1575 |
fsint[0] = (s->codec.config[0] >> 6) & 0x3;
|
|
1576 |
if (fsint[2] < 0xf)
|
|
1577 |
s->codec.rate = omap_eac_fsint3[fsint[2]];
|
|
1578 |
else if (fsint[1] < 0x7)
|
|
1579 |
s->codec.rate = omap_eac_fsint2[fsint[1]];
|
|
1580 |
else
|
|
1581 |
s->codec.rate = omap_eac_fsint[fsint[0]];
|
|
1582 |
}
|
|
1583 |
|
|
1584 |
static void omap_eac_volume_update(struct omap_eac_s *s)
|
|
1585 |
{
|
|
1586 |
/* TODO */
|
|
1587 |
}
|
|
1588 |
|
|
1589 |
static void omap_eac_format_update(struct omap_eac_s *s)
|
|
1590 |
{
|
|
1591 |
audsettings_t fmt;
|
|
1592 |
|
|
1593 |
omap_eac_out_empty(s);
|
|
1594 |
|
|
1595 |
if (s->codec.in_voice) {
|
|
1596 |
AUD_set_active_in(s->codec.in_voice, 0);
|
|
1597 |
AUD_close_in(&s->codec.card, s->codec.in_voice);
|
|
1598 |
s->codec.in_voice = 0;
|
|
1599 |
}
|
|
1600 |
if (s->codec.out_voice) {
|
|
1601 |
AUD_set_active_out(s->codec.out_voice, 0);
|
|
1602 |
AUD_close_out(&s->codec.card, s->codec.out_voice);
|
|
1603 |
s->codec.out_voice = 0;
|
|
1604 |
}
|
|
1605 |
|
|
1606 |
omap_eac_enable_update(s);
|
|
1607 |
if (!s->codec.enable)
|
|
1608 |
return;
|
|
1609 |
|
|
1610 |
omap_eac_rate_update(s);
|
|
1611 |
fmt.endianness = ((s->codec.config[0] >> 8) & 1); /* LI_BI */
|
|
1612 |
fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1; /* MN_ST */
|
|
1613 |
fmt.freq = s->codec.rate;
|
|
1614 |
/* TODO: signedness possibly depends on the CODEC hardware - or
|
|
1615 |
* does I2S specify it? */
|
|
1616 |
/* All register writes are 16 bits so we we store 16-bit samples
|
|
1617 |
* in the buffers regardless of AGCFR[B8_16] value. */
|
|
1618 |
fmt.fmt = AUD_FMT_U16;
|
|
1619 |
|
|
1620 |
s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
|
|
1621 |
"eac.codec.in", s, omap_eac_in_cb, &fmt);
|
|
1622 |
s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
|
|
1623 |
"eac.codec.out", s, omap_eac_out_cb, &fmt);
|
|
1624 |
|
|
1625 |
omap_eac_volume_update(s);
|
|
1626 |
|
|
1627 |
AUD_set_active_in(s->codec.in_voice, 1);
|
|
1628 |
AUD_set_active_out(s->codec.out_voice, 1);
|
|
1629 |
}
|
|
1630 |
|
|
1631 |
static void omap_eac_reset(struct omap_eac_s *s)
|
|
1632 |
{
|
|
1633 |
s->sysconfig = 0;
|
|
1634 |
s->config[0] = 0x0c;
|
|
1635 |
s->config[1] = 0x09;
|
|
1636 |
s->config[2] = 0xab;
|
|
1637 |
s->config[3] = 0x03;
|
|
1638 |
s->control = 0x00;
|
|
1639 |
s->address = 0x00;
|
|
1640 |
s->data = 0x0000;
|
|
1641 |
s->vtol = 0x00;
|
|
1642 |
s->vtsl = 0x00;
|
|
1643 |
s->mixer = 0x0000;
|
|
1644 |
s->gain[0] = 0xe7e7;
|
|
1645 |
s->gain[1] = 0x6767;
|
|
1646 |
s->gain[2] = 0x6767;
|
|
1647 |
s->gain[3] = 0x6767;
|
|
1648 |
s->att = 0xce;
|
|
1649 |
s->max[0] = 0;
|
|
1650 |
s->max[1] = 0;
|
|
1651 |
s->max[2] = 0;
|
|
1652 |
s->max[3] = 0;
|
|
1653 |
s->max[4] = 0;
|
|
1654 |
s->max[5] = 0;
|
|
1655 |
s->max[6] = 0;
|
|
1656 |
|
|
1657 |
s->modem.control = 0x00;
|
|
1658 |
s->modem.config = 0x0000;
|
|
1659 |
s->bt.control = 0x00;
|
|
1660 |
s->bt.config = 0x0000;
|
|
1661 |
s->codec.config[0] = 0x0649;
|
|
1662 |
s->codec.config[1] = 0x0000;
|
|
1663 |
s->codec.config[2] = 0x0007;
|
|
1664 |
s->codec.config[3] = 0x1ffc;
|
|
1665 |
s->codec.rxlen = 0;
|
|
1666 |
s->codec.txlen = 0;
|
|
1667 |
s->codec.rxavail = 0;
|
|
1668 |
s->codec.txavail = 0;
|
|
1669 |
|
|
1670 |
omap_eac_format_update(s);
|
|
1671 |
omap_eac_interrupt_update(s);
|
|
1672 |
}
|
|
1673 |
|
|
1674 |
static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
|
|
1675 |
{
|
|
1676 |
struct omap_eac_s *s = (struct omap_eac_s *) opaque;
|
|
1677 |
int offset = addr - s->base;
|
|
1678 |
|
|
1679 |
switch (offset) {
|
|
1680 |
case 0x000: /* CPCFR1 */
|
|
1681 |
return s->config[0];
|
|
1682 |
case 0x004: /* CPCFR2 */
|
|
1683 |
return s->config[1];
|
|
1684 |
case 0x008: /* CPCFR3 */
|
|
1685 |
return s->config[2];
|
|
1686 |
case 0x00c: /* CPCFR4 */
|
|
1687 |
return s->config[3];
|
|
1688 |
|
|
1689 |
case 0x010: /* CPTCTL */
|
|
1690 |
return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
|
|
1691 |
((s->codec.txlen < s->codec.txavail) << 5);
|
|
1692 |
|
|
1693 |
case 0x014: /* CPTTADR */
|
|
1694 |
return s->address;
|
|
1695 |
case 0x018: /* CPTDATL */
|
|
1696 |
return s->data & 0xff;
|
|
1697 |
case 0x01c: /* CPTDATH */
|
|
1698 |
return s->data >> 8;
|
|
1699 |
case 0x020: /* CPTVSLL */
|
|
1700 |
return s->vtol;
|
|
1701 |
case 0x024: /* CPTVSLH */
|
|
1702 |
return s->vtsl | (3 << 5); /* CRDY1 | CRDY2 */
|
|
1703 |
case 0x040: /* MPCTR */
|
|
1704 |
return s->modem.control;
|
|
1705 |
case 0x044: /* MPMCCFR */
|
|
1706 |
return s->modem.config;
|
|
1707 |
case 0x060: /* BPCTR */
|
|
1708 |
return s->bt.control;
|
|
1709 |
case 0x064: /* BPMCCFR */
|
|
1710 |
return s->bt.config;
|
|
1711 |
case 0x080: /* AMSCFR */
|
|
1712 |
return s->mixer;
|
|
1713 |
case 0x084: /* AMVCTR */
|
|
1714 |
return s->gain[0];
|
|
1715 |
case 0x088: /* AM1VCTR */
|
|
1716 |
return s->gain[1];
|
|
1717 |
case 0x08c: /* AM2VCTR */
|
|
1718 |
return s->gain[2];
|
|
1719 |
case 0x090: /* AM3VCTR */
|
|
1720 |
return s->gain[3];
|
|
1721 |
case 0x094: /* ASTCTR */
|
|
1722 |
return s->att;
|
|
1723 |
case 0x098: /* APD1LCR */
|
|
1724 |
return s->max[0];
|
|
1725 |
case 0x09c: /* APD1RCR */
|
|
1726 |
return s->max[1];
|
|
1727 |
case 0x0a0: /* APD2LCR */
|
|
1728 |
return s->max[2];
|
|
1729 |
case 0x0a4: /* APD2RCR */
|
|
1730 |
return s->max[3];
|
|
1731 |
case 0x0a8: /* APD3LCR */
|
|
1732 |
return s->max[4];
|
|
1733 |
case 0x0ac: /* APD3RCR */
|
|
1734 |
return s->max[5];
|
|
1735 |
case 0x0b0: /* APD4R */
|
|
1736 |
return s->max[6];
|
|
1737 |
case 0x0b4: /* ADWR */
|
|
1738 |
/* This should be write-only? Docs list it as read-only. */
|
|
1739 |
return 0x0000;
|
|
1740 |
case 0x0b8: /* ADRDR */
|
|
1741 |
if (likely(s->codec.rxlen > 1))
|
|
1742 |
return s->codec.rxbuf[EAC_BUF_LEN - s->codec.rxlen --];
|
|
1743 |
else if (s->codec.rxlen) {
|
|
1744 |
if (s->codec.rxavail)
|
|
1745 |
omap_eac_in_refill(s);
|
|
1746 |
else {
|
|
1747 |
s->codec.rxlen = 0;
|
|
1748 |
omap_eac_in_dmarequest_update(s);
|
|
1749 |
}
|
|
1750 |
return s->codec.rxbuf[EAC_BUF_LEN - 1];
|
|
1751 |
}
|
|
1752 |
return 0x0000;
|
|
1753 |
case 0x0bc: /* AGCFR */
|
|
1754 |
return s->codec.config[0];
|
|
1755 |
case 0x0c0: /* AGCTR */
|
|
1756 |
return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
|
|
1757 |
case 0x0c4: /* AGCFR2 */
|
|
1758 |
return s->codec.config[2];
|
|
1759 |
case 0x0c8: /* AGCFR3 */
|
|
1760 |
return s->codec.config[3];
|
|
1761 |
case 0x0cc: /* MBPDMACTR */
|
|
1762 |
case 0x0d0: /* MPDDMARR */
|
|
1763 |
case 0x0d8: /* MPUDMARR */
|
|
1764 |
case 0x0e4: /* BPDDMARR */
|
|
1765 |
case 0x0ec: /* BPUDMARR */
|
|
1766 |
return 0x0000;
|
|
1767 |
|
|
1768 |
case 0x100: /* VERSION_NUMBER */
|
|
1769 |
return 0x0010;
|
|
1770 |
|
|
1771 |
case 0x104: /* SYSCONFIG */
|
|
1772 |
return s->sysconfig;
|
|
1773 |
|
|
1774 |
case 0x108: /* SYSSTATUS */
|
|
1775 |
return 1 | 0xe; /* RESETDONE | stuff */
|
|
1776 |
}
|
|
1777 |
|
|
1778 |
OMAP_BAD_REG(addr);
|
|
1779 |
return 0;
|
|
1780 |
}
|
|
1781 |
|
|
1782 |
static void omap_eac_write(void *opaque, target_phys_addr_t addr,
|
|
1783 |
uint32_t value)
|
|
1784 |
{
|
|
1785 |
struct omap_eac_s *s = (struct omap_eac_s *) opaque;
|
|
1786 |
int offset = addr - s->base;
|
|
1787 |
|
|
1788 |
switch (offset) {
|
|
1789 |
case 0x098: /* APD1LCR */
|
|
1790 |
case 0x09c: /* APD1RCR */
|
|
1791 |
case 0x0a0: /* APD2LCR */
|
|
1792 |
case 0x0a4: /* APD2RCR */
|
|
1793 |
case 0x0a8: /* APD3LCR */
|
|
1794 |
case 0x0ac: /* APD3RCR */
|
|
1795 |
case 0x0b0: /* APD4R */
|
|
1796 |
case 0x0b8: /* ADRDR */
|
|
1797 |
case 0x0d0: /* MPDDMARR */
|
|
1798 |
case 0x0d8: /* MPUDMARR */
|
|
1799 |
case 0x0e4: /* BPDDMARR */
|
|
1800 |
case 0x0ec: /* BPUDMARR */
|
|
1801 |
case 0x100: /* VERSION_NUMBER */
|
|
1802 |
case 0x108: /* SYSSTATUS */
|
|
1803 |
OMAP_RO_REG(addr);
|
|
1804 |
return;
|
|
1805 |
|
|
1806 |
case 0x000: /* CPCFR1 */
|
|
1807 |
s->config[0] = value & 0xff;
|
|
1808 |
omap_eac_format_update(s);
|
|
1809 |
break;
|
|
1810 |
case 0x004: /* CPCFR2 */
|
|
1811 |
s->config[1] = value & 0xff;
|
|
1812 |
omap_eac_format_update(s);
|
|
1813 |
break;
|
|
1814 |
case 0x008: /* CPCFR3 */
|
|
1815 |
s->config[2] = value & 0xff;
|
|
1816 |
omap_eac_format_update(s);
|
|
1817 |
break;
|
|
1818 |
case 0x00c: /* CPCFR4 */
|
|
1819 |
s->config[3] = value & 0xff;
|
|
1820 |
omap_eac_format_update(s);
|
|
1821 |
break;
|
|
1822 |
|
|
1823 |
case 0x010: /* CPTCTL */
|
|
1824 |
/* Assuming TXF and TXE bits are read-only... */
|
|
1825 |
s->control = value & 0x5f;
|
|
1826 |
omap_eac_interrupt_update(s);
|
|
1827 |
break;
|
|
1828 |
|
|
1829 |
case 0x014: /* CPTTADR */
|
|
1830 |
s->address = value & 0xff;
|
|
1831 |
break;
|
|
1832 |
case 0x018: /* CPTDATL */
|
|
1833 |
s->data &= 0xff00;
|
|
1834 |
s->data |= value & 0xff;
|
|
1835 |
break;
|
|
1836 |
case 0x01c: /* CPTDATH */
|
|
1837 |
s->data &= 0x00ff;
|
|
1838 |
s->data |= value << 8;
|
|
1839 |
break;
|
|
1840 |
case 0x020: /* CPTVSLL */
|
|
1841 |
s->vtol = value & 0xf8;
|
|
1842 |
break;
|
|
1843 |
case 0x024: /* CPTVSLH */
|
|
1844 |
s->vtsl = value & 0x9f;
|
|
1845 |
break;
|
|
1846 |
case 0x040: /* MPCTR */
|
|
1847 |
s->modem.control = value & 0x8f;
|
|
1848 |
break;
|
|
1849 |
case 0x044: /* MPMCCFR */
|
|
1850 |
s->modem.config = value & 0x7fff;
|
|
1851 |
break;
|
|
1852 |
case 0x060: /* BPCTR */
|
|
1853 |
s->bt.control = value & 0x8f;
|
|
1854 |
break;
|
|
1855 |
case 0x064: /* BPMCCFR */
|
|
1856 |
s->bt.config = value & 0x7fff;
|
|
1857 |
break;
|
|
1858 |
case 0x080: /* AMSCFR */
|
|
1859 |
s->mixer = value & 0x0fff;
|
|
1860 |
break;
|
|
1861 |
case 0x084: /* AMVCTR */
|
|
1862 |
s->gain[0] = value & 0xffff;
|
|
1863 |
break;
|
|
1864 |
case 0x088: /* AM1VCTR */
|
|
1865 |
s->gain[1] = value & 0xff7f;
|
|
1866 |
break;
|
|
1867 |
case 0x08c: /* AM2VCTR */
|
|
1868 |
s->gain[2] = value & 0xff7f;
|
|
1869 |
break;
|
|
1870 |
case 0x090: /* AM3VCTR */
|
|
1871 |
s->gain[3] = value & 0xff7f;
|
|
1872 |
break;
|
|
1873 |
case 0x094: /* ASTCTR */
|
|
1874 |
s->att = value & 0xff;
|
|
1875 |
break;
|
|
1876 |
|
|
1877 |
case 0x0b4: /* ADWR */
|
|
1878 |
s->codec.txbuf[s->codec.txlen ++] = value;
|
|
1879 |
if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
|
|
1880 |
s->codec.txlen == s->codec.txavail)) {
|
|
1881 |
if (s->codec.txavail)
|
|
1882 |
omap_eac_out_empty(s);
|
|
1883 |
else
|
|
1884 |
s->codec.txlen = 0;
|
|
1885 |
}
|
|
1886 |
break;
|
|
1887 |
|
|
1888 |
case 0x0bc: /* AGCFR */
|
|
1889 |
s->codec.config[0] = value & 0x07ff;
|
|
1890 |
omap_eac_format_update(s);
|
|
1891 |
break;
|
|
1892 |
case 0x0c0: /* AGCTR */
|
|
1893 |
s->codec.config[1] = value & 0x780f;
|
|
1894 |
omap_eac_format_update(s);
|
|
1895 |
break;
|
|
1896 |
case 0x0c4: /* AGCFR2 */
|
|
1897 |
s->codec.config[2] = value & 0x003f;
|
|
1898 |
omap_eac_format_update(s);
|
|
1899 |
break;
|
|
1900 |
case 0x0c8: /* AGCFR3 */
|
|
1901 |
s->codec.config[3] = value & 0xffff;
|
|
1902 |
omap_eac_format_update(s);
|
|
1903 |
break;
|
|
1904 |
case 0x0cc: /* MBPDMACTR */
|
|
1905 |
case 0x0d4: /* MPDDMAWR */
|
|
1906 |
case 0x0e0: /* MPUDMAWR */
|
|
1907 |
case 0x0e8: /* BPDDMAWR */
|
|
1908 |
case 0x0f0: /* BPUDMAWR */
|
|
1909 |
break;
|
|
1910 |
|
|
1911 |
case 0x104: /* SYSCONFIG */
|
|
1912 |
if (value & (1 << 1)) /* SOFTRESET */
|
|
1913 |
omap_eac_reset(s);
|
|
1914 |
s->sysconfig = value & 0x31d;
|
|
1915 |
break;
|
|
1916 |
|
|
1917 |
default:
|
|
1918 |
OMAP_BAD_REG(addr);
|
|
1919 |
return;
|
|
1920 |
}
|
|
1921 |
}
|
|
1922 |
|
|
1923 |
static CPUReadMemoryFunc *omap_eac_readfn[] = {
|
|
1924 |
omap_badwidth_read16,
|
|
1925 |
omap_eac_read,
|
|
1926 |
omap_badwidth_read16,
|
|
1927 |
};
|
|
1928 |
|
|
1929 |
static CPUWriteMemoryFunc *omap_eac_writefn[] = {
|
|
1930 |
omap_badwidth_write16,
|
|
1931 |
omap_eac_write,
|
|
1932 |
omap_badwidth_write16,
|
|
1933 |
};
|
|
1934 |
|
|
1935 |
struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
|
|
1936 |
qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
|
|
1937 |
{
|
|
1938 |
int iomemtype;
|
|
1939 |
struct omap_eac_s *s = (struct omap_eac_s *)
|
|
1940 |
qemu_mallocz(sizeof(struct omap_eac_s));
|
|
1941 |
|
|
1942 |
s->irq = irq;
|
|
1943 |
s->codec.rxdrq = *drq ++;
|
|
1944 |
s->codec.txdrq = *drq ++;
|
|
1945 |
omap_eac_reset(s);
|
|
1946 |
|
|
1947 |
#ifdef HAS_AUDIO
|
|
1948 |
/* TODO: do AUD_init globally for machine */
|
|
1949 |
AUD_register_card(AUD_init(), "OMAP EAC", &s->codec.card);
|
|
1950 |
|
|
1951 |
iomemtype = cpu_register_io_memory(0, omap_eac_readfn,
|
|
1952 |
omap_eac_writefn, s);
|
|
1953 |
s->base = omap_l4_attach(ta, 0, iomemtype);
|
|
1954 |
#endif
|
|
1955 |
|
|
1956 |
return s;
|
|
1957 |
}
|
|
1958 |
|
1423 |
1959 |
/* STI/XTI (emulation interface) console - reverse engineered only */
|
1424 |
1960 |
struct omap_sti_s {
|
1425 |
1961 |
target_phys_addr_t base;
|
... | ... | |
2566 |
3102 |
case 0x200: /* CM_FCLKEN1_CORE */
|
2567 |
3103 |
s->clken[0] = value & 0xbfffffff;
|
2568 |
3104 |
/* TODO update clocks */
|
|
3105 |
/* The EN_EAC bit only gets/puts func_96m_clk. */
|
2569 |
3106 |
break;
|
2570 |
3107 |
case 0x204: /* CM_FCLKEN2_CORE */
|
2571 |
3108 |
s->clken[1] = value & 0x00000007;
|
... | ... | |
2574 |
3111 |
case 0x210: /* CM_ICLKEN1_CORE */
|
2575 |
3112 |
s->clken[2] = value & 0xfffffff9;
|
2576 |
3113 |
/* TODO update clocks */
|
|
3114 |
/* The EN_EAC bit only gets/puts core_l4_iclk. */
|
2577 |
3115 |
break;
|
2578 |
3116 |
case 0x214: /* CM_ICLKEN2_CORE */
|
2579 |
3117 |
s->clken[3] = value & 0x00000007;
|
... | ... | |
3969 |
4507 |
omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
|
3970 |
4508 |
|
3971 |
4509 |
s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
|
3972 |
|
s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ],
|
|
4510 |
s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ],
|
3973 |
4511 |
&s->drq[OMAP24XX_DMA_SPI1_TX0],
|
3974 |
4512 |
omap_findclk(s, "spi1_fclk"),
|
3975 |
4513 |
omap_findclk(s, "spi1_iclk"));
|
3976 |
4514 |
s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
|
3977 |
|
s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ],
|
|
4515 |
s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ],
|
3978 |
4516 |
&s->drq[OMAP24XX_DMA_SPI2_TX0],
|
3979 |
4517 |
omap_findclk(s, "spi2_fclk"),
|
3980 |
4518 |
omap_findclk(s, "spi2_iclk"));
|
... | ... | |
3992 |
4530 |
serial_hds[0] && serial_hds[1] && serial_hds[2] ?
|
3993 |
4531 |
serial_hds[3] : 0);
|
3994 |
4532 |
|
|
4533 |
s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
|
|
4534 |
s->irq[0][OMAP_INT_24XX_EAC_IRQ],
|
|
4535 |
/* Ten consecutive lines */
|
|
4536 |
&s->drq[OMAP24XX_DMA_EAC_AC_RD],
|
|
4537 |
omap_findclk(s, "func_96m_clk"),
|
|
4538 |
omap_findclk(s, "core_l4_iclk"));
|
|
4539 |
|
3995 |
4540 |
/* All register mappings (includin those not currenlty implemented):
|
3996 |
4541 |
* SystemControlMod 48000000 - 48000fff
|
3997 |
4542 |
* SystemControlL4 48001000 - 48001fff
|