diff options
Diffstat (limited to 'drivers/media/common/b2c2')
| -rw-r--r-- | drivers/media/common/b2c2/Kconfig | 23 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/Makefile | 8 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-common.h | 185 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-eeprom.c | 147 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-fe-tuner.c | 678 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-hw-filter.c | 232 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-i2c.c | 288 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-misc.c | 86 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-reg.h | 166 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop-sram.c | 363 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop.c | 325 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop.h | 29 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop_ibi_value_be.h | 455 | ||||
| -rw-r--r-- | drivers/media/common/b2c2/flexcop_ibi_value_le.h | 455 | 
14 files changed, 3440 insertions, 0 deletions
diff --git a/drivers/media/common/b2c2/Kconfig b/drivers/media/common/b2c2/Kconfig new file mode 100644 index 00000000000..a8c6cdfaa2f --- /dev/null +++ b/drivers/media/common/b2c2/Kconfig @@ -0,0 +1,23 @@ +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 + +# 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 00000000000..24993a5b38b --- /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 00000000000..437912e4982 --- /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 00000000000..a25373a9bd8 --- /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 00000000000..7e14e90d292 --- /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, false)) { +		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, false)) { +		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 00000000000..77e45475f4c --- /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 00000000000..965d5eb3375 --- /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 00000000000..f06f3a9070f --- /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 00000000000..dc4528dcbb9 --- /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 00000000000..185c285f70f --- /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 00000000000..412c5daf2b4 --- /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 00000000000..897b10c85ad --- /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 00000000000..8f64bdbd72b --- /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 00000000000..c75830d7d94 --- /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  | 
