I wrote code for PCM streams, which I'd like to discuss here. But since it isn't
really complete yet, I thought I'd ask if I can copy paste the functions that I want to ask
about and clear things that way.
For now I will just write my queries here and try to explain them as best as I can.
Starting off with the get config function for pcm streams. Initially I thought I
was supposed to store those configs in the VirtIOSound struct but then I realized
these configurations should be queried from the backend and then be presented to the driver/guest.
Now, the virtio sound card supports multiple formats and bit rates. If we have fixed settings
turned on in the audiodev, the virtio sound card should support only a single freq and frame rate
depending upon what was passed to the command line which we can get from audio_get_pdo_out.
Is this correct?
Secondly if fixed settings was not set, what should the get config query return with for supported
formats and bitrates? For now I am returning the formats defined in the enum for the qemu
audio subsystem. I read in the man pages that if the mixing engine is off, qemu assumes that
the backend supports the the multiple streams and channels that are supported by the
virtual card. So should I return everything that the virito sound card can support?
Thirdly, for the set params function, how do I change the params for an SWVoiceOut stream? I could
not find a function for changing the audsettings for a stream. Should I close the stream and
reopen it? Should I directly change the values in the pcm info struct inside the stream?
I learned that the callback passed in AUD_open_out, (lets call it the write audio callback,) is supposed to mix and write the
buffers to HWVoiceOut. I have written that, the basic algorithm being:
1. Pop element from tx virtqueue.
2. Get the xfer header from the elem->out_sg (iov_to_buf(elem->out_sg, 1, 0, &hdr, sizeof(hdr)))
3. Get the buffer from elem->out_sg (iov_to_buf(elem->out_sg, 1, sizeof(hdr), &mixbuf, period_bytes))
4. AUD_write the buffer
5. Initialize an VIRTIO_SND_S_OK response.
6. Write the response to elem->in_sg (iov_from_buf(elem->in_sg, elem->in_num, 0, &resp, sizeof(resp)))
7. If tx queue is not empty go back to step 1.
I think I can send a period elapsed notification too after reading period_bytes from the tx_virtqueue.
Will this be enough? From other sound card implementations I found out about a lot of pointers which
I think were read and write pointers for the buffer. But since we are doing this via a virtqueue, I don't
feel as if those pointers will be necessary.
Also I do not understand what the tx virtqueue handler is supposed to do. I have written a handler
for the control queue. But I don't know what to do about the tx queue for now. I thought it would be
something similar to what the callback does, it wouldn't play the audio though.
Also since the callback does so many things, I do not understand how I can implement the
pcm stream prepare, start, stop and release functions. The prepare function is supposed to
allocate resources for the stream, but we already do that in the realize_fn for the device
(AUD_open_out). So should I move that part out of the realize function and into the prepare
stream function? I can then have the write audio callback called in the start stream function.
The release function would just g_free the stream. This version would have set_params store
the params of the streams in the device itself, or in a new device state structure. Then when
prepare is called for a stream, we use the stored audsettings for AUD_open_out. The start
function would simply call the virtio_snd_callback and write the audio using AUD_write. I still
do not know what I would have to write in the stop stream function.
Another thing that I wanted to ask was about the hda codec. The specification mentions that
the virtio sound card has a single codec device in it. I saw a lot of codec device related code
in hda-codec.c which I think can be re-used for this. But there were no headers that exposed
the code elsewhere. After reading through the hda specification I realized that these function
group nids all come under the codec, so the jacks will be pin widgets attached to this codec.
And the streams will be the streams associated with this codec. But I do not understand how
I should go about implementing the codec, or if I need to implement it considering the
already existing source from intel-hda and hda-codec.c.
Also sorry for the late response, I had fallen ill. Also I had to move thrice in the past
month, so I couldn't really work on this a lot, and I didn't want to write a mail without
having any work to show to you guys. Thanks a lot for being patient with me. :)