VirtualBox

Changeset 34443 in vbox


Ignore:
Timestamp:
Nov 29, 2010 7:42:11 AM (14 years ago)
Author:
vboxsync
Message:

Audio/HDA: cosmetic and some reorganization (need to test on linux host).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevIchIntelHDA.cpp

    r34350 r34443  
    223223#define HDA_STREAM_REG_DEF(name, num) (ICH6_HDA_REG_SD##num##name)
    224224#define HDA_STREAM_REG(pState, name, num) (HDA_REG((pState), N_(HDA_STREAM_REG_DEF(name, num))))
     225/* Note: sdnum here _MUST_ be stream reg number [0,7] */
     226#define HDA_STREAM_REG2(pState, name, sdnum) (HDA_REG_IND((pState), ICH6_HDA_REG_SD0##name + (sdnum) * 10))
    225227
    226228#define ICH6_HDA_REG_SD0CTL   32 /* 0x80 */
     
    387389    uint8_t     au8HdaBuffer[HDA_SDONFIFO_256B + 1];
    388390} HDABDLEDESC, *PHDABDLEDESC;
     391
     392typedef struct HDASTREAMTRANSFERDESC
     393{
     394    uint64_t u64BaseDMA;
     395    uint32_t u32Ctl;
     396    uint32_t *pu32Sts;
     397    uint8_t  u8Strm;
     398    uint32_t *pu32Lpib;
     399    uint32_t u32Cbl;
     400    uint32_t u32Fifos;
     401} HDASTREAMTRANSFERDESC, *PHDASTREAMTRANSFERDESC;
    389402
    390403typedef struct INTELHDLinkState
     
    420433    CODECState  Codec;
    421434    uint8_t     u8Counter;
    422     uint8_t     u8StreamsInReset;
    423 } INTELHDLinkState;
     435} INTELHDLinkState, *PINTELHDLinkState;
    424436
    425437#define ICH6_HDASTATE_2_DEVINS(pINTELHD)   ((pINTELHD)->pDevIns)
     
    476488DECLCALLBACK(int)hdaRegReadU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t *pu32Value);
    477489DECLCALLBACK(int)hdaRegWriteU8(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t pu32Value);
     490
     491static inline void hdaInitTransferDescriptor(PINTELHDLinkState pState, PHDABDLEDESC pBdle, uint8_t u8Strm, PHDASTREAMTRANSFERDESC pStreamDesc);
    478492static int hdaLookup(INTELHDLinkState* pState, uint32_t u32Offset);
    479 static void fetch_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA);
     493static void hdaFetchBdle(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc);
     494#ifdef LOG_ENABLED
     495static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA);
     496#endif
    480497
    481498/* see 302349 p 6.2*/
     
    626643};
    627644
    628 static void inline hdaUpdatePosBuf(INTELHDLinkState *pState, uint8_t u8Strm, uint32_t u32Value)
     645static void inline hdaUpdatePosBuf(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc)
    629646{
    630647    if (pState->u64DPBase & DPBASE_ENABLED)
    631648        PDMDevHlpPhysWrite(ICH6_HDASTATE_2_DEVINS(pState),
    632                        (pState->u64DPBase & DPBASE_ADDR_MASK) + u8Strm*8, &u32Value, sizeof(uint32_t));
    633 }
    634 static uint32_t inline hdaFifoWToSz(INTELHDLinkState *pState, int iNum)
    635 {
    636     switch (ICH6_HDA_REG_SD0FIFOW + 10*iNum)
    637     {
    638         case ICH6_HDA_REG_SD0FIFOW:
    639         case ICH6_HDA_REG_SD1FIFOW:
    640         case ICH6_HDA_REG_SD2FIFOW:
    641         case ICH6_HDA_REG_SD3FIFOW:
    642         case ICH6_HDA_REG_SD4FIFOW:
    643         case ICH6_HDA_REG_SD5FIFOW:
    644         case ICH6_HDA_REG_SD6FIFOW:
    645         case ICH6_HDA_REG_SD7FIFOW:
    646             switch(HDA_REG_IND(pState, ICH6_HDA_REG_SD0FIFOW + 10*iNum))
    647             {
    648                 case HDA_SDFIFOW_8B: return 8;
    649                 case HDA_SDFIFOW_16B: return 16;
    650                 case HDA_SDFIFOW_32B: return 32;
    651                 default:
    652                     AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pState, iNum), iNum));
    653             }
     649                       (pState->u64DPBase & DPBASE_ADDR_MASK) + pStreamDesc->u8Strm*8, pStreamDesc->pu32Lpib, sizeof(uint32_t));
     650}
     651static uint32_t inline hdaFifoWToSz(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc)
     652{
     653    switch(HDA_STREAM_REG2(pState, FIFOW, pStreamDesc->u8Strm))
     654    {
     655        case HDA_SDFIFOW_8B: return 8;
     656        case HDA_SDFIFOW_16B: return 16;
     657        case HDA_SDFIFOW_32B: return 32;
    654658        default:
    655             AssertMsgFailed(("hda: Not SDnFIFOW register"));
    656             return 0;
    657     }
     659            AssertMsgFailed(("hda: unsupported value (%x) in SDFIFOW(,%d)\n", HDA_REG_IND(pState, pStreamDesc->u8Strm), pStreamDesc->u8Strm));
     660    }
     661    return 0;
    658662}
    659663
     
    837841}
    838842
    839 static void hdaStreamReset(INTELHDLinkState *pState, uint32_t u32Offset)
    840 {
    841     Log(("hda: reset of stream (%x) started\n", u32Offset));
    842     Log(("hda: reset of stream (%x) finished\n", u32Offset));
     843static void hdaStreamReset(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint8_t u8Strm)
     844{
     845    Log(("hda: reset of stream (%d) started\n", u8Strm));
     846    Assert((   pState
     847            && pBdle
     848            && pStreamDesc
     849            && u8Strm <= 7));
     850    memset(pBdle, 0, sizeof(HDABDLEDESC));
     851    *pStreamDesc->pu32Lpib = 0;
     852    *pStreamDesc->pu32Sts = 0;
     853    /* According to ICH6 datasheet, 0x40000 is default value for stream descriptor register 23:20
     854     * bits are reserved for stream number 18.2.33, resets SDnCTL except SRCT bit */
     855    HDA_STREAM_REG2(pState, CTL, u8Strm) = 0x40000 | (HDA_STREAM_REG2(pState, CTL, u8Strm) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST));
     856
     857    /* ICH6 defines default values (0x77 for input and 0xBF for output descriptors) of FIFO size. 18.2.39 */
     858    HDA_STREAM_REG2(pState, FIFOS, u8Strm) =  u8Strm < 4 ? HDA_SDINFIFO_120B : HDA_SDONFIFO_192B;
     859    HDA_STREAM_REG2(pState, FIFOW, u8Strm) = u8Strm < 4 ? HDA_SDFIFOW_8B : HDA_SDFIFOW_32B;
     860    HDA_STREAM_REG2(pState, CBL, u8Strm) = 0;
     861    HDA_STREAM_REG2(pState, LVI, u8Strm) = 0;
     862    HDA_STREAM_REG2(pState, FMT, u8Strm) = 0;
     863    HDA_STREAM_REG2(pState, BDPU, u8Strm) = 0;
     864    HDA_STREAM_REG2(pState, BDPL, u8Strm) = 0;
     865    Log(("hda: reset of stream (%d) finished\n", u8Strm));
    843866}
    844867
     
    944967    uint32_t v = pState->au32Regs[index];
    945968    uint32_t nv = u32Value & ICH6_HDA_STATES_SCSF;
    946     pState->au32Regs[index] = (v ^ nv) & v; /* write of 1 clears corresponding bit */
     969    pState->au32Regs[index] &= ~(v & nv); /* write of 1 clears corresponding bit */
    947970    return VINF_SUCCESS;
    948971}
     
    10011024{
    10021025    uint32_t v = CORBSTS(pState);
    1003     v = (v ^ u32Value) & v;
    1004     CORBSTS(pState) = v;
     1026    CORBSTS(pState) &= ~(v & u32Value);
    10051027    return VINF_SUCCESS;
    10061028}
     
    10241046    return hdaRegReadU24(pState, offset, index, pu32Value);
    10251047}
    1026 #define HDA_STREAM_BITMASK(offset) (1 << (((offset) - 0x80) >> 5))
    1027 #define HDA_IS_STREAM_IN_RESET(pState, offset) ((pState)->u8StreamsInReset & HDA_STREAM_BITMASK((offset)))
     1048
    10281049DECLCALLBACK(int)hdaRegWriteSDCTL(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
    10291050{
    1030     bool fOn = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)));
     1051    bool fRun = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)));
     1052    bool fInRun = RT_BOOL((HDA_REG_IND(pState, index) & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN)));
     1053    bool fReset = RT_BOOL((u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)));
     1054    bool fInReset = RT_BOOL((HDA_REG_IND(pState, index) & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST)));
    10311055    int rc = VINF_SUCCESS;
    1032     uint64_t u64BaseDMA = 0;
    1033     uint8_t u8Strm = 0;
    1034     PHDABDLEDESC pBdle = NULL;
    1035     uint32_t *pu32Lpib = 0;
    1036     if(u32Value & HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST))
    1037     {
    1038         Log(("hda: guest has initiated hw stream reset\n"));
    1039         pState->u8StreamsInReset |= HDA_STREAM_BITMASK(offset);
    1040         hdaStreamReset(pState, offset);
    1041         HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST);
    1042     }
    1043     else if (HDA_IS_STREAM_IN_RESET(pState, offset))
    1044     {
    1045         Log(("hda: guest has initiated exit of stream reset\n"));
    1046         pState->u8StreamsInReset &= ~HDA_STREAM_BITMASK(offset);
    1047         HDA_REG_IND(pState, index) &= ~HDA_REG_FIELD_FLAG_MASK(SDCTL, SRST);
    1048     }
    1049     /*
    1050      * Stopping streams we postpone up to reset exit to let HDA complete the tasks
    1051      */
    1052     switch (index)
    1053     {
    1054         case ICH6_HDA_REG_SD0CTL:
    1055             u8Strm = 0;
    1056             pBdle = &pState->stInBdle;
    1057             pu32Lpib = &SDLPIB(pState, 0);
    1058             AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(pState), fOn);
    1059             Log(("hda: DMA SD0CTL switched %s\n", fOn ? "on" : " off"));
     1056    if (fInReset)
     1057    {
     1058        /* Assert!!! Guest is resetting HDA's stream, we're expecting guest will mark stream as exit
     1059         * from reset
     1060         */
     1061        Assert((!fReset));
     1062        Log(("hda: guest initiate exit of stream reset.\n"));
     1063        goto done;
     1064    }
     1065    else if (fReset)
     1066    {
     1067        /*
     1068         * Assert!!! ICH6 datasheet 18.2.33 says that RUN bit should be cleared before initiation of reset.
     1069         */
     1070        uint8_t u8Strm = 0;
     1071        PHDABDLEDESC pBdle = NULL;
     1072        HDASTREAMTRANSFERDESC stStreamDesc;
     1073        Assert((!fInRun && !fRun));
     1074        switch (index)
     1075        {
     1076            case ICH6_HDA_REG_SD0CTL:
     1077                u8Strm = 0;
     1078                pBdle = &pState->stInBdle;
    10601079            break;
    1061         case ICH6_HDA_REG_SD4CTL:
    1062             u8Strm = 4;
    1063             pBdle = &pState->stOutBdle;
    1064 
    1065             pu32Lpib = &SDLPIB(pState, 4);
    1066             u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));
    1067             fOn = fOn && u64BaseDMA;
    1068             if (fOn)
    1069                 SDSTS(pState, 4) &= ~(1<<5);
    1070             AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(pState), fOn);
    1071             Log(("hda: DMA SD4CTL switched %s\n", fOn ? "on" : " off"));
     1080            case ICH6_HDA_REG_SD4CTL:
     1081                u8Strm = 4;
     1082                pBdle = &pState->stOutBdle;
    10721083            break;
    1073         default:
    1074             Log(("Attempt to modify DMA state on unattached SDI(%s), ignored\n", s_ichIntelHDRegMap[index].abbrev));
    1075             break;
    1076     }
    1077     if (   !fOn
    1078         && pBdle
    1079         && pu32Lpib)
    1080     {
    1081         memset(pBdle, 0, sizeof(HDABDLEDESC));
    1082         *pu32Lpib = 0;
    1083         hdaUpdatePosBuf(pState, u8Strm, 0);
    1084     }
     1084            default:
     1085                Log(("hda: changing SRST bit on non-attached stream\n"));
     1086                goto done;
     1087        }
     1088        Log(("hda: guest initiate enter to stream reset.\n"));
     1089        hdaInitTransferDescriptor(pState, pBdle, u8Strm, &stStreamDesc);
     1090        hdaStreamReset(pState, pBdle, &stStreamDesc, u8Strm);
     1091        goto done;
     1092    }
     1093
     1094    /* we enter here to change DMA states only */
     1095    if (   (fInRun && !fRun)
     1096        || (fRun && !fInRun))
     1097    {
     1098        Assert((!fReset && !fInReset));
     1099        switch (index)
     1100        {
     1101            case ICH6_HDA_REG_SD0CTL:
     1102                AUD_set_active_in(ISD0FMT_TO_AUDIO_SELECTOR(pState), fRun);
     1103            break;
     1104            case ICH6_HDA_REG_SD4CTL:
     1105                AUD_set_active_out(OSD0FMT_TO_AUDIO_SELECTOR(pState), fRun);
     1106            break;
     1107            default:
     1108                Log(("hda: changing RUN bit on non-attached stream\n"));
     1109                goto done;
     1110        }
     1111    }
     1112
     1113    done:
    10851114    rc = hdaRegWriteU24(pState, offset, index, u32Value);
    10861115    if (RT_FAILURE(rc))
     
    10921121{
    10931122    uint32_t v = HDA_REG_IND(pState, index);
    1094     v ^= (u32Value & v);
     1123    v &= ~(u32Value & v);
    10951124    HDA_REG_IND(pState, index) = v;
    10961125    hdaProcessInterrupt(pState);
    1097 #if 0
    1098     if (   v != u32Value
    1099         && (INTCTL_SALL(pState) & (1 << ((offset - 0x83) >> 5))))
    1100     {
    1101         int rc;
    1102         rc = hdaProcessInterrupt(pState);
    1103         if (RT_FAILURE(rc))
    1104             AssertRCReturn(rc, rc);
    1105     }
    1106 #endif
    11071126    return VINF_SUCCESS;
    11081127}
     1128
    11091129DECLCALLBACK(int)hdaRegWriteSDLVI(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
    11101130{
     
    12921312DECLCALLBACK(int)hdaRegWriteRIRBSTS(INTELHDLinkState* pState, uint32_t offset, uint32_t index, uint32_t u32Value)
    12931313{
    1294     uint8_t nv = u32Value;
    12951314    uint8_t v = RIRBSTS(pState);
    1296     RIRBSTS(pState) = (v ^ nv) & v;
     1315    RIRBSTS(pState) &= ~(v & u32Value);
    12971316
    12981317    return hdaProcessInterrupt(pState);
     
    13021321static void dump_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
    13031322{
     1323#if 0
    13041324    uint64_t addr;
    13051325    uint32_t len;
     
    13261346             i , counter));
    13271347    }
    1328 }
    13291348#endif
    1330 
    1331 static void fetch_bd(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint64_t u64BaseDMA)
     1349}
     1350#endif
     1351
     1352static void hdaFetchBdle(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
    13321353{
    13331354    uint8_t  bdle[16];
    1334     Assert((u64BaseDMA && pBdle && pBdle->u32BdleMaxCvi));
    1335     PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
     1355    Assert((   pStreamDesc->u64BaseDMA
     1356            && pBdle
     1357            && pBdle->u32BdleMaxCvi));
     1358    PDMDevHlpPhysRead(ICH6_HDASTATE_2_DEVINS(pState), pStreamDesc->u64BaseDMA + pBdle->u32BdleCvi*16, bdle, 16);
    13361359    pBdle->u64BdleCviAddr = *(uint64_t *)bdle;
    13371360    pBdle->u32BdleCviLen = *(uint32_t *)&bdle[8];
    13381361    pBdle->fBdleCviIoc = (*(uint32_t *)&bdle[12]) & 0x1;
    13391362#ifdef LOG_ENABLED
    1340     dump_bd(pState, pBdle, u64BaseDMA);
     1363    dump_bd(pState, pBdle, pStreamDesc->u64BaseDMA);
    13411364#endif
    13421365}
    13431366
    1344 static inline uint32_t hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32Fifos, uint32_t u32CblLimit)
     1367static inline uint32_t hdaCalculateTransferBufferLength(PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t u32SoundBackendBufferBytesAvail, uint32_t u32CblLimit)
    13451368{
    13461369    uint32_t cb2Copy;
     1370#if 0
    13471371    if (u32SoundBackendBufferBytesAvail <= u32Fifos + 1)
    13481372    {
     
    13531377        return 0;
    13541378    }
     1379#endif
    13551380    /*
    13561381     * Amounts of bytes depends on current position in buffer (u32BdleCviLen-u32BdleCviPos)
     
    13611386     * we may increase the counter in range of [0, FIFOS + 1]
    13621387     */
    1363     cb2Copy = RT_MIN(cb2Copy, u32Fifos + 1);
     1388    cb2Copy = RT_MIN(cb2Copy, pStreamDesc->u32Fifos + 1);
    13641389    Assert((u32SoundBackendBufferBytesAvail > 0));
    13651390
     
    14161441}
    14171442
    1418 static inline void hdaBackendTransferUnreported(INTELHDLinkState *pState, PHDABDLEDESC pBdle, uint8_t u8Strm, uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity)
     1443static inline void hdaBackendTransferUnreported(INTELHDLinkState *pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t cbCopied, uint32_t *pu32BackendBufferCapacity)
    14191444{
    14201445    Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
     
    14251450        *pu32BackendBufferCapacity -= cbCopied;
    14261451    Log(("hda:hdaBackendTransferUnreported: CVI (cbUnderFifoW:%d, pos:%d, len:%d)\n", pBdle->cbUnderFifoW, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
    1427     Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, u8Strm)));
    1428 }
     1452    Assert((pBdle->cbUnderFifoW <= hdaFifoWToSz(pState, pStreamDesc)));
     1453}
     1454static inline bool hdaIsTransferCountersOverlapped(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
     1455{
     1456    bool fOnBufferEdge = (   *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl
     1457                          || pBdle->u32BdleCviPos == pBdle->u32BdleCviLen);
     1458    Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
     1459    if (*pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
     1460        *pStreamDesc->pu32Lpib -= pStreamDesc->u32Cbl;
     1461    hdaUpdatePosBuf(pState, pStreamDesc);
     1462   
     1463    if (pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
     1464    {
     1465        pBdle->u32BdleCviPos = 0;
     1466        pBdle->u32BdleCvi++;
     1467        if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
     1468            pBdle->u32BdleCvi = 0;
     1469    }
     1470    return fOnBufferEdge;
     1471}
     1472
     1473static inline void hdaStreamCounterUpdate(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t cbInc)
     1474{
     1475    /*
     1476     * if we're under FIFO Watermark it's expected that HDA doesn't fetch anything.
     1477     * (ICH6 datasheet 18.2.38)
     1478     */
     1479    if (!pBdle->cbUnderFifoW)
     1480    {
     1481        *pStreamDesc->pu32Lpib += cbInc;
     1482   
     1483        /*
     1484         * Assert. Overlapping of buffer counter shouldn't happen.
     1485         */
     1486        Assert((*pStreamDesc->pu32Lpib <= pStreamDesc->u32Cbl));
     1487   
     1488        hdaUpdatePosBuf(pState, pStreamDesc);
     1489   
     1490    }
     1491}
     1492
     1493static inline bool hdaDoNextTransferCycle(PINTELHDLinkState pState, PHDABDLEDESC pBdle, PHDASTREAMTRANSFERDESC pStreamDesc)
     1494{
     1495    bool fDoNextTransferLoop = true;
     1496    if (   pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
     1497        || *pStreamDesc->pu32Lpib == pStreamDesc->u32Cbl)
     1498    {
     1499        if (    !pBdle->cbUnderFifoW
     1500             && pBdle->fBdleCviIoc)
     1501        {
     1502            /*
     1503             * @todo - more carefully investigate BCIS flag.
     1504             * Speech synthesis works fine on Mac Guest if this bit isn't set
     1505             * but in general sound quality becomes lesser.
     1506             */
     1507            *pStreamDesc->pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
     1508            /*
     1509             * we should generate the interrupt if ICE bit of SDCTL register is set.
     1510             */
     1511            if (pStreamDesc->u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
     1512                hdaProcessInterrupt(pState);
     1513        }
     1514        fDoNextTransferLoop = false;
     1515    }
     1516    return fDoNextTransferLoop;
     1517}
     1518
    14291519/*
    14301520 * hdaReadAudio - copies samples from Qemu Sound back-end to DMA.
    14311521 * Note: this function writes immediately to DMA buffer, but "reports bytes" when all conditions meet (FIFOW) 
    14321522 */
    1433 static uint32_t hdaReadAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
     1523static uint32_t hdaReadAudio(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
    14341524{
    14351525    PHDABDLEDESC pBdle = &pState->stInBdle;
     
    14401530    Log(("hda:ra: CVI(pos:%d, len:%d)\n", pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
    14411531
    1442     cb2Copy = hdaCalculateTransferBufferLength(pBdle, *pu32Avail, SDFIFOS(pState, 0), u32CblLimit);
     1532    cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
    14431533    if (!cb2Copy)
    14441534    {
     
    14651555    else
    14661556    {
    1467         hdaBackendTransferUnreported(pState, pBdle, 0, cbBackendCopy, pu32Avail);
     1557        hdaBackendTransferUnreported(pState, pBdle, pStreamDesc, cbBackendCopy, pu32Avail);
    14681558        *fStop = true;
    14691559    }
     
    14741564}
    14751565
    1476 static uint32_t hdaWriteAudio(INTELHDLinkState *pState, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
     1566static uint32_t hdaWriteAudio(INTELHDLinkState *pState, PHDASTREAMTRANSFERDESC pStreamDesc, uint32_t *pu32Avail, bool *fStop, uint32_t u32CblLimit)
    14771567{
    14781568    PHDABDLEDESC pBdle = &pState->stOutBdle;
     
    14831573    Log(("hda:wa: CVI(cvi:%d, pos:%d, len:%d)\n", pBdle->u32BdleCvi, pBdle->u32BdleCviPos, pBdle->u32BdleCviLen));
    14841574
    1485     cb2Copy = hdaCalculateTransferBufferLength(pBdle, *pu32Avail, SDFIFOS(pState, 4), u32CblLimit);
     1575    cb2Copy = hdaCalculateTransferBufferLength(pBdle, pStreamDesc, *pu32Avail, u32CblLimit);
    14861576   
    14871577    /*
     
    14981588     * Write to audio backend. we should be sure whether we have enought bytes to copy to Audio backend.
    14991589     */
    1500     if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pState, 4))
     1590    if (cb2Copy + pBdle->cbUnderFifoW >= hdaFifoWToSz(pState, pStreamDesc))
    15011591    {
    15021592        /*
     
    15091599    {
    15101600        /* Not enough bytes to be processed and reported, check luck on next enterence */
    1511         hdaBackendTransferUnreported(pState, pBdle, 4, cb2Copy, NULL);
     1601        hdaBackendTransferUnreported(pState, pBdle, pStreamDesc, cb2Copy, NULL);
    15121602        *fStop = true;
    15131603    }
     
    15251615}
    15261616
     1617static inline void hdaInitTransferDescriptor(PINTELHDLinkState pState, PHDABDLEDESC pBdle, uint8_t u8Strm, PHDASTREAMTRANSFERDESC pStreamDesc)
     1618{
     1619    Assert((   pState
     1620            && pBdle
     1621            && pStreamDesc
     1622            && u8Strm <= 7));               
     1623    memset(pStreamDesc, 0, sizeof(HDASTREAMTRANSFERDESC));
     1624    pStreamDesc->u8Strm = u8Strm;
     1625    pStreamDesc->u32Ctl = HDA_STREAM_REG2(pState, CTL, u8Strm);
     1626    pStreamDesc->u64BaseDMA = RT_MAKE_U64(HDA_STREAM_REG2(pState, BDPL, u8Strm),
     1627                                          HDA_STREAM_REG2(pState, BDPU, u8Strm));
     1628    pStreamDesc->pu32Lpib = &HDA_STREAM_REG2(pState, LPIB, u8Strm);
     1629    pStreamDesc->pu32Sts = &HDA_STREAM_REG2(pState, STS, u8Strm);
     1630    pStreamDesc->u32Cbl = HDA_STREAM_REG2(pState, CBL, u8Strm);
     1631    pStreamDesc->u32Fifos = HDA_STREAM_REG2(pState, FIFOS, u8Strm);
     1632
     1633    pBdle->u32BdleMaxCvi = HDA_STREAM_REG2(pState, LVI, u8Strm);
     1634#ifdef LOG_ENABLED
     1635    if (   pBdle
     1636        && pBdle->u32BdleMaxCvi)
     1637    {
     1638        Log(("Initialization of transfer descriptor:\n"));
     1639        dump_bd(pState, pBdle, pStreamDesc->u64BaseDMA);
     1640    }
     1641#endif
     1642}
     1643
    15271644DECLCALLBACK(void) hdaTransfer(CODECState *pCodecState, ENMSOUNDSOURCE src, int avail)
    15281645{
    15291646    bool fStop = false;
    1530     uint64_t u64BaseDMA = 0;
     1647    uint8_t u8Strm = 0;
    15311648    PHDABDLEDESC pBdle = NULL;
    15321649    INTELHDLinkState *pState = (INTELHDLinkState *)pCodecState->pHDAState;
     1650    HDASTREAMTRANSFERDESC stStreamDesc;
    15331651    uint32_t nBytes;
    1534     uint32_t u32Ctl;
    1535     uint32_t *pu32Sts;
    1536     uint8_t  u8Strm;
    1537     uint32_t *pu32Lpib;
    1538     uint32_t u32Cbl;
    1539     uint32_t u32Fifos;
    1540     uint32_t u32Fifow;
    1541     switch (src)
    1542     {
    1543         case PO_INDEX:
    1544         {
    1545             u8Strm = 4;
    1546             u32Ctl = SDCTL(pState, 4);
    1547             u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 4), SDBDPU(pState, 4));
    1548             pu32Lpib = &SDLPIB(pState, 4);
    1549             pu32Sts = &SDSTS(pState, 4);
    1550             u32Cbl = SDLCBL(pState, 4);
    1551             pBdle = &pState->stOutBdle;
    1552             pBdle->u32BdleMaxCvi = SDLVI(pState, 4);
    1553             u32Fifos = SDFIFOS(pState, 4);
    1554             u32Fifow = hdaFifoWToSz(pState, 4);
    1555             break;
    1556         }
    1557         case PI_INDEX:
    1558         {
    1559             u8Strm = 0;
    1560             u32Ctl = SDCTL(pState, 0);
    1561             pu32Lpib = &SDLPIB(pState, 0);
    1562             pu32Sts = &SDSTS(pState, 0);
    1563             u32Cbl = SDLCBL(pState, 0);
    1564             u64BaseDMA = RT_MAKE_U64(SDBDPL(pState, 0), SDBDPU(pState, 0));
    1565             pBdle = &pState->stInBdle;
    1566             pBdle->u32BdleMaxCvi = SDLVI(pState, 0);
    1567             u32Fifos = SDFIFOS(pState, 0);
    1568             u32Fifow = hdaFifoWToSz(pState, 0);
    1569             break;
    1570         }
    1571         default:
    1572             return;
    1573     }
    1574     if (   !(u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
    1575         || !avail
    1576         || !u64BaseDMA)
    1577         return;
    1578     /* Fetch the Buffer Descriptor Entry (BDE). */
    1579     fetch_bd(pState, pBdle, u64BaseDMA);
    15801652    while( avail && !fStop)
    15811653    {
    1582         *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    1583         Assert((avail >= 0 && (u32Cbl >= (*pu32Lpib)))); /* sanity */
    1584         uint32_t u32CblLimit = u32Cbl - (*pu32Lpib);
    1585         Assert((u32CblLimit > hdaFifoWToSz(pState, u8Strm)));
    1586         Log(("hda: CBL=%d, LPIB=%d\n", u32Cbl, *pu32Lpib));
    15871654        switch (src)
    15881655        {
    15891656            case PO_INDEX:
    1590                 nBytes = hdaWriteAudio(pState, (uint32_t *)&avail, &fStop, u32CblLimit);
     1657            {
     1658                u8Strm = 4;
     1659                pBdle = &pState->stOutBdle;
     1660                break;
     1661            }
     1662            case PI_INDEX:
     1663            {
     1664                u8Strm = 0;
     1665                pBdle = &pState->stInBdle;
     1666                break;
     1667            }
     1668            default:
     1669                return;
     1670        }
     1671        hdaInitTransferDescriptor(pState, pBdle, u8Strm, &stStreamDesc);
     1672        Assert (   (stStreamDesc.u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, RUN))
     1673                && avail
     1674                && stStreamDesc.u64BaseDMA);
     1675
     1676        /* Fetch the Buffer Descriptor Entry (BDE). */
     1677
     1678        if (hdaIsTransferCountersOverlapped(pState, pBdle, &stStreamDesc))
     1679            hdaFetchBdle(pState, pBdle, &stStreamDesc);
     1680        *stStreamDesc.pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     1681        Assert((avail >= 0 && (stStreamDesc.u32Cbl >= (*stStreamDesc.pu32Lpib)))); /* sanity */
     1682        uint32_t u32CblLimit = stStreamDesc.u32Cbl - (*stStreamDesc.pu32Lpib);
     1683        Assert((u32CblLimit > hdaFifoWToSz(pState, &stStreamDesc)));
     1684        Log(("hda: CBL=%d, LPIB=%d\n", stStreamDesc.u32Cbl, *stStreamDesc.pu32Lpib));
     1685        switch (src)
     1686        {
     1687            case PO_INDEX:
     1688                nBytes = hdaWriteAudio(pState, &stStreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
    15911689                break;
    15921690            case PI_INDEX:
    1593                 nBytes = hdaReadAudio(pState, (uint32_t *)&avail, &fStop, u32CblLimit);
     1691                nBytes = hdaReadAudio(pState, &stStreamDesc, (uint32_t *)&avail, &fStop, u32CblLimit);
    15941692                break;
    15951693            default:
     
    15981696                AssertMsgFailed(("Unsupported"));
    15991697        }
    1600         /*
    1601          * if we're under FIFO Watermark it's expected that HDA doesn't fetch anything.
    1602          * (ICH6 datasheet 18.2.38)
    1603          */
    1604         Assert(nBytes <= (u32Fifos + 1));
    1605         *pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
    1606         if (!pBdle->cbUnderFifoW)
    1607         {
    1608             *pu32Lpib += nBytes;
    1609 
    1610             /*
    1611              * Assert. Overlapping of buffer counter shouldn't happen.
    1612              */
    1613             Assert((*pu32Lpib <= u32Cbl));
    1614    
    1615             /* Optionally write back the current DMA position. */
    1616             hdaUpdatePosBuf(pState, u8Strm, *pu32Lpib);
    1617    
    1618         }
     1698        Assert(nBytes <= (stStreamDesc.u32Fifos + 1));
     1699        *stStreamDesc.pu32Sts &= ~HDA_REG_FIELD_FLAG_MASK(SDSTS, FIFORDY);
     1700       
    16191701        /* Process end of buffer condition. */
    1620         if (   pBdle->u32BdleCviPos == pBdle->u32BdleCviLen
    1621             || *pu32Lpib == u32Cbl)
    1622         {
    1623             if (    !pBdle->cbUnderFifoW
    1624                  && pBdle->fBdleCviIoc)
    1625             {
    1626                 /*
    1627                  * @todo - more carefully investigate BCIS flag.
    1628                  * Speech synthesis works fine on Mac Guest if this bit isn't set
    1629                  * but in general sound quality becomes lesser.
    1630                  */
    1631                 *pu32Sts |= HDA_REG_FIELD_FLAG_MASK(SDSTS, BCIS);
    1632                 /*
    1633                  * we should generate the interrupt if ICE bit of SDCTL register is set.
    1634                  */
    1635                 if (u32Ctl & HDA_REG_FIELD_FLAG_MASK(SDCTL, ICE))
    1636                     hdaProcessInterrupt(pState);
    1637             }
    1638             if (*pu32Lpib == u32Cbl)
    1639                 *pu32Lpib -= u32Cbl;
    1640             hdaUpdatePosBuf(pState, u8Strm, *pu32Lpib);
    1641 
    1642             if (pBdle->u32BdleCviPos == pBdle->u32BdleCviLen)
    1643             {
    1644                 pBdle->u32BdleCviPos = 0;
    1645                 pBdle->u32BdleCvi++;
    1646                 if (pBdle->u32BdleCvi == pBdle->u32BdleMaxCvi + 1)
    1647                     pBdle->u32BdleCvi = 0;
    1648 
    1649             }
    1650             fStop = true;
    1651         }
     1702        hdaStreamCounterUpdate(pState, pBdle, &stStreamDesc, nBytes);
     1703        fStop = !hdaDoNextTransferCycle(pState, pBdle, &stStreamDesc);
    16521704    }
    16531705}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette