aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ste_dma40_ll.c
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-01-25 05:18:35 -0500
committerDan Williams <dan.j.williams@intel.com>2011-01-31 01:27:21 -0500
commit0c842b551063c5f7382ac9b457992f3b34972801 (patch)
treeda606f382493e6cf3540b4245b86a784a78e46b4 /drivers/dma/ste_dma40_ll.c
parent86eb5fb61125e4646c9447a1f2ce130817dab34e (diff)
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)
202 202
203static struct d40_phy_lli * 203static struct d40_phy_lli *
204d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size, 204d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
205 dma_addr_t lli_phys, u32 reg_cfg, 205 dma_addr_t lli_phys, dma_addr_t first_phys, u32 reg_cfg,
206 struct stedma40_half_channel_info *info, 206 struct stedma40_half_channel_info *info,
207 struct stedma40_half_channel_info *otherinfo, 207 struct stedma40_half_channel_info *otherinfo,
208 unsigned long flags) 208 unsigned long flags)
209{ 209{
210 bool lastlink = flags & LLI_LAST_LINK;
210 bool addr_inc = flags & LLI_ADDR_INC; 211 bool addr_inc = flags & LLI_ADDR_INC;
211 bool term_int = flags & LLI_TERM_INT; 212 bool term_int = flags & LLI_TERM_INT;
213 bool cyclic = flags & LLI_CYCLIC;
212 int err; 214 int err;
213 dma_addr_t next = lli_phys; 215 dma_addr_t next = lli_phys;
214 int size_rest = size; 216 int size_rest = size;
@@ -226,10 +228,12 @@ d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
226 otherinfo->data_width); 228 otherinfo->data_width);
227 size_rest -= size_seg; 229 size_rest -= size_seg;
228 230
229 if (term_int && size_rest == 0) { 231 if (size_rest == 0 && term_int)
230 next = 0;
231 flags |= LLI_TERM_INT; 232 flags |= LLI_TERM_INT;
232 } else 233
234 if (size_rest == 0 && lastlink)
235 next = cyclic ? first_phys : 0;
236 else
233 next = ALIGN(next + sizeof(struct d40_phy_lli), 237 next = ALIGN(next + sizeof(struct d40_phy_lli),
234 D40_LLI_ALIGN); 238 D40_LLI_ALIGN);
235 239
@@ -257,14 +261,14 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
257 dma_addr_t lli_phys, 261 dma_addr_t lli_phys,
258 u32 reg_cfg, 262 u32 reg_cfg,
259 struct stedma40_half_channel_info *info, 263 struct stedma40_half_channel_info *info,
260 struct stedma40_half_channel_info *otherinfo) 264 struct stedma40_half_channel_info *otherinfo,
265 unsigned long flags)
261{ 266{
262 int total_size = 0; 267 int total_size = 0;
263 int i; 268 int i;
264 struct scatterlist *current_sg = sg; 269 struct scatterlist *current_sg = sg;
265 struct d40_phy_lli *lli = lli_sg; 270 struct d40_phy_lli *lli = lli_sg;
266 dma_addr_t l_phys = lli_phys; 271 dma_addr_t l_phys = lli_phys;
267 unsigned long flags = 0;
268 272
269 if (!target) 273 if (!target)
270 flags |= LLI_ADDR_INC; 274 flags |= LLI_ADDR_INC;
@@ -277,12 +281,12 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
277 total_size += sg_dma_len(current_sg); 281 total_size += sg_dma_len(current_sg);
278 282
279 if (i == sg_len - 1) 283 if (i == sg_len - 1)
280 flags |= LLI_TERM_INT; 284 flags |= LLI_TERM_INT | LLI_LAST_LINK;
281 285
282 l_phys = ALIGN(lli_phys + (lli - lli_sg) * 286 l_phys = ALIGN(lli_phys + (lli - lli_sg) *
283 sizeof(struct d40_phy_lli), D40_LLI_ALIGN); 287 sizeof(struct d40_phy_lli), D40_LLI_ALIGN);
284 288
285 lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, 289 lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, lli_phys,
286 reg_cfg, info, otherinfo, flags); 290 reg_cfg, info, otherinfo, flags);
287 291
288 if (lli == NULL) 292 if (lli == NULL)
@@ -297,15 +301,18 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
297 301
298static void d40_log_lli_link(struct d40_log_lli *lli_dst, 302static void d40_log_lli_link(struct d40_log_lli *lli_dst,
299 struct d40_log_lli *lli_src, 303 struct d40_log_lli *lli_src,
300 int next) 304 int next, unsigned int flags)
301{ 305{
306 bool interrupt = flags & LLI_TERM_INT;
302 u32 slos = 0; 307 u32 slos = 0;
303 u32 dlos = 0; 308 u32 dlos = 0;
304 309
305 if (next != -EINVAL) { 310 if (next != -EINVAL) {
306 slos = next * 2; 311 slos = next * 2;
307 dlos = next * 2 + 1; 312 dlos = next * 2 + 1;
308 } else { 313 }
314
315 if (interrupt) {
309 lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK; 316 lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
310 lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK; 317 lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
311 } 318 }
@@ -320,9 +327,9 @@ static void d40_log_lli_link(struct d40_log_lli *lli_dst,
320void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa, 327void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
321 struct d40_log_lli *lli_dst, 328 struct d40_log_lli *lli_dst,
322 struct d40_log_lli *lli_src, 329 struct d40_log_lli *lli_src,
323 int next) 330 int next, unsigned int flags)
324{ 331{
325 d40_log_lli_link(lli_dst, lli_src, next); 332 d40_log_lli_link(lli_dst, lli_src, next, flags);
326 333
327 writel(lli_src->lcsp02, &lcpa[0].lcsp0); 334 writel(lli_src->lcsp02, &lcpa[0].lcsp0);
328 writel(lli_src->lcsp13, &lcpa[0].lcsp1); 335 writel(lli_src->lcsp13, &lcpa[0].lcsp1);
@@ -333,9 +340,9 @@ void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
333void d40_log_lli_lcla_write(struct d40_log_lli *lcla, 340void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
334 struct d40_log_lli *lli_dst, 341 struct d40_log_lli *lli_dst,
335 struct d40_log_lli *lli_src, 342 struct d40_log_lli *lli_src,
336 int next) 343 int next, unsigned int flags)
337{ 344{
338 d40_log_lli_link(lli_dst, lli_src, next); 345 d40_log_lli_link(lli_dst, lli_src, next, flags);
339 346
340 writel(lli_src->lcsp02, &lcla[0].lcsp02); 347 writel(lli_src->lcsp02, &lcla[0].lcsp02);
341 writel(lli_src->lcsp13, &lcla[0].lcsp13); 348 writel(lli_src->lcsp13, &lcla[0].lcsp13);