diff options
author | Manu Abraham <abraham.manu@gmail.com> | 2009-12-02 19:57:10 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-01-17 08:55:27 -0500 |
commit | 41e840b13e111ba18b138d055ddd250bd5ad5e39 (patch) | |
tree | dd5c1a60f06549925277c396a964724dd87329e1 /drivers/media/dvb/mantis/mantis_dma.c | |
parent | 6ccf80eb15ccaca4d3f1ab5162b9ded5eecd9971 (diff) |
V4L/DVB (13699): [Mantis, MB86A16] Initial checkin: Mantis, MB86A16
Signed-off-by: Manu Abraham <manu@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/mantis/mantis_dma.c')
-rw-r--r-- | drivers/media/dvb/mantis/mantis_dma.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c new file mode 100644 index 000000000000..9e3aa5ec1645 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dma.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | Mantis PCI bridge driver | ||
3 | |||
4 | Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program; if not, write to the Free Software | ||
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <asm/page.h> | ||
22 | #include <linux/vmalloc.h> | ||
23 | #include "mantis_common.h" | ||
24 | |||
25 | #define RISC_WRITE (0x01 << 28) | ||
26 | #define RISC_JUMP (0x07 << 28) | ||
27 | #define RISC_IRQ (0x01 << 24) | ||
28 | |||
29 | #define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) | ||
30 | #define RISC_FLUSH() mantis->risc_pos = 0 | ||
31 | #define RISC_INSTR(opcode) mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode) | ||
32 | |||
33 | #define MANTIS_BUF_SIZE 64 * 1024 | ||
34 | #define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) | ||
35 | #define MANTIS_BLOCK_COUNT (1 << 4) | ||
36 | #define MANTIS_RISC_SIZE PAGE_SIZE | ||
37 | |||
38 | int mantis_dma_exit(struct mantis_pci *mantis) | ||
39 | { | ||
40 | if (mantis->buf_cpu) { | ||
41 | dprintk(verbose, MANTIS_ERROR, 1, | ||
42 | "DMA=0x%lx cpu=0x%p size=%d", | ||
43 | (unsigned long) mantis->buf_dma, | ||
44 | mantis->buf_cpu, | ||
45 | MANTIS_BUF_SIZE); | ||
46 | |||
47 | pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE, | ||
48 | mantis->buf_cpu, mantis->buf_dma); | ||
49 | |||
50 | mantis->buf_cpu = NULL; | ||
51 | } | ||
52 | if (mantis->risc_cpu) { | ||
53 | dprintk(verbose, MANTIS_ERROR, 1, | ||
54 | "RISC=0x%lx cpu=0x%p size=%lx", | ||
55 | (unsigned long) mantis->risc_dma, | ||
56 | mantis->risc_cpu, | ||
57 | MANTIS_RISC_SIZE); | ||
58 | |||
59 | pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE, | ||
60 | mantis->risc_cpu, mantis->risc_dma); | ||
61 | |||
62 | mantis->risc_cpu = NULL; | ||
63 | } | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static inline int mantis_alloc_buffers(struct mantis_pci *mantis) | ||
69 | { | ||
70 | if (!mantis->buf_cpu) { | ||
71 | mantis->buf_cpu = pci_alloc_consistent(mantis->pdev, | ||
72 | MANTIS_BUF_SIZE, | ||
73 | &mantis->buf_dma); | ||
74 | if (!mantis->buf_cpu) { | ||
75 | dprintk(verbose, MANTIS_ERROR, 1, | ||
76 | "DMA buffer allocation failed"); | ||
77 | |||
78 | goto err; | ||
79 | } | ||
80 | dprintk(verbose, MANTIS_ERROR, 1, | ||
81 | "DMA=0x%lx cpu=0x%p size=%d", | ||
82 | (unsigned long) mantis->buf_dma, | ||
83 | mantis->buf_cpu, MANTIS_BUF_SIZE); | ||
84 | } | ||
85 | if (!mantis->risc_cpu) { | ||
86 | mantis->risc_cpu = pci_alloc_consistent(mantis->pdev, | ||
87 | MANTIS_RISC_SIZE, | ||
88 | &mantis->risc_dma); | ||
89 | |||
90 | if (!mantis->risc_cpu) { | ||
91 | dprintk(verbose, MANTIS_ERROR, 1, | ||
92 | "RISC program allocation failed"); | ||
93 | |||
94 | mantis_dma_exit(mantis); | ||
95 | |||
96 | goto err; | ||
97 | } | ||
98 | dprintk(verbose, MANTIS_ERROR, 1, | ||
99 | "RISC=0x%lx cpu=0x%p size=%lx", | ||
100 | (unsigned long) mantis->risc_dma, | ||
101 | mantis->risc_cpu, MANTIS_RISC_SIZE); | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | err: | ||
106 | dprintk(verbose, MANTIS_ERROR, 1, "Out of memory (?) ....."); | ||
107 | return -ENOMEM; | ||
108 | } | ||
109 | |||
110 | static inline int mantis_calc_lines(struct mantis_pci *mantis) | ||
111 | { | ||
112 | mantis->line_bytes = MANTIS_BLOCK_BYTES; | ||
113 | mantis->line_count = MANTIS_BLOCK_COUNT; | ||
114 | |||
115 | while (mantis->line_bytes > 4095) { | ||
116 | mantis->line_bytes >>= 1; | ||
117 | mantis->line_count <<= 1; | ||
118 | } | ||
119 | |||
120 | dprintk(verbose, MANTIS_DEBUG, 1, | ||
121 | "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", | ||
122 | MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); | ||
123 | |||
124 | if (mantis->line_count > 255) { | ||
125 | dprintk(verbose, MANTIS_ERROR, 1, "Buffer size error"); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | int mantis_dma_init(struct mantis_pci *mantis) | ||
133 | { | ||
134 | int err = 0; | ||
135 | |||
136 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DMA init"); | ||
137 | if (mantis_alloc_buffers(mantis) < 0) { | ||
138 | dprintk(verbose, MANTIS_ERROR, 1, "Error allocating DMA buffer"); | ||
139 | |||
140 | // Stop RISC Engine | ||
141 | // mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); | ||
142 | mmwrite(0, MANTIS_DMA_CTL); | ||
143 | |||
144 | goto err; | ||
145 | } | ||
146 | if ((err = mantis_calc_lines(mantis)) < 0) { | ||
147 | dprintk(verbose, MANTIS_ERROR, 1, "Mantis calc lines failed"); | ||
148 | |||
149 | goto err; | ||
150 | } | ||
151 | |||
152 | return 0; | ||
153 | err: | ||
154 | return err; | ||
155 | } | ||
156 | |||
157 | |||
158 | |||
159 | static inline void mantis_risc_program(struct mantis_pci *mantis) | ||
160 | { | ||
161 | u32 buf_pos = 0; | ||
162 | u32 line; | ||
163 | |||
164 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis create RISC program"); | ||
165 | RISC_FLUSH(); | ||
166 | |||
167 | dprintk(verbose, MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", | ||
168 | mantis->line_count, mantis->line_bytes); | ||
169 | |||
170 | for (line = 0; line < mantis->line_count; line++) { | ||
171 | dprintk(verbose, MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); | ||
172 | if (!(buf_pos % MANTIS_BLOCK_BYTES)) { | ||
173 | RISC_INSTR(RISC_WRITE | | ||
174 | RISC_IRQ | | ||
175 | RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) + | ||
176 | (MANTIS_BLOCK_COUNT - 1)) % | ||
177 | MANTIS_BLOCK_COUNT) | | ||
178 | mantis->line_bytes); | ||
179 | } else { | ||
180 | RISC_INSTR(RISC_WRITE | mantis->line_bytes); | ||
181 | } | ||
182 | RISC_INSTR(mantis->buf_dma + buf_pos); | ||
183 | buf_pos += mantis->line_bytes; | ||
184 | } | ||
185 | RISC_INSTR(RISC_JUMP); | ||
186 | RISC_INSTR(mantis->risc_dma); | ||
187 | } | ||
188 | |||
189 | void mantis_dma_start(struct mantis_pci *mantis) | ||
190 | { | ||
191 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); | ||
192 | |||
193 | mantis_risc_program(mantis); | ||
194 | mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); | ||
195 | mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); | ||
196 | |||
197 | mmwrite(0, MANTIS_DMA_CTL); | ||
198 | mantis->last_block = mantis->finished_block = 0; | ||
199 | |||
200 | mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); | ||
201 | |||
202 | mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN | ||
203 | | MANTIS_RISC_EN, MANTIS_DMA_CTL); | ||
204 | |||
205 | } | ||
206 | |||
207 | void mantis_dma_stop(struct mantis_pci *mantis) | ||
208 | { | ||
209 | u32 stat = 0, mask = 0; | ||
210 | |||
211 | stat = mmread(MANTIS_INT_STAT); | ||
212 | mask = mmread(MANTIS_INT_MASK); | ||
213 | dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); | ||
214 | |||
215 | mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | | ||
216 | MANTIS_DCAP_EN | | ||
217 | MANTIS_RISC_EN)), MANTIS_DMA_CTL); | ||
218 | |||
219 | mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT); | ||
220 | |||
221 | mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI | | ||
222 | MANTIS_INT_RISCEN), MANTIS_INT_MASK); | ||
223 | } | ||
224 | |||
225 | |||
226 | void mantis_dma_xfer(unsigned long data) | ||
227 | { | ||
228 | struct mantis_pci *mantis = (struct mantis_pci *) data; | ||
229 | |||
230 | while (mantis->last_block != mantis->finished_block) { | ||
231 | dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", | ||
232 | mantis->last_block, mantis->finished_block); | ||
233 | |||
234 | (mantis->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) | ||
235 | (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); | ||
236 | mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; | ||
237 | } | ||
238 | } | ||