V4L/DVB (4029): [PATCH] Genpix 8PSK->USB driver (Take 2)
This is a patch which includes support for the GENPIX 8PSK->USB module. The board supports QPSK, BPSK and 8PSK decoding (though I don't think it will be DVB-S2 compliant) With the following patch, the boad is equivalent to a budget card (no CA Module) The patch which adds 8psk suppot will follow, but is seperate, as it requires DVB-S2 support More info on the board can be found at www.genpix-electronics.com (and they host the requisite firmwares there as well) Signed off by: Alan Nisota <alannisota@gmail.com> Signed-off-by: Patrick Boettcher <pb@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
6daa4f86e9
commit
9bbe076f36
@ -130,6 +130,15 @@ config DVB_USB_VP702X
|
|||||||
|
|
||||||
DVB-S USB2.0 receivers.
|
DVB-S USB2.0 receivers.
|
||||||
|
|
||||||
|
config DVB_USB_GP8PSK
|
||||||
|
tristate "GENPIX 8PSK->USB module support"
|
||||||
|
depends on DVB_USB
|
||||||
|
help
|
||||||
|
Say Y here to support the
|
||||||
|
GENPIX 8psk module
|
||||||
|
|
||||||
|
DVB-S USB2.0 receivers.
|
||||||
|
|
||||||
config DVB_USB_NOVA_T_USB2
|
config DVB_USB_NOVA_T_USB2
|
||||||
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
|
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
|
||||||
depends on DVB_USB
|
depends on DVB_USB
|
||||||
|
@ -7,6 +7,9 @@ obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
|
|||||||
dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
|
dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
|
||||||
obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
|
obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
|
||||||
|
|
||||||
|
dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
|
||||||
|
obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
|
||||||
|
|
||||||
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
|
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
|
||||||
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
|
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#define USB_VID_VISIONPLUS 0x13d3
|
#define USB_VID_VISIONPLUS 0x13d3
|
||||||
#define USB_VID_TWINHAN 0x1822
|
#define USB_VID_TWINHAN 0x1822
|
||||||
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
||||||
|
#define USB_VID_GENPIX 0x09c0
|
||||||
|
|
||||||
/* Product IDs */
|
/* Product IDs */
|
||||||
#define USB_PID_ADSTECH_USB2_COLD 0xa333
|
#define USB_PID_ADSTECH_USB2_COLD 0xa333
|
||||||
@ -104,5 +105,6 @@
|
|||||||
#define USB_PID_KYE_DVB_T_WARM 0x701f
|
#define USB_PID_KYE_DVB_T_WARM 0x701f
|
||||||
#define USB_PID_PCTV_200E 0x020e
|
#define USB_PID_PCTV_200E 0x020e
|
||||||
#define USB_PID_PCTV_400E 0x020f
|
#define USB_PID_PCTV_400E 0x020f
|
||||||
|
#define USB_PID_GENPIX_8PSK_COLD 0x0200
|
||||||
|
#define USB_PID_GENPIX_8PSK_WARM 0x0201
|
||||||
#endif
|
#endif
|
||||||
|
272
drivers/media/dvb/dvb-usb/gp8psk-fe.c
Normal file
272
drivers/media/dvb/dvb-usb/gp8psk-fe.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
/* DVB USB compliant Linux driver for the
|
||||||
|
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||||
|
*
|
||||||
|
* Thanks to GENPIX for the sample code used to implement this module.
|
||||||
|
*
|
||||||
|
* This module is based off the vp7045 and vp702x modules
|
||||||
|
*
|
||||||
|
* 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, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "gp8psk.h"
|
||||||
|
|
||||||
|
struct gp8psk_fe_state {
|
||||||
|
struct dvb_frontend fe;
|
||||||
|
|
||||||
|
struct dvb_usb_device *d;
|
||||||
|
|
||||||
|
u16 snr;
|
||||||
|
|
||||||
|
unsigned long next_snr_check;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||||
|
u8 lock;
|
||||||
|
|
||||||
|
if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (lock)
|
||||||
|
*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||||
|
else
|
||||||
|
*status = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not supported by this Frontend */
|
||||||
|
static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
|
||||||
|
{
|
||||||
|
(void) fe;
|
||||||
|
*ber = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not supported by this Frontend */
|
||||||
|
static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
|
||||||
|
{
|
||||||
|
(void) fe;
|
||||||
|
*unc = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||||
|
u8 buf[2];
|
||||||
|
|
||||||
|
if (time_after(jiffies,st->next_snr_check)) {
|
||||||
|
gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
|
||||||
|
*snr = (int)(buf[1]) << 8 | buf[0];
|
||||||
|
/* snr is reported in dBu*256 */
|
||||||
|
/* snr / 38.4 ~= 100% strength */
|
||||||
|
/* snr * 17 returns 100% strength as 65535 */
|
||||||
|
if (*snr <= 3855)
|
||||||
|
*snr = (*snr<<4) + *snr; // snr * 17
|
||||||
|
else
|
||||||
|
*snr = 65535;
|
||||||
|
st->next_snr_check = jiffies + (10*HZ)/1000;
|
||||||
|
} else {
|
||||||
|
*snr = st->snr;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
|
||||||
|
{
|
||||||
|
return gp8psk_fe_read_snr(fe, strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
|
||||||
|
{
|
||||||
|
tune->min_delay_ms = 800;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
|
||||||
|
struct dvb_frontend_parameters *fep)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state *state = fe->demodulator_priv;
|
||||||
|
u8 cmd[10];
|
||||||
|
u32 freq = fep->frequency * 1000;
|
||||||
|
|
||||||
|
cmd[4] = freq & 0xff;
|
||||||
|
cmd[5] = (freq >> 8) & 0xff;
|
||||||
|
cmd[6] = (freq >> 16) & 0xff;
|
||||||
|
cmd[7] = (freq >> 24) & 0xff;
|
||||||
|
|
||||||
|
switch(fe->ops.info.type) {
|
||||||
|
case FE_QPSK:
|
||||||
|
cmd[0] = fep->u.qpsk.symbol_rate & 0xff;
|
||||||
|
cmd[1] = (fep->u.qpsk.symbol_rate >> 8) & 0xff;
|
||||||
|
cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
|
||||||
|
cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
|
||||||
|
cmd[8] = ADV_MOD_DVB_QPSK;
|
||||||
|
cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// other modes are unsuported right now
|
||||||
|
cmd[0] = 0;
|
||||||
|
cmd[1] = 0;
|
||||||
|
cmd[2] = 0;
|
||||||
|
cmd[3] = 0;
|
||||||
|
cmd[8] = 0;
|
||||||
|
cmd[9] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
|
||||||
|
|
||||||
|
state->next_snr_check = jiffies;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
|
||||||
|
struct dvb_frontend_parameters *fep)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
|
||||||
|
struct dvb_diseqc_master_cmd *m)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||||
|
|
||||||
|
deb_fe("%s\n",__FUNCTION__);
|
||||||
|
|
||||||
|
if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
|
||||||
|
m->msg, m->msg_len)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
|
||||||
|
fe_sec_mini_cmd_t burst)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state *st = fe->demodulator_priv;
|
||||||
|
u8 cmd;
|
||||||
|
|
||||||
|
deb_fe("%s\n",__FUNCTION__);
|
||||||
|
|
||||||
|
/* These commands are certainly wrong */
|
||||||
|
cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
|
||||||
|
|
||||||
|
if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
|
||||||
|
&cmd, 0)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||||
|
|
||||||
|
if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
|
||||||
|
(tone == SEC_TONE_ON), 0, NULL, 0)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||||
|
|
||||||
|
if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
|
||||||
|
voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state* state = fe->demodulator_priv;
|
||||||
|
u8 cmd = sw_cmd & 0x7f;
|
||||||
|
|
||||||
|
if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
|
||||||
|
NULL, 0)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
|
||||||
|
0, NULL, 0)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gp8psk_fe_release(struct dvb_frontend* fe)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state *state = fe->demodulator_priv;
|
||||||
|
kfree(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops gp8psk_fe_ops;
|
||||||
|
|
||||||
|
struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
|
||||||
|
if (s == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
s->d = d;
|
||||||
|
memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
|
||||||
|
s->fe.demodulator_priv = s;
|
||||||
|
|
||||||
|
goto success;
|
||||||
|
error:
|
||||||
|
return NULL;
|
||||||
|
success:
|
||||||
|
return &s->fe;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops gp8psk_fe_ops = {
|
||||||
|
.info = {
|
||||||
|
.name = "Genpix 8psk-USB DVB-S",
|
||||||
|
.type = FE_QPSK,
|
||||||
|
.frequency_min = 950000,
|
||||||
|
.frequency_max = 2150000,
|
||||||
|
.frequency_stepsize = 100,
|
||||||
|
.symbol_rate_min = 1000000,
|
||||||
|
.symbol_rate_max = 45000000,
|
||||||
|
.symbol_rate_tolerance = 500, /* ppm */
|
||||||
|
.caps = FE_CAN_INVERSION_AUTO |
|
||||||
|
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||||
|
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||||
|
FE_CAN_QPSK
|
||||||
|
},
|
||||||
|
|
||||||
|
.release = gp8psk_fe_release,
|
||||||
|
|
||||||
|
.init = NULL,
|
||||||
|
.sleep = NULL,
|
||||||
|
|
||||||
|
.set_frontend = gp8psk_fe_set_frontend,
|
||||||
|
.get_frontend = gp8psk_fe_get_frontend,
|
||||||
|
.get_tune_settings = gp8psk_fe_get_tune_settings,
|
||||||
|
|
||||||
|
.read_status = gp8psk_fe_read_status,
|
||||||
|
.read_ber = gp8psk_fe_read_ber,
|
||||||
|
.read_signal_strength = gp8psk_fe_read_signal_strength,
|
||||||
|
.read_snr = gp8psk_fe_read_snr,
|
||||||
|
.read_ucblocks = gp8psk_fe_read_unc_blocks,
|
||||||
|
|
||||||
|
.diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
|
||||||
|
.diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
|
||||||
|
.set_tone = gp8psk_fe_set_tone,
|
||||||
|
.set_voltage = gp8psk_fe_set_voltage,
|
||||||
|
.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
|
||||||
|
};
|
254
drivers/media/dvb/dvb-usb/gp8psk.c
Normal file
254
drivers/media/dvb/dvb-usb/gp8psk.c
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
/* DVB USB compliant Linux driver for the
|
||||||
|
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||||
|
*
|
||||||
|
* Thanks to GENPIX for the sample code used to implement this module.
|
||||||
|
*
|
||||||
|
* This module is based off the vp7045 and vp702x modules
|
||||||
|
*
|
||||||
|
* 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, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#include "gp8psk.h"
|
||||||
|
|
||||||
|
/* debug */
|
||||||
|
static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
|
||||||
|
int dvb_usb_gp8psk_debug;
|
||||||
|
module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||||
|
|
||||||
|
int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
|
||||||
|
{
|
||||||
|
int ret = 0,try = 0;
|
||||||
|
|
||||||
|
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
while (ret >= 0 && ret != blen && try < 3) {
|
||||||
|
ret = usb_control_msg(d->udev,
|
||||||
|
usb_rcvctrlpipe(d->udev,0),
|
||||||
|
req,
|
||||||
|
USB_TYPE_VENDOR | USB_DIR_IN,
|
||||||
|
value,index,b,blen,
|
||||||
|
2000);
|
||||||
|
deb_info("reading number %d (ret: %d)\n",try,ret);
|
||||||
|
try++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0 || ret != blen) {
|
||||||
|
warn("usb in operation failed.");
|
||||||
|
ret = -EIO;
|
||||||
|
} else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
|
||||||
|
debug_dump(b,blen,deb_xfer);
|
||||||
|
|
||||||
|
mutex_unlock(&d->usb_mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||||
|
u16 index, u8 *b, int blen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
|
||||||
|
debug_dump(b,blen,deb_xfer);
|
||||||
|
|
||||||
|
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (usb_control_msg(d->udev,
|
||||||
|
usb_sndctrlpipe(d->udev,0),
|
||||||
|
req,
|
||||||
|
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||||
|
value,index,b,blen,
|
||||||
|
2000) != blen) {
|
||||||
|
warn("usb out operation failed.");
|
||||||
|
ret = -EIO;
|
||||||
|
} else
|
||||||
|
ret = 0;
|
||||||
|
mutex_unlock(&d->usb_mutex);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const struct firmware *fw = NULL;
|
||||||
|
u8 *ptr, *buf;
|
||||||
|
if ((ret = request_firmware(&fw, bcm4500_firmware,
|
||||||
|
&d->udev->dev)) != 0) {
|
||||||
|
err("did not find the bcm4500 firmware file. (%s) "
|
||||||
|
"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
|
||||||
|
bcm4500_firmware,ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) {
|
||||||
|
release_firmware(fw);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
|
||||||
|
|
||||||
|
ptr = fw->data;
|
||||||
|
buf = (u8 *) kmalloc(512, GFP_KERNEL | GFP_DMA);
|
||||||
|
|
||||||
|
while (ptr[0] != 0xff) {
|
||||||
|
u16 buflen = ptr[0] + 4;
|
||||||
|
if (ptr + buflen >= fw->data + fw->size) {
|
||||||
|
err("failed to load bcm4500 firmware.");
|
||||||
|
release_firmware(fw);
|
||||||
|
kfree(buf);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memcpy(buf, ptr, buflen);
|
||||||
|
if (dvb_usb_generic_write(d, buf, buflen)) {
|
||||||
|
err("failed to load bcm4500 firmware.");
|
||||||
|
release_firmware(fw);
|
||||||
|
kfree(buf);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
ptr += buflen;
|
||||||
|
}
|
||||||
|
release_firmware(fw);
|
||||||
|
kfree(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
u8 status, buf;
|
||||||
|
if (onoff) {
|
||||||
|
gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
|
||||||
|
if (! (status & 0x01)) /* started */
|
||||||
|
if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (! (status & 0x02)) /* BCM4500 firmware loaded */
|
||||||
|
if(gp8psk_load_bcm4500fw(d))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (! (status & 0x04)) /* LNB Power */
|
||||||
|
if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
|
||||||
|
&buf, 1))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
/* Set DVB mode */
|
||||||
|
if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
|
||||||
|
return -EINVAL;
|
||||||
|
gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
|
||||||
|
} else {
|
||||||
|
/* Turn off LNB power */
|
||||||
|
if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
|
||||||
|
return EINVAL;
|
||||||
|
/* Turn off 8psk power */
|
||||||
|
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gp8psk_frontend_attach(struct dvb_usb_device *d)
|
||||||
|
{
|
||||||
|
d->fe = gp8psk_fe_attach(d);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_usb_properties gp8psk_properties;
|
||||||
|
|
||||||
|
static int gp8psk_usb_probe(struct usb_interface *intf,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_device_id gp8psk_usb_table [] = {
|
||||||
|
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
|
||||||
|
{ USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
|
||||||
|
|
||||||
|
static struct dvb_usb_properties gp8psk_properties = {
|
||||||
|
.caps = 0,
|
||||||
|
|
||||||
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
|
.firmware = "dvb-usb-gp8psk-01.fw",
|
||||||
|
|
||||||
|
.streaming_ctrl = gp8psk_streaming_ctrl,
|
||||||
|
.power_ctrl = gp8psk_power_ctrl,
|
||||||
|
.frontend_attach = gp8psk_frontend_attach,
|
||||||
|
|
||||||
|
.generic_bulk_ctrl_endpoint = 0x01,
|
||||||
|
/* parameter for the MPEG2-data transfer */
|
||||||
|
.urb = {
|
||||||
|
.type = DVB_USB_BULK,
|
||||||
|
.count = 7,
|
||||||
|
.endpoint = 0x82,
|
||||||
|
.u = {
|
||||||
|
.bulk = {
|
||||||
|
.buffersize = 8192,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.num_device_descs = 1,
|
||||||
|
.devices = {
|
||||||
|
{ .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
|
||||||
|
.cold_ids = { &gp8psk_usb_table[0], NULL },
|
||||||
|
.warm_ids = { &gp8psk_usb_table[1], NULL },
|
||||||
|
},
|
||||||
|
{ 0 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* usb specific object needed to register this driver with the usb subsystem */
|
||||||
|
static struct usb_driver gp8psk_usb_driver = {
|
||||||
|
.name = "dvb_usb_gp8psk",
|
||||||
|
.probe = gp8psk_usb_probe,
|
||||||
|
.disconnect = dvb_usb_device_exit,
|
||||||
|
.id_table = gp8psk_usb_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* module stuff */
|
||||||
|
static int __init gp8psk_usb_module_init(void)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
if ((result = usb_register(&gp8psk_usb_driver))) {
|
||||||
|
err("usb_register failed. (%d)",result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit gp8psk_usb_module_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver from the USB subsystem */
|
||||||
|
usb_deregister(&gp8psk_usb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(gp8psk_usb_module_init);
|
||||||
|
module_exit(gp8psk_usb_module_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
|
||||||
|
MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
|
||||||
|
MODULE_VERSION("1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
79
drivers/media/dvb/dvb-usb/gp8psk.h
Normal file
79
drivers/media/dvb/dvb-usb/gp8psk.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/* DVB USB compliant Linux driver for the
|
||||||
|
* - GENPIX 8pks/qpsk USB2.0 DVB-S module
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
|
||||||
|
*
|
||||||
|
* Thanks to GENPIX for the sample code used to implement this module.
|
||||||
|
*
|
||||||
|
* This module is based off the vp7045 and vp702x modules
|
||||||
|
*
|
||||||
|
* 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, version 2.
|
||||||
|
*
|
||||||
|
* see Documentation/dvb/README.dvb-usb for more information
|
||||||
|
*/
|
||||||
|
#ifndef _DVB_USB_GP8PSK_H_
|
||||||
|
#define _DVB_USB_GP8PSK_H_
|
||||||
|
|
||||||
|
#define DVB_USB_LOG_PREFIX "gp8psk"
|
||||||
|
#include "dvb-usb.h"
|
||||||
|
|
||||||
|
extern int dvb_usb_gp8psk_debug;
|
||||||
|
#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
|
||||||
|
#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
|
||||||
|
#define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args)
|
||||||
|
#define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args)
|
||||||
|
/* gp8psk commands */
|
||||||
|
|
||||||
|
/* Twinhan Vendor requests */
|
||||||
|
#define TH_COMMAND_IN 0xC0
|
||||||
|
#define TH_COMMAND_OUT 0xC1
|
||||||
|
|
||||||
|
/* command bytes */
|
||||||
|
#define GET_8PSK_CONFIG 0x80
|
||||||
|
#define SET_8PSK_CONFIG 0x81
|
||||||
|
#define ARM_TRANSFER 0x85
|
||||||
|
#define TUNE_8PSK 0x86
|
||||||
|
#define GET_SIGNAL_STRENGTH 0x87
|
||||||
|
#define LOAD_BCM4500 0x88
|
||||||
|
#define BOOT_8PSK 0x89
|
||||||
|
#define START_INTERSIL 0x8A
|
||||||
|
#define SET_LNB_VOLTAGE 0x8B
|
||||||
|
#define SET_22KHZ_TONE 0x8C
|
||||||
|
#define SEND_DISEQC_COMMAND 0x8D
|
||||||
|
#define SET_DVB_MODE 0x8E
|
||||||
|
#define SET_DN_SWITCH 0x8F
|
||||||
|
#define GET_SIGNAL_LOCK 0x90
|
||||||
|
|
||||||
|
/* Satellite modulation modes */
|
||||||
|
#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */
|
||||||
|
#define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */
|
||||||
|
#define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */
|
||||||
|
#define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */
|
||||||
|
|
||||||
|
#define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */
|
||||||
|
#define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */
|
||||||
|
#define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */
|
||||||
|
#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
|
||||||
|
#define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */
|
||||||
|
#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */
|
||||||
|
|
||||||
|
#define GET_USB_SPEED 0x07
|
||||||
|
#define USB_SPEED_LOW 0
|
||||||
|
#define USB_SPEED_FULL 1
|
||||||
|
#define USB_SPEED_HIGH 2
|
||||||
|
|
||||||
|
#define RESET_FX2 0x13
|
||||||
|
|
||||||
|
#define FW_VERSION_READ 0x0B
|
||||||
|
#define VENDOR_STRING_READ 0x0C
|
||||||
|
#define PRODUCT_STRING_READ 0x0D
|
||||||
|
#define FW_BCD_VERSION_READ 0x14
|
||||||
|
|
||||||
|
extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
|
||||||
|
extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
|
||||||
|
extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
|
||||||
|
u16 index, u8 *b, int blen);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user