- Timestamp:
- Nov 27, 2019 12:10:19 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r82230 r82231 229 229 * Internal Functions * 230 230 *********************************************************************************************************************************/ 231 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis);232 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg);231 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis); 232 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg); 233 233 static void sb16CloseOut(PSB16STATE pThis); 234 234 static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis); 235 235 static void sb16TimerMaybeStop(PSB16STATE pThis); 236 236 237 238 239 static int magic_of_irq(int irq)240 {241 switch (irq)242 {243 case 5:244 return 2;245 case 7:246 return 4;247 case 9:248 return 1;249 case 10:250 return 8;251 default:252 break;253 }254 255 LogFlowFunc(("bad irq %d\n", irq));256 return 2;257 }258 259 static int irq_of_magic(int magic)260 {261 switch (magic)262 {263 case 1:264 return 9;265 case 2:266 return 5;267 case 4:268 return 7;269 case 8:270 return 10;271 default:272 break;273 }274 275 LogFlowFunc(("bad irq magic %d\n", magic));276 return -1;277 }278 237 279 238 #if 0 // unused // def DEBUG … … 927 886 pThis->cmd = -1; 928 887 return; 929 }930 931 static uint8_t sb16MixRegToVol(PSB16STATE pThis, int reg)932 {933 /* The SB16 mixer has a 0 to -62dB range in 32 levels (2dB each step).934 * We use a 0 to -96dB range in 256 levels (0.375dB each step).935 * Only the top 5 bits of a mixer register are used.936 */937 uint8_t steps = 31 - (pThis->mixer_regs[reg] >> 3);938 uint8_t vol = 255 - steps * 16 / 3; /* (2dB*8) / (0.375dB*8) */939 return vol;940 }941 942 /**943 * Returns the device's current master volume.944 *945 * @param pThis SB16 state.946 * @param pVol Where to store the master volume information.947 */948 static void sb16GetMasterVolume(PSB16STATE pThis, PPDMAUDIOVOLUME pVol)949 {950 /* There's no mute switch, only volume controls. */951 uint8_t lvol = sb16MixRegToVol(pThis, 0x30);952 uint8_t rvol = sb16MixRegToVol(pThis, 0x31);953 954 pVol->fMuted = false;955 pVol->uLeft = lvol;956 pVol->uRight = rvol;957 }958 959 /**960 * Returns the device's current output stream volume.961 *962 * @param pThis SB16 state.963 * @param pVol Where to store the output stream volume information.964 */965 static void sb16GetPcmOutVolume(PSB16STATE pThis, PPDMAUDIOVOLUME pVol)966 {967 /* There's no mute switch, only volume controls. */968 uint8_t lvol = sb16MixRegToVol(pThis, 0x32);969 uint8_t rvol = sb16MixRegToVol(pThis, 0x33);970 971 pVol->fMuted = false;972 pVol->uLeft = lvol;973 pVol->uRight = rvol;974 }975 976 static void sb16UpdateVolume(PSB16STATE pThis)977 {978 PDMAUDIOVOLUME VolMaster;979 sb16GetMasterVolume(pThis, &VolMaster);980 981 PDMAUDIOVOLUME VolOut;982 sb16GetPcmOutVolume(pThis, &VolOut);983 984 /* Combine the master + output stream volume. */985 PDMAUDIOVOLUME VolCombined;986 RT_ZERO(VolCombined);987 988 VolCombined.fMuted = VolMaster.fMuted || VolOut.fMuted;989 if (!VolCombined.fMuted)990 {991 VolCombined.uLeft = ( (VolOut.uLeft ? VolOut.uLeft : 1)992 * (VolMaster.uLeft ? VolMaster.uLeft : 1)) / PDMAUDIO_VOLUME_MAX;993 994 VolCombined.uRight = ( (VolOut.uRight ? VolOut.uRight : 1)995 * (VolMaster.uRight ? VolMaster.uRight : 1)) / PDMAUDIO_VOLUME_MAX;996 }997 998 PSB16DRIVER pDrv;999 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)1000 {1001 PPDMAUDIOSTREAM pStream = pDrv->Out.pStream;1002 if (pStream)1003 {1004 int rc2 = pDrv->pConnector->pfnStreamSetVolume(pDrv->pConnector, pStream, &VolCombined);1005 AssertRC(rc2);1006 }1007 }1008 888 } 1009 889 … … 1244 1124 } 1245 1125 1126 1127 /* -=-=-=-=-=- Mixer -=-=-=-=-=- */ 1128 1129 static uint8_t sb16MixRegToVol(PSB16STATE pThis, int reg) 1130 { 1131 /* The SB16 mixer has a 0 to -62dB range in 32 levels (2dB each step). 1132 * We use a 0 to -96dB range in 256 levels (0.375dB each step). 1133 * Only the top 5 bits of a mixer register are used. 1134 */ 1135 uint8_t steps = 31 - (pThis->mixer_regs[reg] >> 3); 1136 uint8_t vol = 255 - steps * 16 / 3; /* (2dB*8) / (0.375dB*8) */ 1137 return vol; 1138 } 1139 1140 /** 1141 * Returns the device's current master volume. 1142 * 1143 * @param pThis SB16 state. 1144 * @param pVol Where to store the master volume information. 1145 */ 1146 static void sb16GetMasterVolume(PSB16STATE pThis, PPDMAUDIOVOLUME pVol) 1147 { 1148 /* There's no mute switch, only volume controls. */ 1149 uint8_t lvol = sb16MixRegToVol(pThis, 0x30); 1150 uint8_t rvol = sb16MixRegToVol(pThis, 0x31); 1151 1152 pVol->fMuted = false; 1153 pVol->uLeft = lvol; 1154 pVol->uRight = rvol; 1155 } 1156 1157 /** 1158 * Returns the device's current output stream volume. 1159 * 1160 * @param pThis SB16 state. 1161 * @param pVol Where to store the output stream volume information. 1162 */ 1163 static void sb16GetPcmOutVolume(PSB16STATE pThis, PPDMAUDIOVOLUME pVol) 1164 { 1165 /* There's no mute switch, only volume controls. */ 1166 uint8_t lvol = sb16MixRegToVol(pThis, 0x32); 1167 uint8_t rvol = sb16MixRegToVol(pThis, 0x33); 1168 1169 pVol->fMuted = false; 1170 pVol->uLeft = lvol; 1171 pVol->uRight = rvol; 1172 } 1173 1174 static void sb16UpdateVolume(PSB16STATE pThis) 1175 { 1176 PDMAUDIOVOLUME VolMaster; 1177 sb16GetMasterVolume(pThis, &VolMaster); 1178 1179 PDMAUDIOVOLUME VolOut; 1180 sb16GetPcmOutVolume(pThis, &VolOut); 1181 1182 /* Combine the master + output stream volume. */ 1183 PDMAUDIOVOLUME VolCombined; 1184 RT_ZERO(VolCombined); 1185 1186 VolCombined.fMuted = VolMaster.fMuted || VolOut.fMuted; 1187 if (!VolCombined.fMuted) 1188 { 1189 VolCombined.uLeft = ( (VolOut.uLeft ? VolOut.uLeft : 1) 1190 * (VolMaster.uLeft ? VolMaster.uLeft : 1)) / PDMAUDIO_VOLUME_MAX; 1191 1192 VolCombined.uRight = ( (VolOut.uRight ? VolOut.uRight : 1) 1193 * (VolMaster.uRight ? VolMaster.uRight : 1)) / PDMAUDIO_VOLUME_MAX; 1194 } 1195 1196 PSB16DRIVER pDrv; 1197 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1198 { 1199 PPDMAUDIOSTREAM pStream = pDrv->Out.pStream; 1200 if (pStream) 1201 { 1202 int rc2 = pDrv->pConnector->pfnStreamSetVolume(pDrv->pConnector, pStream, &VolCombined); 1203 AssertRC(rc2); 1204 } 1205 } 1206 } 1207 1246 1208 static void sb16MixerReset(PSB16STATE pThis) 1247 1209 { … … 1277 1239 /* Update the master (mixer) and PCM out volumes. */ 1278 1240 sb16UpdateVolume(pThis); 1241 } 1242 1243 static int magic_of_irq(int irq) 1244 { 1245 switch (irq) 1246 { 1247 case 5: 1248 return 2; 1249 case 7: 1250 return 4; 1251 case 9: 1252 return 1; 1253 case 10: 1254 return 8; 1255 default: 1256 break; 1257 } 1258 1259 LogFlowFunc(("bad irq %d\n", irq)); 1260 return 2; 1261 } 1262 1263 static int irq_of_magic(int magic) 1264 { 1265 switch (magic) 1266 { 1267 case 1: 1268 return 9; 1269 case 2: 1270 return 5; 1271 case 4: 1272 return 7; 1273 case 8: 1274 return 10; 1275 default: 1276 break; 1277 } 1278 1279 LogFlowFunc(("bad irq magic %d\n", magic)); 1280 return -1; 1279 1281 } 1280 1282 … … 1509 1511 } 1510 1512 1511 /** 1512 * Called by sb16DMARead. 1513 1514 /* -=-=-=-=-=- DMA -=-=-=-=-=- */ 1515 1516 /** 1517 * Worker for sb16DMARead. 1513 1518 */ 1514 1519 static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos, uint32_t dma_len, int len) … … 1579 1584 * Worker callback for both DMA channels.} 1580 1585 */ 1581 static DECLCALLBACK(uint32_t) sb16DMARead(PPDMDEVINS pDevIns, void *opaque, unsigned nchan, uint32_t dma_pos, uint32_t dma_len) 1586 static DECLCALLBACK(uint32_t) sb16DMARead(PPDMDEVINS pDevIns, void *pvUser, unsigned uChannel, uint32_t off, uint32_t cb) 1587 1582 1588 { 1583 1589 RT_NOREF(pDevIns); 1584 PSB16STATE pThis = (PSB16STATE) opaque;1590 PSB16STATE pThis = (PSB16STATE)pvUser; 1585 1591 int till, copy, written, free; 1586 1592 1587 1593 if (pThis->block_size <= 0) 1588 1594 { 1589 LogFlowFunc(("invalid block size=%d nchan=%d dma_pos=%d dma_len=%d\n", 1590 pThis->block_size, nchan, dma_pos, dma_len)); 1591 return dma_pos; 1595 LogFlowFunc(("invalid block size=%d uChannel=%d off=%d cb=%d\n", pThis->block_size, uChannel, off, cb)); 1596 return off; 1592 1597 } 1593 1598 … … 1595 1600 pThis->left_till_irq = pThis->block_size; 1596 1601 1597 free = dma_len;1602 free = cb; 1598 1603 1599 1604 copy = free; … … 1601 1606 1602 1607 #ifdef DEBUG_SB16_MOST 1603 LogFlowFunc(("pos:%06d %d till:%d len:%d\n", dma_pos, free, till, dma_len));1608 LogFlowFunc(("pos:%06d %d till:%d len:%d\n", off, free, till, cb)); 1604 1609 #endif 1605 1610 … … 1617 1622 } 1618 1623 1619 written = sb16WriteAudio(pThis, nchan, dma_pos, dma_len, copy);1620 dma_pos = (dma_pos + written) % dma_len;1624 written = sb16WriteAudio(pThis, uChannel, off, cb, copy); 1625 off = (off + written) % cb; 1621 1626 pThis->left_till_irq -= written; 1622 1627 1623 1628 if (pThis->left_till_irq <= 0) 1624 1629 { 1625 pThis->mixer_regs[0x82] |= ( nchan& 4) ? 2 : 1;1630 pThis->mixer_regs[0x82] |= (uChannel & 4) ? 2 : 1; 1626 1631 PDMDevHlpISASetIrq(pThis->pDevInsR3, pThis->irq, 1); 1627 1632 if (0 == pThis->dma_auto) … … 1633 1638 1634 1639 Log3Func(("pos %d/%d free %5d till %5d copy %5d written %5d block_size %5d\n", 1635 dma_pos, dma_len, free, pThis->left_till_irq, copy, written, pThis->block_size));1640 off, cb, free, pThis->left_till_irq, copy, written, pThis->block_size)); 1636 1641 1637 1642 while (pThis->left_till_irq <= 0) 1638 1643 pThis->left_till_irq += pThis->block_size; 1639 1644 1640 return dma_pos; 1641 } 1645 return off; 1646 } 1647 1648 1649 /* -=-=-=-=-=- I/O timer -=-=-=-=-=- */ 1642 1650 1643 1651 static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis) … … 1741 1749 } 1742 1750 } 1751 1752 1753 /* -=-=-=-=-=- Streams? -=-=-=-=-=- */ 1754 1755 /** 1756 * Creates a PDM audio stream for a specific driver. 1757 * 1758 * @returns IPRT status code. 1759 * @param pCfg Stream configuration to use. 1760 * @param pDrv Driver stream to create PDM stream for. 1761 */ 1762 static int sb16CreateDrvStream(PPDMAUDIOSTREAMCFG pCfg, PSB16DRIVER pDrv) 1763 { 1764 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER); 1765 Assert(DrvAudioHlpStreamCfgIsValid(pCfg)); 1766 1767 PPDMAUDIOSTREAMCFG pCfgHost = DrvAudioHlpStreamCfgDup(pCfg); 1768 if (!pCfgHost) 1769 return VERR_NO_MEMORY; 1770 1771 LogFunc(("[LUN#%RU8] %s\n", pDrv->uLUN, pCfgHost->szName)); 1772 1773 AssertMsg(pDrv->Out.pStream == NULL, ("[LUN#%RU8] Driver stream already present when it must not\n", pDrv->uLUN)); 1774 1775 /* Disable pre-buffering for SB16; not needed for that bit of data. */ 1776 pCfgHost->Backend.cfPreBuf = 0; 1777 1778 int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream); 1779 if (RT_SUCCESS(rc)) 1780 { 1781 pDrv->pConnector->pfnStreamRetain(pDrv->pConnector, pDrv->Out.pStream); 1782 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc)); 1783 } 1784 1785 DrvAudioHlpStreamCfgFree(pCfgHost); 1786 1787 return rc; 1788 } 1789 1790 /** 1791 * Destroys a PDM audio stream of a specific driver. 1792 * 1793 * @param pThis SB16 state. 1794 * @param pDrv Driver stream to destroy PDM stream for. 1795 */ 1796 static void sb16DestroyDrvStream(PSB16STATE pThis, PSB16DRIVER pDrv) 1797 { 1798 AssertPtr(pThis); 1799 AssertPtr(pDrv); 1800 1801 if (pDrv->Out.pStream) 1802 { 1803 pDrv->pConnector->pfnStreamRelease(pDrv->pConnector, pDrv->Out.pStream); 1804 1805 int rc2 = pDrv->pConnector->pfnStreamControl(pDrv->pConnector, pDrv->Out.pStream, PDMAUDIOSTREAMCMD_DISABLE); 1806 AssertRC(rc2); 1807 1808 rc2 = pDrv->pConnector->pfnStreamDestroy(pDrv->pConnector, pDrv->Out.pStream); 1809 AssertRC(rc2); 1810 1811 pDrv->Out.pStream = NULL; 1812 } 1813 } 1814 1815 /** 1816 * Checks if the output stream needs to be (re-)created and does so if needed. 1817 * 1818 * @return VBox status code. 1819 * @param pDevIns The device instance. 1820 * @param pThis SB16 state. 1821 */ 1822 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis) 1823 { 1824 AssertPtr(pThis); 1825 1826 int rc = VINF_SUCCESS; 1827 1828 if (pThis->freq > 0) 1829 { 1830 /* At the moment we only have one stream, the output stream. */ 1831 PDMAUDIOSTREAMCFG Cfg; 1832 RT_ZERO(Cfg); 1833 1834 Cfg.Props.uHz = pThis->freq; 1835 Cfg.Props.cChannels = 1 << pThis->fmt_stereo; 1836 Cfg.Props.cBytes = pThis->fmt_bits / 8; 1837 Cfg.Props.fSigned = RT_BOOL(pThis->fmt_signed); 1838 Cfg.Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(Cfg.Props.cBytes, Cfg.Props.cChannels); 1839 1840 if (!DrvAudioHlpPCMPropsAreEqual(&Cfg.Props, &pThis->Out.Cfg.Props)) 1841 { 1842 Cfg.enmDir = PDMAUDIODIR_OUT; 1843 Cfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 1844 Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 1845 1846 strcpy(Cfg.szName, "Output"); 1847 1848 sb16CloseOut(pThis); 1849 1850 rc = sb16OpenOut(pDevIns, pThis, &Cfg); 1851 AssertRC(rc); 1852 } 1853 } 1854 else 1855 sb16CloseOut(pThis); 1856 1857 LogFlowFuncLeaveRC(rc); 1858 return rc; 1859 } 1860 1861 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg) 1862 { 1863 LogFlowFuncEnter(); 1864 AssertPtr(pThis); 1865 AssertPtr(pCfg); 1866 1867 if (!DrvAudioHlpStreamCfgIsValid(pCfg)) 1868 return VERR_INVALID_PARAMETER; 1869 1870 int rc = DrvAudioHlpStreamCfgCopy(&pThis->Out.Cfg, pCfg); 1871 if (RT_SUCCESS(rc)) 1872 { 1873 /* Set scheduling hint (if available). */ 1874 if (pThis->cTicksTimerIOInterval) 1875 pThis->Out.Cfg.Device.uSchedulingHintMs = 1000 /* ms */ 1876 / ( PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) 1877 / RT_MIN(pThis->cTicksTimerIOInterval, 1)); 1878 1879 PSB16DRIVER pDrv; 1880 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1881 { 1882 int rc2 = sb16CreateDrvStream(&pThis->Out.Cfg, pDrv); 1883 if (RT_FAILURE(rc2)) 1884 LogFunc(("Attaching stream failed with %Rrc\n", rc2)); 1885 1886 /* Do not pass failure to rc here, as there might be drivers which aren't 1887 * configured / ready yet. */ 1888 } 1889 1890 sb16UpdateVolume(pThis); 1891 } 1892 1893 LogFlowFuncLeaveRC(rc); 1894 return rc; 1895 } 1896 1897 static void sb16CloseOut(PSB16STATE pThis) 1898 { 1899 LogFlowFuncEnter(); 1900 AssertPtr(pThis); 1901 1902 PSB16DRIVER pDrv; 1903 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1904 { 1905 sb16DestroyDrvStream(pThis, pDrv); 1906 } 1907 1908 LogFlowFuncLeave(); 1909 } 1910 1911 1912 /* -=-=-=-=-=- Saved state -=-=-=-=-=- */ 1743 1913 1744 1914 /** … … 1949 2119 } 1950 2120 1951 /** 1952 * Creates a PDM audio stream for a specific driver. 1953 * 1954 * @returns IPRT status code. 1955 * @param pCfg Stream configuration to use. 1956 * @param pDrv Driver stream to create PDM stream for. 1957 */ 1958 static int sb16CreateDrvStream(PPDMAUDIOSTREAMCFG pCfg, PSB16DRIVER pDrv) 1959 { 1960 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER); 1961 Assert(DrvAudioHlpStreamCfgIsValid(pCfg)); 1962 1963 PPDMAUDIOSTREAMCFG pCfgHost = DrvAudioHlpStreamCfgDup(pCfg); 1964 if (!pCfgHost) 1965 return VERR_NO_MEMORY; 1966 1967 LogFunc(("[LUN#%RU8] %s\n", pDrv->uLUN, pCfgHost->szName)); 1968 1969 AssertMsg(pDrv->Out.pStream == NULL, ("[LUN#%RU8] Driver stream already present when it must not\n", pDrv->uLUN)); 1970 1971 /* Disable pre-buffering for SB16; not needed for that bit of data. */ 1972 pCfgHost->Backend.cfPreBuf = 0; 1973 1974 int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream); 1975 if (RT_SUCCESS(rc)) 1976 { 1977 pDrv->pConnector->pfnStreamRetain(pDrv->pConnector, pDrv->Out.pStream); 1978 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc)); 1979 } 1980 1981 DrvAudioHlpStreamCfgFree(pCfgHost); 1982 1983 return rc; 1984 } 1985 1986 /** 1987 * Destroys a PDM audio stream of a specific driver. 1988 * 1989 * @param pThis SB16 state. 1990 * @param pDrv Driver stream to destroy PDM stream for. 1991 */ 1992 static void sb16DestroyDrvStream(PSB16STATE pThis, PSB16DRIVER pDrv) 1993 { 1994 AssertPtr(pThis); 1995 AssertPtr(pDrv); 1996 1997 if (pDrv->Out.pStream) 1998 { 1999 pDrv->pConnector->pfnStreamRelease(pDrv->pConnector, pDrv->Out.pStream); 2000 2001 int rc2 = pDrv->pConnector->pfnStreamControl(pDrv->pConnector, pDrv->Out.pStream, PDMAUDIOSTREAMCMD_DISABLE); 2002 AssertRC(rc2); 2003 2004 rc2 = pDrv->pConnector->pfnStreamDestroy(pDrv->pConnector, pDrv->Out.pStream); 2005 AssertRC(rc2); 2006 2007 pDrv->Out.pStream = NULL; 2008 } 2009 } 2010 2011 /** 2012 * Checks if the output stream needs to be (re-)created and does so if needed. 2013 * 2014 * @return VBox status code. 2015 * @param pDevIns The device instance. 2016 * @param pThis SB16 state. 2017 */ 2018 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis) 2019 { 2020 AssertPtr(pThis); 2021 2022 int rc = VINF_SUCCESS; 2023 2024 if (pThis->freq > 0) 2025 { 2026 /* At the moment we only have one stream, the output stream. */ 2027 PDMAUDIOSTREAMCFG Cfg; 2028 RT_ZERO(Cfg); 2029 2030 Cfg.Props.uHz = pThis->freq; 2031 Cfg.Props.cChannels = 1 << pThis->fmt_stereo; 2032 Cfg.Props.cBytes = pThis->fmt_bits / 8; 2033 Cfg.Props.fSigned = RT_BOOL(pThis->fmt_signed); 2034 Cfg.Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(Cfg.Props.cBytes, Cfg.Props.cChannels); 2035 2036 if (!DrvAudioHlpPCMPropsAreEqual(&Cfg.Props, &pThis->Out.Cfg.Props)) 2037 { 2038 Cfg.enmDir = PDMAUDIODIR_OUT; 2039 Cfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 2040 Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 2041 2042 strcpy(Cfg.szName, "Output"); 2043 2044 sb16CloseOut(pThis); 2045 2046 rc = sb16OpenOut(pDevIns, pThis, &Cfg); 2047 AssertRC(rc); 2048 } 2049 } 2050 else 2051 sb16CloseOut(pThis); 2052 2053 LogFlowFuncLeaveRC(rc); 2054 return rc; 2055 } 2056 2057 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg) 2058 { 2059 LogFlowFuncEnter(); 2060 AssertPtr(pThis); 2061 AssertPtr(pCfg); 2062 2063 if (!DrvAudioHlpStreamCfgIsValid(pCfg)) 2064 return VERR_INVALID_PARAMETER; 2065 2066 int rc = DrvAudioHlpStreamCfgCopy(&pThis->Out.Cfg, pCfg); 2067 if (RT_SUCCESS(rc)) 2068 { 2069 /* Set scheduling hint (if available). */ 2070 if (pThis->cTicksTimerIOInterval) 2071 pThis->Out.Cfg.Device.uSchedulingHintMs = 1000 /* ms */ 2072 / ( PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) 2073 / RT_MIN(pThis->cTicksTimerIOInterval, 1)); 2074 2075 PSB16DRIVER pDrv; 2076 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2077 { 2078 int rc2 = sb16CreateDrvStream(&pThis->Out.Cfg, pDrv); 2079 if (RT_FAILURE(rc2)) 2080 LogFunc(("Attaching stream failed with %Rrc\n", rc2)); 2081 2082 /* Do not pass failure to rc here, as there might be drivers which aren't 2083 * configured / ready yet. */ 2084 } 2085 2086 sb16UpdateVolume(pThis); 2087 } 2088 2089 LogFlowFuncLeaveRC(rc); 2090 return rc; 2091 } 2092 2093 static void sb16CloseOut(PSB16STATE pThis) 2094 { 2095 LogFlowFuncEnter(); 2096 AssertPtr(pThis); 2097 2098 PSB16DRIVER pDrv; 2099 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2100 { 2101 sb16DestroyDrvStream(pThis, pDrv); 2102 } 2103 2104 LogFlowFuncLeave(); 2105 } 2106 2121 2122 /* -=-=-=-=-=- IBase -=-=-=-=-=- */ 2107 2123 2108 2124 /** … … 2118 2134 } 2119 2135 2136 2137 /* -=-=-=-=-=- Device -=-=-=-=-=- */ 2120 2138 2121 2139 /** … … 2422 2440 AssertRCReturn(rc, rc); 2423 2441 pThis->cTicksTimerIOInterval = PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) / uTimerHz; 2424 pThis->tsTimerIO = PDMDevHlpTimerGet(pDevIns, pThis->hTimerIO);2442 pThis->tsTimerIO = PDMDevHlpTimerGet(pDevIns, pThis->hTimerIO); 2425 2443 LogFunc(("Timer ticks=%RU64 (%RU16 Hz)\n", pThis->cTicksTimerIOInterval, uTimerHz)); 2426 2444
Note:
See TracChangeset
for help on using the changeset viewer.