dma/cavs_hda: Adds link in/link out compatibles
Adds hda link in and out drivers. The link in and link out channels of HDA have small differences with the host channels. Updates the existing cavs_hda drivers and code to account for these differences. Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
This commit is contained in:
parent
98f1a98cf5
commit
2f320730a1
9 changed files with 225 additions and 12 deletions
|
@ -98,6 +98,81 @@ int cavs_hda_dma_host_out_config(const struct device *dev,
|
|||
return res;
|
||||
}
|
||||
|
||||
int cavs_hda_dma_link_in_config(const struct device *dev,
|
||||
uint32_t channel,
|
||||
struct dma_config *dma_cfg)
|
||||
{
|
||||
const struct cavs_hda_dma_cfg *const cfg = dev->config;
|
||||
struct dma_block_config *blk_cfg;
|
||||
uint8_t *buf;
|
||||
int res;
|
||||
|
||||
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
|
||||
__ASSERT(dma_cfg->block_count == 1,
|
||||
"HDA does not support scatter gather or chained "
|
||||
"block transfers.");
|
||||
__ASSERT(dma_cfg->channel_direction == cfg->direction,
|
||||
"Unexpected channel direction, HDA link in supports "
|
||||
"PERIPHERAL_TO_MEMORY");
|
||||
|
||||
blk_cfg = dma_cfg->head_block;
|
||||
buf = (uint8_t *)(uintptr_t)(blk_cfg->source_address);
|
||||
res = cavs_hda_set_buffer(cfg->base, 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;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int cavs_hda_dma_link_out_config(const struct device *dev,
|
||||
uint32_t channel,
|
||||
struct dma_config *dma_cfg)
|
||||
{
|
||||
const struct cavs_hda_dma_cfg *const cfg = dev->config;
|
||||
struct dma_block_config *blk_cfg;
|
||||
uint8_t *buf;
|
||||
int res;
|
||||
|
||||
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
|
||||
__ASSERT(dma_cfg->block_count == 1,
|
||||
"HDA does not support scatter gather or chained "
|
||||
"block transfers.");
|
||||
__ASSERT(dma_cfg->channel_direction == cfg->direction,
|
||||
"Unexpected channel direction, HDA link out supports "
|
||||
"MEMORY_TO_PERIPHERAL");
|
||||
|
||||
blk_cfg = dma_cfg->head_block;
|
||||
buf = (uint8_t *)(uintptr_t)(blk_cfg->dest_address);
|
||||
|
||||
res = cavs_hda_set_buffer(cfg->base, 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;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int cavs_hda_dma_link_reload(const struct device *dev, uint32_t channel,
|
||||
uint32_t src, uint32_t dst, size_t size)
|
||||
{
|
||||
const struct cavs_hda_dma_cfg *const cfg = dev->config;
|
||||
|
||||
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
|
||||
|
||||
cavs_hda_link_commit(cfg->base, channel, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cavs_hda_dma_host_reload(const struct device *dev, uint32_t channel,
|
||||
uint32_t src, uint32_t dst, size_t size)
|
||||
{
|
||||
|
@ -105,7 +180,7 @@ int cavs_hda_dma_host_reload(const struct device *dev, uint32_t channel,
|
|||
|
||||
__ASSERT(channel < cfg->dma_channels, "Channel does not exist");
|
||||
|
||||
cavs_hda_commit(cfg->base, channel, size);
|
||||
cavs_hda_host_commit(cfg->base, channel, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef ZEPHYR_DRIVERS_DMA_DMA_CAVS_HDA_COMMON_H_
|
||||
#define ZEPHYR_DRIVERS_DMA_DMA_CAVS_HDA_COMMON_H_
|
||||
|
||||
#define CAVS_HDA_MAX_CHANNELS 32
|
||||
#define CAVS_HDA_MAX_CHANNELS DT_PROP(DT_NODELABEL(hda_host_out), dma_channels)
|
||||
|
||||
#include <drivers/dma.h>
|
||||
|
||||
|
@ -31,6 +31,17 @@ int cavs_hda_dma_host_out_config(const struct device *dev,
|
|||
uint32_t channel,
|
||||
struct dma_config *dma_cfg);
|
||||
|
||||
int cavs_hda_dma_link_in_config(const struct device *dev,
|
||||
uint32_t channel,
|
||||
struct dma_config *dma_cfg);
|
||||
|
||||
int cavs_hda_dma_link_out_config(const struct device *dev,
|
||||
uint32_t channel,
|
||||
struct dma_config *dma_cfg);
|
||||
|
||||
int cavs_hda_dma_link_reload(const struct device *dev, uint32_t channel,
|
||||
uint32_t src, uint32_t dst, size_t size);
|
||||
|
||||
int cavs_hda_dma_host_reload(const struct device *dev, uint32_t channel,
|
||||
uint32_t src, uint32_t dst, size_t size);
|
||||
|
||||
|
|
38
drivers/dma/dma_cavs_hda_link_in.c
Normal file
38
drivers/dma/dma_cavs_hda_link_in.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT intel_cavs_hda_link_in
|
||||
|
||||
#include <drivers/dma.h>
|
||||
#include "dma_cavs_hda.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_DMA_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(dma_cavs_hda_dma_link_in);
|
||||
|
||||
static const struct dma_driver_api cavs_hda_dma_link_in_api = {
|
||||
.config = cavs_hda_dma_link_in_config,
|
||||
.reload = cavs_hda_dma_link_reload,
|
||||
.start = cavs_hda_dma_start,
|
||||
.stop = cavs_hda_dma_stop,
|
||||
.get_status = cavs_hda_dma_status,
|
||||
.chan_filter = cavs_hda_dma_chan_filter,
|
||||
};
|
||||
|
||||
#define CAVS_HDA_DMA_LINK_IN_INIT(inst) \
|
||||
static const struct cavs_hda_dma_cfg cavs_hda_dma##inst##_config = { \
|
||||
.base = DT_INST_REG_ADDR(inst), \
|
||||
.dma_channels = DT_INST_PROP(inst, dma_channels), \
|
||||
.direction = MEMORY_TO_HOST \
|
||||
}; \
|
||||
\
|
||||
static struct cavs_hda_dma_data cavs_hda_dma##inst##_data = {}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, &cavs_hda_dma_init, NULL, &cavs_hda_dma##inst##_data, \
|
||||
&cavs_hda_dma##inst##_config, POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, \
|
||||
&cavs_hda_dma_link_in_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(CAVS_HDA_DMA_LINK_IN_INIT)
|
38
drivers/dma/dma_cavs_hda_link_out.c
Normal file
38
drivers/dma/dma_cavs_hda_link_out.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT intel_cavs_hda_link_out
|
||||
|
||||
#include <drivers/dma.h>
|
||||
#include "dma_cavs_hda.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_DMA_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(dma_cavs_hda_dma_link_out);
|
||||
|
||||
static const struct dma_driver_api cavs_hda_dma_link_out_api = {
|
||||
.config = cavs_hda_dma_link_out_config,
|
||||
.reload = cavs_hda_dma_link_reload,
|
||||
.start = cavs_hda_dma_start,
|
||||
.stop = cavs_hda_dma_stop,
|
||||
.get_status = cavs_hda_dma_status,
|
||||
.chan_filter = cavs_hda_dma_chan_filter,
|
||||
};
|
||||
|
||||
#define CAVS_HDA_DMA_LINK_OUT_INIT(inst) \
|
||||
static const struct cavs_hda_dma_cfg cavs_hda_dma##inst##_config = { \
|
||||
.base = DT_INST_REG_ADDR(inst), \
|
||||
.dma_channels = DT_INST_PROP(inst, dma_channels), \
|
||||
.direction = MEMORY_TO_HOST \
|
||||
}; \
|
||||
\
|
||||
static struct cavs_hda_dma_data cavs_hda_dma##inst##_data = {}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, &cavs_hda_dma_init, NULL, &cavs_hda_dma##inst##_data, \
|
||||
&cavs_hda_dma##inst##_config, POST_KERNEL, CONFIG_DMA_INIT_PRIORITY, \
|
||||
&cavs_hda_dma_link_out_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(CAVS_HDA_DMA_LINK_OUT_INIT)
|
8
dts/bindings/dma/intel,cavs-hda-link-in.yaml
Normal file
8
dts/bindings/dma/intel,cavs-hda-link-in.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Intel cAVS HDA Link In controller
|
||||
|
||||
compatible: "intel,cavs-hda-link-in"
|
||||
|
||||
include: intel,cavs-hda.yaml
|
8
dts/bindings/dma/intel,cavs-hda-link-out.yaml
Normal file
8
dts/bindings/dma/intel,cavs-hda-link-out.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Intel cAVS HDA Link Out controller
|
||||
|
||||
compatible: "intel,cavs-hda-link-out"
|
||||
|
||||
include: intel,cavs-hda.yaml
|
|
@ -31,6 +31,25 @@
|
|||
|
||||
status = "okay";
|
||||
};
|
||||
hda_link_out: dma@72400 {
|
||||
compatible = "intel,cavs-hda-link-out";
|
||||
#dma-cells = <1>;
|
||||
reg = <0x00072400 0x40>;
|
||||
dma-channels = <7>;
|
||||
label = "HDA_LINK_OUT";
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
hda_link_in: dma@72600 {
|
||||
compatible = "intel,cavs-hda-link-in";
|
||||
#dma-cells = <1>;
|
||||
reg = <0x00072600 0x40>;
|
||||
dma-channels = <7>;
|
||||
label = "HDA_LINK_IN";
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
hda_host_out: dma@72800 {
|
||||
compatible = "intel,cavs-hda-host-out";
|
||||
|
@ -51,5 +70,7 @@
|
|||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -241,7 +241,7 @@ static inline uint32_t cavs_hda_unused(uint32_t base, uint32_t sid)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Commit a number of bytes that have been transferred
|
||||
* @brief Commit a number of bytes that have been transferred to/from host
|
||||
*
|
||||
* Writes the length to BFPI. For host transfers LLPI and LPIB are
|
||||
* also written to with the given length.
|
||||
|
@ -259,13 +259,27 @@ static inline uint32_t cavs_hda_unused(uint32_t base, uint32_t sid)
|
|||
* @param sid Stream ID within the register block
|
||||
* @param len Len to increment postion by
|
||||
*/
|
||||
static inline void cavs_hda_commit(uint32_t base, uint32_t sid, uint32_t len)
|
||||
static inline void cavs_hda_host_commit(uint32_t base, uint32_t sid, uint32_t len)
|
||||
{
|
||||
*DGBFPI(base, sid) = len;
|
||||
*DGLLPI(base, sid) = len;
|
||||
*DGLPIBI(base, sid) = len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Commit a number of bytes that have been transferred to/from link
|
||||
*
|
||||
* Writes the length to BFPI.
|
||||
*
|
||||
* @seealso cavs_hda_host_commit
|
||||
*
|
||||
* @param base Base address of the IP register block
|
||||
* @param sid Stream ID within the register block
|
||||
* @param len Len to increment postion by
|
||||
*/
|
||||
static inline void cavs_hda_link_commit(uint32_t base, uint32_t sid, uint32_t len)
|
||||
{
|
||||
*DGBFPI(base, sid) = len;
|
||||
if (base == HDA_HOST_IN_BASE || base == HDA_HOST_OUT_BASE) {
|
||||
*DGLLPI(base, sid) = len;
|
||||
*DGLPIBI(base, sid) = len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -287,8 +301,8 @@ static inline bool cavs_hda_buf_full(uint32_t base, uint32_t sid)
|
|||
* For HDA this does not mean that the buffer is full or empty
|
||||
* there are bit flags for those cases.
|
||||
*
|
||||
* This can let you wait on the hardware to catch up to your
|
||||
* reads or writes (ex after a cavs_hda_commit)
|
||||
* Useful for waiting on the hardware to catch up to
|
||||
* reads or writes (e.g. after a cavs_hda_commit)
|
||||
*
|
||||
* @param dev HDA Stream device
|
||||
* @param sid Stream ID
|
||||
|
|
|
@ -90,7 +90,7 @@ void test_hda_host_in_smoke(void)
|
|||
cavs_hda_dbg("host_in", HDA_HOST_IN_BASE, STREAM_ID);
|
||||
|
||||
for (uint32_t i = 0; i < TRANSFER_COUNT; i++) {
|
||||
cavs_hda_commit(HDA_HOST_IN_BASE, STREAM_ID, HDA_BUF_SIZE);
|
||||
cavs_hda_host_commit(HDA_HOST_IN_BASE, STREAM_ID, HDA_BUF_SIZE);
|
||||
printk("dsp inc_pos: "); cavs_hda_dbg("host_in", HDA_HOST_IN_BASE, STREAM_ID);
|
||||
|
||||
WAIT_FOR(cavs_hda_wp_rp_eq(HDA_HOST_IN_BASE, STREAM_ID), 10000, k_msleep(1));
|
||||
|
@ -186,7 +186,7 @@ void test_hda_host_out_smoke(void)
|
|||
}
|
||||
zassert_true(is_ramp, "Expected data to be a ramp");
|
||||
|
||||
cavs_hda_commit(HDA_HOST_OUT_BASE, STREAM_ID, HDA_BUF_SIZE);
|
||||
cavs_hda_host_commit(HDA_HOST_OUT_BASE, STREAM_ID, HDA_BUF_SIZE);
|
||||
printk("dsp inc pos: "); cavs_hda_dbg("host_out", HDA_HOST_OUT_BASE, STREAM_ID);
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue