.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2014 Emilio López |
---|
3 | 4 | * 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. |
---|
9 | 5 | */ |
---|
10 | 6 | |
---|
11 | 7 | #include <linux/bitmap.h> |
---|
.. | .. |
---|
311 | 307 | spin_unlock_irqrestore(&priv->lock, flags); |
---|
312 | 308 | } |
---|
313 | 309 | |
---|
314 | | -/** |
---|
| 310 | +/* |
---|
315 | 311 | * Execute pending operations on a vchan |
---|
316 | 312 | * |
---|
317 | 313 | * When given a vchan, this function will try to acquire a suitable |
---|
.. | .. |
---|
423 | 419 | return 0; |
---|
424 | 420 | } |
---|
425 | 421 | |
---|
426 | | -/** |
---|
| 422 | +/* |
---|
427 | 423 | * Generate a promise, to be used in a normal DMA contract. |
---|
428 | 424 | * |
---|
429 | 425 | * A NDMA promise contains all the information required to program the |
---|
.. | .. |
---|
490 | 486 | return NULL; |
---|
491 | 487 | } |
---|
492 | 488 | |
---|
493 | | -/** |
---|
| 489 | +/* |
---|
494 | 490 | * Generate a promise, to be used in a dedicated DMA contract. |
---|
495 | 491 | * |
---|
496 | 492 | * A DDMA promise contains all the information required to program the |
---|
.. | .. |
---|
547 | 543 | return NULL; |
---|
548 | 544 | } |
---|
549 | 545 | |
---|
550 | | -/** |
---|
| 546 | +/* |
---|
551 | 547 | * Generate a contract |
---|
552 | 548 | * |
---|
553 | 549 | * Contracts function as DMA descriptors. As our hardware does not support |
---|
.. | .. |
---|
569 | 565 | return contract; |
---|
570 | 566 | } |
---|
571 | 567 | |
---|
572 | | -/** |
---|
| 568 | +/* |
---|
573 | 569 | * Get next promise on a cyclic transfer |
---|
574 | 570 | * |
---|
575 | 571 | * Cyclic contracts contain a series of promises which are executed on a |
---|
.. | .. |
---|
593 | 589 | return promise; |
---|
594 | 590 | } |
---|
595 | 591 | |
---|
596 | | -/** |
---|
| 592 | +/* |
---|
597 | 593 | * Free a contract and all its associated promises |
---|
598 | 594 | */ |
---|
599 | 595 | static void sun4i_dma_free_contract(struct virt_dma_desc *vd) |
---|
.. | .. |
---|
673 | 669 | dma_addr_t src, dest; |
---|
674 | 670 | u32 endpoints; |
---|
675 | 671 | int nr_periods, offset, plength, i; |
---|
| 672 | + u8 ram_type, io_mode, linear_mode; |
---|
676 | 673 | |
---|
677 | 674 | if (!is_slave_direction(dir)) { |
---|
678 | 675 | 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"); |
---|
691 | 676 | return NULL; |
---|
692 | 677 | } |
---|
693 | 678 | |
---|
.. | .. |
---|
697 | 682 | |
---|
698 | 683 | contract->is_cyclic = 1; |
---|
699 | 684 | |
---|
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 | + |
---|
701 | 695 | if (dir == DMA_MEM_TO_DEV) { |
---|
702 | 696 | src = buf; |
---|
703 | 697 | 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); |
---|
707 | 702 | } else { |
---|
708 | 703 | src = sconfig->src_addr; |
---|
709 | 704 | 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); |
---|
713 | 709 | } |
---|
714 | 710 | |
---|
715 | 711 | /* |
---|
.. | .. |
---|
751 | 747 | dest = buf + offset; |
---|
752 | 748 | |
---|
753 | 749 | /* 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 | + |
---|
756 | 757 | if (!promise) { |
---|
757 | 758 | /* TODO: should we free everything? */ |
---|
758 | 759 | return NULL; |
---|
.. | .. |
---|
889 | 890 | } |
---|
890 | 891 | |
---|
891 | 892 | spin_lock_irqsave(&vchan->vc.lock, flags); |
---|
892 | | - vchan_dma_desc_free_list(&vchan->vc, &head); |
---|
893 | 893 | /* Clear these so the vchan is usable again */ |
---|
894 | 894 | vchan->processing = NULL; |
---|
895 | 895 | vchan->pchan = NULL; |
---|
896 | 896 | spin_unlock_irqrestore(&vchan->vc.lock, flags); |
---|
| 897 | + |
---|
| 898 | + vchan_dma_desc_free_list(&vchan->vc, &head); |
---|
897 | 899 | |
---|
898 | 900 | return 0; |
---|
899 | 901 | } |
---|
.. | .. |
---|
1136 | 1138 | return PTR_ERR(priv->base); |
---|
1137 | 1139 | |
---|
1138 | 1140 | 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) |
---|
1141 | 1142 | return priv->irq; |
---|
1142 | | - } |
---|
1143 | 1143 | |
---|
1144 | 1144 | priv->clk = devm_clk_get(&pdev->dev, NULL); |
---|
1145 | 1145 | if (IS_ERR(priv->clk)) { |
---|