Commit 0bdd8631 authored by Steve French's avatar Steve French

Merge bk://linux.bkbits.net/linux-2.5

into bkbits.net:/repos/c/cifs/linux-2.5cifs
parents ac99d3f1 90732a8a
Documentation for dib3000mb frontend driver and dibusb device driver
====================================================================
Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de),
Documentation for dib3000mb frontend driver and dibusb device driver
dibusb and dib3000mb/mc drivers based on GPL code, which has
The drivers should work with
Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- Twinhan VisionPlus VisionDTV USB-Ter DVB-T Device (VP7041)
http://www.twinhan.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, version 2.
- CTS Portable (Chinese Television System)
http://www.2cts.tv/ctsportable/
- KWorld V-Stream XPERT DTV - DVB-T USB
http://www.kworld.com.tw/asp/pindex.asp?id=4&pid=13
Supported devices USB1.1
========================
Produced and reselled by Twinhan:
---------------------------------
- TwinhanDTV USB-Ter DVB-T Device (VP7041)
http://www.twinhan.com/product_terrestrial_3.asp
- TwinhanDTV Magic Box (VP7041e)
http://www.twinhan.com/product_terrestrial_4.asp
- HAMA DVB-T USB device
http://www.hama.de/portal/articleId*110620/action*2598
- DiBcom USB DVB-T reference device
- CTS Portable (Chinese Television System)
http://www.2cts.tv/ctsportable/
- Unknown USB DVB-T device with vendor ID Hyper-Paltek
Produced and reselled by KWorld:
--------------------------------
- KWorld V-Stream XPERT DTV DVB-T USB
http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html
- Ultima Electronic/Artec T1 USB TVBOX
- JetWay DTV DVB-T USB
http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm
- ADSTech Instant TV DVB-T USB
http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333
Others:
-------
- Ultima Electronic/Artec T1 USB TVBOX (AN2135 and AN2235)
http://www.arteceuro.com/products-tvbox.html
- Compro Videomate DVB-U2000 - DVB-T USB
http://www.comprousa.com/products/vmu2000.htm
- Unknown USB DVB-T device with vendor ID Hyper-Paltek
- Grandtec USB DVB-T
http://www.grand.com.tw/
Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de),
- Avermedia AverTV DVBT USB
http://www.avermedia.com/
both drivers based on GPL code, which has
- DiBcom USB DVB-T reference device (non-public)
Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
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.
Supported devices USB2.0
========================
- Yakumo DVB-T mobile
http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
- DiBcom USB2.0 DVB-T reference device (non-public)
NEWS:
0. NEWS:
2004-11-07 - added remote control support. Thanks to David Matthews.
2004-11-05 - added support for a new devices (Grandtec/Avermedia/Artec)
- merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD
- moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems
better settled there (added xfer_ops-struct)
- created a common files for frontends (mc/p/mb)
2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
to Amaury Demol for reporting
......@@ -49,7 +88,7 @@ NEWS:
(old news for vp7041.c)
2004-07-15 - found out, by accident, that the device has a TUA6010XS for
frequency generator
PLL
2004-07-12 - figured out, that the driver should also work with the
CTS Portable (Chinese Television System)
2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
......@@ -67,7 +106,7 @@ NEWS:
1. How to use?
NOTE: This driver was developed using Linux 2.6.6.,
it is working with 2.6.7, 2.6.8.1.
it is working with 2.6.7, 2.6.8.1, 2.6.9 .
Linux 2.4.x support is not planned, but patches are very welcome.
......@@ -81,8 +120,15 @@ The USB driver needs to download a firmware to start working.
You can either use "get_dvb_firmware dibusb" to download the firmware or you
can get it directly via
for USB1.1 (AN2135)
http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-5.0.0.11.fw?rev=1.1&content-type=text/plain
for USB1.1 (AN2235) (a few Artec T1 devices)
http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-an2235-1.fw?rev=1.1&content-type=text/plain
for USB2.0 (FX2)
http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-6.0.0.5.fw?rev=1.1&content-type=text/plain
1.2. Compiling
Since the driver is in the linux kernel, activating the driver in
......@@ -94,15 +140,16 @@ to compile the driver as module. Hotplug does the rest.
Hotplug is able to load the driver, when it is needed (because you plugged
in the device).
If you want to enable debug output, you have to load the driver manually.
If you want to enable debug output, you have to load the driver manually and
from withing the dvb-kernel cvs repository.
first have a look, which debug level are available:
modinfo dvb-dibusb
modinfo dib3000mb
modinfo dvb-dibusb
modprobe dvb-dibusb debug=<level>
modprobe dib3000mb debug=<level>
modprobe dvb-dibusb debug=<level>
should do the trick.
......@@ -118,21 +165,19 @@ as a slave device in vdr, was not working for me. Some work has to be done
2. Known problems and bugs
TODO:
- remote control tasklet
- remote control
- signal-quality and strength calculations
- debug messages restructure
- i2c address probing
-
2.1. Adding support for devices
It is not possible to determine the range of devices based on the DiBcom
reference design. This is because the reference design of DiBcom can be sold
to third persons, without telling DiBcom (so done with the Twinhan VP7041 and
reference designs. This is because the reference design of DiBcom can be sold
to thirds, without telling DiBcom (so done with the Twinhan VP7041 and
the HAMA device).
When you think you have a device like this and the driver does not recognizes it,
please send the ****load.inf and the ****cap.inf of the Windows driver to me.
please send the ****load*.inf and the ****cap*.inf of the Windows driver to me.
Sometimes the Vendor or Product ID is identical to the ones of Twinhan, even
though it is not a Twinhan device (e.g. HAMA), then please send me the name
......@@ -153,6 +198,9 @@ Patches, comments and suggestions are very very welcome
providing specs, code and help, on which the dvb-dibusb and dib3000mb are
based.
David Matthews for identifying a new device type (Artec T1 with AN2235)
and for extending dibusb with remote control event handling. Thank you.
Alex Woods for frequently answering question about usb and dvb
stuff, a big thank you
......
......@@ -38,7 +38,7 @@ o Frontends drivers:
Comtech DVBT-6k07 (SP5730 PLL)
(NxtWave Communications NXT6000 demodulator)
- sp887x : Microtune 7202D
- dib3000mb : DiBcom 3000-MB Frontend
- dib3000mb : DiBcom 3000-MB demodulator
DVB-S/C/T:
- dst : TwinHan DST Frontend
......@@ -69,7 +69,17 @@ o Technotrend / Hauppauge DVB USB devices:
o DiBcom DVB-T USB based devices:
- Twinhan VisionPlus VisionDTV USB-Ter DVB-T Device
- KWorld V-Stream XPERT DTV - DVB-T USB
- HAMA DVB-T USB device
- CTS Portable (Chinese Television System)
- KWorld V-Stream XPERT DTV DVB-T USB
- JetWay DTV DVB-T USB
- ADSTech Instant TV DVB-T USB
- Ultima Electronic/Artec T1 USB TVBOX (AN2135 and AN2235)
- Compro Videomate DVB-U2000 - DVB-T USB
- Grandtec USB DVB-T
- Avermedia AverTV DVBT USB
- DiBcom USB DVB-T reference device (non-public)
- Yakumo DVB-T mobile USB2.0
- DiBcom USB2.0 DVB-T reference device (non-public)
o Experimental support for the analog module of the Siemens DVB-C PCI card
......@@ -21,7 +21,7 @@
use File::Temp qw/ tempdir /;
use IO::Handle;
@components = ( "alps_tdlb7", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb" );
@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t", "dec2540t", "dec3000s", "vp7041", "dibusb" );
# Check args
syntax() if (scalar(@ARGV) != 1);
......@@ -32,7 +32,7 @@ for($i=0; $i < scalar(@components); $i++) {
if ($cid eq $components[$i]) {
$outfile = eval($cid);
die $@ if $@;
print STDERR "Firmware $outfile extracted successfully. Now copy it to /usr/lib/hotplug/firmware/.\n";
print STDERR "Firmware $outfile extracted successfully. Now copy it to either /lib/firmware or /usr/lib/hotplug/firmware/ (depending on your hotplug version).\n";
exit(0);
}
}
......@@ -47,11 +47,11 @@ syntax();
# ---------------------------------------------------------------
# Firmware-specific extraction subroutines
sub alps_tdlb7 {
sub sp8870 {
my $sourcefile = "tt_Premium_217g.zip";
my $url = "http://www.technotrend.de/new/217g/$sourcefile";
my $hash = "53970ec17a538945a6d8cb608a7b3899";
my $outfile = "dvb-fe-tdlb7.fw";
my $outfile = "dvb-fe-sp8870.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
checkstandard();
......
......@@ -200,7 +200,7 @@ config M586
bool "586/K5/5x86/6x86/6x86MX"
help
Select this for an 586 or 686 series processor such as the AMD K5,
the Intel 5x86 or 6x86, or the Intel 6x86MX. This choice does not
the Cyrix 5x86, 6x86 and 6x86MX. This choice does not
assume the RDTSC (Read Time Stamp Counter) instruction.
config M586TSC
......
......@@ -723,7 +723,14 @@ static irqreturn_t irq_handler(int intno, void *dev_id, struct pt_regs * regs)
irqbits |= irq_bit;
if (vm86_irqs[intno].sig)
send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
/* else user will poll for IRQs */
spin_unlock_irqrestore(&irqbits_lock, flags);
/*
* IRQ will be re-enabled when user asks for the irq (whether
* polling or as a result of the signal)
*/
disable_irq(intno);
return IRQ_HANDLED;
out:
spin_unlock_irqrestore(&irqbits_lock, flags);
return IRQ_NONE;
......
......@@ -221,23 +221,6 @@ void __devinit arch_init_sched_domains(void)
&cpu_to_phys_group);
}
/* Initialize isolated CPU (physical) domains and groups */
for_each_cpu_mask(i, cpu_isolated_map) {
struct sched_domain *sd;
int group;
sd = &per_cpu(phys_domains, i);
group = cpu_to_phys_group(i);
*sd = SD_CPU_INIT;
cpu_set(i, sd->span);
sd->flags = 0;
sd->balance_interval = INT_MAX;
sd->groups = &sched_group_phys[group];
init_sched_build_groups(sched_group_phys, sd->span,
&cpu_to_phys_group);
sd->groups->cpu_power = SCHED_LOAD_SCALE;
}
#ifdef CONFIG_NUMA
init_sched_build_groups(sched_group_allnodes, cpu_default_map,
&cpu_to_allnodes_group);
......
......@@ -1508,7 +1508,7 @@ syscall_is_too_hard:
.globl ret_sys_call
ret_sys_call:
ld [%curptr + TI_FLAGS], %l6
cmp %o0, -ENOIOCTLCMD
cmp %o0, -ERESTART_RESTARTBLOCK
ld [%sp + STACKFRAME_SZ + PT_PSR], %g3
set PSR_C, %g2
bgeu 1f
......@@ -1587,7 +1587,7 @@ solaris_syscall:
st %o0, [%sp + STACKFRAME_SZ + PT_I0]
set PSR_C, %g2
cmp %o0, -ENOIOCTLCMD
cmp %o0, -ERESTART_RESTARTBLOCK
bgeu 1f
ld [%sp + STACKFRAME_SZ + PT_PSR], %g3
......@@ -1678,7 +1678,7 @@ bsd_is_too_hard:
st %o0, [%sp + STACKFRAME_SZ + PT_I0]
set PSR_C, %g2
cmp %o0, -ENOIOCTLCMD
cmp %o0, -ERESTART_RESTARTBLOCK
bgeu 1f
ld [%sp + STACKFRAME_SZ + PT_PSR], %g3
......
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.10-rc2
# Tue Nov 16 11:09:23 2004
# Linux kernel version: 2.6.10-rc3
# Wed Dec 8 21:14:26 2004
#
CONFIG_64BIT=y
CONFIG_MMU=y
......@@ -233,6 +233,7 @@ CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_SX8=m
CONFIG_BLK_DEV_UB=m
# CONFIG_BLK_DEV_RAM is not set
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
......@@ -387,7 +388,6 @@ CONFIG_SCSI_QLOGIC_ISP=m
CONFIG_SCSI_QLOGIC_FC=y
CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y
# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_QLOGIC_1280_1040 is not set
CONFIG_SCSI_QLOGICPTI=m
CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA21XX is not set
......@@ -1045,6 +1045,11 @@ CONFIG_ISDN_CAPI_CAPI20=m
# Active AVM cards
#
CONFIG_CAPI_AVM=y
CONFIG_ISDN_DRV_AVMB1_B1PCI=m
CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
CONFIG_ISDN_DRV_AVMB1_T1PCI=m
CONFIG_ISDN_DRV_AVMB1_C4=m
#
# Active Eicon DIVA Server cards
......@@ -1178,6 +1183,7 @@ CONFIG_I2C_PCA_ISA=m
CONFIG_I2C_SENSOR=m
CONFIG_SENSORS_ADM1021=m
CONFIG_SENSORS_ADM1025=m
CONFIG_SENSORS_ADM1026=m
CONFIG_SENSORS_ADM1031=m
CONFIG_SENSORS_ASB100=m
CONFIG_SENSORS_DS1621=m
......@@ -1438,39 +1444,6 @@ CONFIG_RADIO_MAESTRO=m
CONFIG_DVB=y
CONFIG_DVB_CORE=m
#
# DVB-S (satellite) frontends
#
CONFIG_DVB_STV0299=m
CONFIG_DVB_CX24110=m
CONFIG_DVB_GRUNDIG_29504_491=m
CONFIG_DVB_MT312=m
CONFIG_DVB_VES1X93=m
#
# DVB-T (terrestrial) frontends
#
CONFIG_DVB_SP887X=m
CONFIG_DVB_ALPS_TDLB7=m
CONFIG_DVB_ALPS_TDMB7=m
CONFIG_DVB_CX22702=m
CONFIG_DVB_GRUNDIG_29504_401=m
CONFIG_DVB_TDA1004X=m
CONFIG_DVB_NXT6000=m
CONFIG_DVB_MT352=m
CONFIG_DVB_DIB3000MB=m
#
# DVB-C (cable) frontends
#
CONFIG_DVB_ATMEL_AT76C651=m
CONFIG_DVB_VES1820=m
#
# Misc. Frontend Modules
#
CONFIG_DVB_TWINHAN_DST=m
#
# Supported SAA7146 based PCI Adapters
#
......@@ -1487,6 +1460,8 @@ CONFIG_DVB_BUDGET_PATCH=m
# CONFIG_DVB_TTUSB_BUDGET is not set
CONFIG_DVB_TTUSB_DEC=m
CONFIG_DVB_DIBUSB=m
CONFIG_DVB_DIBUSB_MISDESIGNED_AN2235=y
CONFIG_DVB_DIBCOM_DEBUG=y
CONFIG_DVB_CINERGYT2=m
# CONFIG_DVB_CINERGYT2_TUNING is not set
......@@ -1499,6 +1474,45 @@ CONFIG_DVB_B2C2_SKYSTAR=m
# Supported BT878 Adapters
#
CONFIG_DVB_BT8XX=m
#
# Supported DVB Frontends
#
#
# Customise DVB Frontends
#
#
# DVB-S (satellite) frontends
#
CONFIG_DVB_STV0299=m
CONFIG_DVB_CX24110=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA80XX=m
CONFIG_DVB_MT312=m
CONFIG_DVB_VES1X93=m
#
# DVB-T (terrestrial) frontends
#
CONFIG_DVB_SP8870=m
CONFIG_DVB_SP887X=m
CONFIG_DVB_CX22700=m
CONFIG_DVB_CX22702=m
CONFIG_DVB_L64781=m
CONFIG_DVB_TDA1004X=m
CONFIG_DVB_NXT6000=m
CONFIG_DVB_MT352=m
CONFIG_DVB_DIB3000MB=m
#
# DVB-C (cable) frontends
#
CONFIG_DVB_ATMEL_AT76C651=m
CONFIG_DVB_VES1820=m
CONFIG_DVB_TDA10021=m
CONFIG_DVB_STV0297=m
CONFIG_VIDEO_SAA7146=m
CONFIG_VIDEO_SAA7146_VV=m
CONFIG_VIDEO_VIDEOBUF=m
......@@ -1634,6 +1648,10 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_MIDI is not set
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_RW_DETECT=y
......
......@@ -79,7 +79,7 @@ typedef struct {
#define elf_check_arch(x) (((x)->e_machine == EM_SPARC) || ((x)->e_machine == EM_SPARC32PLUS))
#define ELF_ET_DYN_BASE 0x08000000
#define ELF_ET_DYN_BASE 0x70000000
#include <asm/processor.h>
......
......@@ -1778,7 +1778,7 @@ ret_sys_call:
stx %l0, [%curptr + TI_FLAGS]
1:
cmp %o0, -ENOIOCTLCMD
cmp %o0, -ERESTART_RESTARTBLOCK
bgeu,pn %xcc, 1f
andcc %l0, _TIF_SYSCALL_TRACE, %l6
80:
......
......@@ -109,7 +109,7 @@ ret_from_solaris:
sra %o0, 0, %o0
mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
cmp %o0, -ENOIOCTLCMD
cmp %o0, -ERESTART_RESTARTBLOCK
sllx %g2, 32, %g2
bgeu,pn %xcc, 1f
andcc %l6, _TIF_SYSCALL_TRACE, %l6
......
......@@ -25,11 +25,11 @@ struct list_head saa7146_devices;
struct semaphore saa7146_devices_lock;
static int initialized = 0;
int saa7146_num = 0;
static int saa7146_num = 0;
unsigned int saa7146_debug = 0;
MODULE_PARM(saa7146_debug,"i");
module_param(saa7146_debug, int, 0644);
MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
#if 0
......@@ -48,7 +48,7 @@ static void dump_registers(struct saa7146_dev* dev)
* gpio and debi helper functions
****************************************************************************/
/* write "data" to the gpio-pin "pin" */
/* write "data" to the gpio-pin "pin" -- unused */
void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
{
u32 value = 0;
......@@ -67,7 +67,7 @@ void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
}
/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
int saa7146_wait_for_debi_done(struct saa7146_dev *dev)
int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
{
unsigned long start;
......@@ -80,6 +80,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev)
DEB_S(("timed out while waiting for registers getting programmed\n"));
return -ETIMEDOUT;
}
if (nobusyloop)
msleep(1);
}
/* wait for transfer to complete */
......@@ -92,6 +94,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev)
DEB_S(("timed out while waiting for transfer completion\n"));
return -ETIMEDOUT;
}
if (nobusyloop)
msleep(1);
}
return 0;
......@@ -248,10 +252,9 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
/********************************************************************************/
/* interrupt handler */
static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
{
struct saa7146_dev *dev = (struct saa7146_dev*)dev_id;
struct saa7146_dev *dev = dev_id;
u32 isr = 0;
/* read out the interrupt status register */
......@@ -318,16 +321,15 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent)
{
unsigned long adr = 0, len = 0;
struct saa7146_dev* dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL);
struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data;
struct saa7146_extension* ext = pci_ext->ext;
int err = 0;
struct saa7146_dev *dev;
int err = -ENOMEM;
if (!(dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL))) {
dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
if (!dev) {
ERR(("out of memory.\n"));
return -ENOMEM;
goto out;
}
/* clear out mem for sure */
......@@ -335,38 +337,37 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
DEB_EE(("pci:%p\n",pci));
if (pci_enable_device(pci)) {
err = pci_enable_device(pci);
if (err < 0) {
ERR(("pci_enable_device() failed.\n"));
err = -EIO;
goto pci_error;
goto err_free;
}
/* enable bus-mastering */
pci_set_master(pci);
dev->pci = pci;
/* get chip-revision; this is needed to enable bug-fixes */
if( 0 > pci_read_config_dword(dev->pci, PCI_CLASS_REVISION, &dev->revision)) {
err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision);
if (err < 0) {
ERR(("pci_read_config_dword() failed.\n"));
err = -ENODEV;
goto pci_error;
goto err_disable;
}
dev->revision &= 0xf;
/* remap the memory from virtual to physical adress */
adr = pci_resource_start(pci,0);
len = pci_resource_len(pci,0);
if (!request_mem_region(pci_resource_start(pci,0), pci_resource_len(pci,0), "saa7146")) {
ERR(("request_mem_region() failed.\n"));
err = -ENODEV;
goto pci_error;
}
err = pci_request_region(pci, 0, "saa7146");
if (err < 0)
goto err_disable;
if (!(dev->mem = ioremap(adr,len))) {
dev->mem = ioremap(pci_resource_start(pci, 0),
pci_resource_len(pci, 0));
if (!dev->mem) {
ERR(("ioremap() failed.\n"));
err = -ENODEV;
goto ioremap_error;
goto err_release;
}
/* we don't do a master reset here anymore, it screws up
......@@ -386,42 +387,40 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
saa7146_write(dev, MC2, 0xf8000000);
/* request an interrupt for the saa7146 */
if (request_irq(dev->pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT,
dev->name, dev))
{
err = request_irq(pci->irq, interrupt_hw, SA_SHIRQ | SA_INTERRUPT,
dev->name, dev);
if (err < 0) {
ERR(("request_irq() failed.\n"));
err = -ENODEV;
goto irq_error;
goto err_unmap;
}
/* get memory for various stuff */
dev->d_rps0.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps0.dma_handle);
if( NULL == dev->d_rps0.cpu_addr ) {
err = -ENOMEM;
goto kmalloc_error_1;
}
/* get memory for various stuff */
dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
&dev->d_rps0.dma_handle);
if (!dev->d_rps0.cpu_addr)
goto err_free_irq;
memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM);
dev->d_rps1.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps1.dma_handle);
if( NULL == dev->d_rps1.cpu_addr ) {
err = -ENOMEM;
goto kmalloc_error_2;
}
dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
&dev->d_rps1.dma_handle);
if (!dev->d_rps1.cpu_addr)
goto err_free_rps0;
memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM);
dev->d_i2c.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_i2c.dma_handle);
if( NULL == dev->d_i2c.cpu_addr ) {
err = -ENOMEM;
goto kmalloc_error_3;
}
dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
&dev->d_i2c.dma_handle);
if (!dev->d_i2c.cpu_addr)
goto err_free_rps1;
memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM);
/* the rest + print status message */
/* create a nice device name */
sprintf(&dev->name[0], "saa7146 (%d)",saa7146_num);
sprintf(dev->name, "saa7146 (%d)", saa7146_num);
INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision,dev->pci->irq,dev->pci->subsystem_vendor,dev->pci->subsystem_device));
INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
dev->ext = ext;
pci_set_drvdata(pci,dev);
......@@ -438,18 +437,18 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
/* set some sane pci arbitrition values */
saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
if( 0 != ext->probe) {
if( 0 != ext->probe(dev) ) {
DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
/* TODO: use the status code of the callback */
err = -ENODEV;
goto probe_error;
}
if (ext->probe && ext->probe(dev)) {
DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
goto err_free_i2c;
}
if( 0 != ext->attach(dev,pci_ext) ) {
if (ext->attach(dev, pci_ext)) {
DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
err = -ENODEV;
goto attach_error;
goto err_unprobe;
}
INIT_LIST_HEAD(&dev->item);
......@@ -457,30 +456,46 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
saa7146_num++;
err = 0;
goto out;
attach_error:
probe_error:
out:
return err;
err_unprobe:
pci_set_drvdata(pci,NULL);
pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle);
kmalloc_error_3:
pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle);
kmalloc_error_2:
pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle);
kmalloc_error_1:
free_irq(dev->pci->irq, (void *)dev);
irq_error:
err_free_i2c:
pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
dev->d_i2c.dma_handle);
err_free_rps1:
pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr,
dev->d_rps1.dma_handle);
err_free_rps0:
pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr,
dev->d_rps0.dma_handle);
err_free_irq:
free_irq(pci->irq, (void *)dev);
err_unmap:
iounmap(dev->mem);
ioremap_error:
release_mem_region(adr,len);
pci_error:
err_release:
pci_release_region(pci, 0);
err_disable:
pci_disable_device(pci);
err_free:
kfree(dev);
out:
return err;
goto out;
}
static void saa7146_remove_one(struct pci_dev *pdev)
{
struct saa7146_dev* dev = (struct saa7146_dev*) pci_get_drvdata(pdev);
struct saa7146_dev* dev = pci_get_drvdata(pdev);
struct {
void *addr;
dma_addr_t dma;
} dev_map[] = {
{ dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle },
{ dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle },
{ dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle },
{ NULL, 0 }
}, *p;
DEB_EE(("dev:%p\n",dev));
dev->ext->detach(dev);
......@@ -491,17 +506,15 @@ static void saa7146_remove_one(struct pci_dev *pdev)
/* disable all irqs, release irq-routine */
saa7146_write(dev, IER, 0);
free_irq(dev->pci->irq, (void *)dev);
free_irq(pdev->irq, dev);
/* free kernel memory */
pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle);
pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle);
pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle);
for (p = dev_map; p->addr; p++)
pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma);
iounmap(dev->mem);
release_mem_region(pci_resource_start(dev->pci,0), pci_resource_len(dev->pci,0));
pci_release_region(pdev, 0);
list_del(&dev->item);
pci_disable_device(pdev);
kfree(dev);
saa7146_num--;
......
#include <media/saa7146_vv.h>
#include <linux/version.h>
#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1)
......@@ -32,17 +33,6 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
return 1;
}
int saa7146_res_check(struct saa7146_fh *fh, unsigned int bit)
{
return (fh->resources & bit);
}
int saa7146_res_locked(struct saa7146_dev *dev, unsigned int bit)
{
struct saa7146_vv *vv = dev->vv_data;
return (vv->resources & bit);
}
void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
{
struct saa7146_dev *dev = fh->dev;
......
......@@ -9,11 +9,6 @@ static void calculate_output_format_register(struct saa7146_dev* saa, u32 palett
*clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16));
}
static void calculate_bcs_ctrl_register(struct saa7146_dev *dev, int brightness, int contrast, int colour, u32 *bcs_ctrl)
{
*bcs_ctrl = ((brightness << 24) | (contrast << 16) | (colour << 0));
}
static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl)
{
*hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28);
......@@ -62,7 +57,7 @@ static struct {
};
/* table of attenuation values for horizontal scaling */
u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0};
static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0};
/* calculate horizontal scale registers */
static int calculate_h_scale_registers(struct saa7146_dev *dev,
......@@ -208,7 +203,7 @@ static struct {
};
/* table of attenuation values for vertical scaling */
u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0};
static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0};
/* calculate vertical scale registers */
static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field,
......@@ -620,18 +615,6 @@ static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long pal
saa7146_write(dev, MC2, (MASK_05 | MASK_21));
}
void saa7146_set_picture_prop(struct saa7146_dev *dev, int brightness, int contrast, int colour)
{
u32 bcs_ctrl = 0;
calculate_bcs_ctrl_register(dev, brightness, contrast, colour, &bcs_ctrl);
saa7146_write(dev, BCS_CTRL, bcs_ctrl);
/* update the bcs register */
saa7146_write(dev, MC2, (MASK_06 | MASK_22));
}
/* select input-source */
void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync)
{
......
#include <linux/version.h>
#include <media/saa7146_vv.h>
u32 saa7146_i2c_func(struct i2c_adapter *adapter)
static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
{
//fm DEB_I2C(("'%s'.\n", adapter->name));
......
......@@ -130,7 +130,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
return 0;
}
void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
{
struct saa7146_vv *vv = dev->vv_data;
......
......@@ -2,7 +2,7 @@
static int max_memory = 32;
MODULE_PARM(max_memory,"i");
module_param(max_memory, int, 0644);
MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
#define IS_CAPTURE_ACTIVE(fh) \
......
......@@ -21,8 +21,6 @@ config DVB
source "drivers/media/dvb/dvb-core/Kconfig"
source "drivers/media/dvb/frontends/Kconfig"
comment "Supported SAA7146 based PCI Adapters"
depends on DVB_CORE && PCI
source "drivers/media/dvb/ttpci/Kconfig"
......@@ -42,5 +40,8 @@ comment "Supported BT878 Adapters"
depends on DVB_CORE && PCI
source "drivers/media/dvb/bt8xx/Kconfig"
endmenu
comment "Supported DVB Frontends"
depends on DVB_CORE
source "drivers/media/dvb/frontends/Kconfig"
endmenu
config DVB_B2C2_SKYSTAR
tristate "Technisat Skystar2 PCI"
depends on DVB_CORE && PCI
select DVB_STV0299
select DVB_MT352
help
Support for the Skystar2 PCI DVB card by Technisat, which
is equipped with the FlexCopII chipset by B2C2.
......
obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
This diff is collapsed.
config DVB_BT8XX
tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards"
depends on DVB_CORE && PCI && VIDEO_BT848
select DVB_MT352
select DVB_SP887X
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards and Twinhan DST cards.
......
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends
......@@ -44,7 +44,7 @@
#include "dmxdev.h"
#include "dvbdev.h"
#include "bt878.h"
#include "dst-bt878.h"
#include "dst_priv.h"
/**************************************/
......@@ -559,22 +559,11 @@ static struct pci_driver bt878_pci_driver = {
static int bt878_pci_driver_registered = 0;
/* This will be used later by dvb-bt8xx to only use the audio
* dma of certain cards */
int bt878_find_audio_dma(void)
{
// pci_register_driver(&bt878_pci_driver);
bt878_pci_driver_registered = 1;
return 0;
}
EXPORT_SYMBOL(bt878_find_audio_dma);
/*******************************/
/* Module management functions */
/*******************************/
int bt878_init_module(void)
static int bt878_init_module(void)
{
bt878_num = 0;
bt878_pci_driver_registered = 0;
......@@ -586,13 +575,13 @@ int bt878_init_module(void)
/*
bt878_check_chipset();
*/
/* later we register inside of bt878_find_audio_dma
/* later we register inside of bt878_find_audio_dma()
* because we may want to ignore certain cards */
bt878_pci_driver_registered = 1;
return pci_module_init(&bt878_pci_driver);
}
void bt878_cleanup_module(void)
static void bt878_cleanup_module(void)
{
if (bt878_pci_driver_registered) {
bt878_pci_driver_registered = 0;
......@@ -601,12 +590,10 @@ void bt878_cleanup_module(void)
return;
}
EXPORT_SYMBOL(bt878_init_module);
EXPORT_SYMBOL(bt878_cleanup_module);
module_init(bt878_init_module);
module_exit(bt878_cleanup_module);
//MODULE_AUTHOR("XXX");
MODULE_LICENSE("GPL");
/*
......
/*
Frontend-driver for TwinHan DST Frontend
Copyright (C) 2003 Jamie Honan
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 DST_H
#define DST_H
#include <linux/dvb/frontend.h>
#include <linux/device.h>
#include "bt878.h"
struct dst_config
{
/* the demodulator's i2c address */
u8 demod_address;
};
extern struct dvb_frontend* dst_attach(const struct dst_config* config,
struct i2c_adapter* i2c,
struct bt878 *bt);
#endif // DST_H
......@@ -30,7 +30,7 @@ union dst_gpio_packet {
#define DST_IG_READ 2
#define DST_IG_TS 3
struct bt878 ;
struct bt878;
int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
......
This diff is collapsed.
......@@ -26,6 +26,10 @@
#include "dvbdev.h"
#include "dvb_net.h"
#include "bttv.h"
#include "mt352.h"
#include "sp887x.h"
#include "dst.h"
#include "nxt6000.h"
struct dvb_bt8xx_card {
struct semaphore lock;
......@@ -44,4 +48,5 @@ struct dvb_bt8xx_card {
struct i2c_adapter *i2c_adapter;
struct dvb_net dvbnet;
struct dvb_frontend* fe;
};
......@@ -23,8 +23,10 @@ config DVB_CINERGYT2_STREAM_URB_COUNT
depends on DVB_CINERGYT2_TUNING
default "32"
help
USB Request Blocks for Highspeed Stream transfers are queued in a
for the Host Controller. Usually the default value is a safe choice.
USB Request Blocks for Highspeed Stream transfers are scheduled in
a queue for the Host Controller.
Usually the default value is a safe choice.
You may increase this number if you are using this device in a
Server Environment with many high-traffic USB Highspeed devices
......@@ -44,6 +46,21 @@ config DVB_CINERGYT2_STREAM_BUF_SIZE
sharing the same USB bus.
config DVB_CINERGYT2_QUERY_INTERVAL
int "Status update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING
default "250"
help
This is the interval for status readouts from the demodulator.
You may try lower values if you need more responsive signal quality
measurements.
Please keep in mind that these updates cause traffic on the tuner
control bus and thus may or may not affect receiption sensitivity.
The default value should be a safe choice for common applications.
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
bool "Register the onboard IR Remote Control Receiver as Input Device"
depends on DVB_CINERGYT2_TUNING
......@@ -57,3 +74,12 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
source code to find out how to add support for other controls.
config DVB_CINERGYT2_RC_QUERY_INTERVAL
int "Infrared Remote Controller update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
default "100"
help
If you have a very fast-repeating remote control you can try lower
values, for normal consumer receivers the default value should be
a safe choice.
This diff is collapsed.
config DVB_DIBUSB
tristate "DiBcom/Twinhan/KWorld/Hama/Artec/Compro USB DVB-T devices"
tristate "DiBcom USB DVB-T devices (see help for device list)"
depends on DVB_CORE && USB
select FW_LOADER
select DVB_DIB3000MB
help
Support for USB 1.1 DVB-T devices based on a reference design made by
Support for USB 1.1 and 2.0 DVB-T devices based on reference designs made by
DiBcom (http://www.dibcom.fr).
Devices supported by this driver:
......@@ -15,19 +16,35 @@ config DVB_DIBUSB
DiBcom reference device (non-public)
Ultima Electronic/Artec T1 USB TVBOX
Compro Videomate DVB-U2000 - DVB-T USB
Grandtec DVB-T USB
Avermedia AverTV DVBT USB
Yakumo DVB-T mobile USB2.0
The VP7041 seems to be identical to "CTS Portable" (Chinese
Television System).
These devices can be understood as budget ones, they "only" deliver
the MPEG data.
(a part of) the MPEG2 transport stream.
Currently all known copies of the DiBcom reference design have the DiBcom 3000-MB
frontend onboard. Please enable and load this one manually in order to use this
device.
A firmware is needed to use the device. See Documentation/dvb/README.dibusb
A firmware is needed to get the device working. See Documentation/dvb/README.dibusb
details.
Say Y if you own such a device and want to use it. You should build it as
a module.
config DVB_DIBUSB_MISDESIGNED_AN2235
bool "Enable support for some Artec T1 device, which identifies as AN2235"
depends on DVB_DIBUSB
help
Somehow Artec forgot to program the eeprom for some of their T1 devices. So
comes that they identify with the default Vendor and Product ID of the Cypress
CY7C64613 (AN2235).
Say Y if your Artec device has 0x0574 as Vendor ID and 0x2235 as Product ID.
config DVB_DIBCOM_DEBUG
bool "Enable extended debug support for DiBcom USB device"
depends on DVB_DIBUSB
help
Say Y if you want to enable debuging. See modinfo dvb-dibusb for
debug level.
obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
This diff is collapsed.
This diff is collapsed.
......@@ -4,6 +4,6 @@
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
dvb_ca_en50221.o dvb_frontend.o \
dvb_net.o dvb_ksyms.o dvb_ringbuffer.o
dvb_net.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
obj-$(CONFIG_DVB_CORE) += crc32.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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