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]

Reply via email to