dma: hda: enable xrun handling
Enable link under/overruns handling and reporting such events in dma status Signed-off-by: Piotr Makaruk <piotr.makaruk@intel.com>
This commit is contained in:
parent
122c7be703
commit
00b5114344
2 changed files with 44 additions and 0 deletions
|
@ -190,6 +190,7 @@ int intel_adsp_hda_dma_status(const struct device *dev, uint32_t channel,
|
||||||
struct dma_status *stat)
|
struct dma_status *stat)
|
||||||
{
|
{
|
||||||
const struct intel_adsp_hda_dma_cfg *const cfg = dev->config;
|
const struct intel_adsp_hda_dma_cfg *const cfg = dev->config;
|
||||||
|
bool xrun_det;
|
||||||
|
|
||||||
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
|
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
|
||||||
|
|
||||||
|
@ -203,6 +204,25 @@ int intel_adsp_hda_dma_status(const struct device *dev, uint32_t channel,
|
||||||
stat->pending_length = used;
|
stat->pending_length = used;
|
||||||
stat->free = unused;
|
stat->free = unused;
|
||||||
|
|
||||||
|
switch (cfg->direction) {
|
||||||
|
case MEMORY_TO_PERIPHERAL:
|
||||||
|
xrun_det = intel_adsp_hda_is_buffer_underrun(cfg->base, cfg->regblock_size,
|
||||||
|
channel);
|
||||||
|
if (xrun_det) {
|
||||||
|
intel_adsp_hda_underrun_clear(cfg->base, cfg->regblock_size, channel);
|
||||||
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
case PERIPHERAL_TO_MEMORY:
|
||||||
|
xrun_det = intel_adsp_hda_is_buffer_overrun(cfg->base, cfg->regblock_size,
|
||||||
|
channel);
|
||||||
|
if (xrun_det) {
|
||||||
|
intel_adsp_hda_overrun_clear(cfg->base, cfg->regblock_size, channel);
|
||||||
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -346,4 +346,28 @@ static inline bool intel_adsp_hda_wp_rp_eq(uint32_t base, uint32_t regblock_size
|
||||||
return *DGBWP(base, regblock_size, sid) == *DGBRP(base, regblock_size, sid);
|
return *DGBWP(base, regblock_size, sid) == *DGBRP(base, regblock_size, sid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool intel_adsp_hda_is_buffer_overrun(uint32_t base, uint32_t regblock_size,
|
||||||
|
uint32_t sid)
|
||||||
|
{
|
||||||
|
return (*DGCS(base, regblock_size, sid) & DGCS_BOR) == DGCS_BOR ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool intel_adsp_hda_is_buffer_underrun(uint32_t base, uint32_t regblock_size,
|
||||||
|
uint32_t sid)
|
||||||
|
{
|
||||||
|
return (*DGCS(base, regblock_size, sid) & DGCS_BUR) == DGCS_BUR ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void intel_adsp_hda_overrun_clear(uint32_t base, uint32_t regblock_size,
|
||||||
|
uint32_t sid)
|
||||||
|
{
|
||||||
|
*DGCS(base, regblock_size, sid) |= DGCS_BOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void intel_adsp_hda_underrun_clear(uint32_t base, uint32_t regblock_size,
|
||||||
|
uint32_t sid)
|
||||||
|
{
|
||||||
|
*DGCS(base, regblock_size, sid) |= DGCS_BUR;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_INTEL_ADSP_HDA_H */
|
#endif /* ZEPHYR_INCLUDE_INTEL_ADSP_HDA_H */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue