Path: blob/master/drivers/media/dvb/mantis/mantis_dma.c
15112 views
/*1Mantis PCI bridge driver23Copyright (C) Manu Abraham ([email protected])45This program is free software; you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation; either version 2 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program; if not, write to the Free Software17Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.18*/1920#include <linux/kernel.h>21#include <asm/page.h>22#include <linux/vmalloc.h>23#include <linux/pci.h>2425#include <asm/irq.h>26#include <linux/signal.h>27#include <linux/sched.h>28#include <linux/interrupt.h>2930#include "dmxdev.h"31#include "dvbdev.h"32#include "dvb_demux.h"33#include "dvb_frontend.h"34#include "dvb_net.h"3536#include "mantis_common.h"37#include "mantis_reg.h"38#include "mantis_dma.h"3940#define RISC_WRITE (0x01 << 28)41#define RISC_JUMP (0x07 << 28)42#define RISC_IRQ (0x01 << 24)4344#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))45#define RISC_FLUSH() (mantis->risc_pos = 0)46#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode))4748#define MANTIS_BUF_SIZE (64 * 1024)49#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4)50#define MANTIS_BLOCK_COUNT (1 << 4)51#define MANTIS_RISC_SIZE PAGE_SIZE5253int mantis_dma_exit(struct mantis_pci *mantis)54{55if (mantis->buf_cpu) {56dprintk(MANTIS_ERROR, 1,57"DMA=0x%lx cpu=0x%p size=%d",58(unsigned long) mantis->buf_dma,59mantis->buf_cpu,60MANTIS_BUF_SIZE);6162pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE,63mantis->buf_cpu, mantis->buf_dma);6465mantis->buf_cpu = NULL;66}67if (mantis->risc_cpu) {68dprintk(MANTIS_ERROR, 1,69"RISC=0x%lx cpu=0x%p size=%lx",70(unsigned long) mantis->risc_dma,71mantis->risc_cpu,72MANTIS_RISC_SIZE);7374pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE,75mantis->risc_cpu, mantis->risc_dma);7677mantis->risc_cpu = NULL;78}7980return 0;81}82EXPORT_SYMBOL_GPL(mantis_dma_exit);8384static inline int mantis_alloc_buffers(struct mantis_pci *mantis)85{86if (!mantis->buf_cpu) {87mantis->buf_cpu = pci_alloc_consistent(mantis->pdev,88MANTIS_BUF_SIZE,89&mantis->buf_dma);90if (!mantis->buf_cpu) {91dprintk(MANTIS_ERROR, 1,92"DMA buffer allocation failed");9394goto err;95}96dprintk(MANTIS_ERROR, 1,97"DMA=0x%lx cpu=0x%p size=%d",98(unsigned long) mantis->buf_dma,99mantis->buf_cpu, MANTIS_BUF_SIZE);100}101if (!mantis->risc_cpu) {102mantis->risc_cpu = pci_alloc_consistent(mantis->pdev,103MANTIS_RISC_SIZE,104&mantis->risc_dma);105106if (!mantis->risc_cpu) {107dprintk(MANTIS_ERROR, 1,108"RISC program allocation failed");109110mantis_dma_exit(mantis);111112goto err;113}114dprintk(MANTIS_ERROR, 1,115"RISC=0x%lx cpu=0x%p size=%lx",116(unsigned long) mantis->risc_dma,117mantis->risc_cpu, MANTIS_RISC_SIZE);118}119120return 0;121err:122dprintk(MANTIS_ERROR, 1, "Out of memory (?) .....");123return -ENOMEM;124}125126static inline int mantis_calc_lines(struct mantis_pci *mantis)127{128mantis->line_bytes = MANTIS_BLOCK_BYTES;129mantis->line_count = MANTIS_BLOCK_COUNT;130131while (mantis->line_bytes > 4095) {132mantis->line_bytes >>= 1;133mantis->line_count <<= 1;134}135136dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]",137MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count);138139if (mantis->line_count > 255) {140dprintk(MANTIS_ERROR, 1, "Buffer size error");141return -EINVAL;142}143144return 0;145}146147int mantis_dma_init(struct mantis_pci *mantis)148{149int err = 0;150151dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");152if (mantis_alloc_buffers(mantis) < 0) {153dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");154155/* Stop RISC Engine */156mmwrite(0, MANTIS_DMA_CTL);157158goto err;159}160err = mantis_calc_lines(mantis);161if (err < 0) {162dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");163164goto err;165}166167return 0;168err:169return err;170}171EXPORT_SYMBOL_GPL(mantis_dma_init);172173static inline void mantis_risc_program(struct mantis_pci *mantis)174{175u32 buf_pos = 0;176u32 line;177178dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");179RISC_FLUSH();180181dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",182mantis->line_count, mantis->line_bytes);183184for (line = 0; line < mantis->line_count; line++) {185dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);186if (!(buf_pos % MANTIS_BLOCK_BYTES)) {187RISC_INSTR(RISC_WRITE |188RISC_IRQ |189RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) +190(MANTIS_BLOCK_COUNT - 1)) %191MANTIS_BLOCK_COUNT) |192mantis->line_bytes);193} else {194RISC_INSTR(RISC_WRITE | mantis->line_bytes);195}196RISC_INSTR(mantis->buf_dma + buf_pos);197buf_pos += mantis->line_bytes;198}199RISC_INSTR(RISC_JUMP);200RISC_INSTR(mantis->risc_dma);201}202203void mantis_dma_start(struct mantis_pci *mantis)204{205dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine");206207mantis_risc_program(mantis);208mmwrite(mantis->risc_dma, MANTIS_RISC_START);209mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);210211mmwrite(0, MANTIS_DMA_CTL);212mantis->last_block = mantis->finished_block = 0;213214mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);215216mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN217| MANTIS_RISC_EN, MANTIS_DMA_CTL);218219}220221void mantis_dma_stop(struct mantis_pci *mantis)222{223u32 stat = 0, mask = 0;224225stat = mmread(MANTIS_INT_STAT);226mask = mmread(MANTIS_INT_MASK);227dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine");228229mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR);230231mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN |232MANTIS_DCAP_EN |233MANTIS_RISC_EN)), MANTIS_DMA_CTL);234235mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT);236237mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI |238MANTIS_INT_RISCEN), MANTIS_INT_MASK);239}240241242void mantis_dma_xfer(unsigned long data)243{244struct mantis_pci *mantis = (struct mantis_pci *) data;245struct mantis_hwconfig *config = mantis->hwconfig;246247while (mantis->last_block != mantis->finished_block) {248dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",249mantis->last_block, mantis->finished_block);250251(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)252(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);253mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT;254}255}256257258