1 // SPDX-License-Identifier: GPL-2.0-or-later
3 Mantis PCI bridge driver
5 Copyright (C) Manu Abraham (abraham.manu@gmail.com)
9 #include <linux/kernel.h>
11 #include <linux/vmalloc.h>
12 #include <linux/pci.h>
15 #include <linux/signal.h>
16 #include <linux/sched.h>
17 #include <linux/interrupt.h>
19 #include <media/dmxdev.h>
20 #include <media/dvbdev.h>
21 #include <media/dvb_demux.h>
22 #include <media/dvb_frontend.h>
23 #include <media/dvb_net.h>
25 #include "mantis_common.h"
26 #include "mantis_reg.h"
27 #include "mantis_dma.h"
29 #define RISC_WRITE (0x01 << 28)
30 #define RISC_JUMP (0x07 << 28)
31 #define RISC_IRQ (0x01 << 24)
33 #define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
34 #define RISC_FLUSH(risc_pos) (risc_pos = 0)
35 #define RISC_INSTR(risc_pos, opcode) (mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode))
37 #define MANTIS_BUF_SIZE (64 * 1024)
38 #define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE / 4)
39 #define MANTIS_DMA_TR_BYTES (2 * 1024) /* upper limit: 4095 bytes. */
40 #define MANTIS_BLOCK_COUNT (MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES)
42 #define MANTIS_DMA_TR_UNITS (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES)
43 /* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */
44 #define MANTIS_RISC_SIZE PAGE_SIZE /* RISC program must fit here. */
46 int mantis_dma_exit(struct mantis_pci
*mantis
)
48 if (mantis
->buf_cpu
) {
49 dprintk(MANTIS_ERROR
, 1,
50 "DMA=0x%lx cpu=0x%p size=%d",
51 (unsigned long) mantis
->buf_dma
,
55 pci_free_consistent(mantis
->pdev
, MANTIS_BUF_SIZE
,
56 mantis
->buf_cpu
, mantis
->buf_dma
);
58 mantis
->buf_cpu
= NULL
;
60 if (mantis
->risc_cpu
) {
61 dprintk(MANTIS_ERROR
, 1,
62 "RISC=0x%lx cpu=0x%p size=%lx",
63 (unsigned long) mantis
->risc_dma
,
67 pci_free_consistent(mantis
->pdev
, MANTIS_RISC_SIZE
,
68 mantis
->risc_cpu
, mantis
->risc_dma
);
70 mantis
->risc_cpu
= NULL
;
75 EXPORT_SYMBOL_GPL(mantis_dma_exit
);
77 static inline int mantis_alloc_buffers(struct mantis_pci
*mantis
)
79 if (!mantis
->buf_cpu
) {
80 mantis
->buf_cpu
= pci_alloc_consistent(mantis
->pdev
,
83 if (!mantis
->buf_cpu
) {
84 dprintk(MANTIS_ERROR
, 1,
85 "DMA buffer allocation failed");
89 dprintk(MANTIS_ERROR
, 1,
90 "DMA=0x%lx cpu=0x%p size=%d",
91 (unsigned long) mantis
->buf_dma
,
92 mantis
->buf_cpu
, MANTIS_BUF_SIZE
);
94 if (!mantis
->risc_cpu
) {
95 mantis
->risc_cpu
= pci_alloc_consistent(mantis
->pdev
,
99 if (!mantis
->risc_cpu
) {
100 dprintk(MANTIS_ERROR
, 1,
101 "RISC program allocation failed");
103 mantis_dma_exit(mantis
);
107 dprintk(MANTIS_ERROR
, 1,
108 "RISC=0x%lx cpu=0x%p size=%lx",
109 (unsigned long) mantis
->risc_dma
,
110 mantis
->risc_cpu
, MANTIS_RISC_SIZE
);
115 dprintk(MANTIS_ERROR
, 1, "Out of memory (?) .....");
119 int mantis_dma_init(struct mantis_pci
*mantis
)
123 dprintk(MANTIS_DEBUG
, 1, "Mantis DMA init");
124 err
= mantis_alloc_buffers(mantis
);
126 dprintk(MANTIS_ERROR
, 1, "Error allocating DMA buffer");
128 /* Stop RISC Engine */
129 mmwrite(0, MANTIS_DMA_CTL
);
136 EXPORT_SYMBOL_GPL(mantis_dma_init
);
138 static inline void mantis_risc_program(struct mantis_pci
*mantis
)
144 dprintk(MANTIS_DEBUG
, 1, "Mantis create RISC program");
145 RISC_FLUSH(risc_pos
);
147 dprintk(MANTIS_DEBUG
, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u",
148 MANTIS_BLOCK_COUNT
, MANTIS_BLOCK_BYTES
, MANTIS_DMA_TR_BYTES
);
150 for (line
= 0; line
< MANTIS_BLOCK_COUNT
; line
++) {
151 for (step
= 0; step
< MANTIS_DMA_TR_UNITS
; step
++) {
152 dprintk(MANTIS_DEBUG
, 1, "RISC PROG line=[%d], step=[%d]", line
, step
);
154 RISC_INSTR(risc_pos
, RISC_WRITE
|
157 MANTIS_DMA_TR_BYTES
);
159 RISC_INSTR(risc_pos
, RISC_WRITE
| MANTIS_DMA_TR_BYTES
);
161 RISC_INSTR(risc_pos
, mantis
->buf_dma
+ buf_pos
);
162 buf_pos
+= MANTIS_DMA_TR_BYTES
;
165 RISC_INSTR(risc_pos
, RISC_JUMP
);
166 RISC_INSTR(risc_pos
, mantis
->risc_dma
);
169 void mantis_dma_start(struct mantis_pci
*mantis
)
171 dprintk(MANTIS_DEBUG
, 1, "Mantis Start DMA engine");
173 mantis_risc_program(mantis
);
174 mmwrite(mantis
->risc_dma
, MANTIS_RISC_START
);
175 mmwrite(mmread(MANTIS_GPIF_ADDR
) | MANTIS_GPIF_HIFRDWRN
, MANTIS_GPIF_ADDR
);
177 mmwrite(0, MANTIS_DMA_CTL
);
178 mantis
->last_block
= mantis
->busy_block
= 0;
180 mantis_unmask_ints(mantis
, MANTIS_INT_RISCI
);
182 mmwrite(MANTIS_FIFO_EN
| MANTIS_DCAP_EN
183 | MANTIS_RISC_EN
, MANTIS_DMA_CTL
);
187 void mantis_dma_stop(struct mantis_pci
*mantis
)
189 dprintk(MANTIS_DEBUG
, 1, "Mantis Stop DMA engine");
191 mmwrite((mmread(MANTIS_GPIF_ADDR
) & (~(MANTIS_GPIF_HIFRDWRN
))), MANTIS_GPIF_ADDR
);
193 mmwrite((mmread(MANTIS_DMA_CTL
) & ~(MANTIS_FIFO_EN
|
195 MANTIS_RISC_EN
)), MANTIS_DMA_CTL
);
197 mmwrite(mmread(MANTIS_INT_STAT
), MANTIS_INT_STAT
);
199 mantis_mask_ints(mantis
, MANTIS_INT_RISCI
| MANTIS_INT_RISCEN
);
203 void mantis_dma_xfer(struct tasklet_struct
*t
)
205 struct mantis_pci
*mantis
= from_tasklet(mantis
, t
, tasklet
);
206 struct mantis_hwconfig
*config
= mantis
->hwconfig
;
208 while (mantis
->last_block
!= mantis
->busy_block
) {
209 dprintk(MANTIS_DEBUG
, 1, "last block=[%d] finished block=[%d]",
210 mantis
->last_block
, mantis
->busy_block
);
212 (config
->ts_size
? dvb_dmx_swfilter_204
: dvb_dmx_swfilter
)
213 (&mantis
->demux
, &mantis
->buf_cpu
[mantis
->last_block
* MANTIS_BLOCK_BYTES
], MANTIS_BLOCK_BYTES
);
214 mantis
->last_block
= (mantis
->last_block
+ 1) % MANTIS_BLOCK_COUNT
;