well laddies, nick dowell has come through by managing to keep what seems to be one of the few surviving copies of AppleUSBAudio.
https://github.com/nickdowell/AppleUSBAudio-273.4.1 <https://github.com/nickdowell/AppleUSBAudio-273.4.1> i have a 27” cinema display and it uses a single engine with two streams, one input and output. i asked myself how APPUL managed to do this. well, first here’s the engine’s getCurrentSampleFrame function: https://github.com/nickdowell/AppleUSBAudio-273.4.1/blob/master/AppleUSBAudioEngine.cpp#L671 <https://github.com/nickdowell/AppleUSBAudio-273.4.1/blob/master/AppleUSBAudioEngine.cpp#L671> what they did was created an AppleUSBAudioStream class that inherits from IOAudioStream. they then defined a getCurrentSampleFrame, and call the member function on each audiostream: https://github.com/nickdowell/AppleUSBAudio-273.4.1/blob/master/AppleUSBAudioStream.cpp#L1867 <https://github.com/nickdowell/AppleUSBAudio-273.4.1/blob/master/AppleUSBAudioStream.cpp#L1867> which behaves slightly differently for the output and input stream. i guess this is similar to what devin roth (of existential.audio) was saying about creating separate engines, but with the interrupt handler i don’t know if that can work. i have more ideas now but it’s becoming clear i will have to override override the audiostream class and/or create engines to deal with multiple streams. if i can think of a way to unify the interrupt handling with different engines, then i may do that. i guess i should be happy i’m in a phase where it’s “heavy thinking”. just imagining if i had a sliver of assistance like the current group did. jeez. if i had jeff moore i’d be done already and consequently been carried on the shoulders of the taiwanese masses. oh well i should stop daydreaming ^_^ Thanks, Gagan > On Dec 21, 2022, at 8:01 PM, Gagan Sidhu via Coreaudio-api > <[email protected]> wrote: > > (sorry for the double, devin. forgot to send to the mailer). > > hi, > > i know you’re helping, so i apologise for correcting you, but this *is* a > mailing list, and, just as i found it through google, some noob may want to > leave the cave. > > as such, i believe you’re suggesting^{1} i create a separate engine for each > stream that’s clocked separately, not device, right? > -i can’t make more than one device since it’s an IOPCIDevice. > > before discussing why i don’t want to do this (not saying i refuse, just > don’t want to at this point), i wanted to ask you something if all streams > were on the same clock: > -how could returning this single UInt32 value suffice for all of the > streams? this is what i kind of struggle to wrap my head around. > -i get what you’re saying that, if all streams have the same > clock, then their positions should be the same. > - but in terms of code, how does the driver use a > single value and spread it across all of those respective streams? > - is that what it does by default? > > > ^{1} again, i’m sorry about this. i don’t _want_ to it, especially when i’m > asking for help! > > --- > re: splitting the driver into more engines > > in theory this sounds very nice but it would result in a lot of problems with > code overlap and also i disagree that others should consider this as a remedy. > > i’m not saying your suggestion wouldn’t work, but off the top-of-my-head i > would have to create redundant Engine objects just to hold a single > input/output stream. > -remember, each engine needs to have an interrupthandler/ioworkloop. > -even if i create a pseudo-engine for SPDIF for its own clock, > i think i may have problems since all of the IOWorkLoop stuff has to go > through the “main object” that handles interrupts from all sources. > > if you’re ever curious you can take a look at what i’m saying here: > https://github.com/i3roly/CMI8788/blob/master/CMI8788/XonarAudioEngine.cpp#L2453 > > <https://github.com/i3roly/CMI8788/blob/master/CMI8788/XonarAudioEngine.cpp#L2453> > -i believe you’d concur that any properly-designed audio driver must > handle all of the interrupts in a single place—i.e. the interrupt handler. > -since you’re likely (far) more experienced than i, it’s > possible having a second ioworkloop/interruptfilter for the same device may > not be as problematic as i’m thinking. > > -why didn’t APPUL foresee this possibility? to me it seems impossible they > did not. ALSA did. yeesh. > > i don’t even think the new “AudioServer”/DEXT crap has added any true > functionality to deal with this potential (massive) pitfall. > - feel free to chime in matt (mora) and correct me > > Thanks, > Gagan > > >>> On Dec 21, 2022, at 7:15 PM, Devin Roth <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> I would create a device for each stream that is clocked separately. >>> On Dec 21, 2022, 5:03 PM -0800, Gagan Sidhu via Coreaudio-api >>> <[email protected] <mailto:[email protected]>>, >>> wrote: >>>> hi, >>>> >>>> thank you for your quick and insightful response. this is the most >>>> sophisticated question i’ve been asked in terms of interfacing code with >>>> hardware (it’s “my first driver’). >>>> >>>> i am not certain this sound card (Xonar HDAV1.3 Deluxe) has a single clock >>>> because it has multiple DMA engines. >>>> >>>> from what i can gather, it may be a single clock for a few of the engines >>>> (an SPI clock) but each engine may be (is) using different periods. >>>> >>>> but for sure there is a separate “sampling clock" for the SPDIF. >>>> >>>> can we attach images on a mailing list? probably not, right? >>>> >>>> at the end of this message, i’ve included relevant portions from the >>>> specification. >>>> - i believe the term ‘codec’ is equivalent to streams. i have a maximum >>>> of 6 IOAudioStream objects, which corresponds to the codecs 0-5. >>>> -not all cards have six engines. it’s a family of cards that >>>> use a different combination of these six. >>>> >>>> man there has to be a way to do this. >>>> >>>> SPI (Serial Port Interface) Bus Control Registers >>>> >>>> PCI 98: SPI Control Register Address Offset: 98h >>>> Default Value: 00h >>>> >>>> Bit >>>> >>>> Attribute >>>> >>>> Description >>>> >>>> 7 >>>> >>>> R/W >>>> >>>> SPI CEN control >>>> 0: codec latch control data at SPI clock low (default) 1: codec latch >>>> control data at SPI clock high >>>> >>>> 6:4 >>>> >>>> R/W >>>> >>>> Codec select >>>> 000: codec 0 (XSPI_CEN0) 001: codec 1 (XSPI_CEN1) 010: codec 2 (XSPI_CEN2) >>>> 011: codec 3 (XSPI_CEN3) >>>> >>>> 100: codec 4 (XSPI_CEN4) 101: codec 5 (XSPI_CEN5) others: no use >>>> >>>> 3:2 >>>> >>>> R/W >>>> >>>> SPI clock period 00: 160 ns 01: 320 ns 10: 640 ns >>>> >>>> 11: 1280 ns (1.28 micro-second) >>>> >>>> 1 >>>> >>>> R/W >>>> >>>> The data length of read/write, 0: 2 bytes (D6-D7), 1: 3 bytes (D6-D8) >>>> >>>> 0 >>>> >>>> R/W >>>> >>>> Write 1 to trigger read/write operation, After read/write operation >>>> completes, the bit will be cleared to 0 automatically. >>>> >>>> >>>> and >>>> >>>> PCI 70: SPDIF Function Control Register Address Offset: 70-73h >>>> Default Value: 02000000h >>>> >>>> High Performance PCI Audio Controller CMI8788/CMI8787 Register >>>> Specification V.0.1 >>>> >>>> Bit >>>> >>>> Attribute >>>> >>>> Description >>>> >>>> 31:27 >>>> >>>> Reserved. >>>> >>>> 26:24 >>>> >>>> R/W >>>> >>>> SPDIF/OUT Sampling Rate (all support) >>>> >>>> SPDOSR[2:0] >>>> >>>> 000 : 001 : 010 : 011 : 100 : 101 : 110 : 111 : >>>> >>>> 32 Khz 44.1 Khz 48 Khz 64 Khz 88.2 Khz 96 Khz 176.4 Khz 192 Khz >>>> >>>> 23:17 >>>> >>>> Reserved. >>>> >>>> 16 >>>> >>>> R/W >>>> >>>> SPDIF/IN Sampling clock >>>> >>>> 1: >96khz 0: <=96khz >>>> >>>> 15 >>>> >>>> R/W/C >>>> >>>> RATE_INT, SPDIN smp rate change interrupt. Write 1 to clear >>>> >>>> 14 >>>> >>>> R/W/C >>>> >>>> LOCK_INT, Interrupt of SPDIN data is locked or not. Write 1 to clear >>>> >>>> 13 >>>> >>>> R/W/C >>>> >>>> SENSE_INT, Interrupt of SPDIN data is sensed or not. Write 1 to clear. >>>> >>>> 12 >>>> >>>> Read only >>>> >>>> LOCK_STUS, indicate SPDIN data is locked or not >>>> >>>> 11 >>>> >>>> Read only >>>> >>>> SENSE_STUS, indicate there is transition in SPDIN >>>> >>>> 10 >>>> >>>> R/W >>>> >>>> LOCK_PAR, LOCK_INTR trigger level 0: low to high, 1: high to low >>>> >>>> 9 >>>> >>>> R/W >>>> >>>> SENSE_PAR, SENSE_INTR trigger level 0: low to high; 1: high to low >>>> >>>> 7-8 >>>> >>>> Reserved >>>> >>>> 6 >>>> >>>> R/W >>>> >>>> SPDVALID, SPDIF/IN valid bit detect enabled. >>>> >>>> 5 >>>> >>>> R/W >>>> >>>> RATE_MASK, 1: RATE_INT is un-masked >>>> >>>> 4 >>>> >>>> R/W >>>> >>>> LOCK_MASK, 1: LOCK_INT is un-masked >>>> >>>> 3 >>>> >>>> R/W >>>> >>>> SENSE_MASK, 1: SENSE_INT is un-masked >>>> >>>> 2 >>>> >>>> R/W >>>> >>>> SPDFLOOPI, internal SPDIF/IN loopback to SPDIF/OUT >>>> >>>> 1 >>>> >>>> R/W >>>> >>>> ENSPDOUT, enable SPDIF/OUT to I/O Interface >>>> >>>> 0 >>>> >>>> - >>>> >>>> <page23image4076672.png> >>>> Reserved >>>> >>>> >>>> btw i do think the panic was caused by having an empty >>>> getCurrentSampleFrame since, 0x08 is the address (on the device) where the >>>> driver writes the IOBufferMemoryDescriptor’s physical address: >>>>> >>>>> Anonymous UUID: 9DD1C300-68BB-0152-2C74-E8415A6CC86C >>>>> >>>>> Wed Dec 21 16:06:45 2022 >>>>> >>>>> *** Panic Report *** >>>>> panic(cpu 0 caller 0xffffff801bcdab9d): Kernel trap at >>>>> 0xffffff801c2200c5, type 14=page fault, registers: >>>>> CR0: 0x000000008001003b, CR2: 0x0000000000000008, CR3: >>>>> 0x000000002253f000, CR4: 0x00000000000226e0 >>>>> RAX: 0x0000000000000000, RBX: 0xffffff818d9b22e0, RCX: >>>>> 0x0000000024000000, RDX: 0xffffff8110f18900 >>>>> RSP: 0xffffff8e20a1bce0, RBP: 0xffffff8e20a1bd30, RSI: >>>>> 0xffffff818d9b22e0, RDI: 0x0000000000000000 >>>>> R8: 0xffffff81927a10c0, R9: 0x0000000000000000, R10: >>>>> 0x0000000000000002, R11: 0x0000000000000000 >>>>> R12: 0xffffff81c8245140, R13: 0xffffff81c8245140, R14: >>>>> 0x0000000000000001, R15: 0xffffff8110f18900 >>>>> RFL: 0x0000000000010206, RIP: 0xffffff801c2200c5, CS: >>>>> 0x0000000000000008, SS: 0x0000000000000010 >>>>> Fault CR2: 0x0000000000000008, Error code: 0x0000000000000000, Fault CPU: >>>>> 0x0, PL: 0, VF: 1 >>>>> >>>>> Backtrace (CPU 0), Frame : Return Address >>>>> 0xffffff8e20a1b7b0 : 0xffffff801bbad5cd >>>>> 0xffffff8e20a1b800 : 0xffffff801bce9245 >>>>> 0xffffff8e20a1b840 : 0xffffff801bcda97a >>>>> 0xffffff8e20a1b8b0 : 0xffffff801bb5a9d0 >>>>> 0xffffff8e20a1b8d0 : 0xffffff801bbacfe7 >>>>> 0xffffff8e20a1b9f0 : 0xffffff801bbace33 >>>>> 0xffffff8e20a1ba60 : 0xffffff801bcdab9d >>>>> 0xffffff8e20a1bbd0 : 0xffffff801bb5a9d0 >>>>> 0xffffff8e20a1bbf0 : 0xffffff801c2200c5 >>>>> 0xffffff8e20a1bd30 : 0xffffff801c2267f7 >>>>> 0xffffff8e20a1bd80 : 0xffffff7f9d0a43d3 >>>>> 0xffffff8e20a1bdb0 : 0xffffff7fa1b5b658 >>>>> 0xffffff8e20a1bdd0 : 0xffffff7fa1b5b321 >>>>> 0xffffff8e20a1be00 : 0xffffff7f9d0a2fd2 >>>>> 0xffffff8e20a1be40 : 0xffffff801c22df6b >>>>> 0xffffff8e20a1be80 : 0xffffff801c22dc25 >>>>> 0xffffff8e20a1bf00 : 0xffffff801c22d1e7 >>>>> 0xffffff8e20a1bf50 : 0xffffff801c22ecd6 >>>>> 0xffffff8e20a1bfa0 : 0xffffff801bb5a0ce >>>>> Kernel Extensions in backtrace: >>>>> >>>>> com.apple.iokit.IOAudioFamily(206.5)[F5DBFDB4-22C9-32C1-BB72-3372EAAB1FCB]@0xffffff7f9d09f000->0xffffff7f9d0ddfff >>>>> dependency: >>>>> com.apple.vecLib.kext(1.2.0)[3B4888B9-CBFC-39DE-A8A2-1C6377702BC3]@0xffffff7f9cfcf000 >>>>> >>>>> com.CMedia.CMI8788.PCIAudioDriver(1337.0)[911B90EB-E9A8-32ED-BE28-B51438A69824]@0xffffff7fa1b58000->0xffffff7fa1c09fff >>>>> dependency: >>>>> com.apple.iokit.IOPCIFamily(2.9)[CE5E5806-48AB-39C0-8C1F-B57921B37D71]@0xffffff7f9c492000 >>>>> dependency: >>>>> com.apple.iokit.IOAudioFamily(206.5)[F5DBFDB4-22C9-32C1-BB72-3372EAAB1FCB]@0xffffff7f9d09f000 >>>>> dependency: >>>>> com.apple.kec.pthread(1)[6C7628FE-2621-3C19-B248-D4DA0D722123]@0xffffff7f9cb26000 >>>>> >>>>> BSD process name corresponding to current thread: kernel_task >>>>> Boot args: agdpmod=pikera enable-gva-support shikigva=80 unfairgva=1 >>>>> mbasd=1 -no_compat_check no32exec=0 debug=0x8 serverperfmode=1 ncl=262144 >>>>> >>>> >>>> >>>>> On Dec 21, 2022, at 5:20 PM, Devin Roth <[email protected] >>>>> <mailto:[email protected]>> wrote: >>>>> >>>>> I assume all your streams use the same clock. In that case it will be the >>>>> same for all of them. I’m pretty sure that clocks run at the device level >>>>> rather than the stream level. >>>>> >>>>> Devin >>>>> On Dec 21, 2022, 3:56 PM -0800, Gagan Sidhu via Coreaudio-api >>>>> <[email protected] <mailto:[email protected]>>, >>>>> wrote: >>>>>> hello all, >>>>>> >>>>>> so the driver completes inithardware, the streams are ready to go, but >>>>>> it’s panicking and there’s no printf to show where. >>>>>> >>>>>> 1. is it possible/likely it’s crashing because i have an empty >>>>>> getCurrentSampleFrame method? >>>>>> -probably? >>>>>> >>>>>> 2. the engine is asking me to return a single UInt32 value. what if i >>>>>> have multiple streams, though? >>>>>> -we would want to update the position of each active stream, would we >>>>>> not? >>>>>> -this would require one UInt32 per stream. >>>>>> >>>>>> this is done in the ALSA driver as follows: >>>>>> >>>>>>> static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream >>>>>>> *substream) >>>>>>> { >>>>>>> struct oxygen *chip = snd_pcm_substream_chip(substream); >>>>>>> struct snd_pcm_runtime *runtime = substream->runtime; >>>>>>> unsigned int channel = oxygen_substream_channel(substream); >>>>>>> u32 curr_addr; >>>>>>> >>>>>>> /* no spinlock, this read should be atomic */ >>>>>>> curr_addr = oxygen_read32(chip, channel_base_registers[channel]); >>>>>>> return bytes_to_frames(runtime, curr_addr - (u32)runtime->dma_addr); >>>>>>> } >>>>>>> >>>>>> >>>>>> it seems ALSA passes the stream to the function and then it can be >>>>>> updated easily. >>>>>> >>>>>> in the APPUL case, it does not seem like we know what stream we’re being >>>>>> asked to update. there are no parameters being passed. >>>>>> >>>>>> in short: how can we update the position of multiple streams using the >>>>>> existing getCurrentSampleFrame prototype? >>>>>> >>>>>> so close to getting this bad boy going (i think)!! >>>>>> >>>>>> Thanks, >>>>>> Gagan >>>>>> >>>>>> _______________________________________________ >>>>>> Do not post admin requests to the list. They will be ignored. >>>>>> Coreaudio-api mailing list ([email protected] >>>>>> <mailto:[email protected]>) >>>>>> Help/Unsubscribe/Update your Subscription: >>>>>> https://lists.apple.com/mailman/options/coreaudio-api/devinroth%40existential.audio >>>>>> >>>>>> <https://lists.apple.com/mailman/options/coreaudio-api/devinroth%40existential.audio> >>>>>> >>>>>> This email sent to [email protected] >>>>>> <mailto:[email protected]> >>>> >>>> _______________________________________________ >>>> Do not post admin requests to the list. They will be ignored. >>>> Coreaudio-api mailing list ([email protected] >>>> <mailto:[email protected]>) >>>> Help/Unsubscribe/Update your Subscription: >>>> https://lists.apple.com/mailman/options/coreaudio-api/devinroth%40existential.audio >>>> >>>> <https://lists.apple.com/mailman/options/coreaudio-api/devinroth%40existential.audio> >>>> >>>> This email sent to [email protected] >>>> <mailto:[email protected]> >> > > _______________________________________________ > Do not post admin requests to the list. They will be ignored. > Coreaudio-api mailing list ([email protected]) > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/coreaudio-api/broly%40mac.com > > This email sent to [email protected]
_______________________________________________ Do not post admin requests to the list. They will be ignored. Coreaudio-api mailing list ([email protected]) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com This email sent to [email protected]
