On Sat, 04 Feb 2017 00:22:00 +0100, Pierre-Louis Bossart wrote:
On 02/03/2017 02:11 PM, Takashi Iwai wrote:
On Fri, 03 Feb 2017 20:47:55 +0100, Pierre-Louis Bossart wrote:
On 2/3/17 10:44 AM, Takashi Iwai wrote:
This is again a big rewrite of the driver; now it touches the code to process PCM stream transfers.
The most fundamental change is that now the driver supports more than four periods. Instead of keeping the same index between the ring buffers (from A to D) and the PCM buffer periods, now we keep difference indices for both. Also, for the cases with less periods than four, we track the head index, too. That is, we now have four indices: ringbuf_head, pcm_head, ringbuf_filled, and pcm_filled.
Well that's not completely right. The DMA can only generate an interrupt once the buffer you submit was played, and with 4 descriptors you can't have more than 4 points where interrupts are generated. If you program different values in different descriptors then the notion of periodic hardware interrupts will be lost.
There is a standard trick such as used for ICH or other drivers. With this kind of hardware, the address to be written to each buffer descriptor can be changed dynamically while streaming. (BTW, on some hardware like HD-audio, it's not allowed, but HD-audio has a larger table, so it doesn't matter.)
That is, each BD maps to each period on the PCM buffer, and it moves there. A picture like below would illustrate:
At time=0
PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1| BD | A | B | C | D |
At time=1 (period elapsed)
PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1| BD | B | C | D | A |
At time=2
PCM | 0 | 1 | 2 | 3 | 4 | 5 | .... |n-1| BD | C | D | A | B |
Yes I thought this was a case of a moving window being used but what sort of application needs this? I never understood the benefits of expanding the number of periods, it just forces additional wake-ups for no good reason. It's really silly from a power perspective.
The usage like dmix requires more periods for more finer wakeups. With the old driver with the fixed 4 periods, dmix doesn't work properly. The dmix needs the synced timing control over multiple streams, and the period wakeup is used. It could be rewritten with POSIX timer, but it'd make things a bit complicated.
and so on.
For the case periods < 4, it works other way round:
t=0 PCM | 0 | 1 | BD | A | B | - | - |
t=1 PCM | 1 | 0 | BD | - | B | C | - |
t=2 PCM | 0 | 1 | BD | - | - | C | D |
it can be done this way but I don't believe this is required. I think you can mark 2 descriptors as invalid and use only two, i.e. to follow your example you'd loop on A-B. The hardware will loop on the 4 descriptors, ignore the invalid ones and stop if it can't find a valid one.
Ah, that's good to know. So I just keep to set the rest invalid. (The code change would be likely only one or two line reduction, though :)
thanks,
Takashi