drivers: dma: intel-adsp-hda: Correct DGCS:SCS bit for 32bit sample size

If the channel was used for 16bit in the once, subsequent 32bit sample size
audio will be broken since the SCS bit remains set.

Example sequence with SOF:
normal audio playback with 16bit
ChainDMA audio playback with 16bit
normal audio playback with 16bit

The last playback results garbled audio.

Introduce intel_adsp_hda_set_sample_container_size() helper function
to handle the SCS bit and use it in the driver.


Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
This commit is contained in:
Peter Ujfalusi 2023-10-11 08:19:00 +03:00 committed by Johan Hedberg
commit 8dfa116750
2 changed files with 32 additions and 16 deletions

View file

@ -53,10 +53,8 @@ int intel_adsp_hda_dma_host_in_config(const struct device *dev,
*DGMBS(cfg->base, cfg->regblock_size, channel) = *DGMBS(cfg->base, cfg->regblock_size, channel) =
blk_cfg->block_size & HDA_ALIGN_MASK; blk_cfg->block_size & HDA_ALIGN_MASK;
if (dma_cfg->source_data_size <= 3) { intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel,
/* set the sample container set bit to 16bits */ dma_cfg->source_data_size);
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
}
} }
return res; return res;
@ -90,10 +88,8 @@ int intel_adsp_hda_dma_host_out_config(const struct device *dev,
*DGMBS(cfg->base, cfg->regblock_size, channel) = *DGMBS(cfg->base, cfg->regblock_size, channel) =
blk_cfg->block_size & HDA_ALIGN_MASK; blk_cfg->block_size & HDA_ALIGN_MASK;
if (dma_cfg->dest_data_size <= 3) { intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel,
/* set the sample container set bit to 16bits */ dma_cfg->dest_data_size);
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
}
} }
return res; return res;
@ -120,10 +116,9 @@ int intel_adsp_hda_dma_link_in_config(const struct device *dev,
buf = (uint8_t *)(uintptr_t)(blk_cfg->dest_address); buf = (uint8_t *)(uintptr_t)(blk_cfg->dest_address);
res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf, res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf,
blk_cfg->block_size); blk_cfg->block_size);
if (res == 0) {
if (res == 0 && dma_cfg->dest_data_size <= 3) { intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel,
/* set the sample container set bit to 16bits */ dma_cfg->dest_data_size);
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
} }
return res; return res;
@ -152,10 +147,9 @@ int intel_adsp_hda_dma_link_out_config(const struct device *dev,
res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf, res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf,
blk_cfg->block_size); blk_cfg->block_size);
if (res == 0) {
if (res == 0 && dma_cfg->source_data_size <= 3) { intel_adsp_hda_set_sample_container_size(cfg->base, cfg->regblock_size, channel,
/* set the sample container set bit to 16bits */ dma_cfg->source_data_size);
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
} }
return res; return res;

View file

@ -469,4 +469,26 @@ static inline uint32_t intel_adsp_hda_check_buffer_interrupt(uint32_t base, uint
return (*DGCS(base, regblock_size, sid) & DGCS_BSC) == DGCS_BSC; return (*DGCS(base, regblock_size, sid) & DGCS_BSC) == DGCS_BSC;
} }
/**
* @brief Set the Sample Container Size (SCS)
*
* Sample Container Size indicates the container size of the audio samples in local memory
* SCS bit must cleared to 0 for 32bit sample size (HD Audio container size)
* SCS bit must be set to 1 for non 32bit sample sizes
*
* @param base Base address of the IP register block
* @param regblock_size Register block size
* @param sid Stream ID
* @param sample_size
*/
static inline void intel_adsp_hda_set_sample_container_size(uint32_t base, uint32_t regblock_size,
uint32_t sid, uint32_t sample_size)
{
if (sample_size <= 3) {
*DGCS(base, regblock_size, sid) |= DGCS_SCS;
} else {
*DGCS(base, regblock_size, sid) &= ~DGCS_SCS;
}
}
#endif /* ZEPHYR_INCLUDE_INTEL_ADSP_HDA_H */ #endif /* ZEPHYR_INCLUDE_INTEL_ADSP_HDA_H */