Repository navigation
ASoC:hdac_hda: use correct format to setup hda codec - #649
Conversation
There was a problem hiding this comment.
Sorry, I don't quite get the issue here nor if your fix is correct
In the prepare step, you configure the codec with a call to snd_hda_codec_prepare. If the fixup changes the format, and you don't reconfigure the codec, then something is very wrong.
Can you please clarify which fixups you are using for capture and how come they change the format?
SOF provide ops function: sof_pcm_dai_link_fixup for be_hw_params_fixup. If our BE format is 24bit, hw params would be changed to 24bit in sof_pcm_dai_link_fixup even stream format is 16bit. For I2S case, all the codec driver in ASoC provide ops for hw_params, so the format changed by fixup function could be set to codec correctly by hw_params following fixup function. For hda case, hdac_hda doesn't provide hw_params function and only get format from runtime. For BE format of 24 bits, if a 16 bits stream is played, SOF would set hda registers in intel IP to 24bit, but codec is set to 16 bits, then only zero data is gotten by arecord. Actually hdac_hdmi provides hw_params function and gets correct format. |
|
@RanderWang I appreciate the explanations, so now I get the SOF-specific part. I still don't get how this works if you configure the codec in .prepare and then change the format in .hw_params without reconfiguring the codec after the fixup. Something's not adding up. |
@plbossart The function hw_params and prepare are called by user mode application by IOCTL. https://vovkos.github.io/doxyrest/samples/alsa/page_pcm.html |
|
Sorry, this is still very unclear. I now get the point that using the information in the PCM runtime is not good enough, the hw_params needs to be invoked. I don't get at all why you need a .prepare and why it necessary to keep this two-level solution with information saved during the .hw_params reused in the .prepare. the stream_tag is allocated on an open, so this feels like a work-around due to an SOF issue. |
I get your idea: you don't want .prepare function, just use .hw_params? right ? |
|
@plbossart steam_tag is allocated by hdac_hda_dai_set_tdm_slot. So now I understand why author didn't do it in hw_params as usually, it is for stream_tag. And And I prepare another solution for this: RanderWang@a5fd59f. |
|
@RanderWang I am still not clear, sorry. I get the flow and the fact that the stream tag isn't allocated, but why is the current solution an issue only on capture? It feels like even the playback should not work without this fix but it does, so there is still something magical about the stream management. |
Yes, I checked it on SST driver, no problem. And The PR also improves playback. Without it, there is some faint noise in one side of headphone for the music file I often use. First, I think this is caused by my board. And I change another music file, I get great noise in one side of headphone. With this PR, all noise disappears. I will update my commit message for it. |
plbossart
left a comment
There was a problem hiding this comment.
Please update the commit message along the following lines. You've got to be more direct on
- what is the issue
- what is the root cause
- how it's fixed and why you selected this implementation over alternatives
- how it's been tested.
e.g.
The current implementation of the hdac_hda codec results in zero-valued samples on capture and noise with headset playback when SOF is used on platforms with an on-board HDaudio codec. This is root-caused to SOF using be_hw_params_fixup, and the prepare() call using invalid runtime fields to determine the format.
This patch moves the format handling to the hw_params() callback, as done already for hdac_hdmi, to make sure the fixed-up information is taken into account but keeps the codec initialization in prepare() as the stream_tag is only available at that time. Moving everything in the prepare() callback is possible but the code is less elegant so this two-step solution was chosen.
The solution was tested with the SST driver with no regressions, and all the issues with SOF playback and capture are solved.
The current implementation of the hdac_hda codec results in zero-valued samples on capture and noise with headset playback when SOF is used on platforms with an on-board HDaudio codec. This is root-caused to SOF using be_hw_params_fixup, and the prepare() call using invalid runtime fields to determine the format. This patch moves the format handling to the hw_params() callback, as done already for hdac_hdmi, to make sure the fixed-up information is taken into account but keeps the codec initialization in prepare() as the stream_tag is only available at that time. Moving everything in the prepare() callback is possible but the code is less elegant so this two-step solution was chosen. The solution was tested with the SST driver with no regressions, and all the issues with SOF playback and capture are solved. Signed-off-by: Rander Wang <rander.wang@linux.intel.com>
|
@plbossart Thanks! I study your commit message and it is a good example for me. |
plbossart
left a comment
There was a problem hiding this comment.
Thanks @RanderWang, please send to alsa-devel.
|
Thanks! I will do it next week for it is slow to update kernel git in china. |
|
@plbossart Done! thanks! |
Hw params may be changed by be_hw_params_fixup, so it is
not correct to calculate format based on runtime information.
This makes arecord get only zero data on hda platforms.
In ASoC, hw params would be applied to be cpu dai and codec
dai by hw_params ops after it is changed by be_hw_params_fixup.
Now calculate format value in hw_params in hdac like hdac_hdmi
and other codec drivers.
Signed-off-by: Rander Wang rander.wang@linux.intel.com