Commit b68e2749 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://lia64.bkbits.net/to-linus-2.5

into home.osdl.org:/home/torvalds/v2.5/linux
parents 0caf7f85 a662cb8b
How to get the Nebula, PCTV and Twinhan DST cards working
=========================================================
This class of cards has a bt878a as the PCI interface, and
require the bttv driver.
Please pay close attention to the warning about the bttv module
options below for the DST card.
1) General informations
=======================
These drivers require the bttv driver to provide the means to access
the i2c bus and the gpio pins of the bt8xx chipset.
Because of this, you need to enable
"Device drivers" => "Multimedia devices"
=> "Video For Linux" => "BT848 Video For Linux"
2) Loading Modules
==================
In general you need to load the bttv driver, which will handle the gpio and
i2c communication for us. Next you need the common dvb-bt8xx device driver
and one frontend driver.
The bttv driver will HANG YOUR SYSTEM IF YOU DO NOT SPECIFY THE CORRECT
CARD ID!
(If you don't get your card running and you suspect that the card id you're
using is wrong, have a look at "bttv-cards.c" for a list of possible card
ids.)
Pay attention to failures when you load the frontend drivers
(e.g. dmesg, /var/log/messages).
3a) Nebula / Pinnacle PCTV
--------------------------
$ modprobe bttv i2c_hw=1 card=0x68
$ modprobe dvb-bt8xx
For Nebula cards use the "nxt6000" frontend driver:
$ modprobe nxt6000
For Pinnacle PCTV cards use the "cx24110" frontend driver:
$ modprobe cx24110
3b) TwinHan
-----------
$ modprobe bttv i2c_hw=1 card=0x71
$ modprobe dvb-bt8xx
$ modprobe dst
The value 0x71 will override the PCI type detection for dvb-bt8xx, which
is necessary for TwinHan cards.#
If you're having an older card (blue color circuit) and card=0x71 locks your
machine, try using 0x68, too. If that does not work, ask on the DVB mailing list.
The DST module takes a couple of useful parameters, in case the
dst drivers fails to detect your type of card correctly.
dst_type takes values 0 (satellite), 1 (terrestial TV), 2 (cable).
dst_type_flags takes bit combined values:
1 = new tuner type packets. You can use this if your card is detected
and you have debug and you continually see the tuner packets not
working (make sure not a basic problem like dish alignment etc.)
2 = TS 204. If your card tunes OK, but the picture is terrible, seemingly
breaking up in one half continually, and crc fails a lot, then
this is worth a try (or trying to turn off)
4 = has symdiv. Some cards, mostly without new tuner packets, require
a symbol division algorithm. Doesn't apply to terrestial TV.
You can also specify a value to have the autodetected values turned off
(e.g. 0). The autodected values are determined bythe cards 'response
string' which you can see in your logs e.g.
dst_check_ci: recognize DST-MOT
or
dst_check_ci: unable to recognize DSTXCI or STXCI
--
Authors: Richard Walker, Jamie Honan, Michael Hunold
......@@ -30,11 +30,15 @@ Steve Brown <sbrown@cortland.com>
Christoph Martin <martin@uni-mainz.de>
for his LIRC infrared handler
Andreas Oberritter <andreas@oberritter.de>
Andreas Oberritter <obi@linuxtv.org>
Dennis Noermann <dennis.noermann@noernet.de>
Felix Domke <tmbinc@elitedvb.net>
Florian Schirmer <jolt@tuxbox.org>
...and all the other dBox2 people
for many bugfixes in the generic DVB Core and their work on the
dBox2 port of the DVB driver
Ronny Strutz <3des@elitedvb.de>
Wolfram Joost <dbox2@frokaschwei.de>
...and all the other dbox2 people
for many bugfixes in the generic DVB Core, frontend drivers and
their work on the dbox2 port of the DVB driver
Oliver Endriss <o.endriss@gmx.de>
for many bugfixes
......@@ -50,5 +54,9 @@ Roberto Ragusa <r.ragusa@libero.it>
Augusto Cardoso <augusto@carhil.net>
for all the work for the FlexCopII chipset by B2C2,Inc.
Davor Emard <emard@softhome.net>
for his work on the budget drivers, the demux code,
the module unloading problems, ...
(If you think you should be in this list, but you are not, drop a
line to the DVB mailing list)
......@@ -36,4 +36,9 @@ files and where to get them.
contains detailed informations about the
TT DEC2000/DEC3000 USB DVB hardware.
"bt8xx.txt"
contains detailed installation instructions for the
various bt8xx based "budget" DVB cards
(Nebula, Pinnacle PCTV, Twinhan DST)
Good luck and have fun!
......@@ -9,6 +9,7 @@ Supported:
Linux Kernels 2.4 and 2.6
Video Streaming
Audio Streaming
Section Filters
Channel Zapping
Hotplug firmware loader under 2.6 kernels
......@@ -16,14 +17,10 @@ In Progress:
DEC3000-s
To Do:
Section data
Teletext streams
Tuner status information
DVB network interface
Streaming video PC->DEC
Note: Since section data can not be retreived yet, scan apps will not work.
Getting the Firmware
--------------------
Currently, the driver only works with v2.15a of the firmware. The firmwares
......@@ -46,7 +43,7 @@ mv STB_PC_S.bin /etc/dvb/dec3000s.bin
Hotplug Firmware Loading for 2.6 kernels
----------------------------------------
For 2.6 kernels the firmware is loaded at the point that the driver module is
loaded. See linux/Documentation/dvb/FIRMWARE for more information.
loaded. See linux/Documentation/dvb/firmware.txt for more information.
mv STB_PC_T.bin /usr/lib/hotplug/firmware/dec2000t.bin
mv STB_PC_S.bin /usr/lib/hotplug/firmware/dec3000s.bin
mv STB_PC_T.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-2000t-2.15a.fw
mv STB_PC_S.bin /usr/lib/hotplug/firmware/dvb-ttusb-dec-3000s-2.15a.fw
/*
* Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <schirmer@taytron.net>
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
*
* 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
......@@ -525,6 +525,6 @@ static void __exit dvb_bt8xx_exit(void)
module_init(dvb_bt8xx_init);
module_exit(dvb_bt8xx_exit);
MODULE_DESCRIPTION("Bt8xx based DVB adapter driver");
MODULE_AUTHOR("Florian Schirmer <schirmer@taytron.net>");
MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");
/*
* Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <schirmer@taytron.net>
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
* Copyright (C) 1999-2001 Ralph Metzler & Marcus Metzler for convergence integrated media GmbH
* Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
......
......@@ -542,33 +542,38 @@ static struct dvb_demux_feed * dvb_dmx_feed_alloc(struct dvb_demux *demux)
return &demux->feed[i];
}
static int dmx_pid_set (u16 pid, struct dvb_demux_feed *feed)
static int dvb_demux_feed_find(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct list_head *pos, *n, *head=&demux->feed_list;
struct dvb_demux_feed *entry;
if (pid > DMX_MAX_PID)
return -EINVAL;
list_for_each_entry(entry, &feed->demux->feed_list, list_head)
if (entry == feed)
return 1;
if (pid == feed->pid)
return 0;
if (feed->pid <= DMX_MAX_PID) {
list_for_each_safe(pos, n, head) {
if (DMX_FEED_ENTRY(pos)->pid == feed->pid) {
list_del(pos);
break;
}
}
static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
{
if (dvb_demux_feed_find(feed)) {
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
return;
}
list_add(&feed->list_head, head);
feed->pid = pid;
list_add(&feed->list_head, &feed->demux->feed_list);
}
return 0;
static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
{
if (!(dvb_demux_feed_find(feed))) {
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
return;
}
list_del(&feed->list_head);
}
static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
enum dmx_ts_pes pes_type, size_t callback_length,
......@@ -577,7 +582,9 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
{
struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
struct dvb_demux *demux = feed->demux;
int ret;
if (pid > DMX_MAX_PID)
return -EINVAL;
if (down_interruptible (&demux->mutex))
return -ERESTARTSYS;
......@@ -594,26 +601,13 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
return -EINVAL;
}
if ((pes_type != DMX_TS_PES_PCR0) &&
(pes_type != DMX_TS_PES_PCR1) &&
(pes_type != DMX_TS_PES_PCR2) &&
(pes_type != DMX_TS_PES_PCR3)) {
if ((ret = dmx_pid_set(pid, feed))<0) {
up(&demux->mutex);
return ret;
}
} else
feed->pid = pid;
demux->pesfilter[pes_type] = feed;
demux->pids[pes_type] = feed->pid;
} else {
if ((ret = dmx_pid_set(pid, feed))<0) {
up(&demux->mutex);
return ret;
}
demux->pids[pes_type] = pid;
}
dvb_demux_feed_add(feed);
feed->pid = pid;
feed->buffer_size = circular_buffer_size;
feed->descramble = descramble;
feed->timeout = timeout;
......@@ -757,7 +751,6 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
{
struct dvb_demux *demux = (struct dvb_demux *) dmx;
struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
struct list_head *pos, *n, *head=&demux->feed_list;
if (down_interruptible (&demux->mutex))
return -ERESTARTSYS;
......@@ -777,14 +770,9 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
feed->state = DMX_STATE_FREE;
feed->filter->state = DMX_STATE_FREE;
if (feed->pid <= DMX_MAX_PID) {
list_for_each_safe(pos, n, head)
if (DMX_FEED_ENTRY(pos)->pid == feed->pid) {
list_del(pos);
break;
}
dvb_demux_feed_del(feed);
feed->pid = 0xffff;
}
if (feed->ts_type & TS_DECODER)
demux->pesfilter[feed->pes_type] = NULL;
......@@ -836,7 +824,6 @@ static int dmx_section_feed_set(struct dmx_section_feed* feed,
{
struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
struct list_head *pos, *n, *head=&dvbdmx->feed_list;
if (pid>0x1fff)
return -EINVAL;
......@@ -844,16 +831,7 @@ static int dmx_section_feed_set(struct dmx_section_feed* feed,
if (down_interruptible (&dvbdmx->mutex))
return -ERESTARTSYS;
if (dvbdmxfeed->pid <= DMX_MAX_PID) {
list_for_each_safe(pos, n, head) {
if (DMX_FEED_ENTRY(pos)->pid == dvbdmxfeed->pid) {
list_del(pos);
break;
}
}
}
list_add(&dvbdmxfeed->list_head, head);
dvb_demux_feed_add(dvbdmxfeed);
dvbdmxfeed->pid = pid;
dvbdmxfeed->buffer_size=circular_buffer_size;
......@@ -1045,7 +1023,6 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
{
struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
struct dvb_demux *dvbdmx=(struct dvb_demux *) demux;
struct list_head *pos, *n, *head=&dvbdmx->feed_list;
if (down_interruptible (&dvbdmx->mutex))
return -ERESTARTSYS;
......@@ -1062,15 +1039,9 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
#endif
dvbdmxfeed->state=DMX_STATE_FREE;
if (dvbdmxfeed->pid <= DMX_MAX_PID) {
list_for_each_safe(pos, n, head) {
if (DMX_FEED_ENTRY(pos)->pid == dvbdmxfeed->pid) {
list_del(pos);
break;
}
}
dvb_demux_feed_del(dvbdmxfeed);
dvbdmxfeed->pid = 0xffff;
}
up(&dvbdmx->mutex);
return 0;
......
......@@ -4,7 +4,8 @@
* Atmel DVB-C Frontend Driver (at76c651/dat7021)
*
* Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
* & 2002 Andreas Oberritter <andreas@oberritter.de>
* & 2002 Andreas Oberritter <obi@linuxtv.org>
* & 2003 Wolfram Joost <dbox2@frokaschwei.de>
*
* 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
......@@ -524,6 +525,6 @@ module_init(at76c651_init);
module_exit(at76c651_exit);
MODULE_DESCRIPTION("at76c651/dat7021 dvb-c frontend driver");
MODULE_AUTHOR("Andreas Oberritter <andreas@oberritter.de>");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");
......@@ -32,6 +32,7 @@ union dst_gpio_packet {
struct bt878 ;
int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
int
bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
struct bt878 *bt878_find_by_dvb_adap(struct dvb_adapter *adap);
......@@ -44,12 +44,15 @@ MODULE_PARM_DESC(dst_verbose,
MODULE_PARM(dst_debug, "i");
MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)");
unsigned int dst_type = (-1U);
unsigned int dst_type_flags = (-1U);
MODULE_PARM(dst_type, "i");
#define DST_MAX_CARDS 6
unsigned int dst_cur_no = 0;
unsigned int dst_type[DST_MAX_CARDS] = { [0 ... (DST_MAX_CARDS-1)] = (-1U)};
unsigned int dst_type_flags[DST_MAX_CARDS] = { [0 ... (DST_MAX_CARDS-1)] = (-1U)};
MODULE_PARM(dst_type, "1-" __stringify(DST_MAX_CARDS) "i");
MODULE_PARM_DESC(dst_type,
"Type of DST card, 0 Satellite, 1 terrestial TV, 2 Cable, default driver determined");
MODULE_PARM(dst_type_flags, "i");
MODULE_PARM(dst_type_flags, "1-" __stringify(DST_MAX_CARDS) "i");
MODULE_PARM_DESC(dst_type_flags,
"Type flags of DST card, bitfield 1=10 byte tuner, 2=TS is 204, 4=symdiv");
......@@ -102,8 +105,7 @@ static struct dvb_frontend_info dst_info_sat = {
.symbol_rate_max = 45000000,
/* . symbol_rate_tolerance = ???,*/
.notifier_delay = 50, /* 1/20 s */
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_AUTO |
.caps = FE_CAN_FEC_AUTO |
FE_CAN_QPSK
};
......@@ -117,8 +119,7 @@ static struct dvb_frontend_info dst_info_cable = {
.symbol_rate_max = 45000000,
/* . symbol_rate_tolerance = ???,*/
.notifier_delay = 50, /* 1/20 s */
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_AUTO |
.caps = FE_CAN_FEC_AUTO |
FE_CAN_QAM_AUTO
};
......@@ -128,8 +129,7 @@ static struct dvb_frontend_info dst_info_tv = {
.frequency_min = 137000000,
.frequency_max = 858000000,
.frequency_stepsize = 166667,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_AUTO |
.caps = FE_CAN_FEC_AUTO |
FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
};
......@@ -421,8 +421,6 @@ static int dst_set_inversion (struct dst_data *dst, fe_spectral_inversion_t inve
case INVERSION_ON:
val[8] |= 0x80;
break;
case INVERSION_AUTO:
break;
default:
return -EINVAL;
}
......@@ -607,25 +605,25 @@ static int dst_check_ci (struct dst_data *dst)
use_dst_type = DST_TYPE_IS_SAT;
use_type_flags = DST_TYPE_HAS_SYMDIV;
}
switch (dst_type) {
switch (dst_type[dst_cur_no]) {
case (-1U):
/* not used */
break;
case DST_TYPE_IS_SAT:
case DST_TYPE_IS_TERR:
case DST_TYPE_IS_CABLE:
use_dst_type = (u8)dst_type;
use_dst_type = (u8)(dst_type[dst_cur_no]);
break;
default:
printk("%s: invalid user override dst type %d, not used\n",
__FUNCTION__, dst_type);
__FUNCTION__, dst_type[dst_cur_no]);
break;
}
dst_type_print(use_dst_type);
if (dst_type_flags != (-1U)) {
if (dst_type_flags[dst_cur_no] != (-1U)) {
printk("%s: user override dst type flags 0x%x\n",
__FUNCTION__, dst_type_flags);
use_type_flags = dst_type_flags;
__FUNCTION__, dst_type_flags[dst_cur_no]);
use_type_flags = dst_type_flags[dst_cur_no];
}
dst->type_flags = use_type_flags;
dst->dst_type= use_dst_type;
......@@ -1129,6 +1127,10 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
struct dvb_frontend_info *info;
dprintk("%s: check ci\n", __FUNCTION__);
if (dst_cur_no >= DST_MAX_CARDS) {
dprintk("%s: can't have more than %d cards\n", __FUNCTION__, DST_MAX_CARDS);
return -ENODEV;
}
bt = bt878_find_by_dvb_adap(i2c->adapter);
if (!bt)
return -ENODEV;
......@@ -1157,7 +1159,7 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
info = &dst_info_cable;
dvb_register_frontend (dst_ioctl, i2c, dst, info);
dst_cur_no++;
return 0;
}
......
/*
Driver for Zarlink MT312 Satellite Channel Decoder
Copyright (C) 2003 Andreas Oberritter <obi@saftware.de>
Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
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
......@@ -813,5 +813,5 @@ MODULE_PARM_DESC(debug, "enable verbose debug messages");
#endif
MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver");
MODULE_AUTHOR("Andreas Oberritter <obi@saftware.de>");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
MODULE_LICENSE("GPL");
/*
Driver for Zarlink MT312 QPSK Frontend
Copyright (C) 2003 Andreas Oberritter <obi@saftware.de>
Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
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
......
......@@ -8,7 +8,7 @@
Alps TDED4 (Tuner: TI ALP510, external Nxt6000)
Comtech DVBT-6k07 (PLL IC: SP5730)
Copyright (C) 2002-2003 Florian Schirmer <schirmer@taytron.net>
Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
This program is free software; you can redistribute it and/or modify
......
......@@ -18,7 +18,7 @@
LG TDQF-S001F
Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
& Andreas Oberritter <andreas@oberritter.de>
& Andreas Oberritter <obi@linuxtv.org>
Support for Samsung TBMU24112IMB used on Technisat SkyStar2 rev. 2.6B
......
......@@ -233,7 +233,7 @@ static int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0,
* check lock and toggle inversion bit if required...
*/
if (INVERSION_AUTO == inversion && !(ves1820_readreg (fe, 0x11) & 0x08)) {
mdelay(30);
mdelay(50);
if (!(ves1820_readreg (fe, 0x11) & 0x08)) {
reg0 ^= 0x20;
ves1820_writereg (fe, 0x00, reg0 & 0xfe);
......@@ -349,7 +349,7 @@ static int ves1820_set_parameters (struct dvb_frontend *fe,
/* yes, this speeds things up: userspace reports lock in about 8 ms
instead of 500 to 1200 ms after calling FE_SET_FRONTEND. */
mdelay(30);
mdelay(50);
return 0;
}
......
......@@ -2,9 +2,9 @@
Driver for VES1893 and VES1993 QPSK Frontends
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
Copyright (C) 2001 Ronny Strutz <3des@tuxbox.org>
Copyright (C) 2001 Ronny Strutz <3des@elitedvb.de>
Copyright (C) 2002 Dennis Noermann <dennis.noermann@noernet.de>
Copyright (C) 2002-2003 Andreas Oberritter <obi@tuxbox.org>
Copyright (C) 2002-2003 Andreas Oberritter <obi@linuxtv.org>
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
......
......@@ -13,6 +13,23 @@ config DVB_AV7110
Say Y if you own such a card and want to use it.
config DVB_AV7110_FIRMWARE
bool "Compile AV7110 firmware into the driver"
depends on DVB_AV7110
help
The AV7110 firmware is normally loaded by the firmware hotplug manager.
If you want to compile the firmware into the driver you need to say
Y here and provide the correct path of the firmware. You need this
option if you want to compile the whole driver statically into the
kernel.
All other people say N.
config DVB_AV7110_FIRMWARE_FILE
string "Full pathname of av7110 firmware file"
depends on DVB_AV7110_FIRMWARE
default "/usr/lib/hotplug/firmware/dvb-ttpci-01.fw"
config DVB_AV7110_OSD
bool "AV7110 OSD support"
depends on DVB_AV7110
......
......@@ -12,3 +12,12 @@ obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o
obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
host-progs := fdump
ifdef CONFIG_DVB_AV7110_FIRMWARE
$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
$(obj)/av7110_firm.h:
$(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@
endif
......@@ -4498,9 +4498,19 @@ static u8 saa7113_init_regs[] = {
static struct saa7146_ext_vv av7110_vv_data_st;
static struct saa7146_ext_vv av7110_vv_data_c;
#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
#include "av7110_firm.h"
#endif
static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext)
{
#ifndef CONFIG_DVB_AV7110_FIRMWARE_FILE
const struct firmware *fw;
#endif
struct av7110 *av7110 = NULL;
int ret = 0;
u32 crc = 0, len = 0;
......@@ -4508,6 +4518,7 @@ static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
DEB_EE(("dev: %p, av7110: %p\n",dev,av7110));
#ifndef CONFIG_DVB_AV7110_FIRMWARE_FILE
/* request the av7110 firmware, this will block until someone uploads it */
ret = request_firmware(&fw, "dvb-ttpci-01.fw", &dev->pci->dev);
if ( 0 != ret ) {
......@@ -4519,6 +4530,7 @@ static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
printk("dvb-ttpci: this firmware is way too small.\n");
return -EINVAL;
}
#endif
/* prepare the av7110 device struct */
if (!(av7110 = kmalloc (sizeof (struct av7110), GFP_KERNEL))) {
......@@ -4527,6 +4539,7 @@ static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
}
memset(av7110, 0, sizeof(struct av7110));
#ifndef CONFIG_DVB_AV7110_FIRMWARE_FILE
/* check if the firmware is available */
av7110->bin_fw = (unsigned char*)vmalloc(fw->size);
if (NULL == av7110->bin_fw) {
......@@ -4536,6 +4549,10 @@ static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
}
memcpy(av7110->bin_fw, fw->data, fw->size);
av7110->size_fw = fw->size;
#else
av7110->bin_fw = dvb_ttpci_fw;
av7110->size_fw = sizeof dvb_ttpci_fw;
#endif
/* check for firmware magic */
ptr = av7110->bin_fw;
......@@ -4850,7 +4867,9 @@ static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
return ret;
fw_error:
#ifndef CONFIG_DVB_AV7110_FIRMWARE_FILE
vfree(av7110->bin_fw);
#endif
kfree(av7110);
return -EINVAL;
}
......@@ -4894,9 +4913,11 @@ static int av7110_detach (struct saa7146_dev* saa)
dvb_unregister_adapter (av7110->dvb_adapter);
av7110_num--;
#ifndef CONFIG_DVB_AV7110_FIRMWARE_FILE
if (NULL != av7110->bin_fw ) {
vfree(av7110->bin_fw);
}
#endif
kfree (av7110);
saa->ext_priv = NULL;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv)
{
unsigned char buf[8];
unsigned int i, count, bytes = 0;
FILE *fd_in, *fd_out;
if (argc != 4) {
fprintf(stderr, "\n\tusage: %s <ucode.bin> <array_name> <output_name>\n\n", argv[0]);
return -1;
}
fd_in = fopen(argv[1], "rb");
if (fd_in == NULL) {
fprintf(stderr, "firmware file '%s' not found\n", argv[1]);
return -1;
}
fd_out = fopen(argv[3], "w+");
if (fd_out == NULL) {
fprintf(stderr, "cannot create output file '%s'\n", argv[3]);
return -1;
}
fprintf(fd_out, "\n#include <asm/types.h>\n\nu8 %s [] = {", argv[2]);
while ((count = fread(buf, 1, 8, fd_in)) > 0) {
fprintf(fd_out, "\n\t");
for (i = 0; i < count; i++, bytes++)
fprintf(fd_out, "0x%02x, ", buf[i]);
}
fprintf(fd_out, "\n};\n\n");
fclose(fd_in);
fclose(fd_out);
return 0;
}
......@@ -2,7 +2,7 @@
* TTUSB DVB driver
*
* Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
* Copyright (c) 2003 Felix Domke <tmbinc@gmx.net>
* Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......
......@@ -13,15 +13,6 @@ config DVB_TTUSB_DEC
The DEC devices require firmware in order to boot into a mode in
which they are slaves to the PC. See
linux/Documentation/dvb/FIRMWARE for details.
The firmware can be obtained and put into the default
locations as follows:
wget http://hauppauge.lightpath.net/de/dec215a.exe
unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_T.bin
mv STB_PC_T.bin /usr/lib/hotplug/firmware/dec2000t.bin
unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_S.bin
mv STB_PC_S.bin /usr/lib/hotplug/firmware/dec3000s.bin
linux/Documentation/dvb/ttusb-dec.txt for details.
Say Y if you own such a device and want to use it.
/*
* TTUSB DEC-2000-t Frontend
*
* Copyright (C) 2003 Alex Woods <linux-dvb@giblets.org>
*
* 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/module.h>
#include "dvb_frontend.h"
#include "dvb_functions.h"
static int debug = 0;
#define dprintk if (debug) printk
static struct dvb_frontend_info dec2000_frontend_info = {
.name = "TechnoTrend/Hauppauge DEC-2000-t Frontend",
.type = FE_OFDM,
.frequency_min = 51000000,
.frequency_max = 858000000,
.frequency_stepsize = 62500,
.caps = 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_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO,
};
static int dec2000_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
void *arg)
{
dprintk("%s\n", __FUNCTION__);
switch (cmd) {
case FE_GET_INFO:
dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
memcpy(arg, &dec2000_frontend_info,
sizeof (struct dvb_frontend_info));
break;
case FE_READ_STATUS: {
fe_status_t *status = (fe_status_t *)arg;
dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);
*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
break;
}
case FE_READ_BER: {
u32 *ber = (u32 *)arg;
dprintk("%s: FE_READ_BER\n", __FUNCTION__);
*ber = 0;
return -ENOSYS;
break;
}
case FE_READ_SIGNAL_STRENGTH: {
dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);
*(s32 *)arg = 0xFF;
return -ENOSYS;
break;
}
case FE_READ_SNR:
dprintk("%s: FE_READ_SNR\n", __FUNCTION__);
*(s32 *)arg = 0;
return -ENOSYS;
break;
case FE_READ_UNCORRECTED_BLOCKS:
dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);
*(u32 *)arg = 0;
return -ENOSYS;
break;
case FE_SET_FRONTEND:{
struct dvb_frontend_parameters *p =
(struct dvb_frontend_parameters *)arg;
u8 b[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0xff };
u32 freq;
struct i2c_msg msg = { addr: 0x71, flags: 0, len:20 };
dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
dprintk(" frequency->%d\n", p->frequency);
dprintk(" symbol_rate->%d\n",
p->u.qam.symbol_rate);
dprintk(" inversion->%d\n", p->inversion);
freq = htonl(p->frequency / 1000);
memcpy(&b[4], &freq, sizeof (int));
msg.buf = b;
fe->i2c->xfer(fe->i2c, &msg, 1);
break;
}
case FE_GET_FRONTEND:
dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);
break;
case FE_SLEEP:
dprintk("%s: FE_SLEEP\n", __FUNCTION__);
return -ENOSYS;
break;
case FE_INIT:
dprintk("%s: FE_INIT\n", __FUNCTION__);
break;
case FE_RESET:
dprintk("%s: FE_RESET\n", __FUNCTION__);
break;
default:
dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
return -EINVAL;
}
return 0;
}
static int dec2000_frontend_attach(struct dvb_i2c_bus *i2c, void **data)
{
dprintk("%s\n", __FUNCTION__);
return dvb_register_frontend(dec2000_frontend_ioctl, i2c, NULL,
&dec2000_frontend_info);
}
static void dec2000_frontend_detach(struct dvb_i2c_bus *i2c, void *data)
{
dprintk("%s\n", __FUNCTION__);
dvb_unregister_frontend(dec2000_frontend_ioctl, i2c);
}
static int __init dec2000_frontend_init(void)
{
return dvb_register_i2c_device(THIS_MODULE, dec2000_frontend_attach,
dec2000_frontend_detach);
}
static void __exit dec2000_frontend_exit(void)
{
dvb_unregister_i2c_device(dec2000_frontend_attach);
}
module_init(dec2000_frontend_init);
module_exit(dec2000_frontend_exit);
MODULE_DESCRIPTION("TechnoTrend/Hauppauge DEC-2000-t Frontend");
MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org");
MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug level");
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main (int argc, char **argv)
{
unsigned char buf[8];
unsigned int i, count, bytes = 0;
int fd;
if (argc != 3) {
fprintf (stderr, "\n\tusage: %s <ucode.bin> <array_name>\n\n",
argv[0]);
return -1;
}
fd = open (argv[1], O_RDONLY);
printf ("\n#include <asm/types.h>\n\nu8 %s [] __initdata = {",
argv[2]);
while ((count = read (fd, buf, 8)) > 0) {
printf ("\n\t");
for (i=0;i<count;i++, bytes++)
printf ("0x%02x, ", buf[i]);
}
printf ("\n};\n\n");
close (fd);
return 0;
}
......@@ -60,13 +60,18 @@ static int debug = 0;
#define LOF_HI 10600000
#define LOF_LO 9750000
enum ttusb_model {
enum ttusb_dec_model {
TTUSB_DEC2000T,
TTUSB_DEC3000S
};
enum ttusb_dec_packet_type {
PACKET_AV_PES,
PACKET_SECTION
};
struct ttusb_dec {
enum ttusb_model model;
enum ttusb_dec_model model;
char *model_name;
char *firmware_name;
......@@ -98,10 +103,14 @@ struct ttusb_dec {
int iso_stream_count;
struct semaphore iso_sem;
u8 av_pes[MAX_AV_PES_LENGTH + 4];
int av_pes_state;
int av_pes_length;
int av_pes_payload_length;
u8 packet[MAX_AV_PES_LENGTH + 4];
enum ttusb_dec_packet_type packet_type;
int packet_state;
int packet_length;
int packet_payload_length;
int av_pes_stream_count;
int filter_stream_count;
struct dvb_filter_pes2ts a_pes2ts;
struct dvb_filter_pes2ts v_pes2ts;
......@@ -114,6 +123,9 @@ struct ttusb_dec {
struct tasklet_struct urb_tasklet;
spinlock_t urb_frame_list_lock;
struct list_head filter_info_list;
spinlock_t filter_info_list_lock;
int active; /* Loaded successfully */
};
......@@ -123,6 +135,12 @@ struct urb_frame {
struct list_head urb_frame_list;
};
struct filter_info {
u8 stream_id;
struct dvb_demux_filter *filter;
struct list_head filter_info_list;
};
static struct dvb_frontend_info dec2000t_frontend_info = {
.name = "TechnoTrend/Hauppauge DEC2000-t Frontend",
.type = FE_OFDM,
......@@ -179,8 +197,8 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
printk("\n");
}
result = usb_bulk_msg(dec->udev, dec->command_pipe, b, sizeof(b),
&actual_len, HZ);
result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
sizeof(b), &actual_len, HZ);
if (result) {
printk("%s: command bulk message failed: error %d\n",
......@@ -189,8 +207,8 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
return result;
}
result = usb_bulk_msg(dec->udev, dec->result_pipe, c, sizeof(c),
&actual_len, HZ);
result = usb_bulk_msg(dec->udev, dec->result_pipe, c,
sizeof(c), &actual_len, HZ);
if (result) {
printk("%s: result bulk message failed: error %d\n",
......@@ -227,8 +245,9 @@ static int ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data)
static void ttusb_dec_set_pids(struct ttusb_dec *dec)
{
u8 b[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff };
u8 b[] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff };
u16 pcr = htons(dec->pid[DMX_PES_PCR]);
u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
......@@ -253,34 +272,13 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
int length)
{
int i;
u16 csum = 0;
u8 c;
if (length < 16) {
printk("%s: packet too short.\n", __FUNCTION__);
if (length < 8) {
printk("%s: packet too short - discarding\n", __FUNCTION__);
return;
}
for (i = 0; i < length; i += 2) {
csum ^= le16_to_cpup((u16 *)(av_pes + i));
c = av_pes[i];
av_pes[i] = av_pes[i + 1];
av_pes[i + 1] = c;
}
if (csum) {
printk("%s: checksum failed.\n", __FUNCTION__);
return;
}
if (length > 8 + MAX_AV_PES_LENGTH + 4) {
printk("%s: packet too long.\n", __FUNCTION__);
return;
}
if (!(av_pes[0] == 'A' && av_pes[1] == 'V')) {
printk("%s: invalid AV_PES packet.\n", __FUNCTION__);
if (length > 8 + MAX_AV_PES_LENGTH) {
printk("%s: packet too long - discarding\n", __FUNCTION__);
return;
}
......@@ -297,16 +295,14 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
&av_pes[12], prebytes);
dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
dec->v_pes_length + prebytes,
1);
dec->v_pes_length + prebytes, 1);
}
if (av_pes[5] & 0x10) {
dec->v_pes[7] = 0x80;
dec->v_pes[8] = 0x05;
dec->v_pes[9] = 0x21 |
((av_pes[8] & 0xc0) >> 5);
dec->v_pes[9] = 0x21 | ((av_pes[8] & 0xc0) >> 5);
dec->v_pes[10] = ((av_pes[8] & 0x3f) << 2) |
((av_pes[9] & 0xc0) >> 6);
dec->v_pes[11] = 0x01 |
......@@ -314,18 +310,17 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
((av_pes[10] & 0x80) >> 6);
dec->v_pes[12] = ((av_pes[10] & 0x7f) << 1) |
((av_pes[11] & 0xc0) >> 7);
dec->v_pes[13] = 0x01 |
((av_pes[11] & 0x7f) << 1);
dec->v_pes[13] = 0x01 | ((av_pes[11] & 0x7f) << 1);
memcpy(&dec->v_pes[14], &av_pes[12 + prebytes],
length - 16 - prebytes);
dec->v_pes_length = 14 + length - 16 - prebytes;
length - 12 - prebytes);
dec->v_pes_length = 14 + length - 12 - prebytes;
} else {
dec->v_pes[7] = 0x00;
dec->v_pes[8] = 0x00;
memcpy(&dec->v_pes[9], &av_pes[8], length - 12);
dec->v_pes_length = 9 + length - 12;
memcpy(&dec->v_pes[9], &av_pes[8], length - 8);
dec->v_pes_length = 9 + length - 8;
}
dec->v_pes_postbytes = postbytes;
......@@ -349,7 +344,7 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
}
case 0x02: /* MainAudioStream */
dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 12,
dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 8,
av_pes[5] & 0x10);
break;
......@@ -357,93 +352,194 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
printk("%s: unknown AV_PES type: %02x.\n", __FUNCTION__,
av_pes[2]);
break;
}
}
static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet,
int length)
{
struct list_head *item;
struct filter_info *finfo;
struct dvb_demux_filter *filter = NULL;
unsigned long flags;
u8 sid;
sid = packet[1];
spin_lock_irqsave(&dec->filter_info_list_lock, flags);
for (item = dec->filter_info_list.next; item != &dec->filter_info_list;
item = item->next) {
finfo = list_entry(item, struct filter_info, filter_info_list);
if (finfo->stream_id == sid) {
filter = finfo->filter;
break;
}
}
spin_unlock_irqrestore(&dec->filter_info_list_lock, flags);
if (filter)
filter->feed->cb.sec(&packet[2], length - 2, NULL, 0,
&filter->filter, DMX_OK);
}
static void ttusb_dec_process_packet(struct ttusb_dec *dec)
{
int i;
u16 csum = 0;
if (dec->packet_length % 2) {
printk("%s: odd sized packet - discarding\n", __FUNCTION__);
return;
}
for (i = 0; i < dec->packet_length; i += 2)
csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
if (csum) {
printk("%s: checksum failed - discarding\n", __FUNCTION__);
return;
}
switch (dec->packet_type) {
case PACKET_AV_PES:
if (dec->av_pes_stream_count)
ttusb_dec_process_av_pes(dec, dec->packet,
dec->packet_payload_length);
break;
case PACKET_SECTION:
if (dec->filter_stream_count)
ttusb_dec_process_filter(dec, dec->packet,
dec->packet_payload_length);
break;
}
}
static void swap_bytes(u8 *b, int length)
{
u8 c;
length -= length % 2;
for (; length; b += 2, length -= 2) {
c = *b;
*b = *(b + 1);
*(b + 1) = c;
}
}
static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b,
int length)
{
swap_bytes(b, length);
while (length) {
switch (dec->av_pes_state) {
switch (dec->packet_state) {
case 0:
case 1:
case 2:
if (*b++ == 0xaa)
dec->packet_state++;
else
dec->packet_state = 0;
length--;
break;
case 3:
if (*b++ == 0xaa) {
dec->av_pes_state++;
if (dec->av_pes_state == 4)
dec->av_pes_length = 0;
if (*b++ == 0x00) {
dec->packet_state++;
dec->packet_length = 0;
} else {
dec->av_pes_state = 0;
dec->packet_state = 0;
}
length--;
break;
case 2:
if (*b++ == 0x00) {
dec->av_pes_state++;
case 4:
dec->packet[dec->packet_length++] = *b++;
if (dec->packet_length == 3) {
if (dec->packet[0] == 'A' &&
dec->packet[1] == 'V') {
dec->packet_type = PACKET_AV_PES;
dec->packet_state++;
} else if (dec->packet[0] == 'S') {
dec->packet_type = PACKET_SECTION;
dec->packet_state++;
} else {
dec->av_pes_state = 0;
dec->packet_state = 0;
}
}
length--;
break;
case 4:
dec->av_pes[dec->av_pes_length++] = *b++;
case 5:
dec->packet[dec->packet_length++] = *b++;
if (dec->av_pes_length == 8) {
dec->av_pes_state++;
dec->av_pes_payload_length = le16_to_cpup(
(u16 *)(dec->av_pes + 6));
if (dec->packet_type == PACKET_AV_PES &&
dec->packet_length == 8) {
dec->packet_state++;
dec->packet_payload_length = 8 +
(dec->packet[6] << 8) +
dec->packet[7];
} else if (dec->packet_type == PACKET_SECTION &&
dec->packet_length == 5) {
dec->packet_state++;
dec->packet_payload_length = 5 +
((dec->packet[3] & 0x0f) << 8) +
dec->packet[4];
}
length--;
break;
case 5: {
int remainder = dec->av_pes_payload_length +
8 - dec->av_pes_length;
case 6: {
int remainder = dec->packet_payload_length -
dec->packet_length;
if (length >= remainder) {
memcpy(dec->av_pes + dec->av_pes_length,
memcpy(dec->packet + dec->packet_length,
b, remainder);
dec->av_pes_length += remainder;
dec->packet_length += remainder;
b += remainder;
length -= remainder;
dec->av_pes_state++;
dec->packet_state++;
} else {
memcpy(&dec->av_pes[dec->av_pes_length],
memcpy(&dec->packet[dec->packet_length],
b, length);
dec->av_pes_length += length;
dec->packet_length += length;
length = 0;
}
break;
}
case 6:
dec->av_pes[dec->av_pes_length++] = *b++;
case 7: {
int tail = 4;
dec->packet[dec->packet_length++] = *b++;
if (dec->packet_type == PACKET_SECTION &&
dec->packet_payload_length % 2)
tail++;
if (dec->av_pes_length ==
8 + dec->av_pes_payload_length + 4) {
ttusb_dec_process_av_pes(dec, dec->av_pes,
dec->av_pes_length);
dec->av_pes_state = 0;
if (dec->packet_length ==
dec->packet_payload_length + tail) {
ttusb_dec_process_packet(dec);
dec->packet_state = 0;
}
length--;
break;
}
default:
printk("%s: illegal packet state encountered.\n",
__FUNCTION__);
dec->av_pes_state = 0;
dec->packet_state = 0;
}
}
}
......@@ -561,12 +657,8 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
dec->iso_stream_count--;
if (!dec->iso_stream_count) {
u8 b0[] = { 0x00 };
for (i = 0; i < ISO_BUF_COUNT; i++)
usb_unlink_urb(dec->iso_urb[i]);
ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL);
}
up(&dec->iso_sem);
......@@ -594,10 +686,6 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
return -EAGAIN;
if (!dec->iso_stream_count) {
u8 b0[] = { 0x05 };
ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
ttusb_dec_setup_urbs(dec);
for (i = 0; i < ISO_BUF_COUNT; i++) {
......@@ -616,7 +704,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
}
}
dec->av_pes_state = 0;
dec->packet_state = 0;
dec->v_pes_postbytes = 0;
}
......@@ -627,34 +715,14 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
return 0;
}
static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct ttusb_dec *dec = dvbdmx->priv;
u8 b0[] = { 0x05 };
dprintk("%s\n", __FUNCTION__);
if (!dvbdmx->dmx.frontend)
return -EINVAL;
dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid);
switch (dvbdmxfeed->type) {
case DMX_TYPE_TS:
dprintk(" type: DMX_TYPE_TS\n");
break;
case DMX_TYPE_SEC:
dprintk(" type: DMX_TYPE_SEC\n");
break;
default:
dprintk(" type: unknown (%d)\n", dvbdmxfeed->type);
return -EINVAL;
}
dprintk(" ts_type:");
if (dvbdmxfeed->ts_type & TS_DECODER)
......@@ -704,22 +772,151 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
}
ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
dec->av_pes_stream_count++;
ttusb_dec_start_iso_xfer(dec);
return 0;
}
static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
u8 b0[] = { 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00 };
u16 pid;
u8 c[COMMAND_PACKET_SIZE];
int c_length;
int result;
struct filter_info *finfo;
unsigned long flags;
u8 x = 1;
dprintk("%s\n", __FUNCTION__);
pid = htons(dvbdmxfeed->pid);
memcpy(&b0[0], &pid, 2);
memcpy(&b0[4], &x, 1);
memcpy(&b0[5], &dvbdmxfeed->filter->filter.filter_value[0], 1);
result = ttusb_dec_send_command(dec, 0x60, sizeof(b0), b0,
&c_length, c);
if (!result) {
if (c_length == 2) {
if (!(finfo = kmalloc(sizeof(struct filter_info),
GFP_ATOMIC)))
return -ENOMEM;
finfo->stream_id = c[1];
finfo->filter = dvbdmxfeed->filter;
spin_lock_irqsave(&dec->filter_info_list_lock, flags);
list_add_tail(&finfo->filter_info_list,
&dec->filter_info_list);
spin_unlock_irqrestore(&dec->filter_info_list_lock,
flags);
dvbdmxfeed->priv = finfo;
dec->filter_stream_count++;
ttusb_dec_start_iso_xfer(dec);
return 0;
}
return -EAGAIN;
} else
return result;
}
static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
dprintk("%s\n", __FUNCTION__);
if (!dvbdmx->dmx.frontend)
return -EINVAL;
dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid);
switch (dvbdmxfeed->type) {
case DMX_TYPE_TS:
return ttusb_dec_start_ts_feed(dvbdmxfeed);
break;
case DMX_TYPE_SEC:
return ttusb_dec_start_sec_feed(dvbdmxfeed);
break;
default:
dprintk(" type: unknown (%d)\n", dvbdmxfeed->type);
return -EINVAL;
}
}
static int ttusb_dec_stop_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
u8 b0[] = { 0x00 };
ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL);
dec->av_pes_stream_count--;
ttusb_dec_stop_iso_xfer(dec);
return 0;
}
static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
u8 b0[] = { 0x00, 0x00 };
struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv;
unsigned long flags;
b0[1] = finfo->stream_id;
spin_lock_irqsave(&dec->filter_info_list_lock, flags);
list_del(&finfo->filter_info_list);
spin_unlock_irqrestore(&dec->filter_info_list_lock, flags);
kfree(finfo);
ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL);
dec->filter_stream_count--;
ttusb_dec_stop_iso_xfer(dec);
return 0;
}
static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
dprintk("%s\n", __FUNCTION__);
switch (dvbdmxfeed->type) {
case DMX_TYPE_TS:
return ttusb_dec_stop_ts_feed(dvbdmxfeed);
break;
case DMX_TYPE_SEC:
return ttusb_dec_stop_sec_feed(dvbdmxfeed);
break;
}
return 0;
}
static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
{
int i;
......@@ -802,8 +999,9 @@ static void ttusb_dec_init_usb(struct ttusb_dec *dec)
static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
{
int i, j, actual_len, result, size, trans_count;
u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00 };
u8 b0[] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
u8 b1[] = { 0x61 };
u8 b[ARM_PACKET_SIZE];
u8 *firmware = NULL;
......@@ -1067,9 +1265,11 @@ static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int
case FE_SET_FRONTEND: {
struct dvb_frontend_parameters *p =
(struct dvb_frontend_parameters *)arg;
u8 b[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0xff, 0x00, 0x00, 0x00, 0xff };
u8 b[] = { 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff };
u32 freq;
dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
......@@ -1112,8 +1312,8 @@ static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int
return 0;
}
static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
void *arg)
static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe,
unsigned int cmd, void *arg)
{
struct ttusb_dec *dec = fe->data;
......@@ -1165,12 +1365,16 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int
case FE_SET_FRONTEND: {
struct dvb_frontend_parameters *p =
(struct dvb_frontend_parameters *)arg;
u8 b[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00 };
u8 b[] = { 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0d,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
u32 freq;
u32 sym_rate;
u32 band;
......@@ -1183,7 +1387,8 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int
p->u.qam.symbol_rate);
dprintk(" inversion->%d\n", p->inversion);
freq = htonl(p->frequency * 1000 + (dec->hi_band ? LOF_HI : LOF_LO));
freq = htonl(p->frequency * 1000 +
(dec->hi_band ? LOF_HI : LOF_LO));
memcpy(&b[4], &freq, sizeof(u32));
sym_rate = htonl(p->u.qam.symbol_rate);
memcpy(&b[12], &sym_rate, sizeof(u32));
......@@ -1265,6 +1470,24 @@ static void ttusb_dec_exit_frontend(struct ttusb_dec *dec)
dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus);
}
static void ttusb_dec_init_filters(struct ttusb_dec *dec)
{
INIT_LIST_HEAD(&dec->filter_info_list);
dec->filter_info_list_lock = SPIN_LOCK_UNLOCKED;
}
static void ttusb_dec_exit_filters(struct ttusb_dec *dec)
{
struct list_head *item;
struct filter_info *finfo;
while ((item = dec->filter_info_list.next) != &dec->filter_info_list) {
finfo = list_entry(item, struct filter_info, filter_info_list);
list_del(&finfo->filter_info_list);
kfree(finfo);
}
}
static int ttusb_dec_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
......@@ -1288,13 +1511,13 @@ static int ttusb_dec_probe(struct usb_interface *intf,
case 0x1006:
dec->model = TTUSB_DEC3000S;
dec->model_name = "DEC3000-s";
dec->firmware_name = "dec3000s.bin";
dec->firmware_name = "dvb-ttusb-dec-3000s-2.15a.fw";
break;
case 0x1008:
dec->model = TTUSB_DEC2000T;
dec->model_name = "DEC2000-t";
dec->firmware_name = "dec2000t.bin";
dec->firmware_name = "dvb-ttusb-dec-2000t-2.15a.fw";
break;
}
......@@ -1308,6 +1531,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_init_dvb(dec);
ttusb_dec_init_frontend(dec);
ttusb_dec_init_v_pes(dec);
ttusb_dec_init_filters(dec);
ttusb_dec_init_tasklet(dec);
dec->active = 1;
......@@ -1327,6 +1551,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
if (dec->active) {
ttusb_dec_exit_tasklet(dec);
ttusb_dec_exit_filters(dec);
ttusb_dec_exit_usb(dec);
ttusb_dec_exit_frontend(dec);
ttusb_dec_exit_dvb(dec);
......
/*
* TTUSB DEC Driver
*
* Copyright (C) 2003 Alex Woods <linux-dvb@giblets.org>
*
* 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 _TTUSB_DEC_H
#define _TTUSB_DEC_H
#include <asm/semaphore.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include "dmxdev.h"
#include "dvb_demux.h"
#include "dvb_filter.h"
#include "dvb_i2c.h"
#include "dvb_net.h"
#define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB"
#define COMMAND_PIPE 0x03
#define RESULT_PIPE 0x84
#define STREAM_PIPE 0x88
#define COMMAND_PACKET_SIZE 0x3c
#define ARM_PACKET_SIZE 0x1000
#define ISO_BUF_COUNT 0x04
#define FRAMES_PER_ISO_BUF 0x04
#define ISO_FRAME_SIZE 0x0380
#define MAX_AV_PES_LENGTH 6144
struct ttusb_dec {
/* DVB bits */
struct dvb_adapter *adapter;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dmx_frontend frontend;
struct dvb_i2c_bus *i2c_bus;
struct dvb_net dvb_net;
u16 pid[DMX_PES_OTHER];
/* USB bits */
struct usb_device *udev;
u8 trans_count;
unsigned int command_pipe;
unsigned int result_pipe;
unsigned int stream_pipe;
int interface;
struct semaphore usb_sem;
void *iso_buffer;
dma_addr_t iso_dma_handle;
struct urb *iso_urb[ISO_BUF_COUNT];
int iso_stream_count;
struct semaphore iso_sem;
u8 av_pes[MAX_AV_PES_LENGTH + 4];
int av_pes_state;
int av_pes_length;
int av_pes_payload_length;
struct dvb_filter_pes2ts a_pes2ts;
struct dvb_filter_pes2ts v_pes2ts;
u8 v_pes[16 + MAX_AV_PES_LENGTH];
int v_pes_length;
int v_pes_postbytes;
struct list_head urb_frame_list;
struct tasklet_struct urb_tasklet;
spinlock_t urb_frame_list_lock;
};
struct urb_frame {
u8 data[ISO_FRAME_SIZE];
int length;
struct list_head urb_frame_list;
};
#endif
/*
* linux/include/asm-arm/keyboard.h
*
* Copyright (C) 1998 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Keyboard driver definitions for ARM
*/
#ifndef __ASM_ARM_KEYBOARD_H
#define __ASM_ARM_KEYBOARD_H
#include <linux/kd.h>
#include <linux/pm.h>
/*
* We provide a unified keyboard interface when in VC_MEDIUMRAW
* mode. This means that all keycodes must be common between
* all supported keyboards. This unfortunately puts us at odds
* with the PC keyboard interface chip... but we can't do anything
* about that now.
*/
#ifdef __KERNEL__
extern int (*k_setkeycode)(unsigned int, unsigned int);
extern int (*k_getkeycode)(unsigned int);
extern int (*k_translate)(unsigned char, unsigned char *, char);
extern char (*k_unexpected_up)(unsigned char);
extern void (*k_leds)(unsigned char);
static inline int kbd_setkeycode(unsigned int sc, unsigned int kc)
{
int ret = -EINVAL;
if (k_setkeycode)
ret = k_setkeycode(sc, kc);
return ret;
}
static inline int kbd_getkeycode(unsigned int sc)
{
int ret = -EINVAL;
if (k_getkeycode)
ret = k_getkeycode(sc);
return ret;
}
static inline void kbd_leds(unsigned char leds)
{
if (k_leds)
k_leds(leds);
}
extern int k_sysrq_key;
extern unsigned char *k_sysrq_xlate;
#define SYSRQ_KEY k_sysrq_key
#define kbd_sysrq_xlate k_sysrq_xlate
#define kbd_translate k_translate
#define kbd_unexpected_up k_unexpected_up
#define NR_SCANCODES 128
extern int a5kkbd_init_hw(void);
#define kbd_disable_irq() disable_irq(IRQ_KEYBOARDRX)
#define kbd_enable_irq() enable_irq(IRQ_KEYBOARDRX)
#define kbd_init_hw() a5kkbd_init_hw()
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_KEYBOARD_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment