dma/hda: Use the correct register block size for each IP block

Previous versions were using, incorrectly, the host in/out regblock size
of 40 bytes for all peripherals when in fact the link in/out regblock size
is 20 bytes in size.

Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
This commit is contained in:
Tom Burdick 2022-08-16 11:15:57 -05:00 committed by Maureen Helm
parent e918783af1
commit efc0928570
13 changed files with 185 additions and 160 deletions

View file

@ -25,12 +25,6 @@
#include <zephyr/drivers/dma.h>
#include "dma_intel_adsp_hda.h"
/* Define low level driver required values */
#define HDA_HOST_IN_BASE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_in), reg, 0)
#define HDA_HOST_OUT_BASE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_out), reg, 0)
#define HDA_STREAM_COUNT DT_PROP(DT_NODELABEL(hda_host_out), dma_channels)
#define HDA_REGBLOCK_SIZE DT_PROP_BY_IDX(DT_NODELABEL(hda_host_out), reg, 1)
#include <intel_adsp_hda.h>
int intel_adsp_hda_dma_host_in_config(const struct device *dev,
@ -52,15 +46,16 @@ int intel_adsp_hda_dma_host_in_config(const struct device *dev,
blk_cfg = dma_cfg->head_block;
buf = (uint8_t *)(uintptr_t)(blk_cfg->source_address);
res = intel_adsp_hda_set_buffer(cfg->base, channel, buf,
res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf,
blk_cfg->block_size);
if (res == 0) {
*DGMBS(cfg->base, channel) = blk_cfg->block_size & HDA_ALIGN_MASK;
*DGMBS(cfg->base, cfg->regblock_size, channel) =
blk_cfg->block_size & HDA_ALIGN_MASK;
if (dma_cfg->source_data_size <= 3) {
/* set the sample container set bit to 16bits */
*DGCS(cfg->base, channel) |= DGCS_SCS;
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
}
}
@ -88,15 +83,16 @@ int intel_adsp_hda_dma_host_out_config(const struct device *dev,
blk_cfg = dma_cfg->head_block;
buf = (uint8_t *)(uintptr_t)(blk_cfg->dest_address);
res = intel_adsp_hda_set_buffer(cfg->base, channel, buf,
res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf,
blk_cfg->block_size);
if (res == 0) {
*DGMBS(cfg->base, channel) = blk_cfg->block_size & HDA_ALIGN_MASK;
*DGMBS(cfg->base, cfg->regblock_size, channel) =
blk_cfg->block_size & HDA_ALIGN_MASK;
if (dma_cfg->dest_data_size <= 3) {
/* set the sample container set bit to 16bits */
*DGCS(cfg->base, channel) |= DGCS_SCS;
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
}
}
@ -122,12 +118,12 @@ int intel_adsp_hda_dma_link_in_config(const struct device *dev,
blk_cfg = dma_cfg->head_block;
buf = (uint8_t *)(uintptr_t)(blk_cfg->source_address);
res = intel_adsp_hda_set_buffer(cfg->base, channel, buf,
res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf,
blk_cfg->block_size);
if (res == 0 && dma_cfg->source_data_size <= 3) {
/* set the sample container set bit to 16bits */
*DGCS(cfg->base, channel) |= DGCS_SCS;
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
}
return res;
@ -154,12 +150,12 @@ int intel_adsp_hda_dma_link_out_config(const struct device *dev,
blk_cfg = dma_cfg->head_block;
buf = (uint8_t *)(uintptr_t)(blk_cfg->dest_address);
res = intel_adsp_hda_set_buffer(cfg->base, channel, buf,
res = intel_adsp_hda_set_buffer(cfg->base, cfg->regblock_size, channel, buf,
blk_cfg->block_size);
if (res == 0 && dma_cfg->dest_data_size <= 3) {
/* set the sample container set bit to 16bits */
*DGCS(cfg->base, channel) |= DGCS_SCS;
*DGCS(cfg->base, cfg->regblock_size, channel) |= DGCS_SCS;
}
return res;
@ -173,7 +169,7 @@ int intel_adsp_hda_dma_link_reload(const struct device *dev, uint32_t channel,
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
intel_adsp_hda_link_commit(cfg->base, channel, size);
intel_adsp_hda_link_commit(cfg->base, cfg->regblock_size, channel, size);
return 0;
}
@ -185,7 +181,7 @@ int intel_adsp_hda_dma_host_reload(const struct device *dev, uint32_t channel,
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
intel_adsp_hda_host_commit(cfg->base, channel, size);
intel_adsp_hda_host_commit(cfg->base, cfg->regblock_size, channel, size);
return 0;
}
@ -197,13 +193,13 @@ int intel_adsp_hda_dma_status(const struct device *dev, uint32_t channel,
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
uint32_t unused = intel_adsp_hda_unused(cfg->base, channel);
uint32_t used = *DGBS(cfg->base, channel) - unused;
uint32_t unused = intel_adsp_hda_unused(cfg->base, cfg->regblock_size, channel);
uint32_t used = *DGBS(cfg->base, cfg->regblock_size, channel) - unused;
stat->dir = cfg->direction;
stat->busy = *DGCS(cfg->base, channel) & DGCS_GBUSY;
stat->write_position = *DGBWP(cfg->base, channel);
stat->read_position = *DGBRP(cfg->base, channel);
stat->busy = *DGCS(cfg->base, cfg->regblock_size, channel) & DGCS_GBUSY;
stat->write_position = *DGBWP(cfg->base, cfg->regblock_size, channel);
stat->read_position = *DGBRP(cfg->base, cfg->regblock_size, channel);
stat->pending_length = used;
stat->free = unused;
@ -233,7 +229,7 @@ int intel_adsp_hda_dma_start(const struct device *dev, uint32_t channel)
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
intel_adsp_hda_enable(cfg->base, channel);
intel_adsp_hda_enable(cfg->base, cfg->regblock_size, channel);
return 0;
}
@ -244,7 +240,7 @@ int intel_adsp_hda_dma_stop(const struct device *dev, uint32_t channel)
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
intel_adsp_hda_disable(cfg->base, channel);
intel_adsp_hda_disable(cfg->base, cfg->regblock_size, channel);
return 0;
}
@ -255,7 +251,7 @@ int intel_adsp_hda_dma_init(const struct device *dev)
const struct intel_adsp_hda_dma_cfg *const cfg = dev->config;
for (uint32_t i = 0; i < cfg->dma_channels; i++) {
intel_adsp_hda_init(cfg->base, i);
intel_adsp_hda_init(cfg->base, cfg->regblock_size, i);
}
data->ctx.dma_channels = cfg->dma_channels;

View file

@ -19,6 +19,7 @@ struct intel_adsp_hda_dma_data {
struct intel_adsp_hda_dma_cfg {
uint32_t base;
uint32_t regblock_size;
uint32_t dma_channels;
enum dma_channel_direction direction;
};

View file

@ -21,6 +21,7 @@ static const struct dma_driver_api intel_adsp_hda_dma_host_in_api = {
#define INTEL_ADSP_HDA_DMA_HOST_IN_INIT(inst) \
static const struct intel_adsp_hda_dma_cfg intel_adsp_hda_dma##inst##_config = { \
.base = DT_INST_REG_ADDR(inst), \
.regblock_size = DT_INST_REG_SIZE(inst), \
.dma_channels = DT_INST_PROP(inst, dma_channels), \
.direction = MEMORY_TO_HOST \
}; \

View file

@ -25,6 +25,7 @@ static const struct dma_driver_api intel_adsp_hda_dma_host_out_api = {
#define INTEL_ADSP_HDA_DMA_HOST_OUT_INIT(inst) \
static const struct intel_adsp_hda_dma_cfg intel_adsp_hda_dma##inst##_config = { \
.base = DT_INST_REG_ADDR(inst), \
.regblock_size = DT_INST_REG_SIZE(inst), \
.dma_channels = DT_INST_PROP(inst, dma_channels), \
.direction = HOST_TO_MEMORY \
}; \

View file

@ -25,6 +25,7 @@ static const struct dma_driver_api intel_adsp_hda_dma_link_in_api = {
#define INTEL_ADSP_HDA_DMA_LINK_IN_INIT(inst) \
static const struct intel_adsp_hda_dma_cfg intel_adsp_hda_dma##inst##_config = { \
.base = DT_INST_REG_ADDR(inst), \
.regblock_size = DT_INST_REG_SIZE(inst), \
.dma_channels = DT_INST_PROP(inst, dma_channels), \
.direction = PERIPHERAL_TO_MEMORY \
}; \

View file

@ -25,6 +25,7 @@ static const struct dma_driver_api intel_adsp_hda_dma_link_out_api = {
#define INTEL_ADSP_HDA_DMA_LINK_OUT_INIT(inst) \
static const struct intel_adsp_hda_dma_cfg intel_adsp_hda_dma##inst##_config = { \
.base = DT_INST_REG_ADDR(inst), \
.regblock_size = DT_INST_REG_SIZE(inst), \
.dma_channels = DT_INST_PROP(inst, dma_channels), \
.direction = MEMORY_TO_PERIPHERAL \
}; \

View file

@ -245,7 +245,7 @@
compatible = "intel,adsp-hda-host-out";
#dma-cells = <1>;
reg = <0x00072800 0x40>;
dma-channels = <5>;
dma-channels = <9>;
dma-buf-alignment = <128>;
status = "okay";
};
@ -254,7 +254,7 @@
compatible = "intel,adsp-hda-host-in";
#dma-cells = <1>;
reg = <0x00072c00 0x40>;
dma-channels = <5>;
dma-channels = <10>;
dma-buf-alignment = <128>;
status = "okay";
};
@ -262,8 +262,8 @@
hda_link_out: dma@72400 {
compatible = "intel,adsp-hda-link-out";
#dma-cells = <1>;
reg = <0x00072400 0x40>;
dma-channels = <5>;
reg = <0x00072400 0x20>;
dma-channels = <9>;
dma-buf-alignment = <128>;
status = "okay";
};
@ -271,8 +271,8 @@
hda_link_in: dma@72600 {
compatible = "intel,adsp-hda-link-in";
#dma-cells = <1>;
reg = <0x00072600 0x40>;
dma-channels = <5>;
reg = <0x00072600 0x20>;
dma-channels = <10>;
dma-buf-alignment = <128>;
status = "okay";
};

View file

@ -33,7 +33,7 @@
hda_link_out: dma@72400 {
compatible = "intel,adsp-hda-link-out";
#dma-cells = <1>;
reg = <0x00072400 0x40>;
reg = <0x00072400 0x20>;
dma-channels = <4>;
dma-buf-alignment = <128>;
@ -43,7 +43,7 @@
hda_link_in: dma@72600 {
compatible = "intel,adsp-hda-link-in";
#dma-cells = <1>;
reg = <0x00072600 0x40>;
reg = <0x00072600 0x20>;
dma-channels = <4>;
dma-buf-alignment = <128>;

View file

@ -155,7 +155,7 @@
hda_link_out: dma@2400 {
compatible = "intel,adsp-hda-link-out";
#dma-cells = <1>;
reg = <0x00002400 0x40>;
reg = <0x00002400 0x20>;
dma-channels = <2>;
dma-buf-alignment = <128>;
@ -165,7 +165,7 @@
hda_link_in: dma@2600 {
compatible = "intel,adsp-hda-link-in";
#dma-cells = <1>;
reg = <0x00002600 0x40>;
reg = <0x00002600 0x20>;
dma-channels = <2>;
dma-buf-alignment = <128>;

View file

@ -21,19 +21,6 @@
* addresses, the stream count, and the size of the ip blocks.
*/
#ifndef HDA_HOST_OUT_BASE
#error Must define HDA_HOST_OUT_BASE
#endif
#ifndef HDA_HOST_IN_BASE
#error Must define HDA_HOST_IN_BASE
#endif
#ifndef HDA_STREAM_COUNT
#error Must define HDA_STREAM_COUNT
#endif
#ifndef HDA_REGBLOCK_SIZE
#error Must define HDA_REGBLOCK_SIZE
#endif
/* The read/write positions are masked to 24 bits */
#define HDA_RWP_MASK 0x00FFFFFF
@ -41,11 +28,12 @@
#define HDA_ALIGN_MASK 0xFFFFFF80
#define HDA_ADDR(base, stream) ((base) + (stream)*HDA_REGBLOCK_SIZE)
/* Calculate base address of the stream registers */
#define HDA_ADDR(base, regblock_size, stream) ((base) + (stream)*(regblock_size))
/* Gateway Control and Status Register */
#define DGCS(base, stream) ((volatile uint32_t *)HDA_ADDR(base, stream))
#define DGCS(base, regblock_size, stream) \
((volatile uint32_t *)HDA_ADDR(base, regblock_size, stream))
#define DGCS_SCS BIT(31) /* Sample container size */
#define DGCS_GEN BIT(26) /* Gateway Enable */
#define DGCS_L1ETP BIT(25) /* L1 Enter Prevent */
@ -62,31 +50,40 @@
#define DGCS_BSCIE BIT(3) /* Buffer Segment Completion Interrupt Enable */
/* Gateway Buffer Base Address */
#define DGBBA(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x04))
#define DGBBA(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x04))
/* Gateway Buffer Size */
#define DGBS(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x08))
#define DGBS(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x08))
/* Gateway Buffer Position Increment */
#define DGBFPI(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x0c))
#define DGBFPI(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x0c))
/* Gateway Buffer Read Position */
#define DGBRP(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x10))
#define DGBRP(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x10))
/* Gateway Buffer Write Position */
#define DGBWP(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x14))
#define DGBWP(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x14))
/* Gateway Buffer Segment Position */
#define DGBSP(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x18))
#define DGBSP(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x18))
/* Gateway Minimum Buffer Size */
#define DGMBS(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x1c))
#define DGMBS(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x1c))
/* Gateway Linear Link Position Increment */
#define DGLLPI(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x24))
#define DGLLPI(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x24))
/* Gateway Linear Position In Buffer Increment */
#define DGLPIBI(base, stream) ((volatile uint32_t *)(HDA_ADDR(base, stream) + 0x28))
#define DGLPIBI(base, regblock_size, stream) \
((volatile uint32_t *)(HDA_ADDR(base, regblock_size, stream) + 0x28))
/**
* @brief Dump all the useful registers of an HDA stream to printk
@ -97,23 +94,24 @@
*
* @param name String that contains a name of the hda stream (or anything really)
* @param base Base address of the IP register block
* @param regblock_size Register block size
* @param sid Stream ID
*/
#define intel_adsp_hda_dbg(name, base, sid) \
printk("%s:%u %s(%u:0x%p), dgcs: 0x%x, dgbba 0x%x, " \
"dgbs %u, dgbrp %u, dgbwp %u, dgbsp %u, " \
"dgmbs %u, dgbllpi 0x%x, dglpibi 0x%x\n", \
__FILE__, __LINE__, name, \
sid, DGCS(base, sid), \
*DGCS(base, sid), \
*DGBBA(base, sid), \
*DGBS(base, sid), \
*DGBRP(base, sid), \
*DGBWP(base, sid), \
*DGBSP(base, sid), \
*DGMBS(base, sid), \
*DGLLPI(base, sid), \
*DGLPIBI(base, sid))
#define intel_adsp_hda_dbg(name, base, regblock_size, sid) \
printk("%s:%u %s(%u:0x%p), dgcs: 0x%x, dgbba 0x%x, " \
"dgbs %u, dgbrp %u, dgbwp %u, dgbsp %u, " \
"dgmbs %u, dgbllpi 0x%x, dglpibi 0x%x\n", \
__FILE__, __LINE__, name, \
sid, DGCS(base, regblock_size, sid), \
*DGCS(base, regblock_size, sid), \
*DGBBA(base, regblock_size, sid), \
*DGBS(base, regblock_size, sid), \
*DGBRP(base, regblock_size, sid), \
*DGBWP(base, regblock_size, sid), \
*DGBSP(base, regblock_size, sid), \
*DGMBS(base, regblock_size, sid), \
*DGLLPI(base, regblock_size, sid), \
*DGLPIBI(base, regblock_size, sid))
@ -123,9 +121,9 @@
* @param hda Stream set to work with
* @param sid Stream ID
*/
static inline void intel_adsp_hda_init(uint32_t base, uint32_t sid)
static inline void intel_adsp_hda_init(uint32_t base, uint32_t regblock_size, uint32_t sid)
{
*DGCS(base, sid) |= DGCS_FWCB;
*DGCS(base, regblock_size, sid) |= DGCS_FWCB;
}
/**
@ -139,6 +137,7 @@ static inline void intel_adsp_hda_init(uint32_t base, uint32_t sid)
*
*
* @param hda Stream set to work with
* @param regblock_size Register block size
* @param sid Stream ID
* @param buf Buffer address to use for the shared FIFO. Must be in L2 and 128 byte aligned.
* @param buf_size Buffer size in bytes Must be 128 byte aligned
@ -147,8 +146,11 @@ static inline void intel_adsp_hda_init(uint32_t base, uint32_t sid)
* @retval -EINVAL if the buf is not in L2, buf isn't aligned on 128 byte boundaries
* @retval 0 on Success
*/
static inline int intel_adsp_hda_set_buffer(uint32_t base, uint32_t sid,
uint8_t *buf, uint32_t buf_size)
static inline int intel_adsp_hda_set_buffer(uint32_t base,
uint32_t regblock_size,
uint32_t sid,
uint8_t *buf,
uint32_t buf_size)
{
/* While we don't actually care if the pointer is in the cached
* region or not, we do need a consistent address space to check
@ -168,16 +170,16 @@ static inline int intel_adsp_hda_set_buffer(uint32_t base, uint32_t sid,
__ASSERT(aligned_addr + aligned_size < L2_SRAM_BASE + L2_SRAM_SIZE,
"Buffer must end in L2 address space");
if (*DGCS(base, sid) & DGCS_GEN) {
if (*DGCS(base, regblock_size, sid) & DGCS_GEN) {
return -EBUSY;
}
if (*DGCS(base, sid) & DGCS_GBUSY) {
if (*DGCS(base, regblock_size, sid) & DGCS_GBUSY) {
return -EBUSY;
}
*DGBBA(base, sid) = aligned_addr;
*DGBS(base, sid) = aligned_size;
*DGBBA(base, regblock_size, sid) = aligned_addr;
*DGBS(base, regblock_size, sid) = aligned_size;
return 0;
}
@ -186,22 +188,24 @@ static inline int intel_adsp_hda_set_buffer(uint32_t base, uint32_t sid,
* @brief Enable the stream
*
* @param hda HDA stream set
* @param regblock_size Register block size
* @param sid Stream ID
*/
static inline void intel_adsp_hda_enable(uint32_t base, uint32_t sid)
static inline void intel_adsp_hda_enable(uint32_t base, uint32_t regblock_size, uint32_t sid)
{
*DGCS(base, sid) |= DGCS_GEN | DGCS_FIFORDY;
*DGCS(base, regblock_size, sid) |= DGCS_GEN | DGCS_FIFORDY;
}
/**
* @brief Disable stream
*
* @param hda HDA stream set
* @param regblock_size Register block size
* @param sid Stream ID
*/
static inline void intel_adsp_hda_disable(uint32_t base, uint32_t sid)
static inline void intel_adsp_hda_disable(uint32_t base, uint32_t regblock_size, uint32_t sid)
{
*DGCS(base, sid) &= ~(DGCS_GEN | DGCS_FIFORDY);
*DGCS(base, regblock_size, sid) &= ~(DGCS_GEN | DGCS_FIFORDY);
}
/**
@ -210,14 +214,15 @@ static inline void intel_adsp_hda_disable(uint32_t base, uint32_t sid)
* This is useful primarily for a host in (dsp -> host) stream.
*
* @param base Base address of the IP register block
* @param regblock_size Register block size
* @param sid Stream ID within the register block
*
* @retval n Number of unused bytes
*/
static inline uint32_t intel_adsp_hda_unused(uint32_t base, uint32_t sid)
static inline uint32_t intel_adsp_hda_unused(uint32_t base, uint32_t regblock_size, uint32_t sid)
{
uint32_t dgcs = *DGCS(base, sid);
uint32_t dgbs = *DGBS(base, sid);
uint32_t dgcs = *DGCS(base, regblock_size, sid);
uint32_t dgbs = *DGBS(base, regblock_size, sid);
/* Check if buffer is empty */
if ((dgcs & DGCS_BNE) == 0) {
@ -229,8 +234,8 @@ static inline uint32_t intel_adsp_hda_unused(uint32_t base, uint32_t sid)
return 0;
}
int32_t rp = *DGBRP(base, sid);
int32_t wp = *DGBWP(base, sid);
int32_t rp = *DGBRP(base, regblock_size, sid);
int32_t wp = *DGBWP(base, regblock_size, sid);
int32_t size = rp - wp;
if (size <= 0) {
@ -256,14 +261,18 @@ static inline uint32_t intel_adsp_hda_unused(uint32_t base, uint32_t sid)
* happen in testing for host transfers.
*
* @param base Base address of the IP register block
* @param regblock_size Register block size
* @param sid Stream ID within the register block
* @param len Len to increment postion by
*/
static inline void intel_adsp_hda_host_commit(uint32_t base, uint32_t sid, uint32_t len)
static inline void intel_adsp_hda_host_commit(uint32_t base,
uint32_t regblock_size,
uint32_t sid,
uint32_t len)
{
*DGBFPI(base, sid) = len;
*DGLLPI(base, sid) = len;
*DGLPIBI(base, sid) = len;
*DGBFPI(base, regblock_size, sid) = len;
*DGLLPI(base, regblock_size, sid) = len;
*DGLPIBI(base, regblock_size, sid) = len;
}
/**
@ -274,25 +283,30 @@ static inline void intel_adsp_hda_host_commit(uint32_t base, uint32_t sid, uint3
* @seealso intel_adsp_hda_host_commit
*
* @param base Base address of the IP register block
* @param regblock_size Register block size
* @param sid Stream ID within the register block
* @param len Len to increment postion by
*/
static inline void intel_adsp_hda_link_commit(uint32_t base, uint32_t sid, uint32_t len)
static inline void intel_adsp_hda_link_commit(uint32_t base,
uint32_t regblock_size,
uint32_t sid,
uint32_t len)
{
*DGBFPI(base, sid) = len;
*DGBFPI(base, regblock_size, sid) = len;
}
/**
* @brief Read the buffer full bit of the given stream.
*
* @param base Base address of the IP register block
* @param regblock_size Register block size
* @param sid Stream ID within the register block
*
* @retval true If the buffer full flag is set
*/
static inline bool intel_adsp_hda_buf_full(uint32_t base, uint32_t sid)
static inline bool intel_adsp_hda_buf_full(uint32_t base, uint32_t regblock_size, uint32_t sid)
{
return *DGCS(base, sid) & DGCS_BF;
return *DGCS(base, regblock_size, sid) & DGCS_BF;
}
/**
@ -304,14 +318,15 @@ static inline bool intel_adsp_hda_buf_full(uint32_t base, uint32_t sid)
* Useful for waiting on the hardware to catch up to
* reads or writes (e.g. after a intel_adsp_hda_commit)
*
* @param dev HDA Stream device
* @param base Base address of the IP register block
* @param regblock_size Register block size
* @param sid Stream D
*
* @retval true If the read and write positions are equal
*/
static inline bool intel_adsp_hda_wp_rp_eq(uint32_t base, uint32_t sid)
static inline bool intel_adsp_hda_wp_rp_eq(uint32_t base, uint32_t regblock_size, uint32_t sid)
{
return *DGBWP(base, sid) == *DGBRP(base, sid);
return *DGBWP(base, regblock_size, sid) == *DGBRP(base, regblock_size, sid);
}
#endif /* ZEPHYR_INCLUDE_INTEL_ADSP_HDA_H */

View file

@ -72,14 +72,14 @@ void test_hda_host_in_dma(void)
channel = dma_request_channel(dma, NULL);
zassert_true(channel >= 0, "Expected a valid DMA channel");
hda_dump_regs(HOST_IN, channel, "dma channel");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel, "dma channel");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_RESET, channel, IPC_TIMEOUT);
hda_dump_regs(HOST_IN, channel, "host reset");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel, "host reset");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_CONFIG,
channel | (DMA_BUF_SIZE << 8), IPC_TIMEOUT);
hda_dump_regs(HOST_IN, channel, "host config");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel, "host config");
struct dma_block_config block_cfg = {
@ -94,20 +94,20 @@ void test_hda_host_in_dma(void)
};
res = dma_config(dma, channel, &dma_cfg);
hda_dump_regs(HOST_IN, channel, "dsp dma config");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel, "dsp dma config");
zassert_ok(res, "Expected dma config to succeed");
res = dma_start(dma, channel);
hda_dump_regs(HOST_IN, channel, "dsp dma start");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel, "dsp dma start");
zassert_ok(res, "Expected dma start to succeed");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_START, channel, IPC_TIMEOUT);
hda_dump_regs(HOST_IN, channel, "host start");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel, "host start");
for (uint32_t i = 0; i < TRANSFER_COUNT; i++) {
res = dma_reload(dma, channel, 0, 0, DMA_BUF_SIZE);
zassert_ok(res, "Expected dma reload to succeed");
hda_dump_regs(HOST_IN, channel, "dsp dma reload");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel, "dsp dma reload");
struct dma_status status;
int j;
@ -120,7 +120,8 @@ void test_hda_host_in_dma(void)
}
k_busy_wait(100);
}
hda_dump_regs(HOST_IN, channel, "dsp read write equal after %d uS", j*100);
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, channel,
"dsp read write equal after %d uS", j*100);
last_msg_cnt = msg_cnt;
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_VALIDATE, channel,
@ -160,15 +161,15 @@ void test_hda_host_out_dma(void)
channel = dma_request_channel(dma, NULL);
zassert_true(channel >= 0, "Expected a valid DMA channel");
hda_dump_regs(HOST_OUT, channel, "dma request channel");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "dma request channel");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_RESET,
(channel + 7), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, channel, "host reset");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "host reset");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_CONFIG,
(channel + 7) | (DMA_BUF_SIZE << 8), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, channel, "host config");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "host config");
struct dma_block_config block_cfg = {
.block_size = DMA_BUF_SIZE,
@ -182,24 +183,25 @@ void test_hda_host_out_dma(void)
};
res = dma_config(dma, channel, &dma_cfg);
hda_dump_regs(HOST_OUT, channel, "dsp dma config");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "dsp dma config");
zassert_ok(res, "Expected dma config to succeed");
res = dma_start(dma, channel);
hda_dump_regs(HOST_OUT, channel, "dsp dma start");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "dsp dma start");
zassert_ok(res, "Expected dma start to succeed");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_START, (channel + 7), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, channel, "host start");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "host start");
for (uint32_t i = 0; i < TRANSFER_COUNT; i++) {
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_SEND,
(channel + 7) | (DMA_BUF_SIZE << 8), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, channel, "host send");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "host send");
/* TODO add a dma_poll() style call for xfer ready/complete maybe? */
WAIT_FOR(intel_adsp_hda_buf_full(HDA_HOST_OUT_BASE, channel), 10000, k_msleep(1));
hda_dump_regs(HOST_OUT, channel, "dsp wait for full");
WAIT_FOR(intel_adsp_hda_buf_full(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, channel),
10000, k_msleep(1));
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "dsp wait for full");
#if (IS_ENABLED(CONFIG_KERNEL_COHERENCE))
zassert_true(arch_mem_coherent(dma_buf), "Buffer is unexpectedly incoherent!");
@ -222,14 +224,14 @@ void test_hda_host_out_dma(void)
res = dma_reload(dma, channel, 0, 0, DMA_BUF_SIZE);
zassert_ok(res, "Expected dma reload to succeed");
hda_dump_regs(HOST_OUT, channel, "dsp dma reload");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "dsp dma reload");
}
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_RESET, (channel + 7), IPC_TIMEOUT);
printk("host reset: "); intel_adsp_hda_dbg("host_out", HDA_HOST_OUT_BASE, channel);
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "host reset");
res = dma_stop(dma, channel);
zassert_ok(res, "Expected dma stop to succeed");
hda_dump_regs(HOST_OUT, channel, "dsp dma stop");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, channel, "dsp dma stop");
}

View file

@ -66,32 +66,35 @@ void test_hda_host_in_smoke(void)
z_xtensa_cache_flush(hda_buf, HDA_BUF_SIZE);
#endif
intel_adsp_hda_init(HDA_HOST_IN_BASE, STREAM_ID);
hda_dump_regs(HOST_IN, STREAM_ID, "dsp init");
intel_adsp_hda_init(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp init");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_RESET, STREAM_ID, IPC_TIMEOUT);
hda_dump_regs(HOST_IN, STREAM_ID, "host reset");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_CONFIG,
STREAM_ID | (HDA_BUF_SIZE << 8), IPC_TIMEOUT);
hda_dump_regs(HOST_IN, STREAM_ID, "host config");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host config");
res = intel_adsp_hda_set_buffer(HDA_HOST_IN_BASE, STREAM_ID, hda_buf, HDA_BUF_SIZE);
hda_dump_regs(HOST_IN, STREAM_ID, "dsp set_buffer");
res = intel_adsp_hda_set_buffer(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
hda_buf, HDA_BUF_SIZE);
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp set_buffer");
zassert_ok(res, "Expected set buffer to succeed");
intel_adsp_hda_enable(HDA_HOST_IN_BASE, STREAM_ID);
hda_dump_regs(HOST_IN, STREAM_ID, "dsp enable");
intel_adsp_hda_enable(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp enable");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_START, STREAM_ID, IPC_TIMEOUT);
hda_dump_regs(HOST_IN, STREAM_ID, "host start");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host start");
for (uint32_t i = 0; i < TRANSFER_COUNT; i++) {
intel_adsp_hda_host_commit(HDA_HOST_IN_BASE, STREAM_ID, HDA_BUF_SIZE);
hda_dump_regs(HOST_IN, STREAM_ID, "dsp inc_pos");
intel_adsp_hda_host_commit(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
HDA_BUF_SIZE);
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp inc_pos");
WAIT_FOR(intel_adsp_hda_wp_rp_eq(HDA_HOST_IN_BASE, STREAM_ID), 10000, k_msleep(1));
hda_dump_regs(HOST_IN, STREAM_ID, "dsp wp == rp");
WAIT_FOR(intel_adsp_hda_wp_rp_eq(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID),
10000, k_msleep(1));
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp wp == rp");
last_msg_cnt = msg_cnt;
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_VALIDATE, STREAM_ID,
@ -103,10 +106,10 @@ void test_hda_host_in_smoke(void)
}
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_RESET, STREAM_ID, IPC_TIMEOUT);
hda_dump_regs(HOST_IN, STREAM_ID, "host reset");
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
intel_adsp_hda_disable(HDA_HOST_IN_BASE, STREAM_ID);
hda_dump_regs(HOST_IN, STREAM_ID, "dsp disable");
intel_adsp_hda_disable(HDA_HOST_IN_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
hda_dump_regs(HOST_IN, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp disable");
}
/*
@ -127,25 +130,26 @@ void test_hda_host_out_smoke(void)
printk("Using buffer of size %d at addr %p\n", HDA_BUF_SIZE, hda_buf);
intel_adsp_hda_init(HDA_HOST_OUT_BASE, STREAM_ID);
hda_dump_regs(HOST_OUT, STREAM_ID, "dsp init");
intel_adsp_hda_init(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp init");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_RESET, (STREAM_ID + 7), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, STREAM_ID, "host reset");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_CONFIG,
(STREAM_ID + 7) | (HDA_BUF_SIZE << 8), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, STREAM_ID, "host config");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host config");
res = intel_adsp_hda_set_buffer(HDA_HOST_OUT_BASE, STREAM_ID, hda_buf, HDA_BUF_SIZE);
hda_dump_regs(HOST_OUT, STREAM_ID, "dsp set buffer");
res = intel_adsp_hda_set_buffer(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
hda_buf, HDA_BUF_SIZE);
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp set buffer");
zassert_ok(res, "Expected set buffer to succeed");
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_START, (STREAM_ID + 7), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, STREAM_ID, "host start");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host start");
intel_adsp_hda_enable(HDA_HOST_OUT_BASE, STREAM_ID);
hda_dump_regs(HOST_OUT, STREAM_ID, "dsp enable");
intel_adsp_hda_enable(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp enable");
for (uint32_t i = 0; i < TRANSFER_COUNT; i++) {
for (int j = 0; j < HDA_BUF_SIZE; j++) {
@ -154,11 +158,12 @@ void test_hda_host_out_smoke(void)
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_SEND,
(STREAM_ID + 7) | (HDA_BUF_SIZE << 8), IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, STREAM_ID, "host send");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host send");
WAIT_FOR(intel_adsp_hda_buf_full(HDA_HOST_OUT_BASE, STREAM_ID), 10000, k_msleep(1));
hda_dump_regs(HOST_OUT, STREAM_ID, "dsp wait for full");
WAIT_FOR(intel_adsp_hda_buf_full(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID),
10000, k_msleep(1));
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp wait for full");
#if (IS_ENABLED(CONFIG_KERNEL_COHERENCE))
zassert_true(arch_mem_coherent(hda_buf), "Buffer is unexpectedly incoherent!");
@ -179,15 +184,16 @@ void test_hda_host_out_smoke(void)
}
zassert_true(is_ramp, "Expected data to be a ramp");
intel_adsp_hda_host_commit(HDA_HOST_OUT_BASE, STREAM_ID, HDA_BUF_SIZE);
hda_dump_regs(HOST_OUT, STREAM_ID, "dsp inc pos");
intel_adsp_hda_host_commit(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID,
HDA_BUF_SIZE);
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp inc pos");
}
hda_ipc_msg(CAVS_HOST_DEV, IPCCMD_HDA_RESET, (STREAM_ID + 7),
IPC_TIMEOUT);
hda_dump_regs(HOST_OUT, STREAM_ID, "host reset");
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "host reset");
intel_adsp_hda_disable(HDA_HOST_OUT_BASE, STREAM_ID);
hda_dump_regs(HOST_OUT, STREAM_ID, "dsp disable");
intel_adsp_hda_disable(HDA_HOST_OUT_BASE, HDA_REGBLOCK_SIZE, STREAM_ID);
hda_dump_regs(HOST_OUT, HDA_REGBLOCK_SIZE, STREAM_ID, "dsp disable");
}

View file

@ -25,11 +25,12 @@ void test_hda_host_in_dma(void);
#define STREAM_SET_NAME(stream_set) STRINGIFY(stream_set)
#if INTEL_ADSP_HDA_DBG
#define hda_dump_regs(stream_set, stream_id, ...) \
#define hda_dump_regs(stream_set, regblock_size, stream_id, ...) \
printk(__VA_ARGS__); printk(": "); \
intel_adsp_hda_dbg(STREAM_SET_NAME(stream_set), STREAM_SET_BASE(stream_set), stream_id)
intel_adsp_hda_dbg(STREAM_SET_NAME(stream_set), STREAM_SET_BASE(stream_set), \
regblock_size, stream_id)
#else
#define hda_dump_regs(stream_set, stream_id, msg, ...) do {} while (0)
#define hda_dump_regs(stream_set, regblock_size, stream_id, msg, ...) do {} while (0)
#endif
static inline void hda_ipc_msg(const struct device *dev, uint32_t data,