tbsecp3-dma.c
· 6.6 KiB · C
Sin formato
/*
TBS ECP3 FPGA based cards PCIe driver
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tbsecp3.h"
static unsigned int dma_pkts[8] = {128, 128, 128, 128, 128, 128, 128, 128};
module_param_array(dma_pkts, int, NULL, 0444); /* No /sys/module write access */
MODULE_PARM_DESC(dma_pkts, "DMA buffer size in TS packets (16-256), default 128");
#define TS_PACKET_SIZE 188
static void tbsecp3_dma_tasklet(unsigned long adap)
{
struct tbsecp3_adapter *adapter = (struct tbsecp3_adapter *) adap;
struct tbsecp3_dev *dev = adapter->dev;
u32 read_buffer, next_buffer;
u8* data;
u8* dataraw;
int i;
spin_lock(&adapter->adap_lock);
if (adapter->dma.cnt < TBSECP3_DMA_PRE_BUFFERS)
{
next_buffer = (tbs_read(adapter->dma.base, TBSECP3_DMA_STAT) - TBSECP3_DMA_PRE_BUFFERS + 1) & (TBSECP3_DMA_BUFFERS - 1);
adapter->dma.cnt++;
}
else
{
next_buffer = (tbs_read(adapter->dma.base, TBSECP3_DMA_STAT) - TBSECP3_DMA_PRE_BUFFERS + 1) & (TBSECP3_DMA_BUFFERS - 1);
read_buffer = (u32)adapter->dma.next_buffer;
while (read_buffer != next_buffer)
{
data = adapter->dma.buf[read_buffer];
dataraw = adapter->dma.buf4raw[read_buffer];
// Let's fake our MPEG-TS Header
for (i = 0; i < adapter->dma.buffer_pkts; i++) {
dataraw[i*TS_PACKET_SIZE] = 0x47;
dataraw[i*TS_PACKET_SIZE+1] = 64 + 0x1F;
dataraw[i*TS_PACKET_SIZE+2] = 0xFE; // PID 0xFF
dataraw[i*TS_PACKET_SIZE+3] = 0x10; // AFC = 1
memcpy(&dataraw[i*TS_PACKET_SIZE+4], &data[i*(TS_PACKET_SIZE-4)], TS_PACKET_SIZE-4);
}
data = dataraw;
// if (data[adapter->dma.offset] != 0x47) {
// /* Find sync byte offset with crude force (this might fail!) */
// for (i = 0; i < TS_PACKET_SIZE; i++)
// if ((data[i] == 0x47) &&
// (data[i + TS_PACKET_SIZE] == 0x47) &&
// (data[i + 2 * TS_PACKET_SIZE] == 0x47) &&
// (data[i + 4 * TS_PACKET_SIZE] == 0x47)) {
// adapter->dma.offset = i;
// break;
// }
// }
// if (adapter->dma.offset != 0) {
// data += adapter->dma.offset;
// /* Copy remains of last packet from buffer 0 behind last one */
// if (read_buffer == (TBSECP3_DMA_BUFFERS - 1)) {
// memcpy( adapter->dma.buf[TBSECP3_DMA_BUFFERS],
// adapter->dma.buf[0], adapter->dma.offset);
// }
// }
dvb_dmx_swfilter_packets(&adapter->demux, data, adapter->dma.buffer_pkts);
read_buffer = (read_buffer + 1) & (TBSECP3_DMA_BUFFERS - 1);
}
}
adapter->dma.next_buffer = (u8)next_buffer;
spin_unlock(&adapter->adap_lock);
}
void tbsecp3_dma_enable(struct tbsecp3_adapter *adap)
{
struct tbsecp3_dev *dev = adap->dev;
spin_lock_irq(&adap->adap_lock);
adap->dma.offset = 0;
adap->dma.cnt = 0;
adap->dma.next_buffer= 0;
tbs_read(adap->dma.base, TBSECP3_DMA_STAT);
tbs_write(TBSECP3_INT_BASE, TBSECP3_DMA_IE(adap->cfg->ts_in), 1);
tbs_write(adap->dma.base, TBSECP3_DMA_EN, 1);
spin_unlock_irq(&adap->adap_lock);
}
void tbsecp3_dma_disable(struct tbsecp3_adapter *adap)
{
struct tbsecp3_dev *dev = adap->dev;
spin_lock_irq(&adap->adap_lock);
tbs_read(adap->dma.base, TBSECP3_DMA_STAT);
tbs_write(TBSECP3_INT_BASE, TBSECP3_DMA_IE(adap->cfg->ts_in), 0);
tbs_write(adap->dma.base, TBSECP3_DMA_EN, 0);
spin_unlock_irq(&adap->adap_lock);
}
void tbsecp3_dma_reg_init(struct tbsecp3_dev *dev)
{
int i;
struct tbsecp3_adapter *adapter = dev->adapter;
for (i = 0; i < dev->info->adapters; i++) {
tbs_write(adapter->dma.base, TBSECP3_DMA_EN, 0);
tbs_write(adapter->dma.base, TBSECP3_DMA_ADDRH, 0);
tbs_write(adapter->dma.base, TBSECP3_DMA_ADDRL, (u32) adapter->dma.dma_addr);
tbs_write(adapter->dma.base, TBSECP3_DMA_TSIZE, adapter->dma.page_size);
tbs_write(adapter->dma.base, TBSECP3_DMA_BSIZE, adapter->dma.buffer_size);
adapter++;
}
}
void tbsecp3_dma_free(struct tbsecp3_dev *dev)
{
struct tbsecp3_adapter *adapter = dev->adapter;
int i;
for (i = 0; i < dev->info->adapters; i++) {
if (adapter->dma.buf[0] != NULL) {
pci_free_consistent(dev->pci_dev,
adapter->dma.page_size + 0x100,
adapter->dma.buf[0], adapter->dma.dma_addr);
adapter->dma.buf[0] = NULL;
}
if (adapter->dma.buf4raw[0] != NULL) {
pci_free_consistent(dev->pci_dev,
adapter->dma.page_size_raw + 0x100,
adapter->dma.buf4raw[0], adapter->dma.dma_addr2);
adapter->dma.buf4raw[0] = NULL;
}
adapter++;
}
}
int tbsecp3_dma_init(struct tbsecp3_dev *dev)
{
struct tbsecp3_adapter *adapter = dev->adapter;
int i, j;
for (i = 0; i < dev->info->adapters; i++) {
if (dma_pkts[i] < 16)
dma_pkts[i] = 16;
if (dma_pkts[i] > 256)
dma_pkts[i] = 256;
adapter->dma.buffer_pkts = dma_pkts[i];
adapter->dma.buffer_size = dma_pkts[i] * (TS_PACKET_SIZE-4);
adapter->dma.page_size = adapter->dma.buffer_size * TBSECP3_DMA_BUFFERS;
adapter->dma.buffer_size_raw = dma_pkts[i] * (TS_PACKET_SIZE);
adapter->dma.page_size_raw = adapter->dma.buffer_size_raw * TBSECP3_DMA_BUFFERS;
adapter->dma.buf[0] = pci_alloc_consistent(dev->pci_dev,
adapter->dma.page_size + 0x100,
&adapter->dma.dma_addr);
if (!adapter->dma.buf[0])
goto err;
adapter->dma.buf4raw[0] = pci_alloc_consistent(dev->pci_dev,
adapter->dma.page_size_raw + 0x100,
&adapter->dma.dma_addr2);
if (!adapter->dma.buf4raw[0])
goto err;
dev_dbg(&dev->pci_dev->dev,
"TS in %d: DMA page %d bytes, %d bytes (%d TS packets) per %d buffers\n", adapter->cfg->ts_in,
adapter->dma.page_size, adapter->dma.buffer_size, adapter->dma.buffer_pkts, TBSECP3_DMA_BUFFERS);
adapter->dma.base = TBSECP3_DMA_BASE(adapter->cfg->ts_in);
adapter->dma.cnt = 0;
adapter->dma.next_buffer = 0;
for (j = 1; j < TBSECP3_DMA_BUFFERS + 1; j++) {
adapter->dma.buf[j] = adapter->dma.buf[j-1] + adapter->dma.buffer_size;
adapter->dma.buf4raw[j] = adapter->dma.buf4raw[j-1] + adapter->dma.buffer_size_raw;
}
tasklet_init(&adapter->tasklet, tbsecp3_dma_tasklet, (unsigned long) adapter);
spin_lock_init(&adapter->adap_lock);
adapter++;
}
tbsecp3_dma_reg_init(dev);
return 0;
err:
dev_err(&dev->pci_dev->dev, "dma: memory alloc failed\n");
tbsecp3_dma_free(dev);
return -ENOMEM;
}
| 1 | /* |
| 2 | TBS ECP3 FPGA based cards PCIe driver |
| 3 | |
| 4 | This program is free software: you can redistribute it and/or modify |
| 5 | it under the terms of the GNU General Public License as published by |
| 6 | the Free Software Foundation, either version 3 of the License, or |
| 7 | (at your option) any later version. |
| 8 | |
| 9 | This program is distributed in the hope that it will be useful, |
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | GNU General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU General Public License |
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ |
| 17 | |
| 18 | #include "tbsecp3.h" |
| 19 | |
| 20 | static unsigned int dma_pkts[8] = {128, 128, 128, 128, 128, 128, 128, 128}; |
| 21 | module_param_array(dma_pkts, int, NULL, 0444); /* No /sys/module write access */ |
| 22 | MODULE_PARM_DESC(dma_pkts, "DMA buffer size in TS packets (16-256), default 128"); |
| 23 | |
| 24 | #define TS_PACKET_SIZE 188 |
| 25 | |
| 26 | static void tbsecp3_dma_tasklet(unsigned long adap) |
| 27 | { |
| 28 | struct tbsecp3_adapter *adapter = (struct tbsecp3_adapter *) adap; |
| 29 | struct tbsecp3_dev *dev = adapter->dev; |
| 30 | u32 read_buffer, next_buffer; |
| 31 | u8* data; |
| 32 | u8* dataraw; |
| 33 | int i; |
| 34 | |
| 35 | spin_lock(&adapter->adap_lock); |
| 36 | |
| 37 | if (adapter->dma.cnt < TBSECP3_DMA_PRE_BUFFERS) |
| 38 | { |
| 39 | next_buffer = (tbs_read(adapter->dma.base, TBSECP3_DMA_STAT) - TBSECP3_DMA_PRE_BUFFERS + 1) & (TBSECP3_DMA_BUFFERS - 1); |
| 40 | adapter->dma.cnt++; |
| 41 | } |
| 42 | else |
| 43 | { |
| 44 | next_buffer = (tbs_read(adapter->dma.base, TBSECP3_DMA_STAT) - TBSECP3_DMA_PRE_BUFFERS + 1) & (TBSECP3_DMA_BUFFERS - 1); |
| 45 | read_buffer = (u32)adapter->dma.next_buffer; |
| 46 | |
| 47 | while (read_buffer != next_buffer) |
| 48 | { |
| 49 | data = adapter->dma.buf[read_buffer]; |
| 50 | dataraw = adapter->dma.buf4raw[read_buffer]; |
| 51 | // Let's fake our MPEG-TS Header |
| 52 | for (i = 0; i < adapter->dma.buffer_pkts; i++) { |
| 53 | dataraw[i*TS_PACKET_SIZE] = 0x47; |
| 54 | dataraw[i*TS_PACKET_SIZE+1] = 64 + 0x1F; |
| 55 | dataraw[i*TS_PACKET_SIZE+2] = 0xFE; // PID 0xFF |
| 56 | dataraw[i*TS_PACKET_SIZE+3] = 0x10; // AFC = 1 |
| 57 | memcpy(&dataraw[i*TS_PACKET_SIZE+4], &data[i*(TS_PACKET_SIZE-4)], TS_PACKET_SIZE-4); |
| 58 | } |
| 59 | |
| 60 | data = dataraw; |
| 61 | |
| 62 | // if (data[adapter->dma.offset] != 0x47) { |
| 63 | // /* Find sync byte offset with crude force (this might fail!) */ |
| 64 | // for (i = 0; i < TS_PACKET_SIZE; i++) |
| 65 | // if ((data[i] == 0x47) && |
| 66 | // (data[i + TS_PACKET_SIZE] == 0x47) && |
| 67 | // (data[i + 2 * TS_PACKET_SIZE] == 0x47) && |
| 68 | // (data[i + 4 * TS_PACKET_SIZE] == 0x47)) { |
| 69 | // adapter->dma.offset = i; |
| 70 | // break; |
| 71 | // } |
| 72 | // } |
| 73 | |
| 74 | // if (adapter->dma.offset != 0) { |
| 75 | // data += adapter->dma.offset; |
| 76 | // /* Copy remains of last packet from buffer 0 behind last one */ |
| 77 | // if (read_buffer == (TBSECP3_DMA_BUFFERS - 1)) { |
| 78 | // memcpy( adapter->dma.buf[TBSECP3_DMA_BUFFERS], |
| 79 | // adapter->dma.buf[0], adapter->dma.offset); |
| 80 | // } |
| 81 | // } |
| 82 | dvb_dmx_swfilter_packets(&adapter->demux, data, adapter->dma.buffer_pkts); |
| 83 | read_buffer = (read_buffer + 1) & (TBSECP3_DMA_BUFFERS - 1); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | adapter->dma.next_buffer = (u8)next_buffer; |
| 88 | |
| 89 | spin_unlock(&adapter->adap_lock); |
| 90 | |
| 91 | } |
| 92 | |
| 93 | void tbsecp3_dma_enable(struct tbsecp3_adapter *adap) |
| 94 | { |
| 95 | struct tbsecp3_dev *dev = adap->dev; |
| 96 | |
| 97 | spin_lock_irq(&adap->adap_lock); |
| 98 | adap->dma.offset = 0; |
| 99 | adap->dma.cnt = 0; |
| 100 | adap->dma.next_buffer= 0; |
| 101 | tbs_read(adap->dma.base, TBSECP3_DMA_STAT); |
| 102 | tbs_write(TBSECP3_INT_BASE, TBSECP3_DMA_IE(adap->cfg->ts_in), 1); |
| 103 | tbs_write(adap->dma.base, TBSECP3_DMA_EN, 1); |
| 104 | spin_unlock_irq(&adap->adap_lock); |
| 105 | } |
| 106 | |
| 107 | void tbsecp3_dma_disable(struct tbsecp3_adapter *adap) |
| 108 | { |
| 109 | struct tbsecp3_dev *dev = adap->dev; |
| 110 | |
| 111 | spin_lock_irq(&adap->adap_lock); |
| 112 | tbs_read(adap->dma.base, TBSECP3_DMA_STAT); |
| 113 | tbs_write(TBSECP3_INT_BASE, TBSECP3_DMA_IE(adap->cfg->ts_in), 0); |
| 114 | tbs_write(adap->dma.base, TBSECP3_DMA_EN, 0); |
| 115 | spin_unlock_irq(&adap->adap_lock); |
| 116 | } |
| 117 | |
| 118 | void tbsecp3_dma_reg_init(struct tbsecp3_dev *dev) |
| 119 | { |
| 120 | int i; |
| 121 | struct tbsecp3_adapter *adapter = dev->adapter; |
| 122 | |
| 123 | for (i = 0; i < dev->info->adapters; i++) { |
| 124 | tbs_write(adapter->dma.base, TBSECP3_DMA_EN, 0); |
| 125 | tbs_write(adapter->dma.base, TBSECP3_DMA_ADDRH, 0); |
| 126 | tbs_write(adapter->dma.base, TBSECP3_DMA_ADDRL, (u32) adapter->dma.dma_addr); |
| 127 | tbs_write(adapter->dma.base, TBSECP3_DMA_TSIZE, adapter->dma.page_size); |
| 128 | tbs_write(adapter->dma.base, TBSECP3_DMA_BSIZE, adapter->dma.buffer_size); |
| 129 | adapter++; |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | void tbsecp3_dma_free(struct tbsecp3_dev *dev) |
| 134 | { |
| 135 | struct tbsecp3_adapter *adapter = dev->adapter; |
| 136 | int i; |
| 137 | for (i = 0; i < dev->info->adapters; i++) { |
| 138 | if (adapter->dma.buf[0] != NULL) { |
| 139 | pci_free_consistent(dev->pci_dev, |
| 140 | adapter->dma.page_size + 0x100, |
| 141 | adapter->dma.buf[0], adapter->dma.dma_addr); |
| 142 | adapter->dma.buf[0] = NULL; |
| 143 | } |
| 144 | |
| 145 | if (adapter->dma.buf4raw[0] != NULL) { |
| 146 | pci_free_consistent(dev->pci_dev, |
| 147 | adapter->dma.page_size_raw + 0x100, |
| 148 | adapter->dma.buf4raw[0], adapter->dma.dma_addr2); |
| 149 | adapter->dma.buf4raw[0] = NULL; |
| 150 | } |
| 151 | adapter++; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | int tbsecp3_dma_init(struct tbsecp3_dev *dev) |
| 156 | { |
| 157 | struct tbsecp3_adapter *adapter = dev->adapter; |
| 158 | int i, j; |
| 159 | |
| 160 | for (i = 0; i < dev->info->adapters; i++) { |
| 161 | if (dma_pkts[i] < 16) |
| 162 | dma_pkts[i] = 16; |
| 163 | if (dma_pkts[i] > 256) |
| 164 | dma_pkts[i] = 256; |
| 165 | |
| 166 | adapter->dma.buffer_pkts = dma_pkts[i]; |
| 167 | adapter->dma.buffer_size = dma_pkts[i] * (TS_PACKET_SIZE-4); |
| 168 | adapter->dma.page_size = adapter->dma.buffer_size * TBSECP3_DMA_BUFFERS; |
| 169 | |
| 170 | adapter->dma.buffer_size_raw = dma_pkts[i] * (TS_PACKET_SIZE); |
| 171 | adapter->dma.page_size_raw = adapter->dma.buffer_size_raw * TBSECP3_DMA_BUFFERS; |
| 172 | |
| 173 | adapter->dma.buf[0] = pci_alloc_consistent(dev->pci_dev, |
| 174 | adapter->dma.page_size + 0x100, |
| 175 | &adapter->dma.dma_addr); |
| 176 | if (!adapter->dma.buf[0]) |
| 177 | goto err; |
| 178 | |
| 179 | adapter->dma.buf4raw[0] = pci_alloc_consistent(dev->pci_dev, |
| 180 | adapter->dma.page_size_raw + 0x100, |
| 181 | &adapter->dma.dma_addr2); |
| 182 | |
| 183 | if (!adapter->dma.buf4raw[0]) |
| 184 | goto err; |
| 185 | |
| 186 | dev_dbg(&dev->pci_dev->dev, |
| 187 | "TS in %d: DMA page %d bytes, %d bytes (%d TS packets) per %d buffers\n", adapter->cfg->ts_in, |
| 188 | adapter->dma.page_size, adapter->dma.buffer_size, adapter->dma.buffer_pkts, TBSECP3_DMA_BUFFERS); |
| 189 | |
| 190 | adapter->dma.base = TBSECP3_DMA_BASE(adapter->cfg->ts_in); |
| 191 | adapter->dma.cnt = 0; |
| 192 | adapter->dma.next_buffer = 0; |
| 193 | for (j = 1; j < TBSECP3_DMA_BUFFERS + 1; j++) { |
| 194 | adapter->dma.buf[j] = adapter->dma.buf[j-1] + adapter->dma.buffer_size; |
| 195 | adapter->dma.buf4raw[j] = adapter->dma.buf4raw[j-1] + adapter->dma.buffer_size_raw; |
| 196 | } |
| 197 | |
| 198 | tasklet_init(&adapter->tasklet, tbsecp3_dma_tasklet, (unsigned long) adapter); |
| 199 | spin_lock_init(&adapter->adap_lock); |
| 200 | adapter++; |
| 201 | } |
| 202 | tbsecp3_dma_reg_init(dev); |
| 203 | return 0; |
| 204 | err: |
| 205 | dev_err(&dev->pci_dev->dev, "dma: memory alloc failed\n"); |
| 206 | tbsecp3_dma_free(dev); |
| 207 | return -ENOMEM; |
| 208 | } |
| 209 |
tbsecp3.h
· 5.7 KiB · C
Sin formato
/*
TBS ECP3 FPGA based cards PCIe driver
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TBSECP3_H_
#define _TBSECP3_H_
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <media/dmxdev.h>
#include <media/dvbdev.h>
#include <media/dvb_demux.h>
#include <media/dvb_frontend.h>
#include <media/dvb_ringbuffer.h>
#include <media/dvb_ca_en50221.h>
#include <media/dvb_net.h>
#include "tbsecp3-regs.h"
#define TBSECP3_VID 0x544d
#define TBSECP3_PID 0x6178
#define TBSECP3_BOARD_TBS6205 0
#define TBSECP3_BOARD_TBS6281SE 1
#define TBSECP3_BOARD_TBS6290SE 2
#define TBSECP3_BOARD_TBS6209 3
#define TBSECP3_BOARD_TBS6522 4
#define TBSECP3_BOARD_TBS6528 5
#define TBSECP3_BOARD_TBS6590 6
#define TBSECP3_BOARD_TBS6902 7
#define TBSECP3_BOARD_TBS6903 8
#define TBSECP3_BOARD_TBS6904 9
#define TBSECP3_BOARD_TBS6905 10
#define TBSECP3_BOARD_TBS6908 11
#define TBSECP3_BOARD_TBS6909 12
#define TBSECP3_BOARD_TBS6910 13
#define TBSECP3_BOARD_TBS6704 14
#define TBSECP3_BOARD_TBS6814 15
#define TBSECP3_BOARD_TBS6514 16
#define TBSECP3_BOARD_TBS690a 17
#define TBSECP3_BOARD_TBS6301 18
#define TBSECP3_BOARD_TBS6304 19
#define TBSECP3_BOARD_TBS6308 20
#define TBSECP3_BOARD_TBS6903X 21
#define TBSECP3_BOARD_TBS6909X 22
#define TBSECP3_BOARD_TBS6904X 23
#define TBSECP3_MAX_ADAPTERS (8)
#define TBSECP3_MAX_I2C_BUS (4)
#define TBSECP3_GPIODEF_NONE (0)
#define TBSECP3_GPIODEF_HIGH (1)
#define TBSECP3_GPIODEF_LOW (2)
#define TBSECP3_DMA_BUFFERS 16
#define TBSECP3_DMA_PRE_BUFFERS 2
struct tbsecp3_dev;
struct tbsecp3_gpio_pin {
u8 lvl;
u8 nr;
};
struct tbsecp3_gpio_config {
struct tbsecp3_gpio_pin lnb_power;
struct tbsecp3_gpio_pin lnb_voltage;
struct tbsecp3_gpio_pin demod_reset;
};
struct tbsecp3_adap_config {
u32 ts_in;
u8 i2c_bus_nr;
struct tbsecp3_gpio_config gpio;
};
struct tbsecp3_board {
u16 board_id;
char *name;
int adapters;
u32 i2c_speed;
u8 eeprom_i2c;
u8 eeprom_addr;
struct tbsecp3_adap_config adap_config[8];
};
struct tbsecp3_i2c {
struct tbsecp3_dev *dev;
u32 base;
struct i2c_adapter i2c_adap;
struct i2c_client i2c_client;
struct mutex lock;
wait_queue_head_t wq;
bool done;
};
struct tbsecp3_dma_channel {
u32 base;
dma_addr_t dma_addr;
dma_addr_t dma_addr2;
u32 page_size;
u32 buffer_size;
u32 buffer_pkts;
u32 page_size_raw;
u32 buffer_size_raw;
u8 *buf[TBSECP3_DMA_BUFFERS + 1];
u8 *buf4raw[TBSECP3_DMA_BUFFERS + 1];
u8 offset;
u8 cnt;
u8 next_buffer;
};
struct tbsecp3_ca {
int nr;
u32 base;
struct dvb_ca_en50221 ca;
struct tbsecp3_adapter *adapter;
struct mutex lock;
int status;
};
struct tbsecp3_adapter {
int nr;
struct tbsecp3_adap_config *cfg;
/* parent device */
struct tbsecp3_dev *dev;
/* i2c */
struct tbsecp3_i2c *i2c;
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
/* dvb */
struct dvb_adapter dvb_adapter;
struct dvb_frontend *fe;
struct dvb_frontend *fe2;
struct dvb_frontend _fe2;
struct dvb_demux demux;
struct dmxdev dmxdev;
struct dvb_net dvbnet;
struct dmx_frontend fe_hw;
struct dmx_frontend fe_mem;
int feeds;
/* dma */
spinlock_t adap_lock;
struct tasklet_struct tasklet;
struct tbsecp3_dma_channel dma;
/* ca interface */
struct tbsecp3_ca *tbsca;
};
struct tbsecp3_dev {
struct tbsecp3_board *info;
/* pcie */
struct pci_dev *pci_dev;
void __iomem *lmmio;
bool msi;
/* dvb adapters */
struct tbsecp3_adapter adapter[TBSECP3_MAX_ADAPTERS];
/* i2c */
struct tbsecp3_i2c i2c_bus[TBSECP3_MAX_I2C_BUS];
u8 mac_num;
};
#define tbs_read(_b, _o) readl(dev->lmmio + (_b + _o))
#define tbs_write(_b, _o, _v) writel((_v), dev->lmmio + (_b + _o))
/* tbsecp3-core.c */
void tbsecp3_gpio_set_pin(struct tbsecp3_dev *dev,
struct tbsecp3_gpio_pin *pin, int state);
/* tbspcie-i2c.c */
extern int tbsecp3_i2c_init(struct tbsecp3_dev *dev);
extern void tbsecp3_i2c_exit(struct tbsecp3_dev *dev);
extern void tbsecp3_i2c_reg_init(struct tbsecp3_dev *dev);
extern void tbsecp3_i2c_remove_clients(struct tbsecp3_adapter *adapter);
/* tbspcie-cards.c */
extern struct tbsecp3_board tbsecp3_boards[];
/* tbspcie-dvb.c */
extern int tbsecp3_dvb_init(struct tbsecp3_adapter *adapter);
extern void tbsecp3_dvb_exit(struct tbsecp3_adapter *adapter);
/* tbsecp3-asi.c */
extern u8 asi_CheckFree(struct tbsecp3_dev *dev,int asi_base_addr, unsigned char OpbyteNum);
extern bool asi_chip_reset(struct tbsecp3_dev *dev,int asi_base_addr);
extern int asi_read16bit(struct tbsecp3_dev *dev,int asi_base_addr,int reg_addr);
extern bool asi_write16bit(struct tbsecp3_dev *dev,int asi_base_addr, int reg_addr, int data16bit);
/* tbsecp3-dma.c */
extern int tbsecp3_dma_init(struct tbsecp3_dev *dev);
extern void tbsecp3_dma_free(struct tbsecp3_dev *dev);
extern void tbsecp3_dma_reg_init(struct tbsecp3_dev *dev);
extern void tbsecp3_dma_enable(struct tbsecp3_adapter *adap);
extern void tbsecp3_dma_disable(struct tbsecp3_adapter *adap);
/* tbsecp3-ca.c */
int tbsecp3_ca_init(struct tbsecp3_adapter *adap, int nr);
void tbsecp3_ca_release(struct tbsecp3_adapter *adap);
#endif
| 1 | /* |
| 2 | TBS ECP3 FPGA based cards PCIe driver |
| 3 | |
| 4 | This program is free software: you can redistribute it and/or modify |
| 5 | it under the terms of the GNU General Public License as published by |
| 6 | the Free Software Foundation, either version 3 of the License, or |
| 7 | (at your option) any later version. |
| 8 | |
| 9 | This program is distributed in the hope that it will be useful, |
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | GNU General Public License for more details. |
| 13 | |
| 14 | You should have received a copy of the GNU General Public License |
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ |
| 17 | |
| 18 | #ifndef _TBSECP3_H_ |
| 19 | #define _TBSECP3_H_ |
| 20 | |
| 21 | #include <linux/i2c.h> |
| 22 | #include <linux/init.h> |
| 23 | #include <linux/interrupt.h> |
| 24 | #include <linux/kernel.h> |
| 25 | #include <linux/module.h> |
| 26 | #include <linux/proc_fs.h> |
| 27 | #include <linux/pci.h> |
| 28 | #include <linux/dma-mapping.h> |
| 29 | #include <linux/slab.h> |
| 30 | |
| 31 | #include <media/dmxdev.h> |
| 32 | #include <media/dvbdev.h> |
| 33 | #include <media/dvb_demux.h> |
| 34 | #include <media/dvb_frontend.h> |
| 35 | #include <media/dvb_ringbuffer.h> |
| 36 | #include <media/dvb_ca_en50221.h> |
| 37 | #include <media/dvb_net.h> |
| 38 | |
| 39 | #include "tbsecp3-regs.h" |
| 40 | |
| 41 | #define TBSECP3_VID 0x544d |
| 42 | #define TBSECP3_PID 0x6178 |
| 43 | |
| 44 | #define TBSECP3_BOARD_TBS6205 0 |
| 45 | #define TBSECP3_BOARD_TBS6281SE 1 |
| 46 | #define TBSECP3_BOARD_TBS6290SE 2 |
| 47 | #define TBSECP3_BOARD_TBS6209 3 |
| 48 | #define TBSECP3_BOARD_TBS6522 4 |
| 49 | #define TBSECP3_BOARD_TBS6528 5 |
| 50 | #define TBSECP3_BOARD_TBS6590 6 |
| 51 | #define TBSECP3_BOARD_TBS6902 7 |
| 52 | #define TBSECP3_BOARD_TBS6903 8 |
| 53 | #define TBSECP3_BOARD_TBS6904 9 |
| 54 | #define TBSECP3_BOARD_TBS6905 10 |
| 55 | #define TBSECP3_BOARD_TBS6908 11 |
| 56 | #define TBSECP3_BOARD_TBS6909 12 |
| 57 | #define TBSECP3_BOARD_TBS6910 13 |
| 58 | #define TBSECP3_BOARD_TBS6704 14 |
| 59 | #define TBSECP3_BOARD_TBS6814 15 |
| 60 | #define TBSECP3_BOARD_TBS6514 16 |
| 61 | #define TBSECP3_BOARD_TBS690a 17 |
| 62 | #define TBSECP3_BOARD_TBS6301 18 |
| 63 | #define TBSECP3_BOARD_TBS6304 19 |
| 64 | #define TBSECP3_BOARD_TBS6308 20 |
| 65 | #define TBSECP3_BOARD_TBS6903X 21 |
| 66 | #define TBSECP3_BOARD_TBS6909X 22 |
| 67 | #define TBSECP3_BOARD_TBS6904X 23 |
| 68 | |
| 69 | #define TBSECP3_MAX_ADAPTERS (8) |
| 70 | #define TBSECP3_MAX_I2C_BUS (4) |
| 71 | |
| 72 | #define TBSECP3_GPIODEF_NONE (0) |
| 73 | #define TBSECP3_GPIODEF_HIGH (1) |
| 74 | #define TBSECP3_GPIODEF_LOW (2) |
| 75 | |
| 76 | #define TBSECP3_DMA_BUFFERS 16 |
| 77 | #define TBSECP3_DMA_PRE_BUFFERS 2 |
| 78 | |
| 79 | |
| 80 | struct tbsecp3_dev; |
| 81 | |
| 82 | |
| 83 | struct tbsecp3_gpio_pin { |
| 84 | u8 lvl; |
| 85 | u8 nr; |
| 86 | }; |
| 87 | |
| 88 | struct tbsecp3_gpio_config { |
| 89 | struct tbsecp3_gpio_pin lnb_power; |
| 90 | struct tbsecp3_gpio_pin lnb_voltage; |
| 91 | struct tbsecp3_gpio_pin demod_reset; |
| 92 | }; |
| 93 | |
| 94 | struct tbsecp3_adap_config { |
| 95 | u32 ts_in; |
| 96 | u8 i2c_bus_nr; |
| 97 | struct tbsecp3_gpio_config gpio; |
| 98 | }; |
| 99 | |
| 100 | struct tbsecp3_board { |
| 101 | u16 board_id; |
| 102 | char *name; |
| 103 | int adapters; |
| 104 | u32 i2c_speed; |
| 105 | u8 eeprom_i2c; |
| 106 | u8 eeprom_addr; |
| 107 | struct tbsecp3_adap_config adap_config[8]; |
| 108 | }; |
| 109 | |
| 110 | struct tbsecp3_i2c { |
| 111 | struct tbsecp3_dev *dev; |
| 112 | u32 base; |
| 113 | |
| 114 | struct i2c_adapter i2c_adap; |
| 115 | struct i2c_client i2c_client; |
| 116 | |
| 117 | struct mutex lock; |
| 118 | wait_queue_head_t wq; |
| 119 | bool done; |
| 120 | }; |
| 121 | |
| 122 | struct tbsecp3_dma_channel { |
| 123 | u32 base; |
| 124 | dma_addr_t dma_addr; |
| 125 | dma_addr_t dma_addr2; |
| 126 | u32 page_size; |
| 127 | u32 buffer_size; |
| 128 | u32 buffer_pkts; |
| 129 | u32 page_size_raw; |
| 130 | u32 buffer_size_raw; |
| 131 | u8 *buf[TBSECP3_DMA_BUFFERS + 1]; |
| 132 | u8 *buf4raw[TBSECP3_DMA_BUFFERS + 1]; |
| 133 | u8 offset; |
| 134 | u8 cnt; |
| 135 | u8 next_buffer; |
| 136 | }; |
| 137 | |
| 138 | struct tbsecp3_ca { |
| 139 | int nr; |
| 140 | u32 base; |
| 141 | struct dvb_ca_en50221 ca; |
| 142 | |
| 143 | struct tbsecp3_adapter *adapter; |
| 144 | struct mutex lock; |
| 145 | int status; |
| 146 | }; |
| 147 | |
| 148 | struct tbsecp3_adapter { |
| 149 | int nr; |
| 150 | struct tbsecp3_adap_config *cfg; |
| 151 | |
| 152 | /* parent device */ |
| 153 | struct tbsecp3_dev *dev; |
| 154 | |
| 155 | /* i2c */ |
| 156 | struct tbsecp3_i2c *i2c; |
| 157 | struct i2c_client *i2c_client_demod; |
| 158 | struct i2c_client *i2c_client_tuner; |
| 159 | |
| 160 | /* dvb */ |
| 161 | struct dvb_adapter dvb_adapter; |
| 162 | struct dvb_frontend *fe; |
| 163 | struct dvb_frontend *fe2; |
| 164 | struct dvb_frontend _fe2; |
| 165 | struct dvb_demux demux; |
| 166 | struct dmxdev dmxdev; |
| 167 | struct dvb_net dvbnet; |
| 168 | struct dmx_frontend fe_hw; |
| 169 | struct dmx_frontend fe_mem; |
| 170 | int feeds; |
| 171 | |
| 172 | /* dma */ |
| 173 | spinlock_t adap_lock; |
| 174 | struct tasklet_struct tasklet; |
| 175 | struct tbsecp3_dma_channel dma; |
| 176 | |
| 177 | /* ca interface */ |
| 178 | struct tbsecp3_ca *tbsca; |
| 179 | }; |
| 180 | |
| 181 | struct tbsecp3_dev { |
| 182 | struct tbsecp3_board *info; |
| 183 | |
| 184 | /* pcie */ |
| 185 | struct pci_dev *pci_dev; |
| 186 | void __iomem *lmmio; |
| 187 | bool msi; |
| 188 | |
| 189 | /* dvb adapters */ |
| 190 | struct tbsecp3_adapter adapter[TBSECP3_MAX_ADAPTERS]; |
| 191 | |
| 192 | /* i2c */ |
| 193 | struct tbsecp3_i2c i2c_bus[TBSECP3_MAX_I2C_BUS]; |
| 194 | |
| 195 | u8 mac_num; |
| 196 | }; |
| 197 | |
| 198 | #define tbs_read(_b, _o) readl(dev->lmmio + (_b + _o)) |
| 199 | #define tbs_write(_b, _o, _v) writel((_v), dev->lmmio + (_b + _o)) |
| 200 | |
| 201 | |
| 202 | /* tbsecp3-core.c */ |
| 203 | void tbsecp3_gpio_set_pin(struct tbsecp3_dev *dev, |
| 204 | struct tbsecp3_gpio_pin *pin, int state); |
| 205 | |
| 206 | /* tbspcie-i2c.c */ |
| 207 | extern int tbsecp3_i2c_init(struct tbsecp3_dev *dev); |
| 208 | extern void tbsecp3_i2c_exit(struct tbsecp3_dev *dev); |
| 209 | extern void tbsecp3_i2c_reg_init(struct tbsecp3_dev *dev); |
| 210 | extern void tbsecp3_i2c_remove_clients(struct tbsecp3_adapter *adapter); |
| 211 | |
| 212 | /* tbspcie-cards.c */ |
| 213 | extern struct tbsecp3_board tbsecp3_boards[]; |
| 214 | |
| 215 | /* tbspcie-dvb.c */ |
| 216 | extern int tbsecp3_dvb_init(struct tbsecp3_adapter *adapter); |
| 217 | extern void tbsecp3_dvb_exit(struct tbsecp3_adapter *adapter); |
| 218 | |
| 219 | /* tbsecp3-asi.c */ |
| 220 | extern u8 asi_CheckFree(struct tbsecp3_dev *dev,int asi_base_addr, unsigned char OpbyteNum); |
| 221 | extern bool asi_chip_reset(struct tbsecp3_dev *dev,int asi_base_addr); |
| 222 | extern int asi_read16bit(struct tbsecp3_dev *dev,int asi_base_addr,int reg_addr); |
| 223 | extern bool asi_write16bit(struct tbsecp3_dev *dev,int asi_base_addr, int reg_addr, int data16bit); |
| 224 | |
| 225 | /* tbsecp3-dma.c */ |
| 226 | extern int tbsecp3_dma_init(struct tbsecp3_dev *dev); |
| 227 | extern void tbsecp3_dma_free(struct tbsecp3_dev *dev); |
| 228 | extern void tbsecp3_dma_reg_init(struct tbsecp3_dev *dev); |
| 229 | extern void tbsecp3_dma_enable(struct tbsecp3_adapter *adap); |
| 230 | extern void tbsecp3_dma_disable(struct tbsecp3_adapter *adap); |
| 231 | |
| 232 | /* tbsecp3-ca.c */ |
| 233 | int tbsecp3_ca_init(struct tbsecp3_adapter *adap, int nr); |
| 234 | void tbsecp3_ca_release(struct tbsecp3_adapter *adap); |
| 235 | |
| 236 | #endif |
| 237 |