summaryrefslogtreecommitdiff
path: root/drivers/media/dvb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/Kconfig1
-rw-r--r--drivers/media/dvb/Makefile2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c2
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c2
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig1
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h2
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c46
-rw-r--r--drivers/media/dvb/dvb-core/demux.h2
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c36
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c17
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c18
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.c78
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.h12
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c8
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig26
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile6
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c553
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.h304
-rw-r--r--drivers/media/dvb/dvb-usb/au6610.c83
-rw-r--r--drivers/media/dvb/dvb-usb/au6610.h22
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c167
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h3
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c28
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h9
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.c425
-rw-r--r--drivers/media/dvb/dvb-usb/dw2102.h9
-rw-r--r--drivers/media/dvb/dvb-usb/gl861.c65
-rw-r--r--drivers/media/dvb/dvb-usb/gl861.h2
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c13
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c7
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c2
-rw-r--r--drivers/media/dvb/frontends/Kconfig24
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/au8522.c30
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c5
-rw-r--r--drivers/media/dvb/frontends/dib0070.h15
-rw-r--r--drivers/media/dvb/frontends/dib7000p.h15
-rw-r--r--drivers/media/dvb/frontends/drx397xD.c1504
-rw-r--r--drivers/media/dvb/frontends/drx397xD.h130
-rw-r--r--drivers/media/dvb/frontends/drx397xD_fw.h40
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c47
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h1
-rw-r--r--drivers/media/dvb/frontends/itd1000.c2
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c24
-rw-r--r--drivers/media/dvb/frontends/mt312.c9
-rw-r--r--drivers/media/dvb/frontends/mt312.h4
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c3
-rw-r--r--drivers/media/dvb/frontends/or51132.c6
-rw-r--r--drivers/media/dvb/frontends/or51211.c4
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c1
-rw-r--r--drivers/media/dvb/frontends/s5h1411.c1
-rw-r--r--drivers/media/dvb/frontends/sp8870.c2
-rw-r--r--drivers/media/dvb/frontends/sp887x.c2
-rw-r--r--drivers/media/dvb/frontends/stv0299.c15
-rw-r--r--drivers/media/dvb/frontends/tda10023.c217
-rw-r--r--drivers/media/dvb/frontends/tda1002x.h41
-rw-r--r--drivers/media/dvb/frontends/tda10048.c2
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c31
-rw-r--r--drivers/media/dvb/frontends/z0194a.h97
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c4
-rw-r--r--drivers/media/dvb/siano/Kconfig26
-rw-r--r--drivers/media/dvb/siano/Makefile8
-rw-r--r--drivers/media/dvb/siano/sms-cards.c102
-rw-r--r--drivers/media/dvb/siano/sms-cards.h45
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c1251
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h434
-rw-r--r--drivers/media/dvb/siano/smsdvb.c449
-rw-r--r--drivers/media/dvb/siano/smsusb.c459
-rw-r--r--drivers/media/dvb/ttpci/Kconfig5
-rw-r--r--drivers/media/dvb/ttpci/Makefile7
-rw-r--r--drivers/media/dvb/ttpci/av7110.c56
-rw-r--r--drivers/media/dvb/ttpci/av7110.h1
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c36
-rw-r--r--drivers/media/dvb/ttpci/av7110_ca.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c5
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h3
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c12
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c24
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c44
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c40
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h1644
-rw-r--r--drivers/media/dvb/ttusb-dec/Kconfig3
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c27
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c10
89 files changed, 6815 insertions, 2120 deletions
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 7b21b49..8bc1445 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -21,6 +21,7 @@ source "drivers/media/dvb/dvb-usb/Kconfig"
source "drivers/media/dvb/ttusb-budget/Kconfig"
source "drivers/media/dvb/ttusb-dec/Kconfig"
source "drivers/media/dvb/cinergyT2/Kconfig"
+source "drivers/media/dvb/siano/Kconfig"
comment "Supported FlexCopII (B2C2) Adapters"
depends on DVB_CORE && (PCI || USB) && I2C
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index a7ad084..d6ba4d1 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/
+obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 7b0ea3b..f9d0876 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -634,7 +634,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
}
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
- fc->fe = dvb_attach(vp310_mt312_attach,
+ fc->fe = dvb_attach(mt312_attach,
&skystar23_samsung_tbdu18132_config, i2c);
if (fc->fe != NULL) {
ops = &fc->fe->ops;
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 449fb5c..ae0d76a 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -379,7 +379,7 @@ static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
{
- u16 frame_size = fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize;
+ u16 frame_size = le16_to_cpu(fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
int buffer_offset = 0;
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index d1239b8..7e9c090 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -9,7 +9,6 @@ config DVB_BT8XX
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
- select FW_LOADER
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index 375fd28..d19b592 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -128,7 +128,7 @@ struct bt878 {
dma_addr_t buf_dma;
u32 risc_size;
- u32 *risc_cpu;
+ __le32 *risc_cpu;
dma_addr_t risc_dma;
u32 risc_pos;
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 3d778c5..c03513b 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -1,6 +1,6 @@
config DVB_CINERGYT2
tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver"
- depends on DVB_CORE && USB
+ depends on DVB_CORE && USB && INPUT
help
Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index f5010e8..a824f37 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -82,22 +82,22 @@ enum cinergyt2_ep1_cmd {
struct dvbt_set_parameters_msg {
uint8_t cmd;
- uint32_t freq;
+ __le32 freq;
uint8_t bandwidth;
- uint16_t tps;
+ __le16 tps;
uint8_t flags;
} __attribute__((packed));
struct dvbt_get_status_msg {
- uint32_t freq;
+ __le32 freq;
uint8_t bandwidth;
- uint16_t tps;
+ __le16 tps;
uint8_t flags;
- uint16_t gain;
+ __le16 gain;
uint8_t snr;
- uint32_t viterbi_error_rate;
- uint32_t rs_error_rate;
- uint32_t uncorrected_block_count;
+ __le32 viterbi_error_rate;
+ __le32 rs_error_rate;
+ __le32 uncorrected_block_count;
uint8_t lock_bits;
uint8_t prev_lock_bits;
} __attribute__((packed));
@@ -136,6 +136,7 @@ struct cinergyt2 {
wait_queue_head_t poll_wq;
int pending_fe_events;
int disconnect_pending;
+ unsigned int uncorrected_block_count;
atomic_t inuse;
void *streambuf;
@@ -147,7 +148,7 @@ struct cinergyt2 {
char phys[64];
struct delayed_work rc_query_work;
int rc_input_event;
- u32 rc_last_code;
+ __le32 rc_last_code;
unsigned long last_event_jiffies;
#endif
};
@@ -160,7 +161,7 @@ enum {
struct cinergyt2_rc_event {
char type;
- uint32_t value;
+ __le32 value;
} __attribute__((packed));
static const uint32_t rc_keys[] = {
@@ -619,8 +620,11 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
{
uint32_t unc_count;
- unc_count = stat->uncorrected_block_count;
- stat->uncorrected_block_count = 0;
+ if (mutex_lock_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+ unc_count = cinergyt2->uncorrected_block_count;
+ cinergyt2->uncorrected_block_count = 0;
+ mutex_unlock(&cinergyt2->sem);
/* UNC are already converted to host byte order... */
return put_user(unc_count,(__u32 __user *) arg);
@@ -769,7 +773,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
input_sync(cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX;
}
- cinergyt2->rc_last_code = ~0;
+ cinergyt2->rc_last_code = cpu_to_le32(~0);
}
goto out;
}
@@ -780,7 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
- rc_events[n].value == ~0) {
+ rc_events[n].value == cpu_to_le32(~0)) {
/* keyrepeat bit -> just repeat last rc_input_event */
} else {
cinergyt2->rc_input_event = KEY_MAX;
@@ -795,7 +799,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
if (cinergyt2->rc_input_event != KEY_MAX) {
if (rc_events[n].value == cinergyt2->rc_last_code &&
- cinergyt2->rc_last_code != ~0) {
+ cinergyt2->rc_last_code != cpu_to_le32(~0)) {
/* emit a key-up so the double event is recognized */
dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
input_report_key(cinergyt2->rc_input_dev,
@@ -829,7 +833,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
usb_make_path(cinergyt2->udev, cinergyt2->phys, sizeof(cinergyt2->phys));
strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys));
cinergyt2->rc_input_event = KEY_MAX;
- cinergyt2->rc_last_code = ~0;
+ cinergyt2->rc_last_code = cpu_to_le32(~0);
INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc);
input_dev->name = DRIVER_NAME " remote control";
@@ -840,8 +844,8 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->keycodesize = 0;
input_dev->keycodemax = 0;
input_dev->id.bustype = BUS_USB;
- input_dev->id.vendor = cinergyt2->udev->descriptor.idVendor;
- input_dev->id.product = cinergyt2->udev->descriptor.idProduct;
+ input_dev->id.vendor = le16_to_cpu(cinergyt2->udev->descriptor.idVendor);
+ input_dev->id.product = le16_to_cpu(cinergyt2->udev->descriptor.idProduct);
input_dev->id.version = 1;
input_dev->dev.parent = &cinergyt2->udev->dev;
@@ -889,18 +893,16 @@ static void cinergyt2_query (struct work_struct *work)
char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS };
struct dvbt_get_status_msg *s = &cinergyt2->status;
uint8_t lock_bits;
- uint32_t unc;
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
return;
- unc = s->uncorrected_block_count;
lock_bits = s->lock_bits;
cinergyt2_command(cinergyt2, cmd, sizeof(cmd), (char *) s, sizeof(*s));
- unc += le32_to_cpu(s->uncorrected_block_count);
- s->uncorrected_block_count = unc;
+ cinergyt2->uncorrected_block_count +=
+ le32_to_cpu(s->uncorrected_block_count);
if (lock_bits != s->lock_bits) {
wake_up_interruptible(&cinergyt2->poll_wq);
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index b0d347d..eb91fd8 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -247,7 +247,7 @@ struct dmx_demux {
void* priv; /* Pointer to private data of the API client */
int (*open) (struct dmx_demux* demux);
int (*close) (struct dmx_demux* demux);
- int (*write) (struct dmx_demux* demux, const char* buf, size_t count);
+ int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
int (*allocate_ts_feed) (struct dmx_demux* demux,
struct dmx_ts_feed** feed,
dmx_ts_cb callback);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index df5bef6..1cf9fcb 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -96,7 +96,7 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
if (avail > todo)
avail = todo;
- ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1);
+ ret = dvb_ringbuffer_read_user(src, buf, avail);
if (ret < 0)
break;
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 8cbdb0e..8e5dd7b 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -910,15 +910,21 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
int curdelay = 100000000;
int slot;
+ /* Beware of too high polling frequency, because one polling
+ * call might take several hundred milliseconds until timeout!
+ */
for (slot = 0; slot < ca->slot_count; slot++) {
switch (ca->slot_info[slot].slot_state) {
default:
case DVB_CA_SLOTSTATE_NONE:
+ delay = HZ * 60; /* 60s */
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+ delay = HZ * 5; /* 5s */
+ break;
case DVB_CA_SLOTSTATE_INVALID:
- delay = HZ * 60;
- if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
- delay = HZ / 10;
- }
+ delay = HZ * 60; /* 60s */
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+ delay = HZ / 10; /* 100ms */
break;
case DVB_CA_SLOTSTATE_UNINITIALISED:
@@ -926,19 +932,17 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
case DVB_CA_SLOTSTATE_VALIDATE:
case DVB_CA_SLOTSTATE_WAITFR:
case DVB_CA_SLOTSTATE_LINKINIT:
- delay = HZ / 10;
+ delay = HZ / 10; /* 100ms */
break;
case DVB_CA_SLOTSTATE_RUNNING:
- delay = HZ * 60;
- if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
- delay = HZ / 10;
- }
+ delay = HZ * 60; /* 60s */
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+ delay = HZ / 10; /* 100ms */
if (ca->open) {
if ((!ca->slot_info[slot].da_irq_supported) ||
- (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) {
- delay = HZ / 10;
- }
+ (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA)))
+ delay = HZ / 10; /* 100ms */
}
break;
}
@@ -1353,7 +1357,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca,
idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
while (idx != -1) {
- dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+ dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
if (connection_id == -1)
connection_id = hdr[0];
if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
@@ -1434,7 +1438,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
goto exit;
}
- dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+ dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
if (connection_id == -1)
connection_id = hdr[0];
if (hdr[0] == connection_id) {
@@ -1445,8 +1449,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
fraglen -= 2;
}
- if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2,
- (u8 *)buf + pktlen, fraglen, 1)) < 0) {
+ if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2,
+ buf + pktlen, fraglen)) < 0) {
goto exit;
}
pktlen += fraglen;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 934e15f..e2eca0b 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1056,16 +1056,27 @@ static int dvbdmx_close(struct dmx_demux *demux)
return 0;
}
-static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
+static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count)
{
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+ void *p;
if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
return -EINVAL;
- if (mutex_lock_interruptible(&dvbdemux->mutex))
+ p = kmalloc(count, GFP_USER);
+ if (!p)
+ return -ENOMEM;
+ if (copy_from_user(p, buf, count)) {
+ kfree(p);
+ return -EFAULT;
+ }
+ if (mutex_lock_interruptible(&dvbdemux->mutex)) {
+ kfree(p);
return -ERESTARTSYS;
- dvb_dmx_swfilter(dvbdemux, (u8 *)buf, count);
+ }
+ dvb_dmx_swfilter(dvbdemux, p, count);
+ kfree(p);
mutex_unlock(&dvbdemux->mutex);
if (signal_pending(current))
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 56d871c..c93019c 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -168,7 +168,7 @@ struct dvb_net_priv {
* stolen from eth.c out of the linux kernel, hacked for dvb-device
* by Michael Holzt <kju@debian.org>
*/
-static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
+static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
struct net_device *dev)
{
struct ethhdr *eth;
@@ -277,10 +277,10 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
if(ext_len >= 0) {
p->ule_next_hdr += ext_len;
if (!p->ule_bridged) {
- p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
+ p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr);
p->ule_next_hdr += 2;
} else {
- p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+ p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
/* This assures the extension handling loop will terminate. */
}
}
@@ -294,7 +294,7 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
if (ule_optional_ext_handlers[htype])
(void)ule_optional_ext_handlers[htype]( p );
p->ule_next_hdr += ext_len;
- p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
+ p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) );
/*
* note: the length of the next header type is included in the
* length of THIS optional extension header
@@ -594,8 +594,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
/* Check for complete payload. */
if (priv->ule_sndu_remain <= 0) {
/* Check CRC32, we've got it in our skb already. */
- unsigned short ulen = htons(priv->ule_sndu_len);
- unsigned short utype = htons(priv->ule_sndu_type);
+ __be16 ulen = htons(priv->ule_sndu_len);
+ __be16 utype = htons(priv->ule_sndu_type);
const u8 *tail;
struct kvec iov[3] = {
{ &ulen, sizeof ulen },
@@ -606,7 +606,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_dbit) {
/* Set D-bit for CRC32 verification,
* if it was set originally. */
- ulen |= 0x0080;
+ ulen |= htons(0x8000);
}
ule_crc = iov_crc32(ule_crc, iov, 3);
@@ -1133,7 +1133,7 @@ static void wq_set_multicast_list (struct work_struct *work)
dvb_net_feed_stop(dev);
priv->rx_mode = RX_MODE_UNI;
- netif_tx_lock_bh(dev);
+ netif_addr_lock_bh(dev);
if (dev->flags & IFF_PROMISC) {
dprintk("%s: promiscuous mode\n", dev->name);
@@ -1158,7 +1158,7 @@ static void wq_set_multicast_list (struct work_struct *work)
}
}
- netif_tx_unlock_bh(dev);
+ netif_addr_unlock_bh(dev);
dvb_net_feed_start(dev);
}
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 872985b..584bbd1 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -107,35 +107,43 @@ void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
wake_up(&rbuf->queue);
}
-
-
-ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, int usermem)
+ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
{
size_t todo = len;
size_t split;
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
- if (!usermem)
- memcpy(buf, rbuf->data+rbuf->pread, split);
- else
- if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+ return -EFAULT;
buf += split;
todo -= split;
rbuf->pread = 0;
}
- if (!usermem)
- memcpy(buf, rbuf->data+rbuf->pread, todo);
- else
- if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
+ return -EFAULT;
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
return len;
}
+void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
+{
+ size_t todo = len;
+ size_t split;
+
+ split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
+ if (split > 0) {
+ memcpy(buf, rbuf->data+rbuf->pread, split);
+ buf += split;
+ todo -= split;
+ rbuf->pread = 0;
+ }
+ memcpy(buf, rbuf->data+rbuf->pread, todo);
+
+ rbuf->pread = (rbuf->pread + todo) % rbuf->size;
+}
ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
@@ -171,8 +179,8 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
return status;
}
-ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem)
+ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+ int offset, u8 __user *buf, size_t len)
{
size_t todo;
size_t split;
@@ -187,21 +195,40 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
todo = len;
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) {
- if (!usermem)
- memcpy(buf, rbuf->data+idx, split);
- else
- if (copy_to_user(buf, rbuf->data+idx, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+idx, split))
+ return -EFAULT;
buf += split;
todo -= split;
idx = 0;
}
- if (!usermem)
- memcpy(buf, rbuf->data+idx, todo);
- else
- if (copy_to_user(buf, rbuf->data+idx, todo))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+idx, todo))
+ return -EFAULT;
+
+ return len;
+}
+ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
+ int offset, u8* buf, size_t len)
+{
+ size_t todo;
+ size_t split;
+ size_t pktlen;
+
+ pktlen = rbuf->data[idx] << 8;
+ pktlen |= rbuf->data[(idx + 1) % rbuf->size];
+ if (offset > pktlen) return -EINVAL;
+ if ((offset + len) > pktlen) len = pktlen - offset;
+
+ idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
+ todo = len;
+ split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
+ if (split > 0) {
+ memcpy(buf, rbuf->data+idx, split);
+ buf += split;
+ todo -= split;
+ idx = 0;
+ }
+ memcpy(buf, rbuf->data+idx, todo);
return len;
}
@@ -266,5 +293,6 @@ EXPORT_SYMBOL(dvb_ringbuffer_empty);
EXPORT_SYMBOL(dvb_ringbuffer_free);
EXPORT_SYMBOL(dvb_ringbuffer_avail);
EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
+EXPORT_SYMBOL(dvb_ringbuffer_read_user);
EXPORT_SYMBOL(dvb_ringbuffer_read);
EXPORT_SYMBOL(dvb_ringbuffer_write);
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index 8908262..41f04da 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -61,7 +61,7 @@ struct dvb_ringbuffer {
** *** read min. 1000, max. <bufsize> bytes ***
** avail = dvb_ringbuffer_avail(rbuf);
** if (avail >= 1000)
-** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0);
+** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
** else
** ...
**
@@ -114,8 +114,10 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
** <usermem> specifies whether <buf> resides in user space
** returns number of bytes transferred or -EFAULT
*/
-extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
- size_t len, int usermem);
+extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
+ u8 __user *buf, size_t len);
+extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
+ u8 *buf, size_t len);
/* write routines & macros */
@@ -157,8 +159,10 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
* <usermem> Set to 1 if <buf> is in userspace.
* returns Number of bytes read, or -EFAULT.
*/
+extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+ int offset, u8 __user *buf, size_t len);
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem);
+ int offset, u8 *buf, size_t len);
/**
* Dispose of a packet in the ring buffer.
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 8b56d92..e713277 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -32,6 +32,7 @@
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
+#include <linux/smp_lock.h>
#include "dvbdev.h"
static int dvbdev_debug;
@@ -74,6 +75,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
+ lock_kernel();
dvbdev = dvbdev_find_device (iminor(inode));
if (dvbdev && dvbdev->fops) {
@@ -90,8 +92,10 @@ static int dvb_device_open(struct inode *inode, struct file *file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
+ unlock_kernel();
return err;
}
+ unlock_kernel();
return -ENODEV;
}
@@ -229,9 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
mutex_unlock(&dvbdev_register_lock);
- clsdev = device_create(dvb_class, adap->device,
+ clsdev = device_create_drvdata(dvb_class, adap->device,
MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
- "dvb%d.%s%d", adap->num, dnames[type], id);
+ NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
if (IS_ERR(clsdev)) {
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 4c1cff9..e84152b 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -1,7 +1,6 @@
config DVB_USB
tristate "Support for various USB DVB devices"
- depends on DVB_CORE && USB && I2C
- select FW_LOADER
+ depends on DVB_CORE && USB && I2C && INPUT
help
By enabling this you will be able to choose the various supported
USB1.1 and USB2.0 DVB devices.
@@ -75,6 +74,7 @@ config DVB_USB_DIB0700
select DVB_DIB3000MC
select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0070
help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -106,6 +106,8 @@ config DVB_USB_CXUSB
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -119,6 +121,8 @@ config DVB_USB_M920X
depends on DVB_USB
select DVB_MT352 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
+ select DVB_TDA1004X if !DVB_FE_CUSTOMISE
help
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
Currently, only devices with a product id of
@@ -240,3 +244,21 @@ config DVB_USB_AF9005_REMOTE
Say Y here to support the default remote control decoding for the
Afatech AF9005 based receiver.
+config DVB_USB_DW2102
+ tristate "DvbWorld 2102 DVB-S USB2.0 receiver"
+ depends on DVB_USB
+ select DVB_STV0299 if !DVB_FE_CUSTOMISE
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver.
+
+config DVB_USB_ANYSEE
+ tristate "Anysee DVB-T/C USB2.0 support"
+ depends on DVB_USB
+ select DVB_PLL if !DVB_FE_CUSTOMISE
+ select DVB_MT352 if !DVB_FE_CUSTOMISE
+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+ select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+ help
+ Say Y here to support the Anysee E30, Anysee E30 Plus or
+ Anysee E30 C Plus DVB USB2.0 receiver.
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index c6511a6..e206f1e 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -61,6 +61,12 @@ obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
dvb-usb-af9005-remote-objs = af9005-remote.o
obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
+dvb-usb-anysee-objs = anysee.o
+obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
+
+dvb-usb-dw2102-objs = dw2102.o
+obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
+
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028
EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
new file mode 100644
index 0000000..2f408d2
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -0,0 +1,553 @@
+/*
+ * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * 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.
+ *
+ * TODO:
+ * - add smart card reader support for Conditional Access (CA)
+ *
+ * Card reader in Anysee is nothing more than ISO 7816 card reader.
+ * There is no hardware CAM in any Anysee device sold.
+ * In my understanding it should be implemented by making own module
+ * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
+ * module registers serial interface that can be used to communicate
+ * with any ISO 7816 smart card.
+ *
+ * Any help according to implement serial smart card reader support
+ * is highly welcome!
+ */
+
+#include "anysee.h"
+#include "tda1002x.h"
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "zl10353.h"
+
+/* debug */
+static int dvb_usb_anysee_debug;
+module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static struct mutex anysee_usb_mutex;
+
+static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
+ u8 *rbuf, u8 rlen)
+{
+ struct anysee_state *state = d->priv;
+ int act_len, ret;
+ u8 buf[64];
+
+ if (slen > sizeof(buf))
+ slen = sizeof(buf);
+ memcpy(&buf[0], sbuf, slen);
+ buf[60] = state->seq++;
+
+ if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
+ return -EAGAIN;
+
+ /* We need receive one message more after dvb_usb_generic_rw due
+ to weird transaction flow, which is 1 x send + 2 x receive. */
+ ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
+
+ if (!ret) {
+ /* receive 2nd answer */
+ ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
+ d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
+ &act_len, 2000);
+ if (ret)
+ err("%s: recv bulk message failed: %d", __func__, ret);
+ else {
+ deb_xfer("<<< ");
+ debug_dump(buf, act_len, deb_xfer);
+ }
+ }
+
+ /* read request, copy returned data to return buf */
+ if (!ret && rbuf && rlen)
+ memcpy(rbuf, buf, rlen);
+
+ mutex_unlock(&anysee_usb_mutex);
+
+ return ret;
+}
+
+static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
+{
+ u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01};
+ int ret;
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1);
+ deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val);
+ return ret;
+}
+
+static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
+{
+ u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val};
+ deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val);
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
+{
+ u8 buf[] = {CMD_GET_HW_INFO};
+ return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3);
+}
+
+static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00};
+ deb_info("%s: onoff:%02x\n", __func__, onoff);
+ return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval)
+{
+ u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval};
+ deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval);
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
+{
+ u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff};
+ deb_info("%s: onoff:%02x\n", __func__, onoff);
+ return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_init(struct dvb_usb_device *d)
+{
+ int ret;
+ /* LED light */
+ ret = anysee_led_ctrl(d, 0x01, 0x03);
+ if (ret)
+ return ret;
+
+ /* enable IR */
+ ret = anysee_ir_ctrl(d, 1);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/* I2C */
+static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int ret, inc, i = 0;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ while (i < num) {
+ if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+ u8 buf[6];
+ buf[0] = CMD_I2C_READ;
+ buf[1] = msg[i].addr + 1;
+ buf[2] = msg[i].buf[0];
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x01;
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
+ msg[i+1].len);
+ inc = 2;
+ } else {
+ u8 buf[4+msg[i].len];
+ buf[0] = CMD_I2C_WRITE;
+ buf[1] = msg[i].addr;
+ buf[2] = msg[i].len;
+ buf[3] = 0x01;
+ memcpy(&buf[4], msg[i].buf, msg[i].len);
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+ inc = 1;
+ }
+ if (ret)
+ return ret;
+
+ i += inc;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+
+ return i;
+}
+
+static u32 anysee_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm anysee_i2c_algo = {
+ .master_xfer = anysee_master_xfer,
+ .functionality = anysee_i2c_func,
+};
+
+static int anysee_mt352_demod_init(struct dvb_frontend *fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
+/* Callbacks for DVB USB */
+static struct tda10023_config anysee_tda10023_config = {
+ .demod_address = 0x1a,
+ .invert = 0,
+ .xtal = 16000000,
+ .pll_m = 11,
+ .pll_p = 3,
+ .pll_n = 1,
+ .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
+ .deltaf = 0xfeeb,
+};
+
+static struct mt352_config anysee_mt352_config = {
+ .demod_address = 0x1e,
+ .demod_init = anysee_mt352_demod_init,
+};
+
+static struct zl10353_config anysee_zl10353_config = {
+ .demod_address = 0x1e,
+ .parallel_ts = 1,
+};
+
+static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ int ret;
+ struct anysee_state *state = adap->dev->priv;
+ u8 hw_info[3];
+ u8 io_d; /* IO port D */
+
+ /* check which hardware we have
+ We must do this call two times to get reliable values (hw bug). */
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ return ret;
+ ret = anysee_get_hw_info(adap->dev, hw_info);
+ if (ret)
+ return ret;
+
+ /* Meaning of these info bytes are guessed. */
+ info("firmware version:%d.%d.%d hardware id:%d",
+ 0, hw_info[1], hw_info[2], hw_info[0]);
+
+ ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */
+ if (ret)
+ return ret;
+ deb_info("%s: IO port D:%02x\n", __func__, io_d);
+
+ /* Select demod using trial and error method. */
+
+ /* Try to attach demodulator in following order:
+ model demod hw firmware
+ 1. E30 MT352 02 0.2.1
+ 2. E30 ZL10353 02 0.2.1
+ 3. E30 Plus ZL10353 06 0.1.0
+ 4. E30C Plus TDA10023 0a 0.1.0 rev 0.2
+ 4. E30C Plus TDA10023 0f 0.1.2 rev 0.4
+ */
+
+ /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
+ adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_THOMSON_DTT7579;
+ return 0;
+ }
+
+ /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
+ adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_THOMSON_DTT7579;
+ return 0;
+ }
+
+ /* connect demod on IO port D for TDA10023 & ZL10353 */
+ ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
+ if (ret)
+ return ret;
+
+ /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
+ adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_THOMSON_DTT7579;
+ return 0;
+ }
+
+ /* IO port E - E30C rev 0.4 board requires this */
+ ret = anysee_write_reg(adap->dev, 0xb1, 0xa7);
+ if (ret)
+ return ret;
+
+ /* Philips TDA10023 DVB-C demod */
+ adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
+ &adap->dev->i2c_adap, 0x48);
+ if (adap->fe != NULL) {
+ state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
+ return 0;
+ }
+
+ /* return IO port D to init value for safe */
+ ret = anysee_write_reg(adap->dev, 0xb0, io_d);
+ if (ret)
+ return ret;
+
+ err("Unkown Anysee version: %02x %02x %02x. "\
+ "Please report the <linux-dvb@linuxtv.org>.",
+ hw_info[0], hw_info[1], hw_info[2]);
+
+ return -ENODEV;
+}
+
+static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ struct anysee_state *state = adap->dev->priv;
+ deb_info("%s: \n", __func__);
+
+ switch (state->tuner) {
+ case DVB_PLL_THOMSON_DTT7579:
+ /* Thomson dtt7579 (not sure) PLL inside of:
+ Samsung DNOS404ZH102A NIM
+ Samsung DNOS404ZH103A NIM */
+ dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+ NULL, DVB_PLL_THOMSON_DTT7579);
+ break;
+ case DVB_PLL_SAMSUNG_DTOS403IH102A:
+ /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */
+ dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
+ &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+ break;
+ }
+
+ return 0;
+}
+
+static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 buf[] = {CMD_GET_IR_CODE};
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ u8 ircode[2];
+ int i, ret;
+
+ ret = anysee_ctrl_msg(d, buf, sizeof(buf), &ircode[0], 2);
+ if (ret)
+ return ret;
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == ircode[0] &&
+ keymap[i].data == ircode[1]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static struct dvb_usb_rc_key anysee_rc_keys[] = {
+ { 0x01, 0x00, KEY_0 },
+ { 0x01, 0x01, KEY_1 },
+ { 0x01, 0x02, KEY_2 },
+ { 0x01, 0x03, KEY_3 },
+ { 0x01, 0x04, KEY_4 },
+ { 0x01, 0x05, KEY_5 },
+ { 0x01, 0x06, KEY_6 },
+ { 0x01, 0x07, KEY_7 },
+ { 0x01, 0x08, KEY_8 },
+ { 0x01, 0x09, KEY_9 },
+ { 0x01, 0x0a, KEY_POWER },
+ { 0x01, 0x0b, KEY_DOCUMENTS }, /* * */
+ { 0x01, 0x19, KEY_FAVORITES },
+ { 0x01, 0x20, KEY_SLEEP },
+ { 0x01, 0x21, KEY_MODE }, /* 4:3 / 16:9 select */
+ { 0x01, 0x22, KEY_ZOOM },
+ { 0x01, 0x47, KEY_TEXT },
+ { 0x01, 0x16, KEY_TV }, /* TV / radio select */
+ { 0x01, 0x1e, KEY_LANGUAGE }, /* Second Audio Program */
+ { 0x01, 0x1a, KEY_SUBTITLE },
+ { 0x01, 0x1b, KEY_CAMERA }, /* screenshot */
+ { 0x01, 0x42, KEY_MUTE },
+ { 0x01, 0x0e, KEY_MENU },
+ { 0x01, 0x0f, KEY_EPG },
+ { 0x01, 0x17, KEY_INFO },
+ { 0x01, 0x10, KEY_EXIT },
+ { 0x01, 0x13, KEY_VOLUMEUP },
+ { 0x01, 0x12, KEY_VOLUMEDOWN },
+ { 0x01, 0x11, KEY_CHANNELUP },
+ { 0x01, 0x14, KEY_CHANNELDOWN },
+ { 0x01, 0x15, KEY_OK },
+ { 0x01, 0x1d, KEY_RED },
+ { 0x01, 0x1f, KEY_GREEN },
+ { 0x01, 0x1c, KEY_YELLOW },
+ { 0x01, 0x44, KEY_BLUE },
+ { 0x01, 0x0c, KEY_SHUFFLE }, /* snapshot */
+ { 0x01, 0x48, KEY_STOP },
+ { 0x01, 0x50, KEY_PLAY },
+ { 0x01, 0x51, KEY_PAUSE },
+ { 0x01, 0x49, KEY_RECORD },
+ { 0x01, 0x18, KEY_PREVIOUS }, /* |<< */
+ { 0x01, 0x0d, KEY_NEXT }, /* >>| */
+ { 0x01, 0x24, KEY_PROG1 }, /* F1 */
+ { 0x01, 0x25, KEY_PROG2 }, /* F2 */
+};
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties anysee_properties;
+
+static int anysee_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct dvb_usb_device *d;
+ struct usb_host_interface *alt;
+ int ret;
+
+ mutex_init(&anysee_usb_mutex);
+
+ /* There is one interface with two alternate settings.
+ Alternate setting 0 is for bulk transfer.
+ Alternate setting 1 is for isochronous transfer.
+ We use bulk transfer (alternate setting 0). */
+ if (intf->num_altsetting < 1)
+ return -ENODEV;
+
+ ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
+ adapter_nr);
+ if (ret)
+ return ret;
+
+ alt = usb_altnum_to_altsetting(intf, 0);
+ if (alt == NULL) {
+ deb_info("%s: no alt found!\n", __func__);
+ return -ENODEV;
+ }
+
+ ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+ alt->desc.bAlternateSetting);
+ if (ret)
+ return ret;
+
+ if (d)
+ ret = anysee_init(d);
+
+ return ret;
+}
+
+static struct usb_device_id anysee_table [] = {
+ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) },
+ { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, anysee_table);
+
+static struct dvb_usb_device_properties anysee_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+
+ .size_of_priv = sizeof(struct anysee_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = anysee_streaming_ctrl,
+ .frontend_attach = anysee_frontend_attach,
+ .tuner_attach = anysee_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 512,
+ }
+ }
+ },
+ }
+ },
+
+ .rc_key_map = anysee_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(anysee_rc_keys),
+ .rc_query = anysee_rc_query,
+ .rc_interval = 200, /* windows driver uses 500ms */
+
+ .i2c_algo = &anysee_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 1,
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ .name = "Anysee DVB USB2.0",
+ .cold_ids = {NULL},
+ .warm_ids = {&anysee_table[0],
+ &anysee_table[1], NULL},
+ },
+ }
+};
+
+static struct usb_driver anysee_driver = {
+ .name = "dvb_usb_anysee",
+ .probe = anysee_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = anysee_table,
+};
+
+/* module stuff */
+static int __init anysee_module_init(void)
+{
+ int ret;
+
+ ret = usb_register(&anysee_driver);
+ if (ret)
+ err("%s: usb_register failed. Error number %d", __func__, ret);
+
+ return ret;
+}
+
+static void __exit anysee_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&anysee_driver);
+}
+
+module_init(anysee_module_init);
+module_exit(anysee_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
new file mode 100644
index 0000000..7ca01ff
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/anysee.h
@@ -0,0 +1,304 @@
+/*
+ * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * 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.
+ *
+ * TODO:
+ * - add smart card reader support for Conditional Access (CA)
+ *
+ * Card reader in Anysee is nothing more than ISO 7816 card reader.
+ * There is no hardware CAM in any Anysee device sold.
+ * In my understanding it should be implemented by making own module
+ * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
+ * module registers serial interface that can be used to communicate
+ * with any ISO 7816 smart card.
+ *
+ * Any help according to implement serial smart card reader support
+ * is highly welcome!
+ */
+
+#ifndef _DVB_USB_ANYSEE_H_
+#define _DVB_USB_ANYSEE_H_
+
+#define DVB_USB_LOG_PREFIX "anysee"
+#include "dvb-usb.h"
+
+#define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
+#define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
+#define deb_rc(args...) dprintk(dvb_usb_anysee_debug, 0x04, args)
+#define deb_reg(args...) dprintk(dvb_usb_anysee_debug, 0x08, args)
+#define deb_i2c(args...) dprintk(dvb_usb_anysee_debug, 0x10, args)
+#define deb_fw(args...) dprintk(dvb_usb_anysee_debug, 0x20, args)
+
+enum cmd {
+ CMD_I2C_READ = 0x33,
+ CMD_I2C_WRITE = 0x31,
+ CMD_REG_READ = 0xb0,
+ CMD_REG_WRITE = 0xb1,
+ CMD_STREAMING_CTRL = 0x12,
+ CMD_LED_AND_IR_CTRL = 0x16,
+ CMD_GET_IR_CODE = 0x41,
+ CMD_GET_HW_INFO = 0x19,
+ CMD_SMARTCARD = 0x34,
+};
+
+struct anysee_state {
+ u8 tuner;
+ u8 seq;
+};
+
+#endif
+
+/***************************************************************************
+ * USB API description (reverse engineered)
+ ***************************************************************************
+
+Transaction flow:
+=================
+BULK[00001] >>> REQUEST PACKET 64 bytes
+BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY)
+BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY)
+
+General reply packet(s) are always used if not own reply defined.
+
+============================================================================
+| 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY)
+============================================================================
+| 00 | reply data (if any) from previous transaction
+| | Just same reply packet as returned during previous transaction.
+| | Needed only if reply is missed in previous transaction.
+| | Just skip normally.
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY)
+============================================================================
+| 00 | reply data (if any)
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | I2C WRITE REQUEST PACKET
+============================================================================
+| 00 | 0x31 I2C write command
+----------------------------------------------------------------------------
+| 01 | i2c address
+----------------------------------------------------------------------------
+| 02 | data length
+| | 0x02 (for typical I2C reg / val pair)
+----------------------------------------------------------------------------
+| 03 | 0x01
+----------------------------------------------------------------------------
+| 04- | data
+----------------------------------------------------------------------------
+| -59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | I2C READ REQUEST PACKET
+============================================================================
+| 00 | 0x33 I2C read command
+----------------------------------------------------------------------------
+| 01 | i2c address + 1
+----------------------------------------------------------------------------
+| 02 | register
+----------------------------------------------------------------------------
+| 03 | 0x00
+----------------------------------------------------------------------------
+| 04 | 0x00
+----------------------------------------------------------------------------
+| 05 | 0x01
+----------------------------------------------------------------------------
+| 06-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET
+============================================================================
+| 00 | 0xb1 register write command
+----------------------------------------------------------------------------
+| 01-02 | register
+----------------------------------------------------------------------------
+| 03 | 0x01
+----------------------------------------------------------------------------
+| 04 | value
+----------------------------------------------------------------------------
+| 05-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET
+============================================================================
+| 00 | 0xb0 register read command
+----------------------------------------------------------------------------
+| 01-02 | register
+----------------------------------------------------------------------------
+| 03 | 0x01
+----------------------------------------------------------------------------
+| 04-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | LED CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x16 LED and IR control command
+----------------------------------------------------------------------------
+| 01 | 0x01 (LED)
+----------------------------------------------------------------------------
+| 03 | 0x00 blink
+| | 0x01 lights continuously
+----------------------------------------------------------------------------
+| 04 | blink interval
+| | 0x00 fastest (looks like LED lights continuously)
+| | 0xff slowest
+----------------------------------------------------------------------------
+| 05-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | IR CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x16 LED and IR control command
+----------------------------------------------------------------------------
+| 01 | 0x02 (IR)
+----------------------------------------------------------------------------
+| 03 | 0x00 IR disabled
+| | 0x01 IR enabled
+----------------------------------------------------------------------------
+| 04-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | STREAMING CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x12 streaming control command
+----------------------------------------------------------------------------
+| 01 | 0x00 streaming disabled
+| | 0x01 streaming enabled
+----------------------------------------------------------------------------
+| 02 | 0x00
+----------------------------------------------------------------------------
+| 03-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | REMOTE CONTROL REQUEST PACKET
+============================================================================
+| 00 | 0x41 remote control command
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | REMOTE CONTROL REPLY PACKET
+============================================================================
+| 00 | 0x00 code not received
+| | 0x01 code received
+----------------------------------------------------------------------------
+| 01 | remote control code
+----------------------------------------------------------------------------
+| 02-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GET HARDWARE INFO REQUEST PACKET
+============================================================================
+| 00 | 0x19 get hardware info command
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GET HARDWARE INFO REPLY PACKET
+============================================================================
+| 00 | hardware id
+----------------------------------------------------------------------------
+| 01-02 | firmware version
+----------------------------------------------------------------------------
+| 03-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | SMART CARD READER PACKET
+============================================================================
+| 00 | 0x34 smart card reader command
+----------------------------------------------------------------------------
+| xx |
+----------------------------------------------------------------------------
+| xx-59 | don't care
+----------------------------------------------------------------------------
+| 60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+*/
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
index 2ccb90f..eb34cc3 100644
--- a/drivers/media/dvb/dvb-usb/au6610.c
+++ b/drivers/media/dvb/dvb-usb/au6610.c
@@ -1,24 +1,31 @@
-/* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver
+/*
+ * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
*
* Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
*
- * 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.
+ * 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.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * 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 "au6610.h"
-
#include "zl10353.h"
#include "qt1010.h"
/* debug */
static int dvb_usb_au6610_debug;
module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
@@ -42,9 +49,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
}
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
- USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, usb_buf,
- sizeof(usb_buf), AU6610_USB_TIMEOUT);
-
+ USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
+ usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT);
if (ret < 0)
return ret;
@@ -116,15 +122,6 @@ static struct i2c_algorithm au6610_i2c_algo = {
};
/* Callbacks for DVB USB */
-static int au6610_identify_state(struct usb_device *udev,
- struct dvb_usb_device_properties *props,
- struct dvb_usb_device_description **desc,
- int *cold)
-{
- *cold = 0;
- return 0;
-}
-
static struct zl10353_config au6610_zl10353_config = {
.demod_address = 0x0f,
.no_tuner = 1,
@@ -133,12 +130,12 @@ static struct zl10353_config au6610_zl10353_config = {
static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
{
- if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
- &adap->dev->i2c_adap)) != NULL) {
- return 0;
- }
+ adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe == NULL)
+ return -ENODEV;
- return -EIO;
+ return 0;
}
static struct qt1010_config au6610_qt1010_config = {
@@ -171,7 +168,7 @@ static int au6610_probe(struct usb_interface *intf,
alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
if (alt == NULL) {
- deb_rc("no alt found!\n");
+ deb_info("%s: no alt found!\n", __func__);
return -ENODEV;
}
ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
@@ -181,18 +178,19 @@ static int au6610_probe(struct usb_interface *intf,
return ret;
}
-
static struct usb_device_id au6610_table [] = {
{ USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, au6610_table);
+MODULE_DEVICE_TABLE(usb, au6610_table);
static struct dvb_usb_device_properties au6610_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
.usb_ctrl = DEVICE_SPECIFIC,
- .size_of_priv = 0,
- .identify_state = au6610_identify_state,
+
+ .size_of_priv = 0,
+
.num_adapters = 1,
.adapter = {
{
@@ -206,20 +204,22 @@ static struct dvb_usb_device_properties au6610_properties = {
.u = {
.isoc = {
.framesperurb = 40,
- .framesize = 942, /* maximum packet size */
- .interval = 1.25, /* 125 us */
+ .framesize = 942,
+ .interval = 1,
}
}
},
}
},
+
.i2c_algo = &au6610_i2c_algo,
+
.num_device_descs = 1,
.devices = {
{
- "Sigmatek DVB-110 DVB-T USB2.0",
- { &au6610_table[0], NULL },
- { NULL },
+ .name = "Sigmatek DVB-110 DVB-T USB2.0",
+ .cold_ids = {NULL},
+ .warm_ids = {&au6610_table[0], NULL},
},
}
};
@@ -236,12 +236,11 @@ static int __init au6610_module_init(void)
{
int ret;
- if ((ret = usb_register(&au6610_driver))) {
+ ret = usb_register(&au6610_driver);
+ if (ret)
err("usb_register failed. Error number %d", ret);
- return ret;
- }
- return 0;
+ return ret;
}
static void __exit au6610_module_exit(void)
@@ -250,10 +249,10 @@ static void __exit au6610_module_exit(void)
usb_deregister(&au6610_driver);
}
-module_init (au6610_module_init);
-module_exit (au6610_module_exit);
+module_init(au6610_module_init);
+module_exit(au6610_module_exit);
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610");
+MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h
index 4161b05..7849abe 100644
--- a/drivers/media/dvb/dvb-usb/au6610.h
+++ b/drivers/media/dvb/dvb-usb/au6610.h
@@ -1,10 +1,30 @@
+/*
+ * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
+ *
+ * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *
+ * 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 _DVB_USB_AU6610_H_
#define _DVB_USB_AU6610_H_
#define DVB_USB_LOG_PREFIX "au6610"
#include "dvb-usb.h"
-#define deb_rc(args...) dprintk(dvb_usb_au6610_debug,0x01,args)
+#define deb_info(args...) dprintk(dvb_usb_au6610_debug, 0x01, args)
#define AU6610_REQ_I2C_WRITE 0x14
#define AU6610_REQ_I2C_READ 0x13
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 720fcd1..578afce 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -24,6 +24,7 @@
* see Documentation/dvb/README.dvb-usb for more information
*/
#include <media/tuner.h>
+#include <linux/vmalloc.h>
#include "cxusb.h"
@@ -34,6 +35,7 @@
#include "zl10353.h"
#include "tuner-xc2028.h"
#include "tuner-simple.h"
+#include "mxl5005s.h"
/* debug */
static int dvb_usb_cxusb_debug;
@@ -42,9 +44,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_ST
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
-#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
- dprintk(dvb_usb_cxusb_debug,0x01,args)
+#define deb_info(args...) dprintk(dvb_usb_cxusb_debug, 0x03, args)
+#define deb_i2c(args...) dprintk(dvb_usb_cxusb_debug, 0x02, args)
static int cxusb_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
@@ -201,6 +202,46 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
}
+static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ int ret;
+ if (!onoff)
+ return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0);
+ if (d->state == DVB_USB_STATE_INIT &&
+ usb_set_interface(d->udev, 0, 0) < 0)
+ err("set interface failed");
+ do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
+ !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
+ !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
+ if (!ret) {
+ /* FIXME: We don't know why, but we need to configure the
+ * lgdt3303 with the register settings below on resume */
+ int i;
+ u8 buf, bufs[] = {
+ 0x0e, 0x2, 0x00, 0x7f,
+ 0x0e, 0x2, 0x02, 0xfe,
+ 0x0e, 0x2, 0x02, 0x01,
+ 0x0e, 0x2, 0x00, 0x03,
+ 0x0e, 0x2, 0x0d, 0x40,
+ 0x0e, 0x2, 0x0e, 0x87,
+ 0x0e, 0x2, 0x0f, 0x8e,
+ 0x0e, 0x2, 0x10, 0x01,
+ 0x0e, 0x2, 0x14, 0xd7,
+ 0x0e, 0x2, 0x47, 0x88,
+ };
+ msleep(20);
+ for (i = 0; i < sizeof(bufs)/sizeof(u8); i += 4/sizeof(u8)) {
+ ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE,
+ bufs+i, 4, &buf, 1);
+ if (ret)
+ break;
+ if (buf != 0x8)
+ return -EREMOTEIO;
+ }
+ }
+ return ret;
+}
+
static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
{
u8 b = 0;
@@ -232,6 +273,16 @@ static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
return 0;
}
+static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+ if (onoff)
+ cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0);
+ else
+ cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF,
+ NULL, 0, NULL, 0);
+ return 0;
+}
+
static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
@@ -422,6 +473,12 @@ static struct lgdt330x_config cxusb_lgdt3303_config = {
.demod_chip = LGDT3303,
};
+static struct lgdt330x_config cxusb_aver_lgdt3303_config = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .clock_polarity_flip = 2,
+};
+
static struct mt352_config cxusb_dee1601_config = {
.demod_address = 0x0f,
.demod_init = cxusb_dee1601_demod_init,
@@ -452,6 +509,24 @@ static struct mt352_config cxusb_mt352_xc3028_config = {
.demod_init = cxusb_mt352_demod_init,
};
+/* FIXME: needs tweaking */
+static struct mxl5005s_config aver_a868r_tuner = {
+ .i2c_address = 0x63,
+ .if_freq = 6000000UL,
+ .xtal_freq = CRYSTAL_FREQ_16000000HZ,
+ .agc_mode = MXL_SINGLE_AGC,
+ .tracking_filter = MXL_TF_C,
+ .rssi_enable = MXL_RSSI_ENABLE,
+ .cap_select = MXL_CAP_SEL_ENABLE,
+ .div_out = MXL_DIV_OUT_4,
+ .clock_out = MXL_CLOCK_OUT_DISABLE,
+ .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+ .top = MXL5005S_TOP_25P2,
+ .mod_mode = MXL_DIGITAL_MODE,
+ .if_mode = MXL_ZERO_IF,
+ .AgcMasterByte = 0x00,
+};
+
/* Callbacks for DVB USB */
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
@@ -532,6 +607,13 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ dvb_attach(mxl5005s_attach, adap->fe,
+ &adap->dev->i2c_adap, &aver_a868r_tuner);
+ return 0;
+}
+
static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
{
u8 b;
@@ -561,6 +643,16 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
return -EIO;
}
+static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe != NULL)
+ return 0;
+
+ return -EIO;
+}
+
static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
{
/* used in both lgz201 and th7579 */
@@ -700,12 +792,26 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
- fw->data[idoff + 2] =
+ struct firmware new_fw;
+ u8 *new_fw_data = vmalloc(fw->size);
+ int ret;
+
+ if (!new_fw_data)
+ return -ENOMEM;
+
+ memcpy(new_fw_data, fw->data, fw->size);
+ new_fw.size = fw->size;
+ new_fw.data = new_fw_data;
+
+ new_fw_data[idoff + 2] =
le16_to_cpu(udev->descriptor.idProduct) + 1;
- fw->data[idoff + 3] =
+ new_fw_data[idoff + 3] =
le16_to_cpu(udev->descriptor.idProduct) >> 8;
- return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
+ ret = usb_cypress_load_firmware(udev, &new_fw,
+ CYPRESS_FX2);
+ vfree(new_fw_data);
+ return ret;
}
}
@@ -721,6 +827,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
+static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -741,7 +848,10 @@ static int cxusb_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf,
&cxusb_bluebird_nano2_needsfirmware_properties,
- THIS_MODULE, NULL, adapter_nr))
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
+ 0)
return 0;
return -EINVAL;
@@ -764,6 +874,7 @@ static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
+ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1167,6 +1278,48 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
}
};
+static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .streaming_ctrl = cxusb_aver_streaming_ctrl,
+ .frontend_attach = cxusb_aver_lgdt3303_frontend_attach,
+ .tuner_attach = cxusb_mxl5003s_tuner_attach,
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ },
+ },
+ .power_ctrl = cxusb_aver_power_ctrl,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .num_device_descs = 1,
+ .devices = {
+ { "AVerMedia AVerTVHD Volar (A868R)",
+ { NULL },
+ { &cxusb_table[16], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 4768a2c..1a51eaf 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -20,6 +20,9 @@
#define CMD_STREAMING_ON 0x36
#define CMD_STREAMING_OFF 0x37
+#define CMD_AVER_STREAM_ON 0x18
+#define CMD_AVER_STREAM_OFF 0x19
+
#define CMD_GET_IR_CODE 0x47
#define CMD_ANALOG 0x50
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 3462238..3dd20bf 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -111,8 +111,8 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
s8 a;
int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_500_2) {
+ if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
+ adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
}
return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
@@ -402,8 +402,8 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
- if (desc->idVendor == USB_VID_PINNACLE &&
- desc->idProduct == USB_PID_PINNACLE_EXPRESSCARD_320CX)
+ if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
+ desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX))
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
@@ -845,8 +845,8 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *tun_i2c;
s8 a;
int if1=1220;
- if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_STICK) {
+ if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
+ adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) {
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
@@ -990,11 +990,12 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
/* STK7070P */
static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
{
- if (adap->dev->udev->descriptor.idVendor == USB_VID_PINNACLE &&
- adap->dev->udev->descriptor.idProduct == USB_PID_PINNACLE_PCTV72E)
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+ struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
+ p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
@@ -1116,6 +1117,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) },
{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
+ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1371,7 +1373,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}
},
- .num_device_descs = 2,
+ .num_device_descs = 3,
.devices = {
{ "DiBcom STK7070PD reference design",
{ &dib0700_usb_id_table[17], NULL },
@@ -1380,6 +1382,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Pinnacle PCTV Dual DVB-T Diversity Stick",
{ &dib0700_usb_id_table[18], NULL },
{ NULL },
+ },
+ { "Hauppauge Nova-TD Stick (52009)",
+ { &dib0700_usb_id_table[35], NULL },
+ { NULL },
}
}
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index e1112e3..733a7ff 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -127,7 +127,7 @@ int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
if ((*pos + hx->len + 4) >= fw->size)
return -EINVAL;
- hx->addr = le16_to_cpu( *((u16 *) &b[1]) );
+ hx->addr = b[1] | (b[2] << 8);
hx->type = b[3];
if (hx->type == 0x04) {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 23428cd..326f760 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -20,11 +20,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
}
strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
- d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
-#else
d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
-#endif
d->i2c_adap.algo = d->props.i2c_algo;
d->i2c_adap.algo_data = NULL;
d->i2c_adap.dev.parent = &d->udev->dev;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 34245d1..029b437 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -14,6 +14,7 @@
#define USB_VID_AFATECH 0x15a4
#define USB_VID_ALCOR_MICRO 0x058f
#define USB_VID_ALINK 0x05e3
+#define USB_VID_AMT 0x1c73
#define USB_VID_ANCHOR 0x0547
#define USB_VID_ANSONIC 0x10b9
#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
@@ -57,6 +58,7 @@
#define USB_PID_AFATECH_AF9005 0x9020
#define USB_VID_ALINK_DTU 0xf170
#define USB_PID_ANSONIC_DVBT_USB 0x6000
+#define USB_PID_ANYSEE 0x861f
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
@@ -132,9 +134,15 @@
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070
#define USB_PID_HAUPPAUGE_MYTV_T 0x7080
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
+#define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200
#define USB_PID_AVERMEDIA_EXPRESS 0xb568
#define USB_PID_AVERMEDIA_VOLAR 0xa807
#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
+#define USB_PID_AVERMEDIA_VOLAR_A868R 0xa868
+#define USB_PID_AVERMEDIA_MCE_USB_M038 0x1228
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
@@ -196,5 +204,6 @@
#define USB_PID_ASUS_U3000 0x171f
#define USB_PID_ASUS_U3100 0x173f
#define USB_PID_YUAN_EC372S 0x1edc
+#define USB_PID_DW2102 0x2102
#endif
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
new file mode 100644
index 0000000..a4d898b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -0,0 +1,425 @@
+/* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+* 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 <linux/version.h>
+#include "dw2102.h"
+#include "stv0299.h"
+#include "z0194a.h"
+
+#ifndef USB_PID_DW2102
+#define USB_PID_DW2102 0x2102
+#endif
+
+#define DW2102_READ_MSG 0
+#define DW2102_WRITE_MSG 1
+
+#define REG_1F_SYMBOLRATE_BYTE0 0x1f
+#define REG_20_SYMBOLRATE_BYTE1 0x20
+#define REG_21_SYMBOLRATE_BYTE2 0x21
+
+#define DW2102_VOLTAGE_CTRL (0x1800)
+#define DW2102_RC_QUERY (0x1a00)
+
+struct dw2102_state {
+ u32 last_key_pressed;
+};
+struct dw2102_rc_keys {
+ u32 keycode;
+ u32 event;
+};
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value,
+ u8 *data, u16 len, int flags)
+{
+ int ret;
+ u8 u8buf[len];
+
+ unsigned int pipe = (flags == DW2102_READ_MSG) ?
+ usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
+ u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
+
+ if (flags == DW2102_WRITE_MSG)
+ memcpy(u8buf, data, len);
+ ret = usb_control_msg(dev, pipe, request,
+ request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000);
+
+ if (flags == DW2102_READ_MSG)
+ memcpy(data, u8buf, len);
+ return ret;
+}
+
+/* I2C */
+
+static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ int num)
+{
+struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int i = 0, ret = 0;
+ u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
+ u8 request;
+ u16 value;
+
+ if (!d)
+ return -ENODEV;
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ switch (num) {
+ case 2:
+ /* read stv0299 register */
+ request = 0xb5;
+ value = msg[0].buf[0];/* register */
+ for (i = 0; i < msg[1].len; i++) {
+ value = value + i;
+ ret = dw2102_op_rw(d->udev, 0xb5,
+ value, buf6, 2, DW2102_READ_MSG);
+ msg[1].buf[i] = buf6[0];
+
+ }
+ break;
+ case 1:
+ switch (msg[0].addr) {
+ case 0x68:
+ /* write to stv0299 register */
+ buf6[0] = 0x2a;
+ buf6[1] = msg[0].buf[0];
+ buf6[2] = msg[0].buf[1];
+ ret = dw2102_op_rw(d->udev, 0xb2,
+ 0, buf6, 3, DW2102_WRITE_MSG);
+ break;
+ case 0x60:
+ if (msg[0].flags == 0) {
+ /* write to tuner pll */
+ buf6[0] = 0x2c;
+ buf6[1] = 5;
+ buf6[2] = 0xc0;
+ buf6[3] = msg[0].buf[0];
+ buf6[4] = msg[0].buf[1];
+ buf6[5] = msg[0].buf[2];
+ buf6[6] = msg[0].buf[3];
+ ret = dw2102_op_rw(d->udev, 0xb2,
+ 0, buf6, 7, DW2102_WRITE_MSG);
+ } else {
+ /* write to tuner pll */
+ ret = dw2102_op_rw(d->udev, 0xb5,
+ 0, buf6, 1, DW2102_READ_MSG);
+ msg[0].buf[0] = buf6[0];
+ }
+ break;
+ case (DW2102_RC_QUERY):
+ ret = dw2102_op_rw(d->udev, 0xb8,
+ 0, buf6, 2, DW2102_READ_MSG);
+ msg[0].buf[0] = buf6[0];
+ msg[0].buf[1] = buf6[1];
+ break;
+ case (DW2102_VOLTAGE_CTRL):
+ buf6[0] = 0x30;
+ buf6[1] = msg[0].buf[0];
+ ret = dw2102_op_rw(d->udev, 0xb2,
+ 0, buf6, 2, DW2102_WRITE_MSG);
+ break;
+ }
+
+ break;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ return num;
+}
+
+static u32 dw2102_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dw2102_i2c_algo = {
+ .master_xfer = dw2102_i2c_transfer,
+ .functionality = dw2102_i2c_func,
+};
+
+static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ static u8 command_13v[1] = {0x00};
+ static u8 command_18v[1] = {0x01};
+ struct i2c_msg msg[] = {
+ {.addr = DW2102_VOLTAGE_CTRL, .flags = 0,
+ .buf = command_13v, .len = 1},
+ };
+
+ struct dvb_usb_adapter *udev_adap =
+ (struct dvb_usb_adapter *)(fe->dvb->priv);
+ if (voltage == SEC_VOLTAGE_18)
+ msg[0].buf = command_18v;
+ i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
+ return 0;
+}
+
+static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
+{
+ d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+ &d->dev->i2c_adap);
+ if (d->fe != NULL) {
+ d->fe->ops.set_voltage = dw2102_set_voltage;
+ info("Attached stv0299!\n");
+ return 0;
+ }
+ return -EIO;
+}
+
+static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
+{
+ dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+ &adap->dev->i2c_adap, DVB_PLL_OPERA1);
+ return 0;
+}
+
+static struct dvb_usb_rc_key dw2102_rc_keys[] = {
+ { 0xf8, 0x0a, KEY_Q }, /*power*/
+ { 0xf8, 0x0c, KEY_M }, /*mute*/
+ { 0xf8, 0x11, KEY_1 },
+ { 0xf8, 0x12, KEY_2 },
+ { 0xf8, 0x13, KEY_3 },
+ { 0xf8, 0x14, KEY_4 },
+ { 0xf8, 0x15, KEY_5 },
+ { 0xf8, 0x16, KEY_6 },
+ { 0xf8, 0x17, KEY_7 },
+ { 0xf8, 0x18, KEY_8 },
+ { 0xf8, 0x19, KEY_9 },
+ { 0xf8, 0x10, KEY_0 },
+ { 0xf8, 0x1c, KEY_PAGEUP }, /*ch+*/
+ { 0xf8, 0x0f, KEY_PAGEDOWN }, /*ch-*/
+ { 0xf8, 0x1a, KEY_O }, /*vol+*/
+ { 0xf8, 0x0e, KEY_Z }, /*vol-*/
+ { 0xf8, 0x04, KEY_R }, /*rec*/
+ { 0xf8, 0x09, KEY_D }, /*fav*/
+ { 0xf8, 0x08, KEY_BACKSPACE }, /*rewind*/
+ { 0xf8, 0x07, KEY_A }, /*fast*/
+ { 0xf8, 0x0b, KEY_P }, /*pause*/
+ { 0xf8, 0x02, KEY_ESC }, /*cancel*/
+ { 0xf8, 0x03, KEY_G }, /*tab*/
+ { 0xf8, 0x00, KEY_UP }, /*up*/
+ { 0xf8, 0x1f, KEY_ENTER }, /*ok*/
+ { 0xf8, 0x01, KEY_DOWN }, /*down*/
+ { 0xf8, 0x05, KEY_C }, /*cap*/
+ { 0xf8, 0x06, KEY_S }, /*stop*/
+ { 0xf8, 0x40, KEY_F }, /*full*/
+ { 0xf8, 0x1e, KEY_W }, /*tvmode*/
+ { 0xf8, 0x1b, KEY_B }, /*recall*/
+
+};
+
+
+
+static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ struct dw2102_state *st = d->priv;
+ u8 key[2];
+ struct i2c_msg msg[] = {
+ {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
+ .len = 2},
+ };
+ int i;
+
+ *state = REMOTE_NO_KEY_PRESSED;
+ if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
+ for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) {
+ if (dw2102_rc_keys[i].data == msg[0].buf[0]) {
+ *state = REMOTE_KEY_PRESSED;
+ *event = dw2102_rc_keys[i].event;
+ st->last_key_pressed =
+ dw2102_rc_keys[i].event;
+ break;
+ }
+ st->last_key_pressed = 0;
+ }
+ }
+ /* info("key: %x %x\n",key[0],key[1]); */
+ return 0;
+}
+
+static struct usb_device_id dw2102_table[] = {
+ {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
+ {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, dw2102_table);
+
+static int dw2102_load_firmware(struct usb_device *dev,
+ const struct firmware *frmwr)
+{
+ u8 *b, *p;
+ int ret = 0, i;
+ u8 reset;
+ u8 reset16 [] = {0, 0, 0, 0, 0, 0, 0};
+ const struct firmware *fw;
+ const char *filename = "dvb-usb-dw2101.fw";
+ switch (dev->descriptor.idProduct) {
+ case 0x2101:
+ ret = request_firmware(&fw, filename, &dev->dev);
+ if (ret != 0) {
+ err("did not find the firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more details "
+ "on firmware-problems.", filename);
+ return ret;
+ }
+ break;
+ case USB_PID_DW2102:
+ fw = frmwr;
+ break;
+ }
+ info("start downloading DW2102 firmware");
+ p = kmalloc(fw->size, GFP_KERNEL);
+ reset = 1;
+ /*stop the CPU*/
+ dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG);
+ dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG);
+
+ if (p != NULL) {
+ memcpy(p, fw->data, fw->size);
+ for (i = 0; i < fw->size; i += 0x40) {
+ b = (u8 *) p + i;
+ if (dw2102_op_rw
+ (dev, 0xa0, i, b , 0x40,
+ DW2102_WRITE_MSG) != 0x40
+ ) {
+ err("error while transferring firmware");
+ ret = -EINVAL;
+ break;
+ }
+ }
+ /* restart the CPU */
+ reset = 0;
+ if (ret || dw2102_op_rw
+ (dev, 0xa0, 0x7f92, &reset, 1,
+ DW2102_WRITE_MSG) != 1) {
+ err("could not restart the USB controller CPU.");
+ ret = -EINVAL;
+ }
+ if (ret || dw2102_op_rw
+ (dev, 0xa0, 0xe600, &reset, 1,
+ DW2102_WRITE_MSG) != 1) {
+ err("could not restart the USB controller CPU.");
+ ret = -EINVAL;
+ }
+ /* init registers */
+ switch (dev->descriptor.idProduct) {
+ case USB_PID_DW2102:
+ dw2102_op_rw
+ (dev, 0xbf, 0x0040, &reset, 0,
+ DW2102_WRITE_MSG);
+ dw2102_op_rw
+ (dev, 0xb9, 0x0000, &reset16[0], 2,
+ DW2102_READ_MSG);
+ break;
+ case 0x2101:
+ dw2102_op_rw
+ (dev, 0xbc, 0x0030, &reset16[0], 2,
+ DW2102_READ_MSG);
+ dw2102_op_rw
+ (dev, 0xba, 0x0000, &reset16[0], 7,
+ DW2102_READ_MSG);
+ dw2102_op_rw
+ (dev, 0xba, 0x0000, &reset16[0], 7,
+ DW2102_READ_MSG);
+ dw2102_op_rw
+ (dev, 0xb9, 0x0000, &reset16[0], 2,
+ DW2102_READ_MSG);
+ break;
+ }
+ kfree(p);
+ }
+ return ret;
+}
+
+static struct dvb_usb_device_properties dw2102_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-dw2102.fw",
+ .size_of_priv = sizeof(struct dw2102_state),
+ .no_reconnect = 1,
+
+ .i2c_algo = &dw2102_i2c_algo,
+ .rc_key_map = dw2102_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys),
+ .rc_interval = 150,
+ .rc_query = dw2102_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x81,
+ /* parameter for the MPEG2-data transfer */
+ .num_adapters = 1,
+ .download_firmware = dw2102_load_firmware,
+ .adapter = {
+ {
+ .frontend_attach = dw2102_frontend_attach,
+ .streaming_ctrl = NULL,
+ .tuner_attach = dw2102_tuner_attach,
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ }
+ },
+ .num_device_descs = 2,
+ .devices = {
+ {"DVBWorld DVB-S 2102 USB2.0",
+ {&dw2102_table[0], NULL},
+ {NULL},
+ },
+ {"DVBWorld DVB-S 2101 USB2.0",
+ {&dw2102_table[1], NULL},
+ {NULL},
+ },
+ }
+};
+
+static int dw2102_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf, &dw2102_properties,
+ THIS_MODULE, NULL, adapter_nr);
+}
+
+static struct usb_driver dw2102_driver = {
+ .name = "dw2102",
+ .probe = dw2102_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = dw2102_table,
+};
+
+static int __init dw2102_module_init(void)
+{
+ int ret = usb_register(&dw2102_driver);
+ if (ret)
+ err("usb_register failed. Error number %d", ret);
+
+ return ret;
+}
+
+static void __exit dw2102_module_exit(void)
+{
+ usb_deregister(&dw2102_driver);
+}
+
+module_init(dw2102_module_init);
+module_exit(dw2102_module_exit);
+
+MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h
new file mode 100644
index 0000000..7a310f9
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dw2102.h
@@ -0,0 +1,9 @@
+#ifndef _DW2102_H_
+#define _DW2102_H_
+
+#define DVB_USB_LOG_PREFIX "dw2102"
+#include "dvb-usb.h"
+
+extern int dvb_usb_dw2102_debug;
+#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
+#endif
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
index 0a8ac64..6f596ed 100644
--- a/drivers/media/dvb/dvb-usb/gl861.c
+++ b/drivers/media/dvb/dvb-usb/gl861.c
@@ -1,8 +1,8 @@
/* DVB USB compliant linux driver for GL861 USB2.0 devices.
*
* 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.
+ * 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
*/
@@ -13,9 +13,9 @@
/* debug */
static int dvb_usb_gl861_debug;
-module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-
+module_param_named(debug, dvb_usb_gl861_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))."
+ DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
@@ -47,6 +47,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
return -EINVAL;
}
+ msleep(1); /* avoid I2C errors */
+
return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
value, index, rbuf, rlen, 2000);
}
@@ -68,7 +70,7 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
/* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
- msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
+ msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
break;
i++;
} else
@@ -92,16 +94,6 @@ static struct i2c_algorithm gl861_i2c_algo = {
};
/* Callbacks for DVB USB */
-static int gl861_identify_state(struct usb_device *udev,
- struct dvb_usb_device_properties *props,
- struct dvb_usb_device_description **desc,
- int *cold)
-{
- *cold = 0;
-
- return 0;
-}
-
static struct zl10353_config gl861_zl10353_config = {
.demod_address = 0x0f,
.no_tuner = 1,
@@ -110,12 +102,13 @@ static struct zl10353_config gl861_zl10353_config = {
static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
{
- if ((adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
- &adap->dev->i2c_adap)) != NULL) {
- return 0;
- }
- return -EIO;
+ adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+ &adap->dev->i2c_adap);
+ if (adap->fe == NULL)
+ return -EIO;
+
+ return 0;
}
static struct qt1010_config gl861_qt1010_config = {
@@ -164,7 +157,7 @@ static struct usb_device_id gl861_table [] = {
{ USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, gl861_table);
+MODULE_DEVICE_TABLE(usb, gl861_table);
static struct dvb_usb_device_properties gl861_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
@@ -172,7 +165,6 @@ static struct dvb_usb_device_properties gl861_properties = {
.size_of_priv = 0,
- .identify_state = gl861_identify_state,
.num_adapters = 1,
.adapter = {{
@@ -189,18 +181,20 @@ static struct dvb_usb_device_properties gl861_properties = {
}
}
},
- }},
+ } },
.i2c_algo = &gl861_i2c_algo,
.num_device_descs = 2,
.devices = {
- { "MSI Mega Sky 55801 DVB-T USB2.0",
- { &gl861_table[0], NULL },
- { NULL },
+ {
+ .name = "MSI Mega Sky 55801 DVB-T USB2.0",
+ .cold_ids = { NULL },
+ .warm_ids = { &gl861_table[0], NULL },
},
- { "A-LINK DTU DVB-T USB2.0",
- { &gl861_table[1], NULL },
- { NULL },
+ {
+ .name = "A-LINK DTU DVB-T USB2.0",
+ .cold_ids = { NULL },
+ .warm_ids = { &gl861_table[1], NULL },
},
}
};
@@ -217,12 +211,11 @@ static int __init gl861_module_init(void)
{
int ret;
- if ((ret = usb_register(&gl861_driver))) {
+ ret = usb_register(&gl861_driver);
+ if (ret)
err("usb_register failed. Error number %d", ret);
- return ret;
- }
- return 0;
+ return ret;
}
static void __exit gl861_module_exit(void)
@@ -231,8 +224,8 @@ static void __exit gl861_module_exit(void)
usb_deregister(&gl861_driver);
}
-module_init (gl861_module_init);
-module_exit (gl861_module_exit);
+module_init(gl861_module_init);
+module_exit(gl861_module_exit);
MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>");
MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861");
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h
index 72a51af..c54855e 100644
--- a/drivers/media/dvb/dvb-usb/gl861.h
+++ b/drivers/media/dvb/dvb-usb/gl861.h
@@ -4,7 +4,7 @@
#define DVB_USB_LOG_PREFIX "gl861"
#include "dvb-usb.h"
-#define deb_rc(args...) dprintk(dvb_usb_gl861_debug,0x01,args)
+#define deb_rc(args...) dprintk(dvb_usb_gl861_debug, 0x01, args)
#define GL861_WRITE 0x40
#define GL861_READ 0xc0
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 9a942af..d965a92 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -86,7 +86,8 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
{
int ret;
const struct firmware *fw = NULL;
- u8 *ptr, *buf;
+ const u8 *ptr;
+ u8 *buf;
if ((ret = request_firmware(&fw, bcm4500_firmware,
&d->udev->dev)) != 0) {
err("did not find the bcm4500 firmware file. (%s) "
@@ -146,24 +147,24 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
if(gp8psk_load_bcm4500fw(d))
- return EINVAL;
+ return -EINVAL;
if (! (status & bmIntersilOn)) /* LNB Power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
&buf, 1))
- return EINVAL;
+ return -EINVAL;
/* Set DVB mode to 1 */
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
- return EINVAL;
+ return -EINVAL;
/* Abort possible TS (if previous tune crashed) */
if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
- return EINVAL;
+ return -EINVAL;
} else {
/* Turn off LNB power */
if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
- return EINVAL;
+ return -EINVAL;
/* Turn off 8psk power */
if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
return -EINVAL;
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index a12e6f7..54626a0 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -16,6 +16,7 @@
#include "qt1010.h"
#include "tda1004x.h"
#include "tda827x.h"
+#include <asm/unaligned.h>
/* debug */
static int dvb_usb_m920x_debug;
@@ -347,13 +348,13 @@ static int m920x_firmware_download(struct usb_device *udev, const struct firmwar
for (pass = 0; pass < 2; pass++) {
for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
- value = le16_to_cpu(*(u16 *)(fw->data + i));
+ value = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
- index = le16_to_cpu(*(u16 *)(fw->data + i));
+ index = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
- size = le16_to_cpu(*(u16 *)(fw->data + i));
+ size = get_unaligned_le16(fw->data + i);
i += sizeof(u16);
if (pass == 1) {
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 9e7653b..118aab1 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -107,7 +107,7 @@ static struct dvb_usb_device_properties umt_properties = {
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 20,
+ .count = MAX_NO_URBS_FOR_DATA_STREAM,
.endpoint = 0x06,
.u = {
.bulk = {
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 6d23846..574dffe 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -30,7 +30,7 @@ config DVB_CX24123
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_MT312
- tristate "Zarlink VP310/MT312 based"
+ tristate "Zarlink VP310/MT312/ZL10313 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
@@ -99,7 +99,6 @@ config DVB_SP8870
tristate "Spase sp8870 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -112,7 +111,6 @@ config DVB_SP887X
tristate "Spase sp887x based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -135,6 +133,20 @@ config DVB_CX22702
help
A DVB-T tuner module. Say Y when you want to support this frontend.
+config DVB_DRX397XD
+ tristate "Micronas DRX3975D/DRX3977D based"
+ depends on DVB_CORE && I2C && HOTPLUG
+ default m if DVB_FE_CUSTOMISE
+ select FW_LOADER
+ help
+ A DVB-T tuner module. Say Y when you want to support this frontend.
+
+ TODO:
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_L64781
tristate "LSI L64781"
depends on DVB_CORE && I2C
@@ -146,7 +158,6 @@ config DVB_TDA1004X
tristate "Philips TDA10045H/TDA10046H based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -213,7 +224,6 @@ config DVB_TDA10048
tristate "Philips TDA10048HN based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
@@ -255,7 +265,6 @@ config DVB_NXT200X
tristate "NxtWave Communications NXT2002/NXT2004 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
@@ -270,7 +279,6 @@ config DVB_OR51211
tristate "Oren OR51211 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
@@ -283,7 +291,6 @@ config DVB_OR51132
tristate "Oren OR51132 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
@@ -299,7 +306,6 @@ config DVB_BCM3510
tristate "Broadcom BCM3510"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
- select FW_LOADER
help
An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
support this frontend.
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index a89dc0f..028da55 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
obj-$(CONFIG_DVB_MT352) += mt352.o
obj-$(CONFIG_DVB_ZL10353) += zl10353.o
obj-$(CONFIG_DVB_CX22702) += cx22702.o
+obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
obj-$(CONFIG_DVB_TDA10023) += tda10023.o
obj-$(CONFIG_DVB_STV0297) += stv0297.o
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
index 084a280..f7b7165 100644
--- a/drivers/media/dvb/frontends/au8522.c
+++ b/drivers/media/dvb/frontends/au8522.c
@@ -26,7 +26,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "au8522.h"
struct au8522_state {
@@ -463,10 +462,13 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
struct au8522_state *state = fe->demodulator_priv;
+ int ret = -EINVAL;
dprintk("%s(frequency=%d)\n", __func__, p->frequency);
- state->current_frequency = p->frequency;
+ if ((state->current_frequency == p->frequency) &&
+ (state->current_modulation == p->u.vsb.modulation))
+ return 0;
au8522_enable_modulation(fe, p->u.vsb.modulation);
@@ -476,11 +478,16 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
- fe->ops.tuner_ops.set_params(fe, p);
+ ret = fe->ops.tuner_ops.set_params(fe, p);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
+ if (ret < 0)
+ return ret;
+
+ state->current_frequency = p->frequency;
+
return 0;
}
@@ -498,6 +505,16 @@ static int au8522_init(struct dvb_frontend *fe)
return 0;
}
+static int au8522_sleep(struct dvb_frontend *fe)
+{
+ struct au8522_state *state = fe->demodulator_priv;
+ dprintk("%s()\n", __func__);
+
+ state->current_frequency = 0;
+
+ return 0;
+}
+
static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct au8522_state *state = fe->demodulator_priv;
@@ -509,10 +526,8 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
if (state->current_modulation == VSB_8) {
dprintk("%s() Checking VSB_8\n", __func__);
reg = au8522_readreg(state, 0x4088);
- if (reg & 0x01)
- *status |= FE_HAS_VITERBI;
- if (reg & 0x02)
- *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+ if ((reg & 0x03) == 0x03)
+ *status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
} else {
dprintk("%s() Checking QAM\n", __func__);
reg = au8522_readreg(state, 0x4541);
@@ -672,6 +687,7 @@ static struct dvb_frontend_ops au8522_ops = {
},
.init = au8522_init,
+ .sleep = au8522_sleep,
.i2c_gate_ctrl = au8522_i2c_gate_ctrl,
.set_frontend = au8522_set_frontend,
.get_frontend = au8522_get_frontend,
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index d268e65..cf5e576 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -590,7 +590,8 @@ static void bcm3510_release(struct dvb_frontend* fe)
*/
#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
-static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, u8 *b, u16 len)
+static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, const u8 *b,
+ u16 len)
{
int ret = 0,i;
bcm3510_register_value vH, vL,vD;
@@ -614,7 +615,7 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe)
struct bcm3510_state* st = fe->demodulator_priv;
const struct firmware *fw;
u16 addr,len;
- u8 *b;
+ const u8 *b;
int ret,i;
deb_info("requesting firmware\n");
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
index 786e37d..3eedfdf 100644
--- a/drivers/media/dvb/frontends/dib0070.h
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -37,7 +37,20 @@ struct dib0070_config {
u8 flip_chip;
};
-extern struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
+#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dib0070_config *cfg);
+#else
+static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dib0070_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
extern u16 dib0070_wbd_offset(struct dvb_frontend *);
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
index 081bd81..07c4d12 100644
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ b/drivers/media/dvb/frontends/dib7000p.h
@@ -37,7 +37,20 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
-extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct dib7000p_config *cfg);
+#else
+static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
+ u8 i2c_addr,
+ struct dib7000p_config *cfg)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return NULL;
+}
+#endif
+
extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c
new file mode 100644
index 0000000..3cbed87
--- /dev/null
+++ b/drivers/media/dvb/frontends/drx397xD.c
@@ -0,0 +1,1504 @@
+/*
+ * Driver for Micronas drx397xD demodulator
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DEBUG /* uncomment if you want debugging output */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/firmware.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drx397xD.h"
+
+static const char mod_name[] = "drx397xD";
+
+#define MAX_CLOCK_DRIFT 200 /* maximal 200 PPM allowed */
+
+#define F_SET_0D0h 1
+#define F_SET_0D4h 2
+
+typedef enum fw_ix {
+#define _FW_ENTRY(a, b) b
+#include "drx397xD_fw.h"
+} fw_ix_t;
+
+/* chip specifics */
+struct drx397xD_state {
+ struct i2c_adapter *i2c;
+ struct dvb_frontend frontend;
+ struct drx397xD_config config;
+ fw_ix_t chip_rev;
+ int flags;
+ u32 bandwidth_parm; /* internal bandwidth conversions */
+ u32 f_osc; /* w90: actual osc frequency [Hz] */
+};
+
+/*******************************************************************************
+ * Firmware
+ ******************************************************************************/
+
+static const char *blob_name[] = {
+#define _BLOB_ENTRY(a, b) a
+#include "drx397xD_fw.h"
+};
+
+typedef enum blob_ix {
+#define _BLOB_ENTRY(a, b) b
+#include "drx397xD_fw.h"
+} blob_ix_t;
+
+static struct {
+ const char *name;
+ const struct firmware *file;
+ rwlock_t lock;
+ int refcnt;
+ const u8 *data[ARRAY_SIZE(blob_name)];
+} fw[] = {
+#define _FW_ENTRY(a, b) { \
+ .name = a, \
+ .file = 0, \
+ .lock = RW_LOCK_UNLOCKED, \
+ .refcnt = 0, \
+ .data = { } }
+#include "drx397xD_fw.h"
+};
+
+/* use only with writer lock aquired */
+static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+ memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+ if (fw[ix].file)
+ release_firmware(fw[ix].file);
+}
+
+static void drx_release_fw(struct drx397xD_state *s)
+{
+ fw_ix_t ix = s->chip_rev;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ write_lock(&fw[ix].lock);
+ if (fw[ix].refcnt) {
+ fw[ix].refcnt--;
+ if (fw[ix].refcnt == 0)
+ _drx_release_fw(s, ix);
+ }
+ write_unlock(&fw[ix].lock);
+}
+
+static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+ const u8 *data;
+ size_t size, len;
+ int i = 0, j, rc = -EINVAL;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if (ix < 0 || ix >= ARRAY_SIZE(fw))
+ return -EINVAL;
+ s->chip_rev = ix;
+
+ write_lock(&fw[ix].lock);
+ if (fw[ix].file) {
+ rc = 0;
+ goto exit_ok;
+ }
+ memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+
+ if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) {
+ printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
+ mod_name, fw[ix].name);
+ rc = -ENOENT;
+ goto exit_err;
+ }
+
+ if (!fw[ix].file->data || fw[ix].file->size < 10)
+ goto exit_corrupt;
+
+ data = fw[ix].file->data;
+ size = fw[ix].file->size;
+
+ if (data[i++] != 2) /* check firmware version */
+ goto exit_corrupt;
+
+ do {
+ switch (data[i++]) {
+ case 0x00: /* bytecode */
+ if (i >= size)
+ break;
+ i += data[i];
+ case 0x01: /* reset */
+ case 0x02: /* sleep */
+ i++;
+ break;
+ case 0xfe: /* name */
+ len = strnlen(&data[i], size - i);
+ if (i + len + 1 >= size)
+ goto exit_corrupt;
+ if (data[i + len + 1] != 0)
+ goto exit_corrupt;
+ for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
+ if (strcmp(blob_name[j], &data[i]) == 0) {
+ fw[ix].data[j] = &data[i + len + 1];
+ pr_debug("Loading %s\n", blob_name[j]);
+ }
+ }
+ i += len + 1;
+ break;
+ case 0xff: /* file terminator */
+ if (i == size) {
+ rc = 0;
+ goto exit_ok;
+ }
+ default:
+ goto exit_corrupt;
+ }
+ } while (i < size);
+ exit_corrupt:
+ printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
+ exit_err:
+ _drx_release_fw(s, ix);
+ fw[ix].refcnt--;
+ exit_ok:
+ fw[ix].refcnt++;
+ write_unlock(&fw[ix].lock);
+ return rc;
+}
+
+/*******************************************************************************
+ * i2c bus IO
+ ******************************************************************************/
+
+static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
+{
+ struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
+ const u8 *data;
+ int len, rc = 0, i = 0;
+
+ if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
+ pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
+
+ read_lock(&fw[s->chip_rev].lock);
+ data = fw[s->chip_rev].data[ix];
+ if (!data) {
+ rc = -EINVAL;
+ goto exit_rc;
+ }
+
+ for (;;) {
+ switch (data[i++]) {
+ case 0: /* bytecode */
+ len = data[i++];
+ msg.len = len;
+ msg.buf = (__u8 *) &data[i];
+ if (i2c_transfer(s->i2c, &msg, 1) != 1) {
+ rc = -EIO;
+ goto exit_rc;
+ }
+ i += len;
+ break;
+ case 1: /* reset */
+ case 2: /* sleep */
+ i++;
+ break;
+ default:
+ goto exit_rc;
+ }
+ }
+ exit_rc:
+ read_unlock(&fw[s->chip_rev].lock);
+ return 0;
+}
+
+/* Function is not endian safe, use the RD16 wrapper below */
+static int _read16(struct drx397xD_state *s, u32 i2c_adr)
+{
+ int rc;
+ u8 a[4];
+ u16 v;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = s->config.demod_address,
+ .flags = 0,
+ .buf = a,
+ .len = sizeof(a)
+ }
+ , {
+ .addr = s->config.demod_address,
+ .flags = I2C_M_RD,
+ .buf = (u8 *) & v,
+ .len = sizeof(v)
+ }
+ };
+
+ *(u32 *) a = i2c_adr;
+
+ rc = i2c_transfer(s->i2c, msg, 2);
+ if (rc != 2)
+ return -EIO;
+
+ return le16_to_cpu(v);
+}
+
+/* Function is not endian safe, use the WR16.. wrappers below */
+static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
+{
+ u8 a[6];
+ int rc;
+ struct i2c_msg msg = {
+ .addr = s->config.demod_address,
+ .flags = 0,
+ .buf = a,
+ .len = sizeof(a)
+ };
+
+ *(u32 *) a = i2c_adr;
+ *(u16 *) & a[4] = val;
+
+ rc = i2c_transfer(s->i2c, &msg, 1);
+ if (rc != 1)
+ return -EIO;
+ return 0;
+}
+
+#define WR16(ss,adr, val) \
+ _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
+#define WR16_E0(ss,adr, val) \
+ _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
+#define RD16(ss,adr) \
+ _read16(ss, I2C_ADR_C0(adr))
+
+#define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
+
+/*******************************************************************************
+ * Tuner callback
+ ******************************************************************************/
+
+static int PLL_Set(struct drx397xD_state *s,
+ struct dvb_frontend_parameters *fep, int *df_tuner)
+{
+ struct dvb_frontend *fe = &s->frontend;
+ u32 f_tuner, f = fep->frequency;
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
+ (f < s->frontend.ops.tuner_ops.info.frequency_min))
+ return -EINVAL;
+
+ *df_tuner = 0;
+ if (!s->frontend.ops.tuner_ops.set_params ||
+ !s->frontend.ops.tuner_ops.get_frequency)
+ return -ENOSYS;
+
+ rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
+ if (rc < 0)
+ return rc;
+
+ rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
+ if (rc < 0)
+ return rc;
+
+ *df_tuner = f_tuner - f;
+ pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
+ f_tuner);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Demodulator helper functions
+ ******************************************************************************/
+
+static int SC_WaitForReady(struct drx397xD_state *s)
+{
+ int cnt = 1000;
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ while (cnt--) {
+ rc = RD16(s, 0x820043);
+ if (rc == 0)
+ return 0;
+ }
+ return -1;
+}
+
+static int SC_SendCommand(struct drx397xD_state *s, int cmd)
+{
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ WR16(s, 0x820043, cmd);
+ SC_WaitForReady(s);
+ rc = RD16(s, 0x820042);
+ if ((rc & 0xffff) == 0xffff)
+ return -1;
+ return 0;
+}
+
+static int HI_Command(struct drx397xD_state *s, u16 cmd)
+{
+ int rc, cnt = 1000;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ rc = WR16(s, 0x420032, cmd);
+ if (rc < 0)
+ return rc;
+
+ do {
+ rc = RD16(s, 0x420032);
+ if (rc == 0) {
+ rc = RD16(s, 0x420031);
+ return rc;
+ }
+ if (rc < 0)
+ return rc;
+ } while (--cnt);
+ return rc;
+}
+
+static int HI_CfgCommand(struct drx397xD_state *s)
+{
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ WR16(s, 0x420033, 0x3973);
+ WR16(s, 0x420034, s->config.w50); // code 4, log 4
+ WR16(s, 0x420035, s->config.w52); // code 15, log 9
+ WR16(s, 0x420036, s->config.demod_address << 1);
+ WR16(s, 0x420037, s->config.w56); // code (set_i2c ?? initX 1 ), log 1
+// WR16(s, 0x420033, 0x3973);
+ if ((s->config.w56 & 8) == 0)
+ return HI_Command(s, 3);
+ return WR16(s, 0x420032, 0x3);
+}
+
+static const u8 fastIncrDecLUT_15273[] = {
+ 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
+ 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
+};
+
+static const u8 slowIncrDecLUT_15272[] = {
+ 3, 4, 4, 5, 6
+};
+
+static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
+{
+ u16 w06 = agc->w06;
+ u16 w08 = agc->w08;
+ u16 w0A = agc->w0A;
+ u16 w0C = agc->w0C;
+ int quot, rem, i, rc = -EINVAL;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if (agc->w04 > 0x3ff)
+ goto exit_rc;
+
+ if (agc->d00 == 1) {
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= ~0x10;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+ return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
+ }
+
+ if (agc->d00 != 0)
+ goto exit_rc;
+ if (w0A < w08)
+ goto exit_rc;
+ if (w0A > 0x3ff)
+ goto exit_rc;
+ if (w0C > 0x3ff)
+ goto exit_rc;
+ if (w06 > 0x3ff)
+ goto exit_rc;
+
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc |= 0x10;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+
+ EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
+ EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
+ EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
+
+ quot = w0C / 113;
+ rem = w0C % 113;
+ if (quot <= 8) {
+ quot = 8 - quot;
+ } else {
+ quot = 0;
+ rem += 113;
+ }
+
+ EXIT_RC(WR16(s, 0x0c20024, quot));
+
+ i = fastIncrDecLUT_15273[rem / 8];
+ EXIT_RC(WR16(s, 0x0c2002d, i));
+ EXIT_RC(WR16(s, 0x0c2002e, i));
+
+ i = slowIncrDecLUT_15272[rem / 28];
+ EXIT_RC(WR16(s, 0x0c2002b, i));
+ rc = WR16(s, 0x0c2002c, i);
+ exit_rc:
+ return rc;
+}
+
+static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
+{
+ u16 w04 = agc->w04;
+ u16 w06 = agc->w06;
+ int rc = -1;
+
+ pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
+
+ if (w04 > 0x3ff)
+ goto exit_rc;
+
+ switch (agc->d00) {
+ case 1:
+ if (w04 == 0x3ff)
+ w04 = 0x400;
+
+ EXIT_RC(WR16(s, 0x0c20036, w04));
+ s->config.w9C &= ~2;
+ EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= 0xbfdf;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+ EXIT_RC(RD16(s, 0x0c20013));
+ rc &= ~2;
+ break;
+ case 0:
+ // loc_8000659
+ s->config.w9C &= ~2;
+ EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= 0xbfdf;
+ rc |= 0x4000;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+ EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
+ EXIT_RC(RD16(s, 0x0c20013));
+ rc &= ~2;
+ break;
+ default:
+ s->config.w9C |= 2;
+ EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+ EXIT_RC(RD16(s, 0x0c20010));
+ rc &= 0xbfdf;
+ EXIT_RC(WR16(s, 0x0c20010, rc));
+
+ EXIT_RC(WR16(s, 0x0c20036, 0));
+
+ EXIT_RC(RD16(s, 0x0c20013));
+ rc |= 2;
+ }
+ rc = WR16(s, 0x0c20013, rc);
+ exit_rc:
+ return rc;
+}
+
+static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
+{
+ int rc;
+
+ *lockstat = 0;
+
+ rc = RD16(s, 0x082004b);
+ if (rc < 0)
+ return rc;
+
+ if (s->config.d60 != 2)
+ return 0;
+
+ if ((rc & 7) == 7)
+ *lockstat |= 1;
+ if ((rc & 3) == 3)
+ *lockstat |= 2;
+ if (rc & 1)
+ *lockstat |= 4;
+ return 0;
+}
+
+static int CorrectSysClockDeviation(struct drx397xD_state *s)
+{
+ int rc = -EINVAL;
+ int lockstat;
+ u32 clk, clk_limit;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if (s->config.d5C == 0) {
+ EXIT_RC(WR16(s, 0x08200e8, 0x010));
+ EXIT_RC(WR16(s, 0x08200e9, 0x113));
+ s->config.d5C = 1;
+ return rc;
+ }
+ if (s->config.d5C != 1)
+ goto exit_rc;
+
+ rc = RD16(s, 0x0820048);
+
+ rc = GetLockStatus(s, &lockstat);
+ if (rc < 0)
+ goto exit_rc;
+ if ((lockstat & 1) == 0)
+ goto exit_rc;
+
+ EXIT_RC(WR16(s, 0x0420033, 0x200));
+ EXIT_RC(WR16(s, 0x0420034, 0xc5));
+ EXIT_RC(WR16(s, 0x0420035, 0x10));
+ EXIT_RC(WR16(s, 0x0420036, 0x1));
+ EXIT_RC(WR16(s, 0x0420037, 0xa));
+ EXIT_RC(HI_Command(s, 6));
+ EXIT_RC(RD16(s, 0x0420040));
+ clk = rc;
+ EXIT_RC(RD16(s, 0x0420041));
+ clk |= rc << 16;
+
+ if (clk <= 0x26ffff)
+ goto exit_rc;
+ if (clk > 0x610000)
+ goto exit_rc;
+
+ if (!s->bandwidth_parm)
+ return -EINVAL;
+
+ /* round & convert to Hz */
+ clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
+ clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
+
+ if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
+ s->f_osc = clk;
+ pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
+ s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
+ }
+ rc = WR16(s, 0x08200e8, 0);
+ exit_rc:
+ return rc;
+}
+
+static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
+{
+ int rc, si, bp;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ si = s->config.wA0;
+ if (s->config.w98 == 0) {
+ si |= 1;
+ bp = 0;
+ } else {
+ si &= ~1;
+ bp = 0x200;
+ }
+ if (s->config.w9A == 0) {
+ si |= 0x80;
+ } else {
+ si &= ~0x80;
+ }
+
+ EXIT_RC(WR16(s, 0x2150045, 0));
+ EXIT_RC(WR16(s, 0x2150010, si));
+ EXIT_RC(WR16(s, 0x2150011, bp));
+ rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
+ exit_rc:
+ return rc;
+}
+
+static int drx_tune(struct drx397xD_state *s,
+ struct dvb_frontend_parameters *fep)
+{
+ u16 v22 = 0;
+ u16 v1C = 0;
+ u16 v1A = 0;
+ u16 v18 = 0;
+ u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
+ u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
+
+ int rc, df_tuner;
+ int a, b, c, d;
+ pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
+
+ if (s->config.d60 != 2)
+ goto set_tuner;
+ rc = CorrectSysClockDeviation(s);
+ if (rc < 0)
+ goto set_tuner;
+
+ s->config.d60 = 1;
+ rc = ConfigureMPEGOutput(s, 0);
+ if (rc < 0)
+ goto set_tuner;
+ set_tuner:
+
+ rc = PLL_Set(s, fep, &df_tuner);
+ if (rc < 0) {
+ printk(KERN_ERR "Error in pll_set\n");
+ goto exit_rc;
+ }
+ msleep(200);
+
+ a = rc = RD16(s, 0x2150016);
+ if (rc < 0)
+ goto exit_rc;
+ b = rc = RD16(s, 0x2150010);
+ if (rc < 0)
+ goto exit_rc;
+ c = rc = RD16(s, 0x2150034);
+ if (rc < 0)
+ goto exit_rc;
+ d = rc = RD16(s, 0x2150035);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2150014, c);
+ rc = WR16(s, 0x2150015, d);
+ rc = WR16(s, 0x2150010, 0);
+ rc = WR16(s, 0x2150000, 2);
+ rc = WR16(s, 0x2150036, 0x0fff);
+ rc = WR16(s, 0x2150016, a);
+
+ rc = WR16(s, 0x2150010, 2);
+ rc = WR16(s, 0x2150007, 0);
+ rc = WR16(s, 0x2150000, 1);
+ rc = WR16(s, 0x2110000, 0);
+ rc = WR16(s, 0x0800000, 0);
+ rc = WR16(s, 0x2800000, 0);
+ rc = WR16(s, 0x2110010, 0x664);
+
+ rc = write_fw(s, DRXD_ResetECRAM);
+ rc = WR16(s, 0x2110000, 1);
+
+ rc = write_fw(s, DRXD_InitSC);
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = SetCfgIfAgc(s, &s->config.ifagc);
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = SetCfgRfAgc(s, &s->config.rfagc);
+ if (rc < 0)
+ goto exit_rc;
+
+ if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
+ v22 = 1;
+ switch (fep->u.ofdm.transmission_mode) {
+ case TRANSMISSION_MODE_8K:
+ edi = 1;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x2010010, 0);
+ if (rc < 0)
+ break;
+ v1C = 0x63;
+ v1A = 0x53;
+ v18 = 0x43;
+ break;
+ default:
+ edi = 0;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x2010010, 1);
+ if (rc < 0)
+ break;
+
+ v1C = 0x61;
+ v1A = 0x47;
+ v18 = 0x41;
+ }
+
+ switch (fep->u.ofdm.guard_interval) {
+ case GUARD_INTERVAL_1_4:
+ edi |= 0x0c;
+ break;
+ case GUARD_INTERVAL_1_8:
+ edi |= 0x08;
+ break;
+ case GUARD_INTERVAL_1_16:
+ edi |= 0x04;
+ break;
+ case GUARD_INTERVAL_1_32:
+ break;
+ default:
+ v22 |= 2;
+ }
+
+ ebx = 0;
+ ebp = 0;
+ v20 = 0;
+ v1E = 0;
+ v16 = 0;
+ v14 = 0;
+ v12 = 0;
+ v10 = 0;
+ v0E = 0;
+
+ switch (fep->u.ofdm.hierarchy_information) {
+ case HIERARCHY_1:
+ edi |= 0x40;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 1);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 1);
+ if (rc < 0)
+ goto exit_rc;
+ ebx = 0x19f;
+ ebp = 0x1fb;
+ v20 = 0x0c0;
+ v1E = 0x195;
+ v16 = 0x1d6;
+ v14 = 0x1ef;
+ v12 = 4;
+ v10 = 5;
+ v0E = 5;
+ break;
+ case HIERARCHY_2:
+ edi |= 0x80;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 2);
+ if (rc < 0)
+ goto exit_rc;
+ ebx = 0x08f;
+ ebp = 0x12f;
+ v20 = 0x0c0;
+ v1E = 0x11e;
+ v16 = 0x1d6;
+ v14 = 0x15e;
+ v12 = 4;
+ v10 = 5;
+ v0E = 5;
+ break;
+ case HIERARCHY_4:
+ edi |= 0xc0;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 3);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 3);
+ if (rc < 0)
+ goto exit_rc;
+ ebx = 0x14d;
+ ebp = 0x197;
+ v20 = 0x0c0;
+ v1E = 0x1ce;
+ v16 = 0x1d6;
+ v14 = 0x11a;
+ v12 = 4;
+ v10 = 6;
+ v0E = 5;
+ break;
+ default:
+ v22 |= 8;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x1c10047, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010012, 0);
+ if (rc < 0)
+ goto exit_rc;
+ // QPSK QAM16 QAM64
+ ebx = 0x19f; // 62
+ ebp = 0x1fb; // 15
+ v20 = 0x16a; // 62
+ v1E = 0x195; // 62
+ v16 = 0x1bb; // 15
+ v14 = 0x1ef; // 15
+ v12 = 5; // 16
+ v10 = 5; // 16
+ v0E = 5; // 16
+ }
+
+ switch (fep->u.ofdm.constellation) {
+ default:
+ v22 |= 4;
+ case QPSK:
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x1c10046, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010011, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001a, 0x10);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001b, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001c, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10062, v20);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c1002a, v1C);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10015, v16);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10016, v12);
+ if (rc < 0)
+ goto exit_rc;
+ break;
+ case QAM_16:
+ edi |= 0x10;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+
+ rc = WR16(s, 0x1c10046, 1);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010011, 1);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001a, 0x10);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001b, 4);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001c, 0);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10062, v1E);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c1002a, v1A);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10015, v14);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10016, v10);
+ if (rc < 0)
+ goto exit_rc;
+ break;
+ case QAM_64:
+ edi |= 0x20;
+ rc = WR16(s, 0x1c10046, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x2010011, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001a, 0x20);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001b, 8);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x201001c, 2);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10062, ebx);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c1002a, v18);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10015, ebp);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x1c10016, v0E);
+ if (rc < 0)
+ goto exit_rc;
+ break;
+ }
+
+ if (s->config.s20d24 == 1) {
+ rc = WR16(s, 0x2010013, 0);
+ } else {
+ rc = WR16(s, 0x2010013, 1);
+ edi |= 0x1000;
+ }
+
+ switch (fep->u.ofdm.code_rate_HP) {
+ default:
+ v22 |= 0x10;
+ case FEC_1_2:
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 0);
+ break;
+ case FEC_2_3:
+ edi |= 0x200;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 1);
+ break;
+ case FEC_3_4:
+ edi |= 0x400;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 2);
+ break;
+ case FEC_5_6: /* 5 */
+ edi |= 0x600;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 3);
+ break;
+ case FEC_7_8: /* 7 */
+ edi |= 0x800;
+ if (s->chip_rev == DRXD_FW_B1)
+ break;
+ rc = WR16(s, 0x2090011, 4);
+ break;
+ };
+ if (rc < 0)
+ goto exit_rc;
+
+ switch (fep->u.ofdm.bandwidth) {
+ default:
+ rc = -EINVAL;
+ goto exit_rc;
+ case BANDWIDTH_8_MHZ: /* 0 */
+ case BANDWIDTH_AUTO:
+ rc = WR16(s, 0x0c2003f, 0x32);
+ s->bandwidth_parm = ebx = 0x8b8249; // 9142857
+ edx = 0;
+ break;
+ case BANDWIDTH_7_MHZ:
+ rc = WR16(s, 0x0c2003f, 0x3b);
+ s->bandwidth_parm = ebx = 0x7a1200; // 8000000
+ edx = 0x4807;
+ break;
+ case BANDWIDTH_6_MHZ:
+ rc = WR16(s, 0x0c2003f, 0x47);
+ s->bandwidth_parm = ebx = 0x68a1b6; // 6857142
+ edx = 0x0f07;
+ break;
+ };
+
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = WR16(s, 0x08200ec, edx);
+ if (rc < 0)
+ goto exit_rc;
+
+ rc = RD16(s, 0x0820050);
+ if (rc < 0)
+ goto exit_rc;
+ rc = WR16(s, 0x0820050, rc);
+
+ {
+ /* Configure bandwidth specific factor */
+ ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1),
+ (u64)ebx) - 0x800000;
+ EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
+ EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
+
+ /* drx397xD oscillator calibration */
+ ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +
+ (s->f_osc >> 1), (u64)s->f_osc);
+ }
+ ebx &= 0xfffffff;
+ if (fep->inversion == INVERSION_ON)
+ ebx = 0x10000000 - ebx;
+
+ EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));
+ EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));
+
+ EXIT_RC(WR16(s, 0x0800000, 1));
+ EXIT_RC(RD16(s, 0x0800000));
+
+
+ EXIT_RC(SC_WaitForReady(s));
+ EXIT_RC(WR16(s, 0x0820042, 0));
+ EXIT_RC(WR16(s, 0x0820041, v22));
+ EXIT_RC(WR16(s, 0x0820040, edi));
+ EXIT_RC(SC_SendCommand(s, 3));
+
+ rc = RD16(s, 0x0800000);
+
+ SC_WaitForReady(s);
+ WR16(s, 0x0820042, 0);
+ WR16(s, 0x0820041, 1);
+ WR16(s, 0x0820040, 1);
+ SC_SendCommand(s, 1);
+
+// rc = WR16(s, 0x2150000, 1);
+// if (rc < 0) goto exit_rc;
+
+ rc = WR16(s, 0x2150000, 2);
+ rc = WR16(s, 0x2150016, a);
+ rc = WR16(s, 0x2150010, 4);
+ rc = WR16(s, 0x2150036, 0);
+ rc = WR16(s, 0x2150000, 1);
+ s->config.d60 = 2;
+ exit_rc:
+ return rc;
+}
+
+/*******************************************************************************
+ * DVB interface
+ ******************************************************************************/
+
+static int drx397x_init(struct dvb_frontend *fe)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ int rc;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ s->config.rfagc.d00 = 2; /* 0x7c */
+ s->config.rfagc.w04 = 0;
+ s->config.rfagc.w06 = 0x3ff;
+
+ s->config.ifagc.d00 = 0; /* 0x68 */
+ s->config.ifagc.w04 = 0;
+ s->config.ifagc.w06 = 140;
+ s->config.ifagc.w08 = 0;
+ s->config.ifagc.w0A = 0x3ff;
+ s->config.ifagc.w0C = 0x388;
+
+ /* for signal strenght calculations */
+ s->config.ss76 = 820;
+ s->config.ss78 = 2200;
+ s->config.ss7A = 150;
+
+ /* HI_CfgCommand */
+ s->config.w50 = 4;
+ s->config.w52 = 9; // 0xf;
+
+ s->config.f_if = 42800000; /* d14: intermediate frequency [Hz] */
+ s->config.f_osc = 48000; /* s66 : oscillator frequency [kHz] */
+ s->config.w92 = 12000; // 20000;
+
+ s->config.w9C = 0x000e;
+ s->config.w9E = 0x0000;
+
+ /* ConfigureMPEGOutput params */
+ s->config.wA0 = 4;
+ s->config.w98 = 1; // 0;
+ s->config.w9A = 1;
+
+ /* get chip revision */
+ rc = RD16(s, 0x2410019);
+ if (rc < 0)
+ return -ENODEV;
+
+ if (rc == 0) {
+ printk(KERN_INFO "%s: chip revision A2\n", mod_name);
+ rc = drx_load_fw(s, DRXD_FW_A2);
+ } else {
+
+ rc = (rc >> 12) - 3;
+ switch (rc) {
+ case 1:
+ s->flags |= F_SET_0D4h;
+ case 0:
+ case 4:
+ s->flags |= F_SET_0D0h;
+ break;
+ case 2:
+ case 5:
+ break;
+ case 3:
+ s->flags |= F_SET_0D4h;
+ break;
+ default:
+ return -ENODEV;
+ };
+ printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);
+ rc = drx_load_fw(s, DRXD_FW_B1);
+ }
+ if (rc < 0)
+ goto error;
+
+ rc = WR16(s, 0x0420033, 0x3973);
+ if (rc < 0)
+ goto error;
+
+ rc = HI_Command(s, 2);
+
+ msleep(1);
+
+ if (s->chip_rev == DRXD_FW_A2) {
+ rc = WR16(s, 0x043012d, 0x47F);
+ if (rc < 0)
+ goto error;
+ }
+ rc = WR16_E0(s, 0x0400000, 0);
+ if (rc < 0)
+ goto error;
+
+ if (s->config.w92 > 20000 || s->config.w92 % 4000) {
+ printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);
+ rc = -1;
+ goto error;
+ }
+
+ rc = WR16(s, 0x2410010, 1);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x2410011, 0x15);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x2410012, s->config.w92 / 4000);
+ if (rc < 0)
+ goto error;
+#ifdef ORIG_FW
+ rc = WR16(s, 0x2410015, 2);
+ if (rc < 0)
+ goto error;
+#endif
+ rc = WR16(s, 0x2410017, 0x3973);
+ if (rc < 0)
+ goto error;
+
+ s->f_osc = s->config.f_osc * 1000; /* initial estimator */
+
+ s->config.w56 = 1;
+
+ rc = HI_CfgCommand(s);
+ if (rc < 0)
+ goto error;
+
+ rc = write_fw(s, DRXD_InitAtomicRead);
+ if (rc < 0)
+ goto error;
+
+ if (s->chip_rev == DRXD_FW_A2) {
+ rc = WR16(s, 0x2150013, 0);
+ if (rc < 0)
+ goto error;
+ }
+
+ rc = WR16_E0(s, 0x0400002, 0);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x0400002, 0);
+ if (rc < 0)
+ goto error;
+
+ if (s->chip_rev == DRXD_FW_A2) {
+ rc = write_fw(s, DRXD_ResetCEFR);
+ if (rc < 0)
+ goto error;
+ }
+ rc = write_fw(s, DRXD_microcode);
+ if (rc < 0)
+ goto error;
+
+ s->config.w9C = 0x0e;
+ if (s->flags & F_SET_0D0h) {
+ s->config.w9C = 0;
+ rc = RD16(s, 0x0c20010);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc &= ~0x1000;
+ rc = WR16(s, 0x0c20010, rc);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc = RD16(s, 0x0c20011);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc &= ~0x8;
+ rc = WR16(s, 0x0c20011, rc);
+ if (rc < 0)
+ goto write_DRXD_InitFE_1;
+
+ rc = WR16(s, 0x0c20012, 1);
+ }
+
+ write_DRXD_InitFE_1:
+
+ rc = write_fw(s, DRXD_InitFE_1);
+ if (rc < 0)
+ goto error;
+
+ rc = 1;
+ if (s->chip_rev == DRXD_FW_B1) {
+ if (s->flags & F_SET_0D0h)
+ rc = 0;
+ } else {
+ if (s->flags & F_SET_0D0h)
+ rc = 4;
+ }
+
+ rc = WR16(s, 0x0C20012, rc);
+ if (rc < 0)
+ goto error;
+
+ rc = WR16(s, 0x0C20013, s->config.w9E);
+ if (rc < 0)
+ goto error;
+ rc = WR16(s, 0x0C20015, s->config.w9C);
+ if (rc < 0)
+ goto error;
+
+ rc = write_fw(s, DRXD_InitFE_2);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitFT);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitCP);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitCE);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitEQ);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitEC);
+ if (rc < 0)
+ goto error;
+ rc = write_fw(s, DRXD_InitSC);
+ if (rc < 0)
+ goto error;
+
+ rc = SetCfgIfAgc(s, &s->config.ifagc);
+ if (rc < 0)
+ goto error;
+
+ rc = SetCfgRfAgc(s, &s->config.rfagc);
+ if (rc < 0)
+ goto error;
+
+ rc = ConfigureMPEGOutput(s, 1);
+ rc = WR16(s, 0x08201fe, 0x0017);
+ rc = WR16(s, 0x08201ff, 0x0101);
+
+ s->config.d5C = 0;
+ s->config.d60 = 1;
+ s->config.d48 = 1;
+ error:
+ return rc;
+}
+
+static int drx397x_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ return 0;
+}
+
+static int drx397x_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+
+ s->config.s20d24 = 1; // 0;
+ return drx_tune(s, params);
+}
+
+static int drx397x_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings
+ *fe_tune_settings)
+{
+ fe_tune_settings->min_delay_ms = 10000;
+ fe_tune_settings->step_size = 0;
+ fe_tune_settings->max_drift = 0;
+ return 0;
+}
+
+static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ int lockstat;
+
+ GetLockStatus(s, &lockstat);
+ /* TODO */
+// if (lockstat & 1)
+// CorrectSysClockDeviation(s);
+
+ *status = 0;
+ if (lockstat & 2) {
+ CorrectSysClockDeviation(s);
+ ConfigureMPEGOutput(s, 1);
+ *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
+ }
+ if (lockstat & 4) {
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ }
+
+ return 0;
+}
+
+static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
+{
+ *ber = 0;
+ return 0;
+}
+
+static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+ *snr = 0;
+ return 0;
+}
+
+static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ int rc;
+
+ if (s->config.ifagc.d00 == 2) {
+ *strength = 0xffff;
+ return 0;
+ }
+ rc = RD16(s, 0x0c20035);
+ if (rc < 0) {
+ *strength = 0;
+ return 0;
+ }
+ rc &= 0x3ff;
+ /* Signal strength is calculated using the following formula:
+ *
+ * a = 2200 * 150 / (2200 + 150);
+ * a = a * 3300 / (a + 820);
+ * b = 2200 * 3300 / (2200 + 820);
+ * c = (((b-a) * rc) >> 10 + a) << 4;
+ * strength = ~c & 0xffff;
+ *
+ * The following does the same but with less rounding errors:
+ */
+ *strength = ~(7720 + (rc * 30744 >> 10));
+ return 0;
+}
+
+static int drx397x_read_ucblocks(struct dvb_frontend *fe,
+ unsigned int *ucblocks)
+{
+ *ucblocks = 0;
+ return 0;
+}
+
+static int drx397x_sleep(struct dvb_frontend *fe)
+{
+ return 0;
+}
+
+static void drx397x_release(struct dvb_frontend *fe)
+{
+ struct drx397xD_state *s = fe->demodulator_priv;
+ printk(KERN_INFO "%s: release demodulator\n", mod_name);
+ if (s) {
+ drx_release_fw(s);
+ kfree(s);
+ }
+
+}
+
+static struct dvb_frontend_ops drx397x_ops = {
+
+ .info = {
+ .name = "Micronas DRX397xD DVB-T Frontend",
+ .type = FE_OFDM,
+ .frequency_min = 47125000,
+ .frequency_max = 855250000,
+ .frequency_stepsize = 166667,
+ .frequency_tolerance = 0,
+ .caps = /* 0x0C01B2EAE */
+ FE_CAN_FEC_1_2 | // = 0x2,
+ FE_CAN_FEC_2_3 | // = 0x4,
+ FE_CAN_FEC_3_4 | // = 0x8,
+ FE_CAN_FEC_5_6 | // = 0x20,
+ FE_CAN_FEC_7_8 | // = 0x80,
+ FE_CAN_FEC_AUTO | // = 0x200,
+ FE_CAN_QPSK | // = 0x400,
+ FE_CAN_QAM_16 | // = 0x800,
+ FE_CAN_QAM_64 | // = 0x2000,
+ FE_CAN_QAM_AUTO | // = 0x10000,
+ FE_CAN_TRANSMISSION_MODE_AUTO | // = 0x20000,
+ FE_CAN_GUARD_INTERVAL_AUTO | // = 0x80000,
+ FE_CAN_HIERARCHY_AUTO | // = 0x100000,
+ FE_CAN_RECOVER | // = 0x40000000,
+ FE_CAN_MUTE_TS // = 0x80000000
+ },
+
+ .release = drx397x_release,
+ .init = drx397x_init,
+ .sleep = drx397x_sleep,
+
+ .set_frontend = drx397x_set_frontend,
+ .get_tune_settings = drx397x_get_tune_settings,
+ .get_frontend = drx397x_get_frontend,
+
+ .read_status = drx397x_read_status,
+ .read_snr = drx397x_read_snr,
+ .read_signal_strength = drx397x_read_signal_strength,
+ .read_ber = drx397x_read_ber,
+ .read_ucblocks = drx397x_read_ucblocks,
+};
+
+struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct drx397xD_state *s = NULL;
+
+ /* allocate memory for the internal state */
+ s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
+ if (s == NULL)
+ goto error;
+
+ /* setup the state */
+ s->i2c = i2c;
+ memcpy(&s->config, config, sizeof(struct drx397xD_config));
+
+ /* check if the demod is there */
+ if (RD16(s, 0x2410019) < 0)
+ goto error;
+
+ /* create dvb_frontend */
+ memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops));
+ s->frontend.demodulator_priv = s;
+
+ return &s->frontend;
+ error:
+ kfree(s);
+ return NULL;
+}
+
+MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
+MODULE_AUTHOR("Henk Vergonet");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(drx397xD_attach);
diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h
new file mode 100644
index 0000000..ddc7a07
--- /dev/null
+++ b/drivers/media/dvb/frontends/drx397xD.h
@@ -0,0 +1,130 @@
+/*
+ * Driver for Micronas DVB-T drx397xD demodulator
+ *
+ * Copyright (C) 2007 Henk vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef _DRX397XD_H_INCLUDED
+#define _DRX397XD_H_INCLUDED
+
+#include <linux/dvb/frontend.h>
+
+#define DRX_F_STEPSIZE 166667
+#define DRX_F_OFFSET 36000000
+
+#define I2C_ADR_C0(x) \
+( (u32)cpu_to_le32( \
+ (u32)( \
+ (((u32)(x) & (u32)0x000000ffUL) ) | \
+ (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+ (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \
+ ( (u32)0x00c00000UL) \
+ )) \
+)
+
+#define I2C_ADR_E0(x) \
+( (u32)cpu_to_le32( \
+ (u32)( \
+ (((u32)(x) & (u32)0x000000ffUL) ) | \
+ (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+ (((u32)(x) & (u32)0x0fff0000UL) >> 8) | \
+ ( (u32)0x00e00000UL) \
+ )) \
+)
+
+struct drx397xD_CfgRfAgc /* 0x7c */
+{
+ int d00; /* 2 */
+ u16 w04;
+ u16 w06;
+};
+
+struct drx397xD_CfgIfAgc /* 0x68 */
+{
+ int d00; /* 0 */
+ u16 w04; /* 0 */
+ u16 w06;
+ u16 w08;
+ u16 w0A;
+ u16 w0C;
+};
+
+struct drx397xD_s20 {
+ int d04;
+ u32 d18;
+ u32 d1C;
+ u32 d20;
+ u32 d14;
+ u32 d24;
+ u32 d0C;
+ u32 d08;
+};
+
+struct drx397xD_config
+{
+ /* demodulator's I2C address */
+ u8 demod_address; /* 0x0f */
+
+ struct drx397xD_CfgIfAgc ifagc; /* 0x68 */
+ struct drx397xD_CfgRfAgc rfagc; /* 0x7c */
+ u32 s20d24;
+
+ /* HI_CfgCommand parameters */
+ u16 w50, w52, /* w54, */ w56;
+
+ int d5C;
+ int d60;
+ int d48;
+ int d28;
+
+ u32 f_if; /* d14: intermediate frequency [Hz] */
+ /* 36000000 on Cinergy 2400i DT */
+ /* 42800000 on Pinnacle Hybrid PRO 330e */
+
+ u16 f_osc; /* s66: 48000 oscillator frequency [kHz] */
+
+ u16 w92; /* 20000 */
+
+ u16 wA0;
+ u16 w98;
+ u16 w9A;
+
+ u16 w9C; /* 0xe0 */
+ u16 w9E; /* 0x00 */
+
+ /* used for signal strength calculations in
+ drx397x_read_signal_strength
+ */
+ u16 ss78; // 2200
+ u16 ss7A; // 150
+ u16 ss76; // 820
+};
+
+#if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE))
+extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+ struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+ struct i2c_adapter *i2c)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+ return NULL;
+}
+#endif /* CONFIG_DVB_DRX397XD */
+
+#endif /* _DRX397XD_H_INCLUDED */
diff --git a/drivers/media/dvb/frontends/drx397xD_fw.h b/drivers/media/dvb/frontends/drx397xD_fw.h
new file mode 100644
index 0000000..01de02a
--- /dev/null
+++ b/drivers/media/dvb/frontends/drx397xD_fw.h
@@ -0,0 +1,40 @@
+/*
+ * Firmware definitions for Micronas drx397xD
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef _FW_ENTRY
+ _FW_ENTRY("drx397xD.A2.fw", DRXD_FW_A2 = 0 ),
+ _FW_ENTRY("drx397xD.B1.fw", DRXD_FW_B1 ),
+#undef _FW_ENTRY
+#endif /* _FW_ENTRY */
+
+#ifdef _BLOB_ENTRY
+ _BLOB_ENTRY("InitAtomicRead", DRXD_InitAtomicRead = 0 ),
+ _BLOB_ENTRY("InitCE", DRXD_InitCE ),
+ _BLOB_ENTRY("InitCP", DRXD_InitCP ),
+ _BLOB_ENTRY("InitEC", DRXD_InitEC ),
+ _BLOB_ENTRY("InitEQ", DRXD_InitEQ ),
+ _BLOB_ENTRY("InitFE_1", DRXD_InitFE_1 ),
+ _BLOB_ENTRY("InitFE_2", DRXD_InitFE_2 ),
+ _BLOB_ENTRY("InitFT", DRXD_InitFT ),
+ _BLOB_ENTRY("InitSC", DRXD_InitSC ),
+ _BLOB_ENTRY("ResetCEFR", DRXD_ResetCEFR ),
+ _BLOB_ENTRY("ResetECRAM", DRXD_ResetECRAM ),
+ _BLOB_ENTRY("microcode", DRXD_microcode ),
+#undef _BLOB_ENTRY
+#endif /* _BLOB_ENTRY */
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index a054894..ea05815 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -343,6 +343,52 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
}
};
+static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf,
+ const struct dvb_frontend_parameters *params)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ struct i2c_msg msg = {
+ .addr = priv->pll_i2c_address,
+ .flags = 0,
+ .buf = buf,
+ .len = 4
+ };
+ int result;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+
+ result = i2c_transfer(priv->i2c, &msg, 1);
+ if (result != 1)
+ printk(KERN_ERR "%s: i2c_transfer failed:%d",
+ __func__, result);
+
+ buf[2] = 0x9e;
+ buf[3] = 0x90;
+
+ return;
+}
+
+/* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
+static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
+ .name = "Samsung DTOS403IH102A",
+ .min = 44250000,
+ .max = 858000000,
+ .iffreq = 36125000,
+ .count = 8,
+ .set = samsung_dtos403ih102a_set,
+ .entries = {
+ { 135000000, 62500, 0xbe, 0x01 },
+ { 177000000, 62500, 0xf6, 0x01 },
+ { 370000000, 62500, 0xbe, 0x02 },
+ { 450000000, 62500, 0xf6, 0x02 },
+ { 466000000, 62500, 0xfe, 0x02 },
+ { 538000000, 62500, 0xbe, 0x08 },
+ { 826000000, 62500, 0xf6, 0x08 },
+ { 999999999, 62500, 0xfe, 0x08 },
+ }
+};
+
/* ----------------------------------------------------------- */
static struct dvb_pll_desc *pll_list[] = {
@@ -360,6 +406,7 @@ static struct dvb_pll_desc *pll_list[] = {
[DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv,
[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
[DVB_PLL_OPERA1] = &dvb_pll_opera1,
+ [DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a,
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 872ca29..05239f5 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -22,6 +22,7 @@
#define DVB_PLL_SAMSUNG_TBMV 11
#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
#define DVB_PLL_OPERA1 13
+#define DVB_PLL_SAMSUNG_DTOS403IH102A 14
/**
* Attach a dvb-pll to the supplied frontend structure.
diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
index 04c562c..600dad6 100644
--- a/drivers/media/dvb/frontends/itd1000.c
+++ b/drivers/media/dvb/frontends/itd1000.c
@@ -195,7 +195,7 @@ static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
}
}
-struct {
+static const struct {
u32 freq;
u8 values[10]; /* RFTR, RFST1 - RFST9 */
} itd1000_fre_values[] = {
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index f0195c8..056387b 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -226,11 +226,16 @@ static int lgdt330x_init(struct dvb_frontend* fe)
0x4c, 0x14
};
- static u8 flip_lgdt3303_init_data[] = {
+ static u8 flip_1_lgdt3303_init_data[] = {
0x4c, 0x14,
0x87, 0xf3
};
+ static u8 flip_2_lgdt3303_init_data[] = {
+ 0x4c, 0x14,
+ 0x87, 0xda
+ };
+
struct lgdt330x_state* state = fe->demodulator_priv;
char *chip_name;
int err;
@@ -243,10 +248,19 @@ static int lgdt330x_init(struct dvb_frontend* fe)
break;
case LGDT3303:
chip_name = "LGDT3303";
- if (state->config->clock_polarity_flip) {
- err = i2c_write_demod_bytes(state, flip_lgdt3303_init_data,
- sizeof(flip_lgdt3303_init_data));
- } else {
+ switch (state->config->clock_polarity_flip) {
+ case 2:
+ err = i2c_write_demod_bytes(state,
+ flip_2_lgdt3303_init_data,
+ sizeof(flip_2_lgdt3303_init_data));
+ break;
+ case 1:
+ err = i2c_write_demod_bytes(state,
+ flip_1_lgdt3303_init_data,
+ sizeof(flip_1_lgdt3303_init_data));
+ break;
+ case 0:
+ default:
err = i2c_write_demod_bytes(state, lgdt3303_init_data,
sizeof(lgdt3303_init_data));
}
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 081ca33..5ac9b15 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -737,7 +737,7 @@ static void mt312_release(struct dvb_frontend *fe)
}
#define MT312_SYS_CLK 90000000UL /* 90 MHz */
-static struct dvb_frontend_ops vp310_mt312_ops = {
+static struct dvb_frontend_ops mt312_ops = {
.info = {
.name = "Zarlink ???? DVB-S",
@@ -776,7 +776,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
.set_voltage = mt312_set_voltage,
};
-struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+struct dvb_frontend *mt312_attach(const struct mt312_config *config,
struct i2c_adapter *i2c)
{
struct mt312_state *state = NULL;
@@ -795,7 +795,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
goto error;
/* create dvb_frontend */
- memcpy(&state->frontend.ops, &vp310_mt312_ops,
+ memcpy(&state->frontend.ops, &mt312_ops,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
@@ -827,12 +827,13 @@ error:
kfree(state);
return NULL;
}
-EXPORT_SYMBOL(vp310_mt312_attach);
+EXPORT_SYMBOL(mt312_attach);
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
+MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
index de796ea..29e3bb5 100644
--- a/drivers/media/dvb/frontends/mt312.h
+++ b/drivers/media/dvb/frontends/mt312.h
@@ -37,10 +37,10 @@ struct mt312_config {
};
#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
-struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
+struct dvb_frontend *mt312_attach(const struct mt312_config *config,
struct i2c_adapter *i2c);
#else
-static inline struct dvb_frontend *vp310_mt312_attach(
+static inline struct dvb_frontend *mt312_attach(
const struct mt312_config *config, struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 23d0228..af29835 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -93,7 +93,8 @@ static u8 i2c_readbytes (struct nxt200x_state* state, u8 addr, u8* buf, u8 len)
return 0;
}
-static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg, u8 *buf, u8 len)
+static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
+ const u8 *buf, u8 len)
{
u8 buf2 [len+1];
int err;
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index c7b5785..5ed3254 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -126,7 +126,7 @@ static int or51132_readreg(struct or51132_state *state, u8 reg)
reg, err);
return -EREMOTEIO;
}
- return le16_to_cpup((u16*)buf);
+ return buf[0] | (buf[1] << 8);
}
static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
@@ -140,9 +140,9 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
dprintk("Firmware is %Zd bytes\n",fw->size);
/* Get size of firmware A and B */
- firmwareAsize = le32_to_cpu(*((u32*)fw->data));
+ firmwareAsize = le32_to_cpu(*((__le32*)fw->data));
dprintk("FirmwareA is %i bytes\n",firmwareAsize);
- firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4)));
+ firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4)));
dprintk("FirmwareB is %i bytes\n",firmwareBsize);
/* Upload firmware */
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 7eaa476..6afe12a 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -69,7 +69,7 @@ struct or51211_state {
u32 current_frequency;
};
-static int i2c_writebytes (struct or51211_state* state, u8 reg, u8 *buf,
+static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
int len)
{
int err;
@@ -77,7 +77,7 @@ static int i2c_writebytes (struct or51211_state* state, u8 reg, u8 *buf,
msg.addr = reg;
msg.flags = 0;
msg.len = len;
- msg.buf = buf;
+ msg.buf = (u8 *)buf;
if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk(KERN_WARNING "or51211: i2c_writebytes error "
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index b999ec4..5ddb2dc 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -26,7 +26,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "s5h1409.h"
struct s5h1409_state {
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
index eb5bfc9..cff360c 100644
--- a/drivers/media/dvb/frontends/s5h1411.c
+++ b/drivers/media/dvb/frontends/s5h1411.c
@@ -26,7 +26,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include "dvb_frontend.h"
-#include "dvb-pll.h"
#include "s5h1411.h"
struct s5h1411_state {
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index aa78aa1..1c9a9b4 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -98,7 +98,7 @@ static int sp8870_readreg (struct sp8870_state* state, u16 reg)
static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
{
struct i2c_msg msg;
- char *fw_buf = fw->data;
+ const char *fw_buf = fw->data;
int fw_pos;
u8 tx_buf[255];
int tx_len;
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 49f5587..4543609 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -140,7 +140,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
u8 buf [BLOCKSIZE+2];
int i;
int fw_size = fw->size;
- unsigned char *mem = fw->data;
+ const unsigned char *mem = fw->data;
dprintk("%s\n", __func__);
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 1755618..35435be 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -63,6 +63,7 @@ struct stv0299_state {
u32 symbol_rate;
fe_code_rate_t fec_inner;
int errmode;
+ u32 ucblocks;
};
#define STATUS_BER 0
@@ -501,8 +502,10 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_BER) return 0;
- *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+ if (state->errmode != STATUS_BER)
+ return -ENOSYS;
+
+ *ber = stv0299_readreg(state, 0x1e) | (stv0299_readreg(state, 0x1d) << 8);
return 0;
}
@@ -540,8 +543,12 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct stv0299_state* state = fe->demodulator_priv;
- if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
- else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+ if (state->errmode != STATUS_UCBLOCKS)
+ return -ENOSYS;
+
+ state->ucblocks += stv0299_readreg(state, 0x1e);
+ state->ucblocks += (stv0299_readreg(state, 0x1d) << 8);
+ *ucblocks = state->ucblocks;
return 0;
}
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c
index 0727b80..a3c34ee 100644
--- a/drivers/media/dvb/frontends/tda10023.c
+++ b/drivers/media/dvb/frontends/tda10023.c
@@ -38,75 +38,29 @@
#include "dvb_frontend.h"
#include "tda1002x.h"
+#define REG0_INIT_VAL 0x23
struct tda10023_state {
struct i2c_adapter* i2c;
/* configuration settings */
- const struct tda1002x_config* config;
+ const struct tda10023_config *config;
struct dvb_frontend frontend;
u8 pwm;
u8 reg0;
-};
+ /* clock settings */
+ u32 xtal;
+ u8 pll_m;
+ u8 pll_p;
+ u8 pll_n;
+ u32 sysclk;
+};
#define dprintk(x...)
static int verbose;
-#define XTAL 28920000UL
-#define PLL_M 8UL
-#define PLL_P 4UL
-#define PLL_N 1UL
-#define SYSCLK (XTAL*PLL_M/(PLL_N*PLL_P)) // -> 57840000
-
-static u8 tda10023_inittab[]={
- // reg mask val
- 0x2a,0xff,0x02, // PLL3, Bypass, Power Down
- 0xff,0x64,0x00, // Sleep 100ms
- 0x2a,0xff,0x03, // PLL3, Bypass, Power Down
- 0xff,0x64,0x00, // Sleep 100ms
- 0x28,0xff,PLL_M-1, // PLL1 M=8
- 0x29,0xff,((PLL_P-1)<<6)|(PLL_N-1), // PLL2
- 0x00,0xff,0x23, // GPR FSAMPLING=1
- 0x2a,0xff,0x08, // PLL3 PSACLK=1
- 0xff,0x64,0x00, // Sleep 100ms
- 0x1f,0xff,0x00, // RESET
- 0xff,0x64,0x00, // Sleep 100ms
- 0xe6,0x0c,0x04, // RSCFG_IND
- 0x10,0xc0,0x80, // DECDVBCFG1 PBER=1
-
- 0x0e,0xff,0x82, // GAIN1
- 0x03,0x08,0x08, // CLKCONF DYN=1
- 0x2e,0xbf,0x30, // AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1 PPWMTUN=0 PPWMIF=0
- 0x01,0xff,0x30, // AGCREF
- 0x1e,0x84,0x84, // CONTROL SACLK_ON=1
- 0x1b,0xff,0xc8, // ADC TWOS=1
- 0x3b,0xff,0xff, // IFMAX
- 0x3c,0xff,0x00, // IFMIN
- 0x34,0xff,0x00, // PWMREF
- 0x35,0xff,0xff, // TUNMAX
- 0x36,0xff,0x00, // TUNMIN
- 0x06,0xff,0x7f, // EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 // 0x77
- 0x1c,0x30,0x30, // EQCONF2 STEPALGO=SGNALGO=1
- 0x37,0xff,0xf6, // DELTAF_LSB
- 0x38,0xff,0xff, // DELTAF_MSB
- 0x02,0xff,0x93, // AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3
- 0x2d,0xff,0xf6, // SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2
- 0x04,0x10,0x00, // SWRAMP=1
- 0x12,0xff,0xa1, // INTP1 POCLKP=1 FEL=1 MFS=0
- 0x2b,0x01,0xa1, // INTS1
- 0x20,0xff,0x04, // INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=?
- 0x2c,0xff,0x0d, // INTP/S TRIP=0 TRIS=0
- 0xc4,0xff,0x00,
- 0xc3,0x30,0x00,
- 0xb5,0xff,0x19, // ERAGC_THD
- 0x00,0x03,0x01, // GPR, CLBS soft reset
- 0x00,0x03,0x03, // GPR, CLBS soft reset
- 0xff,0x64,0x00, // Sleep 100ms
- 0xff,0xff,0xff
-};
-
static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
{
u8 b0 [] = { reg };
@@ -116,9 +70,12 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
int ret;
ret = i2c_transfer (state->i2c, msg, 2);
- if (ret != 2)
- printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
- __func__, ret);
+ if (ret != 2) {
+ int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+ printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error "
+ "(reg == 0x%02x, ret == %i)\n",
+ num, __func__, reg, ret);
+ }
return b1[0];
}
@@ -129,11 +86,12 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
int ret;
ret = i2c_transfer (state->i2c, &msg, 1);
- if (ret != 1)
- printk("DVB: TDA10023(%d): %s, writereg error "
+ if (ret != 1) {
+ int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+ printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error "
"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
- state->frontend.dvb->num, __func__, reg, data, ret);
-
+ num, __func__, reg, data, ret);
+ }
return (ret != 1) ? -EREMOTEIO : 0;
}
@@ -215,30 +173,34 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
s16 SFIL=0;
u16 NDEC = 0;
- if (sr < (u32)(SYSCLK/98.40)) {
+ /* avoid floating point operations multiplying syscloc and divider
+ by 10 */
+ u32 sysclk_x_10 = state->sysclk * 10;
+
+ if (sr < (u32)(sysclk_x_10/984)) {
NDEC=3;
SFIL=1;
- } else if (sr<(u32)(SYSCLK/64.0)) {
+ } else if (sr < (u32)(sysclk_x_10/640)) {
NDEC=3;
SFIL=0;
- } else if (sr<(u32)(SYSCLK/49.2)) {
+ } else if (sr < (u32)(sysclk_x_10/492)) {
NDEC=2;
SFIL=1;
- } else if (sr<(u32)(SYSCLK/32.0)) {
+ } else if (sr < (u32)(sysclk_x_10/320)) {
NDEC=2;
SFIL=0;
- } else if (sr<(u32)(SYSCLK/24.6)) {
+ } else if (sr < (u32)(sysclk_x_10/246)) {
NDEC=1;
SFIL=1;
- } else if (sr<(u32)(SYSCLK/16.0)) {
+ } else if (sr < (u32)(sysclk_x_10/160)) {
NDEC=1;
SFIL=0;
- } else if (sr<(u32)(SYSCLK/12.3)) {
+ } else if (sr < (u32)(sysclk_x_10/123)) {
NDEC=0;
SFIL=1;
}
- BDRI=SYSCLK*16;
+ BDRI = (state->sysclk)*16;
BDRI>>=NDEC;
BDRI +=sr/2;
BDRI /=sr;
@@ -251,11 +213,12 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
BDRX=1<<(24+NDEC);
BDRX*=sr;
- do_div(BDRX,SYSCLK); // BDRX/=SYSCLK;
+ do_div(BDRX, state->sysclk); /* BDRX/=SYSCLK; */
BDR=(s32)BDRX;
}
-// printk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",sr,BDR,BDRI,NDEC);
+ dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",
+ sr, BDR, BDRI, NDEC);
tda10023_writebit (state, 0x03, 0xc0, NDEC<<6);
tda10023_writereg (state, 0x0a, BDR&255);
tda10023_writereg (state, 0x0b, (BDR>>8)&255);
@@ -268,8 +231,67 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
static int tda10023_init (struct dvb_frontend *fe)
{
struct tda10023_state* state = fe->demodulator_priv;
+ u8 tda10023_inittab[] = {
+/* reg mask val */
+/* 000 */ 0x2a, 0xff, 0x02, /* PLL3, Bypass, Power Down */
+/* 003 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 006 */ 0x2a, 0xff, 0x03, /* PLL3, Bypass, Power Down */
+/* 009 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+ /* PLL1 */
+/* 012 */ 0x28, 0xff, (state->pll_m-1),
+ /* PLL2 */
+/* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1),
+ /* GPR FSAMPLING=1 */
+/* 018 */ 0x00, 0xff, REG0_INIT_VAL,
+/* 021 */ 0x2a, 0xff, 0x08, /* PLL3 PSACLK=1 */
+/* 024 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 027 */ 0x1f, 0xff, 0x00, /* RESET */
+/* 030 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 033 */ 0xe6, 0x0c, 0x04, /* RSCFG_IND */
+/* 036 */ 0x10, 0xc0, 0x80, /* DECDVBCFG1 PBER=1 */
+
+/* 039 */ 0x0e, 0xff, 0x82, /* GAIN1 */
+/* 042 */ 0x03, 0x08, 0x08, /* CLKCONF DYN=1 */
+/* 045 */ 0x2e, 0xbf, 0x30, /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1
+ PPWMTUN=0 PPWMIF=0 */
+/* 048 */ 0x01, 0xff, 0x30, /* AGCREF */
+/* 051 */ 0x1e, 0x84, 0x84, /* CONTROL SACLK_ON=1 */
+/* 054 */ 0x1b, 0xff, 0xc8, /* ADC TWOS=1 */
+/* 057 */ 0x3b, 0xff, 0xff, /* IFMAX */
+/* 060 */ 0x3c, 0xff, 0x00, /* IFMIN */
+/* 063 */ 0x34, 0xff, 0x00, /* PWMREF */
+/* 066 */ 0x35, 0xff, 0xff, /* TUNMAX */
+/* 069 */ 0x36, 0xff, 0x00, /* TUNMIN */
+/* 072 */ 0x06, 0xff, 0x7f, /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */
+/* 075 */ 0x1c, 0x30, 0x30, /* EQCONF2 STEPALGO=SGNALGO=1 */
+/* 078 */ 0x37, 0xff, 0xf6, /* DELTAF_LSB */
+/* 081 */ 0x38, 0xff, 0xff, /* DELTAF_MSB */
+/* 084 */ 0x02, 0xff, 0x93, /* AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3 */
+/* 087 */ 0x2d, 0xff, 0xf6, /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */
+/* 090 */ 0x04, 0x10, 0x00, /* SWRAMP=1 */
+/* 093 */ 0x12, 0xff, TDA10023_OUTPUT_MODE_PARALLEL_B, /*
+ INTP1 POCLKP=1 FEL=1 MFS=0 */
+/* 096 */ 0x2b, 0x01, 0xa1, /* INTS1 */
+/* 099 */ 0x20, 0xff, 0x04, /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */
+/* 102 */ 0x2c, 0xff, 0x0d, /* INTP/S TRIP=0 TRIS=0 */
+/* 105 */ 0xc4, 0xff, 0x00,
+/* 108 */ 0xc3, 0x30, 0x00,
+/* 111 */ 0xb5, 0xff, 0x19, /* ERAGC_THD */
+/* 114 */ 0x00, 0x03, 0x01, /* GPR, CLBS soft reset */
+/* 117 */ 0x00, 0x03, 0x03, /* GPR, CLBS soft reset */
+/* 120 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
+/* 123 */ 0xff, 0xff, 0xff
+};
+ dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num);
+
+ /* override default values if set in config */
+ if (state->config->deltaf) {
+ tda10023_inittab[80] = (state->config->deltaf & 0xff);
+ tda10023_inittab[83] = (state->config->deltaf >> 8);
+ }
- dprintk("DVB: TDA10023(%d): init chip\n", fe->adapter->num);
+ if (state->config->output_mode)
+ tda10023_inittab[95] = state->config->output_mode;
tda10023_writetab(state, tda10023_inittab);
@@ -456,36 +478,53 @@ static void tda10023_release(struct dvb_frontend* fe)
static struct dvb_frontend_ops tda10023_ops;
-struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
- struct i2c_adapter* i2c,
+struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
+ struct i2c_adapter *i2c,
u8 pwm)
{
struct tda10023_state* state = NULL;
- int i;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct tda10023_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
- state->pwm = pwm;
- for (i=0; i < ARRAY_SIZE(tda10023_inittab);i+=3) {
- if (tda10023_inittab[i] == 0x00) {
- state->reg0 = tda10023_inittab[i+2];
- break;
- }
- }
- // Wakeup if in standby
+ /* wakeup if in standby */
tda10023_writereg (state, 0x00, 0x33);
/* check if the demod is there */
if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
/* create dvb_frontend */
memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
+ state->pwm = pwm;
+ state->reg0 = REG0_INIT_VAL;
+ if (state->config->xtal) {
+ state->xtal = state->config->xtal;
+ state->pll_m = state->config->pll_m;
+ state->pll_p = state->config->pll_p;
+ state->pll_n = state->config->pll_n;
+ } else {
+ /* set default values if not defined in config */
+ state->xtal = 28920000;
+ state->pll_m = 8;
+ state->pll_p = 4;
+ state->pll_n = 1;
+ }
+
+ /* calc sysclk */
+ state->sysclk = (state->xtal * state->pll_m / \
+ (state->pll_n * state->pll_p));
+
+ state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64;
+ state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4;
+
+ dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n",
+ __func__, state->xtal, state->pll_m, state->pll_p,
+ state->pll_n);
+
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -500,10 +539,10 @@ static struct dvb_frontend_ops tda10023_ops = {
.name = "Philips TDA10023 DVB-C",
.type = FE_QAM,
.frequency_stepsize = 62500,
- .frequency_min = 47000000,
+ .frequency_min = 47000000,
.frequency_max = 862000000,
- .symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */
- .symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */
+ .symbol_rate_min = 0, /* set in tda10023_attach */
+ .symbol_rate_max = 0, /* set in tda10023_attach */
.caps = 0x400 | //FE_CAN_QAM_4
FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
FE_CAN_QAM_128 | FE_CAN_QAM_256 |
diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h
index 1bcc0d4..04d1941 100644
--- a/drivers/media/dvb/frontends/tda1002x.h
+++ b/drivers/media/dvb/frontends/tda1002x.h
@@ -26,13 +26,37 @@
#include <linux/dvb/frontend.h>
-struct tda1002x_config
-{
+struct tda1002x_config {
/* the demodulator's i2c address */
u8 demod_address;
u8 invert;
};
+enum tda10023_output_mode {
+ TDA10023_OUTPUT_MODE_PARALLEL_A = 0xe0,
+ TDA10023_OUTPUT_MODE_PARALLEL_B = 0xa1,
+ TDA10023_OUTPUT_MODE_PARALLEL_C = 0xa0,
+ TDA10023_OUTPUT_MODE_SERIAL, /* TODO: not implemented */
+};
+
+struct tda10023_config {
+ /* the demodulator's i2c address */
+ u8 demod_address;
+ u8 invert;
+
+ /* clock settings */
+ u32 xtal; /* defaults: 28920000 */
+ u8 pll_m; /* defaults: 8 */
+ u8 pll_p; /* defaults: 4 */
+ u8 pll_n; /* defaults: 1 */
+
+ /* MPEG2 TS output mode */
+ u8 output_mode;
+
+ /* input freq offset + baseband conversion type */
+ u16 deltaf;
+};
+
#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE))
extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
struct i2c_adapter* i2c, u8 pwm);
@@ -45,12 +69,15 @@ static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config*
}
#endif // CONFIG_DVB_TDA10021
-#if defined(CONFIG_DVB_TDA10023) || (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
- struct i2c_adapter* i2c, u8 pwm);
+#if defined(CONFIG_DVB_TDA10023) || \
+ (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10023_attach(
+ const struct tda10023_config *config,
+ struct i2c_adapter *i2c, u8 pwm);
#else
-static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
- struct i2c_adapter* i2c, u8 pwm)
+static inline struct dvb_frontend *tda10023_attach(
+ const struct tda10023_config *config,
+ struct i2c_adapter *i2c, u8 pwm)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
index 090fb7d..0ab8d86b 100644
--- a/drivers/media/dvb/frontends/tda10048.c
+++ b/drivers/media/dvb/frontends/tda10048.c
@@ -233,7 +233,7 @@ static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
}
static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
- u8 *data, u16 len)
+ const u8 *data, u16 len)
{
int ret = -EREMOTEIO;
struct i2c_msg msg;
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 4997384..1465ff7 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -317,7 +317,7 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
}
static int tda1004x_do_upload(struct tda1004x_state *state,
- unsigned char *mem, unsigned int len,
+ const unsigned char *mem, unsigned int len,
u8 dspCodeCounterReg, u8 dspCodeInReg)
{
u8 buf[65];
@@ -1248,11 +1248,14 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
struct i2c_adapter* i2c)
{
struct tda1004x_state *state;
+ int id;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
- if (!state)
+ if (!state) {
+ printk(KERN_ERR "Can't alocate memory for tda10045 state\n");
return NULL;
+ }
/* setup the state */
state->config = config;
@@ -1260,7 +1263,15 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
state->demod_type = TDA1004X_DEMOD_TDA10045;
/* check if the demod is there */
- if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) {
+ id = tda1004x_read_byte(state, TDA1004X_CHIPID);
+ if (id < 0) {
+ printk(KERN_ERR "tda10045: chip is not answering. Giving up.\n");
+ kfree(state);
+ return NULL;
+ }
+
+ if (id != 0x25) {
+ printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
kfree(state);
return NULL;
}
@@ -1307,11 +1318,14 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
struct i2c_adapter* i2c)
{
struct tda1004x_state *state;
+ int id;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
- if (!state)
+ if (!state) {
+ printk(KERN_ERR "Can't alocate memory for tda10046 state\n");
return NULL;
+ }
/* setup the state */
state->config = config;
@@ -1319,7 +1333,14 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
state->demod_type = TDA1004X_DEMOD_TDA10046;
/* check if the demod is there */
- if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) {
+ id = tda1004x_read_byte(state, TDA1004X_CHIPID);
+ if (id < 0) {
+ printk(KERN_ERR "tda10046: chip is not answering. Giving up.\n");
+ kfree(state);
+ return NULL;
+ }
+ if (id != 0x46) {
+ printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb/frontends/z0194a.h
new file mode 100644
index 0000000..d2876d2
--- /dev/null
+++ b/drivers/media/dvb/frontends/z0194a.h
@@ -0,0 +1,97 @@
+/* z0194a.h Sharp z0194a tuner support
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+* 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 Z0194A
+#define Z0194A
+
+static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
+ u32 srate, u32 ratio)
+{
+ u8 aclk = 0;
+ u8 bclk = 0;
+
+ if (srate < 1500000) {
+ aclk = 0xb7; bclk = 0x47; }
+ else if (srate < 3000000) {
+ aclk = 0xb7; bclk = 0x4b; }
+ else if (srate < 7000000) {
+ aclk = 0xb7; bclk = 0x4f; }
+ else if (srate < 14000000) {
+ aclk = 0xb7; bclk = 0x53; }
+ else if (srate < 30000000) {
+ aclk = 0xb6; bclk = 0x53; }
+ else if (srate < 45000000) {
+ aclk = 0xb4; bclk = 0x51; }
+
+ stv0299_writereg(fe, 0x13, aclk);
+ stv0299_writereg(fe, 0x14, bclk);
+ stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+ stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+ stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+
+ return 0;
+}
+
+static u8 sharp_z0194a__inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x00,
+ 0x03, 0x00,
+ 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
+ 0x06, 0x40, /* DAC not used, set to high impendance mode */
+ 0x07, 0x00, /* DAC LSB */
+ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
+ 0x09, 0x00, /* FIFO */
+ 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+ 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
+ 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
+ 0x10, 0x3f, /* AGC2 0x3d */
+ 0x11, 0x84,
+ 0x12, 0xb9,
+ 0x15, 0xc9, /* lock detector threshold */
+ 0x16, 0x00,
+ 0x17, 0x00,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1a, 0x00,
+ 0x1f, 0x50,
+ 0x20, 0x00,
+ 0x21, 0x00,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x28, 0x00, /* out imp: normal out type: parallel FEC mode:0 */
+ 0x29, 0x1e, /* 1/2 threshold */
+ 0x2a, 0x14, /* 2/3 threshold */
+ 0x2b, 0x0f, /* 3/4 threshold */
+ 0x2c, 0x09, /* 5/6 threshold */
+ 0x2d, 0x05, /* 7/8 threshold */
+ 0x2e, 0x01,
+ 0x31, 0x1f, /* test all FECs */
+ 0x32, 0x19, /* viterbi and synchro search */
+ 0x33, 0xfc, /* rs control */
+ 0x34, 0x93, /* error control */
+ 0x0f, 0x52,
+ 0xff, 0xff
+};
+
+static struct stv0299_config sharp_z0194a_config = {
+ .demod_address = 0x68,
+ .inittab = sharp_z0194a__inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0299_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = sharp_z0194a__set_symbol_rate,
+};
+
+#endif
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 960ed57..a9653c6 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -234,7 +234,7 @@ static void pluto_reset_ts(struct pluto *pluto, int reenable)
static void pluto_set_dma_addr(struct pluto *pluto)
{
- pluto_writereg(pluto, REG_PCAR, cpu_to_le32(pluto->dma_addr));
+ pluto_writereg(pluto, REG_PCAR, pluto->dma_addr);
}
static int __devinit pluto_dma_map(struct pluto *pluto)
@@ -242,7 +242,7 @@ static int __devinit pluto_dma_map(struct pluto *pluto)
pluto->dma_addr = pci_map_single(pluto->pdev, pluto->dma_buf,
TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
- return pci_dma_mapping_error(pluto->dma_addr);
+ return pci_dma_mapping_error(pluto->pdev, pluto->dma_addr);
}
static void pluto_dma_unmap(struct pluto *pluto)
diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig
new file mode 100644
index 0000000..dd863f2
--- /dev/null
+++ b/drivers/media/dvb/siano/Kconfig
@@ -0,0 +1,26 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config DVB_SIANO_SMS1XXX
+ tristate "Siano SMS1XXX USB dongle support"
+ depends on DVB_CORE && USB
+ ---help---
+ Choose Y here if you have a USB dongle with a SMS1XXX chipset.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sms1xxx.
+
+config DVB_SIANO_SMS1XXX_SMS_IDS
+ bool "Enable support for Siano Mobile Silicon default USB IDs"
+ depends on DVB_SIANO_SMS1XXX
+ default y
+ ---help---
+ Choose Y here if you have a USB dongle with a SMS1XXX chipset
+ that uses Siano Mobile Silicon's default usb vid:pid.
+
+ Choose N here if you would prefer to use Siano's external driver.
+
+ Further documentation on this driver can be found on the WWW at
+ <http://www.siano-ms.com/>.
+
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
new file mode 100644
index 0000000..ee0737a
--- /dev/null
+++ b/drivers/media/dvb/siano/Makefile
@@ -0,0 +1,8 @@
+sms1xxx-objs := smscoreapi.o smsusb.o smsdvb.o sms-cards.o
+
+obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
new file mode 100644
index 0000000..e7a8ac0
--- /dev/null
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -0,0 +1,102 @@
+/*
+ * Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * 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 "sms-cards.h"
+
+struct usb_device_id smsusb_id_table[] = {
+#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
+ { USB_DEVICE(0x187f, 0x0010),
+ .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+ { USB_DEVICE(0x187f, 0x0100),
+ .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+ { USB_DEVICE(0x187f, 0x0200),
+ .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A },
+ { USB_DEVICE(0x187f, 0x0201),
+ .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
+ { USB_DEVICE(0x187f, 0x0300),
+ .driver_info = SMS1XXX_BOARD_SIANO_VEGA },
+#endif
+ { USB_DEVICE(0x2040, 0x1700),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
+ { USB_DEVICE(0x2040, 0x1800),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
+ { USB_DEVICE(0x2040, 0x1801),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
+ { USB_DEVICE(0x2040, 0x5500),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5580),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5590),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, smsusb_id_table);
+
+static struct sms_board sms_boards[] = {
+ [SMS_BOARD_UNKNOWN] = {
+ .name = "Unknown board",
+ },
+ [SMS1XXX_BOARD_SIANO_STELLAR] = {
+ .name = "Siano Stellar Digital Receiver",
+ .type = SMS_STELLAR,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_SIANO_NOVA_A] = {
+ .name = "Siano Nova A Digital Receiver",
+ .type = SMS_NOVA_A0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_SIANO_NOVA_B] = {
+ .name = "Siano Nova B Digital Receiver",
+ .type = SMS_NOVA_B0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_SIANO_VEGA] = {
+ .name = "Siano Vega Digital Receiver",
+ .type = SMS_VEGA,
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
+ .name = "Hauppauge Catamount",
+ .type = SMS_STELLAR,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
+ .name = "Hauppauge Okemo-A",
+ .type = SMS_NOVA_A0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
+ .name = "Hauppauge Okemo-B",
+ .type = SMS_NOVA_B0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
+ .name = "Hauppauge WinTV-Nova-T-MiniStick",
+ .type = SMS_NOVA_B0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
+ },
+};
+
+struct sms_board *sms_get_board(int id)
+{
+ BUG_ON(id >= ARRAY_SIZE(sms_boards));
+
+ return &sms_boards[id];
+}
+
diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h
new file mode 100644
index 0000000..83b39bc
--- /dev/null
+++ b/drivers/media/dvb/siano/sms-cards.h
@@ -0,0 +1,45 @@
+/*
+ * Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * 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 __SMS_CARDS_H__
+#define __SMS_CARDS_H__
+
+#include <linux/usb.h>
+#include "smscoreapi.h"
+
+#define SMS_BOARD_UNKNOWN 0
+#define SMS1XXX_BOARD_SIANO_STELLAR 1
+#define SMS1XXX_BOARD_SIANO_NOVA_A 2
+#define SMS1XXX_BOARD_SIANO_NOVA_B 3
+#define SMS1XXX_BOARD_SIANO_VEGA 4
+#define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7
+#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
+
+struct sms_board {
+ enum sms_device_type_st type;
+ char *name, *fw[DEVICE_MODE_MAX];
+};
+
+struct sms_board *sms_get_board(int id);
+
+extern struct usb_device_id smsusb_id_table[];
+
+#endif /* __SMS_CARDS_H__ */
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
new file mode 100644
index 0000000..c5f45fe
--- /dev/null
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -0,0 +1,1251 @@
+/*
+ * Siano core API module
+ *
+ * This file contains implementation for the interface to sms core component
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <linux/firmware.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+int sms_debug;
+module_param_named(debug, sms_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+
+struct smscore_device_notifyee_t {
+ struct list_head entry;
+ hotplug_t hotplug;
+};
+
+struct smscore_idlist_t {
+ struct list_head entry;
+ int id;
+ int data_type;
+};
+
+struct smscore_client_t {
+ struct list_head entry;
+ struct smscore_device_t *coredev;
+ void *context;
+ struct list_head idlist;
+ onresponse_t onresponse_handler;
+ onremove_t onremove_handler;
+};
+
+struct smscore_device_t {
+ struct list_head entry;
+
+ struct list_head clients;
+ struct list_head subclients;
+ spinlock_t clientslock;
+
+ struct list_head buffers;
+ spinlock_t bufferslock;
+ int num_buffers;
+
+ void *common_buffer;
+ int common_buffer_size;
+ dma_addr_t common_buffer_phys;
+
+ void *context;
+ struct device *device;
+
+ char devpath[32];
+ unsigned long device_flags;
+
+ setmode_t setmode_handler;
+ detectmode_t detectmode_handler;
+ sendrequest_t sendrequest_handler;
+ preload_t preload_handler;
+ postload_t postload_handler;
+
+ int mode, modes_supported;
+
+ struct completion version_ex_done, data_download_done, trigger_done;
+ struct completion init_device_done, reload_start_done, resume_done;
+
+ int board_id;
+};
+
+void smscore_set_board_id(struct smscore_device_t *core, int id)
+{
+ core->board_id = id;
+}
+
+int smscore_get_board_id(struct smscore_device_t *core)
+{
+ return core->board_id;
+}
+
+struct smscore_registry_entry_t {
+ struct list_head entry;
+ char devpath[32];
+ int mode;
+ enum sms_device_type_st type;
+};
+
+static struct list_head g_smscore_notifyees;
+static struct list_head g_smscore_devices;
+static struct mutex g_smscore_deviceslock;
+
+static struct list_head g_smscore_registry;
+static struct mutex g_smscore_registrylock;
+
+static int default_mode = 4;
+
+module_param(default_mode, int, 0644);
+MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
+
+static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
+{
+ struct smscore_registry_entry_t *entry;
+ struct list_head *next;
+
+ kmutex_lock(&g_smscore_registrylock);
+ for (next = g_smscore_registry.next;
+ next != &g_smscore_registry;
+ next = next->next) {
+ entry = (struct smscore_registry_entry_t *) next;
+ if (!strcmp(entry->devpath, devpath)) {
+ kmutex_unlock(&g_smscore_registrylock);
+ return entry;
+ }
+ }
+ entry = (struct smscore_registry_entry_t *)
+ kmalloc(sizeof(struct smscore_registry_entry_t),
+ GFP_KERNEL);
+ if (entry) {
+ entry->mode = default_mode;
+ strcpy(entry->devpath, devpath);
+ list_add(&entry->entry, &g_smscore_registry);
+ } else
+ sms_err("failed to create smscore_registry.");
+ kmutex_unlock(&g_smscore_registrylock);
+ return entry;
+}
+
+int smscore_registry_getmode(char *devpath)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ return entry->mode;
+ else
+ sms_err("No registry found.");
+
+ return default_mode;
+}
+
+static enum sms_device_type_st smscore_registry_gettype(char *devpath)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ return entry->type;
+ else
+ sms_err("No registry found.");
+
+ return -1;
+}
+
+void smscore_registry_setmode(char *devpath, int mode)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ entry->mode = mode;
+ else
+ sms_err("No registry found.");
+}
+
+static void smscore_registry_settype(char *devpath,
+ enum sms_device_type_st type)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ entry->type = type;
+ else
+ sms_err("No registry found.");
+}
+
+
+static void list_add_locked(struct list_head *new, struct list_head *head,
+ spinlock_t *lock)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(lock, flags);
+
+ list_add(new, head);
+
+ spin_unlock_irqrestore(lock, flags);
+}
+
+/**
+ * register a client callback that called when device plugged in/unplugged
+ * NOTE: if devices exist callback is called immediately for each device
+ *
+ * @param hotplug callback
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_hotplug(hotplug_t hotplug)
+{
+ struct smscore_device_notifyee_t *notifyee;
+ struct list_head *next, *first;
+ int rc = 0;
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
+ GFP_KERNEL);
+ if (notifyee) {
+ /* now notify callback about existing devices */
+ first = &g_smscore_devices;
+ for (next = first->next;
+ next != first && !rc;
+ next = next->next) {
+ struct smscore_device_t *coredev =
+ (struct smscore_device_t *) next;
+ rc = hotplug(coredev, coredev->device, 1);
+ }
+
+ if (rc >= 0) {
+ notifyee->hotplug = hotplug;
+ list_add(&notifyee->entry, &g_smscore_notifyees);
+ } else
+ kfree(notifyee);
+ } else
+ rc = -ENOMEM;
+
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ return rc;
+}
+
+/**
+ * unregister a client callback that called when device plugged in/unplugged
+ *
+ * @param hotplug callback
+ *
+ */
+void smscore_unregister_hotplug(hotplug_t hotplug)
+{
+ struct list_head *next, *first;
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ first = &g_smscore_notifyees;
+
+ for (next = first->next; next != first;) {
+ struct smscore_device_notifyee_t *notifyee =
+ (struct smscore_device_notifyee_t *) next;
+ next = next->next;
+
+ if (notifyee->hotplug == hotplug) {
+ list_del(&notifyee->entry);
+ kfree(notifyee);
+ }
+ }
+
+ kmutex_unlock(&g_smscore_deviceslock);
+}
+
+static void smscore_notify_clients(struct smscore_device_t *coredev)
+{
+ struct smscore_client_t *client;
+
+ /* the client must call smscore_unregister_client from remove handler */
+ while (!list_empty(&coredev->clients)) {
+ client = (struct smscore_client_t *) coredev->clients.next;
+ client->onremove_handler(client->context);
+ }
+}
+
+static int smscore_notify_callbacks(struct smscore_device_t *coredev,
+ struct device *device, int arrival)
+{
+ struct list_head *next, *first;
+ int rc = 0;
+
+ /* note: must be called under g_deviceslock */
+
+ first = &g_smscore_notifyees;
+
+ for (next = first->next; next != first; next = next->next) {
+ rc = ((struct smscore_device_notifyee_t *) next)->
+ hotplug(coredev, device, arrival);
+ if (rc < 0)
+ break;
+ }
+
+ return rc;
+}
+
+static struct
+smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
+ dma_addr_t common_buffer_phys)
+{
+ struct smscore_buffer_t *cb =
+ kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
+ if (!cb) {
+ sms_info("kmalloc(...) failed");
+ return NULL;
+ }
+
+ cb->p = buffer;
+ cb->offset_in_common = buffer - (u8 *) common_buffer;
+ cb->phys = common_buffer_phys + cb->offset_in_common;
+
+ return cb;
+}
+
+/**
+ * creates coredev object for a device, prepares buffers,
+ * creates buffer mappings, notifies registered hotplugs about new device.
+ *
+ * @param params device pointer to struct with device specific parameters
+ * and handlers
+ * @param coredev pointer to a value that receives created coredev object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_device(struct smsdevice_params_t *params,
+ struct smscore_device_t **coredev)
+{
+ struct smscore_device_t *dev;
+ u8 *buffer;
+
+ dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
+ if (!dev) {
+ sms_info("kzalloc(...) failed");
+ return -ENOMEM;
+ }
+
+ /* init list entry so it could be safe in smscore_unregister_device */
+ INIT_LIST_HEAD(&dev->entry);
+
+ /* init queues */
+ INIT_LIST_HEAD(&dev->clients);
+ INIT_LIST_HEAD(&dev->buffers);
+
+ /* init locks */
+ spin_lock_init(&dev->clientslock);
+ spin_lock_init(&dev->bufferslock);
+
+ /* init completion events */
+ init_completion(&dev->version_ex_done);
+ init_completion(&dev->data_download_done);
+ init_completion(&dev->trigger_done);
+ init_completion(&dev->init_device_done);
+ init_completion(&dev->reload_start_done);
+ init_completion(&dev->resume_done);
+
+ /* alloc common buffer */
+ dev->common_buffer_size = params->buffer_size * params->num_buffers;
+ dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
+ &dev->common_buffer_phys,
+ GFP_KERNEL | GFP_DMA);
+ if (!dev->common_buffer) {
+ smscore_unregister_device(dev);
+ return -ENOMEM;
+ }
+
+ /* prepare dma buffers */
+ for (buffer = dev->common_buffer;
+ dev->num_buffers < params->num_buffers;
+ dev->num_buffers++, buffer += params->buffer_size) {
+ struct smscore_buffer_t *cb =
+ smscore_createbuffer(buffer, dev->common_buffer,
+ dev->common_buffer_phys);
+ if (!cb) {
+ smscore_unregister_device(dev);
+ return -ENOMEM;
+ }
+
+ smscore_putbuffer(dev, cb);
+ }
+
+ sms_info("allocated %d buffers", dev->num_buffers);
+
+ dev->mode = DEVICE_MODE_NONE;
+ dev->context = params->context;
+ dev->device = params->device;
+ dev->setmode_handler = params->setmode_handler;
+ dev->detectmode_handler = params->detectmode_handler;
+ dev->sendrequest_handler = params->sendrequest_handler;
+ dev->preload_handler = params->preload_handler;
+ dev->postload_handler = params->postload_handler;
+
+ dev->device_flags = params->flags;
+ strcpy(dev->devpath, params->devpath);
+
+ smscore_registry_settype(dev->devpath, params->device_type);
+
+ /* add device to devices list */
+ kmutex_lock(&g_smscore_deviceslock);
+ list_add(&dev->entry, &g_smscore_devices);
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ *coredev = dev;
+
+ sms_info("device %p created", dev);
+
+ return 0;
+}
+
+/**
+ * sets initial device mode and notifies client hotplugs that device is ready
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_start_device(struct smscore_device_t *coredev)
+{
+ int rc = smscore_set_device_mode(
+ coredev, smscore_registry_getmode(coredev->devpath));
+ if (rc < 0) {
+ sms_info("set device mode faile , rc %d", rc);
+ return rc;
+ }
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ rc = smscore_notify_callbacks(coredev, coredev->device, 1);
+
+ sms_info("device %p started, rc %d", coredev, rc);
+
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ return rc;
+}
+
+static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
+ void *buffer, size_t size,
+ struct completion *completion)
+{
+ int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+ if (rc < 0) {
+ sms_info("sendrequest returned error %d", rc);
+ return rc;
+ }
+
+ return wait_for_completion_timeout(completion,
+ msecs_to_jiffies(10000)) ?
+ 0 : -ETIME;
+}
+
+static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
+ void *buffer, size_t size)
+{
+ struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
+ struct SmsMsgHdr_ST *msg;
+ u32 mem_address = firmware->StartAddress;
+ u8 *payload = firmware->Payload;
+ int rc = 0;
+
+ sms_info("loading FW to addr 0x%x size %d",
+ mem_address, firmware->Length);
+ if (coredev->preload_handler) {
+ rc = coredev->preload_handler(coredev->context);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* PAGE_SIZE buffer shall be enough and dma aligned */
+ msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+ if (!msg)
+ return -ENOMEM;
+
+ if (coredev->mode != DEVICE_MODE_NONE) {
+ sms_debug("sending reload command.");
+ SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
+ sizeof(struct SmsMsgHdr_ST));
+ rc = smscore_sendrequest_and_wait(coredev, msg,
+ msg->msgLength,
+ &coredev->reload_start_done);
+ mem_address = *(u32 *) &payload[20];
+ }
+
+ while (size && rc >= 0) {
+ struct SmsDataDownload_ST *DataMsg =
+ (struct SmsDataDownload_ST *) msg;
+ int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
+
+ SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
+ (u16)(sizeof(struct SmsMsgHdr_ST) +
+ sizeof(u32) + payload_size));
+
+ DataMsg->MemAddr = mem_address;
+ memcpy(DataMsg->Payload, payload, payload_size);
+
+ if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
+ (coredev->mode == DEVICE_MODE_NONE))
+ rc = coredev->sendrequest_handler(
+ coredev->context, DataMsg,
+ DataMsg->xMsgHeader.msgLength);
+ else
+ rc = smscore_sendrequest_and_wait(
+ coredev, DataMsg,
+ DataMsg->xMsgHeader.msgLength,
+ &coredev->data_download_done);
+
+ payload += payload_size;
+ size -= payload_size;
+ mem_address += payload_size;
+ }
+
+ if (rc >= 0) {
+ if (coredev->mode == DEVICE_MODE_NONE) {
+ struct SmsMsgData_ST *TriggerMsg =
+ (struct SmsMsgData_ST *) msg;
+
+ SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+ sizeof(struct SmsMsgHdr_ST) +
+ sizeof(u32) * 5);
+
+ TriggerMsg->msgData[0] = firmware->StartAddress;
+ /* Entry point */
+ TriggerMsg->msgData[1] = 5; /* Priority */
+ TriggerMsg->msgData[2] = 0x200; /* Stack size */
+ TriggerMsg->msgData[3] = 0; /* Parameter */
+ TriggerMsg->msgData[4] = 4; /* Task ID */
+
+ if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
+ rc = coredev->sendrequest_handler(
+ coredev->context, TriggerMsg,
+ TriggerMsg->xMsgHeader.msgLength);
+ msleep(100);
+ } else
+ rc = smscore_sendrequest_and_wait(
+ coredev, TriggerMsg,
+ TriggerMsg->xMsgHeader.msgLength,
+ &coredev->trigger_done);
+ } else {
+ SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
+ sizeof(struct SmsMsgHdr_ST));
+
+ rc = coredev->sendrequest_handler(coredev->context,
+ msg, msg->msgLength);
+ }
+ msleep(500);
+ }
+
+ sms_debug("rc=%d, postload=%p ", rc,
+ coredev->postload_handler);
+
+ kfree(msg);
+
+ return ((rc >= 0) && coredev->postload_handler) ?
+ coredev->postload_handler(coredev->context) :
+ rc;
+}
+
+/**
+ * loads specified firmware into a buffer and calls device loadfirmware_handler
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param filename null-terminated string specifies firmware file name
+ * @param loadfirmware_handler device handler that loads firmware
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
+ char *filename,
+ loadfirmware_t loadfirmware_handler)
+{
+ int rc = -ENOENT;
+ const struct firmware *fw;
+ u8 *fw_buffer;
+
+ if (loadfirmware_handler == NULL && !(coredev->device_flags &
+ SMS_DEVICE_FAMILY2))
+ return -EINVAL;
+
+ rc = request_firmware(&fw, filename, coredev->device);
+ if (rc < 0) {
+ sms_info("failed to open \"%s\"", filename);
+ return rc;
+ }
+ sms_info("read FW %s, size=%zd", filename, fw->size);
+ fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+ GFP_KERNEL | GFP_DMA);
+ if (fw_buffer) {
+ memcpy(fw_buffer, fw->data, fw->size);
+
+ rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
+ smscore_load_firmware_family2(coredev,
+ fw_buffer,
+ fw->size) :
+ loadfirmware_handler(coredev->context,
+ fw_buffer, fw->size);
+
+ kfree(fw_buffer);
+ } else {
+ sms_info("failed to allocate firmware buffer");
+ rc = -ENOMEM;
+ }
+
+ release_firmware(fw);
+
+ return rc;
+}
+
+/**
+ * notifies all clients registered with the device, notifies hotplugs,
+ * frees all buffers and coredev object
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+void smscore_unregister_device(struct smscore_device_t *coredev)
+{
+ struct smscore_buffer_t *cb;
+ int num_buffers = 0;
+ int retry = 0;
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ smscore_notify_clients(coredev);
+ smscore_notify_callbacks(coredev, NULL, 0);
+
+ /* at this point all buffers should be back
+ * onresponse must no longer be called */
+
+ while (1) {
+ while ((cb = smscore_getbuffer(coredev))) {
+ kfree(cb);
+ num_buffers++;
+ }
+ if (num_buffers == coredev->num_buffers)
+ break;
+ if (++retry > 10) {
+ sms_info("exiting although "
+ "not all buffers released.");
+ break;
+ }
+
+ sms_info("waiting for %d buffer(s)",
+ coredev->num_buffers - num_buffers);
+ msleep(100);
+ }
+
+ sms_info("freed %d buffers", num_buffers);
+
+ if (coredev->common_buffer)
+ dma_free_coherent(NULL, coredev->common_buffer_size,
+ coredev->common_buffer,
+ coredev->common_buffer_phys);
+
+ list_del(&coredev->entry);
+ kfree(coredev);
+
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ sms_info("device %p destroyed", coredev);
+}
+
+static int smscore_detect_mode(struct smscore_device_t *coredev)
+{
+ void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ struct SmsMsgHdr_ST *msg =
+ (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
+ int rc;
+
+ if (!buffer)
+ return -ENOMEM;
+
+ SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
+ sizeof(struct SmsMsgHdr_ST));
+
+ rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
+ &coredev->version_ex_done);
+ if (rc == -ETIME) {
+ sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
+
+ if (wait_for_completion_timeout(&coredev->resume_done,
+ msecs_to_jiffies(5000))) {
+ rc = smscore_sendrequest_and_wait(
+ coredev, msg, msg->msgLength,
+ &coredev->version_ex_done);
+ if (rc < 0)
+ sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
+ "second try, rc %d", rc);
+ } else
+ rc = -ETIME;
+ }
+
+ kfree(buffer);
+
+ return rc;
+}
+
+static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
+ /*Stellar NOVA A0 Nova B0 VEGA*/
+ /*DVBT*/
+ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+ /*DVBH*/
+ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+ /*TDMB*/
+ {"none", "tdmb_nova_12mhz.inp", "none", "none"},
+ /*DABIP*/
+ {"none", "none", "none", "none"},
+ /*BDA*/
+ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+ /*ISDBT*/
+ {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"},
+ /*ISDBTBDA*/
+ {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
+ /*CMMB*/
+ {"none", "none", "none", "cmmb_vega_12mhz.inp"}
+};
+
+static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
+ int mode, enum sms_device_type_st type)
+{
+ char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
+ return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+}
+
+/**
+ * calls device handler to change mode of operation
+ * NOTE: stellar/usb may disconnect when changing mode
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
+{
+ void *buffer;
+ int rc = 0;
+ enum sms_device_type_st type;
+
+ sms_debug("set device mode to %d", mode);
+ if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
+ if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
+ sms_err("invalid mode specified %d", mode);
+ return -EINVAL;
+ }
+
+ smscore_registry_setmode(coredev->devpath, mode);
+
+ if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
+ rc = smscore_detect_mode(coredev);
+ if (rc < 0) {
+ sms_err("mode detect failed %d", rc);
+ return rc;
+ }
+ }
+
+ if (coredev->mode == mode) {
+ sms_info("device mode %d already set", mode);
+ return 0;
+ }
+
+ if (!(coredev->modes_supported & (1 << mode))) {
+ char *fw_filename;
+
+ type = smscore_registry_gettype(coredev->devpath);
+ fw_filename = sms_get_fw_name(coredev, mode, type);
+
+ rc = smscore_load_firmware_from_file(coredev,
+ fw_filename, NULL);
+ if (rc < 0) {
+ sms_warn("error %d loading firmware: %s, "
+ "trying again with default firmware",
+ rc, fw_filename);
+
+ /* try again with the default firmware */
+ fw_filename = smscore_fw_lkup[mode][type];
+ rc = smscore_load_firmware_from_file(coredev,
+ fw_filename, NULL);
+
+ if (rc < 0) {
+ sms_warn("error %d loading "
+ "firmware: %s", rc,
+ fw_filename);
+ return rc;
+ }
+ }
+ sms_log("firmware download success: %s", fw_filename);
+ } else
+ sms_info("mode %d supported by running "
+ "firmware", mode);
+
+ buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
+ SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+ if (buffer) {
+ struct SmsMsgData_ST *msg =
+ (struct SmsMsgData_ST *)
+ SMS_ALIGN_ADDRESS(buffer);
+
+ SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
+ sizeof(struct SmsMsgData_ST));
+ msg->msgData[0] = mode;
+
+ rc = smscore_sendrequest_and_wait(
+ coredev, msg, msg->xMsgHeader.msgLength,
+ &coredev->init_device_done);
+
+ kfree(buffer);
+ } else {
+ sms_err("Could not allocate buffer for "
+ "init device message.");
+ rc = -ENOMEM;
+ }
+ } else {
+ if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+ sms_err("invalid mode specified %d", mode);
+ return -EINVAL;
+ }
+
+ smscore_registry_setmode(coredev->devpath, mode);
+
+ if (coredev->detectmode_handler)
+ coredev->detectmode_handler(coredev->context,
+ &coredev->mode);
+
+ if (coredev->mode != mode && coredev->setmode_handler)
+ rc = coredev->setmode_handler(coredev->context, mode);
+ }
+
+ if (rc >= 0) {
+ coredev->mode = mode;
+ coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
+ }
+
+ if (rc != 0)
+ sms_err("return error code %d.", rc);
+ return rc;
+}
+
+/**
+ * calls device handler to get current mode of operation
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return current mode
+ */
+int smscore_get_device_mode(struct smscore_device_t *coredev)
+{
+ return coredev->mode;
+}
+
+/**
+ * find client by response id & type within the clients list.
+ * return client handle or NULL.
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param data_type client data type (SMS_DONT_CARE for all types)
+ * @param id client id (SMS_DONT_CARE for all id)
+ *
+ */
+static struct
+smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
+ int data_type, int id)
+{
+ struct smscore_client_t *client = NULL;
+ struct list_head *next, *first;
+ unsigned long flags;
+ struct list_head *firstid, *nextid;
+
+
+ spin_lock_irqsave(&coredev->clientslock, flags);
+ first = &coredev->clients;
+ for (next = first->next;
+ (next != first) && !client;
+ next = next->next) {
+ firstid = &((struct smscore_client_t *)next)->idlist;
+ for (nextid = firstid->next;
+ nextid != firstid;
+ nextid = nextid->next) {
+ if ((((struct smscore_idlist_t *)nextid)->id == id) &&
+ (((struct smscore_idlist_t *)nextid)->data_type == data_type ||
+ (((struct smscore_idlist_t *)nextid)->data_type == 0))) {
+ client = (struct smscore_client_t *) next;
+ break;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&coredev->clientslock, flags);
+ return client;
+}
+
+/**
+ * find client by response id/type, call clients onresponse handler
+ * return buffer to pool on error
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param cb pointer to response buffer descriptor
+ *
+ */
+void smscore_onresponse(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb)
+{
+ struct SmsMsgHdr_ST *phdr =
+ (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);
+ struct smscore_client_t *client =
+ smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+ int rc = -EBUSY;
+
+ static unsigned long last_sample_time; /* = 0; */
+ static int data_total; /* = 0; */
+ unsigned long time_now = jiffies_to_msecs(jiffies);
+
+ if (!last_sample_time)
+ last_sample_time = time_now;
+
+ if (time_now - last_sample_time > 10000) {
+ sms_debug("\ndata rate %d bytes/secs",
+ (int)((data_total * 1000) /
+ (time_now - last_sample_time)));
+
+ last_sample_time = time_now;
+ data_total = 0;
+ }
+
+ data_total += cb->size;
+ /* If no client registered for type & id,
+ * check for control client where type is not registered */
+ if (client)
+ rc = client->onresponse_handler(client->context, cb);
+
+ if (rc < 0) {
+ switch (phdr->msgType) {
+ case MSG_SMS_GET_VERSION_EX_RES:
+ {
+ struct SmsVersionRes_ST *ver =
+ (struct SmsVersionRes_ST *) phdr;
+ sms_debug("MSG_SMS_GET_VERSION_EX_RES "
+ "id %d prots 0x%x ver %d.%d",
+ ver->FirmwareId, ver->SupportedProtocols,
+ ver->RomVersionMajor, ver->RomVersionMinor);
+
+ coredev->mode = ver->FirmwareId == 255 ?
+ DEVICE_MODE_NONE : ver->FirmwareId;
+ coredev->modes_supported = ver->SupportedProtocols;
+
+ complete(&coredev->version_ex_done);
+ break;
+ }
+ case MSG_SMS_INIT_DEVICE_RES:
+ sms_debug("MSG_SMS_INIT_DEVICE_RES");
+ complete(&coredev->init_device_done);
+ break;
+ case MSG_SW_RELOAD_START_RES:
+ sms_debug("MSG_SW_RELOAD_START_RES");
+ complete(&coredev->reload_start_done);
+ break;
+ case MSG_SMS_DATA_DOWNLOAD_RES:
+ complete(&coredev->data_download_done);
+ break;
+ case MSG_SW_RELOAD_EXEC_RES:
+ sms_debug("MSG_SW_RELOAD_EXEC_RES");
+ break;
+ case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
+ sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
+ complete(&coredev->trigger_done);
+ break;
+ case MSG_SMS_SLEEP_RESUME_COMP_IND:
+ complete(&coredev->resume_done);
+ break;
+ default:
+ break;
+ }
+ smscore_putbuffer(coredev, cb);
+ }
+}
+
+/**
+ * return pointer to next free buffer descriptor from core pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return pointer to descriptor on success, NULL on error.
+ */
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+{
+ struct smscore_buffer_t *cb = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&coredev->bufferslock, flags);
+
+ if (!list_empty(&coredev->buffers)) {
+ cb = (struct smscore_buffer_t *) coredev->buffers.next;
+ list_del(&cb->entry);
+ }
+
+ spin_unlock_irqrestore(&coredev->bufferslock, flags);
+
+ return cb;
+}
+
+/**
+ * return buffer descriptor to a pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param cb pointer buffer descriptor
+ *
+ */
+void smscore_putbuffer(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb)
+{
+ list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
+}
+
+static int smscore_validate_client(struct smscore_device_t *coredev,
+ struct smscore_client_t *client,
+ int data_type, int id)
+{
+ struct smscore_idlist_t *listentry;
+ struct smscore_client_t *registered_client;
+
+ if (!client) {
+ sms_err("bad parameter.");
+ return -EFAULT;
+ }
+ registered_client = smscore_find_client(coredev, data_type, id);
+ if (registered_client == client)
+ return 0;
+
+ if (registered_client) {
+ sms_err("The msg ID already registered to another client.");
+ return -EEXIST;
+ }
+ listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
+ if (!listentry) {
+ sms_err("Can't allocate memory for client id.");
+ return -ENOMEM;
+ }
+ listentry->id = id;
+ listentry->data_type = data_type;
+ list_add_locked(&listentry->entry, &client->idlist,
+ &coredev->clientslock);
+ return 0;
+}
+
+/**
+ * creates smsclient object, check that id is taken by another client
+ *
+ * @param coredev pointer to a coredev object from clients hotplug
+ * @param initial_id all messages with this id would be sent to this client
+ * @param data_type all messages of this type would be sent to this client
+ * @param onresponse_handler client handler that is called to
+ * process incoming messages
+ * @param onremove_handler client handler that is called when device is removed
+ * @param context client-specific context
+ * @param client pointer to a value that receives created smsclient object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_client(struct smscore_device_t *coredev,
+ struct smsclient_params_t *params,
+ struct smscore_client_t **client)
+{
+ struct smscore_client_t *newclient;
+ /* check that no other channel with same parameters exists */
+ if (smscore_find_client(coredev, params->data_type,
+ params->initial_id)) {
+ sms_err("Client already exist.");
+ return -EEXIST;
+ }
+
+ newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
+ if (!newclient) {
+ sms_err("Failed to allocate memory for client.");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&newclient->idlist);
+ newclient->coredev = coredev;
+ newclient->onresponse_handler = params->onresponse_handler;
+ newclient->onremove_handler = params->onremove_handler;
+ newclient->context = params->context;
+ list_add_locked(&newclient->entry, &coredev->clients,
+ &coredev->clientslock);
+ smscore_validate_client(coredev, newclient, params->data_type,
+ params->initial_id);
+ *client = newclient;
+ sms_debug("%p %d %d", params->context, params->data_type,
+ params->initial_id);
+
+ return 0;
+}
+
+/**
+ * frees smsclient object and all subclients associated with it
+ *
+ * @param client pointer to smsclient object returned by
+ * smscore_register_client
+ *
+ */
+void smscore_unregister_client(struct smscore_client_t *client)
+{
+ struct smscore_device_t *coredev = client->coredev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&coredev->clientslock, flags);
+
+
+ while (!list_empty(&client->idlist)) {
+ struct smscore_idlist_t *identry =
+ (struct smscore_idlist_t *) client->idlist.next;
+ list_del(&identry->entry);
+ kfree(identry);
+ }
+
+ sms_info("%p", client->context);
+
+ list_del(&client->entry);
+ kfree(client);
+
+ spin_unlock_irqrestore(&coredev->clientslock, flags);
+}
+
+/**
+ * verifies that source id is not taken by another client,
+ * calls device handler to send requests to the device
+ *
+ * @param client pointer to smsclient object returned by
+ * smscore_register_client
+ * @param buffer pointer to a request buffer
+ * @param size size (in bytes) of request buffer
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smsclient_sendrequest(struct smscore_client_t *client,
+ void *buffer, size_t size)
+{
+ struct smscore_device_t *coredev;
+ struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
+ int rc;
+
+ if (client == NULL) {
+ sms_err("Got NULL client");
+ return -EINVAL;
+ }
+
+ coredev = client->coredev;
+
+ /* check that no other channel with same id exists */
+ if (coredev == NULL) {
+ sms_err("Got NULL coredev");
+ return -EINVAL;
+ }
+
+ rc = smscore_validate_client(client->coredev, client, 0,
+ phdr->msgSrcId);
+ if (rc < 0)
+ return rc;
+
+ return coredev->sendrequest_handler(coredev->context, buffer, size);
+}
+
+
+static int __init smscore_module_init(void)
+{
+ int rc = 0;
+
+ INIT_LIST_HEAD(&g_smscore_notifyees);
+ INIT_LIST_HEAD(&g_smscore_devices);
+ kmutex_init(&g_smscore_deviceslock);
+
+ INIT_LIST_HEAD(&g_smscore_registry);
+ kmutex_init(&g_smscore_registrylock);
+
+ /* USB Register */
+ rc = smsusb_register();
+
+ /* DVB Register */
+ rc = smsdvb_register();
+
+ sms_debug("rc %d", rc);
+
+ return rc;
+}
+
+static void __exit smscore_module_exit(void)
+{
+
+ kmutex_lock(&g_smscore_deviceslock);
+ while (!list_empty(&g_smscore_notifyees)) {
+ struct smscore_device_notifyee_t *notifyee =
+ (struct smscore_device_notifyee_t *)
+ g_smscore_notifyees.next;
+
+ list_del(&notifyee->entry);
+ kfree(notifyee);
+ }
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ kmutex_lock(&g_smscore_registrylock);
+ while (!list_empty(&g_smscore_registry)) {
+ struct smscore_registry_entry_t *entry =
+ (struct smscore_registry_entry_t *)
+ g_smscore_registry.next;
+
+ list_del(&entry->entry);
+ kfree(entry);
+ }
+ kmutex_unlock(&g_smscore_registrylock);
+
+ /* DVB UnRegister */
+ smsdvb_unregister();
+
+ /* Unregister USB */
+ smsusb_unregister();
+
+ sms_debug("");
+}
+
+module_init(smscore_module_init);
+module_exit(smscore_module_exit);
+
+MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
+MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
new file mode 100644
index 0000000..c1f8f1d
--- /dev/null
+++ b/drivers/media/dvb/siano/smscoreapi.h
@@ -0,0 +1,434 @@
+/*
+ * Driver for the Siano SMS1xxx USB dongle
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * 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 __smscoreapi_h__
+#define __smscoreapi_h__
+
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/types.h>
+#include <asm/page.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include <linux/mutex.h>
+
+#define kmutex_init(_p_) mutex_init(_p_)
+#define kmutex_lock(_p_) mutex_lock(_p_)
+#define kmutex_trylock(_p_) mutex_trylock(_p_)
+#define kmutex_unlock(_p_) mutex_unlock(_p_)
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define SMS_ALLOC_ALIGNMENT 128
+#define SMS_DMA_ALIGNMENT 16
+#define SMS_ALIGN_ADDRESS(addr) \
+ ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
+
+#define SMS_DEVICE_FAMILY2 1
+#define SMS_ROM_NO_RESPONSE 2
+#define SMS_DEVICE_NOT_READY 0x8000000
+
+enum sms_device_type_st {
+ SMS_STELLAR = 0,
+ SMS_NOVA_A0,
+ SMS_NOVA_B0,
+ SMS_VEGA,
+ SMS_NUM_OF_DEVICE_TYPES
+};
+
+struct smscore_device_t;
+struct smscore_client_t;
+struct smscore_buffer_t;
+
+typedef int (*hotplug_t)(struct smscore_device_t *coredev,
+ struct device *device, int arrival);
+
+typedef int (*setmode_t)(void *context, int mode);
+typedef void (*detectmode_t)(void *context, int *mode);
+typedef int (*sendrequest_t)(void *context, void *buffer, size_t size);
+typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size);
+typedef int (*preload_t)(void *context);
+typedef int (*postload_t)(void *context);
+
+typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb);
+typedef void (*onremove_t)(void *context);
+
+struct smscore_buffer_t {
+ /* public members, once passed to clients can be changed freely */
+ struct list_head entry;
+ int size;
+ int offset;
+
+ /* private members, read-only for clients */
+ void *p;
+ dma_addr_t phys;
+ unsigned long offset_in_common;
+};
+
+struct smsdevice_params_t {
+ struct device *device;
+
+ int buffer_size;
+ int num_buffers;
+
+ char devpath[32];
+ unsigned long flags;
+
+ setmode_t setmode_handler;
+ detectmode_t detectmode_handler;
+ sendrequest_t sendrequest_handler;
+ preload_t preload_handler;
+ postload_t postload_handler;
+
+ void *context;
+ enum sms_device_type_st device_type;
+};
+
+struct smsclient_params_t {
+ int initial_id;
+ int data_type;
+ onresponse_t onresponse_handler;
+ onremove_t onremove_handler;
+
+ void *context;
+};
+
+/* GPIO definitions for antenna frequency domain control (SMS8021) */
+#define SMS_ANTENNA_GPIO_0 1
+#define SMS_ANTENNA_GPIO_1 0
+
+#define BW_8_MHZ 0
+#define BW_7_MHZ 1
+#define BW_6_MHZ 2
+#define BW_5_MHZ 3
+#define BW_ISDBT_1SEG 4
+#define BW_ISDBT_3SEG 5
+
+#define MSG_HDR_FLAG_SPLIT_MSG 4
+
+#define MAX_GPIO_PIN_NUMBER 31
+
+#define HIF_TASK 11
+#define SMS_HOST_LIB 150
+#define DVBT_BDA_CONTROL_MSG_ID 201
+
+#define SMS_MAX_PAYLOAD_SIZE 240
+#define SMS_TUNE_TIMEOUT 500
+
+#define MSG_SMS_GPIO_CONFIG_REQ 507
+#define MSG_SMS_GPIO_CONFIG_RES 508
+#define MSG_SMS_GPIO_SET_LEVEL_REQ 509
+#define MSG_SMS_GPIO_SET_LEVEL_RES 510
+#define MSG_SMS_GPIO_GET_LEVEL_REQ 511
+#define MSG_SMS_GPIO_GET_LEVEL_RES 512
+#define MSG_SMS_RF_TUNE_REQ 561
+#define MSG_SMS_RF_TUNE_RES 562
+#define MSG_SMS_INIT_DEVICE_REQ 578
+#define MSG_SMS_INIT_DEVICE_RES 579
+#define MSG_SMS_ADD_PID_FILTER_REQ 601
+#define MSG_SMS_ADD_PID_FILTER_RES 602
+#define MSG_SMS_REMOVE_PID_FILTER_REQ 603
+#define MSG_SMS_REMOVE_PID_FILTER_RES 604
+#define MSG_SMS_DAB_CHANNEL 607
+#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608
+#define MSG_SMS_GET_PID_FILTER_LIST_RES 609
+#define MSG_SMS_GET_STATISTICS_REQ 615
+#define MSG_SMS_GET_STATISTICS_RES 616
+#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651
+#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652
+#define MSG_SMS_GET_STATISTICS_EX_REQ 653
+#define MSG_SMS_GET_STATISTICS_EX_RES 654
+#define MSG_SMS_SLEEP_RESUME_COMP_IND 655
+#define MSG_SMS_DATA_DOWNLOAD_REQ 660
+#define MSG_SMS_DATA_DOWNLOAD_RES 661
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES 665
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ 666
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES 667
+#define MSG_SMS_GET_VERSION_EX_REQ 668
+#define MSG_SMS_GET_VERSION_EX_RES 669
+#define MSG_SMS_SET_CLOCK_OUTPUT_REQ 670
+#define MSG_SMS_I2C_SET_FREQ_REQ 685
+#define MSG_SMS_GENERIC_I2C_REQ 687
+#define MSG_SMS_GENERIC_I2C_RES 688
+#define MSG_SMS_DVBT_BDA_DATA 693
+#define MSG_SW_RELOAD_REQ 697
+#define MSG_SMS_DATA_MSG 699
+#define MSG_SW_RELOAD_START_REQ 702
+#define MSG_SW_RELOAD_START_RES 703
+#define MSG_SW_RELOAD_EXEC_REQ 704
+#define MSG_SW_RELOAD_EXEC_RES 705
+#define MSG_SMS_SPI_INT_LINE_SET_REQ 710
+#define MSG_SMS_ISDBT_TUNE_REQ 776
+#define MSG_SMS_ISDBT_TUNE_RES 777
+
+#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
+ (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
+ (ptr)->msgLength = len; (ptr)->msgFlags = 0; \
+} while (0)
+#define SMS_INIT_MSG(ptr, type, len) \
+ SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
+
+enum SMS_DEVICE_MODE {
+ DEVICE_MODE_NONE = -1,
+ DEVICE_MODE_DVBT = 0,
+ DEVICE_MODE_DVBH,
+ DEVICE_MODE_DAB_TDMB,
+ DEVICE_MODE_DAB_TDMB_DABIP,
+ DEVICE_MODE_DVBT_BDA,
+ DEVICE_MODE_ISDBT,
+ DEVICE_MODE_ISDBT_BDA,
+ DEVICE_MODE_CMMB,
+ DEVICE_MODE_RAW_TUNER,
+ DEVICE_MODE_MAX,
+};
+
+struct SmsMsgHdr_ST {
+ u16 msgType;
+ u8 msgSrcId;
+ u8 msgDstId;
+ u16 msgLength; /* Length of entire message, including header */
+ u16 msgFlags;
+};
+
+struct SmsMsgData_ST {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[1];
+};
+
+struct SmsDataDownload_ST {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 MemAddr;
+ u8 Payload[SMS_MAX_PAYLOAD_SIZE];
+};
+
+struct SmsVersionRes_ST {
+ struct SmsMsgHdr_ST xMsgHeader;
+
+ u16 ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
+ u8 Step; /* 0 - Step A */
+ u8 MetalFix; /* 0 - Metal 0 */
+
+ u8 FirmwareId; /* 0xFF � ROM, otherwise the
+ * value indicated by
+ * SMSHOSTLIB_DEVICE_MODES_E */
+ u8 SupportedProtocols; /* Bitwise OR combination of
+ * supported protocols */
+
+ u8 VersionMajor;
+ u8 VersionMinor;
+ u8 VersionPatch;
+ u8 VersionFieldPatch;
+
+ u8 RomVersionMajor;
+ u8 RomVersionMinor;
+ u8 RomVersionPatch;
+ u8 RomVersionFieldPatch;
+
+ u8 TextLabel[34];
+};
+
+struct SmsFirmware_ST {
+ u32 CheckSum;
+ u32 Length;
+ u32 StartAddress;
+ u8 Payload[1];
+};
+
+struct SMSHOSTLIB_STATISTICS_ST {
+ u32 Reserved; /* Reserved */
+
+ /* Common parameters */
+ u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+ u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+ u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+
+ /* Reception quality */
+ s32 SNR; /* dB */
+ u32 BER; /* Post Viterbi BER [1E-5] */
+ u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */
+ u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A,
+ * valid only for DVB-T/H */
+ u32 MFER; /* DVB-H frame error rate in percentage,
+ * 0xFFFFFFFF indicate N/A, valid only for DVB-H */
+ s32 RSSI; /* dBm */
+ s32 InBandPwr; /* In band power in dBM */
+ s32 CarrierOffset; /* Carrier Offset in bin/1024 */
+
+ /* Transmission parameters, valid only for DVB-T/H */
+ u32 Frequency; /* Frequency in Hz */
+ u32 Bandwidth; /* Bandwidth in MHz */
+ u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4,
+ * for DVB-T/H FFT mode carriers in Kilos */
+ u32 ModemState; /* from SMS_DvbModemState_ET */
+ u32 GuardInterval; /* Guard Interval, 1 divided by value */
+ u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */
+ u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */
+ u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */
+ u32 Constellation; /* Constellation from SMS_Constellation_ET */
+
+ /* Burst parameters, valid only for DVB-H */
+ u32 BurstSize; /* Current burst size in bytes */
+ u32 BurstDuration; /* Current burst duration in mSec */
+ u32 BurstCycleTime; /* Current burst cycle time in mSec */
+ u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec,
+ * as calculated by demodulator */
+ u32 NumOfRows; /* Number of rows in MPE table */
+ u32 NumOfPaddCols; /* Number of padding columns in MPE table */
+ u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */
+ /* Burst parameters */
+ u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
+ u32 TotalTSPackets; /* Total number of transport-stream packets */
+ u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include
+ * errors after MPE RS decoding */
+ u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors
+ * after MPE RS decoding */
+ u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected
+ * by MPE RS decoding */
+
+ /* Common params */
+ u32 BERErrorCount; /* Number of errornous SYNC bits. */
+ u32 BERBitCount; /* Total number of SYNC bits. */
+
+ /* Interface information */
+ u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+
+ /* DAB/T-DMB */
+ u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
+
+ /* DVB-H TPS parameters */
+ u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero;
+ * if set to 0xFFFFFFFF cell_id not yet recovered */
+
+};
+
+struct SmsMsgStatisticsInfo_ST {
+ u32 RequestResult;
+
+ struct SMSHOSTLIB_STATISTICS_ST Stat;
+
+ /* Split the calc of the SNR in DAB */
+ u32 Signal; /* dB */
+ u32 Noise; /* dB */
+
+};
+
+
+struct smsdvb_client_t {
+ struct list_head entry;
+
+ struct smscore_device_t *coredev;
+ struct smscore_client_t *smsclient;
+
+ struct dvb_adapter adapter;
+ struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dvb_frontend frontend;
+
+ fe_status_t fe_status;
+ int fe_ber, fe_snr, fe_signal_strength;
+
+ struct completion tune_done, stat_done;
+
+ /* todo: save freq/band instead whole struct */
+ struct dvb_frontend_parameters fe_params;
+
+};
+
+extern void smscore_registry_setmode(char *devpath, int mode);
+extern int smscore_registry_getmode(char *devpath);
+
+extern int smscore_register_hotplug(hotplug_t hotplug);
+extern void smscore_unregister_hotplug(hotplug_t hotplug);
+
+extern int smscore_register_device(struct smsdevice_params_t *params,
+ struct smscore_device_t **coredev);
+extern void smscore_unregister_device(struct smscore_device_t *coredev);
+
+extern int smscore_start_device(struct smscore_device_t *coredev);
+extern int smscore_load_firmware(struct smscore_device_t *coredev,
+ char *filename,
+ loadfirmware_t loadfirmware_handler);
+
+extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode);
+extern int smscore_get_device_mode(struct smscore_device_t *coredev);
+
+extern int smscore_register_client(struct smscore_device_t *coredev,
+ struct smsclient_params_t *params,
+ struct smscore_client_t **client);
+extern void smscore_unregister_client(struct smscore_client_t *client);
+
+extern int smsclient_sendrequest(struct smscore_client_t *client,
+ void *buffer, size_t size);
+extern void smscore_onresponse(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb);
+
+
+extern
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
+extern void smscore_putbuffer(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb);
+
+void smscore_set_board_id(struct smscore_device_t *core, int id);
+int smscore_get_board_id(struct smscore_device_t *core);
+
+/* smsdvb.c */
+int smsdvb_register(void);
+void smsdvb_unregister(void);
+
+/* smsusb.c */
+int smsusb_register(void);
+void smsusb_unregister(void);
+
+/* ------------------------------------------------------------------------ */
+
+extern int sms_debug;
+
+#define DBG_INFO 1
+#define DBG_ADV 2
+
+#define sms_printk(kern, fmt, arg...) \
+ printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define dprintk(kern, lvl, fmt, arg...) do {\
+ if (sms_debug & lvl) \
+ sms_printk(kern, fmt, ##arg); } while (0)
+
+#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
+#define sms_err(fmt, arg...) \
+ sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
+#define sms_warn(fmt, arg...) sms_printk(KERN_WARNING, fmt, ##arg)
+#define sms_info(fmt, arg...) \
+ dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
+#define sms_debug(fmt, arg...) \
+ dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
+
+
+#endif /* __smscoreapi_h__ */
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
new file mode 100644
index 0000000..229274a
--- /dev/null
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -0,0 +1,449 @@
+/*
+ * Driver for the Siano SMS1xxx USB dongle
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static struct list_head g_smsdvb_clients;
+static struct mutex g_smsdvb_clientslock;
+
+static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
+{
+ struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
+ struct SmsMsgHdr_ST *phdr =
+ (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset);
+
+ switch (phdr->msgType) {
+ case MSG_SMS_DVBT_BDA_DATA:
+ dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
+ cb->size - sizeof(struct SmsMsgHdr_ST));
+ break;
+
+ case MSG_SMS_RF_TUNE_RES:
+ complete(&client->tune_done);
+ break;
+
+ case MSG_SMS_GET_STATISTICS_RES:
+ {
+ struct SmsMsgStatisticsInfo_ST *p =
+ (struct SmsMsgStatisticsInfo_ST *)(phdr + 1);
+
+ if (p->Stat.IsDemodLocked) {
+ client->fe_status = FE_HAS_SIGNAL |
+ FE_HAS_CARRIER |
+ FE_HAS_VITERBI |
+ FE_HAS_SYNC |
+ FE_HAS_LOCK;
+
+ client->fe_snr = p->Stat.SNR;
+ client->fe_ber = p->Stat.BER;
+
+ if (p->Stat.InBandPwr < -95)
+ client->fe_signal_strength = 0;
+ else if (p->Stat.InBandPwr > -29)
+ client->fe_signal_strength = 100;
+ else
+ client->fe_signal_strength =
+ (p->Stat.InBandPwr + 95) * 3 / 2;
+ } else {
+ client->fe_status = 0;
+ client->fe_snr =
+ client->fe_ber =
+ client->fe_signal_strength = 0;
+ }
+
+ complete(&client->stat_done);
+ break;
+ } }
+
+ smscore_putbuffer(client->coredev, cb);
+
+ return 0;
+}
+
+static void smsdvb_unregister_client(struct smsdvb_client_t *client)
+{
+ /* must be called under clientslock */
+
+ list_del(&client->entry);
+
+ smscore_unregister_client(client->smsclient);
+ dvb_unregister_frontend(&client->frontend);
+ dvb_dmxdev_release(&client->dmxdev);
+ dvb_dmx_release(&client->demux);
+ dvb_unregister_adapter(&client->adapter);
+ kfree(client);
+}
+
+static void smsdvb_onremove(void *context)
+{
+ kmutex_lock(&g_smsdvb_clientslock);
+
+ smsdvb_unregister_client((struct smsdvb_client_t *) context);
+
+ kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+static int smsdvb_start_feed(struct dvb_demux_feed *feed)
+{
+ struct smsdvb_client_t *client =
+ container_of(feed->demux, struct smsdvb_client_t, demux);
+ struct SmsMsgData_ST PidMsg;
+
+ sms_debug("add pid %d(%x)",
+ feed->pid, feed->pid);
+
+ PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+ PidMsg.xMsgHeader.msgFlags = 0;
+ PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
+ PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+ PidMsg.msgData[0] = feed->pid;
+
+ return smsclient_sendrequest(client->smsclient,
+ &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct smsdvb_client_t *client =
+ container_of(feed->demux, struct smsdvb_client_t, demux);
+ struct SmsMsgData_ST PidMsg;
+
+ sms_debug("remove pid %d(%x)",
+ feed->pid, feed->pid);
+
+ PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+ PidMsg.xMsgHeader.msgFlags = 0;
+ PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
+ PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+ PidMsg.msgData[0] = feed->pid;
+
+ return smsclient_sendrequest(client->smsclient,
+ &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
+ void *buffer, size_t size,
+ struct completion *completion)
+{
+ int rc = smsclient_sendrequest(client->smsclient, buffer, size);
+ if (rc < 0)
+ return rc;
+
+ return wait_for_completion_timeout(completion,
+ msecs_to_jiffies(2000)) ?
+ 0 : -ETIME;
+}
+
+static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+{
+ struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
+ DVBT_BDA_CONTROL_MSG_ID,
+ HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 };
+ return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+ &client->stat_done);
+}
+
+static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *stat = client->fe_status;
+
+ return rc;
+}
+
+static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *ber = client->fe_ber;
+
+ return rc;
+}
+
+static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *strength = client->fe_signal_strength;
+
+ return rc;
+}
+
+static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *snr = client->fe_snr;
+
+ return rc;
+}
+
+static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ sms_debug("");
+
+ tune->min_delay_ms = 400;
+ tune->step_size = 250000;
+ tune->max_drift = 0;
+ return 0;
+}
+
+static int smsdvb_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+
+ struct {
+ struct SmsMsgHdr_ST Msg;
+ u32 Data[3];
+ } Msg;
+
+ Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ Msg.Msg.msgDstId = HIF_TASK;
+ Msg.Msg.msgFlags = 0;
+ Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
+ Msg.Msg.msgLength = sizeof(Msg);
+ Msg.Data[0] = fep->frequency;
+ Msg.Data[2] = 12000000;
+
+ sms_debug("freq %d band %d",
+ fep->frequency, fep->u.ofdm.bandwidth);
+
+ switch (fep->u.ofdm.bandwidth) {
+ case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break;
+ case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break;
+ case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break;
+ case BANDWIDTH_AUTO: return -EOPNOTSUPP;
+ default: return -EINVAL;
+ }
+
+ return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+ &client->tune_done);
+}
+
+static int smsdvb_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+
+ sms_debug("");
+
+ /* todo: */
+ memcpy(fep, &client->fe_params,
+ sizeof(struct dvb_frontend_parameters));
+ return 0;
+}
+
+static void smsdvb_release(struct dvb_frontend *fe)
+{
+ /* do nothing */
+}
+
+static struct dvb_frontend_ops smsdvb_fe_ops = {
+ .info = {
+ .name = "Siano Mobile Digital SMS1xxx",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
+ .frequency_stepsize = 250000,
+ .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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+ FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_RECOVER |
+ FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .release = smsdvb_release,
+
+ .set_frontend = smsdvb_set_frontend,
+ .get_frontend = smsdvb_get_frontend,
+ .get_tune_settings = smsdvb_get_tune_settings,
+
+ .read_status = smsdvb_read_status,
+ .read_ber = smsdvb_read_ber,
+ .read_signal_strength = smsdvb_read_signal_strength,
+ .read_snr = smsdvb_read_snr,
+};
+
+static int smsdvb_hotplug(struct smscore_device_t *coredev,
+ struct device *device, int arrival)
+{
+ struct smsclient_params_t params;
+ struct smsdvb_client_t *client;
+ int rc;
+
+ /* device removal handled by onremove callback */
+ if (!arrival)
+ return 0;
+
+ if (smscore_get_device_mode(coredev) != 4) {
+ sms_err("SMS Device mode is not set for "
+ "DVB operation.");
+ return 0;
+ }
+
+ client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
+ if (!client) {
+ sms_err("kmalloc() failed");
+ return -ENOMEM;
+ }
+
+ /* register dvb adapter */
+ rc = dvb_register_adapter(&client->adapter,
+ sms_get_board(
+ smscore_get_board_id(coredev))->name,
+ THIS_MODULE, device, adapter_nr);
+ if (rc < 0) {
+ sms_err("dvb_register_adapter() failed %d", rc);
+ goto adapter_error;
+ }
+
+ /* init dvb demux */
+ client->demux.dmx.capabilities = DMX_TS_FILTERING;
+ client->demux.filternum = 32; /* todo: nova ??? */
+ client->demux.feednum = 32;
+ client->demux.start_feed = smsdvb_start_feed;
+ client->demux.stop_feed = smsdvb_stop_feed;
+
+ rc = dvb_dmx_init(&client->demux);
+ if (rc < 0) {
+ sms_err("dvb_dmx_init failed %d", rc);
+ goto dvbdmx_error;
+ }
+
+ /* init dmxdev */
+ client->dmxdev.filternum = 32;
+ client->dmxdev.demux = &client->demux.dmx;
+ client->dmxdev.capabilities = 0;
+
+ rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
+ if (rc < 0) {
+ sms_err("dvb_dmxdev_init failed %d", rc);
+ goto dmxdev_error;
+ }
+
+ /* init and register frontend */
+ memcpy(&client->frontend.ops, &smsdvb_fe_ops,
+ sizeof(struct dvb_frontend_ops));
+
+ rc = dvb_register_frontend(&client->adapter, &client->frontend);
+ if (rc < 0) {
+ sms_err("frontend registration failed %d", rc);
+ goto frontend_error;
+ }
+
+ params.initial_id = 1;
+ params.data_type = MSG_SMS_DVBT_BDA_DATA;
+ params.onresponse_handler = smsdvb_onresponse;
+ params.onremove_handler = smsdvb_onremove;
+ params.context = client;
+
+ rc = smscore_register_client(coredev, &params, &client->smsclient);
+ if (rc < 0) {
+ sms_err("smscore_register_client() failed %d", rc);
+ goto client_error;
+ }
+
+ client->coredev = coredev;
+
+ init_completion(&client->tune_done);
+ init_completion(&client->stat_done);
+
+ kmutex_lock(&g_smsdvb_clientslock);
+
+ list_add(&client->entry, &g_smsdvb_clients);
+
+ kmutex_unlock(&g_smsdvb_clientslock);
+
+ sms_info("success");
+
+ return 0;
+
+client_error:
+ dvb_unregister_frontend(&client->frontend);
+
+frontend_error:
+ dvb_dmxdev_release(&client->dmxdev);
+
+dmxdev_error:
+ dvb_dmx_release(&client->demux);
+
+dvbdmx_error:
+ dvb_unregister_adapter(&client->adapter);
+
+adapter_error:
+ kfree(client);
+ return rc;
+}
+
+int smsdvb_register(void)
+{
+ int rc;
+
+ INIT_LIST_HEAD(&g_smsdvb_clients);
+ kmutex_init(&g_smsdvb_clientslock);
+
+ rc = smscore_register_hotplug(smsdvb_hotplug);
+
+ sms_debug("");
+
+ return rc;
+}
+
+void smsdvb_unregister(void)
+{
+ smscore_unregister_hotplug(smsdvb_hotplug);
+
+ kmutex_lock(&g_smsdvb_clientslock);
+
+ while (!list_empty(&g_smsdvb_clients))
+ smsdvb_unregister_client(
+ (struct smsdvb_client_t *) g_smsdvb_clients.next);
+
+ kmutex_unlock(&g_smsdvb_clientslock);
+}
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
new file mode 100644
index 0000000..c10b184
--- /dev/null
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -0,0 +1,459 @@
+/*
+ * Driver for the Siano SMS1xxx USB dongle
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+#define USB1_BUFFER_SIZE 0x1000
+#define USB2_BUFFER_SIZE 0x4000
+
+#define MAX_BUFFERS 50
+#define MAX_URBS 10
+
+struct smsusb_device_t;
+
+struct smsusb_urb_t {
+ struct smscore_buffer_t *cb;
+ struct smsusb_device_t *dev;
+
+ struct urb urb;
+};
+
+struct smsusb_device_t {
+ struct usb_device *udev;
+ struct smscore_device_t *coredev;
+
+ struct smsusb_urb_t surbs[MAX_URBS];
+
+ int response_alignment;
+ int buffer_size;
+};
+
+static int smsusb_submit_urb(struct smsusb_device_t *dev,
+ struct smsusb_urb_t *surb);
+
+static void smsusb_onresponse(struct urb *urb)
+{
+ struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
+ struct smsusb_device_t *dev = surb->dev;
+
+ if (urb->status < 0) {
+ sms_err("error, urb status %d, %d bytes",
+ urb->status, urb->actual_length);
+ return;
+ }
+
+ if (urb->actual_length > 0) {
+ struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p;
+
+ if (urb->actual_length >= phdr->msgLength) {
+ surb->cb->size = phdr->msgLength;
+
+ if (dev->response_alignment &&
+ (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) {
+
+ surb->cb->offset =
+ dev->response_alignment +
+ ((phdr->msgFlags >> 8) & 3);
+
+ /* sanity check */
+ if (((int) phdr->msgLength +
+ surb->cb->offset) > urb->actual_length) {
+ sms_err("invalid response "
+ "msglen %d offset %d "
+ "size %d",
+ phdr->msgLength,
+ surb->cb->offset,
+ urb->actual_length);
+ goto exit_and_resubmit;
+ }
+
+ /* move buffer pointer and
+ * copy header to its new location */
+ memcpy((char *) phdr + surb->cb->offset,
+ phdr, sizeof(struct SmsMsgHdr_ST));
+ } else
+ surb->cb->offset = 0;
+
+ smscore_onresponse(dev->coredev, surb->cb);
+ surb->cb = NULL;
+ } else {
+ sms_err("invalid response "
+ "msglen %d actual %d",
+ phdr->msgLength, urb->actual_length);
+ }
+ }
+
+exit_and_resubmit:
+ smsusb_submit_urb(dev, surb);
+}
+
+static int smsusb_submit_urb(struct smsusb_device_t *dev,
+ struct smsusb_urb_t *surb)
+{
+ if (!surb->cb) {
+ surb->cb = smscore_getbuffer(dev->coredev);
+ if (!surb->cb) {
+ sms_err("smscore_getbuffer(...) returned NULL");
+ return -ENOMEM;
+ }
+ }
+
+ usb_fill_bulk_urb(
+ &surb->urb,
+ dev->udev,
+ usb_rcvbulkpipe(dev->udev, 0x81),
+ surb->cb->p,
+ dev->buffer_size,
+ smsusb_onresponse,
+ surb
+ );
+ surb->urb.transfer_dma = surb->cb->phys;
+ surb->urb.transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ return usb_submit_urb(&surb->urb, GFP_ATOMIC);
+}
+
+static void smsusb_stop_streaming(struct smsusb_device_t *dev)
+{
+ int i;
+
+ for (i = 0; i < MAX_URBS; i++) {
+ usb_kill_urb(&dev->surbs[i].urb);
+
+ if (dev->surbs[i].cb) {
+ smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
+ dev->surbs[i].cb = NULL;
+ }
+ }
+}
+
+static int smsusb_start_streaming(struct smsusb_device_t *dev)
+{
+ int i, rc;
+
+ for (i = 0; i < MAX_URBS; i++) {
+ rc = smsusb_submit_urb(dev, &dev->surbs[i]);
+ if (rc < 0) {
+ sms_err("smsusb_submit_urb(...) failed");
+ smsusb_stop_streaming(dev);
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static int smsusb_sendrequest(void *context, void *buffer, size_t size)
+{
+ struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
+ int dummy;
+
+ return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+ buffer, size, &dummy, 1000);
+}
+
+static char *smsusb1_fw_lkup[] = {
+ "dvbt_stellar_usb.inp",
+ "dvbh_stellar_usb.inp",
+ "tdmb_stellar_usb.inp",
+ "none",
+ "dvbt_bda_stellar_usb.inp",
+};
+
+static inline char *sms_get_fw_name(int mode, int board_id)
+{
+ char **fw = sms_get_board(board_id)->fw;
+ return (fw && fw[mode]) ? fw[mode] : smsusb1_fw_lkup[mode];
+}
+
+static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
+{
+ const struct firmware *fw;
+ u8 *fw_buffer;
+ int rc, dummy;
+ char *fw_filename;
+
+ if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) {
+ sms_err("invalid firmware id specified %d", id);
+ return -EINVAL;
+ }
+
+ fw_filename = sms_get_fw_name(id, board_id);
+
+ rc = request_firmware(&fw, fw_filename, &udev->dev);
+ if (rc < 0) {
+ sms_warn("failed to open \"%s\" mode %d, "
+ "trying again with default firmware", fw_filename, id);
+
+ fw_filename = smsusb1_fw_lkup[id];
+ rc = request_firmware(&fw, fw_filename, &udev->dev);
+ if (rc < 0) {
+ sms_warn("failed to open \"%s\" mode %d",
+ fw_filename, id);
+
+ return rc;
+ }
+ }
+
+ fw_buffer = kmalloc(fw->size, GFP_KERNEL);
+ if (fw_buffer) {
+ memcpy(fw_buffer, fw->data, fw->size);
+
+ rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2),
+ fw_buffer, fw->size, &dummy, 1000);
+
+ sms_info("sent %zd(%d) bytes, rc %d", fw->size, dummy, rc);
+
+ kfree(fw_buffer);
+ } else {
+ sms_err("failed to allocate firmware buffer");
+ rc = -ENOMEM;
+ }
+ sms_info("read FW %s, size=%zd", fw_filename, fw->size);
+
+ release_firmware(fw);
+
+ return rc;
+}
+
+static void smsusb1_detectmode(void *context, int *mode)
+{
+ char *product_string =
+ ((struct smsusb_device_t *) context)->udev->product;
+
+ *mode = DEVICE_MODE_NONE;
+
+ if (!product_string) {
+ product_string = "none";
+ sms_err("product string not found");
+ } else if (strstr(product_string, "DVBH"))
+ *mode = 1;
+ else if (strstr(product_string, "BDA"))
+ *mode = 4;
+ else if (strstr(product_string, "DVBT"))
+ *mode = 0;
+ else if (strstr(product_string, "TDMB"))
+ *mode = 2;
+
+ sms_info("%d \"%s\"", *mode, product_string);
+}
+
+static int smsusb1_setmode(void *context, int mode)
+{
+ struct SmsMsgHdr_ST Msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
+ sizeof(struct SmsMsgHdr_ST), 0 };
+
+ if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+ sms_err("invalid firmware id specified %d", mode);
+ return -EINVAL;
+ }
+
+ return smsusb_sendrequest(context, &Msg, sizeof(Msg));
+}
+
+static void smsusb_term_device(struct usb_interface *intf)
+{
+ struct smsusb_device_t *dev =
+ (struct smsusb_device_t *) usb_get_intfdata(intf);
+
+ if (dev) {
+ smsusb_stop_streaming(dev);
+
+ /* unregister from smscore */
+ if (dev->coredev)
+ smscore_unregister_device(dev->coredev);
+
+ kfree(dev);
+
+ sms_info("device %p destroyed", dev);
+ }
+
+ usb_set_intfdata(intf, NULL);
+}
+
+static int smsusb_init_device(struct usb_interface *intf, int board_id)
+{
+ struct smsdevice_params_t params;
+ struct smsusb_device_t *dev;
+ int i, rc;
+
+ /* create device object */
+ dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
+ if (!dev) {
+ sms_err("kzalloc(sizeof(struct smsusb_device_t) failed");
+ return -ENOMEM;
+ }
+
+ memset(&params, 0, sizeof(params));
+ usb_set_intfdata(intf, dev);
+ dev->udev = interface_to_usbdev(intf);
+
+ params.device_type = sms_get_board(board_id)->type;
+
+ switch (params.device_type) {
+ case SMS_STELLAR:
+ dev->buffer_size = USB1_BUFFER_SIZE;
+
+ params.setmode_handler = smsusb1_setmode;
+ params.detectmode_handler = smsusb1_detectmode;
+ break;
+ default:
+ sms_err("Unspecified sms device type!");
+ /* fall-thru */
+ case SMS_NOVA_A0:
+ case SMS_NOVA_B0:
+ case SMS_VEGA:
+ dev->buffer_size = USB2_BUFFER_SIZE;
+ dev->response_alignment =
+ dev->udev->ep_in[1]->desc.wMaxPacketSize -
+ sizeof(struct SmsMsgHdr_ST);
+
+ params.flags |= SMS_DEVICE_FAMILY2;
+ break;
+ }
+
+ params.device = &dev->udev->dev;
+ params.buffer_size = dev->buffer_size;
+ params.num_buffers = MAX_BUFFERS;
+ params.sendrequest_handler = smsusb_sendrequest;
+ params.context = dev;
+ snprintf(params.devpath, sizeof(params.devpath),
+ "usb\\%d-%s", dev->udev->bus->busnum, dev->udev->devpath);
+
+ /* register in smscore */
+ rc = smscore_register_device(&params, &dev->coredev);
+ if (rc < 0) {
+ sms_err("smscore_register_device(...) failed, rc %d", rc);
+ smsusb_term_device(intf);
+ return rc;
+ }
+
+ smscore_set_board_id(dev->coredev, board_id);
+
+ /* initialize urbs */
+ for (i = 0; i < MAX_URBS; i++) {
+ dev->surbs[i].dev = dev;
+ usb_init_urb(&dev->surbs[i].urb);
+ }
+
+ sms_info("smsusb_start_streaming(...).");
+ rc = smsusb_start_streaming(dev);
+ if (rc < 0) {
+ sms_err("smsusb_start_streaming(...) failed");
+ smsusb_term_device(intf);
+ return rc;
+ }
+
+ rc = smscore_start_device(dev->coredev);
+ if (rc < 0) {
+ sms_err("smscore_start_device(...) failed");
+ smsusb_term_device(intf);
+ return rc;
+ }
+
+ sms_info("device %p created", dev);
+
+ return rc;
+}
+
+static int smsusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ char devpath[32];
+ int i, rc;
+
+ rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
+ rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
+
+ if (intf->num_altsetting > 0) {
+ rc = usb_set_interface(
+ udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
+ if (rc < 0) {
+ sms_err("usb_set_interface failed, rc %d", rc);
+ return rc;
+ }
+ }
+
+ sms_info("smsusb_probe %d",
+ intf->cur_altsetting->desc.bInterfaceNumber);
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
+ sms_info("endpoint %d %02x %02x %d", i,
+ intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
+ intf->cur_altsetting->endpoint[i].desc.bmAttributes,
+ intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
+
+ if ((udev->actconfig->desc.bNumInterfaces == 2) &&
+ (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
+ sms_err("rom interface 0 is not used");
+ return -ENODEV;
+ }
+
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
+ snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
+ udev->bus->busnum, udev->devpath);
+ sms_info("stellar device was found.");
+ return smsusb1_load_firmware(
+ udev, smscore_registry_getmode(devpath),
+ id->driver_info);
+ }
+
+ rc = smsusb_init_device(intf, id->driver_info);
+ sms_info("rc %d", rc);
+ return rc;
+}
+
+static void smsusb_disconnect(struct usb_interface *intf)
+{
+ smsusb_term_device(intf);
+}
+
+static struct usb_driver smsusb_driver = {
+ .name = "sms1xxx",
+ .probe = smsusb_probe,
+ .disconnect = smsusb_disconnect,
+ .id_table = smsusb_id_table,
+};
+
+int smsusb_register(void)
+{
+ int rc = usb_register(&smsusb_driver);
+ if (rc)
+ sms_err("usb_register failed. Error number %d", rc);
+
+ sms_debug("");
+
+ return rc;
+}
+
+void smsusb_unregister(void)
+{
+ sms_debug("");
+ /* Regular USB Cleanup */
+ usb_deregister(&smsusb_driver);
+}
+
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index ae882432..41b5a98 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -5,7 +5,6 @@ config TTPCI_EEPROM
config DVB_AV7110
tristate "AV7110 cards"
depends on DVB_CORE && PCI && I2C
- select FW_LOADER if !DVB_AV7110_FIRMWARE
select TTPCI_EEPROM
select VIDEO_SAA7146_VV
depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
@@ -100,10 +99,13 @@ config DVB_BUDGET
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector"
depends on DVB_BUDGET_CORE && I2C
+ depends on INPUT # due to IR
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+ select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+ select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
select VIDEO_IR
help
Support for simple SAA7146 based DVB cards
@@ -129,7 +131,6 @@ config DVB_BUDGET_AV
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
select DVB_TUA6100 if !DVB_FE_CUSTOMISE
- select FW_LOADER
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index d7483f1..7145123 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -3,7 +3,11 @@
# and the AV7110 DVB device driver
#
-dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o av7110_ir.o
+dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o
+
+ifdef CONFIG_INPUT_EVDEV
+dvb-ttpci-objs += av7110_ir.o
+endif
obj-$(CONFIG_TTPCI_EEPROM) += ttpci-eeprom.o
obj-$(CONFIG_DVB_BUDGET_CORE) += budget-core.o
@@ -14,6 +18,7 @@ obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
hostprogs-y := fdump
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 747e7f1..0777e8f 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -51,6 +51,7 @@
#include <linux/crc32.h>
#include <linux/i2c.h>
#include <linux/kthread.h>
+#include <asm/unaligned.h>
#include <asm/system.h>
@@ -586,7 +587,7 @@ static void gpioirq(unsigned long data)
}
DVB_RINGBUFFER_SKIP(cibuf, 2);
- dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
+ dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
@@ -1197,7 +1198,6 @@ static int start_ts_capture(struct av7110 *budget)
if (budget->feeding1)
return ++budget->feeding1;
memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
- budget->tsf = 0xff;
budget->ttbp = 0;
SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
@@ -1461,9 +1461,9 @@ static int check_firmware(struct av7110* av7110)
ptr += 4;
/* check dpram file */
- crc = ntohl(*(u32*) ptr);
+ crc = get_unaligned_be32(ptr);
ptr += 4;
- len = ntohl(*(u32*) ptr);
+ len = get_unaligned_be32(ptr);
ptr += 4;
if (len >= 512) {
printk("dvb-ttpci: dpram file is way too big.\n");
@@ -1478,9 +1478,9 @@ static int check_firmware(struct av7110* av7110)
ptr += len;
/* check root file */
- crc = ntohl(*(u32*) ptr);
+ crc = get_unaligned_be32(ptr);
ptr += 4;
- len = ntohl(*(u32*) ptr);
+ len = get_unaligned_be32(ptr);
ptr += 4;
if (len <= 200000 || len >= 300000 ||
@@ -2402,18 +2402,18 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
saa7146_write(dev, MC1, MASK_29);
/* RPS1 timeout disable */
saa7146_write(dev, RPS_TOV1, 0);
- WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
- WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
- WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
- WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
+ WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
#if RPS_IRQ
/* issue RPS1 interrupt to increment counter */
- WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+ WRITE_RPS1(CMD_INTERRUPT);
#endif
- WRITE_RPS1(cpu_to_le32(CMD_STOP));
+ WRITE_RPS1(CMD_STOP);
/* Jump to begin of RPS program as safety measure (p37) */
- WRITE_RPS1(cpu_to_le32(CMD_JUMP));
- WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
+ WRITE_RPS1(CMD_JUMP);
+ WRITE_RPS1(dev->d_rps1.dma_handle);
#if RPS_IRQ
/* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
@@ -2471,11 +2471,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
get recognized before the main driver is fully loaded */
saa7146_write(dev, GPIO_CTRL, 0x500000);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
- av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
-#else
av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
-#endif
strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
@@ -2526,28 +2522,28 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
count = 0;
/* Wait Source Line Counter Threshold (p36) */
- WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
+ WRITE_RPS1(CMD_PAUSE | EVT_HS);
/* Set GPIO3=1 (p42) */
- WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
- WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
- WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
#if RPS_IRQ
/* issue RPS1 interrupt */
- WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+ WRITE_RPS1(CMD_INTERRUPT);
#endif
/* Wait reset Source Line Counter Threshold (p36) */
- WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
+ WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
/* Set GPIO3=0 (p42) */
- WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
- WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
- WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
#if RPS_IRQ
/* issue RPS1 interrupt */
- WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+ WRITE_RPS1(CMD_INTERRUPT);
#endif
/* Jump to begin of RPS program (p37) */
- WRITE_RPS1(cpu_to_le32(CMD_JUMP));
- WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
+ WRITE_RPS1(CMD_JUMP);
+ WRITE_RPS1(dev->d_rps1.dma_handle);
/* Fix VSYNC level */
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index e494e04..55f23dd 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -188,7 +188,6 @@ struct av7110 {
struct dvb_net dvb_net1;
spinlock_t feedlock1;
int feeding1;
- u8 tsf;
u32 ttbp;
unsigned char *grabbing;
struct saa7146_pgtable pt;
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 3e6b650..184647ad 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -269,7 +269,7 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
return -1;
}
- dvb_ringbuffer_read(buf, dest, (size_t) blen, 0);
+ dvb_ringbuffer_read(buf, dest, (size_t) blen);
dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
(unsigned long) buf->pread, (unsigned long) buf->pwrite);
@@ -965,8 +965,9 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x
static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
{
- int i, n;
+ unsigned i, n;
int progressive = 0;
+ int match = 0;
dprintk(2, "av7110:%p, \n", av7110);
@@ -975,12 +976,31 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len
return -EBUSY;
}
- for (i = 0; i < len - 5; i++) {
- /* get progressive flag from picture extension */
- if (buf[i] == 0x00 && buf[i+1] == 0x00 &&
- buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 &&
- (buf[i+4] & 0xf0) == 0x10)
- progressive = buf[i+5] & 0x08;
+ /* search in buf for instances of 00 00 01 b5 1? */
+ for (i = 0; i < len; i++) {
+ unsigned char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (match == 5) {
+ progressive = c & 0x08;
+ match = 0;
+ }
+ if (c == 0x00) {
+ match = (match == 1 || match == 2) ? 2 : 1;
+ continue;
+ }
+ switch (match++) {
+ case 2: if (c == 0x01)
+ continue;
+ break;
+ case 3: if (c == 0xb5)
+ continue;
+ break;
+ case 4: if ((c & 0xf0) == 0x10)
+ continue;
+ break;
+ }
+ match = 0;
}
/* setting n always > 1, fixes problems when playing stillframes
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index c58e3fc..261135d 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -208,7 +208,7 @@ static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
return -EINVAL;
DVB_RINGBUFFER_SKIP(cibuf, 2);
- return dvb_ringbuffer_read(cibuf, (u8 *)buf, len, 1);
+ return dvb_ringbuffer_read_user(cibuf, buf, len);
}
static int dvb_ca_open(struct inode *inode, struct file *file)
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 9d81074..3a3f527 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -427,6 +427,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (err) {
printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
__func__, type);
+ av7110->arm_errors++;
return -ETIMEDOUT;
}
msleep(1);
@@ -853,10 +854,8 @@ static osd_raw_window_t bpp2bit[8] = {
static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
{
- int ret = wait_event_interruptible_timeout(av7110->bmpq,
+ int ret = wait_event_timeout(av7110->bmpq,
av7110->bmp_state != BMP_LOADING, 10*HZ);
- if (ret == -ERESTARTSYS)
- return ret;
if (ret == 0) {
printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
ret, av7110->bmp_state);
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 74d940f..ca99e5c 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -305,7 +305,6 @@ enum av7110_command_type {
#define IRQ_STATE (DPRAM_BASE + 0x0F4)
#define IRQ_STATE_EXT (DPRAM_BASE + 0x0F6)
#define MSGSTATE (DPRAM_BASE + 0x0F8)
-#define FILT_STATE (DPRAM_BASE + 0x0FA)
#define COMMAND (DPRAM_BASE + 0x0FC)
#define COM_BUFF (DPRAM_BASE + 0x100)
#define COM_BUFF_SIZE 0x20
@@ -332,8 +331,6 @@ enum av7110_command_type {
/* firmware status area */
#define STATUS_BASE (DPRAM_BASE + 0x1FC0)
-#define STATUS_SCR (STATUS_BASE + 0x00)
-#define STATUS_MODES (STATUS_BASE + 0x04)
#define STATUS_LOOPS (STATUS_BASE + 0x08)
#define STATUS_MPEG_WIDTH (STATUS_BASE + 0x0C)
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index b30a528..b7d1f2f 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -667,6 +667,11 @@ static struct tda1002x_config philips_cu1216_config_altaddress = {
.invert = 0,
};
+static struct tda10023_config philips_cu1216_tda10023_config = {
+ .demod_address = 0x0c,
+ .invert = 1,
+};
+
static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
@@ -1019,9 +1024,10 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBC_KNC1_PLUS_MK3:
budget_av->reinitialise_demod = 1;
budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
- fe = dvb_attach(tda10023_attach, &philips_cu1216_config,
- &budget_av->budget.i2c_adap,
- read_pwm(budget_av));
+ fe = dvb_attach(tda10023_attach,
+ &philips_cu1216_tda10023_config,
+ &budget_av->budget.i2c_adap,
+ read_pwm(budget_av));
if (fe) {
fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
}
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 6530323..060e7c7 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -46,6 +46,8 @@
#include "lnbp21.h"
#include "bsbe1.h"
#include "bsru6.h"
+#include "tda1002x.h"
+#include "tda827x.h"
/*
* Regarding DEBIADDR_IR:
@@ -225,6 +227,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
break;
case 0x1010:
case 0x1017:
+ case 0x101a:
/* for the Technotrend 1500 bundled remote */
ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, ir_codes_tt_1500);
@@ -1056,6 +1059,15 @@ static struct stv0297_config dvbc_philips_tdm1316l_config = {
.stop_during_read = 1,
};
+static struct tda10023_config tda10023_config = {
+ .demod_address = 0xc,
+ .invert = 0,
+ .xtal = 16000000,
+ .pll_m = 11,
+ .pll_p = 3,
+ .pll_n = 1,
+ .deltaf = 0xa511,
+};
@@ -1126,7 +1138,17 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dvb_frontend = NULL;
}
}
+ break;
+ case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
+ budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
+ if (budget_ci->budget.dvb_frontend) {
+ if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, NULL) == NULL) {
+ printk(KERN_ERR "%s: No tda827x found!\n", __func__);
+ dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+ budget_ci->budget.dvb_frontend = NULL;
+ }
+ }
break;
}
@@ -1216,6 +1238,7 @@ MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
@@ -1224,6 +1247,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
+ MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
{
.vendor = 0,
}
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 18cac4b..6f4ddb6 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -497,11 +497,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
if (bi->type != BUDGET_FS_ACTIVY)
saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
- budget->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
-#else
budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
-#endif
strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 9a15539..39bd0a2 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -431,22 +431,22 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
// in budget patch GPIO3 is connected to VSYNC_B
count = 0;
#if 0
- WRITE_RPS1(cpu_to_le32(CMD_UPLOAD |
- MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 ));
+ WRITE_RPS1(CMD_UPLOAD |
+ MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 );
#endif
- WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
- WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
- WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
- WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
+ WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
#if RPS_IRQ
// issue RPS1 interrupt to increment counter
- WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+ WRITE_RPS1(CMD_INTERRUPT);
// at least a NOP is neede between two interrupts
- WRITE_RPS1(cpu_to_le32(CMD_NOP));
+ WRITE_RPS1(CMD_NOP);
// interrupt again
- WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+ WRITE_RPS1(CMD_INTERRUPT);
#endif
- WRITE_RPS1(cpu_to_le32(CMD_STOP));
+ WRITE_RPS1(CMD_STOP);
#if RPS_IRQ
// set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
@@ -558,28 +558,28 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
// Wait Source Line Counter Threshold (p36)
- WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS));
+ WRITE_RPS1(CMD_PAUSE | EVT_HS);
// Set GPIO3=1 (p42)
- WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
- WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
- WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24));
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
#if RPS_IRQ
// issue RPS1 interrupt
- WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+ WRITE_RPS1(CMD_INTERRUPT);
#endif
// Wait reset Source Line Counter Threshold (p36)
- WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS));
+ WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
// Set GPIO3=0 (p42)
- WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)));
- WRITE_RPS1(cpu_to_le32(GPIO3_MSK));
- WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24));
+ WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
+ WRITE_RPS1(GPIO3_MSK);
+ WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
#if RPS_IRQ
// issue RPS1 interrupt
- WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT));
+ WRITE_RPS1(CMD_INTERRUPT);
#endif
// Jump to begin of RPS program (p37)
- WRITE_RPS1(cpu_to_le32(CMD_JUMP));
- WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle));
+ WRITE_RPS1(CMD_JUMP);
+ WRITE_RPS1(dev->d_rps1.dma_handle);
// Fix VSYNC level
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 732ce4d..e6c9cd2 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/wait.h>
+#include <linux/fs.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/delay.h>
@@ -19,6 +20,7 @@
#include <linux/errno.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
+#include <linux/firmware.h>
#include "dvb_frontend.h"
#include "dmxdev.h"
@@ -285,13 +287,19 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num
return i;
}
-#include "dvb-ttusb-dspbootcode.h"
-
static int ttusb_boot_dsp(struct ttusb *ttusb)
{
+ const struct firmware *fw;
int i, err;
u8 b[40];
+ err = request_firmware(&fw, "ttusb-budget/dspbootcode.bin",
+ &ttusb->dev->dev);
+ if (err) {
+ printk(KERN_ERR "ttusb-budget: failed to request firmware\n");
+ return err;
+ }
+
/* BootBlock */
b[0] = 0xaa;
b[2] = 0x13;
@@ -299,8 +307,8 @@ static int ttusb_boot_dsp(struct ttusb *ttusb)
/* upload dsp code in 32 byte steps (36 didn't work for me ...) */
/* 32 is max packet size, no messages should be splitted. */
- for (i = 0; i < sizeof(dsp_bootcode); i += 28) {
- memcpy(&b[4], &dsp_bootcode[i], 28);
+ for (i = 0; i < fw->size; i += 28) {
+ memcpy(&b[4], &fw->data[i], 28);
b[1] = ++ttusb->c;
@@ -552,7 +560,7 @@ static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
u16 csum = 0, cc;
int i;
for (i = 0; i < len; i += 2)
- csum ^= le16_to_cpup((u16 *) (muxpack + i));
+ csum ^= le16_to_cpup((__le16 *) (muxpack + i));
if (csum) {
printk("%s: muxpack with incorrect checksum, ignoring\n",
__func__);
@@ -983,22 +991,9 @@ static int stc_open(struct inode *inode, struct file *file)
}
static ssize_t stc_read(struct file *file, char *buf, size_t count,
- loff_t * offset)
+ loff_t *offset)
{
- int tc = count;
-
- if ((tc + *offset) > 8192)
- tc = 8192 - *offset;
-
- if (tc < 0)
- return 0;
-
- if (copy_to_user(buf, stc_firmware + *offset, tc))
- return -EFAULT;
-
- *offset += tc;
-
- return tc;
+ return simple_read_from_buffer(buf, count, offset, stc_firmware, 8192);
}
static int stc_release(struct inode *inode, struct file *file)
@@ -1686,11 +1681,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
i2c_set_adapdata(&ttusb->i2c_adap, ttusb);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
- ttusb->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
-#else
ttusb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
-#endif
ttusb->i2c_adap.algo = &ttusb_dec_algo;
ttusb->i2c_adap.algo_data = NULL;
ttusb->i2c_adap.dev.parent = &udev->dev;
@@ -1820,3 +1811,4 @@ module_exit(ttusb_exit);
MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
MODULE_DESCRIPTION("TTUSB DVB Driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("ttusb-budget/dspbootcode.bin");
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h
deleted file mode 100644
index 8c3cd54..0000000
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h
+++ /dev/null
@@ -1,1644 +0,0 @@
-
-#include <asm/types.h>
-
-static u8 dsp_bootcode [] = {
- 0x08, 0xaa, 0x00, 0x18, 0x00, 0x03, 0x08, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x01, 0x80, 0x18, 0x5f,
- 0x00, 0x00, 0x01, 0x80, 0x77, 0x18, 0x2a, 0xeb,
- 0x6b, 0xf8, 0x00, 0x18, 0x03, 0xff, 0x68, 0xf8,
- 0x00, 0x18, 0xff, 0xfe, 0xf7, 0xb8, 0xf7, 0xbe,
- 0xf6, 0xb9, 0xf4, 0xa0, 0xf6, 0xb7, 0xf6, 0xb5,
- 0xf6, 0xb6, 0xf0, 0x20, 0x19, 0xdf, 0xf1, 0x00,
- 0x00, 0x01, 0xf8, 0x4d, 0x01, 0xab, 0xf6, 0xb8,
- 0xf0, 0x20, 0x19, 0xdf, 0xf0, 0x73, 0x01, 0xa5,
- 0x7e, 0xf8, 0x00, 0x12, 0xf0, 0x00, 0x00, 0x01,
- 0x47, 0xf8, 0x00, 0x11, 0x7e, 0x92, 0x00, 0xf8,
- 0x00, 0x11, 0xf0, 0x00, 0x00, 0x01, 0x7e, 0xf8,
- 0x00, 0x11, 0xf0, 0x00, 0x00, 0x01, 0x6c, 0x89,
- 0x01, 0x9a, 0xf7, 0xb8, 0xee, 0xfc, 0xf0, 0x20,
- 0xff, 0xff, 0xf1, 0x00, 0x00, 0x01, 0xf8, 0x4d,
- 0x01, 0xbf, 0xf2, 0x73, 0x01, 0xb9, 0x4e, 0x02,
- 0xf4, 0x95, 0xf5, 0xe3, 0x56, 0x02, 0x7e, 0x00,
- 0x11, 0x00, 0xfa, 0x4c, 0x01, 0xb7, 0x6b, 0x03,
- 0x00, 0x01, 0xf6, 0xb8, 0xee, 0x04, 0xf0, 0x74,
- 0x0d, 0xa7, 0xf0, 0x74, 0x01, 0xc5, 0x4a, 0x11,
- 0x4a, 0x16, 0x72, 0x11, 0x2a, 0xe6, 0x10, 0xf8,
- 0x00, 0x11, 0xfa, 0x45, 0x01, 0xdb, 0xf4, 0x95,
- 0xee, 0xff, 0x48, 0x11, 0xf0, 0x00, 0x2a, 0xc6,
- 0x88, 0x16, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0xee,
- 0xff, 0xff, 0xf4, 0xe3, 0x6c, 0xe9, 0xff, 0xff,
- 0x01, 0xd5, 0x10, 0xf8, 0x2a, 0xe7, 0xf8, 0x45,
- 0x01, 0xe2, 0x10, 0xf8, 0x2a, 0xe7, 0xf4, 0xe3,
- 0xf0, 0x74, 0x01, 0xff, 0xee, 0x01, 0x8a, 0x16,
- 0x8a, 0x11, 0xfc, 0x00, 0xf7, 0xb8, 0xe9, 0x20,
- 0x4a, 0x11, 0x09, 0xf8, 0x2a, 0xe6, 0xf8, 0x4e,
- 0x01, 0xf3, 0xf2, 0x73, 0x01, 0xfd, 0xf4, 0x95,
- 0xe8, 0x01, 0x72, 0x11, 0x2a, 0xe6, 0x49, 0x11,
- 0x80, 0xe1, 0x2a, 0xc6, 0xf3, 0x00, 0x00, 0x01,
- 0xe8, 0x00, 0x81, 0xf8, 0x2a, 0xe6, 0x8a, 0x11,
- 0xfc, 0x00, 0xf4, 0x95, 0xf0, 0x73, 0x02, 0x00,
- 0x10, 0xf8, 0x2a, 0x0f, 0xfc, 0x00, 0x4a, 0x11,
- 0xf0, 0x74, 0x02, 0x02, 0x80, 0xf8, 0x2a, 0x10,
- 0x73, 0x08, 0x00, 0x09, 0x40, 0xf8, 0x2a, 0x15,
- 0x82, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0x77, 0x10,
- 0x03, 0xe8, 0xf5, 0xa9, 0xf8, 0x30, 0x02, 0x21,
- 0x71, 0xf8, 0x2a, 0x10, 0x2a, 0x15, 0x56, 0xf8,
- 0x2a, 0x0c, 0xf0, 0xe3, 0x4e, 0xf8, 0x2a, 0x16,
- 0xe8, 0x00, 0x4e, 0xf8, 0x2a, 0x0c, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1d,
- 0x68, 0xf8, 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8,
- 0x00, 0x07, 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d,
- 0xff, 0xfc, 0x6b, 0xf8, 0x2a, 0x0f, 0x00, 0x01,
- 0x8a, 0x1d, 0x8a, 0x07, 0x8a, 0x06, 0xf4, 0xeb,
- 0xee, 0xfd, 0x76, 0xf8, 0x2a, 0x0f, 0x00, 0x00,
- 0x76, 0x00, 0x00, 0x00, 0xfb, 0x80, 0x19, 0x4c,
- 0xf4, 0x95, 0xe8, 0x00, 0x80, 0xf8, 0x2a, 0x11,
- 0xf9, 0x80, 0x19, 0x07, 0x80, 0xf8, 0x2a, 0x0e,
- 0xf9, 0x80, 0x16, 0x66, 0x76, 0x00, 0x2a, 0x12,
- 0x10, 0xf8, 0x2a, 0x11, 0xf9, 0x80, 0x18, 0xe3,
- 0x10, 0xf8, 0x2a, 0x0e, 0xf9, 0x80, 0x16, 0x66,
- 0x10, 0xf8, 0x2a, 0x0e, 0xf9, 0x80, 0x16, 0x87,
- 0xee, 0x03, 0xfc, 0x00, 0x4a, 0x11, 0xf6, 0xb8,
- 0xf4, 0x95, 0xf0, 0x20, 0x80, 0x00, 0x11, 0xf8,
- 0x2a, 0x5a, 0xf8, 0x4d, 0x02, 0x93, 0x11, 0xf8,
- 0x2a, 0x9f, 0xf8, 0x4c, 0x02, 0x7c, 0x77, 0x12,
- 0x2a, 0x39, 0x49, 0x12, 0x01, 0xf8, 0x2a, 0x9f,
- 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0x81,
- 0x00, 0x11, 0x6c, 0xe1, 0xff, 0xab, 0x02, 0x93,
- 0x6b, 0xf8, 0x2a, 0x9f, 0x00, 0x01, 0xe9, 0x05,
- 0x01, 0xe2, 0x00, 0x03, 0x81, 0xf8, 0x2a, 0xa0,
- 0xf0, 0x73, 0x02, 0x95, 0x72, 0x11, 0x2a, 0x9f,
- 0xf4, 0x95, 0x10, 0xe1, 0x2a, 0x39, 0x6b, 0xf8,
- 0x2a, 0x9f, 0x00, 0x01, 0x11, 0xf8, 0x2a, 0x9f,
- 0x09, 0xf8, 0x2a, 0xa0, 0xf8, 0x4c, 0x02, 0x93,
- 0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x00, 0x76, 0xf8,
- 0x2a, 0x9f, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa0,
- 0x00, 0x00, 0x88, 0x11, 0xf4, 0x95, 0x48, 0x11,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe,
- 0x10, 0xf8, 0x2a, 0x5a, 0xf8, 0x44, 0x02, 0xb2,
- 0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x01, 0xf0, 0x74,
- 0x02, 0x58, 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10,
- 0x80, 0x00, 0xf4, 0xa9, 0xf8, 0x30, 0x02, 0xb2,
- 0x48, 0x11, 0xf0, 0x30, 0x00, 0xff, 0x80, 0x00,
- 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x18, 0xd6,
- 0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, 0xf4, 0x95,
- 0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, 0x4a, 0x0b,
- 0x4a, 0x0c, 0x4a, 0x0d, 0x4a, 0x10, 0x4a, 0x11,
- 0x4a, 0x12, 0x4a, 0x13, 0x4a, 0x14, 0x4a, 0x15,
- 0x4a, 0x16, 0x4a, 0x17, 0x4a, 0x17, 0x4a, 0x19,
- 0x4a, 0x0e, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1a,
- 0x4a, 0x1d, 0x4a, 0x1b, 0x4a, 0x1c, 0x68, 0xf8,
- 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07,
- 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc,
- 0x48, 0x18, 0x68, 0xf8, 0x00, 0x18, 0xff, 0xfe,
- 0xf4, 0x95, 0xf4, 0x95, 0x4a, 0x08, 0xee, 0xfd,
- 0xf0, 0x74, 0x02, 0x58, 0x88, 0x11, 0xf4, 0x95,
- 0x77, 0x10, 0x80, 0x00, 0xf4, 0xa9, 0xf8, 0x30,
- 0x02, 0xef, 0x48, 0x11, 0xf0, 0x30, 0x00, 0xff,
- 0x80, 0x00, 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80,
- 0x18, 0xd6, 0xee, 0x03, 0x8a, 0x18, 0xf4, 0x95,
- 0x8a, 0x1c, 0x8a, 0x1b, 0x8a, 0x1d, 0x8a, 0x1a,
- 0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0e, 0x8a, 0x19,
- 0x8a, 0x17, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x15,
- 0x8a, 0x14, 0x8a, 0x13, 0x8a, 0x12, 0x8a, 0x11,
- 0x8a, 0x10, 0x8a, 0x0d, 0x8a, 0x0c, 0x8a, 0x0b,
- 0x8a, 0x0a, 0x8a, 0x09, 0x8a, 0x08, 0xf4, 0xeb,
- 0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81,
- 0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2,
- 0x00, 0x01, 0x80, 0xe1, 0x00, 0x01, 0x10, 0xe2,
- 0x00, 0x02, 0x80, 0xe1, 0x00, 0x02, 0x76, 0xe1,
- 0x00, 0x03, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x04,
- 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, 0xf4, 0x95,
- 0xf4, 0x95, 0x10, 0x81, 0x6f, 0xf8, 0x2a, 0x9e,
- 0x0c, 0x88, 0xe8, 0xff, 0x18, 0xe1, 0x00, 0x01,
- 0x1a, 0xf8, 0x2a, 0x9e, 0xf0, 0x30, 0x1f, 0xff,
- 0x80, 0xf8, 0x2a, 0x9e, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81,
- 0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, 0x11, 0xe2,
- 0x00, 0x01, 0x81, 0xe1, 0x00, 0x01, 0x11, 0xe2,
- 0x00, 0x02, 0x81, 0xe1, 0x00, 0x02, 0x76, 0xe1,
- 0x00, 0x03, 0x00, 0x02, 0x48, 0x08, 0x6f, 0xe1,
- 0x00, 0x04, 0x0c, 0x98, 0xf0, 0x30, 0x00, 0xff,
- 0x80, 0xe1, 0x00, 0x05, 0x76, 0xe1, 0x00, 0x06,
- 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39,
- 0x76, 0x81, 0x00, 0x55, 0x77, 0x12, 0x2a, 0x18,
- 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1, 0x00, 0x01,
- 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1, 0x00, 0x02,
- 0x76, 0xe1, 0x00, 0x03, 0x00, 0x04, 0x48, 0x11,
- 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12, 0xf4, 0x95,
- 0x77, 0x13, 0x2a, 0x76, 0xe9, 0x00, 0xe5, 0x98,
- 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8, 0x48, 0x0b,
- 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 0x03, 0x71,
- 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xf0,
- 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0x81,
- 0x00, 0x14, 0x71, 0xe1, 0x00, 0x01, 0x00, 0x15,
- 0x49, 0x11, 0xf3, 0x00, 0x00, 0x02, 0x89, 0x11,
- 0xe7, 0x82, 0x6d, 0xea, 0x00, 0x04, 0xe7, 0x83,
- 0x6d, 0xeb, 0x00, 0x0a, 0x77, 0x1a, 0x00, 0x05,
- 0xf0, 0x72, 0x03, 0xaa, 0x11, 0x81, 0xf2, 0xe8,
- 0x80, 0x82, 0xe9, 0xff, 0x19, 0xe1, 0x00, 0x01,
- 0xf1, 0xa0, 0x81, 0x92, 0x11, 0xe1, 0x00, 0x0c,
- 0xf2, 0xe8, 0x80, 0x83, 0xe9, 0xff, 0x19, 0xe1,
- 0x00, 0x0d, 0xf1, 0xa0, 0x81, 0x93, 0x6d, 0xe9,
- 0x00, 0x02, 0x48, 0x18, 0x49, 0x18, 0x70, 0x00,
- 0x00, 0x15, 0xf0, 0x00, 0x00, 0x04, 0xf3, 0x00,
- 0x00, 0x0a, 0x80, 0x01, 0x81, 0x02, 0xf2, 0x74,
- 0x0e, 0x54, 0xf4, 0x95, 0x48, 0x14, 0xee, 0x10,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xf0, 0x74,
- 0x0c, 0x5e, 0x80, 0xf8, 0x2a, 0x5c, 0x77, 0x12,
- 0x2a, 0x39, 0x76, 0x82, 0x00, 0x55, 0x77, 0x11,
- 0x2a, 0x18, 0x10, 0xe1, 0x00, 0x01, 0x80, 0xe2,
- 0x00, 0x01, 0x10, 0xe1, 0x00, 0x02, 0x80, 0xe2,
- 0x00, 0x02, 0x76, 0xe2, 0x00, 0x03, 0x00, 0x1c,
- 0xf6, 0xb8, 0x56, 0xf8, 0x2a, 0x16, 0xf0, 0xf0,
- 0xf0, 0xf8, 0x80, 0xe2, 0x00, 0x07, 0x56, 0xf8,
- 0x2a, 0x16, 0xf1, 0xf0, 0xe8, 0xff, 0xf2, 0x80,
- 0x80, 0xe2, 0x00, 0x06, 0x56, 0xf8, 0x2a, 0x16,
- 0xf1, 0xf8, 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2,
- 0x00, 0x05, 0x57, 0xf8, 0x2a, 0x16, 0xe8, 0xff,
- 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x04, 0x56, 0xf8,
- 0x27, 0x6c, 0xf0, 0xf0, 0xf0, 0xf8, 0x80, 0xe2,
- 0x00, 0x0b, 0x56, 0xf8, 0x27, 0x6c, 0xf1, 0xf0,
- 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x0a,
- 0x56, 0xf8, 0x27, 0x6c, 0xf1, 0xf8, 0xe8, 0xff,
- 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x09, 0xe8, 0xff,
- 0x57, 0xf8, 0x27, 0x6c, 0xf2, 0x80, 0x80, 0xe2,
- 0x00, 0x08, 0x56, 0xf8, 0x27, 0x6a, 0xf0, 0xf0,
- 0xf0, 0xf8, 0x80, 0xe2, 0x00, 0x0f, 0x56, 0xf8,
- 0x27, 0x6a, 0xf1, 0xf0, 0xe8, 0xff, 0xf2, 0x80,
- 0x80, 0xe2, 0x00, 0x0e, 0x56, 0xf8, 0x27, 0x6a,
- 0xf1, 0xf8, 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2,
- 0x00, 0x0d, 0x57, 0xf8, 0x27, 0x6a, 0xe8, 0xff,
- 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x0c, 0x76, 0xe2,
- 0x00, 0x13, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x12,
- 0x00, 0x00, 0x6f, 0xf8, 0x2a, 0x5c, 0x0c, 0x58,
- 0x80, 0xe2, 0x00, 0x11, 0xe8, 0xff, 0x18, 0xf8,
- 0x2a, 0x5c, 0x80, 0xe2, 0x00, 0x10, 0x76, 0xe2,
- 0x00, 0x17, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x16,
- 0x00, 0x00, 0x6f, 0xf8, 0x2a, 0x9e, 0x0c, 0x58,
- 0x80, 0xe2, 0x00, 0x15, 0xe8, 0xff, 0x18, 0xf8,
- 0x2a, 0x9e, 0x80, 0xe2, 0x00, 0x14, 0x76, 0xe2,
- 0x00, 0x1b, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1a,
- 0x00, 0x00, 0x76, 0xe2, 0x00, 0x19, 0x00, 0x00,
- 0x70, 0xe2, 0x00, 0x18, 0x27, 0x6e, 0x76, 0xe2,
- 0x00, 0x1f, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1e,
- 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1d, 0x00, 0x00,
- 0x76, 0xe2, 0x00, 0x1c, 0x00, 0x00, 0x76, 0xe2,
- 0x00, 0x20, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe,
- 0x10, 0xf8, 0x2a, 0x38, 0xf8, 0x45, 0x04, 0xed,
- 0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x02,
- 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x08,
- 0x6d, 0xe9, 0xff, 0xdf, 0xf6, 0xa9, 0xf8, 0x20,
- 0x04, 0x75, 0xf0, 0x73, 0x04, 0x7d, 0xf0, 0x10,
- 0x00, 0x21, 0xf0, 0x00, 0x1a, 0x83, 0x48, 0x08,
- 0x7e, 0xf8, 0x00, 0x08, 0xf4, 0xe2, 0xf0, 0x74,
- 0x03, 0x0a, 0xf0, 0x73, 0x04, 0xea, 0x48, 0x12,
- 0xf2, 0x74, 0x03, 0x23, 0xf0, 0x00, 0x00, 0x04,
- 0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00,
- 0xf0, 0x73, 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18,
- 0xe8, 0xff, 0x6f, 0xe1, 0x00, 0x04, 0x0d, 0x48,
- 0x18, 0xe1, 0x00, 0x05, 0xf2, 0x74, 0x09, 0x69,
- 0xf4, 0x95, 0xf2, 0xa0, 0xf0, 0x74, 0x03, 0x36,
- 0xf0, 0x73, 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18,
- 0xe8, 0xff, 0x6f, 0xe1, 0x00, 0x04, 0x0d, 0x48,
- 0x18, 0xe1, 0x00, 0x05, 0xf2, 0x74, 0x09, 0x41,
- 0xf4, 0x95, 0xf2, 0xa0, 0xf0, 0x74, 0x03, 0x36,
- 0xf0, 0x73, 0x04, 0xea, 0xf0, 0x74, 0x03, 0x57,
- 0xf0, 0x73, 0x04, 0xea, 0x10, 0xf8, 0x2a, 0x1c,
- 0xf0, 0x74, 0x12, 0xa4, 0xf2, 0x74, 0x03, 0x36,
- 0xf4, 0x95, 0xe8, 0x00, 0xf0, 0x73, 0x04, 0xea,
- 0x48, 0x12, 0xf2, 0x74, 0x03, 0x80, 0xf0, 0x00,
- 0x00, 0x04, 0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95,
- 0xe8, 0x00, 0xf0, 0x73, 0x04, 0xea, 0x10, 0xf8,
- 0x2a, 0x1c, 0xf0, 0x74, 0x12, 0xc5, 0xf2, 0x74,
- 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00, 0xf0, 0x73,
- 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18, 0xe8, 0xff,
- 0x6f, 0xe1, 0x00, 0x06, 0x0d, 0x48, 0x18, 0xe1,
- 0x00, 0x07, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0xf2, 0xa0, 0x70, 0x00, 0x00, 0x12, 0x80, 0x01,
- 0x10, 0xe1, 0x00, 0x04, 0xf0, 0x74, 0x0e, 0x7a,
- 0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00,
- 0xf0, 0x73, 0x04, 0xea, 0xf0, 0x74, 0x03, 0xbc,
- 0x76, 0xf8, 0x2a, 0x38, 0x00, 0x00, 0xee, 0x02,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11,
- 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 0x77, 0x12,
- 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1,
- 0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1,
- 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x09,
- 0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12,
- 0xf4, 0x95, 0x77, 0x13, 0x2a, 0x86, 0xe9, 0x00,
- 0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8,
- 0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43,
- 0x05, 0x0a, 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74,
- 0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55,
- 0x77, 0x13, 0x2a, 0x18, 0x10, 0xe3, 0x00, 0x01,
- 0x80, 0xe1, 0x00, 0x01, 0x10, 0xe3, 0x00, 0x02,
- 0x80, 0xe1, 0x00, 0x02, 0x13, 0xe3, 0x00, 0x03,
- 0x81, 0xe1, 0x00, 0x03, 0x48, 0x11, 0x77, 0x11,
- 0x00, 0x00, 0xf8, 0x4d, 0x05, 0x44, 0xf0, 0x00,
- 0x00, 0x04, 0x88, 0x12, 0x48, 0x13, 0xf0, 0x00,
- 0x00, 0x04, 0x88, 0x13, 0xf4, 0x95, 0xf4, 0x95,
- 0xe5, 0x98, 0x6d, 0x91, 0xf6, 0xb8, 0x48, 0x11,
- 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 0x05, 0x3a,
- 0xf0, 0x20, 0x2a, 0x39, 0x49, 0x11, 0xf5, 0x00,
- 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x76, 0xe1,
- 0x00, 0x04, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11,
- 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 0x77, 0x12,
- 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1,
- 0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1,
- 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x0c,
- 0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12,
- 0xf4, 0x95, 0x77, 0x13, 0x2a, 0x7a, 0xe9, 0x00,
- 0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8,
- 0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43,
- 0x05, 0x6a, 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74,
- 0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55,
- 0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01,
- 0x80, 0xe1, 0x00, 0x01, 0x10, 0xe2, 0x00, 0x02,
- 0x80, 0xe1, 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03,
- 0x00, 0x19, 0x48, 0x11, 0xf0, 0x00, 0x00, 0x04,
- 0x88, 0x12, 0xf4, 0x95, 0x77, 0x13, 0x2a, 0x5d,
- 0xe9, 0x00, 0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01,
- 0xf6, 0xb8, 0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c,
- 0xf8, 0x43, 0x05, 0x93, 0x76, 0x82, 0x00, 0xaa,
- 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0x88, 0x11, 0x10, 0xf8, 0x2a, 0x38,
- 0xf8, 0x44, 0x05, 0xe3, 0x10, 0xf8, 0x2a, 0xa1,
- 0xf8, 0x44, 0x05, 0xba, 0x6c, 0xe1, 0xff, 0x56,
- 0x05, 0xe3, 0x72, 0x12, 0x2a, 0xa1, 0xf4, 0x95,
- 0x70, 0xe2, 0x2a, 0x18, 0x00, 0x11, 0x6b, 0xf8,
- 0x2a, 0xa1, 0x00, 0x01, 0xf0, 0x73, 0x05, 0xe3,
- 0x72, 0x12, 0x2a, 0xa1, 0xf4, 0x95, 0x70, 0xe2,
- 0x2a, 0x18, 0x00, 0x11, 0x10, 0xf8, 0x2a, 0xa1,
- 0xf0, 0x00, 0x00, 0x01, 0x88, 0x12, 0xf4, 0x95,
- 0xf4, 0x95, 0x6e, 0xe2, 0xff, 0xfc, 0x05, 0xd1,
- 0x73, 0x12, 0x2a, 0xa1, 0x48, 0x11, 0xf0, 0x00,
- 0x00, 0x05, 0x80, 0xf8, 0x2a, 0xa2, 0x10, 0xf8,
- 0x2a, 0xa1, 0x08, 0xf8, 0x2a, 0xa2, 0xf8, 0x44,
- 0x05, 0xe3, 0x6c, 0xe1, 0xff, 0xab, 0x05, 0xdd,
- 0x76, 0xf8, 0x2a, 0x38, 0x00, 0x01, 0x76, 0xf8,
- 0x2a, 0xa1, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa2,
- 0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0xf4, 0x95,
- 0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, 0x4a, 0x0b,
- 0x4a, 0x0c, 0x4a, 0x0d, 0x4a, 0x10, 0x4a, 0x11,
- 0x4a, 0x12, 0x4a, 0x13, 0x4a, 0x14, 0x4a, 0x15,
- 0x4a, 0x16, 0x4a, 0x17, 0x4a, 0x17, 0x4a, 0x19,
- 0x4a, 0x0e, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1a,
- 0x4a, 0x1d, 0x4a, 0x1b, 0x4a, 0x1c, 0x68, 0xf8,
- 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07,
- 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc,
- 0x48, 0x18, 0x68, 0xf8, 0x00, 0x18, 0xff, 0xfe,
- 0xf4, 0x95, 0xf4, 0x95, 0x4a, 0x08, 0xee, 0xff,
- 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x18, 0x04,
- 0xf0, 0x74, 0x05, 0xa2, 0xee, 0x01, 0x8a, 0x18,
- 0xf4, 0x95, 0x8a, 0x1c, 0x8a, 0x1b, 0x8a, 0x1d,
- 0x8a, 0x1a, 0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0e,
- 0x8a, 0x19, 0x8a, 0x17, 0x8a, 0x17, 0x8a, 0x16,
- 0x8a, 0x15, 0x8a, 0x14, 0x8a, 0x13, 0x8a, 0x12,
- 0x8a, 0x11, 0x8a, 0x10, 0x8a, 0x0d, 0x8a, 0x0c,
- 0x8a, 0x0b, 0x8a, 0x0a, 0x8a, 0x09, 0x8a, 0x08,
- 0xf4, 0xeb, 0xee, 0xfd, 0x76, 0xf8, 0x2a, 0x38,
- 0x00, 0x00, 0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x00,
- 0xe8, 0x01, 0x4e, 0x00, 0xfb, 0x80, 0x17, 0xd6,
- 0xf4, 0x95, 0xe8, 0x01, 0x80, 0xf8, 0x2a, 0x5b,
- 0x76, 0x00, 0x2a, 0x8f, 0xf9, 0x80, 0x16, 0xaa,
- 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x17, 0x5c,
- 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x17, 0x6f,
- 0xfb, 0x80, 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x1a,
- 0xfb, 0x80, 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x1a,
- 0xfb, 0x80, 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x1b,
- 0xfb, 0x80, 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x1b,
- 0xee, 0x03, 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95,
- 0x13, 0x02, 0x88, 0x11, 0xe8, 0x00, 0xf8, 0x4d,
- 0x06, 0x6a, 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a,
- 0xf4, 0x95, 0xf0, 0x72, 0x06, 0x69, 0x1c, 0x91,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11,
- 0x12, 0x03, 0x11, 0x02, 0xf8, 0x45, 0x06, 0x79,
- 0xf0, 0x10, 0x00, 0x01, 0x88, 0x1a, 0xf4, 0x95,
- 0xf0, 0x72, 0x06, 0x78, 0x81, 0x91, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02,
- 0x00, 0x11, 0x11, 0x03, 0x61, 0xf8, 0x00, 0x11,
- 0x00, 0x01, 0xf8, 0x30, 0x06, 0x91, 0xf6, 0xb8,
- 0x6f, 0xf8, 0x00, 0x11, 0x0c, 0x1f, 0x88, 0x11,
- 0xf3, 0xe8, 0xe8, 0xff, 0x18, 0x81, 0xf1, 0xa0,
- 0x81, 0x81, 0xf0, 0x73, 0x06, 0x9d, 0xf6, 0xb8,
- 0x6f, 0xf8, 0x00, 0x11, 0x0c, 0x1f, 0x88, 0x11,
- 0xf3, 0x30, 0x00, 0xff, 0xf0, 0x20, 0xff, 0x00,
- 0x18, 0x81, 0xf1, 0xa0, 0x81, 0x81, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x11, 0x02,
- 0x61, 0xf8, 0x00, 0x0b, 0x00, 0x01, 0xf8, 0x20,
- 0x06, 0xb1, 0x49, 0x0b, 0xf6, 0x1f, 0x88, 0x11,
- 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xf2, 0x73,
- 0x06, 0xb8, 0xf0, 0x30, 0x00, 0xff, 0x49, 0x0b,
- 0xf6, 0x1f, 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95,
- 0x12, 0x81, 0xf4, 0x78, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x12,
- 0x13, 0x03, 0x88, 0x11, 0xe8, 0x00, 0xf8, 0x4d,
- 0x06, 0xcc, 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a,
- 0xf4, 0x95, 0xf0, 0x72, 0x06, 0xcb, 0x11, 0x92,
- 0xf2, 0xc0, 0x81, 0x91, 0x8a, 0x11, 0xfc, 0x00,
- 0x88, 0x12, 0x12, 0x02, 0x71, 0x01, 0x00, 0x13,
- 0xf8, 0x45, 0x06, 0xdb, 0xf0, 0x10, 0x00, 0x01,
- 0x88, 0x1a, 0xf4, 0x95, 0xf0, 0x72, 0x06, 0xda,
- 0xe5, 0x98, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe,
- 0x88, 0x11, 0x11, 0x04, 0x10, 0x06, 0x71, 0x05,
- 0x00, 0x12, 0x61, 0xf8, 0x00, 0x12, 0x00, 0x01,
- 0xf8, 0x20, 0x06, 0xea, 0xf0, 0x00, 0x00, 0x01,
- 0xf6, 0xb8, 0xf0, 0x00, 0x00, 0x01, 0x6f, 0xf8,
- 0x00, 0x12, 0x0f, 0x1f, 0x48, 0x08, 0x81, 0x00,
- 0xf4, 0x7f, 0x80, 0x01, 0xf2, 0x74, 0x06, 0xba,
- 0xf4, 0x95, 0x48, 0x11, 0xee, 0x02, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 0x88, 0x12,
- 0x11, 0x04, 0x10, 0x06, 0x71, 0x05, 0x00, 0x13,
- 0x61, 0xf8, 0x00, 0x13, 0x00, 0x01, 0xf8, 0x20,
- 0x07, 0x09, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x00,
- 0x00, 0x01, 0x88, 0x11, 0xf6, 0xb8, 0x6f, 0xf8,
- 0x00, 0x13, 0x0f, 0x1f, 0x81, 0x00, 0x48, 0x11,
- 0xf4, 0x7f, 0x80, 0x01, 0xf2, 0x74, 0x06, 0xce,
- 0xf4, 0x95, 0x48, 0x12, 0x48, 0x11, 0xf0, 0x30,
- 0xff, 0xfe, 0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xfc,
- 0xf4, 0x95, 0x80, 0x02, 0x71, 0x08, 0x00, 0x16,
- 0x10, 0x09, 0x71, 0x0b, 0x00, 0x17, 0x80, 0x03,
- 0x71, 0x0a, 0x00, 0x11, 0x48, 0x17, 0xf8, 0x45,
- 0x07, 0x3f, 0x70, 0x00, 0x00, 0x11, 0x10, 0x03,
- 0xf0, 0x74, 0x06, 0x9f, 0x80, 0x01, 0x70, 0x00,
- 0x00, 0x16, 0x10, 0x02, 0xf0, 0x74, 0x06, 0x7b,
- 0x6d, 0x91, 0x6d, 0x96, 0x6c, 0xef, 0xff, 0xff,
- 0x07, 0x2f, 0xee, 0x04, 0x8a, 0x17, 0x8a, 0x16,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe,
- 0x10, 0xf8, 0x2a, 0xe8, 0x08, 0xf8, 0x2a, 0xe9,
- 0xf8, 0x45, 0x07, 0x64, 0x76, 0x00, 0x00, 0x01,
- 0x62, 0xf8, 0x2a, 0xe9, 0x00, 0x5e, 0xf2, 0x74,
- 0x12, 0x0b, 0xf0, 0x00, 0x30, 0x40, 0x72, 0x11,
- 0x2a, 0xe9, 0x77, 0x10, 0x00, 0x0f, 0xf5, 0xa9,
- 0xf8, 0x20, 0x07, 0x61, 0x6b, 0xf8, 0x2a, 0xe9,
- 0x00, 0x01, 0xf0, 0x73, 0x07, 0x64, 0x76, 0xf8,
- 0x2a, 0xe9, 0x00, 0x00, 0xee, 0x02, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, 0xe8, 0x00,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x08, 0xe8, 0x00,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x09, 0xf6, 0xb8,
- 0xf4, 0x95, 0xf0, 0x20, 0xfc, 0x3f, 0x75, 0xf8,
- 0x00, 0x08, 0x00, 0x0d, 0xf0, 0x20, 0x0c, 0x30,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x0c, 0x76, 0xf8,
- 0x2a, 0xe8, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xe9,
- 0x00, 0x00, 0x6c, 0x81, 0x07, 0x92, 0x76, 0xf8,
- 0x2a, 0xea, 0x00, 0x00, 0xfb, 0x80, 0x16, 0x76,
- 0xf4, 0x95, 0xe8, 0x10, 0xe8, 0x00, 0x75, 0xf8,
- 0x00, 0x08, 0x00, 0x00, 0xf0, 0x73, 0x07, 0xa8,
- 0x76, 0xf8, 0x2a, 0xea, 0x00, 0x01, 0xfb, 0x80,
- 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x10, 0xfb, 0x80,
- 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x10, 0xe8, 0x00,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, 0xf6, 0xb8,
- 0xf4, 0x95, 0xf0, 0x20, 0xff, 0xff, 0x75, 0xf8,
- 0x00, 0x08, 0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00,
- 0xf4, 0x95, 0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a,
- 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8,
- 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07,
- 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc,
- 0x10, 0xf8, 0x2a, 0xea, 0xf8, 0x45, 0x07, 0xe1,
- 0x10, 0xf8, 0x2a, 0xe8, 0xf0, 0x00, 0x00, 0x01,
- 0xf0, 0x30, 0x00, 0x0f, 0x80, 0xf8, 0x2a, 0xe8,
- 0x10, 0xf8, 0x2a, 0xe8, 0xf8, 0x44, 0x07, 0xd6,
- 0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xfc, 0x3f,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x0d, 0xf0, 0x20,
- 0x0c, 0x30, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x0c,
- 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x00,
- 0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xff, 0xff,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, 0x8a, 0x1d,
- 0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0a, 0x8a, 0x09,
- 0x8a, 0x08, 0xf4, 0xeb, 0xee, 0xff, 0xf2, 0x74,
- 0x07, 0x67, 0xf4, 0x95, 0xe8, 0x01, 0xee, 0x01,
- 0xfc, 0x00, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8,
- 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07,
- 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc,
- 0x8a, 0x1d, 0x8a, 0x07, 0xf4, 0xeb, 0x4a, 0x11,
- 0x77, 0x11, 0x00, 0x28, 0x76, 0x81, 0x24, 0x00,
- 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01,
- 0xf2, 0x74, 0x07, 0x67, 0xf4, 0x95, 0xe8, 0x00,
- 0x77, 0x11, 0x00, 0x1d, 0x68, 0x81, 0x00, 0x7f,
- 0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xff, 0x80,
- 0x77, 0x11, 0x00, 0x1d, 0xf0, 0x30, 0x01, 0x00,
- 0x1a, 0x81, 0x80, 0x81, 0xf0, 0x74, 0x0a, 0x33,
- 0xf0, 0x74, 0x11, 0xac, 0xf9, 0x80, 0x13, 0x25,
- 0xf9, 0x80, 0x16, 0x53, 0xf9, 0x80, 0x17, 0x82,
- 0xf0, 0x74, 0x06, 0x2f, 0xf9, 0x80, 0x14, 0xb2,
- 0xf9, 0x80, 0x19, 0x10, 0xf0, 0x74, 0x0d, 0xe3,
- 0xf0, 0x74, 0x07, 0xe8, 0xf0, 0x74, 0x02, 0x36,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x60, 0xf8,
- 0x27, 0x7b, 0xff, 0xff, 0xf8, 0x30, 0x08, 0x39,
- 0x71, 0xf8, 0x27, 0x7b, 0x27, 0x79, 0x60, 0xf8,
- 0x27, 0x79, 0xff, 0xff, 0xf8, 0x30, 0x08, 0xb2,
- 0x10, 0xf8, 0x29, 0x86, 0x08, 0xf8, 0x27, 0x79,
- 0xf0, 0x30, 0x7f, 0xff, 0x88, 0x11, 0xf4, 0x95,
- 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x30,
- 0x08, 0x58, 0x10, 0xf8, 0x27, 0x79, 0x08, 0xf8,
- 0x27, 0x7a, 0xf0, 0x30, 0x7f, 0xff, 0x88, 0x11,
- 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9,
- 0xf8, 0x20, 0x08, 0x63, 0x76, 0xf8, 0x27, 0x79,
- 0xff, 0xff, 0x76, 0xf8, 0x27, 0x7b, 0xff, 0xff,
- 0xf7, 0xb8, 0xf2, 0x73, 0x08, 0xd9, 0xf0, 0x20,
- 0xff, 0xff, 0xf6, 0xb8, 0x56, 0xf8, 0x27, 0x74,
- 0xf0, 0xf9, 0x88, 0x11, 0x56, 0xf8, 0x27, 0x72,
- 0xf0, 0xf9, 0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95,
- 0xe7, 0x20, 0xf4, 0xa9, 0xf8, 0x30, 0x08, 0x8f,
- 0xf1, 0x20, 0x27, 0x7c, 0x48, 0x11, 0xf6, 0x00,
- 0x88, 0x13, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x83,
- 0x08, 0xf8, 0x27, 0x79, 0xf0, 0x30, 0x7f, 0xff,
- 0x88, 0x13, 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00,
- 0xf5, 0xab, 0xf8, 0x30, 0x08, 0x8f, 0x6d, 0x91,
- 0x48, 0x11, 0xf0, 0x30, 0x01, 0xff, 0x88, 0x11,
- 0xf4, 0x95, 0xe7, 0x20, 0xf7, 0xa9, 0xf8, 0x30,
- 0x08, 0x74, 0x6d, 0x89, 0x48, 0x11, 0xf0, 0x30,
- 0x01, 0xff, 0xf0, 0xe7, 0xf4, 0x95, 0x48, 0x08,
- 0x4e, 0xf8, 0x27, 0x74, 0x48, 0x08, 0xf1, 0xf9,
- 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0xe1,
- 0x27, 0x7c, 0x27, 0x7a, 0x60, 0xf8, 0x27, 0x7b,
- 0xff, 0xff, 0xf8, 0x30, 0x08, 0xab, 0x48, 0x08,
- 0x4e, 0xf8, 0x27, 0x72, 0x76, 0xf8, 0x27, 0x7b,
- 0xff, 0xff, 0x76, 0xf8, 0x27, 0x79, 0xff, 0xff,
- 0xf2, 0x73, 0x08, 0xd9, 0xf4, 0x95, 0xe8, 0x00,
- 0x44, 0xf8, 0x27, 0x73, 0x40, 0xf8, 0x27, 0x75,
- 0x82, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0x77, 0x10,
- 0x80, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x08, 0xd8,
- 0xf6, 0xb8, 0x10, 0xf8, 0x27, 0x73, 0xf0, 0x00,
- 0x80, 0x00, 0x48, 0x08, 0x4e, 0xf8, 0x27, 0x74,
- 0x48, 0x08, 0xf0, 0xf9, 0x88, 0x11, 0xf4, 0x95,
- 0xf4, 0x95, 0x71, 0xe1, 0x27, 0x7c, 0x27, 0x7a,
- 0xf7, 0xb8, 0x57, 0xf8, 0x27, 0x74, 0xf0, 0x62,
- 0xff, 0xff, 0xf0, 0x40, 0xff, 0x80, 0xf2, 0x80,
- 0x4e, 0xf8, 0x27, 0x74, 0xe8, 0x00, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 0xee, 0xfb,
- 0x11, 0xf8, 0x27, 0x71, 0x09, 0xf8, 0x27, 0x73,
- 0x89, 0x11, 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95,
- 0xf6, 0xa9, 0xf8, 0x20, 0x08, 0xed, 0xf2, 0x73,
- 0x09, 0x0e, 0xf4, 0x95, 0xe8, 0x00, 0xf6, 0x20,
- 0x76, 0x00, 0x00, 0x41, 0xf0, 0x74, 0x12, 0xee,
- 0x88, 0x16, 0xf4, 0x95, 0xf7, 0xb8, 0x6d, 0x96,
- 0x10, 0xf8, 0x00, 0x16, 0xf8, 0x47, 0x09, 0x0a,
- 0xe7, 0x61, 0x76, 0x00, 0x00, 0x00, 0x76, 0x01,
- 0x00, 0x80, 0x76, 0x02, 0x00, 0xff, 0x76, 0x03,
- 0x00, 0x00, 0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95,
- 0xe8, 0x00, 0x6c, 0xe9, 0xff, 0xff, 0x08, 0xfb,
- 0x73, 0x16, 0x00, 0x0e, 0xf0, 0x66, 0x00, 0x41,
- 0xee, 0x05, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x13,
- 0xf6, 0xb8, 0x77, 0x11, 0x7f, 0xff, 0x57, 0xf8,
- 0x27, 0x72, 0x48, 0x11, 0xf2, 0x80, 0xf0, 0x00,
- 0x80, 0x00, 0x88, 0x11, 0xf6, 0x40, 0xf0, 0xe0,
- 0xf1, 0xf1, 0xe8, 0x01, 0xf2, 0x80, 0x80, 0xf8,
- 0x27, 0x78, 0x77, 0x12, 0x80, 0x00, 0x57, 0xf8,
- 0x27, 0x72, 0x48, 0x12, 0xf2, 0x80, 0x88, 0x12,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x82, 0x09, 0x38,
- 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01,
- 0xf0, 0x73, 0x09, 0x3d, 0xf0, 0x20, 0x80, 0x01,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0x70, 0x81,
- 0x00, 0x13, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0xf0, 0x30, 0x7f, 0xff, 0x11, 0xf8, 0x29, 0x86,
- 0xf5, 0x20, 0xf3, 0x30, 0x7f, 0xff, 0x89, 0x11,
- 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9,
- 0xf8, 0x20, 0x09, 0x54, 0xf2, 0x73, 0x09, 0x67,
- 0xf4, 0x95, 0xe8, 0x02, 0x6f, 0xf8, 0x27, 0x7a,
- 0x0d, 0x20, 0xf3, 0x30, 0x7f, 0xff, 0x89, 0x11,
- 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9,
- 0xf8, 0x20, 0x09, 0x64, 0xf2, 0x73, 0x09, 0x67,
- 0xf4, 0x95, 0xe8, 0x01, 0x80, 0xf8, 0x27, 0x7b,
- 0xe8, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0x11, 0xf8, 0x29, 0x86, 0xf5, 0x20, 0xf3, 0x30,
- 0x7f, 0xff, 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10,
- 0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x09, 0x7a,
- 0xf2, 0x73, 0x09, 0x8d, 0xf4, 0x95, 0xe8, 0x02,
- 0x6f, 0xf8, 0x27, 0x7a, 0x0d, 0x20, 0xf3, 0x30,
- 0x7f, 0xff, 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10,
- 0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x09, 0x8a,
- 0xf2, 0x73, 0x09, 0x8d, 0xf4, 0x95, 0xe8, 0x01,
- 0x80, 0xf8, 0x27, 0x79, 0xe8, 0x00, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02,
- 0x00, 0x12, 0x88, 0x11, 0xf6, 0xb8, 0x57, 0xf8,
- 0x27, 0x72, 0xf0, 0x20, 0x7f, 0xff, 0xf2, 0x80,
- 0xf0, 0x00, 0x80, 0x00, 0x80, 0x81, 0x57, 0xf8,
- 0x27, 0x72, 0xe8, 0x01, 0xf3, 0xf1, 0xf2, 0x80,
- 0x80, 0xf8, 0x27, 0x78, 0x77, 0x11, 0x80, 0x00,
- 0x48, 0x11, 0x57, 0xf8, 0x27, 0x72, 0xf2, 0x80,
- 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81,
- 0x09, 0xb5, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08,
- 0x00, 0x01, 0xf0, 0x73, 0x09, 0xba, 0xf0, 0x20,
- 0x80, 0x01, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01,
- 0x45, 0xf8, 0x27, 0x71, 0x43, 0xf8, 0x27, 0x73,
- 0x83, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0xe7, 0x20,
- 0xf6, 0xa9, 0xf8, 0x30, 0x09, 0xc9, 0xf2, 0x73,
- 0x09, 0xe4, 0x77, 0x12, 0x00, 0x00, 0x57, 0xf8,
- 0x27, 0x72, 0xf0, 0x20, 0x7f, 0xff, 0xf2, 0x80,
- 0x49, 0x12, 0xf5, 0x00, 0xf3, 0x00, 0x80, 0x00,
- 0x61, 0xf8, 0x00, 0x0b, 0x80, 0x00, 0xf8, 0x30,
- 0x09, 0xdc, 0xf1, 0x20, 0x80, 0x00, 0xf5, 0x20,
- 0x89, 0x12, 0xf4, 0x95, 0x48, 0x12, 0x6f, 0xf8,
- 0x27, 0x73, 0x0d, 0x00, 0xf4, 0x95, 0x49, 0x0b,
- 0x4f, 0xf8, 0x27, 0x72, 0x8a, 0x11, 0xfe, 0x00,
- 0x48, 0x12, 0xf4, 0x95, 0x4a, 0x11, 0x4a, 0x16,
- 0x4a, 0x17, 0xee, 0xfc, 0xf4, 0x95, 0x71, 0x08,
- 0x00, 0x16, 0x88, 0x17, 0xf0, 0x74, 0x08, 0x30,
- 0x48, 0x18, 0x70, 0x00, 0x00, 0x16, 0xf2, 0x74,
- 0x09, 0x8f, 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 0x0a, 0x0a,
- 0xf2, 0x74, 0x08, 0xdb, 0xf4, 0x95, 0x48, 0x16,
- 0x48, 0x18, 0x70, 0x00, 0x00, 0x16, 0xf2, 0x74,
- 0x09, 0x8f, 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11,
- 0x10, 0x02, 0x70, 0x01, 0x00, 0x11, 0x80, 0x00,
- 0xf2, 0x74, 0x06, 0xce, 0xf4, 0x95, 0x48, 0x17,
- 0x49, 0x11, 0x48, 0x17, 0xf6, 0x00, 0x88, 0x17,
- 0xe7, 0x60, 0xf5, 0xa9, 0xf8, 0x20, 0x0a, 0x2d,
- 0x48, 0x16, 0xf6, 0x20, 0x88, 0x11, 0x48, 0x18,
- 0x70, 0x00, 0x00, 0x11, 0xf2, 0x74, 0x09, 0x8f,
- 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11, 0x70, 0x01,
- 0x00, 0x11, 0x10, 0x02, 0x80, 0x00, 0xf2, 0x74,
- 0x06, 0xce, 0xf4, 0x95, 0x48, 0x17, 0xee, 0x04,
- 0x48, 0x16, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11,
- 0xfc, 0x00, 0xee, 0xfd, 0xe8, 0x00, 0x4e, 0xf8,
- 0x27, 0x70, 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x72,
- 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x74, 0xe8, 0x00,
- 0x4e, 0xf8, 0x27, 0x76, 0x76, 0xf8, 0x27, 0x79,
- 0xff, 0xff, 0x76, 0xf8, 0x27, 0x7a, 0x00, 0x00,
- 0x76, 0xf8, 0x27, 0x7b, 0xff, 0xff, 0x76, 0xf8,
- 0x27, 0x78, 0x00, 0x00, 0xe8, 0x00, 0x75, 0xf8,
- 0x00, 0x08, 0x00, 0x01, 0x76, 0x00, 0x00, 0x00,
- 0x76, 0x01, 0x02, 0x00, 0xf2, 0x74, 0x12, 0xdc,
- 0xf0, 0x20, 0x27, 0x7c, 0xee, 0x03, 0xfc, 0x00,
- 0x4a, 0x11, 0xee, 0xfc, 0xf4, 0x95, 0x4e, 0x00,
- 0x77, 0x12, 0x7f, 0xff, 0xf6, 0xb8, 0x49, 0x12,
- 0xf1, 0x80, 0xf3, 0x00, 0x80, 0x00, 0x89, 0x12,
- 0xf0, 0xe0, 0xf1, 0xf1, 0x4f, 0x02, 0xe9, 0x01,
- 0xf4, 0x95, 0x48, 0x0b, 0xf5, 0x40, 0x56, 0x02,
- 0xf1, 0x80, 0x81, 0xf8, 0x27, 0x78, 0x77, 0x11,
- 0x80, 0x00, 0x56, 0x00, 0x49, 0x11, 0xf1, 0x80,
- 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81,
- 0x0a, 0x81, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08,
- 0x00, 0x01, 0xf0, 0x73, 0x0a, 0x86, 0xf0, 0x20,
- 0x80, 0x01, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01,
- 0x10, 0x82, 0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0xee, 0xfe, 0xf4, 0x95, 0x4e, 0x00,
- 0x77, 0x11, 0x7f, 0xff, 0xf6, 0xb8, 0x49, 0x11,
- 0xf1, 0x80, 0xf3, 0x00, 0x80, 0x00, 0x89, 0x11,
- 0xf0, 0xe0, 0xf1, 0xf1, 0xe8, 0x01, 0xf2, 0x80,
- 0x80, 0xf8, 0x27, 0x78, 0x56, 0x00, 0xf1, 0x20,
- 0x80, 0x00, 0xf1, 0x80, 0xf4, 0x95, 0x49, 0x0b,
- 0xf8, 0x4d, 0x0a, 0xab, 0xf0, 0x20, 0x80, 0x01,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0xf0, 0x73,
- 0x0a, 0xaf, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08,
- 0x00, 0x01, 0xee, 0x02, 0x48, 0x11, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x12, 0x13, 0x02,
- 0x77, 0x11, 0x00, 0x00, 0xf8, 0x4d, 0x0a, 0xcb,
- 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a, 0xf4, 0x95,
- 0xf0, 0x72, 0x0a, 0xca, 0x48, 0x11, 0x1c, 0xf8,
- 0x29, 0x7e, 0x88, 0x11, 0x11, 0xf8, 0x29, 0x7e,
- 0xf2, 0x00, 0x00, 0x01, 0x80, 0xf8, 0x29, 0x7e,
- 0x81, 0x92, 0x48, 0x11, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x11,
- 0x88, 0x12, 0xf6, 0xb8, 0xf0, 0x20, 0x7f, 0xff,
- 0x57, 0xf8, 0x27, 0x70, 0xf2, 0x80, 0xf0, 0x00,
- 0x80, 0x00, 0x80, 0x82, 0x57, 0xf8, 0x27, 0x70,
- 0xe8, 0x01, 0xf3, 0xf1, 0xf2, 0x80, 0x80, 0xf8,
- 0x27, 0x78, 0x77, 0x12, 0x80, 0x00, 0x48, 0x12,
- 0x57, 0xf8, 0x27, 0x70, 0xf2, 0x80, 0x88, 0x12,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x82, 0x0a, 0xf4,
- 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01,
- 0xf0, 0x73, 0x0a, 0xf9, 0xf0, 0x20, 0x80, 0x01,
- 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0x45, 0xf8,
- 0x27, 0x75, 0xe7, 0x10, 0x43, 0xf8, 0x27, 0x71,
- 0x83, 0xf8, 0x00, 0x12, 0x6d, 0xe8, 0x00, 0x04,
- 0x6d, 0x8a, 0xf6, 0xaa, 0xf8, 0x30, 0x0b, 0x0a,
- 0xf2, 0x73, 0x0b, 0x25, 0x77, 0x11, 0x00, 0x00,
- 0x57, 0xf8, 0x27, 0x70, 0xf0, 0x20, 0x7f, 0xff,
- 0xf2, 0x80, 0x49, 0x11, 0xf5, 0x00, 0xf3, 0x00,
- 0x80, 0x00, 0x61, 0xf8, 0x00, 0x0b, 0x80, 0x00,
- 0xf8, 0x30, 0x0b, 0x1d, 0xf1, 0x20, 0x80, 0x00,
- 0xf5, 0x20, 0x89, 0x11, 0xf4, 0x95, 0x48, 0x11,
- 0x6f, 0xf8, 0x27, 0x71, 0x0d, 0x00, 0xf4, 0x95,
- 0x49, 0x0b, 0x4f, 0xf8, 0x27, 0x70, 0x48, 0x11,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16,
- 0x4a, 0x17, 0xee, 0xf0, 0x88, 0x17, 0x10, 0x17,
- 0x80, 0x05, 0x10, 0x16, 0x80, 0x06, 0x10, 0x15,
- 0x80, 0x07, 0x71, 0x14, 0x00, 0x11, 0x10, 0x05,
- 0xf0, 0x30, 0x00, 0x01, 0x88, 0x10, 0x10, 0x06,
- 0xf0, 0x30, 0x00, 0x01, 0x80, 0x08, 0x49, 0x11,
- 0x10, 0x05, 0xf6, 0x01, 0x80, 0x09, 0x10, 0x06,
- 0x61, 0xf8, 0x00, 0x08, 0x00, 0x01, 0xf8, 0x20,
- 0x0b, 0x4b, 0x10, 0x09, 0xf0, 0x00, 0x00, 0x01,
- 0x80, 0x09, 0x71, 0x08, 0x00, 0x12, 0xf4, 0xaa,
- 0xf8, 0x30, 0x0b, 0x54, 0x10, 0x09, 0xf0, 0x00,
- 0x00, 0x01, 0x80, 0x09, 0x12, 0x09, 0x49, 0x11,
- 0xf4, 0x7f, 0x80, 0x09, 0xf6, 0x20, 0x80, 0x0a,
- 0x56, 0xf8, 0x27, 0x70, 0x4e, 0x0c, 0x10, 0x09,
- 0x80, 0x00, 0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce,
- 0xf0, 0x00, 0x00, 0x04, 0x88, 0x16, 0xf4, 0x95,
- 0xf4, 0x95, 0x6c, 0x86, 0x0b, 0x6d, 0xf2, 0x73,
- 0x0c, 0x59, 0xf4, 0x95, 0xe8, 0x00, 0xf6, 0xb8,
- 0xf4, 0x95, 0x56, 0x0c, 0xf0, 0xf9, 0x88, 0x12,
- 0xf4, 0x95, 0xf4, 0x95, 0x70, 0xe2, 0x27, 0x7c,
- 0x29, 0x86, 0xe8, 0x00, 0x80, 0x0e, 0x48, 0x11,
- 0xf8, 0x45, 0x0b, 0xcc, 0x77, 0x10, 0x00, 0x01,
- 0xf4, 0xa9, 0xf8, 0x30, 0x0b, 0x89, 0x6c, 0xe1,
- 0xff, 0xfd, 0x0b, 0x8b, 0x10, 0xe7, 0x00, 0x02,
- 0x80, 0x0e, 0xf0, 0x73, 0x0b, 0x8b, 0x10, 0x87,
- 0x80, 0x0e, 0xe7, 0x10, 0xf5, 0xae, 0xf8, 0x20,
- 0x0b, 0xb2, 0x70, 0x00, 0x00, 0x17, 0x70, 0x01,
- 0x00, 0x16, 0x10, 0x04, 0xf0, 0x74, 0x06, 0xce,
- 0x48, 0x17, 0x49, 0x16, 0xf6, 0x00, 0x88, 0x17,
- 0x48, 0x11, 0xf6, 0x20, 0x88, 0x11, 0x10, 0x09,
- 0xf6, 0x20, 0x80, 0x00, 0x48, 0x18, 0xf2, 0x74,
- 0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x16,
- 0x10, 0x04, 0x70, 0x00, 0x00, 0x17, 0x70, 0x01,
- 0x00, 0x11, 0xf0, 0x74, 0x06, 0xce, 0x48, 0x11,
- 0x00, 0x04, 0x80, 0x04, 0xf0, 0x73, 0x0b, 0xbc,
- 0x70, 0x00, 0x00, 0x17, 0x70, 0x01, 0x00, 0x11,
- 0x10, 0x04, 0xf0, 0x74, 0x06, 0xce, 0x48, 0x11,
- 0x00, 0x04, 0x80, 0x04, 0x49, 0x11, 0x48, 0x16,
- 0xf6, 0x20, 0x88, 0x16, 0xf4, 0x95, 0xf4, 0x95,
- 0x6c, 0x86, 0x0b, 0xcc, 0x10, 0x0a, 0x80, 0x00,
- 0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00,
- 0x00, 0x04, 0x88, 0x16, 0x12, 0x0a, 0xf8, 0x45,
- 0x0c, 0x33, 0x71, 0x0a, 0x00, 0x10, 0xf4, 0xae,
- 0xf8, 0x30, 0x0c, 0x1c, 0x48, 0x16, 0xf0, 0xe1,
- 0x88, 0x11, 0x12, 0x08, 0xf8, 0x45, 0x0b, 0xdb,
- 0x6d, 0x89, 0x12, 0x07, 0xf8, 0x45, 0x0b, 0xe9,
- 0x10, 0x07, 0x80, 0x00, 0x70, 0x02, 0x00, 0x11,
- 0x10, 0x06, 0x80, 0x01, 0x10, 0x04, 0xf0, 0x74,
- 0x06, 0xdc, 0xf0, 0x73, 0x0b, 0xef, 0x48, 0x11,
- 0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, 0xf0, 0x74,
- 0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, 0x81, 0x0e,
- 0x10, 0x06, 0x49, 0x11, 0xf6, 0x00, 0x80, 0x06,
- 0x10, 0x05, 0xf6, 0x20, 0x88, 0x11, 0xf0, 0x00,
- 0x00, 0x01, 0x48, 0x08, 0x6f, 0x00, 0x0c, 0x9f,
- 0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00,
- 0x00, 0x04, 0x12, 0x07, 0xf8, 0x45, 0x0c, 0x11,
- 0x10, 0x07, 0x80, 0x00, 0x70, 0x02, 0x00, 0x11,
- 0x10, 0x06, 0x80, 0x01, 0x10, 0x04, 0xf0, 0x74,
- 0x06, 0xdc, 0xf0, 0x73, 0x0c, 0x17, 0x48, 0x11,
- 0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, 0xf0, 0x74,
- 0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, 0x81, 0x0e,
- 0xf0, 0x73, 0x0c, 0x33, 0x12, 0x07, 0xf8, 0x45,
- 0x0c, 0x2a, 0x10, 0x07, 0x80, 0x00, 0x10, 0x06,
- 0x80, 0x01, 0x10, 0x05, 0x80, 0x02, 0x10, 0x04,
- 0xf0, 0x74, 0x06, 0xdc, 0xf0, 0x73, 0x0c, 0x30,
- 0x12, 0x05, 0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04,
- 0xf0, 0x74, 0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0,
- 0x81, 0x0e, 0x76, 0x00, 0x00, 0x01, 0x48, 0x18,
- 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04,
- 0x71, 0x04, 0x00, 0x11, 0x70, 0x81, 0x29, 0x86,
- 0x10, 0x0e, 0x1c, 0xf8, 0x29, 0x86, 0x80, 0x0e,
- 0x76, 0x00, 0x00, 0x01, 0x48, 0x18, 0xf2, 0x74,
- 0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, 0x10, 0x0e,
- 0x71, 0x04, 0x00, 0x11, 0x80, 0x81, 0x10, 0xf8,
- 0x29, 0x86, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x30,
- 0x7f, 0xff, 0x80, 0xf8, 0x29, 0x86, 0x10, 0x09,
- 0xf0, 0x00, 0x00, 0x02, 0x80, 0x09, 0xee, 0x10,
- 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00,
- 0x10, 0xf8, 0x27, 0x75, 0x08, 0xf8, 0x27, 0x71,
- 0xf0, 0x10, 0x00, 0x01, 0x48, 0x08, 0xfc, 0x00,
- 0x4a, 0x11, 0x4a, 0x16, 0xee, 0xff, 0xf4, 0x95,
- 0x71, 0x04, 0x00, 0x16, 0xf0, 0x00, 0x00, 0x01,
- 0x48, 0x08, 0x4e, 0xf8, 0x29, 0x7c, 0x6d, 0xee,
- 0xff, 0xfd, 0x48, 0x16, 0xf8, 0x45, 0x0c, 0x99,
- 0x56, 0xf8, 0x29, 0x7c, 0xf0, 0x74, 0x0a, 0x5a,
- 0x88, 0x11, 0x10, 0xf8, 0x29, 0x7d, 0xf0, 0x00,
- 0x00, 0x01, 0x48, 0x08, 0x4e, 0xf8, 0x29, 0x7c,
- 0x10, 0xf8, 0x29, 0x82, 0xf0, 0x00, 0x00, 0x01,
- 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xa9,
- 0xfa, 0x30, 0x0c, 0x96, 0x80, 0xf8, 0x29, 0x82,
- 0x56, 0xf8, 0x29, 0x80, 0xf0, 0x00, 0x00, 0x01,
- 0x4e, 0xf8, 0x29, 0x80, 0x73, 0x11, 0x29, 0x82,
- 0x6c, 0xee, 0xff, 0xff, 0x0c, 0x76, 0xee, 0x01,
- 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0x76, 0xf8, 0x29, 0x84, 0x00, 0x00, 0x76, 0xf8,
- 0x29, 0x85, 0x00, 0x01, 0xe8, 0x00, 0x4e, 0xf8,
- 0x2a, 0x0c, 0x76, 0xf8, 0x29, 0x86, 0x00, 0x00,
- 0x76, 0xf8, 0x29, 0x87, 0x00, 0x00, 0x77, 0x11,
- 0x29, 0x88, 0x76, 0x81, 0xaa, 0xaa, 0x76, 0xe1,
- 0x00, 0x01, 0xaa, 0xaa, 0x76, 0xe1, 0x00, 0x02,
- 0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0xee, 0xfc, 0xf4, 0x95, 0x71, 0x06, 0x00, 0x14,
- 0x71, 0x07, 0x00, 0x13, 0x71, 0x08, 0x00, 0x12,
- 0x71, 0x09, 0x00, 0x15, 0x77, 0x10, 0x00, 0xff,
- 0xf4, 0xaa, 0xf8, 0x30, 0x0d, 0x44, 0x49, 0x13,
- 0x53, 0xf8, 0x2a, 0x0c, 0x4f, 0xf8, 0x2a, 0x0c,
- 0x73, 0x12, 0x00, 0x0e, 0xf1, 0x66, 0x00, 0x0d,
- 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x01,
- 0x71, 0xe1, 0x24, 0x00, 0x00, 0x11, 0xf4, 0xa9,
- 0xf8, 0x30, 0x0d, 0x17, 0x77, 0x10, 0x00, 0x02,
- 0xf4, 0xa9, 0xf8, 0x30, 0x0c, 0xec, 0x77, 0x11,
- 0x29, 0x8a, 0x76, 0x81, 0x00, 0x00, 0xe8, 0x00,
- 0x77, 0x14, 0x00, 0x00, 0x77, 0x13, 0x00, 0x00,
- 0xf0, 0x73, 0x0d, 0x48, 0x6c, 0x83, 0x0c, 0xfa,
- 0x77, 0x11, 0x29, 0x8a, 0x48, 0x12, 0xf0, 0xe8,
- 0xf0, 0x40, 0x80, 0x00, 0x80, 0x81, 0xe8, 0x00,
- 0x77, 0x14, 0x00, 0x00, 0xf0, 0x73, 0x0d, 0x48,
- 0x49, 0x13, 0xf3, 0x40, 0x80, 0x00, 0x81, 0xf8,
- 0x29, 0x8a, 0x61, 0xf8, 0x00, 0x15, 0x00, 0x01,
- 0xf8, 0x20, 0x0d, 0x07, 0x69, 0xf8, 0x29, 0x8a,
- 0x40, 0x00, 0x61, 0xf8, 0x00, 0x14, 0x00, 0x01,
- 0xf8, 0x20, 0x0d, 0x0f, 0x69, 0xf8, 0x29, 0x8a,
- 0x20, 0x00, 0x77, 0x11, 0x29, 0x8a, 0x49, 0x12,
- 0xf3, 0xe8, 0x1b, 0x81, 0x81, 0x81, 0xf0, 0x73,
- 0x0d, 0x48, 0x11, 0xf8, 0x29, 0x84, 0xf8, 0x4c,
- 0x0d, 0x37, 0x77, 0x11, 0x29, 0x88, 0x76, 0x81,
- 0xaa, 0xaa, 0x11, 0xf8, 0x29, 0x85, 0xf3, 0x10,
- 0x00, 0x01, 0xf3, 0x40, 0xaa, 0x00, 0x81, 0xe1,
- 0x00, 0x01, 0x76, 0x00, 0x00, 0x02, 0x80, 0x01,
- 0x70, 0x02, 0x00, 0x14, 0x70, 0x03, 0x00, 0x13,
- 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 0x48, 0x11,
- 0x71, 0xf8, 0x29, 0x85, 0x29, 0x84, 0xf0, 0x73,
- 0x0d, 0x73, 0x76, 0x00, 0x00, 0x00, 0x80, 0x01,
- 0x76, 0x02, 0x00, 0x00, 0x70, 0x03, 0x00, 0x13,
- 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 0xe8, 0x00,
- 0xf0, 0x73, 0x0d, 0x73, 0x77, 0x11, 0x29, 0x8a,
- 0x70, 0x81, 0x00, 0x13, 0x11, 0xf8, 0x29, 0x84,
- 0xf8, 0x4c, 0x0d, 0x68, 0x77, 0x11, 0x29, 0x88,
- 0x76, 0x81, 0xaa, 0xaa, 0x11, 0xf8, 0x29, 0x85,
- 0xf3, 0x10, 0x00, 0x01, 0xf3, 0x40, 0xaa, 0x00,
- 0x81, 0xe1, 0x00, 0x01, 0x76, 0x00, 0x00, 0x03,
- 0x80, 0x01, 0x70, 0x02, 0x00, 0x14, 0x70, 0x03,
- 0x00, 0x13, 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95,
- 0x48, 0x11, 0x71, 0xf8, 0x29, 0x85, 0x29, 0x84,
- 0xf0, 0x73, 0x0d, 0x73, 0x76, 0x00, 0x00, 0x01,
- 0x80, 0x01, 0x70, 0x02, 0x00, 0x14, 0x70, 0x03,
- 0x00, 0x13, 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95,
- 0x48, 0x11, 0x6b, 0xf8, 0x29, 0x84, 0xff, 0xff,
- 0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0xf5, 0x40, 0xf4, 0x95, 0x48, 0x0b, 0xf4, 0x78,
- 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0xe1,
- 0xff, 0xb9, 0x0d, 0x88, 0xf2, 0x73, 0x0d, 0xa5,
- 0xf4, 0x95, 0xe8, 0x60, 0xf2, 0x00, 0x00, 0x06,
- 0x61, 0xf8, 0x00, 0x11, 0x00, 0x20, 0xf8, 0x30,
- 0x0d, 0x98, 0x61, 0xf8, 0x00, 0x0b, 0x00, 0x01,
- 0xf8, 0x20, 0x0d, 0xa3, 0xf2, 0x00, 0x00, 0x07,
- 0xf0, 0x73, 0x0d, 0xa3, 0x61, 0xf8, 0x00, 0x0b,
- 0x00, 0x01, 0xf8, 0x20, 0x0d, 0xa1, 0xf2, 0x73,
- 0x0d, 0xa3, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x00,
- 0x00, 0x02, 0x48, 0x08, 0xf4, 0x7f, 0x8a, 0x11,
- 0xfc, 0x00, 0xee, 0xff, 0xf0, 0x74, 0x07, 0xfd,
- 0xf0, 0x74, 0x07, 0x44, 0xf0, 0x74, 0x0d, 0xb4,
- 0xf0, 0x74, 0x02, 0x05, 0xf0, 0x74, 0x04, 0x60,
- 0xf0, 0x73, 0x0d, 0xaa, 0xee, 0xfd, 0x10, 0xf8,
- 0x2a, 0xa3, 0xf8, 0x44, 0x0d, 0xcb, 0x10, 0xf8,
- 0x2a, 0xa4, 0xf8, 0x45, 0x0d, 0xd7, 0x76, 0x00,
- 0x02, 0x00, 0xf2, 0x74, 0x09, 0xe8, 0xf0, 0x20,
- 0x22, 0x00, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x00,
- 0x76, 0xf8, 0x2a, 0xa7, 0x00, 0x00, 0xf0, 0x73,
- 0x0d, 0xd7, 0x76, 0x00, 0x02, 0x00, 0xf2, 0x74,
- 0x09, 0xe8, 0xf0, 0x20, 0x20, 0x00, 0x76, 0xf8,
- 0x2a, 0xa3, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa7,
- 0x00, 0x01, 0xf0, 0x74, 0x0c, 0x5e, 0xf0, 0xe0,
- 0xf0, 0x10, 0x3a, 0x98, 0xf8, 0x47, 0x0d, 0xe1,
- 0x76, 0xf8, 0x27, 0x6e, 0x00, 0x00, 0xee, 0x03,
- 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 0x77, 0x11,
- 0x20, 0x00, 0x76, 0x00, 0xaa, 0xaa, 0x76, 0x01,
- 0x02, 0x00, 0xf2, 0x74, 0x06, 0x6c, 0xf4, 0x95,
- 0x48, 0x11, 0x76, 0x00, 0x55, 0x55, 0x76, 0x01,
- 0x02, 0x00, 0x48, 0x11, 0xf2, 0x74, 0x06, 0x6c,
- 0xf0, 0x00, 0x02, 0x00, 0x76, 0xf8, 0x2a, 0xa3,
- 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x00,
- 0xe8, 0x00, 0x4e, 0x00, 0xfb, 0x80, 0x15, 0x3e,
- 0xf4, 0x95, 0xe8, 0x04, 0x80, 0xf8, 0x2a, 0xa5,
- 0x76, 0x00, 0x2a, 0xa8, 0xf9, 0x80, 0x14, 0x87,
- 0x76, 0x00, 0x2a, 0xad, 0xfb, 0x80, 0x13, 0x62,
- 0xf4, 0x95, 0xe8, 0x02, 0x10, 0xf8, 0x2a, 0xa5,
- 0xf9, 0x80, 0x14, 0x63, 0xfb, 0x80, 0x16, 0x66,
- 0xf4, 0x95, 0xe8, 0x1c, 0xfb, 0x80, 0x16, 0x87,
- 0xf4, 0x95, 0xe8, 0x1c, 0xe8, 0x01, 0x4e, 0x00,
- 0xfb, 0x80, 0x17, 0xd6, 0xf4, 0x95, 0xe8, 0x00,
- 0x80, 0xf8, 0x2a, 0xa6, 0x76, 0x00, 0x2a, 0xb7,
- 0xf9, 0x80, 0x16, 0xaa, 0x10, 0xf8, 0x2a, 0xa6,
- 0xf9, 0x80, 0x17, 0x5c, 0x10, 0xf8, 0x2a, 0xa6,
- 0xf9, 0x80, 0x17, 0x6f, 0xee, 0x02, 0x8a, 0x11,
- 0xfc, 0x00, 0xf4, 0x95, 0x4a, 0x08, 0x4a, 0x09,
- 0x4a, 0x0a, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8,
- 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07,
- 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc,
- 0x10, 0xf8, 0x2a, 0xa7, 0xf8, 0x44, 0x0e, 0x4b,
- 0x76, 0xf8, 0x2a, 0xa3, 0x00, 0x01, 0xf0, 0x73,
- 0x0e, 0x4e, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x01,
- 0x8a, 0x1d, 0x8a, 0x07, 0x8a, 0x0a, 0x8a, 0x09,
- 0x8a, 0x08, 0xf4, 0xeb, 0x4a, 0x11, 0x4a, 0x16,
- 0x4a, 0x17, 0xee, 0xfe, 0x88, 0x0e, 0x71, 0x08,
- 0x00, 0x16, 0x71, 0x06, 0x00, 0x17, 0x11, 0x07,
- 0xf0, 0x66, 0x00, 0x0d, 0xf0, 0x00, 0x25, 0xa0,
- 0x88, 0x11, 0x76, 0x01, 0x00, 0x06, 0x81, 0x00,
- 0xf2, 0x74, 0x06, 0xce, 0xf0, 0x00, 0x00, 0x01,
- 0x76, 0x01, 0x00, 0x06, 0x70, 0x00, 0x00, 0x16,
- 0x48, 0x11, 0xf2, 0x74, 0x06, 0xce, 0xf0, 0x00,
- 0x00, 0x07, 0x70, 0x81, 0x00, 0x17, 0xee, 0x02,
- 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00,
- 0x4a, 0x11, 0x88, 0x0e, 0x71, 0x02, 0x00, 0x12,
- 0x11, 0x03, 0xf0, 0x66, 0x00, 0x0d, 0xf0, 0x00,
- 0x24, 0x00, 0x88, 0x11, 0xf4, 0x95, 0x70, 0x81,
- 0x00, 0x12, 0x6e, 0xe2, 0xff, 0xfe, 0x0e, 0x8d,
- 0xf4, 0x95, 0xe8, 0x00, 0xe8, 0x01, 0x80, 0xe1,
- 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff,
- 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1,
- 0x00, 0x0b, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0c,
- 0x00, 0x00, 0x81, 0xe1, 0x00, 0x01, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfc, 0x88, 0x0e,
- 0xf4, 0x95, 0xf1, 0x66, 0x00, 0x0d, 0xf3, 0x00,
- 0x24, 0x00, 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95,
- 0x76, 0xe1, 0x00, 0x0c, 0x00, 0x00, 0x76, 0xe1,
- 0x00, 0x0b, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02,
- 0x00, 0x01, 0x76, 0x00, 0x00, 0x00, 0x76, 0x01,
- 0x00, 0x00, 0x80, 0x02, 0x76, 0x03, 0x00, 0x00,
- 0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, 0xe8, 0x00,
- 0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0x88, 0x19, 0xf4, 0x95, 0x73, 0x19, 0x00, 0x0e,
- 0xf1, 0x66, 0x00, 0x0d, 0xf2, 0x00, 0x24, 0x00,
- 0x77, 0x15, 0x25, 0xa0, 0x77, 0x14, 0x00, 0x00,
- 0x77, 0x1a, 0x00, 0x1f, 0xf0, 0x72, 0x0f, 0x14,
- 0xf6, 0xb8, 0x49, 0x19, 0x09, 0x85, 0xf8, 0x4c,
- 0x0f, 0x13, 0xf1, 0x00, 0x00, 0x05, 0x89, 0x11,
- 0x49, 0x15, 0xf3, 0x00, 0x00, 0x01, 0x89, 0x13,
- 0x49, 0x15, 0xf3, 0x00, 0x00, 0x07, 0x89, 0x12,
- 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13,
- 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13,
- 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13,
- 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13,
- 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13,
- 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x11,
- 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 0x0f, 0x13,
- 0x6d, 0x94, 0x6d, 0xed, 0x00, 0x0d, 0x48, 0x14,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16,
- 0x4a, 0x17, 0xee, 0xf8, 0x88, 0x17, 0x10, 0x0d,
- 0x80, 0x04, 0x10, 0x0c, 0x80, 0x05, 0x71, 0x0e,
- 0x00, 0x16, 0x73, 0x17, 0x00, 0x0e, 0xf0, 0x66,
- 0x00, 0x0d, 0xf0, 0x00, 0x24, 0x00, 0x88, 0x11,
- 0x10, 0xf8, 0x27, 0x63, 0xf8, 0x45, 0x0f, 0x32,
- 0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17,
- 0x10, 0xf8, 0x27, 0x60, 0xf8, 0x44, 0x0f, 0x3d,
- 0x60, 0xe1, 0x00, 0x02, 0x00, 0x01, 0xf8, 0x20,
- 0x0f, 0x6d, 0xf0, 0x73, 0x11, 0x33, 0x10, 0x04,
- 0x80, 0x00, 0x10, 0x05, 0xf0, 0x74, 0x06, 0x9f,
- 0x11, 0x04, 0xf3, 0x00, 0x00, 0x01, 0x81, 0x04,
- 0x6d, 0x8e, 0x77, 0x10, 0x00, 0x01, 0x71, 0xe1,
- 0x00, 0x02, 0x00, 0x12, 0xf4, 0xaa, 0xf8, 0x30,
- 0x0f, 0x62, 0x77, 0x10, 0x00, 0x02, 0xf4, 0xaa,
- 0xf8, 0x30, 0x0f, 0x6d, 0x45, 0xe1, 0x00, 0x0b,
- 0x88, 0x10, 0x43, 0xe1, 0x00, 0x0c, 0x83, 0xf8,
- 0x00, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xaa,
- 0xf8, 0x30, 0x0f, 0x6d, 0xf0, 0x73, 0x0f, 0x96,
- 0xf5, 0x00, 0x81, 0x04, 0x49, 0x16, 0xf5, 0x20,
- 0x89, 0x16, 0x76, 0xe1, 0x00, 0x0c, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x48, 0x16,
- 0xf8, 0x45, 0x11, 0x33, 0xf7, 0xb8, 0x71, 0xe1,
- 0x00, 0x02, 0x00, 0x12, 0x10, 0xf8, 0x00, 0x12,
- 0xf0, 0x10, 0x00, 0x03, 0xf8, 0x46, 0x0f, 0x8c,
- 0x10, 0xf8, 0x00, 0x12, 0xf0, 0x10, 0x00, 0x03,
- 0xf8, 0x45, 0x10, 0x16, 0x77, 0x10, 0x00, 0x01,
- 0xf4, 0xaa, 0xf8, 0x30, 0x0f, 0x9c, 0x77, 0x10,
- 0x00, 0x02, 0xf4, 0xaa, 0xf8, 0x30, 0x0f, 0xa8,
- 0xf0, 0x73, 0x0f, 0x96, 0x77, 0x10, 0x00, 0x04,
- 0xf4, 0xaa, 0xf8, 0x30, 0x10, 0xb7, 0x77, 0x10,
- 0x00, 0x05, 0xf4, 0xaa, 0xf8, 0x30, 0x10, 0xbc,
- 0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17,
- 0xf0, 0x73, 0x11, 0x31, 0x76, 0xe1, 0x00, 0x0c,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1,
- 0x00, 0x02, 0x00, 0x02, 0x11, 0xe1, 0x00, 0x0c,
- 0xe8, 0x03, 0xf6, 0x20, 0x89, 0x12, 0xf4, 0x95,
- 0x77, 0x10, 0x00, 0x03, 0xf5, 0xaa, 0xf8, 0x30,
- 0x0f, 0xb6, 0x6b, 0xf8, 0x27, 0x6f, 0x00, 0x01,
- 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 0xf5, 0xae,
- 0xf8, 0x20, 0x0f, 0xbd, 0x48, 0x16, 0x80, 0x06,
- 0x88, 0x13, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x03,
- 0xf6, 0xab, 0xf8, 0x20, 0x0f, 0xc8, 0x6b, 0xf8,
- 0x27, 0x6f, 0x00, 0x01, 0x12, 0x06, 0xf8, 0x45,
- 0x10, 0x00, 0x10, 0xe1, 0x00, 0x04, 0x80, 0x00,
- 0x10, 0x05, 0x80, 0x01, 0x10, 0x04, 0x80, 0x02,
- 0x10, 0x06, 0x80, 0x03, 0x48, 0x11, 0xf2, 0x74,
- 0x07, 0x1e, 0xf0, 0x00, 0x00, 0x05, 0x10, 0x06,
- 0x00, 0xe1, 0x00, 0x04, 0x80, 0xe1, 0x00, 0x04,
- 0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1,
- 0x00, 0x0c, 0x88, 0x12, 0x11, 0x06, 0x10, 0x04,
- 0xf6, 0x00, 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20,
- 0x88, 0x16, 0x89, 0x13, 0xf4, 0x95, 0x77, 0x10,
- 0x00, 0x03, 0xf6, 0xab, 0xf8, 0x20, 0x0f, 0xf5,
- 0x6b, 0xf8, 0x27, 0x6f, 0x00, 0x01, 0x77, 0x10,
- 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x13,
- 0xf6, 0xab, 0xf8, 0x20, 0x10, 0x00, 0x6b, 0xf8,
- 0x27, 0x6f, 0x00, 0x01, 0x6c, 0xe2, 0xff, 0xfd,
- 0x11, 0x31, 0xf6, 0xb8, 0x6f, 0xe1, 0x00, 0x05,
- 0x0c, 0x48, 0x6f, 0xe1, 0x00, 0x06, 0x0c, 0x18,
- 0xf0, 0x30, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03,
- 0x80, 0xe1, 0x00, 0x0b, 0x76, 0xe1, 0x00, 0x02,
- 0x00, 0x03, 0x48, 0x16, 0xf8, 0x45, 0x11, 0x33,
- 0x71, 0xe1, 0x00, 0x0c, 0x00, 0x12, 0x10, 0xe1,
- 0x00, 0x0b, 0x49, 0x12, 0xf6, 0x20, 0x88, 0x13,
- 0xe8, 0x0c, 0xf6, 0x20, 0x88, 0x10, 0xf4, 0x95,
- 0xf4, 0x95, 0xf5, 0xab, 0xf8, 0x20, 0x10, 0x27,
- 0x48, 0x13, 0x80, 0x06, 0x88, 0x10, 0xf4, 0x95,
- 0xf4, 0x95, 0xf5, 0xae, 0xf8, 0x20, 0x10, 0x30,
- 0x70, 0x06, 0x00, 0x16, 0x12, 0x06, 0xf8, 0x45,
- 0x10, 0x5f, 0x10, 0xe1, 0x00, 0x04, 0x80, 0x00,
- 0x10, 0x05, 0x80, 0x01, 0x10, 0x04, 0x80, 0x02,
- 0x10, 0x06, 0x80, 0x03, 0x48, 0x11, 0xf2, 0x74,
- 0x07, 0x1e, 0xf0, 0x00, 0x00, 0x05, 0x10, 0x06,
- 0x00, 0xe1, 0x00, 0x04, 0x80, 0xe1, 0x00, 0x04,
- 0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1,
- 0x00, 0x0c, 0x88, 0x12, 0x11, 0x06, 0x10, 0x04,
- 0xf6, 0x00, 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20,
- 0x88, 0x16, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x0c,
- 0x71, 0xe1, 0x00, 0x04, 0x00, 0x13, 0xf6, 0xab,
- 0xf8, 0x20, 0x10, 0x5f, 0x6b, 0xf8, 0x27, 0x6f,
- 0x00, 0x01, 0x77, 0x10, 0x00, 0x0c, 0xf6, 0xaa,
- 0xf8, 0x20, 0x10, 0x6b, 0xf2, 0x74, 0x0e, 0x9f,
- 0xf4, 0x95, 0x48, 0x17, 0x71, 0xe1, 0x00, 0x0c,
- 0x00, 0x12, 0x77, 0x10, 0x00, 0x0c, 0xf4, 0xaa,
- 0xf8, 0x30, 0x10, 0x7c, 0x77, 0x10, 0x00, 0x0c,
- 0x71, 0xe1, 0x00, 0x0b, 0x00, 0x13, 0xf6, 0xab,
- 0xf8, 0x30, 0x10, 0xb4, 0xe7, 0x30, 0xf7, 0xaa,
- 0xf8, 0x30, 0x10, 0xb4, 0xf2, 0x74, 0x0e, 0xc1,
- 0xf4, 0x95, 0x48, 0x17, 0x88, 0x12, 0xf4, 0x95,
- 0xf4, 0x95, 0x6c, 0x82, 0x10, 0x8d, 0x76, 0xe1,
- 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02,
- 0x00, 0x05, 0xf0, 0x73, 0x10, 0xb4, 0x76, 0xe1,
- 0x00, 0x02, 0x00, 0x04, 0x77, 0x10, 0x00, 0x0c,
- 0x71, 0xe1, 0x00, 0x0b, 0x00, 0x12, 0xf5, 0xaa,
- 0xf8, 0x20, 0x10, 0x9a, 0xf0, 0x73, 0x10, 0x9c,
- 0x77, 0x12, 0x00, 0x0c, 0x76, 0x00, 0x00, 0x00,
- 0x70, 0x01, 0x00, 0x12, 0x70, 0x02, 0x00, 0x17,
- 0x76, 0x03, 0x00, 0x01, 0x48, 0x11, 0xf2, 0x74,
- 0x0c, 0xb9, 0xf0, 0x00, 0x00, 0x05, 0x76, 0xe1,
- 0x00, 0x04, 0x00, 0x00, 0x77, 0x10, 0x00, 0x0c,
- 0x71, 0xe1, 0x00, 0x0b, 0x00, 0x12, 0xf6, 0xaa,
- 0xf8, 0x20, 0x11, 0x1c, 0x48, 0x16, 0xf8, 0x45,
- 0x11, 0x33, 0x60, 0xe1, 0x00, 0x02, 0x00, 0x05,
- 0xf8, 0x20, 0x10, 0xdf, 0x10, 0xe1, 0x00, 0x0b,
- 0x08, 0xe1, 0x00, 0x0c, 0x11, 0xe1, 0x00, 0x04,
- 0xf8, 0x4d, 0x10, 0xc7, 0x6b, 0xf8, 0x27, 0x6f,
- 0x00, 0x01, 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95,
- 0xf5, 0xae, 0xf8, 0x20, 0x10, 0xcf, 0x48, 0x16,
- 0xf4, 0x95, 0x48, 0x08, 0xf8, 0x45, 0x11, 0x16,
- 0x6f, 0xe1, 0x00, 0x0c, 0x0d, 0x00, 0x81, 0xe1,
- 0x00, 0x0c, 0x11, 0x04, 0xf5, 0x00, 0x81, 0x04,
- 0x49, 0x16, 0xf5, 0x20, 0x89, 0x16, 0xf0, 0x73,
- 0x11, 0x0e, 0x10, 0xe1, 0x00, 0x0b, 0x71, 0xe1,
- 0x00, 0x0c, 0x00, 0x12, 0x88, 0x10, 0xf4, 0x95,
- 0xf4, 0x95, 0xf6, 0xaa, 0xf8, 0x30, 0x11, 0x16,
- 0x49, 0x12, 0xf6, 0x20, 0x88, 0x10, 0xf4, 0x95,
- 0xf4, 0x95, 0xf5, 0xae, 0xf8, 0x20, 0x10, 0xf3,
- 0x48, 0x16, 0x80, 0x06, 0x48, 0x08, 0xf8, 0x45,
- 0x11, 0x16, 0x10, 0x04, 0x70, 0x02, 0x00, 0x17,
- 0x80, 0x00, 0x76, 0x03, 0x00, 0x00, 0x10, 0x06,
- 0x80, 0x01, 0x10, 0x05, 0xf0, 0x74, 0x0c, 0xb9,
- 0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1,
- 0x00, 0x0c, 0x11, 0x06, 0x10, 0x04, 0xf6, 0x00,
- 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20, 0x88, 0x16,
- 0x10, 0xe1, 0x00, 0x0c, 0x08, 0xe1, 0x00, 0x0b,
- 0xf8, 0x45, 0x11, 0x1c, 0xf0, 0x73, 0x11, 0x31,
- 0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17,
- 0xf0, 0x73, 0x11, 0x33, 0x76, 0xe1, 0x00, 0x0c,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0x02, 0x00, 0x01, 0x10, 0x04,
- 0x80, 0x00, 0x10, 0x05, 0xf0, 0x74, 0x06, 0x9f,
- 0x88, 0x12, 0xf4, 0x95, 0x77, 0x10, 0x00, 0xff,
- 0xf4, 0xaa, 0xf8, 0x30, 0x11, 0x33, 0x6c, 0x86,
- 0x0f, 0x70, 0xee, 0x08, 0x8a, 0x17, 0x8a, 0x16,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfc,
- 0xf4, 0x95, 0x71, 0x06, 0x00, 0x12, 0x88, 0x11,
- 0x73, 0x12, 0x00, 0x0e, 0xf1, 0x66, 0x00, 0x0d,
- 0xf3, 0x00, 0x24, 0x00, 0x89, 0x14, 0x13, 0x81,
- 0xf7, 0x7a, 0xf3, 0x30, 0x00, 0x01, 0x81, 0xf8,
- 0x27, 0x60, 0x13, 0xe1, 0x00, 0x01, 0xf7, 0x7c,
- 0xf3, 0x30, 0x00, 0x03, 0x81, 0xf8, 0x27, 0x61,
- 0xe9, 0x0f, 0x19, 0xe1, 0x00, 0x01, 0x81, 0xf8,
- 0x27, 0x62, 0x71, 0xe4, 0x00, 0x03, 0x00, 0x13,
- 0xf6, 0xb8, 0x49, 0x13, 0xf3, 0x00, 0x00, 0x01,
- 0xf3, 0x30, 0x00, 0x0f, 0x49, 0x0b, 0x09, 0xf8,
- 0x27, 0x62, 0xf8, 0x4d, 0x11, 0x75, 0x77, 0x10,
- 0x00, 0xff, 0xf4, 0xab, 0xf8, 0x30, 0x11, 0x75,
- 0x57, 0xf8, 0x27, 0x6c, 0xf3, 0x00, 0x00, 0x01,
- 0x4f, 0xf8, 0x27, 0x6c, 0x76, 0xf8, 0x27, 0x63,
- 0x00, 0x01, 0xf0, 0x73, 0x11, 0x78, 0x76, 0xf8,
- 0x27, 0x63, 0x00, 0x00, 0x70, 0xe4, 0x00, 0x03,
- 0x27, 0x62, 0x76, 0xf8, 0x27, 0x64, 0x00, 0x00,
- 0x11, 0xf8, 0x27, 0x61, 0x61, 0xf8, 0x00, 0x0b,
- 0x00, 0x02, 0xf8, 0x20, 0x11, 0x8d, 0xe9, 0x01,
- 0x6f, 0xe1, 0x00, 0x02, 0x0f, 0x18, 0x81, 0xf8,
- 0x27, 0x64, 0x11, 0xf8, 0x27, 0x61, 0x61, 0xf8,
- 0x00, 0x0b, 0x00, 0x01, 0xf8, 0x20, 0x11, 0xa9,
- 0x10, 0xf8, 0x27, 0x64, 0xf1, 0x00, 0x00, 0x04,
- 0x89, 0x13, 0xe9, 0xb8, 0xf5, 0x20, 0x81, 0xf8,
- 0x27, 0x65, 0x60, 0x84, 0x00, 0x02, 0xf8, 0x20,
- 0x11, 0xa9, 0x70, 0x00, 0x00, 0x11, 0x70, 0x01,
- 0x00, 0x13, 0x70, 0x02, 0x27, 0x65, 0xf2, 0x74,
- 0x0f, 0x18, 0xf4, 0x95, 0x48, 0x12, 0xee, 0x04,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16,
- 0x4a, 0x17, 0xee, 0xfc, 0xe8, 0x00, 0x4e, 0xf8,
- 0x27, 0x66, 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x68,
- 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x6c, 0xe8, 0x00,
- 0x4e, 0xf8, 0x27, 0x6a, 0x77, 0x12, 0x27, 0x40,
- 0x77, 0x11, 0x24, 0x00, 0x77, 0x1a, 0x00, 0x1f,
- 0xf0, 0x72, 0x11, 0xdb, 0x70, 0x92, 0x00, 0x11,
- 0x76, 0xe1, 0x00, 0x01, 0xff, 0xff, 0x76, 0x81,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff, 0x76, 0xe1,
- 0x00, 0x0c, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00,
- 0x6d, 0xe9, 0x00, 0x0d, 0xf0, 0x20, 0x25, 0xa0,
- 0xf1, 0x00, 0x00, 0x07, 0x89, 0x11, 0xf1, 0x00,
- 0x00, 0x01, 0x81, 0x02, 0x88, 0x16, 0xf4, 0x95,
- 0x77, 0x17, 0x00, 0x20, 0x76, 0x86, 0x00, 0xff,
- 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x06,
- 0x10, 0x02, 0xf0, 0x74, 0x06, 0x6c, 0x76, 0x00,
- 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0xf2, 0x74,
- 0x06, 0x6c, 0xf4, 0x95, 0x48, 0x11, 0x10, 0x02,
- 0xf0, 0x00, 0x00, 0x0d, 0x80, 0x02, 0x6d, 0xe9,
- 0x00, 0x0d, 0x6d, 0xee, 0x00, 0x0d, 0x6c, 0xef,
- 0xff, 0xff, 0x11, 0xe8, 0xf0, 0x74, 0x0c, 0x9d,
- 0xee, 0x04, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11,
- 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17,
- 0xee, 0xfa, 0x88, 0x11, 0x10, 0x0a, 0x49, 0x11,
- 0xf8, 0x4d, 0x12, 0x9f, 0x48, 0x08, 0xf8, 0x45,
- 0x12, 0x9f, 0x80, 0x04, 0x12, 0x81, 0xf5, 0x78,
- 0x89, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0xe2,
- 0xff, 0xb9, 0x12, 0x8a, 0x61, 0xf8, 0x00, 0x08,
- 0x00, 0x80, 0xf8, 0x30, 0x12, 0x8a, 0x13, 0xe1,
- 0x00, 0x01, 0xf0, 0xe8, 0xf7, 0x78, 0xf1, 0xa0,
- 0xf2, 0x30, 0x1f, 0xff, 0x88, 0x17, 0xf4, 0x95,
- 0x77, 0x12, 0x24, 0x00, 0x77, 0x16, 0x00, 0x00,
- 0x77, 0x13, 0x00, 0x20, 0xf6, 0xb8, 0x48, 0x17,
- 0x08, 0xe2, 0x00, 0x01, 0xf8, 0x45, 0x12, 0x42,
- 0x6d, 0xea, 0x00, 0x0d, 0x6d, 0x96, 0x6c, 0xeb,
- 0xff, 0xff, 0x12, 0x34, 0xf0, 0x73, 0x12, 0x90,
- 0x56, 0xf8, 0x27, 0x6a, 0xf0, 0x00, 0x00, 0x01,
- 0x4e, 0xf8, 0x27, 0x6a, 0x60, 0x82, 0x00, 0x01,
- 0xf8, 0x30, 0x12, 0x54, 0x70, 0x00, 0x00, 0x16,
- 0xf2, 0x74, 0x11, 0x38, 0xf4, 0x95, 0x48, 0x11,
- 0xf0, 0x73, 0x12, 0x90, 0x70, 0x00, 0x00, 0x16,
- 0xf2, 0x74, 0x11, 0x38, 0xf4, 0x95, 0x48, 0x11,
- 0x72, 0x10, 0x2a, 0x9e, 0xf4, 0x95, 0xf4, 0xaf,
- 0xf8, 0x30, 0x12, 0x6e, 0x76, 0x00, 0x00, 0x00,
- 0x76, 0x01, 0x00, 0xbc, 0x70, 0x02, 0x00, 0x16,
- 0x76, 0x03, 0x00, 0x00, 0xf2, 0x74, 0x0c, 0xb9,
- 0xf4, 0x95, 0x48, 0x11, 0xf0, 0x73, 0x12, 0x90,
- 0x10, 0xf8, 0x27, 0x6e, 0xf8, 0x44, 0x12, 0x90,
- 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0xbc,
- 0x70, 0x02, 0x00, 0x16, 0x76, 0x03, 0x00, 0x00,
- 0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, 0x48, 0x11,
- 0xf0, 0x74, 0x0c, 0x5e, 0xf0, 0xe0, 0xf0, 0x10,
- 0x13, 0x88, 0xf8, 0x42, 0x12, 0x90, 0x76, 0xf8,
- 0x27, 0x6e, 0x00, 0x01, 0xf0, 0x73, 0x12, 0x90,
- 0x56, 0xf8, 0x27, 0x66, 0xf0, 0x00, 0x00, 0x01,
- 0x4e, 0xf8, 0x27, 0x66, 0x6d, 0xe9, 0x00, 0x5e,
- 0x56, 0xf8, 0x27, 0x68, 0xf0, 0x00, 0x00, 0x01,
- 0x4e, 0xf8, 0x27, 0x68, 0x71, 0x04, 0x00, 0x12,
- 0x6e, 0xea, 0xff, 0xff, 0x12, 0x18, 0x70, 0x04,
- 0x00, 0x12, 0xee, 0x06, 0x8a, 0x17, 0x8a, 0x16,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe,
- 0x88, 0x0e, 0xf4, 0x95, 0xf0, 0x66, 0x00, 0x0d,
- 0xf0, 0x00, 0x25, 0xa0, 0x88, 0x11, 0xf4, 0x95,
- 0xf4, 0x95, 0x76, 0x81, 0x00, 0xff, 0x76, 0x00,
- 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0xf2, 0x74,
- 0x06, 0x6c, 0xf0, 0x00, 0x00, 0x01, 0x76, 0x00,
- 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0x48, 0x11,
- 0xf2, 0x74, 0x06, 0x6c, 0xf0, 0x00, 0x00, 0x07,
- 0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11,
- 0x88, 0x0e, 0xf4, 0x95, 0xf0, 0x66, 0x00, 0x0d,
- 0xf0, 0x00, 0x24, 0x00, 0x88, 0x11, 0xf4, 0x95,
- 0xf4, 0x95, 0x76, 0xe1, 0x00, 0x01, 0xff, 0xff,
- 0x76, 0x81, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff,
- 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95,
- 0x13, 0x03, 0x88, 0x11, 0xfa, 0x4d, 0x12, 0xec,
- 0x71, 0x02, 0x00, 0x12, 0xf3, 0x10, 0x00, 0x01,
- 0x89, 0x1a, 0xf4, 0x95, 0xf0, 0x72, 0x12, 0xeb,
- 0x70, 0x91, 0x00, 0x12, 0x8a, 0x11, 0xfc, 0x00,
- 0xf4, 0x95, 0x4a, 0x0b, 0x4a, 0x0c, 0x4a, 0x0d,
- 0xf7, 0xb8, 0xee, 0xfe, 0x10, 0xf8, 0x00, 0x08,
- 0x11, 0x06, 0xf1, 0xc0, 0x83, 0x00, 0xf4, 0x85,
- 0x11, 0x06, 0xf7, 0x85, 0x81, 0x06, 0xf6, 0xb8,
- 0xec, 0x0f, 0x1e, 0x06, 0x61, 0x00, 0x80, 0x00,
- 0xf8, 0x20, 0x13, 0x05, 0xf4, 0x84, 0xee, 0x02,
- 0x8a, 0x0d, 0x8a, 0x0c, 0x8a, 0x0b, 0xfc, 0x00,
- 0xf4, 0x95, 0x4a, 0x0b, 0x4a, 0x0c, 0x4a, 0x0d,
- 0xee, 0xfe, 0xf7, 0xb8, 0x80, 0x00, 0x10, 0xf8,
- 0x00, 0x08, 0xf4, 0x85, 0x11, 0x06, 0xf7, 0x85,
- 0x81, 0x06, 0xf6, 0xb8, 0xec, 0x0f, 0x1e, 0x06,
- 0xf0, 0xf0, 0x61, 0x00, 0x80, 0x00, 0xf8, 0x20,
- 0x13, 0x20, 0xf4, 0x84, 0xee, 0x02, 0x8a, 0x0d,
- 0x8a, 0x0c, 0x8a, 0x0b, 0xfc, 0x00, 0x4a, 0x11,
- 0x77, 0x11, 0x00, 0x7b, 0x76, 0x81, 0x2e, 0xec,
- 0x77, 0x11, 0x00, 0x7b, 0xee, 0xff, 0x71, 0x81,
- 0x00, 0x11, 0xee, 0x01, 0x76, 0xe1, 0x00, 0x01,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0x06, 0x00, 0x00, 0x76, 0xe1,
- 0x00, 0x62, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x76,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x92, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0x94, 0x00, 0x00, 0x76, 0xe1,
- 0x00, 0xb0, 0x00, 0x00, 0x76, 0xe1, 0x00, 0xb3,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0xbe, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0xbf, 0x00, 0x00, 0x76, 0xe1,
- 0x00, 0xc1, 0x00, 0x00, 0x76, 0xe1, 0x00, 0xc3,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0xc5, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0xc7, 0x00, 0x00, 0x76, 0x81,
- 0x00, 0x00, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4,
- 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xff,
- 0xf4, 0x95, 0x71, 0x06, 0x00, 0x16, 0xfb, 0x80,
- 0x16, 0xa2, 0x88, 0x17, 0xf4, 0x95, 0xf7, 0xb8,
- 0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x02,
- 0xfa, 0x46, 0x13, 0x88, 0x77, 0x11, 0x00, 0x00,
- 0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x02,
- 0xf8, 0x45, 0x13, 0xf9, 0x10, 0xf8, 0x00, 0x17,
- 0xf8, 0x45, 0x14, 0x39, 0x10, 0xf8, 0x00, 0x17,
- 0xf0, 0x10, 0x00, 0x01, 0xf8, 0x45, 0x14, 0x1f,
- 0xf0, 0x73, 0x14, 0x52, 0x10, 0xf8, 0x00, 0x17,
- 0xf0, 0x10, 0x00, 0x03, 0xf8, 0x45, 0x13, 0xd3,
- 0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x06,
- 0xf8, 0x44, 0x14, 0x52, 0x77, 0x12, 0x00, 0x7b,
- 0x71, 0x82, 0x00, 0x14, 0x61, 0xe4, 0x00, 0x07,
- 0x00, 0x40, 0xf8, 0x30, 0x14, 0x52, 0x49, 0x14,
- 0x48, 0x17, 0xf6, 0x00, 0x88, 0x12, 0xf4, 0x95,
- 0x77, 0x13, 0x00, 0x55, 0x77, 0x11, 0x00, 0x57,
- 0x6d, 0xea, 0x00, 0x3b, 0xe5, 0x01, 0x10, 0xe6,
- 0x00, 0x06, 0x80, 0x81, 0x48, 0x14, 0x00, 0xf8,
- 0x00, 0x17, 0x88, 0x12, 0xf4, 0x95, 0x77, 0x11,
- 0x00, 0x55, 0x10, 0xe2, 0x00, 0x40, 0x80, 0x81,
- 0x77, 0x11, 0x00, 0x57, 0x10, 0xe6, 0x00, 0x07,
- 0x80, 0x81, 0x77, 0x11, 0x00, 0x55, 0x10, 0xe2,
- 0x00, 0x45, 0x80, 0x81, 0x10, 0xe6, 0x00, 0x08,
- 0x77, 0x11, 0x00, 0x57, 0x80, 0x81, 0x77, 0x11,
- 0x00, 0x55, 0x10, 0xe2, 0x00, 0x4a, 0x80, 0x81,
- 0x77, 0x11, 0x00, 0x57, 0x10, 0xe6, 0x00, 0x09,
- 0x80, 0x81, 0xf2, 0x73, 0x14, 0x52, 0x77, 0x11,
- 0x03, 0xc0, 0x77, 0x12, 0x00, 0x7b, 0x10, 0x82,
- 0xf0, 0x00, 0x00, 0x07, 0x88, 0x13, 0xf4, 0x95,
- 0xf4, 0x95, 0x96, 0x1b, 0xf8, 0x30, 0x14, 0x52,
- 0x10, 0xe3, 0x00, 0x35, 0x77, 0x12, 0x00, 0x55,
- 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6,
- 0x00, 0x04, 0x80, 0x82, 0x77, 0x12, 0x00, 0x55,
- 0x10, 0xe3, 0x00, 0x37, 0x80, 0x82, 0x77, 0x12,
- 0x00, 0x57, 0x10, 0xe6, 0x00, 0x05, 0x80, 0x82,
- 0x48, 0x11, 0xf0, 0x40, 0x00, 0x10, 0xf2, 0x73,
- 0x14, 0x50, 0xf0, 0x40, 0x00, 0x20, 0x77, 0x12,
- 0x00, 0x7b, 0x10, 0x82, 0xf0, 0x00, 0x00, 0x07,
- 0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x96, 0x0d,
- 0xf8, 0x30, 0x14, 0x52, 0x10, 0xe2, 0x00, 0x34,
- 0x77, 0x13, 0x00, 0x55, 0x80, 0x83, 0x77, 0x13,
- 0x00, 0x57, 0x10, 0xe6, 0x00, 0x02, 0x80, 0x83,
- 0x10, 0xe2, 0x00, 0x36, 0x77, 0x12, 0x00, 0x55,
- 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6,
- 0x00, 0x03, 0x80, 0x82, 0x48, 0x11, 0xf0, 0x40,
- 0x00, 0x04, 0xf2, 0x73, 0x14, 0x50, 0xf0, 0x40,
- 0x00, 0x08, 0x77, 0x12, 0x00, 0x7b, 0x10, 0x82,
- 0xf0, 0x00, 0x00, 0x07, 0x88, 0x12, 0xf4, 0x95,
- 0xf4, 0x95, 0x96, 0x0e, 0xf8, 0x30, 0x14, 0x52,
- 0x10, 0xe2, 0x00, 0x33, 0x77, 0x12, 0x00, 0x55,
- 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6,
- 0x00, 0x01, 0x80, 0x82, 0x48, 0x11, 0xf2, 0x73,
- 0x14, 0x50, 0xf0, 0x40, 0x00, 0x02, 0x77, 0x12,
- 0x00, 0x7b, 0x10, 0x82, 0xf0, 0x00, 0x00, 0x07,
- 0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x96, 0x0f,
- 0xf8, 0x30, 0x14, 0x52, 0x10, 0xe2, 0x00, 0x32,
- 0x77, 0x12, 0x00, 0x55, 0x77, 0x13, 0x00, 0x57,
- 0x80, 0x82, 0x48, 0x11, 0xe7, 0x62, 0xf0, 0x40,
- 0x00, 0x01, 0xe5, 0x01, 0x88, 0x11, 0xf4, 0x95,
- 0x77, 0x12, 0x00, 0x7b, 0x48, 0x11, 0x71, 0x82,
- 0x00, 0x12, 0x1a, 0xe2, 0x00, 0x07, 0x80, 0xe2,
- 0x00, 0x07, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01,
- 0x8a, 0x17, 0x48, 0x11, 0x8a, 0x16, 0x8a, 0x11,
- 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0x77, 0x0e,
- 0x00, 0x05, 0x77, 0x12, 0x00, 0x55, 0xe8, 0x04,
- 0xf6, 0xb8, 0x28, 0xe1, 0x00, 0x02, 0xee, 0xff,
- 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0xf0, 0x20,
- 0x80, 0x00, 0xee, 0x01, 0x1a, 0x82, 0x77, 0x12,
- 0x00, 0x57, 0x80, 0x82, 0xe8, 0x01, 0x32, 0xe1,
- 0x00, 0x02, 0xf5, 0x82, 0x77, 0x11, 0x00, 0x54,
- 0xf6, 0x93, 0x18, 0x81, 0x77, 0x11, 0x00, 0x54,
- 0xf2, 0xa0, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95,
- 0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95,
- 0x71, 0x04, 0x00, 0x11, 0xfb, 0x80, 0x16, 0xa2,
- 0x88, 0x16, 0xf4, 0x95, 0x77, 0x12, 0x00, 0x55,
- 0x10, 0xe6, 0x00, 0x03, 0x80, 0x82, 0x77, 0x12,
- 0x00, 0x56, 0x10, 0xe1, 0x00, 0x02, 0x77, 0x13,
- 0x00, 0x56, 0x80, 0x82, 0x77, 0x12, 0x00, 0x56,
- 0x10, 0xe1, 0x00, 0x03, 0x80, 0x82, 0x10, 0xe1,
- 0x00, 0x04, 0x77, 0x12, 0x00, 0x56, 0x80, 0x82,
- 0x77, 0x12, 0x00, 0x56, 0x10, 0xe1, 0x00, 0x01,
- 0x80, 0x82, 0xe7, 0x12, 0xe5, 0x01, 0xf9, 0x80,
- 0x16, 0x9a, 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4,
- 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xf9,
- 0x77, 0x11, 0x00, 0x7b, 0x76, 0x00, 0x00, 0x16,
- 0x76, 0x01, 0x00, 0x17, 0x76, 0x02, 0x00, 0x1a,
- 0x76, 0x03, 0x00, 0x1b, 0x76, 0x04, 0x00, 0x1c,
- 0x76, 0x05, 0x00, 0x1d, 0x71, 0x81, 0x00, 0x17,
- 0x71, 0xe7, 0x00, 0x06, 0x00, 0x11, 0x10, 0x81,
- 0xf8, 0x44, 0x14, 0xdf, 0xf9, 0x80, 0x16, 0x53,
- 0xf6, 0xb8, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x20,
- 0xff, 0xff, 0xf6, 0xb8, 0xfb, 0x80, 0x16, 0x08,
- 0xf0, 0x20, 0xff, 0xff, 0x77, 0x11, 0x00, 0x7b,
- 0x71, 0x81, 0x00, 0x17, 0x76, 0xe7, 0x00, 0x06,
- 0x00, 0x01, 0x48, 0x17, 0x77, 0x16, 0x00, 0x00,
- 0x77, 0x10, 0x00, 0x04, 0x77, 0x15, 0x00, 0x03,
- 0x77, 0x14, 0x00, 0x02, 0x77, 0x13, 0x00, 0x01,
- 0xf0, 0x00, 0x00, 0x39, 0x76, 0xe7, 0x00, 0x08,
- 0x00, 0x1f, 0x76, 0xe7, 0x00, 0x07, 0x00, 0x00,
- 0x88, 0x0e, 0x77, 0x1a, 0x00, 0x05, 0x48, 0x17,
- 0xf0, 0x00, 0x00, 0x09, 0x88, 0x12, 0x48, 0x18,
- 0x88, 0x19, 0xe8, 0x00, 0xf0, 0x72, 0x15, 0x2c,
- 0x73, 0x19, 0x00, 0x11, 0x76, 0x82, 0x00, 0x00,
- 0x11, 0x91, 0x73, 0x11, 0x00, 0x19, 0x70, 0xe2,
- 0x00, 0x03, 0x00, 0x16, 0x70, 0xe2, 0x00, 0x04,
- 0x00, 0x13, 0x70, 0xe2, 0x00, 0x05, 0x00, 0x14,
- 0x81, 0xe2, 0x00, 0x01, 0x70, 0xe2, 0x00, 0x06,
- 0x00, 0x15, 0x70, 0xe2, 0x00, 0x07, 0x00, 0x10,
- 0x80, 0xe2, 0x00, 0x02, 0x73, 0x0e, 0x00, 0x11,
- 0xf1, 0x00, 0x00, 0x1e, 0x6d, 0xee, 0x00, 0x05,
- 0x6d, 0xeb, 0x00, 0x05, 0x6d, 0xec, 0x00, 0x05,
- 0x6d, 0xed, 0x00, 0x05, 0x6d, 0xe8, 0x00, 0x05,
- 0xf0, 0x00, 0x00, 0x01, 0x81, 0x91, 0x6d, 0xea,
- 0x00, 0x08, 0x73, 0x11, 0x00, 0x0e, 0xee, 0x07,
- 0x76, 0xe7, 0x00, 0x41, 0x00, 0x24, 0x76, 0xe7,
- 0x00, 0x46, 0x00, 0x25, 0x76, 0xe7, 0x00, 0x4b,
- 0x00, 0x26, 0x76, 0xe7, 0x00, 0x50, 0x00, 0x27,
- 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4,
- 0x4a, 0x11, 0x4a, 0x16, 0xee, 0xfe, 0x88, 0x11,
- 0x56, 0x06, 0x4e, 0x00, 0xf9, 0x80, 0x16, 0xa2,
- 0xf7, 0xb8, 0x10, 0xf8, 0x00, 0x11, 0xf0, 0x10,
- 0xff, 0xff, 0xfa, 0x45, 0x15, 0x60, 0x77, 0x16,
- 0xff, 0xff, 0x77, 0x12, 0x00, 0x7b, 0x49, 0x11,
- 0x10, 0x82, 0xf6, 0x03, 0xf0, 0x00, 0x00, 0x09,
- 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81,
- 0xf8, 0x44, 0x15, 0x71, 0xf2, 0x73, 0x15, 0x71,
- 0xf4, 0x95, 0xe7, 0x16, 0x77, 0x11, 0x00, 0x7b,
- 0x10, 0x81, 0xf0, 0x00, 0x00, 0x09, 0x88, 0x11,
- 0xf4, 0x95, 0x77, 0x12, 0x00, 0x06, 0x10, 0x81,
- 0xf8, 0x45, 0x15, 0x5c, 0x6e, 0xea, 0xff, 0xff,
- 0x15, 0x69, 0x6d, 0xe9, 0x00, 0x08, 0x76, 0x86,
- 0x00, 0x01, 0xe9, 0x01, 0x56, 0x00, 0xf1, 0x80,
- 0x10, 0xf8, 0x00, 0x0b, 0xf8, 0x45, 0x15, 0x7e,
- 0xfb, 0x80, 0x15, 0x85, 0xf4, 0x95, 0x48, 0x16,
- 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x02, 0x48, 0x16,
- 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11,
- 0xee, 0xff, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11,
- 0xf4, 0x95, 0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9,
- 0xf8, 0x30, 0x15, 0xc4, 0x10, 0xe1, 0x00, 0x03,
- 0x77, 0x12, 0x00, 0x55, 0x80, 0x82, 0x77, 0x12,
- 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12,
- 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12,
- 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12,
- 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12,
- 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1,
- 0x00, 0x02, 0xf0, 0x00, 0x00, 0x08, 0x32, 0xf8,
- 0x00, 0x08, 0x77, 0x12, 0x00, 0x54, 0xe8, 0x01,
- 0xf4, 0x82, 0xf4, 0x93, 0x18, 0x82, 0x77, 0x12,
- 0x00, 0x54, 0xf0, 0x40, 0x00, 0x00, 0x80, 0x82,
- 0x10, 0xe1, 0x00, 0x01, 0xf9, 0x80, 0x16, 0x76,
- 0x10, 0xe1, 0x00, 0x01, 0xf9, 0x80, 0x16, 0x66,
- 0xf0, 0x73, 0x16, 0x03, 0x77, 0x11, 0x00, 0x7b,
- 0x71, 0x81, 0x00, 0x11, 0x71, 0xe1, 0x00, 0x07,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1,
- 0x00, 0x09, 0xf9, 0x80, 0x15, 0x85, 0x77, 0x11,
- 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1,
- 0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00,
- 0x00, 0x08, 0x77, 0x11, 0x00, 0x7b, 0x71, 0x81,
- 0x00, 0x11, 0x10, 0xe1, 0x00, 0x09, 0xfb, 0x80,
- 0x15, 0x85, 0xf0, 0x00, 0x00, 0x10, 0x77, 0x11,
- 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1,
- 0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00,
- 0x00, 0x18, 0x77, 0x11, 0x00, 0x7b, 0x71, 0x81,
- 0x00, 0x11, 0x10, 0xe1, 0x00, 0x09, 0xfb, 0x80,
- 0x15, 0x85, 0xf0, 0x00, 0x00, 0x20, 0x77, 0x11,
- 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1,
- 0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00,
- 0x00, 0x28, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01,
- 0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff,
- 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95,
- 0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30,
- 0x16, 0x41, 0x77, 0x11, 0x00, 0x55, 0x76, 0x81,
- 0x00, 0x1e, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81,
- 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0xf2, 0x73,
- 0x16, 0x4e, 0x76, 0x81, 0x00, 0x00, 0x77, 0x11,
- 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x71, 0xe1,
- 0x00, 0x07, 0x00, 0x12, 0x76, 0x82, 0x00, 0x00,
- 0x10, 0xe1, 0x00, 0x39, 0xf9, 0x80, 0x16, 0x08,
- 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11,
- 0xf4, 0xe4, 0x4a, 0x11, 0x77, 0x11, 0x00, 0x7b,
- 0x10, 0x81, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x11,
- 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xfa, 0x44,
- 0x16, 0x63, 0xf4, 0x95, 0xee, 0xff, 0x76, 0x81,
- 0x00, 0x01, 0xee, 0x01, 0x8a, 0x11, 0xf4, 0xe4,
- 0xf0, 0x10, 0x00, 0x10, 0x4a, 0x11, 0x32, 0xf8,
- 0x00, 0x08, 0xee, 0xff, 0x77, 0x11, 0x00, 0x01,
- 0xe8, 0x01, 0xee, 0x01, 0xf4, 0x82, 0x1a, 0x81,
- 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4,
- 0xf0, 0x10, 0x00, 0x10, 0x4a, 0x11, 0x32, 0xf8,
- 0x00, 0x08, 0xee, 0xff, 0xe8, 0x01, 0x77, 0x11,
- 0x00, 0x00, 0xf4, 0x82, 0xee, 0x01, 0xf4, 0x93,
- 0x18, 0x81, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95,
- 0xf4, 0xe4, 0x4a, 0x11, 0xf0, 0x10, 0x00, 0x10,
- 0x77, 0x11, 0x00, 0x00, 0x32, 0xf8, 0x00, 0x08,
- 0xee, 0xff, 0x11, 0x81, 0xe8, 0x01, 0xee, 0x01,
- 0x77, 0x11, 0x00, 0x00, 0xf4, 0x82, 0xf2, 0xa0,
- 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4,
- 0xf2, 0x73, 0x16, 0x9e, 0xf6, 0xbb, 0xf4, 0x95,
- 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xe4,
- 0xf2, 0x73, 0x16, 0xa6, 0xf7, 0xbb, 0xf4, 0x95,
- 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xe4,
- 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95, 0x71, 0x04,
- 0x00, 0x16, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11,
- 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x0e, 0x10, 0xe6, 0x00, 0x0e,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x80, 0x82,
- 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x0d, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12,
- 0x10, 0xe6, 0x00, 0x0d, 0x80, 0x82, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0c,
- 0x10, 0xe6, 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x0b, 0x10, 0xe6,
- 0x00, 0x0b, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12,
- 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x0a, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x10, 0xe6, 0x00, 0x0a, 0x80, 0x82,
- 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x09, 0x10, 0xe6, 0x00, 0x09, 0x71, 0xe1,
- 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x08,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6,
- 0x00, 0x08, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x07, 0x10, 0xe6,
- 0x00, 0x07, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12,
- 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x06, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x10, 0xe6, 0x00, 0x06, 0x80, 0x82,
- 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x05, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12,
- 0x10, 0xe6, 0x00, 0x05, 0x80, 0x82, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x04,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6,
- 0x00, 0x04, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x03, 0x71, 0xe1,
- 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6, 0x00, 0x03,
- 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x02, 0x10, 0xe6, 0x00, 0x02,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x80, 0x82,
- 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x01, 0x10, 0xe6, 0x00, 0x01, 0x71, 0xe1,
- 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x00,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x13, 0xe7, 0x62,
- 0xe5, 0x01, 0xf9, 0x80, 0x16, 0x9a, 0x8a, 0x16,
- 0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11,
- 0xf4, 0x95, 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05,
- 0x00, 0x12, 0xee, 0xff, 0x76, 0x82, 0x00, 0x00,
- 0xee, 0x01, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x11,
- 0x69, 0x81, 0x00, 0x01, 0x8a, 0x11, 0xf4, 0x95,
- 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0xf4, 0x95,
- 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0xee, 0xff, 0x76, 0x82, 0x00, 0x01, 0xee, 0x01,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x11, 0x69, 0x81,
- 0x00, 0x01, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4,
- 0x4a, 0x11, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81,
- 0xf0, 0x00, 0x00, 0x94, 0x88, 0x11, 0xf4, 0x95,
- 0xf4, 0x95, 0x10, 0x81, 0xfa, 0x44, 0x17, 0x9c,
- 0xf4, 0x95, 0xee, 0xff, 0xf9, 0x80, 0x16, 0x53,
- 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 0xf0, 0x00,
- 0x00, 0x94, 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95,
- 0x76, 0x81, 0x00, 0x01, 0xee, 0x01, 0x76, 0xe1,
- 0x00, 0x01, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02,
- 0x00, 0x21, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x20,
- 0x76, 0xe1, 0x00, 0x04, 0x00, 0x23, 0x76, 0xe1,
- 0x00, 0x05, 0x00, 0x22, 0x76, 0xe1, 0x00, 0x06,
- 0x00, 0x38, 0x76, 0xe1, 0x00, 0x07, 0x00, 0x39,
- 0x76, 0xe1, 0x00, 0x08, 0x00, 0x15, 0x76, 0xe1,
- 0x00, 0x09, 0x00, 0x14, 0x76, 0xe1, 0x00, 0x0a,
- 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x41,
- 0x76, 0xe1, 0x00, 0x0c, 0x00, 0x40, 0x76, 0xe1,
- 0x00, 0x0d, 0x00, 0x43, 0x76, 0xe1, 0x00, 0x0e,
- 0x00, 0x42, 0x76, 0xe1, 0x00, 0x0f, 0x00, 0x48,
- 0x76, 0xe1, 0x00, 0x10, 0x00, 0x49, 0x76, 0xe1,
- 0x00, 0x11, 0x00, 0x1b, 0x76, 0xe1, 0x00, 0x12,
- 0x00, 0x1a, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4,
- 0x4a, 0x11, 0xee, 0xfd, 0x88, 0x11, 0x56, 0x06,
- 0x4e, 0x00, 0xf9, 0x80, 0x16, 0xa2, 0x77, 0x12,
- 0x00, 0x7b, 0x77, 0x0e, 0x00, 0x09, 0x10, 0x82,
- 0x28, 0xf8, 0x00, 0x11, 0xf0, 0x00, 0x00, 0x95,
- 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81,
- 0xf8, 0x45, 0x17, 0xf0, 0xf2, 0x73, 0x17, 0xfd,
- 0x77, 0x11, 0xff, 0xff, 0x76, 0x81, 0x00, 0x01,
- 0xe9, 0x01, 0x56, 0x00, 0xf1, 0x80, 0x10, 0xf8,
- 0x00, 0x0b, 0xf8, 0x45, 0x17, 0xfd, 0xfb, 0x80,
- 0x18, 0x10, 0xf4, 0x95, 0x48, 0x11, 0xf9, 0x80,
- 0x16, 0x9a, 0xee, 0x03, 0x48, 0x11, 0x8a, 0x11,
- 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11,
- 0xf4, 0x95, 0xee, 0xff, 0x71, 0xe1, 0x00, 0x01,
- 0x00, 0x11, 0xee, 0x01, 0x10, 0x81, 0x8a, 0x11,
- 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff,
- 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95,
- 0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30,
- 0x18, 0xc3, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x01,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x02, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x03,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x04, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x05,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x06, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x01, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x07,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82,
- 0x20, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x08, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x09,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x0a, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0b,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1,
- 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0d,
- 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82,
- 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12,
- 0x76, 0x82, 0x00, 0x0e, 0x71, 0xe1, 0x00, 0x06,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1,
- 0x00, 0x07, 0xf9, 0x80, 0x16, 0x76, 0x10, 0xe1,
- 0x00, 0x08, 0xf9, 0x80, 0x16, 0x76, 0x10, 0xe1,
- 0x00, 0x07, 0xf9, 0x80, 0x16, 0x66, 0x10, 0xe1,
- 0x00, 0x08, 0xf9, 0x80, 0x16, 0x66, 0xf0, 0x73,
- 0x18, 0xd1, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81,
- 0xfb, 0x80, 0x18, 0x10, 0xf0, 0x00, 0x00, 0x95,
- 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 0xfb, 0x80,
- 0x18, 0x10, 0xf0, 0x00, 0x00, 0x9e, 0xf9, 0x80,
- 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11, 0xf4, 0xe4,
- 0x4a, 0x11, 0x88, 0x11, 0xee, 0xff, 0xf4, 0x95,
- 0x10, 0x04, 0x71, 0xe1, 0x00, 0x03, 0x00, 0x11,
- 0xee, 0x01, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95,
- 0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95,
- 0x71, 0x04, 0x00, 0x16, 0xfb, 0x80, 0x16, 0xa2,
- 0x88, 0x11, 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x02,
- 0x00, 0x12, 0x76, 0x82, 0x00, 0x10, 0x10, 0xe6,
- 0x00, 0x01, 0x71, 0xe1, 0x00, 0x03, 0x00, 0x12,
- 0x80, 0x82, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x12,
- 0x10, 0xe6, 0x00, 0x02, 0x80, 0x82, 0xe7, 0x62,
- 0x71, 0xe1, 0x00, 0x02, 0x00, 0x13, 0xe5, 0x01,
- 0xf9, 0x80, 0x16, 0x9a, 0x8a, 0x16, 0x8a, 0x11,
- 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0xee, 0xff,
- 0xee, 0x01, 0x10, 0xe1, 0x00, 0x01, 0x8a, 0x11,
- 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x77, 0x11,
- 0x00, 0x7b, 0x10, 0x81, 0xf0, 0x00, 0x00, 0xb3,
- 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81,
- 0xfa, 0x44, 0x19, 0x2a, 0xf4, 0x95, 0xee, 0xff,
- 0xf9, 0x80, 0x16, 0x53, 0x77, 0x11, 0x00, 0x7b,
- 0x10, 0x81, 0xf0, 0x00, 0x00, 0xb3, 0x88, 0x11,
- 0xf4, 0x95, 0xf4, 0x95, 0x76, 0x81, 0x00, 0x01,
- 0xee, 0x01, 0x76, 0xe1, 0x00, 0x01, 0x00, 0x00,
- 0x76, 0xe1, 0x00, 0x02, 0x00, 0x13, 0x76, 0xe1,
- 0x00, 0x03, 0x00, 0x26, 0x76, 0xe1, 0x00, 0x04,
- 0x00, 0x25, 0x76, 0xe1, 0x00, 0x05, 0x00, 0x24,
- 0x76, 0xe1, 0x00, 0x06, 0x00, 0x00, 0x76, 0xe1,
- 0x00, 0x07, 0x00, 0x17, 0x76, 0xe1, 0x00, 0x08,
- 0x00, 0x32, 0x76, 0xe1, 0x00, 0x09, 0x00, 0x31,
- 0x76, 0xe1, 0x00, 0x0a, 0x00, 0x30, 0x8a, 0x11,
- 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16,
- 0x4a, 0x17, 0xee, 0xff, 0xf4, 0x95, 0x71, 0x06,
- 0x00, 0x17, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11,
- 0xf4, 0x95, 0xf7, 0xb8, 0x10, 0xf8, 0x00, 0x11,
- 0xf0, 0x10, 0xff, 0xff, 0xfa, 0x45, 0x19, 0x73,
- 0x77, 0x16, 0xff, 0xff, 0x77, 0x12, 0x00, 0x7b,
- 0x77, 0x0e, 0x00, 0x05, 0x10, 0x82, 0x28, 0xf8,
- 0x00, 0x11, 0xf0, 0x00, 0x00, 0xb4, 0x88, 0x11,
- 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xf8, 0x44,
- 0x19, 0x84, 0xf2, 0x73, 0x19, 0x84, 0xf4, 0x95,
- 0xe7, 0x16, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81,
- 0xf0, 0x00, 0x00, 0xb4, 0x88, 0x11, 0xf4, 0x95,
- 0x77, 0x12, 0x00, 0x02, 0x10, 0x81, 0xf8, 0x45,
- 0x19, 0x6f, 0x6e, 0xea, 0xff, 0xff, 0x19, 0x7c,
- 0x6d, 0xe9, 0x00, 0x05, 0x61, 0xf8, 0x00, 0x17,
- 0x00, 0x01, 0xfa, 0x20, 0x19, 0x8f, 0x76, 0x86,
- 0x00, 0x01, 0xfb, 0x80, 0x19, 0x97, 0xf4, 0x95,
- 0x48, 0x16, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01,
- 0x8a, 0x17, 0x48, 0x16, 0x8a, 0x16, 0x8a, 0x11,
- 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff, 0xfb, 0x80,
- 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10,
- 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30, 0x19, 0xcc,
- 0x71, 0xe1, 0x00, 0x02, 0x00, 0x12, 0x69, 0x82,
- 0x00, 0x10, 0x71, 0xe1, 0x00, 0x02, 0x00, 0x12,
- 0x68, 0x82, 0xf7, 0xff, 0x71, 0xe1, 0x00, 0x02,
- 0x00, 0x12, 0x68, 0x82, 0xfb, 0xff, 0x71, 0xe1,
- 0x00, 0x02, 0x00, 0x12, 0x68, 0x82, 0xff, 0xf0,
- 0x71, 0xe1, 0x00, 0x03, 0x00, 0x12, 0x76, 0x82,
- 0xff, 0xff, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x12,
- 0x76, 0x82, 0xff, 0xff, 0x71, 0xe1, 0x00, 0x02,
- 0x00, 0x12, 0x69, 0x82, 0x00, 0x20, 0x71, 0xe1,
- 0x00, 0x02, 0x00, 0x11, 0xf2, 0x73, 0x19, 0xda,
- 0x68, 0x81, 0xff, 0xef, 0x77, 0x11, 0x00, 0x7b,
- 0x10, 0x81, 0xfb, 0x80, 0x19, 0x97, 0xf0, 0x00,
- 0x00, 0xb4, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81,
- 0xfb, 0x80, 0x19, 0x97, 0xf0, 0x00, 0x00, 0xb9,
- 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11,
- 0xf4, 0xe4, 0x00, 0xa4, 0x00, 0x00, 0x19, 0xdf,
- 0x00, 0x01, 0x2a, 0xe6, 0x00, 0x00, 0x00, 0x01,
- 0x2a, 0xe7, 0x00, 0x00, 0x00, 0x03, 0x2a, 0x12,
- 0x0c, 0x01, 0xc3, 0x4f, 0x00, 0x00, 0x00, 0x01,
- 0x2a, 0x15, 0x00, 0x00, 0x00, 0x02, 0x2a, 0x16,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x2a, 0x5d,
- 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79,
- 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68,
- 0x00, 0x74, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65,
- 0x00, 0x63, 0x00, 0x68, 0x00, 0x6e, 0x00, 0x6f,
- 0x00, 0x54, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6e,
- 0x00, 0x64, 0x00, 0x20, 0x00, 0x41, 0x00, 0x47,
- 0x00, 0x00, 0x00, 0x04, 0x2a, 0x76, 0x00, 0x30,
- 0x00, 0x2e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0c,
- 0x2a, 0x7a, 0x00, 0x46, 0x00, 0x65, 0x00, 0x62,
- 0x00, 0x20, 0x00, 0x32, 0x00, 0x37, 0x00, 0x20,
- 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x31,
- 0x00, 0x00, 0x00, 0x09, 0x2a, 0x86, 0x00, 0x31,
- 0x00, 0x34, 0x00, 0x3a, 0x00, 0x33, 0x00, 0x35,
- 0x00, 0x3a, 0x00, 0x33, 0x00, 0x33, 0x00, 0x00,
- 0x00, 0x0f, 0x2a, 0x8f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x2a, 0x9e, 0x00, 0x00,
- 0x00, 0x01, 0x2a, 0x9f, 0x00, 0x00, 0x00, 0x01,
- 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x2a, 0xa1,
- 0x00, 0x00, 0x00, 0x01, 0x2a, 0xa2, 0x00, 0x00,
- 0x00, 0x01, 0x29, 0x7e, 0x00, 0x00, 0x00, 0x02,
- 0x29, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x29, 0x82, 0xff, 0xff, 0x00, 0x01, 0x2a, 0xa7,
- 0x00, 0x00, 0x00, 0x05, 0x2a, 0xa8, 0x71, 0x41,
- 0x20, 0x00, 0x20, 0x00, 0x00, 0x23, 0x04, 0x00,
- 0x00, 0x0a, 0x2a, 0xad, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x2a, 0xb7, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0xa0, 0x82, 0x40,
- 0x00, 0x08, 0x30, 0x7f, 0x00, 0x80, 0x01, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x27, 0x6e, 0x00, 0x00,
- 0x00, 0x01, 0x27, 0x6f, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x09, 0x00, 0x00, 0x1a, 0x83, 0x04, 0xe8,
- 0x04, 0xcf, 0x04, 0xc5, 0x04, 0xba, 0x04, 0xb0,
- 0x04, 0xac, 0x04, 0x9c, 0x04, 0x8c, 0x04, 0x81,
- 0x00, 0x78, 0x00, 0x00, 0x01, 0x00, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xaa, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x02, 0x23, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x05, 0xe5, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x02, 0xb5, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x0e, 0x33, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73,
- 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0x00, 0x00,
-};
-
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
index 8361101..d5f48a3 100644
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/drivers/media/dvb/ttusb-dec/Kconfig
@@ -1,7 +1,6 @@
config DVB_TTUSB_DEC
tristate "Technotrend/Hauppauge USB DEC devices"
- depends on DVB_CORE && USB
- select FW_LOADER
+ depends on DVB_CORE && USB && INPUT
select CRC32
help
Support for external USB adapters designed by Technotrend and
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 42eee04..de5829b 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -343,7 +343,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
u8 c[COMMAND_PACKET_SIZE];
int c_length;
int result;
- unsigned int tmp;
+ __be32 tmp;
dprintk("%s\n", __func__);
@@ -398,9 +398,9 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff };
- u16 pcr = htons(dec->pid[DMX_PES_PCR]);
- u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
- u16 video = htons(dec->pid[DMX_PES_VIDEO]);
+ __be16 pcr = htons(dec->pid[DMX_PES_PCR]);
+ __be16 audio = htons(dec->pid[DMX_PES_AUDIO]);
+ __be16 video = htons(dec->pid[DMX_PES_VIDEO]);
dprintk("%s\n", __func__);
@@ -435,7 +435,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
case 0x01: { /* VideoStream */
int prebytes = pva[5] & 0x03;
int postbytes = (pva[5] & 0x0c) >> 2;
- u16 v_pes_payload_length;
+ __be16 v_pes_payload_length;
if (output_pva) {
dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
@@ -1006,7 +1006,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00 };
- u16 pid;
+ __be16 pid;
u8 c[COMMAND_PACKET_SIZE];
int c_length;
int result;
@@ -1275,12 +1275,13 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
u8 b1[] = { 0x61 };
u8 *b;
char idstring[21];
- u8 *firmware = NULL;
+ const u8 *firmware = NULL;
size_t firmware_size = 0;
u16 firmware_csum = 0;
- u16 firmware_csum_ns;
- u32 firmware_size_nl;
- u32 crc32_csum, crc32_check, tmp;
+ __be16 firmware_csum_ns;
+ __be32 firmware_size_nl;
+ u32 crc32_csum, crc32_check;
+ __be32 tmp;
const struct firmware *fw_entry = NULL;
dprintk("%s\n", __func__);
@@ -1306,7 +1307,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
valid. */
crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
memcpy(&tmp, &firmware[56], 4);
- crc32_check = htonl(tmp);
+ crc32_check = ntohl(tmp);
if (crc32_csum != crc32_check) {
printk("%s: crc32 check of DSP code failed (calculated "
"0x%08x != 0x%08x in file), file invalid.\n",
@@ -1627,7 +1628,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
usb_set_intfdata(intf, (void *)dec);
- switch (le16_to_cpu(id->idProduct)) {
+ switch (id->idProduct) {
case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
break;
@@ -1652,7 +1653,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_init_dvb(dec);
dec->adapter.priv = dec;
- switch (le16_to_cpu(id->idProduct)) {
+ switch (id->idProduct) {
case 0x1006:
dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
break;
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index eb5eaec..443af24 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -86,7 +86,7 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0xff };
- u32 freq = htonl(p->frequency / 1000);
+ __be32 freq = htonl(p->frequency / 1000);
memcpy(&b[4], &freq, sizeof (u32));
state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
@@ -117,10 +117,10 @@ static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_fron
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
- u32 freq;
- u32 sym_rate;
- u32 band;
- u32 lnb_voltage;
+ __be32 freq;
+ __be32 sym_rate;
+ __be32 band;
+ __be32 lnb_voltage;
freq = htonl(p->frequency +
(state->hi_band ? LOF_HI : LOF_LO));