提交 2faae422 编写于 作者: L Linus Torvalds

Merge branch 'mantis' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'mantis' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (117 commits)
  V4L/DVB (13851): Fix Input dependency for Mantis
  V4L/DVB(13824a): mantis: Fix __devexit bad annotations
  V4L/DVB (13808b): mantis: replace DMA_nnBIT_MASK to DMA_BIT_MASK(32)
  V4L/DVB (13808): [Mantis/Hopper] Build update for Mantis/Hopper based cards
  V4L/DVB(13808a): mantis: convert it to the new ir-core register/unregister functions
  V4L/DVB (13812): [Mantis/Hopper] Update Copyright header
  V4L/DVB (13811): [MB86A16] Update Copyright header
  V4L/DVB (13810): [MB86A16] Use DVB_* macros
  V4L/DVB (13809): Fix Checkpatch violations
  V4L/DVB (13807): Fix: Free device in the device registration failure case
  V4L/DVB (13806): Register and Initialize Remote control
  V4L/DVB (13805): Fix: Unregister the frontend before detaching
  V4L/DVB (13804): Remove unused I2C Adapter ID
  V4L/DVB (13803): Remove unused dependency on CU1216
  V4L/DVB (13802): [Mantis/Hopper] Fix all build related warnings
  V4L/DVB (13801): [MB86A16] Use the search callback
  V4L/DVB (13800): [Mantis] I2C optimization. Required delay is much lesser than 1mS.
  V4L/DVB (13799): [Mantis] Unregister frontend
  V4L/DVB (13798): [Mantis] Enable power for all cards, use byte mode only on relevant devices
  V4L/DVB (13797): [Mantis/Hopper/TDA665x] Large overhaul,
  ...
