hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/dma/sun4i-dma.c
....@@ -1,11 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2014 Emilio López
34 * Emilio López <emilio@elopez.com.ar>
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation; either version 2 of the License, or
8
- * (at your option) any later version.
95 */
106
117 #include <linux/bitmap.h>
....@@ -311,7 +307,7 @@
311307 spin_unlock_irqrestore(&priv->lock, flags);
312308 }
313309
314
-/**
310
+/*
315311 * Execute pending operations on a vchan
316312 *
317313 * When given a vchan, this function will try to acquire a suitable
....@@ -423,7 +419,7 @@
423419 return 0;
424420 }
425421
426
-/**
422
+/*
427423 * Generate a promise, to be used in a normal DMA contract.
428424 *
429425 * A NDMA promise contains all the information required to program the
....@@ -490,7 +486,7 @@
490486 return NULL;
491487 }
492488
493
-/**
489
+/*
494490 * Generate a promise, to be used in a dedicated DMA contract.
495491 *
496492 * A DDMA promise contains all the information required to program the
....@@ -547,7 +543,7 @@
547543 return NULL;
548544 }
549545
550
-/**
546
+/*
551547 * Generate a contract
552548 *
553549 * Contracts function as DMA descriptors. As our hardware does not support
....@@ -569,7 +565,7 @@
569565 return contract;
570566 }
571567
572
-/**
568
+/*
573569 * Get next promise on a cyclic transfer
574570 *
575571 * Cyclic contracts contain a series of promises which are executed on a
....@@ -593,7 +589,7 @@
593589 return promise;
594590 }
595591
596
-/**
592
+/*
597593 * Free a contract and all its associated promises
598594 */
599595 static void sun4i_dma_free_contract(struct virt_dma_desc *vd)
....@@ -673,21 +669,10 @@
673669 dma_addr_t src, dest;
674670 u32 endpoints;
675671 int nr_periods, offset, plength, i;
672
+ u8 ram_type, io_mode, linear_mode;
676673
677674 if (!is_slave_direction(dir)) {
678675 dev_err(chan2dev(chan), "Invalid DMA direction\n");
679
- return NULL;
680
- }
681
-
682
- if (vchan->is_dedicated) {
683
- /*
684
- * As we are using this just for audio data, we need to use
685
- * normal DMA. There is nothing stopping us from supporting
686
- * dedicated DMA here as well, so if a client comes up and
687
- * requires it, it will be simple to implement it.
688
- */
689
- dev_err(chan2dev(chan),
690
- "Cyclic transfers are only supported on Normal DMA\n");
691676 return NULL;
692677 }
693678
....@@ -697,19 +682,30 @@
697682
698683 contract->is_cyclic = 1;
699684
700
- /* Figure out the endpoints and the address we need */
685
+ if (vchan->is_dedicated) {
686
+ io_mode = SUN4I_DDMA_ADDR_MODE_IO;
687
+ linear_mode = SUN4I_DDMA_ADDR_MODE_LINEAR;
688
+ ram_type = SUN4I_DDMA_DRQ_TYPE_SDRAM;
689
+ } else {
690
+ io_mode = SUN4I_NDMA_ADDR_MODE_IO;
691
+ linear_mode = SUN4I_NDMA_ADDR_MODE_LINEAR;
692
+ ram_type = SUN4I_NDMA_DRQ_TYPE_SDRAM;
693
+ }
694
+
701695 if (dir == DMA_MEM_TO_DEV) {
702696 src = buf;
703697 dest = sconfig->dst_addr;
704
- endpoints = SUN4I_DMA_CFG_SRC_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM) |
705
- SUN4I_DMA_CFG_DST_DRQ_TYPE(vchan->endpoint) |
706
- SUN4I_DMA_CFG_DST_ADDR_MODE(SUN4I_NDMA_ADDR_MODE_IO);
698
+ endpoints = SUN4I_DMA_CFG_DST_DRQ_TYPE(vchan->endpoint) |
699
+ SUN4I_DMA_CFG_DST_ADDR_MODE(io_mode) |
700
+ SUN4I_DMA_CFG_SRC_DRQ_TYPE(ram_type) |
701
+ SUN4I_DMA_CFG_SRC_ADDR_MODE(linear_mode);
707702 } else {
708703 src = sconfig->src_addr;
709704 dest = buf;
710
- endpoints = SUN4I_DMA_CFG_SRC_DRQ_TYPE(vchan->endpoint) |
711
- SUN4I_DMA_CFG_SRC_ADDR_MODE(SUN4I_NDMA_ADDR_MODE_IO) |
712
- SUN4I_DMA_CFG_DST_DRQ_TYPE(SUN4I_NDMA_DRQ_TYPE_SDRAM);
705
+ endpoints = SUN4I_DMA_CFG_DST_DRQ_TYPE(ram_type) |
706
+ SUN4I_DMA_CFG_DST_ADDR_MODE(linear_mode) |
707
+ SUN4I_DMA_CFG_SRC_DRQ_TYPE(vchan->endpoint) |
708
+ SUN4I_DMA_CFG_SRC_ADDR_MODE(io_mode);
713709 }
714710
715711 /*
....@@ -751,8 +747,13 @@
751747 dest = buf + offset;
752748
753749 /* Make the promise */
754
- promise = generate_ndma_promise(chan, src, dest,
755
- plength, sconfig, dir);
750
+ if (vchan->is_dedicated)
751
+ promise = generate_ddma_promise(chan, src, dest,
752
+ plength, sconfig);
753
+ else
754
+ promise = generate_ndma_promise(chan, src, dest,
755
+ plength, sconfig, dir);
756
+
756757 if (!promise) {
757758 /* TODO: should we free everything? */
758759 return NULL;
....@@ -889,11 +890,12 @@
889890 }
890891
891892 spin_lock_irqsave(&vchan->vc.lock, flags);
892
- vchan_dma_desc_free_list(&vchan->vc, &head);
893893 /* Clear these so the vchan is usable again */
894894 vchan->processing = NULL;
895895 vchan->pchan = NULL;
896896 spin_unlock_irqrestore(&vchan->vc.lock, flags);
897
+
898
+ vchan_dma_desc_free_list(&vchan->vc, &head);
897899
898900 return 0;
899901 }
....@@ -1136,10 +1138,8 @@
11361138 return PTR_ERR(priv->base);
11371139
11381140 priv->irq = platform_get_irq(pdev, 0);
1139
- if (priv->irq < 0) {
1140
- dev_err(&pdev->dev, "Cannot claim IRQ\n");
1141
+ if (priv->irq < 0)
11411142 return priv->irq;
1142
- }
11431143
11441144 priv->clk = devm_clk_get(&pdev->dev, NULL);
11451145 if (IS_ERR(priv->clk)) {