1/* 2 Mantis PCI bridge driver 3 4 Copyright (C) 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 <linux/kernel.h> 22#include <asm/page.h> 23#include <linux/vmalloc.h> 24#include <linux/pci.h> 25 26#include <asm/irq.h> 27#include <linux/signal.h> 28#include <linux/sched.h> 29#include <linux/interrupt.h> 30 31#include "dmxdev.h" 32#include "dvbdev.h" 33#include "dvb_demux.h" 34#include "dvb_frontend.h" 35#include "dvb_net.h" 36 37#include "mantis_common.h" 38#include "mantis_reg.h" 39#include "mantis_dma.h" 40 41#define RISC_WRITE (0x01 << 28) 42#define RISC_JUMP (0x07 << 28) 43#define RISC_IRQ (0x01 << 24) 44 45#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) 46#define RISC_FLUSH() (mantis->risc_pos = 0) 47#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode)) 48 49#define MANTIS_BUF_SIZE (64 * 1024) 50#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) 51#define MANTIS_BLOCK_COUNT (1 << 4) 52#define MANTIS_RISC_SIZE PAGE_SIZE 53 54int mantis_dma_exit(struct mantis_pci *mantis) 55{ 56 if (mantis->buf_cpu) { 57 dprintk(MANTIS_ERROR, 1, 58 "DMA=0x%lx cpu=0x%p size=%d", 59 (unsigned long) mantis->buf_dma, 60 mantis->buf_cpu, 61 MANTIS_BUF_SIZE); 62 63 pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE, 64 mantis->buf_cpu, mantis->buf_dma); 65 66 mantis->buf_cpu = NULL; 67 } 68 if (mantis->risc_cpu) { 69 dprintk(MANTIS_ERROR, 1, 70 "RISC=0x%lx cpu=0x%p size=%lx", 71 (unsigned long) mantis->risc_dma, 72 mantis->risc_cpu, 73 MANTIS_RISC_SIZE); 74 75 pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE, 76 mantis->risc_cpu, mantis->risc_dma); 77 78 mantis->risc_cpu = NULL; 79 } 80 81 return 0; 82} 83EXPORT_SYMBOL_GPL(mantis_dma_exit); 84 85static inline int mantis_alloc_buffers(struct mantis_pci *mantis) 86{ 87 if (!mantis->buf_cpu) { 88 mantis->buf_cpu = pci_alloc_consistent(mantis->pdev, 89 MANTIS_BUF_SIZE, 90 &mantis->buf_dma); 91 if (!mantis->buf_cpu) { 92 dprintk(MANTIS_ERROR, 1, 93 "DMA buffer allocation failed"); 94 95 goto err; 96 } 97 dprintk(MANTIS_ERROR, 1, 98 "DMA=0x%lx cpu=0x%p size=%d", 99 (unsigned long) mantis->buf_dma, 100 mantis->buf_cpu, MANTIS_BUF_SIZE); 101 } 102 if (!mantis->risc_cpu) { 103 mantis->risc_cpu = pci_alloc_consistent(mantis->pdev, 104 MANTIS_RISC_SIZE, 105 &mantis->risc_dma); 106 107 if (!mantis->risc_cpu) { 108 dprintk(MANTIS_ERROR, 1, 109 "RISC program allocation failed"); 110 111 mantis_dma_exit(mantis); 112 113 goto err; 114 } 115 dprintk(MANTIS_ERROR, 1, 116 "RISC=0x%lx cpu=0x%p size=%lx", 117 (unsigned long) mantis->risc_dma, 118 mantis->risc_cpu, MANTIS_RISC_SIZE); 119 } 120 121 return 0; 122err: 123 dprintk(MANTIS_ERROR, 1, "Out of memory (?) ....."); 124 return -ENOMEM; 125} 126 127static inline int mantis_calc_lines(struct mantis_pci *mantis) 128{ 129 mantis->line_bytes = MANTIS_BLOCK_BYTES; 130 mantis->line_count = MANTIS_BLOCK_COUNT; 131 132 while (mantis->line_bytes > 4095) { 133 mantis->line_bytes >>= 1; 134 mantis->line_count <<= 1; 135 } 136 137 dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", 138 MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); 139 140 if (mantis->line_count > 255) { 141 dprintk(MANTIS_ERROR, 1, "Buffer size error"); 142 return -EINVAL; 143 } 144 145 return 0; 146} 147 148int mantis_dma_init(struct mantis_pci *mantis) 149{ 150 int err = 0; 151 152 dprintk(MANTIS_DEBUG, 1, "Mantis DMA init"); 153 if (mantis_alloc_buffers(mantis) < 0) { 154 dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer"); 155 156 /* Stop RISC Engine */ 157 mmwrite(0, MANTIS_DMA_CTL); 158 159 goto err; 160 } 161 err = mantis_calc_lines(mantis); 162 if (err < 0) { 163 dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed"); 164 165 goto err; 166 } 167 168 return 0; 169err: 170 return err; 171} 172EXPORT_SYMBOL_GPL(mantis_dma_init); 173 174static inline void mantis_risc_program(struct mantis_pci *mantis) 175{ 176 u32 buf_pos = 0; 177 u32 line; 178 179 dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program"); 180 RISC_FLUSH(); 181 182 dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", 183 mantis->line_count, mantis->line_bytes); 184 185 for (line = 0; line < mantis->line_count; line++) { 186 dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); 187 if (!(buf_pos % MANTIS_BLOCK_BYTES)) { 188 RISC_INSTR(RISC_WRITE | 189 RISC_IRQ | 190 RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) + 191 (MANTIS_BLOCK_COUNT - 1)) % 192 MANTIS_BLOCK_COUNT) | 193 mantis->line_bytes); 194 } else { 195 RISC_INSTR(RISC_WRITE | mantis->line_bytes); 196 } 197 RISC_INSTR(mantis->buf_dma + buf_pos); 198 buf_pos += mantis->line_bytes; 199 } 200 RISC_INSTR(RISC_JUMP); 201 RISC_INSTR(mantis->risc_dma); 202} 203 204void mantis_dma_start(struct mantis_pci *mantis) 205{ 206 dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine"); 207 208 mantis_risc_program(mantis); 209 mmwrite(mantis->risc_dma, MANTIS_RISC_START); 210 mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); 211 212 mmwrite(0, MANTIS_DMA_CTL); 213 mantis->last_block = mantis->finished_block = 0; 214 215 mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); 216 217 mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN 218 | MANTIS_RISC_EN, MANTIS_DMA_CTL); 219 220} 221 222void mantis_dma_stop(struct mantis_pci *mantis) 223{ 224 u32 stat = 0, mask = 0; 225 226 stat = mmread(MANTIS_INT_STAT); 227 mask = mmread(MANTIS_INT_MASK); 228 dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); 229 230 mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR); 231 232 mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | 233 MANTIS_DCAP_EN | 234 MANTIS_RISC_EN)), MANTIS_DMA_CTL); 235 236 mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT); 237 238 mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI | 239 MANTIS_INT_RISCEN), MANTIS_INT_MASK); 240} 241 242 243void mantis_dma_xfer(unsigned long data) 244{ 245 struct mantis_pci *mantis = (struct mantis_pci *) data; 246 struct mantis_hwconfig *config = mantis->hwconfig; 247 248 while (mantis->last_block != mantis->finished_block) { 249 dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", 250 mantis->last_block, mantis->finished_block); 251 252 (config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter) 253 (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); 254 mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; 255 } 256} 257