summaryrefslogtreecommitdiff
path: root/drivers/media/common/b2c2
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 12:49:05 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 12:49:05 +0400
commit0b8e74c6f44094189dbe78baf4101acc7570c6af (patch)
tree6440561d09fb71ba5928664604ec92f29940be6b /drivers/media/common/b2c2
parent7f60ba388f5b9dd8b0da463b394412dace3ab814 (diff)
parentbd0d10498826ed150da5e4c45baf8b9c7088fb71 (diff)
downloadlinux-0b8e74c6f44094189dbe78baf4101acc7570c6af.tar.xz
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "The first part of the media updates for Kernel 3.7. This series contain: - A major tree renaming patch series: now, drivers are organized internally by their used bus, instead of by V4L2 and/or DVB API, providing a cleaner driver location for hybrid drivers that implement both APIs, and allowing to cleanup the Kconfig items and make them more intuitive for the end user; - Media Kernel developers are typically very lazy with their duties of keeping the MAINTAINERS entries for their drivers updated. As now the tree is more organized, we're doing an effort to add/update those entries for the drivers that aren't currently orphan; - Several DVB USB drivers got moved to a new DVB USB v2 core; the new core fixes several bugs (as the existing one that got bitroted). Now, suspend/resume finally started to work fine (at least with some devices - we should expect more work with regards to it); - added multistream support for DVB-T2, and unified the API for DVB-S2 and ISDB-S. Backward binary support is preserved; - as usual, a few new drivers, some V4L2 core improvements and lots of drivers improvements and fixes. There are some points to notice on this series: 1) you should expect a trivial merge conflict on your tree, with the removal of Documentation/feature-removal-schedule.txt: this series would be adding two additional entries there. I opted to not rebase it due to this recent change; 2) With regards to the PCTV 520e udev-related breakage, I opted to fix it in a way that the patches can be backported to 3.5 even without your firmware fix patch. This way, Greg doesn't need to rush backporting your patch (as there are still the firmware cache and firmware path customization issues to be addressed there). I'll send later a patch (likely after the end of the merge window) reverting the rest of the DRX-K async firmware request, fully restoring its original behaviour to allow media drivers to initialize everything serialized as before for 3.7 and upper. 3) I'm planning to work on this weekend to test the DMABUF patches for V4L2. The patches are on my queue for several Kernel cycles, but, up to now, there is/was no way to test the series locally. I have some concerns about this particular changeset with regards to security issues, and with regards to the replacement of the old VIDIOC_OVERLAY ioctl's that is broken on modern systems, due to GPU drivers change. The Overlay API allows direct PCI2PCI transfers from a media capture card into the GPU framebuffer, but its API is crappy. Also, the only existing X11 driver that implements it requires a XV extension that is not available anymore on modern drivers. The DMABUF can do the same thing, but with it is promising to be a properly-designed API. If I can successfully test this series and be happy with it, I should be asking you to pull them next week." * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (717 commits) em28xx: regression fix: use DRX-K sync firmware requests on em28xx drxk: allow loading firmware synchrousnously em28xx: Make all em28xx extensions to be initialized asynchronously [media] tda18271: properly report read errors in tda18271_get_id [media] tda18271: delay IR & RF calibration until init() if delay_cal is set [media] MAINTAINERS: add Michael Krufky as tda827x maintainer [media] MAINTAINERS: add Michael Krufky as tda8290 maintainer [media] MAINTAINERS: add Michael Krufky as cxusb maintainer [media] MAINTAINERS: add Michael Krufky as lg2160 maintainer [media] MAINTAINERS: add Michael Krufky as lgdt3305 maintainer [media] MAINTAINERS: add Michael Krufky as mxl111sf maintainer [media] MAINTAINERS: add Michael Krufky as mxl5007t maintainer [media] MAINTAINERS: add Michael Krufky as tda18271 maintainer [media] s5p-tv: Report only multi-plane capabilities in vidioc_querycap [media] s5p-mfc: Fix misplaced return statement in s5p_mfc_suspend() [media] exynos-gsc: Add missing static storage class specifiers [media] exynos-gsc: Remove <linux/version.h> header file inclusion [media] s5p-fimc: Fix incorrect condition in fimc_lite_reqbufs() [media] s5p-tv: Fix potential NULL pointer dereference error [media] s5k6aa: Fix possible NULL pointer dereference ...
Diffstat (limited to 'drivers/media/common/b2c2')
-rw-r--r--drivers/media/common/b2c2/Kconfig28
-rw-r--r--drivers/media/common/b2c2/Makefile8
-rw-r--r--drivers/media/common/b2c2/flexcop-common.h185
-rw-r--r--drivers/media/common/b2c2/flexcop-eeprom.c147
-rw-r--r--drivers/media/common/b2c2/flexcop-fe-tuner.c678
-rw-r--r--drivers/media/common/b2c2/flexcop-hw-filter.c232
-rw-r--r--drivers/media/common/b2c2/flexcop-i2c.c288
-rw-r--r--drivers/media/common/b2c2/flexcop-misc.c86
-rw-r--r--drivers/media/common/b2c2/flexcop-reg.h166
-rw-r--r--drivers/media/common/b2c2/flexcop-sram.c363
-rw-r--r--drivers/media/common/b2c2/flexcop.c325
-rw-r--r--drivers/media/common/b2c2/flexcop.h29
-rw-r--r--drivers/media/common/b2c2/flexcop_ibi_value_be.h455
-rw-r--r--drivers/media/common/b2c2/flexcop_ibi_value_le.h455
14 files changed, 3445 insertions, 0 deletions
diff --git a/drivers/media/common/b2c2/Kconfig b/drivers/media/common/b2c2/Kconfig
new file mode 100644
index 000000000000..1df9e578daa5
--- /dev/null
+++ b/drivers/media/common/b2c2/Kconfig
@@ -0,0 +1,28 @@
+config DVB_B2C2_FLEXCOP
+ tristate
+ depends on DVB_CORE && I2C
+ depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB
+ default y
+ select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_BCM3510 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_TUNER_ITD1000 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_TUNER_CX24113 if MEDIA_SUBDRV_AUTOSELECT
+ help
+ Support for the digital TV receiver chip made by B2C2 Inc. included in
+ Technisats PCI cards and USB boxes.
+
+ Say Y if you own such a device and want to use it.
+
+# Selected via the PCI or USB flexcop drivers
+config DVB_B2C2_FLEXCOP_DEBUG
+ bool
diff --git a/drivers/media/common/b2c2/Makefile b/drivers/media/common/b2c2/Makefile
new file mode 100644
index 000000000000..24993a5b38ba
--- /dev/null
+++ b/drivers/media/common/b2c2/Makefile
@@ -0,0 +1,8 @@
+b2c2-flexcop-objs += flexcop.o flexcop-fe-tuner.o flexcop-i2c.o
+b2c2-flexcop-objs += flexcop-sram.o flexcop-eeprom.o flexcop-misc.o
+b2c2-flexcop-objs += flexcop-hw-filter.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
diff --git a/drivers/media/common/b2c2/flexcop-common.h b/drivers/media/common/b2c2/flexcop-common.h
new file mode 100644
index 000000000000..437912e49824
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-common.h
@@ -0,0 +1,185 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-common.h - common header file for device-specific source files
+ * see flexcop.c for copyright information
+ */
+#ifndef __FLEXCOP_COMMON_H__
+#define __FLEXCOP_COMMON_H__
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+
+#include "flexcop-reg.h"
+
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_filter.h"
+#include "dvb_net.h"
+#include "dvb_frontend.h"
+
+#define FC_MAX_FEED 256
+
+#ifndef FC_LOG_PREFIX
+#warning please define a log prefix for your file, using a default one
+#define FC_LOG_PREFIX "b2c2-undef"
+#endif
+
+/* Steal from usb.h */
+#undef err
+#define err(format, arg...) \
+ printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) \
+ printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) \
+ printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg)
+
+struct flexcop_dma {
+ struct pci_dev *pdev;
+
+ u8 *cpu_addr0;
+ dma_addr_t dma_addr0;
+ u8 *cpu_addr1;
+ dma_addr_t dma_addr1;
+ u32 size; /* size of each address in bytes */
+};
+
+struct flexcop_i2c_adapter {
+ struct flexcop_device *fc;
+ struct i2c_adapter i2c_adap;
+
+ u8 no_base_addr;
+ flexcop_i2c_port_t port;
+};
+
+/* Control structure for data definitions that are common to
+ * the B2C2-based PCI and USB devices.
+ */
+struct flexcop_device {
+ /* general */
+ struct device *dev; /* for firmware_class */
+
+#define FC_STATE_DVB_INIT 0x01
+#define FC_STATE_I2C_INIT 0x02
+#define FC_STATE_FE_INIT 0x04
+ int init_state;
+
+ /* device information */
+ int has_32_hw_pid_filter;
+ flexcop_revision_t rev;
+ flexcop_device_type_t dev_type;
+ flexcop_bus_t bus_type;
+
+ /* dvb stuff */
+ struct dvb_adapter dvb_adapter;
+ struct dvb_frontend *fe;
+ struct dvb_net dvbnet;
+ struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
+ int (*fe_sleep) (struct dvb_frontend *);
+
+ struct flexcop_i2c_adapter fc_i2c_adap[3];
+ struct mutex i2c_mutex;
+ struct module *owner;
+
+ /* options and status */
+ int extra_feedcount;
+ int feedcount;
+ int pid_filtering;
+ int fullts_streaming_state;
+
+ /* bus specific callbacks */
+ flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *,
+ flexcop_ibi_register);
+ int (*write_ibi_reg) (struct flexcop_device *,
+ flexcop_ibi_register, flexcop_ibi_value);
+ int (*i2c_request) (struct flexcop_i2c_adapter *,
+ flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+ int (*stream_control) (struct flexcop_device *, int);
+ int (*get_mac_addr) (struct flexcop_device *fc, int extended);
+ void *bus_specific;
+};
+
+/* exported prototypes */
+
+/* from flexcop.c */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len);
+void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no);
+
+struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len);
+void flexcop_device_kfree(struct flexcop_device *);
+
+int flexcop_device_initialize(struct flexcop_device *);
+void flexcop_device_exit(struct flexcop_device *fc);
+void flexcop_reset_block_300(struct flexcop_device *fc);
+
+/* from flexcop-dma.c */
+int flexcop_dma_allocate(struct pci_dev *pdev,
+ struct flexcop_dma *dma, u32 size);
+void flexcop_dma_free(struct flexcop_dma *dma);
+
+int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
+ flexcop_dma_index_t no, int onoff);
+int flexcop_dma_control_size_irq(struct flexcop_device *fc,
+ flexcop_dma_index_t no, int onoff);
+int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma,
+ flexcop_dma_index_t dma_idx);
+int flexcop_dma_xfer_control(struct flexcop_device *fc,
+ flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index,
+ int onoff);
+int flexcop_dma_config_timer(struct flexcop_device *fc,
+ flexcop_dma_index_t dma_idx, u8 cycles);
+
+/* from flexcop-eeprom.c */
+/* the PCI part uses this call to get the MAC address, the USB part has its own */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
+
+/* from flexcop-i2c.c */
+/* the PCI part uses this a i2c_request callback, whereas the usb part has its own
+ * one. We have it in flexcop-i2c.c, because it is going via the actual
+ * I2C-channel of the flexcop.
+ */
+int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
+ u8 chipaddr, u8 addr, u8 *buf, u16 len);
+
+/* from flexcop-sram.c */
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest,
+ flexcop_sram_dest_target_t target);
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s);
+void flexcop_sram_ctrl(struct flexcop_device *fc,
+ int usb_wan, int sramdma, int maximumfill);
+
+/* global prototypes for the flexcop-chip */
+/* from flexcop-fe-tuner.c */
+int flexcop_frontend_init(struct flexcop_device *fc);
+void flexcop_frontend_exit(struct flexcop_device *fc);
+
+/* from flexcop-i2c.c */
+int flexcop_i2c_init(struct flexcop_device *fc);
+void flexcop_i2c_exit(struct flexcop_device *fc);
+
+/* from flexcop-sram.c */
+int flexcop_sram_init(struct flexcop_device *fc);
+
+/* from flexcop-misc.c */
+void flexcop_determine_revision(struct flexcop_device *fc);
+void flexcop_device_name(struct flexcop_device *fc,
+ const char *prefix, const char *suffix);
+void flexcop_dump_reg(struct flexcop_device *fc,
+ flexcop_ibi_register reg, int num);
+
+/* from flexcop-hw-filter.c */
+int flexcop_pid_feed_control(struct flexcop_device *fc,
+ struct dvb_demux_feed *dvbdmxfeed, int onoff);
+void flexcop_hw_filter_init(struct flexcop_device *fc);
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff);
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]);
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff);
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop-eeprom.c b/drivers/media/common/b2c2/flexcop-eeprom.c
new file mode 100644
index 000000000000..a25373a9bd84
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-eeprom.c
@@ -0,0 +1,147 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading)
+ * see flexcop.c for copyright information
+ */
+#include "flexcop.h"
+
+#if 0
+/*EEPROM (Skystar2 has one "24LC08B" chip on board) */
+static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
+{
+ return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len);
+}
+
+static int eeprom_lrc_write(struct adapter *adapter, u32 addr,
+ u32 len, u8 *wbuf, u8 *rbuf, int retries)
+{
+int i;
+
+for (i = 0; i < retries; i++) {
+ if (eeprom_write(adapter, addr, wbuf, len) == len) {
+ if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* These functions could be used to unlock SkyStar2 cards. */
+
+static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
+{
+ u8 rbuf[20];
+ u8 wbuf[20];
+
+ if (len != 16)
+ return 0;
+
+ memcpy(wbuf, key, len);
+ wbuf[16] = 0;
+ wbuf[17] = 0;
+ wbuf[18] = 0;
+ wbuf[19] = calc_lrc(wbuf, 19);
+ return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4);
+}
+
+static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
+{
+ u8 buf[20];
+
+ if (len != 16)
+ return 0;
+
+ if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0)
+ return 0;
+
+ memcpy(key, buf, len);
+ return 1;
+}
+
+static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
+{
+ u8 tmp[8];
+
+ if (type != 0) {
+ tmp[0] = mac[0];
+ tmp[1] = mac[1];
+ tmp[2] = mac[2];
+ tmp[3] = mac[5];
+ tmp[4] = mac[6];
+ tmp[5] = mac[7];
+ } else {
+ tmp[0] = mac[0];
+ tmp[1] = mac[1];
+ tmp[2] = mac[2];
+ tmp[3] = mac[3];
+ tmp[4] = mac[4];
+ tmp[5] = mac[5];
+ }
+
+ tmp[6] = 0;
+ tmp[7] = calc_lrc(tmp, 7);
+
+ if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8)
+ return 1;
+ return 0;
+}
+
+static int flexcop_eeprom_read(struct flexcop_device *fc,
+ u16 addr, u8 *buf, u16 len)
+{
+ return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
+}
+
+#endif
+
+static u8 calc_lrc(u8 *buf, int len)
+{
+ int i;
+ u8 sum = 0;
+ for (i = 0; i < len; i++)
+ sum = sum ^ buf[i];
+ return sum;
+}
+
+static int flexcop_eeprom_request(struct flexcop_device *fc,
+ flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries)
+{
+ int i,ret = 0;
+ u8 chipaddr = 0x50 | ((addr >> 8) & 3);
+ for (i = 0; i < retries; i++) {
+ ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
+ addr & 0xff, buf, len);
+ if (ret == 0)
+ break;
+ }
+ return ret;
+}
+
+static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr,
+ u8 *buf, u16 len, int retries)
+{
+ int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
+ if (ret == 0)
+ if (calc_lrc(buf, len - 1) != buf[len - 1])
+ ret = -EINVAL;
+ return ret;
+}
+
+/* JJ's comment about extended == 1: it is not presently used anywhere but was
+ * added to the low-level functions for possible support of EUI64 */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
+{
+ u8 buf[8];
+ int ret = 0;
+
+ if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) {
+ if (extended != 0) {
+ err("TODO: extended (EUI64) MAC addresses aren't "
+ "completely supported yet");
+ ret = -EINVAL;
+ } else
+ memcpy(fc->dvb_adapter.proposed_mac,buf,6);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c
new file mode 100644
index 000000000000..850a6c606750
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c
@@ -0,0 +1,678 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling
+ * see flexcop.c for copyright information
+ */
+#include <media/tuner.h>
+#include "flexcop.h"
+#include "mt312.h"
+#include "stv0299.h"
+#include "s5h1420.h"
+#include "itd1000.h"
+#include "cx24113.h"
+#include "cx24123.h"
+#include "isl6421.h"
+#include "mt352.h"
+#include "bcm3510.h"
+#include "nxt200x.h"
+#include "dvb-pll.h"
+#include "lgdt330x.h"
+#include "tuner-simple.h"
+#include "stv0297.h"
+
+
+/* Can we use the specified front-end? Remember that if we are compiled
+ * into the kernel we can't call code that's in modules. */
+#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
+ (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
+
+/* lnb control */
+#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
+static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+ flexcop_ibi_value v;
+ deb_tuner("polarity/voltage = %u\n", voltage);
+
+ v = fc->read_ibi_reg(fc, misc_204);
+ switch (voltage) {
+ case SEC_VOLTAGE_OFF:
+ v.misc_204.ACPI1_sig = 1;
+ break;
+ case SEC_VOLTAGE_13:
+ v.misc_204.ACPI1_sig = 0;
+ v.misc_204.LNB_L_H_sig = 0;
+ break;
+ case SEC_VOLTAGE_18:
+ v.misc_204.ACPI1_sig = 0;
+ v.misc_204.LNB_L_H_sig = 1;
+ break;
+ default:
+ err("unknown SEC_VOLTAGE value");
+ return -EINVAL;
+ }
+ return fc->write_ibi_reg(fc, misc_204, v);
+}
+#endif
+
+#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
+static int flexcop_sleep(struct dvb_frontend* fe)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+ if (fc->fe_sleep)
+ return fc->fe_sleep(fe);
+ return 0;
+}
+#endif
+
+/* SkyStar2 DVB-S rev 2.3 */
+#if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL)
+static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
+ struct flexcop_device *fc = fe->dvb->priv;
+ flexcop_ibi_value v;
+ u16 ax;
+ v.raw = 0;
+ deb_tuner("tone = %u\n",tone);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ ax = 0x01ff;
+ break;
+ case SEC_TONE_OFF:
+ ax = 0;
+ break;
+ default:
+ err("unknown SEC_TONE value");
+ return -EINVAL;
+ }
+
+ v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
+ v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
+ v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax;
+ return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
+}
+
+static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
+{
+ flexcop_set_tone(fe, SEC_TONE_ON);
+ udelay(data ? 500 : 1000);
+ flexcop_set_tone(fe, SEC_TONE_OFF);
+ udelay(data ? 1000 : 500);
+}
+
+static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
+{
+ int i, par = 1, d;
+ for (i = 7; i >= 0; i--) {
+ d = (data >> i) & 1;
+ par ^= d;
+ flexcop_diseqc_send_bit(fe, d);
+ }
+ flexcop_diseqc_send_bit(fe, par);
+}
+
+static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
+ int len, u8 *msg, unsigned long burst)
+{
+ int i;
+
+ flexcop_set_tone(fe, SEC_TONE_OFF);
+ mdelay(16);
+
+ for (i = 0; i < len; i++)
+ flexcop_diseqc_send_byte(fe,msg[i]);
+ mdelay(16);
+
+ if (burst != -1) {
+ if (burst)
+ flexcop_diseqc_send_byte(fe, 0xff);
+ else {
+ flexcop_set_tone(fe, SEC_TONE_ON);
+ mdelay(12);
+ udelay(500);
+ flexcop_set_tone(fe, SEC_TONE_OFF);
+ }
+ msleep(20);
+ }
+ return 0;
+}
+
+static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe,
+ struct dvb_diseqc_master_cmd *cmd)
+{
+ return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
+}
+
+static int flexcop_diseqc_send_burst(struct dvb_frontend *fe,
+ fe_sec_mini_cmd_t minicmd)
+{
+ return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
+}
+
+static struct mt312_config skystar23_samsung_tbdu18132_config = {
+ .demod_address = 0x0e,
+};
+
+static int skystar2_rev23_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ struct dvb_frontend_ops *ops;
+
+ fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
+ if (!fc->fe)
+ return 0;
+
+ if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
+ DVB_PLL_SAMSUNG_TBDU18132))
+ return 0;
+
+ ops = &fc->fe->ops;
+ ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
+ ops->diseqc_send_burst = flexcop_diseqc_send_burst;
+ ops->set_tone = flexcop_set_tone;
+ ops->set_voltage = flexcop_set_voltage;
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
+ return 1;
+}
+#else
+#define skystar2_rev23_attach NULL
+#endif
+
+/* SkyStar2 DVB-S rev 2.6 */
+#if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL)
+static int samsung_tbmu24112_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 samsung_tbmu24112_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x30,
+ 0x03, 0x00,
+ 0x04, 0x7D,
+ 0x05, 0x35,
+ 0x06, 0x02,
+ 0x07, 0x00,
+ 0x08, 0xC3,
+ 0x0C, 0x00,
+ 0x0D, 0x81,
+ 0x0E, 0x23,
+ 0x0F, 0x12,
+ 0x10, 0x7E,
+ 0x11, 0x84,
+ 0x12, 0xB9,
+ 0x13, 0x88,
+ 0x14, 0x89,
+ 0x15, 0xC9,
+ 0x16, 0x00,
+ 0x17, 0x5C,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1A, 0x00,
+ 0x1C, 0x00,
+ 0x1D, 0x00,
+ 0x1E, 0x00,
+ 0x1F, 0x3A,
+ 0x20, 0x2E,
+ 0x21, 0x80,
+ 0x22, 0xFF,
+ 0x23, 0xC1,
+ 0x28, 0x00,
+ 0x29, 0x1E,
+ 0x2A, 0x14,
+ 0x2B, 0x0F,
+ 0x2C, 0x09,
+ 0x2D, 0x05,
+ 0x31, 0x1F,
+ 0x32, 0x19,
+ 0x33, 0xFE,
+ 0x34, 0x93,
+ 0xff, 0xff,
+};
+
+static struct stv0299_config samsung_tbmu24112_config = {
+ .demod_address = 0x68,
+ .inittab = samsung_tbmu24112_inittab,
+ .mclk = 88000000UL,
+ .invert = 0,
+ .skip_reinit = 0,
+ .lock_output = STV0299_LOCKOUTPUT_LK,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
+};
+
+static int skystar2_rev26_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
+ if (!fc->fe)
+ return 0;
+
+ if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
+ DVB_PLL_SAMSUNG_TBMU24112))
+ return 0;
+
+ fc->fe->ops.set_voltage = flexcop_set_voltage;
+ fc->fe_sleep = fc->fe->ops.sleep;
+ fc->fe->ops.sleep = flexcop_sleep;
+ return 1;
+
+}
+#else
+#define skystar2_rev26_attach NULL
+#endif
+
+/* SkyStar2 DVB-S rev 2.7 */
+#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
+static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
+ .demod_address = 0x53,
+ .invert = 1,
+ .repeated_start_workaround = 1,
+ .serial_mpeg = 1,
+};
+
+static struct itd1000_config skystar2_rev2_7_itd1000_config = {
+ .i2c_address = 0x61,
+};
+
+static int skystar2_rev27_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ flexcop_ibi_value r108;
+ struct i2c_adapter *i2c_tuner;
+
+ /* enable no_base_addr - no repeated start when reading */
+ fc->fc_i2c_adap[0].no_base_addr = 1;
+ fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
+ i2c);
+ if (!fc->fe)
+ goto fail;
+
+ i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+ if (!i2c_tuner)
+ goto fail;
+
+ fc->fe_sleep = fc->fe->ops.sleep;
+ fc->fe->ops.sleep = flexcop_sleep;
+
+ /* enable no_base_addr - no repeated start when reading */
+ fc->fc_i2c_adap[2].no_base_addr = 1;
+ if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+ 0x08, 1, 1)) {
+ err("ISL6421 could NOT be attached");
+ goto fail_isl;
+ }
+ info("ISL6421 successfully attached");
+
+ /* the ITD1000 requires a lower i2c clock - is it a problem ? */
+ r108.raw = 0x00000506;
+ fc->write_ibi_reg(fc, tw_sm_c_108, r108);
+ if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
+ &skystar2_rev2_7_itd1000_config)) {
+ err("ITD1000 could NOT be attached");
+ /* Should i2c clock be restored? */
+ goto fail_isl;
+ }
+ info("ITD1000 successfully attached");
+
+ return 1;
+
+fail_isl:
+ fc->fc_i2c_adap[2].no_base_addr = 0;
+fail:
+ /* for the next devices we need it again */
+ fc->fc_i2c_adap[0].no_base_addr = 0;
+ return 0;
+}
+#else
+#define skystar2_rev27_attach NULL
+#endif
+
+/* SkyStar2 rev 2.8 */
+#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
+static struct cx24123_config skystar2_rev2_8_cx24123_config = {
+ .demod_address = 0x55,
+ .dont_use_pll = 1,
+ .agc_callback = cx24113_agc_callback,
+};
+
+static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
+ .i2c_addr = 0x54,
+ .xtal_khz = 10111,
+};
+
+static int skystar2_rev28_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ struct i2c_adapter *i2c_tuner;
+
+ fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
+ i2c);
+ if (!fc->fe)
+ return 0;
+
+ i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
+ if (!i2c_tuner)
+ return 0;
+
+ if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
+ i2c_tuner)) {
+ err("CX24113 could NOT be attached");
+ return 0;
+ }
+ info("CX24113 successfully attached");
+
+ fc->fc_i2c_adap[2].no_base_addr = 1;
+ if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+ 0x08, 0, 0)) {
+ err("ISL6421 could NOT be attached");
+ fc->fc_i2c_adap[2].no_base_addr = 0;
+ return 0;
+ }
+ info("ISL6421 successfully attached");
+ /* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
+ * IR-receiver (PIC16F818) - but the card has no input for that ??? */
+ return 1;
+}
+#else
+#define skystar2_rev28_attach NULL
+#endif
+
+/* AirStar DVB-T */
+#if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL)
+static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
+{
+ static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
+ static u8 mt352_reset[] = { 0x50, 0x80 };
+ static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
+ static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
+ static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+ mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+ udelay(2000);
+ mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+ mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+ mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+ mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+ return 0;
+}
+
+static struct mt352_config samsung_tdtc9251dh0_config = {
+ .demod_address = 0x0f,
+ .demod_init = samsung_tdtc9251dh0_demod_init,
+};
+
+static int airstar_dvbt_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
+ if (!fc->fe)
+ return 0;
+
+ return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
+ DVB_PLL_SAMSUNG_TDTC9251DH0);
+}
+#else
+#define airstar_dvbt_attach NULL
+#endif
+
+/* AirStar ATSC 1st generation */
+#if FE_SUPPORTED(BCM3510)
+static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
+ const struct firmware **fw, char* name)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+ return request_firmware(fw, name, fc->dev);
+}
+
+static struct bcm3510_config air2pc_atsc_first_gen_config = {
+ .demod_address = 0x0f,
+ .request_firmware = flexcop_fe_request_firmware,
+};
+
+static int airstar_atsc1_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
+ return fc->fe != NULL;
+}
+#else
+#define airstar_atsc1_attach NULL
+#endif
+
+/* AirStar ATSC 2nd generation */
+#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
+static struct nxt200x_config samsung_tbmv_config = {
+ .demod_address = 0x0a,
+};
+
+static int airstar_atsc2_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
+ if (!fc->fe)
+ return 0;
+
+ return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
+ DVB_PLL_SAMSUNG_TBMV);
+}
+#else
+#define airstar_atsc2_attach NULL
+#endif
+
+/* AirStar ATSC 3rd generation */
+#if FE_SUPPORTED(LGDT330X)
+static struct lgdt330x_config air2pc_atsc_hd5000_config = {
+ .demod_address = 0x59,
+ .demod_chip = LGDT3303,
+ .serial_mpeg = 0x04,
+ .clock_polarity_flip = 1,
+};
+
+static int airstar_atsc3_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
+ if (!fc->fe)
+ return 0;
+
+ return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
+ TUNER_LG_TDVS_H06XF);
+}
+#else
+#define airstar_atsc3_attach NULL
+#endif
+
+/* CableStar2 DVB-C */
+#if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL)
+static u8 alps_tdee4_stv0297_inittab[] = {
+ 0x80, 0x01,
+ 0x80, 0x00,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x48,
+ 0x01, 0x58,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x30, 0xff,
+ 0x31, 0x9d,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x29,
+ 0x35, 0x55,
+ 0x36, 0x80,
+ 0x37, 0x6e,
+ 0x38, 0x9c,
+ 0x40, 0x1a,
+ 0x41, 0xfe,
+ 0x42, 0x33,
+ 0x43, 0x00,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0x51,
+ 0x4b, 0xf8,
+ 0x52, 0x30,
+ 0x53, 0x06,
+ 0x59, 0x06,
+ 0x5a, 0x5e,
+ 0x5b, 0x04,
+ 0x61, 0x49,
+ 0x62, 0x0a,
+ 0x70, 0xff,
+ 0x71, 0x04,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x20,
+ 0x81, 0x00,
+ 0x82, 0x30,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x22,
+ 0x86, 0x08,
+ 0x87, 0x1b,
+ 0x88, 0x00,
+ 0x89, 0x00,
+ 0x90, 0x00,
+ 0x91, 0x04,
+ 0xa0, 0x86,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x5b,
+ 0xc1, 0x10,
+ 0xc2, 0x12,
+ 0xd0, 0x02,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x02,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x01,
+ 0xff, 0xff,
+};
+
+static struct stv0297_config alps_tdee4_stv0297_config = {
+ .demod_address = 0x1c,
+ .inittab = alps_tdee4_stv0297_inittab,
+};
+
+static int cablestar2_attach(struct flexcop_device *fc,
+ struct i2c_adapter *i2c)
+{
+ fc->fc_i2c_adap[0].no_base_addr = 1;
+ fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
+ if (!fc->fe)
+ goto fail;
+
+ /* This tuner doesn't use the stv0297's I2C gate, but instead the
+ * tuner is connected to a different flexcop I2C adapter. */
+ if (fc->fe->ops.i2c_gate_ctrl)
+ fc->fe->ops.i2c_gate_ctrl(fc->fe, 0);
+ fc->fe->ops.i2c_gate_ctrl = NULL;
+
+ if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61,
+ &fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4))
+ goto fail;
+
+ return 1;
+
+fail:
+ /* Reset for next frontend to try */
+ fc->fc_i2c_adap[0].no_base_addr = 0;
+ return 0;
+}
+#else
+#define cablestar2_attach NULL
+#endif
+
+static struct {
+ flexcop_device_type_t type;
+ int (*attach)(struct flexcop_device *, struct i2c_adapter *);
+} flexcop_frontends[] = {
+ { FC_SKY_REV27, skystar2_rev27_attach },
+ { FC_SKY_REV28, skystar2_rev28_attach },
+ { FC_SKY_REV26, skystar2_rev26_attach },
+ { FC_AIR_DVBT, airstar_dvbt_attach },
+ { FC_AIR_ATSC2, airstar_atsc2_attach },
+ { FC_AIR_ATSC3, airstar_atsc3_attach },
+ { FC_AIR_ATSC1, airstar_atsc1_attach },
+ { FC_CABLE, cablestar2_attach },
+ { FC_SKY_REV23, skystar2_rev23_attach },
+};
+
+/* try to figure out the frontend */
+int flexcop_frontend_init(struct flexcop_device *fc)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
+ if (!flexcop_frontends[i].attach)
+ continue;
+ /* type needs to be set before, because of some workarounds
+ * done based on the probed card type */
+ fc->dev_type = flexcop_frontends[i].type;
+ if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
+ goto fe_found;
+ /* Clean up partially attached frontend */
+ if (fc->fe) {
+ dvb_frontend_detach(fc->fe);
+ fc->fe = NULL;
+ }
+ }
+ fc->dev_type = FC_UNK;
+ err("no frontend driver found for this B2C2/FlexCop adapter");
+ return -ENODEV;
+
+fe_found:
+ info("found '%s' .", fc->fe->ops.info.name);
+ if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+ err("frontend registration failed!");
+ dvb_frontend_detach(fc->fe);
+ fc->fe = NULL;
+ return -EINVAL;
+ }
+ fc->init_state |= FC_STATE_FE_INIT;
+ return 0;
+}
+
+void flexcop_frontend_exit(struct flexcop_device *fc)
+{
+ if (fc->init_state & FC_STATE_FE_INIT) {
+ dvb_unregister_frontend(fc->fe);
+ dvb_frontend_detach(fc->fe);
+ }
+ fc->init_state &= ~FC_STATE_FE_INIT;
+}
diff --git a/drivers/media/common/b2c2/flexcop-hw-filter.c b/drivers/media/common/b2c2/flexcop-hw-filter.c
new file mode 100644
index 000000000000..77e45475f4c7
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-hw-filter.c
@@ -0,0 +1,232 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-hw-filter.c - pid and mac address filtering and control functions
+ * see flexcop.c for copyright information
+ */
+#include "flexcop.h"
+
+static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff);
+ deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off");
+}
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff);
+}
+
+static void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208, Null_filter_sig, onoff);
+}
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
+{
+ flexcop_ibi_value v418, v41c;
+ v41c = fc->read_ibi_reg(fc, mac_address_41c);
+
+ v418.mac_address_418.MAC1 = mac[0];
+ v418.mac_address_418.MAC2 = mac[1];
+ v418.mac_address_418.MAC3 = mac[2];
+ v418.mac_address_418.MAC6 = mac[3];
+ v41c.mac_address_41c.MAC7 = mac[4];
+ v41c.mac_address_41c.MAC8 = mac[5];
+
+ fc->write_ibi_reg(fc, mac_address_418, v418);
+ fc->write_ibi_reg(fc, mac_address_41c, v41c);
+}
+
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208, MAC_filter_Mode_sig, onoff);
+}
+
+static void flexcop_pid_group_filter(struct flexcop_device *fc,
+ u16 pid, u16 mask)
+{
+ /* index_reg_310.extra_index_reg need to 0 or 7 to work */
+ flexcop_ibi_value v30c;
+ v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid;
+ v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask;
+ fc->write_ibi_reg(fc, pid_filter_30c, v30c);
+}
+
+static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208, Mask_filter_sig, onoff);
+}
+
+/* this fancy define reduces the code size of the quite similar PID controlling of
+ * the first 6 PIDs
+ */
+
+#define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
+ flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
+v208 = fc->read_ibi_reg(fc, ctrl_208); \
+vpid.vregname.field = onoff ? pid : 0x1fff; \
+vpid.vregname.trans_field = transval; \
+v208.ctrl_208.enablefield = onoff; \
+fc->write_ibi_reg(fc, vregname, vpid); \
+fc->write_ibi_reg(fc, ctrl_208, v208);
+
+static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc,
+ u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_300, Stream1_PID, Stream1_filter_sig,
+ Stream1_trans, 0);
+}
+
+static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc,
+ u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_300, Stream2_PID, Stream2_filter_sig,
+ Stream2_trans, 0);
+}
+
+static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc,
+ u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_304, PCR_PID, PCR_filter_sig, PCR_trans, 0);
+}
+
+static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc,
+ u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_304, PMT_PID, PMT_filter_sig, PMT_trans, 0);
+}
+
+static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc,
+ u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_308, EMM_PID, EMM_filter_sig, EMM_trans, 0);
+}
+
+static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc,
+ u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_308, ECM_PID, ECM_filter_sig, ECM_trans, 0);
+}
+
+static void flexcop_pid_control(struct flexcop_device *fc,
+ int index, u16 pid, int onoff)
+{
+ if (pid == 0x2000)
+ return;
+
+ deb_ts("setting pid: %5d %04x at index %d '%s'\n",
+ pid, pid, index, onoff ? "on" : "off");
+
+ /* We could use bit magic here to reduce source code size.
+ * I decided against it, but to use the real register names */
+ switch (index) {
+ case 0:
+ flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff);
+ break;
+ case 1:
+ flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff);
+ break;
+ case 2:
+ flexcop_pid_PCR_PID_ctrl(fc, pid, onoff);
+ break;
+ case 3:
+ flexcop_pid_PMT_PID_ctrl(fc, pid, onoff);
+ break;
+ case 4:
+ flexcop_pid_EMM_PID_ctrl(fc, pid, onoff);
+ break;
+ case 5:
+ flexcop_pid_ECM_PID_ctrl(fc, pid, onoff);
+ break;
+ default:
+ if (fc->has_32_hw_pid_filter && index < 38) {
+ flexcop_ibi_value vpid, vid;
+
+ /* set the index */
+ vid = fc->read_ibi_reg(fc, index_reg_310);
+ vid.index_reg_310.index_reg = index - 6;
+ fc->write_ibi_reg(fc, index_reg_310, vid);
+
+ vpid = fc->read_ibi_reg(fc, pid_n_reg_314);
+ vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
+ vpid.pid_n_reg_314.PID_enable_bit = onoff;
+ fc->write_ibi_reg(fc, pid_n_reg_314, vpid);
+ }
+ break;
+ }
+}
+
+static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc, int onoff)
+{
+ if (fc->fullts_streaming_state != onoff) {
+ deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling");
+ flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
+ flexcop_pid_group_filter_ctrl(fc, onoff);
+ fc->fullts_streaming_state = onoff;
+ }
+ return 0;
+}
+
+int flexcop_pid_feed_control(struct flexcop_device *fc,
+ struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+ int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
+
+ fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */
+ if (dvbdmxfeed->index >= max_pid_filter)
+ fc->extra_feedcount += onoff ? 1 : -1;
+
+ /* toggle complete-TS-streaming when:
+ * - pid_filtering is not enabled and it is the first or last feed requested
+ * - pid_filtering is enabled,
+ * - but the number of requested feeds is exceeded
+ * - or the requested pid is 0x2000 */
+
+ if (!fc->pid_filtering && fc->feedcount == onoff)
+ flexcop_toggle_fullts_streaming(fc, onoff);
+
+ if (fc->pid_filtering) {
+ flexcop_pid_control \
+ (fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
+
+ if (fc->extra_feedcount > 0)
+ flexcop_toggle_fullts_streaming(fc, 1);
+ else if (dvbdmxfeed->pid == 0x2000)
+ flexcop_toggle_fullts_streaming(fc, onoff);
+ else
+ flexcop_toggle_fullts_streaming(fc, 0);
+ }
+
+ /* if it was the first or last feed request change the stream-status */
+ if (fc->feedcount == onoff) {
+ flexcop_rcv_data_ctrl(fc, onoff);
+ if (fc->stream_control) /* device specific stream control */
+ fc->stream_control(fc, onoff);
+
+ /* feeding stopped -> reset the flexcop filter*/
+ if (onoff == 0) {
+ flexcop_reset_block_300(fc);
+ flexcop_hw_filter_init(fc);
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_pid_feed_control);
+
+void flexcop_hw_filter_init(struct flexcop_device *fc)
+{
+ int i;
+ flexcop_ibi_value v;
+ for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
+ flexcop_pid_control(fc, i, 0x1fff, 0);
+
+ flexcop_pid_group_filter(fc, 0, 0x1fe0);
+ flexcop_pid_group_filter_ctrl(fc, 0);
+
+ v = fc->read_ibi_reg(fc, pid_filter_308);
+ v.pid_filter_308.EMM_filter_4 = 1;
+ v.pid_filter_308.EMM_filter_6 = 0;
+ fc->write_ibi_reg(fc, pid_filter_308, v);
+
+ flexcop_null_filter_ctrl(fc, 1);
+}
diff --git a/drivers/media/common/b2c2/flexcop-i2c.c b/drivers/media/common/b2c2/flexcop-i2c.c
new file mode 100644
index 000000000000..965d5eb33752
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-i2c.c
@@ -0,0 +1,288 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
+ * see flexcop.c for copyright information
+ */
+#include "flexcop.h"
+
+#define FC_MAX_I2C_RETRIES 100000
+
+static int flexcop_i2c_operation(struct flexcop_device *fc,
+ flexcop_ibi_value *r100)
+{
+ int i;
+ flexcop_ibi_value r;
+
+ r100->tw_sm_c_100.working_start = 1;
+ deb_i2c("r100 before: %08x\n",r100->raw);
+
+ fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
+ fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */
+
+ for (i = 0; i < FC_MAX_I2C_RETRIES; i++) {
+ r = fc->read_ibi_reg(fc, tw_sm_c_100);
+
+ if (!r.tw_sm_c_100.no_base_addr_ack_error) {
+ if (r.tw_sm_c_100.st_done) {
+ *r100 = r;
+ deb_i2c("i2c success\n");
+ return 0;
+ }
+ } else {
+ deb_i2c("suffering from an i2c ack_error\n");
+ return -EREMOTEIO;
+ }
+ }
+ deb_i2c("tried %d times i2c operation, "
+ "never finished or too many ack errors.\n", i);
+ return -EREMOTEIO;
+}
+
+static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
+ flexcop_ibi_value r100, u8 *buf)
+{
+ flexcop_ibi_value r104;
+ int len = r100.tw_sm_c_100.total_bytes,
+ /* remember total_bytes is buflen-1 */
+ ret;
+
+ /* work-around to have CableStar2 and SkyStar2 rev 2.7 work
+ * correctly:
+ *
+ * the ITD1000 is behind an i2c-gate which closes automatically
+ * after an i2c-transaction the STV0297 needs 2 consecutive reads
+ * one with no_base_addr = 0 and one with 1
+ *
+ * those two work-arounds are conflictin: we check for the card
+ * type, it is set when probing the ITD1000 */
+ if (i2c->fc->dev_type == FC_SKY_REV27)
+ r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
+
+ ret = flexcop_i2c_operation(i2c->fc, &r100);
+ if (ret != 0) {
+ deb_i2c("Retrying operation\n");
+ r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
+ ret = flexcop_i2c_operation(i2c->fc, &r100);
+ }
+ if (ret != 0) {
+ deb_i2c("read failed. %d\n", ret);
+ return ret;
+ }
+
+ buf[0] = r100.tw_sm_c_100.data1_reg;
+
+ if (len > 0) {
+ r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
+ deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+
+ /* there is at least one more byte, otherwise we wouldn't be here */
+ buf[1] = r104.tw_sm_c_104.data2_reg;
+ if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
+ if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
+ }
+ return 0;
+}
+
+static int flexcop_i2c_write4(struct flexcop_device *fc,
+ flexcop_ibi_value r100, u8 *buf)
+{
+ flexcop_ibi_value r104;
+ int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
+ r104.raw = 0;
+
+ /* there is at least one byte, otherwise we wouldn't be here */
+ r100.tw_sm_c_100.data1_reg = buf[0];
+ r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;
+ r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
+ r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
+
+ deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+
+ /* write the additional i2c data before doing the actual i2c operation */
+ fc->write_ibi_reg(fc, tw_sm_c_104, r104);
+ return flexcop_i2c_operation(fc, &r100);
+}
+
+int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
+ flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+{
+ int ret;
+
+#ifdef DUMP_I2C_MESSAGES
+ int i;
+#endif
+
+ u16 bytes_to_transfer;
+ flexcop_ibi_value r100;
+
+ deb_i2c("op = %d\n",op);
+ r100.raw = 0;
+ r100.tw_sm_c_100.chipaddr = chipaddr;
+ r100.tw_sm_c_100.twoWS_rw = op;
+ r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
+
+#ifdef DUMP_I2C_MESSAGES
+ printk(KERN_DEBUG "%d ", i2c->port);
+ if (op == FC_READ)
+ printk("rd(");
+ else
+ printk("wr(");
+ printk("%02x): %02x ", chipaddr, addr);
+#endif
+
+ /* in that case addr is the only value ->
+ * we write it twice as baseaddr and val0
+ * BBTI is doing it like that for ISL6421 at least */
+ if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
+ buf = &addr;
+ len = 1;
+ }
+
+ while (len != 0) {
+ bytes_to_transfer = len > 4 ? 4 : len;
+
+ r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
+ r100.tw_sm_c_100.baseaddr = addr;
+
+ if (op == FC_READ)
+ ret = flexcop_i2c_read4(i2c, r100, buf);
+ else
+ ret = flexcop_i2c_write4(i2c->fc, r100, buf);
+
+#ifdef DUMP_I2C_MESSAGES
+ for (i = 0; i < bytes_to_transfer; i++)
+ printk("%02x ", buf[i]);
+#endif
+
+ if (ret < 0)
+ return ret;
+
+ buf += bytes_to_transfer;
+ addr += bytes_to_transfer;
+ len -= bytes_to_transfer;
+ }
+
+#ifdef DUMP_I2C_MESSAGES
+ printk("\n");
+#endif
+
+ return 0;
+}
+/* exported for PCI i2c */
+EXPORT_SYMBOL(flexcop_i2c_request);
+
+/* master xfer callback for demodulator */
+static int flexcop_master_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msgs[], int num)
+{
+ struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
+ int i, ret = 0;
+
+ /* Some drivers use 1 byte or 0 byte reads as probes, which this
+ * driver doesn't support. These probes will always fail, so this
+ * hack makes them always succeed. If one knew how, it would of
+ * course be better to actually do the read. */
+ if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
+ return 1;
+
+ if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
+ return -ERESTARTSYS;
+
+ for (i = 0; i < num; i++) {
+ /* reading */
+ if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
+ ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
+ msgs[i].buf[0], msgs[i+1].buf,
+ msgs[i+1].len);
+ i++; /* skip the following message */
+ } else /* writing */
+ ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
+ msgs[i].buf[0], &msgs[i].buf[1],
+ msgs[i].len - 1);
+ if (ret < 0) {
+ deb_i2c("i2c master_xfer failed");
+ break;
+ }
+ }
+
+ mutex_unlock(&i2c->fc->i2c_mutex);
+
+ if (ret == 0)
+ ret = num;
+ return ret;
+}
+
+static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm flexcop_algo = {
+ .master_xfer = flexcop_master_xfer,
+ .functionality = flexcop_i2c_func,
+};
+
+int flexcop_i2c_init(struct flexcop_device *fc)
+{
+ int ret;
+ mutex_init(&fc->i2c_mutex);
+
+ fc->fc_i2c_adap[0].fc = fc;
+ fc->fc_i2c_adap[1].fc = fc;
+ fc->fc_i2c_adap[2].fc = fc;
+ fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
+ fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
+ fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
+
+ strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
+ sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
+ strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
+ sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
+ strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
+ sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
+
+ i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
+ i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
+ i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
+
+ fc->fc_i2c_adap[0].i2c_adap.algo =
+ fc->fc_i2c_adap[1].i2c_adap.algo =
+ fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
+ fc->fc_i2c_adap[0].i2c_adap.algo_data =
+ fc->fc_i2c_adap[1].i2c_adap.algo_data =
+ fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
+ fc->fc_i2c_adap[0].i2c_adap.dev.parent =
+ fc->fc_i2c_adap[1].i2c_adap.dev.parent =
+ fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;
+
+ ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+ if (ret < 0)
+ goto adap_1_failed;
+
+ ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+ if (ret < 0)
+ goto adap_2_failed;
+
+ fc->init_state |= FC_STATE_I2C_INIT;
+ return 0;
+
+adap_2_failed:
+ i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+adap_1_failed:
+ i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+ return ret;
+}
+
+void flexcop_i2c_exit(struct flexcop_device *fc)
+{
+ if (fc->init_state & FC_STATE_I2C_INIT) {
+ i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+ i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+ i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+ }
+ fc->init_state &= ~FC_STATE_I2C_INIT;
+}
diff --git a/drivers/media/common/b2c2/flexcop-misc.c b/drivers/media/common/b2c2/flexcop-misc.c
new file mode 100644
index 000000000000..f06f3a9070f5
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-misc.c
@@ -0,0 +1,86 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-misc.c - miscellaneous functions
+ * see flexcop.c for copyright information
+ */
+#include "flexcop.h"
+
+void flexcop_determine_revision(struct flexcop_device *fc)
+{
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204);
+
+ switch (v.misc_204.Rev_N_sig_revision_hi) {
+ case 0x2:
+ deb_info("found a FlexCopII.\n");
+ fc->rev = FLEXCOP_II;
+ break;
+ case 0x3:
+ deb_info("found a FlexCopIIb.\n");
+ fc->rev = FLEXCOP_IIB;
+ break;
+ case 0x0:
+ deb_info("found a FlexCopIII.\n");
+ fc->rev = FLEXCOP_III;
+ break;
+ default:
+ err("unknown FlexCop Revision: %x. Please report this to "
+ "linux-dvb@linuxtv.org.",
+ v.misc_204.Rev_N_sig_revision_hi);
+ break;
+ }
+
+ if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps))
+ deb_info("this FlexCop has "
+ "the additional 32 hardware pid filter.\n");
+ else
+ deb_info("this FlexCop has "
+ "the 6 basic main hardware pid filter.\n");
+ /* bus parts have to decide if hw pid filtering is used or not. */
+}
+
+static const char *flexcop_revision_names[] = {
+ "Unknown chip",
+ "FlexCopII",
+ "FlexCopIIb",
+ "FlexCopIII",
+};
+
+static const char *flexcop_device_names[] = {
+ [FC_UNK] = "Unknown device",
+ [FC_CABLE] = "Cable2PC/CableStar 2 DVB-C",
+ [FC_AIR_DVBT] = "Air2PC/AirStar 2 DVB-T",
+ [FC_AIR_ATSC1] = "Air2PC/AirStar 2 ATSC 1st generation",
+ [FC_AIR_ATSC2] = "Air2PC/AirStar 2 ATSC 2nd generation",
+ [FC_AIR_ATSC3] = "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
+ [FC_SKY_REV23] = "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)",
+ [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6",
+ [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
+ [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8",
+};
+
+static const char *flexcop_bus_names[] = {
+ "USB",
+ "PCI",
+};
+
+void flexcop_device_name(struct flexcop_device *fc,
+ const char *prefix, const char *suffix)
+{
+ info("%s '%s' at the '%s' bus controlled by a '%s' %s",
+ prefix, flexcop_device_names[fc->dev_type],
+ flexcop_bus_names[fc->bus_type],
+ flexcop_revision_names[fc->rev], suffix);
+}
+
+void flexcop_dump_reg(struct flexcop_device *fc,
+ flexcop_ibi_register reg, int num)
+{
+ flexcop_ibi_value v;
+ int i;
+ for (i = 0; i < num; i++) {
+ v = fc->read_ibi_reg(fc, reg+4*i);
+ deb_rdump("0x%03x: %08x, ", reg+4*i, v.raw);
+ }
+ deb_rdump("\n");
+}
+EXPORT_SYMBOL(flexcop_dump_reg);
diff --git a/drivers/media/common/b2c2/flexcop-reg.h b/drivers/media/common/b2c2/flexcop-reg.h
new file mode 100644
index 000000000000..dc4528dcbb98
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-reg.h
@@ -0,0 +1,166 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII
+ * see flexcop.c for copyright information
+ */
+#ifndef __FLEXCOP_REG_H__
+#define __FLEXCOP_REG_H__
+
+typedef enum {
+ FLEXCOP_UNK = 0,
+ FLEXCOP_II,
+ FLEXCOP_IIB,
+ FLEXCOP_III,
+} flexcop_revision_t;
+
+typedef enum {
+ FC_UNK = 0,
+ FC_CABLE,
+ FC_AIR_DVBT,
+ FC_AIR_ATSC1,
+ FC_AIR_ATSC2,
+ FC_AIR_ATSC3,
+ FC_SKY_REV23,
+ FC_SKY_REV26,
+ FC_SKY_REV27,
+ FC_SKY_REV28,
+} flexcop_device_type_t;
+
+typedef enum {
+ FC_USB = 0,
+ FC_PCI,
+} flexcop_bus_t;
+
+/* FlexCop IBI Registers */
+#if defined(__LITTLE_ENDIAN)
+#include "flexcop_ibi_value_le.h"
+#else
+#if defined(__BIG_ENDIAN)
+#include "flexcop_ibi_value_be.h"
+#else
+#error no endian defined
+#endif
+#endif
+
+#define fc_data_Tag_ID_DVB 0x3e
+#define fc_data_Tag_ID_ATSC 0x3f
+#define fc_data_Tag_ID_IDSB 0x8b
+
+#define fc_key_code_default 0x1
+#define fc_key_code_even 0x2
+#define fc_key_code_odd 0x3
+
+extern flexcop_ibi_value ibi_zero;
+
+typedef enum {
+ FC_I2C_PORT_DEMOD = 1,
+ FC_I2C_PORT_EEPROM = 2,
+ FC_I2C_PORT_TUNER = 3,
+} flexcop_i2c_port_t;
+
+typedef enum {
+ FC_WRITE = 0,
+ FC_READ = 1,
+} flexcop_access_op_t;
+
+typedef enum {
+ FC_SRAM_DEST_NET = 1,
+ FC_SRAM_DEST_CAI = 2,
+ FC_SRAM_DEST_CAO = 4,
+ FC_SRAM_DEST_MEDIA = 8
+} flexcop_sram_dest_t;
+
+typedef enum {
+ FC_SRAM_DEST_TARGET_WAN_USB = 0,
+ FC_SRAM_DEST_TARGET_DMA1 = 1,
+ FC_SRAM_DEST_TARGET_DMA2 = 2,
+ FC_SRAM_DEST_TARGET_FC3_CA = 3
+} flexcop_sram_dest_target_t;
+
+typedef enum {
+ FC_SRAM_2_32KB = 0, /* 64KB */
+ FC_SRAM_1_32KB = 1, /* 32KB - default fow FCII */
+ FC_SRAM_1_128KB = 2, /* 128KB */
+ FC_SRAM_1_48KB = 3, /* 48KB - default for FCIII */
+} flexcop_sram_type_t;
+
+typedef enum {
+ FC_WAN_SPEED_4MBITS = 0,
+ FC_WAN_SPEED_8MBITS = 1,
+ FC_WAN_SPEED_12MBITS = 2,
+ FC_WAN_SPEED_16MBITS = 3,
+} flexcop_wan_speed_t;
+
+typedef enum {
+ FC_DMA_1 = 1,
+ FC_DMA_2 = 2,
+} flexcop_dma_index_t;
+
+typedef enum {
+ FC_DMA_SUBADDR_0 = 1,
+ FC_DMA_SUBADDR_1 = 2,
+} flexcop_dma_addr_index_t;
+
+/* names of the particular registers */
+typedef enum {
+ dma1_000 = 0x000,
+ dma1_004 = 0x004,
+ dma1_008 = 0x008,
+ dma1_00c = 0x00c,
+ dma2_010 = 0x010,
+ dma2_014 = 0x014,
+ dma2_018 = 0x018,
+ dma2_01c = 0x01c,
+
+ tw_sm_c_100 = 0x100,
+ tw_sm_c_104 = 0x104,
+ tw_sm_c_108 = 0x108,
+ tw_sm_c_10c = 0x10c,
+ tw_sm_c_110 = 0x110,
+
+ lnb_switch_freq_200 = 0x200,
+ misc_204 = 0x204,
+ ctrl_208 = 0x208,
+ irq_20c = 0x20c,
+ sw_reset_210 = 0x210,
+ misc_214 = 0x214,
+ mbox_v8_to_host_218 = 0x218,
+ mbox_host_to_v8_21c = 0x21c,
+
+ pid_filter_300 = 0x300,
+ pid_filter_304 = 0x304,
+ pid_filter_308 = 0x308,
+ pid_filter_30c = 0x30c,
+ index_reg_310 = 0x310,
+ pid_n_reg_314 = 0x314,
+ mac_low_reg_318 = 0x318,
+ mac_high_reg_31c = 0x31c,
+
+ data_tag_400 = 0x400,
+ card_id_408 = 0x408,
+ card_id_40c = 0x40c,
+ mac_address_418 = 0x418,
+ mac_address_41c = 0x41c,
+
+ ci_600 = 0x600,
+ pi_604 = 0x604,
+ pi_608 = 0x608,
+ dvb_reg_60c = 0x60c,
+
+ sram_ctrl_reg_700 = 0x700,
+ net_buf_reg_704 = 0x704,
+ cai_buf_reg_708 = 0x708,
+ cao_buf_reg_70c = 0x70c,
+ media_buf_reg_710 = 0x710,
+ sram_dest_reg_714 = 0x714,
+ net_buf_reg_718 = 0x718,
+ wan_ctrl_reg_71c = 0x71c,
+} flexcop_ibi_register;
+
+#define flexcop_set_ibi_value(reg,attr,val) { \
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
+ v.reg.attr = val; \
+ fc->write_ibi_reg(fc,reg,v); \
+}
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop-sram.c b/drivers/media/common/b2c2/flexcop-sram.c
new file mode 100644
index 000000000000..f2199e43e803
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-sram.c
@@ -0,0 +1,363 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-sram.c - functions for controlling the SRAM
+ * see flexcop.c for copyright information
+ */
+#include "flexcop.h"
+
+static void flexcop_sram_set_chip(struct flexcop_device *fc,
+ flexcop_sram_type_t type)
+{
+ flexcop_set_ibi_value(wan_ctrl_reg_71c, sram_chip, type);
+}
+
+int flexcop_sram_init(struct flexcop_device *fc)
+{
+ switch (fc->rev) {
+ case FLEXCOP_II:
+ case FLEXCOP_IIB:
+ flexcop_sram_set_chip(fc, FC_SRAM_1_32KB);
+ break;
+ case FLEXCOP_III:
+ flexcop_sram_set_chip(fc, FC_SRAM_1_48KB);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest,
+ flexcop_sram_dest_target_t target)
+{
+ flexcop_ibi_value v;
+ v = fc->read_ibi_reg(fc, sram_dest_reg_714);
+
+ if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) {
+ err("SRAM destination target to available on FlexCopII(b)\n");
+ return -EINVAL;
+ }
+ deb_sram("sram dest: %x target: %x\n", dest, target);
+
+ if (dest & FC_SRAM_DEST_NET)
+ v.sram_dest_reg_714.NET_Dest = target;
+ if (dest & FC_SRAM_DEST_CAI)
+ v.sram_dest_reg_714.CAI_Dest = target;
+ if (dest & FC_SRAM_DEST_CAO)
+ v.sram_dest_reg_714.CAO_Dest = target;
+ if (dest & FC_SRAM_DEST_MEDIA)
+ v.sram_dest_reg_714.MEDIA_Dest = target;
+
+ fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+ udelay(1000); /* TODO delay really necessary */
+
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_sram_set_dest);
+
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s)
+{
+ flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s);
+}
+EXPORT_SYMBOL(flexcop_wan_set_speed);
+
+void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill)
+{
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+ v.sram_dest_reg_714.ctrl_usb_wan = usb_wan;
+ v.sram_dest_reg_714.ctrl_sramdma = sramdma;
+ v.sram_dest_reg_714.ctrl_maximumfill = maximumfill;
+ fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+}
+EXPORT_SYMBOL(flexcop_sram_ctrl);
+
+#if 0
+static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+ int i, retries;
+ u32 command;
+
+ for (i = 0; i < len; i++) {
+ command = bank | addr | 0x04000000 | (*buf << 0x10);
+
+ retries = 2;
+
+ while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+ mdelay(1);
+ retries--;
+ };
+
+ if (retries == 0)
+ printk("%s: SRAM timeout\n", __func__);
+
+ write_reg_dw(adapter, 0x700, command);
+
+ buf++;
+ addr++;
+ }
+}
+
+static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+ int i, retries;
+ u32 command, value;
+
+ for (i = 0; i < len; i++) {
+ command = bank | addr | 0x04008000;
+
+ retries = 10000;
+
+ while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+ mdelay(1);
+ retries--;
+ };
+
+ if (retries == 0)
+ printk("%s: SRAM timeout\n", __func__);
+
+ write_reg_dw(adapter, 0x700, command);
+
+ retries = 10000;
+
+ while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+ mdelay(1);
+ retries--;
+ };
+
+ if (retries == 0)
+ printk("%s: SRAM timeout\n", __func__);
+
+ value = read_reg_dw(adapter, 0x700) >> 0x10;
+
+ *buf = (value & 0xff);
+
+ addr++;
+ buf++;
+ }
+}
+
+static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
+{
+ u32 bank;
+
+ bank = 0;
+
+ if (adapter->dw_sram_type == 0x20000) {
+ bank = (addr & 0x18000) << 0x0d;
+ }
+
+ if (adapter->dw_sram_type == 0x00000) {
+ if ((addr >> 0x0f) == 0)
+ bank = 0x20000000;
+ else
+ bank = 0x10000000;
+ }
+ flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
+}
+
+static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
+{
+ u32 bank;
+ bank = 0;
+
+ if (adapter->dw_sram_type == 0x20000) {
+ bank = (addr & 0x18000) << 0x0d;
+ }
+
+ if (adapter->dw_sram_type == 0x00000) {
+ if ((addr >> 0x0f) == 0)
+ bank = 0x20000000;
+ else
+ bank = 0x10000000;
+ }
+ flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
+}
+
+static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
+{
+ u32 length;
+ while (len != 0) {
+ length = len;
+ /* check if the address range belongs to the same
+ * 32K memory chip. If not, the data is read
+ * from one chip at a time */
+ if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+ length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
+ }
+
+ sram_read_chunk(adapter, addr, buf, length);
+ addr = addr + length;
+ buf = buf + length;
+ len = len - length;
+ }
+}
+
+static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
+{
+ u32 length;
+ while (len != 0) {
+ length = len;
+
+ /* check if the address range belongs to the same
+ * 32K memory chip. If not, the data is
+ * written to one chip at a time */
+ if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+ length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
+ }
+
+ sram_write_chunk(adapter, addr, buf, length);
+ addr = addr + length;
+ buf = buf + length;
+ len = len - length;
+ }
+}
+
+static void sram_set_size(struct adapter *adapter, u32 mask)
+{
+ write_reg_dw(adapter, 0x71c,
+ (mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
+}
+
+static void sram_init(struct adapter *adapter)
+{
+ u32 tmp;
+ tmp = read_reg_dw(adapter, 0x71c);
+ write_reg_dw(adapter, 0x71c, 1);
+
+ if (read_reg_dw(adapter, 0x71c) != 0) {
+ write_reg_dw(adapter, 0x71c, tmp);
+ adapter->dw_sram_type = tmp & 0x30000;
+ ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
+ } else {
+ adapter->dw_sram_type = 0x10000;
+ ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
+ }
+}
+
+static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+{
+ u8 tmp1, tmp2;
+ dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
+
+ sram_set_size(adapter, mask);
+ sram_init(adapter);
+
+ tmp2 = 0xa5;
+ tmp1 = 0x4f;
+
+ sram_write(adapter, addr, &tmp2, 1);
+ sram_write(adapter, addr + 4, &tmp1, 1);
+
+ tmp2 = 0;
+ mdelay(20);
+
+ sram_read(adapter, addr, &tmp2, 1);
+ sram_read(adapter, addr, &tmp2, 1);
+
+ dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
+
+ if (tmp2 != 0xa5)
+ return 0;
+
+ tmp2 = 0x5a;
+ tmp1 = 0xf4;
+
+ sram_write(adapter, addr, &tmp2, 1);
+ sram_write(adapter, addr + 4, &tmp1, 1);
+
+ tmp2 = 0;
+ mdelay(20);
+
+ sram_read(adapter, addr, &tmp2, 1);
+ sram_read(adapter, addr, &tmp2, 1);
+
+ dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
+
+ if (tmp2 != 0x5a)
+ return 0;
+ return 1;
+}
+
+static u32 sram_length(struct adapter *adapter)
+{
+ if (adapter->dw_sram_type == 0x10000)
+ return 32768; /* 32K */
+ if (adapter->dw_sram_type == 0x00000)
+ return 65536; /* 64K */
+ if (adapter->dw_sram_type == 0x20000)
+ return 131072; /* 128K */
+ return 32768; /* 32K */
+}
+
+/* FlexcopII can work with 32K, 64K or 128K of external SRAM memory.
+ - for 128K there are 4x32K chips at bank 0,1,2,3.
+ - for 64K there are 2x32K chips at bank 1,2.
+ - for 32K there is one 32K chip at bank 0.
+
+ FlexCop works only with one bank at a time. The bank is selected
+ by bits 28-29 of the 0x700 register.
+
+ bank 0 covers addresses 0x00000-0x07fff
+ bank 1 covers addresses 0x08000-0x0ffff
+ bank 2 covers addresses 0x10000-0x17fff
+ bank 3 covers addresses 0x18000-0x1ffff */
+
+static int flexcop_sram_detect(struct flexcop_device *fc)
+{
+ flexcop_ibi_value r208, r71c_0, vr71c_1;
+ r208 = fc->read_ibi_reg(fc, ctrl_208);
+ fc->write_ibi_reg(fc, ctrl_208, ibi_zero);
+
+ r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c);
+ write_reg_dw(adapter, 0x71c, 1);
+ tmp3 = read_reg_dw(adapter, 0x71c);
+ dprintk("%s: tmp3 = %x\n", __func__, tmp3);
+ write_reg_dw(adapter, 0x71c, tmp2);
+
+ // check for internal SRAM ???
+ tmp3--;
+ if (tmp3 != 0) {
+ sram_set_size(adapter, 0x10000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+ dprintk("%s: sram size = 32K\n", __func__);
+ return 32;
+ }
+
+ if (sram_test_location(adapter, 0x20000, 0x18000) != 0) {
+ sram_set_size(adapter, 0x20000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+ dprintk("%s: sram size = 128K\n", __func__);
+ return 128;
+ }
+
+ if (sram_test_location(adapter, 0x00000, 0x10000) != 0) {
+ sram_set_size(adapter, 0x00000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+ dprintk("%s: sram size = 64K\n", __func__);
+ return 64;
+ }
+
+ if (sram_test_location(adapter, 0x10000, 0x00000) != 0) {
+ sram_set_size(adapter, 0x10000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+ dprintk("%s: sram size = 32K\n", __func__);
+ return 32;
+ }
+
+ sram_set_size(adapter, 0x10000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+ dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
+ return 0;
+}
+
+static void sll_detect_sram_size(struct adapter *adapter)
+{
+ sram_detect_for_flex2(adapter);
+}
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c
new file mode 100644
index 000000000000..412c5daf2b48
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop.c
@@ -0,0 +1,325 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop.c - main module part
+ * Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@desy.de>
+ * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
+ *
+ * Acknowledgements:
+ * John Jurrius from BBTI, Inc. for extensive support
+ * with code examples and data books
+ * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
+ *
+ * Contributions to the skystar2-driver have been done by
+ * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
+ * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
+ * Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu)
+ * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac
+ * filtering)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "flexcop.h"
+
+#define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de"
+
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define DEBSTATUS ""
+#else
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+int b2c2_flexcop_debug;
+EXPORT_SYMBOL_GPL(b2c2_flexcop_debug);
+module_param_named(debug, b2c2_flexcop_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+ "set debug level (1=info,2=tuner,4=i2c,8=ts,"
+ "16=sram,32=reg (|-able))."
+ DEBSTATUS);
+#undef DEBSTATUS
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* global zero for ibi values */
+flexcop_ibi_value ibi_zero;
+
+static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct flexcop_device *fc = dvbdmxfeed->demux->priv;
+ return flexcop_pid_feed_control(fc, dvbdmxfeed, 1);
+}
+
+static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct flexcop_device *fc = dvbdmxfeed->demux->priv;
+ return flexcop_pid_feed_control(fc, dvbdmxfeed, 0);
+}
+
+static int flexcop_dvb_init(struct flexcop_device *fc)
+{
+ int ret = dvb_register_adapter(&fc->dvb_adapter,
+ "FlexCop Digital TV device", fc->owner,
+ fc->dev, adapter_nr);
+ if (ret < 0) {
+ err("error registering DVB adapter");
+ return ret;
+ }
+ fc->dvb_adapter.priv = fc;
+
+ fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING
+ | DMX_MEMORY_BASED_FILTERING);
+ fc->demux.priv = fc;
+ fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED;
+ fc->demux.start_feed = flexcop_dvb_start_feed;
+ fc->demux.stop_feed = flexcop_dvb_stop_feed;
+ fc->demux.write_to_decoder = NULL;
+
+ ret = dvb_dmx_init(&fc->demux);
+ if (ret < 0) {
+ err("dvb_dmx failed: error %d", ret);
+ goto err_dmx;
+ }
+
+ fc->hw_frontend.source = DMX_FRONTEND_0;
+
+ fc->dmxdev.filternum = fc->demux.feednum;
+ fc->dmxdev.demux = &fc->demux.dmx;
+ fc->dmxdev.capabilities = 0;
+ ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter);
+ if (ret < 0) {
+ err("dvb_dmxdev_init failed: error %d", ret);
+ goto err_dmx_dev;
+ }
+
+ ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend);
+ if (ret < 0) {
+ err("adding hw_frontend to dmx failed: error %d", ret);
+ goto err_dmx_add_hw_frontend;
+ }
+
+ fc->mem_frontend.source = DMX_MEMORY_FE;
+ ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend);
+ if (ret < 0) {
+ err("adding mem_frontend to dmx failed: error %d", ret);
+ goto err_dmx_add_mem_frontend;
+ }
+
+ ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend);
+ if (ret < 0) {
+ err("connect frontend failed: error %d", ret);
+ goto err_connect_frontend;
+ }
+
+ ret = dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+ if (ret < 0) {
+ err("dvb_net_init failed: error %d", ret);
+ goto err_net;
+ }
+
+ fc->init_state |= FC_STATE_DVB_INIT;
+ return 0;
+
+err_net:
+ fc->demux.dmx.disconnect_frontend(&fc->demux.dmx);
+err_connect_frontend:
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend);
+err_dmx_add_mem_frontend:
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->hw_frontend);
+err_dmx_add_hw_frontend:
+ dvb_dmxdev_release(&fc->dmxdev);
+err_dmx_dev:
+ dvb_dmx_release(&fc->demux);
+err_dmx:
+ dvb_unregister_adapter(&fc->dvb_adapter);
+ return ret;
+}
+
+static void flexcop_dvb_exit(struct flexcop_device *fc)
+{
+ if (fc->init_state & FC_STATE_DVB_INIT) {
+ dvb_net_release(&fc->dvbnet);
+
+ fc->demux.dmx.close(&fc->demux.dmx);
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx,
+ &fc->mem_frontend);
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx,
+ &fc->hw_frontend);
+ dvb_dmxdev_release(&fc->dmxdev);
+ dvb_dmx_release(&fc->demux);
+ dvb_unregister_adapter(&fc->dvb_adapter);
+ deb_info("deinitialized dvb stuff\n");
+ }
+ fc->init_state &= ~FC_STATE_DVB_INIT;
+}
+
+/* these methods are necessary to achieve the long-term-goal of hiding the
+ * struct flexcop_device from the bus-parts */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len)
+{
+ dvb_dmx_swfilter(&fc->demux, buf, len);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_data);
+
+void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no)
+{
+ dvb_dmx_swfilter_packets(&fc->demux, buf, no);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_packets);
+
+static void flexcop_reset(struct flexcop_device *fc)
+{
+ flexcop_ibi_value v210, v204;
+
+ /* reset the flexcop itself */
+ fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
+
+ v210.raw = 0;
+ v210.sw_reset_210.reset_block_000 = 1;
+ v210.sw_reset_210.reset_block_100 = 1;
+ v210.sw_reset_210.reset_block_200 = 1;
+ v210.sw_reset_210.reset_block_300 = 1;
+ v210.sw_reset_210.reset_block_400 = 1;
+ v210.sw_reset_210.reset_block_500 = 1;
+ v210.sw_reset_210.reset_block_600 = 1;
+ v210.sw_reset_210.reset_block_700 = 1;
+ v210.sw_reset_210.Block_reset_enable = 0xb2;
+ v210.sw_reset_210.Special_controls = 0xc259;
+ fc->write_ibi_reg(fc,sw_reset_210,v210);
+ msleep(1);
+
+ /* reset the periphical devices */
+
+ v204 = fc->read_ibi_reg(fc,misc_204);
+ v204.misc_204.Per_reset_sig = 0;
+ fc->write_ibi_reg(fc,misc_204,v204);
+ msleep(1);
+ v204.misc_204.Per_reset_sig = 1;
+ fc->write_ibi_reg(fc,misc_204,v204);
+}
+
+void flexcop_reset_block_300(struct flexcop_device *fc)
+{
+ flexcop_ibi_value v208_save = fc->read_ibi_reg(fc, ctrl_208),
+ v210 = fc->read_ibi_reg(fc, sw_reset_210);
+
+ deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw);
+ fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
+
+ v210.sw_reset_210.reset_block_300 = 1;
+ v210.sw_reset_210.Block_reset_enable = 0xb2;
+
+ fc->write_ibi_reg(fc,sw_reset_210,v210);
+ fc->write_ibi_reg(fc,ctrl_208,v208_save);
+}
+
+struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
+{
+ void *bus;
+ struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device),
+ GFP_KERNEL);
+ if (!fc) {
+ err("no memory");
+ return NULL;
+ }
+
+ bus = kzalloc(bus_specific_len, GFP_KERNEL);
+ if (!bus) {
+ err("no memory");
+ kfree(fc);
+ return NULL;
+ }
+
+ fc->bus_specific = bus;
+
+ return fc;
+}
+EXPORT_SYMBOL(flexcop_device_kmalloc);
+
+void flexcop_device_kfree(struct flexcop_device *fc)
+{
+ kfree(fc->bus_specific);
+ kfree(fc);
+}
+EXPORT_SYMBOL(flexcop_device_kfree);
+
+int flexcop_device_initialize(struct flexcop_device *fc)
+{
+ int ret;
+ ibi_zero.raw = 0;
+
+ flexcop_reset(fc);
+ flexcop_determine_revision(fc);
+ flexcop_sram_init(fc);
+ flexcop_hw_filter_init(fc);
+ flexcop_smc_ctrl(fc, 0);
+
+ ret = flexcop_dvb_init(fc);
+ if (ret)
+ goto error;
+
+ /* i2c has to be done before doing EEProm stuff -
+ * because the EEProm is accessed via i2c */
+ ret = flexcop_i2c_init(fc);
+ if (ret)
+ goto error;
+
+ /* do the MAC address reading after initializing the dvb_adapter */
+ if (fc->get_mac_addr(fc, 0) == 0) {
+ u8 *b = fc->dvb_adapter.proposed_mac;
+ info("MAC address = %pM", b);
+ flexcop_set_mac_filter(fc,b);
+ flexcop_mac_filter_ctrl(fc,1);
+ } else
+ warn("reading of MAC address failed.\n");
+
+ ret = flexcop_frontend_init(fc);
+ if (ret)
+ goto error;
+
+ flexcop_device_name(fc,"initialization of","complete");
+ return 0;
+
+error:
+ flexcop_device_exit(fc);
+ return ret;
+}
+EXPORT_SYMBOL(flexcop_device_initialize);
+
+void flexcop_device_exit(struct flexcop_device *fc)
+{
+ flexcop_frontend_exit(fc);
+ flexcop_i2c_exit(fc);
+ flexcop_dvb_exit(fc);
+}
+EXPORT_SYMBOL(flexcop_device_exit);
+
+static int flexcop_module_init(void)
+{
+ info(DRIVER_NAME " loaded successfully");
+ return 0;
+}
+
+static void flexcop_module_cleanup(void)
+{
+ info(DRIVER_NAME " unloaded successfully");
+}
+
+module_init(flexcop_module_init);
+module_exit(flexcop_module_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/b2c2/flexcop.h b/drivers/media/common/b2c2/flexcop.h
new file mode 100644
index 000000000000..897b10c85ad9
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop.h
@@ -0,0 +1,29 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop.h - private header file for all flexcop-chip-source files
+ * see flexcop.c for copyright information
+ */
+#ifndef __FLEXCOP_H__
+#define __FLEXCOP_H___
+
+#define FC_LOG_PREFIX "b2c2-flexcop"
+#include "flexcop-common.h"
+
+extern int b2c2_flexcop_debug;
+
+/* debug */
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+ do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0)
+#else
+#define dprintk(level,args...)
+#endif
+
+#define deb_info(args...) dprintk(0x01, args)
+#define deb_tuner(args...) dprintk(0x02, args)
+#define deb_i2c(args...) dprintk(0x04, args)
+#define deb_ts(args...) dprintk(0x08, args)
+#define deb_sram(args...) dprintk(0x10, args)
+#define deb_rdump(args...) dprintk(0x20, args)
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop_ibi_value_be.h b/drivers/media/common/b2c2/flexcop_ibi_value_be.h
new file mode 100644
index 000000000000..8f64bdbd72bb
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop_ibi_value_be.h
@@ -0,0 +1,455 @@
+/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * register descriptions
+ * see flexcop.c for copyright information
+ */
+/* This file is automatically generated, do not edit things here. */
+#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
+#define __FLEXCOP_IBI_VALUE_INCLUDED__
+
+typedef union {
+ u32 raw;
+
+ struct {
+ u32 dma_address0 :30;
+ u32 dma_0No_update : 1;
+ u32 dma_0start : 1;
+ } dma_0x0;
+
+ struct {
+ u32 dma_addr_size :24;
+ u32 DMA_maxpackets : 8;
+ } dma_0x4_remap;
+
+ struct {
+ u32 dma_addr_size :24;
+ u32 unused : 1;
+ u32 dma1timer : 7;
+ } dma_0x4_read;
+
+ struct {
+ u32 dma_addr_size :24;
+ u32 dmatimer : 7;
+ u32 unused : 1;
+ } dma_0x4_write;
+
+ struct {
+ u32 dma_cur_addr :30;
+ u32 unused : 2;
+ } dma_0x8;
+
+ struct {
+ u32 dma_address1 :30;
+ u32 remap_enable : 1;
+ u32 dma_1start : 1;
+ } dma_0xc;
+
+ struct {
+ u32 st_done : 1;
+ u32 no_base_addr_ack_error : 1;
+ u32 twoWS_port_reg : 2;
+ u32 total_bytes : 2;
+ u32 twoWS_rw : 1;
+ u32 working_start : 1;
+ u32 data1_reg : 8;
+ u32 baseaddr : 8;
+ u32 reserved1 : 1;
+ u32 chipaddr : 7;
+ } tw_sm_c_100;
+
+ struct {
+ u32 unused : 6;
+ u32 force_stop : 1;
+ u32 exlicit_stops : 1;
+ u32 data4_reg : 8;
+ u32 data3_reg : 8;
+ u32 data2_reg : 8;
+ } tw_sm_c_104;
+
+ struct {
+ u32 reserved2 :19;
+ u32 tlo1 : 5;
+ u32 reserved1 : 2;
+ u32 thi1 : 6;
+ } tw_sm_c_108;
+
+ struct {
+ u32 reserved2 :19;
+ u32 tlo1 : 5;
+ u32 reserved1 : 2;
+ u32 thi1 : 6;
+ } tw_sm_c_10c;
+
+ struct {
+ u32 reserved2 :19;
+ u32 tlo1 : 5;
+ u32 reserved1 : 2;
+ u32 thi1 : 6;
+ } tw_sm_c_110;
+
+ struct {
+ u32 LNB_CTLPrescaler_sig : 2;
+ u32 LNB_CTLLowCount_sig :15;
+ u32 LNB_CTLHighCount_sig :15;
+ } lnb_switch_freq_200;
+
+ struct {
+ u32 Rev_N_sig_reserved2 : 1;
+ u32 Rev_N_sig_caps : 1;
+ u32 Rev_N_sig_reserved1 : 2;
+ u32 Rev_N_sig_revision_hi : 4;
+ u32 reserved :20;
+ u32 Per_reset_sig : 1;
+ u32 LNB_L_H_sig : 1;
+ u32 ACPI3_sig : 1;
+ u32 ACPI1_sig : 1;
+ } misc_204;
+
+ struct {
+ u32 unused : 9;
+ u32 Mailbox_from_V8_Enable_sig : 1;
+ u32 DMA2_Size_IRQ_Enable_sig : 1;
+ u32 DMA1_Size_IRQ_Enable_sig : 1;
+ u32 DMA2_Timer_Enable_sig : 1;
+ u32 DMA2_IRQ_Enable_sig : 1;
+ u32 DMA1_Timer_Enable_sig : 1;
+ u32 DMA1_IRQ_Enable_sig : 1;
+ u32 Rcv_Data_sig : 1;
+ u32 MAC_filter_Mode_sig : 1;
+ u32 Multi2_Enable_sig : 1;
+ u32 Per_CA_Enable_sig : 1;
+ u32 SMC_Enable_sig : 1;
+ u32 CA_Enable_sig : 1;
+ u32 WAN_CA_Enable_sig : 1;
+ u32 WAN_Enable_sig : 1;
+ u32 Mask_filter_sig : 1;
+ u32 Null_filter_sig : 1;
+ u32 ECM_filter_sig : 1;
+ u32 EMM_filter_sig : 1;
+ u32 PMT_filter_sig : 1;
+ u32 PCR_filter_sig : 1;
+ u32 Stream2_filter_sig : 1;
+ u32 Stream1_filter_sig : 1;
+ } ctrl_208;
+
+ struct {
+ u32 reserved :21;
+ u32 Transport_Error : 1;
+ u32 LLC_SNAP_FLAG_set : 1;
+ u32 Continuity_error_flag : 1;
+ u32 Data_receiver_error : 1;
+ u32 Mailbox_from_V8_Status_sig : 1;
+ u32 DMA2_Size_IRQ_Status : 1;
+ u32 DMA1_Size_IRQ_Status : 1;
+ u32 DMA2_Timer_Status : 1;
+ u32 DMA2_IRQ_Status : 1;
+ u32 DMA1_Timer_Status : 1;
+ u32 DMA1_IRQ_Status : 1;
+ } irq_20c;
+
+ struct {
+ u32 Special_controls :16;
+ u32 Block_reset_enable : 8;
+ u32 reset_block_700 : 1;
+ u32 reset_block_600 : 1;
+ u32 reset_block_500 : 1;
+ u32 reset_block_400 : 1;
+ u32 reset_block_300 : 1;
+ u32 reset_block_200 : 1;
+ u32 reset_block_100 : 1;
+ u32 reset_block_000 : 1;
+ } sw_reset_210;
+
+ struct {
+ u32 unused2 :20;
+ u32 polarity_PS_ERR_sig : 1;
+ u32 polarity_PS_SYNC_sig : 1;
+ u32 polarity_PS_VALID_sig : 1;
+ u32 polarity_PS_CLK_sig : 1;
+ u32 unused1 : 3;
+ u32 s2p_sel_sig : 1;
+ u32 section_pkg_enable_sig : 1;
+ u32 halt_V8_sig : 1;
+ u32 v2WS_oe_sig : 1;
+ u32 vuart_oe_sig : 1;
+ } misc_214;
+
+ struct {
+ u32 Mailbox_from_V8 :32;
+ } mbox_v8_to_host_218;
+
+ struct {
+ u32 sysramaccess_busmuster : 1;
+ u32 sysramaccess_write : 1;
+ u32 unused : 7;
+ u32 sysramaccess_addr :15;
+ u32 sysramaccess_data : 8;
+ } mbox_host_to_v8_21c;
+
+ struct {
+ u32 debug_fifo_problem : 1;
+ u32 debug_flag_write_status00 : 1;
+ u32 Stream2_trans : 1;
+ u32 Stream2_PID :13;
+ u32 debug_flag_pid_saved : 1;
+ u32 MAC_Multicast_filter : 1;
+ u32 Stream1_trans : 1;
+ u32 Stream1_PID :13;
+ } pid_filter_300;
+
+ struct {
+ u32 reserved : 2;
+ u32 PMT_trans : 1;
+ u32 PMT_PID :13;
+ u32 debug_overrun2 : 1;
+ u32 debug_overrun3 : 1;
+ u32 PCR_trans : 1;
+ u32 PCR_PID :13;
+ } pid_filter_304;
+
+ struct {
+ u32 reserved : 2;
+ u32 ECM_trans : 1;
+ u32 ECM_PID :13;
+ u32 EMM_filter_6 : 1;
+ u32 EMM_filter_4 : 1;
+ u32 EMM_trans : 1;
+ u32 EMM_PID :13;
+ } pid_filter_308;
+
+ struct {
+ u32 unused2 : 3;
+ u32 Group_mask :13;
+ u32 unused1 : 2;
+ u32 Group_trans : 1;
+ u32 Group_PID :13;
+ } pid_filter_30c_ext_ind_0_7;
+
+ struct {
+ u32 unused :15;
+ u32 net_master_read :17;
+ } pid_filter_30c_ext_ind_1;
+
+ struct {
+ u32 unused :15;
+ u32 net_master_write :17;
+ } pid_filter_30c_ext_ind_2;
+
+ struct {
+ u32 unused :15;
+ u32 next_net_master_write :17;
+ } pid_filter_30c_ext_ind_3;
+
+ struct {
+ u32 reserved2 : 5;
+ u32 stack_read :10;
+ u32 reserved1 : 6;
+ u32 state_write :10;
+ u32 unused1 : 1;
+ } pid_filter_30c_ext_ind_4;
+
+ struct {
+ u32 unused :22;
+ u32 stack_cnt :10;
+ } pid_filter_30c_ext_ind_5;
+
+ struct {
+ u32 unused : 4;
+ u32 data_size_reg :12;
+ u32 write_status4 : 2;
+ u32 write_status1 : 2;
+ u32 pid_fsm_save_reg300 : 2;
+ u32 pid_fsm_save_reg4 : 2;
+ u32 pid_fsm_save_reg3 : 2;
+ u32 pid_fsm_save_reg2 : 2;
+ u32 pid_fsm_save_reg1 : 2;
+ u32 pid_fsm_save_reg0 : 2;
+ } pid_filter_30c_ext_ind_6;
+
+ struct {
+ u32 unused :22;
+ u32 pass_alltables : 1;
+ u32 AB_select : 1;
+ u32 extra_index_reg : 3;
+ u32 index_reg : 5;
+ } index_reg_310;
+
+ struct {
+ u32 reserved :17;
+ u32 PID_enable_bit : 1;
+ u32 PID_trans : 1;
+ u32 PID :13;
+ } pid_n_reg_314;
+
+ struct {
+ u32 reserved : 6;
+ u32 HighAB_bit : 1;
+ u32 Enable_bit : 1;
+ u32 A6_byte : 8;
+ u32 A5_byte : 8;
+ u32 A4_byte : 8;
+ } mac_low_reg_318;
+
+ struct {
+ u32 reserved : 8;
+ u32 A3_byte : 8;
+ u32 A2_byte : 8;
+ u32 A1_byte : 8;
+ } mac_high_reg_31c;
+
+ struct {
+ u32 data_Tag_ID :16;
+ u32 reserved :16;
+ } data_tag_400;
+
+ struct {
+ u32 Card_IDbyte3 : 8;
+ u32 Card_IDbyte4 : 8;
+ u32 Card_IDbyte5 : 8;
+ u32 Card_IDbyte6 : 8;
+ } card_id_408;
+
+ struct {
+ u32 Card_IDbyte1 : 8;
+ u32 Card_IDbyte2 : 8;
+ } card_id_40c;
+
+ struct {
+ u32 MAC6 : 8;
+ u32 MAC3 : 8;
+ u32 MAC2 : 8;
+ u32 MAC1 : 8;
+ } mac_address_418;
+
+ struct {
+ u32 reserved :16;
+ u32 MAC8 : 8;
+ u32 MAC7 : 8;
+ } mac_address_41c;
+
+ struct {
+ u32 reserved :21;
+ u32 txbuffempty : 1;
+ u32 ReceiveByteFrameError : 1;
+ u32 ReceiveDataReady : 1;
+ u32 transmitter_data_byte : 8;
+ } ci_600;
+
+ struct {
+ u32 pi_component_reg : 3;
+ u32 pi_rw : 1;
+ u32 pi_ha :20;
+ u32 pi_d : 8;
+ } pi_604;
+
+ struct {
+ u32 pi_busy_n : 1;
+ u32 pi_wait_n : 1;
+ u32 pi_timeout_status : 1;
+ u32 pi_CiMax_IRQ_n : 1;
+ u32 config_cclk : 1;
+ u32 config_cs_n : 1;
+ u32 config_wr_n : 1;
+ u32 config_Prog_n : 1;
+ u32 config_Init_stat : 1;
+ u32 config_Done_stat : 1;
+ u32 pcmcia_b_mod_pwr_n : 1;
+ u32 pcmcia_a_mod_pwr_n : 1;
+ u32 reserved : 3;
+ u32 Timer_addr : 5;
+ u32 unused : 1;
+ u32 timer_data : 7;
+ u32 Timer_Load_req : 1;
+ u32 Timer_Read_req : 1;
+ u32 oncecycle_read : 1;
+ u32 serialReset : 1;
+ } pi_608;
+
+ struct {
+ u32 reserved : 6;
+ u32 rw_flag : 1;
+ u32 dvb_en : 1;
+ u32 key_array_row : 5;
+ u32 key_array_col : 3;
+ u32 key_code : 2;
+ u32 key_enable : 1;
+ u32 PID :13;
+ } dvb_reg_60c;
+
+ struct {
+ u32 start_sram_ibi : 1;
+ u32 reserved2 : 1;
+ u32 ce_pin_reg : 1;
+ u32 oe_pin_reg : 1;
+ u32 reserved1 : 3;
+ u32 sc_xfer_bit : 1;
+ u32 sram_data : 8;
+ u32 sram_rw : 1;
+ u32 sram_addr :15;
+ } sram_ctrl_reg_700;
+
+ struct {
+ u32 net_addr_write :16;
+ u32 net_addr_read :16;
+ } net_buf_reg_704;
+
+ struct {
+ u32 cai_cnt : 4;
+ u32 reserved2 : 6;
+ u32 cai_write :11;
+ u32 reserved1 : 5;
+ u32 cai_read :11;
+ } cai_buf_reg_708;
+
+ struct {
+ u32 cao_cnt : 4;
+ u32 reserved2 : 6;
+ u32 cap_write :11;
+ u32 reserved1 : 5;
+ u32 cao_read :11;
+ } cao_buf_reg_70c;
+
+ struct {
+ u32 media_cnt : 4;
+ u32 reserved2 : 6;
+ u32 media_write :11;
+ u32 reserved1 : 5;
+ u32 media_read :11;
+ } media_buf_reg_710;
+
+ struct {
+ u32 reserved :17;
+ u32 ctrl_maximumfill : 1;
+ u32 ctrl_sramdma : 1;
+ u32 ctrl_usb_wan : 1;
+ u32 cao_ovflow_error : 1;
+ u32 cai_ovflow_error : 1;
+ u32 media_ovflow_error : 1;
+ u32 net_ovflow_error : 1;
+ u32 MEDIA_Dest : 2;
+ u32 CAO_Dest : 2;
+ u32 CAI_Dest : 2;
+ u32 NET_Dest : 2;
+ } sram_dest_reg_714;
+
+ struct {
+ u32 reserved3 :11;
+ u32 net_addr_write : 1;
+ u32 reserved2 : 3;
+ u32 net_addr_read : 1;
+ u32 reserved1 : 4;
+ u32 net_cnt :12;
+ } net_buf_reg_718;
+
+ struct {
+ u32 reserved3 : 4;
+ u32 wan_pkt_frame : 4;
+ u32 reserved2 : 4;
+ u32 sram_memmap : 2;
+ u32 sram_chip : 2;
+ u32 wan_wait_state : 8;
+ u32 reserved1 : 6;
+ u32 wan_speed_sig : 2;
+ } wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop_ibi_value_le.h b/drivers/media/common/b2c2/flexcop_ibi_value_le.h
new file mode 100644
index 000000000000..c75830d7d942
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop_ibi_value_le.h
@@ -0,0 +1,455 @@
+/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * register descriptions
+ * see flexcop.c for copyright information
+ */
+/* This file is automatically generated, do not edit things here. */
+#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
+#define __FLEXCOP_IBI_VALUE_INCLUDED__
+
+typedef union {
+ u32 raw;
+
+ struct {
+ u32 dma_0start : 1;
+ u32 dma_0No_update : 1;
+ u32 dma_address0 :30;
+ } dma_0x0;
+
+ struct {
+ u32 DMA_maxpackets : 8;
+ u32 dma_addr_size :24;
+ } dma_0x4_remap;
+
+ struct {
+ u32 dma1timer : 7;
+ u32 unused : 1;
+ u32 dma_addr_size :24;
+ } dma_0x4_read;
+
+ struct {
+ u32 unused : 1;
+ u32 dmatimer : 7;
+ u32 dma_addr_size :24;
+ } dma_0x4_write;
+
+ struct {
+ u32 unused : 2;
+ u32 dma_cur_addr :30;
+ } dma_0x8;
+
+ struct {
+ u32 dma_1start : 1;
+ u32 remap_enable : 1;
+ u32 dma_address1 :30;
+ } dma_0xc;
+
+ struct {
+ u32 chipaddr : 7;
+ u32 reserved1 : 1;
+ u32 baseaddr : 8;
+ u32 data1_reg : 8;
+ u32 working_start : 1;
+ u32 twoWS_rw : 1;
+ u32 total_bytes : 2;
+ u32 twoWS_port_reg : 2;
+ u32 no_base_addr_ack_error : 1;
+ u32 st_done : 1;
+ } tw_sm_c_100;
+
+ struct {
+ u32 data2_reg : 8;
+ u32 data3_reg : 8;
+ u32 data4_reg : 8;
+ u32 exlicit_stops : 1;
+ u32 force_stop : 1;
+ u32 unused : 6;
+ } tw_sm_c_104;
+
+ struct {
+ u32 thi1 : 6;
+ u32 reserved1 : 2;
+ u32 tlo1 : 5;
+ u32 reserved2 :19;
+ } tw_sm_c_108;
+
+ struct {
+ u32 thi1 : 6;
+ u32 reserved1 : 2;
+ u32 tlo1 : 5;
+ u32 reserved2 :19;
+ } tw_sm_c_10c;
+
+ struct {
+ u32 thi1 : 6;
+ u32 reserved1 : 2;
+ u32 tlo1 : 5;
+ u32 reserved2 :19;
+ } tw_sm_c_110;
+
+ struct {
+ u32 LNB_CTLHighCount_sig :15;
+ u32 LNB_CTLLowCount_sig :15;
+ u32 LNB_CTLPrescaler_sig : 2;
+ } lnb_switch_freq_200;
+
+ struct {
+ u32 ACPI1_sig : 1;
+ u32 ACPI3_sig : 1;
+ u32 LNB_L_H_sig : 1;
+ u32 Per_reset_sig : 1;
+ u32 reserved :20;
+ u32 Rev_N_sig_revision_hi : 4;
+ u32 Rev_N_sig_reserved1 : 2;
+ u32 Rev_N_sig_caps : 1;
+ u32 Rev_N_sig_reserved2 : 1;
+ } misc_204;
+
+ struct {
+ u32 Stream1_filter_sig : 1;
+ u32 Stream2_filter_sig : 1;
+ u32 PCR_filter_sig : 1;
+ u32 PMT_filter_sig : 1;
+ u32 EMM_filter_sig : 1;
+ u32 ECM_filter_sig : 1;
+ u32 Null_filter_sig : 1;
+ u32 Mask_filter_sig : 1;
+ u32 WAN_Enable_sig : 1;
+ u32 WAN_CA_Enable_sig : 1;
+ u32 CA_Enable_sig : 1;
+ u32 SMC_Enable_sig : 1;
+ u32 Per_CA_Enable_sig : 1;
+ u32 Multi2_Enable_sig : 1;
+ u32 MAC_filter_Mode_sig : 1;
+ u32 Rcv_Data_sig : 1;
+ u32 DMA1_IRQ_Enable_sig : 1;
+ u32 DMA1_Timer_Enable_sig : 1;
+ u32 DMA2_IRQ_Enable_sig : 1;
+ u32 DMA2_Timer_Enable_sig : 1;
+ u32 DMA1_Size_IRQ_Enable_sig : 1;
+ u32 DMA2_Size_IRQ_Enable_sig : 1;
+ u32 Mailbox_from_V8_Enable_sig : 1;
+ u32 unused : 9;
+ } ctrl_208;
+
+ struct {
+ u32 DMA1_IRQ_Status : 1;
+ u32 DMA1_Timer_Status : 1;
+ u32 DMA2_IRQ_Status : 1;
+ u32 DMA2_Timer_Status : 1;
+ u32 DMA1_Size_IRQ_Status : 1;
+ u32 DMA2_Size_IRQ_Status : 1;
+ u32 Mailbox_from_V8_Status_sig : 1;
+ u32 Data_receiver_error : 1;
+ u32 Continuity_error_flag : 1;
+ u32 LLC_SNAP_FLAG_set : 1;
+ u32 Transport_Error : 1;
+ u32 reserved :21;
+ } irq_20c;
+
+ struct {
+ u32 reset_block_000 : 1;
+ u32 reset_block_100 : 1;
+ u32 reset_block_200 : 1;
+ u32 reset_block_300 : 1;
+ u32 reset_block_400 : 1;
+ u32 reset_block_500 : 1;
+ u32 reset_block_600 : 1;
+ u32 reset_block_700 : 1;
+ u32 Block_reset_enable : 8;
+ u32 Special_controls :16;
+ } sw_reset_210;
+
+ struct {
+ u32 vuart_oe_sig : 1;
+ u32 v2WS_oe_sig : 1;
+ u32 halt_V8_sig : 1;
+ u32 section_pkg_enable_sig : 1;
+ u32 s2p_sel_sig : 1;
+ u32 unused1 : 3;
+ u32 polarity_PS_CLK_sig : 1;
+ u32 polarity_PS_VALID_sig : 1;
+ u32 polarity_PS_SYNC_sig : 1;
+ u32 polarity_PS_ERR_sig : 1;
+ u32 unused2 :20;
+ } misc_214;
+
+ struct {
+ u32 Mailbox_from_V8 :32;
+ } mbox_v8_to_host_218;
+
+ struct {
+ u32 sysramaccess_data : 8;
+ u32 sysramaccess_addr :15;
+ u32 unused : 7;
+ u32 sysramaccess_write : 1;
+ u32 sysramaccess_busmuster : 1;
+ } mbox_host_to_v8_21c;
+
+ struct {
+ u32 Stream1_PID :13;
+ u32 Stream1_trans : 1;
+ u32 MAC_Multicast_filter : 1;
+ u32 debug_flag_pid_saved : 1;
+ u32 Stream2_PID :13;
+ u32 Stream2_trans : 1;
+ u32 debug_flag_write_status00 : 1;
+ u32 debug_fifo_problem : 1;
+ } pid_filter_300;
+
+ struct {
+ u32 PCR_PID :13;
+ u32 PCR_trans : 1;
+ u32 debug_overrun3 : 1;
+ u32 debug_overrun2 : 1;
+ u32 PMT_PID :13;
+ u32 PMT_trans : 1;
+ u32 reserved : 2;
+ } pid_filter_304;
+
+ struct {
+ u32 EMM_PID :13;
+ u32 EMM_trans : 1;
+ u32 EMM_filter_4 : 1;
+ u32 EMM_filter_6 : 1;
+ u32 ECM_PID :13;
+ u32 ECM_trans : 1;
+ u32 reserved : 2;
+ } pid_filter_308;
+
+ struct {
+ u32 Group_PID :13;
+ u32 Group_trans : 1;
+ u32 unused1 : 2;
+ u32 Group_mask :13;
+ u32 unused2 : 3;
+ } pid_filter_30c_ext_ind_0_7;
+
+ struct {
+ u32 net_master_read :17;
+ u32 unused :15;
+ } pid_filter_30c_ext_ind_1;
+
+ struct {
+ u32 net_master_write :17;
+ u32 unused :15;
+ } pid_filter_30c_ext_ind_2;
+
+ struct {
+ u32 next_net_master_write :17;
+ u32 unused :15;
+ } pid_filter_30c_ext_ind_3;
+
+ struct {
+ u32 unused1 : 1;
+ u32 state_write :10;
+ u32 reserved1 : 6;
+ u32 stack_read :10;
+ u32 reserved2 : 5;
+ } pid_filter_30c_ext_ind_4;
+
+ struct {
+ u32 stack_cnt :10;
+ u32 unused :22;
+ } pid_filter_30c_ext_ind_5;
+
+ struct {
+ u32 pid_fsm_save_reg0 : 2;
+ u32 pid_fsm_save_reg1 : 2;
+ u32 pid_fsm_save_reg2 : 2;
+ u32 pid_fsm_save_reg3 : 2;
+ u32 pid_fsm_save_reg4 : 2;
+ u32 pid_fsm_save_reg300 : 2;
+ u32 write_status1 : 2;
+ u32 write_status4 : 2;
+ u32 data_size_reg :12;
+ u32 unused : 4;
+ } pid_filter_30c_ext_ind_6;
+
+ struct {
+ u32 index_reg : 5;
+ u32 extra_index_reg : 3;
+ u32 AB_select : 1;
+ u32 pass_alltables : 1;
+ u32 unused :22;
+ } index_reg_310;
+
+ struct {
+ u32 PID :13;
+ u32 PID_trans : 1;
+ u32 PID_enable_bit : 1;
+ u32 reserved :17;
+ } pid_n_reg_314;
+
+ struct {
+ u32 A4_byte : 8;
+ u32 A5_byte : 8;
+ u32 A6_byte : 8;
+ u32 Enable_bit : 1;
+ u32 HighAB_bit : 1;
+ u32 reserved : 6;
+ } mac_low_reg_318;
+
+ struct {
+ u32 A1_byte : 8;
+ u32 A2_byte : 8;
+ u32 A3_byte : 8;
+ u32 reserved : 8;
+ } mac_high_reg_31c;
+
+ struct {
+ u32 reserved :16;
+ u32 data_Tag_ID :16;
+ } data_tag_400;
+
+ struct {
+ u32 Card_IDbyte6 : 8;
+ u32 Card_IDbyte5 : 8;
+ u32 Card_IDbyte4 : 8;
+ u32 Card_IDbyte3 : 8;
+ } card_id_408;
+
+ struct {
+ u32 Card_IDbyte2 : 8;
+ u32 Card_IDbyte1 : 8;
+ } card_id_40c;
+
+ struct {
+ u32 MAC1 : 8;
+ u32 MAC2 : 8;
+ u32 MAC3 : 8;
+ u32 MAC6 : 8;
+ } mac_address_418;
+
+ struct {
+ u32 MAC7 : 8;
+ u32 MAC8 : 8;
+ u32 reserved :16;
+ } mac_address_41c;
+
+ struct {
+ u32 transmitter_data_byte : 8;
+ u32 ReceiveDataReady : 1;
+ u32 ReceiveByteFrameError : 1;
+ u32 txbuffempty : 1;
+ u32 reserved :21;
+ } ci_600;
+
+ struct {
+ u32 pi_d : 8;
+ u32 pi_ha :20;
+ u32 pi_rw : 1;
+ u32 pi_component_reg : 3;
+ } pi_604;
+
+ struct {
+ u32 serialReset : 1;
+ u32 oncecycle_read : 1;
+ u32 Timer_Read_req : 1;
+ u32 Timer_Load_req : 1;
+ u32 timer_data : 7;
+ u32 unused : 1;
+ u32 Timer_addr : 5;
+ u32 reserved : 3;
+ u32 pcmcia_a_mod_pwr_n : 1;
+ u32 pcmcia_b_mod_pwr_n : 1;
+ u32 config_Done_stat : 1;
+ u32 config_Init_stat : 1;
+ u32 config_Prog_n : 1;
+ u32 config_wr_n : 1;
+ u32 config_cs_n : 1;
+ u32 config_cclk : 1;
+ u32 pi_CiMax_IRQ_n : 1;
+ u32 pi_timeout_status : 1;
+ u32 pi_wait_n : 1;
+ u32 pi_busy_n : 1;
+ } pi_608;
+
+ struct {
+ u32 PID :13;
+ u32 key_enable : 1;
+ u32 key_code : 2;
+ u32 key_array_col : 3;
+ u32 key_array_row : 5;
+ u32 dvb_en : 1;
+ u32 rw_flag : 1;
+ u32 reserved : 6;
+ } dvb_reg_60c;
+
+ struct {
+ u32 sram_addr :15;
+ u32 sram_rw : 1;
+ u32 sram_data : 8;
+ u32 sc_xfer_bit : 1;
+ u32 reserved1 : 3;
+ u32 oe_pin_reg : 1;
+ u32 ce_pin_reg : 1;
+ u32 reserved2 : 1;
+ u32 start_sram_ibi : 1;
+ } sram_ctrl_reg_700;
+
+ struct {
+ u32 net_addr_read :16;
+ u32 net_addr_write :16;
+ } net_buf_reg_704;
+
+ struct {
+ u32 cai_read :11;
+ u32 reserved1 : 5;
+ u32 cai_write :11;
+ u32 reserved2 : 6;
+ u32 cai_cnt : 4;
+ } cai_buf_reg_708;
+
+ struct {
+ u32 cao_read :11;
+ u32 reserved1 : 5;
+ u32 cap_write :11;
+ u32 reserved2 : 6;
+ u32 cao_cnt : 4;
+ } cao_buf_reg_70c;
+
+ struct {
+ u32 media_read :11;
+ u32 reserved1 : 5;
+ u32 media_write :11;
+ u32 reserved2 : 6;
+ u32 media_cnt : 4;
+ } media_buf_reg_710;
+
+ struct {
+ u32 NET_Dest : 2;
+ u32 CAI_Dest : 2;
+ u32 CAO_Dest : 2;
+ u32 MEDIA_Dest : 2;
+ u32 net_ovflow_error : 1;
+ u32 media_ovflow_error : 1;
+ u32 cai_ovflow_error : 1;
+ u32 cao_ovflow_error : 1;
+ u32 ctrl_usb_wan : 1;
+ u32 ctrl_sramdma : 1;
+ u32 ctrl_maximumfill : 1;
+ u32 reserved :17;
+ } sram_dest_reg_714;
+
+ struct {
+ u32 net_cnt :12;
+ u32 reserved1 : 4;
+ u32 net_addr_read : 1;
+ u32 reserved2 : 3;
+ u32 net_addr_write : 1;
+ u32 reserved3 :11;
+ } net_buf_reg_718;
+
+ struct {
+ u32 wan_speed_sig : 2;
+ u32 reserved1 : 6;
+ u32 wan_wait_state : 8;
+ u32 sram_chip : 2;
+ u32 sram_memmap : 2;
+ u32 reserved2 : 4;
+ u32 wan_pkt_frame : 4;
+ u32 reserved3 : 4;
+ } wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+#endif