summaryrefslogtreecommitdiffstats
path: root/drivers/dma/ste_dma40_ll.c
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-01-25 11:18:35 +0100
committerDan Williams <dan.j.williams@intel.com>2011-01-31 07:27:21 +0100
commit0c842b551063c5f7382ac9b457992f3b34972801 (patch)
treeda606f382493e6cf3540b4245b86a784a78e46b4 /drivers/dma/ste_dma40_ll.c
parentdma40: stop ongoing transfers in DMA_TERMINATE_ALL (diff)
downloadlinux-0c842b551063c5f7382ac9b457992f3b34972801.tar.xz
linux-0c842b551063c5f7382ac9b457992f3b34972801.zip
dma40: cyclic xfer support
Support cyclic transfers, which are useful for ALSA drivers. Acked-by: Per Forlin <per.forlin@stericsson.com> Acked-by: Jonas Aaberg <jonas.aberg@stericsson.com> Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma/ste_dma40_ll.c')
-rw-r--r--drivers/dma/ste_dma40_ll.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index 88b9e371be2f..cad9e1daedff 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -202,13 +202,15 @@ static int d40_seg_size(int size, int data_width1, int data_width2)
static struct d40_phy_lli *
d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
- dma_addr_t lli_phys, u32 reg_cfg,
+ dma_addr_t lli_phys, dma_addr_t first_phys, u32 reg_cfg,
struct stedma40_half_channel_info *info,
struct stedma40_half_channel_info *otherinfo,
unsigned long flags)
{
+ bool lastlink = flags & LLI_LAST_LINK;
bool addr_inc = flags & LLI_ADDR_INC;
bool term_int = flags & LLI_TERM_INT;
+ bool cyclic = flags & LLI_CYCLIC;
int err;
dma_addr_t next = lli_phys;
int size_rest = size;
@@ -226,10 +228,12 @@ d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
otherinfo->data_width);
size_rest -= size_seg;
- if (term_int && size_rest == 0) {
- next = 0;
+ if (size_rest == 0 && term_int)
flags |= LLI_TERM_INT;
- } else
+
+ if (size_rest == 0 && lastlink)
+ next = cyclic ? first_phys : 0;
+ else
next = ALIGN(next + sizeof(struct d40_phy_lli),
D40_LLI_ALIGN);
@@ -257,14 +261,14 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
dma_addr_t lli_phys,
u32 reg_cfg,
struct stedma40_half_channel_info *info,
- struct stedma40_half_channel_info *otherinfo)
+ struct stedma40_half_channel_info *otherinfo,
+ unsigned long flags)
{
int total_size = 0;
int i;
struct scatterlist *current_sg = sg;
struct d40_phy_lli *lli = lli_sg;
dma_addr_t l_phys = lli_phys;
- unsigned long flags = 0;
if (!target)
flags |= LLI_ADDR_INC;
@@ -277,12 +281,12 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
total_size += sg_dma_len(current_sg);
if (i == sg_len - 1)
- flags |= LLI_TERM_INT;
+ flags |= LLI_TERM_INT | LLI_LAST_LINK;
l_phys = ALIGN(lli_phys + (lli - lli_sg) *
sizeof(struct d40_phy_lli), D40_LLI_ALIGN);
- lli = d40_phy_buf_to_lli(lli, dst, len, l_phys,
+ lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, lli_phys,
reg_cfg, info, otherinfo, flags);
if (lli == NULL)
@@ -297,15 +301,18 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
static void d40_log_lli_link(struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
- int next)
+ int next, unsigned int flags)
{
+ bool interrupt = flags & LLI_TERM_INT;
u32 slos = 0;
u32 dlos = 0;
if (next != -EINVAL) {
slos = next * 2;
dlos = next * 2 + 1;
- } else {
+ }
+
+ if (interrupt) {
lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
}
@@ -320,9 +327,9 @@ static void d40_log_lli_link(struct d40_log_lli *lli_dst,
void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
- int next)
+ int next, unsigned int flags)
{
- d40_log_lli_link(lli_dst, lli_src, next);
+ d40_log_lli_link(lli_dst, lli_src, next, flags);
writel(lli_src->lcsp02, &lcpa[0].lcsp0);
writel(lli_src->lcsp13, &lcpa[0].lcsp1);
@@ -333,9 +340,9 @@ void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
struct d40_log_lli *lli_dst,
struct d40_log_lli *lli_src,
- int next)
+ int next, unsigned int flags)
{
- d40_log_lli_link(lli_dst, lli_src, next);
+ d40_log_lli_link(lli_dst, lli_src, next, flags);
writel(lli_src->lcsp02, &lcla[0].lcsp02);
writel(lli_src->lcsp13, &lcla[0].lcsp13);