......@@ -72,6 +72,10 @@ comment "Supported Earthsoft PT1 Adapters"
depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/pt1/Kconfig"
comment "Supported Mantis Adapters"
depends on DVB_CORE && PCI && I2C
source "drivers/media/dvb/mantis/Kconfig"
comment "Supported DVB Frontends"
depends on DVB_CORE
source "drivers/media/dvb/frontends/Kconfig"
......
......@@ -2,6 +2,18 @@
# Makefile for the kernel multimedia device drivers.
#
obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ pt1/
obj-y := dvb-core/ \
frontends/ \
ttpci/ \
ttusb-dec/ \
ttusb-budget/ \
b2c2/ \
bt8xx/ \
dvb-usb/ \
pluto2/ \
siano/ \
dm1105/ \
pt1/ \
mantis/
obj-$(CONFIG_DVB_FIREDTV) += firewire/
......@@ -208,6 +208,14 @@ config DVB_DS3000
help
A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
config DVB_MB86A16
tristate "Fujitsu MB86A16 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S/DSS Direct Conversion reveiver.
Say Y when you want to support this frontend.
comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
......@@ -587,6 +595,17 @@ config DVB_ATBM8830
help
A DMB-TH tuner module. Say Y when you want to support this frontend.
config DVB_TDA665x
tristate "TDA665x tuner"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
Support for tuner modules based on Philips TDA6650/TDA6651 chips.
Say Y when you want to support this chip.
Currently supported tuners:
* Panasonic ENV57H12D5 (ET-50DT)
comment "Tools to develop new frontends"
config DVB_DUMMY_FE
......
......@@ -64,6 +64,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o
obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
obj-$(CONFIG_DVB_TDA665x) += tda665x.o
obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o
obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o
obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
......@@ -80,3 +81,4 @@ obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
obj-$(CONFIG_DVB_ISL6423) += isl6423.o
obj-$(CONFIG_DVB_EC100) += ec100.o
obj-$(CONFIG_DVB_DS3000) += ds3000.o
obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
此差异已折叠。
/*
Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MB86A16_H
#define __MB86A16_H
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
struct mb86a16_config {
u8 demod_address;
int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
};
#if defined(CONFIG_DVB_MB86A16) || (defined(CONFIG_DVB_MB86A16_MODULE) && defined(MODULE))
extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
struct i2c_adapter *i2c_adap);
#else
static inline struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
struct i2c_adapter *i2c_adap)
{
printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_MB86A16 */
#endif /* __MB86A16_H */
/*
Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MB86A16_PRIV_H
#define __MB86A16_PRIV_H
#define MB86A16_TSOUT 0x00
#define MB86A16_TSOUT_HIZSEL (0x01 << 5)
#define MB86A16_TSOUT_HIZCNTI (0x01 << 4)
#define MB86A16_TSOUT_MODE (0x01 << 3)
#define MB86A16_TSOUT_ORDER (0x01 << 2)
#define MB86A16_TSOUT_ERROR (0x01 << 1)
#define Mb86A16_TSOUT_EDGE (0x01 << 0)
#define MB86A16_FEC 0x01
#define MB86A16_FEC_FSYNC (0x01 << 5)
#define MB86A16_FEC_PCKB8 (0x01 << 4)
#define MB86A16_FEC_DVDS (0x01 << 3)
#define MB86A16_FEC_EREN (0x01 << 2)
#define Mb86A16_FEC_RSEN (0x01 << 1)
#define MB86A16_FEC_DIEN (0x01 << 0)
#define MB86A16_AGC 0x02
#define MB86A16_AGC_AGMD (0x01 << 6)
#define MB86A16_AGC_AGCW (0x0f << 2)
#define MB86A16_AGC_AGCP (0x01 << 1)
#define MB86A16_AGC_AGCR (0x01 << 0)
#define MB86A16_SRATE1 0x03
#define MB86A16_SRATE1_DECI (0x07 << 2)
#define MB86A16_SRATE1_CSEL (0x01 << 1)
#define MB86A16_SRATE1_RSEL (0x01 << 0)
#define MB86A16_SRATE2 0x04
#define MB86A16_SRATE2_STOFSL (0xff << 0)
#define MB86A16_SRATE3 0x05
#define MB86A16_SRATE2_STOFSH (0xff << 0)
#define MB86A16_VITERBI 0x06
#define MB86A16_FRAMESYNC 0x07
#define MB86A16_CRLFILTCOEF1 0x08
#define MB86A16_CRLFILTCOEF2 0x09
#define MB86A16_STRFILTCOEF1 0x0a
#define MB86A16_STRFILTCOEF2 0x0b
#define MB86A16_RESET 0x0c
#define MB86A16_STATUS 0x0d
#define MB86A16_AFCML 0x0e
#define MB86A16_AFCMH 0x0f
#define MB86A16_BERMON 0x10
#define MB86A16_BERTAB 0x11
#define MB86A16_BERLSB 0x12
#define MB86A16_BERMID 0x13
#define MB86A16_BERMSB 0x14
#define MB86A16_AGCM 0x15
#define MB86A16_DCC1 0x16
#define MB86A16_DCC1_DISTA (0x01 << 7)
#define MB86A16_DCC1_PRTY (0x01 << 6)
#define MB86A16_DCC1_CTOE (0x01 << 5)
#define MB86A16_DCC1_TBEN (0x01 << 4)
#define MB86A16_DCC1_TBO (0x01 << 3)
#define MB86A16_DCC1_NUM (0x07 << 0)
#define MB86A16_DCC2 0x17
#define MB86A16_DCC2_DCBST (0x01 << 0)
#define MB86A16_DCC3 0x18
#define MB86A16_DCC3_CODE0 (0xff << 0)
#define MB86A16_DCC4 0x19
#define MB86A16_DCC4_CODE1 (0xff << 0)
#define MB86A16_DCC5 0x1a
#define MB86A16_DCC5_CODE2 (0xff << 0)
#define MB86A16_DCC6 0x1b
#define MB86A16_DCC6_CODE3 (0xff << 0)
#define MB86A16_DCC7 0x1c
#define MB86A16_DCC7_CODE4 (0xff << 0)
#define MB86A16_DCC8 0x1d
#define MB86A16_DCC8_CODE5 (0xff << 0)
#define MB86A16_DCCOUT 0x1e
#define MB86A16_DCCOUT_DISEN (0x01 << 0)
#define MB86A16_TONEOUT1 0x1f
#define MB86A16_TONE_TDIVL (0xff << 0)
#define MB86A16_TONEOUT2 0x20
#define MB86A16_TONE_TMD (0x03 << 2)
#define MB86A16_TONE_TDIVH (0x03 << 0)
#define MB86A16_FREQ1 0x21
#define MB86A16_FREQ2 0x22
#define MB86A16_FREQ3 0x23
#define MB86A16_FREQ4 0x24
#define MB86A16_FREQSET 0x25
#define MB86A16_CNM 0x26
#define MB86A16_PORT0 0x27
#define MB86A16_PORT1 0x28
#define MB86A16_DRCFILT 0x29
#define MB86A16_AFC 0x2a
#define MB86A16_AFCEXL 0x2b
#define MB86A16_AFCEXH 0x2c
#define MB86A16_DAGC 0x2d
#define MB86A16_SEQMODE 0x32
#define MB86A16_S0S1T 0x33
#define MB86A16_S2S3T 0x34
#define MB86A16_S4S5T 0x35
#define MB86A16_CNTMR 0x36
#define MB86A16_SIG1 0x37
#define MB86A16_SIG2 0x38
#define MB86A16_VIMAG 0x39
#define MB86A16_VISET1 0x3a
#define MB86A16_VISET2 0x3b
#define MB86A16_VISET3 0x3c
#define MB86A16_FAGCS1 0x3d
#define MB86A16_FAGCS2 0x3e
#define MB86A16_FAGCS3 0x3f
#define MB86A16_FAGCS4 0x40
#define MB86A16_FAGCS5 0x41
#define MB86A16_FAGCS6 0x42
#define MB86A16_CRM 0x43
#define MB86A16_STRM 0x44
#define MB86A16_DAGCML 0x45
#define MB86A16_DAGCMH 0x46
#define MB86A16_QPSKTST 0x49
#define MB86A16_DISTMON 0x52
#define MB86A16_VERSION 0x7f
#endif /* __MB86A16_PRIV_H */
......@@ -426,6 +426,10 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
id = tda10021_readreg(state, 0x1a);
if ((id & 0xf0) != 0x70) goto error;
/* Don't claim TDA10023 */
if (id == 0x7d)
goto error;
printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n",
state->config->demod_address, id);
......
/*
TDA665x tuner driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include "dvb_frontend.h"
#include "tda665x.h"
struct tda665x_state {
struct dvb_frontend *fe;
struct i2c_adapter *i2c;
const struct tda665x_config *config;
u32 frequency;
u32 bandwidth;
};
static int tda665x_read(struct tda665x_state *state, u8 *buf)
{
const struct tda665x_config *config = state->config;
int err = 0;
struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 };
err = i2c_transfer(state->i2c, &msg, 1);
if (err != 1)
goto exit;
return err;
exit:
printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
return err;
}
static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length)
{
const struct tda665x_config *config = state->config;
int err = 0;
struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length };
err = i2c_transfer(state->i2c, &msg, 1);
if (err != 1)
goto exit;
return err;
exit:
printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
return err;
}
static int tda665x_get_state(struct dvb_frontend *fe,
enum tuner_param param,
struct tuner_state *tstate)
{
struct tda665x_state *state = fe->tuner_priv;
int err = 0;
switch (param) {
case DVBFE_TUNER_FREQUENCY:
tstate->frequency = state->frequency;
break;
case DVBFE_TUNER_BANDWIDTH:
break;
default:
printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
err = -EINVAL;
break;
}
return err;
}
static int tda665x_get_status(struct dvb_frontend *fe, u32 *status)
{
struct tda665x_state *state = fe->tuner_priv;
u8 result = 0;
int err = 0;
*status = 0;
err = tda665x_read(state, &result);
if (err < 0)
goto exit;
if ((result >> 6) & 0x01) {
printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__);
*status = 1;
}
return err;
exit:
printk(KERN_ERR "%s: I/O Error\n", __func__);
return err;
}
static int tda665x_set_state(struct dvb_frontend *fe,
enum tuner_param param,
struct tuner_state *tstate)
{
struct tda665x_state *state = fe->tuner_priv;
const struct tda665x_config *config = state->config;
u32 frequency, status = 0;
u8 buf[4];
int err = 0;
if (param & DVBFE_TUNER_FREQUENCY) {
frequency = tstate->frequency;
if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) {
printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
return -EINVAL;
}
frequency += config->frequency_offst;
frequency *= config->ref_multiplier;
frequency += config->ref_divider >> 1;
frequency /= config->ref_divider;
buf[0] = (u8) (frequency & 0x7f00) >> 8;
buf[1] = (u8) (frequency & 0x00ff) >> 0;
buf[2] = 0x80 | 0x40 | 0x02;
buf[3] = 0x00;
/* restore frequency */
frequency = tstate->frequency;
if (frequency < 153000000) {
/* VHF-L */
buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */
if (frequency < 68000000)
buf[3] |= 0x40; /* 83uA */
if (frequency < 1040000000)
buf[3] |= 0x60; /* 122uA */
if (frequency < 1250000000)
buf[3] |= 0x80; /* 163uA */
else
buf[3] |= 0xa0; /* 254uA */
} else if (frequency < 438000000) {
/* VHF-H */
buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */
if (frequency < 230000000)
buf[3] |= 0x40;
if (frequency < 300000000)
buf[3] |= 0x60;
else
buf[3] |= 0x80;
} else {
/* UHF */
buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */
if (frequency < 470000000)
buf[3] |= 0x60;
if (frequency < 526000000)
buf[3] |= 0x80;
else
buf[3] |= 0xa0;
}
/* Set params */
err = tda665x_write(state, buf, 5);
if (err < 0)
goto exit;
/* sleep for some time */
printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__);
msleep(20);
/* check status */
err = tda665x_get_status(fe, &status);
if (err < 0)
goto exit;
if (status == 1) {
printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status);
state->frequency = frequency; /* cache successful state */
} else {
printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status);
}
} else {
printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
return -EINVAL;
}
return 0;
exit:
printk(KERN_ERR "%s: I/O Error\n", __func__);
return err;
}
static int tda665x_release(struct dvb_frontend *fe)
{
struct tda665x_state *state = fe->tuner_priv;
fe->tuner_priv = NULL;
kfree(state);
return 0;
}
static struct dvb_tuner_ops tda665x_ops = {
.set_state = tda665x_set_state,
.get_state = tda665x_get_state,
.get_status = tda665x_get_status,
.release = tda665x_release
};
struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
const struct tda665x_config *config,
struct i2c_adapter *i2c)
{
struct tda665x_state *state = NULL;
struct dvb_tuner_info *info;
state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
if (state == NULL)
goto exit;
state->config = config;
state->i2c = i2c;
state->fe = fe;
fe->tuner_priv = state;
fe->ops.tuner_ops = tda665x_ops;
info = &fe->ops.tuner_ops.info;
memcpy(info->name, config->name, sizeof(config->name));
info->frequency_min = config->frequency_min;
info->frequency_max = config->frequency_max;
info->frequency_step = config->frequency_offst;
printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
return fe;
exit:
kfree(state);
return NULL;
}
EXPORT_SYMBOL(tda665x_attach);
MODULE_DESCRIPTION("TDA665x driver");
MODULE_AUTHOR("Manu Abraham");
MODULE_LICENSE("GPL");
/*
TDA665x tuner driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __TDA665x_H
#define __TDA665x_H
struct tda665x_config {
char name[128];
u8 addr;
u32 frequency_min;
u32 frequency_max;
u32 frequency_offst;
u32 ref_multiplier;
u32 ref_divider;
};
#if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE))
extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
const struct tda665x_config *config,
struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
const struct tda665x_config *config,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_TDA665x */
#endif /* __TDA665x_H */
config MANTIS_CORE
tristate "Mantis/Hopper PCI bridge based devices"
depends on PCI && I2C && INPUT
help
Support for PCI cards based on the Mantis and Hopper PCi bridge.
Say Y if you own such a device and want to use it.
config DVB_MANTIS
tristate "MANTIS based cards"
depends on MANTIS_CORE && DVB_CORE && PCI && I2C
select DVB_MB86A16
select DVB_ZL10353
select DVB_STV0299
select DVB_PLL
help
Support for PCI cards based on the Mantis PCI bridge.
Say Y when you have a Mantis based DVB card and want to use it.
If unsure say N.
config DVB_HOPPER
tristate "HOPPER based cards"
depends on MANTIS_CORE && DVB_CORE && PCI && I2C
select DVB_ZL10353
select DVB_PLL
help
Support for PCI cards based on the Hopper PCI bridge.
Say Y when you have a Hopper based DVB card and want to use it.
If unsure say N
mantis_core-objs := mantis_ioc.o \
mantis_uart.o \
mantis_dma.o \
mantis_pci.o \
mantis_i2c.o \
mantis_dvb.o \
mantis_evm.o \
mantis_hif.o \
mantis_ca.o \
mantis_pcmcia.o \
mantis_input.o
mantis-objs := mantis_cards.o \
mantis_vp1033.o \
mantis_vp1034.o \
mantis_vp1041.o \
mantis_vp2033.o \
mantis_vp2040.o \
mantis_vp3030.o
hopper-objs := hopper_cards.o \
hopper_vp3028.o
obj-$(CONFIG_MANTIS_CORE) += mantis_core.o
obj-$(CONFIG_DVB_MANTIS) += mantis.o
obj-$(CONFIG_DVB_HOPPER) += hopper.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
/*
Hopper PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "mantis_common.h"
#include "hopper_vp3028.h"
#include "mantis_dma.h"
#include "mantis_dvb.h"
#include "mantis_uart.h"
#include "mantis_ioc.h"
#include "mantis_pci.h"
#include "mantis_i2c.h"
#include "mantis_reg.h"
static unsigned int verbose;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
#define DRIVER_NAME "Hopper"
static char *label[10] = {
"DMA",
"IRQ-0",
"IRQ-1",
"OCERR",
"PABRT",
"RIPRR",
"PPERR",
"FTRGT",
"RISCI",
"RACK"
};
static int devs;
static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
{
u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
struct mantis_ca *ca;
mantis = (struct mantis_pci *) dev_id;
if (unlikely(mantis == NULL)) {
dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
return IRQ_NONE;
}
ca = mantis->mantis_ca;
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
rst_mask = MANTIS_GPIF_WRACK |
MANTIS_GPIF_OTHERR |
MANTIS_SBUF_WSTO |
MANTIS_GPIF_EXTIRQ;
rst_stat = mmread(MANTIS_GPIF_STATUS);
rst_stat &= rst_mask;
mmwrite(rst_stat, MANTIS_GPIF_STATUS);
mantis->mantis_int_stat = stat;
mantis->mantis_int_mask = mask;
dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
if (stat & MANTIS_INT_RISCEN) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
}
if (stat & MANTIS_INT_IRQ0) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
mantis->gpif_status = rst_stat;
wake_up(&ca->hif_write_wq);
schedule_work(&ca->hif_evm_work);
}
if (stat & MANTIS_INT_IRQ1) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
schedule_work(&mantis->uart_work);
}
if (stat & MANTIS_INT_OCERR) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
}
if (stat & MANTIS_INT_PABORT) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
}
if (stat & MANTIS_INT_RIPERR) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
}
if (stat & MANTIS_INT_PPERR) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
}
if (stat & MANTIS_INT_FTRGT) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
}
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
}
if (stat & MANTIS_INT_I2CDONE) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
wake_up(&mantis->i2c_wq);
}
mmwrite(stat, MANTIS_INT_STAT);
stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE |
MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 |
MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 |
MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 |
MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 |
MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 |
MANTIS_INT_IRQ0 | MANTIS_INT_OCERR |
MANTIS_INT_PABORT | MANTIS_INT_RIPERR |
MANTIS_INT_PPERR | MANTIS_INT_FTRGT |
MANTIS_INT_RISCI);
if (stat)
dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
dprintk(MANTIS_DEBUG, 0, "\n");
return IRQ_HANDLED;
}
static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
{
struct mantis_pci *mantis;
struct mantis_hwconfig *config;
int err = 0;
mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
if (mantis == NULL) {
printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
err = -ENOMEM;
goto fail0;
}
mantis->num = devs;
mantis->verbose = verbose;
mantis->pdev = pdev;
config = (struct mantis_hwconfig *) pci_id->driver_data;
config->irq_handler = &hopper_irq_handler;
mantis->hwconfig = config;
err = mantis_pci_init(mantis);
if (err) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
goto fail1;
}
err = mantis_stream_control(mantis, STREAM_TO_HIF);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
goto fail1;
}
err = mantis_i2c_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
goto fail2;
}
err = mantis_get_mac(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
goto fail2;
}
err = mantis_dma_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
goto fail3;
}
err = mantis_dvb_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
goto fail4;
}
devs++;
return err;
fail4:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
mantis_dma_exit(mantis);
fail3:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
mantis_i2c_exit(mantis);
fail2:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
mantis_pci_exit(mantis);
fail1:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
kfree(mantis);
fail0:
return err;
}
static void __devexit hopper_pci_remove(struct pci_dev *pdev)
{
struct mantis_pci *mantis = pci_get_drvdata(pdev);
if (mantis) {
mantis_dvb_exit(mantis);
mantis_dma_exit(mantis);
mantis_i2c_exit(mantis);
mantis_pci_exit(mantis);
kfree(mantis);
}
return;
}
static struct pci_device_id hopper_pci_table[] = {
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config),
{ }
};
static struct pci_driver hopper_pci_driver = {
.name = DRIVER_NAME,
.id_table = hopper_pci_table,
.probe = hopper_pci_probe,
.remove = hopper_pci_remove,
};
static int __devinit hopper_init(void)
{
return pci_register_driver(&hopper_pci_driver);
}
static void __devexit hopper_exit(void)
{
return pci_unregister_driver(&hopper_pci_driver);
}
module_init(hopper_init);
module_exit(hopper_exit);
MODULE_DESCRIPTION("HOPPER driver");
MODULE_AUTHOR("Manu Abraham");
MODULE_LICENSE("GPL");
/*
Hopper VP-3028 driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "zl10353.h"
#include "mantis_common.h"
#include "mantis_ioc.h"
#include "mantis_dvb.h"
#include "hopper_vp3028.h"
struct zl10353_config hopper_vp3028_config = {
.demod_address = 0x0f,
};
#define MANTIS_MODEL_NAME "VP-3028"
#define MANTIS_DEV_TYPE "DVB-T"
static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
{
struct i2c_adapter *adapter = &mantis->adapter;
struct mantis_hwconfig *config = mantis->hwconfig;
int err = 0;
gpio_set_bits(mantis, config->reset, 0);
msleep(100);
err = mantis_frontend_power(mantis, POWER_ON);
msleep(100);
gpio_set_bits(mantis, config->reset, 1);
err = mantis_frontend_power(mantis, POWER_ON);
if (err == 0) {
msleep(250);
dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
fe = zl10353_attach(&hopper_vp3028_config, adapter);
if (!fe)
return -1;
} else {
dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
adapter->name,
err);
return -EIO;
}
dprintk(MANTIS_ERROR, 1, "Done!");
return 0;
}
struct mantis_hwconfig vp3028_config = {
.model_name = MANTIS_MODEL_NAME,
.dev_type = MANTIS_DEV_TYPE,
.ts_size = MANTIS_TS_188,
.baud_rate = MANTIS_BAUD_9600,
.parity = MANTIS_PARITY_NONE,
.bytes = 0,
.frontend_init = vp3028_frontend_init,
.power = GPIF_A00,
.reset = GPIF_A03,
};
/*
Hopper VP-3028 driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_VP3028_H
#define __MANTIS_VP3028_H
#include "mantis_common.h"
#define MANTIS_VP_3028_DVB_T 0x0028
extern struct mantis_hwconfig vp3028_config;
#endif /* __MANTIS_VP3028_H */
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "mantis_common.h"
#include "mantis_link.h"
#include "mantis_hif.h"
#include "mantis_reg.h"
#include "mantis_ca.h"
static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot);
if (slot != 0)
return -EINVAL;
return mantis_hif_read_mem(ca, addr);
}
static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot);
if (slot != 0)
return -EINVAL;
return mantis_hif_write_mem(ca, addr, data);
}
static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot);
if (slot != 0)
return -EINVAL;
return mantis_hif_read_iom(ca, addr);
}
static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot);
if (slot != 0)
return -EINVAL;
return mantis_hif_write_iom(ca, addr, data);
}
static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
udelay(500); /* Wait.. */
mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
udelay(500);
mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
msleep(1000);
dvb_ca_en50221_camready_irq(&ca->en50221, 0);
return 0;
}
static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot);
return 0;
}
static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot);
/* mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */
return 0;
}
static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
{
struct mantis_ca *ca = en50221->data;
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
if (ca->slot_state == MODULE_INSERTED) {
dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
} else {
dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
}
return 0;
}
int mantis_ca_init(struct mantis_pci *mantis)
{
struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter;
struct mantis_ca *ca;
int ca_flags = 0, result;
dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
if (!ca) {
dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
result = -ENOMEM;
goto err;
}
ca->ca_priv = mantis;
mantis->mantis_ca = ca;
ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
/* register CA interface */
ca->en50221.owner = THIS_MODULE;
ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem;
ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem;
ca->en50221.read_cam_control = mantis_ca_read_cam_ctl;
ca->en50221.write_cam_control = mantis_ca_write_cam_ctl;
ca->en50221.slot_reset = mantis_ca_slot_reset;
ca->en50221.slot_shutdown = mantis_ca_slot_shutdown;
ca->en50221.slot_ts_enable = mantis_ts_control;
ca->en50221.poll_slot_status = mantis_slot_status;
ca->en50221.data = ca;
mutex_init(&ca->ca_lock);
init_waitqueue_head(&ca->hif_data_wq);
init_waitqueue_head(&ca->hif_opdone_wq);
init_waitqueue_head(&ca->hif_write_wq);
dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
if (result != 0) {
dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
goto err;
}
dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
mantis_evmgr_init(ca);
return 0;
err:
kfree(ca);
return result;
}
EXPORT_SYMBOL_GPL(mantis_ca_init);
void mantis_ca_exit(struct mantis_pci *mantis)
{
struct mantis_ca *ca = mantis->mantis_ca;
dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
mantis_evmgr_exit(ca);
dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
if (ca)
dvb_ca_en50221_release(&ca->en50221);
kfree(ca);
}
EXPORT_SYMBOL_GPL(mantis_ca_exit);
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_CA_H
#define __MANTIS_CA_H
extern int mantis_ca_init(struct mantis_pci *mantis);
extern void mantis_ca_exit(struct mantis_pci *mantis);
#endif /* __MANTIS_CA_H */
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "mantis_common.h"
#include "mantis_vp1033.h"
#include "mantis_vp1034.h"
#include "mantis_vp1041.h"
#include "mantis_vp2033.h"
#include "mantis_vp2040.h"
#include "mantis_vp3030.h"
#include "mantis_dma.h"
#include "mantis_ca.h"
#include "mantis_dvb.h"
#include "mantis_uart.h"
#include "mantis_ioc.h"
#include "mantis_pci.h"
#include "mantis_i2c.h"
#include "mantis_reg.h"
static unsigned int verbose;
module_param(verbose, int, 0644);
MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
static int devs;
#define DRIVER_NAME "Mantis"
static char *label[10] = {
"DMA",
"IRQ-0",
"IRQ-1",
"OCERR",
"PABRT",
"RIPRR",
"PPERR",
"FTRGT",
"RISCI",
"RACK"
};
static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
{
u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
u32 rst_stat = 0, rst_mask = 0;
struct mantis_pci *mantis;
struct mantis_ca *ca;
mantis = (struct mantis_pci *) dev_id;
if (unlikely(mantis == NULL)) {
dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
return IRQ_NONE;
}
ca = mantis->mantis_ca;
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
if (!(stat & mask))
return IRQ_NONE;
rst_mask = MANTIS_GPIF_WRACK |
MANTIS_GPIF_OTHERR |
MANTIS_SBUF_WSTO |
MANTIS_GPIF_EXTIRQ;
rst_stat = mmread(MANTIS_GPIF_STATUS);
rst_stat &= rst_mask;
mmwrite(rst_stat, MANTIS_GPIF_STATUS);
mantis->mantis_int_stat = stat;
mantis->mantis_int_mask = mask;
dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
if (stat & MANTIS_INT_RISCEN) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
}
if (stat & MANTIS_INT_IRQ0) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
mantis->gpif_status = rst_stat;
wake_up(&ca->hif_write_wq);
schedule_work(&ca->hif_evm_work);
}
if (stat & MANTIS_INT_IRQ1) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
schedule_work(&mantis->uart_work);
}
if (stat & MANTIS_INT_OCERR) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
}
if (stat & MANTIS_INT_PABORT) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
}
if (stat & MANTIS_INT_RIPERR) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
}
if (stat & MANTIS_INT_PPERR) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
}
if (stat & MANTIS_INT_FTRGT) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
}
if (stat & MANTIS_INT_RISCI) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
tasklet_schedule(&mantis->tasklet);
}
if (stat & MANTIS_INT_I2CDONE) {
dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
wake_up(&mantis->i2c_wq);
}
mmwrite(stat, MANTIS_INT_STAT);
stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE |
MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 |
MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 |
MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 |
MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 |
MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 |
MANTIS_INT_IRQ0 | MANTIS_INT_OCERR |
MANTIS_INT_PABORT | MANTIS_INT_RIPERR |
MANTIS_INT_PPERR | MANTIS_INT_FTRGT |
MANTIS_INT_RISCI);
if (stat)
dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
dprintk(MANTIS_DEBUG, 0, "\n");
return IRQ_HANDLED;
}
static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
{
struct mantis_pci *mantis;
struct mantis_hwconfig *config;
int err = 0;
mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
if (mantis == NULL) {
printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
err = -ENOMEM;
goto fail0;
}
mantis->num = devs;
mantis->verbose = verbose;
mantis->pdev = pdev;
config = (struct mantis_hwconfig *) pci_id->driver_data;
config->irq_handler = &mantis_irq_handler;
mantis->hwconfig = config;
err = mantis_pci_init(mantis);
if (err) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
goto fail1;
}
err = mantis_stream_control(mantis, STREAM_TO_HIF);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
goto fail1;
}
err = mantis_i2c_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
goto fail2;
}
err = mantis_get_mac(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
goto fail2;
}
err = mantis_dma_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
goto fail3;
}
err = mantis_dvb_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
goto fail4;
}
err = mantis_uart_init(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err);
goto fail6;
}
devs++;
return err;
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err);
mantis_uart_exit(mantis);
fail6:
fail4:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
mantis_dma_exit(mantis);
fail3:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
mantis_i2c_exit(mantis);
fail2:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
mantis_pci_exit(mantis);
fail1:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
kfree(mantis);
fail0:
return err;
}
static void __devexit mantis_pci_remove(struct pci_dev *pdev)
{
struct mantis_pci *mantis = pci_get_drvdata(pdev);
if (mantis) {
mantis_uart_exit(mantis);
mantis_dvb_exit(mantis);
mantis_dma_exit(mantis);
mantis_i2c_exit(mantis);
mantis_pci_exit(mantis);
kfree(mantis);
}
return;
}
static struct pci_device_id mantis_pci_table[] = {
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config),
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config),
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config),
MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config),
MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config),
MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config),
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config),
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config),
MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config),
MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config),
MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config),
{ }
};
static struct pci_driver mantis_pci_driver = {
.name = DRIVER_NAME,
.id_table = mantis_pci_table,
.probe = mantis_pci_probe,
.remove = mantis_pci_remove,
};
static int __devinit mantis_init(void)
{
return pci_register_driver(&mantis_pci_driver);
}
static void __devexit mantis_exit(void)
{
return pci_unregister_driver(&mantis_pci_driver);
}
module_init(mantis_init);
module_exit(mantis_exit);
MODULE_DESCRIPTION("MANTIS driver");
MODULE_AUTHOR("Manu Abraham");
MODULE_LICENSE("GPL");
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_COMMON_H
#define __MANTIS_COMMON_H
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include "mantis_uart.h"
#include "mantis_link.h"
#define MANTIS_ERROR 0
#define MANTIS_NOTICE 1
#define MANTIS_INFO 2
#define MANTIS_DEBUG 3
#define MANTIS_TMG 9
#define dprintk(y, z, format, arg...) do { \
if (z) { \
if ((mantis->verbose > MANTIS_ERROR) && (mantis->verbose > y)) \
printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \
else if ((mantis->verbose > MANTIS_NOTICE) && (mantis->verbose > y)) \
printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \
else if ((mantis->verbose > MANTIS_INFO) && (mantis->verbose > y)) \
printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \
else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y)) \
printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \
else if ((mantis->verbose > MANTIS_TMG) && (mantis->verbose > y)) \
printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \
} else { \
if (mantis->verbose > y) \
printk(format , ##arg); \
} \
} while(0)
#define mwrite(dat, addr) writel((dat), addr)
#define mread(addr) readl(addr)
#define mmwrite(dat, addr) mwrite((dat), (mantis->mmio + (addr)))
#define mmread(addr) mread(mantis->mmio + (addr))
#define MANTIS_TS_188 0
#define MANTIS_TS_204 1
#define TWINHAN_TECHNOLOGIES 0x1822
#define MANTIS 0x4e35
#define TECHNISAT 0x1ae4
#define TERRATEC 0x153b
#define MAKE_ENTRY(__subven, __subdev, __configptr) { \
.vendor = TWINHAN_TECHNOLOGIES, \
.device = MANTIS, \
.subvendor = (__subven), \
.subdevice = (__subdev), \
.driver_data = (unsigned long) (__configptr) \
}
enum mantis_i2c_mode {
MANTIS_PAGE_MODE = 0,
MANTIS_BYTE_MODE,
};
struct mantis_pci;
struct mantis_hwconfig {
char *model_name;
char *dev_type;
u32 ts_size;
enum mantis_baud baud_rate;
enum mantis_parity parity;
u32 bytes;
irqreturn_t (*irq_handler)(int irq, void *dev_id);
int (*frontend_init)(struct mantis_pci *mantis, struct dvb_frontend *fe);
u8 power;
u8 reset;
enum mantis_i2c_mode i2c_mode;
};
struct mantis_pci {
unsigned int verbose;
/* PCI stuff */
u16 vendor_id;
u16 device_id;
u16 subsystem_vendor;
u16 subsystem_device;
u8 latency;
struct pci_dev *pdev;
unsigned long mantis_addr;
void __iomem *mmio;
u8 irq;
u8 revision;
unsigned int num;
/* RISC Core */
u32 finished_block;
u32 last_block;
u32 line_bytes;
u32 line_count;
u32 risc_pos;
u8 *buf_cpu;
dma_addr_t buf_dma;
u32 *risc_cpu;
dma_addr_t risc_dma;
struct tasklet_struct tasklet;
struct i2c_adapter adapter;
int i2c_rc;
wait_queue_head_t i2c_wq;
struct mutex i2c_lock;
/* DVB stuff */
struct dvb_adapter dvb_adapter;
struct dvb_frontend *fe;
struct dvb_demux demux;
struct dmxdev dmxdev;
struct dmx_frontend fe_hw;
struct dmx_frontend fe_mem;
struct dvb_net dvbnet;
u8 feeds;
struct mantis_hwconfig *hwconfig;
u32 mantis_int_stat;
u32 mantis_int_mask;
/* board specific */
u8 mac_address[8];
u32 sub_vendor_id;
u32 sub_device_id;
/* A12 A13 A14 */
u32 gpio_status;
u32 gpif_status;
struct mantis_ca *mantis_ca;
wait_queue_head_t uart_wq;
struct work_struct uart_work;
spinlock_t uart_lock;
struct input_dev *rc;
};
#define MANTIS_HIF_STATUS (mantis->gpio_status)
#endif /* __MANTIS_COMMON_H */
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "mantis_common.h"
#include "mantis_core.h"
#include "mantis_vp1033.h"
#include "mantis_vp1034.h"
#include "mantis_vp1041.h"
#include "mantis_vp2033.h"
#include "mantis_vp2040.h"
#include "mantis_vp3030.h"
static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
{
int err;
struct i2c_msg msg[] = {
{
.addr = 0x50,
.flags = 0,
.buf = data,
.len = 1
}, {
.addr = 0x50,
.flags = I2C_M_RD,
.buf = data,
.len = length
},
};
err = i2c_transfer(&mantis->adapter, msg, 2);
if (err < 0) {
dprintk(verbose, MANTIS_ERROR, 1,
"ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
err, data[0], data[1]);
return err;
}
return 0;
}
static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
{
int err;
struct i2c_msg msg = {
.addr = 0x50,
.flags = 0,
.buf = data,
.len = length
};
err = i2c_transfer(&mantis->adapter, &msg, 1);
if (err < 0) {
dprintk(verbose, MANTIS_ERROR, 1,
"ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >",
err, length, data[0], data[1]);
return err;
}
return 0;
}
static int get_mac_address(struct mantis_pci *mantis)
{
int err;
mantis->mac_address[0] = 0x08;
err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6);
if (err < 0) {
dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error");
return err;
}
dprintk(verbose, MANTIS_ERROR, 0,
" MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n",
mantis->mac_address[0], mantis->mac_address[1],
mantis->mac_address[2], mantis->mac_address[3],
mantis->mac_address[4], mantis->mac_address[5]);
return 0;
}
#define MANTIS_MODEL_UNKNOWN "UNKNOWN"
#define MANTIS_DEV_UNKNOWN "UNKNOWN"
struct mantis_hwconfig unknown_device = {
.model_name = MANTIS_MODEL_UNKNOWN,
.dev_type = MANTIS_DEV_UNKNOWN,
};
static void mantis_load_config(struct mantis_pci *mantis)
{
switch (mantis->subsystem_device) {
case MANTIS_VP_1033_DVB_S: /* VP-1033 */
mantis->hwconfig = &vp1033_mantis_config;
break;
case MANTIS_VP_1034_DVB_S: /* VP-1034 */
mantis->hwconfig = &vp1034_mantis_config;
break;
case MANTIS_VP_1041_DVB_S2: /* VP-1041 */
case TECHNISAT_SKYSTAR_HD2:
mantis->hwconfig = &vp1041_mantis_config;
break;
case MANTIS_VP_2033_DVB_C: /* VP-2033 */
mantis->hwconfig = &vp2033_mantis_config;
break;
case MANTIS_VP_2040_DVB_C: /* VP-2040 */
case TERRATEC_CINERGY_C_PCI: /* VP-2040 clone */
case TECHNISAT_CABLESTAR_HD2:
mantis->hwconfig = &vp2040_mantis_config;
break;
case MANTIS_VP_3030_DVB_T: /* VP-3030 */
mantis->hwconfig = &vp3030_mantis_config;
break;
default:
mantis->hwconfig = &unknown_device;
break;
}
}
int mantis_core_init(struct mantis_pci *mantis)
{
int err = 0;
mantis_load_config(mantis);
dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
mantis->hwconfig->model_name, mantis->hwconfig->dev_type,
mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn));
dprintk(verbose, MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ",
mantis->revision,
mantis->subsystem_vendor, mantis->subsystem_device);
dprintk(verbose, MANTIS_ERROR, 0,
"irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n",
mantis->pdev->irq, mantis->latency,
mantis->mantis_addr, mantis->mantis_mmio);
err = mantis_i2c_init(mantis);
if (err < 0) {
dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed");
return err;
}
err = get_mac_address(mantis);
if (err < 0) {
dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed");
return err;
}
err = mantis_dma_init(mantis);
if (err < 0) {
dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed");
return err;
}
err = mantis_dvb_init(mantis);
if (err < 0) {
dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed");
return err;
}
err = mantis_uart_init(mantis);
if (err < 0) {
dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed");
return err;
}
return 0;
}
int mantis_core_exit(struct mantis_pci *mantis)
{
mantis_dma_stop(mantis);
dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping");
mantis_uart_exit(mantis);
dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed");
if (mantis_dma_exit(mantis) < 0)
dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed");
if (mantis_dvb_exit(mantis) < 0)
dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed");
if (mantis_i2c_exit(mantis) < 0)
dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed");
return 0;
}
/* Turn the given bit on or off. */
void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
{
u32 cur;
cur = mmread(MANTIS_GPIF_ADDR);
if (value)
mantis->gpio_status = cur | (1 << bitpos);
else
mantis->gpio_status = cur & (~(1 << bitpos));
mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
mmwrite(0x00, MANTIS_GPIF_DOUT);
udelay(100);
}
/* direction = 0 , no CI passthrough ; 1 , CI passthrough */
void mantis_set_direction(struct mantis_pci *mantis, int direction)
{
u32 reg;
reg = mmread(0x28);
dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup");
if (direction == 0x01) {
/* to CI */
reg |= 0x04;
mmwrite(reg, 0x28);
reg &= 0xff - 0x04;
mmwrite(reg, 0x28);
} else {
reg &= 0xff - 0x04;
mmwrite(reg, 0x28);
reg |= 0x04;
mmwrite(reg, 0x28);
}
}
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_CORE_H
#define __MANTIS_CORE_H
#include "mantis_common.h"
#define FE_TYPE_SAT 0
#define FE_TYPE_CAB 1
#define FE_TYPE_TER 2
#define FE_TYPE_TS204 0
#define FE_TYPE_TS188 1
struct vendorname {
u8 *sub_vendor_name;
u32 sub_vendor_id;
};
struct devicetype {
u8 *sub_device_name;
u32 sub_device_id;
u8 device_type;
u32 type_flags;
};
extern int mantis_dma_init(struct mantis_pci *mantis);
extern int mantis_dma_exit(struct mantis_pci *mantis);
extern void mantis_dma_start(struct mantis_pci *mantis);
extern void mantis_dma_stop(struct mantis_pci *mantis);
extern int mantis_i2c_init(struct mantis_pci *mantis);
extern int mantis_i2c_exit(struct mantis_pci *mantis);
extern int mantis_core_init(struct mantis_pci *mantis);
extern int mantis_core_exit(struct mantis_pci *mantis);
#endif /* __MANTIS_CORE_H */
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <asm/page.h>
#include <linux/vmalloc.h>
#include <linux/pci.h>
#include <asm/irq.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "mantis_common.h"
#include "mantis_reg.h"
#include "mantis_dma.h"
#define RISC_WRITE (0x01 << 28)
#define RISC_JUMP (0x07 << 28)
#define RISC_IRQ (0x01 << 24)
#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
#define RISC_FLUSH() (mantis->risc_pos = 0)
#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode))
#define MANTIS_BUF_SIZE (64 * 1024)
#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4)
#define MANTIS_BLOCK_COUNT (1 << 4)
#define MANTIS_RISC_SIZE PAGE_SIZE
int mantis_dma_exit(struct mantis_pci *mantis)
{
if (mantis->buf_cpu) {
dprintk(MANTIS_ERROR, 1,
"DMA=0x%lx cpu=0x%p size=%d",
(unsigned long) mantis->buf_dma,
mantis->buf_cpu,
MANTIS_BUF_SIZE);
pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE,
mantis->buf_cpu, mantis->buf_dma);
mantis->buf_cpu = NULL;
}
if (mantis->risc_cpu) {
dprintk(MANTIS_ERROR, 1,
"RISC=0x%lx cpu=0x%p size=%lx",
(unsigned long) mantis->risc_dma,
mantis->risc_cpu,
MANTIS_RISC_SIZE);
pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE,
mantis->risc_cpu, mantis->risc_dma);
mantis->risc_cpu = NULL;
}
return 0;
}
EXPORT_SYMBOL_GPL(mantis_dma_exit);
static inline int mantis_alloc_buffers(struct mantis_pci *mantis)
{
if (!mantis->buf_cpu) {
mantis->buf_cpu = pci_alloc_consistent(mantis->pdev,
MANTIS_BUF_SIZE,
&mantis->buf_dma);
if (!mantis->buf_cpu) {
dprintk(MANTIS_ERROR, 1,
"DMA buffer allocation failed");
goto err;
}
dprintk(MANTIS_ERROR, 1,
"DMA=0x%lx cpu=0x%p size=%d",
(unsigned long) mantis->buf_dma,
mantis->buf_cpu, MANTIS_BUF_SIZE);
}
if (!mantis->risc_cpu) {
mantis->risc_cpu = pci_alloc_consistent(mantis->pdev,
MANTIS_RISC_SIZE,
&mantis->risc_dma);
if (!mantis->risc_cpu) {
dprintk(MANTIS_ERROR, 1,
"RISC program allocation failed");
mantis_dma_exit(mantis);
goto err;
}
dprintk(MANTIS_ERROR, 1,
"RISC=0x%lx cpu=0x%p size=%lx",
(unsigned long) mantis->risc_dma,
mantis->risc_cpu, MANTIS_RISC_SIZE);
}
return 0;
err:
dprintk(MANTIS_ERROR, 1, "Out of memory (?) .....");
return -ENOMEM;
}
static inline int mantis_calc_lines(struct mantis_pci *mantis)
{
mantis->line_bytes = MANTIS_BLOCK_BYTES;
mantis->line_count = MANTIS_BLOCK_COUNT;
while (mantis->line_bytes > 4095) {
mantis->line_bytes >>= 1;
mantis->line_count <<= 1;
}
dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]",
MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count);
if (mantis->line_count > 255) {
dprintk(MANTIS_ERROR, 1, "Buffer size error");
return -EINVAL;
}
return 0;
}
int mantis_dma_init(struct mantis_pci *mantis)
{
int err = 0;
dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
if (mantis_alloc_buffers(mantis) < 0) {
dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
/* Stop RISC Engine */
mmwrite(0, MANTIS_DMA_CTL);
goto err;
}
err = mantis_calc_lines(mantis);
if (err < 0) {
dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
goto err;
}
return 0;
err:
return err;
}
EXPORT_SYMBOL_GPL(mantis_dma_init);
static inline void mantis_risc_program(struct mantis_pci *mantis)
{
u32 buf_pos = 0;
u32 line;
dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
RISC_FLUSH();
dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",
mantis->line_count, mantis->line_bytes);
for (line = 0; line < mantis->line_count; line++) {
dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);
if (!(buf_pos % MANTIS_BLOCK_BYTES)) {
RISC_INSTR(RISC_WRITE |
RISC_IRQ |
RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) +
(MANTIS_BLOCK_COUNT - 1)) %
MANTIS_BLOCK_COUNT) |
mantis->line_bytes);
} else {
RISC_INSTR(RISC_WRITE | mantis->line_bytes);
}
RISC_INSTR(mantis->buf_dma + buf_pos);
buf_pos += mantis->line_bytes;
}
RISC_INSTR(RISC_JUMP);
RISC_INSTR(mantis->risc_dma);
}
void mantis_dma_start(struct mantis_pci *mantis)
{
dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine");
mantis_risc_program(mantis);
mmwrite(mantis->risc_dma, MANTIS_RISC_START);
mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
mmwrite(0, MANTIS_DMA_CTL);
mantis->last_block = mantis->finished_block = 0;
mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN
| MANTIS_RISC_EN, MANTIS_DMA_CTL);
}
void mantis_dma_stop(struct mantis_pci *mantis)
{
u32 stat = 0, mask = 0;
stat = mmread(MANTIS_INT_STAT);
mask = mmread(MANTIS_INT_MASK);
dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine");
mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR);
mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN |
MANTIS_DCAP_EN |
MANTIS_RISC_EN)), MANTIS_DMA_CTL);
mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT);
mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI |
MANTIS_INT_RISCEN), MANTIS_INT_MASK);
}
void mantis_dma_xfer(unsigned long data)
{
struct mantis_pci *mantis = (struct mantis_pci *) data;
struct mantis_hwconfig *config = mantis->hwconfig;
while (mantis->last_block != mantis->finished_block) {
dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
mantis->last_block, mantis->finished_block);
(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT;
}
}
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_DMA_H
#define __MANTIS_DMA_H
extern int mantis_dma_init(struct mantis_pci *mantis);
extern int mantis_dma_exit(struct mantis_pci *mantis);
extern void mantis_dma_start(struct mantis_pci *mantis);
extern void mantis_dma_stop(struct mantis_pci *mantis);
extern void mantis_dma_xfer(unsigned long data);
#endif /* __MANTIS_DMA_H */
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "mantis_common.h"
#include "mantis_dma.h"
#include "mantis_ca.h"
#include "mantis_ioc.h"
#include "mantis_dvb.h"
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
{
struct mantis_hwconfig *config = mantis->hwconfig;
switch (power) {
case POWER_ON:
dprintk(MANTIS_DEBUG, 1, "Power ON");
gpio_set_bits(mantis, config->power, POWER_ON);
msleep(100);
gpio_set_bits(mantis, config->power, POWER_ON);
msleep(100);
break;
case POWER_OFF:
dprintk(MANTIS_DEBUG, 1, "Power OFF");
gpio_set_bits(mantis, config->power, POWER_OFF);
msleep(100);
break;
default:
dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
return -1;
}
return 0;
}
EXPORT_SYMBOL_GPL(mantis_frontend_power);
void mantis_frontend_soft_reset(struct mantis_pci *mantis)
{
struct mantis_hwconfig *config = mantis->hwconfig;
dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
gpio_set_bits(mantis, config->reset, 0);
msleep(100);
gpio_set_bits(mantis, config->reset, 0);
msleep(100);
gpio_set_bits(mantis, config->reset, 1);
msleep(100);
gpio_set_bits(mantis, config->reset, 1);
msleep(100);
return;
}
EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
static int mantis_frontend_shutdown(struct mantis_pci *mantis)
{
int err;
mantis_frontend_soft_reset(mantis);
err = mantis_frontend_power(mantis, POWER_OFF);
if (err != 0) {
dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
return 1;
}
return 0;
}
static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct mantis_pci *mantis = dvbdmx->priv;
dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
if (!dvbdmx->dmx.frontend) {
dprintk(MANTIS_DEBUG, 1, "no frontend ?");
return -EINVAL;
}
mantis->feeds++;
dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds);
if (mantis->feeds == 1) {
dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
mantis_dma_start(mantis);
}
return mantis->feeds;
}
static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct mantis_pci *mantis = dvbdmx->priv;
dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
if (!dvbdmx->dmx.frontend) {
dprintk(MANTIS_DEBUG, 1, "no frontend ?");
return -EINVAL;
}
mantis->feeds--;
if (mantis->feeds == 0) {
dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
mantis_dma_stop(mantis);
}
return 0;
}
int __devinit mantis_dvb_init(struct mantis_pci *mantis)
{
struct mantis_hwconfig *config = mantis->hwconfig;
int result = -1;
dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
result = dvb_register_adapter(&mantis->dvb_adapter,
"Mantis DVB adapter",
THIS_MODULE,
&mantis->pdev->dev,
adapter_nr);
if (result < 0) {
dprintk(MANTIS_ERROR, 1, "Error registering adapter");
return -ENODEV;
}
mantis->dvb_adapter.priv = mantis;
mantis->demux.dmx.capabilities = DMX_TS_FILTERING |
DMX_SECTION_FILTERING |
DMX_MEMORY_BASED_FILTERING;
mantis->demux.priv = mantis;
mantis->demux.filternum = 256;
mantis->demux.feednum = 256;
mantis->demux.start_feed = mantis_dvb_start_feed;
mantis->demux.stop_feed = mantis_dvb_stop_feed;
mantis->demux.write_to_decoder = NULL;
dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
result = dvb_dmx_init(&mantis->demux);
if (result < 0) {
dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
goto err0;
}
mantis->dmxdev.filternum = 256;
mantis->dmxdev.demux = &mantis->demux.dmx;
mantis->dmxdev.capabilities = 0;
dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
if (result < 0) {
dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
goto err1;
}
mantis->fe_hw.source = DMX_FRONTEND_0;
result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
if (result < 0) {
dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
goto err2;
}
mantis->fe_mem.source = DMX_MEMORY_FE;
result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
if (result < 0) {
dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
goto err3;
}
result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
if (result < 0) {
dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
goto err4;
}
dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
if (mantis->hwconfig) {
result = config->frontend_init(mantis, mantis->fe);
if (result < 0) {
dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
goto err5;
} else {
if (mantis->fe == NULL) {
dprintk(MANTIS_ERROR, 1, "FE <NULL>");
goto err5;
}
if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) {
dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
if (mantis->fe->ops.release)
mantis->fe->ops.release(mantis->fe);
mantis->fe = NULL;
goto err5;
}
}
}
return 0;
/* Error conditions .. */
err5:
tasklet_kill(&mantis->tasklet);
dvb_net_release(&mantis->dvbnet);
dvb_unregister_frontend(mantis->fe);
dvb_frontend_detach(mantis->fe);
err4:
mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
err3:
mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
err2:
dvb_dmxdev_release(&mantis->dmxdev);
err1:
dvb_dmx_release(&mantis->demux);
err0:
dvb_unregister_adapter(&mantis->dvb_adapter);
return result;
}
EXPORT_SYMBOL_GPL(mantis_dvb_init);
int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
{
int err;
if (mantis->fe) {
/* mantis_ca_exit(mantis); */
err = mantis_frontend_shutdown(mantis);
if (err != 0)
dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
dvb_unregister_frontend(mantis->fe);
dvb_frontend_detach(mantis->fe);
}
tasklet_kill(&mantis->tasklet);
dvb_net_release(&mantis->dvbnet);
mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
dvb_dmxdev_release(&mantis->dmxdev);
dvb_dmx_release(&mantis->demux);
dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
dvb_unregister_adapter(&mantis->dvb_adapter);
return 0;
}
EXPORT_SYMBOL_GPL(mantis_dvb_exit);
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_DVB_H
#define __MANTIS_DVB_H
enum mantis_power {
POWER_OFF = 0,
POWER_ON = 1
};
extern int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power);
extern void mantis_frontend_soft_reset(struct mantis_pci *mantis);
extern int mantis_dvb_init(struct mantis_pci *mantis);
extern int mantis_dvb_exit(struct mantis_pci *mantis);
#endif /* __MANTIS_DVB_H */
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "mantis_common.h"
#include "mantis_link.h"
#include "mantis_hif.h"
#include "mantis_reg.h"
static void mantis_hifevm_work(struct work_struct *work)
{
struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work);
struct mantis_pci *mantis = ca->ca_priv;
u32 gpif_stat, gpif_mask;
gpif_stat = mmread(MANTIS_GPIF_STATUS);
gpif_mask = mmread(MANTIS_GPIF_IRQCFG);
if (gpif_stat & MANTIS_GPIF_DETSTAT) {
if (gpif_stat & MANTIS_CARD_PLUGIN) {
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num);
mmwrite(0xdada0000, MANTIS_CARD_RESET);
mantis_event_cam_plugin(ca);
dvb_ca_en50221_camchange_irq(&ca->en50221,
0,
DVB_CA_EN50221_CAMCHANGE_INSERTED);
}
} else {
if (gpif_stat & MANTIS_CARD_PLUGOUT) {
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num);
mmwrite(0xdada0000, MANTIS_CARD_RESET);
mantis_event_cam_unplug(ca);
dvb_ca_en50221_camchange_irq(&ca->en50221,
0,
DVB_CA_EN50221_CAMCHANGE_REMOVED);
}
}
if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ)
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num);
if (mantis->gpif_status & MANTIS_SBUF_WSTO)
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num);
if (mantis->gpif_status & MANTIS_GPIF_OTHERR)
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num);
if (gpif_stat & MANTIS_SBUF_OVFLW)
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num);
if (gpif_stat & MANTIS_GPIF_BRRDY)
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num);
if (gpif_stat & MANTIS_GPIF_INTSTAT)
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num);
if (gpif_stat & MANTIS_SBUF_EMPTY)
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num);
if (gpif_stat & MANTIS_SBUF_OPDONE) {
dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num);
ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL;
ca->hif_event = MANTIS_SBUF_OPDONE;
wake_up(&ca->hif_opdone_wq);
}
}
int mantis_evmgr_init(struct mantis_ca *ca)
{
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager");
INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work);
mantis_pcmcia_init(ca);
schedule_work(&ca->hif_evm_work);
mantis_hif_init(ca);
return 0;
}
void mantis_evmgr_exit(struct mantis_ca *ca)
{
struct mantis_pci *mantis = ca->ca_priv;
dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting");
flush_scheduled_work();
mantis_hif_exit(ca);
mantis_pcmcia_exit(ca);
}
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "dvb_net.h"
#include "mantis_common.h"
#include "mantis_hif.h"
#include "mantis_link.h" /* temporary due to physical layer stuff */
#include "mantis_reg.h"
static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca)
{
struct mantis_pci *mantis = ca->ca_priv;
int rc = 0;
if (wait_event_timeout(ca->hif_opdone_wq,
ca->hif_event & MANTIS_SBUF_OPDONE,
msecs_to_jiffies(500)) == -ERESTARTSYS) {
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num);
rc = -EREMOTEIO;
}
dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete");
ca->hif_event &= ~MANTIS_SBUF_OPDONE;
return rc;
}
static int mantis_hif_write_wait(struct mantis_ca *ca)
{
struct mantis_pci *mantis = ca->ca_priv;
u32 opdone = 0, timeout = 0;
int rc = 0;
if (wait_event_timeout(ca->hif_write_wq,
mantis->gpif_status & MANTIS_GPIF_WRACK,
msecs_to_jiffies(500)) == -ERESTARTSYS) {
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num);
rc = -EREMOTEIO;
}
dprintk(MANTIS_DEBUG, 1, "Write Acknowledged");
mantis->gpif_status &= ~MANTIS_GPIF_WRACK;
while (!opdone) {
opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE);
udelay(500);
timeout++;
if (timeout > 100) {
dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num);
rc = -ETIMEDOUT;
break;
}
}
dprintk(MANTIS_DEBUG, 1, "HIF Write success");
return rc;
}
int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr)
{
struct mantis_pci *mantis = ca->ca_priv;
u32 hif_addr = 0, data, count = 4;
dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num);
mutex_lock(&ca->ca_lock);
hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
hif_addr |= MANTIS_HIF_STATUS;
hif_addr |= addr;
mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
mmwrite(count, MANTIS_GPIF_BRBYTES);
udelay(20);
mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num);
mutex_unlock(&ca->ca_lock);
return -EREMOTEIO;
}
data = mmread(MANTIS_GPIF_DIN);
mutex_unlock(&ca->ca_lock);
dprintk(MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data);
return (data >> 24) & 0xff;
}
int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data)
{
struct mantis_slot *slot = ca->slot;
struct mantis_pci *mantis = ca->ca_priv;
u32 hif_addr = 0;
dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num);
mutex_lock(&ca->ca_lock);
hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
hif_addr |= MANTIS_HIF_STATUS;
hif_addr |= addr;
mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */
mmwrite(hif_addr, MANTIS_GPIF_ADDR);
mmwrite(data, MANTIS_GPIF_DOUT);
if (mantis_hif_write_wait(ca) != 0) {
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
mutex_unlock(&ca->ca_lock);
return -EREMOTEIO;
}
dprintk(MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr);
mutex_unlock(&ca->ca_lock);
return 0;
}
int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr)
{
struct mantis_pci *mantis = ca->ca_priv;
u32 data, hif_addr = 0;
dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num);
mutex_lock(&ca->ca_lock);
hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
hif_addr |= MANTIS_GPIF_PCMCIAIOM;
hif_addr |= MANTIS_HIF_STATUS;
hif_addr |= addr;
mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
mmwrite(1, MANTIS_GPIF_BRBYTES);
udelay(20);
mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
mutex_unlock(&ca->ca_lock);
return -EREMOTEIO;
}
data = mmread(MANTIS_GPIF_DIN);
dprintk(MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data);
udelay(50);
mutex_unlock(&ca->ca_lock);
return (u8) data;
}
int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data)
{
struct mantis_pci *mantis = ca->ca_priv;
u32 hif_addr = 0;
dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num);
mutex_lock(&ca->ca_lock);
hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
hif_addr |= MANTIS_GPIF_PCMCIAIOM;
hif_addr |= MANTIS_HIF_STATUS;
hif_addr |= addr;
mmwrite(hif_addr, MANTIS_GPIF_ADDR);
mmwrite(data, MANTIS_GPIF_DOUT);
if (mantis_hif_write_wait(ca) != 0) {
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
mutex_unlock(&ca->ca_lock);
return -EREMOTEIO;
}
dprintk(MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr);
mutex_unlock(&ca->ca_lock);
udelay(50);
return 0;
}
int mantis_hif_init(struct mantis_ca *ca)
{
struct mantis_slot *slot = ca->slot;
struct mantis_pci *mantis = ca->ca_priv;
u32 irqcfg;
slot[0].slave_cfg = 0x70773028;
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num);
mutex_lock(&ca->ca_lock);
irqcfg = mmread(MANTIS_GPIF_IRQCFG);
irqcfg = MANTIS_MASK_BRRDY |
MANTIS_MASK_WRACK |
MANTIS_MASK_EXTIRQ |
MANTIS_MASK_WSTO |
MANTIS_MASK_OTHERR |
MANTIS_MASK_OVFLW;
mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
mutex_unlock(&ca->ca_lock);
return 0;
}
void mantis_hif_exit(struct mantis_ca *ca)
{
struct mantis_pci *mantis = ca->ca_priv;
u32 irqcfg;
dprintk(MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num);
mutex_lock(&ca->ca_lock);
irqcfg = mmread(MANTIS_GPIF_IRQCFG);
irqcfg &= ~MANTIS_MASK_BRRDY;
mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
mutex_unlock(&ca->ca_lock);
}
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_HIF_H
#define __MANTIS_HIF_H
#define MANTIS_HIF_MEMRD 1
#define MANTIS_HIF_MEMWR 2
#define MANTIS_HIF_IOMRD 3
#define MANTIS_HIF_IOMWR 4
#endif /* __MANTIS_HIF_H */
此差异已折叠。
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_I2C_H
#define __MANTIS_I2C_H
#define I2C_STOP (1 << 0)
#define I2C_READ (1 << 1)
extern int mantis_i2c_init(struct mantis_pci *mantis);
extern int mantis_i2c_exit(struct mantis_pci *mantis);
#endif /* __MANTIS_I2C_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
Mantis PCI bridge driver
Copyright (C) Manu Abraham (abraham.manu@gmail.com)
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __MANTIS_PCI_H
#define __MANTIS_PCI_H
extern int mantis_pci_init(struct mantis_pci *mantis);
extern void mantis_pci_exit(struct mantis_pci *mantis);
#endif /* __MANTIS_PCI_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册